Skip to content

Commit ac527c4

Browse files
committed
refactor: simplify node code generation logic in utils.ts for improved readability and maintainability
1 parent 2ca3a80 commit ac527c4

1 file changed

Lines changed: 25 additions & 70 deletions

File tree

src/utils.ts

Lines changed: 25 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import {
1010
} from "@code0-tech/sagittarius-graphql-types";
1111
import ts from "typescript";
1212
import {createSystem, createVirtualTypeScriptEnvironment, VirtualTypeScriptEnvironment} from "@typescript/vfs"
13-
import {DataTypeVariant, getTypeVariant} from "./extraction/getTypeVariant";
14-
import {getTypesFromFunction} from "./extraction/getTypesFromFunction";
1513
import {stringify} from "lossless-json";
1614

1715
/**
@@ -113,59 +111,14 @@ export function generateFlowSourceCode(
113111
const funcMap = new Map(functions?.map(f => [f.identifier, f]));
114112
const visited = new Set<string>();
115113

116-
const generateNodeCall = (nodeId: string, parentNodeId?: string, parentParamIndex?: number): string => {
117-
const node = nodes.find(n => n?.id === nodeId);
118-
if (!node || !node.functionDefinition?.identifier) return "undefined";
119-
120-
const params = (node.parameters?.nodes as NodeParameter[]) || [];
121-
const args = params.map((p, paramIdx) => {
122-
const val = p.value;
123-
if (!val) return isForInference ? `/* @pos ${nodeId} ${paramIdx} */ {}` : `/* @pos ${nodeId} ${paramIdx} */ undefined`;
124-
if (val.__typename === "ReferenceValue") {
125-
const ref = val as ReferenceValue;
126-
let refCode = typeof ref.inputIndex === "number"
127-
? `p_${sanitizeId(ref.nodeFunctionId ?? "undefined")}_${ref.parameterIndex}[${ref.inputIndex}]`
128-
: ref.nodeFunctionId ? `node_${sanitizeId(ref.nodeFunctionId)}` : `flow_${sanitizeId(flow?.id ?? "undefined")}`;
129-
ref.referencePath?.forEach(pathObj => {
130-
refCode += `?.${pathObj.path}`;
131-
});
132-
return `/* @pos ${nodeId} ${paramIdx} */ ${refCode}`;
133-
}
134-
if (val.__typename === "LiteralValue") {
135-
const jsonString = stringify(val?.value)
136-
return `/* @pos ${nodeId} ${paramIdx} */ ${jsonString}`;
137-
}
138-
if (val.__typename === "NodeFunctionIdWrapper") {
139-
const wrapper = val as NodeFunctionIdWrapper;
140-
return generateNodeCall(wrapper.id!, nodeId, paramIdx);
141-
}
142-
return isForInference ? `/* @pos ${nodeId} ${paramIdx} */ ({} as any)` : `/* @pos ${nodeId} ${paramIdx} */ undefined`;
143-
}).join(", ");
144-
145-
const funcName = `/* @pos ${nodeId} null */ fn_${node.functionDefinition.identifier.replace(/::/g, '_')}`;
146-
const call = `${funcName}(${args})`;
147-
// Add position comment only for nested calls (when called from within an argument)
148-
if (parentNodeId !== undefined && parentParamIndex !== undefined) {
149-
return `${call}`;
150-
}
151-
return call;
152-
};
153-
154114
const generateNodeCode = (nodeId: string, indent: string = ""): string => {
155-
if (visited.has(nodeId)) return "";
156115
const node = nodes.find(n => n?.id === nodeId);
157116
if (!node || !node.functionDefinition) return "";
158117
visited.add(nodeId);
159118

160119
const funcDef = funcMap.get(node.functionDefinition.identifier);
161120
if (!funcDef) return `${indent}// Error: Function ${node.functionDefinition.identifier} not found\n`;
162121

