@pikku/inspector 0.11.2 → 0.12.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 +11 -1
- package/OPTIMIZATION-PLAN.md +195 -0
- package/dist/add/add-ai-agent.d.ts +2 -0
- package/dist/add/add-ai-agent.js +314 -0
- package/dist/add/add-channel.js +69 -61
- package/dist/add/add-cli.js +36 -18
- package/dist/add/add-file-with-factory.js +2 -0
- package/dist/add/add-functions.js +250 -75
- package/dist/add/add-http-route.d.ts +19 -10
- package/dist/add/add-http-route.js +152 -66
- package/dist/add/add-http-routes.d.ts +5 -0
- package/dist/add/add-http-routes.js +159 -0
- package/dist/add/add-keyed-wiring.d.ts +12 -0
- package/dist/add/add-keyed-wiring.js +97 -0
- package/dist/add/add-mcp-prompt.js +14 -9
- package/dist/add/add-mcp-resource.js +14 -9
- package/dist/add/add-middleware.d.ts +1 -4
- package/dist/add/add-middleware.js +364 -79
- package/dist/add/add-permission.d.ts +1 -1
- package/dist/add/add-permission.js +152 -40
- package/dist/add/add-queue-worker.js +18 -12
- package/dist/add/add-rpc-invocations.js +14 -0
- package/dist/add/add-schedule.js +11 -5
- package/dist/add/add-secret.d.ts +3 -0
- package/dist/add/add-secret.js +82 -0
- package/dist/add/add-trigger.d.ts +2 -0
- package/dist/add/add-trigger.js +87 -0
- package/dist/add/add-variable.d.ts +1 -0
- package/dist/add/add-variable.js +8 -0
- package/dist/add/add-workflow-graph.d.ts +3 -2
- package/dist/add/add-workflow-graph.js +143 -406
- package/dist/add/add-workflow.js +6 -4
- package/dist/error-codes.d.ts +14 -1
- package/dist/error-codes.js +19 -1
- package/dist/index.d.ts +9 -8
- package/dist/index.js +5 -4
- package/dist/inspector.d.ts +1 -1
- package/dist/inspector.js +91 -14
- package/dist/schema-generator.d.ts +1 -0
- package/dist/schema-generator.js +1 -0
- package/dist/types-map.js +10 -1
- package/dist/types.d.ts +163 -39
- package/dist/utils/compute-required-schemas.d.ts +4 -0
- package/dist/utils/compute-required-schemas.js +41 -0
- package/dist/utils/contract-hashes.d.ts +35 -0
- package/dist/utils/contract-hashes.js +202 -0
- package/dist/utils/custom-types-generator.d.ts +9 -0
- package/dist/utils/custom-types-generator.js +71 -0
- package/dist/utils/detect-schema-vendor.d.ts +22 -0
- package/dist/utils/detect-schema-vendor.js +76 -0
- package/dist/utils/ensure-function-metadata.d.ts +5 -2
- package/dist/utils/ensure-function-metadata.js +220 -6
- package/dist/utils/extract-function-name.d.ts +5 -16
- package/dist/utils/extract-function-name.js +86 -291
- package/dist/utils/extract-services.d.ts +2 -1
- package/dist/utils/extract-services.js +25 -1
- package/dist/utils/filter-inspector-state.js +107 -23
- package/dist/utils/get-property-value.d.ts +6 -1
- package/dist/utils/get-property-value.js +28 -3
- package/dist/utils/hash.d.ts +2 -0
- package/dist/utils/hash.js +23 -0
- package/dist/utils/middleware.d.ts +7 -30
- package/dist/utils/middleware.js +80 -66
- package/dist/utils/permissions.d.ts +2 -2
- package/dist/utils/permissions.js +10 -10
- package/dist/utils/post-process.d.ts +9 -10
- package/dist/utils/post-process.js +231 -24
- package/dist/utils/resolve-external-package.d.ts +12 -0
- package/dist/utils/resolve-external-package.js +34 -0
- package/dist/utils/resolve-function-types.d.ts +6 -0
- package/dist/utils/resolve-function-types.js +29 -0
- package/dist/utils/resolve-identifier.d.ts +10 -0
- package/dist/utils/resolve-identifier.js +36 -0
- package/dist/utils/resolve-versions.d.ts +2 -0
- package/dist/utils/resolve-versions.js +78 -0
- package/dist/utils/schema-generator.d.ts +9 -0
- package/dist/utils/schema-generator.js +209 -0
- package/dist/utils/serialize-inspector-state.d.ts +59 -22
- package/dist/utils/serialize-inspector-state.js +92 -20
- package/dist/utils/serialize-mcp-json.d.ts +2 -0
- package/dist/utils/serialize-mcp-json.js +99 -0
- package/dist/utils/serialize-middleware-groups-meta.d.ts +12 -0
- package/dist/utils/serialize-middleware-groups-meta.js +28 -0
- package/dist/utils/serialize-openapi-json.d.ts +85 -0
- package/dist/utils/serialize-openapi-json.js +151 -0
- package/dist/utils/serialize-permissions-groups-meta.d.ts +6 -0
- package/dist/utils/serialize-permissions-groups-meta.js +31 -0
- package/dist/utils/workflow/dsl/deserialize-dsl-workflow.js +34 -102
- package/dist/utils/workflow/dsl/extract-dsl-workflow.js +23 -4
- package/dist/utils/workflow/graph/convert-dsl-to-graph.js +12 -10
- package/dist/utils/workflow/graph/finalize-workflow-wires.d.ts +3 -0
- package/dist/utils/workflow/graph/finalize-workflow-wires.js +276 -0
- package/dist/utils/workflow/graph/finalize-workflows.d.ts +2 -0
- package/dist/utils/workflow/graph/finalize-workflows.js +75 -0
- package/dist/utils/workflow/graph/index.d.ts +2 -0
- package/dist/utils/workflow/graph/index.js +2 -0
- package/dist/utils/workflow/graph/serialize-workflow-graph.d.ts +0 -8
- package/dist/utils/workflow/graph/serialize-workflow-graph.js +1 -3
- package/dist/utils/workflow/graph/workflow-graph.types.d.ts +53 -79
- package/dist/utils/workflow/graph/workflow-graph.types.js +1 -1
- package/dist/visit.js +11 -6
- package/package.json +14 -4
- package/src/add/add-ai-agent.ts +468 -0
- package/src/add/add-channel.ts +82 -79
- package/src/add/add-cli.ts +49 -20
- package/src/add/add-file-with-factory.ts +2 -0
- package/src/add/add-functions.ts +330 -86
- package/src/add/add-http-route.ts +245 -88
- package/src/add/add-http-routes.ts +228 -0
- package/src/add/add-keyed-wiring.ts +151 -0
- package/src/add/add-mcp-prompt.ts +26 -15
- package/src/add/add-mcp-resource.ts +27 -15
- package/src/add/add-middleware.ts +482 -80
- package/src/add/add-permission.ts +199 -40
- package/src/add/add-queue-worker.ts +24 -19
- package/src/add/add-rpc-invocations.ts +17 -0
- package/src/add/add-schedule.ts +16 -11
- package/src/add/add-secret.ts +140 -0
- package/src/add/add-trigger.ts +154 -0
- package/src/add/add-variable.ts +9 -0
- package/src/add/add-workflow-graph.ts +180 -522
- package/src/add/add-workflow.ts +5 -4
- package/src/error-codes.ts +24 -1
- package/src/index.ts +22 -13
- package/src/inspector.ts +129 -17
- package/src/schema-generator.ts +1 -0
- package/src/types-map.ts +12 -1
- package/src/types.ts +175 -58
- package/src/utils/compute-required-schemas.ts +49 -0
- package/src/utils/contract-hashes.test.ts +528 -0
- package/src/utils/contract-hashes.ts +290 -0
- package/src/utils/custom-types-generator.ts +88 -0
- package/src/utils/detect-schema-vendor.ts +90 -0
- package/src/utils/ensure-function-metadata.ts +324 -7
- package/src/utils/extract-function-name.ts +101 -351
- package/src/utils/extract-services.ts +35 -2
- package/src/utils/filter-inspector-state.test.ts +34 -20
- package/src/utils/filter-inspector-state.ts +140 -31
- package/src/utils/get-property-value.ts +42 -4
- package/src/utils/hash.ts +26 -0
- package/src/utils/middleware.test.ts +204 -0
- package/src/utils/middleware.ts +129 -67
- package/src/utils/permissions.test.ts +35 -12
- package/src/utils/permissions.ts +10 -10
- package/src/utils/post-process.ts +283 -43
- package/src/utils/resolve-external-package.ts +42 -0
- package/src/utils/resolve-function-types.ts +42 -0
- package/src/utils/resolve-identifier.ts +46 -0
- package/src/utils/resolve-versions.test.ts +249 -0
- package/src/utils/resolve-versions.ts +105 -0
- package/src/utils/schema-generator.ts +329 -0
- package/src/utils/serialize-inspector-state.ts +163 -40
- package/src/utils/serialize-mcp-json.ts +145 -0
- package/src/utils/serialize-middleware-groups-meta.ts +33 -0
- package/src/utils/serialize-openapi-json.ts +277 -0
- package/src/utils/serialize-permissions-groups-meta.ts +35 -0
- package/src/utils/test-data/inspector-state.json +69 -66
- package/src/utils/workflow/dsl/deserialize-dsl-workflow.ts +43 -119
- package/src/utils/workflow/dsl/extract-dsl-workflow.ts +24 -4
- package/src/utils/workflow/graph/convert-dsl-to-graph.ts +17 -10
- package/src/utils/workflow/graph/finalize-workflow-wires.ts +310 -0
- package/src/utils/workflow/graph/finalize-workflows.ts +100 -0
- package/src/utils/workflow/graph/index.ts +5 -0
- package/src/utils/workflow/graph/serialize-workflow-graph.ts +1 -8
- package/src/utils/workflow/graph/workflow-graph.types.ts +29 -78
- package/src/visit.ts +12 -6
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/add/add-forge-credential.d.ts +0 -8
- package/dist/add/add-forge-credential.js +0 -77
- package/dist/add/add-forge-node.d.ts +0 -7
- package/dist/add/add-forge-node.js +0 -77
- package/dist/add/add-mcp-tool.d.ts +0 -2
- package/dist/add/add-mcp-tool.js +0 -81
- package/dist/utils/extract-service-metadata.d.ts +0 -19
- package/dist/utils/extract-service-metadata.js +0 -244
- package/dist/utils/write-service-metadata.d.ts +0 -13
- package/dist/utils/write-service-metadata.js +0 -37
- package/src/add/add-forge-credential.ts +0 -119
- package/src/add/add-forge-node.ts +0 -132
- package/src/add/add-mcp-tool.ts +0 -141
- package/src/utils/extract-service-metadata.ts +0 -353
- package/src/utils/write-service-metadata.ts +0 -51
|
@@ -1,256 +1,90 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
2
|
import { ErrorCode } from '../error-codes.js';
|
|
3
3
|
import { extractStringLiteral } from '../utils/extract-node-value.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
else if (httpPropName === 'startNode') {
|
|
30
|
-
httpWire.startNode = extractStringLiteral(httpProp.initializer, checker);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
if (httpWire.route && httpWire.method && httpWire.startNode) {
|
|
34
|
-
wires.http.push(httpWire);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
else if (propName === 'channel' &&
|
|
40
|
-
ts.isArrayLiteralExpression(prop.initializer)) {
|
|
41
|
-
wires.channel = [];
|
|
42
|
-
for (const elem of prop.initializer.elements) {
|
|
43
|
-
if (ts.isObjectLiteralExpression(elem)) {
|
|
44
|
-
const channelWire = {};
|
|
45
|
-
for (const channelProp of elem.properties) {
|
|
46
|
-
if (!ts.isPropertyAssignment(channelProp) ||
|
|
47
|
-
!ts.isIdentifier(channelProp.name))
|
|
48
|
-
continue;
|
|
49
|
-
const channelPropName = channelProp.name.text;
|
|
50
|
-
if (channelPropName === 'name') {
|
|
51
|
-
channelWire.name = extractStringLiteral(channelProp.initializer, checker);
|
|
52
|
-
}
|
|
53
|
-
else if (channelPropName === 'onConnect') {
|
|
54
|
-
channelWire.onConnect = extractStringLiteral(channelProp.initializer, checker);
|
|
55
|
-
}
|
|
56
|
-
else if (channelPropName === 'onDisconnect') {
|
|
57
|
-
channelWire.onDisconnect = extractStringLiteral(channelProp.initializer, checker);
|
|
58
|
-
}
|
|
59
|
-
else if (channelPropName === 'onMessage') {
|
|
60
|
-
channelWire.onMessage = extractStringLiteral(channelProp.initializer, checker);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
if (channelWire.name) {
|
|
64
|
-
wires.channel.push(channelWire);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
else if (propName === 'queue' &&
|
|
70
|
-
ts.isArrayLiteralExpression(prop.initializer)) {
|
|
71
|
-
wires.queue = [];
|
|
72
|
-
for (const elem of prop.initializer.elements) {
|
|
73
|
-
if (ts.isObjectLiteralExpression(elem)) {
|
|
74
|
-
const queueWire = {};
|
|
75
|
-
for (const queueProp of elem.properties) {
|
|
76
|
-
if (!ts.isPropertyAssignment(queueProp) ||
|
|
77
|
-
!ts.isIdentifier(queueProp.name))
|
|
78
|
-
continue;
|
|
79
|
-
const queuePropName = queueProp.name.text;
|
|
80
|
-
if (queuePropName === 'name') {
|
|
81
|
-
queueWire.name = extractStringLiteral(queueProp.initializer, checker);
|
|
82
|
-
}
|
|
83
|
-
else if (queuePropName === 'startNode') {
|
|
84
|
-
queueWire.startNode = extractStringLiteral(queueProp.initializer, checker);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
if (queueWire.name && queueWire.startNode) {
|
|
88
|
-
wires.queue.push(queueWire);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
else if (propName === 'cli' &&
|
|
94
|
-
ts.isArrayLiteralExpression(prop.initializer)) {
|
|
95
|
-
wires.cli = [];
|
|
96
|
-
for (const elem of prop.initializer.elements) {
|
|
97
|
-
if (ts.isObjectLiteralExpression(elem)) {
|
|
98
|
-
const cliWire = {};
|
|
99
|
-
for (const cliProp of elem.properties) {
|
|
100
|
-
if (!ts.isPropertyAssignment(cliProp) ||
|
|
101
|
-
!ts.isIdentifier(cliProp.name))
|
|
102
|
-
continue;
|
|
103
|
-
const cliPropName = cliProp.name.text;
|
|
104
|
-
if (cliPropName === 'command') {
|
|
105
|
-
cliWire.command = extractStringLiteral(cliProp.initializer, checker);
|
|
106
|
-
}
|
|
107
|
-
else if (cliPropName === 'startNode') {
|
|
108
|
-
cliWire.startNode = extractStringLiteral(cliProp.initializer, checker);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
if (cliWire.command && cliWire.startNode) {
|
|
112
|
-
wires.cli.push(cliWire);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
else if (propName === 'mcp' &&
|
|
118
|
-
ts.isObjectLiteralExpression(prop.initializer)) {
|
|
119
|
-
const mcpWires = {};
|
|
120
|
-
for (const mcpProp of prop.initializer.properties) {
|
|
121
|
-
if (!ts.isPropertyAssignment(mcpProp) || !ts.isIdentifier(mcpProp.name))
|
|
122
|
-
continue;
|
|
123
|
-
const mcpPropName = mcpProp.name.text;
|
|
124
|
-
if (mcpPropName === 'tool' &&
|
|
125
|
-
ts.isArrayLiteralExpression(mcpProp.initializer)) {
|
|
126
|
-
mcpWires.tool = extractMcpToolWireArray(mcpProp.initializer, checker);
|
|
127
|
-
}
|
|
128
|
-
else if (mcpPropName === 'prompt' &&
|
|
129
|
-
ts.isArrayLiteralExpression(mcpProp.initializer)) {
|
|
130
|
-
mcpWires.prompt = extractMcpToolWireArray(mcpProp.initializer, checker);
|
|
131
|
-
}
|
|
132
|
-
else if (mcpPropName === 'resource' &&
|
|
133
|
-
ts.isArrayLiteralExpression(mcpProp.initializer)) {
|
|
134
|
-
mcpWires.resource = extractMcpResourceWireArray(mcpProp.initializer, checker);
|
|
135
|
-
}
|
|
4
|
+
function extractAstValue(expr, refParamName, templateParamName) {
|
|
5
|
+
if (ts.isStringLiteral(expr)) {
|
|
6
|
+
return expr.text;
|
|
7
|
+
}
|
|
8
|
+
if (ts.isNumericLiteral(expr)) {
|
|
9
|
+
return Number(expr.text);
|
|
10
|
+
}
|
|
11
|
+
if (expr.kind === ts.SyntaxKind.TrueKeyword) {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
if (expr.kind === ts.SyntaxKind.FalseKeyword) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
if (expr.kind === ts.SyntaxKind.NullKeyword) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
if (ts.isCallExpression(expr)) {
|
|
21
|
+
const callee = expr.expression;
|
|
22
|
+
if (ts.isIdentifier(callee)) {
|
|
23
|
+
if (callee.text === refParamName) {
|
|
24
|
+
const args = expr.arguments;
|
|
25
|
+
const nodeId = args[0] && ts.isStringLiteral(args[0]) ? args[0].text : 'unknown';
|
|
26
|
+
const path = args[1] && ts.isStringLiteral(args[1]) ? args[1].text : undefined;
|
|
27
|
+
return { $ref: nodeId, path };
|
|
136
28
|
}
|
|
137
|
-
if (
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
continue;
|
|
151
|
-
const schedulePropName = scheduleProp.name.text;
|
|
152
|
-
if (schedulePropName === 'cron') {
|
|
153
|
-
scheduleWire.cron = extractStringLiteral(scheduleProp.initializer, checker);
|
|
154
|
-
}
|
|
155
|
-
else if (schedulePropName === 'interval') {
|
|
156
|
-
scheduleWire.interval = extractStringLiteral(scheduleProp.initializer, checker);
|
|
29
|
+
if (templateParamName && callee.text === templateParamName) {
|
|
30
|
+
const templateStr = expr.arguments[0] && ts.isStringLiteral(expr.arguments[0])
|
|
31
|
+
? expr.arguments[0].text
|
|
32
|
+
: '';
|
|
33
|
+
const refsArg = expr.arguments[1];
|
|
34
|
+
const refs = [];
|
|
35
|
+
if (refsArg && ts.isArrayLiteralExpression(refsArg)) {
|
|
36
|
+
for (const el of refsArg.elements) {
|
|
37
|
+
const resolved = extractAstValue(el, refParamName, templateParamName);
|
|
38
|
+
if (typeof resolved === 'object' &&
|
|
39
|
+
resolved !== null &&
|
|
40
|
+
'$ref' in resolved) {
|
|
41
|
+
refs.push(resolved);
|
|
157
42
|
}
|
|
158
|
-
else if (schedulePropName === 'startNode') {
|
|
159
|
-
scheduleWire.startNode = extractStringLiteral(scheduleProp.initializer, checker);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
if ((scheduleWire.cron || scheduleWire.interval) &&
|
|
163
|
-
scheduleWire.startNode) {
|
|
164
|
-
wires.schedule.push(scheduleWire);
|
|
165
43
|
}
|
|
166
44
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
!ts.isIdentifier(triggerProp.name))
|
|
178
|
-
continue;
|
|
179
|
-
const triggerPropName = triggerProp.name.text;
|
|
180
|
-
if (triggerPropName === 'name') {
|
|
181
|
-
triggerWire.name = extractStringLiteral(triggerProp.initializer, checker);
|
|
182
|
-
}
|
|
183
|
-
else if (triggerPropName === 'startNode') {
|
|
184
|
-
triggerWire.startNode = extractStringLiteral(triggerProp.initializer, checker);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
if (triggerWire.name && triggerWire.startNode) {
|
|
188
|
-
wires.trigger.push(triggerWire);
|
|
189
|
-
}
|
|
45
|
+
const parts = [];
|
|
46
|
+
const expressions = [];
|
|
47
|
+
const regex = /\$(\d+)/g;
|
|
48
|
+
let lastIndex = 0;
|
|
49
|
+
let match;
|
|
50
|
+
while ((match = regex.exec(templateStr)) !== null) {
|
|
51
|
+
parts.push(templateStr.slice(lastIndex, match.index));
|
|
52
|
+
const refIndex = parseInt(match[1], 10);
|
|
53
|
+
expressions.push(refs[refIndex] ?? { $ref: 'unknown' });
|
|
54
|
+
lastIndex = regex.lastIndex;
|
|
190
55
|
}
|
|
56
|
+
parts.push(templateStr.slice(lastIndex));
|
|
57
|
+
return { $template: { parts, expressions } };
|
|
191
58
|
}
|
|
192
59
|
}
|
|
193
60
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
name = extractStringLiteral(prop.initializer, checker);
|
|
211
|
-
}
|
|
212
|
-
else if (propName === 'startNode') {
|
|
213
|
-
startNode = extractStringLiteral(prop.initializer, checker);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
if (name && startNode) {
|
|
217
|
-
result.push({ name, startNode });
|
|
218
|
-
}
|
|
61
|
+
if (ts.isArrayLiteralExpression(expr)) {
|
|
62
|
+
return expr.elements.map((el) => extractAstValue(el, refParamName, templateParamName));
|
|
63
|
+
}
|
|
64
|
+
if (ts.isObjectLiteralExpression(expr)) {
|
|
65
|
+
const obj = {};
|
|
66
|
+
for (const prop of expr.properties) {
|
|
67
|
+
if (!ts.isPropertyAssignment(prop))
|
|
68
|
+
continue;
|
|
69
|
+
const key = ts.isIdentifier(prop.name)
|
|
70
|
+
? prop.name.text
|
|
71
|
+
: ts.isStringLiteral(prop.name)
|
|
72
|
+
? prop.name.text
|
|
73
|
+
: null;
|
|
74
|
+
if (!key)
|
|
75
|
+
continue;
|
|
76
|
+
obj[key] = extractAstValue(prop.initializer, refParamName, templateParamName);
|
|
219
77
|
}
|
|
78
|
+
return obj;
|
|
220
79
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
*/
|
|
226
|
-
function extractMcpResourceWireArray(arrayNode, checker) {
|
|
227
|
-
const result = [];
|
|
228
|
-
for (const elem of arrayNode.elements) {
|
|
229
|
-
if (ts.isObjectLiteralExpression(elem)) {
|
|
230
|
-
let uri;
|
|
231
|
-
let startNode;
|
|
232
|
-
for (const prop of elem.properties) {
|
|
233
|
-
if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name))
|
|
234
|
-
continue;
|
|
235
|
-
const propName = prop.name.text;
|
|
236
|
-
if (propName === 'uri') {
|
|
237
|
-
uri = extractStringLiteral(prop.initializer, checker);
|
|
238
|
-
}
|
|
239
|
-
else if (propName === 'startNode') {
|
|
240
|
-
startNode = extractStringLiteral(prop.initializer, checker);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
if (uri && startNode) {
|
|
244
|
-
result.push({ uri, startNode });
|
|
245
|
-
}
|
|
80
|
+
if (ts.isPrefixUnaryExpression(expr)) {
|
|
81
|
+
if (expr.operator === ts.SyntaxKind.MinusToken &&
|
|
82
|
+
ts.isNumericLiteral(expr.operand)) {
|
|
83
|
+
return -Number(expr.operand.text);
|
|
246
84
|
}
|
|
247
85
|
}
|
|
248
|
-
return
|
|
86
|
+
return undefined;
|
|
249
87
|
}
|
|
250
|
-
/**
|
|
251
|
-
* Extract input mapping from an arrow function
|
|
252
|
-
* Parses: (ref) => ({ key: ref('nodeId', 'path'), key2: 'literal' })
|
|
253
|
-
*/
|
|
254
88
|
function extractInputMapping(node, _checker) {
|
|
255
89
|
if (!ts.isArrowFunction(node)) {
|
|
256
90
|
return {};
|
|
@@ -279,6 +113,9 @@ function extractInputMapping(node, _checker) {
|
|
|
279
113
|
const refParamName = node.parameters.length > 0 && ts.isIdentifier(node.parameters[0].name)
|
|
280
114
|
? node.parameters[0].name.text
|
|
281
115
|
: 'ref';
|
|
116
|
+
const templateParamName = node.parameters.length > 1 && ts.isIdentifier(node.parameters[1].name)
|
|
117
|
+
? node.parameters[1].name.text
|
|
118
|
+
: undefined;
|
|
282
119
|
const input = {};
|
|
283
120
|
for (const prop of bodyObj.properties) {
|
|
284
121
|
if (!ts.isPropertyAssignment(prop))
|
|
@@ -290,32 +127,9 @@ function extractInputMapping(node, _checker) {
|
|
|
290
127
|
: null;
|
|
291
128
|
if (!key)
|
|
292
129
|
continue;
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
const args = prop.initializer.arguments;
|
|
297
|
-
const nodeIdArg = args[0];
|
|
298
|
-
const pathArg = args[1];
|
|
299
|
-
const nodeId = nodeIdArg && ts.isStringLiteral(nodeIdArg)
|
|
300
|
-
? nodeIdArg.text
|
|
301
|
-
: 'unknown';
|
|
302
|
-
const path = pathArg && ts.isStringLiteral(pathArg) ? pathArg.text : undefined;
|
|
303
|
-
input[key] = { $ref: nodeId, path };
|
|
304
|
-
continue;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
if (ts.isStringLiteral(prop.initializer)) {
|
|
308
|
-
input[key] = prop.initializer.text;
|
|
309
|
-
}
|
|
310
|
-
else if (ts.isNumericLiteral(prop.initializer)) {
|
|
311
|
-
input[key] = Number(prop.initializer.text);
|
|
312
|
-
}
|
|
313
|
-
else if (prop.initializer.kind === ts.SyntaxKind.TrueKeyword ||
|
|
314
|
-
prop.initializer.kind === ts.SyntaxKind.FalseKeyword) {
|
|
315
|
-
input[key] = prop.initializer.kind === ts.SyntaxKind.TrueKeyword;
|
|
316
|
-
}
|
|
317
|
-
else if (prop.initializer.kind === ts.SyntaxKind.NullKeyword) {
|
|
318
|
-
input[key] = null;
|
|
130
|
+
const value = extractAstValue(prop.initializer, refParamName, templateParamName);
|
|
131
|
+
if (value !== undefined) {
|
|
132
|
+
input[key] = value;
|
|
319
133
|
}
|
|
320
134
|
}
|
|
321
135
|
return input;
|
|
@@ -357,35 +171,6 @@ function extractNextConfig(node, _checker) {
|
|
|
357
171
|
}
|
|
358
172
|
return undefined;
|
|
359
173
|
}
|
|
360
|
-
/**
|
|
361
|
-
* Extract definition object from wireWorkflow call
|
|
362
|
-
*/
|
|
363
|
-
function extractDefinitionObject(firstArg) {
|
|
364
|
-
if (ts.isObjectLiteralExpression(firstArg)) {
|
|
365
|
-
return firstArg;
|
|
366
|
-
}
|
|
367
|
-
if (ts.isArrowFunction(firstArg)) {
|
|
368
|
-
const body = firstArg.body;
|
|
369
|
-
if (ts.isObjectLiteralExpression(body)) {
|
|
370
|
-
return body;
|
|
371
|
-
}
|
|
372
|
-
if (ts.isParenthesizedExpression(body)) {
|
|
373
|
-
if (ts.isObjectLiteralExpression(body.expression)) {
|
|
374
|
-
return body.expression;
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
if (ts.isBlock(body)) {
|
|
378
|
-
for (const stmt of body.statements) {
|
|
379
|
-
if (ts.isReturnStatement(stmt) && stmt.expression) {
|
|
380
|
-
if (ts.isObjectLiteralExpression(stmt.expression)) {
|
|
381
|
-
return stmt.expression;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
return undefined;
|
|
388
|
-
}
|
|
389
174
|
/**
|
|
390
175
|
* Compute entry node IDs from graph nodes
|
|
391
176
|
*/
|
|
@@ -416,77 +201,46 @@ function computeEntryNodeIds(graphNodes) {
|
|
|
416
201
|
return Object.keys(graphNodes).filter((nodeId) => !hasIncomingEdge.has(nodeId));
|
|
417
202
|
}
|
|
418
203
|
/**
|
|
419
|
-
* Extract pikkuWorkflowGraph config from
|
|
420
|
-
* New format: pikkuWorkflowGraph({ nodes: {...}, wires: {...}, config: {...} })
|
|
204
|
+
* Extract pikkuWorkflowGraph config from an object literal argument
|
|
421
205
|
*/
|
|
422
|
-
function
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
? decl.name.text
|
|
436
|
-
: undefined;
|
|
437
|
-
}
|
|
438
|
-
return result;
|
|
439
|
-
}
|
|
440
|
-
}
|
|
206
|
+
function extractWorkflowGraphConfig(configArg, checker) {
|
|
207
|
+
let name;
|
|
208
|
+
let description;
|
|
209
|
+
let tags;
|
|
210
|
+
let disabled;
|
|
211
|
+
let nodesNode;
|
|
212
|
+
let configNode;
|
|
213
|
+
for (const prop of configArg.properties) {
|
|
214
|
+
if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name))
|
|
215
|
+
continue;
|
|
216
|
+
const propName = prop.name.text;
|
|
217
|
+
if (propName === 'name') {
|
|
218
|
+
name = extractStringLiteral(prop.initializer, checker);
|
|
441
219
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
const configArg = node.arguments[0];
|
|
449
|
-
if (configArg && ts.isObjectLiteralExpression(configArg)) {
|
|
450
|
-
let name;
|
|
451
|
-
let description;
|
|
452
|
-
let tags;
|
|
453
|
-
let wires;
|
|
454
|
-
let nodesNode;
|
|
455
|
-
let configNode;
|
|
456
|
-
for (const prop of configArg.properties) {
|
|
457
|
-
if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name))
|
|
458
|
-
continue;
|
|
459
|
-
const propName = prop.name.text;
|
|
460
|
-
if (propName === 'name') {
|
|
461
|
-
name = extractStringLiteral(prop.initializer, checker);
|
|
462
|
-
}
|
|
463
|
-
else if (propName === 'description') {
|
|
464
|
-
description = extractStringLiteral(prop.initializer, checker);
|
|
465
|
-
}
|
|
466
|
-
else if (propName === 'tags' &&
|
|
467
|
-
ts.isArrayLiteralExpression(prop.initializer)) {
|
|
468
|
-
tags = prop.initializer.elements
|
|
469
|
-
.filter(ts.isStringLiteral)
|
|
470
|
-
.map((el) => el.text);
|
|
471
|
-
}
|
|
472
|
-
else if (propName === 'wires' &&
|
|
473
|
-
ts.isObjectLiteralExpression(prop.initializer)) {
|
|
474
|
-
wires = extractWiresConfig(prop.initializer, checker);
|
|
475
|
-
}
|
|
476
|
-
else if (propName === 'nodes' &&
|
|
477
|
-
ts.isObjectLiteralExpression(prop.initializer)) {
|
|
478
|
-
nodesNode = prop.initializer;
|
|
479
|
-
}
|
|
480
|
-
else if (propName === 'config' &&
|
|
481
|
-
ts.isObjectLiteralExpression(prop.initializer)) {
|
|
482
|
-
configNode = prop.initializer;
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
return { name, description, tags, wires, nodesNode, configNode };
|
|
220
|
+
else if (propName === 'description') {
|
|
221
|
+
description = extractStringLiteral(prop.initializer, checker);
|
|
222
|
+
}
|
|
223
|
+
else if (propName === 'disabled') {
|
|
224
|
+
if (prop.initializer.kind === ts.SyntaxKind.TrueKeyword) {
|
|
225
|
+
disabled = true;
|
|
486
226
|
}
|
|
487
227
|
}
|
|
228
|
+
else if (propName === 'tags' &&
|
|
229
|
+
ts.isArrayLiteralExpression(prop.initializer)) {
|
|
230
|
+
tags = prop.initializer.elements
|
|
231
|
+
.filter(ts.isStringLiteral)
|
|
232
|
+
.map((el) => el.text);
|
|
233
|
+
}
|
|
234
|
+
else if (propName === 'nodes' &&
|
|
235
|
+
ts.isObjectLiteralExpression(prop.initializer)) {
|
|
236
|
+
nodesNode = prop.initializer;
|
|
237
|
+
}
|
|
238
|
+
else if (propName === 'config' &&
|
|
239
|
+
ts.isObjectLiteralExpression(prop.initializer)) {
|
|
240
|
+
configNode = prop.initializer;
|
|
241
|
+
}
|
|
488
242
|
}
|
|
489
|
-
return
|
|
243
|
+
return { name, description, tags, disabled, nodesNode, configNode };
|
|
490
244
|
}
|
|
491
245
|
/**
|
|
492
246
|
* Extract graph nodes from the new pikkuWorkflowGraph format
|
|
@@ -513,6 +267,10 @@ function extractGraphFromNewFormat(nodesNode, configNode, checker, state) {
|
|
|
513
267
|
if (rpcName) {
|
|
514
268
|
nodeRpcMap[nodeId] = rpcName;
|
|
515
269
|
state.rpc.invokedFunctions.add(rpcName);
|
|
270
|
+
const funcFile = state.functions.files.get(rpcName);
|
|
271
|
+
if (funcFile && !state.rpc.internalFiles.has(rpcName)) {
|
|
272
|
+
state.rpc.internalFiles.set(rpcName, funcFile);
|
|
273
|
+
}
|
|
516
274
|
}
|
|
517
275
|
}
|
|
518
276
|
// Initialize nodes with their RPC names
|
|
@@ -573,87 +331,66 @@ function extractNodeConfigFromObject(obj, checker) {
|
|
|
573
331
|
return { next, onError, input };
|
|
574
332
|
}
|
|
575
333
|
/**
|
|
576
|
-
* Inspector for
|
|
577
|
-
* Detects:
|
|
334
|
+
* Inspector for pikkuWorkflowGraph() calls
|
|
335
|
+
* Detects: pikkuWorkflowGraph({ nodes: {...}, config: {...} })
|
|
336
|
+
* or: export const x = pikkuWorkflowGraph({...}) where the call is found via variable declaration
|
|
578
337
|
*/
|
|
579
338
|
export const addWorkflowGraph = (logger, node, checker, state) => {
|
|
580
339
|
if (!ts.isCallExpression(node)) {
|
|
581
340
|
return;
|
|
582
341
|
}
|
|
583
342
|
const expression = node.expression;
|
|
584
|
-
if (!ts.isIdentifier(expression) ||
|
|
343
|
+
if (!ts.isIdentifier(expression) ||
|
|
344
|
+
expression.text !== 'pikkuWorkflowGraph') {
|
|
585
345
|
return;
|
|
586
346
|
}
|
|
587
347
|
const args = node.arguments;
|
|
588
348
|
const firstArg = args[0];
|
|
589
349
|
if (!firstArg) {
|
|
590
|
-
logger.critical(ErrorCode.MISSING_FUNC, '
|
|
350
|
+
logger.critical(ErrorCode.MISSING_FUNC, 'pikkuWorkflowGraph requires an argument');
|
|
591
351
|
return;
|
|
592
352
|
}
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
logger.critical(ErrorCode.MISSING_FUNC, 'wireWorkflow requires an object argument');
|
|
596
|
-
return;
|
|
597
|
-
}
|
|
598
|
-
// Check if this is a graph workflow (has 'graph' property)
|
|
599
|
-
let graphPropNode;
|
|
600
|
-
let enabled = true; // Default to true
|
|
601
|
-
for (const prop of definitionObj.properties) {
|
|
602
|
-
if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name))
|
|
603
|
-
continue;
|
|
604
|
-
const propName = prop.name.text;
|
|
605
|
-
if (propName === 'graph') {
|
|
606
|
-
graphPropNode = prop.initializer;
|
|
607
|
-
}
|
|
608
|
-
else if (propName === 'enabled') {
|
|
609
|
-
// Check if enabled is explicitly set to false
|
|
610
|
-
if (prop.initializer.kind === ts.SyntaxKind.FalseKeyword) {
|
|
611
|
-
enabled = false;
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
// Note: We no longer extract wires from wireWorkflow - they come from pikkuWorkflowGraph
|
|
615
|
-
}
|
|
616
|
-
// If no graph property, this is a DSL workflow - skip (handled by add-workflow.ts)
|
|
617
|
-
if (!graphPropNode) {
|
|
353
|
+
if (!ts.isObjectLiteralExpression(firstArg)) {
|
|
354
|
+
logger.critical(ErrorCode.MISSING_FUNC, 'pikkuWorkflowGraph requires an object argument');
|
|
618
355
|
return;
|
|
619
356
|
}
|
|
620
|
-
|
|
621
|
-
const graphConfig = extractPikkuWorkflowGraphConfig(graphPropNode, checker);
|
|
357
|
+
const graphConfig = extractWorkflowGraphConfig(firstArg, checker);
|
|
622
358
|
if (!graphConfig) {
|
|
623
|
-
logger.critical(ErrorCode.MISSING_NAME, '
|
|
359
|
+
logger.critical(ErrorCode.MISSING_NAME, 'pikkuWorkflowGraph: failed to extract config');
|
|
624
360
|
return;
|
|
625
361
|
}
|
|
626
|
-
//
|
|
362
|
+
// Resolve exportedName from variable declaration if this is `export const x = pikkuWorkflowGraph({...})`
|
|
363
|
+
const parent = node.parent;
|
|
364
|
+
if (!graphConfig.exportedName &&
|
|
365
|
+
parent &&
|
|
366
|
+
ts.isVariableDeclaration(parent) &&
|
|
367
|
+
ts.isIdentifier(parent.name)) {
|
|
368
|
+
graphConfig.exportedName = parent.name.text;
|
|
369
|
+
}
|
|
627
370
|
const workflowName = graphConfig.name || graphConfig.exportedName;
|
|
628
371
|
if (!workflowName) {
|
|
629
|
-
logger.critical(ErrorCode.MISSING_NAME, '
|
|
372
|
+
logger.critical(ErrorCode.MISSING_NAME, 'pikkuWorkflowGraph requires a name property or exported variable name');
|
|
630
373
|
return;
|
|
631
374
|
}
|
|
632
|
-
// Extract graph nodes from the new format (nodes + config properties)
|
|
633
375
|
let graphNodes = {};
|
|
634
376
|
if (graphConfig.nodesNode) {
|
|
635
377
|
graphNodes = extractGraphFromNewFormat(graphConfig.nodesNode, graphConfig.configNode, checker, state);
|
|
636
378
|
}
|
|
637
379
|
const entryNodeIds = computeEntryNodeIds(graphNodes);
|
|
638
|
-
// Use wires from pikkuWorkflowGraph (not from wireWorkflow)
|
|
639
|
-
const wires = graphConfig.wires || {};
|
|
640
380
|
const serialized = {
|
|
641
381
|
name: workflowName,
|
|
642
|
-
|
|
382
|
+
pikkuFuncId: workflowName,
|
|
643
383
|
source: 'graph',
|
|
644
384
|
description: graphConfig.description,
|
|
645
385
|
tags: graphConfig.tags,
|
|
646
|
-
wires,
|
|
647
386
|
nodes: graphNodes,
|
|
648
387
|
entryNodeIds,
|
|
649
388
|
};
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
});
|
|
658
|
-
}
|
|
389
|
+
if (graphConfig.disabled)
|
|
390
|
+
return;
|
|
391
|
+
state.workflows.graphMeta[workflowName] = serialized;
|
|
392
|
+
state.workflows.graphFiles.set(workflowName, {
|
|
393
|
+
path: node.getSourceFile().fileName,
|
|
394
|
+
exportedName: graphConfig.exportedName || workflowName,
|
|
395
|
+
});
|
|
659
396
|
};
|