@pikku/inspector 0.12.74 → 0.12.81

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 (219) hide show
  1. package/CHANGELOG.md +347 -0
  2. package/dist/add/add-analytics.d.ts +9 -0
  3. package/dist/add/add-analytics.js +178 -0
  4. package/dist/add/add-auth.js +0 -54
  5. package/dist/add/add-feature-flag.d.ts +2 -0
  6. package/dist/add/add-feature-flag.js +162 -0
  7. package/dist/add/add-wire-addon.js +1 -0
  8. package/dist/add/add-wire-remote-addon.js +1 -0
  9. package/dist/index.d.ts +3 -1
  10. package/dist/index.js +3 -1
  11. package/dist/inspector.js +4 -0
  12. package/dist/surface/collect-surface.d.ts +58 -0
  13. package/dist/surface/collect-surface.js +613 -0
  14. package/dist/types.d.ts +20 -11
  15. package/dist/utils/filter-inspector-state.js +23 -13
  16. package/dist/utils/post-process.js +15 -0
  17. package/dist/utils/read-module-specifiers.d.ts +8 -0
  18. package/dist/utils/read-module-specifiers.js +23 -0
  19. package/dist/utils/read-tsconfig-out-dir.d.ts +5 -0
  20. package/dist/utils/read-tsconfig-out-dir.js +12 -0
  21. package/dist/utils/resolve-deploy-target.d.ts +7 -0
  22. package/dist/utils/resolve-deploy-target.js +15 -7
  23. package/dist/utils/serialize-inspector-state.d.ts +5 -0
  24. package/dist/utils/serialize-inspector-state.js +8 -0
  25. package/dist/visit.js +4 -0
  26. package/package.json +16 -6
  27. package/run-tests.sh +21 -6
  28. package/src/add/add-addon-bans.ts +0 -85
  29. package/src/add/add-agent-scorer.test.ts +0 -197
  30. package/src/add/add-agent-scorer.ts +0 -83
  31. package/src/add/add-agent.test.ts +0 -87
  32. package/src/add/add-agent.ts +0 -638
  33. package/src/add/add-approval-description.ts +0 -76
  34. package/src/add/add-auth.test.ts +0 -791
  35. package/src/add/add-auth.ts +0 -424
  36. package/src/add/add-channel.ts +0 -778
  37. package/src/add/add-cli-renderers.test.ts +0 -74
  38. package/src/add/add-cli.ts +0 -1006
  39. package/src/add/add-credential.ts +0 -186
  40. package/src/add/add-feature.test.ts +0 -306
  41. package/src/add/add-feature.ts +0 -253
  42. package/src/add/add-file-extends-core-type.ts +0 -66
  43. package/src/add/add-file-with-config.ts +0 -45
  44. package/src/add/add-file-with-factory.test.ts +0 -134
  45. package/src/add/add-file-with-factory.ts +0 -288
  46. package/src/add/add-functions.test.ts +0 -743
  47. package/src/add/add-functions.ts +0 -1548
  48. package/src/add/add-gateway.ts +0 -143
  49. package/src/add/add-http-route-ref.test.ts +0 -149
  50. package/src/add/add-http-route.ts +0 -530
  51. package/src/add/add-http-routes.ts +0 -471
  52. package/src/add/add-keyed-wiring.ts +0 -180
  53. package/src/add/add-mcp-prompt.ts +0 -157
  54. package/src/add/add-mcp-resource.ts +0 -175
  55. package/src/add/add-middleware.test.ts +0 -196
  56. package/src/add/add-middleware.ts +0 -879
  57. package/src/add/add-permission-auth.test.ts +0 -59
  58. package/src/add/add-permission.ts +0 -311
  59. package/src/add/add-personas.test.ts +0 -406
  60. package/src/add/add-personas.ts +0 -287
  61. package/src/add/add-queue-worker.ts +0 -117
  62. package/src/add/add-rpc-invocations.test.ts +0 -287
  63. package/src/add/add-rpc-invocations.ts +0 -221
  64. package/src/add/add-scenario-step.test.ts +0 -509
  65. package/src/add/add-schedule.ts +0 -120
  66. package/src/add/add-scope.test.ts +0 -419
  67. package/src/add/add-scope.ts +0 -221
  68. package/src/add/add-secret.ts +0 -10
  69. package/src/add/add-subject-scenario-steps.test.ts +0 -161
  70. package/src/add/add-system-role.test.ts +0 -297
  71. package/src/add/add-system-role.ts +0 -162
  72. package/src/add/add-trigger.ts +0 -165
  73. package/src/add/add-variable.ts +0 -10
  74. package/src/add/add-wire-addon.test.ts +0 -185
  75. package/src/add/add-wire-addon.ts +0 -146
  76. package/src/add/add-wire-remote-addon.ts +0 -80
  77. package/src/add/add-workflow-edge-cases.test.ts +0 -201
  78. package/src/add/add-workflow-fanout.test.ts +0 -166
  79. package/src/add/add-workflow-graph-foreach.test.ts +0 -174
  80. package/src/add/add-workflow-graph-input.test.ts +0 -94
  81. package/src/add/add-workflow-graph-notes.test.ts +0 -74
  82. package/src/add/add-workflow-graph.ts +0 -644
  83. package/src/add/add-workflow-on-error.test.ts +0 -118
  84. package/src/add/add-workflow-return-switch.test.ts +0 -121
  85. package/src/add/add-workflow-silent-drops.test.ts +0 -261
  86. package/src/add/add-workflow-sleep-expression.test.ts +0 -96
  87. package/src/add/add-workflow.test.ts +0 -155
  88. package/src/add/add-workflow.ts +0 -482
  89. package/src/add/addon-bans.test.ts +0 -121
  90. package/src/add/addon-contracts.test.ts +0 -221
  91. package/src/add/allow-escape-hatches.test.ts +0 -144
  92. package/src/add/audit-meta.test.ts +0 -75
  93. package/src/add/classified-sink-check.test.ts +0 -347
  94. package/src/add/config-value-metadata.test.ts +0 -263
  95. package/src/add/dynamic-import-check.test.ts +0 -119
  96. package/src/add/expect-eventually-scenario-only.test.ts +0 -108
  97. package/src/add/function-body-span.test.ts +0 -96
  98. package/src/add/inline-wiring-function.test.ts +0 -104
  99. package/src/add/pii-check.test.ts +0 -258
  100. package/src/add/rpc-type-cast.test.ts +0 -123
  101. package/src/add/scenario-instrumentation.test.ts +0 -89
  102. package/src/add/scenario-instrumentation.ts +0 -42
  103. package/src/add/scenario-marker.test.ts +0 -89
  104. package/src/add/scenario-not-extractable.test.ts +0 -159
  105. package/src/add/scenario-services.test.ts +0 -103
  106. package/src/add/scenario-skip.test.ts +0 -83
  107. package/src/add/validate-workflow-graph-addons.test.ts +0 -102
  108. package/src/add/wire-name-literal.test.ts +0 -117
  109. package/src/error-codes-emitted.test.ts +0 -76
  110. package/src/error-codes.ts +0 -145
  111. package/src/index.ts +0 -66
  112. package/src/inspector.ts +0 -575
  113. package/src/schema-generator.ts +0 -1
  114. package/src/source-file-cache.ts +0 -73
  115. package/src/tsconfig-paths.test.ts +0 -90
  116. package/src/types-map.ts +0 -141
  117. package/src/types.ts +0 -775
  118. package/src/utils/annotate-http-route-auth.test.ts +0 -161
  119. package/src/utils/annotate-http-route-auth.ts +0 -53
  120. package/src/utils/check-classified-sinks.ts +0 -215
  121. package/src/utils/check-pii-output.ts +0 -120
  122. package/src/utils/compute-diagnostics.test.ts +0 -106
  123. package/src/utils/compute-required-schemas.ts +0 -48
  124. package/src/utils/contract-hashes.test.ts +0 -553
  125. package/src/utils/contract-hashes.ts +0 -387
  126. package/src/utils/custom-types-generator.test.ts +0 -124
  127. package/src/utils/custom-types-generator.ts +0 -150
  128. package/src/utils/detect-schema-vendor.test.ts +0 -123
  129. package/src/utils/detect-schema-vendor.ts +0 -120
  130. package/src/utils/does-type-extend-core-type.ts +0 -53
  131. package/src/utils/ensure-function-metadata.ts +0 -385
  132. package/src/utils/extract-function-name.ts +0 -612
  133. package/src/utils/extract-function-node.ts +0 -70
  134. package/src/utils/extract-node-value.test.ts +0 -117
  135. package/src/utils/extract-node-value.ts +0 -172
  136. package/src/utils/extract-secret-usage.test.ts +0 -81
  137. package/src/utils/extract-secret-usage.ts +0 -73
  138. package/src/utils/extract-services.ts +0 -70
  139. package/src/utils/extract-surface-usage.test.ts +0 -147
  140. package/src/utils/extract-surface-usage.ts +0 -121
  141. package/src/utils/filter-inspector-state.test.ts +0 -2207
  142. package/src/utils/filter-inspector-state.ts +0 -1302
  143. package/src/utils/filter-utils.test.ts +0 -843
  144. package/src/utils/filter-utils.ts +0 -161
  145. package/src/utils/find-root-dir.ts +0 -68
  146. package/src/utils/find-zod-transform.test.ts +0 -70
  147. package/src/utils/find-zod-transform.ts +0 -103
  148. package/src/utils/get-exported-variable-name.ts +0 -48
  149. package/src/utils/get-files-and-methods.ts +0 -157
  150. package/src/utils/get-property-value.test.ts +0 -141
  151. package/src/utils/get-property-value.ts +0 -331
  152. package/src/utils/hash.ts +0 -26
  153. package/src/utils/literal-properties.ts +0 -97
  154. package/src/utils/load-addon-functions-meta.test.ts +0 -157
  155. package/src/utils/load-addon-functions-meta.ts +0 -508
  156. package/src/utils/load-addon-scopes.test.ts +0 -138
  157. package/src/utils/middleware.test.ts +0 -204
  158. package/src/utils/middleware.ts +0 -303
  159. package/src/utils/nested-project-filter.test.ts +0 -53
  160. package/src/utils/nested-project-filter.ts +0 -28
  161. package/src/utils/permissions-shorthand.test.ts +0 -79
  162. package/src/utils/permissions.test.ts +0 -125
  163. package/src/utils/permissions.ts +0 -129
  164. package/src/utils/post-process.test.ts +0 -1094
  165. package/src/utils/post-process.ts +0 -1604
  166. package/src/utils/resolve-addon-package.ts +0 -106
  167. package/src/utils/resolve-core-type.test.ts +0 -142
  168. package/src/utils/resolve-core-type.ts +0 -35
  169. package/src/utils/resolve-deploy-target.test.ts +0 -135
  170. package/src/utils/resolve-deploy-target.ts +0 -65
  171. package/src/utils/resolve-function-meta.ts +0 -25
  172. package/src/utils/resolve-function-types.ts +0 -42
  173. package/src/utils/resolve-identifier.ts +0 -46
  174. package/src/utils/resolve-ref-contract.ts +0 -71
  175. package/src/utils/resolve-versions.test.ts +0 -499
  176. package/src/utils/resolve-versions.ts +0 -228
  177. package/src/utils/schema-cache.test.ts +0 -124
  178. package/src/utils/schema-generator.test.ts +0 -272
  179. package/src/utils/schema-generator.ts +0 -780
  180. package/src/utils/secret-alias-services.test.ts +0 -146
  181. package/src/utils/secret-alias-services.ts +0 -58
  182. package/src/utils/serialize-inspector-state.ts +0 -742
  183. package/src/utils/serialize-mcp-json.ts +0 -150
  184. package/src/utils/serialize-middleware-groups-meta.ts +0 -36
  185. package/src/utils/serialize-openapi-json.ts +0 -277
  186. package/src/utils/serialize-permissions-groups-meta.ts +0 -7
  187. package/src/utils/single-declaration.ts +0 -57
  188. package/src/utils/type-utils.ts +0 -145
  189. package/src/utils/validate-auth-sessionless.ts +0 -30
  190. package/src/utils/validate-exposed-functions-gated.test.ts +0 -230
  191. package/src/utils/validate-exposed-functions-gated.ts +0 -103
  192. package/src/utils/validate-tags-resolve-to-middleware.test.ts +0 -108
  193. package/src/utils/validate-tags-resolve-to-middleware.ts +0 -48
  194. package/src/utils/workflow/derive-workflow-plan.test.ts +0 -178
  195. package/src/utils/workflow/derive-workflow-plan.ts +0 -117
  196. package/src/utils/workflow/dsl/deserialize-dsl-workflow.ts +0 -1465
  197. package/src/utils/workflow/dsl/deserialize-fanout-body.test.ts +0 -71
  198. package/src/utils/workflow/dsl/deserialize-fanout-fidelity.test.ts +0 -99
  199. package/src/utils/workflow/dsl/deserialize-graph-next.test.ts +0 -161
  200. package/src/utils/workflow/dsl/deserialize-roundtrip-bindings.test.ts +0 -121
  201. package/src/utils/workflow/dsl/deserialize-roundtrip-values.test.ts +0 -116
  202. package/src/utils/workflow/dsl/deserialize-roundtrip.test.ts +0 -145
  203. package/src/utils/workflow/dsl/extract-approval-policy.test.ts +0 -71
  204. package/src/utils/workflow/dsl/extract-dsl-workflow.ts +0 -2254
  205. package/src/utils/workflow/dsl/index.ts +0 -11
  206. package/src/utils/workflow/dsl/patterns.ts +0 -440
  207. package/src/utils/workflow/dsl/validation.ts +0 -203
  208. package/src/utils/workflow/graph/convert-dsl-to-graph-skip.test.ts +0 -35
  209. package/src/utils/workflow/graph/convert-dsl-to-graph.ts +0 -543
  210. package/src/utils/workflow/graph/fanout-node-identity.test.ts +0 -105
  211. package/src/utils/workflow/graph/finalize-workflow-wires.ts +0 -310
  212. package/src/utils/workflow/graph/finalize-workflows.test.ts +0 -50
  213. package/src/utils/workflow/graph/finalize-workflows.ts +0 -130
  214. package/src/utils/workflow/graph/index.ts +0 -28
  215. package/src/utils/workflow/graph/serialize-workflow-graph.ts +0 -240
  216. package/src/utils/workflow/graph/workflow-graph.types.ts +0 -281
  217. package/src/visit.ts +0 -181
  218. package/tsconfig.json +0 -19
  219. package/tsconfig.tsbuildinfo +0 -1
