@pikku/inspector 0.12.103 → 0.12.107
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.
- package/dist/add/add-auth.d.ts +1 -9
- package/dist/add/add-auth.js +64 -17
- package/dist/add/add-cli.js +25 -11
- package/dist/add/add-functions.js +35 -39
- package/dist/add/add-keyed-wiring.js +22 -2
- package/dist/add/add-middleware.js +17 -16
- package/dist/add/add-permission.d.ts +0 -3
- package/dist/add/add-permission.js +213 -22
- package/dist/add/add-scope.d.ts +1 -7
- package/dist/add/add-scope.js +1 -21
- package/dist/add/add-virtual-users.d.ts +13 -0
- package/dist/add/{add-personas.js → add-virtual-users.js} +33 -33
- package/dist/add/add-workflow.js +14 -10
- package/dist/add/check-indirect-registrations.d.ts +9 -0
- package/dist/add/check-indirect-registrations.js +114 -0
- package/dist/error-codes.d.ts +5 -3
- package/dist/error-codes.js +5 -3
- package/dist/finalize.d.ts +10 -0
- package/dist/finalize.js +102 -0
- package/dist/index.d.ts +8 -6
- package/dist/index.js +6 -5
- package/dist/initial-state.d.ts +7 -0
- package/dist/initial-state.js +216 -0
- package/dist/inspector.d.ts +6 -4
- package/dist/inspector.js +28 -300
- package/dist/lite.d.ts +26 -0
- package/dist/lite.js +25 -0
- package/dist/source-file-cache.d.ts +11 -0
- package/dist/source-file-cache.js +34 -10
- package/dist/types-map.js +2 -1
- package/dist/types.d.ts +35 -3
- package/dist/utils/apply-declared-scopes.d.ts +8 -0
- package/dist/utils/apply-declared-scopes.js +21 -0
- package/dist/utils/canonical-type-string.d.ts +14 -0
- package/dist/utils/canonical-type-string.js +162 -0
- package/dist/utils/context-based-id.d.ts +7 -0
- package/dist/utils/context-based-id.js +9 -0
- package/dist/utils/custom-types-generator.d.ts +15 -1
- package/dist/utils/custom-types-generator.js +17 -5
- package/dist/utils/ensure-function-metadata.d.ts +0 -14
- package/dist/utils/ensure-function-metadata.js +4 -1
- package/dist/utils/extract-function-name.d.ts +1 -1
- package/dist/utils/extract-function-name.js +2 -4
- package/dist/utils/filter-inspector-state.js +31 -1
- package/dist/utils/get-property-value.d.ts +5 -0
- package/dist/utils/get-property-value.js +15 -1
- package/dist/utils/inspector-constants.d.ts +16 -0
- package/dist/utils/inspector-constants.js +16 -0
- package/dist/utils/load-addon-functions-meta.js +1 -0
- package/dist/utils/post-process.d.ts +35 -36
- package/dist/utils/post-process.js +218 -193
- package/dist/utils/resolve-callee-name.d.ts +27 -0
- package/dist/utils/resolve-callee-name.js +147 -0
- package/dist/utils/resolve-service-types.d.ts +8 -0
- package/dist/utils/resolve-service-types.js +21 -0
- package/dist/utils/schema-generator.js +29 -2
- package/dist/utils/serialize-inspector-state.d.ts +9 -3
- package/dist/utils/serialize-inspector-state.js +22 -7
- package/dist/utils/single-declaration.d.ts +3 -3
- package/dist/utils/single-declaration.js +3 -3
- package/dist/utils/validate-single-step-workflows.d.ts +3 -0
- package/dist/utils/validate-single-step-workflows.js +32 -0
- package/dist/utils/workflow/dsl/extract-dsl-workflow.js +3 -3
- package/dist/utils/workflow/dsl/patterns.d.ts +4 -11
- package/dist/utils/workflow/dsl/patterns.js +5 -11
- package/dist/utils/workflow/graph/convert-dsl-to-graph.js +6 -6
- package/dist/utils/workflow/graph/workflow-graph.types.d.ts +5 -5
- package/dist/visit.js +4 -2
- package/package.json +25 -9
- package/CHANGELOG.md +0 -4318
- package/OPTIMIZATION-PLAN.md +0 -201
- package/dist/add/add-personas.d.ts +0 -13
- package/run-tests.sh +0 -68
- package/src/utils/test-data/inspector-state.json +0 -1687
package/dist/inspector.js
CHANGED
|
@@ -1,243 +1,21 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
|
-
import { applyDeclaredScopes } from './add/add-scope.js';
|
|
3
2
|
import { performance } from 'perf_hooks';
|
|
4
3
|
import { dirname, relative, resolve } from 'path';
|
|
5
4
|
import { visitSetup, visitFunctions, visitRoutes } from './visit.js';
|
|
6
|
-
import { TypesMap } from './types-map.js';
|
|
7
|
-
import { getFilesAndMethods } from './utils/get-files-and-methods.js';
|
|
8
5
|
import { findCommonAncestor } from './utils/find-root-dir.js';
|
|
9
6
|
import { createSourceFileCacheHost } from './source-file-cache.js';
|
|
10
7
|
import { createNestedProjectFilter } from './utils/nested-project-filter.js';
|
|
11
8
|
import { toProgramPath } from './utils/program-path.js';
|
|
12
|
-
import { aggregateRequiredServices, stampAuthHandlerServices, validateAgentModels, validateAgentToolReferences, validateAgentScorerReferences, validateSecretOverrides, validateVariableOverrides, validateCredentialOverrides, validateAddonUses, validateAddonContentGrants, validateRemoteAddonDependencies, validateRemoteAddonAuth, validateScopeReferences, validateSystemRoleScopes, validatePersonaRoles, computeResolvedIOTypes, computeMiddlewareGroupsMeta, computePermissionsGroupsMeta, computeRequiredSchemas, validateNoSecretAliasServices, registerDerivedOAuth2AppSecrets, validateSecretUsage, computeDiagnostics, validateSchemaReferences, validateSchemaWiringSeparation, validateScenarioServices, validateScenarioSteps, validateScenarioFeatures, validateWorkflowGraphAddons, } from './utils/post-process.js';
|
|
13
|
-
import { validateExposedFunctionsGated } from './utils/validate-exposed-functions-gated.js';
|
|
14
|
-
import { validateTagsResolveToMiddleware } from './utils/validate-tags-resolve-to-middleware.js';
|
|
15
|
-
import { annotateHttpRouteAuth } from './utils/annotate-http-route-auth.js';
|
|
16
|
-
import { generateOpenAPISpec } from './utils/serialize-openapi-json.js';
|
|
17
|
-
import { pikkuState } from '@pikku/core/state';
|
|
18
9
|
import { resolveLatestVersions } from './utils/resolve-versions.js';
|
|
19
10
|
import { validateWebhookSourceTriggers } from './add/add-trigger.js';
|
|
20
|
-
import { finalizeWorkflows } from './utils/workflow/graph/finalize-workflows.js';
|
|
21
|
-
import { finalizeWorkflowHelperTypes, finalizeWorkflowWires, } from './utils/workflow/graph/finalize-workflow-wires.js';
|
|
22
11
|
import { generateAllSchemas } from './utils/schema-generator.js';
|
|
23
12
|
import { extractSecretUsage } from './utils/extract-secret-usage.js';
|
|
24
13
|
import { accumulateSurfaceUsage, surfaceUsageArea, } from './utils/extract-surface-usage.js';
|
|
25
|
-
import { loadAddonFunctionsMeta
|
|
26
|
-
import {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
* @returns A fresh InspectorState with empty collections
|
|
31
|
-
*/
|
|
32
|
-
export function getInitialInspectorState(rootDir) {
|
|
33
|
-
return {
|
|
34
|
-
rootDir,
|
|
35
|
-
singletonServicesTypeImportMap: new Map(),
|
|
36
|
-
wireServicesTypeImportMap: new Map(),
|
|
37
|
-
userSessionTypeImportMap: new Map(),
|
|
38
|
-
configTypeImportMap: new Map(),
|
|
39
|
-
singletonServicesFactories: new Map(),
|
|
40
|
-
wireServicesFactories: new Map(),
|
|
41
|
-
wireServicesMeta: new Map(),
|
|
42
|
-
addonRequiredParentServices: [],
|
|
43
|
-
addonCreatedServices: [],
|
|
44
|
-
addonServicesFactorySeen: false,
|
|
45
|
-
addonServerlessIncompatible: new Map(),
|
|
46
|
-
configFactories: new Map(),
|
|
47
|
-
serverLifecycleFactories: new Map(),
|
|
48
|
-
filesAndMethods: {},
|
|
49
|
-
filesAndMethodsErrors: new Map(),
|
|
50
|
-
typesLookup: new Map(),
|
|
51
|
-
schemaLookup: new Map(),
|
|
52
|
-
schemas: {},
|
|
53
|
-
functions: {
|
|
54
|
-
typesMap: new TypesMap(),
|
|
55
|
-
meta: {},
|
|
56
|
-
files: new Map(),
|
|
57
|
-
approvalDescriptions: {},
|
|
58
|
-
dynamicImportIds: new Set(),
|
|
59
|
-
},
|
|
60
|
-
http: {
|
|
61
|
-
metaInputTypes: new Map(),
|
|
62
|
-
meta: {
|
|
63
|
-
get: {},
|
|
64
|
-
post: {},
|
|
65
|
-
put: {},
|
|
66
|
-
delete: {},
|
|
67
|
-
head: {},
|
|
68
|
-
patch: {},
|
|
69
|
-
options: {},
|
|
70
|
-
},
|
|
71
|
-
files: new Set(),
|
|
72
|
-
routeMiddleware: new Map(),
|
|
73
|
-
},
|
|
74
|
-
channels: {
|
|
75
|
-
files: new Set(),
|
|
76
|
-
meta: {},
|
|
77
|
-
},
|
|
78
|
-
gateways: {
|
|
79
|
-
meta: {},
|
|
80
|
-
files: new Set(),
|
|
81
|
-
},
|
|
82
|
-
triggers: {
|
|
83
|
-
meta: {},
|
|
84
|
-
sourceMeta: {},
|
|
85
|
-
webhookSourceMeta: {},
|
|
86
|
-
files: new Set(),
|
|
87
|
-
},
|
|
88
|
-
scheduledTasks: {
|
|
89
|
-
meta: {},
|
|
90
|
-
files: new Set(),
|
|
91
|
-
},
|
|
92
|
-
queueWorkers: {
|
|
93
|
-
meta: {},
|
|
94
|
-
files: new Set(),
|
|
95
|
-
},
|
|
96
|
-
workflows: {
|
|
97
|
-
meta: {},
|
|
98
|
-
files: new Map(),
|
|
99
|
-
graphMeta: {},
|
|
100
|
-
graphFiles: new Map(),
|
|
101
|
-
featureFiles: new Map(),
|
|
102
|
-
invokedWorkflows: new Set(),
|
|
103
|
-
},
|
|
104
|
-
rpc: {
|
|
105
|
-
internalMeta: {},
|
|
106
|
-
internalFiles: new Map(),
|
|
107
|
-
exposedMeta: {},
|
|
108
|
-
exposedFiles: new Map(),
|
|
109
|
-
remoteMeta: {},
|
|
110
|
-
remoteFiles: new Map(),
|
|
111
|
-
invokedFunctions: new Set(),
|
|
112
|
-
invokedFunctionsByFile: new Map(),
|
|
113
|
-
usedAddons: new Set(),
|
|
114
|
-
wireAddonDeclarations: new Map(),
|
|
115
|
-
wireAddonFiles: new Set(),
|
|
116
|
-
},
|
|
117
|
-
mcpEndpoints: {
|
|
118
|
-
resourcesMeta: {},
|
|
119
|
-
toolsMeta: {},
|
|
120
|
-
promptsMeta: {},
|
|
121
|
-
files: new Set(),
|
|
122
|
-
surfaces: {},
|
|
123
|
-
},
|
|
124
|
-
agents: {
|
|
125
|
-
agentsMeta: {},
|
|
126
|
-
files: new Map(),
|
|
127
|
-
invokedAgentsByFile: new Map(),
|
|
128
|
-
},
|
|
129
|
-
scorers: {
|
|
130
|
-
scorersMeta: {},
|
|
131
|
-
files: new Map(),
|
|
132
|
-
},
|
|
133
|
-
cli: {
|
|
134
|
-
meta: {
|
|
135
|
-
programs: {},
|
|
136
|
-
renderers: {},
|
|
137
|
-
},
|
|
138
|
-
files: new Set(),
|
|
139
|
-
},
|
|
140
|
-
nodes: {
|
|
141
|
-
meta: {},
|
|
142
|
-
files: new Set(),
|
|
143
|
-
},
|
|
144
|
-
auth: {
|
|
145
|
-
providers: [],
|
|
146
|
-
plugins: [],
|
|
147
|
-
files: new Set(),
|
|
148
|
-
definition: null,
|
|
149
|
-
},
|
|
150
|
-
secrets: {
|
|
151
|
-
definitions: [],
|
|
152
|
-
files: new Set(),
|
|
153
|
-
usage: new Map(),
|
|
154
|
-
},
|
|
155
|
-
surfaceUsage: {},
|
|
156
|
-
credentials: {
|
|
157
|
-
definitions: [],
|
|
158
|
-
files: new Set(),
|
|
159
|
-
},
|
|
160
|
-
scopes: {
|
|
161
|
-
definitions: [],
|
|
162
|
-
files: new Set(),
|
|
163
|
-
},
|
|
164
|
-
systemRoles: {
|
|
165
|
-
definitions: [],
|
|
166
|
-
files: new Set(),
|
|
167
|
-
},
|
|
168
|
-
featureFlags: {
|
|
169
|
-
definitions: [],
|
|
170
|
-
files: new Set(),
|
|
171
|
-
},
|
|
172
|
-
personas: {
|
|
173
|
-
definitions: [],
|
|
174
|
-
files: new Set(),
|
|
175
|
-
},
|
|
176
|
-
variables: {
|
|
177
|
-
definitions: [],
|
|
178
|
-
files: new Set(),
|
|
179
|
-
},
|
|
180
|
-
manifest: {
|
|
181
|
-
initial: null,
|
|
182
|
-
current: null,
|
|
183
|
-
errors: [],
|
|
184
|
-
},
|
|
185
|
-
middleware: {
|
|
186
|
-
definitions: {},
|
|
187
|
-
instances: {},
|
|
188
|
-
tagMiddleware: new Map(),
|
|
189
|
-
globalFiles: new Set(),
|
|
190
|
-
},
|
|
191
|
-
channelMiddleware: {
|
|
192
|
-
definitions: {},
|
|
193
|
-
instances: {},
|
|
194
|
-
tagMiddleware: new Map(),
|
|
195
|
-
},
|
|
196
|
-
agentMiddleware: {
|
|
197
|
-
definitions: {},
|
|
198
|
-
},
|
|
199
|
-
permissions: {
|
|
200
|
-
definitions: {},
|
|
201
|
-
instances: {},
|
|
202
|
-
},
|
|
203
|
-
serviceAggregation: {
|
|
204
|
-
requiredServices: new Set(),
|
|
205
|
-
usedFunctions: new Set(),
|
|
206
|
-
usedMiddleware: new Set(),
|
|
207
|
-
usedPermissions: new Set(),
|
|
208
|
-
allSingletonServices: [],
|
|
209
|
-
allWireServices: [],
|
|
210
|
-
},
|
|
211
|
-
resolvedIOTypes: {},
|
|
212
|
-
middlewareGroupsMeta: {
|
|
213
|
-
definitions: {},
|
|
214
|
-
instances: {},
|
|
215
|
-
httpGroups: {},
|
|
216
|
-
tagGroups: {},
|
|
217
|
-
channelMiddleware: {
|
|
218
|
-
definitions: {},
|
|
219
|
-
instances: {},
|
|
220
|
-
tagGroups: {},
|
|
221
|
-
},
|
|
222
|
-
},
|
|
223
|
-
permissionsGroupsMeta: {
|
|
224
|
-
definitions: {},
|
|
225
|
-
},
|
|
226
|
-
requiredSchemas: new Set(),
|
|
227
|
-
openAPISpec: null,
|
|
228
|
-
diagnostics: [],
|
|
229
|
-
addonFunctions: {},
|
|
230
|
-
exportedContracts: {
|
|
231
|
-
http: {},
|
|
232
|
-
cli: {},
|
|
233
|
-
channel: {},
|
|
234
|
-
addonHttp: {},
|
|
235
|
-
addonCli: {},
|
|
236
|
-
addonChannel: {},
|
|
237
|
-
},
|
|
238
|
-
program: null,
|
|
239
|
-
};
|
|
240
|
-
}
|
|
14
|
+
import { loadAddonFunctionsMeta } from './utils/load-addon-functions-meta.js';
|
|
15
|
+
import { resolveServiceTypes } from './utils/resolve-service-types.js';
|
|
16
|
+
import { finalizeInspectorState } from './finalize.js';
|
|
17
|
+
import { getInitialInspectorState } from './initial-state.js';
|
|
18
|
+
export { getInitialInspectorState };
|
|
241
19
|
/**
|
|
242
20
|
* The path mappings the inspector's program has to share with the project.
|
|
243
21
|
*
|
|
@@ -271,7 +49,12 @@ const readProjectPathMappings = (logger, tsconfig) => {
|
|
|
271
49
|
...(pathsBasePath !== undefined ? { pathsBasePath } : {}),
|
|
272
50
|
};
|
|
273
51
|
};
|
|
274
|
-
|
|
52
|
+
/**
|
|
53
|
+
* The engine-specific half of an inspection: builds the program, walks it with
|
|
54
|
+
* the checker and generates the schemas. What it returns is the pre-finalize
|
|
55
|
+
* state that `finalizeInspectorState` completes.
|
|
56
|
+
*/
|
|
57
|
+
export const analyzeProgram = async (logger, routeFiles, options = {}) => {
|
|
275
58
|
const normalizedRouteFiles = routeFiles.map((file) => resolve(file));
|
|
276
59
|
const compilerOptions = {
|
|
277
60
|
...readProjectPathMappings(logger, options.tsconfig),
|
|
@@ -363,80 +146,11 @@ export const inspect = async (logger, routeFiles, options = {}) => {
|
|
|
363
146
|
const startSchemas = performance.now();
|
|
364
147
|
state.schemas = await generateAllSchemas(logger, options.schemaConfig, state);
|
|
365
148
|
logger.debug(`generateAllSchemas took ${(performance.now() - startSchemas).toFixed(0)}ms`);
|
|
366
|
-
computeContractHashes(state.schemas, state.functions.typesMap, state.functions.meta);
|
|
367
|
-
computeRequiredSchemas(state, options);
|
|
368
|
-
}
|
|
369
|
-
// Re-load addon schemas (generateAllSchemas replaces state.schemas)
|
|
370
|
-
await loadAddonSchemas(logger, state);
|
|
371
|
-
// After the addon merge, not before: an addon supplies its own schemas here,
|
|
372
|
-
// and checking earlier would report every one of them as unresolved.
|
|
373
|
-
if (options.schemaConfig) {
|
|
374
|
-
validateSchemaReferences(logger, state);
|
|
375
149
|
}
|
|
376
|
-
state.manifest.initial = options.manifest ?? null;
|
|
377
|
-
const contracts = extractContractsFromMeta(state.functions.meta);
|
|
378
|
-
const baseManifest = state.manifest.initial ?? createEmptyManifest();
|
|
379
|
-
state.manifest.current = updateManifest(baseManifest, contracts);
|
|
380
|
-
state.manifest.errors = validateContracts(baseManifest, contracts).errors;
|
|
381
|
-
finalizeWorkflows(state);
|
|
382
|
-
finalizeWorkflowHelperTypes(state);
|
|
383
|
-
finalizeWorkflowWires(state);
|
|
384
|
-
}
|
|
385
|
-
// Populate filesAndMethods
|
|
386
|
-
const startFilesAndMethods = performance.now();
|
|
387
|
-
const { result, errors } = getFilesAndMethods(state, options.types);
|
|
388
|
-
state.filesAndMethods = result;
|
|
389
|
-
state.filesAndMethodsErrors = errors;
|
|
390
|
-
logger.debug(`Get files and methods completed in ${(performance.now() - startFilesAndMethods).toFixed(2)}ms`);
|
|
391
|
-
if (!options.setupOnly) {
|
|
392
|
-
// Everything below re-derives from the state this pass just built, so it
|
|
393
|
-
// supersedes whatever an earlier pass concluded about a source graph the
|
|
394
|
-
// run has since finished generating into.
|
|
395
|
-
logger.beginValidationPass?.();
|
|
396
|
-
const startAggregate = performance.now();
|
|
397
|
-
// Apply the inspected auth handler service set before aggregation so it
|
|
398
|
-
// flows into requiredServices (the generated handler's own func is opaque).
|
|
399
|
-
stampAuthHandlerServices(state);
|
|
400
|
-
aggregateRequiredServices(state);
|
|
401
|
-
logger.debug(`Aggregate required services completed in ${(performance.now() - startAggregate).toFixed(2)}ms`);
|
|
402
|
-
computeResolvedIOTypes(state);
|
|
403
|
-
computeMiddlewareGroupsMeta(state);
|
|
404
|
-
computePermissionsGroupsMeta(state);
|
|
405
|
-
validateNoSecretAliasServices(logger, checker, state);
|
|
406
|
-
registerDerivedOAuth2AppSecrets(state);
|
|
407
|
-
validateSecretUsage(logger, state);
|
|
408
|
-
computeDiagnostics(state);
|
|
409
|
-
validateSchemaWiringSeparation(logger, state);
|
|
410
|
-
validateWorkflowGraphAddons(logger, state);
|
|
411
|
-
validateScenarioServices(logger, state);
|
|
412
|
-
validateScenarioSteps(logger, state);
|
|
413
|
-
validateScenarioFeatures(logger, state);
|
|
414
|
-
// Needs every route, every function and every wireAddon declaration
|
|
415
|
-
// together, so it can only run once the whole program is inspected.
|
|
416
|
-
annotateHttpRouteAuth(state);
|
|
417
|
-
// Last of the validators: they read function meta and every wireAddon
|
|
418
|
-
// declaration together, so they need the whole program inspected.
|
|
419
|
-
validateExposedFunctionsGated(logger, state);
|
|
420
|
-
validateTagsResolveToMiddleware(logger, state);
|
|
421
|
-
if (options.openAPI) {
|
|
422
|
-
state.openAPISpec = await generateOpenAPISpec(logger, state.functions.meta, state.http.meta, state.schemas, options.openAPI.additionalInfo, pikkuState(null, 'misc', 'errors'));
|
|
423
|
-
}
|
|
424
|
-
validateAgentModels(logger, state, options.modelAliases);
|
|
425
|
-
validateAgentToolReferences(logger, state, options);
|
|
426
|
-
validateAgentScorerReferences(logger, state);
|
|
427
|
-
validateSecretOverrides(logger, state);
|
|
428
|
-
validateVariableOverrides(logger, state);
|
|
429
|
-
validateCredentialOverrides(logger, state);
|
|
430
|
-
validateAddonUses(logger, state);
|
|
431
|
-
validateAddonContentGrants(logger, state);
|
|
432
|
-
validateRemoteAddonDependencies(logger, state);
|
|
433
|
-
validateRemoteAddonAuth(logger, state);
|
|
434
|
-
applyDeclaredScopes(state);
|
|
435
|
-
validateScopeReferences(logger, state);
|
|
436
|
-
validateSystemRoleScopes(logger, state);
|
|
437
|
-
validatePersonaRoles(logger, state);
|
|
438
|
-
logger.endValidationPass?.();
|
|
439
150
|
}
|
|
151
|
+
// On a setup-only pass too: the CLI reads the singleton service names off
|
|
152
|
+
// a setup-only state to decide whether workflows have a workflowService.
|
|
153
|
+
state.serviceTypes = resolveServiceTypes(state, checker);
|
|
440
154
|
const cpu = process.cpuUsage(cpuStart);
|
|
441
155
|
state.stats = {
|
|
442
156
|
files: program.getSourceFiles().length,
|
|
@@ -452,3 +166,17 @@ export const inspect = async (logger, routeFiles, options = {}) => {
|
|
|
452
166
|
state.program = program;
|
|
453
167
|
return state;
|
|
454
168
|
};
|
|
169
|
+
export const inspect = async (logger, routeFiles, options = {}) => {
|
|
170
|
+
const cpuStart = process.cpuUsage();
|
|
171
|
+
const start = performance.now();
|
|
172
|
+
const state = await analyzeProgram(logger, routeFiles, options);
|
|
173
|
+
await finalizeInspectorState(logger, state, options);
|
|
174
|
+
const cpu = process.cpuUsage(cpuStart);
|
|
175
|
+
state.stats = {
|
|
176
|
+
...state.stats,
|
|
177
|
+
cpuMs: Math.round((cpu.user + cpu.system) / 1000),
|
|
178
|
+
wallMs: Math.round(performance.now() - start),
|
|
179
|
+
heapUsedMb: Math.round(process.memoryUsage().heapUsed / 1048576),
|
|
180
|
+
};
|
|
181
|
+
return state;
|
|
182
|
+
};
|
package/dist/lite.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The inspector's exports that never load the TypeScript compiler.
|
|
3
|
+
*
|
|
4
|
+
* `@pikku/inspector` itself pulls in `typescript` and `ts-json-schema-generator`
|
|
5
|
+
* at module load, which costs a CLI command that only wants an error code or a
|
|
6
|
+
* serializer most of its startup time, and costs the native engine the
|
|
7
|
+
* compiler's memory for nothing. Everything a consumer of an `InspectorState`
|
|
8
|
+
* needs is here and safe to import eagerly; `lite.test.ts` fails if anything
|
|
9
|
+
* reachable from this file imports `typescript`.
|
|
10
|
+
*/
|
|
11
|
+
export { getInitialInspectorState } from './initial-state.js';
|
|
12
|
+
export { ErrorCode } from './error-codes.js';
|
|
13
|
+
export type { DiagnosticSeverity, CodedDiagnostic } from './error-codes.js';
|
|
14
|
+
export { AUTH_HANDLER_FUNC_ID } from './utils/inspector-constants.js';
|
|
15
|
+
export { SCENARIO_INSTRUMENTATION_FUNCTIONS, isScenarioInstrumentationFunction, } from './add/scenario-instrumentation.js';
|
|
16
|
+
export { serializeInspectorState, deserializeInspectorState, } from './utils/serialize-inspector-state.js';
|
|
17
|
+
export { filterInspectorState } from './utils/filter-inspector-state.js';
|
|
18
|
+
export { incompatibleServicesFor, resolveDeployTarget, } from './utils/resolve-deploy-target.js';
|
|
19
|
+
export { customTypeNames, generateCustomTypes, sanitizeTypeName, } from './utils/custom-types-generator.js';
|
|
20
|
+
export { unresolvedSchemaReferences } from './utils/post-process.js';
|
|
21
|
+
export { createEmptyManifest, serializeManifest, } from './utils/contract-hashes.js';
|
|
22
|
+
export { serializeMCPJson } from './utils/serialize-mcp-json.js';
|
|
23
|
+
export { deserializeDslWorkflow, deserializeGraphWorkflow, deserializeAllDslWorkflows, } from './utils/workflow/dsl/deserialize-dsl-workflow.js';
|
|
24
|
+
export { resolveFunctionMeta } from './utils/resolve-function-meta.js';
|
|
25
|
+
export { resolveCoreType } from './utils/resolve-core-type.js';
|
|
26
|
+
export { addonResolutionDirs, createAddonResolver, } from './utils/addon-resolution.js';
|
package/dist/lite.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The inspector's exports that never load the TypeScript compiler.
|
|
3
|
+
*
|
|
4
|
+
* `@pikku/inspector` itself pulls in `typescript` and `ts-json-schema-generator`
|
|
5
|
+
* at module load, which costs a CLI command that only wants an error code or a
|
|
6
|
+
* serializer most of its startup time, and costs the native engine the
|
|
7
|
+
* compiler's memory for nothing. Everything a consumer of an `InspectorState`
|
|
8
|
+
* needs is here and safe to import eagerly; `lite.test.ts` fails if anything
|
|
9
|
+
* reachable from this file imports `typescript`.
|
|
10
|
+
*/
|
|
11
|
+
export { getInitialInspectorState } from './initial-state.js';
|
|
12
|
+
export { ErrorCode } from './error-codes.js';
|
|
13
|
+
export { AUTH_HANDLER_FUNC_ID } from './utils/inspector-constants.js';
|
|
14
|
+
export { SCENARIO_INSTRUMENTATION_FUNCTIONS, isScenarioInstrumentationFunction, } from './add/scenario-instrumentation.js';
|
|
15
|
+
export { serializeInspectorState, deserializeInspectorState, } from './utils/serialize-inspector-state.js';
|
|
16
|
+
export { filterInspectorState } from './utils/filter-inspector-state.js';
|
|
17
|
+
export { incompatibleServicesFor, resolveDeployTarget, } from './utils/resolve-deploy-target.js';
|
|
18
|
+
export { customTypeNames, generateCustomTypes, sanitizeTypeName, } from './utils/custom-types-generator.js';
|
|
19
|
+
export { unresolvedSchemaReferences } from './utils/post-process.js';
|
|
20
|
+
export { createEmptyManifest, serializeManifest, } from './utils/contract-hashes.js';
|
|
21
|
+
export { serializeMCPJson } from './utils/serialize-mcp-json.js';
|
|
22
|
+
export { deserializeDslWorkflow, deserializeGraphWorkflow, deserializeAllDslWorkflows, } from './utils/workflow/dsl/deserialize-dsl-workflow.js';
|
|
23
|
+
export { resolveFunctionMeta } from './utils/resolve-function-meta.js';
|
|
24
|
+
export { resolveCoreType } from './utils/resolve-core-type.js';
|
|
25
|
+
export { addonResolutionDirs, createAddonResolver, } from './utils/addon-resolution.js';
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
|
+
/**
|
|
3
|
+
* Parse through the shared cache. With `populate: false` the cache is only
|
|
4
|
+
* read: a short-lived program (the schema generator's) reuses what the
|
|
5
|
+
* inspector parsed without pinning its own files past its lifetime.
|
|
6
|
+
*/
|
|
7
|
+
export declare const getCachedSourceFile: (fileName: string, text: string, languageVersionOrOptions: ts.ScriptTarget | ts.CreateSourceFileOptions, { populate }?: {
|
|
8
|
+
populate?: boolean;
|
|
9
|
+
}) => {
|
|
10
|
+
file: ts.SourceFile;
|
|
11
|
+
reused: boolean;
|
|
12
|
+
};
|
|
2
13
|
export interface SourceFileCacheHost extends ts.CompilerHost {
|
|
3
14
|
/** Files served from the cache by the program just built. */
|
|
4
15
|
readonly reused: () => number;
|
|
@@ -17,6 +17,35 @@ import { createHash } from 'crypto';
|
|
|
17
17
|
* worth having if it outlives the call.
|
|
18
18
|
*/
|
|
19
19
|
const cache = new Map();
|
|
20
|
+
/**
|
|
21
|
+
* A SourceFile is only shareable between programs that would have parsed it
|
|
22
|
+
* the same way: the language version and the module format the program
|
|
23
|
+
* implies for it (ESM vs CJS) are baked into the AST. The inspector and the
|
|
24
|
+
* schema generator use different compiler options, so both go into the key.
|
|
25
|
+
*/
|
|
26
|
+
const cacheKey = (fileName, languageVersionOrOptions) => {
|
|
27
|
+
if (typeof languageVersionOrOptions !== 'object') {
|
|
28
|
+
return `${fileName}\0${languageVersionOrOptions}`;
|
|
29
|
+
}
|
|
30
|
+
const { languageVersion, impliedNodeFormat, jsDocParsingMode } = languageVersionOrOptions;
|
|
31
|
+
return `${fileName}\0${languageVersion}\0${impliedNodeFormat ?? ''}\0${jsDocParsingMode ?? ''}`;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Parse through the shared cache. With `populate: false` the cache is only
|
|
35
|
+
* read: a short-lived program (the schema generator's) reuses what the
|
|
36
|
+
* inspector parsed without pinning its own files past its lifetime.
|
|
37
|
+
*/
|
|
38
|
+
export const getCachedSourceFile = (fileName, text, languageVersionOrOptions, { populate = true } = {}) => {
|
|
39
|
+
const key = cacheKey(fileName, languageVersionOrOptions);
|
|
40
|
+
const hash = createHash('sha1').update(text).digest('hex');
|
|
41
|
+
const hit = cache.get(key);
|
|
42
|
+
if (hit && hit.hash === hash)
|
|
43
|
+
return { file: hit.file, reused: true };
|
|
44
|
+
const file = ts.createSourceFile(fileName, text, languageVersionOrOptions, true);
|
|
45
|
+
if (populate)
|
|
46
|
+
cache.set(key, { hash, file });
|
|
47
|
+
return { file, reused: false };
|
|
48
|
+
};
|
|
20
49
|
export const createSourceFileCacheHost = (options) => {
|
|
21
50
|
const host = ts.createCompilerHost(options, true);
|
|
22
51
|
let reused = 0;
|
|
@@ -31,23 +60,18 @@ export const createSourceFileCacheHost = (options) => {
|
|
|
31
60
|
}
|
|
32
61
|
if (text === undefined)
|
|
33
62
|
return undefined;
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
if (hit && hit.hash === hash) {
|
|
63
|
+
const { file, reused: hit } = getCachedSourceFile(fileName, text, languageVersionOrOptions);
|
|
64
|
+
if (hit)
|
|
37
65
|
reused++;
|
|
38
|
-
return hit.file;
|
|
39
|
-
}
|
|
40
|
-
const file = ts.createSourceFile(fileName, text, languageVersionOrOptions, true);
|
|
41
|
-
cache.set(fileName, { hash, file });
|
|
42
66
|
return file;
|
|
43
67
|
};
|
|
44
68
|
return Object.assign(host, {
|
|
45
69
|
reused: () => reused,
|
|
46
70
|
prune: (program) => {
|
|
47
71
|
const live = new Set(program.getSourceFiles().map((sf) => sf.fileName));
|
|
48
|
-
for (const
|
|
49
|
-
if (!live.has(fileName))
|
|
50
|
-
cache.delete(
|
|
72
|
+
for (const [key, entry] of cache) {
|
|
73
|
+
if (!live.has(entry.file.fileName))
|
|
74
|
+
cache.delete(key);
|
|
51
75
|
}
|
|
52
76
|
},
|
|
53
77
|
});
|
package/dist/types-map.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
+
import { canonicalTypeString } from './utils/canonical-type-string.js';
|
|
2
3
|
export class TypesMap {
|
|
3
4
|
map = new Map();
|
|
4
5
|
customTypes = new Map();
|
|
5
6
|
addCustomType(name, type, references) {
|
|
6
|
-
this.customTypes.set(name, { type, references });
|
|
7
|
+
this.customTypes.set(name, { type: canonicalTypeString(type), references });
|
|
7
8
|
}
|
|
8
9
|
addType(originalName, path) {
|
|
9
10
|
this.map.set(originalName, { originalName, path });
|
package/dist/types.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ import type { CredentialDefinitions } from '@pikku/core/credential';
|
|
|
19
19
|
import type { ScopeDefinitions } from '@pikku/core/scope';
|
|
20
20
|
import type { SystemRoleDefinitions } from '@pikku/core/role';
|
|
21
21
|
import type { FeatureFlagDefinitions } from '@pikku/core/flag';
|
|
22
|
-
import type {
|
|
22
|
+
import type { VirtualUserDefinitions } from '@pikku/core/virtual-user';
|
|
23
23
|
import type { VariableDefinitions } from '@pikku/core/variable';
|
|
24
24
|
import type { TypesMap } from './types-map.js';
|
|
25
25
|
import type { FunctionsMeta } from '@pikku/core/services';
|
|
@@ -206,9 +206,21 @@ export interface InspectorPermissionInstance {
|
|
|
206
206
|
position: number;
|
|
207
207
|
isFactoryCall: boolean;
|
|
208
208
|
}
|
|
209
|
+
/**
|
|
210
|
+
* One `addGlobalPermission(...)` call. It registers at module evaluation, so
|
|
211
|
+
* codegen must import its file — or call `exportName`, when the call sits in an
|
|
212
|
+
* exported zero-argument factory — or the global gate does not exist.
|
|
213
|
+
*/
|
|
214
|
+
export interface InspectorGlobalPermissionRegistration {
|
|
215
|
+
sourceFile: string;
|
|
216
|
+
position: number;
|
|
217
|
+
exportName: string | null;
|
|
218
|
+
definitionIds: string[];
|
|
219
|
+
}
|
|
209
220
|
export interface InspectorPermissionState {
|
|
210
221
|
definitions: Record<string, InspectorPermissionDefinition>;
|
|
211
222
|
instances: Record<string, InspectorPermissionInstance>;
|
|
223
|
+
global: InspectorGlobalPermissionRegistration[];
|
|
212
224
|
}
|
|
213
225
|
export type InspectorFilters = {
|
|
214
226
|
names?: string[];
|
|
@@ -428,6 +440,12 @@ export interface AuthDefinition {
|
|
|
428
440
|
/** Whether `session.cookieCache` is enabled — drives the stateless session
|
|
429
441
|
* middleware split in the auth codegen. Absent/false ⇒ stateful middleware. */
|
|
430
442
|
cookieCache?: boolean;
|
|
443
|
+
/** `advanced.cookiePrefix`, when written as a string literal. */
|
|
444
|
+
cookiePrefix?: string;
|
|
445
|
+
/** `session.cookieCache.strategy`, when written as a string literal. */
|
|
446
|
+
cookieCacheStrategy?: string;
|
|
447
|
+
/** `session.cookieCache.version`, when written as a string literal. */
|
|
448
|
+
cookieCacheVersion?: string;
|
|
431
449
|
/**
|
|
432
450
|
* Singleton services the generated auth handler must have available at
|
|
433
451
|
* runtime — the services the `pikkuBetterAuth` factory reaches for (either
|
|
@@ -518,6 +536,14 @@ export type ScreensManifestMeta = {
|
|
|
518
536
|
*/
|
|
519
537
|
scopes?: string[];
|
|
520
538
|
};
|
|
539
|
+
export interface InspectorServiceTypes {
|
|
540
|
+
/** Property names of the project's SingletonServices type, sorted. */
|
|
541
|
+
singletonServices: string[] | null;
|
|
542
|
+
/** Property names of the project's Services type, unfiltered. */
|
|
543
|
+
services: string[] | null;
|
|
544
|
+
/** Singleton services that are a `SecretService` under another name. */
|
|
545
|
+
secretAliases: string[];
|
|
546
|
+
}
|
|
521
547
|
export interface InspectorState {
|
|
522
548
|
/** Set when this package calls `defineScreens`: the screens it ships. */
|
|
523
549
|
screensManifest?: ScreensManifestMeta;
|
|
@@ -784,8 +810,8 @@ export interface InspectorState {
|
|
|
784
810
|
definitions: FeatureFlagDefinitions;
|
|
785
811
|
files: Set<string>;
|
|
786
812
|
};
|
|
787
|
-
|
|
788
|
-
definitions:
|
|
813
|
+
virtualUsers: {
|
|
814
|
+
definitions: VirtualUserDefinitions;
|
|
789
815
|
files: Set<string>;
|
|
790
816
|
};
|
|
791
817
|
variables: {
|
|
@@ -801,6 +827,12 @@ export interface InspectorState {
|
|
|
801
827
|
channelMiddleware: InspectorChannelMiddlewareState;
|
|
802
828
|
agentMiddleware: InspectorAIMiddlewareState;
|
|
803
829
|
permissions: InspectorPermissionState;
|
|
830
|
+
/**
|
|
831
|
+
* What the checker concluded about the project's core service types, read
|
|
832
|
+
* during analysis so that finalize never needs `typesLookup`. A field is null
|
|
833
|
+
* when the type did not resolve.
|
|
834
|
+
*/
|
|
835
|
+
serviceTypes?: InspectorServiceTypes;
|
|
804
836
|
serviceAggregation: {
|
|
805
837
|
requiredServices: Set<string>;
|
|
806
838
|
usedFunctions: Set<string>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { InspectorState } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Folds `declareScopes` ids into `state.scopes.definitions`. An id the
|
|
4
|
+
* definitions already hold (an addon's tree, a `defineScope`) is left alone;
|
|
5
|
+
* a missing one is added as a bare node under its root, creating the root when
|
|
6
|
+
* nothing declared it.
|
|
7
|
+
*/
|
|
8
|
+
export declare const applyDeclaredScopes: (state: Pick<InspectorState, "scopes">) => void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Folds `declareScopes` ids into `state.scopes.definitions`. An id the
|
|
3
|
+
* definitions already hold (an addon's tree, a `defineScope`) is left alone;
|
|
4
|
+
* a missing one is added as a bare node under its root, creating the root when
|
|
5
|
+
* nothing declared it.
|
|
6
|
+
*/
|
|
7
|
+
export const applyDeclaredScopes = (state) => {
|
|
8
|
+
for (const [id, sourceFile] of state.scopes.declared ?? []) {
|
|
9
|
+
const [rootName, ...rest] = id.split(':');
|
|
10
|
+
let root = state.scopes.definitions.find((d) => d.name === rootName);
|
|
11
|
+
if (!root) {
|
|
12
|
+
root = { name: rootName, sourceFile };
|
|
13
|
+
state.scopes.definitions.push(root);
|
|
14
|
+
}
|
|
15
|
+
let level = root;
|
|
16
|
+
for (const segment of rest) {
|
|
17
|
+
level.scopes ??= {};
|
|
18
|
+
level = level.scopes[segment] ??= {};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A printed type with the members of every union in it sorted: by text, with
|
|
3
|
+
* `null` and `undefined` last. The checker prints a union in the order its
|
|
4
|
+
* members were created, which follows whichever file it happened to check
|
|
5
|
+
* first, and so differs between runtimes and between the TypeScript and native
|
|
6
|
+
* inspectors. Everything other than a union's order is left byte for byte.
|
|
7
|
+
*
|
|
8
|
+
* A level the scanner cannot split safely (a conditional type, a type
|
|
9
|
+
* parameter's constraint, a type predicate) keeps its order and only has the
|
|
10
|
+
* brackets inside it canonicalized. The native inspector's
|
|
11
|
+
* `typesmap.CanonicalTypeString` is the same algorithm, and both run the cases
|
|
12
|
+
* in `canonical-type-string.cases.json`.
|
|
13
|
+
*/
|
|
14
|
+
export declare const canonicalTypeString: (type: string) => string;
|