@mnci/az-durable 0.1.1 → 0.1.3

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.
@@ -0,0 +1,628 @@
1
+ 'use strict';
2
+
3
+ var df = require('durable-functions');
4
+
5
+ function _interopNamespaceDefault(e) {
6
+ var n = Object.create(null);
7
+ if (e) {
8
+ Object.keys(e).forEach(function (k) {
9
+ if (k !== 'default') {
10
+ var d = Object.getOwnPropertyDescriptor(e, k);
11
+ Object.defineProperty(n, k, d.get ? d : {
12
+ enumerable: true,
13
+ get: function () { return e[k]; }
14
+ });
15
+ }
16
+ });
17
+ }
18
+ n.default = e;
19
+ return Object.freeze(n);
20
+ }
21
+
22
+ var df__namespace = /*#__PURE__*/_interopNamespaceDefault(df);
23
+
24
+ /**
25
+ * Duplicate-name detection for activities and orchestrations.
26
+ *
27
+ * @remarks
28
+ * Activity and orchestration names are **global to the Function App** and are
29
+ * baked into orchestration history in the task hub. Two features registering
30
+ * the same string is a silent misbinding: the second registration wins, and the
31
+ * first feature's calls quietly execute the wrong handler. Nothing surfaces
32
+ * until replay, by which point the history already refers to the wrong thing.
33
+ *
34
+ * Failing loudly at startup is strictly better, so registration throws.
35
+ */
36
+ /** Every name registered so far, and where. Module-level, matching the SDK's own global scope. */
37
+ const registered = new Map();
38
+ /**
39
+ * Records a name, throwing if it was already taken.
40
+ *
41
+ * @remarks
42
+ * The error names **both** call sites when the stack makes them available. A
43
+ * bare "duplicate name" message sends the reader hunting through a Function App
44
+ * for the other registration, which is the slowest part of fixing this.
45
+ *
46
+ * @param kind - `activity` or `orchestration`, for the message.
47
+ * @param name - The name being registered.
48
+ * @returns Nothing.
49
+ * @throws Error when `name` has already been registered.
50
+ * @typeParam None - this function has no generic type parameters.
51
+ */
52
+ function claimName(kind, name) {
53
+ const previous = registered.get(name);
54
+ if (previous !== undefined) {
55
+ throw new Error(`Duplicate ${kind} name '${name}'. Names are global to the Function App and are ` + 'baked into orchestration history, so two registrations silently misbind.\n' + ` first registered at: ${previous}\n` + ` registered again at: ${callSite()}`);
56
+ }
57
+ registered.set(name, callSite());
58
+ }
59
+ /**
60
+ * The caller's source location, as best the stack can tell.
61
+ *
62
+ * @remarks
63
+ * Best-effort by design: stack formats differ across runtimes, and a bundled or
64
+ * minified app may yield nothing useful. A vague location beats throwing while
65
+ * building an error message, so an unreadable stack degrades to a placeholder
66
+ * rather than failing.
67
+ *
68
+ * @returns A `file:line:col` string, or `<unknown location>`.
69
+ * @throws Never - falls back to a placeholder.
70
+ * @typeParam None - this function has no generic type parameters.
71
+ */
72
+ function callSite() {
73
+ const stack = new Error('locate').stack;
74
+ if (stack === undefined) {
75
+ return '<unknown location>';
76
+ }
77
+ // [0] is the Error line, [1] is callSite, [2] is claimName, [3] is
78
+ // defineActivity/defineOrchestration, [4] is the consumer — the one we want.
79
+ const frame = stack.split('\n', 5)[4];
80
+ return frame === undefined ? '<unknown location>' : frame.trim().replace(/^at\s+/, '');
81
+ }
82
+
83
+ /**
84
+ * Registers an activity and remembers its input and output types.
85
+ *
86
+ * @remarks
87
+ * **Do not annotate `handler` as `ActivityHandler`.** That type is an alias for
88
+ * `FunctionHandler`, which the SDK declares as
89
+ * `(triggerInput: any, context: InvocationContext) => FunctionResult<any>` — so
90
+ * annotating it discards the very signature this function exists to capture and
91
+ * silently reduces the activity to `any` in and `any` out. The same applies to
92
+ * any middleware wrapper typed `(h: ActivityHandler) => ActivityHandler`; make
93
+ * such wrappers generic instead. Both traps are lintable — see the
94
+ * `no-untyped-activity-handler` rule.
95
+ *
96
+ * `TOutput` is wrapped in `Awaited` so an `async` handler contributes its
97
+ * resolved type rather than a `Promise`.
98
+ *
99
+ * @param name - The activity name, a literal. Never derived from a variable or
100
+ * file name: it is baked into orchestration history, so a rename breaks every
101
+ * in-flight instance.
102
+ * @param handler - The activity implementation.
103
+ * @returns The activity, carrying its input and output types.
104
+ * @throws Error when `name` is already registered.
105
+ * @typeParam TInput - The JSON-serialisable input.
106
+ * @typeParam TOutput - The handler's return type, awaited.
107
+ */
108
+ function defineActivity(name, handler) {
109
+ claimName('activity', name);
110
+ const registered = df__namespace.app.activity(name, {
111
+ handler: handler
112
+ });
113
+ return {
114
+ name,
115
+ registered
116
+ };
117
+ }
118
+ /**
119
+ * Schedules an activity without yielding it, for fan-out.
120
+ *
121
+ * @remarks
122
+ * The single place in this package that schedules an activity. `callActivity`
123
+ * is implemented in terms of it, so there is exactly one line to audit against
124
+ * an SDK change.
125
+ *
126
+ * **Scheduled through `context`, not through `activity.registered`,** and the
127
+ * two are equivalent — verified in the SDK source rather than assumed:
128
+ *
129
+ * ```
130
+ * registered(input) -> new AtomicTask(false, new CallActivityAction(name, input))
131
+ * context.df.callActivity(...) -> new AtomicTask(false, new CallActivityAction(name, input))
132
+ * ```
133
+ *
134
+ * `RegisteredActivityTask` is an `AtomicTask` subclass that only ADDS
135
+ * `withRetry`; the retry paths are identical too, both producing
136
+ * `RetryableTask(AtomicTask(CallActivityWithRetryAction(...)))`. The action is
137
+ * what enters orchestration history, so replay is unaffected.
138
+ *
139
+ * Routing through `context` is what makes {@link runWorkflow} possible without
140
+ * reading `task.action.functionName` — an undocumented internal the package's
141
+ * non-goals forbid depending on. It also makes every helper here uniformly
142
+ * context-first.
143
+ *
144
+ * @param context - The orchestration context.
145
+ * @param activity - The activity to schedule.
146
+ * @param input - The input, checked against the activity's declared type.
147
+ * @param retry - Optional retry policy.
148
+ * @returns A scheduled task, for `all`/`any`.
149
+ * @throws Never - scheduling is synchronous and cannot fail here.
150
+ * @typeParam TInput - The activity's input type.
151
+ * @typeParam TOutput - The activity's output type.
152
+ */
153
+ function activityTask(context, activity, input, retry) {
154
+ const task = retry === undefined ? context.df.callActivity(activity.name, input) : context.df.callActivityWithRetry(activity.name, retry, input);
155
+ return {
156
+ task
157
+ };
158
+ }
159
+ /**
160
+ * Calls an activity and returns its typed result.
161
+ *
162
+ * @remarks
163
+ * **Must be invoked with `yield*`, not `yield`.** The delegation is what carries
164
+ * the type: `yield*` returns this generator's `TReturn`, which is per-call
165
+ * generic, whereas a generator's `TNext` is shared by every `yield` and so can
166
+ * never be typed per call. A bare `yield` is a compile error rather than a
167
+ * silent `any` — `callActivity` returns a `Generator`, and yielding one where a
168
+ * `Task` is expected does not typecheck — but the error message is obscure, so
169
+ * prefer the lint rule's.
170
+ *
171
+ * Determinism is unaffected. The task yielded up to the Durable driver is the
172
+ * identical object a hand-written call would yield, so replay history and
173
+ * in-flight instances are untouched. This is a type-level change only.
174
+ *
175
+ * @param context - The orchestration context.
176
+ * @param activity - The activity to call.
177
+ * @param input - The input, checked against the activity's declared type.
178
+ * @param retry - Optional retry policy.
179
+ * @returns A generator to delegate to; its return value is the activity output.
180
+ * @throws Whatever the activity threw, once the driver resumes with a failure.
181
+ * @typeParam TInput - The activity's input type.
182
+ * @typeParam TOutput - The activity's output type.
183
+ */
184
+ function* callActivity(context, activity, input, retry) {
185
+ const result = yield activityTask(context, activity, input, retry).task;
186
+ // The one cast in the package. The SDK resumes the generator with the
187
+ // activity's result typed `any`; `TOutput` is the claim `defineActivity`
188
+ // captured from the handler's real signature.
189
+ return result;
190
+ }
191
+
192
+ /**
193
+ * Registers an orchestration, handing the handler its deserialised input.
194
+ *
195
+ * @remarks
196
+ * The SDK's `OrchestrationHandler` takes **only** `context` — there is no input
197
+ * parameter — so this wrapper calls `getInput` itself and passes the result as a
198
+ * second argument. That is why consumers never write
199
+ * `context.df.getInput() as SomeType`.
200
+ *
201
+ * @param name - The orchestration name, a literal. Baked into history; never derive it.
202
+ * @param handler - The orchestration generator, receiving context and input.
203
+ * @param options - Optional input validation. See {@link DefineOrchestrationOptions}.
204
+ * @returns The orchestration, carrying its input and output types.
205
+ * @throws Error when `name` is already registered.
206
+ * @typeParam TInput - The JSON-serialisable input.
207
+ * @typeParam TOutput - The value the orchestration returns.
208
+ */
209
+ function defineOrchestration(name, handler, options) {
210
+ claimName('orchestration', name);
211
+ const parse = options?.parse;
212
+ const bind = context => ({
213
+ name,
214
+ continueAsNew: next => {
215
+ context.df.continueAsNew(next);
216
+ }
217
+ });
218
+ const registered = df__namespace.app.orchestration(name, function* (context) {
219
+ const raw = context.df.getInput();
220
+ const input = parse === undefined ? raw : parse(raw);
221
+ return yield* handler(context, input, bind(context));
222
+ });
223
+ return {
224
+ name,
225
+ registered,
226
+ handler: (context, input) => handler(context, input, bind(context))
227
+ };
228
+ }
229
+ /**
230
+ * Calls a sub-orchestration and returns its typed result.
231
+ *
232
+ * @remarks
233
+ * **Must be invoked with `yield*`.** See `callActivity` for why delegation is
234
+ * what carries the type.
235
+ *
236
+ * @param orchestration - The sub-orchestration to call.
237
+ * @param input - The input, checked against its declared type.
238
+ * @param options - Optional instance id and retry policy.
239
+ * @returns A generator to delegate to; its return value is the sub-orchestration output.
240
+ * @throws Whatever the sub-orchestration threw, once the driver resumes with a failure.
241
+ * @typeParam TInput - The sub-orchestration's input type.
242
+ * @typeParam TOutput - The sub-orchestration's output type.
243
+ */
244
+ function* callSubOrchestration(context, orchestration, input, options) {
245
+ const result = yield subOrchestrationTask(context, orchestration, input, options).task;
246
+ return result;
247
+ }
248
+ /**
249
+ * Schedules a sub-orchestration without yielding it.
250
+ *
251
+ * @remarks
252
+ * The task form of {@link callSubOrchestration}, so several sub-orchestrations
253
+ * can run concurrently through `all`. Fanning out over sub-orchestrations is
254
+ * the standard way to bound a large batch — each child gets its own history,
255
+ * so the parent's history does not grow with the batch size.
256
+ *
257
+ * @param context - The orchestration context.
258
+ * @param orchestration - The sub-orchestration to schedule.
259
+ * @param input - Its input, checked against its declared type.
260
+ * @param options - Optional fixed instance id and retry policy.
261
+ * @returns A task carrying the sub-orchestration's output type.
262
+ * @throws Never - scheduling only.
263
+ * @typeParam TInput - The sub-orchestration's input type.
264
+ * @typeParam TOutput - The sub-orchestration's output type.
265
+ */
266
+ function subOrchestrationTask(context, orchestration, input, options) {
267
+ const retry = options?.retry;
268
+ const task = retry === undefined ? context.df.callSubOrchestrator(orchestration.name, input, options?.instanceId) : context.df.callSubOrchestratorWithRetry(orchestration.name, retry, input, options?.instanceId);
269
+ return {
270
+ task
271
+ };
272
+ }
273
+
274
+ /**
275
+ * Starts an orchestration with an input checked against its declared type.
276
+ *
277
+ * @remarks
278
+ * `DurableClient.startNew` takes the orchestration **name** and an options
279
+ * object carrying `input`, both untyped. This narrows the pair so a caller
280
+ * cannot start an orchestration with the wrong payload shape.
281
+ *
282
+ * @param client - The Durable client, from `df.getClient(context)`.
283
+ * @param orchestration - The orchestration to start.
284
+ * @param input - The input, checked against its declared type.
285
+ * @param options - Optional instance id.
286
+ * @returns The new instance id.
287
+ * @throws Propagates whatever the client throws.
288
+ * @typeParam TInput - The orchestration's input type.
289
+ * @typeParam TOutput - The orchestration's output type, unused at runtime.
290
+ */
291
+ async function startOrchestration(client, orchestration, input, options) {
292
+ const instanceId = options?.instanceId;
293
+ return await client.startNew(orchestration.name, {
294
+ input,
295
+ ...(instanceId !== undefined && {
296
+ instanceId
297
+ })
298
+ });
299
+ }
300
+
301
+ /**
302
+ * Builds a real SDK `RetryOptions` from a plain object.
303
+ *
304
+ * @remarks
305
+ * Returns a genuine class instance rather than a structurally-similar literal,
306
+ * deliberately: handing `callActivityWithRetry` a plain object would depend on
307
+ * the SDK reading it structurally, which is undocumented and exactly the kind
308
+ * of internal this package refuses to rely on.
309
+ *
310
+ * Only the properties actually supplied are assigned, so the SDK's own
311
+ * defaults stand for the rest instead of being overwritten with `undefined`.
312
+ *
313
+ * @param policy - The retry settings.
314
+ * @returns An SDK `RetryOptions` instance.
315
+ * @throws Whatever the SDK constructor throws for an invalid interval.
316
+ * @typeParam None - this function has no generic type parameters.
317
+ */
318
+ function retryPolicy(policy) {
319
+ const options = new df.RetryOptions(policy.firstRetryIntervalInMilliseconds, policy.maxNumberOfAttempts);
320
+ if (policy.backoffCoefficient !== undefined) {
321
+ options.backoffCoefficient = policy.backoffCoefficient;
322
+ }
323
+ if (policy.maxRetryIntervalInMilliseconds !== undefined) {
324
+ options.maxRetryIntervalInMilliseconds = policy.maxRetryIntervalInMilliseconds;
325
+ }
326
+ if (policy.retryTimeoutInMilliseconds !== undefined) {
327
+ options.retryTimeoutInMilliseconds = policy.retryTimeoutInMilliseconds;
328
+ }
329
+ return options;
330
+ }
331
+
332
+ /**
333
+ * Waits for every task, preserving tuple positions.
334
+ *
335
+ * @remarks
336
+ * **Must be invoked with `yield *`.** Takes `context` because `Task.all` is an
337
+ * instance member of `context.df`, not a static — the build plan's
338
+ * context-free signature cannot reach it.
339
+ *
340
+ * @param context - The orchestration context.
341
+ * @param tasks - The scheduled tasks, as a tuple.
342
+ * @returns A generator whose return value is the outputs, in input order.
343
+ * @throws `AggregatedError` when any task failed, matching the SDK.
344
+ * @typeParam T - The tuple of tasks.
345
+ */
346
+ function* all(context, tasks) {
347
+ const results = yield context.df.Task.all(tasks.map(t => t.task));
348
+ return results;
349
+ }
350
+ /**
351
+ * Waits for the first task to complete and returns **which one won**.
352
+ *
353
+ * @remarks
354
+ * Returns the winning task, not its result, because that is what the SDK does:
355
+ * `Task.any` is documented as returning "the first Task from tasks to
356
+ * complete", and the SDK's own example compares it by identity
357
+ * (`if (winner === otherTask)`). The build plan's signature returned the
358
+ * output type instead, which would hand back a `Task` at runtime while the
359
+ * compiler believed it was the output — the exact class of silent mistyping
360
+ * this package exists to prevent.
361
+ *
362
+ * The winner is mapped back to the `TypedTask` the caller passed, so `===`
363
+ * against the original works. Read its value with {@link resultOf}.
364
+ *
365
+ * **Must be invoked with `yield *`.**
366
+ *
367
+ * @param context - The orchestration context.
368
+ * @param tasks - The scheduled tasks.
369
+ * @returns A generator whose return value is the winning task.
370
+ * @throws Error when the SDK returns a task that was not one of the inputs.
371
+ * @typeParam T - The tuple of tasks.
372
+ */
373
+ function* any(context, tasks) {
374
+ const won = yield context.df.Task.any(tasks.map(t => t.task));
375
+ const winner = tasks.find(t => t.task === won);
376
+ if (winner === undefined) {
377
+ // Not defensive padding: if this ever fires, the SDK returned something
378
+ // other than one of the tasks handed to it, and silently returning the
379
+ // wrong element would misroute the branch the caller takes next.
380
+ throw new Error('Task.any returned a task that was not one of the inputs.');
381
+ }
382
+ return winner;
383
+ }
384
+ /**
385
+ * Reads a completed task's result, typed.
386
+ *
387
+ * @remarks
388
+ * `Task.result` is declared `unknown` by the SDK. This applies the output type
389
+ * the `TypedTask` was carrying all along. Only meaningful after the task has
390
+ * completed — typically on the winner from {@link any}.
391
+ *
392
+ * @param task - A completed task.
393
+ * @returns Its result, typed as the task's output.
394
+ * @throws Never - reads a property.
395
+ * @typeParam TOutput - The task's output type.
396
+ */
397
+ function resultOf(task) {
398
+ return task.task.result;
399
+ }
400
+
401
+ /**
402
+ * Declares an external event and its payload type.
403
+ *
404
+ * @remarks
405
+ * Deliberately does not register anything — external events have no
406
+ * registration step in Durable Functions. This exists only to pair a name with
407
+ * a payload type so the waiter and the raiser cannot disagree.
408
+ *
409
+ * @param name - The event name, a literal.
410
+ * @returns The event reference.
411
+ * @throws Never - constructs an object.
412
+ * @typeParam TPayload - The payload type.
413
+ */
414
+ function defineEvent(name) {
415
+ return {
416
+ name
417
+ };
418
+ }
419
+ /**
420
+ * Waits for an external event and returns its typed payload.
421
+ *
422
+ * @remarks
423
+ * **Must be invoked with `yield *`.**
424
+ *
425
+ * @param context - The orchestration context.
426
+ * @param event - The event to wait for.
427
+ * @returns A generator whose return value is the event payload.
428
+ * @throws Never - resolves when the event arrives.
429
+ * @typeParam TPayload - The payload type.
430
+ */
431
+ function* waitForEvent(context, event) {
432
+ const payload = yield eventTask(context, event).task;
433
+ return payload;
434
+ }
435
+ /**
436
+ * Schedules a wait for an external event, without yielding it.
437
+ *
438
+ * @remarks
439
+ * The task form of {@link waitForEvent}, and the reason it exists is a gap the
440
+ * reconstructed workflows found: `any` and `all` take `TypedTask`s, so with
441
+ * only the generator form the single most common Durable Functions pattern —
442
+ * **wait for human approval, or time out** — could not be expressed at all.
443
+ *
444
+ * Pair it with {@link timerTask} and hand both to `any`.
445
+ *
446
+ * @param context - The orchestration context.
447
+ * @param event - The event to wait for.
448
+ * @returns A task carrying the event's payload type.
449
+ * @throws Never - scheduling only.
450
+ * @typeParam TPayload - The payload type.
451
+ */
452
+ function eventTask(context, event) {
453
+ return {
454
+ task: context.df.waitForExternalEvent(event.name)
455
+ };
456
+ }
457
+ /**
458
+ * Raises an external event to a waiting instance, with a checked payload.
459
+ *
460
+ * @remarks
461
+ * The client half of {@link waitForEvent}. Pairing both sides through the same
462
+ * `EventRef` is what stops the raiser and the waiter disagreeing about the
463
+ * payload shape — the SDK types `eventData` as `unknown`, so nothing else would.
464
+ *
465
+ * @param client - The Durable client.
466
+ * @param instanceId - The instance to signal.
467
+ * @param event - The event being raised.
468
+ * @param payload - The payload, checked against the event's declared type.
469
+ * @returns A promise resolving when the event is enqueued.
470
+ * @throws Propagates whatever the client throws.
471
+ * @typeParam TPayload - The payload type.
472
+ */
473
+ async function raiseEvent(client, instanceId, event, payload) {
474
+ await client.raiseEvent(instanceId, event.name, payload);
475
+ }
476
+
477
+ /**
478
+ * The current time, safely for replay.
479
+ *
480
+ * @remarks
481
+ * `new Date()` and `Date.now()` return a different value on every replay, which
482
+ * silently corrupts orchestration output rather than failing. `currentUtcDateTime`
483
+ * is derived from orchestration history and returns the same value at the same
484
+ * point every time. This is the replacement the lint rule suggests.
485
+ *
486
+ * @param context - The orchestration context.
487
+ * @returns The replay-safe current time.
488
+ * @throws Never - reads a property.
489
+ * @typeParam None - this function has no generic type parameters.
490
+ */
491
+ function now(context) {
492
+ return context.df.currentUtcDateTime;
493
+ }
494
+ /**
495
+ * Sleeps until an absolute time.
496
+ *
497
+ * @remarks
498
+ * **Must be invoked with `yield *`.**
499
+ *
500
+ * @param context - The orchestration context.
501
+ * @param when - The absolute time to wake at.
502
+ * @returns A generator that completes when the timer fires.
503
+ * @throws Never - the timer either fires or the instance ends.
504
+ * @typeParam None - this function has no generic type parameters.
505
+ */
506
+ function* sleepUntil(context, when) {
507
+ yield context.df.createTimer(when);
508
+ }
509
+ /**
510
+ * Sleeps for a duration.
511
+ *
512
+ * @remarks
513
+ * The deadline is computed from {@link now}, **never** `Date.now()`. Using wall
514
+ * clock here would make the deadline move on every replay, so a timer could fire
515
+ * early, late, or repeatedly. This is the single most common determinism bug in
516
+ * hand-written orchestrations.
517
+ *
518
+ * **Must be invoked with `yield *`.**
519
+ *
520
+ * @param context - The orchestration context.
521
+ * @param ms - How long to sleep, in milliseconds.
522
+ * @returns A generator that completes when the timer fires.
523
+ * @throws Never - the timer either fires or the instance ends.
524
+ * @typeParam None - this function has no generic type parameters.
525
+ */
526
+ function* sleepFor(context, ms) {
527
+ yield* sleepUntil(context, new Date(now(context).getTime() + ms));
528
+ }
529
+ /**
530
+ * Schedules a durable timer for an absolute instant, without yielding it.
531
+ *
532
+ * @remarks
533
+ * The task form of {@link sleepUntil}, so a timer can race an event or an
534
+ * activity through `any`. See {@link TypedTimerTask} for why the returned
535
+ * value carries `cancel` — **a pending timer keeps the instance alive**, so the
536
+ * loser of a race must be cancelled.
537
+ *
538
+ * @param context - The orchestration context.
539
+ * @param when - The instant to fire at.
540
+ * @returns A cancellable timer task.
541
+ * @throws Never - scheduling only.
542
+ * @typeParam None - this function has no generic type parameters.
543
+ */
544
+ function timerTaskUntil(context, when) {
545
+ const task = context.df.createTimer(when);
546
+ return {
547
+ task,
548
+ cancel: () => {
549
+ task.cancel();
550
+ },
551
+ isCompleted: () => task.isCompleted
552
+ };
553
+ }
554
+ /**
555
+ * Schedules a durable timer a fixed duration ahead, without yielding it.
556
+ *
557
+ * @remarks
558
+ * Computes the deadline from `context.df.currentUtcDateTime`, never
559
+ * `Date.now()` — the same replay-safety reason {@link sleepFor} does.
560
+ *
561
+ * @param context - The orchestration context.
562
+ * @param ms - How far ahead to fire, in milliseconds.
563
+ * @returns A cancellable timer task.
564
+ * @throws Never - scheduling only.
565
+ * @typeParam None - this function has no generic type parameters.
566
+ */
567
+ function timerTask(context, ms) {
568
+ return timerTaskUntil(context, new Date(now(context).getTime() + ms));
569
+ }
570
+
571
+ /**
572
+ * Declares the custom statuses an orchestration can report.
573
+ *
574
+ * @remarks
575
+ * `const` on the type parameter preserves the literal types, so `setStatus`
576
+ * can check the key against the actual set rather than against `string`. The
577
+ * object is returned unchanged — this is a typing device, not a transform.
578
+ *
579
+ * @param statuses - The status map.
580
+ * @returns The same object, with its literal types preserved.
581
+ * @throws Never - returns its argument.
582
+ * @typeParam T - The status map's literal type.
583
+ */
584
+ function defineStatuses(statuses) {
585
+ return statuses;
586
+ }
587
+ /**
588
+ * Sets the orchestration's custom status from a declared set.
589
+ *
590
+ * @remarks
591
+ * `setCustomStatus` accepts `unknown`, so a typo in a status string is invisible
592
+ * until someone reads the instance's status and finds a value nothing produces.
593
+ * Constraining `key` to the declared map is the whole point.
594
+ *
595
+ * @param context - The orchestration context.
596
+ * @param statuses - The declared status map.
597
+ * @param key - Which status to set; checked against the map.
598
+ * @returns Nothing.
599
+ * @throws Never - delegates to the SDK.
600
+ * @typeParam T - The status map's literal type.
601
+ */
602
+ function setStatus(context, statuses, key) {
603
+ context.df.setCustomStatus(statuses[key]);
604
+ }
605
+
606
+ exports.activityTask = activityTask;
607
+ exports.all = all;
608
+ exports.any = any;
609
+ exports.callActivity = callActivity;
610
+ exports.callSubOrchestration = callSubOrchestration;
611
+ exports.defineActivity = defineActivity;
612
+ exports.defineEvent = defineEvent;
613
+ exports.defineOrchestration = defineOrchestration;
614
+ exports.defineStatuses = defineStatuses;
615
+ exports.eventTask = eventTask;
616
+ exports.now = now;
617
+ exports.raiseEvent = raiseEvent;
618
+ exports.resultOf = resultOf;
619
+ exports.retryPolicy = retryPolicy;
620
+ exports.setStatus = setStatus;
621
+ exports.sleepFor = sleepFor;
622
+ exports.sleepUntil = sleepUntil;
623
+ exports.startOrchestration = startOrchestration;
624
+ exports.subOrchestrationTask = subOrchestrationTask;
625
+ exports.timerTask = timerTask;
626
+ exports.timerTaskUntil = timerTaskUntil;
627
+ exports.waitForEvent = waitForEvent;
628
+ //# sourceMappingURL=index.cjs.js.map