@superdurable/dex 0.1.5 → 0.1.6

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.
Files changed (50) hide show
  1. package/README.md +102 -6
  2. package/dist/src/client.d.ts +18 -23
  3. package/dist/src/client.js +94 -65
  4. package/dist/src/client.js.map +1 -1
  5. package/dist/src/codec.d.ts +1 -1
  6. package/dist/src/context.d.ts +7 -0
  7. package/dist/src/errors.d.ts +2 -33
  8. package/dist/src/errors.js +2 -45
  9. package/dist/src/errors.js.map +1 -1
  10. package/dist/src/flow-result.d.ts +47 -0
  11. package/dist/src/flow-result.js +82 -0
  12. package/dist/src/flow-result.js.map +1 -0
  13. package/dist/src/flow.d.ts +13 -1
  14. package/dist/src/flow.js +1 -0
  15. package/dist/src/flow.js.map +1 -1
  16. package/dist/src/gen/dex.d.ts +209 -33
  17. package/dist/src/gen/dex.js +1619 -213
  18. package/dist/src/gen/dex.js.map +1 -1
  19. package/dist/src/grpc-status.js +6 -5
  20. package/dist/src/grpc-status.js.map +1 -1
  21. package/dist/src/index.d.ts +2 -0
  22. package/dist/src/index.js +1 -0
  23. package/dist/src/index.js.map +1 -1
  24. package/dist/src/invocation-context.d.ts +5 -1
  25. package/dist/src/invocation-context.js +23 -1
  26. package/dist/src/invocation-context.js.map +1 -1
  27. package/dist/src/options.d.ts +42 -19
  28. package/dist/src/options.js +20 -4
  29. package/dist/src/options.js.map +1 -1
  30. package/dist/src/rpc.d.ts +3 -1
  31. package/dist/src/rpc.js.map +1 -1
  32. package/dist/src/step.d.ts +32 -2
  33. package/dist/src/step.js +37 -0
  34. package/dist/src/step.js.map +1 -1
  35. package/dist/src/subflow.d.ts +62 -0
  36. package/dist/src/subflow.js +62 -0
  37. package/dist/src/subflow.js.map +1 -0
  38. package/dist/src/wait.d.ts +10 -2
  39. package/dist/src/wait.js.map +1 -1
  40. package/dist/src/worker-dispatcher.d.ts +4 -3
  41. package/dist/src/worker-dispatcher.js +256 -28
  42. package/dist/src/worker-dispatcher.js.map +1 -1
  43. package/dist/src/worker.js +21 -5
  44. package/dist/src/worker.js.map +1 -1
  45. package/native/linux-aarch64/dex_blob_cache_node.node +0 -0
  46. package/native/linux-x86_64/dex_blob_cache_node.node +0 -0
  47. package/native/macos-aarch64/dex_blob_cache_node.node +0 -0
  48. package/native/macos-x86_64/dex_blob_cache_node.node +0 -0
  49. package/native/windows-x86_64/dex_blob_cache_node.node +0 -0
  50. package/package.json +1 -1
