@pikku/inspector 0.11.1 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/CHANGELOG.md +26 -1
  2. package/OPTIMIZATION-PLAN.md +195 -0
  3. package/dist/add/add-ai-agent.d.ts +2 -0
  4. package/dist/add/add-ai-agent.js +314 -0
  5. package/dist/add/add-channel.js +69 -61
  6. package/dist/add/add-cli.js +36 -18
  7. package/dist/add/add-file-with-factory.js +2 -0
  8. package/dist/add/add-functions.js +327 -59
  9. package/dist/add/add-http-route.d.ts +19 -10
  10. package/dist/add/add-http-route.js +153 -44
  11. package/dist/add/add-http-routes.d.ts +5 -0
  12. package/dist/add/add-http-routes.js +159 -0
  13. package/dist/add/add-keyed-wiring.d.ts +12 -0
  14. package/dist/add/add-keyed-wiring.js +97 -0
  15. package/dist/add/add-mcp-prompt.js +14 -9
  16. package/dist/add/add-mcp-resource.js +14 -9
  17. package/dist/add/add-middleware.d.ts +1 -4
  18. package/dist/add/add-middleware.js +364 -79
  19. package/dist/add/add-permission.d.ts +1 -1
  20. package/dist/add/add-permission.js +152 -40
  21. package/dist/add/add-queue-worker.js +18 -12
  22. package/dist/add/add-rpc-invocations.d.ts +3 -0
  23. package/dist/add/add-rpc-invocations.js +65 -25
  24. package/dist/add/add-schedule.js +11 -5
  25. package/dist/add/add-secret.d.ts +3 -0
  26. package/dist/add/add-secret.js +82 -0
  27. package/dist/add/add-trigger.d.ts +2 -0
  28. package/dist/add/add-trigger.js +87 -0
  29. package/dist/add/add-variable.d.ts +1 -0
  30. package/dist/add/add-variable.js +8 -0
  31. package/dist/add/add-workflow-graph.d.ts +7 -0
  32. package/dist/add/add-workflow-graph.js +396 -0
  33. package/dist/add/add-workflow.js +124 -26
  34. package/dist/error-codes.d.ts +16 -1
  35. package/dist/error-codes.js +21 -1
  36. package/dist/index.d.ts +9 -5
  37. package/dist/index.js +5 -2
  38. package/dist/inspector.d.ts +1 -1
  39. package/dist/inspector.js +106 -13
  40. package/dist/schema-generator.d.ts +1 -0
  41. package/dist/schema-generator.js +1 -0
  42. package/dist/types-map.js +10 -1
  43. package/dist/types.d.ts +180 -30
  44. package/dist/utils/compute-required-schemas.d.ts +4 -0
  45. package/dist/utils/compute-required-schemas.js +41 -0
  46. package/dist/utils/contract-hashes.d.ts +35 -0
  47. package/dist/utils/contract-hashes.js +202 -0
  48. package/dist/utils/custom-types-generator.d.ts +9 -0
  49. package/dist/utils/custom-types-generator.js +71 -0
  50. package/dist/utils/detect-schema-vendor.d.ts +22 -0
  51. package/dist/utils/detect-schema-vendor.js +76 -0
  52. package/dist/utils/ensure-function-metadata.d.ts +5 -2
  53. package/dist/utils/ensure-function-metadata.js +220 -6
  54. package/dist/utils/extract-function-name.d.ts +5 -16
  55. package/dist/utils/extract-function-name.js +93 -298
  56. package/dist/utils/extract-services.d.ts +2 -1
  57. package/dist/utils/extract-services.js +25 -1
  58. package/dist/utils/filter-inspector-state.js +107 -23
  59. package/dist/utils/get-property-value.d.ts +8 -2
  60. package/dist/utils/get-property-value.js +33 -4
  61. package/dist/utils/hash.d.ts +2 -0
  62. package/dist/utils/hash.js +23 -0
  63. package/dist/utils/middleware.d.ts +7 -30
  64. package/dist/utils/middleware.js +80 -66
  65. package/dist/utils/permissions.d.ts +2 -2
  66. package/dist/utils/permissions.js +10 -10
  67. package/dist/utils/post-process.d.ts +9 -10
  68. package/dist/utils/post-process.js +231 -24
  69. package/dist/utils/resolve-external-package.d.ts +12 -0
  70. package/dist/utils/resolve-external-package.js +34 -0
  71. package/dist/utils/resolve-function-types.d.ts +6 -0
  72. package/dist/utils/resolve-function-types.js +29 -0
  73. package/dist/utils/resolve-identifier.d.ts +10 -0
  74. package/dist/utils/resolve-identifier.js +36 -0
  75. package/dist/utils/resolve-versions.d.ts +2 -0
  76. package/dist/utils/resolve-versions.js +78 -0
  77. package/dist/utils/schema-generator.d.ts +9 -0
  78. package/dist/utils/schema-generator.js +209 -0
  79. package/dist/utils/serialize-inspector-state.d.ts +73 -13
  80. package/dist/utils/serialize-inspector-state.js +102 -6
  81. package/dist/utils/serialize-mcp-json.d.ts +2 -0
  82. package/dist/utils/serialize-mcp-json.js +99 -0
  83. package/dist/utils/serialize-middleware-groups-meta.d.ts +12 -0
  84. package/dist/utils/serialize-middleware-groups-meta.js +28 -0
  85. package/dist/utils/serialize-openapi-json.d.ts +85 -0
  86. package/dist/utils/serialize-openapi-json.js +151 -0
  87. package/dist/utils/serialize-permissions-groups-meta.d.ts +6 -0
  88. package/dist/utils/serialize-permissions-groups-meta.js +31 -0
  89. package/dist/utils/workflow/dsl/deserialize-dsl-workflow.d.ts +24 -0
  90. package/dist/utils/workflow/dsl/deserialize-dsl-workflow.js +830 -0
  91. package/dist/{workflow/extract-simple-workflow.d.ts → utils/workflow/dsl/extract-dsl-workflow.d.ts} +4 -2
  92. package/dist/{workflow/extract-simple-workflow.js → utils/workflow/dsl/extract-dsl-workflow.js} +572 -72
  93. package/dist/utils/workflow/dsl/index.d.ts +7 -0
  94. package/dist/utils/workflow/dsl/index.js +7 -0
  95. package/dist/{workflow → utils/workflow/dsl}/patterns.d.ts +21 -0
  96. package/dist/{workflow → utils/workflow/dsl}/patterns.js +90 -10
  97. package/dist/{workflow → utils/workflow/dsl}/validation.d.ts +2 -0
  98. package/dist/{workflow → utils/workflow/dsl}/validation.js +25 -7
  99. package/dist/utils/workflow/graph/convert-dsl-to-graph.d.ts +13 -0
  100. package/dist/utils/workflow/graph/convert-dsl-to-graph.js +318 -0
  101. package/dist/utils/workflow/graph/finalize-workflow-wires.d.ts +3 -0
  102. package/dist/utils/workflow/graph/finalize-workflow-wires.js +276 -0
  103. package/dist/utils/workflow/graph/finalize-workflows.d.ts +2 -0
  104. package/dist/utils/workflow/graph/finalize-workflows.js +75 -0
  105. package/dist/utils/workflow/graph/index.d.ts +8 -0
  106. package/dist/utils/workflow/graph/index.js +8 -0
  107. package/dist/utils/workflow/graph/serialize-workflow-graph.d.ts +35 -0
  108. package/dist/utils/workflow/graph/serialize-workflow-graph.js +150 -0
  109. package/dist/utils/workflow/graph/workflow-graph.types.d.ts +203 -0
  110. package/dist/utils/workflow/graph/workflow-graph.types.js +38 -0
  111. package/dist/visit.js +13 -2
  112. package/package.json +26 -4
  113. package/src/add/add-ai-agent.ts +468 -0
  114. package/src/add/add-channel.ts +82 -79
  115. package/src/add/add-cli.ts +49 -20
  116. package/src/add/add-file-with-factory.ts +2 -0
  117. package/src/add/add-functions.ts +429 -71
  118. package/src/add/add-http-route.ts +246 -65
  119. package/src/add/add-http-routes.ts +228 -0
  120. package/src/add/add-keyed-wiring.ts +151 -0
  121. package/src/add/add-mcp-prompt.ts +26 -15
  122. package/src/add/add-mcp-resource.ts +27 -15
  123. package/src/add/add-middleware.ts +482 -80
  124. package/src/add/add-permission.ts +199 -40
  125. package/src/add/add-queue-worker.ts +24 -19
  126. package/src/add/add-rpc-invocations.ts +78 -31
  127. package/src/add/add-schedule.ts +16 -11
  128. package/src/add/add-secret.ts +140 -0
  129. package/src/add/add-trigger.ts +154 -0
  130. package/src/add/add-variable.ts +9 -0
  131. package/src/add/add-workflow-graph.ts +522 -0
  132. package/src/add/add-workflow.ts +117 -30
  133. package/src/error-codes.ts +26 -1
  134. package/src/index.ts +27 -8
  135. package/src/inspector.ts +145 -17
  136. package/src/schema-generator.ts +1 -0
  137. package/src/types-map.ts +12 -1
  138. package/src/types.ts +192 -51
  139. package/src/utils/compute-required-schemas.ts +49 -0
  140. package/src/utils/contract-hashes.test.ts +528 -0
  141. package/src/utils/contract-hashes.ts +290 -0
  142. package/src/utils/custom-types-generator.ts +88 -0
  143. package/src/utils/detect-schema-vendor.ts +90 -0
  144. package/src/utils/ensure-function-metadata.ts +324 -7
  145. package/src/utils/extract-function-name.ts +108 -358
  146. package/src/utils/extract-services.ts +35 -2
  147. package/src/utils/filter-inspector-state.test.ts +34 -20
  148. package/src/utils/filter-inspector-state.ts +140 -31
  149. package/src/utils/get-property-value.ts +50 -5
  150. package/src/utils/hash.ts +26 -0
  151. package/src/utils/middleware.test.ts +204 -0
  152. package/src/utils/middleware.ts +129 -67
  153. package/src/utils/permissions.test.ts +35 -12
  154. package/src/utils/permissions.ts +10 -10
  155. package/src/utils/post-process.ts +283 -43
  156. package/src/utils/resolve-external-package.ts +42 -0
  157. package/src/utils/resolve-function-types.ts +42 -0
  158. package/src/utils/resolve-identifier.ts +46 -0
  159. package/src/utils/resolve-versions.test.ts +249 -0
  160. package/src/utils/resolve-versions.ts +105 -0
  161. package/src/utils/schema-generator.ts +329 -0
  162. package/src/utils/serialize-inspector-state.ts +181 -20
  163. package/src/utils/serialize-mcp-json.ts +145 -0
  164. package/src/utils/serialize-middleware-groups-meta.ts +33 -0
  165. package/src/utils/serialize-openapi-json.ts +277 -0
  166. package/src/utils/serialize-permissions-groups-meta.ts +35 -0
  167. package/src/utils/test-data/inspector-state.json +69 -66
  168. package/src/utils/workflow/dsl/deserialize-dsl-workflow.ts +1104 -0
  169. package/src/{workflow/extract-simple-workflow.ts → utils/workflow/dsl/extract-dsl-workflow.ts} +678 -85
  170. package/src/utils/workflow/dsl/index.ts +11 -0
  171. package/src/{workflow → utils/workflow/dsl}/patterns.ts +108 -11
  172. package/src/{workflow → utils/workflow/dsl}/validation.ts +34 -7
  173. package/src/utils/workflow/graph/convert-dsl-to-graph.ts +422 -0
  174. package/src/utils/workflow/graph/finalize-workflow-wires.ts +310 -0
  175. package/src/utils/workflow/graph/finalize-workflows.ts +100 -0
  176. package/src/utils/workflow/graph/index.ts +11 -0
  177. package/src/utils/workflow/graph/serialize-workflow-graph.ts +216 -0
  178. package/src/utils/workflow/graph/workflow-graph.types.ts +231 -0
  179. package/src/visit.ts +14 -2
  180. package/tsconfig.tsbuildinfo +1 -1
  181. package/dist/add/add-mcp-tool.d.ts +0 -2
  182. package/dist/add/add-mcp-tool.js +0 -81
  183. package/dist/utils/extract-service-metadata.d.ts +0 -19
  184. package/dist/utils/extract-service-metadata.js +0 -244
  185. package/dist/utils/write-service-metadata.d.ts +0 -13
  186. package/dist/utils/write-service-metadata.js +0 -37
  187. package/src/add/add-mcp-tool.ts +0 -141
  188. package/src/utils/extract-service-metadata.ts +0 -353
  189. package/src/utils/write-service-metadata.ts +0 -51
