@pikku/inspector 0.9.4 → 0.9.6-next.0

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 (95) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/{add-channel.d.ts → add/add-channel.d.ts} +2 -2
  3. package/dist/{add-channel.js → add/add-channel.js} +12 -5
  4. package/dist/add/add-cli.d.ts +5 -0
  5. package/dist/add/add-cli.js +461 -0
  6. package/dist/{add-file-extends-core-type.d.ts → add/add-file-extends-core-type.d.ts} +2 -2
  7. package/dist/{add-file-extends-core-type.js → add/add-file-extends-core-type.js} +17 -5
  8. package/dist/{add-file-with-config.d.ts → add/add-file-with-config.d.ts} +1 -1
  9. package/dist/{add-file-with-config.js → add/add-file-with-config.js} +1 -1
  10. package/dist/{add-file-with-factory.d.ts → add/add-file-with-factory.d.ts} +1 -1
  11. package/dist/{add-file-with-factory.js → add/add-file-with-factory.js} +4 -4
  12. package/dist/add/add-functions.d.ts +6 -0
  13. package/dist/{add-functions.js → add/add-functions.js} +26 -6
  14. package/dist/{add-http-route.d.ts → add/add-http-route.d.ts} +2 -3
  15. package/dist/{add-http-route.js → add/add-http-route.js} +10 -4
  16. package/dist/add/add-mcp-prompt.d.ts +2 -0
  17. package/dist/{add-mcp-prompt.js → add/add-mcp-prompt.js} +10 -4
  18. package/dist/add/add-mcp-resource.d.ts +2 -0
  19. package/dist/{add-mcp-resource.js → add/add-mcp-resource.js} +10 -4
  20. package/dist/add/add-mcp-tool.d.ts +2 -0
  21. package/dist/{add-mcp-tool.js → add/add-mcp-tool.js} +10 -4
  22. package/dist/add/add-middleware.d.ts +5 -0
  23. package/dist/add/add-middleware.js +251 -0
  24. package/dist/add/add-permission.d.ts +6 -0
  25. package/dist/{add-permission.js → add/add-permission.js} +4 -3
  26. package/dist/add/add-queue-worker.d.ts +2 -0
  27. package/dist/{add-queue-worker.js → add/add-queue-worker.js} +10 -4
  28. package/dist/{add-rpc-invocations.d.ts → add/add-rpc-invocations.d.ts} +1 -1
  29. package/dist/add/add-schedule.d.ts +2 -0
  30. package/dist/{add-schedule.js → add/add-schedule.js} +10 -4
  31. package/dist/index.d.ts +2 -0
  32. package/dist/index.js +1 -0
  33. package/dist/inspector.d.ts +2 -3
  34. package/dist/inspector.js +19 -8
  35. package/dist/types.d.ts +79 -0
  36. package/dist/{utils.d.ts → utils/extract-function-name.d.ts} +7 -15
  37. package/dist/{utils.js → utils/extract-function-name.js} +23 -142
  38. package/dist/utils/extract-services.d.ts +6 -0
  39. package/dist/utils/extract-services.js +29 -0
  40. package/dist/utils/filter-utils.d.ts +9 -0
  41. package/dist/utils/filter-utils.js +45 -0
  42. package/dist/utils/get-files-and-methods.d.ts +21 -0
  43. package/dist/utils/get-files-and-methods.js +60 -0
  44. package/dist/utils/middleware.d.ts +39 -0
  45. package/dist/utils/middleware.js +157 -0
  46. package/dist/utils/type-utils.d.ts +3 -0
  47. package/dist/utils/type-utils.js +50 -0
  48. package/dist/visit.d.ts +3 -3
  49. package/dist/visit.js +33 -30
  50. package/package.json +3 -4
  51. package/run-tests.sh +1 -1
  52. package/src/{add-channel.ts → add/add-channel.ts} +19 -19
  53. package/src/add/add-cli.ts +663 -0
  54. package/src/{add-file-extends-core-type.ts → add/add-file-extends-core-type.ts} +21 -6
  55. package/src/{add-file-with-config.ts → add/add-file-with-config.ts} +2 -2
  56. package/src/{add-file-with-factory.ts → add/add-file-with-factory.ts} +5 -5
  57. package/src/{add-functions.ts → add/add-functions.ts} +30 -15
  58. package/src/{add-http-route.ts → add/add-http-route.ts} +23 -14
  59. package/src/{add-mcp-prompt.ts → add/add-mcp-prompt.ts} +18 -15
  60. package/src/{add-mcp-resource.ts → add/add-mcp-resource.ts} +18 -15
  61. package/src/{add-mcp-tool.ts → add/add-mcp-tool.ts} +18 -15
  62. package/src/add/add-middleware.ts +326 -0
  63. package/src/{add-permission.ts → add/add-permission.ts} +4 -8
  64. package/src/{add-queue-worker.ts → add/add-queue-worker.ts} +17 -14
  65. package/src/{add-rpc-invocations.ts → add/add-rpc-invocations.ts} +1 -1
  66. package/src/{add-schedule.ts → add/add-schedule.ts} +17 -14
  67. package/src/index.ts +5 -0
  68. package/src/inspector.ts +20 -17
  69. package/src/types.ts +92 -0
  70. package/src/{utils.ts → utils/extract-function-name.ts} +25 -199
  71. package/src/utils/extract-services.ts +35 -0
  72. package/src/{utils.test.ts → utils/filter-utils.test.ts} +2 -2
  73. package/src/utils/filter-utils.ts +72 -0
  74. package/src/utils/get-files-and-methods.ts +143 -0
  75. package/src/utils/middleware.ts +234 -0
  76. package/src/utils/type-utils.ts +74 -0
  77. package/src/visit.ts +47 -33
  78. package/tsconfig.tsbuildinfo +1 -1
  79. package/dist/add-functions.d.ts +0 -7
  80. package/dist/add-mcp-prompt.d.ts +0 -3
  81. package/dist/add-mcp-resource.d.ts +0 -3
  82. package/dist/add-mcp-tool.d.ts +0 -3
  83. package/dist/add-middleware.d.ts +0 -7
  84. package/dist/add-middleware.js +0 -35
  85. package/dist/add-permission.d.ts +0 -7
  86. package/dist/add-queue-worker.d.ts +0 -3
  87. package/dist/add-schedule.d.ts +0 -3
  88. package/src/add-middleware.ts +0 -51
  89. /package/dist/{add-rpc-invocations.js → add/add-rpc-invocations.js} +0 -0
  90. /package/dist/{does-type-extend-core-type.d.ts → utils/does-type-extend-core-type.d.ts} +0 -0
  91. /package/dist/{does-type-extend-core-type.js → utils/does-type-extend-core-type.js} +0 -0
  92. /package/dist/{get-property-value.d.ts → utils/get-property-value.d.ts} +0 -0
  93. /package/dist/{get-property-value.js → utils/get-property-value.js} +0 -0
  94. /package/src/{does-type-extend-core-type.ts → utils/does-type-extend-core-type.ts} +0 -0
  95. /package/src/{get-property-value.ts → utils/get-property-value.ts} +0 -0
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export { inspect } from './inspector.js';
2
+ export { getFilesAndMethods } from './utils/get-files-and-methods.js';
2
3
  export type { TypesMap } from './types-map.js';
