@fluidgrids/workflows 2026.1027.1 → 2026.1028.1
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/README.md +144 -13
- package/dist/activation-BBh1p82z.d.cts +57 -0
- package/dist/activation-DnhG7SmF.d.ts +57 -0
- package/dist/assemble-BLqQ8lSu.d.cts +39 -0
- package/dist/assemble-DWgaXHd-.d.ts +39 -0
- package/dist/chunk-2DP2Y6EU.cjs +832 -0
- package/dist/chunk-2J6TF7YI.cjs +86 -0
- package/dist/chunk-3FOTFQ3J.js +1622 -0
- package/dist/chunk-4LYSEANA.js +199 -0
- package/dist/{chunk-TQF7MYEN.cjs → chunk-57MSZ24T.cjs} +134 -96
- package/dist/{chunk-EEAIM35V.js → chunk-5HDSBTBX.js} +64 -23
- package/dist/chunk-623FVQSN.cjs +251 -0
- package/dist/{chunk-W32BSO3M.js → chunk-6FSHT5IL.js} +2 -2
- package/dist/{chunk-E3APHA6O.cjs → chunk-7AAZGVKD.js} +1 -64
- package/dist/chunk-7NQ37GZU.js +73 -0
- package/dist/chunk-ABFZWYHT.js +612 -0
- package/dist/{chunk-6U446SKY.js → chunk-BD7ZPG53.js} +2 -2
- package/dist/chunk-BO6OVILK.js +79 -0
- package/dist/chunk-C5OLWZ42.js +245 -0
- package/dist/chunk-CBL5JSCC.cjs +75 -0
- package/dist/{chunk-OSPTJCDI.cjs → chunk-CPDK3K5N.cjs} +6 -6
- package/dist/chunk-CSNWNFKU.cjs +1635 -0
- package/dist/chunk-DJYMDLV5.js +227 -0
- package/dist/{chunk-IHKXLG6I.js → chunk-E2VK7J2C.js} +1 -1
- package/dist/chunk-FMSW2HDF.cjs +267 -0
- package/dist/chunk-FQIHX7YI.cjs +80 -0
- package/dist/chunk-FR7KYWRO.cjs +41 -0
- package/dist/{chunk-7YR7DI7B.cjs → chunk-GBQ33SIZ.cjs} +44 -44
- package/dist/{chunk-6AIAC2FP.cjs → chunk-GVTZMA5C.cjs} +4 -4
- package/dist/chunk-H7KEVW2M.js +816 -0
- package/dist/{chunk-3M34AUIY.cjs → chunk-HR3BN4C4.cjs} +3 -3
- package/dist/chunk-IISBRUWJ.js +13 -0
- package/dist/chunk-JD2VQIDZ.cjs +15 -0
- package/dist/{chunk-UB2BHU2M.js → chunk-JZ4TOOLN.js} +1 -1
- package/dist/chunk-L24YIZY7.cjs +207 -0
- package/dist/chunk-LNUQE6D6.js +39 -0
- package/dist/{chunk-TWOYB4Y7.cjs → chunk-NEIUQASE.cjs} +13 -13
- package/dist/chunk-P6TA5EZT.cjs +634 -0
- package/dist/chunk-PDHLTDZB.js +72 -0
- package/dist/chunk-PMCM2OH4.js +46 -0
- package/dist/chunk-PZCVF76Q.cjs +868 -0
- package/dist/{chunk-6BEW4QD6.js → chunk-QAN5MZEM.js} +1 -1
- package/dist/{chunk-CSYBNN3V.cjs → chunk-QKZL3ONM.cjs} +2 -2
- package/dist/chunk-SAENRNBJ.cjs +52 -0
- package/dist/{chunk-XBIID5DY.js → chunk-SMCANK3F.js} +5 -4
- package/dist/{chunk-UWQWD7BP.cjs → chunk-SX2PNKKT.cjs} +18 -17
- package/dist/{chunk-UJNHTS6D.js → chunk-TBDXTV22.cjs} +8 -45
- package/dist/chunk-VOKMAAJP.js +848 -0
- package/dist/{chunk-5AW745OG.js → chunk-XB53G2DK.js} +1 -1
- package/dist/chunk-Z2Y65YOY.cjs +7 -0
- package/dist/codegen/index.cjs +9 -7
- package/dist/codegen/index.d.cts +2 -2
- package/dist/codegen/index.d.ts +2 -2
- package/dist/codegen/index.js +6 -5
- package/dist/file-BOoHZgoQ.d.cts +1557 -0
- package/dist/file-yuPCFU5b.d.ts +1557 -0
- package/dist/history/index.cjs +287 -0
- package/dist/history/index.d.cts +157 -0
- package/dist/history/index.d.ts +157 -0
- package/dist/history/index.js +5 -0
- package/dist/index.cjs +134 -36
- package/dist/index.d.cts +137 -9
- package/dist/index.d.ts +137 -9
- package/dist/index.js +8 -3
- package/dist/ir/index.cjs +152 -158
- package/dist/ir/index.d.cts +14 -4
- package/dist/ir/index.d.ts +14 -4
- package/dist/ir/index.js +41 -50
- package/dist/lower-BuSvAFqi.d.cts +129 -0
- package/dist/lower-C_Qv_34S.d.ts +129 -0
- package/dist/lower-types-nofRXw9c.d.cts +15 -0
- package/dist/lower-types-nofRXw9c.d.ts +15 -0
- package/dist/{manifest-Duf-gHdO.d.cts → manifest-0OLw0i7k.d.cts} +1 -1
- package/dist/{manifest-Bp9ZJlav.d.ts → manifest-C8N6HDYl.d.ts} +1 -1
- package/dist/node-evaluator-CJNP4GHX.js +12 -0
- package/dist/node-evaluator-DMKPKUWA.cjs +22 -0
- package/dist/quickjs/index.cjs +236 -12
- package/dist/quickjs/index.d.cts +46 -5
- package/dist/quickjs/index.d.ts +46 -5
- package/dist/quickjs/index.js +230 -9
- package/dist/roundtrip/index.cjs +333 -131
- package/dist/roundtrip/index.d.cts +39 -7
- package/dist/roundtrip/index.d.ts +39 -7
- package/dist/roundtrip/index.js +185 -13
- package/dist/runtime/index.cjs +90 -0
- package/dist/runtime/index.d.cts +297 -0
- package/dist/runtime/index.d.ts +297 -0
- package/dist/runtime/index.js +8 -0
- package/dist/testing/index.cjs +1057 -0
- package/dist/testing/index.d.cts +305 -0
- package/dist/testing/index.d.ts +305 -0
- package/dist/testing/index.js +1037 -0
- package/dist/{types-Dr2Fn1Ax.d.ts → types-BGoPzgcl.d.cts} +1 -1
- package/dist/{types-Dr2Fn1Ax.d.cts → types-BGoPzgcl.d.ts} +1 -1
- package/dist/types-CpBBjaGX.d.cts +380 -0
- package/dist/types-DV-HX_Gt.d.ts +380 -0
- package/dist/{assemble-CrpUyd_3.d.ts → workflow-Bpr3vnA_.d.ts} +40 -160
- package/dist/workflow-C2a05WUJ.d.ts +444 -0
- package/dist/{assemble-DEf3znGD.d.cts → workflow-FXUkpIBc.d.cts} +40 -160
- package/dist/workflow-J-yYixny.d.cts +444 -0
- package/fixtures/README.md +128 -0
- package/fixtures/histories/activity-failure-fails-run.history.json +163 -0
- package/fixtures/histories/activity-retry-then-success.history.json +147 -0
- package/fixtures/histories/cancel-activity-abandon.history.json +126 -0
- package/fixtures/histories/cancel-activity-compensate.history.json +307 -0
- package/fixtures/histories/cancel-concurrent-non-cancellable.history.json +234 -0
- package/fixtures/histories/cancel-concurrent-scope-timeout.history.json +184 -0
- package/fixtures/histories/cancel-condition-after-cancel.history.json +200 -0
- package/fixtures/histories/cancel-during-timer.history.json +123 -0
- package/fixtures/histories/cancel-saga-compensations.history.json +325 -0
- package/fixtures/histories/cancel-scope-timeout.history.json +148 -0
- package/fixtures/histories/child-abandon-outlives-parent.history.json +191 -0
- package/fixtures/histories/child-cancel-default.history.json +234 -0
- package/fixtures/histories/child-cancel-request.history.json +206 -0
- package/fixtures/histories/child-durable-child-side.history.json +124 -0
- package/fixtures/histories/child-durable-result.history.json +163 -0
- package/fixtures/histories/child-failure-caught.history.json +166 -0
- package/fixtures/histories/child-graph-by-key.history.json +138 -0
- package/fixtures/histories/child-terminated-by-parent-close.history.json +85 -0
- package/fixtures/histories/continue-as-new-first-run.history.json +146 -0
- package/fixtures/histories/continue-as-new-history-limit.history.json +489 -0
- package/fixtures/histories/continue-as-new-last-run.history.json +147 -0
- package/fixtures/histories/continue-as-new-suggested.history.json +352 -0
- package/fixtures/histories/details-and-context.history.json +176 -0
- package/fixtures/histories/deterministic-values.history.json +128 -0
- package/fixtures/histories/engine-builtins.history.json +172 -0
- package/fixtures/histories/gather-activities.history.json +291 -0
- package/fixtures/histories/gather-all-settled.history.json +219 -0
- package/fixtures/histories/gather-mixed.history.json +281 -0
- package/fixtures/histories/input-during-running-task.history.json +111 -0
- package/fixtures/histories/nondeterminism-reordered.history.json +218 -0
- package/fixtures/histories/patched-deprecated.history.json +271 -0
- package/fixtures/histories/patched-new-run.history.json +270 -0
- package/fixtures/histories/patched-old-history.history.json +190 -0
- package/fixtures/histories/race-activity-wins.history.json +152 -0
- package/fixtures/histories/race-signal-beats-child.history.json +161 -0
- package/fixtures/histories/race-timeout-wins.history.json +118 -0
- package/fixtures/histories/side-effect-recorded.history.json +153 -0
- package/fixtures/histories/signal-buffered-at-start.history.json +157 -0
- package/fixtures/histories/signal-default-handler.history.json +187 -0
- package/fixtures/histories/signal-handler.history.json +191 -0
- package/fixtures/histories/signal-parent-child-side.history.json +132 -0
- package/fixtures/histories/signal-parent.history.json +202 -0
- package/fixtures/histories/signal-run-delivered.history.json +128 -0
- package/fixtures/histories/signal-run-undelivered.history.json +134 -0
- package/fixtures/histories/signal-wait.history.json +111 -0
- package/fixtures/histories/task-failure-code-error.history.json +137 -0
- package/fixtures/histories/task-failure-then-transient-attempt.history.json +140 -0
- package/fixtures/histories/timer-condition-met.history.json +201 -0
- package/fixtures/histories/timer-condition-timeout.history.json +118 -0
- package/fixtures/histories/timer-sleep-once.history.json +118 -0
- package/fixtures/histories/timer-sleep-sequence.history.json +210 -0
- package/fixtures/histories/update-accepted-completed.history.json +149 -0
- package/fixtures/histories/update-with-start-rejected-validation.history.json +91 -0
- package/package.json +44 -5
- package/schema/history-file.schema.json +2544 -0
- package/schema/ir-v2.schema.json +16 -0
- package/schema/run-event.schema.json +2374 -0
- package/schema/workflow-command.schema.json +1095 -0
- package/schema/workflow-task.schema.json +3560 -0
- package/dist/chunk-MBBKGD7K.js +0 -440
- package/dist/chunk-Y7NWR3WH.cjs +0 -450
- package/dist/lower-CXggJTIo.d.ts +0 -67
- package/dist/lower-DAzvsJCo.d.cts +0 -67
- package/dist/node-evaluator-CH3XCJND.cjs +0 -17
- package/dist/node-evaluator-TULXA3WE.js +0 -8
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
import { a as Json, J as JsonObject, W as WorkflowInterface } from './types-BGoPzgcl.cjs';
|
|
2
|
+
import { a6 as WorkflowInfoSnapshot, R as RetryPolicy, c as ActivityCancellationType, w as Headers, P as ParentClosePolicy, C as ChildCancellationType } from './types-CpBBjaGX.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Node operation descriptors: what a builder call needs to know about the node
|
|
6
|
+
* it emits. Generated clients (`.fluidgrids/nodes.ts`) are lists of these;
|
|
7
|
+
* the built-in internal nodes and triggers ship here so `nodes.internal.*` and
|
|
8
|
+
* `triggers.*` work without a registry.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** A file reference in node inputs and outputs. */
|
|
12
|
+
interface FileRef {
|
|
13
|
+
fileId: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
mimeType?: string;
|
|
16
|
+
size?: number;
|
|
17
|
+
}
|
|
18
|
+
declare const OPERATION_TYPES: unique symbol;
|
|
19
|
+
/** One node operation. `In` and `Out` type the arguments and the output. */
|
|
20
|
+
interface Operation<In = Record<string, Json>, Out = Json> {
|
|
21
|
+
readonly kind: 'operation';
|
|
22
|
+
readonly nodeType: string;
|
|
23
|
+
/** Written as the node's `version` unless the call overrides it. */
|
|
24
|
+
readonly version?: string;
|
|
25
|
+
/** Written as the node's `operation_name` unless the call overrides it. */
|
|
26
|
+
readonly operation?: string;
|
|
27
|
+
readonly role?: 'trigger';
|
|
28
|
+
/** Type-level only; never present at run time. */
|
|
29
|
+
readonly [OPERATION_TYPES]?: {
|
|
30
|
+
input: In;
|
|
31
|
+
output: Out;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** A trigger operation. */
|
|
35
|
+
type TriggerOperation<In = Record<string, Json>, Out = Json> = Operation<In, Out> & {
|
|
36
|
+
readonly role: 'trigger';
|
|
37
|
+
};
|
|
38
|
+
/** Describe a node operation (generated clients call this). */
|
|
39
|
+
declare function op<In = Record<string, Json>, Out = Json>(nodeType: string, version?: string, operation?: string): Operation<In, Out>;
|
|
40
|
+
/** Describe a trigger operation (generated clients call this). */
|
|
41
|
+
declare function trigger<In = Record<string, Json>, Out = Json>(nodeType: string, version?: string, operation?: string): TriggerOperation<In, Out>;
|
|
42
|
+
/** True for a value made by {@link op} or {@link trigger}. */
|
|
43
|
+
declare function isOperation(value: unknown): value is Operation<unknown, unknown>;
|
|
44
|
+
/** Built-in trigger nodes (`wspace-workflow-svc` `triggers/manifests`). */
|
|
45
|
+
declare const triggers: {
|
|
46
|
+
readonly api: TriggerOperation<Record<string, Json>, Json>;
|
|
47
|
+
readonly manual: TriggerOperation<Record<string, Json>, Json>;
|
|
48
|
+
readonly schedule: TriggerOperation<Record<string, Json>, Json>;
|
|
49
|
+
readonly webhook: TriggerOperation<Record<string, Json>, Json>;
|
|
50
|
+
readonly form: TriggerOperation<Record<string, Json>, Json>;
|
|
51
|
+
readonly errorTrigger: TriggerOperation<Record<string, Json>, Json>;
|
|
52
|
+
readonly workflowCall: TriggerOperation<Record<string, Json>, Json>;
|
|
53
|
+
readonly rssFeed: TriggerOperation<Record<string, Json>, Json>;
|
|
54
|
+
readonly httpPoll: TriggerOperation<Record<string, Json>, Json>;
|
|
55
|
+
readonly databasePoll: TriggerOperation<Record<string, Json>, Json>;
|
|
56
|
+
readonly emailImap: TriggerOperation<Record<string, Json>, Json>;
|
|
57
|
+
readonly fileUpload: TriggerOperation<Record<string, Json>, Json>;
|
|
58
|
+
readonly recordChange: TriggerOperation<Record<string, Json>, Json>;
|
|
59
|
+
readonly stateChange: TriggerOperation<Record<string, Json>, Json>;
|
|
60
|
+
};
|
|
61
|
+
/** Built-in internal nodes (`wspace-workflow-svc` `internalnodes/manifests`, plus the two IR v2 nodes). */
|
|
62
|
+
declare const internalNodes: {
|
|
63
|
+
readonly merge: Operation<Record<string, Json>, Json>;
|
|
64
|
+
readonly if: Operation<Record<string, Json>, Json>;
|
|
65
|
+
readonly switch: Operation<Record<string, Json>, Json>;
|
|
66
|
+
readonly loop: Operation<Record<string, Json>, Json>;
|
|
67
|
+
readonly set: Operation<Record<string, Json>, Json>;
|
|
68
|
+
readonly filter: Operation<Record<string, Json>, Json>;
|
|
69
|
+
readonly aggregate: Operation<Record<string, Json>, Json>;
|
|
70
|
+
readonly wait: Operation<Record<string, Json>, Json>;
|
|
71
|
+
readonly noop: Operation<Record<string, Json>, Json>;
|
|
72
|
+
readonly code: Operation<Record<string, Json>, Json>;
|
|
73
|
+
readonly http: Operation<Record<string, Json>, Json>;
|
|
74
|
+
readonly transform: Operation<Record<string, Json>, Json>;
|
|
75
|
+
readonly validate: Operation<Record<string, Json>, Json>;
|
|
76
|
+
readonly log: Operation<Record<string, Json>, Json>;
|
|
77
|
+
readonly error: Operation<Record<string, Json>, Json>;
|
|
78
|
+
readonly subworkflow: Operation<Record<string, Json>, Json>;
|
|
79
|
+
readonly compareDatasets: Operation<Record<string, Json>, Json>;
|
|
80
|
+
readonly splitOut: Operation<Record<string, Json>, Json>;
|
|
81
|
+
readonly limit: Operation<Record<string, Json>, Json>;
|
|
82
|
+
readonly dedupe: Operation<Record<string, Json>, Json>;
|
|
83
|
+
readonly sort: Operation<Record<string, Json>, Json>;
|
|
84
|
+
readonly dataTable: Operation<Record<string, Json>, Json>;
|
|
85
|
+
readonly respondToWebhook: Operation<Record<string, Json>, Json>;
|
|
86
|
+
readonly sendAndWait: Operation<Record<string, Json>, Json>;
|
|
87
|
+
readonly codeWorkflow: Operation<Record<string, Json>, Json>;
|
|
88
|
+
readonly waitForSignal: Operation<Record<string, Json>, Json>;
|
|
89
|
+
};
|
|
90
|
+
/** Node clients that need no registry: the internal nodes and `custom()`. */
|
|
91
|
+
declare const nodes: {
|
|
92
|
+
readonly internal: {
|
|
93
|
+
readonly merge: Operation<Record<string, Json>, Json>;
|
|
94
|
+
readonly if: Operation<Record<string, Json>, Json>;
|
|
95
|
+
readonly switch: Operation<Record<string, Json>, Json>;
|
|
96
|
+
readonly loop: Operation<Record<string, Json>, Json>;
|
|
97
|
+
readonly set: Operation<Record<string, Json>, Json>;
|
|
98
|
+
readonly filter: Operation<Record<string, Json>, Json>;
|
|
99
|
+
readonly aggregate: Operation<Record<string, Json>, Json>;
|
|
100
|
+
readonly wait: Operation<Record<string, Json>, Json>;
|
|
101
|
+
readonly noop: Operation<Record<string, Json>, Json>;
|
|
102
|
+
readonly code: Operation<Record<string, Json>, Json>;
|
|
103
|
+
readonly http: Operation<Record<string, Json>, Json>;
|
|
104
|
+
readonly transform: Operation<Record<string, Json>, Json>;
|
|
105
|
+
readonly validate: Operation<Record<string, Json>, Json>;
|
|
106
|
+
readonly log: Operation<Record<string, Json>, Json>;
|
|
107
|
+
readonly error: Operation<Record<string, Json>, Json>;
|
|
108
|
+
readonly subworkflow: Operation<Record<string, Json>, Json>;
|
|
109
|
+
readonly compareDatasets: Operation<Record<string, Json>, Json>;
|
|
110
|
+
readonly splitOut: Operation<Record<string, Json>, Json>;
|
|
111
|
+
readonly limit: Operation<Record<string, Json>, Json>;
|
|
112
|
+
readonly dedupe: Operation<Record<string, Json>, Json>;
|
|
113
|
+
readonly sort: Operation<Record<string, Json>, Json>;
|
|
114
|
+
readonly dataTable: Operation<Record<string, Json>, Json>;
|
|
115
|
+
readonly respondToWebhook: Operation<Record<string, Json>, Json>;
|
|
116
|
+
readonly sendAndWait: Operation<Record<string, Json>, Json>;
|
|
117
|
+
readonly codeWorkflow: Operation<Record<string, Json>, Json>;
|
|
118
|
+
readonly waitForSignal: Operation<Record<string, Json>, Json>;
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* Any node type, including ones the registry snapshot does not know. Typed
|
|
122
|
+
* as JSON in and out.
|
|
123
|
+
*/
|
|
124
|
+
readonly custom: (nodeType: string, operation?: string, version?: string) => Operation<Record<string, Json>, Json>;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Signal, query and update definitions (spec 02 §4, 05). Signals work in Phase
|
|
129
|
+
* B; queries and updates can be declared (they appear in the interface) but
|
|
130
|
+
* custom handlers are Phase C.
|
|
131
|
+
*/
|
|
132
|
+
declare const PAYLOAD: unique symbol;
|
|
133
|
+
interface SignalDefinition<Payload = unknown> {
|
|
134
|
+
readonly kind: 'signal';
|
|
135
|
+
readonly name: string;
|
|
136
|
+
readonly description?: string;
|
|
137
|
+
/** JSON Schema of the payload, written into the workflow interface. */
|
|
138
|
+
readonly schema?: Record<string, unknown>;
|
|
139
|
+
/** Type-level only. */
|
|
140
|
+
readonly [PAYLOAD]?: Payload;
|
|
141
|
+
}
|
|
142
|
+
interface QueryDefinition<Result = unknown, Args = unknown> {
|
|
143
|
+
readonly kind: 'query';
|
|
144
|
+
readonly name: string;
|
|
145
|
+
readonly description?: string;
|
|
146
|
+
readonly [PAYLOAD]?: {
|
|
147
|
+
result: Result;
|
|
148
|
+
args: Args;
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
interface UpdateDefinition<Args = unknown, Result = unknown> {
|
|
152
|
+
readonly kind: 'update';
|
|
153
|
+
readonly name: string;
|
|
154
|
+
readonly description?: string;
|
|
155
|
+
readonly [PAYLOAD]?: {
|
|
156
|
+
result: Result;
|
|
157
|
+
args: Args;
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
interface DefinitionOptions {
|
|
161
|
+
description?: string;
|
|
162
|
+
schema?: Record<string, unknown>;
|
|
163
|
+
}
|
|
164
|
+
/** Declare a signal. */
|
|
165
|
+
declare function defineSignal<Payload = unknown>(name: string, options?: DefinitionOptions): SignalDefinition<Payload>;
|
|
166
|
+
/** Declare a query. Handlers are Phase C; the declaration appears in the interface. */
|
|
167
|
+
declare function defineQuery<Result = unknown, Args = unknown>(name: string, options?: {
|
|
168
|
+
description?: string;
|
|
169
|
+
}): QueryDefinition<Result, Args>;
|
|
170
|
+
/** Declare an update. Handlers are Phase C; the declaration appears in the interface. */
|
|
171
|
+
declare function defineUpdate<Args = unknown, Result = unknown>(name: string, options?: {
|
|
172
|
+
description?: string;
|
|
173
|
+
}): UpdateDefinition<Args, Result>;
|
|
174
|
+
|
|
175
|
+
/** A duration: milliseconds, or a string such as `'30s'` or `'PT2H'`. */
|
|
176
|
+
type Duration = number | string;
|
|
177
|
+
/** Milliseconds of `value`; throws a `TypeError` naming `what` when it is not a duration. */
|
|
178
|
+
declare function toMs(value: Duration, what?: string): number;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* The `WorkflowContext` a tier-2 workflow function receives (spec 02 §4). The
|
|
182
|
+
* runtime (`src/runtime/`) implements it; this module is types only.
|
|
183
|
+
*/
|
|
184
|
+
|
|
185
|
+
/** Options of `ctx.run`. */
|
|
186
|
+
interface RunOptions<In> {
|
|
187
|
+
args: In;
|
|
188
|
+
/** Connection name, resolved by the service at `SCHEDULE_ACTIVITY`. */
|
|
189
|
+
connection?: string;
|
|
190
|
+
/** Default: 1 s, x2, at most 100 s, unlimited attempts (Temporal's policy). */
|
|
191
|
+
retry?: Partial<RetryPolicy>;
|
|
192
|
+
startToCloseTimeout?: Duration;
|
|
193
|
+
scheduleToCloseTimeout?: Duration;
|
|
194
|
+
scheduleToStartTimeout?: Duration;
|
|
195
|
+
heartbeatTimeout?: Duration;
|
|
196
|
+
cancellationType?: ActivityCancellationType;
|
|
197
|
+
/** 1 (highest) to 5; default 3. */
|
|
198
|
+
priority?: number;
|
|
199
|
+
/** Label in the History tab (at most 200 characters). */
|
|
200
|
+
summary?: string;
|
|
201
|
+
runOn?: string;
|
|
202
|
+
/** Overrides the operation name the descriptor carries. */
|
|
203
|
+
operation?: string;
|
|
204
|
+
/** Overrides the node version the descriptor carries. */
|
|
205
|
+
nodeVersion?: string;
|
|
206
|
+
headers?: Headers;
|
|
207
|
+
}
|
|
208
|
+
/** Options of `ctx.child` and `ctx.startChild` (11 §2.35). */
|
|
209
|
+
interface ChildOptions {
|
|
210
|
+
input?: unknown;
|
|
211
|
+
/** `active` (default), `vN` or `@alias`. */
|
|
212
|
+
version?: string;
|
|
213
|
+
taskQueue?: string;
|
|
214
|
+
/** Default `TERMINATE` for `ctx.child`, `ABANDON` for `ctx.startChild` (DB13). */
|
|
215
|
+
parentClosePolicy?: ParentClosePolicy;
|
|
216
|
+
/**
|
|
217
|
+
* How the awaitable reacts when its scope is cancelled. Unset, it rejects at
|
|
218
|
+
* once and the child is left to the parent-close policy; set, the SDK sends
|
|
219
|
+
* a cancel request to the child (`REQUEST_CANCEL_EXTERNAL_RUN`, a parity
|
|
220
|
+
* command).
|
|
221
|
+
*/
|
|
222
|
+
cancellationType?: ChildCancellationType;
|
|
223
|
+
workflowId?: string;
|
|
224
|
+
priority?: number;
|
|
225
|
+
summary?: string;
|
|
226
|
+
details?: string;
|
|
227
|
+
context?: JsonObject;
|
|
228
|
+
startDelay?: Duration;
|
|
229
|
+
executionTimeout?: Duration;
|
|
230
|
+
runTimeout?: Duration;
|
|
231
|
+
workflowTaskTimeout?: Duration;
|
|
232
|
+
headers?: Headers;
|
|
233
|
+
}
|
|
234
|
+
/** A started child run. */
|
|
235
|
+
interface ChildHandle<Out = Json> {
|
|
236
|
+
readonly childId: string;
|
|
237
|
+
readonly runId: string;
|
|
238
|
+
result(): Promise<Out>;
|
|
239
|
+
signal<P>(signal: SignalDefinition<P> | string, payload?: P): Promise<void>;
|
|
240
|
+
/** Request cancellation of the child (parity command `REQUEST_CANCEL_EXTERNAL_RUN`). */
|
|
241
|
+
cancel(): Promise<void>;
|
|
242
|
+
}
|
|
243
|
+
/** A handle to another run of the workspace (11 §2.24). */
|
|
244
|
+
interface ExternalRunHandle {
|
|
245
|
+
readonly runId: string;
|
|
246
|
+
signal<P>(signal: SignalDefinition<P> | string, payload?: P): Promise<void>;
|
|
247
|
+
/** Resolves when the cancel request was delivered, not when the run ends. */
|
|
248
|
+
cancel(): Promise<void>;
|
|
249
|
+
}
|
|
250
|
+
/** A cancellation scope (11 §2.24). */
|
|
251
|
+
interface CancellationScope {
|
|
252
|
+
/** Rejects with `CancelledFailure` when the scope is cancelled. */
|
|
253
|
+
readonly cancelRequested: Promise<never>;
|
|
254
|
+
readonly consideredCancelled: boolean;
|
|
255
|
+
cancel(): void;
|
|
256
|
+
}
|
|
257
|
+
interface CancellationScopeOptions {
|
|
258
|
+
/** A durable timer that cancels the scope when it fires. */
|
|
259
|
+
timeout?: Duration;
|
|
260
|
+
nonCancellable?: boolean;
|
|
261
|
+
}
|
|
262
|
+
/** `ctx.cancellationScope(fn, options)` and `ctx.cancellationScope.current()`. */
|
|
263
|
+
interface CancellationScopeFunction {
|
|
264
|
+
<T>(fn: (ctx: WorkflowContext) => Promise<T>, options?: CancellationScopeOptions): Promise<T>;
|
|
265
|
+
current(): CancellationScope;
|
|
266
|
+
}
|
|
267
|
+
/** What workflow code knows about its run. */
|
|
268
|
+
interface WorkflowInfo extends WorkflowInfoSnapshot {
|
|
269
|
+
readonly workflowFn: string;
|
|
270
|
+
/** Events in the history when the current workflow task started. */
|
|
271
|
+
readonly historyLength: number;
|
|
272
|
+
/** UTF-8 bytes of their payloads. */
|
|
273
|
+
readonly historyBytes: number;
|
|
274
|
+
/** True from 80 % of the history cap; continue as new soon. */
|
|
275
|
+
readonly continueAsNewSuggested: boolean;
|
|
276
|
+
readonly isReplaying: boolean;
|
|
277
|
+
}
|
|
278
|
+
/** Logging from workflow code; lines are emitted once, never during replay. */
|
|
279
|
+
interface WorkflowLogger {
|
|
280
|
+
debug(message: string, data?: Json): void;
|
|
281
|
+
info(message: string, data?: Json): void;
|
|
282
|
+
warn(message: string, data?: Json): void;
|
|
283
|
+
error(message: string, data?: Json): void;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Compensations run in reverse order, each in its own non-cancellable scope,
|
|
287
|
+
* so they still run after a cancel request. A compensation receives that
|
|
288
|
+
* scope's `ctx`; use it for every call after the compensation's first await.
|
|
289
|
+
*/
|
|
290
|
+
interface Saga {
|
|
291
|
+
add(compensation: (ctx: WorkflowContext) => unknown): void;
|
|
292
|
+
compensate(): Promise<void>;
|
|
293
|
+
}
|
|
294
|
+
interface ContinueAsNewOptions {
|
|
295
|
+
taskQueue?: string;
|
|
296
|
+
retry?: Partial<RetryPolicy>;
|
|
297
|
+
workflowTaskTimeout?: Duration;
|
|
298
|
+
context?: JsonObject;
|
|
299
|
+
versioningBehavior?: 'PINNED' | 'AUTO_UPGRADE';
|
|
300
|
+
}
|
|
301
|
+
/** A child target: a workflow key (graph or durable) or a tier-2 function of the same bundle. */
|
|
302
|
+
type ChildTarget<Out> = string | DurableWorkflow<never, Out> | DurableWorkflow<Json, Out>;
|
|
303
|
+
/** The context of a tier-2 workflow function. */
|
|
304
|
+
interface WorkflowContext {
|
|
305
|
+
readonly info: WorkflowInfo;
|
|
306
|
+
readonly log: WorkflowLogger;
|
|
307
|
+
/** Run a canvas node operation as a durable activity (`SCHEDULE_ACTIVITY`, kind `node`). */
|
|
308
|
+
run<In, Out>(operation: Operation<In, Out>, options: RunOptions<In>): Promise<Out>;
|
|
309
|
+
/** A durable timer. */
|
|
310
|
+
sleep(duration: Duration, options?: {
|
|
311
|
+
summary?: string;
|
|
312
|
+
}): Promise<void>;
|
|
313
|
+
/** Resolves `true` once `predicate` holds after an event, or `false` when `timeout` passes first. */
|
|
314
|
+
condition(predicate: () => boolean, timeout?: Duration): Promise<boolean>;
|
|
315
|
+
/** The next signal of this name (buffered signals first). */
|
|
316
|
+
signalReceived<P>(signal: SignalDefinition<P> | string): Promise<P>;
|
|
317
|
+
/** Handle every signal of this name, buffered ones first. */
|
|
318
|
+
onSignal<P>(signal: SignalDefinition<P> | string, handler: (payload: P) => unknown): void;
|
|
319
|
+
/** Handle signals no other handler or waiter takes. */
|
|
320
|
+
setDefaultSignalHandler(handler: (name: string, payload: unknown) => unknown): void;
|
|
321
|
+
/** Start a child run and wait for its result. */
|
|
322
|
+
child<Out = Json>(target: ChildTarget<Out>, options?: ChildOptions): Promise<Out>;
|
|
323
|
+
/** Start a child run; resolves once it has started. */
|
|
324
|
+
startChild<Out = Json>(target: ChildTarget<Out>, options?: ChildOptions): Promise<ChildHandle<Out>>;
|
|
325
|
+
/** Signal another run of the workspace; resolves on delivery. */
|
|
326
|
+
signalRun<P>(runId: string, signal: SignalDefinition<P> | string, payload?: P): Promise<void>;
|
|
327
|
+
/** Signal the parent run. */
|
|
328
|
+
signalParent<P>(signal: SignalDefinition<P> | string, payload?: P): Promise<void>;
|
|
329
|
+
getRunHandle(runId: string): ExternalRunHandle;
|
|
330
|
+
/** Shorthand for `getRunHandle(runId).cancel()`. */
|
|
331
|
+
cancelRun(runId: string): Promise<void>;
|
|
332
|
+
/** The workflow clock (the task's start time), in epoch milliseconds. */
|
|
333
|
+
now(): number;
|
|
334
|
+
/** A deterministic random number in [0, 1), seeded per run. */
|
|
335
|
+
random(): number;
|
|
336
|
+
/** A deterministic version-4 UUID. */
|
|
337
|
+
uuid(): string;
|
|
338
|
+
/** Record a value once (`RECORD_SIDE_EFFECT`); replays return the recorded value. */
|
|
339
|
+
sideEffect<T extends Json>(fn: () => T): T;
|
|
340
|
+
/** In-place versioning (spec 06 §4). */
|
|
341
|
+
patched(patchId: string): boolean;
|
|
342
|
+
deprecatePatch(patchId: string): void;
|
|
343
|
+
/** Live Markdown status for the run page and `__metadata` (at most 20 KiB). */
|
|
344
|
+
setCurrentDetails(markdown: string): void;
|
|
345
|
+
/** Merge keys into the run's context (parity command `UPSERT_CONTEXT`). */
|
|
346
|
+
upsertContext(entries: JsonObject): void;
|
|
347
|
+
/** End this run and start a fresh history (parity command `CONTINUE_AS_NEW`). */
|
|
348
|
+
continueAsNew(input: unknown, options?: ContinueAsNewOptions): Promise<never>;
|
|
349
|
+
/**
|
|
350
|
+
* Run `fn` in a new cancellation scope. `fn` gets a `ctx` bound to the
|
|
351
|
+
* scope: use it inside `fn`. This outer `ctx` joins the scope only while
|
|
352
|
+
* `fn` runs synchronously; after an await it is back in its own scope, so
|
|
353
|
+
* concurrent branches never share a scope by accident.
|
|
354
|
+
*/
|
|
355
|
+
readonly cancellationScope: CancellationScopeFunction;
|
|
356
|
+
/** `cancellationScope(fn, { nonCancellable: true })`; the same `ctx` rule applies. */
|
|
357
|
+
nonCancellable<T>(fn: (ctx: WorkflowContext) => Promise<T>): Promise<T>;
|
|
358
|
+
/**
|
|
359
|
+
* Run `fn` when the current scope is cancelled. An error thrown by `fn` is
|
|
360
|
+
* handled like an error thrown by the workflow; the other handlers still run.
|
|
361
|
+
*/
|
|
362
|
+
onCancel(fn: () => void): void;
|
|
363
|
+
isCancellation(error: unknown): boolean;
|
|
364
|
+
saga(): Saga;
|
|
365
|
+
/** Resolves when no asynchronous signal handler is running; cancellation does not interrupt the wait. */
|
|
366
|
+
allHandlersFinished(): Promise<void>;
|
|
367
|
+
/** Phase C: user activities. Throws `PhaseCFeatureError`. */
|
|
368
|
+
activity(...args: unknown[]): Promise<never>;
|
|
369
|
+
/** Phase B parity: local activities. Throws `PhaseCFeatureError` in this release. */
|
|
370
|
+
localActivity(...args: unknown[]): Promise<never>;
|
|
371
|
+
/** Phase C: custom queries. Throws `PhaseCFeatureError`. */
|
|
372
|
+
handleQuery(...args: unknown[]): void;
|
|
373
|
+
/** Phase C: updates. Throws `PhaseCFeatureError`. */
|
|
374
|
+
handleUpdate(...args: unknown[]): void;
|
|
375
|
+
/** Phase C: search attributes. Throws `PhaseCFeatureError`. */
|
|
376
|
+
upsertSearchAttributes(...args: unknown[]): void;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* `workflow()`: declare a tier-2 durable workflow function (spec 02 §4).
|
|
381
|
+
*
|
|
382
|
+
* The value is inert data plus the function: nothing runs at module load.
|
|
383
|
+
* `lower()` reads it to report `code.exports.workflows[exportName]`, and the
|
|
384
|
+
* runtime (`src/runtime/`) calls the function by export name inside a
|
|
385
|
+
* workflow task.
|
|
386
|
+
*/
|
|
387
|
+
|
|
388
|
+
declare const DURABLE_MARKER = "fluidgrids.durable-workflow";
|
|
389
|
+
/**
|
|
390
|
+
* A payload schema: a JSON Schema object, or a schema library value with a
|
|
391
|
+
* `toJSONSchema()` method. Anything else (a zod schema without one, for
|
|
392
|
+
* example) types the code but leaves the interface without that schema.
|
|
393
|
+
*/
|
|
394
|
+
type SchemaLike = Record<string, unknown> | {
|
|
395
|
+
toJSONSchema(): unknown;
|
|
396
|
+
};
|
|
397
|
+
/** How a standalone tier-2 workflow starts (lowered to its trigger node). */
|
|
398
|
+
type TriggerSpec = Operation<never, unknown> | Operation<Record<string, Json>, Json> | {
|
|
399
|
+
operation: Operation<never, unknown> | Operation<Record<string, Json>, Json>;
|
|
400
|
+
args?: JsonObject;
|
|
401
|
+
id?: string;
|
|
402
|
+
};
|
|
403
|
+
interface DurableWorkflowOptions {
|
|
404
|
+
/** Display name of the standalone workflow. */
|
|
405
|
+
title?: string;
|
|
406
|
+
description?: string;
|
|
407
|
+
input?: SchemaLike;
|
|
408
|
+
output?: SchemaLike;
|
|
409
|
+
signals?: ReadonlyArray<SignalDefinition<never> | SignalDefinition<unknown>>;
|
|
410
|
+
/** Declared only; handlers are Phase C. */
|
|
411
|
+
queries?: ReadonlyArray<QueryDefinition<unknown, unknown>>;
|
|
412
|
+
/** Declared only; handlers are Phase C. */
|
|
413
|
+
updates?: ReadonlyArray<UpdateDefinition<unknown, unknown>>;
|
|
414
|
+
/** Default `managed`. */
|
|
415
|
+
taskQueue?: string;
|
|
416
|
+
/** Lowers to the trigger node of the standalone workflow (default `internal:api`). */
|
|
417
|
+
trigger?: TriggerSpec;
|
|
418
|
+
/**
|
|
419
|
+
* Whether the function is a workflow of its own (07 §4): by default, when it
|
|
420
|
+
* declares a trigger or nothing in the project embeds it with `wf.codeWorkflow`.
|
|
421
|
+
*/
|
|
422
|
+
standalone?: boolean;
|
|
423
|
+
/** Error classes that fail the run instead of the workflow task (11 §2.25). */
|
|
424
|
+
failureErrorTypes?: ReadonlyArray<abstract new (...args: never[]) => Error>;
|
|
425
|
+
}
|
|
426
|
+
/** A declared tier-2 workflow. */
|
|
427
|
+
interface DurableWorkflow<In = Json, Out = Json> {
|
|
428
|
+
readonly __fluidgrids: typeof DURABLE_MARKER;
|
|
429
|
+
/** The workflow key it gets when it is standalone. */
|
|
430
|
+
readonly name: string;
|
|
431
|
+
readonly options: DurableWorkflowOptions;
|
|
432
|
+
readonly fn: (ctx: WorkflowContext, input: In) => Promise<Out>;
|
|
433
|
+
}
|
|
434
|
+
/** Declare a tier-2 workflow. `name` is its workflow key when it is standalone. */
|
|
435
|
+
declare function workflow<In = Json, Out = Json>(name: string, options: DurableWorkflowOptions, fn: (ctx: WorkflowContext, input: In) => Promise<Out>): DurableWorkflow<In, Out>;
|
|
436
|
+
declare function workflow<In = Json, Out = Json>(name: string, fn: (ctx: WorkflowContext, input: In) => Promise<Out>): DurableWorkflow<In, Out>;
|
|
437
|
+
/** True for a value made by {@link workflow}. */
|
|
438
|
+
declare function isDurableWorkflow(value: unknown): value is DurableWorkflow<never, unknown>;
|
|
439
|
+
/** The JSON Schema of a {@link SchemaLike}, or undefined when it has none. */
|
|
440
|
+
declare function jsonSchemaOf(schema: SchemaLike | undefined): JsonObject | undefined;
|
|
441
|
+
/** The workflow `interface` (spec 01 §4) a tier-2 declaration describes. */
|
|
442
|
+
declare function interfaceOf(definition: DurableWorkflow<never, unknown>): WorkflowInterface;
|
|
443
|
+
|
|
444
|
+
export { trigger as A, triggers as B, type CancellationScope as C, DURABLE_MARKER as D, type ExternalRunHandle as E, type FileRef as F, workflow as G, type Operation as O, type QueryDefinition as Q, type RunOptions as R, type Saga as S, type TriggerOperation as T, type UpdateDefinition as U, type WorkflowContext as W, type CancellationScopeFunction as a, type CancellationScopeOptions as b, type ChildHandle as c, type ChildOptions as d, type ChildTarget as e, type ContinueAsNewOptions as f, type DefinitionOptions as g, type DurableWorkflow as h, type DurableWorkflowOptions as i, type Duration as j, type SchemaLike as k, type SignalDefinition as l, type TriggerSpec as m, type WorkflowInfo as n, type WorkflowLogger as o, defineQuery as p, defineSignal as q, defineUpdate as r, interfaceOf as s, internalNodes as t, isDurableWorkflow as u, isOperation as v, jsonSchemaOf as w, nodes as x, op as y, toMs as z };
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Shared round-trip fixtures
|
|
2
|
+
|
|
3
|
+
These fixtures are the conformance suite for the tier-1 builders in
|
|
4
|
+
`@fluidgrids/workflows` (TypeScript, this repo) and `fluidgrids-workflows`
|
|
5
|
+
(Python, `fluidgrids-workflows-sdk-python`). Spec 03 §2 and spec 10 §2 require
|
|
6
|
+
both SDKs to lower the same graph to byte-identical IR; this directory is where
|
|
7
|
+
that is checked.
|
|
8
|
+
|
|
9
|
+
Everything except `ir.json`, `index.json`, `registry.json` and
|
|
10
|
+
`connections.json` is generated. Regenerate with `bun run check:fixtures --write`
|
|
11
|
+
and check with `bun run check:fixtures --ruff` (CI does both checks).
|
|
12
|
+
|
|
13
|
+
## Layout
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
fixtures/
|
|
17
|
+
index.json every fixture: name, source, what it covers
|
|
18
|
+
registry.json node registry snapshot (9 store nodes from fluidgrids-nodes, contract fields only)
|
|
19
|
+
connections.json connectionId -> { name, adapter }
|
|
20
|
+
.fluidgrids/nodes.ts generated clients for registry.json (generateNodeClients(..., 'ts'))
|
|
21
|
+
.fluidgrids/nodes.py generated clients for registry.json (generateNodeClients(..., 'py'))
|
|
22
|
+
<fixture>/
|
|
23
|
+
ir.json the input definition, as stored (not normalised)
|
|
24
|
+
expected.ir.json normalizeDefinition(ir) with the workflow key and without authoring:
|
|
25
|
+
what lowering the code must reproduce
|
|
26
|
+
fixture.json { key, irHash, fidelity, items }
|
|
27
|
+
workflows/<key>.ts lifted tier-1 TypeScript (Prettier, pinned options)
|
|
28
|
+
workflows/<key_snake>.py lifted tier-1 Python (Ruff-stable, line length 88)
|
|
29
|
+
workflows/<key>.layout.json positions, sticky notes and meta.layout
|
|
30
|
+
.fluidgrids -> ../.fluidgrids so each fixture directory is a complete project
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## The conformance check
|
|
34
|
+
|
|
35
|
+
For every fixture, lowering `workflows/<key_snake>.py` (with the layout sidecar
|
|
36
|
+
and `connections.json` resolving connection names to `{ connectionId, adapter }`)
|
|
37
|
+
must give a definition whose `irHash` equals `fixture.json` `irHash`. That is
|
|
38
|
+
the same check the TypeScript suite runs on `workflows/<key>.ts`
|
|
39
|
+
(`tests/fixtures.test.ts`, invariants 1 and 2 of spec 07 §5).
|
|
40
|
+
|
|
41
|
+
`irHash` is `sha256:` + the SHA-256 of the RFC 8785 canonical JSON of the
|
|
42
|
+
normalised definition without its `authoring` block. Provenance
|
|
43
|
+
(`authoring.generator` is `sdk-ts` or `sdk-py`) is not content, so the two SDKs
|
|
44
|
+
hash equally. Implement RFC 8785 exactly (keys sorted by UTF-16 code units,
|
|
45
|
+
ECMAScript number formatting, no whitespace) and `normalizeDefinition` as
|
|
46
|
+
`src/ir/normalize.ts` documents it.
|
|
47
|
+
|
|
48
|
+
## The Python tier-1 surface the fixtures pin
|
|
49
|
+
|
|
50
|
+
The Python files are printed from the same lift plan as the TypeScript files,
|
|
51
|
+
so they define the Python builder's surface:
|
|
52
|
+
|
|
53
|
+
- Imports: `from fluidgrids_workflows import and_, define_workflow, edge, expr, nodes, or_, triggers`
|
|
54
|
+
and `from fluidgrids_workflows.project import nodes as n`, which resolves to the
|
|
55
|
+
project's `.fluidgrids/nodes.py`.
|
|
56
|
+
- `@define_workflow(key=..., name=..., description=..., config=..., interface=..., code=..., tags=..., meta=..., extra=...)`
|
|
57
|
+
on `def <key_snake>(wf):`.
|
|
58
|
+
- Builder methods: `wf.trigger(op, ...)`, `wf.step(op, ...)` and the helpers
|
|
59
|
+
`if_`, `switch`, `loop`, `merge`, `wait`, `wait_for_signal`, `send_and_wait`,
|
|
60
|
+
`subworkflow`, `validate`, `compare_datasets`, `set`, `filter`, `aggregate`,
|
|
61
|
+
`split_out`, `limit`, `dedupe`, `sort`, `data_table`, `http`, `code`,
|
|
62
|
+
`transform`, `log`, `respond_to_webhook`, `stop_and_error`, `noop`; plus
|
|
63
|
+
`wf.ref(id)`, `wf.connect(source, target_id, **edge_options)`,
|
|
64
|
+
`wf.edge_order_is([...])`, `wf.json`, `wf.vars`, `wf.now`, `wf.execution`.
|
|
65
|
+
- Keyword options are the TypeScript option names in snake_case: `id`, `label`,
|
|
66
|
+
`after`, `args`, `operation`, `version`, `connection`, `connections`,
|
|
67
|
+
`credentials`, `context`, `retry`, `timeout`, `on_error`, `error_config`,
|
|
68
|
+
`execution_settings`, `disabled`, `extra`, `condition`; edge options `id`,
|
|
69
|
+
`type`, `target_handle`, `label`, `data`, `mapping`, `extra`.
|
|
70
|
+
- Option values are never converted: `args`, `retry`, `timeout`, `config`,
|
|
71
|
+
`extra` and every other dictionary keep the IR's own keys (`maxRetries`,
|
|
72
|
+
`channelId`, `link_names`), so they lower byte for byte. This is a deliberate
|
|
73
|
+
difference from the snake_case `retry` keys sketched in spec 03 §2.
|
|
74
|
+
- `False` for `operation`, `version` and edge `id` / `type` means "write no
|
|
75
|
+
such field"; leaving the option out means "write the default" (the
|
|
76
|
+
descriptor's operation and version, the default edge id
|
|
77
|
+
`e-<source>-<target>[-<sourceHandle>][-<targetHandle>]`, edge type `deletable`).
|
|
78
|
+
Default ids are given after the callback returns: explicit ids are claimed
|
|
79
|
+
first, and a default id that is already taken gets `-2`, `-3`, … in
|
|
80
|
+
declaration order. Only a repeated explicit id is an error.
|
|
81
|
+
- References: `node.output.a.b`, `["key"]` for keys that are not identifiers,
|
|
82
|
+
Python keywords, names starting with `_`, or reference method names, and
|
|
83
|
+
`[0]` for indices. They lower to `{{ $node["<id>"].item.<path> }}`;
|
|
84
|
+
`wf.json.x` lowers to `{{ $json.x }}`.
|
|
85
|
+
- Conditions: `>=`, `>`, `<=`, `<`, `==`, `!=` on a reference, the methods
|
|
86
|
+
`contains`, `not_contains`, `starts_with`, `ends_with`, `matches` (operator
|
|
87
|
+
`regex`), `has_property`, `is_empty`, `is_not_empty`, `is_null`,
|
|
88
|
+
`is_not_null`, `is_true`, `is_false`, the generic `is_(operator[, value])`,
|
|
89
|
+
and `and_()` / `or_()`. A condition field is `WorkflowState.<id>.<path>` for a
|
|
90
|
+
node output and `output.<path>` for `wf.json`; one top-level rule is wrapped
|
|
91
|
+
in an `AND` group.
|
|
92
|
+
- `expr("text ", ref, " more")` concatenates its parts; references render as
|
|
93
|
+
`{{ … }}`.
|
|
94
|
+
- Typed handles: `if_` → `.true`, `.false`; `loop` → `.body`, `.done`;
|
|
95
|
+
`validate` → `.valid`, `.invalid`; `send_and_wait` → `.approved`,
|
|
96
|
+
`.declined`, `.timed_out`; `wait_for_signal` → `.received`, `.timed_out`;
|
|
97
|
+
`compare_datasets` → `.in_a_only`, `.in_b_only`, `.same`, `.different`;
|
|
98
|
+
`switch` → `.case("h")`, `.default`; any node → `.handle("h")`.
|
|
99
|
+
- Generated clients: `op(node_type, version, operation, InputTypedDict, OutputTypedDict)`
|
|
100
|
+
and `trigger(...)` with the same arguments; `nodes.<group>.<operation>` and
|
|
101
|
+
`triggers.<group>.<operation>` use snake_case names (`n.slack.send_message`).
|
|
102
|
+
`fluidgrids_workflows` must export `op`, `trigger`, `Json` and `FileRef`.
|
|
103
|
+
|
|
104
|
+
## Substitutions and corrections in the fixtures
|
|
105
|
+
|
|
106
|
+
- **Real nodes only.** `store/clearbit` (example 02) is replaced by
|
|
107
|
+
`internal:http` calling the Clearbit API with a saved connection;
|
|
108
|
+
`store/warehouse-erp` (example 01) by `store/postgresql` `executeQuery`; the
|
|
109
|
+
`store/slack` `sendAndWait` operation (example 01), which does not exist, by
|
|
110
|
+
`internal:send-and-wait`. Store operations and argument names are the ones in
|
|
111
|
+
`registry.json` (for example Slack `channelId`, Stripe `createRefund`
|
|
112
|
+
`charge`).
|
|
113
|
+
- **The expression form the workers evaluate.** The examples write
|
|
114
|
+
`{{ $node["x"].json.path }}`; the expression language exposes
|
|
115
|
+
`$node["x"].item` (there is no `.json`), so the fixtures use `.item`.
|
|
116
|
+
- **The condition tree the IF node evaluates.** The examples write
|
|
117
|
+
`{ op, left, right }`; `internal:if` evaluates
|
|
118
|
+
`{ type: "group", combinator, children: [{ type: "rule", field, operator, value }] }`.
|
|
119
|
+
- **Example 01** routed both `declined` and `timedOut` from `approve` to
|
|
120
|
+
`refund`. Two edges between the same pair of nodes are rejected by the
|
|
121
|
+
service validator, so the fixture keeps the `declined` edge only.
|
|
122
|
+
- **Examples 03, 04 and 05** have no canvas JSON in the spec. Their `ir.json`
|
|
123
|
+
was produced by writing the example's tier-1 code against the real nodes and
|
|
124
|
+
lowering it once; the lifted `workflows/*.ts` is that code in canonical form.
|
|
125
|
+
- **Doctor samples** (`fg-uc-*`, `doctor-*`) are the `definitionJson` of the
|
|
126
|
+
fluidgrids-doctor samples, with `key` added from the file name. They keep
|
|
127
|
+
their legacy `${…}` templates, `config` parameters and `store:<name>` types,
|
|
128
|
+
which is the point: they are what stored definitions look like.
|