Skip to content

Commit 716e0f0

Browse files
authored
Merge pull request #38 from code0-tech/feat/#32
Add Flow input to reference suggestion and flow settings to validation
2 parents e8630f7 + a1b8ff8 commit 716e0f0

7 files changed

Lines changed: 52 additions & 65 deletions

File tree

package-lock.json

Lines changed: 10 additions & 35 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"build": "vite build"
2424
},
2525
"devDependencies": {
26-
"@code0-tech/sagittarius-graphql-types": "0.0.0-experimental-2414125487-fbc8a5ec8a2dd07cc76957d4315281c246e98d57",
26+
"@code0-tech/sagittarius-graphql-types": "0.0.0-experimental-2430052572-f89aa9d01636e56a17463920775d073b09dd132b",
2727
"@types/node": "^25.5.0",
2828
"typescript": "^6.0.2",
2929
"vite": "^8.0.3",
@@ -32,7 +32,7 @@
3232
"@typescript/vfs": "^1.6.4"
3333
},
3434
"peerDependencies": {
35-
"@code0-tech/sagittarius-graphql-types": "0.0.0-experimental-2414125487-fbc8a5ec8a2dd07cc76957d4315281c246e98d57",
35+
"@code0-tech/sagittarius-graphql-types": "0.0.0-experimental-2430052572-f89aa9d01636e56a17463920775d073b09dd132b",
3636
"typescript": "^5.9.3 || ^6.0.2",
3737
"@typescript/vfs": "^1.6.4"
3838
}

src/suggestion/getReferenceSuggestions.ts

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import ts from "typescript";
2-
import {DataType, Flow, FunctionDefinition, NodeFunction, ReferenceValue} from "@code0-tech/sagittarius-graphql-types";
2+
import {
3+
DataType,
4+
Flow,
5+
FunctionDefinition,
6+
NodeFunction,
7+
ReferencePath,
8+
ReferenceValue
9+
} from "@code0-tech/sagittarius-graphql-types";
310
import {createCompilerHost, generateFlowSourceCode} from "../utils";
411

512
/**
@@ -41,9 +48,9 @@ const extractObjectProperties = (
4148
type: ts.Type,
4249
checker: ts.TypeChecker,
4350
expectedType: ts.Type,
44-
currentPath: string[] = []
45-
): Array<{ path: string[]; type: ts.Type }> => {
46-
const results: Array<{ path: string[]; type: ts.Type }> = [];
51+
currentPath: ReferencePath[] = []
52+
): Array<{ path: ReferencePath[]; type: ts.Type }> => {
53+
const results: Array<{ path: ReferencePath[]; type: ts.Type }> = [];
4754

4855
// Add the current type if it matches the expected type
4956
if (checker.isTypeAssignableTo(type, expectedType)) {
@@ -56,7 +63,7 @@ const extractObjectProperties = (
5663
if (properties && properties.length > 0) {
5764
properties.forEach(property => {
5865
const propType = checker.getTypeOfSymbolAtLocation(property, property.valueDeclaration!);
59-
const propName = property.getName();
66+
const propName = property.getName() as ReferencePath;
6067
const newPath = [...currentPath, propName];
6168

6269
// Recursively extract nested properties
@@ -143,7 +150,7 @@ export const getReferenceSuggestions = (
143150

144151
allSymbols.forEach(symbol => {
145152
const name = symbol.getName();
146-
if (!name.startsWith("node_") && !name.startsWith("p_")) return;
153+
if (!name.startsWith("node_") && !name.startsWith("p_") && !name.startsWith("flow_")) return;
147154

148155
// Get the variable declaration
149156
const declaration = symbol.valueDeclaration || symbol.declarations?.[0];
@@ -175,7 +182,6 @@ export const getReferenceSuggestions = (
175182
};
176183

177184
if (path.length > 0) {
178-
//@ts-ignore
179185
referenceValue.referencePath = path;
180186
}
181187

@@ -211,12 +217,10 @@ export const getReferenceSuggestions = (
211217
nodeFunctionId: nodeFunctionId as any,
212218
parameterIndex: isNaN(paramIndexFromName) ? 0 : paramIndexFromName,
213219
inputIndex: tupleIndex,
214-
//@ts-ignore
215220
inputTypeIdentifier: (typeReference.target as any).labeledElementDeclarations?.[tupleIndex].name.getText()
216221
};
217222

218223
if (path.length > 0) {
219-
//@ts-ignore
220224
referenceValue.referencePath = path;
221225
}
222226

@@ -225,6 +229,21 @@ export const getReferenceSuggestions = (
225229
});
226230
}
227231
}
232+
else if (name.startsWith("flow_")) {
233+
const propertyPaths = extractObjectProperties(symbolType, checker, expectedType)
234+
propertyPaths.forEach(({ path }) => {
235+
const referenceValue: ReferenceValue = {
236+
__typename: 'ReferenceValue',
237+
nodeFunctionId: null
238+
};
239+
240+
if (path.length > 0) {
241+
referenceValue.referencePath = path;
242+
}
243+
244+
referenceValues.push(referenceValue);
245+
})
246+
}
228247
});
229248

230249
return referenceValues;

src/utils.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ export function generateFlowSourceCode(
209209
};
210210

211211
const typeDefs = getSharedTypeDeclarations(dataTypes);
212+
const flowTypeDeclaration = `declare function flow${flow?.signature ?? "(): void"}`
212213
const funcDeclarations = functions?.map(f => `declare function fn_${f.identifier?.replace(/::/g, '_')}${f.signature}`).join('\n');
213214

214215
const nextNodeIds = new Set(nodes.map(n => n?.nextNodeId).filter(id => !!id));
@@ -217,12 +218,14 @@ export function generateFlowSourceCode(
217218
if (p?.value?.__typename === "NodeFunctionIdWrapper" && p.value.id) subTreeIds.add(p.value.id);
218219
}));
219220

221+
const flowCode = flow ? `const flow_${sanitizeId(flow.id ?? "")} = flow(${flow.settings?.nodes?.map((setting, index) => `/* @pos undefined ${index} */ ${JSON.stringify(setting?.value)}`).join(", ") ?? ""});` : ""
222+
220223
const executionCode = nodes
221224
.filter(n => n?.id && !nextNodeIds.has(n.id) && !subTreeIds.has(n.id))
222225
.map(n => generateNodeCode(n!.id!))
223226
.join('\n');
224227

