@pikku/inspector 0.9.5 → 0.10.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 (133) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/add/add-channel.d.ts +17 -0
  3. package/dist/{add-channel.js → add/add-channel.js} +60 -34
  4. package/dist/add/add-cli.d.ts +9 -0
  5. package/dist/add/add-cli.js +566 -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 -4
  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} +2 -2
  11. package/dist/{add-file-with-factory.js → add/add-file-with-factory.js} +38 -5
  12. package/dist/add/add-functions.d.ts +6 -0
  13. package/dist/{add-functions.js → add/add-functions.js} +77 -10
  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} +26 -13
  16. package/dist/add/add-mcp-prompt.d.ts +2 -0
  17. package/dist/add/add-mcp-prompt.js +74 -0
  18. package/dist/add/add-mcp-resource.d.ts +2 -0
  19. package/dist/add/add-mcp-resource.js +84 -0
  20. package/dist/add/add-mcp-tool.d.ts +2 -0
  21. package/dist/add/add-mcp-tool.js +80 -0
  22. package/dist/add/add-middleware.d.ts +5 -0
  23. package/dist/add/add-middleware.js +290 -0
  24. package/dist/add/add-permission.d.ts +5 -0
  25. package/dist/add/add-permission.js +292 -0
  26. package/dist/add/add-queue-worker.d.ts +2 -0
  27. package/dist/add/add-queue-worker.js +52 -0
  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} +16 -11
  31. package/dist/error-codes.d.ts +35 -0
  32. package/dist/error-codes.js +40 -0
  33. package/dist/index.d.ts +6 -0
  34. package/dist/index.js +4 -0
  35. package/dist/inspector.d.ts +2 -3
  36. package/dist/inspector.js +38 -8
  37. package/dist/types.d.ts +108 -1
  38. package/dist/utils/ensure-function-metadata.d.ts +6 -0
  39. package/dist/utils/ensure-function-metadata.js +18 -0
  40. package/dist/utils/extract-function-name.d.ts +31 -0
  41. package/dist/{utils.js → utils/extract-function-name.js} +35 -149
  42. package/dist/utils/extract-services.d.ts +6 -0
  43. package/dist/utils/extract-services.js +29 -0
  44. package/dist/utils/filter-inspector-state.d.ts +6 -0
  45. package/dist/utils/filter-inspector-state.js +382 -0
  46. package/dist/utils/filter-utils.d.ts +19 -0
  47. package/dist/utils/filter-utils.js +109 -0
  48. package/dist/utils/find-root-dir.d.ts +23 -0
  49. package/dist/utils/find-root-dir.js +55 -0
  50. package/dist/utils/get-files-and-methods.d.ts +22 -0
  51. package/dist/utils/get-files-and-methods.js +61 -0
  52. package/dist/utils/get-property-value.d.ts +12 -0
  53. package/dist/{get-property-value.js → utils/get-property-value.js} +20 -0
  54. package/dist/utils/middleware.d.ts +39 -0
  55. package/dist/utils/middleware.js +157 -0
  56. package/dist/utils/permissions.d.ts +43 -0
  57. package/dist/utils/permissions.js +178 -0
  58. package/dist/utils/post-process.d.ts +16 -0
  59. package/dist/utils/post-process.js +132 -0
  60. package/dist/utils/serialize-inspector-state.d.ts +179 -0
  61. package/dist/utils/serialize-inspector-state.js +170 -0
  62. package/dist/utils/type-utils.d.ts +3 -0
  63. package/dist/utils/type-utils.js +50 -0
  64. package/dist/visit.d.ts +3 -3
  65. package/dist/visit.js +35 -31
  66. package/package.json +5 -6
  67. package/src/{add-channel.ts → add/add-channel.ts} +108 -56
  68. package/src/add/add-cli.ts +822 -0
  69. package/src/{add-file-extends-core-type.ts → add/add-file-extends-core-type.ts} +23 -5
  70. package/src/{add-file-with-config.ts → add/add-file-with-config.ts} +2 -2
  71. package/src/{add-file-with-factory.ts → add/add-file-with-factory.ts} +49 -6
  72. package/src/{add-functions.ts → add/add-functions.ts} +89 -19
  73. package/src/{add-http-route.ts → add/add-http-route.ts} +66 -32
  74. package/src/add/add-mcp-prompt.ts +128 -0
  75. package/src/add/add-mcp-prompt.ts.tmp +0 -0
  76. package/src/add/add-mcp-resource.ts +145 -0
  77. package/src/add/add-mcp-resource.ts.tmp +0 -0
  78. package/src/add/add-mcp-tool.ts +137 -0
  79. package/src/add/add-middleware.ts +385 -0
  80. package/src/add/add-permission.ts +391 -0
  81. package/src/add/add-queue-worker.ts +92 -0
  82. package/src/{add-rpc-invocations.ts → add/add-rpc-invocations.ts} +1 -1
  83. package/src/{add-schedule.ts → add/add-schedule.ts} +30 -28
  84. package/src/error-codes.ts +43 -0
  85. package/src/index.ts +12 -0
  86. package/src/inspector.ts +41 -17
  87. package/src/types.ts +128 -1
  88. package/src/utils/ensure-function-metadata.ts +24 -0
  89. package/src/{utils.ts → utils/extract-function-name.ts} +44 -206
  90. package/src/utils/extract-services.ts +35 -0
  91. package/src/utils/filter-inspector-state.test.ts +1433 -0
  92. package/src/utils/filter-inspector-state.ts +526 -0
  93. package/src/{utils.test.ts → utils/filter-utils.test.ts} +351 -2
  94. package/src/utils/filter-utils.ts +152 -0
  95. package/src/utils/find-root-dir.ts +68 -0
  96. package/src/utils/get-files-and-methods.ts +151 -0
  97. package/src/{get-property-value.ts → utils/get-property-value.ts} +27 -0
  98. package/src/utils/middleware.ts +241 -0
  99. package/src/utils/permissions.test.ts +327 -0
  100. package/src/utils/permissions.ts +262 -0
  101. package/src/utils/post-process.ts +178 -0
  102. package/src/utils/serialize-inspector-state.ts +375 -0
  103. package/src/utils/test-data/inspector-state.json +1680 -0
  104. package/src/utils/type-utils.ts +74 -0
  105. package/src/visit.ts +50 -34
  106. package/tsconfig.tsbuildinfo +1 -1
  107. package/dist/add-channel.d.ts +0 -13
  108. package/dist/add-functions.d.ts +0 -7
  109. package/dist/add-mcp-prompt.d.ts +0 -3
  110. package/dist/add-mcp-prompt.js +0 -61
  111. package/dist/add-mcp-resource.d.ts +0 -3
  112. package/dist/add-mcp-resource.js +0 -68
  113. package/dist/add-mcp-tool.d.ts +0 -3
  114. package/dist/add-mcp-tool.js +0 -64
  115. package/dist/add-middleware.d.ts +0 -7
  116. package/dist/add-middleware.js +0 -35
  117. package/dist/add-permission.d.ts +0 -7
  118. package/dist/add-permission.js +0 -35
  119. package/dist/add-queue-worker.d.ts +0 -3
  120. package/dist/add-queue-worker.js +0 -48
  121. package/dist/add-schedule.d.ts +0 -3
  122. package/dist/get-property-value.d.ts +0 -3
  123. package/dist/utils.d.ts +0 -39
  124. package/src/add-mcp-prompt.ts +0 -104
  125. package/src/add-mcp-resource.ts +0 -116
  126. package/src/add-mcp-tool.ts +0 -107
  127. package/src/add-middleware.ts +0 -51
  128. package/src/add-permission.ts +0 -53
  129. package/src/add-queue-worker.ts +0 -92
  130. /package/dist/{add-rpc-invocations.js → add/add-rpc-invocations.js} +0 -0
  131. /package/dist/{does-type-extend-core-type.d.ts → utils/does-type-extend-core-type.d.ts} +0 -0
  132. /package/dist/{does-type-extend-core-type.js → utils/does-type-extend-core-type.js} +0 -0
  133. /package/src/{does-type-extend-core-type.ts → utils/does-type-extend-core-type.ts} +0 -0
