@blokjs/helper 0.2.1 → 0.6.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/dist/components/AddElse.d.ts +15 -0
- package/dist/components/AddIf.d.ts +15 -0
- package/dist/components/StepNode.d.ts +6 -0
- package/dist/components/StepNode.js +8 -0
- package/dist/components/StepNode.js.map +1 -1
- package/dist/components/Trigger.d.ts +10 -2
- package/dist/components/Trigger.js +16 -5
- package/dist/components/Trigger.js.map +1 -1
- package/dist/components/branch.d.ts +44 -0
- package/dist/components/branch.js +57 -0
- package/dist/components/branch.js.map +1 -0
- package/dist/components/forEach.d.ts +53 -0
- package/dist/components/forEach.js +64 -0
- package/dist/components/forEach.js.map +1 -0
- package/dist/components/loop.d.ts +52 -0
- package/dist/components/loop.js +54 -0
- package/dist/components/loop.js.map +1 -0
- package/dist/components/switchOn.d.ts +68 -0
- package/dist/components/switchOn.js +76 -0
- package/dist/components/switchOn.js.map +1 -0
- package/dist/components/tryCatch.d.ts +63 -0
- package/dist/components/tryCatch.js +68 -0
- package/dist/components/tryCatch.js.map +1 -0
- package/dist/components/workflowV2.d.ts +83 -0
- package/dist/components/workflowV2.js +84 -0
- package/dist/components/workflowV2.js.map +1 -0
- package/dist/index.d.ts +12 -3
- package/dist/index.js +25 -4
- package/dist/index.js.map +1 -1
- package/dist/proxy/$.d.ts +102 -0
- package/dist/proxy/$.js +130 -0
- package/dist/proxy/$.js.map +1 -0
- package/dist/types/StepOpts.d.ts +723 -3
- package/dist/types/StepOpts.js +702 -3
- package/dist/types/StepOpts.js.map +1 -1
- package/dist/types/TriggerOpts.d.ts +1600 -35
- package/dist/types/TriggerOpts.js +601 -29
- package/dist/types/TriggerOpts.js.map +1 -1
- package/dist/types/WorkflowOpts.d.ts +478 -28
- package/dist/types/WorkflowOpts.js +66 -3
- package/dist/types/WorkflowOpts.js.map +1 -1
- package/dist/utils/parseDuration.d.ts +33 -0
- package/dist/utils/parseDuration.js +78 -0
- package/dist/utils/parseDuration.js.map +1 -0
- package/dist/workflow.schema.json +662 -0
- package/package.json +6 -6
|
@@ -0,0 +1,662 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "Blok Workflow v2",
|
|
4
|
+
"description": "Schema for Blok v2 JSON workflows. Steps inline their `inputs`; output auto-persists to ctx.state[id]. Use the `branch` step shape for if/else flow control. See https://blok.build/docs/workflow-v2 for full reference.",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"name": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"minLength": 3,
|
|
10
|
+
"description": "Workflow display name. Min 3 characters. Shown in Studio."
|
|
11
|
+
},
|
|
12
|
+
"version": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"minLength": 5,
|
|
15
|
+
"description": "Semantic version (x.x.x). Used for trace recording and audit."
|
|
16
|
+
},
|
|
17
|
+
"description": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"description": "What this workflow does. Optional but recommended — surfaces in Studio and CLI."
|
|
20
|
+
},
|
|
21
|
+
"trigger": {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"additionalProperties": {},
|
|
24
|
+
"propertyNames": {
|
|
25
|
+
"enum": [
|
|
26
|
+
"http",
|
|
27
|
+
"grpc",
|
|
28
|
+
"manual",
|
|
29
|
+
"cron",
|
|
30
|
+
"queue",
|
|
31
|
+
"pubsub",
|
|
32
|
+
"worker",
|
|
33
|
+
"webhook",
|
|
34
|
+
"sse",
|
|
35
|
+
"websocket"
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
"description": "Trigger configuration. Most workflows use { http: { method: 'GET' } }. Optional ONLY when `middleware: true` is set — middleware-only workflows are invoked from another workflow's `trigger.http.middleware: [...]` array and don't have a public route of their own. See TRIGGER_SCHEMAS for per-kind shapes."
|
|
39
|
+
},
|
|
40
|
+
"middleware": {
|
|
41
|
+
"type": "boolean",
|
|
42
|
+
"const": true,
|
|
43
|
+
"description": "v0.5 — when true, this workflow is registered as middleware and is NOT exposed as a public HTTP route. It's invoked by another workflow that lists this one's `name` in its `trigger.http.middleware: [...]` array. Middleware runs on the parent ctx (state mutations carry forward) and can short-circuit by setting `ctx.response` and using a step with `stop: true`. Middleware-only workflows MAY omit `trigger`."
|
|
44
|
+
},
|
|
45
|
+
"steps": {
|
|
46
|
+
"type": "array",
|
|
47
|
+
"items": {
|
|
48
|
+
"anyOf": [
|
|
49
|
+
{
|
|
50
|
+
"type": "object",
|
|
51
|
+
"properties": {
|
|
52
|
+
"id": {
|
|
53
|
+
"type": "string",
|
|
54
|
+
"minLength": 1,
|
|
55
|
+
"description": "Stable identifier for the branch step. Visible in traces."
|
|
56
|
+
},
|
|
57
|
+
"branch": {
|
|
58
|
+
"type": "object",
|
|
59
|
+
"properties": {
|
|
60
|
+
"when": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"minLength": 1,
|
|
63
|
+
"description": "JavaScript expression. Truthy → run `then` branch; falsy → run `else` branch. $ proxy expressions compile to strings at the call site (e.g. $.req.query.kind === 'true')."
|
|
64
|
+
},
|
|
65
|
+
"then": {
|
|
66
|
+
"type": "array",
|
|
67
|
+
"items": {},
|
|
68
|
+
"description": "Steps to execute when `when` is truthy."
|
|
69
|
+
},
|
|
70
|
+
"else": {
|
|
71
|
+
"type": "array",
|
|
72
|
+
"items": {},
|
|
73
|
+
"description": "Steps to execute when `when` is falsy. Optional."
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"required": [
|
|
77
|
+
"when",
|
|
78
|
+
"then"
|
|
79
|
+
],
|
|
80
|
+
"additionalProperties": false,
|
|
81
|
+
"description": "Conditional sub-pipeline."
|
|
82
|
+
},
|
|
83
|
+
"active": {
|
|
84
|
+
"type": "boolean"
|
|
85
|
+
},
|
|
86
|
+
"stop": {
|
|
87
|
+
"type": "boolean"
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"required": [
|
|
91
|
+
"id",
|
|
92
|
+
"branch"
|
|
93
|
+
],
|
|
94
|
+
"additionalProperties": false
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"type": "object",
|
|
98
|
+
"properties": {
|
|
99
|
+
"id": {
|
|
100
|
+
"type": "string",
|
|
101
|
+
"minLength": 1,
|
|
102
|
+
"description": "Stable identifier. The sub-workflow's output lands on $.state[id] after the child completes. Required."
|
|
103
|
+
},
|
|
104
|
+
"subworkflow": {
|
|
105
|
+
"type": "string",
|
|
106
|
+
"minLength": 1,
|
|
107
|
+
"description": "Name of the workflow to invoke. Looked up in the WorkflowRegistry at run time. **Literal names** (`\"send-receipt-email\"`) are matched directly. **Polymorphic expressions** (`\"$.req.body.kind\"`, `\"js/ctx.req.body.kind\"`) resolve against the live ctx at dispatch time — pair with `allowList` to constrain which workflows the expression may resolve to."
|
|
108
|
+
},
|
|
109
|
+
"inputs": {
|
|
110
|
+
"type": "object",
|
|
111
|
+
"additionalProperties": {},
|
|
112
|
+
"description": "Inputs passed to the child as `ctx.request.body`. The child reads them via `$.req.body.<key>` exactly as if HTTP-triggered. May contain $ proxy refs."
|
|
113
|
+
},
|
|
114
|
+
"wait": {
|
|
115
|
+
"type": "boolean",
|
|
116
|
+
"description": "If true (default), parent step blocks until child completes and the child's ctx.response becomes the parent step's output. If false, dispatch is fire-and-forget — the parent step returns immediately with `{runId, workflowName, scheduledAt}` and the child runs asynchronously via setImmediate. The child still appears in Studio's Sub-runs strip and the parentRunId/parentNodeRunId lineage is preserved. Combine with `idempotencyKey` for at-most-once dispatch (Trigger.dev / Stripe semantics: the runId is cached against the key regardless of child outcome; new key needed to retry on failure)."
|
|
117
|
+
},
|
|
118
|
+
"as": {
|
|
119
|
+
"type": "string",
|
|
120
|
+
"minLength": 1,
|
|
121
|
+
"description": "Alternative state key (defaults to id). Mutually exclusive with spread."
|
|
122
|
+
},
|
|
123
|
+
"spread": {
|
|
124
|
+
"type": "boolean",
|
|
125
|
+
"description": "Shallow-merge child's response keys into state. Mutually exclusive with as."
|
|
126
|
+
},
|
|
127
|
+
"ephemeral": {
|
|
128
|
+
"type": "boolean",
|
|
129
|
+
"description": "If true, child output is NOT stored in state. Only ctx.prev carries it."
|
|
130
|
+
},
|
|
131
|
+
"active": {
|
|
132
|
+
"type": "boolean",
|
|
133
|
+
"description": "If false, the step is skipped at runtime. Default true."
|
|
134
|
+
},
|
|
135
|
+
"stop": {
|
|
136
|
+
"type": "boolean",
|
|
137
|
+
"description": "If true, the workflow halts after this step completes."
|
|
138
|
+
},
|
|
139
|
+
"idempotencyKey": {
|
|
140
|
+
"type": "string",
|
|
141
|
+
"minLength": 1,
|
|
142
|
+
"description": "When set, the sub-workflow's parent step output is cached against the triple (parentWorkflow, step.id, key). Cache semantics depend on `wait`: with `wait: true` (default), cache HIT means the child workflow is NEVER invoked — including any side effects (use with care for sub-workflows that send emails, charge cards, etc.). With `wait: false`, cache HIT returns the SAME `{runId, workflowName, scheduledAt}` for the lifetime of the cache entry — at-most-once dispatch deduplication. To retry on child failure, use a new key."
|
|
143
|
+
},
|
|
144
|
+
"idempotencyKeyTTL": {
|
|
145
|
+
"type": "integer",
|
|
146
|
+
"minimum": 0,
|
|
147
|
+
"description": "Cache lifetime in milliseconds. Defaults to 24h. Pass 0 to immediately expire."
|
|
148
|
+
},
|
|
149
|
+
"retry": {
|
|
150
|
+
"type": "object",
|
|
151
|
+
"properties": {
|
|
152
|
+
"maxAttempts": {
|
|
153
|
+
"type": "integer",
|
|
154
|
+
"minimum": 1,
|
|
155
|
+
"maximum": 20,
|
|
156
|
+
"description": "Total attempts including the first run. 1 = no retry. Capped at 20."
|
|
157
|
+
},
|
|
158
|
+
"minTimeoutInMs": {
|
|
159
|
+
"type": "integer",
|
|
160
|
+
"minimum": 0,
|
|
161
|
+
"description": "Initial backoff delay in ms before the second attempt. Default 1000."
|
|
162
|
+
},
|
|
163
|
+
"maxTimeoutInMs": {
|
|
164
|
+
"type": "integer",
|
|
165
|
+
"minimum": 0,
|
|
166
|
+
"description": "Cap on the backoff delay between attempts. Default 30000."
|
|
167
|
+
},
|
|
168
|
+
"factor": {
|
|
169
|
+
"type": "number",
|
|
170
|
+
"minimum": 1,
|
|
171
|
+
"description": "Exponential backoff factor: delay = min(maxTimeout, minTimeout * factor^(attempt-1)). Default 2."
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
"required": [
|
|
175
|
+
"maxAttempts"
|
|
176
|
+
],
|
|
177
|
+
"additionalProperties": false,
|
|
178
|
+
"description": "Retry the WHOLE sub-workflow on failure. Each retry creates a fresh child run record under the same parent."
|
|
179
|
+
},
|
|
180
|
+
"maxDuration": {
|
|
181
|
+
"anyOf": [
|
|
182
|
+
{
|
|
183
|
+
"type": "integer",
|
|
184
|
+
"minimum": 0
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"type": "string",
|
|
188
|
+
"minLength": 1,
|
|
189
|
+
"pattern": "^\\d+(ms|s|m|h|d)$"
|
|
190
|
+
}
|
|
191
|
+
],
|
|
192
|
+
"description": "OPTIONAL. Per-attempt execution timeout. Caps the synchronous wait for `wait: true` sub-workflows. No-op for `wait: false` (parent returns immediately; the child's max-duration is the child's concern). Number (ms) or duration string. On final-attempt timeout, the run auto-flips to `\"timedOut\"`."
|
|
193
|
+
},
|
|
194
|
+
"allowList": {
|
|
195
|
+
"type": "array",
|
|
196
|
+
"items": {
|
|
197
|
+
"type": "string",
|
|
198
|
+
"minLength": 1
|
|
199
|
+
},
|
|
200
|
+
"description": "Exact-match allow-list for polymorphic dispatch. When the resolved workflow name (after any `namespace` prefix is applied) is not in this array, the dispatch is rejected at run time with a structured error. Strongly recommended when `subworkflow` is an expression (`$.<path>` or `js/...`) so a malicious or buggy ctx value can't dispatch arbitrary workflows. Ignored for literal names (they don't need the guard)."
|
|
201
|
+
},
|
|
202
|
+
"dispatch": {
|
|
203
|
+
"type": "string",
|
|
204
|
+
"enum": [
|
|
205
|
+
"in-process",
|
|
206
|
+
"http-self"
|
|
207
|
+
],
|
|
208
|
+
"description": "G2 (v0.6) — dispatch strategy. `in-process` (default) invokes the child workflow in the same Node process — synchronous when `wait: true`, `setImmediate`-based when `wait: false`. `http-self` makes an HTTP request to the deployment's own base URL (`BLOK_SELF_BASE_URL` env var, defaults to `http://localhost:${PORT || 4000}`). Use `http-self` when you want each child run to land on a different process in a horizontally-scaled deployment, or to fully isolate child execution from the parent's call stack. The child must have an HTTP trigger; a runtime error is thrown otherwise. Lineage (parentRunId / parentNodeRunId) is preserved across the HTTP hop via `X-Blok-Parent-Run-Id` / `X-Blok-Parent-Node-Run-Id` headers."
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
"required": [
|
|
212
|
+
"id",
|
|
213
|
+
"subworkflow"
|
|
214
|
+
],
|
|
215
|
+
"additionalProperties": false
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"type": "object",
|
|
219
|
+
"properties": {
|
|
220
|
+
"id": {
|
|
221
|
+
"type": "string",
|
|
222
|
+
"minLength": 1,
|
|
223
|
+
"description": "Stable identifier."
|
|
224
|
+
},
|
|
225
|
+
"wait": {
|
|
226
|
+
"type": "object",
|
|
227
|
+
"properties": {
|
|
228
|
+
"for": {
|
|
229
|
+
"anyOf": [
|
|
230
|
+
{
|
|
231
|
+
"type": "integer",
|
|
232
|
+
"minimum": 0
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"type": "string",
|
|
236
|
+
"minLength": 1,
|
|
237
|
+
"pattern": "^\\d+(ms|s|m|h|d)$"
|
|
238
|
+
}
|
|
239
|
+
],
|
|
240
|
+
"description": "Wait this long. Mutually exclusive with `until`. Number (ms) or duration string (`500ms`, `30s`, `5m`, `2h`, `1d`)."
|
|
241
|
+
},
|
|
242
|
+
"until": {
|
|
243
|
+
"type": [
|
|
244
|
+
"number",
|
|
245
|
+
"string"
|
|
246
|
+
],
|
|
247
|
+
"description": "Wait until this absolute time. Number is ms-since-epoch; string is an ISO date or a $-proxy expression. Mutually exclusive with `for`."
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
"additionalProperties": false
|
|
251
|
+
},
|
|
252
|
+
"as": {
|
|
253
|
+
"type": "string",
|
|
254
|
+
"minLength": 1,
|
|
255
|
+
"description": "Alternative state key (defaults to `id`)."
|
|
256
|
+
},
|
|
257
|
+
"ephemeral": {
|
|
258
|
+
"type": "boolean",
|
|
259
|
+
"description": "If true, no state entry is recorded."
|
|
260
|
+
},
|
|
261
|
+
"active": {
|
|
262
|
+
"type": "boolean"
|
|
263
|
+
},
|
|
264
|
+
"stop": {
|
|
265
|
+
"type": "boolean"
|
|
266
|
+
},
|
|
267
|
+
"idempotencyKey": {
|
|
268
|
+
"not": {}
|
|
269
|
+
},
|
|
270
|
+
"retry": {
|
|
271
|
+
"not": {}
|
|
272
|
+
},
|
|
273
|
+
"maxDuration": {
|
|
274
|
+
"not": {}
|
|
275
|
+
},
|
|
276
|
+
"concurrencyKey": {
|
|
277
|
+
"not": {}
|
|
278
|
+
},
|
|
279
|
+
"spread": {
|
|
280
|
+
"not": {}
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
"required": [
|
|
284
|
+
"id",
|
|
285
|
+
"wait"
|
|
286
|
+
],
|
|
287
|
+
"additionalProperties": false
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"type": "object",
|
|
291
|
+
"properties": {
|
|
292
|
+
"id": {
|
|
293
|
+
"type": "string",
|
|
294
|
+
"minLength": 1,
|
|
295
|
+
"description": "Stable identifier for the forEach step. Visible in traces."
|
|
296
|
+
},
|
|
297
|
+
"forEach": {
|
|
298
|
+
"type": "object",
|
|
299
|
+
"properties": {
|
|
300
|
+
"in": {
|
|
301
|
+
"description": "Array source. Literal expression string (`'$.state.items'`) or `$` proxy expression."
|
|
302
|
+
},
|
|
303
|
+
"as": {
|
|
304
|
+
"type": "string",
|
|
305
|
+
"minLength": 1,
|
|
306
|
+
"pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$",
|
|
307
|
+
"description": "Per-iteration variable name. Each iteration sets ctx.state[as] = item and ctx.state[as+'Index'] = i."
|
|
308
|
+
},
|
|
309
|
+
"mode": {
|
|
310
|
+
"type": "string",
|
|
311
|
+
"enum": [
|
|
312
|
+
"sequential",
|
|
313
|
+
"parallel"
|
|
314
|
+
],
|
|
315
|
+
"description": "Execution mode. `sequential` (default) awaits each iteration; `parallel` runs with bounded concurrency."
|
|
316
|
+
},
|
|
317
|
+
"concurrency": {
|
|
318
|
+
"type": "integer",
|
|
319
|
+
"minimum": 1,
|
|
320
|
+
"maximum": 1000,
|
|
321
|
+
"description": "Max concurrent inner pipelines when `mode: 'parallel'`. Default 10."
|
|
322
|
+
},
|
|
323
|
+
"do": {
|
|
324
|
+
"type": "array",
|
|
325
|
+
"items": {},
|
|
326
|
+
"minItems": 1,
|
|
327
|
+
"description": "Sub-pipeline run for each item."
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
"required": [
|
|
331
|
+
"as",
|
|
332
|
+
"do"
|
|
333
|
+
],
|
|
334
|
+
"additionalProperties": false,
|
|
335
|
+
"description": "forEach configuration."
|
|
336
|
+
},
|
|
337
|
+
"active": {
|
|
338
|
+
"type": "boolean"
|
|
339
|
+
},
|
|
340
|
+
"stop": {
|
|
341
|
+
"type": "boolean"
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
"required": [
|
|
345
|
+
"id",
|
|
346
|
+
"forEach"
|
|
347
|
+
],
|
|
348
|
+
"additionalProperties": false
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
"type": "object",
|
|
352
|
+
"properties": {
|
|
353
|
+
"id": {
|
|
354
|
+
"type": "string",
|
|
355
|
+
"minLength": 1,
|
|
356
|
+
"description": "Stable identifier for the loop step. Visible in traces."
|
|
357
|
+
},
|
|
358
|
+
"loop": {
|
|
359
|
+
"type": "object",
|
|
360
|
+
"properties": {
|
|
361
|
+
"while": {
|
|
362
|
+
"type": "string",
|
|
363
|
+
"minLength": 1,
|
|
364
|
+
"description": "JS expression evaluated against ctx before each iteration. Loop continues while truthy."
|
|
365
|
+
},
|
|
366
|
+
"maxIterations": {
|
|
367
|
+
"type": "integer",
|
|
368
|
+
"minimum": 1,
|
|
369
|
+
"description": "Hard safety cap on iterations. Default 1000 (override via env BLOK_LOOP_MAX_ITERATIONS). Hitting the cap throws LoopMaxIterationsError."
|
|
370
|
+
},
|
|
371
|
+
"do": {
|
|
372
|
+
"type": "array",
|
|
373
|
+
"items": {},
|
|
374
|
+
"minItems": 1,
|
|
375
|
+
"description": "Sub-pipeline run each iteration."
|
|
376
|
+
}
|
|
377
|
+
},
|
|
378
|
+
"required": [
|
|
379
|
+
"while",
|
|
380
|
+
"do"
|
|
381
|
+
],
|
|
382
|
+
"additionalProperties": false,
|
|
383
|
+
"description": "loop configuration."
|
|
384
|
+
},
|
|
385
|
+
"active": {
|
|
386
|
+
"type": "boolean"
|
|
387
|
+
},
|
|
388
|
+
"stop": {
|
|
389
|
+
"type": "boolean"
|
|
390
|
+
}
|
|
391
|
+
},
|
|
392
|
+
"required": [
|
|
393
|
+
"id",
|
|
394
|
+
"loop"
|
|
395
|
+
],
|
|
396
|
+
"additionalProperties": false
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
"type": "object",
|
|
400
|
+
"properties": {
|
|
401
|
+
"id": {
|
|
402
|
+
"type": "string",
|
|
403
|
+
"minLength": 1,
|
|
404
|
+
"description": "Stable identifier for the switch step. Visible in traces."
|
|
405
|
+
},
|
|
406
|
+
"switch": {
|
|
407
|
+
"type": "object",
|
|
408
|
+
"properties": {
|
|
409
|
+
"on": {
|
|
410
|
+
"description": "Value to match against. Literal, `$` proxy expression, or `js/...` string. Resolved by the blueprint mapper before matching."
|
|
411
|
+
},
|
|
412
|
+
"cases": {
|
|
413
|
+
"type": "array",
|
|
414
|
+
"items": {
|
|
415
|
+
"type": "object",
|
|
416
|
+
"properties": {
|
|
417
|
+
"when": {
|
|
418
|
+
"description": "Match value. Literal scalar (number/string/boolean) for `on === when` matching, or an array for `array.includes(on)` matching."
|
|
419
|
+
},
|
|
420
|
+
"do": {
|
|
421
|
+
"type": "array",
|
|
422
|
+
"items": {},
|
|
423
|
+
"minItems": 1,
|
|
424
|
+
"description": "Sub-pipeline run when this case matches."
|
|
425
|
+
}
|
|
426
|
+
},
|
|
427
|
+
"required": [
|
|
428
|
+
"do"
|
|
429
|
+
],
|
|
430
|
+
"additionalProperties": false
|
|
431
|
+
},
|
|
432
|
+
"minItems": 1,
|
|
433
|
+
"description": "Ordered list of cases. First match wins."
|
|
434
|
+
},
|
|
435
|
+
"default": {
|
|
436
|
+
"type": "array",
|
|
437
|
+
"items": {},
|
|
438
|
+
"description": "Fallback sub-pipeline when no case matches. Optional."
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
"required": [
|
|
442
|
+
"cases"
|
|
443
|
+
],
|
|
444
|
+
"additionalProperties": false,
|
|
445
|
+
"description": "switch configuration."
|
|
446
|
+
},
|
|
447
|
+
"active": {
|
|
448
|
+
"type": "boolean"
|
|
449
|
+
},
|
|
450
|
+
"stop": {
|
|
451
|
+
"type": "boolean"
|
|
452
|
+
}
|
|
453
|
+
},
|
|
454
|
+
"required": [
|
|
455
|
+
"id",
|
|
456
|
+
"switch"
|
|
457
|
+
],
|
|
458
|
+
"additionalProperties": false
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
"type": "object",
|
|
462
|
+
"properties": {
|
|
463
|
+
"id": {
|
|
464
|
+
"type": "string",
|
|
465
|
+
"minLength": 1,
|
|
466
|
+
"description": "Stable identifier for the tryCatch step. Visible in traces."
|
|
467
|
+
},
|
|
468
|
+
"tryCatch": {
|
|
469
|
+
"type": "object",
|
|
470
|
+
"properties": {
|
|
471
|
+
"try": {
|
|
472
|
+
"type": "array",
|
|
473
|
+
"items": {},
|
|
474
|
+
"minItems": 1,
|
|
475
|
+
"description": "Sub-pipeline run first. If any step throws, control jumps to `catch`."
|
|
476
|
+
},
|
|
477
|
+
"catch": {
|
|
478
|
+
"type": "array",
|
|
479
|
+
"items": {},
|
|
480
|
+
"minItems": 1,
|
|
481
|
+
"description": "Sub-pipeline run when `try` throws. Has access to `$.error` (message, name, stack). Errors here propagate — they do NOT re-trigger catch."
|
|
482
|
+
},
|
|
483
|
+
"finally": {
|
|
484
|
+
"type": "array",
|
|
485
|
+
"items": {},
|
|
486
|
+
"description": "Sub-pipeline run unconditionally after try/catch. Runs even if `catch` itself throws. Errors here propagate."
|
|
487
|
+
}
|
|
488
|
+
},
|
|
489
|
+
"required": [
|
|
490
|
+
"try",
|
|
491
|
+
"catch"
|
|
492
|
+
],
|
|
493
|
+
"additionalProperties": false,
|
|
494
|
+
"description": "tryCatch configuration."
|
|
495
|
+
},
|
|
496
|
+
"active": {
|
|
497
|
+
"type": "boolean"
|
|
498
|
+
},
|
|
499
|
+
"stop": {
|
|
500
|
+
"type": "boolean"
|
|
501
|
+
}
|
|
502
|
+
},
|
|
503
|
+
"required": [
|
|
504
|
+
"id",
|
|
505
|
+
"tryCatch"
|
|
506
|
+
],
|
|
507
|
+
"additionalProperties": false
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
"type": "object",
|
|
511
|
+
"properties": {
|
|
512
|
+
"id": {
|
|
513
|
+
"type": "string",
|
|
514
|
+
"minLength": 1,
|
|
515
|
+
"description": "Stable identifier. Other steps reference this step's output as $.state[id]. Required."
|
|
516
|
+
},
|
|
517
|
+
"use": {
|
|
518
|
+
"type": "string",
|
|
519
|
+
"minLength": 1,
|
|
520
|
+
"description": "Node reference. Examples: '@blokjs/api-call', 'my-custom-node'. Type is inferred from this value when `type` is not set."
|
|
521
|
+
},
|
|
522
|
+
"type": {
|
|
523
|
+
"type": "string",
|
|
524
|
+
"enum": [
|
|
525
|
+
"local",
|
|
526
|
+
"module",
|
|
527
|
+
"runtime.python3",
|
|
528
|
+
"runtime.nodejs",
|
|
529
|
+
"runtime.bun",
|
|
530
|
+
"runtime.go",
|
|
531
|
+
"runtime.java",
|
|
532
|
+
"runtime.rust",
|
|
533
|
+
"runtime.php",
|
|
534
|
+
"runtime.csharp",
|
|
535
|
+
"runtime.ruby",
|
|
536
|
+
"runtime.docker",
|
|
537
|
+
"runtime.wasm"
|
|
538
|
+
],
|
|
539
|
+
"description": "Node type (module/local/runtime.*). When omitted, inferred from `use`: runtime.* prefixes are explicit; @blokjs/* and most others default to 'module'."
|
|
540
|
+
},
|
|
541
|
+
"inputs": {
|
|
542
|
+
"type": "object",
|
|
543
|
+
"additionalProperties": {},
|
|
544
|
+
"description": "Inputs passed to the node. May contain $ proxy references (e.g. $.state.foo, $.req.body.id) or 'js/...' expressions for runtime evaluation."
|
|
545
|
+
},
|
|
546
|
+
"as": {
|
|
547
|
+
"type": "string",
|
|
548
|
+
"minLength": 1,
|
|
549
|
+
"description": "Alternative name for this step's output in state. Defaults to `id`. Useful when the id is implementation-detail-y and the output is referenced by a domain term."
|
|
550
|
+
},
|
|
551
|
+
"spread": {
|
|
552
|
+
"type": "boolean",
|
|
553
|
+
"description": "If true, the result.data object's top-level keys are shallow-merged into state. Use for multi-output nodes in data-pipeline workflows. Mutually exclusive with `as`."
|
|
554
|
+
},
|
|
555
|
+
"ephemeral": {
|
|
556
|
+
"type": "boolean",
|
|
557
|
+
"description": "If true, this step's output is NOT stored in state. Only ctx.prev carries it to the immediately next step. Use for side-effects (logging, audit, telemetry)."
|
|
558
|
+
},
|
|
559
|
+
"runtime": {
|
|
560
|
+
"type": "string",
|
|
561
|
+
"enum": [
|
|
562
|
+
"nodejs",
|
|
563
|
+
"bun",
|
|
564
|
+
"python3",
|
|
565
|
+
"go",
|
|
566
|
+
"java",
|
|
567
|
+
"rust",
|
|
568
|
+
"php",
|
|
569
|
+
"csharp",
|
|
570
|
+
"ruby",
|
|
571
|
+
"docker",
|
|
572
|
+
"wasm"
|
|
573
|
+
],
|
|
574
|
+
"description": "Optional runtime hint. Most authors don't need this; the type already encodes it."
|
|
575
|
+
},
|
|
576
|
+
"active": {
|
|
577
|
+
"type": "boolean",
|
|
578
|
+
"description": "If false, the step is skipped at runtime. Default true."
|
|
579
|
+
},
|
|
580
|
+
"stop": {
|
|
581
|
+
"type": "boolean",
|
|
582
|
+
"description": "If true, the workflow halts after this step completes. Default false."
|
|
583
|
+
},
|
|
584
|
+
"stream_logs": {
|
|
585
|
+
"type": "boolean",
|
|
586
|
+
"description": "Per-step opt-in for live log streaming. Inherits from BLOK_STREAM_LOGS env when unset."
|
|
587
|
+
},
|
|
588
|
+
"idempotencyKey": {
|
|
589
|
+
"type": "string",
|
|
590
|
+
"minLength": 1,
|
|
591
|
+
"description": "When set, the step's result is cached against the triple (workflowName, step.id, idempotencyKey). On a subsequent run with the same triple, execution is skipped and the cached result populates state through the same persistence rules (ephemeral / spread / as). Accepts a literal string or a $ proxy expression that compiles to `js/ctx....` (e.g. $.req.body.requestId)."
|
|
592
|
+
},
|
|
593
|
+
"idempotencyKeyTTL": {
|
|
594
|
+
"type": "integer",
|
|
595
|
+
"minimum": 0,
|
|
596
|
+
"description": "Cache lifetime in milliseconds. Defaults to 24h (86_400_000) when omitted. Pass 0 to mark a cached result as immediately expired (effectively disables caching)."
|
|
597
|
+
},
|
|
598
|
+
"retry": {
|
|
599
|
+
"type": "object",
|
|
600
|
+
"properties": {
|
|
601
|
+
"maxAttempts": {
|
|
602
|
+
"type": "integer",
|
|
603
|
+
"minimum": 1,
|
|
604
|
+
"maximum": 20,
|
|
605
|
+
"description": "Total attempts including the first run. 1 = no retry. Capped at 20."
|
|
606
|
+
},
|
|
607
|
+
"minTimeoutInMs": {
|
|
608
|
+
"type": "integer",
|
|
609
|
+
"minimum": 0,
|
|
610
|
+
"description": "Initial backoff delay in ms before the second attempt. Default 1000."
|
|
611
|
+
},
|
|
612
|
+
"maxTimeoutInMs": {
|
|
613
|
+
"type": "integer",
|
|
614
|
+
"minimum": 0,
|
|
615
|
+
"description": "Cap on the backoff delay between attempts. Default 30000."
|
|
616
|
+
},
|
|
617
|
+
"factor": {
|
|
618
|
+
"type": "number",
|
|
619
|
+
"minimum": 1,
|
|
620
|
+
"description": "Exponential backoff factor: delay = min(maxTimeout, minTimeout * factor^(attempt-1)). Default 2."
|
|
621
|
+
}
|
|
622
|
+
},
|
|
623
|
+
"required": [
|
|
624
|
+
"maxAttempts"
|
|
625
|
+
],
|
|
626
|
+
"additionalProperties": false,
|
|
627
|
+
"description": "Retry configuration with capped exponential backoff. When omitted, the step runs at most once (no retry) — matches pre-v0.3.x behavior."
|
|
628
|
+
},
|
|
629
|
+
"maxDuration": {
|
|
630
|
+
"anyOf": [
|
|
631
|
+
{
|
|
632
|
+
"type": "integer",
|
|
633
|
+
"minimum": 0
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
"type": "string",
|
|
637
|
+
"minLength": 1,
|
|
638
|
+
"pattern": "^\\d+(ms|s|m|h|d)$"
|
|
639
|
+
}
|
|
640
|
+
],
|
|
641
|
+
"description": "OPTIONAL. Per-attempt execution timeout. Number (ms) or duration string ('30s', '5m', '500ms'). When the step's `step.process()` exceeds this duration, the attempt fails with a StepTimeoutError. Pairs with `retry` — each attempt gets its own timeout (total budget = maxDuration × maxAttempts). On final-attempt timeout, the run auto-flips to `\"timedOut\"` status (distinct from `\"failed\"` so SLA dashboards can separate timeouts from logic failures)."
|
|
642
|
+
}
|
|
643
|
+
},
|
|
644
|
+
"required": [
|
|
645
|
+
"id",
|
|
646
|
+
"use"
|
|
647
|
+
],
|
|
648
|
+
"additionalProperties": false
|
|
649
|
+
}
|
|
650
|
+
]
|
|
651
|
+
},
|
|
652
|
+
"minItems": 1,
|
|
653
|
+
"description": "Pipeline of steps to execute in order. At least one step required."
|
|
654
|
+
}
|
|
655
|
+
},
|
|
656
|
+
"required": [
|
|
657
|
+
"name",
|
|
658
|
+
"version",
|
|
659
|
+
"steps"
|
|
660
|
+
],
|
|
661
|
+
"additionalProperties": false
|
|
662
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blokjs/helper",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18.0.0"
|
|
@@ -8,14 +8,13 @@
|
|
|
8
8
|
"type": "module",
|
|
9
9
|
"main": "dist/index.js",
|
|
10
10
|
"types": "dist/index.d.ts",
|
|
11
|
-
"files": [
|
|
12
|
-
"dist"
|
|
13
|
-
],
|
|
11
|
+
"files": ["dist"],
|
|
14
12
|
"author": "Marco A. Castillo Della Sera",
|
|
15
13
|
"license": "MIT",
|
|
16
14
|
"scripts": {
|
|
17
|
-
"build": "rm -rf dist && bun run tsc",
|
|
15
|
+
"build": "rm -rf dist && bun run tsc && bun run build:schema",
|
|
18
16
|
"build:dev": "tsc --watch",
|
|
17
|
+
"build:schema": "bun run scripts/build-schema.ts",
|
|
19
18
|
"test:dev": "vitest",
|
|
20
19
|
"test": "vitest run",
|
|
21
20
|
"typecheck": "tsc --noEmit --incremental"
|
|
@@ -23,7 +22,8 @@
|
|
|
23
22
|
"devDependencies": {
|
|
24
23
|
"@types/node": "^22.15.21",
|
|
25
24
|
"typescript": "^5.8.3",
|
|
26
|
-
"vitest": "^4.0.18"
|
|
25
|
+
"vitest": "^4.0.18",
|
|
26
|
+
"zod-to-json-schema": "^3.25.2"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"zod": "^3.24.2"
|