163-
// Only use getTypesFromNode if we are NOT already doing inference to avoid infinite recursion
164-
let nodeTypes: any = {parameters: []};
165-
if (!isForInference) {
166-
nodeTypes = getTypesFromFunction(funcDef);
167-
}
168-
169122
const params = (node.parameters?.nodes as NodeParameter[]) || [];
170123
const args = params.map((p, index) => {
171124
const val = p.value;
@@ -186,35 +139,37 @@ export function generateFlowSourceCode(
186139
}
187140
if (val.__typename === "NodeFunctionIdWrapper") {
188141
const wrapper = val as NodeFunctionIdWrapper;
189-
190-
if (!isForInference) {
191-
const expectedType = nodeTypes.parameters[index];
192-
const isFunctionType = expectedType ? getTypeVariant(expectedType, dataTypes)[0].variant === DataTypeVariant.NODE : false;
193-
194-
if (isFunctionType) {
195-
const lambdaArgName = `p_${sanitizeId(nodeId)}_${index}`;
196-
const subTreeCode = generateNodeCode(wrapper.id!, indent + " ");
197-
return `/* @pos ${nodeId} ${index} */ (...${lambdaArgName}) => {\n${subTreeCode}${indent}}`;
198-
} else {
199-
const nestedCall = generateNodeCall(wrapper.id!, nodeId, index);
200-
return `/* @pos ${nodeId} ${index} */ ${nestedCall}`;
201-
}
202-
} else {
203-
// During inference, we just need something valid.
204-
// Defaulting to a lambda is safer for type inference of the parent node's parameters.
205-
const lambdaArgName = `p_${sanitizeId(nodeId)}_${index}`;
206-
const subTreeCode = generateNodeCode(wrapper.id!, indent + " ");
207-
return `/* @pos ${nodeId} ${index} */ (...${lambdaArgName}) => {\n${subTreeCode}${indent}}`;
208-
}
142+
const lambdaArgName = `p_${sanitizeId(nodeId)}_${index}`;
143+
const subTreeCode = generateNodeCode(wrapper.id!, indent + " ");
144+
return `/* @pos ${nodeId} ${index} */ (...${lambdaArgName}) => {\n${subTreeCode}${indent}}`;
209145
}
210146
return isForInference ? `/* @pos ${nodeId} ${index} */ {}` : `/* @pos ${nodeId} ${index} */ undefined`;
211-
}).join(", ");
147+
});
212148

213149
const varName = `node_${sanitizeId(node.id!)}`;
214150
const funcName = `fn_${node?.functionDefinition?.identifier?.replace(/::/g, '_')}`;
215151
const needsAnyCast = args.includes("undefined");
216-
const isReturnNode = node.functionDefinition.identifier === "std::control::return";
217-
let code = `${indent}${isReturnNode ? "return " : `const ${varName} = `}/* @pos ${nodeId} null */ ${funcName}(${args})${needsAnyCast ? "" : ""} ;\n`;
152+
153+
154+
155+
let code = `${indent}`;
156+
157+
if (node.functionDefinition.identifier === "std::control::return") {
158+
code += `return /* @pos ${nodeId} null */ ${funcName}(${args.join(", ")})${needsAnyCast ? "" : ""} ;\n`
159+
} else if (node.functionDefinition.identifier === "std::control::if") {
160+
code += `/* @pos ${nodeId} null */ if(${args[0]}) {
161+
${generateNodeCode((node.parameters?.nodes?.[1]?.value as NodeFunctionIdWrapper)?.id!, indent + " ")}
162+
}`
163+
} else if (node.functionDefinition.identifier === "std::control::if_else") {
164+
code += `/* @pos ${nodeId} null */ if(${args[0]}) {
165+
${generateNodeCode((node.parameters?.nodes?.[1]?.value as NodeFunctionIdWrapper)?.id!, indent + " ")}
166+
} else {
167+
${generateNodeCode((node.parameters?.nodes?.[2]?.value as NodeFunctionIdWrapper)?.id!, indent + " ")}
168+
}`
169+
} else {
170+
code += `const ${varName} = /* @pos ${nodeId} null */ ${funcName}(${args.join(", ")})${needsAnyCast ? "" : ""} ;\n`
171+
}
172+
218173
if (node.nextNodeId) code += generateNodeCode(node.nextNodeId, indent);
219174
return code;
220175
};

0 commit comments

Comments
 (0)