@pikku/inspector 0.11.0 → 0.11.2
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 +32 -2
- package/dist/add/add-channel.js +11 -10
- package/dist/add/add-file-with-factory.js +10 -10
- package/dist/add/add-forge-credential.d.ts +8 -0
- package/dist/add/add-forge-credential.js +77 -0
- package/dist/add/add-forge-node.d.ts +7 -0
- package/dist/add/add-forge-node.js +77 -0
- package/dist/add/add-functions.js +158 -51
- package/dist/add/add-http-route.js +28 -4
- package/dist/add/add-mcp-prompt.js +6 -5
- package/dist/add/add-mcp-resource.js +6 -5
- package/dist/add/add-mcp-tool.js +6 -5
- package/dist/add/add-middleware.js +1 -1
- package/dist/add/add-permission.js +1 -1
- package/dist/add/add-queue-worker.js +6 -5
- package/dist/add/add-rpc-invocations.d.ts +3 -0
- package/dist/add/add-rpc-invocations.js +51 -25
- package/dist/add/add-schedule.js +5 -4
- package/dist/add/add-workflow-graph.d.ts +6 -0
- package/dist/add/add-workflow-graph.js +659 -0
- package/dist/add/add-workflow.d.ts +1 -1
- package/dist/add/add-workflow.js +191 -69
- package/dist/error-codes.d.ts +3 -0
- package/dist/error-codes.js +3 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +3 -0
- package/dist/inspector.js +29 -9
- package/dist/types.d.ts +47 -8
- package/dist/utils/extract-function-name.js +7 -7
- package/dist/utils/extract-function-node.d.ts +10 -0
- package/dist/utils/extract-function-node.js +38 -0
- package/dist/utils/extract-node-value.d.ts +8 -0
- package/dist/utils/extract-node-value.js +24 -0
- package/dist/utils/extract-service-metadata.d.ts +19 -0
- package/dist/utils/extract-service-metadata.js +244 -0
- package/dist/utils/get-files-and-methods.d.ts +3 -3
- package/dist/utils/get-files-and-methods.js +3 -3
- package/dist/utils/get-property-value.d.ts +14 -6
- package/dist/utils/get-property-value.js +55 -43
- package/dist/utils/post-process.d.ts +9 -0
- package/dist/utils/post-process.js +30 -3
- package/dist/utils/serialize-inspector-state.d.ts +42 -6
- package/dist/utils/serialize-inspector-state.js +36 -10
- package/dist/utils/workflow/dsl/deserialize-dsl-workflow.d.ts +24 -0
- package/dist/utils/workflow/dsl/deserialize-dsl-workflow.js +898 -0
- package/dist/utils/workflow/dsl/extract-dsl-workflow.d.ts +17 -0
- package/dist/utils/workflow/dsl/extract-dsl-workflow.js +1284 -0
- package/dist/utils/workflow/dsl/index.d.ts +7 -0
- package/dist/utils/workflow/dsl/index.js +7 -0
- package/dist/utils/workflow/dsl/patterns.d.ts +60 -0
- package/dist/utils/workflow/dsl/patterns.js +218 -0
- package/dist/utils/workflow/dsl/validation.d.ts +30 -0
- package/dist/utils/workflow/dsl/validation.js +142 -0
- package/dist/utils/workflow/graph/convert-dsl-to-graph.d.ts +13 -0
- package/dist/utils/workflow/graph/convert-dsl-to-graph.js +316 -0
- package/dist/utils/workflow/graph/index.d.ts +6 -0
- package/dist/utils/workflow/graph/index.js +6 -0
- package/dist/utils/workflow/graph/serialize-workflow-graph.d.ts +43 -0
- package/dist/utils/workflow/graph/serialize-workflow-graph.js +152 -0
- package/dist/utils/workflow/graph/workflow-graph.types.d.ts +229 -0
- package/dist/utils/workflow/graph/workflow-graph.types.js +38 -0
- package/dist/utils/write-service-metadata.d.ts +13 -0
- package/dist/utils/write-service-metadata.js +37 -0
- package/dist/visit.js +8 -2
- package/package.json +16 -4
- package/src/add/add-channel.ts +37 -17
- package/src/add/add-file-with-factory.ts +10 -10
- package/src/add/add-forge-credential.ts +119 -0
- package/src/add/add-forge-node.ts +132 -0
- package/src/add/add-functions.ts +199 -69
- package/src/add/add-http-route.ts +34 -5
- package/src/add/add-mcp-prompt.ts +11 -7
- package/src/add/add-mcp-resource.ts +11 -7
- package/src/add/add-mcp-tool.ts +11 -7
- package/src/add/add-middleware.ts +1 -1
- package/src/add/add-permission.ts +1 -1
- package/src/add/add-queue-worker.ts +11 -12
- package/src/add/add-rpc-invocations.ts +61 -31
- package/src/add/add-schedule.ts +10 -5
- package/src/add/add-workflow-graph.ts +864 -0
- package/src/add/add-workflow.ts +212 -116
- package/src/error-codes.ts +3 -0
- package/src/index.ts +12 -0
- package/src/inspector.ts +36 -10
- package/src/types.ts +43 -9
- package/src/utils/extract-function-name.ts +7 -7
- package/src/utils/extract-function-node.ts +58 -0
- package/src/utils/extract-node-value.ts +31 -0
- package/src/utils/extract-service-metadata.ts +353 -0
- package/src/utils/filter-inspector-state.test.ts +3 -3
- package/src/utils/filter-utils.test.ts +45 -51
- package/src/utils/get-files-and-methods.ts +11 -11
- package/src/utils/get-property-value.ts +67 -53
- package/src/utils/permissions.test.ts +3 -3
- package/src/utils/post-process.ts +56 -3
- package/src/utils/serialize-inspector-state.ts +67 -19
- package/src/utils/test-data/inspector-state.json +9 -9
- package/src/utils/workflow/dsl/deserialize-dsl-workflow.ts +1180 -0
- package/src/utils/workflow/dsl/extract-dsl-workflow.ts +1608 -0
- package/src/utils/workflow/dsl/index.ts +11 -0
- package/src/utils/workflow/dsl/patterns.ts +279 -0
- package/src/utils/workflow/dsl/validation.ts +180 -0
- package/src/utils/workflow/graph/convert-dsl-to-graph.ts +415 -0
- package/src/utils/workflow/graph/index.ts +6 -0
- package/src/utils/workflow/graph/serialize-workflow-graph.ts +223 -0
- package/src/utils/workflow/graph/workflow-graph.types.ts +280 -0
- package/src/utils/write-service-metadata.ts +51 -0
- package/src/visit.ts +9 -3
- package/tsconfig.tsbuildinfo +1 -1
package/dist/add/add-workflow.js
CHANGED
|
@@ -1,20 +1,85 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
|
-
import { getPropertyValue, getPropertyTags, } from '../utils/get-property-value.js';
|
|
3
2
|
import { extractFunctionName } from '../utils/extract-function-name.js';
|
|
4
|
-
import {
|
|
5
|
-
import { resolveMiddleware } from '../utils/middleware.js';
|
|
6
|
-
import { extractWireNames } from '../utils/post-process.js';
|
|
3
|
+
import { extractFunctionNode } from '../utils/extract-function-node.js';
|
|
7
4
|
import { ErrorCode } from '../error-codes.js';
|
|
8
|
-
import { extractStringLiteral,
|
|
5
|
+
import { extractStringLiteral, isStringLike, isFunctionLike, extractDescription, extractDuration, } from '../utils/extract-node-value.js';
|
|
6
|
+
import { getCommonWireMetaData } from '../utils/get-property-value.js';
|
|
7
|
+
import { extractDSLWorkflow } from '../utils/workflow/dsl/extract-dsl-workflow.js';
|
|
9
8
|
/**
|
|
10
|
-
*
|
|
9
|
+
* Recursively check if any step has inline type (non-serializable)
|
|
10
|
+
*/
|
|
11
|
+
function hasInlineSteps(steps) {
|
|
12
|
+
for (const step of steps) {
|
|
13
|
+
if (step.type === 'inline') {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
else if (step.type === 'branch') {
|
|
17
|
+
for (const branch of step.branches) {
|
|
18
|
+
if (hasInlineSteps(branch.steps))
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
if (step.elseSteps && hasInlineSteps(step.elseSteps))
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
else if (step.type === 'switch' && step.cases) {
|
|
25
|
+
for (const c of step.cases) {
|
|
26
|
+
if (c.steps && hasInlineSteps(c.steps))
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
if (step.defaultSteps && hasInlineSteps(step.defaultSteps))
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
else if (step.type === 'fanout' && step.child) {
|
|
33
|
+
if (hasInlineSteps([step.child]))
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
else if (step.type === 'parallel' && step.children) {
|
|
37
|
+
if (hasInlineSteps(step.children))
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Recursively collect all RPC names from workflow steps
|
|
45
|
+
*/
|
|
46
|
+
function collectInvokedRPCs(steps, rpcs) {
|
|
47
|
+
for (const step of steps) {
|
|
48
|
+
if (step.type === 'rpc' && step.rpcName) {
|
|
49
|
+
rpcs.add(step.rpcName);
|
|
50
|
+
}
|
|
51
|
+
else if (step.type === 'branch') {
|
|
52
|
+
for (const branch of step.branches) {
|
|
53
|
+
collectInvokedRPCs(branch.steps, rpcs);
|
|
54
|
+
}
|
|
55
|
+
if (step.elseSteps)
|
|
56
|
+
collectInvokedRPCs(step.elseSteps, rpcs);
|
|
57
|
+
}
|
|
58
|
+
else if (step.type === 'switch' && step.cases) {
|
|
59
|
+
for (const c of step.cases) {
|
|
60
|
+
if (c.steps)
|
|
61
|
+
collectInvokedRPCs(c.steps, rpcs);
|
|
62
|
+
}
|
|
63
|
+
if (step.defaultSteps)
|
|
64
|
+
collectInvokedRPCs(step.defaultSteps, rpcs);
|
|
65
|
+
}
|
|
66
|
+
else if (step.type === 'fanout' && step.child) {
|
|
67
|
+
collectInvokedRPCs([step.child], rpcs);
|
|
68
|
+
}
|
|
69
|
+
else if (step.type === 'parallel' && step.children) {
|
|
70
|
+
collectInvokedRPCs(step.children, rpcs);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Scan for workflow.do(), workflow.sleep(), and workflow.cancel() calls to extract workflow steps
|
|
11
76
|
*/
|
|
12
77
|
function getWorkflowInvocations(node, checker, state, workflowName, steps) {
|
|
13
78
|
// Look for property access expressions: workflow.do or workflow.sleep
|
|
14
79
|
if (ts.isPropertyAccessExpression(node)) {
|
|
15
80
|
const { name } = node;
|
|
16
81
|
// Check if this is accessing 'do' or 'sleep' property
|
|
17
|
-
if (name.text === 'do' || name.text === 'sleep') {
|
|
82
|
+
if (name.text === 'do' || name.text === 'sleep' || name.text === 'cancel') {
|
|
18
83
|
// Check if the parent is a call expression
|
|
19
84
|
const parent = node.parent;
|
|
20
85
|
if (ts.isCallExpression(parent) && parent.expression === node) {
|
|
@@ -34,7 +99,6 @@ function getWorkflowInvocations(node, checker, state, workflowName, steps) {
|
|
|
34
99
|
type: 'rpc',
|
|
35
100
|
stepName,
|
|
36
101
|
rpcName,
|
|
37
|
-
description,
|
|
38
102
|
});
|
|
39
103
|
state.rpc.invokedFunctions.add(rpcName);
|
|
40
104
|
}
|
|
@@ -59,94 +123,152 @@ function getWorkflowInvocations(node, checker, state, workflowName, steps) {
|
|
|
59
123
|
duration: duration || '<dynamic>',
|
|
60
124
|
});
|
|
61
125
|
}
|
|
126
|
+
else if (name.text === 'cancel') {
|
|
127
|
+
// workflow.cancel(reason?)
|
|
128
|
+
steps.push({
|
|
129
|
+
type: 'cancel',
|
|
130
|
+
});
|
|
131
|
+
}
|
|
62
132
|
}
|
|
63
133
|
}
|
|
64
134
|
}
|
|
65
|
-
//
|
|
135
|
+
// Recurse into children, including arrow functions (for Promise.all callbacks)
|
|
136
|
+
// but skip function declarations (which would be separate functions)
|
|
66
137
|
ts.forEachChild(node, (child) => {
|
|
67
|
-
if (ts.isFunctionDeclaration(child)
|
|
68
|
-
ts.isFunctionExpression(child) ||
|
|
69
|
-
ts.isArrowFunction(child)) {
|
|
138
|
+
if (ts.isFunctionDeclaration(child)) {
|
|
70
139
|
return;
|
|
71
140
|
}
|
|
72
141
|
getWorkflowInvocations(child, checker, state, workflowName, steps);
|
|
73
142
|
});
|
|
74
143
|
}
|
|
75
144
|
/**
|
|
76
|
-
*
|
|
77
|
-
*/
|
|
78
|
-
function extractDescription(optionsNode, checker) {
|
|
79
|
-
if (!optionsNode || !ts.isObjectLiteralExpression(optionsNode)) {
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
return extractPropertyString(optionsNode, 'description', checker);
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Extract duration value (number or string)
|
|
86
|
-
*/
|
|
87
|
-
function extractDuration(node, checker) {
|
|
88
|
-
const numValue = extractNumberLiteral(node);
|
|
89
|
-
if (numValue !== null) {
|
|
90
|
-
return numValue;
|
|
91
|
-
}
|
|
92
|
-
return extractStringLiteral(node, checker);
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Inspector for wireWorkflow() calls
|
|
145
|
+
* Inspector for pikkuWorkflow() and pikkuSimpleWorkflow() calls
|
|
96
146
|
* Detects workflow registration and extracts metadata
|
|
97
147
|
*/
|
|
98
|
-
export const addWorkflow = (logger, node, checker, state
|
|
148
|
+
export const addWorkflow = (logger, node, checker, state) => {
|
|
99
149
|
if (!ts.isCallExpression(node)) {
|
|
100
150
|
return;
|
|
101
151
|
}
|
|
102
152
|
const args = node.arguments;
|
|
103
153
|
const firstArg = args[0];
|
|
104
154
|
const expression = node.expression;
|
|
105
|
-
|
|
106
|
-
|
|
155
|
+
if (!ts.isIdentifier(expression)) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
let wrapperType = null;
|
|
159
|
+
if (expression.text === 'pikkuWorkflowFunc') {
|
|
160
|
+
wrapperType = 'dsl';
|
|
161
|
+
}
|
|
162
|
+
else if (expression.text === 'pikkuWorkflowComplexFunc') {
|
|
163
|
+
wrapperType = 'regular';
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
107
166
|
return;
|
|
108
167
|
}
|
|
109
168
|
if (!firstArg) {
|
|
110
169
|
return;
|
|
111
170
|
}
|
|
171
|
+
// Extract workflow name and metadata using same logic as add-functions
|
|
172
|
+
const { pikkuFuncName, name, exportedName } = extractFunctionName(node, checker, state.rootDir);
|
|
173
|
+
const workflowName = exportedName || name;
|
|
174
|
+
if (!workflowName) {
|
|
175
|
+
logger.critical(ErrorCode.MISSING_NAME, `Could not determine workflow name from export.`);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
// Extract the function node (either direct function or from config.func)
|
|
179
|
+
const { funcNode, resolvedFunc } = extractFunctionNode(firstArg, checker);
|
|
180
|
+
// Extract metadata if using object form
|
|
181
|
+
let tags;
|
|
182
|
+
let summary;
|
|
183
|
+
let description;
|
|
184
|
+
let errors;
|
|
112
185
|
if (ts.isObjectLiteralExpression(firstArg)) {
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
186
|
+
const metadata = getCommonWireMetaData(firstArg, 'Workflow', workflowName, logger);
|
|
187
|
+
tags = metadata.tags;
|
|
188
|
+
summary = metadata.summary;
|
|
189
|
+
description = metadata.description;
|
|
190
|
+
errors = metadata.errors;
|
|
191
|
+
}
|
|
192
|
+
// Validate that we got a valid function
|
|
193
|
+
if (ts.isObjectLiteralExpression(firstArg) &&
|
|
194
|
+
(!funcNode || funcNode === firstArg)) {
|
|
195
|
+
logger.critical(ErrorCode.MISSING_FUNC, `No valid 'func' property for workflow '${workflowName}'.`);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (!resolvedFunc) {
|
|
199
|
+
logger.critical(ErrorCode.MISSING_FUNC, `Could not resolve workflow function for '${workflowName}'.`);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
// Track workflow file for wiring generation
|
|
203
|
+
if (exportedName) {
|
|
204
|
+
state.workflows.files.set(pikkuFuncName, {
|
|
205
|
+
path: node.getSourceFile().fileName,
|
|
206
|
+
exportedName,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
let steps = [];
|
|
210
|
+
let context = undefined;
|
|
211
|
+
let dsl = undefined;
|
|
212
|
+
// Try DSL workflow extraction first
|
|
213
|
+
// Pass the whole CallExpression node so findWorkflowFunction can find the arrow function
|
|
214
|
+
const result = extractDSLWorkflow(node, checker);
|
|
215
|
+
if (result.status === 'ok' && result.steps) {
|
|
216
|
+
// Extraction succeeded
|
|
217
|
+
steps = result.steps;
|
|
218
|
+
context = result.context;
|
|
219
|
+
// Check if workflow contains inline steps (non-serializable)
|
|
220
|
+
if (hasInlineSteps(steps)) {
|
|
221
|
+
if (wrapperType === 'dsl') {
|
|
222
|
+
// pikkuWorkflowFunc should not have inline steps
|
|
223
|
+
logger.critical(ErrorCode.INVALID_DSL_WORKFLOW, `Workflow '${workflowName}' uses pikkuWorkflowFunc but contains inline steps which are not allowed in DSL workflows. Use pikkuWorkflowComplexFunc instead.`);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
// pikkuWorkflowComplexFunc with inline steps is marked as non-dsl
|
|
227
|
+
dsl = false;
|
|
123
228
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
229
|
+
else {
|
|
230
|
+
// pikkuWorkflowComplexFunc is always non-dsl, pikkuWorkflowFunc is dsl
|
|
231
|
+
dsl = wrapperType === 'dsl';
|
|
232
|
+
}
|
|
233
|
+
// Collect all invoked RPCs from workflow steps
|
|
234
|
+
const rpcs = new Set();
|
|
235
|
+
collectInvokedRPCs(steps, rpcs);
|
|
236
|
+
for (const rpc of rpcs) {
|
|
237
|
+
state.rpc.invokedFunctions.add(rpc);
|
|
127
238
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
state.workflows.files.add(node.getSourceFile().fileName);
|
|
135
|
-
// Extract workflow steps from function body
|
|
136
|
-
// Resolve the identifier to the actual function declaration
|
|
137
|
-
const resolvedFunc = resolveFunctionDeclaration(funcInitializer, checker);
|
|
138
|
-
const steps = [];
|
|
139
|
-
if (resolvedFunc) {
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
// DSL extraction failed
|
|
242
|
+
if (wrapperType === 'dsl') {
|
|
243
|
+
// For pikkuWorkflowFunc, this is a critical error
|
|
244
|
+
// But still track RPC invocations for function registration
|
|
140
245
|
getWorkflowInvocations(resolvedFunc, checker, state, workflowName, steps);
|
|
246
|
+
logger.critical(ErrorCode.INVALID_DSL_WORKFLOW, `Workflow '${workflowName}' uses pikkuWorkflowFunc but does not conform to DSL workflow rules:\n${result.reason || 'Unknown error'}`);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
// For pikkuWorkflowComplexFunc, fall back to basic extraction
|
|
251
|
+
logger.debug(`Workflow '${workflowName}' could not be extracted as DSL workflow: ${result.reason || 'Unknown error'}. Falling back to basic extraction.`);
|
|
252
|
+
dsl = false;
|
|
141
253
|
}
|
|
142
|
-
state.workflows.meta[workflowName] = {
|
|
143
|
-
pikkuFuncName,
|
|
144
|
-
workflowName,
|
|
145
|
-
description,
|
|
146
|
-
docs,
|
|
147
|
-
tags,
|
|
148
|
-
middleware,
|
|
149
|
-
steps,
|
|
150
|
-
};
|
|
151
254
|
}
|
|
255
|
+
/**
|
|
256
|
+
* For non-dsl workflows or pikkuWorkflowComplexFunc, run basic extraction
|
|
257
|
+
* to ensure all RPC invocations are tracked for function registration.
|
|
258
|
+
* This catches RPCs in Promise.all callbacks and other patterns DSL can't extract.
|
|
259
|
+
*/
|
|
260
|
+
if (!dsl || wrapperType === 'regular') {
|
|
261
|
+
getWorkflowInvocations(resolvedFunc, checker, state, workflowName, steps);
|
|
262
|
+
}
|
|
263
|
+
state.workflows.meta[workflowName] = {
|
|
264
|
+
pikkuFuncName,
|
|
265
|
+
workflowName,
|
|
266
|
+
steps,
|
|
267
|
+
context,
|
|
268
|
+
dsl,
|
|
269
|
+
summary,
|
|
270
|
+
description,
|
|
271
|
+
errors,
|
|
272
|
+
tags,
|
|
273
|
+
};
|
|
152
274
|
};
|
package/dist/error-codes.d.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
export declare enum ErrorCode {
|
|
10
10
|
MISSING_NAME = "PKU111",
|
|
11
11
|
MISSING_DESCRIPTION = "PKU123",
|
|
12
|
+
INVALID_VALUE = "PKU124",
|
|
12
13
|
MISSING_URI = "PKU220",
|
|
13
14
|
MISSING_FUNC = "PKU236",
|
|
14
15
|
INVALID_TAGS_TYPE = "PKU247",
|
|
@@ -19,11 +20,13 @@ export declare enum ErrorCode {
|
|
|
19
20
|
CLI_CLIENTSIDE_RENDERER_HAS_SERVICES = "PKU672",
|
|
20
21
|
DYNAMIC_STEP_NAME = "PKU529",
|
|
21
22
|
WORKFLOW_ORCHESTRATOR_NOT_CONFIGURED = "PKU600",
|
|
23
|
+
INVALID_DSL_WORKFLOW = "PKU641",
|
|
22
24
|
CONFIG_TYPE_NOT_FOUND = "PKU426",
|
|
23
25
|
CONFIG_TYPE_UNDEFINED = "PKU427",
|
|
24
26
|
SCHEMA_NO_ROOT = "PKU431",
|
|
25
27
|
SCHEMA_GENERATION_ERROR = "PKU456",
|
|
26
28
|
SCHEMA_LOAD_ERROR = "PKU488",
|
|
29
|
+
INLINE_ZOD_SCHEMA = "PKU489",
|
|
27
30
|
FUNCTION_METADATA_NOT_FOUND = "PKU559",
|
|
28
31
|
HANDLER_NOT_RESOLVED = "PKU568",
|
|
29
32
|
MIDDLEWARE_HANDLER_INVALID = "PKU685",
|
package/dist/error-codes.js
CHANGED
|
@@ -11,6 +11,7 @@ export var ErrorCode;
|
|
|
11
11
|
// Validation errors
|
|
12
12
|
ErrorCode["MISSING_NAME"] = "PKU111";
|
|
13
13
|
ErrorCode["MISSING_DESCRIPTION"] = "PKU123";
|
|
14
|
+
ErrorCode["INVALID_VALUE"] = "PKU124";
|
|
14
15
|
ErrorCode["MISSING_URI"] = "PKU220";
|
|
15
16
|
ErrorCode["MISSING_FUNC"] = "PKU236";
|
|
16
17
|
ErrorCode["INVALID_TAGS_TYPE"] = "PKU247";
|
|
@@ -21,12 +22,14 @@ export var ErrorCode;
|
|
|
21
22
|
ErrorCode["CLI_CLIENTSIDE_RENDERER_HAS_SERVICES"] = "PKU672";
|
|
22
23
|
ErrorCode["DYNAMIC_STEP_NAME"] = "PKU529";
|
|
23
24
|
ErrorCode["WORKFLOW_ORCHESTRATOR_NOT_CONFIGURED"] = "PKU600";
|
|
25
|
+
ErrorCode["INVALID_DSL_WORKFLOW"] = "PKU641";
|
|
24
26
|
// Configuration errors
|
|
25
27
|
ErrorCode["CONFIG_TYPE_NOT_FOUND"] = "PKU426";
|
|
26
28
|
ErrorCode["CONFIG_TYPE_UNDEFINED"] = "PKU427";
|
|
27
29
|
ErrorCode["SCHEMA_NO_ROOT"] = "PKU431";
|
|
28
30
|
ErrorCode["SCHEMA_GENERATION_ERROR"] = "PKU456";
|
|
29
31
|
ErrorCode["SCHEMA_LOAD_ERROR"] = "PKU488";
|
|
32
|
+
ErrorCode["INLINE_ZOD_SCHEMA"] = "PKU489";
|
|
30
33
|
// Function errors
|
|
31
34
|
ErrorCode["FUNCTION_METADATA_NOT_FOUND"] = "PKU559";
|
|
32
35
|
ErrorCode["HANDLER_NOT_RESOLVED"] = "PKU568";
|
package/dist/index.d.ts
CHANGED
|
@@ -8,3 +8,8 @@ export { ErrorCode } from './error-codes.js';
|
|
|
8
8
|
export { serializeInspectorState, deserializeInspectorState, } from './utils/serialize-inspector-state.js';
|
|
9
9
|
export type { SerializableInspectorState } from './utils/serialize-inspector-state.js';
|
|
10
10
|
export { filterInspectorState } from './utils/filter-inspector-state.js';
|
|
11
|
+
export { writeAllServiceMetadata } from './utils/write-service-metadata.js';
|
|
12
|
+
export type { ServiceMetadata } from './utils/extract-service-metadata.js';
|
|
13
|
+
export { convertAllDslToGraphs, convertDslToGraph, } from './utils/workflow/graph/convert-dsl-to-graph.js';
|
|
14
|
+
export { deserializeDslWorkflow, deserializeGraphWorkflow, deserializeAllDslWorkflows, } from './utils/workflow/dsl/deserialize-dsl-workflow.js';
|
|
15
|
+
export type { SerializedWorkflowGraph } from './utils/workflow/graph/workflow-graph.types.js';
|
package/dist/index.js
CHANGED
|
@@ -3,3 +3,6 @@ export { getFilesAndMethods } from './utils/get-files-and-methods.js';
|
|
|
3
3
|
export { ErrorCode } from './error-codes.js';
|
|
4
4
|
export { serializeInspectorState, deserializeInspectorState, } from './utils/serialize-inspector-state.js';
|
|
5
5
|
export { filterInspectorState } from './utils/filter-inspector-state.js';
|
|
6
|
+
export { writeAllServiceMetadata } from './utils/write-service-metadata.js';
|
|
7
|
+
export { convertAllDslToGraphs, convertDslToGraph, } from './utils/workflow/graph/convert-dsl-to-graph.js';
|
|
8
|
+
export { deserializeDslWorkflow, deserializeGraphWorkflow, deserializeAllDslWorkflows, } from './utils/workflow/dsl/deserialize-dsl-workflow.js';
|
package/dist/inspector.js
CHANGED
|
@@ -4,7 +4,7 @@ import { visitSetup, visitRoutes } from './visit.js';
|
|
|
4
4
|
import { TypesMap } from './types-map.js';
|
|
5
5
|
import { getFilesAndMethods } from './utils/get-files-and-methods.js';
|
|
6
6
|
import { findCommonAncestor } from './utils/find-root-dir.js';
|
|
7
|
-
import { aggregateRequiredServices } from './utils/post-process.js';
|
|
7
|
+
import { aggregateRequiredServices, extractServiceInterfaceMetadata, } from './utils/post-process.js';
|
|
8
8
|
/**
|
|
9
9
|
* Creates an initial/empty inspector state with all required properties initialized
|
|
10
10
|
* @param rootDir - The root directory for the project
|
|
@@ -14,16 +14,17 @@ export function getInitialInspectorState(rootDir) {
|
|
|
14
14
|
return {
|
|
15
15
|
rootDir,
|
|
16
16
|
singletonServicesTypeImportMap: new Map(),
|
|
17
|
-
|
|
17
|
+
wireServicesTypeImportMap: new Map(),
|
|
18
18
|
userSessionTypeImportMap: new Map(),
|
|
19
19
|
configTypeImportMap: new Map(),
|
|
20
20
|
singletonServicesFactories: new Map(),
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
wireServicesFactories: new Map(),
|
|
22
|
+
wireServicesMeta: new Map(),
|
|
23
23
|
configFactories: new Map(),
|
|
24
24
|
filesAndMethods: {},
|
|
25
25
|
filesAndMethodsErrors: new Map(),
|
|
26
26
|
typesLookup: new Map(),
|
|
27
|
+
zodLookup: new Map(),
|
|
27
28
|
functions: {
|
|
28
29
|
typesMap: new TypesMap(),
|
|
29
30
|
meta: {},
|
|
@@ -58,7 +59,9 @@ export function getInitialInspectorState(rootDir) {
|
|
|
58
59
|
},
|
|
59
60
|
workflows: {
|
|
60
61
|
meta: {},
|
|
61
|
-
files: new
|
|
62
|
+
files: new Map(),
|
|
63
|
+
graphMeta: {},
|
|
64
|
+
graphFiles: new Map(),
|
|
62
65
|
},
|
|
63
66
|
rpc: {
|
|
64
67
|
internalMeta: {},
|
|
@@ -66,6 +69,7 @@ export function getInitialInspectorState(rootDir) {
|
|
|
66
69
|
exposedMeta: {},
|
|
67
70
|
exposedFiles: new Map(),
|
|
68
71
|
invokedFunctions: new Set(),
|
|
72
|
+
usedExternalPackages: new Set(),
|
|
69
73
|
},
|
|
70
74
|
mcpEndpoints: {
|
|
71
75
|
resourcesMeta: {},
|
|
@@ -80,6 +84,14 @@ export function getInitialInspectorState(rootDir) {
|
|
|
80
84
|
},
|
|
81
85
|
files: new Set(),
|
|
82
86
|
},
|
|
87
|
+
forgeNodes: {
|
|
88
|
+
meta: {},
|
|
89
|
+
files: new Set(),
|
|
90
|
+
},
|
|
91
|
+
forgeCredentials: {
|
|
92
|
+
meta: {},
|
|
93
|
+
files: new Set(),
|
|
94
|
+
},
|
|
83
95
|
middleware: {
|
|
84
96
|
meta: {},
|
|
85
97
|
tagMiddleware: new Map(),
|
|
@@ -94,8 +106,9 @@ export function getInitialInspectorState(rootDir) {
|
|
|
94
106
|
usedMiddleware: new Set(),
|
|
95
107
|
usedPermissions: new Set(),
|
|
96
108
|
allSingletonServices: [],
|
|
97
|
-
|
|
109
|
+
allWireServices: [],
|
|
98
110
|
},
|
|
111
|
+
serviceMetadata: [],
|
|
99
112
|
};
|
|
100
113
|
}
|
|
101
114
|
export const inspect = (logger, routeFiles, options = {}) => {
|
|
@@ -114,11 +127,15 @@ export const inspect = (logger, routeFiles, options = {}) => {
|
|
|
114
127
|
const startChecker = performance.now();
|
|
115
128
|
const checker = program.getTypeChecker();
|
|
116
129
|
logger.debug(`Got type checker in ${(performance.now() - startChecker).toFixed(2)}ms`);
|
|
130
|
+
// Use provided rootDir or infer from source files
|
|
131
|
+
const rootDir = options.rootDir || findCommonAncestor(routeFiles);
|
|
117
132
|
const startSourceFiles = performance.now();
|
|
118
|
-
|
|
133
|
+
// Filter source files to only include files within the project rootDir
|
|
134
|
+
// This prevents picking up types from external packages (including workspace symlinks)
|
|
135
|
+
const sourceFiles = program
|
|
136
|
+
.getSourceFiles()
|
|
137
|
+
.filter((sf) => sf.fileName.startsWith(rootDir));
|
|
119
138
|
logger.debug(`Got source files in ${(performance.now() - startSourceFiles).toFixed(2)}ms`);
|
|
120
|
-
// Infer root directory from source files
|
|
121
|
-
const rootDir = findCommonAncestor(routeFiles);
|
|
122
139
|
const state = getInitialInspectorState(rootDir);
|
|
123
140
|
// First sweep: add all functions
|
|
124
141
|
const startSetup = performance.now();
|
|
@@ -144,6 +161,9 @@ export const inspect = (logger, routeFiles, options = {}) => {
|
|
|
144
161
|
const startAggregate = performance.now();
|
|
145
162
|
aggregateRequiredServices(state);
|
|
146
163
|
logger.debug(`Aggregate required services completed in ${(performance.now() - startAggregate).toFixed(2)}ms`);
|
|
164
|
+
const startServiceMeta = performance.now();
|
|
165
|
+
extractServiceInterfaceMetadata(state, checker);
|
|
166
|
+
logger.debug(`Extract service metadata completed in ${(performance.now() - startServiceMeta).toFixed(2)}ms`);
|
|
147
167
|
}
|
|
148
168
|
return state;
|
|
149
169
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -6,9 +6,11 @@ import { QueueWorkersMeta } from '@pikku/core/queue';
|
|
|
6
6
|
import { WorkflowsMeta } from '@pikku/core/workflow';
|
|
7
7
|
import { MCPResourceMeta, MCPToolMeta, MCPPromptMeta } from '@pikku/core/mcp';
|
|
8
8
|
import { CLIMeta } from '@pikku/core/cli';
|
|
9
|
+
import { ForgeNodesMeta, ForgeCredentialsMeta } from '@pikku/core/forge-node';
|
|
9
10
|
import { TypesMap } from './types-map.js';
|
|
10
11
|
import { FunctionsMeta, FunctionServicesMeta } from '@pikku/core';
|
|
11
12
|
import { ErrorCode } from './error-codes.js';
|
|
13
|
+
import type { SerializedWorkflowGraphs } from './utils/workflow/graph/workflow-graph.types.js';
|
|
12
14
|
export type PathToNameAndType = Map<string, {
|
|
13
15
|
variable: string;
|
|
14
16
|
type: string | null;
|
|
@@ -42,6 +44,13 @@ export interface InspectorHTTPState {
|
|
|
42
44
|
routeMiddleware: Map<string, MiddlewareGroupMeta>;
|
|
43
45
|
routePermissions: Map<string, PermissionGroupMeta>;
|
|
44
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Zod schema reference for deferred conversion to JSON Schema at build time
|
|
49
|
+
*/
|
|
50
|
+
export interface ZodSchemaRef {
|
|
51
|
+
variableName: string;
|
|
52
|
+
sourceFile: string;
|
|
53
|
+
}
|
|
45
54
|
export interface InspectorFunctionState {
|
|
46
55
|
typesMap: TypesMap;
|
|
47
56
|
meta: FunctionsMeta;
|
|
@@ -88,11 +97,13 @@ export type InspectorFilters = {
|
|
|
88
97
|
};
|
|
89
98
|
export type InspectorOptions = Partial<{
|
|
90
99
|
setupOnly: boolean;
|
|
100
|
+
/** Project root directory - used to filter out external package files */
|
|
101
|
+
rootDir: string;
|
|
91
102
|
types: Partial<{
|
|
92
103
|
configFileType: string;
|
|
93
104
|
userSessionType: string;
|
|
94
105
|
singletonServicesFactoryType: string;
|
|
95
|
-
|
|
106
|
+
wireServicesFactoryType: string;
|
|
96
107
|
}>;
|
|
97
108
|
}>;
|
|
98
109
|
export interface InspectorLogger {
|
|
@@ -111,7 +122,7 @@ export interface InspectorFilesAndMethods {
|
|
|
111
122
|
type: string;
|
|
112
123
|
typePath: string;
|
|
113
124
|
};
|
|
114
|
-
|
|
125
|
+
wireServicesType?: {
|
|
115
126
|
file: string;
|
|
116
127
|
variable: string;
|
|
117
128
|
type: string;
|
|
@@ -141,7 +152,7 @@ export interface InspectorFilesAndMethods {
|
|
|
141
152
|
type: string;
|
|
142
153
|
typePath: string;
|
|
143
154
|
};
|
|
144
|
-
|
|
155
|
+
wireServicesFactory?: {
|
|
145
156
|
file: string;
|
|
146
157
|
variable: string;
|
|
147
158
|
type: string;
|
|
@@ -151,16 +162,17 @@ export interface InspectorFilesAndMethods {
|
|
|
151
162
|
export interface InspectorState {
|
|
152
163
|
rootDir: string;
|
|
153
164
|
singletonServicesTypeImportMap: PathToNameAndType;
|
|
154
|
-
|
|
165
|
+
wireServicesTypeImportMap: PathToNameAndType;
|
|
155
166
|
userSessionTypeImportMap: PathToNameAndType;
|
|
156
167
|
configTypeImportMap: PathToNameAndType;
|
|
157
168
|
singletonServicesFactories: PathToNameAndType;
|
|
158
|
-
|
|
159
|
-
|
|
169
|
+
wireServicesFactories: PathToNameAndType;
|
|
170
|
+
wireServicesMeta: Map<string, string[]>;
|
|
160
171
|
configFactories: PathToNameAndType;
|
|
161
172
|
filesAndMethods: InspectorFilesAndMethods;
|
|
162
173
|
filesAndMethodsErrors: Map<string, PathToNameAndType>;
|
|
163
174
|
typesLookup: Map<string, ts.Type[]>;
|
|
175
|
+
zodLookup: Map<string, ZodSchemaRef>;
|
|
164
176
|
http: InspectorHTTPState;
|
|
165
177
|
functions: InspectorFunctionState;
|
|
166
178
|
channels: InspectorChannelState;
|
|
@@ -174,7 +186,15 @@ export interface InspectorState {
|
|
|
174
186
|
};
|
|
175
187
|
workflows: {
|
|
176
188
|
meta: WorkflowsMeta;
|
|
177
|
-
files:
|
|
189
|
+
files: Map<string, {
|
|
190
|
+
path: string;
|
|
191
|
+
exportedName: string;
|
|
192
|
+
}>;
|
|
193
|
+
graphMeta: SerializedWorkflowGraphs;
|
|
194
|
+
graphFiles: Map<string, {
|
|
195
|
+
path: string;
|
|
196
|
+
exportedName: string;
|
|
197
|
+
}>;
|
|
178
198
|
};
|
|
179
199
|
rpc: {
|
|
180
200
|
internalMeta: Record<string, string>;
|
|
@@ -188,6 +208,7 @@ export interface InspectorState {
|
|
|
188
208
|
exportedName: string;
|
|
189
209
|
}>;
|
|
190
210
|
invokedFunctions: Set<string>;
|
|
211
|
+
usedExternalPackages: Set<string>;
|
|
191
212
|
};
|
|
192
213
|
mcpEndpoints: {
|
|
193
214
|
resourcesMeta: MCPResourceMeta;
|
|
@@ -199,6 +220,14 @@ export interface InspectorState {
|
|
|
199
220
|
meta: CLIMeta;
|
|
200
221
|
files: Set<string>;
|
|
201
222
|
};
|
|
223
|
+
forgeNodes: {
|
|
224
|
+
meta: ForgeNodesMeta;
|
|
225
|
+
files: Set<string>;
|
|
226
|
+
};
|
|
227
|
+
forgeCredentials: {
|
|
228
|
+
meta: ForgeCredentialsMeta;
|
|
229
|
+
files: Set<string>;
|
|
230
|
+
};
|
|
202
231
|
middleware: InspectorMiddlewareState;
|
|
203
232
|
permissions: InspectorPermissionState;
|
|
204
233
|
serviceAggregation: {
|
|
@@ -207,6 +236,16 @@ export interface InspectorState {
|
|
|
207
236
|
usedMiddleware: Set<string>;
|
|
208
237
|
usedPermissions: Set<string>;
|
|
209
238
|
allSingletonServices: string[];
|
|
210
|
-
|
|
239
|
+
allWireServices: string[];
|
|
211
240
|
};
|
|
241
|
+
serviceMetadata: Array<{
|
|
242
|
+
name: string;
|
|
243
|
+
summary: string;
|
|
244
|
+
description: string;
|
|
245
|
+
package: string;
|
|
246
|
+
path: string;
|
|
247
|
+
version: string;
|
|
248
|
+
interface: string;
|
|
249
|
+
expandedProperties: Record<string, string>;
|
|
250
|
+
}>;
|
|
212
251
|
}
|
|
@@ -274,9 +274,9 @@ export function extractFunctionName(callExpr, checker, rootDir) {
|
|
|
274
274
|
for (const prop of firstArg.properties) {
|
|
275
275
|
if (ts.isPropertyAssignment(prop) &&
|
|
276
276
|
ts.isIdentifier(prop.name) &&
|
|
277
|
-
prop.name.text === '
|
|
277
|
+
prop.name.text === 'override' &&
|
|
278
278
|
ts.isStringLiteral(prop.initializer)) {
|
|
279
|
-
// Priority 1: Object with
|
|
279
|
+
// Priority 1: Object with override property
|
|
280
280
|
result.explicitName = prop.initializer.text;
|
|
281
281
|
break;
|
|
282
282
|
}
|
|
@@ -475,15 +475,15 @@ export function extractFunctionName(callExpr, checker, rootDir) {
|
|
|
475
475
|
// Update originalCallExpr to use the call expression position
|
|
476
476
|
// instead of the variable declaration position
|
|
477
477
|
originalCallExpr = decl.initializer;
|
|
478
|
-
// Check for object with '
|
|
478
|
+
// Check for object with 'override' property in first argument
|
|
479
479
|
const firstArg = decl.initializer.arguments[0];
|
|
480
480
|
if (firstArg && ts.isObjectLiteralExpression(firstArg)) {
|
|
481
481
|
for (const prop of firstArg.properties) {
|
|
482
482
|
if (ts.isPropertyAssignment(prop) &&
|
|
483
483
|
ts.isIdentifier(prop.name) &&
|
|
484
|
-
prop.name.text === '
|
|
484
|
+
prop.name.text === 'override' &&
|
|
485
485
|
ts.isStringLiteral(prop.initializer)) {
|
|
486
|
-
// Priority 1: Object with
|
|
486
|
+
// Priority 1: Object with override property
|
|
487
487
|
result.explicitName = prop.initializer.text;
|
|
488
488
|
break;
|
|
489
489
|
}
|
|
@@ -558,14 +558,14 @@ export function extractFunctionName(callExpr, checker, rootDir) {
|
|
|
558
558
|
ts.isIdentifier(parent.name)) {
|
|
559
559
|
result.propertyName = parent.name.text;
|
|
560
560
|
}
|
|
561
|
-
// 3) Handle any remaining cases for pikkuFunc({
|
|
561
|
+
// 3) Handle any remaining cases for pikkuFunc({ override: '…', func: … })
|
|
562
562
|
else if (ts.isCallExpression(originalCallExpr)) {
|
|
563
563
|
const firstArg = originalCallExpr.arguments[0];
|
|
564
564
|
if (firstArg && ts.isObjectLiteralExpression(firstArg)) {
|
|
565
565
|
for (const prop of firstArg.properties) {
|
|
566
566
|
if (ts.isPropertyAssignment(prop) &&
|
|
567
567
|
ts.isIdentifier(prop.name) &&
|
|
568
|
-
prop.name.text === '
|
|
568
|
+
prop.name.text === 'override' &&
|
|
569
569
|
ts.isStringLiteral(prop.initializer) &&
|
|
570
570
|
!result.explicitName // Only set if not already set
|
|
571
571
|
) {
|