@@ -0,0 +1,22 @@
1
+ import * as ts from 'typescript';
2
+ import type { SchemaVendor, InspectorLogger } from '../types.js';
3
+ /**
4
+ * Detect the schema vendor by tracing the type back to its library origin.
5
+ * This handles locally-defined schemas like `export const MySchema = z.object({...})`
6
+ * by checking where the type itself originates from.
7
+ *
8
+ * Supports multiple schema libraries in the same project (e.g., during migration
9
+ * from one library to another).
10
+ */
11
+ export declare const detectSchemaVendor: (identifier: ts.Identifier, checker: ts.TypeChecker) => SchemaVendor;
12
+ /**
13
+ * Detect schema vendor and log a fatal error if unknown.
14
+ * Returns the vendor if successful, or undefined if unknown (after logging error).
15
+ *
16
+ * @param identifier - The TypeScript identifier for the schema variable
17
+ * @param checker - TypeScript type checker
18
+ * @param logger - Inspector logger for error reporting
19
+ * @param context - Description of what the schema is for (e.g., "Credential 'myCredential'")
20
+ * @param sourceFile - Source file path for error message
21
+ */
22
+ export declare const detectSchemaVendorOrError: (identifier: ts.Identifier, checker: ts.TypeChecker, logger: InspectorLogger, context: string, sourceFile: string) => Exclude<SchemaVendor, "unknown"> | undefined;
@@ -0,0 +1,76 @@
1
+ import { ErrorCode } from '../error-codes.js';
2
+ /**
3
+ * Detect the schema vendor by tracing the type back to its library origin.
4
+ * This handles locally-defined schemas like `export const MySchema = z.object({...})`
5
+ * by checking where the type itself originates from.
6
+ *
7
+ * Supports multiple schema libraries in the same project (e.g., during migration
8
+ * from one library to another).
9
+ */
10
+ export const detectSchemaVendor = (identifier, checker) => {
11
+ const type = checker.getTypeAtLocation(identifier);
12
+ if (!type)
13
+ return 'unknown';
14
+ // Check the type's symbol declarations to find the library origin
15
+ const checkTypeOrigin = (t) => {
16
+ const symbol = t.getSymbol() || t.aliasSymbol;
17
+ if (symbol) {
18
+ const decls = symbol.getDeclarations();
19
+ if (decls) {
20
+ for (const decl of decls) {
21
+ const fileName = decl.getSourceFile().fileName;
22
+ if (fileName.includes('node_modules/zod'))
23
+ return 'zod';
24
+ if (fileName.includes('node_modules/valibot'))
25
+ return 'valibot';
26
+ if (fileName.includes('node_modules/arktype'))
27
+ return 'arktype';
28
+ if (fileName.includes('node_modules/@effect/schema'))
29
+ return 'effect';
30
+ }
31
+ }
32
+ }
33
+ // Check base types for class/interface hierarchies
34
+ const baseTypes = t.getBaseTypes?.();
35
+ if (baseTypes) {
36
+ for (const baseType of baseTypes) {
37
+ const result = checkTypeOrigin(baseType);
38
+ if (result)
39
+ return result;
40
+ }
41
+ }
42
+ return null;
43
+ };
44
+ const vendor = checkTypeOrigin(type);
45
+ if (vendor)
46
+ return vendor;
47
+ // Fallback: check type arguments (for generic types like z.ZodObject<...>)
48
+ if (type.typeArguments) {
49
+ for (const arg of type.typeArguments || []) {
50
+ const result = checkTypeOrigin(arg);
51
+ if (result)
52
+ return result;
53
+ }
54
+ }
55
+ return 'unknown';
56
+ };
57
+ /**
58
+ * Detect schema vendor and log a fatal error if unknown.
59
+ * Returns the vendor if successful, or undefined if unknown (after logging error).
60
+ *
61
+ * @param identifier - The TypeScript identifier for the schema variable
62
+ * @param checker - TypeScript type checker
63
+ * @param logger - Inspector logger for error reporting
64
+ * @param context - Description of what the schema is for (e.g., "Credential 'myCredential'")
65
+ * @param sourceFile - Source file path for error message
66
+ */
67
+ export const detectSchemaVendorOrError = (identifier, checker, logger, context, sourceFile) => {
68
+ const vendor = detectSchemaVendor(identifier, checker);
69
+ if (vendor === 'unknown') {
70
+ logger.critical(ErrorCode.INLINE_SCHEMA, `${context} schema vendor could not be determined from '${sourceFile}'. ` +
71
+ `Supported vendors: zod, valibot, arktype, @effect/schema. ` +
72
+ `Ensure your schema is imported from a supported validation library.`);
73
+ return undefined;
74
+ }
75
+ return vendor;
76
+ };
@@ -1,6 +1,9 @@
1
+ import * as ts from 'typescript';
1
2
  import { InspectorState } from '../types.js';