@@ -0,0 +1,62 @@
1
+ // Copyright (c) 2026 Super Durable, Inc.
2
+ //
3
+ // Licensed under the Super Durable Source License 1.0.
4
+ // You may not use this file except in compliance with the License.
5
+ // See the LICENSE file in the repository root.
6
+ //
7
+ // SPDX-License-Identifier: LicenseRef-Super-Durable-1.0
8
+ import { InvocationContext } from "./invocation-context.js";
9
+ /** Controls how a generated SubFlow Flow ID resolves an existing execution. */
10
+ export const SubFlowReusePolicy = Object.freeze({
11
+ /** Attaches to a running execution or returns its existing terminal result. */
12
+ ATTACH: "attach",
13
+ /** Restarts abnormal executions, attaches while running, and returns completed results. */
14
+ RESTART_IF_PREVIOUS_EXITS_ABNORMALLY: "restartIfPreviousExitsAbnormally",
15
+ /** Replaces any different existing execution, including a running one. */
16
+ ALWAYS_RESTART: "alwaysRestart",
17
+ });
18
+ /** Creates durable SubFlow conditions and reads their Execute results. */
19
+ export const SubFlow = Object.freeze({
20
+ /**
21
+ * Creates a condition that starts or reuses a registered Flow and awaits completion.
22
+ * @typeParam Input - Target starting Step input type.
23
+ * @param flow - Exact target Flow instance registered by the Worker.
24
+ * @param input - Input accepted by its starting Step.
25
+ * @param options - Optional timing, retry, Attribute, configuration, reuse, and ID settings.
26
+ * @returns A durable SubFlow condition accepted by Wait factories.
27
+ */
28
+ run(flow, input, options = {}) {
29
+ return Object.freeze({
30
+ kind: "subFlow",
31
+ subFlow: flow,
32
+ subFlowInput: input,
33
+ subFlowOptions: options,
34
+ ...(options.conditionId === undefined ? {} : { conditionId: options.conditionId }),
35
+ });
36
+ },
37
+ /**
38
+ * Returns one stable-indexed SubFlow result during Step execute.
39
+ * @param context - Current Dex Execute context.
40
+ * @param index - Zero-based SubFlow order; defaults to zero.
41
+ * @returns A terminal result or an AnyOf loser's running snapshot.
42
+ */
43
+ getConditionResults(context, index = 0) {
44
+ return invocation(context).subFlowResult(index);
45
+ },
46
+ /**
47
+ * Returns one generated SubFlow Flow ID during Step execute.
48
+ * @param context - Current Dex Execute context.
49
+ * @param index - Zero-based SubFlow order; defaults to zero.
50
+ * @returns An addressable Flow ID suitable for `Client.stopFlow`.
51
+ */
52
+ getFlowId(context, index = 0) {
53
+ return invocation(context).subFlowId(index);
54
+ },
55
+ });
56
+ function invocation(context) {
57
+ if (!(context instanceof InvocationContext)) {
58
+ throw new TypeError("SubFlow access requires a Dex invocation Context");
59
+ }
60
+ return context;
61
+ }
62
+ //# sourceMappingURL=subflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subflow.js","sourceRoot":"","sources":["../../src/subflow.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,uDAAuD;AACvD,mEAAmE;AACnE,+CAA+C;AAC/C,EAAE;AACF,wDAAwD;AAKxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAK5D,+EAA+E;AAC/E,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC;IAC9C,+EAA+E;IAC/E,MAAM,EAAE,QAAQ;IAChB,2FAA2F;IAC3F,oCAAoC,EAAE,kCAAkC;IACxE,0EAA0E;IAC1E,cAAc,EAAE,eAAe;CACvB,CAAC,CAAC;AA0BZ,0EAA0E;AAC1E,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC;IACnC;;;;;;;OAOG;IACH,GAAG,CAAQ,IAAiB,EAAE,KAAY,EAAE,UAA0B,EAAE;QACtE,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,SAAkB;YACxB,OAAO,EAAE,IAAI;YACb,YAAY,EAAE,KAAK;YACnB,cAAc,EAAE,OAAO;YACvB,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;SACnF,CAAC,CAAC;IACL,CAAC;IACD;;;;;OAKG;IACH,mBAAmB,CAAC,OAAgB,EAAE,KAAK,GAAG,CAAC;QAC7C,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC;IACD;;;;;OAKG;IACH,SAAS,CAAC,OAAgB,EAAE,KAAK,GAAG,CAAC;QACnC,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9C,CAAC;CACF,CAAC,CAAC;AAEH,SAAS,UAAU,CAAC,OAAgB;IAClC,IAAI,CAAC,CAAC,OAAO,YAAY,iBAAiB,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,SAAS,CAAC,kDAAkD,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -1,9 +1,11 @@
1
1
  import type { Codec } from "./codec.js";
2
2
  import type { Context } from "./context.js";
