@pikku/inspector 0.12.31 → 0.12.33
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 +36 -0
- package/dist/add/add-functions.js +4 -2
- package/dist/add/add-workflow.d.ts +2 -2
- package/dist/add/add-workflow.js +28 -5
- package/dist/error-codes.d.ts +1 -0
- package/dist/error-codes.js +1 -0
- package/dist/utils/workflow/graph/convert-dsl-to-graph.js +7 -2
- package/dist/utils/workflow/graph/workflow-graph.types.d.ts +2 -1
- package/package.json +2 -2
- package/src/add/add-functions.ts +6 -2
- package/src/add/add-workflow.ts +34 -6
- package/src/error-codes.ts +1 -0
- package/src/utils/workflow/graph/convert-dsl-to-graph.ts +7 -2
- package/src/utils/workflow/graph/workflow-graph.types.ts +2 -1
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,39 @@
|
|
|
1
|
+
## 0.12.33
|
|
2
|
+
|
|
3
|
+
### Patch Changes
|
|
4
|
+
|
|
5
|
+
- 4c17f7e: user flows: actors move onto the workflow wire + `pikku userflow` command
|
|
6
|
+
- Actors are no longer a singleton service: `startWorkflow(..., { actors })`
|
|
7
|
+
registers them per run and they arrive on the wire —
|
|
8
|
+
`func: async ({ logger }, input, { workflow, actors })`.
|
|
9
|
+
- Inspector enforces user flows are pure remote stories (PKU673): a
|
|
10
|
+
pikkuUserFlow func may only destructure `logger`/`config` from services.
|
|
11
|
+
- New `pikku userflow run <environment> [--flows a,b] [--tags x,y]` runs flows
|
|
12
|
+
against `userFlows.environments` from pikku.config.json (secret from
|
|
13
|
+
USER_FLOW_ACTOR_SECRET env), refusing internal (non-actor) steps so runs
|
|
14
|
+
against staging/production never touch local services; non-zero exit on
|
|
15
|
+
failure. `pikku userflow list` prints names, descriptions and tags.
|
|
16
|
+
- Workflow meta now carries `title` (parity with HTTP routes/functions).
|
|
17
|
+
|
|
18
|
+
- Updated dependencies [4c17f7e]
|
|
19
|
+
- @pikku/core@0.12.49
|
|
20
|
+
|
|
21
|
+
## 0.12.32
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- 8dfddc3: pikkuUserFlow: user flows as workflows. A complex workflow whose steps can run
|
|
26
|
+
as actors over the real transport — `workflow.do(step, rpc, data, { actor:
|
|
27
|
+
actors.yasser })` — plus `workflow.expectEventually(...)` for polling async
|
|
28
|
+
effects. Actor steps never queue and never dispatch internally, so auth
|
|
29
|
+
middleware/permissions are exercised end-to-end; flows double as e2e tests and
|
|
30
|
+
staged/production health checks. Ships UserFlowActor types +
|
|
31
|
+
createHttpUserFlowActors (lazy sign-in via `/auth/sign-in/actor` with a
|
|
32
|
+
server-held secret), inspector source `'user-flow'`, and a console badge.
|
|
33
|
+
- Updated dependencies [5f2c566]
|
|
34
|
+
- Updated dependencies [8dfddc3]
|
|
35
|
+
- @pikku/core@0.12.48
|
|
36
|
+
|
|
1
37
|
## 0.12.31
|
|
2
38
|
|
|
3
39
|
### Patch Changes
|
|
@@ -250,9 +250,11 @@ export const addFunctions = (logger, node, checker, state, options) => {
|
|
|
250
250
|
if (!ts.isIdentifier(expression)) {
|
|
251
251
|
return;
|
|
252
252
|
}
|
|
253
|
-
// Match identifiers that contain both "pikku" and "func" (case insensitive)
|
|
253
|
+
// Match identifiers that contain both "pikku" and "func" (case insensitive),
|
|
254
|
+
// plus pikkuUserFlow (a workflow wrapper without "func" in its name)
|
|
254
255
|
const pikkuFuncPattern = /pikku.*func/i;
|
|
255
|
-
if (!pikkuFuncPattern.test(expression.text)
|
|
256
|
+
if (!pikkuFuncPattern.test(expression.text) &&
|
|
257
|
+
expression.text !== 'pikkuUserFlow') {
|
|
256
258
|
return;
|
|
257
259
|
}
|
|
258
260
|
// only handle calls like pikkuFunc(...)
|
|
@@ -5,7 +5,7 @@ import type { WorkflowStepMeta } from '@pikku/core/workflow';
|
|
|
5
5
|
*/
|
|
6
6
|
export declare function collectInvokedRPCs(steps: WorkflowStepMeta[], rpcs: Set<string>): void;
|
|
7
7
|
/**
|
|
8
|
-
* Inspector for pikkuWorkflowFunc()
|
|
9
|
-
* Detects workflow registration and extracts metadata
|
|
8
|
+
* Inspector for pikkuWorkflowFunc(), pikkuWorkflowComplexFunc() and
|
|
9
|
+
* pikkuUserFlow() calls. Detects workflow registration and extracts metadata.
|
|
10
10
|
*/
|
|
11
11
|
export declare const addWorkflow: AddWiring;
|
package/dist/add/add-workflow.js
CHANGED
|
@@ -156,8 +156,8 @@ function getWorkflowInvocations(node, checker, state, workflowName, steps) {
|
|
|
156
156
|
});
|
|
157
157
|
}
|
|
158
158
|
/**
|
|
159
|
-
* Inspector for pikkuWorkflowFunc()
|
|
160
|
-
* Detects workflow registration and extracts metadata
|
|
159
|
+
* Inspector for pikkuWorkflowFunc(), pikkuWorkflowComplexFunc() and
|
|
160
|
+
* pikkuUserFlow() calls. Detects workflow registration and extracts metadata.
|
|
161
161
|
*/
|
|
162
162
|
export const addWorkflow = (logger, node, checker, state) => {
|
|
163
163
|
if (!ts.isCallExpression(node)) {
|
|
@@ -176,6 +176,11 @@ export const addWorkflow = (logger, node, checker, state) => {
|
|
|
176
176
|
else if (expression.text === 'pikkuWorkflowComplexFunc') {
|
|
177
177
|
wrapperType = 'complex';
|
|
178
178
|
}
|
|
179
|
+
else if (expression.text === 'pikkuUserFlow') {
|
|
180
|
+
// A user flow is a complex workflow whose steps run as actors over the
|
|
181
|
+
// real transport — same extraction rules as complex, distinct meta.
|
|
182
|
+
wrapperType = 'user-flow';
|
|
183
|
+
}
|
|
179
184
|
else {
|
|
180
185
|
return;
|
|
181
186
|
}
|
|
@@ -193,6 +198,7 @@ export const addWorkflow = (logger, node, checker, state) => {
|
|
|
193
198
|
const { funcNode, resolvedFunc } = extractFunctionNode(firstArg, checker);
|
|
194
199
|
// Extract metadata if using object form
|
|
195
200
|
let tags;
|
|
201
|
+
let title;
|
|
196
202
|
let summary;
|
|
197
203
|
let description;
|
|
198
204
|
let errors;
|
|
@@ -202,6 +208,7 @@ export const addWorkflow = (logger, node, checker, state) => {
|
|
|
202
208
|
if (metadata.disabled)
|
|
203
209
|
return;
|
|
204
210
|
tags = metadata.tags;
|
|
211
|
+
title = metadata.title;
|
|
205
212
|
summary = metadata.summary;
|
|
206
213
|
description = metadata.description;
|
|
207
214
|
errors = metadata.errors;
|
|
@@ -230,7 +237,7 @@ export const addWorkflow = (logger, node, checker, state) => {
|
|
|
230
237
|
// Try DSL workflow extraction first
|
|
231
238
|
// Pass the whole CallExpression node so findWorkflowFunction can find the arrow function
|
|
232
239
|
const result = extractDSLWorkflow(node, checker, {
|
|
233
|
-
allowInline: wrapperType
|
|
240
|
+
allowInline: wrapperType !== 'dsl',
|
|
234
241
|
});
|
|
235
242
|
if (result.status === 'ok' && result.steps) {
|
|
236
243
|
// Extraction succeeded
|
|
@@ -275,7 +282,7 @@ export const addWorkflow = (logger, node, checker, state) => {
|
|
|
275
282
|
// For pikkuWorkflowComplexFunc, also run basic extraction so RPCs in
|
|
276
283
|
// patterns the DSL extractor doesn't handle (array+push, nested Promise.all
|
|
277
284
|
// with identifier args, etc.) are still registered as invoked functions.
|
|
278
|
-
if (wrapperType
|
|
285
|
+
if (wrapperType !== 'dsl') {
|
|
279
286
|
getWorkflowInvocations(resolvedFunc, checker, state, workflowName, steps);
|
|
280
287
|
}
|
|
281
288
|
state.workflows.meta[workflowName] = {
|
|
@@ -284,15 +291,31 @@ export const addWorkflow = (logger, node, checker, state) => {
|
|
|
284
291
|
steps,
|
|
285
292
|
context,
|
|
286
293
|
dsl,
|
|
294
|
+
title,
|
|
287
295
|
summary,
|
|
288
296
|
description,
|
|
289
297
|
errors,
|
|
290
298
|
tags,
|
|
291
299
|
expose,
|
|
300
|
+
userFlow: wrapperType === 'user-flow' ? true : undefined,
|
|
292
301
|
};
|
|
302
|
+
// User flows are pure stories of remote RPCs (same rule as client-side CLI
|
|
303
|
+
// renderers): the func may only destructure logger/config — everything else
|
|
304
|
+
// must go through actor steps so the flow runs against the TARGET
|
|
305
|
+
// environment, never local services.
|
|
306
|
+
const funcMeta = state.functions.meta[pikkuFuncId];
|
|
307
|
+
if (wrapperType === 'user-flow' && funcMeta?.services) {
|
|
308
|
+
const disallowed = funcMeta.services.services.filter((svc) => svc !== 'logger' && svc !== 'config');
|
|
309
|
+
if (disallowed.length > 0) {
|
|
310
|
+
logger.critical(ErrorCode.USER_FLOW_HAS_SERVICES, `User flow '${workflowName}' destructures services: ${disallowed.join(', ')}. ` +
|
|
311
|
+
`User flows may only use 'logger'/'config' — drive everything else through ` +
|
|
312
|
+
`actor steps (workflow.do(step, rpc, data, { actor: actors.x })) so the flow ` +
|
|
313
|
+
`runs against the target environment.`);
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
293
317
|
// Workflow functions require platform services that aren't visible
|
|
294
318
|
// through parameter destructuring (they're accessed via workflow.do/sleep)
|
|
295
|
-
const funcMeta = state.functions.meta[pikkuFuncId];
|
|
296
319
|
if (funcMeta?.services) {
|
|
297
320
|
for (const svc of [
|
|
298
321
|
'workflowService',
|
package/dist/error-codes.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export declare enum ErrorCode {
|
|
|
19
19
|
MISSING_QUEUE_NAME = "PKU384",
|
|
20
20
|
MISSING_CHANNEL_NAME = "PKU400",
|
|
21
21
|
CLI_CLIENTSIDE_RENDERER_HAS_SERVICES = "PKU672",
|
|
22
|
+
USER_FLOW_HAS_SERVICES = "PKU673",
|
|
22
23
|
DYNAMIC_STEP_NAME = "PKU529",
|
|
23
24
|
WORKFLOW_ORCHESTRATOR_NOT_CONFIGURED = "PKU600",
|
|
24
25
|
INVALID_DSL_WORKFLOW = "PKU641",
|
package/dist/error-codes.js
CHANGED
|
@@ -21,6 +21,7 @@ export var ErrorCode;
|
|
|
21
21
|
ErrorCode["MISSING_QUEUE_NAME"] = "PKU384";
|
|
22
22
|
ErrorCode["MISSING_CHANNEL_NAME"] = "PKU400";
|
|
23
23
|
ErrorCode["CLI_CLIENTSIDE_RENDERER_HAS_SERVICES"] = "PKU672";
|
|
24
|
+
ErrorCode["USER_FLOW_HAS_SERVICES"] = "PKU673";
|
|
24
25
|
ErrorCode["DYNAMIC_STEP_NAME"] = "PKU529";
|
|
25
26
|
ErrorCode["WORKFLOW_ORCHESTRATOR_NOT_CONFIGURED"] = "PKU600";
|
|
26
27
|
ErrorCode["INVALID_DSL_WORKFLOW"] = "PKU641";
|
|
@@ -291,10 +291,15 @@ export function convertDslToGraph(workflowName, meta) {
|
|
|
291
291
|
nodesRecord[node.nodeId] = node;
|
|
292
292
|
}
|
|
293
293
|
const entryNodeIds = nodes.length > 0 ? [nodes[0].nodeId] : [];
|
|
294
|
-
// Determine source type
|
|
294
|
+
// Determine source type:
|
|
295
|
+
// - userFlow: complex workflow whose steps run as actors (user flow)
|
|
295
296
|
// - dsl === true: pure DSL workflow, can be serialized
|
|
296
297
|
// - dsl === false: complex workflow with inline steps, not serializable
|
|
297
|
-
const source = meta.
|
|
298
|
+
const source = meta.userFlow
|
|
299
|
+
? 'user-flow'
|
|
300
|
+
: meta.dsl === false
|
|
301
|
+
? 'complex'
|
|
302
|
+
: 'dsl';
|
|
298
303
|
return {
|
|
299
304
|
name: workflowName,
|
|
300
305
|
pikkuFuncId: meta.pikkuFuncId,
|
|
@@ -123,8 +123,9 @@ export declare const isFlowNode: (node: SerializedGraphNode) => node is FlowNode
|
|
|
123
123
|
* - 'dsl': Pure DSL workflow (pikkuWorkflowFunc) - can be round-tripped to code
|
|
124
124
|
* - 'complex': Complex workflow (pikkuWorkflowComplexFunc) - contains inline steps, not serializable
|
|
125
125
|
* - 'graph': Graph-based workflow (pikkuWorkflowGraph)
|
|
126
|
+
* - 'user-flow': User flow (pikkuUserFlow) - complex workflow whose steps run as actors
|
|
126
127
|
*/
|
|
127
|
-
export type WorkflowSourceType = 'dsl' | 'complex' | 'graph';
|
|
128
|
+
export type WorkflowSourceType = 'dsl' | 'complex' | 'graph' | 'user-flow';
|
|
128
129
|
/**
|
|
129
130
|
* Serialized workflow graph - the canonical JSON format
|
|
130
131
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pikku/inspector",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.33",
|
|
4
4
|
"author": "yasser.fadl@gmail.com",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"type": "module",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@openapi-contrib/json-schema-to-openapi-schema": "^4.3.1",
|
|
38
|
-
"@pikku/core": "^0.12.
|
|
38
|
+
"@pikku/core": "^0.12.49",
|
|
39
39
|
"openapi-types": "^12.1.3",
|
|
40
40
|
"path-to-regexp": "^8.3.0",
|
|
41
41
|
"ts-json-schema-generator": "2.9.1-next.16",
|
package/src/add/add-functions.ts
CHANGED
|
@@ -357,9 +357,13 @@ export const addFunctions: AddWiring = (
|
|
|
357
357
|
return
|
|
358
358
|
}
|
|
359
359
|
|
|
360
|
-
// Match identifiers that contain both "pikku" and "func" (case insensitive)
|
|
360
|
+
// Match identifiers that contain both "pikku" and "func" (case insensitive),
|
|
361
|
+
// plus pikkuUserFlow (a workflow wrapper without "func" in its name)
|
|
361
362
|
const pikkuFuncPattern = /pikku.*func/i
|
|
362
|
-
if (
|
|
363
|
+
if (
|
|
364
|
+
!pikkuFuncPattern.test(expression.text) &&
|
|
365
|
+
expression.text !== 'pikkuUserFlow'
|
|
366
|
+
) {
|
|
363
367
|
return
|
|
364
368
|
}
|
|
365
369
|
|
package/src/add/add-workflow.ts
CHANGED
|
@@ -169,8 +169,8 @@ function getWorkflowInvocations(
|
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
/**
|
|
172
|
-
* Inspector for pikkuWorkflowFunc()
|
|
173
|
-
* Detects workflow registration and extracts metadata
|
|
172
|
+
* Inspector for pikkuWorkflowFunc(), pikkuWorkflowComplexFunc() and
|
|
173
|
+
* pikkuUserFlow() calls. Detects workflow registration and extracts metadata.
|
|
174
174
|
*/
|
|
175
175
|
export const addWorkflow: AddWiring = (logger, node, checker, state) => {
|
|
176
176
|
if (!ts.isCallExpression(node)) {
|
|
@@ -185,11 +185,15 @@ export const addWorkflow: AddWiring = (logger, node, checker, state) => {
|
|
|
185
185
|
return
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
let wrapperType: 'dsl' | 'complex' | null = null
|
|
188
|
+
let wrapperType: 'dsl' | 'complex' | 'user-flow' | null = null
|
|
189
189
|
if (expression.text === 'pikkuWorkflowFunc') {
|
|
190
190
|
wrapperType = 'dsl'
|
|
191
191
|
} else if (expression.text === 'pikkuWorkflowComplexFunc') {
|
|
192
192
|
wrapperType = 'complex'
|
|
193
|
+
} else if (expression.text === 'pikkuUserFlow') {
|
|
194
|
+
// A user flow is a complex workflow whose steps run as actors over the
|
|
195
|
+
// real transport — same extraction rules as complex, distinct meta.
|
|
196
|
+
wrapperType = 'user-flow'
|
|
193
197
|
} else {
|
|
194
198
|
return
|
|
195
199
|
}
|
|
@@ -220,6 +224,7 @@ export const addWorkflow: AddWiring = (logger, node, checker, state) => {
|
|
|
220
224
|
|
|
221
225
|
// Extract metadata if using object form
|
|
222
226
|
let tags: string[] | undefined
|
|
227
|
+
let title: string | undefined
|
|
223
228
|
let summary: string | undefined
|
|
224
229
|
let description: string | undefined
|
|
225
230
|
let errors: string[] | undefined
|
|
@@ -235,6 +240,7 @@ export const addWorkflow: AddWiring = (logger, node, checker, state) => {
|
|
|
235
240
|
)
|
|
236
241
|
if (metadata.disabled) return
|
|
237
242
|
tags = metadata.tags
|
|
243
|
+
title = metadata.title
|
|
238
244
|
summary = metadata.summary
|
|
239
245
|
description = metadata.description
|
|
240
246
|
errors = metadata.errors
|
|
@@ -277,7 +283,7 @@ export const addWorkflow: AddWiring = (logger, node, checker, state) => {
|
|
|
277
283
|
// Try DSL workflow extraction first
|
|
278
284
|
// Pass the whole CallExpression node so findWorkflowFunction can find the arrow function
|
|
279
285
|
const result = extractDSLWorkflow(node, checker, {
|
|
280
|
-
allowInline: wrapperType
|
|
286
|
+
allowInline: wrapperType !== 'dsl',
|
|
281
287
|
})
|
|
282
288
|
|
|
283
289
|
if (result.status === 'ok' && result.steps) {
|
|
@@ -331,7 +337,7 @@ export const addWorkflow: AddWiring = (logger, node, checker, state) => {
|
|
|
331
337
|
// For pikkuWorkflowComplexFunc, also run basic extraction so RPCs in
|
|
332
338
|
// patterns the DSL extractor doesn't handle (array+push, nested Promise.all
|
|
333
339
|
// with identifier args, etc.) are still registered as invoked functions.
|
|
334
|
-
if (wrapperType
|
|
340
|
+
if (wrapperType !== 'dsl') {
|
|
335
341
|
getWorkflowInvocations(resolvedFunc, checker, state, workflowName, steps)
|
|
336
342
|
}
|
|
337
343
|
|
|
@@ -341,16 +347,38 @@ export const addWorkflow: AddWiring = (logger, node, checker, state) => {
|
|
|
341
347
|
steps,
|
|
342
348
|
context,
|
|
343
349
|
dsl,
|
|
350
|
+
title,
|
|
344
351
|
summary,
|
|
345
352
|
description,
|
|
346
353
|
errors,
|
|
347
354
|
tags,
|
|
348
355
|
expose,
|
|
356
|
+
userFlow: wrapperType === 'user-flow' ? true : undefined,
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// User flows are pure stories of remote RPCs (same rule as client-side CLI
|
|
360
|
+
// renderers): the func may only destructure logger/config — everything else
|
|
361
|
+
// must go through actor steps so the flow runs against the TARGET
|
|
362
|
+
// environment, never local services.
|
|
363
|
+
const funcMeta = state.functions.meta[pikkuFuncId]
|
|
364
|
+
if (wrapperType === 'user-flow' && funcMeta?.services) {
|
|
365
|
+
const disallowed = funcMeta.services.services.filter(
|
|
366
|
+
(svc) => svc !== 'logger' && svc !== 'config'
|
|
367
|
+
)
|
|
368
|
+
if (disallowed.length > 0) {
|
|
369
|
+
logger.critical(
|
|
370
|
+
ErrorCode.USER_FLOW_HAS_SERVICES,
|
|
371
|
+
`User flow '${workflowName}' destructures services: ${disallowed.join(', ')}. ` +
|
|
372
|
+
`User flows may only use 'logger'/'config' — drive everything else through ` +
|
|
373
|
+
`actor steps (workflow.do(step, rpc, data, { actor: actors.x })) so the flow ` +
|
|
374
|
+
`runs against the target environment.`
|
|
375
|
+
)
|
|
376
|
+
return
|
|
377
|
+
}
|
|
349
378
|
}
|
|
350
379
|
|
|
351
380
|
// Workflow functions require platform services that aren't visible
|
|
352
381
|
// through parameter destructuring (they're accessed via workflow.do/sleep)
|
|
353
|
-
const funcMeta = state.functions.meta[pikkuFuncId]
|
|
354
382
|
if (funcMeta?.services) {
|
|
355
383
|
for (const svc of [
|
|
356
384
|
'workflowService',
|
package/src/error-codes.ts
CHANGED
|
@@ -21,6 +21,7 @@ export enum ErrorCode {
|
|
|
21
21
|
MISSING_QUEUE_NAME = 'PKU384',
|
|
22
22
|
MISSING_CHANNEL_NAME = 'PKU400',
|
|
23
23
|
CLI_CLIENTSIDE_RENDERER_HAS_SERVICES = 'PKU672',
|
|
24
|
+
USER_FLOW_HAS_SERVICES = 'PKU673',
|
|
24
25
|
DYNAMIC_STEP_NAME = 'PKU529',
|
|
25
26
|
WORKFLOW_ORCHESTRATOR_NOT_CONFIGURED = 'PKU600',
|
|
26
27
|
INVALID_DSL_WORKFLOW = 'PKU641',
|
|
@@ -389,10 +389,15 @@ export function convertDslToGraph(
|
|
|
389
389
|
|
|
390
390
|
const entryNodeIds = nodes.length > 0 ? [nodes[0].nodeId] : []
|
|
391
391
|
|
|
392
|
-
// Determine source type
|
|
392
|
+
// Determine source type:
|
|
393
|
+
// - userFlow: complex workflow whose steps run as actors (user flow)
|
|
393
394
|
// - dsl === true: pure DSL workflow, can be serialized
|
|
394
395
|
// - dsl === false: complex workflow with inline steps, not serializable
|
|
395
|
-
const source = meta.
|
|
396
|
+
const source = meta.userFlow
|
|
397
|
+
? 'user-flow'
|
|
398
|
+
: meta.dsl === false
|
|
399
|
+
? 'complex'
|
|
400
|
+
: 'dsl'
|
|
396
401
|
|
|
397
402
|
return {
|
|
398
403
|
name: workflowName,
|
|
@@ -177,8 +177,9 @@ export const isFlowNode = (node: SerializedGraphNode): node is FlowNode =>
|
|
|
177
177
|
* - 'dsl': Pure DSL workflow (pikkuWorkflowFunc) - can be round-tripped to code
|
|
178
178
|
* - 'complex': Complex workflow (pikkuWorkflowComplexFunc) - contains inline steps, not serializable
|
|
179
179
|
* - 'graph': Graph-based workflow (pikkuWorkflowGraph)
|
|
180
|
+
* - 'user-flow': User flow (pikkuUserFlow) - complex workflow whose steps run as actors
|
|
180
181
|
*/
|
|
181
|
-
export type WorkflowSourceType = 'dsl' | 'complex' | 'graph'
|
|
182
|
+
export type WorkflowSourceType = 'dsl' | 'complex' | 'graph' | 'user-flow'
|
|
182
183
|
|
|
183
184
|
/**
|
|
184
185
|
* Serialized workflow graph - the canonical JSON format
|