2
3
  /**
3
- * Ensures that function metadata exists for a given pikkuFuncName.
4
+ * Ensures that function metadata exists for a given pikkuFuncId.
4
5
  * Creates stub metadata if it doesn't exist (useful for inline functions).
6
+ * When funcInitializer and checker are provided, resolves types and
7
+ * extracts tags/middleware/permissions from the pikkuFunc() config.
5
8
  */
6
- export declare function ensureFunctionMetadata(state: InspectorState, pikkuFuncName: string, fallbackName?: string): void;
9
+ export declare function ensureFunctionMetadata(state: InspectorState, pikkuFuncId: string, fallbackName?: string, funcInitializer?: ts.Node, checker?: ts.TypeChecker, isHelper?: boolean): void;
@@ -1,12 +1,172 @@
1
+ import * as ts from 'typescript';
2
+ import { funcIdToTypeName } from './extract-function-name.js';
3
+ import { getCommonWireMetaData } from './get-property-value.js';
4
+ import { resolveMiddleware } from './middleware.js';
5
+ import { resolvePermissions } from './permissions.js';
6
+ function isVoidLike(type) {
7
+ return !!(type.flags &
8
+ (ts.TypeFlags.Void | ts.TypeFlags.Undefined | ts.TypeFlags.VoidLike));
9
+ }
10
+ function isPromiseOfVoid(checker, type) {
11
+ if (!type?.symbol)
12
+ return false;
13
+ const isPromise = type.symbol.name === 'Promise' &&
14
+ checker.getFullyQualifiedName(type.symbol).includes('Promise');
15
+ if (!isPromise)
16
+ return false;
17
+ const inner = type.aliasTypeArguments?.[0] ??
18
+ type.typeArguments?.[0];
19
+ return !!inner && isVoidLike(inner);
20
+ }
21
+ function unwrapPromise(checker, type) {
22
+ if (type.isUnion()) {
23
+ const nonVoid = type.types.filter((t) => !isVoidLike(t) && !isPromiseOfVoid(checker, t));
24
+ if (nonVoid.length === 1) {
25
+ return unwrapPromise(checker, nonVoid[0]);
26
+ }
27
+ if (nonVoid.length > 1) {
28
+ return unwrapPromise(checker, nonVoid[0]);
29
+ }
30
+ return type;
31
+ }
32
+ if (!type?.symbol)
33
+ return type;
34
+ const isPromise = type.symbol.name === 'Promise' &&
35
+ checker.getFullyQualifiedName(type.symbol).includes('Promise');
36
+ if (isPromise && type.aliasTypeArguments?.length === 1) {
37
+ return type.aliasTypeArguments[0];
38
+ }
39
+ if (isPromise && type.typeArguments?.length === 1) {
40
+ return type.typeArguments[0];
41
+ }
42
+ return type;
43
+ }
44
+ function resolveTypeName(checker, type, state, funcName, direction) {
45
+ if (type.flags & (ts.TypeFlags.VoidLike | ts.TypeFlags.Null))
46
+ return null;
47
+ const typeStr = checker.typeToString(type, undefined, ts.TypeFormatFlags.NoTruncation);
48
+ if (!typeStr ||
49
+ typeStr === 'void' ||
50
+ typeStr === 'undefined' ||
51
+ typeStr === 'null')
52
+ return null;
53
+ const isSimpleName = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(typeStr);
54
+ if (isSimpleName) {
55
+ const symbol = type.aliasSymbol || type.getSymbol();
56
+ if (symbol) {
57
+ const decl = symbol.getDeclarations()?.[0];
58
+ if (decl) {
59
+ const path = decl.getSourceFile().fileName;
60
+ if (!state.functions.typesMap.exists(typeStr, path)) {
61
+ state.functions.typesMap.addType(typeStr, path);
62
+ }
63
+ }
64
+ }
65
+ return typeStr;
66
+ }
67
+ const aliasName = funcIdToTypeName(funcName) + direction;
68
+ state.functions.typesMap.addCustomType(aliasName, typeStr, []);
69
+ return aliasName;
70
+ }
71
+ function getFirstCallSignature(type) {
72
+ const sigs = type.getCallSignatures();
73
+ if (sigs.length > 0)
74
+ return sigs[0];
75
+ if (type.isUnion()) {
76
+ for (const member of type.types) {
77
+ const memberSigs = member.getCallSignatures();
78
+ if (memberSigs.length > 0)
79
+ return memberSigs[0];
80
+ }
81
+ }
82
+ return undefined;
83
+ }
84
+ function resolveFromConfigTypeArgs(state, pikkuFuncId, configType, checker, meta) {
85
+ const typeArgs = configType.aliasTypeArguments ??
86
+ configType.typeArguments;
87
+ if (!typeArgs || typeArgs.length < 2)
88
+ return;
89
+ const inputType = typeArgs[0];
90
+ const outputType = typeArgs[1];
91
+ if (!meta.inputs || meta.inputs.length === 0) {
92
+ const inputName = resolveTypeName(checker, inputType, state, pikkuFuncId, 'Input');
93
+ if (inputName) {
94
+ meta.inputs = [inputName];
95
+ meta.inputSchemaName = inputName;
96
+ }
97
+ }
98
+ if (!meta.outputs || meta.outputs.length === 0) {
99
+ const resolvedOutput = unwrapPromise(checker, outputType);
100
+ const outputName = resolveTypeName(checker, resolvedOutput, state, pikkuFuncId, 'Output');
101
+ if (outputName) {
102
+ meta.outputs = [outputName];
103
+ meta.outputSchemaName = outputName;
104
+ }
105
+ }
106
+ }
107
+ function resolveFuncConfigTypes(state, pikkuFuncId, funcInitializer, checker) {
108
+ const meta = state.functions.meta[pikkuFuncId];
109
+ if (!meta || (meta.inputs && meta.inputs.length > 0))
110
+ return;
111
+ const configType = checker.getTypeAtLocation(funcInitializer);
112
+ const funcProp = configType.getProperty('func');
113
+ if (!funcProp)
114
+ return;
115
+ const funcType = checker.getTypeOfSymbolAtLocation(funcProp, funcInitializer);
116
+ const sig = getFirstCallSignature(funcType);
117
+ if (!sig)
118
+ return;
119
+ const params = sig.getParameters();
120
+ if (params.length >= 2) {
121
+ const inputType = checker.getTypeOfSymbolAtLocation(params[1], funcInitializer);
122
+ const inputName = resolveTypeName(checker, inputType, state, pikkuFuncId, 'Input');
123
+ if (inputName) {
124
+ meta.inputs = [inputName];
125
+ meta.inputSchemaName = inputName;
126
+ }
127
+ }
128
+ const rawReturnType = checker.getReturnTypeOfSignature(sig);
129
+ const outputType = unwrapPromise(checker, rawReturnType);
130
+ const outputName = resolveTypeName(checker, outputType, state, pikkuFuncId, 'Output');
131
+ if (outputName) {
132
+ meta.outputs = [outputName];
133
+ meta.outputSchemaName = outputName;
134
+ }
135
+ resolveFromConfigTypeArgs(state, pikkuFuncId, configType, checker, meta);
136
+ }
137
+ function resolveToPikkuFuncCall(node, checker) {
138
+ if (ts.isCallExpression(node) &&
139
+ ts.isIdentifier(node.expression) &&
140
+ node.expression.text.startsWith('pikku')) {
141
+ return node;
142
+ }
143
+ if (ts.isIdentifier(node)) {
144
+ const sym = checker.getSymbolAtLocation(node);
145
+ if (sym) {
146
+ let resolved = sym;
147
+ if (resolved.flags & ts.SymbolFlags.Alias) {
148
+ resolved = checker.getAliasedSymbol(resolved) ?? resolved;
149
+ }
150
+ const decl = resolved.declarations?.[0];
151
+ if (decl && ts.isVariableDeclaration(decl) && decl.initializer) {
152
+ return resolveToPikkuFuncCall(decl.initializer, checker);
153
+ }
154
+ }
155
+ }
156
+ return null;
157
+ }
1
158
  /**
2
- * Ensures that function metadata exists for a given pikkuFuncName.
159
+ * Ensures that function metadata exists for a given pikkuFuncId.
3
160
  * Creates stub metadata if it doesn't exist (useful for inline functions).
161
+ * When funcInitializer and checker are provided, resolves types and
162
+ * extracts tags/middleware/permissions from the pikkuFunc() config.
4
163
  */