@@ -1,21 +1,20 @@
1
1
  import * as ts from 'typescript'
2
- import { getPropertyValue } from './get-property-value.js'
3
- import { pathToRegexp } from 'path-to-regexp'
4
- import { PikkuDocs, PikkuWiringTypes } from '@pikku/core'
2
+ import { ErrorCode } from '../error-codes.js'
5
3
  import {
6
- extractFunctionName,
7
- getPropertyAssignmentInitializer,
8
- matchesFilters,
9
- } from './utils.js'
4
+ getPropertyValue,
5
+ getPropertyTags,
6
+ } from '../utils/get-property-value.js'
7
+ import { pathToRegexp } from 'path-to-regexp'
8
+ import { PikkuDocs } from '@pikku/core'
9
+ import { extractFunctionName } from '../utils/extract-function-name.js'
10
+ import { getPropertyAssignmentInitializer } from '../utils/type-utils.js'
10
11
  import type { ChannelMessageMeta, ChannelMeta } from '@pikku/core/channel'
11
- import type {
12
- InspectorFilters,
13
- InspectorState,
14
- InspectorLogger,
15
- } from './types.js'
12
+ import type { InspectorState, AddWiring } from '../types.js'
13
+ import { resolveMiddleware } from '../utils/middleware.js'
14
+ import { extractWireNames } from '../utils/post-process.js'
16
15
 
