@pikku/inspector 0.7.7 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/dist/add-channel.d.ts +2 -2
- package/dist/add-channel.js +4 -2
- package/dist/add-functions.d.ts +2 -2
- package/dist/add-functions.js +2 -3
- package/dist/add-http-route.d.ts +2 -2
- package/dist/add-http-route.js +4 -2
- package/dist/add-mcp-prompt.d.ts +3 -0
- package/dist/add-mcp-prompt.js +61 -0
- package/dist/add-mcp-resource.d.ts +3 -0
- package/dist/add-mcp-resource.js +68 -0
- package/dist/add-mcp-tool.d.ts +3 -0
- package/dist/add-mcp-tool.js +64 -0
- package/dist/add-queue-worker.d.ts +3 -0
- package/dist/add-queue-worker.js +48 -0
- package/dist/add-schedule.d.ts +2 -2
- package/dist/add-schedule.js +8 -9
- package/dist/inspector.d.ts +2 -2
- package/dist/inspector.js +13 -3
- package/dist/types.d.ts +21 -1
- package/dist/utils.d.ts +5 -3
- package/dist/utils.js +40 -5
- package/dist/visit.d.ts +3 -3
- package/dist/visit.js +16 -8
- package/lcov.info +4655 -0
- package/package.json +2 -2
- package/run-tests.sh +0 -0
- package/src/add-channel.ts +19 -4
- package/src/add-functions.ts +4 -6
- package/src/add-http-route.ts +14 -4
- package/src/add-mcp-prompt.ts +104 -0
- package/src/add-mcp-resource.ts +116 -0
- package/src/add-mcp-tool.ts +107 -0
- package/src/add-queue-worker.ts +92 -0
- package/src/add-schedule.ts +26 -15
- package/src/inspector.ts +14 -2
- package/src/types.ts +22 -1
- package/src/utils.test.ts +484 -0
- package/src/utils.ts +60 -6
- package/src/visit.ts +23 -9
- package/tsconfig.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
package/src/types.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { ChannelsMeta } from '@pikku/core/channel'
|
|
2
2
|
import { HTTPRoutesMeta } from '@pikku/core/http'
|
|
3
3
|
import { ScheduledTasksMeta } from '@pikku/core/scheduler'
|
|
4
|
+
import { queueWorkersMeta } from '@pikku/core/queue'
|
|
5
|
+
import { MCPResourceMeta, MCPToolMeta, MCPPromptMeta } from '@pikku/core'
|
|
4
6
|
import { TypesMap } from './types-map.js'
|
|
5
7
|
import { FunctionsMeta } from '@pikku/core'
|
|
6
|
-
import { RPCMeta } from '
|
|
8
|
+
import { RPCMeta } from '@pikku/core/rpc'
|
|
7
9
|
|
|
8
10
|
export type PathToNameAndType = Map<
|
|
9
11
|
string,
|
|
@@ -38,6 +40,15 @@ export interface InspectorChannelState {
|
|
|
38
40
|
|
|
39
41
|
export type InspectorFilters = {
|
|
40
42
|
tags?: string[]
|
|
43
|
+
types?: string[]
|
|
44
|
+
directories?: string[]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface InspectorLogger {
|
|
48
|
+
info: (message: string) => void
|
|
49
|
+
error: (message: string) => void
|
|
50
|
+
warn: (message: string) => void
|
|
51
|
+
debug: (message: string) => void
|
|
41
52
|
}
|
|
42
53
|
export interface InspectorState {
|
|
43
54
|
singletonServicesTypeImportMap: PathToNameAndType
|
|
@@ -53,7 +64,17 @@ export interface InspectorState {
|
|
|
53
64
|
meta: ScheduledTasksMeta
|
|
54
65
|
files: Set<string>
|
|
55
66
|
}
|
|
67
|
+
queueWorkers: {
|
|
68
|
+
meta: queueWorkersMeta
|
|
69
|
+
files: Set<string>
|
|
70
|
+
}
|
|
56
71
|
rpc: {
|
|
57
72
|
meta: Record<string, RPCMeta>
|
|
58
73
|
}
|
|
74
|
+
mcpEndpoints: {
|
|
75
|
+
resourcesMeta: MCPResourceMeta
|
|
76
|
+
toolsMeta: MCPToolMeta
|
|
77
|
+
promptsMeta: MCPPromptMeta
|
|
78
|
+
files: Set<string>
|
|
79
|
+
}
|
|
59
80
|
}
|
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
import { test, describe } from 'node:test'
|
|
2
|
+
import { strict as assert } from 'node:assert'
|
|
3
|
+
import { matchesFilters } from './utils.js'
|
|
4
|
+
import { InspectorFilters } from './types.js'
|
|
5
|
+
import { PikkuEventTypes } from '@pikku/core'
|
|
6
|
+
|
|
7
|
+
describe('matchesFilters', () => {
|
|
8
|
+
// Mock logger for testing
|
|
9
|
+
const mockLogger = {
|
|
10
|
+
info: () => {},
|
|
11
|
+
error: () => {},
|
|
12
|
+
warn: () => {},
|
|
13
|
+
debug: () => {},
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe('Empty filters', () => {
|
|
17
|
+
test('should return true when no filters are provided', () => {
|
|
18
|
+
const filters: InspectorFilters = {}
|
|
19
|
+
|
|
20
|
+
const result = matchesFilters(
|
|
21
|
+
filters,
|
|
22
|
+
{ tags: ['test'] },
|
|
23
|
+
{ type: PikkuEventTypes.http, name: 'test-route' },
|
|
24
|
+
mockLogger
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
assert.equal(result, true)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
test('should return true when all filter arrays are empty', () => {
|
|
31
|
+
const filters: InspectorFilters = {
|
|
32
|
+
tags: [],
|
|
33
|
+
types: [],
|
|
34
|
+
directories: [],
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const result = matchesFilters(
|
|
38
|
+
filters,
|
|
39
|
+
{ tags: ['test'] },
|
|
40
|
+
{ type: PikkuEventTypes.http, name: 'test-route' },
|
|
41
|
+
mockLogger
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
assert.equal(result, true)
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
describe('Tag filtering', () => {
|
|
49
|
+
test('should return true when tags match', () => {
|
|
50
|
+
const filters: InspectorFilters = {
|
|
51
|
+
tags: ['api', 'public'],
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const result = matchesFilters(
|
|
55
|
+
filters,
|
|
56
|
+
{ tags: ['api', 'internal'] },
|
|
57
|
+
{ type: PikkuEventTypes.http, name: 'test-route' },
|
|
58
|
+
mockLogger
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
assert.equal(result, true)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
test('should return false when tags do not match', () => {
|
|
65
|
+
const filters: InspectorFilters = {
|
|
66
|
+
tags: ['api', 'public'],
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const result = matchesFilters(
|
|
70
|
+
filters,
|
|
71
|
+
{ tags: ['internal', 'private'] },
|
|
72
|
+
{ type: PikkuEventTypes.http, name: 'test-route' },
|
|
73
|
+
mockLogger
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
assert.equal(result, false)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
test('should return false when function has no tags but filter requires tags', () => {
|
|
80
|
+
const filters: InspectorFilters = {
|
|
81
|
+
tags: ['api'],
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const result = matchesFilters(
|
|
85
|
+
filters,
|
|
86
|
+
{ tags: undefined },
|
|
87
|
+
{ type: PikkuEventTypes.http, name: 'test-route' },
|
|
88
|
+
mockLogger
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
assert.equal(result, false)
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
test('should return false when function has empty tags but filter requires tags', () => {
|
|
95
|
+
const filters: InspectorFilters = {
|
|
96
|
+
tags: ['api'],
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const result = matchesFilters(
|
|
100
|
+
filters,
|
|
101
|
+
{ tags: [] },
|
|
102
|
+
{ type: PikkuEventTypes.http, name: 'test-route' },
|
|
103
|
+
mockLogger
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
assert.equal(result, false)
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
describe('Type filtering', () => {
|
|
111
|
+
test('should return true when type matches', () => {
|
|
112
|
+
const filters: InspectorFilters = {
|
|
113
|
+
types: ['http', 'channel'],
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const result = matchesFilters(
|
|
117
|
+
filters,
|
|
118
|
+
{ tags: ['test'] },
|
|
119
|
+
{ type: PikkuEventTypes.http, name: 'test-route' },
|
|
120
|
+
mockLogger
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
assert.equal(result, true)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
test('should return false when type does not match', () => {
|
|
127
|
+
const filters: InspectorFilters = {
|
|
128
|
+
types: ['channel', 'queue'],
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const result = matchesFilters(
|
|
132
|
+
filters,
|
|
133
|
+
{ tags: ['test'] },
|
|
134
|
+
{ type: PikkuEventTypes.http, name: 'test-route' },
|
|
135
|
+
mockLogger
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
assert.equal(result, false)
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
test('should handle all PikkuEventTypes correctly', () => {
|
|
142
|
+
const eventTypes = [
|
|
143
|
+
PikkuEventTypes.http,
|
|
144
|
+
PikkuEventTypes.channel,
|
|
145
|
+
PikkuEventTypes.queue,
|
|
146
|
+
PikkuEventTypes.scheduler,
|
|
147
|
+
PikkuEventTypes.rpc,
|
|
148
|
+
PikkuEventTypes.mcp,
|
|
149
|
+
]
|
|
150
|
+
|
|
151
|
+
eventTypes.forEach((eventType) => {
|
|
152
|
+
const filters: InspectorFilters = {
|
|
153
|
+
types: [eventType],
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const result = matchesFilters(
|
|
157
|
+
filters,
|
|
158
|
+
{ tags: ['test'] },
|
|
159
|
+
{ type: eventType, name: 'test-route' },
|
|
160
|
+
mockLogger
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
assert.equal(result, true, `Should match for type: ${eventType}`)
|
|
164
|
+
})
|
|
165
|
+
})
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
describe('Directory filtering', () => {
|
|
169
|
+
test('should return true when directory matches', () => {
|
|
170
|
+
const filters: InspectorFilters = {
|
|
171
|
+
directories: ['src/api', 'src/internal'],
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const result = matchesFilters(
|
|
175
|
+
filters,
|
|
176
|
+
{ tags: ['test'] },
|
|
177
|
+
{
|
|
178
|
+
type: PikkuEventTypes.http,
|
|
179
|
+
name: 'test-route',
|
|
180
|
+
filePath: '/project/src/api/routes.ts',
|
|
181
|
+
},
|
|
182
|
+
mockLogger
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
assert.equal(result, true)
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
test('should return false when directory does not match', () => {
|
|
189
|
+
const filters: InspectorFilters = {
|
|
190
|
+
directories: ['src/api', 'src/internal'],
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const result = matchesFilters(
|
|
194
|
+
filters,
|
|
195
|
+
{ tags: ['test'] },
|
|
196
|
+
{
|
|
197
|
+
type: PikkuEventTypes.http,
|
|
198
|
+
name: 'test-route',
|
|
199
|
+
filePath: '/project/src/public/routes.ts',
|
|
200
|
+
},
|
|
201
|
+
mockLogger
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
assert.equal(result, false)
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
test('should handle Windows paths correctly', () => {
|
|
208
|
+
const filters: InspectorFilters = {
|
|
209
|
+
directories: ['src\\api'],
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const result = matchesFilters(
|
|
213
|
+
filters,
|
|
214
|
+
{ tags: ['test'] },
|
|
215
|
+
{
|
|
216
|
+
type: PikkuEventTypes.http,
|
|
217
|
+
name: 'test-route',
|
|
218
|
+
filePath: 'C:\\project\\src\\api\\routes.ts',
|
|
219
|
+
},
|
|
220
|
+
mockLogger
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
assert.equal(result, true)
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
test('should handle mixed path separators', () => {
|
|
227
|
+
const filters: InspectorFilters = {
|
|
228
|
+
directories: ['src/api'],
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const result = matchesFilters(
|
|
232
|
+
filters,
|
|
233
|
+
{ tags: ['test'] },
|
|
234
|
+
{
|
|
235
|
+
type: PikkuEventTypes.http,
|
|
236
|
+
name: 'test-route',
|
|
237
|
+
filePath: 'C:\\project\\src\\api\\routes.ts',
|
|
238
|
+
},
|
|
239
|
+
mockLogger
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
assert.equal(result, true)
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
test('should return false when filePath is not provided but directory filter exists', () => {
|
|
246
|
+
const filters: InspectorFilters = {
|
|
247
|
+
directories: ['src/api'],
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const result = matchesFilters(
|
|
251
|
+
filters,
|
|
252
|
+
{ tags: ['test'] },
|
|
253
|
+
{ type: PikkuEventTypes.http, name: 'test-route' }, // no filePath
|
|
254
|
+
mockLogger
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
assert.equal(result, false)
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
test('should handle partial path matches', () => {
|
|
261
|
+
const filters: InspectorFilters = {
|
|
262
|
+
directories: ['api'],
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const result = matchesFilters(
|
|
266
|
+
filters,
|
|
267
|
+
{ tags: ['test'] },
|
|
268
|
+
{
|
|
269
|
+
type: PikkuEventTypes.http,
|
|
270
|
+
name: 'test-route',
|
|
271
|
+
filePath: '/project/src/api/v1/routes.ts',
|
|
272
|
+
},
|
|
273
|
+
mockLogger
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
assert.equal(result, true)
|
|
277
|
+
})
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
describe('Combined filtering', () => {
|
|
281
|
+
test('should return true when all filters pass', () => {
|
|
282
|
+
const filters: InspectorFilters = {
|
|
283
|
+
tags: ['api'],
|
|
284
|
+
types: ['http'],
|
|
285
|
+
directories: ['src/api'],
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const result = matchesFilters(
|
|
289
|
+
filters,
|
|
290
|
+
{ tags: ['api', 'public'] },
|
|
291
|
+
{
|
|
292
|
+
type: PikkuEventTypes.http,
|
|
293
|
+
name: 'test-route',
|
|
294
|
+
filePath: '/project/src/api/routes.ts',
|
|
295
|
+
},
|
|
296
|
+
mockLogger
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
assert.equal(result, true)
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
test('should return false when type filter fails (even if others pass)', () => {
|
|
303
|
+
const filters: InspectorFilters = {
|
|
304
|
+
tags: ['api'],
|
|
305
|
+
types: ['channel'],
|
|
306
|
+
directories: ['src/api'],
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const result = matchesFilters(
|
|
310
|
+
filters,
|
|
311
|
+
{ tags: ['api', 'public'] },
|
|
312
|
+
{
|
|
313
|
+
type: PikkuEventTypes.http,
|
|
314
|
+
name: 'test-route',
|
|
315
|
+
filePath: '/project/src/api/routes.ts',
|
|
316
|
+
},
|
|
317
|
+
mockLogger
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
assert.equal(result, false)
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
test('should return false when directory filter fails (even if others pass)', () => {
|
|
324
|
+
const filters: InspectorFilters = {
|
|
325
|
+
tags: ['api'],
|
|
326
|
+
types: ['http'],
|
|
327
|
+
directories: ['src/internal'],
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const result = matchesFilters(
|
|
331
|
+
filters,
|
|
332
|
+
{ tags: ['api', 'public'] },
|
|
333
|
+
{
|
|
334
|
+
type: PikkuEventTypes.http,
|
|
335
|
+
name: 'test-route',
|
|
336
|
+
filePath: '/project/src/api/routes.ts',
|
|
337
|
+
},
|
|
338
|
+
mockLogger
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
assert.equal(result, false)
|
|
342
|
+
})
|
|
343
|
+
|
|
344
|
+
test('should return false when tag filter fails (even if others pass)', () => {
|
|
345
|
+
const filters: InspectorFilters = {
|
|
346
|
+
tags: ['internal'],
|
|
347
|
+
types: ['http'],
|
|
348
|
+
directories: ['src/api'],
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const result = matchesFilters(
|
|
352
|
+
filters,
|
|
353
|
+
{ tags: ['api', 'public'] },
|
|
354
|
+
{
|
|
355
|
+
type: PikkuEventTypes.http,
|
|
356
|
+
name: 'test-route',
|
|
357
|
+
filePath: '/project/src/api/routes.ts',
|
|
358
|
+
},
|
|
359
|
+
mockLogger
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
assert.equal(result, false)
|
|
363
|
+
})
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
describe('Edge cases', () => {
|
|
367
|
+
test('should handle undefined params', () => {
|
|
368
|
+
const filters: InspectorFilters = {
|
|
369
|
+
tags: ['api'],
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const result = matchesFilters(
|
|
373
|
+
filters,
|
|
374
|
+
{ tags: undefined },
|
|
375
|
+
{ type: PikkuEventTypes.http, name: 'test-route' },
|
|
376
|
+
mockLogger
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
assert.equal(result, false)
|
|
380
|
+
})
|
|
381
|
+
|
|
382
|
+
test('should handle empty meta name', () => {
|
|
383
|
+
const filters: InspectorFilters = {
|
|
384
|
+
types: ['channel'],
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const result = matchesFilters(
|
|
388
|
+
filters,
|
|
389
|
+
{ tags: ['test'] },
|
|
390
|
+
{ type: PikkuEventTypes.http, name: '' },
|
|
391
|
+
mockLogger
|
|
392
|
+
)
|
|
393
|
+
|
|
394
|
+
assert.equal(result, false)
|
|
395
|
+
})
|
|
396
|
+
|
|
397
|
+
test('should handle special characters in paths', () => {
|
|
398
|
+
const filters: InspectorFilters = {
|
|
399
|
+
directories: ['src/api-v2'],
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const result = matchesFilters(
|
|
403
|
+
filters,
|
|
404
|
+
{ tags: ['test'] },
|
|
405
|
+
{
|
|
406
|
+
type: PikkuEventTypes.http,
|
|
407
|
+
name: 'test-route',
|
|
408
|
+
filePath: '/project/src/api-v2/routes.ts',
|
|
409
|
+
},
|
|
410
|
+
mockLogger
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
assert.equal(result, true)
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
test('should handle case sensitivity in directory paths', () => {
|
|
417
|
+
const filters: InspectorFilters = {
|
|
418
|
+
directories: ['src/API'],
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const result = matchesFilters(
|
|
422
|
+
filters,
|
|
423
|
+
{ tags: ['test'] },
|
|
424
|
+
{
|
|
425
|
+
type: PikkuEventTypes.http,
|
|
426
|
+
name: 'test-route',
|
|
427
|
+
filePath: '/project/src/api/routes.ts',
|
|
428
|
+
},
|
|
429
|
+
mockLogger
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
assert.equal(result, false)
|
|
433
|
+
})
|
|
434
|
+
|
|
435
|
+
test('should handle multiple matching tags', () => {
|
|
436
|
+
const filters: InspectorFilters = {
|
|
437
|
+
tags: ['api', 'v1'],
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const result = matchesFilters(
|
|
441
|
+
filters,
|
|
442
|
+
{ tags: ['api', 'public', 'v1'] },
|
|
443
|
+
{ type: PikkuEventTypes.http, name: 'test-route' },
|
|
444
|
+
mockLogger
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
assert.equal(result, true)
|
|
448
|
+
})
|
|
449
|
+
|
|
450
|
+
test('should handle multiple matching types', () => {
|
|
451
|
+
const filters: InspectorFilters = {
|
|
452
|
+
types: ['http', 'channel'],
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
const result = matchesFilters(
|
|
456
|
+
filters,
|
|
457
|
+
{ tags: ['test'] },
|
|
458
|
+
{ type: PikkuEventTypes.channel, name: 'test-channel' },
|
|
459
|
+
mockLogger
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
assert.equal(result, true)
|
|
463
|
+
})
|
|
464
|
+
|
|
465
|
+
test('should handle multiple matching directories', () => {
|
|
466
|
+
const filters: InspectorFilters = {
|
|
467
|
+
directories: ['src/api', 'src/internal'],
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const result = matchesFilters(
|
|
471
|
+
filters,
|
|
472
|
+
{ tags: ['test'] },
|
|
473
|
+
{
|
|
474
|
+
type: PikkuEventTypes.http,
|
|
475
|
+
name: 'test-route',
|
|
476
|
+
filePath: '/project/src/internal/routes.ts',
|
|
477
|
+
},
|
|
478
|
+
mockLogger
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
assert.equal(result, true)
|
|
482
|
+
})
|
|
483
|
+
})
|
|
484
|
+
})
|
package/src/utils.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as ts from 'typescript'
|
|
2
|
-
import { InspectorFilters } from './types.js'
|
|
2
|
+
import { InspectorFilters, InspectorLogger } from './types.js'
|
|
3
|
+
import { PikkuEventTypes } from '@pikku/core'
|
|
3
4
|
|
|
4
5
|
type ExtractedFunctionName = {
|
|
5
6
|
pikkuFuncName: string
|
|
@@ -843,16 +844,69 @@ export function getPropertyAssignmentInitializer(
|
|
|
843
844
|
export const matchesFilters = (
|
|
844
845
|
filters: InspectorFilters,
|
|
845
846
|
params: { tags?: string[] },
|
|
846
|
-
meta: {
|
|
847
|
+
meta: {
|
|
848
|
+
type: PikkuEventTypes
|
|
849
|
+
name: string
|
|
850
|
+
filePath?: string
|
|
851
|
+
},
|
|
852
|
+
logger: InspectorLogger
|
|
847
853
|
) => {
|
|
848
|
-
|
|
854
|
+
// If no filters are provided, allow everything
|
|
855
|
+
if (Object.keys(filters).length === 0) {
|
|
849
856
|
return true
|
|
850
857
|
}
|
|
851
858
|
|
|
852
|
-
|
|
859
|
+
// If all filter arrays are empty, allow everything
|
|
860
|
+
if (
|
|
861
|
+
(!filters.tags || filters.tags.length === 0) &&
|
|
862
|
+
(!filters.types || filters.types.length === 0) &&
|
|
863
|
+
(!filters.directories || filters.directories.length === 0)
|
|
864
|
+
) {
|
|
853
865
|
return true
|
|
854
866
|
}
|
|
855
867
|
|
|
856
|
-
|
|
857
|
-
|
|
868
|
+
// Check type filter
|
|
869
|
+
if (filters.types && filters.types.length > 0) {
|
|
870
|
+
if (!filters.types.includes(meta.type)) {
|
|
871
|
+
logger.debug(`⒡ Filtered by type: ${meta.type}:${meta.name}`)
|
|
872
|
+
return false
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
// Check directory filter
|
|
877
|
+
if (filters.directories && filters.directories.length > 0) {
|
|
878
|
+
if (!meta.filePath) {
|
|
879
|
+
logger.debug(
|
|
880
|
+
`⒡ Filtered by directory: ${meta.type}:${meta.name} (${meta.filePath})`
|
|
881
|
+
)
|
|
882
|
+
return false
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
const matchesDirectory = filters.directories.some((dir) => {
|
|
886
|
+
// Normalize paths for comparison
|
|
887
|
+
const normalizedFilePath = meta.filePath!.replace(/\\/g, '/')
|
|
888
|
+
const normalizedDir = dir.replace(/\\/g, '/')
|
|
889
|
+
return normalizedFilePath.includes(normalizedDir)
|
|
890
|
+
})
|
|
891
|
+
|
|
892
|
+
if (!matchesDirectory) {
|
|
893
|
+
logger.debug(
|
|
894
|
+
`⒡ Filtered by directory: ${meta.type}:${meta.name} (${meta.filePath})`
|
|
895
|
+
)
|
|
896
|
+
return false
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
// Check tag filter
|
|
901
|
+
if (filters.tags && filters.tags.length > 0) {
|
|
902
|
+
if (
|
|
903
|
+
!params.tags ||
|
|
904
|
+
!filters.tags.some((tag) => params.tags!.includes(tag))
|
|
905
|
+
) {
|
|
906
|
+
logger.debug(`⒡ Filtered by tags: ${meta.type}:${meta.name}`)
|
|
907
|
+
return false
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
return true
|
|
858
912
|
}
|
package/src/visit.ts
CHANGED
|
@@ -3,7 +3,11 @@ import { addFileWithFactory } from './add-file-with-factory.js'
|
|
|
3
3
|
import { addFileExtendsCoreType } from './add-file-extends-core-type.js'
|
|
4
4
|
import { addHTTPRoute } from './add-http-route.js'
|
|
5
5
|
import { addSchedule } from './add-schedule.js'
|
|
6
|
-
import {
|
|
6
|
+
import { addQueueWorker } from './add-queue-worker.js'
|
|
7
|
+
import { addMCPResource } from './add-mcp-resource.js'
|
|
8
|
+
import { addMCPTool } from './add-mcp-tool.js'
|
|
9
|
+
import { addMCPPrompt } from './add-mcp-prompt.js'
|
|
10
|
+
import { InspectorFilters, InspectorState, InspectorLogger } from './types.js'
|
|
7
11
|
import { addFunctions } from './add-functions.js'
|
|
8
12
|
import { addChannel } from './add-channel.js'
|
|
9
13
|
|
|
@@ -11,7 +15,8 @@ export const visitSetup = (
|
|
|
11
15
|
checker: ts.TypeChecker,
|
|
12
16
|
node: ts.Node,
|
|
13
17
|
state: InspectorState,
|
|
14
|
-
filters: InspectorFilters
|
|
18
|
+
filters: InspectorFilters,
|
|
19
|
+
logger: InspectorLogger
|
|
15
20
|
) => {
|
|
16
21
|
addFileExtendsCoreType(
|
|
17
22
|
node,
|
|
@@ -49,19 +54,28 @@ export const visitSetup = (
|
|
|
49
54
|
)
|
|
50
55
|
|
|
51
56
|
addFileWithFactory(node, checker, state.configFactories, 'CreateConfig')
|
|
52
|
-
addFunctions(node, checker, state, filters)
|
|
57
|
+
addFunctions(node, checker, state, filters, logger)
|
|
53
58
|
|
|
54
|
-
ts.forEachChild(node, (child) =>
|
|
59
|
+
ts.forEachChild(node, (child) =>
|
|
60
|
+
visitSetup(checker, child, state, filters, logger)
|
|
61
|
+
)
|
|
55
62
|
}
|
|
56
63
|
|
|
57
64
|
export const visitRoutes = (
|
|
58
65
|
checker: ts.TypeChecker,
|
|
59
66
|
node: ts.Node,
|
|
60
67
|
state: InspectorState,
|
|
61
|
-
filters: InspectorFilters
|
|
68
|
+
filters: InspectorFilters,
|
|
69
|
+
logger: InspectorLogger
|
|
62
70
|
) => {
|
|
63
|
-
addHTTPRoute(node, checker, state, filters)
|
|
64
|
-
addSchedule(node, checker, state, filters)
|
|
65
|
-
|
|
66
|
-
|
|
71
|
+
addHTTPRoute(node, checker, state, filters, logger)
|
|
72
|
+
addSchedule(node, checker, state, filters, logger)
|
|
73
|
+
addQueueWorker(node, checker, state, filters, logger)
|
|
74
|
+
addChannel(node, checker, state, filters, logger)
|
|
75
|
+
addMCPResource(node, checker, state, filters, logger)
|
|
76
|
+
addMCPTool(node, checker, state, filters, logger)
|
|
77
|
+
addMCPPrompt(node, checker, state, filters, logger)
|
|
78
|
+
ts.forEachChild(node, (child) =>
|
|
79
|
+
visitRoutes(checker, child, state, filters, logger)
|
|
80
|
+
)
|
|
67
81
|
}
|