5
- export function ensureFunctionMetadata(state, pikkuFuncName, fallbackName) {
6
- if (!state.functions.meta[pikkuFuncName]) {
7
- state.functions.meta[pikkuFuncName] = {
8
- pikkuFuncName,
9
- name: fallbackName || pikkuFuncName,
164
+ export function ensureFunctionMetadata(state, pikkuFuncId, fallbackName, funcInitializer, checker, isHelper) {
165
+ if (!state.functions.meta[pikkuFuncId]) {
166
+ state.functions.meta[pikkuFuncId] = {
167
+ pikkuFuncId,
168
+ functionType: isHelper ? 'helper' : 'inline',
169
+ name: fallbackName || pikkuFuncId,
10
170
  services: { optimized: false, services: [] },
11
171
  inputSchemaName: null,
12
172
  outputSchemaName: null,
@@ -15,4 +175,58 @@ export function ensureFunctionMetadata(state, pikkuFuncName, fallbackName) {
15
175
  middleware: undefined,
16
176
  };
17
177
  }
178
+ const meta = state.functions.meta[pikkuFuncId];
179
+ if (funcInitializer && checker) {
180
+ let pikkuFuncCall = null;
181
+ if (ts.isCallExpression(funcInitializer)) {
182
+ pikkuFuncCall = funcInitializer;
183
+ resolveFuncConfigTypes(state, pikkuFuncId, pikkuFuncCall, checker);
184
+ if (!state.typesLookup.has(pikkuFuncId)) {
185
+ populateTypesLookup(state, pikkuFuncId, pikkuFuncCall, checker);
186
+ }
187
+ }
188
+ else {
189
+ pikkuFuncCall = resolveToPikkuFuncCall(funcInitializer, checker);
190
+ }
191
+ if (pikkuFuncCall) {
192
+ const firstArg = pikkuFuncCall.arguments[0];
193
+ if (firstArg && ts.isObjectLiteralExpression(firstArg)) {
194
+ if (!meta.tags) {
195
+ const { tags } = getCommonWireMetaData(firstArg, 'Function', fallbackName || pikkuFuncId);
196
+ if (tags) {
197
+ meta.tags = tags;
198
+ }
199
+ }
200
+ if (!meta.middleware) {
201
+ meta.middleware = resolveMiddleware(state, firstArg, meta.tags, checker);
202
+ }
203
+ if (!meta.permissions) {
204
+ meta.permissions = resolvePermissions(state, firstArg, meta.tags, checker);
205
+ }
206
+ }
207
+ }
208
+ }
209
+ }
210
+ function populateTypesLookup(state, pikkuFuncId, funcInitializer, checker) {
211
+ const typeArgs = funcInitializer.typeArguments;
212
+ if (typeArgs && typeArgs.length >= 1) {
213
+ const inputType = checker.getTypeFromTypeNode(typeArgs[0]);
214
+ state.typesLookup.set(pikkuFuncId, [inputType]);
215
+ return;
216
+ }
217
+ const configType = checker.getTypeAtLocation(funcInitializer);
218
+ const funcProp = configType.getProperty('func');
219
+ if (!funcProp)
220
+ return;
221
+ const funcType = checker.getTypeOfSymbolAtLocation(funcProp, funcInitializer);
222
+ const sig = getFirstCallSignature(funcType);
223
+ if (!sig)
224
+ return;
225
+ const params = sig.getParameters();
226
+ if (params.length >= 2) {
227
+ const inputType = checker.getTypeOfSymbolAtLocation(params[1], funcInitializer);
228
+ if (!(inputType.flags & ts.TypeFlags.VoidLike)) {
229
+ state.typesLookup.set(pikkuFuncId, [inputType]);
230
+ }
231
+ }
18
232
  }
@@ -1,25 +1,14 @@
1
1
  import * as ts from 'typescript';
2
2
  export type ExtractedFunctionName = {
3
- pikkuFuncName: string;
3
+ pikkuFuncId: string;
4
4
  name: string;
5
5
  explicitName: string | null;
6
6
  exportedName: string | null;
7
- localName: string | null;
8
7
  propertyName: string | null;
8
+ isHelper: boolean;
9
9
  };
10
- /**
11
- * Generate a deterministic "anonymous" name for any expression node,
12
- * but if it's an Identifier pointing to a function, resolve it back
13
- * to the function's declaration (so you get the true source location).
14
- */
15
- export declare function makeDeterministicAnonName(start: ts.Node, checker: ts.TypeChecker, rootDir: string): string;
16
- /**
17
- * Updated function to extract and prioritize function names correctly
18
- * This function follows the priority:
19
- * 1. Object with a name property
20
- * 2. Exported name
21
- * 3. Fallback to deterministic name
22
- */
10
+ export declare function makeContextBasedId(wiringType: string, ...segments: string[]): string;
11
+ export declare function funcIdToTypeName(id: string): string;
23
12
  export declare function extractFunctionName(callExpr: ts.Node, checker: ts.TypeChecker, rootDir: string): ExtractedFunctionName;
24
13
  /**
25
14
  * Helper function to populate the 'name' field based on priority
@@ -28,4 +17,4 @@ export declare function populateNameByPriority(result: ExtractedFunctionName): v
28
17
  /**
29
18
  * Helper function to check if a variable declaration is a named export
30
19
  */
31
- export declare function isNamedExport(declaration: ts.VariableDeclaration): boolean;
20
+ export declare function isNamedExport(declaration: ts.VariableDeclaration, checker?: ts.TypeChecker): boolean;