@nocobase/plugin-workflow 2.1.0-beta.6 → 2.1.0-beta.8

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.
@@ -34,15 +34,69 @@ var swagger_default = {
34
34
  info: {
35
35
  title: "NocoBase API - Workflow plugin"
36
36
  },
37
- tags: [],
37
+ tags: [
38
+ { name: "workflows", description: "Workflow management: CRUD, versioning, sync, manual execution" },
39
+ { name: "workflows.nodes", description: "Create nodes inside a workflow (association resource)" },
40
+ { name: "flow_nodes", description: "Flow node management: update, delete, move, duplicate, test" },
41
+ { name: "executions", description: "Execution record management: list, get, cancel, delete" },
42
+ { name: "jobs", description: "Node job management: list, get, resume" },
43
+ { name: "userWorkflowTasks", description: "Current-user workflow task queries" }
44
+ ],
38
45
  paths: {
46
+ // ─────────────────────────────────────────────────────────────────────────
47
+ // workflows
48
+ // ─────────────────────────────────────────────────────────────────────────
39
49
  "/workflows:list": {
40
50
  get: {
41
51
  tags: ["workflows"],
42
- description: "",
52
+ summary: "List workflows",
53
+ description: [
54
+ "Get paginated list of workflows.",
55
+ "",
56
+ "Tip: filter by `current: true` to retrieve only the active version of each workflow.",
57
+ "",
58
+ "Example:",
59
+ "```",
60
+ 'GET /api/workflows:list?filter={"current":true}&sort=-createdAt&except[]=config',
61
+ "```"
62
+ ].join("\n"),
43
63
  parameters: [
64
+ { $ref: "#/components/schemas/workflow/filter" },
44
65
  {
45
- $ref: "#/components/schemas/workflow/filter"
66
+ name: "sort",
67
+ in: "query",
68
+ description: "Sort fields. Prefix with `-` for descending. e.g. `-createdAt`",
69
+ schema: { type: "string" }
70
+ },
71
+ {
72
+ name: "fields",
73
+ in: "query",
74
+ description: "Return only specified fields",
75
+ schema: { type: "array", items: { type: "string" } }
76
+ },
77
+ {
78
+ name: "except",
79
+ in: "query",
80
+ description: "Exclude specified fields from response (e.g. `config` to reduce payload)",
81
+ schema: { type: "array", items: { type: "string" } }
82
+ },
83
+ {
84
+ name: "appends",
85
+ in: "query",
86
+ description: "Append association data (e.g. `stats`, `versionStats`)",
87
+ schema: { type: "array", items: { type: "string" } }
88
+ },
89
+ {
90
+ name: "page",
91
+ in: "query",
92
+ description: "Page number (1-based)",
93
+ schema: { type: "integer", default: 1 }
94
+ },
95
+ {
96
+ name: "pageSize",
97
+ in: "query",
98
+ description: "Number of items per page",
99
+ schema: { type: "integer", default: 20 }
46
100
  }
47
101
  ],
48
102
  responses: {
@@ -52,9 +106,7 @@ var swagger_default = {
52
106
  "application/json": {
53
107
  schema: {
54
108
  type: "array",
55
- items: {
56
- $ref: "#/components/schemas/workflow/model"
57
- }
109
+ items: { $ref: "#/components/schemas/workflow/model" }
58
110
  }
59
111
  }
60
112
  }
@@ -65,13 +117,29 @@ var swagger_default = {
65
117
  "/workflows:get": {
66
118
  get: {
67
119
  tags: ["workflows"],
68
- description: "Get single workflow",
120
+ summary: "Get single workflow",
121
+ description: [
122
+ "Get details of a single workflow. Use `appends` to include nodes and statistics.",
123
+ "",
124
+ "Example:",
125
+ "```",
126
+ "GET /api/workflows:get?filterByTk=1&appends[]=nodes&appends[]=versionStats",
127
+ "```"
128
+ ].join("\n"),
69
129
  parameters: [
130
+ { $ref: "#/components/schemas/workflow/filterByTk" },
131
+ { $ref: "#/components/schemas/workflow/filter" },
70
132
  {
71
- $ref: "#/components/schemas/workflow/filterByTk"
133
+ name: "appends",
134
+ in: "query",
135
+ description: "Append associations: `nodes`, `stats`, `versionStats`, `executions`",
136
+ schema: { type: "array", items: { type: "string" } }
72
137
  },
73
138
  {
74
- $ref: "#/components/schemas/workflow/filter"
139
+ name: "except",
140
+ in: "query",
141
+ description: "Exclude fields from response",
142
+ schema: { type: "array", items: { type: "string" } }
75
143
  }
76
144
  ],
77
145
  responses: {
@@ -81,17 +149,13 @@ var swagger_default = {
81
149
  "application/json": {
82
150
  schema: {
83
151
  allOf: [
84
- {
85
- $ref: "#/components/schemas/workflow/model"
86
- },
152
+ { $ref: "#/components/schemas/workflow/model" },
87
153
  {
88
154
  type: "object",
89
155
  properties: {
90
156
  nodes: {
91
157
  type: "array",
92
- items: {
93
- $ref: "#/components/schemas/node"
94
- }
158
+ items: { $ref: "#/components/schemas/node" }
95
159
  }
96
160
  }
97
161
  }
@@ -106,23 +170,29 @@ var swagger_default = {
106
170
  "/workflows:create": {
107
171
  post: {
108
172
  tags: ["workflows"],
109
- description: "Create new workflow",
173
+ summary: "Create new workflow",
174
+ description: [
175
+ "Create a new workflow. The `type` (trigger type) must be specified at creation time.",
176
+ "",
177
+ "Note: `sync` mode (synchronous/asynchronous execution) **cannot be changed after creation**."
178
+ ].join("\n"),
110
179
  parameters: [],
111
180
  requestBody: {
112
181
  content: {
113
182
  "application/json": {
114
183
  schema: {
115
184
  type: "object",
185
+ required: ["title", "type"],
116
186
  properties: {
117
- title: {
118
- $ref: "#/components/schemas/workflow/model/properties/title"
119
- },
120
- type: {
121
- $ref: "#/components/schemas/workflow/model/properties/type"
122
- },
123
- description: {
124
- $ref: "#/components/schemas/workflow/model/properties/description"
125
- }
187
+ title: { $ref: "#/components/schemas/workflow/model/properties/title" },
188
+ type: { $ref: "#/components/schemas/workflow/model/properties/type" },
189
+ description: { $ref: "#/components/schemas/workflow/model/properties/description" },
190
+ enabled: { $ref: "#/components/schemas/workflow/model/properties/enabled" },
191
+ sync: { $ref: "#/components/schemas/workflow/model/properties/sync" },
192
+ triggerTitle: { $ref: "#/components/schemas/workflow/model/properties/triggerTitle" },
193
+ config: { $ref: "#/components/schemas/workflow/model/properties/config" },
194
+ options: { $ref: "#/components/schemas/workflow/model/properties/options" },
195
+ categories: { $ref: "#/components/schemas/workflow/model/properties/categories" }
126
196
  }
127
197
  }
128
198
  }
@@ -133,13 +203,7 @@ var swagger_default = {
133
203
  description: "OK",
134
204
  content: {
135
205
  "application/json": {
136
- schema: {
137
- allOf: [
138
- {
139
- $ref: "#/components/schemas/workflow"
140
- }
141
- ]
142
- }
206
+ schema: { $ref: "#/components/schemas/workflow/model" }
143
207
  }
144
208
  }
145
209
  }
@@ -149,34 +213,38 @@ var swagger_default = {
149
213
  "/workflows:update": {
150
214
  post: {
151
215
  tags: ["workflows"],
152
- description: "Update a workflow",
153
- parameters: [],
216
+ summary: "Update a workflow",
217
+ description: [
218
+ "Update workflow properties.",
219
+ "",
220
+ "Allowed fields (server-side whitelist): `title`, `description`, `enabled`, `triggerTitle`, `config`, `options`, `categories`.",
221
+ "",
222
+ "**Constraint:** `config` (trigger configuration) cannot be updated if the workflow version",
223
+ "has already been executed (`versionStats.executed > 0`). Create a new revision instead."
224
+ ].join("\n"),
225
+ parameters: [{ $ref: "#/components/schemas/workflow/filterByTk" }],
154
226
  requestBody: {
155
227
  content: {
156
228
  "application/json": {
157
229
  schema: {
158
230
  type: "object",
159
231
  properties: {
160
- title: {
161
- $ref: "#/components/schemas/workflow/model/properties/title"
162
- },
163
- enabled: {
164
- $ref: "#/components/schemas/workflow/model/properties/enabled"
165
- },
166
- description: {
167
- $ref: "#/components/schemas/workflow/model/properties/description"
168
- },
169
- config: {
170
- $ref: "#/components/schemas/workflow/model/properties/config"
171
- }
232
+ title: { $ref: "#/components/schemas/workflow/model/properties/title" },
233
+ enabled: { $ref: "#/components/schemas/workflow/model/properties/enabled" },
234
+ description: { $ref: "#/components/schemas/workflow/model/properties/description" },
235
+ triggerTitle: { $ref: "#/components/schemas/workflow/model/properties/triggerTitle" },
236
+ config: { $ref: "#/components/schemas/workflow/model/properties/config" },
237
+ options: { $ref: "#/components/schemas/workflow/model/properties/options" },
238
+ categories: { $ref: "#/components/schemas/workflow/model/properties/categories" }
172
239
  }
173
240
  }
174
241
  }
175
242
  }
176
243
  },
177
244
  responses: {
178
- 200: {
179
- description: "OK"
245
+ 200: { description: "OK" },
246
+ 400: {
247
+ description: "Bad Request. `config` cannot be updated when the workflow version has already been executed."
180
248
  }
181
249
  }
182
250
  }
@@ -184,122 +252,258 @@ var swagger_default = {
184
252
  "/workflows:destroy": {
185
253
  post: {
186
254
  tags: ["workflows"],
187
- description: "Delete workflows. Also will delete all nodes and executions of the workflow.",
255
+ summary: "Delete workflows",
256
+ description: [
257
+ "Delete one or more workflows, along with all their nodes and execution records.",
258
+ "",
259
+ "- If `filterByTk` targets a **current** (latest) version, **all other revisions** sharing",
260
+ " the same `key` are also deleted automatically.",
261
+ "- If `filter.key` is provided, all versions sharing that key are deleted."
262
+ ].join("\n"),
188
263
  parameters: [
189
264
  {
190
265
  name: "filterByTk",
191
266
  in: "query",
192
- description: "Primary key of a record",
193
- schema: {
194
- type: "integer",
195
- description: "ID. The only workflow with ID will be deleted."
196
- }
267
+ description: "ID of the workflow to delete",
268
+ schema: { type: "integer" }
197
269
  },
198
270
  {
199
271
  name: "filter",
200
272
  in: "query",
201
- description: "Filter",
273
+ description: "Filter to select workflows for deletion",
202
274
  schema: {
203
275
  type: "object",
204
276
  properties: {
205
277
  key: {
206
278
  type: "string",
207
- description: "Key. If provided, all workflow with same key will be deleted."
279
+ description: "Workflow key. All versions sharing this key will be deleted."
208
280
  }
209
281
  }
210
282
  }
211
283
  }
212
284
  ],
213
285
  responses: {
214
- 200: {
215
- description: "OK"
216
- }
286
+ 200: { description: "OK" }
217
287
  }
218
288
  }
219
289
  },
220
290
  "/workflows:revision": {
221
291
  post: {
222
292
  tags: ["workflows"],
223
- description: "Duplicate a workflow to a new version or a new workflow. All nodes will be duplicated too.",
293
+ summary: "Duplicate a workflow (create a revision)",
294
+ description: [
295
+ "Duplicate an existing workflow. All nodes are duplicated too.",
296
+ "",
297
+ "- If `filter.key` is provided, creates a **new version** under the same key (version control).",
298
+ "- Otherwise, creates an independent copy as a **new workflow** with a new key.",
299
+ "",
300
+ "The new workflow/version is created with `enabled: false` and `current: false` by default",
301
+ "unless overridden via `values`."
302
+ ].join("\n"),
224
303
  parameters: [
225
304
  {
226
305
  name: "filterByTk",
227
306
  in: "query",
228
- description: "Primary key of a record",
229
- schema: {
230
- type: "integer",
231
- description: "ID. The workflow to duplicate."
232
- }
307
+ description: "ID of the workflow to duplicate",
308
+ schema: { type: "integer" }
233
309
  },
234
310
  {
235
311
  name: "filter",
236
312
  in: "query",
237
- description: "Filter",
313
+ description: "Filter options",
238
314
  schema: {
239
315
  type: "object",
240
316
  properties: {
241
317
  key: {
242
318
  type: "string",
243
- description: "Key. If provided, only duplicate to a new version. Or will be duplicated to a new workflow."
319
+ description: "If provided, creates a new version under the same key. Otherwise duplicates as a new workflow."
244
320
  }
245
321
  }
246
322
  }
247
323
  }
248
324
  ],
325
+ requestBody: {
326
+ content: {
327
+ "application/json": {
328
+ schema: {
329
+ type: "object",
330
+ properties: {
331
+ values: {
332
+ type: "object",
333
+ description: "Override fields for the new workflow/version",
334
+ properties: {
335
+ title: { type: "string", description: "Override title" },
336
+ enabled: { type: "boolean", description: "Override enabled state" },
337
+ current: { type: "boolean", description: "Set as current version" }
338
+ }
339
+ }
340
+ }
341
+ }
342
+ }
343
+ }
344
+ },
249
345
  responses: {
250
346
  200: {
251
- description: "OK"
347
+ description: "OK",
348
+ content: {
349
+ "application/json": {
350
+ schema: { $ref: "#/components/schemas/workflow/model" }
351
+ }
352
+ }
252
353
  }
253
354
  }
254
355
  }
255
356
  },
256
- "/workflows:trigger": {
357
+ "/workflows:sync": {
257
358
  post: {
258
359
  tags: ["workflows"],
259
- description: "",
360
+ summary: "Sync workflow trigger registration",
361
+ description: [
362
+ "Re-register one or more workflows in the trigger system.",
363
+ "",
364
+ "This is used to reload a workflow's trigger listener after its configuration has been",
365
+ "changed directly in the database or via external tooling, bypassing the normal update API.",
366
+ "",
367
+ "Returns HTTP 204 No Content on success."
368
+ ].join("\n"),
260
369
  parameters: [
261
370
  {
262
- name: "triggerWorkflows",
371
+ name: "filterByTk",
263
372
  in: "query",
264
- description: "A combined string to describe workflows to trigger and context data to use. e.g. `?triggerWorkflows=1,2!category`. Each comma separated part is a trigger pair, as `1` and `2!category`. The number part is the ID of workflow, exclamation means the path of association to use in form data. If ignored, will trigger with the full form data object.",
265
- schema: {
266
- type: "string"
267
- }
373
+ description: "ID of the workflow to sync",
374
+ schema: { type: "integer" }
375
+ },
376
+ {
377
+ name: "filter",
378
+ in: "query",
379
+ description: "Filter to select multiple workflows to sync",
380
+ schema: { type: "object" }
268
381
  }
269
382
  ],
270
383
  responses: {
271
- 202: {
272
- description: "Accepted"
384
+ 204: { description: "No Content. Sync successful." }
385
+ }
386
+ }
387
+ },
388
+ "/workflows:execute": {
389
+ post: {
390
+ tags: ["workflows"],
391
+ summary: "Manually execute a workflow",
392
+ description: [
393
+ "Manually trigger execution of a workflow by ID.",
394
+ "",
395
+ "**Requirements:**",
396
+ "- `filterByTk` (query param) is required.",
397
+ "- `values` (request body) is required \u2014 provide the context/input data the trigger expects.",
398
+ "",
399
+ "**autoRevision:** When set to `1`, if the workflow has never been executed",
400
+ "(`executed === 0`), a new revision is created automatically after execution.",
401
+ "",
402
+ "**Returns:** `{ execution: { id, status }, newVersionId? }`"
403
+ ].join("\n"),
404
+ parameters: [
405
+ {
406
+ name: "filterByTk",
407
+ in: "query",
408
+ required: true,
409
+ description: "ID of the workflow to execute",
410
+ schema: { type: "integer" }
273
411
  },
274
- 400: {
275
- description: "Bad Request"
412
+ {
413
+ name: "autoRevision",
414
+ in: "query",
415
+ description: "If `1`, automatically create a new revision after the first execution",
416
+ schema: { type: "integer", enum: [0, 1] }
276
417
  }
418
+ ],
419
+ requestBody: {
420
+ required: true,
421
+ content: {
422
+ "application/json": {
423
+ schema: {
424
+ type: "object",
425
+ required: ["values"],
426
+ properties: {
427
+ values: {
428
+ type: "object",
429
+ description: "Context/input data for the workflow trigger. Structure depends on the trigger type."
430
+ }
431
+ }
432
+ }
433
+ }
434
+ }
435
+ },
436
+ responses: {
437
+ 200: {
438
+ description: "OK",
439
+ content: {
440
+ "application/json": {
441
+ schema: {
442
+ type: "object",
443
+ properties: {
444
+ execution: {
445
+ type: "object",
446
+ properties: {
447
+ id: { type: "integer", description: "Execution ID" },
448
+ status: { type: "integer", description: "Execution status code" }
449
+ }
450
+ },
451
+ newVersionId: {
452
+ type: "integer",
453
+ nullable: true,
454
+ description: "ID of the newly created revision, if autoRevision was triggered"
455
+ }
456
+ }
457
+ }
458
+ }
459
+ }
460
+ },
461
+ 400: {
462
+ description: "Bad Request. `values` or `filterByTk` is missing, invalid, or workflow not triggered."
463
+ },
464
+ 404: { description: "Not Found. Workflow does not exist." }
277
465
  }
278
466
  }
279
467
  },
468
+ // ─────────────────────────────────────────────────────────────────────────
469
+ // workflows.nodes (association: create node within a workflow)
470
+ // ─────────────────────────────────────────────────────────────────────────
280
471
  "/workflows/{workflowId}/nodes:create": {
281
472
  post: {
282
473
  tags: ["workflows.nodes"],
283
- description: "Create a new node in workflow",
284
- parameters: [],
474
+ summary: "Create a node in a workflow",
475
+ description: [
476
+ "Create a new node inside the specified workflow.",
477
+ "",
478
+ "**Insertion logic:**",
479
+ "- `upstreamId: null` \u2014 node becomes the new head; the previous head (if any) becomes its downstream.",
480
+ "- `branchIndex: null` \u2014 node is inserted in the main chain after `upstreamId`.",
481
+ "- `branchIndex: <n>` \u2014 node becomes the head of branch `n` from `upstreamId`.",
482
+ "",
483
+ "**Constraint:** Cannot create nodes in a workflow version that has already been executed.",
484
+ "An optional `WORKFLOW_NODES_LIMIT` env var caps the total number of nodes allowed per workflow."
485
+ ].join("\n"),
486
+ parameters: [
487
+ {
488
+ name: "workflowId",
489
+ in: "path",
490
+ required: true,
491
+ description: "Workflow ID",
492
+ schema: { type: "integer" }
493
+ }
494
+ ],
285
495
  requestBody: {
286
496
  content: {
287
497
  "application/json": {
288
498
  schema: {
289
499
  type: "object",
500
+ required: ["type"],
290
501
  properties: {
291
- title: {
292
- $ref: "#/components/schemas/node/properties/title"
293
- },
294
- type: {
295
- $ref: "#/components/schemas/node/properties/type"
296
- },
297
- upstreamId: {
298
- $ref: "#/components/schemas/node/properties/upstreamId"
299
- },
300
- branchIndex: {
301
- $ref: "#/components/schemas/node/properties/branchIndex"
302
- }
502
+ type: { $ref: "#/components/schemas/node/properties/type" },
503
+ title: { $ref: "#/components/schemas/node/properties/title" },
504
+ config: { $ref: "#/components/schemas/node/properties/config" },
505
+ upstreamId: { $ref: "#/components/schemas/node/properties/upstreamId" },
506
+ branchIndex: { $ref: "#/components/schemas/node/properties/branchIndex" }
303
507
  }
304
508
  }
305
509
  }
@@ -311,14 +515,48 @@ var swagger_default = {
311
515
  content: {
312
516
  "application/json": {
313
517
  schema: {
314
- allOf: [
315
- {
316
- $ref: "#/components/schemas/node"
317
- }
318
- ]
518
+ allOf: [{ $ref: "#/components/schemas/node" }]
319
519
  }
320
520
  }
321
521
  }
522
+ },
523
+ 400: {
524
+ description: "Bad Request. Cannot create node in an already-executed workflow version, or node limit exceeded."
525
+ }
526
+ }
527
+ }
528
+ },
529
+ // ─────────────────────────────────────────────────────────────────────────
530
+ // flow_nodes
531
+ // ─────────────────────────────────────────────────────────────────────────
532
+ "/flow_nodes:get": {
533
+ get: {
534
+ tags: ["flow_nodes"],
535
+ summary: "Get single node",
536
+ description: "Get details of a single flow node.",
537
+ parameters: [
538
+ {
539
+ name: "filterByTk",
540
+ in: "query",
541
+ required: true,
542
+ description: "Node ID",
543
+ schema: { type: "integer" }
544
+ },
545
+ {
546
+ name: "appends",
547
+ in: "query",
548
+ description: "Append associations (e.g. `upstream`, `downstream`)",
549
+ schema: { type: "array", items: { type: "string" } }
550
+ }
551
+ ],
552
+ responses: {
553
+ 200: {
554
+ description: "OK",
555
+ content: {
556
+ "application/json": {
557
+ schema: { $ref: "#/components/schemas/node" }
558
+ }
559
+ }
322
560
  }
323
561
  }
324
562
  }
@@ -326,16 +564,23 @@ var swagger_default = {
326
564
  "/flow_nodes:update": {
327
565
  post: {
328
566
  tags: ["flow_nodes"],
329
- description: "Update node properties.",
567
+ summary: "Update node properties",
568
+ description: [
569
+ "Update properties or configuration of a flow node.",
570
+ "",
571
+ "**Constraint:** Cannot update nodes in a workflow version that has already been executed",
572
+ "(`versionStats.executed > 0`).",
573
+ "",
574
+ "`updateAssociationValues` can be used to update linked nodes simultaneously,",
575
+ "e.g. when re-connecting upstream/downstream after inserting a new node."
576
+ ].join("\n"),
330
577
  parameters: [
331
578
  {
332
579
  name: "filterByTk",
333
580
  in: "query",
334
- description: "Primary key of a record",
335
- schema: {
336
- type: "integer",
337
- description: "ID"
338
- }
581
+ required: true,
582
+ description: "Node ID",
583
+ schema: { type: "integer" }
339
584
  }
340
585
  ],
341
586
  requestBody: {
@@ -344,11 +589,13 @@ var swagger_default = {
344
589
  schema: {
345
590
  type: "object",
346
591
  properties: {
347
- title: {
348
- $ref: "#/components/schemas/node/properties/title"
349
- },
350
- config: {
351
- $ref: "#/components/schemas/node/properties/config"
592
+ title: { $ref: "#/components/schemas/node/properties/title" },
593
+ config: { $ref: "#/components/schemas/node/properties/config" },
594
+ branchIndex: { $ref: "#/components/schemas/node/properties/branchIndex" },
595
+ updateAssociationValues: {
596
+ type: "array",
597
+ description: 'Association fields to update simultaneously (e.g. `["upstream"]` to reconnect upstream node)',
598
+ items: { type: "string" }
352
599
  }
353
600
  }
354
601
  }
@@ -356,11 +603,9 @@ var swagger_default = {
356
603
  }
357
604
  },
358
605
  responses: {
359
- 200: {
360
- description: "OK"
361
- },
606
+ 200: { description: "OK" },
362
607
  400: {
363
- description: "Bad Request. Node in exected workflow cannot be updated."
608
+ description: "Bad Request. Node in executed workflow cannot be updated."
364
609
  }
365
610
  }
366
611
  }
@@ -368,33 +613,303 @@ var swagger_default = {
368
613
  "/flow_nodes:destroy": {
369
614
  post: {
370
615
  tags: ["flow_nodes"],
371
- description: "Delete a node. All nodes in sub-branches will also be deleted.",
616
+ summary: "Delete a node",
617
+ description: [
618
+ "Delete a node from the workflow. All nodes in sub-branches are also deleted by default.",
619
+ "",
620
+ "**keepBranch:** Optionally preserve one branch by specifying its `branchIndex`.",
621
+ "The kept branch will be reconnected to the deleted node's upstream/downstream.",
622
+ "",
623
+ "**Constraint:** Cannot delete nodes in a workflow version that has already been executed."
624
+ ].join("\n"),
372
625
  parameters: [
373
626
  {
374
627
  name: "filterByTk",
375
628
  in: "query",
376
- description: "Primary key of a record",
377
- schema: {
378
- type: "integer",
379
- description: "ID"
629
+ required: true,
630
+ description: "Node ID",
631
+ schema: { type: "integer" }
632
+ },
633
+ {
634
+ name: "keepBranch",
635
+ in: "query",
636
+ description: "Branch index to preserve (all other branches will be deleted)",
637
+ schema: { type: "integer" }
638
+ }
639
+ ],
640
+ responses: {
641
+ 200: { description: "OK" },
642
+ 400: {
643
+ description: "Bad Request. Node in executed workflow cannot be deleted."
644
+ }
645
+ }
646
+ }
647
+ },
648
+ "/flow_nodes:destroyBranch": {
649
+ post: {
650
+ tags: ["flow_nodes"],
651
+ summary: "Delete a specific branch of a branching node",
652
+ description: [
653
+ "Delete all nodes under a specific branch of a branching node (e.g. a condition node).",
654
+ "",
655
+ "**shift:** If `1`, branches with a higher `branchIndex` are shifted down by 1",
656
+ "to keep indexes contiguous after deletion.",
657
+ "",
658
+ "**Constraint:** Cannot delete branches in a workflow version that has already been executed."
659
+ ].join("\n"),
660
+ parameters: [
661
+ {
662
+ name: "filterByTk",
663
+ in: "query",
664
+ required: true,
665
+ description: "ID of the parent branching node",
666
+ schema: { type: "integer" }
667
+ },
668
+ {
669
+ name: "branchIndex",
670
+ in: "query",
671
+ required: true,
672
+ description: "Index of the branch to delete",
673
+ schema: { type: "integer" }
674
+ },
675
+ {
676
+ name: "shift",
677
+ in: "query",
678
+ description: "If `1`, shift remaining branch indexes down after deletion",
679
+ schema: { type: "integer", enum: [0, 1] }
680
+ }
681
+ ],
682
+ responses: {
683
+ 200: { description: "OK" },
684
+ 400: {
685
+ description: "Bad Request. Branch in executed workflow cannot be deleted, or `branchIndex` is missing/invalid."
686
+ }
687
+ }
688
+ }
689
+ },
690
+ "/flow_nodes:duplicate": {
691
+ post: {
692
+ tags: ["flow_nodes"],
693
+ summary: "Duplicate a node",
694
+ description: [
695
+ "Duplicate an existing node to a new position in the same workflow.",
696
+ "The node's `type`, `title`, and `config` are copied. If the instruction defines a",
697
+ "`duplicateConfig` method, it is called to transform the config during duplication.",
698
+ "",
699
+ "**Constraint:** Cannot duplicate into a workflow version that has already been executed.",
700
+ "An optional `WORKFLOW_NODES_LIMIT` env var caps the total number of nodes allowed."
701
+ ].join("\n"),
702
+ parameters: [
703
+ {
704
+ name: "filterByTk",
705
+ in: "query",
706
+ required: true,
707
+ description: "ID of the source node to duplicate",
708
+ schema: { type: "integer" }
709
+ }
710
+ ],
711
+ requestBody: {
712
+ content: {
713
+ "application/json": {
714
+ schema: {
715
+ type: "object",
716
+ properties: {
717
+ values: {
718
+ type: "object",
719
+ description: "Target position and optional config override for the new node",
720
+ properties: {
721
+ upstreamId: { $ref: "#/components/schemas/node/properties/upstreamId" },
722
+ branchIndex: { $ref: "#/components/schemas/node/properties/branchIndex" },
723
+ config: { $ref: "#/components/schemas/node/properties/config" }
724
+ }
725
+ }
726
+ }
727
+ }
728
+ }
729
+ }
730
+ },
731
+ responses: {
732
+ 200: {
733
+ description: "OK",
734
+ content: {
735
+ "application/json": {
736
+ schema: { $ref: "#/components/schemas/node" }
737
+ }
380
738
  }
739
+ },
740
+ 400: {
741
+ description: "Bad Request. Cannot duplicate node in executed workflow, or node limit exceeded."
742
+ },
743
+ 404: { description: "Not Found. Source node not found." }
744
+ }
745
+ }
746
+ },
747
+ "/flow_nodes:move": {
748
+ post: {
749
+ tags: ["flow_nodes"],
750
+ summary: "Move a node to a different position",
751
+ description: [
752
+ "Move a node to a new position in the workflow graph.",
753
+ "Upstream/downstream connections of both the old and new positions are automatically re-linked.",
754
+ "",
755
+ "**Target position (in `values`):**",
756
+ "- `upstreamId: null` \u2014 move node to the head of the workflow.",
757
+ "- `upstreamId: <id>` + `branchIndex: null` \u2014 insert into the main chain after that node.",
758
+ "- `upstreamId: <id>` + `branchIndex: <n>` \u2014 insert as head of branch `n` from that node.",
759
+ "",
760
+ "**Constraint:** Cannot move nodes in a workflow version that has already been executed."
761
+ ].join("\n"),
762
+ parameters: [
763
+ {
764
+ name: "filterByTk",
765
+ in: "query",
766
+ required: true,
767
+ description: "ID of the node to move",
768
+ schema: { type: "integer" }
381
769
  }
382
770
  ],
771
+ requestBody: {
772
+ content: {
773
+ "application/json": {
774
+ schema: {
775
+ type: "object",
776
+ properties: {
777
+ values: {
778
+ type: "object",
779
+ description: "Target position descriptor",
780
+ properties: {
781
+ upstreamId: {
782
+ type: "integer",
783
+ nullable: true,
784
+ description: "Target upstream node ID. `null` = move to head position."
785
+ },
786
+ branchIndex: {
787
+ type: "integer",
788
+ nullable: true,
789
+ description: "Branch index at the target upstream. `null` = main chain."
790
+ }
791
+ }
792
+ }
793
+ }
794
+ }
795
+ }
796
+ }
797
+ },
383
798
  responses: {
384
799
  200: {
385
- description: "OK"
800
+ description: "OK",
801
+ content: {
802
+ "application/json": {
803
+ schema: { $ref: "#/components/schemas/node" }
804
+ }
805
+ }
386
806
  },
387
807
  400: {
388
- description: "Bad Request. Node in exected workflow cannot be deleted."
808
+ description: "Bad Request. Cannot move node in executed workflow, or target position is invalid."
809
+ },
810
+ 404: { description: "Not Found. Node or target upstream node not found." }
811
+ }
812
+ }
813
+ },
814
+ "/flow_nodes:test": {
815
+ post: {
816
+ tags: ["flow_nodes"],
817
+ summary: "Test a node configuration",
818
+ description: [
819
+ "Test a node's configuration without creating a real workflow execution.",
820
+ "Only applicable to node types whose instruction implements a `test` method.",
821
+ "",
822
+ "Returns the result produced by the instruction's `test(config)` method."
823
+ ].join("\n"),
824
+ parameters: [],
825
+ requestBody: {
826
+ required: true,
827
+ content: {
828
+ "application/json": {
829
+ schema: {
830
+ type: "object",
831
+ required: ["values"],
832
+ properties: {
833
+ values: {
834
+ type: "object",
835
+ required: ["type"],
836
+ properties: {
837
+ type: { $ref: "#/components/schemas/node/properties/type" },
838
+ config: { $ref: "#/components/schemas/node/properties/config" }
839
+ }
840
+ }
841
+ }
842
+ }
843
+ }
389
844
  }
845
+ },
846
+ responses: {
847
+ 200: {
848
+ description: "OK. Returns the test result from the instruction.",
849
+ content: {
850
+ "application/json": {
851
+ schema: { type: "object" }
852
+ }
853
+ }
854
+ },
855
+ 400: {
856
+ description: "Bad Request. Node type not registered or `test` method not implemented."
857
+ },
858
+ 500: { description: "Internal Server Error. Test execution threw an error." }
390
859
  }
391
860
  }
392
861
  },
862
+ // ─────────────────────────────────────────────────────────────────────────
863
+ // executions
864
+ // ─────────────────────────────────────────────────────────────────────────
393
865
  "/executions:list": {
394
866
  get: {
395
867
  tags: ["executions"],
396
- description: "Get list of executions",
397
- parameters: [],
868
+ summary: "List executions",
869
+ description: [
870
+ "Get paginated list of workflow execution records.",
871
+ "",
872
+ "Example:",
873
+ "```",
874
+ 'GET /api/executions:list?filter={"workflowId":1}&sort=-id&page=1&pageSize=20',
875
+ "```"
876
+ ].join("\n"),
877
+ parameters: [
878
+ {
879
+ name: "filter",
880
+ in: "query",
881
+ description: "Filter conditions (e.g. `{ workflowId: 1, status: 1 }`)",
882
+ schema: { type: "object" }
883
+ },
884
+ {
885
+ name: "appends",
886
+ in: "query",
887
+ description: "Append associations (e.g. `jobs`, `workflow`)",
888
+ schema: { type: "array", items: { type: "string" } }
889
+ },
890
+ {
891
+ name: "except",
892
+ in: "query",
893
+ description: "Exclude fields to reduce payload",
894
+ schema: { type: "array", items: { type: "string" } }
895
+ },
896
+ {
897
+ name: "sort",
898
+ in: "query",
899
+ description: "Sort fields. Prefix with `-` for descending. e.g. `-id`",
900
+ schema: { type: "string" }
901
+ },
902
+ {
903
+ name: "page",
904
+ in: "query",
905
+ schema: { type: "integer", default: 1 }
906
+ },
907
+ {
908
+ name: "pageSize",
909
+ in: "query",
910
+ schema: { type: "integer", default: 20 }
911
+ }
912
+ ],
398
913
  responses: {
399
914
  200: {
400
915
  description: "OK",
@@ -420,16 +935,34 @@ var swagger_default = {
420
935
  "/executions:get": {
421
936
  get: {
422
937
  tags: ["executions"],
423
- description: "Get single execution",
938
+ summary: "Get single execution",
939
+ description: [
940
+ "Get details of a single execution. Use `appends` to include jobs, workflow and node data.",
941
+ "",
942
+ "Example:",
943
+ "```",
944
+ "GET /api/executions:get?filterByTk=1&appends[]=jobs&appends[]=workflow&appends[]=workflow.nodes",
945
+ "```"
946
+ ].join("\n"),
424
947
  parameters: [
425
948
  {
426
949
  name: "filterByTk",
427
950
  in: "query",
428
- description: "Primary key of a record",
429
- schema: {
430
- type: "integer",
431
- description: "ID"
432
- }
951
+ required: true,
952
+ description: "Execution ID",
953
+ schema: { type: "integer" }
954
+ },
955
+ {
956
+ name: "appends",
957
+ in: "query",
958
+ description: "Append associations: `jobs`, `workflow`, `workflow.nodes`, `workflow.versionStats`, `workflow.stats`",
959
+ schema: { type: "array", items: { type: "string" } }
960
+ },
961
+ {
962
+ name: "except",
963
+ in: "query",
964
+ description: "Exclude fields to reduce payload (e.g. `jobs.result`, `workflow.options`)",
965
+ schema: { type: "array", items: { type: "string" } }
433
966
  }
434
967
  ],
435
968
  responses: {
@@ -437,20 +970,115 @@ var swagger_default = {
437
970
  description: "OK",
438
971
  content: {
439
972
  "application/json": {
440
- schema: {
441
- $ref: "#/components/schemas/execution"
442
- }
973
+ schema: { $ref: "#/components/schemas/execution" }
443
974
  }
444
975
  }
445
976
  }
446
977
  }
447
978
  }
448
979
  },
449
- "/workflowManualTasks:list": {
980
+ "/executions:cancel": {
981
+ post: {
982
+ tags: ["executions"],
983
+ summary: "Cancel a running execution",
984
+ description: [
985
+ "Abort a currently running execution.",
986
+ "Sets the execution status to `ABORTED` (-3) and all `PENDING` (0) jobs to `ABORTED` (-3).",
987
+ "",
988
+ "**Constraint:** Only executions with `status = 0` (STARTED) can be cancelled.",
989
+ "",
990
+ "Returns the updated execution record."
991
+ ].join("\n"),
992
+ parameters: [
993
+ {
994
+ name: "filterByTk",
995
+ in: "query",
996
+ required: true,
997
+ description: "Execution ID",
998
+ schema: { type: "integer" }
999
+ }
1000
+ ],
1001
+ responses: {
1002
+ 200: {
1003
+ description: "OK. Returns the updated execution.",
1004
+ content: {
1005
+ "application/json": {
1006
+ schema: { $ref: "#/components/schemas/execution" }
1007
+ }
1008
+ }
1009
+ },
1010
+ 400: {
1011
+ description: "Bad Request. Execution has already ended (status \u2260 0)."
1012
+ },
1013
+ 404: { description: "Not Found. Execution does not exist." }
1014
+ }
1015
+ }
1016
+ },
1017
+ "/executions:destroy": {
1018
+ post: {
1019
+ tags: ["executions"],
1020
+ summary: "Delete execution records",
1021
+ description: [
1022
+ "Delete one or more execution records.",
1023
+ "**Running executions (`status = 0`, STARTED) cannot be deleted.**",
1024
+ "Call `executions:cancel` first if you need to delete a running execution."
1025
+ ].join("\n"),
1026
+ parameters: [
1027
+ {
1028
+ name: "filterByTk",
1029
+ in: "query",
1030
+ description: "Execution ID",
1031
+ schema: { type: "integer" }
1032
+ },
1033
+ {
1034
+ name: "filter",
1035
+ in: "query",
1036
+ description: "Filter for batch deletion. Running executions are automatically excluded from deletion.",
1037
+ schema: { type: "object" }
1038
+ }
1039
+ ],
1040
+ responses: {
1041
+ 200: { description: "OK" }
1042
+ }
1043
+ }
1044
+ },
1045
+ // ─────────────────────────────────────────────────────────────────────────
1046
+ // jobs
1047
+ // ─────────────────────────────────────────────────────────────────────────
1048
+ "/jobs:list": {
450
1049
  get: {
451
- tags: ["workflowManualTasks"],
452
- description: "List manual jobs",
453
- parameters: [],
1050
+ tags: ["jobs"],
1051
+ summary: "List jobs",
1052
+ description: 'Get list of node job records. Usually more convenient to access via `executions:get` with `appends: ["jobs"]`.',
1053
+ parameters: [
1054
+ {
1055
+ name: "filter",
1056
+ in: "query",
1057
+ description: "Filter conditions (e.g. `{ executionId: 1 }`, `{ nodeId: 2 }`)",
1058
+ schema: { type: "object" }
1059
+ },
1060
+ {
1061
+ name: "appends",
1062
+ in: "query",
1063
+ description: "Append associations",
1064
+ schema: { type: "array", items: { type: "string" } }
1065
+ },
1066
+ {
1067
+ name: "sort",
1068
+ in: "query",
1069
+ schema: { type: "string" }
1070
+ },
1071
+ {
1072
+ name: "page",
1073
+ in: "query",
1074
+ schema: { type: "integer" }
1075
+ },
1076
+ {
1077
+ name: "pageSize",
1078
+ in: "query",
1079
+ schema: { type: "integer" }
1080
+ }
1081
+ ],
454
1082
  responses: {
455
1083
  200: {
456
1084
  description: "OK",
@@ -458,10 +1086,7 @@ var swagger_default = {
458
1086
  "application/json": {
459
1087
  schema: {
460
1088
  type: "array",
461
- description: "List of manual jobs",
462
- items: {
463
- $ref: "#/components/schemas/user_job"
464
- }
1089
+ items: { $ref: "#/components/schemas/job" }
465
1090
  }
466
1091
  }
467
1092
  }
@@ -469,50 +1094,59 @@ var swagger_default = {
469
1094
  }
470
1095
  }
471
1096
  },
472
- "/workflowManualTasks:get": {
1097
+ "/jobs:get": {
473
1098
  get: {
474
- tags: ["workflowManualTasks"],
475
- description: "Single user job",
476
- parameters: [],
1099
+ tags: ["jobs"],
1100
+ summary: "Get single job",
1101
+ description: "Get details of a single node job record.",
1102
+ parameters: [
1103
+ {
1104
+ name: "filterByTk",
1105
+ in: "query",
1106
+ required: true,
1107
+ description: "Job ID",
1108
+ schema: { type: "integer" }
1109
+ },
1110
+ {
1111
+ name: "appends",
1112
+ in: "query",
1113
+ description: "Append associations",
1114
+ schema: { type: "array", items: { type: "string" } }
1115
+ }
1116
+ ],
477
1117
  responses: {
478
1118
  200: {
479
1119
  description: "OK",
480
1120
  content: {
481
1121
  "application/json": {
482
- schema: {
483
- allOf: [
484
- {
485
- $ref: "#/components/schemas/user_job"
486
- },
487
- {
488
- type: "object",
489
- properties: {
490
- execution: {
491
- $ref: "#/components/schemas/execution"
492
- }
493
- }
494
- }
495
- ]
496
- }
1122
+ schema: { $ref: "#/components/schemas/job" }
497
1123
  }
498
1124
  }
499
1125
  }
500
1126
  }
501
1127
  }
502
1128
  },
503
- "/workflowManualTasks:submit": {
1129
+ "/jobs:resume": {
504
1130
  post: {
505
- tags: ["workflowManualTasks"],
506
- description: "",
1131
+ tags: ["jobs"],
1132
+ summary: "Resume execution via a job",
1133
+ description: [
1134
+ "Update a job's fields and signal the workflow processor to resume the paused execution.",
1135
+ "",
1136
+ "This is the mechanism for continuing execution after a waiting/interactive node",
1137
+ "(e.g. manual processing, approval) has been handled.",
1138
+ "",
1139
+ "The job must exist. After the update the execution is resumed asynchronously.",
1140
+ "",
1141
+ "Returns HTTP 202 Accepted with the updated job."
1142
+ ].join("\n"),
507
1143
  parameters: [
508
1144
  {
509
1145
  name: "filterByTk",
510
1146
  in: "query",
511
- description: "Primary key of a record",
512
- schema: {
513
- type: "integer",
514
- description: "ID"
515
- }
1147
+ required: true,
1148
+ description: "Job ID",
1149
+ schema: { type: "integer" }
516
1150
  }
517
1151
  ],
518
1152
  requestBody: {
@@ -521,14 +1155,21 @@ var swagger_default = {
521
1155
  schema: {
522
1156
  type: "object",
523
1157
  properties: {
524
- result: {
1158
+ values: {
525
1159
  type: "object",
1160
+ description: "Fields to update on the job before resuming",
526
1161
  properties: {
527
- $formKey: {
528
- type: "object"
1162
+ status: {
1163
+ type: "integer",
1164
+ description: "Job status: 1=RESOLVED, -1=FAILED, -3=ABORTED, -4=CANCELED, -5=REJECTED"
1165
+ },
1166
+ result: {
1167
+ type: "object",
1168
+ description: "Result data to store on the job"
529
1169
  },
530
- _: {
531
- type: "string"
1170
+ meta: {
1171
+ type: "object",
1172
+ description: "Metadata to store on the job"
532
1173
  }
533
1174
  }
534
1175
  }
@@ -539,15 +1180,80 @@ var swagger_default = {
539
1180
  },
540
1181
  responses: {
541
1182
  202: {
542
- description: "Accepted"
1183
+ description: "Accepted. Job updated and execution resume signalled.",
1184
+ content: {
1185
+ "application/json": {
1186
+ schema: { $ref: "#/components/schemas/job" }
1187
+ }
1188
+ }
543
1189
  },
544
- 400: {
545
- description: "Bad Request. Status of the job is not 0."
1190
+ 404: { description: "Not Found. Job does not exist." }
1191
+ }
1192
+ }
1193
+ },
1194
+ // ─────────────────────────────────────────────────────────────────────────
1195
+ // userWorkflowTasks
1196
+ // ─────────────────────────────────────────────────────────────────────────
1197
+ "/userWorkflowTasks:listMine": {
1198
+ get: {
1199
+ tags: ["userWorkflowTasks"],
1200
+ summary: "List my workflow tasks",
1201
+ description: [
1202
+ "Get workflow tasks assigned to the currently logged-in user.",
1203
+ "The server automatically injects `userId = currentUser.id` into the filter.",
1204
+ "",
1205
+ "This is the base action for listing user-specific interactive tasks.",
1206
+ "Extension plugins (e.g. plugin-workflow-manual, plugin-workflow-approval) may",
1207
+ "provide additional task-type-specific actions on this same resource."
1208
+ ].join("\n"),
1209
+ parameters: [
1210
+ {
1211
+ name: "filter",
1212
+ in: "query",
1213
+ description: "Additional filter conditions",
1214
+ schema: { type: "object" }
1215
+ },
1216
+ {
1217
+ name: "appends",
1218
+ in: "query",
1219
+ description: "Append associations",
1220
+ schema: { type: "array", items: { type: "string" } }
1221
+ },
1222
+ {
1223
+ name: "sort",
1224
+ in: "query",
1225
+ schema: { type: "string" }
1226
+ },
1227
+ {
1228
+ name: "page",
1229
+ in: "query",
1230
+ schema: { type: "integer" }
1231
+ },
1232
+ {
1233
+ name: "pageSize",
1234
+ in: "query",
1235
+ schema: { type: "integer" }
1236
+ }
1237
+ ],
1238
+ responses: {
1239
+ 200: {
1240
+ description: "OK",
1241
+ content: {
1242
+ "application/json": {
1243
+ schema: {
1244
+ type: "array",
1245
+ items: { $ref: "#/components/schemas/user_job" }
1246
+ }
1247
+ }
1248
+ }
546
1249
  }
547
1250
  }
548
1251
  }
549
1252
  }
550
1253
  },
1254
+ // ───────────────────────────────────────────────────────────────────────────
1255
+ // Schemas
1256
+ // ───────────────────────────────────────────────────────────────────────────
551
1257
  components: {
552
1258
  schemas: {
553
1259
  workflow: {
@@ -561,7 +1267,7 @@ var swagger_default = {
561
1267
  },
562
1268
  key: {
563
1269
  type: "string",
564
- description: "Key. Variant versions of the same workflow share the same key."
1270
+ description: "Version group key. All versions of the same workflow share the same key."
565
1271
  },
566
1272
  title: {
567
1273
  type: "string",
@@ -571,40 +1277,69 @@ var swagger_default = {
571
1277
  type: "string",
572
1278
  description: "Description"
573
1279
  },
1280
+ triggerTitle: {
1281
+ type: "string",
1282
+ description: "Trigger display label (optional, UI only)"
1283
+ },
574
1284
  current: {
575
1285
  type: "boolean",
576
- description: "Current version"
1286
+ description: "Whether this is the active version. Only one version per `key` can have `current: true`."
577
1287
  },
578
1288
  enabled: {
579
1289
  type: "boolean",
580
- description: "Enabled"
1290
+ description: "Whether the workflow is enabled. Enabling registers the trigger listener."
581
1291
  },
582
1292
  type: {
583
1293
  type: "string",
584
- description: "Event type"
1294
+ description: "Trigger type (e.g. `collection`, `schedule`)"
1295
+ },
1296
+ sync: {
1297
+ type: "boolean",
1298
+ description: "Synchronous execution mode. `true` = execute immediately and return; `false` = queue async. Cannot be changed after creation."
585
1299
  },
586
1300
  config: {
587
1301
  type: "object",
588
- description: "Configuration JSON object"
1302
+ description: "Trigger configuration JSON object. Structure depends on `type`."
1303
+ },
1304
+ options: {
1305
+ type: "object",
1306
+ description: "Engine options",
1307
+ properties: {
1308
+ deleteExecutionOnStatus: {
1309
+ type: "array",
1310
+ description: "Auto-delete execution records when they reach any of these status codes.",
1311
+ items: { type: "integer" }
1312
+ },
1313
+ stackLimit: {
1314
+ type: "integer",
1315
+ description: "Maximum recursive trigger depth. Executions beyond this limit are skipped. Default: 1.",
1316
+ default: 1
1317
+ }
1318
+ }
1319
+ },
1320
+ categories: {
1321
+ type: "array",
1322
+ description: "Category IDs (belongsToMany `workflowCategories`)",
1323
+ items: { type: "integer" }
589
1324
  },
590
1325
  nodes: {
591
1326
  type: "array",
592
- description: "Workflow nodes"
1327
+ description: "Workflow nodes (association)"
593
1328
  },
594
1329
  executions: {
595
1330
  type: "array",
596
- description: "Executions"
1331
+ description: "Executions (association)"
597
1332
  },
598
1333
  revisions: {
599
1334
  type: "array",
600
- description: "Revisions"
1335
+ description: "Other versions sharing the same `key` (association)"
601
1336
  }
602
1337
  }
603
1338
  },
604
1339
  filterByTk: {
605
1340
  name: "filterByTk",
606
1341
  in: "query",
607
- description: "Primary key of a record",
1342
+ description: "Primary key (ID) of the workflow",
608
1343
  schema: {
609
1344
  type: "integer",
610
1345
  description: "ID"
@@ -657,38 +1392,40 @@ var swagger_default = {
657
1392
  },
658
1393
  upstreamId: {
659
1394
  type: "integer",
660
- description: "Upstream node ID"
1395
+ nullable: true,
1396
+ description: "Upstream node ID. `null` means this is the first node (head) after the trigger."
661
1397
  },
662
1398
  upstream: {
663
1399
  type: "object",
664
- description: "Upstream node",
1400
+ description: "Upstream node (association)",
665
1401
  $ref: "#/components/schemas/node"
666
1402
  },
667
1403
  downstreamId: {
668
1404
  type: "integer",
669
- description: "Downstream node ID in flow, not in sub-branches",
670
- $ref: "#/components/schemas/node"
1405
+ nullable: true,
1406
+ description: "Downstream node ID in the main chain (not counting sub-branches)"
671
1407
  },
672
1408
  downstream: {
673
1409
  type: "object",
674
- description: "Downstream node",
1410
+ description: "Downstream node (association)",
675
1411
  $ref: "#/components/schemas/node"
676
1412
  },
677
1413
  type: {
678
1414
  type: "string",
679
- description: "Node type"
1415
+ description: "Node type (e.g. `calculation`, `condition`, `query`, `create`, `update`, `destroy`)"
680
1416
  },
681
1417
  config: {
682
1418
  type: "object",
683
- description: "Configuration JSON object"
1419
+ description: "Node configuration JSON object. Structure depends on the node `type`."
684
1420
  },
685
1421
  branchIndex: {
686
1422
  type: "integer",
687
- description: "Non-null if the node is a branch node of upstream"
1423
+ nullable: true,
1424
+ description: "Branch index. Non-null when the node is the head of a branch from its upstream."
688
1425
  },
689
1426
  branches: {
690
1427
  type: "array",
691
- description: "Branch nodes under the node",
1428
+ description: "Branch head nodes of this node (association)",
692
1429
  items: {
693
1430
  $ref: "#/components/schemas/node"
694
1431
  }
@@ -697,7 +1434,7 @@ var swagger_default = {
697
1434
  },
698
1435
  execution: {
699
1436
  type: "object",
700
- description: "Execution record of workflow",
1437
+ description: "Workflow execution record",
701
1438
  properties: {
702
1439
  id: {
703
1440
  type: "integer",
@@ -705,23 +1442,38 @@ var swagger_default = {
705
1442
  },
706
1443
  key: {
707
1444
  type: "string",
708
- description: "Workflow key"
1445
+ description: "Workflow key (version group identifier)"
709
1446
  },
710
1447
  workflowId: {
711
1448
  type: "integer",
712
- description: "Workflow ID"
1449
+ description: "Workflow version ID"
713
1450
  },
714
1451
  context: {
715
1452
  type: "object",
716
- description: "Context data"
1453
+ description: "Trigger context data passed at the time of execution"
717
1454
  },
718
1455
  status: {
719
1456
  type: "integer",
720
- description: "Status of execution"
1457
+ description: [
1458
+ "Execution status code:",
1459
+ "- `null` : QUEUEING (waiting to start)",
1460
+ "- `0` : STARTED (running)",
1461
+ "- `1` : RESOLVED (completed successfully)",
1462
+ "- `-1` : FAILED",
1463
+ "- `-2` : ERROR",
1464
+ "- `-3` : ABORTED (forcibly cancelled)",
1465
+ "- `-4` : CANCELED",
1466
+ "- `-5` : REJECTED",
1467
+ "- `-6` : RETRY_NEEDED"
1468
+ ].join("\n")
1469
+ },
1470
+ output: {
1471
+ type: "object",
1472
+ description: "Output node results"
721
1473
  },
722
1474
  jobs: {
723
1475
  type: "array",
724
- description: "Results of executed nodes",
1476
+ description: 'Node job results (included when `appends: ["jobs"]`)',
725
1477
  items: {
726
1478
  $ref: "#/components/schemas/job"
727
1479
  }
@@ -730,7 +1482,7 @@ var swagger_default = {
730
1482
  },
731
1483
  job: {
732
1484
  type: "object",
733
- description: "Job record of exected node",
1485
+ description: "Node job execution record",
734
1486
  properties: {
735
1487
  id: {
736
1488
  type: "integer",
@@ -744,19 +1496,37 @@ var swagger_default = {
744
1496
  type: "integer",
745
1497
  description: "Node ID"
746
1498
  },
1499
+ nodeKey: {
1500
+ type: "string",
1501
+ description: "Node key (for cross-version reference)"
1502
+ },
747
1503
  status: {
748
1504
  type: "integer",
749
- description: "Status of job"
1505
+ description: [
1506
+ "Job status code:",
1507
+ "- `0` : PENDING (waiting, e.g. manual node)",
1508
+ "- `1` : RESOLVED (completed)",
1509
+ "- `-1` : FAILED",
1510
+ "- `-2` : ERROR",
1511
+ "- `-3` : ABORTED",
1512
+ "- `-4` : CANCELED",
1513
+ "- `-5` : REJECTED",
1514
+ "- `-6` : RETRY_NEEDED"
1515
+ ].join("\n")
750
1516
  },
751
1517
  result: {
752
1518
  type: "object",
753
- description: "Result data of job"
1519
+ description: "Result data of the job"
1520
+ },
1521
+ meta: {
1522
+ type: "object",
1523
+ description: "Metadata of the job"
754
1524
  }
755
1525
  }
756
1526
  },
757
1527
  user_job: {
758
1528
  type: "object",
759
- description: "User job",
1529
+ description: "User workflow task (an interactive task assigned to a specific user)",
760
1530
  properties: {
761
1531
  id: {
762
1532
  type: "integer",
@@ -776,15 +1546,15 @@ var swagger_default = {
776
1546
  },
777
1547
  userId: {
778
1548
  type: "integer",
779
- description: "User ID"
1549
+ description: "Assigned user ID"
780
1550
  },
781
1551
  status: {
782
1552
  type: "integer",
783
- description: "Status of job"
1553
+ description: "Task status (same enum as JOB_STATUS)"
784
1554
  },
785
1555
  result: {
786
1556
  type: "object",
787
- description: "Result data of job"
1557
+ description: "Task result data"
788
1558
  }
789
1559
  }
790
1560
  }