17
16
  /**
18
- * Safely get the initializer expression of a property-like AST node:
17
+ * Safely get the "initializer" expression of a property-like AST node:
19
18
  * - for `foo: expr`, returns `expr`
20
19
  * - for `{ foo }` shorthand, returns the identifier `foo`
21
20
  * - otherwise, returns undefined
@@ -38,7 +37,8 @@ function getInitializerOf(
38
37
  */
39
38
  function getHandlerNameFromExpression(
40
39
  expr: ts.Expression,
41
- checker: ts.TypeChecker
40
+ checker: ts.TypeChecker,
41
+ rootDir: string
42
42
  ): string | null {
43
43
  // Handle direct identifier case (which includes shorthand properties)
44
44
  if (ts.isIdentifier(expr)) {
@@ -64,27 +64,28 @@ function getHandlerNameFromExpression(
64
64
  // Extract function name from the declaration's initializer
65
65
  const { pikkuFuncName } = extractFunctionName(
66
66
  decl.initializer,
67
- checker
67
+ checker,
68
+ rootDir
68
69
  )
69
70
  return pikkuFuncName
70
71
  }
71
72
  }
72
73
  // For function declarations, use directly
73
74
  else if (ts.isFunctionDeclaration(decl)) {
74
- const { pikkuFuncName } = extractFunctionName(decl, checker)
75
+ const { pikkuFuncName } = extractFunctionName(decl, checker, rootDir)
75
76
  return pikkuFuncName
76
77
  }
77
78
  }
78
79
  }
79
80
 
80
81
  // Fallback: try to extract directly from the identifier
81
- const { pikkuFuncName } = extractFunctionName(expr, checker)
82
+ const { pikkuFuncName } = extractFunctionName(expr, checker, rootDir)
82
83
  return pikkuFuncName
83
84
  }
84
85
 
85
86
  // Handle call expressions
86
87
  if (ts.isCallExpression(expr)) {
87
- const { pikkuFuncName } = extractFunctionName(expr, checker)
88
+ const { pikkuFuncName } = extractFunctionName(expr, checker, rootDir)
88
89
  return pikkuFuncName
89
90
  }
90
91
 
