Skip to content

Commit 0d898c6

Browse files
committed
feat: implement getSubFlows utility function to create SubFlowValue from compatible function declarations
1 parent 2cac9da commit 0d898c6

1 file changed

Lines changed: 96 additions & 0 deletions

File tree

src/util/subflows.util.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import ts from "typescript";
2+
import {FunctionDefinition, SubFlowValue, SubFlowValueSetting} from "@code0-tech/sagittarius-graphql-types";
3+
import {isSubFlow} from "./schema.util";
4+
5+
export const getSubFlows = (
6+
checker: ts.TypeChecker,
7+
functionDeclarations: ts.FunctionDeclaration[],
8+
functions: FunctionDefinition[],
9+
paramType: ts.Type
10+
): SubFlowValue[] => {
11+
12+
if (!isSubFlow(paramType)) {
13+
return [];
14+
}
15+
16+
return functionDeclarations.flatMap((func) => {
17+
const subFlow = createSubFlowIfCompatible(checker, func, functions, paramType);
18+
return subFlow ? [subFlow] : [];
19+
});
20+
21+
}
22+
23+
const createSubFlowIfCompatible = (
24+
checker: ts.TypeChecker,
25+
func: ts.FunctionDeclaration,
26+
functions: FunctionDefinition[],
27+
paramType: ts.Type
28+
): SubFlowValue | null => {
29+
30+
// 2. Hole den Typ der Funktion (nicht nur den Return Type!)
31+
const functionType = checker.getTypeAtLocation(func);
32+
33+
// 3. Prüfe ob functionType zu paramType assignierbar ist
34+
// paramType ist z.B. (number: number) => void
35+
// functionType sollte auch (number: number) => void (oder kompatibel) sein
36+
if (!checker.isTypeAssignableTo(functionType, paramType)) {
37+
return null;
38+
}
39+
40+
// 4. Wenn kompatibel: Erstelle SubFlowValue
41+
const functionName = normalizeFunctionName(func.name?.getText());
42+
const functionDefinition = functions.find((f) => f.identifier === functionName);
43+
44+
if (!functionDefinition) {
45+
return null;
46+
}
47+
48+
return buildSubFlowValue(functionDefinition);
49+
50+
}
51+
52+
/**
53+
* Normalizes a function name by removing prefixes and replacing underscores with
54+
* double colons (::).
55+
*
56+
* This function applies the following transformations:
57+
* 1. Removes the "fn_" prefix
58+
* 2. Replaces the first underscore with "::"
59+
* 3. Replaces the second underscore with "::"
60+
*
61+
* Example: "fn_module_submodule" becomes "module::submodule"
62+
*
63+
* @param {string | undefined} rawName - The raw function name from the declaration
64+
*
65+
* @returns {string} The normalized function name, or an empty string if the input
66+
* is undefined
67+
*
68+
* @private
69+
*/
70+
const normalizeFunctionName = (rawName: string | undefined): string => {
71+
if (!rawName) {
72+
return "";
73+
}
74+
return rawName
75+
.replace("fn_", "")
76+
.replace("_", "::")
77+
.replace("_", "::");
78+
}
79+
80+
const buildSubFlowValue = (functionDefinition: FunctionDefinition): SubFlowValue => {
81+
return {
82+
__typename: "SubFlowValue",
83+
functionDefinition: functionDefinition,
84+
signature: functionDefinition.signature,
85+
settings: functionDefinition.parameterDefinitions?.nodes?.map(param => {
86+
const setting: SubFlowValueSetting = {
87+
__typename: "SubFlowValueSetting",
88+
identifier: param?.identifier,
89+
defaultValue: param?.defaultValue ?? null,
90+
hidden: param?.hidden ?? false,
91+
optional: param?.optional ?? false,
92+
}
93+
return setting
94+
})
95+
}
96+
}

0 commit comments

Comments
 (0)