3
- /** Describes one durable Timer or Channel readiness condition. */
3
+ import type { Flow } from "./flow.js";
4
+ import type { SubFlowOptions } from "./subflow.js";
5
+ /** Describes one durable Timer, Channel, or SubFlow readiness condition. */
4
6
  export interface Condition {
5
7
  /** Condition family interpreted by Dex. */
6
- readonly kind: "timer" | "channel";
8
+ readonly kind: "timer" | "channel" | "subFlow";
7
9
  /** Optional stable ID unique within the Wait tree. */
8
10
  readonly conditionId?: string;
9
11
  /** Timer delay in non-negative milliseconds. */
@@ -16,6 +18,12 @@ export interface Condition {
16
18
  readonly atLeast?: number;
17
19
  /** Inclusive upper queued-value bound. */
18
20
  readonly atMost?: number;
21
+ /** Exact registered Flow instance targeted by a SubFlow condition. */
22
+ readonly subFlow?: Flow<any>;
23
+ /** Starting Step input for a SubFlow condition. */
24
+ readonly subFlowInput?: unknown;
25
+ /** Start, reuse, and condition options for a SubFlow condition. */
26
+ readonly subFlowOptions?: SubFlowOptions;
19
27
  }
20
28
  /** Groups Conditions that must become ready together. */
21
29
  export interface ConditionCombination {
@@ -1 +1 @@
1
- {"version":3,"file":"wait.js","sourceRoot":"","sources":["../../src/wait.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wait.js","sourceRoot":"","sources":["../../src/wait.ts"],"names":[],"mappings":"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"}
@@ -5,9 +5,10 @@ export declare class WorkerDispatcher {
5
5
  private readonly registry;
6
6
  private readonly hydrator;
7
7
  constructor(registry: Registry, hydrator: ValueHydrator);
8
- invokeWaitFor(original: InvokeWaitForMethodRequest): Promise<InvokeWaitForMethodResponse>;
9
- invokeExecute(original: InvokeExecuteMethodRequest): Promise<InvokeExecuteMethodResponse>;
10
- invokeRPC(original: InvokeWorkerRPCRequest): Promise<InvokeWorkerRPCResponse>;
8
+ invokeWaitFor(original: InvokeWaitForMethodRequest, cancellationSignal?: AbortSignal): Promise<InvokeWaitForMethodResponse>;
9
+ invokeExecute(original: InvokeExecuteMethodRequest, cancellationSignal?: AbortSignal): Promise<InvokeExecuteMethodResponse>;
10
+ private invokeTimeoutHandler;
11
+ invokeRPC(original: InvokeWorkerRPCRequest, cancellationSignal?: AbortSignal): Promise<InvokeWorkerRPCResponse>;
11
12
  private hydrateWaitFor;
12
13
  private hydrateExecute;
13
14
  private hydrateRPC;
@@ -5,12 +5,17 @@
5
5
  // See the LICENSE file in the repository root.
6
6
  //
7
7
  // SPDX-License-Identifier: LicenseRef-Super-Durable-1.0
8
- import { ChannelCondition, CloseDecision, CloseDecisionType, ConditionCombination as ProtoConditionCombination, ExecuteMethodFailurePolicy, InvokeExecuteMethodResponse, InvokeWaitForMethodResponse, InvokeWorkerRPCResponse, StepDecision as ProtoStepDecision, StepMovement as ProtoStepMovement, StepOptions as ProtoStepOptions, TimerCondition, WaitForMethodFailurePolicy, WaitingCondition, WaitingConditionType, } from "./gen/dex.js";
8
+ import { ChannelCondition, CloseDecision, CloseDecisionType, ConditionCombination as ProtoConditionCombination, ExecuteMethodFailurePolicy, InvokeExecuteMethodResponse, InvokeWaitForMethodResponse, InvokeWorkerRPCResponse, StepDecision as ProtoStepDecision, StepMovement as ProtoStepMovement, StepOptions as ProtoStepOptions, TimerCondition, SubFlowCondition as ProtoSubFlowCondition, SubFlowOptions as ProtoSubFlowOptions, SubFlowReusePolicy as ProtoSubFlowReusePolicy, FlowRetryPolicy, FlowTimeoutPolicy as ProtoFlowTimeoutPolicy, FlowConfig as ProtoFlowConfig, ActiveStepSearchMode as ProtoActiveStepSearchMode, StepDurability as ProtoStepDurability, IndexType as ProtoIndexType, WaitForMethodFailurePolicy, WaitingCondition, WaitingConditionType, } from "./gen/dex.js";
9
9
  import { InvalidStepResultError, ValueMappingError } from "./errors.js";
10
- import { registeredFlowByName, registeredRPCByName, registeredStep, } from "./flow.js";
10
+ import { registeredFlowByName, registeredFlow, registeredRPCByName, registeredStep, } from "./flow.js";
11
11
  import { InvocationContext } from "./invocation-context.js";
12
+ import { AttributeMap, IndexType } from "./persistence.js";
13
+ import { mapAttributeStoreName, mapAttributeStoreSync } from "./attribute-store-sync.js";
14
+ import { ActiveStepSearchMode, FlowTimeoutPolicy } from "./options.js";
15
+ import { SubFlowReusePolicy } from "./subflow.js";
12
16
  import { decodeValue, encodeUnknown, encodeValue, } from "./value-mapper.js";
13
17
  import { Channel, ChannelMap } from "./wait.js";
18
+ const timeoutHandlerStepType = "sys:timeout_handler";
14
19
  export class WorkerDispatcher {
15
20
  registry;
16
21
  hydrator;
@@ -18,11 +23,12 @@ export class WorkerDispatcher {
18
23
  this.registry = registry;
19
24
  this.hydrator = hydrator;
20
25
  }
21
- async invokeWaitFor(original) {
26
+ async invokeWaitFor(original, cancellationSignal = new AbortController().signal) {
22
27
  const request = await this.hydrateWaitFor(original);
28
+ cancellationSignal.throwIfAborted();
23
29
  const flow = registeredFlowByName(this.registry, request.flowType);
24
30
  const step = registeredStep(flow, request.stepType);
25
- const context = new InvocationContext("waitFor", flow, request.context, request.attributes);
31
+ const context = new InvocationContext("waitFor", flow, request.context, request.attributes, [], undefined, {}, cancellationSignal);
26
32
  const input = decodeValue(step.step.inputCodec, requireValue(request.stepInput, "Step input"));
27
33
  if (step.step.waitFor === undefined) {
28
34
  throw new TypeError(`Step ${step.name} does not implement waitFor`);
@@ -31,7 +37,7 @@ export class WorkerDispatcher {
31
37
  try {
32
38
  return InvokeWaitForMethodResponse.create({
33
39
  upsertAttributes: [...context.getAttributeWrites()],
34
- waitingCondition: mapWait(flow, wait),
40
+ waitingCondition: mapWait(this.registry, flow, wait),
35
41
  upsertStepExeLocals: [...context.getLocalWrites()],
36
42
  recordEvents: [...context.getEvents()],
37
43
  publishToChannel: [...context.getPublications()],
@@ -41,11 +47,15 @@ export class WorkerDispatcher {
41
47
  throw invalidStepResult(flow.name, step.name, "waitFor", failure);
42
48
  }
43
49
  }
44
- async invokeExecute(original) {
50
+ async invokeExecute(original, cancellationSignal = new AbortController().signal) {
45
51
  const request = await this.hydrateExecute(original);
52
+ cancellationSignal.throwIfAborted();
46
53
  const flow = registeredFlowByName(this.registry, request.flowType);
54
+ if (request.stepType === timeoutHandlerStepType) {
55
+ return this.invokeTimeoutHandler(request, flow, cancellationSignal);
56
+ }
47
57
  const step = registeredStep(flow, request.stepType);
48
- const context = new InvocationContext("execute", flow, request.context, request.attributes, request.stepExeLocals, request.conditionResults);
58
+ const context = new InvocationContext("execute", flow, request.context, request.attributes, request.stepExeLocals, request.conditionResults, {}, cancellationSignal);
49
59
  const input = decodeValue(step.step.inputCodec, requireValue(request.stepInput, "Step input"));
50
60
  const decision = await step.step.execute(context, input);
51
61
  try {
@@ -61,11 +71,34 @@ export class WorkerDispatcher {
61
71
  throw invalidStepResult(flow.name, step.name, "execute", failure);
62
72
  }
63
73
  }
64
- async invokeRPC(original) {
74
+ async invokeTimeoutHandler(request, flow, cancellationSignal) {
75
+ try {
76
+ if (request.stepInput !== undefined) {
77
+ throw new TypeError("timeout handler input must be absent");
78
+ }
79
+ if (flow.flow.handleTimeout === undefined) {
80
+ throw new TypeError(`Flow ${flow.name} does not implement handleTimeout`);
81
+ }
82
+ const context = new InvocationContext("execute", flow, request.context, request.attributes, request.stepExeLocals, request.conditionResults, {}, cancellationSignal);
83
+ const decision = await flow.flow.handleTimeout(context);
84
+ return InvokeExecuteMethodResponse.create({
85
+ stepDecision: mapDecision(flow, decision),
86
+ upsertAttributes: [...context.getAttributeWrites()],
87
+ recordEvents: [...context.getEvents()],
88
+ upsertStepExeLocals: [...context.getLocalWrites()],
89
+ publishToChannel: [...context.getPublications()],
90
+ });
91
+ }
92
+ catch (failure) {
93
+ throw invalidStepResult(flow.name, timeoutHandlerStepType, "execute", failure);
94
+ }
95
+ }
96
+ async invokeRPC(original, cancellationSignal = new AbortController().signal) {
65
97
  const request = await this.hydrateRPC(original);
98
+ cancellationSignal.throwIfAborted();
66
99
  const flow = registeredFlowByName(this.registry, request.flowType);
67
100
  const rpc = registeredRPCByName(flow, request.rpcName);
68
- const context = new InvocationContext("rpc", flow, request.context, request.attributes, [], undefined, request.channelInfos);
101
+ const context = new InvocationContext("rpc", flow, request.context, request.attributes, [], undefined, request.channelInfos, cancellationSignal);
69
102
  const returned = await invokeRPC(flow, rpc, context, request.input);
70
103
  try {
71
104
  const result = rpcResult(rpc, returned);
@@ -73,9 +106,7 @@ export class WorkerDispatcher {
73
106
  output: rpc.options.outputCodec === undefined
74
107
  ? encodeUnknown(undefined)
75
108
  : encodeValue(rpc.options.outputCodec, result?.output),
76
- stepDecision: result?.nextSteps === undefined || result.nextSteps.length === 0
77
- ? undefined
78
- : ProtoStepDecision.create({ nextSteps: mapMovements(flow, result.nextSteps) }),
109
+ stepDecision: rpcDecision(flow, result),
79
110
  upsertAttributes: [...context.getAttributeWrites()],
80
111
  recordEvents: [...context.getEvents()],
81
112
  publishToChannel: [...context.getPublications()],
@@ -98,17 +129,26 @@ export class WorkerDispatcher {
98
129
  }
99
130
  async hydrateExecute(request) {
100
131
  const channelValues = request.conditionResults?.channelResults.flatMap((result) => result.values) ?? [];
132
+ const subFlowValues = request.conditionResults?.subFlowResults.flatMap((result) => result.results.map((completion) => completion.completedStepOutput)) ?? [];
133
+ const hasInput = request.stepInput !== undefined;
101
134
  const values = await this.hydrator.hydrateAll([
102
- request.stepInput,
135
+ ...(hasInput ? [request.stepInput] : []),
103
136
  ...request.attributes.map((entry) => entry.value),
104
137
  ...request.stepExeLocals.map((entry) => entry.value),
105
138
  ...channelValues,
139
+ ...subFlowValues,
106
140
  ]);
107
- let offset = 1;
141
+ let offset = hasInput ? 1 : 0;
108
142
  const attributes = replaceEntryValues(request.attributes, values.slice(offset, (offset += request.attributes.length)));
109
143
  const stepExeLocals = replaceEntryValues(request.stepExeLocals, values.slice(offset, (offset += request.stepExeLocals.length)));
110
144
  const conditionResults = replaceConditionValues(request.conditionResults, values.slice(offset));
111
- return { ...request, attributes, stepExeLocals, conditionResults };
145
+ return {
146
+ ...request,
147
+ stepInput: hasInput ? values[0] : undefined,
148
+ attributes,
149
+ stepExeLocals,
150
+ conditionResults,
151
+ };
112
152
  }
113
153
  async hydrateRPC(request) {
114
154
  const hasInput = request.input !== undefined;
@@ -141,14 +181,14 @@ function rpcResult(rpc, returned) {
141
181
  }
142
182
  return returned;
143
183
  }
144
- function mapWait(flow, wait) {
184
+ function mapWait(registry, flow, wait) {
145
185
  if (wait === undefined) {
146
186
  throw new TypeError("waitFor returned undefined");
147
187
  }
148
188
  if (wait.kind === "skipImmediately") {
149
189
  return undefined;
150
190
  }
151
- const mapper = new ConditionMapper(flow);
191
+ const mapper = new ConditionMapper(registry, flow);
152
192
  let waitingConditionType;
153
193
  const combinations = [];
154
194
  if (wait.kind === "allOf" || wait.kind === "anyOf") {
@@ -176,6 +216,7 @@ function mapWait(flow, wait) {
176
216
  waitingConditionType,
177
217
  timerConditions: mapper.timers,
178
218
  channelConditions: mapper.channels,
219
+ subFlowConditions: mapper.subFlows,
179
220
  conditionCombinations: combinations,
180
221
  });
181
222
  }
@@ -187,14 +228,14 @@ function mapDecision(flow, decision) {
187
228
  if (decision.movements.length === 0) {
188
229
  throw new TypeError("goToMulti requires a movement");
189
230
  }
190
- return ProtoStepDecision.create({ nextSteps: mapMovements(flow, decision.movements) });
231
+ return withCancellationSelection(flow, decision, ProtoStepDecision.create({ nextSteps: mapMovements(flow, decision.movements) }));
191
232
  }
192
233
  if (decision.kind === "deadEnd") {
193
- return ProtoStepDecision.create({
234
+ return withCancellationSelection(flow, decision, ProtoStepDecision.create({
194
235
  closeDecision: CloseDecision.create({
195
236
  closeDecisionType: CloseDecisionType.CLOSE_DECISION_TYPE_DEAD_END,
196
237
  }),
197
- });
238
+ }));
198
239
  }
199
240
  if (decision.kind === "forceCompleteIfChannelsEmpty") {
200
241
  const channels = decision.channels.map((channel) => {
@@ -203,26 +244,64 @@ function mapDecision(flow, decision) {
203
244
  }
204
245
  return channel.name;
205
246
  });
206
- return ProtoStepDecision.create({
247
+ return withCancellationSelection(flow, decision, ProtoStepDecision.create({
207
248
  nextSteps: [mapMovement(flow, decision.fallback)],
208
249
  closeDecision: CloseDecision.create({
209
250
  closeDecisionType: CloseDecisionType.CLOSE_DECISION_TYPE_FORCE_COMPLETE_ON_CHANNELS_EMPTY,
210
251
  conditionalChannelNames: channels,
211
252
  closeInput: encodeUnknown(decision.output),
212
253
  }),
213
- });
254
+ }));
214
255
  }
215
256
  const closeTypes = {
216
257
  gracefulComplete: CloseDecisionType.CLOSE_DECISION_TYPE_GRACEFUL_COMPLETE,
217
258
  forceComplete: CloseDecisionType.CLOSE_DECISION_TYPE_FORCE_COMPLETE,
218
259
  forceFail: CloseDecisionType.CLOSE_DECISION_TYPE_FORCE_FAIL,
219
260
  };
220
- return ProtoStepDecision.create({
261
+ const closeInput = decision.kind === "forceFail"
262
+ ? encodeUnknown(decision.reason)
263
+ : decision.output === undefined
264
+ ? undefined
265
+ : encodeUnknown(decision.output);
266
+ return withCancellationSelection(flow, decision, ProtoStepDecision.create({
221
267
  closeDecision: CloseDecision.create({
222
268
  closeDecisionType: closeTypes[decision.kind],
223
- closeInput: encodeUnknown(decision.kind === "forceFail" ? decision.reason : decision.output),
269
+ closeInput,
224
270
  }),
225
- });
271
+ }));
272
+ }
273
+ function withCancellationSelection(flow, decision, mapped) {
274
+ mapped.cancelStepTypes = mapCancellationSteps(flow, decision.cancelingSteps);
275
+ const globalTypes = new Set(mapped.cancelStepTypes);
276
+ mapped.cancelSiblingStepTypes = mapCancellationSteps(flow, decision.cancelingSiblingSteps).filter((stepType) => !globalTypes.has(stepType));
277
+ return mapped;
278
+ }
279
+ function mapCancellationSteps(flow, steps) {
280
+ const stepTypes = [];
281
+ const seen = new Set();
282
+ for (const step of steps ?? []) {
283
+ const target = flow.steps.find((candidate) => candidate.step === step);
284
+ if (target === undefined) {
285
+ throw new TypeError("cancellation Step must belong to the Flow");
286
+ }
287
+ if (seen.has(target.name)) {
288
+ continue;
289
+ }
290
+ seen.add(target.name);
291
+ stepTypes.push(target.name);
292
+ }
293
+ return stepTypes;
294
+ }
295
+ function rpcDecision(flow, result) {
296
+ if (result === undefined) {
297
+ return undefined;
298
+ }
299
+ const nextSteps = mapMovements(flow, result.nextSteps ?? []);
300
+ const cancelStepTypes = mapCancellationSteps(flow, result.cancelingSteps);
301
+ if (nextSteps.length === 0 && cancelStepTypes.length === 0) {
302
+ return undefined;
303
+ }
304
+ return ProtoStepDecision.create({ nextSteps, cancelStepTypes });
226
305
  }
227
306
  function mapMovements(flow, movements) {
228
307
  return movements.map((movement) => mapMovement(flow, movement));
@@ -250,6 +329,7 @@ function mapStepOptions(flow, options, skipWaitFor) {
250
329
  return ProtoStepOptions.create({
251
330
  waitForTimeoutSeconds: seconds(options?.waitForMethodTimeoutMs),
252
331
  executeTimeoutSeconds: seconds(options?.executeMethodTimeoutMs),
332
+ heartbeatTimeoutSeconds: heartbeatSeconds(options?.heartbeatTimeoutMs),
253
333
  waitForRetryPolicy: mapRetry(options?.waitForRetry),
254
334
  executeRetryPolicy: mapRetry(options?.executeRetry),
255
335
  waitForFailurePolicy: options?.waitForFailure === "proceed"
@@ -296,12 +376,15 @@ function mapRetry(retry) {
296
376
  };
297
377
  }
298
378
  class ConditionMapper {
379
+ registry;
299
380
  flow;
300
381
  timers = [];
301
382
  channels = [];
383
+ subFlows = [];
302
384
  ids = new Map();
303
385
  used = new Set();
304
- constructor(flow) {
386
+ constructor(registry, flow) {
387
+ this.registry = registry;
305
388
  this.flow = flow;
306
389
  }
307
390
  add(condition, idRequired) {
@@ -328,7 +411,7 @@ class ConditionMapper {
328
411
  durationSeconds: BigInt(seconds(condition.durationMs)),
329
412
  }));
330
413
  }
331
- else {
414
+ else if (condition.kind === "channel") {
332
415
  const registered = this.flow.persistence.get(condition.channelName ?? "");
333
416
  if (!(registered instanceof Channel) && !(registered instanceof ChannelMap)) {
334
417
  throw new TypeError(`Channel is not registered: ${condition.channelName ?? ""}`);
@@ -343,10 +426,141 @@ class ConditionMapper {
343
426
  atMost: condition.atMost,
344
427
  }));
345
428
  }
429
+ else {
430
+ const targetFlow = condition.subFlow;
431
+ if (targetFlow === undefined) {
432
+ throw new TypeError("SubFlow requires a target Flow");
433
+ }
434
+ const target = registeredFlow(this.registry, targetFlow);
435
+ const start = target.startStep;
436
+ if (start === undefined) {
437
+ throw new TypeError(`SubFlow ${target.name} has no starting Step`);
438
+ }
439
+ const options = condition.subFlowOptions ?? {};
440
+ this.subFlows.push(ProtoSubFlowCondition.create({
441
+ conditionId: id,
442
+ subFlowType: target.name,
443
+ startStepType: start.name,
444
+ stepInput: encodeValue(start.step.inputCodec, condition.subFlowInput),
445
+ stepOptions: mapStepOptions(target, start.step.getStepOptions?.(), start.step.waitFor === undefined),
446
+ options: mapSubFlowOptions(target, options),
447
+ subFlowIndex: this.subFlows.length,
448
+ }));
449
+ }
346
450
  this.ids.set(condition, id);
347
451
  return id;
348
452
  }
349
453
  }
454
+ function mapSubFlowOptions(target, options) {
455
+ const timeoutSeconds = seconds(options.timeoutMs);
456
+ const attributes = (options.attributes ?? []).map((initial) => {
457
+ if (target.persistence.get(initial.attribute.name) !== initial.attribute) {
458
+ throw new TypeError(`SubFlow Attribute does not belong to ${target.name}`);
459
+ }
460
+ let key;
461
+ if (initial.attribute instanceof AttributeMap) {
462
+ key = physicalName(initial.attribute.name, initial.instance);
463
+ }
464
+ else {
465
+ if (initial.instance !== undefined) {
466
+ throw new TypeError("static Attribute cannot use an instance");
467
+ }
468
+ key = initial.attribute.name;
469
+ }
470
+ return {
471
+ key,
472
+ value: encodeValue(initial.attribute.codec, initial.value),
473
+ indexConfig: mapIndex(initial.attribute.index),
474
+ syncConfig: mapAttributeStoreSync(initial.attribute),
475
+ };
476
+ });
477
+ const reusePolicy = options.reusePolicy === SubFlowReusePolicy.ATTACH
478
+ ? ProtoSubFlowReusePolicy.SUB_FLOW_REUSE_POLICY_ATTACH
479
+ : options.reusePolicy === SubFlowReusePolicy.ALWAYS_RESTART
480
+ ? ProtoSubFlowReusePolicy.SUB_FLOW_REUSE_POLICY_ALWAYS_RESTART
481
+ : ProtoSubFlowReusePolicy.SUB_FLOW_REUSE_POLICY_RESTART_IF_PREVIOUS_EXITS_ABNORMALLY;
482
+ return ProtoSubFlowOptions.create({
483
+ reusePolicy,
484
+ flowTimeoutSeconds: timeoutSeconds,
485
+ flowTimeoutPolicy: resolveFlowTimeoutPolicy(target, timeoutSeconds, options.timeoutPolicy),
486
+ flowStartDelaySeconds: seconds(options.startDelayMs),
487
+ retryPolicy: mapFlowRetry(options.retryPolicy),
488
+ attributes,
489
+ flowConfigOverride: mapSubFlowConfig(options.configOverride),
490
+ });
491
+ }
492
+ function resolveFlowTimeoutPolicy(flow, timeoutSeconds, policy) {
493
+ const requested = policy ?? FlowTimeoutPolicy.DEFAULT;
494
+ if (timeoutSeconds === 0) {
495
+ if (requested !== FlowTimeoutPolicy.DEFAULT) {
496
+ throw new RangeError("Flow timeout policy requires a positive timeout");
497
+ }
498
+ return ProtoFlowTimeoutPolicy.FLOW_TIMEOUT_POLICY_UNSPECIFIED;
499
+ }
500
+ const resolved = requested === FlowTimeoutPolicy.DEFAULT
501
+ ? flow.hasTimeoutHandler
502
+ ? FlowTimeoutPolicy.HANDLER
503
+ : FlowTimeoutPolicy.FAIL
504
+ : requested;
505
+ if (resolved === FlowTimeoutPolicy.HANDLER && !flow.hasTimeoutHandler) {
506
+ throw new TypeError(`Flow ${flow.name} does not implement handleTimeout`);
507
+ }
508
+ return {
509
+ [FlowTimeoutPolicy.DEFAULT]: ProtoFlowTimeoutPolicy.FLOW_TIMEOUT_POLICY_UNSPECIFIED,
510
+ [FlowTimeoutPolicy.FAIL]: ProtoFlowTimeoutPolicy.FLOW_TIMEOUT_POLICY_FAIL,
511
+ [FlowTimeoutPolicy.CANCEL]: ProtoFlowTimeoutPolicy.FLOW_TIMEOUT_POLICY_CANCEL,
512
+ [FlowTimeoutPolicy.HANDLER]: ProtoFlowTimeoutPolicy.FLOW_TIMEOUT_POLICY_HANDLER,
513
+ }[resolved];
514
+ }
515
+ function mapFlowRetry(retry) {
516
+ if (retry === undefined)
517
+ return undefined;
518
+ return FlowRetryPolicy.create({
519
+ initialIntervalSeconds: seconds(retry.initialIntervalMs),
520
+ backoffCoefficient: retry.backoffCoefficient ?? 0,
521
+ maximumIntervalSeconds: seconds(retry.maximumIntervalMs),
522
+ maximumAttempts: retry.maximumAttempts ?? 0,
523
+ });
524
+ }
525
+ function mapSubFlowConfig(config) {
526
+ if (config === undefined)
527
+ return undefined;
528
+ return ProtoFlowConfig.create({
529
+ activeStepSearchMode: config.activeStepSearchMode === ActiveStepSearchMode.ALL
530
+ ? ProtoActiveStepSearchMode.ACTIVE_STEP_SEARCH_MODE_ENABLED_FOR_ALL
531
+ : config.activeStepSearchMode === undefined
532
+ ? undefined
533
+ : ProtoActiveStepSearchMode.ACTIVE_STEP_SEARCH_MODE_UNSPECIFIED,
534
+ attributeSyncConfigName: mapAttributeStoreName(config),
535
+ continueAsNewThreshold: config.continueAsNewThreshold,
536
+ continueAsNewPageSizeInBytes: config.continueAsNewPageSizeBytes,
537
+ stepDurability: config.stepDurability === "sync"
538
+ ? ProtoStepDurability.STEP_DURABILITY_SYNC
539
+ : config.stepDurability === "async"
540
+ ? ProtoStepDurability.STEP_DURABILITY_ASYNC
541
+ : undefined,
542
+ workerTarget: config.workerTarget === undefined
543
+ ? undefined
544
+ : {
545
+ address: config.workerTarget.address,
546
+ isHeadlessAddress: config.workerTarget.headless ?? false,
547
+ },
548
+ });
549
+ }
550
+ function mapIndex(index) {
551
+ if (index === undefined)
552
+ return undefined;
553
+ const types = {
554
+ [IndexType.KEYWORD]: ProtoIndexType.INDEX_TYPE_KEYWORD,
555
+ [IndexType.FULL_TEXT]: ProtoIndexType.INDEX_TYPE_TEXT,
556
+ [IndexType.KEYWORD_ARRAY]: ProtoIndexType.INDEX_TYPE_KEYWORD_ARRAY,
557
+ [IndexType.INT]: ProtoIndexType.INDEX_TYPE_INT,
558
+ [IndexType.DOUBLE]: ProtoIndexType.INDEX_TYPE_DOUBLE,
559
+ [IndexType.BOOL]: ProtoIndexType.INDEX_TYPE_BOOL,
560
+ [IndexType.DATETIME]: ProtoIndexType.INDEX_TYPE_DATETIME,
561
+ };
562
+ return { enable: true, type: types[index.type], indexKey: index.indexKey ?? "" };
563
+ }
350
564
  function replaceEntryValues(entries, values) {
351
565
  if (entries.length !== values.length) {
352
566
  throw new TypeError("hydrated entry count does not match request");
@@ -367,10 +581,17 @@ function replaceConditionValues(results, values) {
367
581
  offset = next;
368
582
  return replaced;
369
583
  });
584
+ const subFlowResults = results.subFlowResults.map((result) => ({
585
+ ...result,
586
+ results: result.results.map((completion) => ({
587
+ ...completion,
588
+ completedStepOutput: values[offset++],
589
+ })),
590
+ }));
370
591
  if (offset !== values.length) {
371
592
  throw new TypeError("hydrated Condition value count does not match request");
372
593
  }
373
- return { ...results, channelResults };
594
+ return { ...results, channelResults, subFlowResults };
374
595
  }
375
596
  function requireValue(value, kind) {
376
597
  if (value?.kind === undefined) {
@@ -393,6 +614,13 @@ function seconds(milliseconds) {
393
614
  }
394
615
  return milliseconds / 1_000;
395
616
  }
617
+ function heartbeatSeconds(milliseconds) {
618
+ const value = seconds(milliseconds);
619
+ if (value > 2_147_483_647) {
620
+ throw new RangeError("heartbeat timeout exceeds int32 seconds");
621
+ }
622
+ return value;
623
+ }
396
624
  function invalidStepResult(flowType, stepType, method, failure) {
397
625
  if (failure instanceof ValueMappingError) {
398
626
  return failure;