3
4
  export type * from './types.js';
4
5
  export type { InspectorState } from './types.js';
6
+ export type { FilesAndMethods, FilesAndMethodsErrors, } from './utils/get-files-and-methods.js';
package/dist/index.js CHANGED
@@ -1 +1,2 @@
1
1
  export { inspect } from './inspector.js';
2
+ export { getFilesAndMethods } from './utils/get-files-and-methods.js';
@@ -1,3 +1,2 @@
1
- import { InspectorState, InspectorHTTPState, InspectorFilters, InspectorLogger } from './types.js';
2
- export declare const normalizeHTTPTypes: (httpState: InspectorHTTPState) => InspectorHTTPState;
3
- export declare const inspect: (logger: InspectorLogger, routeFiles: string[], filters: InspectorFilters) => InspectorState;
1
+ import { InspectorState, InspectorLogger, InspectorOptions } from './types.js';
2
+ export declare const inspect: (logger: InspectorLogger, routeFiles: string[], options?: InspectorOptions) => InspectorState;
package/dist/inspector.js CHANGED
@@ -1,10 +1,8 @@
1
1
  import * as ts from 'typescript';
2
2
  import { visitSetup, visitRoutes } from './visit.js';
3
3
  import { TypesMap } from './types-map.js';
4
- export const normalizeHTTPTypes = (httpState) => {
5
- return httpState;
6
- };
7
- export const inspect = (logger, routeFiles, filters) => {
4
+ import { getFilesAndMethods } from './utils/get-files-and-methods.js';
5
+ export const inspect = (logger, routeFiles, options = {}) => {
8
6
  const program = ts.createProgram(routeFiles, {
9
7
  target: ts.ScriptTarget.ESNext,
10
8
  module: ts.ModuleKind.CommonJS,
@@ -15,12 +13,17 @@ export const inspect = (logger, routeFiles, filters) => {
15
13
  singletonServicesTypeImportMap: new Map(),
16
14
  sessionServicesTypeImportMap: new Map(),
17
15
  userSessionTypeImportMap: new Map(),
16
+ configTypeImportMap: new Map(),
18
17
  singletonServicesFactories: new Map(),
19
18
  sessionServicesFactories: new Map(),
20
19
  configFactories: new Map(),
20
+ filesAndMethods: {},
21
+ filesAndMethodsErrors: new Map(),
22
+ typesLookup: new Map(),
21
23
  functions: {
22
24
  typesMap: new TypesMap(),
23
25
  meta: {},
26
+ files: new Map(),
24
27
  },
25
28
  http: {
26
29
  metaInputTypes: new Map(),
@@ -34,6 +37,7 @@ export const inspect = (logger, routeFiles, filters) => {
34
37
  options: {},
35
38
  },
36
39
  files: new Set(),
40
+ routeMiddleware: new Map(),
37
41
  },
38
42
  channels: {
39
43
  files: new Set(),
@@ -60,8 +64,13 @@ export const inspect = (logger, routeFiles, filters) => {
60
64
  promptsMeta: {},
61
65
  files: new Set(),
62
66
  },
67
+ cli: {
68
+ meta: {},
69
+ files: new Set(),
70
+ },
63
71
  middleware: {
64
72
  meta: {},
73
+ tagMiddleware: new Map(),
65
74
  },
66
75
  permissions: {
67
76
  meta: {},
@@ -69,13 +78,15 @@ export const inspect = (logger, routeFiles, filters) => {
69
78
  };
70
79
  // First sweep: add all functions
71
80
  for (const sourceFile of sourceFiles) {
72
- ts.forEachChild(sourceFile, (child) => visitSetup(checker, child, state, filters, logger));
81
+ ts.forEachChild(sourceFile, (child) => visitSetup(logger, checker, child, state, options));
73
82
  }
74
83
  // Second sweep: add all transports
75
84
  for (const sourceFile of sourceFiles) {
76
- ts.forEachChild(sourceFile, (child) => visitRoutes(checker, child, state, filters, logger));
85
+ ts.forEachChild(sourceFile, (child) => visitRoutes(logger, checker, child, state, options));
77
86
  }
78
- // Normalise the typesMap
79
- state.http = normalizeHTTPTypes(state.http);
87
+ // Populate filesAndMethods
88
+ const { result, errors } = getFilesAndMethods(state, options.types);
89
+ state.filesAndMethods = result;
90
+ state.filesAndMethodsErrors = errors;
80
91
  return state;
81
92
  };
package/dist/types.d.ts CHANGED
@@ -1,8 +1,10 @@
1
+ import * as ts from 'typescript';
1
2
  import { ChannelsMeta } from '@pikku/core/channel';
2
3
  import { HTTPWiringsMeta } from '@pikku/core/http';
3
4
  import { ScheduledTasksMeta } from '@pikku/core/scheduler';
4
5
  import { queueWorkersMeta } from '@pikku/core/queue';
5
6
  import { MCPResourceMeta, MCPToolMeta, MCPPromptMeta } from '@pikku/core';
7
+ import { CLIMeta } from '@pikku/core';
6
8
  import { TypesMap } from './types-map.js';
7
9
  import { FunctionsMeta, FunctionServicesMeta } from '@pikku/core';
8
10
  export type PathToNameAndType = Map<string, {
@@ -15,14 +17,27 @@ export type MetaInputTypes = Map<string, {
15
17
  params: string[] | undefined;
16
18
  body: string[] | undefined;
17
19
  }>;
20
+ export interface MiddlewareGroupMeta {
21
+ exportName: string | null;
22
+ sourceFile: string;
23
+ position: number;
24
+ services: FunctionServicesMeta;
25
+ middlewareCount: number;
26
+ isFactory: boolean;
27
+ }
18
28
  export interface InspectorHTTPState {
19
29
  metaInputTypes: MetaInputTypes;
20
30
  meta: HTTPWiringsMeta;
21
31
  files: Set<string>;
32
+ routeMiddleware: Map<string, MiddlewareGroupMeta>;
22
33
  }
23
34
  export interface InspectorFunctionState {
24
35
  typesMap: TypesMap;
25
36
  meta: FunctionsMeta;
37
+ files: Map<string, {
38
+ path: string;
39
+ exportedName: string;
40
+ }>;
26
41
  }
27
42
  export interface InspectorChannelState {
28
43
  meta: ChannelsMeta;
@@ -34,7 +49,9 @@ export interface InspectorMiddlewareState {
34
49
  sourceFile: string;
35
50
  position: number;
36
51
  exportedName: string | null;
52
+ factory?: boolean;
37
53
  }>;
54
+ tagMiddleware: Map<string, MiddlewareGroupMeta>;
38
55
  }
39
56
  export interface InspectorPermissionState {
40
57
  meta: Record<string, {
@@ -49,19 +66,77 @@ export type InspectorFilters = {
49
66
  types?: string[];
50
67
  directories?: string[];
51
68
  };
69
+ export type InspectorOptions = Partial<{
70
+ types: Partial<{
71
+ configFileType: string;
72
+ userSessionType: string;
73
+ singletonServicesFactoryType: string;
74
+ sessionServicesFactoryType: string;
75
+ }>;
76
+ filters: InspectorFilters;
77
+ }>;
52
78
  export interface InspectorLogger {
53
79
  info: (message: string) => void;
54
80
  error: (message: string) => void;
55
81
  warn: (message: string) => void;
56
82
  debug: (message: string) => void;
57
83
  }
84
+ export type AddWiring = (logger: InspectorLogger, node: ts.Node, checker: ts.TypeChecker, state: InspectorState, options: InspectorOptions) => void;
85
+ export interface InspectorFilesAndMethods {
86
+ userSessionType?: {
87
+ file: string;
88
+ variable: string;
89
+ type: string;
90
+ typePath: string;
91
+ };
92
+ sessionServicesType?: {
93
+ file: string;
94
+ variable: string;
95
+ type: string;
96
+ typePath: string;
97
+ };
98
+ singletonServicesType?: {
99
+ file: string;
100
+ variable: string;
101
+ type: string;
102
+ typePath: string;
103
+ };
104
+ pikkuConfigType?: {
105
+ file: string;
106
+ variable: string;
107
+ type: string;
108
+ typePath: string;
109
+ };
110
+ pikkuConfigFactory?: {
111
+ file: string;
112
+ variable: string;
113
+ type: string;
114
+ typePath: string;
115
+ };
116
+ singletonServicesFactory?: {
117
+ file: string;
118
+ variable: string;
119
+ type: string;
120
+ typePath: string;
121
+ };
122
+ sessionServicesFactory?: {
123
+ file: string;
124
+ variable: string;
125
+ type: string;
126
+ typePath: string;
127
+ };
128
+ }
58
129
  export interface InspectorState {
59
130
  singletonServicesTypeImportMap: PathToNameAndType;
60
131
  sessionServicesTypeImportMap: PathToNameAndType;
61
132
  userSessionTypeImportMap: PathToNameAndType;
133
+ configTypeImportMap: PathToNameAndType;
62
134
  singletonServicesFactories: PathToNameAndType;
63
135
  sessionServicesFactories: PathToNameAndType;
64
136
  configFactories: PathToNameAndType;
137
+ filesAndMethods: InspectorFilesAndMethods;
138
+ filesAndMethodsErrors: Map<string, PathToNameAndType>;
139
+ typesLookup: Map<string, ts.Type[]>;
65
140
  http: InspectorHTTPState;
66
141
  functions: InspectorFunctionState;
67
142
  channels: InspectorChannelState;
@@ -92,6 +167,10 @@ export interface InspectorState {
92
167
  promptsMeta: MCPPromptMeta;
93
168
  files: Set<string>;
94
169
  };
170
+ cli: {
171
+ meta: CLIMeta;
172
+ files: Set<string>;
173
+ };
95
174
  middleware: InspectorMiddlewareState;
96
175
  permissions: InspectorPermissionState;
97
176
  }
@@ -1,7 +1,5 @@
1
1
  import * as ts from 'typescript';
2
- import { InspectorFilters, InspectorLogger } from './types.js';
3
- import { PikkuWiringTypes, FunctionServicesMeta } from '@pikku/core';
4
- type ExtractedFunctionName = {
2
+ export type ExtractedFunctionName = {
5
3
  pikkuFuncName: string;
6
4
  name: string;
7
5
  explicitName: string | null;
@@ -23,17 +21,11 @@ export declare function makeDeterministicAnonName(start: ts.Node, checker: ts.Ty
23
21
  * 3. Fallback to deterministic name
24
22
  */
25
23
  export declare function extractFunctionName(callExpr: ts.Node, checker: ts.TypeChecker): ExtractedFunctionName;
26
- export declare const extractTypeKeys: (type: ts.Type) => string[];
27
- export declare function getPropertyAssignmentInitializer(obj: ts.ObjectLiteralExpression, propName: string, followShorthand?: boolean, checker?: ts.TypeChecker): ts.Expression | undefined;
28
- export declare const matchesFilters: (filters: InspectorFilters, params: {
29
- tags?: string[];
30
- }, meta: {
31
- type: PikkuWiringTypes;
32
- name: string;
33
- filePath?: string;
34
- }, logger: InspectorLogger) => boolean;
35
24
  /**
36
- * Extract services from a function's first parameter destructuring pattern
25
+ * Helper function to populate the 'name' field based on priority
26
+ */
27
+ export declare function populateNameByPriority(result: ExtractedFunctionName): void;
28
+ /**
29
+ * Helper function to check if a variable declaration is a named export
37
30
  */
38
- export declare function extractServicesFromFunction(handlerNode: ts.FunctionExpression | ts.ArrowFunction): FunctionServicesMeta;
39
- export {};
31
+ export declare function isNamedExport(declaration: ts.VariableDeclaration): boolean;
@@ -256,9 +256,8 @@ export function extractFunctionName(callExpr, checker) {
256
256
  }
257
257
  }
258
258
  }
259
- // First, figure out what function we're really dealing with
260
- let mainFunc = callExpr;
261
- let originalCallExpr = callExpr; // Keep track of the original call expression for name extraction
259
+ // Keep track of the original call expression for position-based naming
260
+ let originalCallExpr = callExpr;
262
261
  // For direct pikku function calls where callExpr is the call expression itself
263
262
  if (ts.isCallExpression(callExpr)) {
264
263
  const { expression, arguments: args } = callExpr;
@@ -284,7 +283,7 @@ export function extractFunctionName(callExpr, checker) {
284
283
  const firstArg = args[0];
285
284
  if (ts.isArrowFunction(firstArg) ||
286
285
  ts.isFunctionExpression(firstArg)) {
287
- mainFunc = firstArg; // Use the arrow function directly instead of the call expression
286
+ // mainFunc = firstArg // Use the arrow function directly instead of the call expression
288
287
  }
289
288
  }
290
289
  }
@@ -321,7 +320,7 @@ export function extractFunctionName(callExpr, checker) {
321
320
  if (firstArg &&
322
321
  (ts.isArrowFunction(firstArg) ||
323
322
  ts.isFunctionExpression(firstArg))) {
324
- mainFunc = firstArg;
323
+ // mainFunc = firstArg
325
324
  // Check if the variable is exported
326
325
  if (isNamedExport(funcDecl) &&
327
326
  ts.isIdentifier(funcDecl.name)) {
@@ -336,7 +335,7 @@ export function extractFunctionName(callExpr, checker) {
336
335
  }
337
336
  else if (ts.isFunctionExpression(funcDecl.initializer) ||
338
337
  ts.isArrowFunction(funcDecl.initializer)) {
339
- mainFunc = funcDecl.initializer;
338
+ // mainFunc = funcDecl.initializer
340
339
  // Check if the variable is exported
341
340
  if (isNamedExport(funcDecl) &&
342
341
  ts.isIdentifier(funcDecl.name)) {
@@ -350,7 +349,7 @@ export function extractFunctionName(callExpr, checker) {
350
349
  }
351
350
  }
352
351
  else if (ts.isFunctionDeclaration(funcDecl)) {
353
- mainFunc = funcDecl;
352
+ // mainFunc = funcDecl
354
353
  // Check if the function is exported
355
354
  if (funcDecl.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) &&
356
355
  funcDecl.name &&
@@ -368,14 +367,14 @@ export function extractFunctionName(callExpr, checker) {
368
367
  }
369
368
  else {
370
369
  // If we can't resolve the symbol, use the identifier itself
371
- mainFunc = prop.initializer;
370
+ // mainFunc = prop.initializer
372
371
  }
373
372
  break;
374
373
  }
375
374
  else if (ts.isFunctionExpression(prop.initializer) ||
376
375
  ts.isArrowFunction(prop.initializer)) {
377
376
  // func: () => {} or func: function() {} - use directly
378
- mainFunc = prop.initializer;
377
+ // mainFunc = prop.initializer
379
378
  break;
380
379
  }
381
380
  }
@@ -401,7 +400,7 @@ export function extractFunctionName(callExpr, checker) {
401
400
  if (firstArg &&
402
401
  (ts.isArrowFunction(firstArg) ||
403
402
  ts.isFunctionExpression(firstArg))) {
404
- mainFunc = firstArg;
403
+ // mainFunc = firstArg
405
404
  // Check if the variable is exported
406
405
  if (isNamedExport(shorthandDecl) &&
407
406
  ts.isIdentifier(shorthandDecl.name)) {
@@ -416,7 +415,7 @@ export function extractFunctionName(callExpr, checker) {
416
415
  }
417
416
  else if (ts.isFunctionExpression(shorthandDecl.initializer) ||
418
417
  ts.isArrowFunction(shorthandDecl.initializer)) {
419
- mainFunc = shorthandDecl.initializer;
418
+ // mainFunc = shorthandDecl.initializer
420
419
  // Check if the variable is exported
421
420
  if (isNamedExport(shorthandDecl) &&
422
421
  ts.isIdentifier(shorthandDecl.name)) {
@@ -430,7 +429,7 @@ export function extractFunctionName(callExpr, checker) {
430
429
  }
431
430
  }
432
431
  else if (ts.isFunctionDeclaration(shorthandDecl)) {
433
- mainFunc = shorthandDecl;
432
+ // mainFunc = shorthandDecl
434
433
  // Check if the function is exported
435
434
  if (shorthandDecl.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) &&
436
435
  shorthandDecl.name &&
@@ -468,6 +467,9 @@ export function extractFunctionName(callExpr, checker) {
468
467
  if (ts.isCallExpression(decl.initializer) &&
469
468
  ts.isIdentifier(decl.initializer.expression) &&
470
469
  decl.initializer.expression.text.startsWith('pikku')) {
470
+ // Update originalCallExpr to use the call expression position
471
+ // instead of the variable declaration position
472
+ originalCallExpr = decl.initializer;
471
473
  // Check for object with 'name' property in first argument
472
474
  const firstArg = decl.initializer.arguments[0];
473
475
  if (firstArg && ts.isObjectLiteralExpression(firstArg)) {
@@ -486,7 +488,7 @@ export function extractFunctionName(callExpr, checker) {
486
488
  if (firstArg &&
487
489
  (ts.isArrowFunction(firstArg) ||
488
490
  ts.isFunctionExpression(firstArg))) {
489
- mainFunc = firstArg;
491
+ // mainFunc = firstArg
490
492
  }
491
493
  }
492
494
  // Check if the variable is exported
@@ -502,7 +504,7 @@ export function extractFunctionName(callExpr, checker) {
502
504
  }
503
505
  else if (ts.isFunctionExpression(decl.initializer) ||
504
506
  ts.isArrowFunction(decl.initializer)) {
505
- mainFunc = decl.initializer;
507
+ // mainFunc = decl.initializer
506
508
  // Check if the variable is exported
507
509
  if (isNamedExport(decl) && ts.isIdentifier(decl.name)) {
508
510
  result.exportedName = decl.name.text;
@@ -513,7 +515,7 @@ export function extractFunctionName(callExpr, checker) {
513
515
  }
514
516
  }
515
517
  else if (ts.isFunctionDeclaration(decl)) {
516
- mainFunc = decl;
518
+ // mainFunc = decl
517
519
  // Check if the function is exported
518
520
  if (decl.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) &&
519
521
  decl.name &&
@@ -527,8 +529,10 @@ export function extractFunctionName(callExpr, checker) {
527
529
  }
528
530
  }
529
531
  }
530
- // Now generate the deterministic function name based on the resolved function
531
- result.pikkuFuncName = makeDeterministicAnonName(mainFunc, checker);
532
+ // Generate the deterministic function name based on the original call expression
533
+ // (the config), not the resolved inner function. This ensures the metadata key
534
+ // matches what will be looked up at runtime when referencing the config object.
535
+ result.pikkuFuncName = makeDeterministicAnonName(originalCallExpr, checker);
532
536
  // Continue with regular name extraction for remaining cases
533
537
  // 1) const foo = pikkuFunc(...)
534
538
  if (ts.isVariableDeclaration(parent) && ts.isIdentifier(parent.name)) {
@@ -577,7 +581,7 @@ export function extractFunctionName(callExpr, checker) {
577
581
  /**
578
582
  * Helper function to populate the 'name' field based on priority
579
583
  */
580
- function populateNameByPriority(result) {
584
+ export function populateNameByPriority(result) {
581
585
  // Priority 1: If we have an explict name, use that
582
586
  if (result.explicitName) {
583
587
  result.name = result.explicitName;
@@ -599,7 +603,7 @@ function populateNameByPriority(result) {
599
603
  /**
600
604
  * Helper function to check if a variable declaration is a named export
601
605
  */
602
- function isNamedExport(declaration) {
606
+ export function isNamedExport(declaration) {
603
607
  let parent = declaration.parent;
604
608
  if (!parent)
605
609
  return false;
@@ -616,126 +620,3 @@ function isNamedExport(declaration) {
616
620
  }
617
621
  return false;
618
622
  }
619
- // Until here
620
- export const extractTypeKeys = (type) => {
621
- return type.getProperties().map((symbol) => symbol.getName());
622
- };
623
- export function getPropertyAssignmentInitializer(obj, propName, followShorthand = false, checker) {
624
- for (const prop of obj.properties) {
625
- // ① foo: () => {}
626
- if (ts.isPropertyAssignment(prop) &&
627
- ts.isIdentifier(prop.name) &&
628
- prop.name.text === propName) {
629
- return prop.initializer;
630
- }
631
- // ② foo() { … }
632
- if (ts.isMethodDeclaration(prop) &&
633
- ts.isIdentifier(prop.name) &&
634
- prop.name.text === propName) {
635
- return prop.name; // the method node *is* the function
636
- }
637
- // ③ { foo } (shorthand)
638
- if (followShorthand &&
639
- ts.isShorthandPropertyAssignment(prop) &&
640
- prop.name.text === propName) {
641
- if (!checker)
642
- return prop.name; // best effort without a checker
643
- let sym = checker.getSymbolAtLocation(prop.name);
644
- if (sym && sym.flags & ts.SymbolFlags.Alias) {
645
- sym = checker.getAliasedSymbol(sym);
646
- }
647
- const decl = sym?.declarations?.[0];
648
- // const foo = () => {}
649
- if (decl &&
650
- ts.isVariableDeclaration(decl) &&
651
- decl.initializer &&
652
- (ts.isArrowFunction(decl.initializer) ||
653
- ts.isFunctionExpression(decl.initializer))) {
654
- return decl.initializer;
655
- }
656
- // function foo() {}
657
- if (decl &&
658
- (ts.isFunctionDeclaration(decl) ||
659
- ts.isArrowFunction(decl) ||
660
- ts.isFunctionExpression(decl))) {
661
- return decl;
662
- }
663
- // fallback – just give back the identifier
664
- return prop.name;
665
- }
666
- }
667
- return undefined;
668
- }
669
- export const matchesFilters = (filters, params, meta, logger) => {
670
- // If no filters are provided, allow everything
671
- if (Object.keys(filters).length === 0) {
672
- return true;
673
- }
674
- // If all filter arrays are empty, allow everything
675
- if ((!filters.tags || filters.tags.length === 0) &&
676
- (!filters.types || filters.types.length === 0) &&
677
- (!filters.directories || filters.directories.length === 0)) {
678
- return true;
679
- }
680
- // Check type filter
681
- if (filters.types && filters.types.length > 0) {
682
- if (!filters.types.includes(meta.type)) {
683
- logger.debug(`⒡ Filtered by type: ${meta.type}:${meta.name}`);
684
- return false;
685
- }
686
- }
687
- // Check directory filter
688
- if (filters.directories && filters.directories.length > 0) {
689
- if (!meta.filePath) {
690
- logger.debug(`⒡ Filtered by directory: ${meta.type}:${meta.name} (${meta.filePath})`);
691
- return false;
692
- }
693
- const matchesDirectory = filters.directories.some((dir) => {
694
- // Normalize paths for comparison
695
- const normalizedFilePath = meta.filePath.replace(/\\/g, '/');
696
- const normalizedDir = dir.replace(/\\/g, '/');
697
- return normalizedFilePath.includes(normalizedDir);
698
- });
699
- if (!matchesDirectory) {
700
- logger.debug(`⒡ Filtered by directory: ${meta.type}:${meta.name} (${meta.filePath})`);
701
- return false;
702
- }
703
- }
704
- // Check tag filter
705
- if (filters.tags && filters.tags.length > 0) {
706
- if (!params.tags ||
707
- !filters.tags.some((tag) => params.tags.includes(tag))) {
708
- logger.debug(`⒡ Filtered by tags: ${meta.type}:${meta.name}`);
709
- return false;
710
- }
711
- }
712
- return true;
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
- }
@@ -0,0 +1,6 @@
1
+ import * as ts from 'typescript';
2
+ import { FunctionServicesMeta } from '@pikku/core';
3
+ /**
4
+ * Extract services from a function's first parameter destructuring pattern
5
+ */
6
+ export declare function extractServicesFromFunction(handlerNode: ts.FunctionExpression | ts.ArrowFunction): FunctionServicesMeta;
@@ -0,0 +1,29 @@
1
+ import * as ts from 'typescript';
2
+ /**
3
+ * Extract services from a function's first parameter destructuring pattern
4
+ */
5
+ export function extractServicesFromFunction(handlerNode) {
6
+ const services = {
7
+ optimized: true,
8
+ services: [],
9
+ };
10
+ const firstParam = handlerNode.parameters[0];
11
+ if (firstParam) {
12
+ if (ts.isObjectBindingPattern(firstParam.name)) {
13
+ for (const elem of firstParam.name.elements) {
14
+ const original = elem.propertyName && ts.isIdentifier(elem.propertyName)
15
+ ? elem.propertyName.text
16
+ : ts.isIdentifier(elem.name)
17
+ ? elem.name.text
18
+ : undefined;
19
+ if (original) {
20
+ services.services.push(original);
21
+ }
22
+ }
23
+ }
24
+ else if (ts.isIdentifier(firstParam.name)) {
25
+ services.optimized = false;
26
+ }
27
+ }
28
+ return services;
29
+ }
@@ -0,0 +1,9 @@
1
+ import { InspectorFilters, InspectorLogger } from '../types.js';
2
+ import { PikkuWiringTypes } from '@pikku/core';
3
+ export declare const matchesFilters: (filters: InspectorFilters, params: {
4
+ tags?: string[];
5
+ }, meta: {
6
+ type: PikkuWiringTypes;
7
+ name: string;
8
+ filePath?: string;
9
+ }, logger: InspectorLogger) => boolean;
@@ -0,0 +1,45 @@
1
+ export const matchesFilters = (filters, params, meta, logger) => {
2
+ // If no filters are provided, allow everything
3
+ if (Object.keys(filters).length === 0) {
4
+ return true;
5
+ }
6
+ // If all filter arrays are empty, allow everything
7
+ if ((!filters.tags || filters.tags.length === 0) &&
8
+ (!filters.types || filters.types.length === 0) &&
9
+ (!filters.directories || filters.directories.length === 0)) {
10
+ return true;
11
+ }
12
+ // Check type filter
13
+ if (filters.types && filters.types.length > 0) {
14
+ if (!filters.types.includes(meta.type)) {
15
+ logger.debug(`⒡ Filtered by type: ${meta.type}:${meta.name}`);
16
+ return false;
17
+ }
18
+ }
19
+ // Check directory filter
20
+ if (filters.directories && filters.directories.length > 0) {
21
+ if (!meta.filePath) {
22
+ logger.debug(`⒡ Filtered by directory: ${meta.type}:${meta.name} (${meta.filePath})`);
23
+ return false;
24
+ }
25
+ const matchesDirectory = filters.directories.some((dir) => {
26
+ // Normalize paths for comparison
27
+ const normalizedFilePath = meta.filePath.replace(/\\/g, '/');
28
+ const normalizedDir = dir.replace(/\\/g, '/');
29
+ return normalizedFilePath.includes(normalizedDir);
30
+ });
31
+ if (!matchesDirectory) {
32
+ logger.debug(`⒡ Filtered by directory: ${meta.type}:${meta.name} (${meta.filePath})`);
33
+ return false;
34
+ }
35
+ }
36
+ // Check tag filter
37
+ if (filters.tags && filters.tags.length > 0) {
38
+ if (!params.tags ||
39
+ !filters.tags.some((tag) => params.tags.includes(tag))) {
40
+ logger.debug(`⒡ Filtered by tags: ${meta.type}:${meta.name}`);
41
+ return false;
42
+ }
43
+ }
44
+ return true;
45
+ };
@@ -0,0 +1,21 @@
1
+ import { PathToNameAndType, InspectorState, InspectorOptions } from '../types.js';
2
+ interface Meta {
3
+ file: string;
4
+ variable: string;
5
+ type: string;
6
+ typePath: string;
7
+ }
8
+ export type FilesAndMethods = {
9
+ userSessionType: Meta;
10
+ sessionServicesType: Meta;
11
+ singletonServicesType: Meta;
12
+ pikkuConfigFactory: Meta;
13
+ singletonServicesFactory: Meta;
14
+ sessionServicesFactory: Meta;
15
+ };
16
+ export type FilesAndMethodsErrors = Map<string, PathToNameAndType>;
17
+ export declare const getFilesAndMethods: ({ singletonServicesTypeImportMap, sessionServicesTypeImportMap, userSessionTypeImportMap, sessionServicesFactories, singletonServicesFactories, configFactories, }: InspectorState, { configFileType, userSessionType, singletonServicesFactoryType, sessionServicesFactoryType, }?: InspectorOptions["types"]) => {
18
+ result: Partial<FilesAndMethods>;
19
+ errors: FilesAndMethodsErrors;
20
+ };
21
+ export {};