@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
package/src/inspector.ts DELETED
@@ -1,575 +0,0 @@
1
- import * as ts from 'typescript'
2
- import { performance } from 'perf_hooks'
3
- import { dirname, relative, resolve } from 'path'
4
- import { visitSetup, visitFunctions, visitRoutes } from './visit.js'
5
- import { TypesMap } from './types-map.js'
6
- import type {
7
- InspectorState,
8
- InspectorLogger,
9
- InspectorOptions,
10
- } from './types.js'
11
- import { getFilesAndMethods } from './utils/get-files-and-methods.js'
12
- import { findCommonAncestor } from './utils/find-root-dir.js'
13
- import { createSourceFileCacheHost } from './source-file-cache.js'
14
- import { createNestedProjectFilter } from './utils/nested-project-filter.js'
15
- import {
16
- aggregateRequiredServices,
17
- stampAuthHandlerServices,
18
- validateAgentModels,
19
- validateAgentToolReferences,
20
- validateAgentScorerReferences,
21
- validateSecretOverrides,
22
- validateVariableOverrides,
23
- validateCredentialOverrides,
24
- validateRemoteAddonDependencies,
25
- validateRemoteAddonAuth,
26
- validateScopeReferences,
27
- validateSystemRoleScopes,
28
- validatePersonaRoles,
29
- computeResolvedIOTypes,
30
- computeMiddlewareGroupsMeta,
31
- computePermissionsGroupsMeta,
32
- computeRequiredSchemas,
33
- validateNoSecretAliasServices,
34
- validateSecretUsage,
35
- computeDiagnostics,
36
- validateSchemaReferences,
37
- validateSchemaWiringSeparation,
38
- validateScenarioServices,
39
- validateScenarioSteps,
40
- validateWorkflowGraphAddons,
41
- } from './utils/post-process.js'
42
- import { validateExposedFunctionsGated } from './utils/validate-exposed-functions-gated.js'
43
- import { validateTagsResolveToMiddleware } from './utils/validate-tags-resolve-to-middleware.js'
44
- import { annotateHttpRouteAuth } from './utils/annotate-http-route-auth.js'
45
- import { generateOpenAPISpec } from './utils/serialize-openapi-json.js'
46
- import { pikkuState } from '@pikku/core/state'
47
- import { resolveLatestVersions } from './utils/resolve-versions.js'
48
- import { finalizeWorkflows } from './utils/workflow/graph/finalize-workflows.js'
49
- import {
50
- finalizeWorkflowHelperTypes,
51
- finalizeWorkflowWires,
52
- } from './utils/workflow/graph/finalize-workflow-wires.js'
53
- import { generateAllSchemas } from './utils/schema-generator.js'
54
- import { extractSecretUsage } from './utils/extract-secret-usage.js'
55
- import {
56
- accumulateSurfaceUsage,
57
- surfaceUsageArea,
58
- } from './utils/extract-surface-usage.js'
59
- import {
60
- loadAddonFunctionsMeta,
61
- loadAddonSchemas,
62
- } from './utils/load-addon-functions-meta.js'
63
- import {
64
- computeContractHashes,
65
- extractContractsFromMeta,
66
- updateManifest,
67
- createEmptyManifest,
68
- validateContracts,
69
- } from './utils/contract-hashes.js'
70
-
71
- /**
72
- * Creates an initial/empty inspector state with all required properties initialized
73
- * @param rootDir - The root directory for the project
74
- * @returns A fresh InspectorState with empty collections
75
- */
76
- export function getInitialInspectorState(rootDir: string): InspectorState {
77
- return {
78
- rootDir,
79
- singletonServicesTypeImportMap: new Map(),
80
- wireServicesTypeImportMap: new Map(),
81
- userSessionTypeImportMap: new Map(),
82
- configTypeImportMap: new Map(),
83
- singletonServicesFactories: new Map(),
84
- wireServicesFactories: new Map(),
85
- wireServicesMeta: new Map(),
86
- addonRequiredParentServices: [],
87
- addonCreatedServices: [],
88
- addonServicesFactorySeen: false,
89
- addonServerlessIncompatible: new Map(),
90
- configFactories: new Map(),
91
- serverLifecycleFactories: new Map(),
92
- filesAndMethods: {},
93
- filesAndMethodsErrors: new Map(),
94
- typesLookup: new Map(),
95
- schemaLookup: new Map(),
96
- schemas: {},
97
- functions: {
98
- typesMap: new TypesMap(),
99
- meta: {},
100
- files: new Map(),
101
- approvalDescriptions: {},
102
- dynamicImportIds: new Set(),
103
- },
104
- http: {
105
- metaInputTypes: new Map(),
106
- meta: {
107
- get: {},
108
- post: {},
109
- put: {},
110
- delete: {},
111
- head: {},
112
- patch: {},
113
- options: {},
114
- },
115
- files: new Set(),
116
- routeMiddleware: new Map(),
117
- },
118
- channels: {
119
- files: new Set(),
120
- meta: {},
121
- },
122
- gateways: {
123
- meta: {},
124
- files: new Set(),
125
- },
126
- triggers: {
127
- meta: {},
128
- sourceMeta: {},
129
- files: new Set(),
130
- },
131
- scheduledTasks: {
132
- meta: {},
133
- files: new Set(),
134
- },
135
- queueWorkers: {
136
- meta: {},
137
- files: new Set(),
138
- },
139
- workflows: {
140
- meta: {},
141
- files: new Map(),
142
- graphMeta: {},
143
- graphFiles: new Map(),
144
- featureFiles: new Map(),
145
- invokedWorkflows: new Set(),
146
- },
147
- rpc: {
148
- internalMeta: {},
149
- internalFiles: new Map(),
150
- exposedMeta: {},
151
- exposedFiles: new Map(),
152
- remoteMeta: {},
153
- remoteFiles: new Map(),
154
- invokedFunctions: new Set(),
155
- invokedFunctionsByFile: new Map(),
156
- usedAddons: new Set(),
157
- wireAddonDeclarations: new Map(),
158
- wireAddonFiles: new Set(),
159
- },
160
- mcpEndpoints: {
161
- resourcesMeta: {},
162
- toolsMeta: {},
163
- promptsMeta: {},
164
- files: new Set(),
165
- },
166
- agents: {
167
- agentsMeta: {},
168
- files: new Map(),
169
- invokedAgentsByFile: new Map(),
170
- },
171
- scorers: {
172
- scorersMeta: {},
173
- files: new Map(),
174
- },
175
- cli: {
176
- meta: {
177
- programs: {},
178
- renderers: {},
179
- },
180
- files: new Set(),
181
- },
182
- nodes: {
183
- meta: {},
184
- files: new Set(),
185
- },
186
- auth: {
187
- providers: [],
188
- plugins: [],
189
- files: new Set(),
190
- definition: null,
191
- },
192
- secrets: {
193
- definitions: [],
194
- files: new Set(),
195
- usage: new Map(),
196
- },
197
- surfaceUsage: {},
198
- credentials: {
199
- definitions: [],
200
- files: new Set(),
201
- },
202
- scopes: {
203
- definitions: [],
204
- files: new Set(),
205
- },
206
- systemRoles: {
207
- definitions: [],
208
- files: new Set(),
209
- },
210
- personas: {
211
- definitions: [],
212
- files: new Set(),
213
- },
214
- variables: {
215
- definitions: [],
216
- files: new Set(),
217
- },
218
- manifest: {
219
- initial: null,
220
- current: null,
221
- errors: [],
222
- },
223
- middleware: {
224
- definitions: {},
225
- instances: {},
226
- tagMiddleware: new Map(),
227
- },
228
- channelMiddleware: {
229
- definitions: {},
230
- instances: {},
231
- tagMiddleware: new Map(),
232
- },
233
- agentMiddleware: {
234
- definitions: {},
235
- },
236
- permissions: {
237
- definitions: {},
238
- instances: {},
239
- },
240
- serviceAggregation: {
241
- requiredServices: new Set(),
242
- usedFunctions: new Set(),
243
- usedMiddleware: new Set(),
244
- usedPermissions: new Set(),
245
- allSingletonServices: [],
246
- allWireServices: [],
247
- },
248
- resolvedIOTypes: {},
249
- middlewareGroupsMeta: {
250
- definitions: {},
251
- instances: {},
252
- httpGroups: {},
253
- tagGroups: {},
254
- channelMiddleware: {
255
- definitions: {},
256
- instances: {},
257
- tagGroups: {},
258
- },
259
- },
260
- permissionsGroupsMeta: {
261
- definitions: {},
262
- },
263
- requiredSchemas: new Set(),
264
- openAPISpec: null,
265
- diagnostics: [],
266
- addonFunctions: {},
267
- exportedContracts: {
268
- http: {},
269
- cli: {},
270
- channel: {},
271
- addonHttp: {},
272
- addonCli: {},
273
- addonChannel: {},
274
- },
275
- program: null,
276
- }
277
- }
278
-
279
- /**
280
- * The path mappings the inspector's program has to share with the project.
281
- *
282
- * The inspector builds its own program rather than reusing the project's, which
283
- * is what keeps a cold run affordable — but a project that reaches its generated
284
- * code through a tsconfig `paths` entry resolves that import through those
285
- * mappings and nothing else. Without them the factory an inspected function is
286
- * passed to resolves to `any`, so a function whose input type comes from the
287
- * factory's contextual type (rather than an explicit generic or a named schema)
288
- * silently records no input at all.
289
- *
290
- * Only resolution keys are copied. Type-inference options such as `strict` stay
291
- * the inspector's own, because changing those would change the recorded types.
292
- */
293
- const readProjectPathMappings = (
294
- logger: InspectorLogger,
295
- tsconfig: string | undefined
296
- ): ts.CompilerOptions => {
297
- if (!tsconfig) {
298
- return {}
299
- }
300
- const configPath = resolve(tsconfig)
301
- const configFile = ts.readConfigFile(configPath, ts.sys.readFile)
302
- if (configFile.error || !configFile.config) {
303
- logger.debug(
304
- `Could not read ${configPath} for path mappings; imports that rely on them will not resolve`
305
- )
306
- return {}
307
- }
308
- const { options: projectOptions } = ts.parseJsonConfigFileContent(
309
- configFile.config,
310
- ts.sys,
311
- dirname(configPath)
312
- )
313
- const { baseUrl, paths, rootDirs, pathsBasePath } = projectOptions
314
- return {
315
- ...(baseUrl !== undefined ? { baseUrl } : {}),
316
- ...(paths !== undefined ? { paths } : {}),
317
- ...(rootDirs !== undefined ? { rootDirs } : {}),
318
- ...(pathsBasePath !== undefined ? { pathsBasePath } : {}),
319
- }
320
- }
321
-
322
- export const inspect = async (
323
- logger: InspectorLogger,
324
- routeFiles: string[],
325
- options: InspectorOptions = {}
326
- ): Promise<InspectorState> => {
327
- const normalizedRouteFiles = routeFiles.map((file) => resolve(file))
328
- const compilerOptions: ts.CompilerOptions = {
329
- ...readProjectPathMappings(logger, options.tsconfig),
330
- target: ts.ScriptTarget.ESNext,
331
- module: ts.ModuleKind.Node16,
332
- skipLibCheck: true,
333
- skipDefaultLibCheck: true,
334
- moduleResolution: ts.ModuleResolutionKind.Node16,
335
- types: [],
336
- allowJs: false,
337
- checkJs: false,
338
- }
339
- const cpuStart = process.cpuUsage()
340
- const startProgram = performance.now()
341
- const host = createSourceFileCacheHost(compilerOptions)
342
- const program = ts.createProgram(
343
- normalizedRouteFiles,
344
- compilerOptions,
345
- host,
346
- options.oldProgram
347
- )
348
- host.prune(program)
349
- const filesReused = host.reused()
350
- logger.debug(
351
- `Created program in ${(performance.now() - startProgram).toFixed(0)}ms (${normalizedRouteFiles.length} files, ${filesReused} source files reused)`
352
- )
353
-
354
- const startChecker = performance.now()
355
- const checker = program.getTypeChecker()
356
- logger.debug(
357
- `Got type checker in ${(performance.now() - startChecker).toFixed(2)}ms`
358
- )
359
-
360
- // Use provided rootDir or infer from source files
361
- const rootDir = options.rootDir || findCommonAncestor(normalizedRouteFiles)
362
-
363
- const startSourceFiles = performance.now()
364
- // node_modules under rootDir (e.g. a locally-installed addon) is a
365
- // dependency, not project source — scanning it double-counts the addon's
366
- // own application types (CoreConfig/Services/SingletonServices). Nested
367
- // pikku projects (a workspace addon at packages/<addon>) are the same case:
368
- // TS resolves the node_modules symlink to its realpath under rootDir, so
369
- // the node_modules check alone misses them.
370
- // Sort by file name so the sweeps populate state in a stable order. The
371
- // program's own file order depends on glob + import-graph resolution, which
372
- // varies run to run — leaving generated meta keys (and anything serialized
373
- // in insertion order) non-reproducible across identical `pikku all` runs.
374
- // Safe because function registration is a dedicated pass (visitFunctions)
375
- // that completes before any order-sensitive wiring resolution in visitRoutes.
376
- const isNestedProjectFile = createNestedProjectFilter(rootDir)
377
- const sourceFiles = program
378
- .getSourceFiles()
379
- .filter(
380
- (sf) =>
381
- sf.fileName.startsWith(rootDir) &&
382
- !sf.fileName.includes('/node_modules/') &&
383
- !isNestedProjectFile(sf.fileName)
384
- )
385
- .sort((a, b) =>
386
- a.fileName < b.fileName ? -1 : a.fileName > b.fileName ? 1 : 0
387
- )
388
- logger.debug(
389
- `Got source files in ${(performance.now() - startSourceFiles).toFixed(2)}ms`
390
- )
391
-
392
- const state = getInitialInspectorState(rootDir)
393
-
394
- const surfaceAreaCache = new Map<string, string | null>()
395
- for (const sourceFile of sourceFiles) {
396
- const usage = extractSecretUsage(sourceFile)
397
- if (usage.keys.length > 0 || usage.dynamic.length > 0) {
398
- state.secrets.usage.set(sourceFile.fileName, usage)
399
- }
400
- // Counted in the sweep that already has this file open. The public surface
401
- // is documentation, and documentation may not cost a project a second pass
402
- // over its source.
403
- accumulateSurfaceUsage(
404
- sourceFile,
405
- {
406
- area: surfaceUsageArea(sourceFile.fileName, rootDir, surfaceAreaCache),
407
- file: relative(rootDir, sourceFile.fileName),
408
- },
409
- state.surfaceUsage
410
- )
411
- }
412
-
413
- // First sweep: add all functions
414
- const startSetup = performance.now()
415
- for (const sourceFile of sourceFiles) {
416
- const sourceOptions = { ...options, sourceFile }
417
- ts.forEachChild(sourceFile, (child) =>
418
- visitSetup(logger, checker, child, state, sourceOptions)
419
- )
420
- }
421
- logger.debug(
422
- `Visit setup phase completed in ${(performance.now() - startSetup).toFixed(0)}ms`
423
- )
424
-
425
- // Load addon function metadata so wirings can reference addon functions
426
- await loadAddonFunctionsMeta(logger, state)
427
-
428
- if (!options.setupOnly) {
429
- // Function sweep: register every function before transports/wirings resolve
430
- // them, so resolution doesn't depend on source-file order.
431
- const startFunctions = performance.now()
432
- for (const sourceFile of sourceFiles) {
433
- const sourceOptions = { ...options, sourceFile }
434
- ts.forEachChild(sourceFile, (child) =>
435
- visitFunctions(logger, checker, child, state, sourceOptions)
436
- )
437
- }
438
- logger.debug(
439
- `Visit functions phase completed in ${(performance.now() - startFunctions).toFixed(0)}ms`
440
- )
441
-
442
- // Transport sweep: add all transports/wirings
443
- const startRoutes = performance.now()
444
- for (const sourceFile of sourceFiles) {
445
- const sourceOptions = { ...options, sourceFile }
446
- ts.forEachChild(sourceFile, (child) =>
447
- visitRoutes(logger, checker, child, state, sourceOptions)
448
- )
449
- }
450
- logger.debug(
451
- `Visit routes phase completed in ${(performance.now() - startRoutes).toFixed(0)}ms`
452
- )
453
-
454
- resolveLatestVersions(state, logger)
455
-
456
- if (options.schemaConfig) {
457
- const startSchemas = performance.now()
458
- state.schemas = await generateAllSchemas(
459
- logger,
460
- options.schemaConfig,
461
- state
462
- )
463
- logger.debug(
464
- `generateAllSchemas took ${(performance.now() - startSchemas).toFixed(0)}ms`
465
- )
466
- computeContractHashes(
467
- state.schemas,
468
- state.functions.typesMap,
469
- state.functions.meta
470
- )
471
- computeRequiredSchemas(state, options)
472
- }
473
-
474
- // Re-load addon schemas (generateAllSchemas replaces state.schemas)
475
- await loadAddonSchemas(logger, state)
476
-
477
- // After the addon merge, not before: an addon supplies its own schemas here,
478
- // and checking earlier would report every one of them as unresolved.
479
- if (options.schemaConfig) {
480
- validateSchemaReferences(logger, state)
481
- }
482
-
483
- state.manifest.initial = options.manifest ?? null
484
- const contracts = extractContractsFromMeta(state.functions.meta)
485
- const baseManifest = state.manifest.initial ?? createEmptyManifest()
486
- state.manifest.current = updateManifest(baseManifest, contracts)
487
- state.manifest.errors = validateContracts(baseManifest, contracts).errors
488
-
489
- finalizeWorkflows(state)
490
- finalizeWorkflowHelperTypes(state)
491
- finalizeWorkflowWires(state)
492
- }
493
-
494
- // Populate filesAndMethods
495
- const startFilesAndMethods = performance.now()
496
- const { result, errors } = getFilesAndMethods(state, options.types)
497
- state.filesAndMethods = result
498
- state.filesAndMethodsErrors = errors
499
- logger.debug(
500
- `Get files and methods completed in ${(performance.now() - startFilesAndMethods).toFixed(2)}ms`
501
- )
502
-
503
- if (!options.setupOnly) {
504
- // Everything below re-derives from the state this pass just built, so it
505
- // supersedes whatever an earlier pass concluded about a source graph the
506
- // run has since finished generating into.
507
- logger.beginValidationPass?.()
508
- const startAggregate = performance.now()
509
- // Apply the inspected auth handler service set before aggregation so it
510
- // flows into requiredServices (the generated handler's own func is opaque).
511
- stampAuthHandlerServices(state)
512
- aggregateRequiredServices(state)
513
- logger.debug(
514
- `Aggregate required services completed in ${(performance.now() - startAggregate).toFixed(2)}ms`
515
- )
516
-
517
- computeResolvedIOTypes(state)
518
- computeMiddlewareGroupsMeta(state)
519
- computePermissionsGroupsMeta(state)
520
- validateNoSecretAliasServices(logger, checker, state)
521
- validateSecretUsage(logger, state)
522
- computeDiagnostics(state)
523
- validateSchemaWiringSeparation(logger, state)
524
- validateWorkflowGraphAddons(logger, state)
525
- validateScenarioServices(logger, state)
526
- validateScenarioSteps(logger, state)
527
- // Needs every route, every function and every wireAddon declaration
528
- // together, so it can only run once the whole program is inspected.
529
- annotateHttpRouteAuth(state)
530
- // Last of the validators: they read function meta and every wireAddon
531
- // declaration together, so they need the whole program inspected.
532
- validateExposedFunctionsGated(logger, state)
533
- validateTagsResolveToMiddleware(logger, state)
534
-
535
- if (options.openAPI) {
536
- state.openAPISpec = await generateOpenAPISpec(
537
- logger,
538
- state.functions.meta,
539
- state.http.meta,
540
- state.schemas,
541
- options.openAPI.additionalInfo,
542
- pikkuState(null, 'misc', 'errors')
543
- )
544
- }
545
-
546
- validateAgentModels(logger, state, options.modelAliases)
547
- validateAgentToolReferences(logger, state, options)
548
- validateAgentScorerReferences(logger, state)
549
- validateSecretOverrides(logger, state)
550
- validateVariableOverrides(logger, state)
551
- validateCredentialOverrides(logger, state)
552
- validateRemoteAddonDependencies(logger, state)
553
- validateRemoteAddonAuth(logger, state)
554
- validateScopeReferences(logger, state)
555
- validateSystemRoleScopes(logger, state)
556
- validatePersonaRoles(logger, state)
557
- logger.endValidationPass?.()
558
- }
559
-
560
- const cpu = process.cpuUsage(cpuStart)
561
- state.stats = {
562
- files: program.getSourceFiles().length,
563
- projectFiles: sourceFiles.length,
564
- filesReused,
565
- types: program.getTypeCount(),
566
- instantiations: program.getInstantiationCount(),
567
- symbols: program.getSymbolCount(),
568
- cpuMs: Math.round((cpu.user + cpu.system) / 1000),
569
- wallMs: Math.round(performance.now() - startProgram),
570
- heapUsedMb: Math.round(process.memoryUsage().heapUsed / 1048576),
571
- }
572
- state.program = program
573
-
574
- return state
575
- }
@@ -1 +0,0 @@
1
- export { generateAllSchemas } from './utils/schema-generator.js'
@@ -1,73 +0,0 @@
1
- import * as ts from 'typescript'
2
- import { createHash } from 'crypto'
3
-
4
- /**
5
- * Parsed source files, kept across programs so a re-inspection only re-parses
6
- * what changed. Keyed by path; an entry is valid while the file's content
7
- * hash matches.
8
- *
9
- * This is the incremental reuse `oldProgram` used to give, without its cost.
10
- * Passing the previous ts.Program keeps that program reachable, and a program
11
- * memoises its type checker — so every re-inspection held a second, fully
12
- * exercised checker for the sake of skipping a re-parse. A bare SourceFile
13
- * carries its AST and binder symbols and nothing else; sharing it between
14
- * programs is what the language service's document registry does.
15
- *
16
- * Module-level on purpose: `inspect()` is called several times per `pikku all`
17
- * (and indefinitely in watch mode) from one process, and the cache is only
18
- * worth having if it outlives the call.
19
- */
20
- const cache = new Map<string, { hash: string; file: ts.SourceFile }>()
21
-
22
- export interface SourceFileCacheHost extends ts.CompilerHost {
23
- /** Files served from the cache by the program just built. */
24
- readonly reused: () => number
25
- /**
26
- * Drop entries the program did not use, so a file that left the project
27
- * (or watch mode's churn) does not pin its AST forever.
28
- */
29
- readonly prune: (program: ts.Program) => void
30
- }
31
-
32
- export const createSourceFileCacheHost = (
33
- options: ts.CompilerOptions
34
- ): SourceFileCacheHost => {
35
- const host = ts.createCompilerHost(options, true)
36
- let reused = 0
37
-
38
- host.getSourceFile = (fileName, languageVersionOrOptions, onError) => {
39
- let text: string | undefined
40
- try {
41
- text = host.readFile(fileName)
42
- } catch (e) {
43
- onError?.(e instanceof Error ? e.message : String(e))
44
- return undefined
45
- }
46
- if (text === undefined) return undefined
47
-
48
- const hash = createHash('sha1').update(text).digest('hex')
49
- const hit = cache.get(fileName)
50
- if (hit && hit.hash === hash) {
51
- reused++
52
- return hit.file
53
- }
54
- const file = ts.createSourceFile(
55
- fileName,
56
- text,
57
- languageVersionOrOptions,
58
- true
59
- )
60
- cache.set(fileName, { hash, file })
61
- return file
62
- }
63
-
64
- return Object.assign(host, {
65
- reused: () => reused,
66
- prune: (program: ts.Program) => {
67
- const live = new Set(program.getSourceFiles().map((sf) => sf.fileName))
68
- for (const fileName of cache.keys()) {
69
- if (!live.has(fileName)) cache.delete(fileName)
70
- }
71
- },
72
- })
73
- }