@pikku/inspector 0.9.6-next.0 → 0.10.1
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/CHANGELOG.md +14 -0
- package/dist/add/add-channel.d.ts +5 -1
- package/dist/add/add-channel.js +51 -32
- package/dist/add/add-cli.d.ts +4 -0
- package/dist/add/add-cli.js +128 -23
- package/dist/add/add-file-extends-core-type.js +3 -2
- package/dist/add/add-file-with-factory.d.ts +2 -2
- package/dist/add/add-file-with-factory.js +87 -1
- package/dist/add/add-functions.js +52 -5
- package/dist/add/add-http-route.js +19 -12
- package/dist/add/add-mcp-prompt.js +20 -13
- package/dist/add/add-mcp-resource.js +24 -14
- package/dist/add/add-mcp-tool.js +23 -13
- package/dist/add/add-middleware.js +51 -12
- package/dist/add/add-permission.d.ts +1 -2
- package/dist/add/add-permission.js +275 -19
- package/dist/add/add-queue-worker.js +10 -12
- package/dist/add/add-schedule.js +9 -10
- package/dist/error-codes.d.ts +35 -0
- package/dist/error-codes.js +40 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/inspector.js +20 -1
- package/dist/types.d.ts +31 -3
- package/dist/utils/ensure-function-metadata.d.ts +6 -0
- package/dist/utils/ensure-function-metadata.js +18 -0
- package/dist/utils/extract-function-name.d.ts +2 -2
- package/dist/utils/extract-function-name.js +13 -8
- package/dist/utils/filter-inspector-state.d.ts +6 -0
- package/dist/utils/filter-inspector-state.js +382 -0
- package/dist/utils/filter-utils.d.ts +10 -0
- package/dist/utils/filter-utils.js +66 -2
- package/dist/utils/find-root-dir.d.ts +23 -0
- package/dist/utils/find-root-dir.js +55 -0
- package/dist/utils/get-files-and-methods.d.ts +2 -1
- package/dist/utils/get-files-and-methods.js +4 -3
- package/dist/utils/get-property-value.d.ts +9 -0
- package/dist/utils/get-property-value.js +20 -0
- package/dist/utils/middleware.d.ts +1 -1
- package/dist/utils/middleware.js +7 -7
- package/dist/utils/permissions.d.ts +43 -0
- package/dist/utils/permissions.js +178 -0
- package/dist/utils/post-process.d.ts +16 -0
- package/dist/utils/post-process.js +132 -0
- package/dist/utils/serialize-inspector-state.d.ts +179 -0
- package/dist/utils/serialize-inspector-state.js +170 -0
- package/dist/visit.js +3 -2
- package/package.json +4 -4
- package/src/add/add-channel.ts +92 -40
- package/src/add/add-cli.ts +188 -29
- package/src/add/add-file-extends-core-type.ts +5 -2
- package/src/add/add-file-with-factory.ts +114 -2
- package/src/add/add-functions.ts +60 -5
- package/src/add/add-http-route.ts +46 -21
- package/src/add/add-mcp-prompt.ts +42 -21
- package/src/add/add-mcp-prompt.ts.tmp +0 -0
- package/src/add/add-mcp-resource.ts +50 -24
- package/src/add/add-mcp-resource.ts.tmp +0 -0
- package/src/add/add-mcp-tool.ts +48 -21
- package/src/add/add-middleware.ts +74 -15
- package/src/add/add-permission.ts +364 -22
- package/src/add/add-queue-worker.ts +22 -25
- package/src/add/add-schedule.ts +19 -20
- package/src/error-codes.ts +43 -0
- package/src/index.ts +7 -0
- package/src/inspector.ts +22 -1
- package/src/types.ts +38 -3
- package/src/utils/ensure-function-metadata.ts +24 -0
- package/src/utils/extract-function-name.ts +20 -8
- package/src/utils/filter-inspector-state.test.ts +1433 -0
- package/src/utils/filter-inspector-state.ts +526 -0
- package/src/utils/filter-utils.test.ts +350 -1
- package/src/utils/filter-utils.ts +82 -2
- package/src/utils/find-root-dir.ts +68 -0
- package/src/utils/get-files-and-methods.ts +10 -2
- package/src/utils/get-property-value.ts +27 -0
- package/src/utils/middleware.ts +14 -7
- package/src/utils/permissions.test.ts +327 -0
- package/src/utils/permissions.ts +262 -0
- package/src/utils/post-process.ts +178 -0
- package/src/utils/serialize-inspector-state.ts +375 -0
- package/src/utils/test-data/inspector-state.json +1680 -0
- package/src/visit.ts +4 -2
- package/tsconfig.tsbuildinfo +1 -1
package/dist/inspector.js
CHANGED
|
@@ -2,6 +2,8 @@ import * as ts from 'typescript';
|
|
|
2
2
|
import { visitSetup, visitRoutes } from './visit.js';
|
|
3
3
|
import { TypesMap } from './types-map.js';
|
|
4
4
|
import { getFilesAndMethods } from './utils/get-files-and-methods.js';
|
|
5
|
+
import { findCommonAncestor } from './utils/find-root-dir.js';
|
|
6
|
+
import { aggregateRequiredServices } from './utils/post-process.js';
|
|
5
7
|
export const inspect = (logger, routeFiles, options = {}) => {
|
|
6
8
|
const program = ts.createProgram(routeFiles, {
|
|
7
9
|
target: ts.ScriptTarget.ESNext,
|
|
@@ -9,13 +11,17 @@ export const inspect = (logger, routeFiles, options = {}) => {
|
|
|
9
11
|
});
|
|
10
12
|
const checker = program.getTypeChecker();
|
|
11
13
|
const sourceFiles = program.getSourceFiles();
|
|
14
|
+
// Infer root directory from source files
|
|
15
|
+
const rootDir = findCommonAncestor(routeFiles);
|
|
12
16
|
const state = {
|
|
17
|
+
rootDir,
|
|
13
18
|
singletonServicesTypeImportMap: new Map(),
|
|
14
19
|
sessionServicesTypeImportMap: new Map(),
|
|
15
20
|
userSessionTypeImportMap: new Map(),
|
|
16
21
|
configTypeImportMap: new Map(),
|
|
17
22
|
singletonServicesFactories: new Map(),
|
|
18
23
|
sessionServicesFactories: new Map(),
|
|
24
|
+
sessionServicesMeta: new Map(),
|
|
19
25
|
configFactories: new Map(),
|
|
20
26
|
filesAndMethods: {},
|
|
21
27
|
filesAndMethodsErrors: new Map(),
|
|
@@ -38,6 +44,7 @@ export const inspect = (logger, routeFiles, options = {}) => {
|
|
|
38
44
|
},
|
|
39
45
|
files: new Set(),
|
|
40
46
|
routeMiddleware: new Map(),
|
|
47
|
+
routePermissions: new Map(),
|
|
41
48
|
},
|
|
42
49
|
channels: {
|
|
43
50
|
files: new Set(),
|
|
@@ -65,7 +72,10 @@ export const inspect = (logger, routeFiles, options = {}) => {
|
|
|
65
72
|
files: new Set(),
|
|
66
73
|
},
|
|
67
74
|
cli: {
|
|
68
|
-
meta: {
|
|
75
|
+
meta: {
|
|
76
|
+
programs: {},
|
|
77
|
+
renderers: {},
|
|
78
|
+
},
|
|
69
79
|
files: new Set(),
|
|
70
80
|
},
|
|
71
81
|
middleware: {
|
|
@@ -74,6 +84,13 @@ export const inspect = (logger, routeFiles, options = {}) => {
|
|
|
74
84
|
},
|
|
75
85
|
permissions: {
|
|
76
86
|
meta: {},
|
|
87
|
+
tagPermissions: new Map(),
|
|
88
|
+
},
|
|
89
|
+
serviceAggregation: {
|
|
90
|
+
requiredServices: new Set(),
|
|
91
|
+
usedFunctions: new Set(),
|
|
92
|
+
usedMiddleware: new Set(),
|
|
93
|
+
usedPermissions: new Set(),
|
|
77
94
|
},
|
|
78
95
|
};
|
|
79
96
|
// First sweep: add all functions
|
|
@@ -88,5 +105,7 @@ export const inspect = (logger, routeFiles, options = {}) => {
|
|
|
88
105
|
const { result, errors } = getFilesAndMethods(state, options.types);
|
|
89
106
|
state.filesAndMethods = result;
|
|
90
107
|
state.filesAndMethodsErrors = errors;
|
|
108
|
+
// Post-processing: Aggregate required services from wired functions/middleware/permissions
|
|
109
|
+
aggregateRequiredServices(state);
|
|
91
110
|
return state;
|
|
92
111
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -3,10 +3,11 @@ import { ChannelsMeta } from '@pikku/core/channel';
|
|
|
3
3
|
import { HTTPWiringsMeta } from '@pikku/core/http';
|
|
4
4
|
import { ScheduledTasksMeta } from '@pikku/core/scheduler';
|
|
5
5
|
import { queueWorkersMeta } from '@pikku/core/queue';
|
|
6
|
-
import { MCPResourceMeta, MCPToolMeta, MCPPromptMeta } from '@pikku/core';
|
|
7
|
-
import { CLIMeta } from '@pikku/core';
|
|
6
|
+
import { MCPResourceMeta, MCPToolMeta, MCPPromptMeta } from '@pikku/core/mcp';
|
|
7
|
+
import { CLIMeta } from '@pikku/core/cli';
|
|
8
8
|
import { TypesMap } from './types-map.js';
|
|
9
9
|
import { FunctionsMeta, FunctionServicesMeta } from '@pikku/core';
|
|
10
|
+
import { ErrorCode } from './error-codes.js';
|
|
10
11
|
export type PathToNameAndType = Map<string, {
|
|
11
12
|
variable: string;
|
|
12
13
|
type: string | null;
|
|
@@ -25,11 +26,20 @@ export interface MiddlewareGroupMeta {
|
|
|
25
26
|
middlewareCount: number;
|
|
26
27
|
isFactory: boolean;
|
|
27
28
|
}
|
|
29
|
+
export interface PermissionGroupMeta {
|
|
30
|
+
exportName: string | null;
|
|
31
|
+
sourceFile: string;
|
|
32
|
+
position: number;
|
|
33
|
+
services: FunctionServicesMeta;
|
|
34
|
+
permissionCount: number;
|
|
35
|
+
isFactory: boolean;
|
|
36
|
+
}
|
|
28
37
|
export interface InspectorHTTPState {
|
|
29
38
|
metaInputTypes: MetaInputTypes;
|
|
30
39
|
meta: HTTPWiringsMeta;
|
|
31
40
|
files: Set<string>;
|
|
32
41
|
routeMiddleware: Map<string, MiddlewareGroupMeta>;
|
|
42
|
+
routePermissions: Map<string, PermissionGroupMeta>;
|
|
33
43
|
}
|
|
34
44
|
export interface InspectorFunctionState {
|
|
35
45
|
typesMap: TypesMap;
|
|
@@ -50,6 +60,8 @@ export interface InspectorMiddlewareState {
|
|
|
50
60
|
position: number;
|
|
51
61
|
exportedName: string | null;
|
|
52
62
|
factory?: boolean;
|
|
63
|
+
name?: string;
|
|
64
|
+
description?: string;
|
|
53
65
|
}>;
|
|
54
66
|
tagMiddleware: Map<string, MiddlewareGroupMeta>;
|
|
55
67
|
}
|
|
@@ -59,12 +71,19 @@ export interface InspectorPermissionState {
|
|
|
59
71
|
sourceFile: string;
|
|
60
72
|
position: number;
|
|
61
73
|
exportedName: string | null;
|
|
74
|
+
factory?: boolean;
|
|
75
|
+
name?: string;
|
|
76
|
+
description?: string;
|
|
62
77
|
}>;
|
|
78
|
+
tagPermissions: Map<string, PermissionGroupMeta>;
|
|
63
79
|
}
|
|
64
80
|
export type InspectorFilters = {
|
|
81
|
+
names?: string[];
|
|
65
82
|
tags?: string[];
|
|
66
83
|
types?: string[];
|
|
67
84
|
directories?: string[];
|
|
85
|
+
httpRoutes?: string[];
|
|
86
|
+
httpMethods?: string[];
|
|
68
87
|
};
|
|
69
88
|
export type InspectorOptions = Partial<{
|
|
70
89
|
types: Partial<{
|
|
@@ -73,13 +92,14 @@ export type InspectorOptions = Partial<{
|
|
|
73
92
|
singletonServicesFactoryType: string;
|
|
74
93
|
sessionServicesFactoryType: string;
|
|
75
94
|
}>;
|
|
76
|
-
filters: InspectorFilters;
|
|
77
95
|
}>;
|
|
78
96
|
export interface InspectorLogger {
|
|
79
97
|
info: (message: string) => void;
|
|
80
98
|
error: (message: string) => void;
|
|
81
99
|
warn: (message: string) => void;
|
|
82
100
|
debug: (message: string) => void;
|
|
101
|
+
critical: (code: ErrorCode, message: string) => void;
|
|
102
|
+
hasCriticalErrors: () => boolean;
|
|
83
103
|
}
|
|
84
104
|
export type AddWiring = (logger: InspectorLogger, node: ts.Node, checker: ts.TypeChecker, state: InspectorState, options: InspectorOptions) => void;
|
|
85
105
|
export interface InspectorFilesAndMethods {
|
|
@@ -127,12 +147,14 @@ export interface InspectorFilesAndMethods {
|
|
|
127
147
|
};
|
|
128
148
|
}
|
|
129
149
|
export interface InspectorState {
|
|
150
|
+
rootDir: string;
|
|
130
151
|
singletonServicesTypeImportMap: PathToNameAndType;
|
|
131
152
|
sessionServicesTypeImportMap: PathToNameAndType;
|
|
132
153
|
userSessionTypeImportMap: PathToNameAndType;
|
|
133
154
|
configTypeImportMap: PathToNameAndType;
|
|
134
155
|
singletonServicesFactories: PathToNameAndType;
|
|
135
156
|
sessionServicesFactories: PathToNameAndType;
|
|
157
|
+
sessionServicesMeta: Map<string, string[]>;
|
|
136
158
|
configFactories: PathToNameAndType;
|
|
137
159
|
filesAndMethods: InspectorFilesAndMethods;
|
|
138
160
|
filesAndMethodsErrors: Map<string, PathToNameAndType>;
|
|
@@ -173,4 +195,10 @@ export interface InspectorState {
|
|
|
173
195
|
};
|
|
174
196
|
middleware: InspectorMiddlewareState;
|
|
175
197
|
permissions: InspectorPermissionState;
|
|
198
|
+
serviceAggregation: {
|
|
199
|
+
requiredServices: Set<string>;
|
|
200
|
+
usedFunctions: Set<string>;
|
|
201
|
+
usedMiddleware: Set<string>;
|
|
202
|
+
usedPermissions: Set<string>;
|
|
203
|
+
};
|
|
176
204
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { InspectorState } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Ensures that function metadata exists for a given pikkuFuncName.
|
|
4
|
+
* Creates stub metadata if it doesn't exist (useful for inline functions).
|
|
5
|
+
*/
|
|
6
|
+
export declare function ensureFunctionMetadata(state: InspectorState, pikkuFuncName: string, fallbackName?: string): void;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensures that function metadata exists for a given pikkuFuncName.
|
|
3
|
+
* Creates stub metadata if it doesn't exist (useful for inline functions).
|
|
4
|
+
*/
|
|
5
|
+
export function ensureFunctionMetadata(state, pikkuFuncName, fallbackName) {
|
|
6
|
+
if (!state.functions.meta[pikkuFuncName]) {
|
|
7
|
+
state.functions.meta[pikkuFuncName] = {
|
|
8
|
+
pikkuFuncName,
|
|
9
|
+
name: fallbackName || pikkuFuncName,
|
|
10
|
+
services: { optimized: false, services: [] },
|
|
11
|
+
inputSchemaName: null,
|
|
12
|
+
outputSchemaName: null,
|
|
13
|
+
inputs: [],
|
|
14
|
+
outputs: [],
|
|
15
|
+
middleware: undefined,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -12,7 +12,7 @@ export type ExtractedFunctionName = {
|
|
|
12
12
|
* but if it's an Identifier pointing to a function, resolve it back
|
|
13
13
|
* to the function's declaration (so you get the true source location).
|
|
14
14
|
*/
|
|
15
|
-
export declare function makeDeterministicAnonName(start: ts.Node, checker: ts.TypeChecker): string;
|
|
15
|
+
export declare function makeDeterministicAnonName(start: ts.Node, checker: ts.TypeChecker, rootDir: string): string;
|
|
16
16
|
/**
|
|
17
17
|
* Updated function to extract and prioritize function names correctly
|
|
18
18
|
* This function follows the priority:
|
|
@@ -20,7 +20,7 @@ export declare function makeDeterministicAnonName(start: ts.Node, checker: ts.Ty
|
|
|
20
20
|
* 2. Exported name
|
|
21
21
|
* 3. Fallback to deterministic name
|
|
22
22
|
*/
|
|
23
|
-
export declare function extractFunctionName(callExpr: ts.Node, checker: ts.TypeChecker): ExtractedFunctionName;
|
|
23
|
+
export declare function extractFunctionName(callExpr: ts.Node, checker: ts.TypeChecker, rootDir: string): ExtractedFunctionName;
|
|
24
24
|
/**
|
|
25
25
|
* Helper function to populate the 'name' field based on priority
|
|
26
26
|
*/
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
|
+
import { toRelativePath } from './find-root-dir.js';
|
|
2
3
|
/**
|
|
3
4
|
* Generate a deterministic "anonymous" name for any expression node,
|
|
4
5
|
* but if it's an Identifier pointing to a function, resolve it back
|
|
5
6
|
* to the function's declaration (so you get the true source location).
|
|
6
7
|
*/
|
|
7
|
-
export function makeDeterministicAnonName(start, checker) {
|
|
8
|
+
export function makeDeterministicAnonName(start, checker, rootDir) {
|
|
8
9
|
let node = start;
|
|
9
10
|
let target = start;
|
|
10
11
|
// Handle the case where we're starting with an identifier directly
|
|
@@ -27,7 +28,8 @@ export function makeDeterministicAnonName(start, checker) {
|
|
|
27
28
|
target = decl.initializer;
|
|
28
29
|
// Return early - we found the function directly
|
|
29
30
|
const sf = target.getSourceFile();
|
|
30
|
-
const
|
|
31
|
+
const relativePath = toRelativePath(sf.fileName, rootDir);
|
|
32
|
+
const file = relativePath.replace(/[^A-Za-z0-9_]/g, '_');
|
|
31
33
|
const { line, character } = ts.getLineAndCharacterOfPosition(sf, target.getStart());
|
|
32
34
|
return `pikkuFn_${file}_L${line + 1}C${character + 1}`;
|
|
33
35
|
}
|
|
@@ -62,7 +64,8 @@ export function makeDeterministicAnonName(start, checker) {
|
|
|
62
64
|
target = decl.initializer;
|
|
63
65
|
// Return early - we found the function directly
|
|
64
66
|
const sf = target.getSourceFile();
|
|
65
|
-
const
|
|
67
|
+
const relativePath = toRelativePath(sf.fileName, rootDir);
|
|
68
|
+
const file = relativePath.replace(/[^A-Za-z0-9_]/g, '_');
|
|
66
69
|
const { line, character } = ts.getLineAndCharacterOfPosition(sf, target.getStart());
|
|
67
70
|
return `pikkuFn_${file}_L${line + 1}C${character + 1}`;
|
|
68
71
|
}
|
|
@@ -72,7 +75,8 @@ export function makeDeterministicAnonName(start, checker) {
|
|
|
72
75
|
target = decl;
|
|
73
76
|
// Return early
|
|
74
77
|
const sf = target.getSourceFile();
|
|
75
|
-
const
|
|
78
|
+
const relativePath = toRelativePath(sf.fileName, rootDir);
|
|
79
|
+
const file = relativePath.replace(/[^A-Za-z0-9_]/g, '_');
|
|
76
80
|
const { line, character } = ts.getLineAndCharacterOfPosition(sf, target.getStart());
|
|
77
81
|
return `pikkuFn_${file}_L${line + 1}C${character + 1}`;
|
|
78
82
|
}
|
|
@@ -182,7 +186,8 @@ export function makeDeterministicAnonName(start, checker) {
|
|
|
182
186
|
break;
|
|
183
187
|
}
|
|
184
188
|
const sf = target.getSourceFile();
|
|
185
|
-
const
|
|
189
|
+
const relativePath = toRelativePath(sf.fileName, rootDir);
|
|
190
|
+
const file = relativePath.replace(/[^A-Za-z0-9_]/g, '_');
|
|
186
191
|
const { line, character } = ts.getLineAndCharacterOfPosition(sf, target.getStart());
|
|
187
192
|
return `pikkuFn_${file}_L${line + 1}C${character + 1}`;
|
|
188
193
|
}
|
|
@@ -193,7 +198,7 @@ export function makeDeterministicAnonName(start, checker) {
|
|
|
193
198
|
* 2. Exported name
|
|
194
199
|
* 3. Fallback to deterministic name
|
|
195
200
|
*/
|
|
196
|
-
export function extractFunctionName(callExpr, checker) {
|
|
201
|
+
export function extractFunctionName(callExpr, checker, rootDir) {
|
|
197
202
|
const parent = callExpr.parent;
|
|
198
203
|
// Initialize the result
|
|
199
204
|
const result = {
|
|
@@ -230,7 +235,7 @@ export function extractFunctionName(callExpr, checker) {
|
|
|
230
235
|
(ts.isArrowFunction(firstArg) ||
|
|
231
236
|
ts.isFunctionExpression(firstArg))) {
|
|
232
237
|
// Use the function directly for position calculation
|
|
233
|
-
result.pikkuFuncName = makeDeterministicAnonName(firstArg, checker);
|
|
238
|
+
result.pikkuFuncName = makeDeterministicAnonName(firstArg, checker, rootDir);
|
|
234
239
|
// Continue with name extraction
|
|
235
240
|
if (ts.isIdentifier(parent.name)) {
|
|
236
241
|
result.propertyName = parent.name.text;
|
|
@@ -532,7 +537,7 @@ export function extractFunctionName(callExpr, checker) {
|
|
|
532
537
|
// Generate the deterministic function name based on the original call expression
|
|
533
538
|
// (the config), not the resolved inner function. This ensures the metadata key
|
|
534
539
|
// matches what will be looked up at runtime when referencing the config object.
|
|
535
|
-
result.pikkuFuncName = makeDeterministicAnonName(originalCallExpr, checker);
|
|
540
|
+
result.pikkuFuncName = makeDeterministicAnonName(originalCallExpr, checker, rootDir);
|
|
536
541
|
// Continue with regular name extraction for remaining cases
|
|
537
542
|
// 1) const foo = pikkuFunc(...)
|
|
538
543
|
if (ts.isVariableDeclaration(parent) && ts.isIdentifier(parent.name)) {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { InspectorState, InspectorFilters, InspectorLogger } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Filters inspector state based on provided filters
|
|
4
|
+
* This is applied post-inspection to support the inspect-once, filter-many pattern
|
|
5
|
+
*/
|
|
6
|
+
export declare function filterInspectorState(state: InspectorState | Omit<InspectorState, 'typesLookup'>, filters: InspectorFilters, logger: InspectorLogger): typeof state;
|