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