225-
return `${typeDefs}\n${funcDeclarations}\n\n// --- Flow ---\n${executionCode}`;
228+
return `${typeDefs}\n${flowTypeDeclaration}\n${funcDeclarations}\n\n// --- Flow ---\n${flowCode}\n${executionCode}`;
226229
}
227230

228231
export interface InferredTypes {

src/validation/getFlowValidation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export const getFlowValidation = (
6262
}
6363

6464
if (closestMatch) {
65-
nodeId = closestMatch[1] as NodeFunction['id'];
65+
nodeId = closestMatch[1] === "undefined" ? undefined : closestMatch[1] as NodeFunction['id'];
6666
parameterIndex = parseInt(closestMatch[2], 10);
6767
}
6868
}

test/flowValidation.test.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {describe, expect, it} from 'vitest';
22
import {getFlowValidation} from '../src/validation/getFlowValidation';
33
import {Flow} from "@code0-tech/sagittarius-graphql-types"; // Pfad ggf. anpassen
4+
// @ts-ignore
45
import {DATA_TYPES, FUNCTION_SIGNATURES} from "./data";
56

67
describe('getFlowValidation - Integrationstest', () => {
@@ -69,7 +70,6 @@ describe('getFlowValidation - Integrationstest', () => {
6970
expect(result.isValid).toBe(true);
7071
expect(result.diagnostics).toHaveLength(0);
7172
result.diagnostics.forEach((error) => {
72-
expect(error.nodeId).toBeDefined()
7373
expect(error.parameterIndex).toBeDefined()
7474
})
7575
});
@@ -142,7 +142,6 @@ describe('getFlowValidation - Integrationstest', () => {
142142

143143
expect(result.isValid).toBe(false);
144144
result.diagnostics.forEach((error) => {
145-
expect(error.nodeId).toBeDefined()
146145
expect(error.parameterIndex).toBeDefined()
147146
})
148147
});
@@ -192,7 +191,6 @@ describe('getFlowValidation - Integrationstest', () => {
192191
expect(result.isValid).toBe(true);
193192
expect(result.diagnostics).toHaveLength(0);
194193
result.diagnostics.forEach((error) => {
195-
expect(error.nodeId).toBeDefined()
196194
expect(error.parameterIndex).toBeDefined()
197195
})
198196
});
@@ -249,7 +247,6 @@ describe('getFlowValidation - Integrationstest', () => {
249247
expect(result.isValid).toBe(true);
250248
expect(result.diagnostics).toHaveLength(0);
251249
result.diagnostics.forEach((error) => {
252-
expect(error.nodeId).toBeDefined()
253250
expect(error.parameterIndex).toBeDefined()
254251
})
255252
});
@@ -261,8 +258,7 @@ describe('getFlowValidation - Integrationstest', () => {
261258
"id": "gid://sagittarius/Flow/1",
262259
"createdAt": "2026-03-17T14:02:31Z",
263260
"name": "Test",
264-
"inputType": "REST_ADAPTER_INPUT",
265-
"returnType": "HTTP_RESPONSE",
261+
"signature": "(httpURL: HTTP_URL, httpMethod: HTTP_METHOD): REST_ADAPTER_INPUT<{}>",
266262
"nodes": {
267263
"__typename": "NodeFunctionConnection",
268264
"nodes": [
@@ -364,7 +360,6 @@ describe('getFlowValidation - Integrationstest', () => {
364360

365361
expect(result.isValid).toBe(false);
366362
result.diagnostics.forEach((error) => {
367-
expect(error.nodeId).toBeDefined()
368363
expect(error.parameterIndex).toBeDefined()
369364
})
370365
});
@@ -376,8 +371,7 @@ describe('getFlowValidation - Integrationstest', () => {
376371
"id": "gid://sagittarius/Flow/1",
377372
"createdAt": "2026-03-17T14:02:31Z",
378373
"name": "Test",
379-
"inputType": "REST_ADAPTER_INPUT",
380-
"returnType": "HTTP_RESPONSE",
374+
"signature": "(httpURL: HTTP_URL, httpMethod: HTTP_METHOD): REST_ADAPTER_INPUT<{}>",
381375
"nodes": {
382376
"__typename": "NodeFunctionConnection",
383377
"nodes": [
@@ -539,8 +533,6 @@ describe('getFlowValidation - Integrationstest', () => {
539533

540534
expect(result.isValid).toBe(false);
541535
result.diagnostics.forEach((error) => {
542-
543-
expect(error.nodeId).toBeDefined()
544536
expect(error.parameterIndex).toBeDefined()
545537
})
546538
});

0 commit comments

Comments
 (0)