@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.
- package/CHANGELOG.md +14 -0
- package/dist/add/add-channel.d.ts +17 -0
- package/dist/{add-channel.js → add/add-channel.js} +60 -34
- package/dist/add/add-cli.d.ts +9 -0
- package/dist/add/add-cli.js +566 -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 -4
- 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} +2 -2
- package/dist/{add-file-with-factory.js → add/add-file-with-factory.js} +38 -5
- package/dist/add/add-functions.d.ts +6 -0
- package/dist/{add-functions.js → add/add-functions.js} +77 -10
- 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} +26 -13
- package/dist/add/add-mcp-prompt.d.ts +2 -0
- package/dist/add/add-mcp-prompt.js +74 -0
- package/dist/add/add-mcp-resource.d.ts +2 -0
- package/dist/add/add-mcp-resource.js +84 -0
- package/dist/add/add-mcp-tool.d.ts +2 -0
- package/dist/add/add-mcp-tool.js +80 -0
- package/dist/add/add-middleware.d.ts +5 -0
- package/dist/add/add-middleware.js +290 -0
- package/dist/add/add-permission.d.ts +5 -0
- package/dist/add/add-permission.js +292 -0
- package/dist/add/add-queue-worker.d.ts +2 -0
- package/dist/add/add-queue-worker.js +52 -0
- 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} +16 -11
- package/dist/error-codes.d.ts +35 -0
- package/dist/error-codes.js +40 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +4 -0
- package/dist/inspector.d.ts +2 -3
- package/dist/inspector.js +38 -8
- package/dist/types.d.ts +108 -1
- package/dist/utils/ensure-function-metadata.d.ts +6 -0
- package/dist/utils/ensure-function-metadata.js +18 -0
- package/dist/utils/extract-function-name.d.ts +31 -0
- package/dist/{utils.js → utils/extract-function-name.js} +35 -149
- package/dist/utils/extract-services.d.ts +6 -0
- package/dist/utils/extract-services.js +29 -0
- package/dist/utils/filter-inspector-state.d.ts +6 -0
- package/dist/utils/filter-inspector-state.js +382 -0
- package/dist/utils/filter-utils.d.ts +19 -0
- package/dist/utils/filter-utils.js +109 -0
- package/dist/utils/find-root-dir.d.ts +23 -0
- package/dist/utils/find-root-dir.js +55 -0
- package/dist/utils/get-files-and-methods.d.ts +22 -0
- package/dist/utils/get-files-and-methods.js +61 -0
- package/dist/utils/get-property-value.d.ts +12 -0
- package/dist/{get-property-value.js → utils/get-property-value.js} +20 -0
- package/dist/utils/middleware.d.ts +39 -0
- package/dist/utils/middleware.js +157 -0
- package/dist/utils/permissions.d.ts +43 -0
- package/dist/utils/permissions.js +178 -0
- package/dist/utils/post-process.d.ts +16 -0
- package/dist/utils/post-process.js +132 -0
- package/dist/utils/serialize-inspector-state.d.ts +179 -0
- package/dist/utils/serialize-inspector-state.js +170 -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 +35 -31
- package/package.json +5 -6
- package/src/{add-channel.ts → add/add-channel.ts} +108 -56
- package/src/add/add-cli.ts +822 -0
- package/src/{add-file-extends-core-type.ts → add/add-file-extends-core-type.ts} +23 -5
- 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} +49 -6
- package/src/{add-functions.ts → add/add-functions.ts} +89 -19
- package/src/{add-http-route.ts → add/add-http-route.ts} +66 -32
- package/src/add/add-mcp-prompt.ts +128 -0
- package/src/add/add-mcp-prompt.ts.tmp +0 -0
- package/src/add/add-mcp-resource.ts +145 -0
- package/src/add/add-mcp-resource.ts.tmp +0 -0
- package/src/add/add-mcp-tool.ts +137 -0
- package/src/add/add-middleware.ts +385 -0
- package/src/add/add-permission.ts +391 -0
- package/src/add/add-queue-worker.ts +92 -0
- package/src/{add-rpc-invocations.ts → add/add-rpc-invocations.ts} +1 -1
- package/src/{add-schedule.ts → add/add-schedule.ts} +30 -28
- package/src/error-codes.ts +43 -0
- package/src/index.ts +12 -0
- package/src/inspector.ts +41 -17
- package/src/types.ts +128 -1
- package/src/utils/ensure-function-metadata.ts +24 -0
- package/src/{utils.ts → utils/extract-function-name.ts} +44 -206
- package/src/utils/extract-services.ts +35 -0
- package/src/utils/filter-inspector-state.test.ts +1433 -0
- package/src/utils/filter-inspector-state.ts +526 -0
- package/src/{utils.test.ts → utils/filter-utils.test.ts} +351 -2
- package/src/utils/filter-utils.ts +152 -0
- package/src/utils/find-root-dir.ts +68 -0
- package/src/utils/get-files-and-methods.ts +151 -0
- package/src/{get-property-value.ts → utils/get-property-value.ts} +27 -0
- package/src/utils/middleware.ts +241 -0
- package/src/utils/permissions.test.ts +327 -0
- package/src/utils/permissions.ts +262 -0
- package/src/utils/post-process.ts +178 -0
- package/src/utils/serialize-inspector-state.ts +375 -0
- package/src/utils/test-data/inspector-state.json +1680 -0
- package/src/utils/type-utils.ts +74 -0
- package/src/visit.ts +50 -34
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/add-channel.d.ts +0 -13
- package/dist/add-functions.d.ts +0 -7
- package/dist/add-mcp-prompt.d.ts +0 -3
- package/dist/add-mcp-prompt.js +0 -61
- package/dist/add-mcp-resource.d.ts +0 -3
- package/dist/add-mcp-resource.js +0 -68
- package/dist/add-mcp-tool.d.ts +0 -3
- package/dist/add-mcp-tool.js +0 -64
- 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-permission.js +0 -35
- package/dist/add-queue-worker.d.ts +0 -3
- package/dist/add-queue-worker.js +0 -48
- package/dist/add-schedule.d.ts +0 -3
- package/dist/get-property-value.d.ts +0 -3
- package/dist/utils.d.ts +0 -39
- package/src/add-mcp-prompt.ts +0 -104
- package/src/add-mcp-resource.ts +0 -116
- package/src/add-mcp-tool.ts +0 -107
- package/src/add-middleware.ts +0 -51
- package/src/add-permission.ts +0 -53
- package/src/add-queue-worker.ts +0 -92
- /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/src/{does-type-extend-core-type.ts → utils/does-type-extend-core-type.ts} +0 -0
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
import { aggregateRequiredServices } from './post-process.js';
|
|
2
|
+
/**
|
|
3
|
+
* Match a value against a pattern with wildcard support
|
|
4
|
+
* Supports "*" at the beginning, end, or both (e.g., "send*", "*Payment", "*process*")
|
|
5
|
+
*/
|
|
6
|
+
function matchesWildcard(value, pattern) {
|
|
7
|
+
if (pattern === '*')
|
|
8
|
+
return true;
|
|
9
|
+
const startsWithWildcard = pattern.startsWith('*');
|
|
10
|
+
const endsWithWildcard = pattern.endsWith('*');
|
|
11
|
+
if (startsWithWildcard && endsWithWildcard) {
|
|
12
|
+
const middle = pattern.slice(1, -1);
|
|
13
|
+
if (middle === '')
|
|
14
|
+
return true;
|
|
15
|
+
return value.includes(middle);
|
|
16
|
+
}
|
|
17
|
+
else if (startsWithWildcard) {
|
|
18
|
+
const suffix = pattern.slice(1);
|
|
19
|
+
return value.endsWith(suffix) && value.length > suffix.length;
|
|
20
|
+
}
|
|
21
|
+
else if (endsWithWildcard) {
|
|
22
|
+
const prefix = pattern.slice(0, -1);
|
|
23
|
+
return value.startsWith(prefix) && value.length > prefix.length;
|
|
24
|
+
}
|
|
25
|
+
return value === pattern;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Check if metadata matches the given filters
|
|
29
|
+
*/
|
|
30
|
+
function matchesFilters(filters, meta, logger) {
|
|
31
|
+
// If no filters, allow everything
|
|
32
|
+
if (Object.keys(filters).length === 0)
|
|
33
|
+
return true;
|
|
34
|
+
// If all filter arrays are empty, allow everything
|
|
35
|
+
if ((!filters.names || filters.names.length === 0) &&
|
|
36
|
+
(!filters.tags || filters.tags.length === 0) &&
|
|
37
|
+
(!filters.types || filters.types.length === 0) &&
|
|
38
|
+
(!filters.directories || filters.directories.length === 0) &&
|
|
39
|
+
(!filters.httpRoutes || filters.httpRoutes.length === 0) &&
|
|
40
|
+
(!filters.httpMethods || filters.httpMethods.length === 0)) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
// Check type filter
|
|
44
|
+
if (filters.types && filters.types.length > 0) {
|
|
45
|
+
if (!filters.types.includes(meta.type)) {
|
|
46
|
+
logger.debug(`⒡ Filtered by type: ${meta.type}:${meta.name}`);
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Check directory filter
|
|
51
|
+
if (filters.directories && filters.directories.length > 0 && meta.filePath) {
|
|
52
|
+
const matchesDirectory = filters.directories.some((dir) => {
|
|
53
|
+
const normalizedFilePath = meta.filePath.replace(/\\/g, '/');
|
|
54
|
+
const normalizedDir = dir.replace(/\\/g, '/');
|
|
55
|
+
return normalizedFilePath.includes(normalizedDir);
|
|
56
|
+
});
|
|
57
|
+
if (!matchesDirectory) {
|
|
58
|
+
logger.debug(`⒡ Filtered by directory: ${meta.type}:${meta.name}`);
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Check tag filter
|
|
63
|
+
if (filters.tags && filters.tags.length > 0) {
|
|
64
|
+
if (!meta.tags || !filters.tags.some((tag) => meta.tags.includes(tag))) {
|
|
65
|
+
logger.debug(`⒡ Filtered by tags: ${meta.type}:${meta.name}`);
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Check name filter
|
|
70
|
+
if (filters.names && filters.names.length > 0) {
|
|
71
|
+
const nameMatches = filters.names.some((pattern) => matchesWildcard(meta.name, pattern));
|
|
72
|
+
if (!nameMatches) {
|
|
73
|
+
logger.debug(`⒡ Filtered by name: ${meta.type}:${meta.name}`);
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Check HTTP route filter
|
|
78
|
+
if (filters.httpRoutes && filters.httpRoutes.length > 0 && meta.httpRoute) {
|
|
79
|
+
const routeMatches = filters.httpRoutes.some((pattern) => matchesWildcard(meta.httpRoute, pattern));
|
|
80
|
+
if (!routeMatches) {
|
|
81
|
+
logger.debug(`⒡ Filtered by HTTP route: ${meta.httpRoute}`);
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Check HTTP method filter
|
|
86
|
+
if (filters.httpMethods &&
|
|
87
|
+
filters.httpMethods.length > 0 &&
|
|
88
|
+
meta.httpMethod) {
|
|
89
|
+
const normalizedMethod = meta.httpMethod.toUpperCase();
|
|
90
|
+
if (!filters.httpMethods.includes(normalizedMethod)) {
|
|
91
|
+
logger.debug(`⒡ Filtered by HTTP method: ${meta.httpMethod}`);
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Extract wire names from middleware/permissions metadata
|
|
99
|
+
*/
|
|
100
|
+
function extractWireNames(obj) {
|
|
101
|
+
if (!obj)
|
|
102
|
+
return [];
|
|
103
|
+
const names = [];
|
|
104
|
+
for (const key of Object.keys(obj)) {
|
|
105
|
+
if (obj[key] && typeof obj[key] === 'object' && 'name' in obj[key]) {
|
|
106
|
+
names.push(obj[key].name);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return names;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Filters inspector state based on provided filters
|
|
113
|
+
* This is applied post-inspection to support the inspect-once, filter-many pattern
|
|
114
|
+
*/
|
|
115
|
+
export function filterInspectorState(state, filters, logger) {
|
|
116
|
+
// If no filters, return original state
|
|
117
|
+
if (Object.keys(filters).length === 0 ||
|
|
118
|
+
((!filters.names || filters.names.length === 0) &&
|
|
119
|
+
(!filters.tags || filters.tags.length === 0) &&
|
|
120
|
+
(!filters.types || filters.types.length === 0) &&
|
|
121
|
+
(!filters.directories || filters.directories.length === 0) &&
|
|
122
|
+
(!filters.httpRoutes || filters.httpRoutes.length === 0) &&
|
|
123
|
+
(!filters.httpMethods || filters.httpMethods.length === 0))) {
|
|
124
|
+
return state;
|
|
125
|
+
}
|
|
126
|
+
// Create a shallow copy with new Maps/Sets to avoid mutating the original
|
|
127
|
+
const filteredState = {
|
|
128
|
+
...state,
|
|
129
|
+
serviceAggregation: {
|
|
130
|
+
...state.serviceAggregation,
|
|
131
|
+
requiredServices: new Set(), // Reset requiredServices - will be recalculated
|
|
132
|
+
usedFunctions: new Set(),
|
|
133
|
+
usedMiddleware: new Set(),
|
|
134
|
+
usedPermissions: new Set(),
|
|
135
|
+
},
|
|
136
|
+
http: {
|
|
137
|
+
...state.http,
|
|
138
|
+
meta: JSON.parse(JSON.stringify(state.http.meta)), // Deep clone metadata
|
|
139
|
+
files: new Set(), // Will be repopulated with filtered files
|
|
140
|
+
},
|
|
141
|
+
channels: {
|
|
142
|
+
...state.channels,
|
|
143
|
+
meta: JSON.parse(JSON.stringify(state.channels.meta)),
|
|
144
|
+
files: new Set(), // Will be repopulated with filtered files
|
|
145
|
+
},
|
|
146
|
+
scheduledTasks: {
|
|
147
|
+
...state.scheduledTasks,
|
|
148
|
+
meta: JSON.parse(JSON.stringify(state.scheduledTasks.meta)),
|
|
149
|
+
files: new Set(), // Will be repopulated with filtered files
|
|
150
|
+
},
|
|
151
|
+
queueWorkers: {
|
|
152
|
+
...state.queueWorkers,
|
|
153
|
+
meta: JSON.parse(JSON.stringify(state.queueWorkers.meta)),
|
|
154
|
+
files: new Set(), // Will be repopulated with filtered files
|
|
155
|
+
},
|
|
156
|
+
mcpEndpoints: {
|
|
157
|
+
...state.mcpEndpoints,
|
|
158
|
+
toolsMeta: JSON.parse(JSON.stringify(state.mcpEndpoints.toolsMeta)),
|
|
159
|
+
resourcesMeta: JSON.parse(JSON.stringify(state.mcpEndpoints.resourcesMeta)),
|
|
160
|
+
promptsMeta: JSON.parse(JSON.stringify(state.mcpEndpoints.promptsMeta)),
|
|
161
|
+
files: new Set(), // Will be repopulated with filtered files
|
|
162
|
+
},
|
|
163
|
+
cli: {
|
|
164
|
+
...state.cli,
|
|
165
|
+
meta: JSON.parse(JSON.stringify(state.cli.meta)),
|
|
166
|
+
files: new Set(), // Will be repopulated with filtered files
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
// Filter HTTP routes
|
|
170
|
+
for (const method of Object.keys(filteredState.http.meta)) {
|
|
171
|
+
const routes = filteredState.http.meta[method];
|
|
172
|
+
for (const route of Object.keys(routes)) {
|
|
173
|
+
const routeMeta = routes[route];
|
|
174
|
+
// Get function file path for directory filtering
|
|
175
|
+
const funcFile = filteredState.functions.files.get(routeMeta.pikkuFuncName);
|
|
176
|
+
const filePath = funcFile?.path;
|
|
177
|
+
const matches = matchesFilters(filters, {
|
|
178
|
+
type: 'http',
|
|
179
|
+
name: routeMeta.pikkuFuncName, // Use function name, not route
|
|
180
|
+
tags: routeMeta.tags,
|
|
181
|
+
filePath,
|
|
182
|
+
httpRoute: routeMeta.route,
|
|
183
|
+
httpMethod: routeMeta.method,
|
|
184
|
+
}, logger);
|
|
185
|
+
if (!matches) {
|
|
186
|
+
delete routes[route];
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
// Track used functions/middleware/permissions
|
|
190
|
+
if (routeMeta.pikkuFuncName) {
|
|
191
|
+
filteredState.serviceAggregation.usedFunctions.add(routeMeta.pikkuFuncName);
|
|
192
|
+
}
|
|
193
|
+
extractWireNames(routeMeta.middleware).forEach((name) => filteredState.serviceAggregation.usedMiddleware.add(name));
|
|
194
|
+
extractWireNames(routeMeta.permissions).forEach((name) => filteredState.serviceAggregation.usedPermissions.add(name));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Repopulate http.files if any routes remain
|
|
199
|
+
const hasHttpRoutes = Object.values(filteredState.http.meta).some((routes) => Object.keys(routes).length > 0);
|
|
200
|
+
if (hasHttpRoutes) {
|
|
201
|
+
filteredState.http.files = new Set(state.http.files);
|
|
202
|
+
}
|
|
203
|
+
// Filter channels
|
|
204
|
+
for (const name of Object.keys(filteredState.channels.meta)) {
|
|
205
|
+
const channelMeta = filteredState.channels.meta[name];
|
|
206
|
+
const matches = matchesFilters(filters, {
|
|
207
|
+
type: 'channel',
|
|
208
|
+
name,
|
|
209
|
+
tags: channelMeta.tags,
|
|
210
|
+
}, logger);
|
|
211
|
+
if (!matches) {
|
|
212
|
+
delete filteredState.channels.meta[name];
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
if (channelMeta.pikkuFuncName) {
|
|
216
|
+
filteredState.serviceAggregation.usedFunctions.add(channelMeta.pikkuFuncName);
|
|
217
|
+
}
|
|
218
|
+
extractWireNames(channelMeta.middleware).forEach((name) => filteredState.serviceAggregation.usedMiddleware.add(name));
|
|
219
|
+
extractWireNames(channelMeta.permissions).forEach((name) => filteredState.serviceAggregation.usedPermissions.add(name));
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// Repopulate channels.files if any channels remain
|
|
223
|
+
if (Object.keys(filteredState.channels.meta).length > 0) {
|
|
224
|
+
filteredState.channels.files = new Set(state.channels.files);
|
|
225
|
+
}
|
|
226
|
+
// Filter scheduled tasks
|
|
227
|
+
for (const name of Object.keys(filteredState.scheduledTasks.meta)) {
|
|
228
|
+
const taskMeta = filteredState.scheduledTasks.meta[name];
|
|
229
|
+
const matches = matchesFilters(filters, {
|
|
230
|
+
type: 'scheduler',
|
|
231
|
+
name,
|
|
232
|
+
tags: taskMeta.tags,
|
|
233
|
+
}, logger);
|
|
234
|
+
if (!matches) {
|
|
235
|
+
delete filteredState.scheduledTasks.meta[name];
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
if (taskMeta.pikkuFuncName) {
|
|
239
|
+
filteredState.serviceAggregation.usedFunctions.add(taskMeta.pikkuFuncName);
|
|
240
|
+
}
|
|
241
|
+
extractWireNames(taskMeta.middleware).forEach((name) => filteredState.serviceAggregation.usedMiddleware.add(name));
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// Repopulate scheduledTasks.files if any tasks remain
|
|
245
|
+
if (Object.keys(filteredState.scheduledTasks.meta).length > 0) {
|
|
246
|
+
filteredState.scheduledTasks.files = new Set(state.scheduledTasks.files);
|
|
247
|
+
}
|
|
248
|
+
// Filter queue workers
|
|
249
|
+
for (const name of Object.keys(filteredState.queueWorkers.meta)) {
|
|
250
|
+
const workerMeta = filteredState.queueWorkers.meta[name];
|
|
251
|
+
const matches = matchesFilters(filters, {
|
|
252
|
+
type: 'queue',
|
|
253
|
+
name,
|
|
254
|
+
tags: workerMeta.tags,
|
|
255
|
+
}, logger);
|
|
256
|
+
if (!matches) {
|
|
257
|
+
delete filteredState.queueWorkers.meta[name];
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
if (workerMeta.pikkuFuncName) {
|
|
261
|
+
filteredState.serviceAggregation.usedFunctions.add(workerMeta.pikkuFuncName);
|
|
262
|
+
}
|
|
263
|
+
extractWireNames(workerMeta.middleware).forEach((name) => filteredState.serviceAggregation.usedMiddleware.add(name));
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
// Repopulate queueWorkers.files if any workers remain
|
|
267
|
+
if (Object.keys(filteredState.queueWorkers.meta).length > 0) {
|
|
268
|
+
filteredState.queueWorkers.files = new Set(state.queueWorkers.files);
|
|
269
|
+
}
|
|
270
|
+
// Filter MCP tools
|
|
271
|
+
for (const name of Object.keys(filteredState.mcpEndpoints.toolsMeta)) {
|
|
272
|
+
const toolMeta = filteredState.mcpEndpoints.toolsMeta[name];
|
|
273
|
+
const matches = matchesFilters(filters, {
|
|
274
|
+
type: 'mcp',
|
|
275
|
+
name,
|
|
276
|
+
tags: toolMeta.tags,
|
|
277
|
+
}, logger);
|
|
278
|
+
if (!matches) {
|
|
279
|
+
delete filteredState.mcpEndpoints.toolsMeta[name];
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
if (toolMeta.pikkuFuncName) {
|
|
283
|
+
filteredState.serviceAggregation.usedFunctions.add(toolMeta.pikkuFuncName);
|
|
284
|
+
}
|
|
285
|
+
extractWireNames(toolMeta.middleware).forEach((name) => filteredState.serviceAggregation.usedMiddleware.add(name));
|
|
286
|
+
extractWireNames(toolMeta.permissions).forEach((name) => filteredState.serviceAggregation.usedPermissions.add(name));
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
// Filter MCP resources
|
|
290
|
+
for (const name of Object.keys(filteredState.mcpEndpoints.resourcesMeta)) {
|
|
291
|
+
const resourceMeta = filteredState.mcpEndpoints.resourcesMeta[name];
|
|
292
|
+
const matches = matchesFilters(filters, {
|
|
293
|
+
type: 'mcp',
|
|
294
|
+
name,
|
|
295
|
+
tags: resourceMeta.tags,
|
|
296
|
+
}, logger);
|
|
297
|
+
if (!matches) {
|
|
298
|
+
delete filteredState.mcpEndpoints.resourcesMeta[name];
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
if (resourceMeta.pikkuFuncName) {
|
|
302
|
+
filteredState.serviceAggregation.usedFunctions.add(resourceMeta.pikkuFuncName);
|
|
303
|
+
}
|
|
304
|
+
extractWireNames(resourceMeta.middleware).forEach((name) => filteredState.serviceAggregation.usedMiddleware.add(name));
|
|
305
|
+
extractWireNames(resourceMeta.permissions).forEach((name) => filteredState.serviceAggregation.usedPermissions.add(name));
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
// Filter MCP prompts
|
|
309
|
+
for (const name of Object.keys(filteredState.mcpEndpoints.promptsMeta)) {
|
|
310
|
+
const promptMeta = filteredState.mcpEndpoints.promptsMeta[name];
|
|
311
|
+
const matches = matchesFilters(filters, {
|
|
312
|
+
type: 'mcp',
|
|
313
|
+
name,
|
|
314
|
+
tags: promptMeta.tags,
|
|
315
|
+
}, logger);
|
|
316
|
+
if (!matches) {
|
|
317
|
+
delete filteredState.mcpEndpoints.promptsMeta[name];
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
if (promptMeta.pikkuFuncName) {
|
|
321
|
+
filteredState.serviceAggregation.usedFunctions.add(promptMeta.pikkuFuncName);
|
|
322
|
+
}
|
|
323
|
+
extractWireNames(promptMeta.middleware).forEach((name) => filteredState.serviceAggregation.usedMiddleware.add(name));
|
|
324
|
+
extractWireNames(promptMeta.permissions).forEach((name) => filteredState.serviceAggregation.usedPermissions.add(name));
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
// Repopulate mcpEndpoints.files if any MCP endpoints remain
|
|
328
|
+
const hasMcpEndpoints = Object.keys(filteredState.mcpEndpoints.toolsMeta).length > 0 ||
|
|
329
|
+
Object.keys(filteredState.mcpEndpoints.resourcesMeta).length > 0 ||
|
|
330
|
+
Object.keys(filteredState.mcpEndpoints.promptsMeta).length > 0;
|
|
331
|
+
if (hasMcpEndpoints) {
|
|
332
|
+
filteredState.mcpEndpoints.files = new Set(state.mcpEndpoints.files);
|
|
333
|
+
}
|
|
334
|
+
// Filter CLI programs (note: CLI filtering might be more complex with nested commands)
|
|
335
|
+
const referencedRenderers = new Set();
|
|
336
|
+
for (const programName of Object.keys(filteredState.cli.meta.programs)) {
|
|
337
|
+
const programMeta = filteredState.cli.meta.programs[programName];
|
|
338
|
+
// Filter commands in the program
|
|
339
|
+
for (const commandName of Object.keys(programMeta.commands)) {
|
|
340
|
+
const commandMeta = programMeta.commands[commandName];
|
|
341
|
+
const matches = matchesFilters(filters, {
|
|
342
|
+
type: 'cli',
|
|
343
|
+
name: commandName,
|
|
344
|
+
tags: commandMeta.tags,
|
|
345
|
+
}, logger);
|
|
346
|
+
if (!matches) {
|
|
347
|
+
delete programMeta.commands[commandName];
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
if (commandMeta.pikkuFuncName) {
|
|
351
|
+
filteredState.serviceAggregation.usedFunctions.add(commandMeta.pikkuFuncName);
|
|
352
|
+
}
|
|
353
|
+
extractWireNames(commandMeta.middleware).forEach((name) => filteredState.serviceAggregation.usedMiddleware.add(name));
|
|
354
|
+
// Track referenced renderers
|
|
355
|
+
if (commandMeta.defaultRenderName) {
|
|
356
|
+
referencedRenderers.add(commandMeta.defaultRenderName);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
// Remove program if it has no commands left
|
|
361
|
+
if (Object.keys(programMeta.commands).length === 0) {
|
|
362
|
+
delete filteredState.cli.meta.programs[programName];
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
// Filter out renderers that aren't referenced by any remaining commands
|
|
366
|
+
for (const rendererName of Object.keys(filteredState.cli.meta.renderers || {})) {
|
|
367
|
+
if (!referencedRenderers.has(rendererName)) {
|
|
368
|
+
delete filteredState.cli.meta.renderers[rendererName];
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
// Repopulate cli.files if any CLI programs or referenced renderers remain
|
|
372
|
+
const hasCliPrograms = Object.keys(filteredState.cli.meta.programs).length > 0;
|
|
373
|
+
const hasCliRenderers = Object.keys(filteredState.cli.meta.renderers || {}).length > 0;
|
|
374
|
+
if (hasCliPrograms || hasCliRenderers) {
|
|
375
|
+
filteredState.cli.files = new Set(state.cli.files);
|
|
376
|
+
}
|
|
377
|
+
// Recalculate requiredServices based on filtered functions/middleware/permissions
|
|
378
|
+
// Need to cast to InspectorState temporarily for aggregateRequiredServices
|
|
379
|
+
const stateForAggregation = filteredState;
|
|
380
|
+
aggregateRequiredServices(stateForAggregation);
|
|
381
|
+
return filteredState;
|
|
382
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { InspectorFilters, InspectorLogger } from '../types.js';
|
|
2
|
+
import { PikkuWiringTypes } from '@pikku/core';
|
|
3
|
+
/**
|
|
4
|
+
* Match a value against a pattern with wildcard support
|
|
5
|
+
* Supports "*" at the beginning, end, or both (e.g., "send*", "*Payment", "*process*")
|
|
6
|
+
* @param value - The value to check
|
|
7
|
+
* @param pattern - The pattern with optional "*" wildcard(s)
|
|
8
|
+
*/
|
|
9
|
+
export declare function matchesWildcard(value: string, pattern: string): boolean;
|
|
10
|
+
export declare const matchesFilters: (filters: InspectorFilters, params: {
|
|
11
|
+
tags?: string[];
|
|
12
|
+
name?: string;
|
|
13
|
+
}, meta: {
|
|
14
|
+
type: PikkuWiringTypes;
|
|
15
|
+
name: string;
|
|
16
|
+
filePath?: string;
|
|
17
|
+
httpRoute?: string;
|
|
18
|
+
httpMethod?: string;
|
|
19
|
+
}, logger: InspectorLogger) => boolean;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Match a value against a pattern with wildcard support
|
|
3
|
+
* Supports "*" at the beginning, end, or both (e.g., "send*", "*Payment", "*process*")
|
|
4
|
+
* @param value - The value to check
|
|
5
|
+
* @param pattern - The pattern with optional "*" wildcard(s)
|
|
6
|
+
*/
|
|
7
|
+
export function matchesWildcard(value, pattern) {
|
|
8
|
+
// If pattern is just '*', match everything
|
|
9
|
+
if (pattern === '*') {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
const startsWithWildcard = pattern.startsWith('*');
|
|
13
|
+
const endsWithWildcard = pattern.endsWith('*');
|
|
14
|
+
if (startsWithWildcard && endsWithWildcard) {
|
|
15
|
+
// Pattern like "*middle*" - check if value contains the middle part
|
|
16
|
+
const middle = pattern.slice(1, -1);
|
|
17
|
+
if (middle === '') {
|
|
18
|
+
return true; // Pattern is "**", match everything
|
|
19
|
+
}
|
|
20
|
+
return value.includes(middle);
|
|
21
|
+
}
|
|
22
|
+
else if (startsWithWildcard) {
|
|
23
|
+
// Pattern like "*suffix" - check if value ends with suffix and has content before
|
|
24
|
+
const suffix = pattern.slice(1);
|
|
25
|
+
return value.endsWith(suffix) && value.length > suffix.length;
|
|
26
|
+
}
|
|
27
|
+
else if (endsWithWildcard) {
|
|
28
|
+
// Pattern like "prefix*" - check if value starts with prefix and has content after
|
|
29
|
+
const prefix = pattern.slice(0, -1);
|
|
30
|
+
return value.startsWith(prefix) && value.length > prefix.length;
|
|
31
|
+
}
|
|
32
|
+
// No wildcard, exact match
|
|
33
|
+
return value === pattern;
|
|
34
|
+
}
|
|
35
|
+
export const matchesFilters = (filters, params, meta, logger) => {
|
|
36
|
+
// If no filters are provided, allow everything
|
|
37
|
+
if (Object.keys(filters).length === 0) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
// If all filter arrays are empty, allow everything
|
|
41
|
+
if ((!filters.names || filters.names.length === 0) &&
|
|
42
|
+
(!filters.tags || filters.tags.length === 0) &&
|
|
43
|
+
(!filters.types || filters.types.length === 0) &&
|
|
44
|
+
(!filters.directories || filters.directories.length === 0) &&
|
|
45
|
+
(!filters.httpRoutes || filters.httpRoutes.length === 0) &&
|
|
46
|
+
(!filters.httpMethods || filters.httpMethods.length === 0)) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
// Check type filter
|
|
50
|
+
if (filters.types && filters.types.length > 0) {
|
|
51
|
+
if (!filters.types.includes(meta.type)) {
|
|
52
|
+
logger.debug(`⒡ Filtered by type: ${meta.type}:${meta.name}`);
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Check directory filter
|
|
57
|
+
if (filters.directories && filters.directories.length > 0) {
|
|
58
|
+
if (!meta.filePath) {
|
|
59
|
+
logger.debug(`⒡ Filtered by directory: ${meta.type}:${meta.name} (${meta.filePath})`);
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
const matchesDirectory = filters.directories.some((dir) => {
|
|
63
|
+
// Normalize paths for comparison
|
|
64
|
+
const normalizedFilePath = meta.filePath.replace(/\\/g, '/');
|
|
65
|
+
const normalizedDir = dir.replace(/\\/g, '/');
|
|
66
|
+
return normalizedFilePath.includes(normalizedDir);
|
|
67
|
+
});
|
|
68
|
+
if (!matchesDirectory) {
|
|
69
|
+
logger.debug(`⒡ Filtered by directory: ${meta.type}:${meta.name} (${meta.filePath})`);
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Check tag filter
|
|
74
|
+
if (filters.tags && filters.tags.length > 0) {
|
|
75
|
+
if (!params.tags ||
|
|
76
|
+
!filters.tags.some((tag) => params.tags.includes(tag))) {
|
|
77
|
+
logger.debug(`⒡ Filtered by tags: ${meta.type}:${meta.name}`);
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Check name filter (with wildcard support)
|
|
82
|
+
if (filters.names && filters.names.length > 0) {
|
|
83
|
+
const nameToMatch = params.name || meta.name;
|
|
84
|
+
const nameMatches = filters.names.some((pattern) => matchesWildcard(nameToMatch, pattern));
|
|
85
|
+
if (!nameMatches) {
|
|
86
|
+
logger.debug(`⒡ Filtered by name: ${meta.type}:${meta.name}`);
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Check HTTP route filter (with wildcard support)
|
|
91
|
+
if (filters.httpRoutes && filters.httpRoutes.length > 0 && meta.httpRoute) {
|
|
92
|
+
const routeMatches = filters.httpRoutes.some((pattern) => matchesWildcard(meta.httpRoute, pattern));
|
|
93
|
+
if (!routeMatches) {
|
|
94
|
+
logger.debug(`⒡ Filtered by HTTP route: ${meta.httpRoute}`);
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Check HTTP method filter
|
|
99
|
+
if (filters.httpMethods &&
|
|
100
|
+
filters.httpMethods.length > 0 &&
|
|
101
|
+
meta.httpMethod) {
|
|
102
|
+
const normalizedMethod = meta.httpMethod.toUpperCase();
|
|
103
|
+
if (!filters.httpMethods.includes(normalizedMethod)) {
|
|
104
|
+
logger.debug(`⒡ Filtered by HTTP method: ${meta.httpMethod}`);
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return true;
|
|
109
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finds the common ancestor directory of all the given file paths.
|
|
3
|
+
* This is used to determine the project root directory.
|
|
4
|
+
*
|
|
5
|
+
* @param filePaths - Array of absolute file paths
|
|
6
|
+
* @returns The common ancestor directory path
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* findCommonAncestor([
|
|
10
|
+
* '/Users/yasser/git/pikku/pikku/src/functions/a.ts',
|
|
11
|
+
* '/Users/yasser/git/pikku/pikku/src/routes/b.ts'
|
|
12
|
+
* ])
|
|
13
|
+
* // Returns: '/Users/yasser/git/pikku/pikku'
|
|
14
|
+
*/
|
|
15
|
+
export declare function findCommonAncestor(filePaths: string[]): string;
|
|
16
|
+
/**
|
|
17
|
+
* Converts an absolute file path to a relative path from the root directory.
|
|
18
|
+
*
|
|
19
|
+
* @param absolutePath - The absolute file path
|
|
20
|
+
* @param rootDir - The root directory to make the path relative to
|
|
21
|
+
* @returns A relative path from rootDir to the file
|
|
22
|
+
*/
|
|
23
|
+
export declare function toRelativePath(absolutePath: string, rootDir: string): string;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
/**
|
|
3
|
+
* Finds the common ancestor directory of all the given file paths.
|
|
4
|
+
* This is used to determine the project root directory.
|
|
5
|
+
*
|
|
6
|
+
* @param filePaths - Array of absolute file paths
|
|
7
|
+
* @returns The common ancestor directory path
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* findCommonAncestor([
|
|
11
|
+
* '/Users/yasser/git/pikku/pikku/src/functions/a.ts',
|
|
12
|
+
* '/Users/yasser/git/pikku/pikku/src/routes/b.ts'
|
|
13
|
+
* ])
|
|
14
|
+
* // Returns: '/Users/yasser/git/pikku/pikku'
|
|
15
|
+
*/
|
|
16
|
+
export function findCommonAncestor(filePaths) {
|
|
17
|
+
if (filePaths.length === 0) {
|
|
18
|
+
return process.cwd();
|
|
19
|
+
}
|
|
20
|
+
if (filePaths.length === 1) {
|
|
21
|
+
return path.dirname(filePaths[0]);
|
|
22
|
+
}
|
|
23
|
+
// Normalize all paths and get their directory parts
|
|
24
|
+
const normalizedPaths = filePaths.map((p) => path.dirname(path.normalize(p)).split(path.sep));
|
|
25
|
+
// Start with the first path's parts
|
|
26
|
+
const firstPath = normalizedPaths[0];
|
|
27
|
+
let commonParts = [];
|
|
28
|
+
// Check each part of the first path
|
|
29
|
+
for (let i = 0; i < firstPath.length; i++) {
|
|
30
|
+
const part = firstPath[i];
|
|
31
|
+
// Check if this part exists in all other paths at the same position
|
|
32
|
+
const existsInAll = normalizedPaths.every((pathParts) => pathParts[i] === part);
|
|
33
|
+
if (existsInAll) {
|
|
34
|
+
commonParts.push(part);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// If no common parts, return root
|
|
41
|
+
if (commonParts.length === 0) {
|
|
42
|
+
return path.sep;
|
|
43
|
+
}
|
|
44
|
+
return commonParts.join(path.sep);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Converts an absolute file path to a relative path from the root directory.
|
|
48
|
+
*
|
|
49
|
+
* @param absolutePath - The absolute file path
|
|
50
|
+
* @param rootDir - The root directory to make the path relative to
|
|
51
|
+
* @returns A relative path from rootDir to the file
|
|
52
|
+
*/
|
|
53
|
+
export function toRelativePath(absolutePath, rootDir) {
|
|
54
|
+
return path.relative(rootDir, absolutePath);
|
|
55
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
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
|
+
pikkuConfigType: Meta;
|
|
13
|
+
pikkuConfigFactory: Meta;
|
|
14
|
+
singletonServicesFactory: Meta;
|
|
15
|
+
sessionServicesFactory: Meta;
|
|
16
|
+
};
|
|
17
|
+
export type FilesAndMethodsErrors = Map<string, PathToNameAndType>;
|
|
18
|
+
export declare const getFilesAndMethods: ({ singletonServicesTypeImportMap, sessionServicesTypeImportMap, userSessionTypeImportMap, configTypeImportMap, sessionServicesFactories, singletonServicesFactories, configFactories, }: InspectorState, { configFileType, userSessionType, singletonServicesFactoryType, sessionServicesFactoryType, }?: InspectorOptions["types"]) => {
|
|
19
|
+
result: Partial<FilesAndMethods>;
|
|
20
|
+
errors: FilesAndMethodsErrors;
|
|
21
|
+
};
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const getMetaTypes = (type, map, desiredType, errors) => {
|
|
2
|
+
if (desiredType) {
|
|
3
|
+
for (const [file, meta] of map.entries()) {
|
|
4
|
+
for (const { type: entryType, variable, typePath } of meta) {
|
|
5
|
+
if (entryType === desiredType) {
|
|
6
|
+
if (entryType === null || typePath === null) {
|
|
7
|
+
throw new Error(`Unknown state due to metaType calculation: entryType or typePath is null for ${desiredType} in ${file}`);
|
|
8
|
+
}
|
|
9
|
+
return { file, variable, type: entryType, typePath };
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
if (errors) {
|
|
14
|
+
errors.set(`No ${desiredType} found that extends ${type}`, map);
|
|
15
|
+
}
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const totalValues = Array.from(map.values()).flat();
|
|
19
|
+
if (totalValues.length === 0) {
|
|
20
|
+
const helpMessage = type === 'CoreConfig'
|
|
21
|
+
? `No ${type} found. Make sure you have exported a createConfig function in your codebase:\n\n` +
|
|
22
|
+
`export const createConfig: CreateConfig<Config> = async () => {\n` +
|
|
23
|
+
` return {}\n` +
|
|
24
|
+
`}\n\n` +
|
|
25
|
+
`Possible issues:\n` +
|
|
26
|
+
`- srcDirectories in pikku.config.json doesn't include the file with the createConfig method`
|
|
27
|
+
: `No ${type} found`;
|
|
28
|
+
if (errors) {
|
|
29
|
+
errors.set(helpMessage, map);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else if (totalValues.length > 1) {
|
|
33
|
+
if (errors) {
|
|
34
|
+
errors.set(`More than one ${type} found`, map);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
const entry = Array.from(map.entries())[0];
|
|
39
|
+
if (entry) {
|
|
40
|
+
const [file, [{ type: entryType, variable, typePath }]] = entry;
|
|
41
|
+
if (entryType === null || typePath === null) {
|
|
42
|
+
throw new Error(`Unknown state due to metaType calculation: entryType or typePath is null for ${type} in ${file}`);
|
|
43
|
+
}
|
|
44
|
+
return { file, type: entryType, variable, typePath };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return;
|
|
48
|
+
};
|
|
49
|
+
export const getFilesAndMethods = ({ singletonServicesTypeImportMap, sessionServicesTypeImportMap, userSessionTypeImportMap, configTypeImportMap, sessionServicesFactories, singletonServicesFactories, configFactories, }, { configFileType, userSessionType, singletonServicesFactoryType, sessionServicesFactoryType, } = {}) => {
|
|
50
|
+
const errors = new Map();
|
|
51
|
+
const result = {
|
|
52
|
+
userSessionType: getMetaTypes('CoreUserSession', userSessionTypeImportMap, userSessionType, errors),
|
|
53
|
+
singletonServicesType: getMetaTypes('CoreSingletonServices', singletonServicesTypeImportMap, undefined, errors),
|
|
54
|
+
sessionServicesType: getMetaTypes('CoreServices', sessionServicesTypeImportMap, undefined, errors),
|
|
55
|
+
pikkuConfigType: getMetaTypes('CoreConfig', configTypeImportMap, undefined, errors),
|
|
56
|
+
pikkuConfigFactory: getMetaTypes('CoreConfig', configFactories, configFileType, errors),
|
|
57
|
+
singletonServicesFactory: getMetaTypes('CreateSingletonServices', singletonServicesFactories, singletonServicesFactoryType, errors),
|
|
58
|
+
sessionServicesFactory: getMetaTypes('CreateSessionServices', sessionServicesFactories, sessionServicesFactoryType, errors),
|
|
59
|
+
};
|
|
60
|
+
return { result, errors };
|
|
61
|
+
};
|