@pikku/inspector 0.11.1 → 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 +16 -1
- 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 +102 -9
- package/dist/add/add-http-route.js +24 -1
- package/dist/add/add-rpc-invocations.d.ts +3 -0
- package/dist/add/add-rpc-invocations.js +51 -25
- package/dist/add/add-workflow-graph.d.ts +6 -0
- package/dist/add/add-workflow-graph.js +659 -0
- package/dist/add/add-workflow.js +118 -22
- package/dist/error-codes.d.ts +3 -1
- package/dist/error-codes.js +3 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/inspector.js +19 -3
- package/dist/types.d.ts +26 -0
- package/dist/utils/extract-function-name.js +7 -7
- package/dist/utils/get-property-value.d.ts +2 -1
- package/dist/utils/get-property-value.js +6 -2
- package/dist/utils/serialize-inspector-state.d.ts +24 -1
- package/dist/utils/serialize-inspector-state.js +24 -0
- 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/{workflow/extract-simple-workflow.d.ts → utils/workflow/dsl/extract-dsl-workflow.d.ts} +4 -2
- package/dist/{workflow/extract-simple-workflow.js → utils/workflow/dsl/extract-dsl-workflow.js} +549 -68
- package/dist/utils/workflow/dsl/index.d.ts +7 -0
- package/dist/utils/workflow/dsl/index.js +7 -0
- package/dist/{workflow → utils/workflow/dsl}/patterns.d.ts +21 -0
- package/dist/{workflow → utils/workflow/dsl}/patterns.js +90 -10
- package/dist/{workflow → utils/workflow/dsl}/validation.d.ts +2 -0
- package/dist/{workflow → utils/workflow/dsl}/validation.js +25 -7
- 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/visit.js +6 -0
- package/package.json +14 -2
- package/src/add/add-forge-credential.ts +119 -0
- package/src/add/add-forge-node.ts +132 -0
- package/src/add/add-functions.ts +129 -15
- package/src/add/add-http-route.ts +25 -1
- package/src/add/add-rpc-invocations.ts +61 -31
- package/src/add/add-workflow-graph.ts +864 -0
- package/src/add/add-workflow.ts +112 -26
- package/src/error-codes.ts +3 -1
- package/src/index.ts +10 -0
- package/src/inspector.ts +20 -4
- package/src/types.ts +25 -1
- package/src/utils/extract-function-name.ts +7 -7
- package/src/utils/get-property-value.ts +9 -2
- package/src/utils/serialize-inspector-state.ts +39 -1
- package/src/utils/workflow/dsl/deserialize-dsl-workflow.ts +1180 -0
- package/src/{workflow/extract-simple-workflow.ts → utils/workflow/dsl/extract-dsl-workflow.ts} +654 -81
- package/src/utils/workflow/dsl/index.ts +11 -0
- package/src/{workflow → utils/workflow/dsl}/patterns.ts +108 -11
- package/src/{workflow → utils/workflow/dsl}/validation.ts +34 -7
- 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/visit.ts +6 -0
- package/tsconfig.tsbuildinfo +1 -1
package/dist/add/add-workflow.js
CHANGED
|
@@ -3,8 +3,74 @@ import { extractFunctionName } from '../utils/extract-function-name.js';
|
|
|
3
3
|
import { extractFunctionNode } from '../utils/extract-function-node.js';
|
|
4
4
|
import { ErrorCode } from '../error-codes.js';
|
|
5
5
|
import { extractStringLiteral, isStringLike, isFunctionLike, extractDescription, extractDuration, } from '../utils/extract-node-value.js';
|
|
6
|
-
import { extractSimpleWorkflow } from '../workflow/extract-simple-workflow.js';
|
|
7
6
|
import { getCommonWireMetaData } from '../utils/get-property-value.js';
|
|
7
|
+
import { extractDSLWorkflow } from '../utils/workflow/dsl/extract-dsl-workflow.js';
|
|
8
|
+
/**
|
|
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
|
+
}
|
|
8
74
|
/**
|
|
9
75
|
* Scan for workflow.do(), workflow.sleep(), and workflow.cancel() calls to extract workflow steps
|
|
10
76
|
*/
|
|
@@ -66,11 +132,10 @@ function getWorkflowInvocations(node, checker, state, workflowName, steps) {
|
|
|
66
132
|
}
|
|
67
133
|
}
|
|
68
134
|
}
|
|
69
|
-
//
|
|
135
|
+
// Recurse into children, including arrow functions (for Promise.all callbacks)
|
|
136
|
+
// but skip function declarations (which would be separate functions)
|
|
70
137
|
ts.forEachChild(node, (child) => {
|
|
71
|
-
if (ts.isFunctionDeclaration(child)
|
|
72
|
-
ts.isFunctionExpression(child) ||
|
|
73
|
-
ts.isArrowFunction(child)) {
|
|
138
|
+
if (ts.isFunctionDeclaration(child)) {
|
|
74
139
|
return;
|
|
75
140
|
}
|
|
76
141
|
getWorkflowInvocations(child, checker, state, workflowName, steps);
|
|
@@ -92,10 +157,10 @@ export const addWorkflow = (logger, node, checker, state) => {
|
|
|
92
157
|
}
|
|
93
158
|
let wrapperType = null;
|
|
94
159
|
if (expression.text === 'pikkuWorkflowFunc') {
|
|
95
|
-
wrapperType = '
|
|
160
|
+
wrapperType = 'dsl';
|
|
96
161
|
}
|
|
97
|
-
else if (expression.text === '
|
|
98
|
-
wrapperType = '
|
|
162
|
+
else if (expression.text === 'pikkuWorkflowComplexFunc') {
|
|
163
|
+
wrapperType = 'regular';
|
|
99
164
|
}
|
|
100
165
|
else {
|
|
101
166
|
return;
|
|
@@ -142,34 +207,65 @@ export const addWorkflow = (logger, node, checker, state) => {
|
|
|
142
207
|
});
|
|
143
208
|
}
|
|
144
209
|
let steps = [];
|
|
145
|
-
let
|
|
146
|
-
|
|
210
|
+
let context = undefined;
|
|
211
|
+
let dsl = undefined;
|
|
212
|
+
// Try DSL workflow extraction first
|
|
147
213
|
// Pass the whole CallExpression node so findWorkflowFunction can find the arrow function
|
|
148
|
-
const result =
|
|
214
|
+
const result = extractDSLWorkflow(node, checker);
|
|
149
215
|
if (result.status === 'ok' && result.steps) {
|
|
150
|
-
//
|
|
216
|
+
// Extraction succeeded
|
|
151
217
|
steps = result.steps;
|
|
152
|
-
|
|
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;
|
|
228
|
+
}
|
|
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);
|
|
238
|
+
}
|
|
153
239
|
}
|
|
154
240
|
else {
|
|
155
|
-
//
|
|
156
|
-
if (wrapperType === '
|
|
157
|
-
// For
|
|
158
|
-
|
|
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
|
|
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'}`);
|
|
159
247
|
return;
|
|
160
248
|
}
|
|
161
249
|
else {
|
|
162
|
-
// For
|
|
163
|
-
logger.debug(`Workflow '${workflowName}' could not be extracted as
|
|
164
|
-
|
|
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;
|
|
165
253
|
}
|
|
166
254
|
}
|
|
167
|
-
|
|
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
|
+
}
|
|
168
263
|
state.workflows.meta[workflowName] = {
|
|
169
264
|
pikkuFuncName,
|
|
170
265
|
workflowName,
|
|
171
266
|
steps,
|
|
172
|
-
|
|
267
|
+
context,
|
|
268
|
+
dsl,
|
|
173
269
|
summary,
|
|
174
270
|
description,
|
|
175
271
|
errors,
|
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,12 +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",
|
|
22
|
-
|
|
23
|
+
INVALID_DSL_WORKFLOW = "PKU641",
|
|
23
24
|
CONFIG_TYPE_NOT_FOUND = "PKU426",
|
|
24
25
|
CONFIG_TYPE_UNDEFINED = "PKU427",
|
|
25
26
|
SCHEMA_NO_ROOT = "PKU431",
|
|
26
27
|
SCHEMA_GENERATION_ERROR = "PKU456",
|
|
27
28
|
SCHEMA_LOAD_ERROR = "PKU488",
|
|
29
|
+
INLINE_ZOD_SCHEMA = "PKU489",
|
|
28
30
|
FUNCTION_METADATA_NOT_FOUND = "PKU559",
|
|
29
31
|
HANDLER_NOT_RESOLVED = "PKU568",
|
|
30
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,13 +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";
|
|
24
|
-
ErrorCode["
|
|
25
|
+
ErrorCode["INVALID_DSL_WORKFLOW"] = "PKU641";
|
|
25
26
|
// Configuration errors
|
|
26
27
|
ErrorCode["CONFIG_TYPE_NOT_FOUND"] = "PKU426";
|
|
27
28
|
ErrorCode["CONFIG_TYPE_UNDEFINED"] = "PKU427";
|
|
28
29
|
ErrorCode["SCHEMA_NO_ROOT"] = "PKU431";
|
|
29
30
|
ErrorCode["SCHEMA_GENERATION_ERROR"] = "PKU456";
|
|
30
31
|
ErrorCode["SCHEMA_LOAD_ERROR"] = "PKU488";
|
|
32
|
+
ErrorCode["INLINE_ZOD_SCHEMA"] = "PKU489";
|
|
31
33
|
// Function errors
|
|
32
34
|
ErrorCode["FUNCTION_METADATA_NOT_FOUND"] = "PKU559";
|
|
33
35
|
ErrorCode["HANDLER_NOT_RESOLVED"] = "PKU568";
|
package/dist/index.d.ts
CHANGED
|
@@ -10,3 +10,6 @@ export type { SerializableInspectorState } from './utils/serialize-inspector-sta
|
|
|
10
10
|
export { filterInspectorState } from './utils/filter-inspector-state.js';
|
|
11
11
|
export { writeAllServiceMetadata } from './utils/write-service-metadata.js';
|
|
12
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
|
@@ -4,3 +4,5 @@ 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
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
|
@@ -24,6 +24,7 @@ export function getInitialInspectorState(rootDir) {
|
|
|
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: {},
|
|
@@ -59,6 +60,8 @@ export function getInitialInspectorState(rootDir) {
|
|
|
59
60
|
workflows: {
|
|
60
61
|
meta: {},
|
|
61
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(),
|
|
@@ -115,11 +127,15 @@ export const inspect = (logger, routeFiles, options = {}) => {
|
|
|
115
127
|
const startChecker = performance.now();
|
|
116
128
|
const checker = program.getTypeChecker();
|
|
117
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);
|
|
118
132
|
const startSourceFiles = performance.now();
|
|
119
|
-
|
|
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));
|
|
120
138
|
logger.debug(`Got source files in ${(performance.now() - startSourceFiles).toFixed(2)}ms`);
|
|
121
|
-
// Infer root directory from source files
|
|
122
|
-
const rootDir = findCommonAncestor(routeFiles);
|
|
123
139
|
const state = getInitialInspectorState(rootDir);
|
|
124
140
|
// First sweep: add all functions
|
|
125
141
|
const startSetup = performance.now();
|
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,6 +97,8 @@ 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;
|
|
@@ -161,6 +172,7 @@ export interface InspectorState {
|
|
|
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;
|
|
@@ -178,6 +190,11 @@ export interface InspectorState {
|
|
|
178
190
|
path: string;
|
|
179
191
|
exportedName: string;
|
|
180
192
|
}>;
|
|
193
|
+
graphMeta: SerializedWorkflowGraphs;
|
|
194
|
+
graphFiles: Map<string, {
|
|
195
|
+
path: string;
|
|
196
|
+
exportedName: string;
|
|
197
|
+
}>;
|
|
181
198
|
};
|
|
182
199
|
rpc: {
|
|
183
200
|
internalMeta: Record<string, string>;
|
|
@@ -191,6 +208,7 @@ export interface InspectorState {
|
|
|
191
208
|
exportedName: string;
|
|
192
209
|
}>;
|
|
193
210
|
invokedFunctions: Set<string>;
|
|
211
|
+
usedExternalPackages: Set<string>;
|
|
194
212
|
};
|
|
195
213
|
mcpEndpoints: {
|
|
196
214
|
resourcesMeta: MCPResourceMeta;
|
|
@@ -202,6 +220,14 @@ export interface InspectorState {
|
|
|
202
220
|
meta: CLIMeta;
|
|
203
221
|
files: Set<string>;
|
|
204
222
|
};
|
|
223
|
+
forgeNodes: {
|
|
224
|
+
meta: ForgeNodesMeta;
|
|
225
|
+
files: Set<string>;
|
|
226
|
+
};
|
|
227
|
+
forgeCredentials: {
|
|
228
|
+
meta: ForgeCredentialsMeta;
|
|
229
|
+
files: Set<string>;
|
|
230
|
+
};
|
|
205
231
|
middleware: InspectorMiddlewareState;
|
|
206
232
|
permissions: InspectorPermissionState;
|
|
207
233
|
serviceAggregation: {
|
|
@@ -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
|
) {
|
|
@@ -2,7 +2,7 @@ import * as ts from 'typescript';
|
|
|
2
2
|
import { ErrorCode } from '../error-codes.js';
|
|
3
3
|
export declare const getPropertyValue: (obj: ts.ObjectLiteralExpression, propertyName: string) => string | string[] | null | boolean;
|
|
4
4
|
/**
|
|
5
|
-
* Extracts common wire metadata (tags, summary, description, errors) directly from an object
|
|
5
|
+
* Extracts common wire metadata (title, tags, summary, description, errors) directly from an object
|
|
6
6
|
* @param obj - The TypeScript object literal expression to extract metadata from
|
|
7
7
|
* @param wiringType - The type of wiring (e.g., 'HTTP route', 'Channel', 'Queue worker')
|
|
8
8
|
* @param wiringName - The name/identifier of the wiring (e.g., route path, channel name)
|
|
@@ -12,6 +12,7 @@ export declare const getPropertyValue: (obj: ts.ObjectLiteralExpression, propert
|
|
|
12
12
|
export declare const getCommonWireMetaData: (obj: ts.ObjectLiteralExpression, wiringType: string, wiringName: string | null, logger?: {
|
|
13
13
|
critical: (code: ErrorCode, message: string) => void;
|
|
14
14
|
}) => {
|
|
15
|
+
title?: string;
|
|
15
16
|
tags?: string[];
|
|
16
17
|
summary?: string;
|
|
17
18
|
description?: string;
|
|
@@ -37,7 +37,7 @@ export const getPropertyValue = (obj, propertyName) => {
|
|
|
37
37
|
return null;
|
|
38
38
|
};
|
|
39
39
|
/**
|
|
40
|
-
* Extracts common wire metadata (tags, summary, description, errors) directly from an object
|
|
40
|
+
* Extracts common wire metadata (title, tags, summary, description, errors) directly from an object
|
|
41
41
|
* @param obj - The TypeScript object literal expression to extract metadata from
|
|
42
42
|
* @param wiringType - The type of wiring (e.g., 'HTTP route', 'Channel', 'Queue worker')
|
|
43
43
|
* @param wiringName - The name/identifier of the wiring (e.g., route path, channel name)
|
|
@@ -49,7 +49,11 @@ export const getCommonWireMetaData = (obj, wiringType, wiringName, logger) => {
|
|
|
49
49
|
obj.properties.forEach((prop) => {
|
|
50
50
|
if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) {
|
|
51
51
|
const propName = prop.name.text;
|
|
52
|
-
if (propName === '
|
|
52
|
+
if (propName === 'title' && ts.isStringLiteral(prop.initializer)) {
|
|
53
|
+
metadata.title = prop.initializer.text;
|
|
54
|
+
}
|
|
55
|
+
else if (propName === 'summary' &&
|
|
56
|
+
ts.isStringLiteral(prop.initializer)) {
|
|
53
57
|
metadata.summary = prop.initializer.text;
|
|
54
58
|
}
|
|
55
59
|
else if (propName === 'description' &&
|
|
@@ -74,6 +74,10 @@ export interface SerializableInspectorState {
|
|
|
74
74
|
}[]
|
|
75
75
|
]>
|
|
76
76
|
]>;
|
|
77
|
+
zodLookup: Array<[string, {
|
|
78
|
+
variableName: string;
|
|
79
|
+
sourceFile: string;
|
|
80
|
+
}]>;
|
|
77
81
|
functions: {
|
|
78
82
|
typesMap: {
|
|
79
83
|
map: Array<[string, {
|
|
@@ -129,6 +133,11 @@ export interface SerializableInspectorState {
|
|
|
129
133
|
path: string;
|
|
130
134
|
exportedName: string;
|
|
131
135
|
}]>;
|
|
136
|
+
graphMeta: InspectorState['workflows']['graphMeta'];
|
|
137
|
+
graphFiles: Array<[string, {
|
|
138
|
+
path: string;
|
|
139
|
+
exportedName: string;
|
|
140
|
+
}]>;
|
|
132
141
|
};
|
|
133
142
|
rpc: {
|
|
134
143
|
internalMeta: InspectorState['rpc']['internalMeta'];
|
|
@@ -142,6 +151,7 @@ export interface SerializableInspectorState {
|
|
|
142
151
|
exportedName: string;
|
|
143
152
|
}]>;
|
|
144
153
|
invokedFunctions: string[];
|
|
154
|
+
usedExternalPackages: string[];
|
|
145
155
|
};
|
|
146
156
|
mcpEndpoints: {
|
|
147
157
|
resourcesMeta: InspectorState['mcpEndpoints']['resourcesMeta'];
|
|
@@ -153,6 +163,14 @@ export interface SerializableInspectorState {
|
|
|
153
163
|
meta: InspectorState['cli']['meta'];
|
|
154
164
|
files: string[];
|
|
155
165
|
};
|
|
166
|
+
forgeNodes: {
|
|
167
|
+
meta: InspectorState['forgeNodes']['meta'];
|
|
168
|
+
files: string[];
|
|
169
|
+
};
|
|
170
|
+
forgeCredentials: {
|
|
171
|
+
meta: InspectorState['forgeCredentials']['meta'];
|
|
172
|
+
files: string[];
|
|
173
|
+
};
|
|
156
174
|
middleware: {
|
|
157
175
|
meta: InspectorState['middleware']['meta'];
|
|
158
176
|
tagMiddleware: Array<[
|
|
@@ -195,4 +213,9 @@ export declare function serializeInspectorState(state: InspectorState): Serializ
|
|
|
195
213
|
* Deserializes JSON data back to InspectorState
|
|
196
214
|
* Creates a partial state suitable for filtering/generation (without typesLookup)
|
|
197
215
|
*/
|
|
198
|
-
export declare function deserializeInspectorState(data: SerializableInspectorState): Omit<InspectorState, 'typesLookup'
|
|
216
|
+
export declare function deserializeInspectorState(data: SerializableInspectorState): Omit<InspectorState, 'typesLookup' | 'zodLookup'> & {
|
|
217
|
+
zodLookup: Map<string, {
|
|
218
|
+
variableName: string;
|
|
219
|
+
sourceFile: string;
|
|
220
|
+
}>;
|
|
221
|
+
};
|
|
@@ -26,6 +26,7 @@ export function serializeInspectorState(state) {
|
|
|
26
26
|
configFactories: Array.from(state.configFactories.entries()),
|
|
27
27
|
filesAndMethods: state.filesAndMethods,
|
|
28
28
|
filesAndMethodsErrors: Array.from(state.filesAndMethodsErrors.entries()).map(([key, mapValue]) => [key, Array.from(mapValue.entries())]),
|
|
29
|
+
zodLookup: Array.from(state.zodLookup.entries()),
|
|
29
30
|
functions: {
|
|
30
31
|
typesMap: serializeTypesMap(state.functions.typesMap),
|
|
31
32
|
meta: state.functions.meta,
|
|
@@ -53,6 +54,8 @@ export function serializeInspectorState(state) {
|
|
|
53
54
|
workflows: {
|
|
54
55
|
meta: state.workflows.meta,
|
|
55
56
|
files: Array.from(state.workflows.files.entries()),
|
|
57
|
+
graphMeta: state.workflows.graphMeta,
|
|
58
|
+
graphFiles: Array.from(state.workflows.graphFiles.entries()),
|
|
56
59
|
},
|
|
57
60
|
rpc: {
|
|
58
61
|
internalMeta: state.rpc.internalMeta,
|
|
@@ -60,6 +63,7 @@ export function serializeInspectorState(state) {
|
|
|
60
63
|
exposedMeta: state.rpc.exposedMeta,
|
|
61
64
|
exposedFiles: Array.from(state.rpc.exposedFiles.entries()),
|
|
62
65
|
invokedFunctions: Array.from(state.rpc.invokedFunctions),
|
|
66
|
+
usedExternalPackages: Array.from(state.rpc.usedExternalPackages),
|
|
63
67
|
},
|
|
64
68
|
mcpEndpoints: {
|
|
65
69
|
resourcesMeta: state.mcpEndpoints.resourcesMeta,
|
|
@@ -71,6 +75,14 @@ export function serializeInspectorState(state) {
|
|
|
71
75
|
meta: state.cli.meta,
|
|
72
76
|
files: Array.from(state.cli.files),
|
|
73
77
|
},
|
|
78
|
+
forgeNodes: {
|
|
79
|
+
meta: state.forgeNodes.meta,
|
|
80
|
+
files: Array.from(state.forgeNodes.files),
|
|
81
|
+
},
|
|
82
|
+
forgeCredentials: {
|
|
83
|
+
meta: state.forgeCredentials.meta,
|
|
84
|
+
files: Array.from(state.forgeCredentials.files),
|
|
85
|
+
},
|
|
74
86
|
middleware: {
|
|
75
87
|
meta: state.middleware.meta,
|
|
76
88
|
tagMiddleware: Array.from(state.middleware.tagMiddleware.entries()),
|
|
@@ -118,6 +130,7 @@ export function deserializeInspectorState(data) {
|
|
|
118
130
|
key,
|
|
119
131
|
new Map(entries),
|
|
120
132
|
])),
|
|
133
|
+
zodLookup: new Map(data.zodLookup || []),
|
|
121
134
|
functions: {
|
|
122
135
|
typesMap: deserializeTypesMap(data.functions.typesMap),
|
|
123
136
|
meta: data.functions.meta,
|
|
@@ -145,6 +158,8 @@ export function deserializeInspectorState(data) {
|
|
|
145
158
|
workflows: {
|
|
146
159
|
meta: data.workflows.meta,
|
|
147
160
|
files: new Map(data.workflows.files),
|
|
161
|
+
graphMeta: data.workflows.graphMeta || {},
|
|
162
|
+
graphFiles: new Map(data.workflows.graphFiles || []),
|
|
148
163
|
},
|
|
149
164
|
rpc: {
|
|
150
165
|
internalMeta: data.rpc.internalMeta,
|
|
@@ -152,6 +167,7 @@ export function deserializeInspectorState(data) {
|
|
|
152
167
|
exposedMeta: data.rpc.exposedMeta,
|
|
153
168
|
exposedFiles: new Map(data.rpc.exposedFiles),
|
|
154
169
|
invokedFunctions: new Set(data.rpc.invokedFunctions),
|
|
170
|
+
usedExternalPackages: new Set(data.rpc.usedExternalPackages || []),
|
|
155
171
|
},
|
|
156
172
|
mcpEndpoints: {
|
|
157
173
|
resourcesMeta: data.mcpEndpoints.resourcesMeta,
|
|
@@ -163,6 +179,14 @@ export function deserializeInspectorState(data) {
|
|
|
163
179
|
meta: data.cli.meta,
|
|
164
180
|
files: new Set(data.cli.files),
|
|
165
181
|
},
|
|
182
|
+
forgeNodes: {
|
|
183
|
+
meta: data.forgeNodes?.meta || {},
|
|
184
|
+
files: new Set(data.forgeNodes?.files || []),
|
|
185
|
+
},
|
|
186
|
+
forgeCredentials: {
|
|
187
|
+
meta: data.forgeCredentials?.meta || {},
|
|
188
|
+
files: new Set(data.forgeCredentials?.files || []),
|
|
189
|
+
},
|
|
166
190
|
middleware: {
|
|
167
191
|
meta: data.middleware.meta,
|
|
168
192
|
tagMiddleware: new Map(data.middleware.tagMiddleware),
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deserialize workflow JSON back to DSL code
|
|
3
|
+
* Converts the serialized workflow graph format back to TypeScript DSL code
|
|
4
|
+
*/
|
|
5
|
+
import type { SerializedWorkflowGraph } from '../graph/workflow-graph.types.js';
|
|
6
|
+
interface DeserializeOptions {
|
|
7
|
+
/** Import path for pikkuWorkflowFunc */
|
|
8
|
+
pikkuImportPath?: string;
|
|
9
|
+
/** Whether to include type annotations */
|
|
10
|
+
includeTypes?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Deserialize a workflow graph to DSL code
|
|
14
|
+
*/
|
|
15
|
+
export declare function deserializeDslWorkflow(workflow: SerializedWorkflowGraph, options?: DeserializeOptions): string;
|
|
16
|
+
/**
|
|
17
|
+
* Deserialize a graph workflow to pikkuWorkflowGraph code
|
|
18
|
+
*/
|
|
19
|
+
export declare function deserializeGraphWorkflow(workflow: SerializedWorkflowGraph, options?: DeserializeOptions): string;
|
|
20
|
+
/**
|
|
21
|
+
* Deserialize all workflows from JSON to DSL code
|
|
22
|
+
*/
|
|
23
|
+
export declare function deserializeAllDslWorkflows(workflows: Record<string, SerializedWorkflowGraph>, options?: DeserializeOptions): Record<string, string>;
|
|
24
|
+
export {};
|