@dudousxd/nestjs-durable 0.48.2 → 0.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -58,7 +58,7 @@ __export(index_exports, {
58
58
  ProxyRunGateway: () => ProxyRunGateway,
59
59
  RUN_GATEWAY: () => RUN_GATEWAY,
60
60
  RUN_REDIS_WORKER: () => RUN_REDIS_WORKER,
61
- RunGateway: () => import_nestjs_durable_core17.RunGateway,
61
+ RunGateway: () => import_nestjs_durable_core18.RunGateway,
62
62
  RunRequestResponder: () => RunRequestResponder,
63
63
  STEP_INTERCEPTOR_METADATA: () => STEP_INTERCEPTOR_METADATA,
64
64
  Step: () => Step,
@@ -71,7 +71,7 @@ __export(index_exports, {
71
71
  UNSUPPORTED_RUN_REQUEST: () => UNSUPPORTED_RUN_REQUEST,
72
72
  WORKFLOW_METADATA: () => WORKFLOW_METADATA,
73
73
  Workflow: () => Workflow,
74
- WorkflowEngine: () => import_nestjs_durable_core17.WorkflowEngine,
74
+ WorkflowEngine: () => import_nestjs_durable_core18.WorkflowEngine,
75
75
  WorkflowService: () => WorkflowService,
76
76
  attributesOf: () => attributesOf,
77
77
  entityConfigFor: () => entityConfigFor,
@@ -85,7 +85,7 @@ __export(index_exports, {
85
85
  isOperatorRole: () => isOperatorRole,
86
86
  isStepInterceptor: () => isStepInterceptor,
87
87
  onErrorCodesOf: () => onErrorCodesOf,
88
- readSearchAttributes: () => import_nestjs_durable_core17.readSearchAttributes,
88
+ readSearchAttributes: () => import_nestjs_durable_core18.readSearchAttributes,
89
89
  thinWorkerProviders: () => thinWorkerProviders,
90
90
  unavailableRunGateway: () => unavailableRunGateway
91
91
  });
@@ -209,6 +209,9 @@ __name(fileOfFrame, "fileOfFrame");
209
209
  var WORKFLOW_METADATA = Symbol("nestjs-durable:workflow");
210
210
  function Workflow(options) {
211
211
  const declaredIn = declaringFile(Workflow);
212
+ if (options.input !== void 0 && options.inputSchema !== void 0) {
213
+ throw new Error(`@Workflow ${options.name}: set either \`input\` or its alias \`inputSchema\`, not both`);
214
+ }
212
215
  return (target) => {
213
216
  rememberDeclaringFile(target, declaredIn);
214
217
  const meta = {
@@ -220,7 +223,8 @@ function Workflow(options) {
220
223
  singleton: options.singleton,
221
224
  concurrency: options.concurrency,
222
225
  executionTimeout: options.executionTimeout,
223
- inputSchema: options.inputSchema,
226
+ input: options.input ?? options.inputSchema,
227
+ output: options.output,
224
228
  validateInput: options.validateInput,
225
229
  searchAttributes: options.searchAttributes,
226
230
  onEvent: options.onEvent,
@@ -474,10 +478,98 @@ function tenantUnsupported(method) {
474
478
  __name(tenantUnsupported, "tenantUnsupported");
475
479
 
476
480
  // src/durable-worker.module.ts
477
- var import_nestjs_durable_core5 = require("@dudousxd/nestjs-durable-core");
481
+ var import_nestjs_durable_core6 = require("@dudousxd/nestjs-durable-core");
478
482
  var import_common2 = require("@nestjs/common");
479
483
  var import_core = require("@nestjs/core");
480
484
 
485
+ // src/schema-parse.ts
486
+ var import_nestjs_durable_core4 = require("@dudousxd/nestjs-durable-core");
487
+ function schemaParser(schema, kind, label) {
488
+ const code = kind === "input" ? "invalid_input" : "invalid_output";
489
+ if (isStandardSchema(schema)) {
490
+ return async (value) => {
491
+ const result = await schema["~standard"].validate(value);
492
+ if (result.issues) {
493
+ const issues = result.issues.map((i) => ({
494
+ message: i.message,
495
+ ...i.path ? {
496
+ path: i.path.map((p) => String(typeof p === "object" ? p.key : p))
497
+ } : {}
498
+ }));
499
+ throw new import_nestjs_durable_core4.FatalError(`invalid ${label}: ${formatIssues(issues)}`, code, issues);
500
+ }
501
+ return result.value;
502
+ };
503
+ }
504
+ if (isZodLike(schema)) {
505
+ return async (value) => {
506
+ const result = schema.safeParse(value);
507
+ if (!result.success) {
508
+ const issues = result.error.issues.map((i) => ({
509
+ message: i.message,
510
+ path: i.path.map(String)
511
+ }));
512
+ throw new import_nestjs_durable_core4.FatalError(`invalid ${label}: ${formatIssues(issues)}`, code, issues);
513
+ }
514
+ return result.data;
515
+ };
516
+ }
517
+ if (typeof schema === "function") return classValidatorParser(schema, code, label);
518
+ throw new Error(`${label}: expected a Standard Schema (zod, valibot, \u2026) or a class-validator DTO class`);
519
+ }
520
+ __name(schemaParser, "schemaParser");
521
+ function classValidatorParser(cls, code, label) {
522
+ return async (value) => {
523
+ let cv;
524
+ let ct;
525
+ try {
526
+ cv = await import("class-validator");
527
+ ct = await import("class-transformer");
528
+ } catch {
529
+ throw new Error(`${label} uses a class-validator DTO, which needs the optional peers "class-validator" and "class-transformer" \u2014 install them, or use a Standard Schema (zod, valibot, \u2026) instead.`);
530
+ }
531
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
532
+ const got = value === null ? "null" : Array.isArray(value) ? "an array" : typeof value;
533
+ const message = `expected an object, got ${got}`;
534
+ throw new import_nestjs_durable_core4.FatalError(`invalid ${label}: ${message}`, code, [
535
+ {
536
+ message
537
+ }
538
+ ]);
539
+ }
540
+ const instance = ct.plainToInstance(cls, value);
541
+ const errors = await cv.validate(instance, {
542
+ whitelist: true
543
+ });
544
+ if (errors.length > 0) {
545
+ const issues = errors.map((e) => ({
546
+ message: Object.values(e.constraints ?? {
547
+ _: `${e.property} is invalid`
548
+ }).join(", "),
549
+ path: [
550
+ String(e.property)
551
+ ]
552
+ }));
553
+ const message = issues.map((i) => i.message).join("; ");
554
+ throw new import_nestjs_durable_core4.FatalError(`invalid ${label}: ${message}`, code, issues);
555
+ }
556
+ return instance;
557
+ };
558
+ }
559
+ __name(classValidatorParser, "classValidatorParser");
560
+ function isStandardSchema(schema) {
561
+ return (typeof schema === "object" || typeof schema === "function") && schema !== null && "~standard" in schema;
562
+ }
563
+ __name(isStandardSchema, "isStandardSchema");
564
+ function isZodLike(schema) {
565
+ return typeof schema === "object" && schema !== null && typeof schema.safeParse === "function";
566
+ }
567
+ __name(isZodLike, "isZodLike");
568
+ function formatIssues(issues) {
569
+ return issues.map((i) => i.path && i.path.length > 0 ? `${i.path.join(".")}: ${i.message}` : i.message).join("; ");
570
+ }
571
+ __name(formatIssues, "formatIssues");
572
+
481
573
  // src/discovery-helpers.ts
482
574
  function scanWorkflows(discovery, register) {
483
575
  for (const wrapper of discovery.getProviders()) {
@@ -504,10 +596,12 @@ function scanSteps(discovery, scanner, register) {
504
596
  const meta = getDurableStepMeta(method);
505
597
  if (!meta) continue;
506
598
  const boundMethod = method;
599
+ const parseInput = meta.input && schemaParser(meta.input, "input", `step "${meta.name}" input`);
600
+ const parseOutput = meta.output && schemaParser(meta.output, "output", `step "${meta.name}" output`);
507
601
  const handler = /* @__PURE__ */ __name(async (input, log) => {
508
- const validInput = meta.input ? meta.input.parse(input) : input;
602
+ const validInput = parseInput ? await parseInput(input) : input;
509
603
  const output = await boundMethod.call(instance, validInput, log);
510
- return meta.output ? meta.output.parse(output) : output;
604
+ return parseOutput ? parseOutput(output) : output;
511
605
  }, "handler");
512
606
  register(meta, handler);
513
607
  }
@@ -516,7 +610,7 @@ function scanSteps(discovery, scanner, register) {
516
610
  __name(scanSteps, "scanSteps");
517
611
 
518
612
  // src/on-error-handlers.ts
519
- var import_nestjs_durable_core4 = require("@dudousxd/nestjs-durable-core");
613
+ var import_nestjs_durable_core5 = require("@dudousxd/nestjs-durable-core");
520
614
  function onErrorHandlersOf(meta, instance, scanner) {
521
615
  const handlers = [];
522
616
  const routes = [];
@@ -537,7 +631,7 @@ function onErrorHandlersOf(meta, instance, scanner) {
537
631
  for (const r of meta.onError ?? []) {
538
632
  routes.push({
539
633
  code: r.code === void 0 || typeof r.code === "string" ? r.code : r.code.code,
540
- workflow: (0, import_nestjs_durable_core4.workflowName)(r.workflow)
634
+ workflow: (0, import_nestjs_durable_core5.workflowName)(r.workflow)
541
635
  });
542
636
  }
543
637
  return {
@@ -547,6 +641,24 @@ function onErrorHandlersOf(meta, instance, scanner) {
547
641
  }
548
642
  __name(onErrorHandlersOf, "onErrorHandlersOf");
549
643
 
644
+ // src/workflow-io.ts
645
+ function workflowIo(meta) {
646
+ const parseInput = meta.input && schemaParser(meta.input, "input", `workflow "${meta.name}" input`);
647
+ const parseOutput = meta.output && schemaParser(meta.output, "output", `workflow "${meta.name}" output`);
648
+ const validateInput = meta.validateInput;
649
+ return {
650
+ validateAtStart: parseInput || validateInput ? async (input) => {
651
+ if (parseInput) await parseInput(input);
652
+ await validateInput?.(input);
653
+ } : void 0,
654
+ wrap: /* @__PURE__ */ __name((body) => !parseInput && !parseOutput ? body : async (ctx, input) => {
655
+ const output = await body(ctx, parseInput ? await parseInput(input) : input);
656
+ return parseOutput ? parseOutput(output) : output;
657
+ }, "wrap")
658
+ };
659
+ }
660
+ __name(workflowIo, "workflowIo");
661
+
550
662
  // src/runtime-registration.ts
551
663
  function registerOnRuntime(runtime, scanner, meta, instance, origin) {
552
664
  const { handlers, routes } = onErrorHandlersOf(meta, instance, scanner);
@@ -556,7 +668,8 @@ function registerOnRuntime(runtime, scanner, meta, instance, origin) {
556
668
  origin
557
669
  } : {}
558
670
  };
559
- runtime.registerWorkflow(meta.name, (ctx, input) => instance.run(ctx, input), {
671
+ const body = workflowIo(meta).wrap((ctx, input) => instance.run(ctx, input));
672
+ runtime.registerWorkflow(meta.name, body, {
560
673
  ...announced,
561
674
  ...meta.requires !== void 0 ? {
562
675
  requires: meta.requires
@@ -632,7 +745,7 @@ var ThinWorkflowRegistrar = class {
632
745
  ThinWorkflowRegistrar = _ts_decorate2([
633
746
  (0, import_common2.Injectable)(),
634
747
  _ts_param(2, (0, import_common2.Inject)(DURABLE_WORKER_RUNTIME)),
635
- _ts_param(3, (0, import_common2.Inject)(import_nestjs_durable_core5.DURABLE_OPTIONS_CANONICAL)),
748
+ _ts_param(3, (0, import_common2.Inject)(import_nestjs_durable_core6.DURABLE_OPTIONS_CANONICAL)),
636
749
  _ts_metadata2("design:type", Function),
637
750
  _ts_metadata2("design:paramtypes", [
638
751
  typeof import_core.DiscoveryService === "undefined" ? Object : import_core.DiscoveryService,
@@ -664,7 +777,7 @@ var ThinStepRegistrar = class {
664
777
  ThinStepRegistrar = _ts_decorate2([
665
778
  (0, import_common2.Injectable)(),
666
779
  _ts_param(2, (0, import_common2.Inject)(DURABLE_WORKER_RUNTIME)),
667
- _ts_param(3, (0, import_common2.Inject)(import_nestjs_durable_core5.DURABLE_OPTIONS_CANONICAL)),
780
+ _ts_param(3, (0, import_common2.Inject)(import_nestjs_durable_core6.DURABLE_OPTIONS_CANONICAL)),
668
781
  _ts_metadata2("design:type", Function),
669
782
  _ts_metadata2("design:paramtypes", [
670
783
  typeof import_core.DiscoveryService === "undefined" ? Object : import_core.DiscoveryService,
@@ -719,7 +832,7 @@ var ThinWorkerBootstrap = class {
719
832
  ThinWorkerBootstrap = _ts_decorate2([
720
833
  (0, import_common2.Injectable)(),
721
834
  _ts_param(0, (0, import_common2.Inject)(DURABLE_WORKER_RUNTIME)),
722
- _ts_param(1, (0, import_common2.Inject)(import_nestjs_durable_core5.DURABLE_OPTIONS_CANONICAL)),
835
+ _ts_param(1, (0, import_common2.Inject)(import_nestjs_durable_core6.DURABLE_OPTIONS_CANONICAL)),
723
836
  _ts_param(2, (0, import_common2.Inject)(RUN_REDIS_WORKER)),
724
837
  _ts_param(3, (0, import_common2.Inject)(DURABLE_WORKER_RUNNERS)),
725
838
  _ts_metadata2("design:type", Function),
@@ -749,7 +862,7 @@ function thinWorkerProviders() {
749
862
  workflowGroup: options.partition ?? ""
750
863
  }) : null, "useFactory"),
751
864
  inject: [
752
- import_nestjs_durable_core5.DURABLE_OPTIONS_CANONICAL
865
+ import_nestjs_durable_core6.DURABLE_OPTIONS_CANONICAL
753
866
  ]
754
867
  },
755
868
  {
@@ -819,12 +932,12 @@ function unavailableRunGateway() {
819
932
  __name(unavailableRunGateway, "unavailableRunGateway");
820
933
 
821
934
  // src/durable.module.ts
822
- var import_nestjs_durable_core16 = require("@dudousxd/nestjs-durable-core");
935
+ var import_nestjs_durable_core17 = require("@dudousxd/nestjs-durable-core");
823
936
  var import_common12 = require("@nestjs/common");
824
937
  var import_core5 = require("@nestjs/core");
825
938
 
826
939
  // src/durable-step.registrar.ts
827
- var import_nestjs_durable_core6 = require("@dudousxd/nestjs-durable-core");
940
+ var import_nestjs_durable_core7 = require("@dudousxd/nestjs-durable-core");
828
941
  var import_common3 = require("@nestjs/common");
829
942
  var import_core2 = require("@nestjs/core");
830
943
 
@@ -892,8 +1005,8 @@ var DurableStepRegistrar = class {
892
1005
  };
893
1006
  DurableStepRegistrar = _ts_decorate3([
894
1007
  (0, import_common3.Injectable)(),
895
- _ts_param2(2, (0, import_common3.Inject)(import_nestjs_durable_core6.TRANSPORT_CANONICAL)),
896
- _ts_param2(3, (0, import_common3.Inject)(import_nestjs_durable_core6.DURABLE_OPTIONS_CANONICAL)),
1008
+ _ts_param2(2, (0, import_common3.Inject)(import_nestjs_durable_core7.TRANSPORT_CANONICAL)),
1009
+ _ts_param2(3, (0, import_common3.Inject)(import_nestjs_durable_core7.DURABLE_OPTIONS_CANONICAL)),
897
1010
  _ts_metadata3("design:type", Function),
898
1011
  _ts_metadata3("design:paramtypes", [
899
1012
  typeof import_core2.DiscoveryService === "undefined" ? Object : import_core2.DiscoveryService,
@@ -904,7 +1017,7 @@ DurableStepRegistrar = _ts_decorate3([
904
1017
  ], DurableStepRegistrar);
905
1018
 
906
1019
  // src/entity.ts
907
- var import_nestjs_durable_core7 = require("@dudousxd/nestjs-durable-core");
1020
+ var import_nestjs_durable_core8 = require("@dudousxd/nestjs-durable-core");
908
1021
  var import_common4 = require("@nestjs/common");
909
1022
  var import_reflect_metadata2 = require("reflect-metadata");
910
1023
  function _ts_decorate4(decorators, target, key, desc) {
@@ -987,12 +1100,12 @@ EntityService = _ts_decorate4([
987
1100
  (0, import_common4.Injectable)(),
988
1101
  _ts_metadata4("design:type", Function),
989
1102
  _ts_metadata4("design:paramtypes", [
990
- typeof import_nestjs_durable_core7.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core7.WorkflowEngine
1103
+ typeof import_nestjs_durable_core8.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core8.WorkflowEngine
991
1104
  ])
992
1105
  ], EntityService);
993
1106
 
994
1107
  // src/in-app-worker.ts
995
- var import_nestjs_durable_core8 = require("@dudousxd/nestjs-durable-core");
1108
+ var import_nestjs_durable_core9 = require("@dudousxd/nestjs-durable-core");
996
1109
  var import_common5 = require("@nestjs/common");
997
1110
  var import_core3 = require("@nestjs/core");
998
1111
  function _ts_decorate5(decorators, target, key, desc) {
@@ -1097,7 +1210,7 @@ var InAppWorkerBootstrap = class {
1097
1210
  };
1098
1211
  InAppWorkerBootstrap = _ts_decorate5([
1099
1212
  (0, import_common5.Injectable)(),
1100
- _ts_param3(2, (0, import_common5.Inject)(import_nestjs_durable_core8.DURABLE_OPTIONS_CANONICAL)),
1213
+ _ts_param3(2, (0, import_common5.Inject)(import_nestjs_durable_core9.DURABLE_OPTIONS_CANONICAL)),
1101
1214
  _ts_param3(3, (0, import_common5.Inject)(IN_APP_WORKER_RUNTIME)),
1102
1215
  _ts_param3(4, (0, import_common5.Inject)(IN_APP_RUN_REDIS_WORKER)),
1103
1216
  _ts_param3(5, (0, import_common5.Inject)(IN_APP_WORKER_RUNNERS)),
@@ -1117,8 +1230,8 @@ function inAppWorkerProviders() {
1117
1230
  provide: IN_APP_WORKER_BINDING,
1118
1231
  useFactory: /* @__PURE__ */ __name((transport, options) => inAppWorkerBinding(transport, options), "useFactory"),
1119
1232
  inject: [
1120
- import_nestjs_durable_core8.TRANSPORT_CANONICAL,
1121
- import_nestjs_durable_core8.DURABLE_OPTIONS_CANONICAL
1233
+ import_nestjs_durable_core9.TRANSPORT_CANONICAL,
1234
+ import_nestjs_durable_core9.DURABLE_OPTIONS_CANONICAL
1122
1235
  ]
1123
1236
  },
1124
1237
  {
@@ -1138,7 +1251,7 @@ function inAppWorkerProviders() {
1138
1251
  workflowGroup: options.partition ?? ""
1139
1252
  }) : null, "useFactory"),
1140
1253
  inject: [
1141
- import_nestjs_durable_core8.DURABLE_OPTIONS_CANONICAL
1254
+ import_nestjs_durable_core9.DURABLE_OPTIONS_CANONICAL
1142
1255
  ]
1143
1256
  },
1144
1257
  {
@@ -1155,7 +1268,7 @@ function inAppWorkerProviders() {
1155
1268
  __name(inAppWorkerProviders, "inAppWorkerProviders");
1156
1269
 
1157
1270
  // src/proxy-run-gateway.ts
1158
- var import_nestjs_durable_core9 = require("@dudousxd/nestjs-durable-core");
1271
+ var import_nestjs_durable_core10 = require("@dudousxd/nestjs-durable-core");
1159
1272
  var import_common6 = require("@nestjs/common");
1160
1273
 
1161
1274
  // src/run-request-responder.ts
@@ -1470,12 +1583,12 @@ var ProxyRunGateway = class {
1470
1583
  });
1471
1584
  const over = options?.summarizeFansOver;
1472
1585
  if (over === void 0 || !detail || detail.fans !== void 0) return detail;
1473
- const { timeline, fans } = (0, import_nestjs_durable_core9.summarizeTimeline)(detail.timeline, over);
1474
- const ids = (0, import_nestjs_durable_core9.childIdsOf)(detail.timeline);
1586
+ const { timeline, fans } = (0, import_nestjs_durable_core10.summarizeTimeline)(detail.timeline, over);
1587
+ const ids = (0, import_nestjs_durable_core10.childIdsOf)(detail.timeline);
1475
1588
  return {
1476
1589
  ...detail,
1477
1590
  timeline,
1478
- children: ids.slice(0, import_nestjs_durable_core9.SUMMARY_CHILD_LIMIT),
1591
+ children: ids.slice(0, import_nestjs_durable_core10.SUMMARY_CHILD_LIMIT),
1479
1592
  fans,
1480
1593
  childCount: ids.length
1481
1594
  };
@@ -1500,7 +1613,7 @@ var ProxyRunGateway = class {
1500
1613
  kind: "getRunDetail",
1501
1614
  runId
1502
1615
  });
1503
- return detail ? (0, import_nestjs_durable_core9.pageFan)(detail.timeline, group, query) : null;
1616
+ return detail ? (0, import_nestjs_durable_core10.pageFan)(detail.timeline, group, query) : null;
1504
1617
  }
1505
1618
  knownUnsupported(kind) {
1506
1619
  const until = this.unsupportedUntil.get(kind);
@@ -1603,7 +1716,7 @@ ProxyRunGateway = _ts_decorate6([
1603
1716
  ], ProxyRunGateway);
1604
1717
 
1605
1718
  // src/retention-poller.ts
1606
- var import_nestjs_durable_core10 = require("@dudousxd/nestjs-durable-core");
1719
+ var import_nestjs_durable_core11 = require("@dudousxd/nestjs-durable-core");
1607
1720
  var import_common7 = require("@nestjs/common");
1608
1721
 
1609
1722
  // src/settle-within.ts
@@ -1669,10 +1782,10 @@ function validateRetention(retention) {
1669
1782
  if (policy.maxAge == null && policy.maxCount == null) {
1670
1783
  throw new Error("durable retention: each policy must set maxAge and/or maxCount");
1671
1784
  }
1672
- if (policy.maxAge != null) (0, import_nestjs_durable_core10.parseDuration)(policy.maxAge);
1785
+ if (policy.maxAge != null) (0, import_nestjs_durable_core11.parseDuration)(policy.maxAge);
1673
1786
  for (const status of policy.statuses) {
1674
- if (!import_nestjs_durable_core10.TERMINAL_RUN_STATUSES.includes(status)) {
1675
- throw new Error(`durable retention: status "${status}" is not terminal; only ${import_nestjs_durable_core10.TERMINAL_RUN_STATUSES.join(", ")} can be pruned`);
1787
+ if (!import_nestjs_durable_core11.TERMINAL_RUN_STATUSES.includes(status)) {
1788
+ throw new Error(`durable retention: status "${status}" is not terminal; only ${import_nestjs_durable_core11.TERMINAL_RUN_STATUSES.join(", ")} can be pruned`);
1676
1789
  }
1677
1790
  const key = `${scopeKey}|${status}`;
1678
1791
  if (seen.has(key)) {
@@ -1724,7 +1837,7 @@ var RetentionPoller = class {
1724
1837
  return;
1725
1838
  }
1726
1839
  await this.sweep();
1727
- const intervalMs = retention.sweepInterval != null ? (0, import_nestjs_durable_core10.parseDuration)(retention.sweepInterval) : DEFAULT_SWEEP_INTERVAL_MS;
1840
+ const intervalMs = retention.sweepInterval != null ? (0, import_nestjs_durable_core11.parseDuration)(retention.sweepInterval) : DEFAULT_SWEEP_INTERVAL_MS;
1728
1841
  if (intervalMs > 0) {
1729
1842
  this.timer = setInterval(() => void this.sweep(), intervalMs);
1730
1843
  this.timer.unref?.();
@@ -1786,8 +1899,8 @@ var RetentionPoller = class {
1786
1899
  };
1787
1900
  RetentionPoller = _ts_decorate7([
1788
1901
  (0, import_common7.Injectable)(),
1789
- _ts_param4(0, (0, import_common7.Inject)(import_nestjs_durable_core10.STATE_STORE_CANONICAL)),
1790
- _ts_param4(1, (0, import_common7.Inject)(import_nestjs_durable_core10.DURABLE_OPTIONS_CANONICAL)),
1902
+ _ts_param4(0, (0, import_common7.Inject)(import_nestjs_durable_core11.STATE_STORE_CANONICAL)),
1903
+ _ts_param4(1, (0, import_common7.Inject)(import_nestjs_durable_core11.DURABLE_OPTIONS_CANONICAL)),
1791
1904
  _ts_metadata7("design:type", Function),
1792
1905
  _ts_metadata7("design:paramtypes", [
1793
1906
  Object,
@@ -1796,7 +1909,7 @@ RetentionPoller = _ts_decorate7([
1796
1909
  ], RetentionPoller);
1797
1910
 
1798
1911
  // src/store-run-gateway.ts
1799
- var import_nestjs_durable_core11 = require("@dudousxd/nestjs-durable-core");
1912
+ var import_nestjs_durable_core12 = require("@dudousxd/nestjs-durable-core");
1800
1913
  var import_common8 = require("@nestjs/common");
1801
1914
  function _ts_decorate8(decorators, target, key, desc) {
1802
1915
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -1854,10 +1967,10 @@ var StoreRunGateway = class {
1854
1967
  children
1855
1968
  };
1856
1969
  }
1857
- if ((0, import_nestjs_durable_core11.aggregatesCheckpoints)(this.store)) {
1970
+ if ((0, import_nestjs_durable_core12.aggregatesCheckpoints)(this.store)) {
1858
1971
  const stats = await this.store.checkpointStats(runId);
1859
- const etag = (0, import_nestjs_durable_core11.runDetailEtag)(run, stats, over);
1860
- if ((0, import_nestjs_durable_core11.etagMatches)(options?.ifNoneMatch, etag)) {
1972
+ const etag = (0, import_nestjs_durable_core12.runDetailEtag)(run, stats, over);
1973
+ if ((0, import_nestjs_durable_core12.etagMatches)(options?.ifNoneMatch, etag)) {
1861
1974
  return {
1862
1975
  run,
1863
1976
  timeline: [],
@@ -1868,17 +1981,17 @@ var StoreRunGateway = class {
1868
1981
  }
1869
1982
  return {
1870
1983
  run,
1871
- ...await (0, import_nestjs_durable_core11.summarizeRunFromStore)(this.store, runId, over, stats),
1984
+ ...await (0, import_nestjs_durable_core12.summarizeRunFromStore)(this.store, runId, over, stats),
1872
1985
  etag
1873
1986
  };
1874
1987
  }
1875
1988
  const full = await this.store.listCheckpoints(runId);
1876
- const { timeline, fans } = (0, import_nestjs_durable_core11.summarizeTimeline)(full, over);
1877
- const ids = (0, import_nestjs_durable_core11.childIdsOf)(full);
1989
+ const { timeline, fans } = (0, import_nestjs_durable_core12.summarizeTimeline)(full, over);
1990
+ const ids = (0, import_nestjs_durable_core12.childIdsOf)(full);
1878
1991
  return {
1879
1992
  run,
1880
1993
  timeline,
1881
- children: ids.slice(0, import_nestjs_durable_core11.SUMMARY_CHILD_LIMIT),
1994
+ children: ids.slice(0, import_nestjs_durable_core12.SUMMARY_CHILD_LIMIT),
1882
1995
  fans,
1883
1996
  childCount: ids.length
1884
1997
  };
@@ -1888,12 +2001,12 @@ var StoreRunGateway = class {
1888
2001
  }
1889
2002
  async getFanMembers(runId, group, query) {
1890
2003
  if (!await this.store.getRun(runId)) return null;
1891
- if ((0, import_nestjs_durable_core11.aggregatesCheckpoints)(this.store)) {
2004
+ if ((0, import_nestjs_durable_core12.aggregatesCheckpoints)(this.store)) {
1892
2005
  const stats = await this.store.checkpointStats(runId, {
1893
2006
  group
1894
2007
  });
1895
- const etag = (0, import_nestjs_durable_core11.fanPageEtag)(group, stats, query);
1896
- if ((0, import_nestjs_durable_core11.etagMatches)(query.ifNoneMatch, etag)) {
2008
+ const etag = (0, import_nestjs_durable_core12.fanPageEtag)(group, stats, query);
2009
+ if ((0, import_nestjs_durable_core12.etagMatches)(query.ifNoneMatch, etag)) {
1897
2010
  return {
1898
2011
  items: [],
1899
2012
  total: 0,
@@ -1902,17 +2015,17 @@ var StoreRunGateway = class {
1902
2015
  };
1903
2016
  }
1904
2017
  return {
1905
- ...await (0, import_nestjs_durable_core11.pageFanFromStore)(this.store, runId, group, query, stats),
2018
+ ...await (0, import_nestjs_durable_core12.pageFanFromStore)(this.store, runId, group, query, stats),
1906
2019
  etag
1907
2020
  };
1908
2021
  }
1909
- return (0, import_nestjs_durable_core11.pageFan)(await this.store.listCheckpoints(runId), group, query);
2022
+ return (0, import_nestjs_durable_core12.pageFan)(await this.store.listCheckpoints(runId), group, query);
1910
2023
  }
1911
2024
  async listRuns(query) {
1912
2025
  const runs = await this.store.listRuns(query);
1913
- const waiterByRun = (0, import_nestjs_durable_core11.indexWaitersByRun)(await (0, import_nestjs_durable_core11.listSignalWaitersOfRuns)(this.store, runs.filter((run) => run.status === "suspended").map((run) => run.id)));
2026
+ const waiterByRun = (0, import_nestjs_durable_core12.indexWaitersByRun)(await (0, import_nestjs_durable_core12.listSignalWaitersOfRuns)(this.store, runs.filter((run) => run.status === "suspended").map((run) => run.id)));
1914
2027
  return runs.map((run) => {
1915
- const waiting = (0, import_nestjs_durable_core11.resolveRunWaiting)(run, waiterByRun);
2028
+ const waiting = (0, import_nestjs_durable_core12.resolveRunWaiting)(run, waiterByRun);
1916
2029
  return waiting ? {
1917
2030
  ...run,
1918
2031
  waiting
@@ -1928,7 +2041,7 @@ var StoreRunGateway = class {
1928
2041
  async runFacets(query) {
1929
2042
  if (this.store.runFacets) return this.store.runFacets(query);
1930
2043
  const runs = await this.store.listRuns(query);
1931
- return (0, import_nestjs_durable_core11.mergeRunFacetRows)(runs.map((r) => ({
2044
+ return (0, import_nestjs_durable_core12.mergeRunFacetRows)(runs.map((r) => ({
1932
2045
  status: r.status,
1933
2046
  origin: r.origin,
1934
2047
  count: 1
@@ -1963,13 +2076,13 @@ var StoreRunGateway = class {
1963
2076
  "suspended"
1964
2077
  ]
1965
2078
  }),
1966
- (0, import_nestjs_durable_core11.listSignalWaitersOfRuns)(this.store, runIds)
2079
+ (0, import_nestjs_durable_core12.listSignalWaitersOfRuns)(this.store, runIds)
1967
2080
  ]);
1968
- const waiterByRun = (0, import_nestjs_durable_core11.indexWaitersByRun)(waiters);
2081
+ const waiterByRun = (0, import_nestjs_durable_core12.indexWaitersByRun)(waiters);
1969
2082
  const result = {};
1970
2083
  for (const run of suspended) {
1971
2084
  if (!idSet.has(run.id)) continue;
1972
- const waiting = (0, import_nestjs_durable_core11.resolveRunWaiting)(run, waiterByRun);
2085
+ const waiting = (0, import_nestjs_durable_core12.resolveRunWaiting)(run, waiterByRun);
1973
2086
  if (waiting) result[run.id] = waiting;
1974
2087
  }
1975
2088
  return result;
@@ -2003,11 +2116,11 @@ var StoreRunGateway = class {
2003
2116
  };
2004
2117
  StoreRunGateway = _ts_decorate8([
2005
2118
  (0, import_common8.Injectable)(),
2006
- _ts_param5(0, (0, import_common8.Inject)(import_nestjs_durable_core11.STATE_STORE_CANONICAL)),
2119
+ _ts_param5(0, (0, import_common8.Inject)(import_nestjs_durable_core12.STATE_STORE_CANONICAL)),
2007
2120
  _ts_metadata8("design:type", Function),
2008
2121
  _ts_metadata8("design:paramtypes", [
2009
2122
  typeof StateStore === "undefined" ? Object : StateStore,
2010
- typeof import_nestjs_durable_core11.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core11.WorkflowEngine
2123
+ typeof import_nestjs_durable_core12.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core12.WorkflowEngine
2011
2124
  ])
2012
2125
  ], StoreRunGateway);
2013
2126
 
@@ -2053,7 +2166,7 @@ var TenantEventRepublisher = class {
2053
2166
  };
2054
2167
 
2055
2168
  // src/timer-poller.ts
2056
- var import_nestjs_durable_core12 = require("@dudousxd/nestjs-durable-core");
2169
+ var import_nestjs_durable_core13 = require("@dudousxd/nestjs-durable-core");
2057
2170
  var import_common9 = require("@nestjs/common");
2058
2171
  function _ts_decorate9(decorators, target, key, desc) {
2059
2172
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -2163,9 +2276,10 @@ var TimerPoller = class {
2163
2276
  await this.sweep("recoverIncomplete", () => this.engine.recoverIncomplete());
2164
2277
  await this.sweep("resumeDueTimers", () => this.engine.resumeDueTimers());
2165
2278
  await this.sweep("sweepTimeouts", () => this.engine.sweepTimeouts());
2279
+ await this.sweep("sweepStalled", async () => this.engine.sweepStalled?.());
2166
2280
  const schedules = this.options.schedules;
2167
2281
  if (schedules && schedules.length > 0) {
2168
- await this.sweep("schedules", () => (0, import_nestjs_durable_core12.runSchedules)(this.engine, schedules, Date.now()));
2282
+ await this.sweep("schedules", () => (0, import_nestjs_durable_core13.runSchedules)(this.engine, schedules, Date.now()));
2169
2283
  }
2170
2284
  if (this.options.persistedSchedules) {
2171
2285
  await this.sweep("persistedSchedules", () => this.engine.schedules.tick());
@@ -2183,49 +2297,24 @@ var TimerPoller = class {
2183
2297
  };
2184
2298
  TimerPoller = _ts_decorate9([
2185
2299
  (0, import_common9.Injectable)(),
2186
- _ts_param6(1, (0, import_common9.Inject)(import_nestjs_durable_core12.DURABLE_OPTIONS_CANONICAL)),
2300
+ _ts_param6(1, (0, import_common9.Inject)(import_nestjs_durable_core13.DURABLE_OPTIONS_CANONICAL)),
2187
2301
  _ts_metadata9("design:type", Function),
2188
2302
  _ts_metadata9("design:paramtypes", [
2189
- typeof import_nestjs_durable_core12.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core12.WorkflowEngine,
2303
+ typeof import_nestjs_durable_core13.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core13.WorkflowEngine,
2190
2304
  typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions
2191
2305
  ])
2192
2306
  ], TimerPoller);
2193
2307
 
2194
2308
  // src/tokens.ts
2195
- var import_nestjs_durable_core13 = require("@dudousxd/nestjs-durable-core");
2309
+ var import_nestjs_durable_core14 = require("@dudousxd/nestjs-durable-core");
2196
2310
  var CONTEXT_ACCESSOR = Symbol.for("@dudousxd/nestjs-context:accessor");
2197
- var RUN_GATEWAY = import_nestjs_durable_core13.RunGateway;
2311
+ var RUN_GATEWAY = import_nestjs_durable_core14.RunGateway;
2198
2312
 
2199
2313
  // src/workflow.registrar.ts
2200
- var import_nestjs_durable_core14 = require("@dudousxd/nestjs-durable-core");
2314
+ var import_nestjs_durable_core15 = require("@dudousxd/nestjs-durable-core");
2201
2315
  var import_common10 = require("@nestjs/common");
2202
2316
  var import_core4 = require("@nestjs/core");
2203
2317
 
2204
- // src/input-validation.ts
2205
- function classValidatorInput(cls) {
2206
- return async (input) => {
2207
- let cv;
2208
- let ct;
2209
- try {
2210
- cv = await import("class-validator");
2211
- ct = await import("class-transformer");
2212
- } catch {
2213
- throw new Error('@Workflow({ inputSchema }) needs the optional peers "class-validator" and "class-transformer" \u2014 install them, or pass a `validateInput` function instead.');
2214
- }
2215
- const instance = ct.plainToInstance(cls, input);
2216
- const errors = await cv.validate(instance, {
2217
- whitelist: true
2218
- });
2219
- if (errors.length > 0) {
2220
- const message = errors.map((e) => Object.values(e.constraints ?? {
2221
- _: e.property
2222
- }).join(", ")).join("; ");
2223
- throw new Error(`invalid input for workflow: ${message}`);
2224
- }
2225
- };
2226
- }
2227
- __name(classValidatorInput, "classValidatorInput");
2228
-
2229
2318
  // src/step-interceptor.ts
2230
2319
  var import_reflect_metadata3 = require("reflect-metadata");
2231
2320
  var STEP_INTERCEPTOR_METADATA = Symbol("nestjs-durable:step-interceptor");
@@ -2328,14 +2417,15 @@ var WorkflowRegistrar = class {
2328
2417
  const unattributed = [];
2329
2418
  scanWorkflows(this.discovery, (meta, workflow, origin) => {
2330
2419
  if (origin === void 0) unattributed.push(meta.name);
2331
- const validateInput = meta.validateInput ?? (meta.inputSchema ? classValidatorInput(meta.inputSchema) : void 0);
2420
+ const io = workflowIo(meta);
2421
+ const body = io.wrap((ctx, input) => workflow.run(ctx, input));
2332
2422
  const eventBatch = meta.debounce ? {
2333
2423
  mode: "debounce",
2334
- windowMs: (0, import_nestjs_durable_core14.parseDuration)(meta.debounce)
2424
+ windowMs: (0, import_nestjs_durable_core15.parseDuration)(meta.debounce)
2335
2425
  } : meta.batch ? {
2336
2426
  mode: "batch",
2337
2427
  maxSize: meta.batch.maxSize,
2338
- windowMs: (0, import_nestjs_durable_core14.parseDuration)(meta.batch.within)
2428
+ windowMs: (0, import_nestjs_durable_core15.parseDuration)(meta.batch.within)
2339
2429
  } : void 0;
2340
2430
  const workflowCtor = workflow.constructor;
2341
2431
  const onError = onErrorHandlersOf(meta, workflow, this.metadataScanner);
@@ -2344,7 +2434,7 @@ var WorkflowRegistrar = class {
2344
2434
  origin
2345
2435
  });
2346
2436
  }
2347
- this.engine.register(meta.name, meta.version, (ctx, input) => workflow.run(ctx, input), {
2437
+ this.engine.register(meta.name, meta.version, body, {
2348
2438
  // Stamped onto every run this workflow starts (see `WorkflowRun.origin`). Derived from the
2349
2439
  // class's declaring file, so a lib gets attributed without opting in; `undefined` when it
2350
2440
  // could not be derived, which the engine records as unknown rather than defaulting.
@@ -2354,7 +2444,7 @@ var WorkflowRegistrar = class {
2354
2444
  concurrency: meta.concurrency,
2355
2445
  executionTimeout: meta.executionTimeout,
2356
2446
  requires: meta.requires,
2357
- validateInput,
2447
+ validateInput: io.validateAtStart,
2358
2448
  searchAttributesSchema: meta.searchAttributes,
2359
2449
  onEvent: getOnEvents(meta, workflowCtor),
2360
2450
  eventBatch,
@@ -2369,11 +2459,11 @@ var WorkflowRegistrar = class {
2369
2459
  // so a turn dispatched under the wrong token would never be consumed. Absent → the inline fast
2370
2460
  // path (unchanged).
2371
2461
  ...this.inAppWorker ? {
2372
- group: (0, import_nestjs_durable_core14.tenantGroup)((0, import_nestjs_durable_core14.sanitizeQueueToken)(meta.name), this.inAppWorker.partition),
2373
- executor: new import_nestjs_durable_core14.RemoteWorkflowExecutor(this.inAppWorker.transport, meta.name, this.inAppWorker.partition)
2462
+ group: (0, import_nestjs_durable_core15.tenantGroup)((0, import_nestjs_durable_core15.sanitizeQueueToken)(meta.name), this.inAppWorker.partition),
2463
+ executor: new import_nestjs_durable_core15.RemoteWorkflowExecutor(this.inAppWorker.transport, meta.name, this.inAppWorker.partition)
2374
2464
  } : {}
2375
2465
  });
2376
- (0, import_nestjs_durable_core14.bindWorkflowClass)(workflowCtor, {
2466
+ (0, import_nestjs_durable_core15.bindWorkflowClass)(workflowCtor, {
2377
2467
  start: /* @__PURE__ */ __name((name, input, runId, opts) => this.engine.start(name, input, runId, opts), "start"),
2378
2468
  waitForRun: /* @__PURE__ */ __name((runId, opts) => this.engine.waitForRun(runId, opts), "waitForRun")
2379
2469
  });
@@ -2388,7 +2478,7 @@ var WorkflowRegistrar = class {
2388
2478
  });
2389
2479
  deadLetterByWorkflow.set(meta.name, dlqName);
2390
2480
  } else if (meta.deadLetterWorkflow) {
2391
- deadLetterByWorkflow.set(meta.name, (0, import_nestjs_durable_core14.workflowName)(meta.deadLetterWorkflow));
2481
+ deadLetterByWorkflow.set(meta.name, (0, import_nestjs_durable_core15.workflowName)(meta.deadLetterWorkflow));
2392
2482
  }
2393
2483
  });
2394
2484
  this.reportUnattributed(unattributed);
@@ -2436,7 +2526,7 @@ var WorkflowRegistrar = class {
2436
2526
  * a `dlq:<runId>` id, so re-recovery never double-dispatches.
2437
2527
  */
2438
2528
  installDeadLetterRouting(byWorkflow) {
2439
- const fallback = this.options.deadLetterWorkflow ? (0, import_nestjs_durable_core14.workflowName)(this.options.deadLetterWorkflow) : void 0;
2529
+ const fallback = this.options.deadLetterWorkflow ? (0, import_nestjs_durable_core15.workflowName)(this.options.deadLetterWorkflow) : void 0;
2440
2530
  if (byWorkflow.size === 0 && !fallback) return;
2441
2531
  this.engine.onDead((run) => {
2442
2532
  const target = byWorkflow.get(run.workflow) ?? fallback;
@@ -2461,14 +2551,14 @@ var WorkflowRegistrar = class {
2461
2551
  };
2462
2552
  WorkflowRegistrar = _ts_decorate10([
2463
2553
  (0, import_common10.Injectable)(),
2464
- _ts_param7(3, (0, import_common10.Inject)(import_nestjs_durable_core14.STATE_STORE_CANONICAL)),
2465
- _ts_param7(4, (0, import_common10.Inject)(import_nestjs_durable_core14.DURABLE_OPTIONS_CANONICAL)),
2554
+ _ts_param7(3, (0, import_common10.Inject)(import_nestjs_durable_core15.STATE_STORE_CANONICAL)),
2555
+ _ts_param7(4, (0, import_common10.Inject)(import_nestjs_durable_core15.DURABLE_OPTIONS_CANONICAL)),
2466
2556
  _ts_param7(5, (0, import_common10.Inject)(IN_APP_WORKER_BINDING)),
2467
2557
  _ts_metadata10("design:type", Function),
2468
2558
  _ts_metadata10("design:paramtypes", [
2469
2559
  typeof import_core4.DiscoveryService === "undefined" ? Object : import_core4.DiscoveryService,
2470
2560
  typeof import_core4.MetadataScanner === "undefined" ? Object : import_core4.MetadataScanner,
2471
- typeof import_nestjs_durable_core14.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core14.WorkflowEngine,
2561
+ typeof import_nestjs_durable_core15.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core15.WorkflowEngine,
2472
2562
  Object,
2473
2563
  typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions,
2474
2564
  Object
@@ -2477,7 +2567,7 @@ WorkflowRegistrar = _ts_decorate10([
2477
2567
 
2478
2568
  // src/workflow.service.ts
2479
2569
  var import_node_crypto = require("crypto");
2480
- var import_nestjs_durable_core15 = require("@dudousxd/nestjs-durable-core");
2570
+ var import_nestjs_durable_core16 = require("@dudousxd/nestjs-durable-core");
2481
2571
  var import_common11 = require("@nestjs/common");
2482
2572
  function _ts_decorate11(decorators, target, key, desc) {
2483
2573
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -2548,7 +2638,7 @@ WorkflowService = _ts_decorate11([
2548
2638
  (0, import_common11.Injectable)(),
2549
2639
  _ts_metadata11("design:type", Function),
2550
2640
  _ts_metadata11("design:paramtypes", [
2551
- typeof import_nestjs_durable_core15.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core15.WorkflowEngine
2641
+ typeof import_nestjs_durable_core16.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core16.WorkflowEngine
2552
2642
  ])
2553
2643
  ], WorkflowService);
2554
2644
 
@@ -2760,14 +2850,14 @@ var RunGatewayBootstrap = class RunGatewayBootstrap2 {
2760
2850
  };
2761
2851
  RunGatewayBootstrap = _ts_decorate12([
2762
2852
  (0, import_common12.Injectable)(),
2763
- _ts_param8(1, (0, import_common12.Inject)(import_nestjs_durable_core16.TRANSPORT_CANONICAL)),
2764
- _ts_param8(3, (0, import_common12.Inject)(import_nestjs_durable_core16.STATE_STORE_CANONICAL)),
2765
- _ts_param8(4, (0, import_common12.Inject)(import_nestjs_durable_core16.DURABLE_OPTIONS_CANONICAL)),
2853
+ _ts_param8(1, (0, import_common12.Inject)(import_nestjs_durable_core17.TRANSPORT_CANONICAL)),
2854
+ _ts_param8(3, (0, import_common12.Inject)(import_nestjs_durable_core17.STATE_STORE_CANONICAL)),
2855
+ _ts_param8(4, (0, import_common12.Inject)(import_nestjs_durable_core17.DURABLE_OPTIONS_CANONICAL)),
2766
2856
  _ts_metadata12("design:type", Function),
2767
2857
  _ts_metadata12("design:paramtypes", [
2768
- typeof import_nestjs_durable_core16.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core16.WorkflowEngine,
2858
+ typeof import_nestjs_durable_core17.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core17.WorkflowEngine,
2769
2859
  Object,
2770
- typeof import_nestjs_durable_core16.RunGateway === "undefined" ? Object : import_nestjs_durable_core16.RunGateway,
2860
+ typeof import_nestjs_durable_core17.RunGateway === "undefined" ? Object : import_nestjs_durable_core17.RunGateway,
2771
2861
  Object,
2772
2862
  typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions
2773
2863
  ])
@@ -2779,13 +2869,13 @@ var DurableModule = class _DurableModule {
2779
2869
  static forRoot(options) {
2780
2870
  _DurableModule.assertValid(options);
2781
2871
  return _DurableModule.build({
2782
- provide: import_nestjs_durable_core16.DURABLE_OPTIONS_CANONICAL,
2872
+ provide: import_nestjs_durable_core17.DURABLE_OPTIONS_CANONICAL,
2783
2873
  useValue: resolveTopology(options)
2784
2874
  });
2785
2875
  }
2786
2876
  static forRootAsync(options) {
2787
2877
  return _DurableModule.build({
2788
- provide: import_nestjs_durable_core16.DURABLE_OPTIONS_CANONICAL,
2878
+ provide: import_nestjs_durable_core17.DURABLE_OPTIONS_CANONICAL,
2789
2879
  useFactory: /* @__PURE__ */ __name(async (...args) => {
2790
2880
  const resolved = await options.useFactory(...args);
2791
2881
  _DurableModule.assertValid(resolved);
@@ -2818,41 +2908,41 @@ var DurableModule = class _DurableModule {
2818
2908
  providers: [
2819
2909
  optionsProvider,
2820
2910
  {
2821
- provide: import_nestjs_durable_core16.STATE_STORE_CANONICAL,
2911
+ provide: import_nestjs_durable_core17.STATE_STORE_CANONICAL,
2822
2912
  useFactory: /* @__PURE__ */ __name((options) => options.store !== void 0 ? scopedStore(options.store, options) : null, "useFactory"),
2823
2913
  inject: [
2824
- import_nestjs_durable_core16.DURABLE_OPTIONS_CANONICAL
2914
+ import_nestjs_durable_core17.DURABLE_OPTIONS_CANONICAL
2825
2915
  ]
2826
2916
  },
2827
2917
  {
2828
- provide: import_nestjs_durable_core16.TRANSPORT_CANONICAL,
2918
+ provide: import_nestjs_durable_core17.TRANSPORT_CANONICAL,
2829
2919
  // With a POOL (`transports`) and no singular `transport`, the canonical transport is the
2830
2920
  // pool's PRIMARY — the same one the engine dispatches on first. Leaving it null starved
2831
2921
  // the step registrar / in-app worker of a transport, so a pool-configured operator
2832
2922
  // registered NO step handlers and its own steps parked in `wait` with no consumer.
2833
2923
  useFactory: /* @__PURE__ */ __name((options) => options.transport ?? options.transports?.[0]?.transport ?? null, "useFactory"),
2834
2924
  inject: [
2835
- import_nestjs_durable_core16.DURABLE_OPTIONS_CANONICAL
2925
+ import_nestjs_durable_core17.DURABLE_OPTIONS_CANONICAL
2836
2926
  ]
2837
2927
  },
2838
2928
  // Legacy back-compat aliases (deprecated tokens still resolve to the same instances):
2839
2929
  {
2840
- provide: import_nestjs_durable_core16.STATE_STORE,
2841
- useExisting: import_nestjs_durable_core16.STATE_STORE_CANONICAL
2930
+ provide: import_nestjs_durable_core17.STATE_STORE,
2931
+ useExisting: import_nestjs_durable_core17.STATE_STORE_CANONICAL
2842
2932
  },
2843
2933
  {
2844
- provide: import_nestjs_durable_core16.TRANSPORT,
2845
- useExisting: import_nestjs_durable_core16.TRANSPORT_CANONICAL
2934
+ provide: import_nestjs_durable_core17.TRANSPORT,
2935
+ useExisting: import_nestjs_durable_core17.TRANSPORT_CANONICAL
2846
2936
  },
2847
2937
  {
2848
- provide: import_nestjs_durable_core16.DURABLE_OPTIONS,
2849
- useExisting: import_nestjs_durable_core16.DURABLE_OPTIONS_CANONICAL
2938
+ provide: import_nestjs_durable_core17.DURABLE_OPTIONS,
2939
+ useExisting: import_nestjs_durable_core17.DURABLE_OPTIONS_CANONICAL
2850
2940
  },
2851
2941
  {
2852
2942
  // Shared token, bound EXACTLY once: a real engine for the operator role, or a store-less
2853
2943
  // `DurableStartClient` facade for a thin worker (no `store`) — either way, `WorkflowService`
2854
2944
  // and app code call `engine.start(...)` unchanged.
2855
- provide: import_nestjs_durable_core16.WorkflowEngine,
2945
+ provide: import_nestjs_durable_core17.WorkflowEngine,
2856
2946
  useFactory: /* @__PURE__ */ __name(async (options, store, transport, moduleRef) => {
2857
2947
  if (options.store === void 0) {
2858
2948
  return new DurableStartClient(options);
@@ -2873,7 +2963,7 @@ var DurableModule = class _DurableModule {
2873
2963
  if (t) deferTransportConsumers(t);
2874
2964
  }
2875
2965
  }
2876
- const engine = new import_nestjs_durable_core16.WorkflowEngine({
2966
+ const engine = new import_nestjs_durable_core17.WorkflowEngine({
2877
2967
  store,
2878
2968
  transport: transport ?? void 0,
2879
2969
  transports: options.transports,
@@ -2885,6 +2975,7 @@ var DurableModule = class _DurableModule {
2885
2975
  remoteRedispatchMs: options.remoteRedispatchMs,
2886
2976
  remoteRedispatchMax: options.remoteRedispatchMax,
2887
2977
  reconcileMs: options.reconcileMs,
2978
+ stalledAfterMs: options.stalledAfterMs,
2888
2979
  timerBatchSize: options.timerBatchSize,
2889
2980
  eventBufferTtlMs: options.eventBufferTtlMs,
2890
2981
  blockedPollMs: options.blockedPollMs,
@@ -2908,12 +2999,13 @@ var DurableModule = class _DurableModule {
2908
2999
  } : void 0
2909
3000
  });
2910
3001
  for (const queue of options.queues ?? []) engine.registerQueue(queue);
3002
+ if (options.onStalled) engine.onStalled(options.onStalled);
2911
3003
  return engine;
2912
3004
  }, "useFactory"),
2913
3005
  inject: [
2914
- import_nestjs_durable_core16.DURABLE_OPTIONS_CANONICAL,
2915
- import_nestjs_durable_core16.STATE_STORE_CANONICAL,
2916
- import_nestjs_durable_core16.TRANSPORT_CANONICAL,
3006
+ import_nestjs_durable_core17.DURABLE_OPTIONS_CANONICAL,
3007
+ import_nestjs_durable_core17.STATE_STORE_CANONICAL,
3008
+ import_nestjs_durable_core17.TRANSPORT_CANONICAL,
2917
3009
  import_core5.ModuleRef
2918
3010
  ]
2919
3011
  },
@@ -2927,7 +3019,7 @@ var DurableModule = class _DurableModule {
2927
3019
  // or (for a thin worker, no `store`) a `ProxyRunGateway` over `transport` when given, else a
2928
3020
  // gateway whose every method rejects with a clear tenant error.
2929
3021
  {
2930
- provide: import_nestjs_durable_core16.RunGateway,
3022
+ provide: import_nestjs_durable_core17.RunGateway,
2931
3023
  useFactory: /* @__PURE__ */ __name((options, store, engine) => {
2932
3024
  if (options.store !== void 0) {
2933
3025
  if (!store) {
@@ -2938,9 +3030,9 @@ var DurableModule = class _DurableModule {
2938
3030
  return options.transport ? new ProxyRunGateway(options.transport, options.partition ?? "default", options.runGatewayTimeoutMs) : unavailableRunGateway();
2939
3031
  }, "useFactory"),
2940
3032
  inject: [
2941
- import_nestjs_durable_core16.DURABLE_OPTIONS_CANONICAL,
2942
- import_nestjs_durable_core16.STATE_STORE_CANONICAL,
2943
- import_nestjs_durable_core16.WorkflowEngine
3033
+ import_nestjs_durable_core17.DURABLE_OPTIONS_CANONICAL,
3034
+ import_nestjs_durable_core17.STATE_STORE_CANONICAL,
3035
+ import_nestjs_durable_core17.WorkflowEngine
2944
3036
  ]
2945
3037
  },
2946
3038
  RunGatewayBootstrap,
@@ -2954,13 +3046,13 @@ var DurableModule = class _DurableModule {
2954
3046
  exports: [
2955
3047
  WorkflowService,
2956
3048
  EntityService,
2957
- import_nestjs_durable_core16.WorkflowEngine,
2958
- import_nestjs_durable_core16.STATE_STORE,
2959
- import_nestjs_durable_core16.STATE_STORE_CANONICAL,
2960
- import_nestjs_durable_core16.TRANSPORT,
2961
- import_nestjs_durable_core16.TRANSPORT_CANONICAL,
2962
- import_nestjs_durable_core16.DURABLE_OPTIONS_CANONICAL,
2963
- import_nestjs_durable_core16.RunGateway
3049
+ import_nestjs_durable_core17.WorkflowEngine,
3050
+ import_nestjs_durable_core17.STATE_STORE,
3051
+ import_nestjs_durable_core17.STATE_STORE_CANONICAL,
3052
+ import_nestjs_durable_core17.TRANSPORT,
3053
+ import_nestjs_durable_core17.TRANSPORT_CANONICAL,
3054
+ import_nestjs_durable_core17.DURABLE_OPTIONS_CANONICAL,
3055
+ import_nestjs_durable_core17.RunGateway
2964
3056
  ]
2965
3057
  };
2966
3058
  }
@@ -2970,7 +3062,7 @@ DurableModule = _ts_decorate12([
2970
3062
  ], DurableModule);
2971
3063
 
2972
3064
  // src/index.ts
2973
- var import_nestjs_durable_core17 = require("@dudousxd/nestjs-durable-core");
3065
+ var import_nestjs_durable_core18 = require("@dudousxd/nestjs-durable-core");
2974
3066
  // Annotate the CommonJS export names for ESM import in node:
2975
3067
  0 && (module.exports = {
2976
3068
  CONTEXT_ACCESSOR,