@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
package/src/inspector.ts CHANGED
@@ -1,23 +1,15 @@
1
1
  import * as ts from 'typescript'
2
2
  import { visitSetup, visitRoutes } from './visit.js'
3
3
  import { TypesMap } from './types-map.js'
4
- import {
5
- InspectorState,
6
- InspectorHTTPState,
7
- InspectorFilters,
8
- InspectorLogger,
9
- } from './types.js'
10
-
11
- export const normalizeHTTPTypes = (
12
- httpState: InspectorHTTPState
13
- ): InspectorHTTPState => {
14
- return httpState
15
- }
4
+ import { InspectorState, InspectorLogger, InspectorOptions } from './types.js'
5
+ import { getFilesAndMethods } from './utils/get-files-and-methods.js'
6
+ import { findCommonAncestor } from './utils/find-root-dir.js'
7
+ import { aggregateRequiredServices } from './utils/post-process.js'
16
8
 
17
9
  export const inspect = (
18
10
  logger: InspectorLogger,
19
11
  routeFiles: string[],
20
- filters: InspectorFilters
12
+ options: InspectorOptions = {}
21
13
  ): InspectorState => {
22
14
  const program = ts.createProgram(routeFiles, {
23
15
  target: ts.ScriptTarget.ESNext,
@@ -26,16 +18,26 @@ export const inspect = (
26
18
  const checker = program.getTypeChecker()
27
19
  const sourceFiles = program.getSourceFiles()
28
20
 
21
+ // Infer root directory from source files
22
+ const rootDir = findCommonAncestor(routeFiles)
23
+
29
24
  const state: InspectorState = {
25
+ rootDir,
30
26
  singletonServicesTypeImportMap: new Map(),
31
27
  sessionServicesTypeImportMap: new Map(),
32
28
  userSessionTypeImportMap: new Map(),
29
+ configTypeImportMap: new Map(),
33
30
  singletonServicesFactories: new Map(),
34
31
  sessionServicesFactories: new Map(),
32
+ sessionServicesMeta: new Map(),
35
33
  configFactories: new Map(),
34
+ filesAndMethods: {},
35
+ filesAndMethodsErrors: new Map(),
36
+ typesLookup: new Map(),
36
37
  functions: {
37
38
  typesMap: new TypesMap(),
38
39
  meta: {},
40
+ files: new Map(),
39
41
  },
40
42
  http: {
41
43
  metaInputTypes: new Map(),
@@ -49,6 +51,8 @@ export const inspect = (
49
51
  options: {},
50
52
  },
51
53
  files: new Set(),
54
+ routeMiddleware: new Map(),
55
+ routePermissions: new Map(),
52
56
  },
53
57
  channels: {
54
58
  files: new Set(),
@@ -75,30 +79,50 @@ export const inspect = (
75
79
  promptsMeta: {},
76
80
  files: new Set(),
77
81
  },
82
+ cli: {
83
+ meta: {
84
+ programs: {},
85
+ renderers: {},
86
+ },
87
+ files: new Set(),
88
+ },
78
89
  middleware: {
79
90
  meta: {},
91
+ tagMiddleware: new Map(),
80
92
  },
81
93
  permissions: {
82
94
  meta: {},
95
+ tagPermissions: new Map(),
96
+ },
97
+ serviceAggregation: {
98
+ requiredServices: new Set(),
99
+ usedFunctions: new Set(),
100
+ usedMiddleware: new Set(),
101
+ usedPermissions: new Set(),
83
102
  },
84
103
  }
85
104
 
86
105
  // First sweep: add all functions
87
106
  for (const sourceFile of sourceFiles) {
88
107
  ts.forEachChild(sourceFile, (child) =>
89
- visitSetup(checker, child, state, filters, logger)
108
+ visitSetup(logger, checker, child, state, options)
90
109
  )
91
110
  }
92
111
 
93
112
  // Second sweep: add all transports
94
113
  for (const sourceFile of sourceFiles) {
95
114
  ts.forEachChild(sourceFile, (child) =>
96
- visitRoutes(checker, child, state, filters, logger)
115
+ visitRoutes(logger, checker, child, state, options)
97
116
  )
98
117
  }
99
118
 
100
- // Normalise the typesMap
101
- state.http = normalizeHTTPTypes(state.http)
119
+ // Populate filesAndMethods
120
+ const { result, errors } = getFilesAndMethods(state, options.types)
121
+ state.filesAndMethods = result
122
+ state.filesAndMethodsErrors = errors
123
+
124
+ // Post-processing: Aggregate required services from wired functions/middleware/permissions
125
+ aggregateRequiredServices(state)
102
126
 
103
127
  return state
104
128
  }
package/src/types.ts CHANGED
@@ -1,10 +1,13 @@
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
- import { MCPResourceMeta, MCPToolMeta, MCPPromptMeta } from '@pikku/core'
6
+ import { MCPResourceMeta, MCPToolMeta, MCPPromptMeta } from '@pikku/core/mcp'
7
+ import { CLIMeta } from '@pikku/core/cli'
6
8
  import { TypesMap } from './types-map.js'
7
9
  import { FunctionsMeta, FunctionServicesMeta } from '@pikku/core'
10
+ import { ErrorCode } from './error-codes.js'
8
11
 
9
12
  export type PathToNameAndType = Map<
10
13
  string,
@@ -20,15 +23,42 @@ export type MetaInputTypes = Map<
20
23
  }
21
24
  >
22
25
 
26
+ export interface MiddlewareGroupMeta {
27
+ exportName: string | null // null if not exported
28
+ sourceFile: string
29
+ position: number
30
+ services: FunctionServicesMeta
31
+ middlewareCount: number
32
+ isFactory: boolean // true if wrapped in () => add...()
33
+ }
34
+
35
+ export interface PermissionGroupMeta {
36
+ exportName: string | null // null if not exported
37
+ sourceFile: string
38
+ position: number
39
+ services: FunctionServicesMeta
40
+ permissionCount: number
41
+ isFactory: boolean // true if wrapped in () => add...()
42
+ }
43
+
23
44
  export interface InspectorHTTPState {
24
45
  metaInputTypes: MetaInputTypes
25
46
  meta: HTTPWiringsMeta
26
47
  files: Set<string>
48
+ // HTTP middleware calls tracking - route pattern -> group metadata
49
+ // Pattern '*' matches all routes (from addHTTPMiddleware('*', [...]))
50
+ // Pattern '/api/*' matches specific routes (from addHTTPMiddleware('/api/*', [...]))
51
+ routeMiddleware: Map<string, MiddlewareGroupMeta>
52
+ // HTTP permission calls tracking - route pattern -> group metadata
53
+ // Pattern '*' matches all routes (from addHTTPPermission('*', [...]))
54
+ // Pattern '/api/*' matches specific routes (from addHTTPPermission('/api/*', [...]))
55
+ routePermissions: Map<string, PermissionGroupMeta>
27
56
  }
28
57
 
29
58
  export interface InspectorFunctionState {
30
59
  typesMap: TypesMap
31
60
  meta: FunctionsMeta
61
+ files: Map<string, { path: string; exportedName: string }>
32
62
  }
33
63
 
34
64
  export interface InspectorChannelState {
@@ -37,6 +67,7 @@ export interface InspectorChannelState {
37
67
  }
38
68
 
39
69
  export interface InspectorMiddlewareState {
70
+ // Individual middleware function metadata
40
71
  meta: Record<
41
72
  string,
42
73
  {
@@ -44,11 +75,18 @@ export interface InspectorMiddlewareState {
44
75
  sourceFile: string
45
76
  position: number
46
77
  exportedName: string | null
78
+ factory?: boolean // true if wrapped with pikkuMiddlewareFactory
79
+ name?: string // optional name from pikkuMiddleware({ name: '...' })
80
+ description?: string // optional description from pikkuMiddleware({ description: '...' })
47
81
  }
48
82
  >
83
+ // Tag-based middleware calls tracking - tag -> group metadata
84
+ // e.g., export const adminMiddleware = () => addMiddleware('admin', [...])
85
+ tagMiddleware: Map<string, MiddlewareGroupMeta>
49
86
  }
50
87
 
51
88
  export interface InspectorPermissionState {
89
+ // Individual permission function metadata
52
90
  meta: Record<
53
91
  string,
54
92
  {
@@ -56,29 +94,108 @@ export interface InspectorPermissionState {
56
94
  sourceFile: string
57
95
  position: number
58
96
  exportedName: string | null
97
+ factory?: boolean // true if wrapped with pikkuPermissionFactory
98
+ name?: string // optional name from pikkuPermission({ name: '...' })
99
+ description?: string // optional description from pikkuPermission({ description: '...' })
59
100
  }
60
101
  >
102
+ // Tag-based permission calls tracking - tag -> group metadata
103
+ // e.g., export const adminPermissions = () => addPermission('admin', [...])
104
+ tagPermissions: Map<string, PermissionGroupMeta>
61
105
  }
62
106
 
63
107
  export type InspectorFilters = {
108
+ names?: string[] // Wildcard support: "email-*" matches "email-worker", "email-sender"
64
109
  tags?: string[]
65
110
  types?: string[]
66
111
  directories?: string[]
112
+ httpRoutes?: string[] // HTTP route patterns: "/api/*", "/webhooks/*"
113
+ httpMethods?: string[] // HTTP methods: "GET", "POST", "DELETE", etc.
67
114
  }
68
115
 
116
+ export type InspectorOptions = Partial<{
117
+ types: Partial<{
118
+ configFileType: string
119
+ userSessionType: string
120
+ singletonServicesFactoryType: string
121
+ sessionServicesFactoryType: string
122
+ }>
123
+ }>
124
+
69
125
  export interface InspectorLogger {
70
126
  info: (message: string) => void
71
127
  error: (message: string) => void
72
128
  warn: (message: string) => void
73
129
  debug: (message: string) => void
130
+ critical: (code: ErrorCode, message: string) => void
131
+ hasCriticalErrors: () => boolean
132
+ }
133
+
134
+ export type AddWiring = (
135
+ logger: InspectorLogger,
136
+ node: ts.Node,
137
+ checker: ts.TypeChecker,
138
+ state: InspectorState,
139
+ options: InspectorOptions
140
+ ) => void
141
+ export interface InspectorFilesAndMethods {
142
+ userSessionType?: {
143
+ file: string
144
+ variable: string
145
+ type: string
146
+ typePath: string
147
+ }
148
+ sessionServicesType?: {
149
+ file: string
150
+ variable: string
151
+ type: string
152
+ typePath: string
153
+ }
154
+ singletonServicesType?: {
155
+ file: string
156
+ variable: string
157
+ type: string
158
+ typePath: string
159
+ }
160
+ pikkuConfigType?: {
161
+ file: string
162
+ variable: string
163
+ type: string
164
+ typePath: string
165
+ }
166
+ pikkuConfigFactory?: {
167
+ file: string
168
+ variable: string
169
+ type: string
170
+ typePath: string
171
+ }
172
+ singletonServicesFactory?: {
173
+ file: string
174
+ variable: string
175
+ type: string
176
+ typePath: string
177
+ }
178
+ sessionServicesFactory?: {
179
+ file: string
180
+ variable: string
181
+ type: string
182
+ typePath: string
183
+ }
74
184
  }
185
+
75
186
  export interface InspectorState {
187
+ rootDir: string // Root directory inferred from source files
76
188
  singletonServicesTypeImportMap: PathToNameAndType
77
189
  sessionServicesTypeImportMap: PathToNameAndType
78
190
  userSessionTypeImportMap: PathToNameAndType
191
+ configTypeImportMap: PathToNameAndType
79
192
  singletonServicesFactories: PathToNameAndType
80
193
  sessionServicesFactories: PathToNameAndType
194
+ sessionServicesMeta: Map<string, string[]> // variable name -> singleton services consumed
81
195
  configFactories: PathToNameAndType
196
+ filesAndMethods: InspectorFilesAndMethods
197
+ filesAndMethodsErrors: Map<string, PathToNameAndType>
198
+ typesLookup: Map<string, ts.Type[]> // Lookup for types by name (e.g., function input types, Config type)
82
199
  http: InspectorHTTPState
83
200
  functions: InspectorFunctionState
84
201
  channels: InspectorChannelState
@@ -103,6 +220,16 @@ export interface InspectorState {
103
220
  promptsMeta: MCPPromptMeta
104
221
  files: Set<string>
105
222
  }
223
+ cli: {
224
+ meta: CLIMeta
225
+ files: Set<string>
226
+ }
106
227
  middleware: InspectorMiddlewareState
107
228
  permissions: InspectorPermissionState
229
+ serviceAggregation: {
230
+ requiredServices: Set<string> // All services needed across the app
231
+ usedFunctions: Set<string> // Function names actually wired/exposed
232
+ usedMiddleware: Set<string> // Middleware names used by wired functions
233
+ usedPermissions: Set<string> // Permission names used by wired functions
234
+ }
108
235
  }
@@ -0,0 +1,24 @@
1
+ import { InspectorState } from '../types.js'
2
+
3
+ /**
4
+ * Ensures that function metadata exists for a given pikkuFuncName.
5
+ * Creates stub metadata if it doesn't exist (useful for inline functions).
6
+ */
7
+ export function ensureFunctionMetadata(
8
+ state: InspectorState,
9
+ pikkuFuncName: string,
10
+ fallbackName?: string
11
+ ): void {
12
+ if (!state.functions.meta[pikkuFuncName]) {
13
+ state.functions.meta[pikkuFuncName] = {
14
+ pikkuFuncName,
15
+ name: fallbackName || pikkuFuncName,
16
+ services: { optimized: false, services: [] },
17
+ inputSchemaName: null,
18
+ outputSchemaName: null,
19
+ inputs: [],
20
+ outputs: [],
21
+ middleware: undefined,
22
+ }
23
+ }
24
+ }