@pikku/inspector 0.9.5 → 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.
- package/CHANGELOG.md +8 -0
- package/dist/{add-channel.d.ts → add/add-channel.d.ts} +2 -2
- package/dist/{add-channel.js → add/add-channel.js} +12 -5
- package/dist/add/add-cli.d.ts +5 -0
- package/dist/add/add-cli.js +461 -0
- package/dist/{add-file-extends-core-type.d.ts → add/add-file-extends-core-type.d.ts} +2 -2
- package/dist/{add-file-extends-core-type.js → add/add-file-extends-core-type.js} +17 -5
- package/dist/{add-file-with-config.d.ts → add/add-file-with-config.d.ts} +1 -1
- package/dist/{add-file-with-config.js → add/add-file-with-config.js} +1 -1
- package/dist/{add-file-with-factory.d.ts → add/add-file-with-factory.d.ts} +1 -1
- package/dist/{add-file-with-factory.js → add/add-file-with-factory.js} +4 -4
- package/dist/add/add-functions.d.ts +6 -0
- package/dist/{add-functions.js → add/add-functions.js} +25 -5
- package/dist/{add-http-route.d.ts → add/add-http-route.d.ts} +2 -3
- package/dist/{add-http-route.js → add/add-http-route.js} +10 -4
- package/dist/add/add-mcp-prompt.d.ts +2 -0
- package/dist/{add-mcp-prompt.js → add/add-mcp-prompt.js} +10 -4
- package/dist/add/add-mcp-resource.d.ts +2 -0
- package/dist/{add-mcp-resource.js → add/add-mcp-resource.js} +10 -4
- package/dist/add/add-mcp-tool.d.ts +2 -0
- package/dist/{add-mcp-tool.js → add/add-mcp-tool.js} +10 -4
- package/dist/add/add-middleware.d.ts +5 -0
- package/dist/add/add-middleware.js +251 -0
- package/dist/add/add-permission.d.ts +6 -0
- package/dist/{add-permission.js → add/add-permission.js} +4 -3
- package/dist/add/add-queue-worker.d.ts +2 -0
- package/dist/{add-queue-worker.js → add/add-queue-worker.js} +10 -4
- package/dist/{add-rpc-invocations.d.ts → add/add-rpc-invocations.d.ts} +1 -1
- package/dist/add/add-schedule.d.ts +2 -0
- package/dist/{add-schedule.js → add/add-schedule.js} +10 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/inspector.d.ts +2 -3
- package/dist/inspector.js +19 -8
- package/dist/types.d.ts +79 -0
- package/dist/{utils.d.ts → utils/extract-function-name.d.ts} +7 -15
- package/dist/{utils.js → utils/extract-function-name.js} +23 -142
- package/dist/utils/extract-services.d.ts +6 -0
- package/dist/utils/extract-services.js +29 -0
- package/dist/utils/filter-utils.d.ts +9 -0
- package/dist/utils/filter-utils.js +45 -0
- package/dist/utils/get-files-and-methods.d.ts +21 -0
- package/dist/utils/get-files-and-methods.js +60 -0
- package/dist/utils/middleware.d.ts +39 -0
- package/dist/utils/middleware.js +157 -0
- package/dist/utils/type-utils.d.ts +3 -0
- package/dist/utils/type-utils.js +50 -0
- package/dist/visit.d.ts +3 -3
- package/dist/visit.js +33 -30
- package/package.json +3 -4
- package/src/{add-channel.ts → add/add-channel.ts} +19 -19
- package/src/add/add-cli.ts +663 -0
- package/src/{add-file-extends-core-type.ts → add/add-file-extends-core-type.ts} +21 -6
- package/src/{add-file-with-config.ts → add/add-file-with-config.ts} +2 -2
- package/src/{add-file-with-factory.ts → add/add-file-with-factory.ts} +5 -5
- package/src/{add-functions.ts → add/add-functions.ts} +29 -14
- package/src/{add-http-route.ts → add/add-http-route.ts} +23 -14
- package/src/{add-mcp-prompt.ts → add/add-mcp-prompt.ts} +18 -15
- package/src/{add-mcp-resource.ts → add/add-mcp-resource.ts} +18 -15
- package/src/{add-mcp-tool.ts → add/add-mcp-tool.ts} +18 -15
- package/src/add/add-middleware.ts +326 -0
- package/src/{add-permission.ts → add/add-permission.ts} +4 -8
- package/src/{add-queue-worker.ts → add/add-queue-worker.ts} +17 -14
- package/src/{add-rpc-invocations.ts → add/add-rpc-invocations.ts} +1 -1
- package/src/{add-schedule.ts → add/add-schedule.ts} +17 -14
- package/src/index.ts +5 -0
- package/src/inspector.ts +20 -17
- package/src/types.ts +92 -0
- package/src/{utils.ts → utils/extract-function-name.ts} +25 -199
- package/src/utils/extract-services.ts +35 -0
- package/src/{utils.test.ts → utils/filter-utils.test.ts} +2 -2
- package/src/utils/filter-utils.ts +72 -0
- package/src/utils/get-files-and-methods.ts +143 -0
- package/src/utils/middleware.ts +234 -0
- package/src/utils/type-utils.ts +74 -0
- package/src/visit.ts +47 -33
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/add-functions.d.ts +0 -7
- package/dist/add-mcp-prompt.d.ts +0 -3
- package/dist/add-mcp-resource.d.ts +0 -3
- package/dist/add-mcp-tool.d.ts +0 -3
- package/dist/add-middleware.d.ts +0 -7
- package/dist/add-middleware.js +0 -35
- package/dist/add-permission.d.ts +0 -7
- package/dist/add-queue-worker.d.ts +0 -3
- package/dist/add-schedule.d.ts +0 -3
- package/src/add-middleware.ts +0 -51
- /package/dist/{add-rpc-invocations.js → add/add-rpc-invocations.js} +0 -0
- /package/dist/{does-type-extend-core-type.d.ts → utils/does-type-extend-core-type.d.ts} +0 -0
- /package/dist/{does-type-extend-core-type.js → utils/does-type-extend-core-type.js} +0 -0
- /package/dist/{get-property-value.d.ts → utils/get-property-value.d.ts} +0 -0
- /package/dist/{get-property-value.js → utils/get-property-value.js} +0 -0
- /package/src/{does-type-extend-core-type.ts → utils/does-type-extend-core-type.ts} +0 -0
- /package/src/{get-property-value.ts → utils/get-property-value.ts} +0 -0
package/src/types.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
|
|
|
@@ -20,15 +22,29 @@ export type MetaInputTypes = Map<
|
|
|
20
22
|
}
|
|
21
23
|
>
|
|
22
24
|
|
|
25
|
+
export interface MiddlewareGroupMeta {
|
|
26
|
+
exportName: string | null // null if not exported
|
|
27
|
+
sourceFile: string
|
|
28
|
+
position: number
|
|
29
|
+
services: FunctionServicesMeta
|
|
30
|
+
middlewareCount: number
|
|
31
|
+
isFactory: boolean // true if wrapped in () => add...()
|
|
32
|
+
}
|
|
33
|
+
|
|
23
34
|
export interface InspectorHTTPState {
|
|
24
35
|
metaInputTypes: MetaInputTypes
|
|
25
36
|
meta: HTTPWiringsMeta
|
|
26
37
|
files: Set<string>
|
|
38
|
+
// HTTP middleware calls tracking - route pattern -> group metadata
|
|
39
|
+
// Pattern '*' matches all routes (from addHTTPMiddleware('*', [...]))
|
|
40
|
+
// Pattern '/api/*' matches specific routes (from addHTTPMiddleware('/api/*', [...]))
|
|
41
|
+
routeMiddleware: Map<string, MiddlewareGroupMeta>
|
|
27
42
|
}
|
|
28
43
|
|
|
29
44
|
export interface InspectorFunctionState {
|
|
30
45
|
typesMap: TypesMap
|
|
31
46
|
meta: FunctionsMeta
|
|
47
|
+
files: Map<string, { path: string; exportedName: string }>
|
|
32
48
|
}
|
|
33
49
|
|
|
34
50
|
export interface InspectorChannelState {
|
|
@@ -37,6 +53,7 @@ export interface InspectorChannelState {
|
|
|
37
53
|
}
|
|
38
54
|
|
|
39
55
|
export interface InspectorMiddlewareState {
|
|
56
|
+
// Individual middleware function metadata
|
|
40
57
|
meta: Record<
|
|
41
58
|
string,
|
|
42
59
|
{
|
|
@@ -44,8 +61,12 @@ export interface InspectorMiddlewareState {
|
|
|
44
61
|
sourceFile: string
|
|
45
62
|
position: number
|
|
46
63
|
exportedName: string | null
|
|
64
|
+
factory?: boolean // true if wrapped with pikkuMiddlewareFactory
|
|
47
65
|
}
|
|
48
66
|
>
|
|
67
|
+
// Tag-based middleware calls tracking - tag -> group metadata
|
|
68
|
+
// e.g., export const adminMiddleware = () => addMiddleware('admin', [...])
|
|
69
|
+
tagMiddleware: Map<string, MiddlewareGroupMeta>
|
|
49
70
|
}
|
|
50
71
|
|
|
51
72
|
export interface InspectorPermissionState {
|
|
@@ -66,19 +87,86 @@ export type InspectorFilters = {
|
|
|
66
87
|
directories?: string[]
|
|
67
88
|
}
|
|
68
89
|
|
|
90
|
+
export type InspectorOptions = Partial<{
|
|
91
|
+
types: Partial<{
|
|
92
|
+
configFileType: string
|
|
93
|
+
userSessionType: string
|
|
94
|
+
singletonServicesFactoryType: string
|
|
95
|
+
sessionServicesFactoryType: string
|
|
96
|
+
}>
|
|
97
|
+
filters: InspectorFilters
|
|
98
|
+
}>
|
|
99
|
+
|
|
69
100
|
export interface InspectorLogger {
|
|
70
101
|
info: (message: string) => void
|
|
71
102
|
error: (message: string) => void
|
|
72
103
|
warn: (message: string) => void
|
|
73
104
|
debug: (message: string) => void
|
|
74
105
|
}
|
|
106
|
+
|
|
107
|
+
export type AddWiring = (
|
|
108
|
+
logger: InspectorLogger,
|
|
109
|
+
node: ts.Node,
|
|
110
|
+
checker: ts.TypeChecker,
|
|
111
|
+
state: InspectorState,
|
|
112
|
+
options: InspectorOptions
|
|
113
|
+
) => void
|
|
114
|
+
export interface InspectorFilesAndMethods {
|
|
115
|
+
userSessionType?: {
|
|
116
|
+
file: string
|
|
117
|
+
variable: string
|
|
118
|
+
type: string
|
|
119
|
+
typePath: string
|
|
120
|
+
}
|
|
121
|
+
sessionServicesType?: {
|
|
122
|
+
file: string
|
|
123
|
+
variable: string
|
|
124
|
+
type: string
|
|
125
|
+
typePath: string
|
|
126
|
+
}
|
|
127
|
+
singletonServicesType?: {
|
|
128
|
+
file: string
|
|
129
|
+
variable: string
|
|
130
|
+
type: string
|
|
131
|
+
typePath: string
|
|
132
|
+
}
|
|
133
|
+
pikkuConfigType?: {
|
|
134
|
+
file: string
|
|
135
|
+
variable: string
|
|
136
|
+
type: string
|
|
137
|
+
typePath: string
|
|
138
|
+
}
|
|
139
|
+
pikkuConfigFactory?: {
|
|
140
|
+
file: string
|
|
141
|
+
variable: string
|
|
142
|
+
type: string
|
|
143
|
+
typePath: string
|
|
144
|
+
}
|
|
145
|
+
singletonServicesFactory?: {
|
|
146
|
+
file: string
|
|
147
|
+
variable: string
|
|
148
|
+
type: string
|
|
149
|
+
typePath: string
|
|
150
|
+
}
|
|
151
|
+
sessionServicesFactory?: {
|
|
152
|
+
file: string
|
|
153
|
+
variable: string
|
|
154
|
+
type: string
|
|
155
|
+
typePath: string
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
75
159
|
export interface InspectorState {
|
|
76
160
|
singletonServicesTypeImportMap: PathToNameAndType
|
|
77
161
|
sessionServicesTypeImportMap: PathToNameAndType
|
|
78
162
|
userSessionTypeImportMap: PathToNameAndType
|
|
163
|
+
configTypeImportMap: PathToNameAndType
|
|
79
164
|
singletonServicesFactories: PathToNameAndType
|
|
80
165
|
sessionServicesFactories: PathToNameAndType
|
|
81
166
|
configFactories: PathToNameAndType
|
|
167
|
+
filesAndMethods: InspectorFilesAndMethods
|
|
168
|
+
filesAndMethodsErrors: Map<string, PathToNameAndType>
|
|
169
|
+
typesLookup: Map<string, ts.Type[]> // Lookup for types by name (e.g., function input types, Config type)
|
|
82
170
|
http: InspectorHTTPState
|
|
83
171
|
functions: InspectorFunctionState
|
|
84
172
|
channels: InspectorChannelState
|
|
@@ -103,6 +191,10 @@ export interface InspectorState {
|
|
|
103
191
|
promptsMeta: MCPPromptMeta
|
|
104
192
|
files: Set<string>
|
|
105
193
|
}
|
|
194
|
+
cli: {
|
|
195
|
+
meta: CLIMeta
|
|
196
|
+
files: Set<string>
|
|
197
|
+
}
|
|
106
198
|
middleware: InspectorMiddlewareState
|
|
107
199
|
permissions: InspectorPermissionState
|
|
108
200
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import * as ts from 'typescript'
|
|
2
|
-
import { InspectorFilters, InspectorLogger } from './types.js'
|
|
3
|
-
import { PikkuWiringTypes, FunctionServicesMeta } from '@pikku/core'
|
|
4
2
|
|
|
5
|
-
type ExtractedFunctionName = {
|
|
3
|
+
export type ExtractedFunctionName = {
|
|
6
4
|
pikkuFuncName: string
|
|
7
5
|
name: string
|
|
8
6
|
explicitName: string | null
|
|
@@ -338,9 +336,8 @@ export function extractFunctionName(
|
|
|
338
336
|
}
|
|
339
337
|
}
|
|
340
338
|
|
|
341
|
-
//
|
|
342
|
-
let
|
|
343
|
-
let originalCallExpr = callExpr // Keep track of the original call expression for name extraction
|
|
339
|
+
// Keep track of the original call expression for position-based naming
|
|
340
|
+
let originalCallExpr = callExpr
|
|
344
341
|
|
|
345
342
|
// For direct pikku function calls where callExpr is the call expression itself
|
|
346
343
|
if (ts.isCallExpression(callExpr)) {
|
|
@@ -373,7 +370,7 @@ export function extractFunctionName(
|
|
|
373
370
|
ts.isArrowFunction(firstArg) ||
|
|
374
371
|
ts.isFunctionExpression(firstArg)
|
|
375
372
|
) {
|
|
376
|
-
mainFunc = firstArg // Use the arrow function directly instead of the call expression
|
|
373
|
+
// mainFunc = firstArg // Use the arrow function directly instead of the call expression
|
|
377
374
|
}
|
|
378
375
|
}
|
|
379
376
|
}
|
|
@@ -420,7 +417,7 @@ export function extractFunctionName(
|
|
|
420
417
|
(ts.isArrowFunction(firstArg) ||
|
|
421
418
|
ts.isFunctionExpression(firstArg))
|
|
422
419
|
) {
|
|
423
|
-
mainFunc = firstArg
|
|
420
|
+
// mainFunc = firstArg
|
|
424
421
|
|
|
425
422
|
// Check if the variable is exported
|
|
426
423
|
if (
|
|
@@ -439,7 +436,7 @@ export function extractFunctionName(
|
|
|
439
436
|
ts.isFunctionExpression(funcDecl.initializer) ||
|
|
440
437
|
ts.isArrowFunction(funcDecl.initializer)
|
|
441
438
|
) {
|
|
442
|
-
mainFunc = funcDecl.initializer
|
|
439
|
+
// mainFunc = funcDecl.initializer
|
|
443
440
|
|
|
444
441
|
// Check if the variable is exported
|
|
445
442
|
if (
|
|
@@ -455,7 +452,7 @@ export function extractFunctionName(
|
|
|
455
452
|
break
|
|
456
453
|
}
|
|
457
454
|
} else if (ts.isFunctionDeclaration(funcDecl)) {
|
|
458
|
-
mainFunc = funcDecl
|
|
455
|
+
// mainFunc = funcDecl
|
|
459
456
|
|
|
460
457
|
// Check if the function is exported
|
|
461
458
|
if (
|
|
@@ -479,7 +476,7 @@ export function extractFunctionName(
|
|
|
479
476
|
}
|
|
480
477
|
} else {
|
|
481
478
|
// If we can't resolve the symbol, use the identifier itself
|
|
482
|
-
mainFunc = prop.initializer
|
|
479
|
+
// mainFunc = prop.initializer
|
|
483
480
|
}
|
|
484
481
|
break
|
|
485
482
|
} else if (
|
|
@@ -487,7 +484,7 @@ export function extractFunctionName(
|
|
|
487
484
|
ts.isArrowFunction(prop.initializer)
|
|
488
485
|
) {
|
|
489
486
|
// func: () => {} or func: function() {} - use directly
|
|
490
|
-
mainFunc = prop.initializer
|
|
487
|
+
// mainFunc = prop.initializer
|
|
491
488
|
break
|
|
492
489
|
}
|
|
493
490
|
} else if (
|
|
@@ -522,7 +519,7 @@ export function extractFunctionName(
|
|
|
522
519
|
(ts.isArrowFunction(firstArg) ||
|
|
523
520
|
ts.isFunctionExpression(firstArg))
|
|
524
521
|
) {
|
|
525
|
-
mainFunc = firstArg
|
|
522
|
+
// mainFunc = firstArg
|
|
526
523
|
|
|
527
524
|
// Check if the variable is exported
|
|
528
525
|
if (
|
|
@@ -541,7 +538,7 @@ export function extractFunctionName(
|
|
|
541
538
|
ts.isFunctionExpression(shorthandDecl.initializer) ||
|
|
542
539
|
ts.isArrowFunction(shorthandDecl.initializer)
|
|
543
540
|
) {
|
|
544
|
-
mainFunc = shorthandDecl.initializer
|
|
541
|
+
// mainFunc = shorthandDecl.initializer
|
|
545
542
|
|
|
546
543
|
// Check if the variable is exported
|
|
547
544
|
if (
|
|
@@ -557,7 +554,7 @@ export function extractFunctionName(
|
|
|
557
554
|
break
|
|
558
555
|
}
|
|
559
556
|
} else if (ts.isFunctionDeclaration(shorthandDecl)) {
|
|
560
|
-
mainFunc = shorthandDecl
|
|
557
|
+
// mainFunc = shorthandDecl
|
|
561
558
|
|
|
562
559
|
// Check if the function is exported
|
|
563
560
|
if (
|
|
@@ -605,6 +602,10 @@ export function extractFunctionName(
|
|
|
605
602
|
ts.isIdentifier(decl.initializer.expression) &&
|
|
606
603
|
decl.initializer.expression.text.startsWith('pikku')
|
|
607
604
|
) {
|
|
605
|
+
// Update originalCallExpr to use the call expression position
|
|
606
|
+
// instead of the variable declaration position
|
|
607
|
+
originalCallExpr = decl.initializer
|
|
608
|
+
|
|
608
609
|
// Check for object with 'name' property in first argument
|
|
609
610
|
const firstArg = decl.initializer.arguments[0]
|
|
610
611
|
if (firstArg && ts.isObjectLiteralExpression(firstArg)) {
|
|
@@ -628,7 +629,7 @@ export function extractFunctionName(
|
|
|
628
629
|
(ts.isArrowFunction(firstArg) ||
|
|
629
630
|
ts.isFunctionExpression(firstArg))
|
|
630
631
|
) {
|
|
631
|
-
mainFunc = firstArg
|
|
632
|
+
// mainFunc = firstArg
|
|
632
633
|
}
|
|
633
634
|
}
|
|
634
635
|
|
|
@@ -645,7 +646,7 @@ export function extractFunctionName(
|
|
|
645
646
|
ts.isFunctionExpression(decl.initializer) ||
|
|
646
647
|
ts.isArrowFunction(decl.initializer)
|
|
647
648
|
) {
|
|
648
|
-
mainFunc = decl.initializer
|
|
649
|
+
// mainFunc = decl.initializer
|
|
649
650
|
|
|
650
651
|
// Check if the variable is exported
|
|
651
652
|
if (isNamedExport(decl) && ts.isIdentifier(decl.name)) {
|
|
@@ -655,7 +656,7 @@ export function extractFunctionName(
|
|
|
655
656
|
}
|
|
656
657
|
}
|
|
657
658
|
} else if (ts.isFunctionDeclaration(decl)) {
|
|
658
|
-
mainFunc = decl
|
|
659
|
+
// mainFunc = decl
|
|
659
660
|
|
|
660
661
|
// Check if the function is exported
|
|
661
662
|
if (
|
|
@@ -674,8 +675,10 @@ export function extractFunctionName(
|
|
|
674
675
|
}
|
|
675
676
|
}
|
|
676
677
|
|
|
677
|
-
//
|
|
678
|
-
|
|
678
|
+
// Generate the deterministic function name based on the original call expression
|
|
679
|
+
// (the config), not the resolved inner function. This ensures the metadata key
|
|
680
|
+
// matches what will be looked up at runtime when referencing the config object.
|
|
681
|
+
result.pikkuFuncName = makeDeterministicAnonName(originalCallExpr, checker)
|
|
679
682
|
|
|
680
683
|
// Continue with regular name extraction for remaining cases
|
|
681
684
|
// 1) const foo = pikkuFunc(...)
|
|
@@ -731,7 +734,7 @@ export function extractFunctionName(
|
|
|
731
734
|
/**
|
|
732
735
|
* Helper function to populate the 'name' field based on priority
|
|
733
736
|
*/
|
|
734
|
-
function populateNameByPriority(result: ExtractedFunctionName): void {
|
|
737
|
+
export function populateNameByPriority(result: ExtractedFunctionName): void {
|
|
735
738
|
// Priority 1: If we have an explict name, use that
|
|
736
739
|
if (result.explicitName) {
|
|
737
740
|
result.name = result.explicitName
|
|
@@ -754,7 +757,7 @@ function populateNameByPriority(result: ExtractedFunctionName): void {
|
|
|
754
757
|
/**
|
|
755
758
|
* Helper function to check if a variable declaration is a named export
|
|
756
759
|
*/
|
|
757
|
-
function isNamedExport(declaration: ts.VariableDeclaration): boolean {
|
|
760
|
+
export function isNamedExport(declaration: ts.VariableDeclaration): boolean {
|
|
758
761
|
let parent: any = declaration.parent
|
|
759
762
|
if (!parent) return false
|
|
760
763
|
|
|
@@ -774,180 +777,3 @@ function isNamedExport(declaration: ts.VariableDeclaration): boolean {
|
|
|
774
777
|
|
|
775
778
|
return false
|
|
776
779
|
}
|
|
777
|
-
|
|
778
|
-
// Until here
|
|
779
|
-
export const extractTypeKeys = (type: ts.Type): string[] => {
|
|
780
|
-
return type.getProperties().map((symbol) => symbol.getName())
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
export function getPropertyAssignmentInitializer(
|
|
784
|
-
obj: ts.ObjectLiteralExpression,
|
|
785
|
-
propName: string,
|
|
786
|
-
followShorthand = false,
|
|
787
|
-
checker?: ts.TypeChecker
|
|
788
|
-
): ts.Expression | undefined {
|
|
789
|
-
for (const prop of obj.properties) {
|
|
790
|
-
// ① foo: () => {}
|
|
791
|
-
if (
|
|
792
|
-
ts.isPropertyAssignment(prop) &&
|
|
793
|
-
ts.isIdentifier(prop.name) &&
|
|
794
|
-
prop.name.text === propName
|
|
795
|
-
) {
|
|
796
|
-
return prop.initializer
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
// ② foo() { … }
|
|
800
|
-
if (
|
|
801
|
-
ts.isMethodDeclaration(prop) &&
|
|
802
|
-
ts.isIdentifier(prop.name) &&
|
|
803
|
-
prop.name.text === propName
|
|
804
|
-
) {
|
|
805
|
-
return prop.name // the method node *is* the function
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
// ③ { foo } (shorthand)
|
|
809
|
-
if (
|
|
810
|
-
followShorthand &&
|
|
811
|
-
ts.isShorthandPropertyAssignment(prop) &&
|
|
812
|
-
prop.name.text === propName
|
|
813
|
-
) {
|
|
814
|
-
if (!checker) return prop.name // best effort without a checker
|
|
815
|
-
|
|
816
|
-
let sym = checker.getSymbolAtLocation(prop.name)
|
|
817
|
-
if (sym && sym.flags & ts.SymbolFlags.Alias) {
|
|
818
|
-
sym = checker.getAliasedSymbol(sym)
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
const decl = sym?.declarations?.[0]
|
|
822
|
-
|
|
823
|
-
// const foo = () => {}
|
|
824
|
-
if (
|
|
825
|
-
decl &&
|
|
826
|
-
ts.isVariableDeclaration(decl) &&
|
|
827
|
-
decl.initializer &&
|
|
828
|
-
(ts.isArrowFunction(decl.initializer) ||
|
|
829
|
-
ts.isFunctionExpression(decl.initializer))
|
|
830
|
-
) {
|
|
831
|
-
return decl.initializer
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
// function foo() {}
|
|
835
|
-
if (
|
|
836
|
-
decl &&
|
|
837
|
-
(ts.isFunctionDeclaration(decl) ||
|
|
838
|
-
ts.isArrowFunction(decl) ||
|
|
839
|
-
ts.isFunctionExpression(decl))
|
|
840
|
-
) {
|
|
841
|
-
return decl as ts.Expression
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
// fallback – just give back the identifier
|
|
845
|
-
return prop.name
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
return undefined
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
export const matchesFilters = (
|
|
853
|
-
filters: InspectorFilters,
|
|
854
|
-
params: { tags?: string[] },
|
|
855
|
-
meta: {
|
|
856
|
-
type: PikkuWiringTypes
|
|
857
|
-
name: string
|
|
858
|
-
filePath?: string
|
|
859
|
-
},
|
|
860
|
-
logger: InspectorLogger
|
|
861
|
-
) => {
|
|
862
|
-
// If no filters are provided, allow everything
|
|
863
|
-
if (Object.keys(filters).length === 0) {
|
|
864
|
-
return true
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
// If all filter arrays are empty, allow everything
|
|
868
|
-
if (
|
|
869
|
-
(!filters.tags || filters.tags.length === 0) &&
|
|
870
|
-
(!filters.types || filters.types.length === 0) &&
|
|
871
|
-
(!filters.directories || filters.directories.length === 0)
|
|
872
|
-
) {
|
|
873
|
-
return true
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
// Check type filter
|
|
877
|
-
if (filters.types && filters.types.length > 0) {
|
|
878
|
-
if (!filters.types.includes(meta.type)) {
|
|
879
|
-
logger.debug(`⒡ Filtered by type: ${meta.type}:${meta.name}`)
|
|
880
|
-
return false
|
|
881
|
-
}
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
// Check directory filter
|
|
885
|
-
if (filters.directories && filters.directories.length > 0) {
|
|
886
|
-
if (!meta.filePath) {
|
|
887
|
-
logger.debug(
|
|
888
|
-
`⒡ Filtered by directory: ${meta.type}:${meta.name} (${meta.filePath})`
|
|
889
|
-
)
|
|
890
|
-
return false
|
|
891
|
-
}
|
|
892
|
-
|
|
893
|
-
const matchesDirectory = filters.directories.some((dir) => {
|
|
894
|
-
// Normalize paths for comparison
|
|
895
|
-
const normalizedFilePath = meta.filePath!.replace(/\\/g, '/')
|
|
896
|
-
const normalizedDir = dir.replace(/\\/g, '/')
|
|
897
|
-
return normalizedFilePath.includes(normalizedDir)
|
|
898
|
-
})
|
|
899
|
-
|
|
900
|
-
if (!matchesDirectory) {
|
|
901
|
-
logger.debug(
|
|
902
|
-
`⒡ Filtered by directory: ${meta.type}:${meta.name} (${meta.filePath})`
|
|
903
|
-
)
|
|
904
|
-
return false
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
// Check tag filter
|
|
909
|
-
if (filters.tags && filters.tags.length > 0) {
|
|
910
|
-
if (
|
|
911
|
-
!params.tags ||
|
|
912
|
-
!filters.tags.some((tag) => params.tags!.includes(tag))
|
|
913
|
-
) {
|
|
914
|
-
logger.debug(`⒡ Filtered by tags: ${meta.type}:${meta.name}`)
|
|
915
|
-
return false
|
|
916
|
-
}
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
return true
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
/**
|
|
923
|
-
* Extract services from a function's first parameter destructuring pattern
|
|
924
|
-
*/
|
|
925
|
-
export function extractServicesFromFunction(
|
|
926
|
-
handlerNode: ts.FunctionExpression | ts.ArrowFunction
|
|
927
|
-
): FunctionServicesMeta {
|
|
928
|
-
const services: FunctionServicesMeta = {
|
|
929
|
-
optimized: true,
|
|
930
|
-
services: [],
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
const firstParam = handlerNode.parameters[0]
|
|
934
|
-
if (firstParam) {
|
|
935
|
-
if (ts.isObjectBindingPattern(firstParam.name)) {
|
|
936
|
-
for (const elem of firstParam.name.elements) {
|
|
937
|
-
const original =
|
|
938
|
-
elem.propertyName && ts.isIdentifier(elem.propertyName)
|
|
939
|
-
? elem.propertyName.text
|
|
940
|
-
: ts.isIdentifier(elem.name)
|
|
941
|
-
? elem.name.text
|
|
942
|
-
: undefined
|
|
943
|
-
if (original) {
|
|
944
|
-
services.services.push(original)
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
} else if (ts.isIdentifier(firstParam.name)) {
|
|
948
|
-
services.optimized = false
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
|
|
952
|
-
return services
|
|
953
|
-
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as ts from 'typescript'
|
|
2
|
+
import { FunctionServicesMeta } from '@pikku/core'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Extract services from a function's first parameter destructuring pattern
|
|
6
|
+
*/
|
|
7
|
+
export function extractServicesFromFunction(
|
|
8
|
+
handlerNode: ts.FunctionExpression | ts.ArrowFunction
|
|
9
|
+
): FunctionServicesMeta {
|
|
10
|
+
const services: FunctionServicesMeta = {
|
|
11
|
+
optimized: true,
|
|
12
|
+
services: [],
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const firstParam = handlerNode.parameters[0]
|
|
16
|
+
if (firstParam) {
|
|
17
|
+
if (ts.isObjectBindingPattern(firstParam.name)) {
|
|
18
|
+
for (const elem of firstParam.name.elements) {
|
|
19
|
+
const original =
|
|
20
|
+
elem.propertyName && ts.isIdentifier(elem.propertyName)
|
|
21
|
+
? elem.propertyName.text
|
|
22
|
+
: ts.isIdentifier(elem.name)
|
|
23
|
+
? elem.name.text
|
|
24
|
+
: undefined
|
|
25
|
+
if (original) {
|
|
26
|
+
services.services.push(original)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
} else if (ts.isIdentifier(firstParam.name)) {
|
|
30
|
+
services.optimized = false
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return services
|
|
35
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { test, describe } from 'node:test'
|
|
2
2
|
import { strict as assert } from 'node:assert'
|
|
3
|
-
import { matchesFilters } from './utils.js'
|
|
4
|
-
import { InspectorFilters } from './types.js'
|
|
5
3
|
import { PikkuWiringTypes } from '@pikku/core'
|
|
4
|
+
import { InspectorFilters } from '../types'
|
|
5
|
+
import { matchesFilters } from './filter-utils'
|
|
6
6
|
|
|
7
7
|
describe('matchesFilters', () => {
|
|
8
8
|
// Mock logger for testing
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { InspectorFilters, InspectorLogger } from '../types.js'
|
|
2
|
+
import { PikkuWiringTypes } from '@pikku/core'
|
|
3
|
+
|
|
4
|
+
export const matchesFilters = (
|
|
5
|
+
filters: InspectorFilters,
|
|
6
|
+
params: { tags?: string[] },
|
|
7
|
+
meta: {
|
|
8
|
+
type: PikkuWiringTypes
|
|
9
|
+
name: string
|
|
10
|
+
filePath?: string
|
|
11
|
+
},
|
|
12
|
+
logger: InspectorLogger
|
|
13
|
+
) => {
|
|
14
|
+
// If no filters are provided, allow everything
|
|
15
|
+
if (Object.keys(filters).length === 0) {
|
|
16
|
+
return true
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// If all filter arrays are empty, allow everything
|
|
20
|
+
if (
|
|
21
|
+
(!filters.tags || filters.tags.length === 0) &&
|
|
22
|
+
(!filters.types || filters.types.length === 0) &&
|
|
23
|
+
(!filters.directories || filters.directories.length === 0)
|
|
24
|
+
) {
|
|
25
|
+
return true
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Check type filter
|
|
29
|
+
if (filters.types && filters.types.length > 0) {
|
|
30
|
+
if (!filters.types.includes(meta.type)) {
|
|
31
|
+
logger.debug(`⒡ Filtered by type: ${meta.type}:${meta.name}`)
|
|
32
|
+
return false
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Check directory filter
|
|
37
|
+
if (filters.directories && filters.directories.length > 0) {
|
|
38
|
+
if (!meta.filePath) {
|
|
39
|
+
logger.debug(
|
|
40
|
+
`⒡ Filtered by directory: ${meta.type}:${meta.name} (${meta.filePath})`
|
|
41
|
+
)
|
|
42
|
+
return false
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const matchesDirectory = filters.directories.some((dir) => {
|
|
46
|
+
// Normalize paths for comparison
|
|
47
|
+
const normalizedFilePath = meta.filePath!.replace(/\\/g, '/')
|
|
48
|
+
const normalizedDir = dir.replace(/\\/g, '/')
|
|
49
|
+
return normalizedFilePath.includes(normalizedDir)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
if (!matchesDirectory) {
|
|
53
|
+
logger.debug(
|
|
54
|
+
`⒡ Filtered by directory: ${meta.type}:${meta.name} (${meta.filePath})`
|
|
55
|
+
)
|
|
56
|
+
return false
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Check tag filter
|
|
61
|
+
if (filters.tags && filters.tags.length > 0) {
|
|
62
|
+
if (
|
|
63
|
+
!params.tags ||
|
|
64
|
+
!filters.tags.some((tag) => params.tags!.includes(tag))
|
|
65
|
+
) {
|
|
66
|
+
logger.debug(`⒡ Filtered by tags: ${meta.type}:${meta.name}`)
|
|
67
|
+
return false
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return true
|
|
72
|
+
}
|