@@ -1,530 +0,0 @@
1
- import * as ts from 'typescript'
2
- import {
3
- getPropertyValue,
4
- getCommonWireMetaData,
5
- } from '../utils/get-property-value.js'
6
- import { pathToRegexp } from 'path-to-regexp'
7
- import type { HTTPMethod } from '@pikku/core/http'
8
- import {
9
- extractFunctionName,
10
- makeContextBasedId,
11
- } from '../utils/extract-function-name.js'
12
- import {
13
- getPropertyAssignmentInitializer,
14
- extractTypeKeys,
15
- } from '../utils/type-utils.js'
16
- import type {
17
- AddWiring,
18
- ExportedHTTPRouteConfigMeta,
19
- InspectorState,
20
- } from '../types.js'
21
- import { resolveHTTPMiddlewareFromObject } from '../utils/middleware.js'
22
- import { resolvePermissions } from '../utils/permissions.js'
23
- import { extractWireNames } from '../utils/post-process.js'
24
- import { ensureFunctionMetadata } from '../utils/ensure-function-metadata.js'
25
- import { resolveFunctionMeta } from '../utils/resolve-function-meta.js'
26
- import { ErrorCode } from '../error-codes.js'
27
- import { validateAuthSessionless } from '../utils/validate-auth-sessionless.js'
28
- import { detectSchemaVendorOrError } from '../utils/detect-schema-vendor.js'
29
- import { resolveAddonName } from '../utils/resolve-addon-package.js'
30
-
31
- import type { InspectorLogger } from '../types.js'
32
-
33
- /**
34
- * Parameters for registering an HTTP route
35
- */
36
- export interface RegisterHTTPRouteParams {
37
- obj: ts.ObjectLiteralExpression
38
- state: InspectorState
39
- checker: ts.TypeChecker
40
- logger: InspectorLogger
41
- sourceFile: ts.SourceFile
42
- basePath?: string
43
- inheritedTags?: string[]
44
- inheritedAuth?: boolean
45
- }
46
-
47
- export interface RegisterHTTPRouteMetaParams {
48
- route: ExportedHTTPRouteConfigMeta
49
- state: InspectorState
50
- logger: InspectorLogger
51
- sourceFile: ts.SourceFile
52
- basePath?: string
53
- inheritedTags?: string[]
54
- inheritedAuth?: boolean
55
- }
56
-
57
- /**
58
- * Extract header schema reference from headers property
59
- */
60
- const extractHeadersSchema = (
61
- obj: ts.ObjectLiteralExpression,
62
- routeName: string,
63
- method: string,
64
- state: InspectorState,
65
- checker: ts.TypeChecker,
66
- logger: InspectorLogger
67
- ): string | undefined => {
68
- const headersNode = getPropertyAssignmentInitializer(
69
- obj,
70
- 'headers',
71
- true,
72
- checker
73
- )
74
- if (!headersNode || !ts.isIdentifier(headersNode)) return undefined
75
-
76
- // Resolve the schema reference
77
- const symbol = checker.getSymbolAtLocation(headersNode)
78
- if (!symbol) return undefined
79
-
80
- const decl = symbol.valueDeclaration || symbol.declarations?.[0]
81
- if (!decl) return undefined
82
-
83
- let sourceFile: string
84
- if (ts.isImportSpecifier(decl)) {
85
- const aliasedSymbol = checker.getAliasedSymbol(symbol)
86
- if (aliasedSymbol) {
87
- const aliasedDecl =
88
- aliasedSymbol.valueDeclaration || aliasedSymbol.declarations?.[0]
89
- if (aliasedDecl) {
90
- sourceFile = aliasedDecl.getSourceFile().fileName
91
- } else {
92
- return undefined
93
- }
94
- } else {
95
- return undefined
96
- }
97
- } else {
98
- sourceFile = decl.getSourceFile().fileName
99
- }
100
-
101
- const vendor = detectSchemaVendorOrError(
102
- headersNode,
103
- checker,
104
- logger,
105
- `Route '${routeName}' header`,
106
- sourceFile
107
- )
108
- if (!vendor) return undefined
109
-
110
- // Create a sanitized schema name from route and method to avoid collisions
111
- const sanitizedRoute = routeName
112
- .replace(/[^a-zA-Z0-9]/g, '_')
113
- .replace(/^_+|_+$/g, '')
114
- const schemaName = `${method.toUpperCase()}_${sanitizedRoute}_Headers`
115
-
116
- state.schemaLookup.set(schemaName, {
117
- variableName: headersNode.text,
118
- sourceFile,
119
- vendor,
120
- })
121
-
122
- return schemaName
123
- }
124
-
125
- /**
126
- * Populate metaInputTypes for a given route based on method, input type,
127
- * query and params.
128
- */
129
- const computeInputTypes = (
130
- metaTypes: Map<
131
- string,
132
- { query?: string[]; params?: string[]; body?: string[] }
133
- >,
134
- methodType: string,
135
- inputType: string | null,
136
- queryValues: string[],
137
- paramsValues: string[]
138
- ): void => {
139
- if (!inputType) return
140
- metaTypes.set(inputType, {
141
- query: queryValues,
142
- params: paramsValues,
143
- body: ['post', 'put', 'patch'].includes(methodType)
144
- ? [...new Set([...queryValues, ...paramsValues])]
145
- : [],
146
- })
147
- }
148
-
149
- /**
150
- * Shared function to register an HTTP route in the inspector state.
151
- * Used by both wireHTTP and wireHTTPRoutes.
152
- */
153
- export function registerHTTPRoute({
154
- obj,
155
- state,
156
- checker,
157
- logger,
158
- sourceFile,
159
- basePath = '',
160
- inheritedTags = [],
161
- inheritedAuth,
162
- }: RegisterHTTPRouteParams): void {
163
- // Extract route path
164
- const routePath = getPropertyValue(obj, 'route') as string | null
165
- if (!routePath) return
166
-
167
- const method = (
168
- (getPropertyValue(obj, 'method') as string) || 'get'
169
- ).toLowerCase()
170
- const fullRoute = basePath + routePath
171
-
172
- // Extract params from route path
173
- let params: string[] = []
174
- try {
175
- const keys = pathToRegexp(fullRoute).keys
176
- params = keys.filter((k) => k.type === 'param').map((k) => k.name)
177
- } catch (e) {
178
- logger.error(
179
- `Failed to parse route '${fullRoute}': ${e instanceof Error ? e.message : e}`
180
- )
181
- return
182
- }
183
-
184
- // Get common metadata
185
- const {
186
- disabled,
187
- title,
188
- tags: routeTags,
189
- summary,
190
- description,
191
- errors,
192
- } = getCommonWireMetaData(obj, 'HTTP route', fullRoute, logger, checker)
193
-
194
- if (disabled) return
195
-
196
- // Merge inherited tags with route tags
197
- const tags = [...inheritedTags, ...(routeTags || [])]
198
-
199
- const query = (getPropertyValue(obj, 'query') as string[]) || []
200
-
201
- // Get function reference
202
- const funcInitializer = getPropertyAssignmentInitializer(
203
- obj,
204
- 'func',
205
- true,
206
- checker
207
- )
208
- if (!funcInitializer) {
209
- logger.critical(
210
- ErrorCode.MISSING_FUNC,
211
- `No valid 'func' property for route '${fullRoute}'.`
212
- )
213
- return
214
- }
215
-
216
- const extracted = extractFunctionName(funcInitializer, checker, state.rootDir)
217
- let funcName = extracted.pikkuFuncId
218
- if (funcName.startsWith('__temp_')) {
219
- funcName = makeContextBasedId('http', method, fullRoute)
220
- }
221
-
222
- let refAddonTarget: string | null = null
223
- if (
224
- ts.isCallExpression(funcInitializer) &&
225
- ts.isIdentifier(funcInitializer.expression) &&
226
- funcInitializer.expression.text === 'ref'
227
- ) {
228
- const [firstArg] = funcInitializer.arguments
229
- if (
230
- firstArg &&
231
- ts.isStringLiteral(firstArg) &&
232
- firstArg.text.includes(':')
233
- ) {
234
- refAddonTarget = firstArg.text
235
- }
236
- }
237
-
238
- const packageName = ts.isIdentifier(funcInitializer)
239
- ? resolveAddonName(
240
- funcInitializer,
241
- checker,
242
- state.rpc.wireAddonDeclarations
243
- )
244
- : null
245
-
246
- // A ref()-wired route points straight at the addon function, the same way the
247
- // CLI and channel adders record one. The addon's own metadata is the contract
248
- // — and it is authoritative where the checker is not: `ref('ns:fn')` only
249
- // types precisely once the consumer's own rpc map already lists the addon's
250
- // functions, so a cold run inferred the whole `FlattenedRPCMap` and a warm one
251
- // inferred the real input. The addon's metadata says which it is either way.
252
- //
253
- // The route stays the consuming app's all the same, so it records no
254
- // packageName: that names the package a wire *runs in*, and running this one
255
- // inside the addon would hand it the addon's middleware and services instead
256
- // of the app's. `ref` reaches the addon over RPC, which enters it properly.
257
- if (refAddonTarget) {
258
- const targetMeta = resolveFunctionMeta(state, refAddonTarget)
259
- if (!targetMeta) {
260
- logger.warn(
261
- `Skipping route '${fullRoute}': addon function metadata for '${refAddonTarget}' is not available yet.`
262
- )
263
- return
264
- }
265
- funcName = refAddonTarget
266
- } else {
267
- ensureFunctionMetadata(
268
- state,
269
- funcName,
270
- fullRoute,
271
- funcInitializer,
272
- checker,
273
- extracted.isHelper
274
- )
275
- }
276
-
277
- // The route's own `auth`, falling back to the group's. Recorded on the meta
278
- // below so an audit can answer "is this route open?" without re-reading the
279
- // source: the route can tighten a sessionless function, and until this was
280
- // written down that tightening existed only in the wiring.
281
- const routeAuthProp = getPropertyValue(obj, 'auth')
282
- const resolvedAuth =
283
- routeAuthProp === true || routeAuthProp === false
284
- ? routeAuthProp
285
- : inheritedAuth
286
-
287
- // For inline functions (e.g. oauth2 handlers), propagate sessionless: true
288
- // when auth is explicitly disabled at the route or group level — the
289
- // developer opted out of auth so no session is required.
290
- {
291
- const inlineMeta = state.functions.meta[funcName]
292
- if (
293
- inlineMeta &&
294
- inlineMeta.sessionless === undefined &&
295
- resolvedAuth === false
296
- ) {
297
- inlineMeta.sessionless = true
298
- }
299
- }
300
-
301
- // Lookup existing function metadata
302
- const fnMeta = resolveFunctionMeta(state, funcName)
303
- if (!fnMeta) {
304
- logger.critical(
305
- ErrorCode.FUNCTION_METADATA_NOT_FOUND,
306
- `No function metadata found for '${funcName}'.`
307
- )
308
- return
309
- }
310
-
311
- if (
312
- !validateAuthSessionless(
313
- logger,
314
- obj,
315
- state,
316
- funcName,
317
- `Route '${fullRoute}'`,
318
- inheritedAuth
319
- )
320
- ) {
321
- return
322
- }
323
-
324
- const input = fnMeta.inputs?.[0] || null
325
-
326
- const getRouteInputKeys = (): string[] | null => {
327
- const inputTypes = state.typesLookup.get(funcName)
328
- if (inputTypes && inputTypes.length > 0) {
329
- return extractTypeKeys(inputTypes[0])
330
- }
331
-
332
- const targetMeta = resolveFunctionMeta(state, funcName)
333
- if (targetMeta?.inputSchemaName) {
334
- const schema = state.schemas[targetMeta.inputSchemaName] as any
335
- const properties = schema?.properties
336
- if (properties && typeof properties === 'object') {
337
- return Object.keys(properties)
338
- }
339
- }
340
-
341
- return null
342
- }
343
-
344
- // Validate that route params and query params exist in function input type
345
- if (params.length > 0 || query.length > 0) {
346
- const inputKeys = getRouteInputKeys()
347
- if (!inputKeys) {
348
- // Input shape isn't inspectable at this phase (e.g. addon ref or opaque handler).
349
- // Skip param/query validation rather than emitting a false positive.
350
- } else {
351
- // Check path params
352
- if (params.length > 0) {
353
- const missingParams = params.filter((p) => !inputKeys.includes(p))
354
- if (missingParams.length > 0) {
355
- logger.critical(
356
- ErrorCode.ROUTE_PARAM_MISMATCH,
357
- `Route '${fullRoute}' has path parameter(s) [${missingParams.join(', ')}] ` +
358
- `not found in function '${funcName}' input type. ` +
359
- `Input type has: [${inputKeys.join(', ')}]`
360
- )
361
- return
362
- }
363
- }
364
-
365
- // Check query params
366
- if (query.length > 0) {
367
- const missingQuery = query.filter((q) => !inputKeys.includes(q))
368
- if (missingQuery.length > 0) {
369
- logger.critical(
370
- ErrorCode.ROUTE_QUERY_MISMATCH,
371
- `Route '${fullRoute}' has query parameter(s) [${missingQuery.join(', ')}] ` +
372
- `not found in function '${funcName}' input type. ` +
373
- `Input type has: [${inputKeys.join(', ')}]`
374
- )
375
- return
376
- }
377
- }
378
- }
379
- }
380
-
381
- // Compute inputTypes (body/query/params)
382
- computeInputTypes(state.http.metaInputTypes, method, input, query, params)
383
-
384
- // Resolve middleware
385
- const middleware = resolveHTTPMiddlewareFromObject(
386
- state,
387
- fullRoute,
388
- obj,
389
- tags,
390
- checker
391
- )
392
-
393
- // Resolve permissions
394
- const permissions = resolvePermissions(state, obj, tags, checker)
395
-
396
- state.serviceAggregation.usedFunctions.add(funcName)
397
- extractWireNames(middleware).forEach((name) =>
398
- state.serviceAggregation.usedMiddleware.add(name)
399
- )
400
- extractWireNames(permissions).forEach((name) =>
401
- state.serviceAggregation.usedPermissions.add(name)
402
- )
403
-
404
- // Check for SSE
405
- const sse = getPropertyValue(obj, 'sse') === true
406
-
407
- // Extract header schema
408
- const headersSchemaName = extractHeadersSchema(
409
- obj,
410
- fullRoute,
411
- method,
412
- state,
413
- checker,
414
- logger
415
- )
416
-
417
- // Record route
418
- state.http.files.add(sourceFile.fileName)
419
- state.http.meta[method][fullRoute] = {
420
- pikkuFuncId: funcName,
421
- ...(packageName && { packageName }),
422
- route: fullRoute,
423
- sourceFile: sourceFile.fileName,
424
- method: method as HTTPMethod,
425
- ...(resolvedAuth !== undefined && { auth: resolvedAuth }),
426
- params: params.length > 0 ? params : undefined,
427
- query: query.length > 0 ? query : undefined,
428
- inputTypes: undefined,
429
- title,
430
- summary,
431
- description,
432
- errors,
433
- tags: tags.length > 0 ? tags : undefined,
434
- middleware,
435
- permissions,
436
- sse: sse ? true : undefined,
437
- headersSchemaName,
438
- groupBasePath: basePath || undefined,
439
- }
440
- }
441
-
442
- export function registerHTTPRouteMeta({
443
- route,
444
- state,
445
- logger,
446
- sourceFile,
447
- basePath = '',
448
- inheritedTags = [],
449
- inheritedAuth,
450
- }: RegisterHTTPRouteMetaParams): void {
451
- const method = route.method.toLowerCase()
452
- const fullRoute = basePath + route.route
453
- const tags = [...inheritedTags, ...(route.tags || [])]
454
- const funcName = route.func.pikkuFuncId
455
- const fnMeta = resolveFunctionMeta(state, funcName)
456
-
457
- if (!fnMeta) {
458
- logger.critical(
459
- ErrorCode.FUNCTION_METADATA_NOT_FOUND,
460
- `No function metadata found for '${funcName}'.`
461
- )
462
- return
463
- }
464
-
465
- let params: string[] = []
466
- try {
467
- const keys = pathToRegexp(fullRoute).keys
468
- params = keys.filter((k) => k.type === 'param').map((k) => k.name)
469
- } catch (error) {
470
- logger.error(
471
- `Failed to parse route '${fullRoute}': ${error instanceof Error ? error.message : error}`
472
- )
473
- return
474
- }
475
-
476
- if (!route.func.packageName) {
477
- computeInputTypes(
478
- state.http.metaInputTypes,
479
- method,
480
- fnMeta.inputs?.[0] || null,
481
- [],
482
- params
483
- )
484
- }
485
-
486
- state.serviceAggregation.usedFunctions.add(funcName)
487
- state.http.files.add(sourceFile.fileName)
488
- state.http.meta[method][fullRoute] = {
489
- pikkuFuncId: funcName,
490
- ...(route.func.packageName && { packageName: route.func.packageName }),
491
- route: fullRoute,
492
- sourceFile: sourceFile.fileName,
493
- method: method as HTTPMethod,
494
- ...((route.auth ?? inheritedAuth) !== undefined && {
495
- auth: route.auth ?? inheritedAuth,
496
- }),
497
- params: params.length > 0 ? params : undefined,
498
- inputTypes: undefined,
499
- tags: tags.length > 0 ? tags : undefined,
500
- sse: route.sse ? true : undefined,
501
- groupBasePath: basePath || undefined,
502
- }
503
- }
504
-
505
- /**
506
- * Process wireHTTP calls
507
- */
508
- export const addHTTPRoute: AddWiring = (
509
- logger,
510
- node,
511
- checker,
512
- state,
513
- _options
514
- ) => {
515
- if (!ts.isCallExpression(node)) return
516
-
517
- const { expression, arguments: args } = node
518
- if (!ts.isIdentifier(expression) || expression.text !== 'wireHTTP') return
519
-
520
- const firstArg = args[0]
521
- if (!firstArg || !ts.isObjectLiteralExpression(firstArg)) return
522
-
523
- registerHTTPRoute({
524
- obj: firstArg,
525
- state,
526
- checker,
527
- logger,
528
- sourceFile: node.getSourceFile(),
529
- })
530
- }