@pikku/inspector 0.9.2 → 0.9.4
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 +25 -0
- package/dist/add-functions.d.ts +2 -2
- package/dist/add-functions.js +45 -25
- package/dist/add-http-route.js +2 -2
- package/dist/add-middleware.d.ts +7 -0
- package/dist/add-middleware.js +35 -0
- package/dist/add-permission.d.ts +7 -0
- package/dist/add-permission.js +35 -0
- package/dist/add-rpc-invocations.d.ts +6 -0
- package/dist/add-rpc-invocations.js +36 -0
- package/dist/inspector.js +20 -3
- package/dist/types.d.ts +30 -7
- package/dist/utils.d.ts +5 -1
- package/dist/utils.js +35 -1
- package/dist/visit.js +7 -1
- package/package.json +2 -2
- package/src/add-functions.ts +53 -24
- package/src/add-http-route.ts +2 -2
- package/src/add-middleware.ts +51 -0
- package/src/add-permission.ts +53 -0
- package/src/add-rpc-invocations.ts +49 -0
- package/src/inspector.ts +20 -3
- package/src/types.ts +32 -4
- package/src/utils.ts +43 -2
- package/src/visit.ts +8 -1
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @pikku/inspector
|
|
2
2
|
|
|
3
|
+
## 0.9.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 6059c87: refactor: move PikkuPermission to pikkuPermission and same for middleware for api consistency to to improve future features
|
|
8
|
+
- 6db63bb: perf: changing http meta to a lookup map to reduce loops
|
|
9
|
+
- Updated dependencies [6059c87]
|
|
10
|
+
- Updated dependencies [6db63bb]
|
|
11
|
+
- Updated dependencies [74f8634]
|
|
12
|
+
- Updated dependencies [766fef1]
|
|
13
|
+
- @pikku/core@0.9.6
|
|
14
|
+
|
|
15
|
+
## 0.9.3
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- 9691aba: fix: add-functions should support both functions only and objects
|
|
20
|
+
- 2ab0278: refactor: no longer import ALL functions, only the ones used by rpcs
|
|
21
|
+
- 81005ba: feat: creating a smaller meta file for functions to reduce size
|
|
22
|
+
- b3c2829: fix (using ai): generating custom types broke imports.. this fixes it, but needs more robust training
|
|
23
|
+
- Updated dependencies [9691aba]
|
|
24
|
+
- Updated dependencies [2ab0278]
|
|
25
|
+
- Updated dependencies [81005ba]
|
|
26
|
+
- @pikku/core@0.9.3
|
|
27
|
+
|
|
3
28
|
## 0.9.2
|
|
4
29
|
|
|
5
30
|
### Patch Changes
|
package/dist/add-functions.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
|
-
import {
|
|
2
|
+
import { InspectorLogger, InspectorState } from './types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Inspect pikkuFunc calls, extract input/output and first-arg destructuring,
|
|
5
5
|
* then push into state.functions.meta.
|
|
6
6
|
*/
|
|
7
|
-
export declare function addFunctions(node: ts.Node, checker: ts.TypeChecker, state: InspectorState,
|
|
7
|
+
export declare function addFunctions(node: ts.Node, checker: ts.TypeChecker, state: InspectorState, logger: InspectorLogger): void;
|
package/dist/add-functions.js
CHANGED
|
@@ -60,6 +60,20 @@ const resolveTypeImports = (type, resolvedTypes, isCustom) => {
|
|
|
60
60
|
typeRef.typeArguments?.forEach(visitType);
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
|
+
// Always traverse type arguments for thorough type collection
|
|
64
|
+
if (currentType.aliasTypeArguments) {
|
|
65
|
+
currentType.aliasTypeArguments.forEach(visitType);
|
|
66
|
+
}
|
|
67
|
+
// Always handle intersections and unions
|
|
68
|
+
if (currentType.isUnionOrIntersection()) {
|
|
69
|
+
currentType.types.forEach(visitType);
|
|
70
|
+
}
|
|
71
|
+
// Always handle object types with type arguments
|
|
72
|
+
if (currentType.flags & ts.TypeFlags.Object &&
|
|
73
|
+
currentType.objectFlags & ts.ObjectFlags.Reference) {
|
|
74
|
+
const typeRef = currentType;
|
|
75
|
+
typeRef.typeArguments?.forEach(visitType);
|
|
76
|
+
}
|
|
63
77
|
};
|
|
64
78
|
visitType(type);
|
|
65
79
|
return types;
|
|
@@ -172,7 +186,7 @@ function unwrapPromise(checker, type) {
|
|
|
172
186
|
* Inspect pikkuFunc calls, extract input/output and first-arg destructuring,
|
|
173
187
|
* then push into state.functions.meta.
|
|
174
188
|
*/
|
|
175
|
-
export function addFunctions(node, checker, state,
|
|
189
|
+
export function addFunctions(node, checker, state, logger) {
|
|
176
190
|
if (!ts.isCallExpression(node))
|
|
177
191
|
return;
|
|
178
192
|
const { expression, arguments: args, typeArguments } = node;
|
|
@@ -198,21 +212,23 @@ export function addFunctions(node, checker, state, filters, logger) {
|
|
|
198
212
|
// determine the actual handler expression:
|
|
199
213
|
// either the `func` prop or the first argument directly
|
|
200
214
|
let handlerNode = args[0];
|
|
215
|
+
let isDirectFunction = true; // Default to direct function format
|
|
201
216
|
if (ts.isObjectLiteralExpression(handlerNode)) {
|
|
217
|
+
isDirectFunction = false; // This is object format with func property
|
|
202
218
|
tags = getPropertyValue(handlerNode, 'tags') || undefined;
|
|
203
219
|
expose = getPropertyValue(handlerNode, 'expose');
|
|
204
220
|
docs = getPropertyValue(handlerNode, 'docs');
|
|
205
221
|
const fnProp = getPropertyAssignmentInitializer(handlerNode, 'func', true, checker);
|
|
206
222
|
if (!fnProp ||
|
|
207
223
|
(!ts.isArrowFunction(fnProp) && !ts.isFunctionExpression(fnProp))) {
|
|
208
|
-
|
|
224
|
+
logger.error(`• No valid 'func' property found for ${pikkuFuncName}.`);
|
|
209
225
|
return;
|
|
210
226
|
}
|
|
211
227
|
handlerNode = fnProp;
|
|
212
228
|
}
|
|
213
229
|
if (!ts.isArrowFunction(handlerNode) &&
|
|
214
230
|
!ts.isFunctionExpression(handlerNode)) {
|
|
215
|
-
|
|
231
|
+
logger.error(`• Handler for ${name} is not a function.`);
|
|
216
232
|
return;
|
|
217
233
|
}
|
|
218
234
|
const services = {
|
|
@@ -244,7 +260,7 @@ export function addFunctions(node, checker, state, filters, logger) {
|
|
|
244
260
|
// --- Input Extraction ---
|
|
245
261
|
let { names: inputNames } = getNamesAndTypes(checker, state.functions.typesMap, 'Input', name, genericTypes[0]);
|
|
246
262
|
// if (inputTypes.length === 0) {
|
|
247
|
-
//
|
|
263
|
+
// logger.debug(
|
|
248
264
|
// `\x1b[31m• Unknown input type for '${name}', assuming void.\x1b[0m`
|
|
249
265
|
// )
|
|
250
266
|
// }
|
|
@@ -262,38 +278,42 @@ export function addFunctions(node, checker, state, filters, logger) {
|
|
|
262
278
|
}
|
|
263
279
|
}
|
|
264
280
|
if (inputNames.length > 1) {
|
|
265
|
-
|
|
281
|
+
logger.warn('More than one input type detected, only the first one will be used as a schema.');
|
|
266
282
|
}
|
|
267
283
|
state.functions.meta[pikkuFuncName] = {
|
|
268
284
|
pikkuFuncName,
|
|
269
285
|
name,
|
|
270
286
|
services,
|
|
271
|
-
|
|
287
|
+
inputSchemaName: inputNames[0] ?? null,
|
|
288
|
+
outputSchemaName: outputNames[0] ?? null,
|
|
272
289
|
inputs: inputNames.filter((n) => n !== 'void') ?? null,
|
|
273
290
|
outputs: outputNames.filter((n) => n !== 'void') ?? null,
|
|
274
|
-
expose,
|
|
275
|
-
tags,
|
|
276
|
-
docs,
|
|
291
|
+
expose: expose || undefined,
|
|
292
|
+
tags: tags || undefined,
|
|
293
|
+
docs: docs || undefined,
|
|
294
|
+
isDirectFunction,
|
|
277
295
|
};
|
|
278
|
-
if (
|
|
296
|
+
if (exportedName || explicitName) {
|
|
279
297
|
if (!exportedName) {
|
|
280
|
-
|
|
298
|
+
logger.error(`• Function with explicit name '${name}' is not exported, this is not allowed.`);
|
|
281
299
|
return;
|
|
282
300
|
}
|
|
283
|
-
if (
|
|
284
|
-
|
|
285
|
-
|
|
301
|
+
if (expose) {
|
|
302
|
+
state.rpc.exposedMeta[name] = pikkuFuncName;
|
|
303
|
+
state.rpc.exposedFiles.set(name, {
|
|
304
|
+
path: node.getSourceFile().fileName,
|
|
305
|
+
exportedName,
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
// We add it to internal meta to allow autocomplete for everything
|
|
309
|
+
state.rpc.internalMeta[name] = pikkuFuncName;
|
|
310
|
+
// But we only import the actual function if it's actually invoked to keep
|
|
311
|
+
// bundle size down
|
|
312
|
+
if (state.rpc.invokedFunctions.has(pikkuFuncName)) {
|
|
313
|
+
state.rpc.internalFiles.set(name, {
|
|
314
|
+
path: node.getSourceFile().fileName,
|
|
315
|
+
exportedName,
|
|
316
|
+
});
|
|
286
317
|
}
|
|
287
|
-
state.rpc.meta[name] = {
|
|
288
|
-
pikkuFuncName,
|
|
289
|
-
exposed: false,
|
|
290
|
-
};
|
|
291
|
-
state.functions.files.set(name, {
|
|
292
|
-
path: node.getSourceFile().fileName,
|
|
293
|
-
exportedName,
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
else {
|
|
297
|
-
console.log(`• Function name '${name}' not exported, skipping.`);
|
|
298
318
|
}
|
|
299
319
|
}
|
package/dist/add-http-route.js
CHANGED
|
@@ -67,7 +67,7 @@ export const addHTTPRoute = (node, checker, state, filters, logger) => {
|
|
|
67
67
|
const inputTypes = getInputTypes(state.http.metaInputTypes, method, input, query, params);
|
|
68
68
|
// --- record route ---
|
|
69
69
|
state.http.files.add(node.getSourceFile().fileName);
|
|
70
|
-
state.http.meta
|
|
70
|
+
state.http.meta[method][route] = {
|
|
71
71
|
pikkuFuncName: funcName,
|
|
72
72
|
route,
|
|
73
73
|
method: method,
|
|
@@ -76,5 +76,5 @@ export const addHTTPRoute = (node, checker, state, filters, logger) => {
|
|
|
76
76
|
inputTypes,
|
|
77
77
|
docs,
|
|
78
78
|
tags,
|
|
79
|
-
}
|
|
79
|
+
};
|
|
80
80
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as ts from 'typescript';
|
|
2
|
+
import { InspectorLogger, InspectorState } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Inspect pikkuMiddleware calls and extract first-arg destructuring
|
|
5
|
+
* for tree shaking optimization.
|
|
6
|
+
*/
|
|
7
|
+
export declare function addMiddleware(node: ts.Node, checker: ts.TypeChecker, state: InspectorState, logger: InspectorLogger): void;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as ts from 'typescript';
|
|
2
|
+
import { extractFunctionName, extractServicesFromFunction } from './utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* Inspect pikkuMiddleware calls and extract first-arg destructuring
|
|
5
|
+
* for tree shaking optimization.
|
|
6
|
+
*/
|
|
7
|
+
export function addMiddleware(node, checker, state, logger) {
|
|
8
|
+
if (!ts.isCallExpression(node))
|
|
9
|
+
return;
|
|
10
|
+
const { expression, arguments: args } = node;
|
|
11
|
+
// only handle calls like pikkuMiddleware(...)
|
|
12
|
+
if (!ts.isIdentifier(expression)) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
if (expression.text !== 'pikkuMiddleware') {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const handlerNode = args[0];
|
|
19
|
+
if (!handlerNode)
|
|
20
|
+
return;
|
|
21
|
+
if (!ts.isArrowFunction(handlerNode) &&
|
|
22
|
+
!ts.isFunctionExpression(handlerNode)) {
|
|
23
|
+
logger.error(`• Handler for pikkuMiddleware is not a function.`);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const services = extractServicesFromFunction(handlerNode);
|
|
27
|
+
const { pikkuFuncName, exportedName } = extractFunctionName(node, checker);
|
|
28
|
+
state.middleware.meta[pikkuFuncName] = {
|
|
29
|
+
services,
|
|
30
|
+
sourceFile: node.getSourceFile().fileName,
|
|
31
|
+
position: node.getStart(),
|
|
32
|
+
exportedName,
|
|
33
|
+
};
|
|
34
|
+
logger.debug(`• Found middleware with services: ${services.services.join(', ')}`);
|
|
35
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as ts from 'typescript';
|
|
2
|
+
import { InspectorLogger, InspectorState } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Inspect pikkuPermission calls and extract first-arg destructuring
|
|
5
|
+
* for tree shaking optimization.
|
|
6
|
+
*/
|
|
7
|
+
export declare function addPermission(node: ts.Node, checker: ts.TypeChecker, state: InspectorState, logger: InspectorLogger): void;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as ts from 'typescript';
|
|
2
|
+
import { extractFunctionName, extractServicesFromFunction } from './utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* Inspect pikkuPermission calls and extract first-arg destructuring
|
|
5
|
+
* for tree shaking optimization.
|
|
6
|
+
*/
|
|
7
|
+
export function addPermission(node, checker, state, logger) {
|
|
8
|
+
if (!ts.isCallExpression(node))
|
|
9
|
+
return;
|
|
10
|
+
const { expression, arguments: args } = node;
|
|
11
|
+
// only handle calls like pikkuPermission(...)
|
|
12
|
+
if (!ts.isIdentifier(expression)) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
if (expression.text !== 'pikkuPermission') {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const handlerNode = args[0];
|
|
19
|
+
if (!handlerNode)
|
|
20
|
+
return;
|
|
21
|
+
if (!ts.isArrowFunction(handlerNode) &&
|
|
22
|
+
!ts.isFunctionExpression(handlerNode)) {
|
|
23
|
+
logger.error(`• Handler for pikkuPermission is not a function.`);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const services = extractServicesFromFunction(handlerNode);
|
|
27
|
+
const { pikkuFuncName, exportedName } = extractFunctionName(node, checker);
|
|
28
|
+
state.permissions.meta[pikkuFuncName] = {
|
|
29
|
+
services,
|
|
30
|
+
sourceFile: node.getSourceFile().fileName,
|
|
31
|
+
position: node.getStart(),
|
|
32
|
+
exportedName,
|
|
33
|
+
};
|
|
34
|
+
logger.debug(`• Found permission with services: ${services.services.join(', ')}`);
|
|
35
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as ts from 'typescript';
|
|
2
|
+
import { InspectorState, InspectorLogger } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Scan for rpc.invoke() calls to track which functions are actually being invoked
|
|
5
|
+
*/
|
|
6
|
+
export declare function addRPCInvocations(node: ts.Node, state: InspectorState, logger: InspectorLogger): void;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as ts from 'typescript';
|
|
2
|
+
/**
|
|
3
|
+
* Scan for rpc.invoke() calls to track which functions are actually being invoked
|
|
4
|
+
*/
|
|
5
|
+
export function addRPCInvocations(node, state, logger) {
|
|
6
|
+
// Look for property access expressions: rpc.invoke
|
|
7
|
+
if (ts.isPropertyAccessExpression(node)) {
|
|
8
|
+
const { expression, name } = node;
|
|
9
|
+
// Check if this is accessing 'invoke' property
|
|
10
|
+
if (name.text === 'invoke') {
|
|
11
|
+
// Check if the object is 'rpc' (or a variable containing rpc)
|
|
12
|
+
if (ts.isIdentifier(expression) && expression.text === 'rpc') {
|
|
13
|
+
// This is rpc.invoke - now we need to find the parent call expression
|
|
14
|
+
const parent = node.parent;
|
|
15
|
+
if (ts.isCallExpression(parent) && parent.expression === node) {
|
|
16
|
+
// This is rpc.invoke('function-name')
|
|
17
|
+
const [firstArg] = parent.arguments;
|
|
18
|
+
if (firstArg) {
|
|
19
|
+
// Extract the function name from string literal
|
|
20
|
+
if (ts.isStringLiteral(firstArg)) {
|
|
21
|
+
const functionName = firstArg.text;
|
|
22
|
+
logger.debug(`• Found RPC invocation: ${functionName}`);
|
|
23
|
+
state.rpc.invokedFunctions.add(functionName);
|
|
24
|
+
}
|
|
25
|
+
// Handle template literals like `function-${name}`
|
|
26
|
+
else if (ts.isTemplateExpression(firstArg) ||
|
|
27
|
+
ts.isNoSubstitutionTemplateLiteral(firstArg)) {
|
|
28
|
+
logger.warn(`• Found dynamic RPC invocation: ${firstArg.getText()}`);
|
|
29
|
+
logger.warn(`\tYou can only use string literals for RPC function names, with ' or " and not \``);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
package/dist/inspector.js
CHANGED
|
@@ -21,11 +21,18 @@ export const inspect = (logger, routeFiles, filters) => {
|
|
|
21
21
|
functions: {
|
|
22
22
|
typesMap: new TypesMap(),
|
|
23
23
|
meta: {},
|
|
24
|
-
files: new Map(),
|
|
25
24
|
},
|
|
26
25
|
http: {
|
|
27
26
|
metaInputTypes: new Map(),
|
|
28
|
-
meta:
|
|
27
|
+
meta: {
|
|
28
|
+
get: {},
|
|
29
|
+
post: {},
|
|
30
|
+
put: {},
|
|
31
|
+
delete: {},
|
|
32
|
+
head: {},
|
|
33
|
+
patch: {},
|
|
34
|
+
options: {},
|
|
35
|
+
},
|
|
29
36
|
files: new Set(),
|
|
30
37
|
},
|
|
31
38
|
channels: {
|
|
@@ -41,7 +48,11 @@ export const inspect = (logger, routeFiles, filters) => {
|
|
|
41
48
|
files: new Set(),
|
|
42
49
|
},
|
|
43
50
|
rpc: {
|
|
44
|
-
|
|
51
|
+
internalMeta: {},
|
|
52
|
+
internalFiles: new Map(),
|
|
53
|
+
exposedMeta: {},
|
|
54
|
+
exposedFiles: new Map(),
|
|
55
|
+
invokedFunctions: new Set(),
|
|
45
56
|
},
|
|
46
57
|
mcpEndpoints: {
|
|
47
58
|
resourcesMeta: {},
|
|
@@ -49,6 +60,12 @@ export const inspect = (logger, routeFiles, filters) => {
|
|
|
49
60
|
promptsMeta: {},
|
|
50
61
|
files: new Set(),
|
|
51
62
|
},
|
|
63
|
+
middleware: {
|
|
64
|
+
meta: {},
|
|
65
|
+
},
|
|
66
|
+
permissions: {
|
|
67
|
+
meta: {},
|
|
68
|
+
},
|
|
52
69
|
};
|
|
53
70
|
// First sweep: add all functions
|
|
54
71
|
for (const sourceFile of sourceFiles) {
|
package/dist/types.d.ts
CHANGED
|
@@ -4,8 +4,7 @@ import { ScheduledTasksMeta } from '@pikku/core/scheduler';
|
|
|
4
4
|
import { queueWorkersMeta } from '@pikku/core/queue';
|
|
5
5
|
import { MCPResourceMeta, MCPToolMeta, MCPPromptMeta } from '@pikku/core';
|
|
6
6
|
import { TypesMap } from './types-map.js';
|
|
7
|
-
import { FunctionsMeta } from '@pikku/core';
|
|
8
|
-
import { RPCMeta } from '@pikku/core/rpc';
|
|
7
|
+
import { FunctionsMeta, FunctionServicesMeta } from '@pikku/core';
|
|
9
8
|
export type PathToNameAndType = Map<string, {
|
|
10
9
|
variable: string;
|
|
11
10
|
type: string | null;
|
|
@@ -23,16 +22,28 @@ export interface InspectorHTTPState {
|
|
|
23
22
|
}
|
|
24
23
|
export interface InspectorFunctionState {
|
|
25
24
|
typesMap: TypesMap;
|
|
26
|
-
files: Map<string, {
|
|
27
|
-
path: string;
|
|
28
|
-
exportedName: string;
|
|
29
|
-
}>;
|
|
30
25
|
meta: FunctionsMeta;
|
|
31
26
|
}
|
|
32
27
|
export interface InspectorChannelState {
|
|
33
28
|
meta: ChannelsMeta;
|
|
34
29
|
files: Set<string>;
|
|
35
30
|
}
|
|
31
|
+
export interface InspectorMiddlewareState {
|
|
32
|
+
meta: Record<string, {
|
|
33
|
+
services: FunctionServicesMeta;
|
|
34
|
+
sourceFile: string;
|
|
35
|
+
position: number;
|
|
36
|
+
exportedName: string | null;
|
|
37
|
+
}>;
|
|
38
|
+
}
|
|
39
|
+
export interface InspectorPermissionState {
|
|
40
|
+
meta: Record<string, {
|
|
41
|
+
services: FunctionServicesMeta;
|
|
42
|
+
sourceFile: string;
|
|
43
|
+
position: number;
|
|
44
|
+
exportedName: string | null;
|
|
45
|
+
}>;
|
|
46
|
+
}
|
|
36
47
|
export type InspectorFilters = {
|
|
37
48
|
tags?: string[];
|
|
38
49
|
types?: string[];
|
|
@@ -63,7 +74,17 @@ export interface InspectorState {
|
|
|
63
74
|
files: Set<string>;
|
|
64
75
|
};
|
|
65
76
|
rpc: {
|
|
66
|
-
|
|
77
|
+
internalMeta: Record<string, string>;
|
|
78
|
+
internalFiles: Map<string, {
|
|
79
|
+
path: string;
|
|
80
|
+
exportedName: string;
|
|
81
|
+
}>;
|
|
82
|
+
exposedMeta: Record<string, string>;
|
|
83
|
+
exposedFiles: Map<string, {
|
|
84
|
+
path: string;
|
|
85
|
+
exportedName: string;
|
|
86
|
+
}>;
|
|
87
|
+
invokedFunctions: Set<string>;
|
|
67
88
|
};
|
|
68
89
|
mcpEndpoints: {
|
|
69
90
|
resourcesMeta: MCPResourceMeta;
|
|
@@ -71,4 +92,6 @@ export interface InspectorState {
|
|
|
71
92
|
promptsMeta: MCPPromptMeta;
|
|
72
93
|
files: Set<string>;
|
|
73
94
|
};
|
|
95
|
+
middleware: InspectorMiddlewareState;
|
|
96
|
+
permissions: InspectorPermissionState;
|
|
74
97
|
}
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
2
|
import { InspectorFilters, InspectorLogger } from './types.js';
|
|
3
|
-
import { PikkuWiringTypes } from '@pikku/core';
|
|
3
|
+
import { PikkuWiringTypes, FunctionServicesMeta } from '@pikku/core';
|
|
4
4
|
type ExtractedFunctionName = {
|
|
5
5
|
pikkuFuncName: string;
|
|
6
6
|
name: string;
|
|
@@ -32,4 +32,8 @@ export declare const matchesFilters: (filters: InspectorFilters, params: {
|
|
|
32
32
|
name: string;
|
|
33
33
|
filePath?: string;
|
|
34
34
|
}, logger: InspectorLogger) => boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Extract services from a function's first parameter destructuring pattern
|
|
37
|
+
*/
|
|
38
|
+
export declare function extractServicesFromFunction(handlerNode: ts.FunctionExpression | ts.ArrowFunction): FunctionServicesMeta;
|
|
35
39
|
export {};
|
package/dist/utils.js
CHANGED
|
@@ -219,7 +219,7 @@ export function extractFunctionName(callExpr, checker) {
|
|
|
219
219
|
const decls = resolvedSym.declarations ?? [];
|
|
220
220
|
if (decls.length > 0) {
|
|
221
221
|
const decl = decls[0];
|
|
222
|
-
// Check if the declaration is a variable that uses
|
|
222
|
+
// Check if the declaration is a variable that uses a pikkuFun
|
|
223
223
|
if (ts.isVariableDeclaration(decl) && decl.initializer) {
|
|
224
224
|
if (ts.isCallExpression(decl.initializer) &&
|
|
225
225
|
ts.isIdentifier(decl.initializer.expression) &&
|
|
@@ -240,6 +240,8 @@ export function extractFunctionName(callExpr, checker) {
|
|
|
240
240
|
isNamedExport(decl) &&
|
|
241
241
|
ts.isIdentifier(decl.name)) {
|
|
242
242
|
result.exportedName = decl.name.text;
|
|
243
|
+
// CRITICAL FIX: Use exported name as pikkuFuncName for consistency
|
|
244
|
+
result.pikkuFuncName = decl.name.text;
|
|
243
245
|
}
|
|
244
246
|
else if (ts.isIdentifier(decl.name)) {
|
|
245
247
|
// If not exported, still capture the variable name
|
|
@@ -566,6 +568,10 @@ export function extractFunctionName(callExpr, checker) {
|
|
|
566
568
|
}
|
|
567
569
|
// Apply name priority logic
|
|
568
570
|
populateNameByPriority(result);
|
|
571
|
+
// CRITICAL FIX: If we have an exported name, use it as the pikkuFuncName for consistent lookup
|
|
572
|
+
if (result.exportedName && !result.explicitName) {
|
|
573
|
+
result.pikkuFuncName = result.exportedName;
|
|
574
|
+
}
|
|
569
575
|
return result;
|
|
570
576
|
}
|
|
571
577
|
/**
|
|
@@ -705,3 +711,31 @@ export const matchesFilters = (filters, params, meta, logger) => {
|
|
|
705
711
|
}
|
|
706
712
|
return true;
|
|
707
713
|
};
|
|
714
|
+
/**
|
|
715
|
+
* Extract services from a function's first parameter destructuring pattern
|
|
716
|
+
*/
|
|
717
|
+
export function extractServicesFromFunction(handlerNode) {
|
|
718
|
+
const services = {
|
|
719
|
+
optimized: true,
|
|
720
|
+
services: [],
|
|
721
|
+
};
|
|
722
|
+
const firstParam = handlerNode.parameters[0];
|
|
723
|
+
if (firstParam) {
|
|
724
|
+
if (ts.isObjectBindingPattern(firstParam.name)) {
|
|
725
|
+
for (const elem of firstParam.name.elements) {
|
|
726
|
+
const original = elem.propertyName && ts.isIdentifier(elem.propertyName)
|
|
727
|
+
? elem.propertyName.text
|
|
728
|
+
: ts.isIdentifier(elem.name)
|
|
729
|
+
? elem.name.text
|
|
730
|
+
: undefined;
|
|
731
|
+
if (original) {
|
|
732
|
+
services.services.push(original);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
else if (ts.isIdentifier(firstParam.name)) {
|
|
737
|
+
services.optimized = false;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
return services;
|
|
741
|
+
}
|
package/dist/visit.js
CHANGED
|
@@ -9,6 +9,9 @@ import { addMCPTool } from './add-mcp-tool.js';
|
|
|
9
9
|
import { addMCPPrompt } from './add-mcp-prompt.js';
|
|
10
10
|
import { addFunctions } from './add-functions.js';
|
|
11
11
|
import { addChannel } from './add-channel.js';
|
|
12
|
+
import { addRPCInvocations } from './add-rpc-invocations.js';
|
|
13
|
+
import { addMiddleware } from './add-middleware.js';
|
|
14
|
+
import { addPermission } from './add-permission.js';
|
|
12
15
|
export const visitSetup = (checker, node, state, filters, logger) => {
|
|
13
16
|
addFileExtendsCoreType(node, checker, state.singletonServicesTypeImportMap, 'CoreSingletonServices');
|
|
14
17
|
addFileExtendsCoreType(node, checker, state.sessionServicesTypeImportMap, 'CoreServices');
|
|
@@ -16,10 +19,11 @@ export const visitSetup = (checker, node, state, filters, logger) => {
|
|
|
16
19
|
addFileWithFactory(node, checker, state.singletonServicesFactories, 'CreateSingletonServices');
|
|
17
20
|
addFileWithFactory(node, checker, state.sessionServicesFactories, 'CreateSessionServices');
|
|
18
21
|
addFileWithFactory(node, checker, state.configFactories, 'CreateConfig');
|
|
19
|
-
|
|
22
|
+
addRPCInvocations(node, state, logger);
|
|
20
23
|
ts.forEachChild(node, (child) => visitSetup(checker, child, state, filters, logger));
|
|
21
24
|
};
|
|
22
25
|
export const visitRoutes = (checker, node, state, filters, logger) => {
|
|
26
|
+
addFunctions(node, checker, state, logger);
|
|
23
27
|
addHTTPRoute(node, checker, state, filters, logger);
|
|
24
28
|
addSchedule(node, checker, state, filters, logger);
|
|
25
29
|
addQueueWorker(node, checker, state, filters, logger);
|
|
@@ -27,5 +31,7 @@ export const visitRoutes = (checker, node, state, filters, logger) => {
|
|
|
27
31
|
addMCPResource(node, checker, state, filters, logger);
|
|
28
32
|
addMCPTool(node, checker, state, filters, logger);
|
|
29
33
|
addMCPPrompt(node, checker, state, filters, logger);
|
|
34
|
+
addMiddleware(node, checker, state, logger);
|
|
35
|
+
addPermission(node, checker, state, logger);
|
|
30
36
|
ts.forEachChild(node, (child) => visitRoutes(checker, child, state, filters, logger));
|
|
31
37
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pikku/inspector",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.4",
|
|
4
4
|
"author": "yasser.fadl@gmail.com",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"test:coverage": "bash run-tests.sh --coverage"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@pikku/core": "^0.9.
|
|
20
|
+
"@pikku/core": "^0.9.6",
|
|
21
21
|
"path-to-regexp": "^8.2.0",
|
|
22
22
|
"typescript": "^5.9"
|
|
23
23
|
},
|