@@ -92,7 +93,7 @@ function getHandlerNameFromExpression(
92
93
  if (ts.isObjectLiteralExpression(expr)) {
93
94
  const fnProp = getPropertyAssignmentInitializer(expr, 'func', true, checker)
94
95
  if (fnProp) {
95
- return getHandlerNameFromExpression(fnProp, checker)
96
+ return getHandlerNameFromExpression(fnProp, checker, rootDir)
96
97
  }
97
98
  }
98
99
 
@@ -104,6 +105,10 @@ function getHandlerNameFromExpression(
104
105
  * in state.functions.meta instead of re-inferring it here.
105
106
  */
106
107
  export function addMessagesRoutes(
108
+ logger: {
109
+ error: (msg: string) => void
110
+ critical: (code: ErrorCode, msg: string) => void
111
+ },
107
112
  obj: ts.ObjectLiteralExpression,
108
113
  state: InspectorState,
109
114
  checker: ts.TypeChecker
@@ -183,7 +188,8 @@ export function addMessagesRoutes(
183
188
  ) {
184
189
  const { pikkuFuncName } = extractFunctionName(
185
190
  importDecl.initializer,
186
- checker
191
+ checker,
192
+ state.rootDir
187
193
  )
188
194
  const handlerName = pikkuFuncName
189
195
 
@@ -200,7 +206,8 @@ export function addMessagesRoutes(
200
206
  // Extract from the function declaration
201
207
  const { pikkuFuncName } = extractFunctionName(
202
208
  importDecl,
203
- checker
209
+ checker,
210
+ state.rootDir
204
211
  )
205
212
  const handlerName = pikkuFuncName
206
213
 
@@ -235,7 +242,8 @@ export function addMessagesRoutes(
235
242
  ) {
236
243
  const { pikkuFuncName } = extractFunctionName(
237
244
  exportDecl.initializer,
238
- checker
245
+ checker,
246
+ state.rootDir
239
247
  )
240
248
  const handlerName = pikkuFuncName
241
249
 
@@ -249,7 +257,8 @@ export function addMessagesRoutes(
249
257
  } else if (ts.isFunctionDeclaration(exportDecl)) {
250
258
  const { pikkuFuncName } = extractFunctionName(
251
259
  exportDecl,
252
- checker
260
+ checker,
261
+ state.rootDir
253
262
  )
254
263
  const handlerName = pikkuFuncName
255
264
 
@@ -282,7 +291,8 @@ export function addMessagesRoutes(
282
291
  if (possibleMatch) {
283
292
  const fnMeta = state.functions.meta[possibleMatch]
284
293
  if (!fnMeta) {
285
- console.error(
294
+ logger.critical(
295
+ ErrorCode.FUNCTION_METADATA_NOT_FOUND,
286
296
  `No function metadata found for handler '${possibleMatch}'`
287
297
  )
288
298
  continue
@@ -317,7 +327,8 @@ export function addMessagesRoutes(
317
327
  // Extract the function name directly from the actual function
318
328
  const { pikkuFuncName } = extractFunctionName(
319
329
  actualFunction,
320
- checker
330
+ checker,
331
+ state.rootDir
321
332
  )
322
333
  const handlerName = pikkuFuncName
323
334
 
@@ -336,9 +347,13 @@ export function addMessagesRoutes(
336
347
  }
337
348
 
338
349
  // Normal processing for non-shorthand properties
339
- const handlerName = getHandlerNameFromExpression(init, checker)
350
+ const handlerName = getHandlerNameFromExpression(
351
+ init,
352
+ checker,
353
+ state.rootDir
354
+ )
340
355
  if (!handlerName) {
341
- console.error(
356
+ logger.error(
342
357
  `Could not resolve handler for message route '${routeKey}'`
343
358
  )
344
359
  continue
@@ -346,7 +361,10 @@ export function addMessagesRoutes(
346
361
 
347
362
  const fnMeta = state.functions.meta[handlerName]
348
363
  if (!fnMeta) {
349
- console.error(`No function metadata found for handler '${handlerName}'`)
364
+ logger.critical(
365
+ ErrorCode.FUNCTION_METADATA_NOT_FOUND,
366
+ `No function metadata found for handler '${handlerName}'`
367
+ )
350
368
  continue
351
369
  }
352
370
 
@@ -363,13 +381,13 @@ export function addMessagesRoutes(
363
381
  * Inspect addChannel calls, look up all handlers in state.functions.meta,
364
382
  * and emit one entry into state.channels.meta.
365
383
  */
366
- export function addChannel(
367
- node: ts.Node,
368
- checker: ts.TypeChecker,
369
- state: InspectorState,
370
- filters: InspectorFilters,
371
- logger: InspectorLogger
372
- ) {
384
+ export const addChannel: AddWiring = (
385
+ logger,
386
+ node,
387
+ checker,
388
+ state,
389
+ options
390
+ ) => {
373
391
  if (!ts.isCallExpression(node)) return
374
392
  const { expression, arguments: args } = node
375
393
  if (!ts.isIdentifier(expression) || expression.text !== 'wireChannel') return
@@ -381,7 +399,7 @@ export function addChannel(
381
399
  const route = (getPropertyValue(obj, 'route') as string) ?? ''
382
400
 
383
401
  if (!name) {
384
- console.error('Channel name is required')
402
+ logger.critical(ErrorCode.MISSING_CHANNEL_NAME, 'Channel name is required')
385
403
  return
386
404
  }
387
405
 
@@ -393,21 +411,9 @@ export function addChannel(
393
411
  : []
394
412
 
395
413
  const docs = getPropertyValue(obj, 'docs') as PikkuDocs | undefined
396
- const tags = getPropertyValue(obj, 'tags') as string[] | undefined
414
+ const tags = getPropertyTags(obj, 'Channel', route, logger)
397
415
  const query = getPropertyValue(obj, 'query') as string[] | []
398
416
 
399
- const filePath = node.getSourceFile().fileName
400
-
401
- if (
402
- !matchesFilters(
403
- filters,
404
- { tags },
405
- { type: PikkuWiringTypes.channel, name, filePath },
406
- logger
407
- )
408
- )
409
- return
410
-
411
417
  const connect = getPropertyAssignmentInitializer(
412
418
  obj,
413
419
  'onConnect',
@@ -432,7 +438,8 @@ export function addChannel(
432
438
 
433
439
  if (onMsgProp) {
434
440
  const handlerName =
435
- onMsgProp && getHandlerNameFromExpression(onMsgProp, checker)
441
+ onMsgProp &&
442
+ getHandlerNameFromExpression(onMsgProp, checker, state.rootDir)
436
443
  const fnMeta = handlerName && state.functions.meta[handlerName]
437
444
  if (!fnMeta) {
438
445
  console.error(
@@ -441,14 +448,52 @@ export function addChannel(
441
448
  throw new Error()
442
449
  } else {
443
450
  message = {
444
- pikkuFuncName: extractFunctionName(onMsgProp as any, checker)
445
- .pikkuFuncName,
451
+ pikkuFuncName: extractFunctionName(
452
+ onMsgProp as any,
453
+ checker,
454
+ state.rootDir
455
+ ).pikkuFuncName,
446
456
  }
447
457
  }
448
458
  }
449
459
 
450
460
  // nested message-routes
451
- const messageWirings = addMessagesRoutes(obj, state, checker)
461
+ const messageWirings = addMessagesRoutes(logger, obj, state, checker)
462
+
463
+ // --- resolve middleware ---
464
+ const middleware = resolveMiddleware(state, obj, tags, checker)
465
+
466
+ // --- track used functions/middleware for service aggregation ---
467
+ // Track connect/disconnect/message handlers
468
+ if (connect) {
469
+ const connectFuncName = extractFunctionName(
470
+ connect,
471
+ checker,
472
+ state.rootDir
473
+ ).pikkuFuncName
474
+ state.serviceAggregation.usedFunctions.add(connectFuncName)
475
+ }
476
+ if (disconnect) {
477
+ const disconnectFuncName = extractFunctionName(
478
+ disconnect as any,
479
+ checker,
480
+ state.rootDir
481
+ ).pikkuFuncName
482
+ state.serviceAggregation.usedFunctions.add(disconnectFuncName)
483
+ }
484
+ if (message) {
485
+ state.serviceAggregation.usedFunctions.add(message.pikkuFuncName)
486
+ }
487
+ // Track message wiring handlers
488
+ for (const channelHandlers of Object.values(messageWirings)) {
489
+ for (const handler of Object.values(channelHandlers)) {
490
+ state.serviceAggregation.usedFunctions.add(handler.pikkuFuncName)
491
+ }
492
+ }
493
+ // Track middleware
494
+ extractWireNames(middleware).forEach((name) =>
495
+ state.serviceAggregation.usedMiddleware.add(name)
496
+ )
452
497
 
453
498
  // record into state
454
499
  state.channels.files.add(node.getSourceFile().fileName)
@@ -466,17 +511,24 @@ export function addChannel(
466
511
  // params
467
512
  // ),
468
513
  connect: connect
469
- ? { pikkuFuncName: extractFunctionName(connect, checker).pikkuFuncName }
514
+ ? {
515
+ pikkuFuncName: extractFunctionName(connect, checker, state.rootDir)
516
+ .pikkuFuncName,
517
+ }
470
518
  : null,
471
519
  disconnect: disconnect
472
520
  ? {
473
- pikkuFuncName: extractFunctionName(disconnect as any, checker)
474
- .pikkuFuncName,
521
+ pikkuFuncName: extractFunctionName(
522
+ disconnect as any,
523
+ checker,
524
+ state.rootDir
525
+ ).pikkuFuncName,
475
526
  }
476
527
  : null,
477
528
  message,
478
529
  messageWirings,
479
530
  docs: docs ?? undefined,
480
531
  tags: tags ?? undefined,
532
+ middleware,
481
533
  }
482
534
  }