@dudousxd/nestjs-durable 0.26.0 → 0.28.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
@@ -24,29 +24,33 @@ __export(index_exports, {
24
24
  CONTEXT_ACCESSOR: () => CONTEXT_ACCESSOR,
25
25
  DEAD_LETTER_METADATA: () => DEAD_LETTER_METADATA,
26
26
  DURABLE_STEP_METADATA: () => DURABLE_STEP_METADATA,
27
- DURABLE_WORKER_OPTIONS: () => DURABLE_WORKER_OPTIONS,
28
27
  DURABLE_WORKER_RUNNERS: () => DURABLE_WORKER_RUNNERS,
29
28
  DeadLetter: () => DeadLetter,
30
29
  DurableModule: () => DurableModule,
30
+ DurableStartClient: () => DurableStartClient,
31
31
  DurableStep: () => DurableStep,
32
- DurableWorkerModule: () => DurableWorkerModule,
33
32
  ENTITY_METADATA: () => ENTITY_METADATA,
34
33
  ENTITY_ON_METADATA: () => ENTITY_ON_METADATA,
35
34
  Entity: () => Entity,
36
35
  EntityService: () => EntityService,
37
36
  IN_APP_RUN_REDIS_WORKER: () => IN_APP_RUN_REDIS_WORKER,
38
37
  IN_APP_WORKER_BINDING: () => IN_APP_WORKER_BINDING,
39
- IN_APP_WORKER_OPTIONS: () => IN_APP_WORKER_OPTIONS,
40
38
  IN_APP_WORKER_RUNNERS: () => IN_APP_WORKER_RUNNERS,
41
39
  IN_APP_WORKER_RUNTIME: () => IN_APP_WORKER_RUNTIME,
42
40
  InAppWorkerBootstrap: () => InAppWorkerBootstrap,
43
41
  ON_EVENT_METADATA: () => ON_EVENT_METADATA,
44
42
  On: () => On,
43
+ OnDurableEvent: () => OnDurableEvent,
45
44
  OnEvent: () => OnEvent,
45
+ ProxyRunGateway: () => ProxyRunGateway,
46
+ RUN_GATEWAY: () => RUN_GATEWAY,
46
47
  RUN_REDIS_WORKER: () => RUN_REDIS_WORKER,
48
+ RunRequestResponder: () => RunRequestResponder,
47
49
  STEP_INTERCEPTOR_METADATA: () => STEP_INTERCEPTOR_METADATA,
48
50
  Step: () => Step,
49
51
  StepInterceptor: () => StepInterceptor,
52
+ StoreRunGateway: () => StoreRunGateway,
53
+ TenantEventRepublisher: () => TenantEventRepublisher,
50
54
  ThinStepRegistrar: () => ThinStepRegistrar,
51
55
  ThinWorkerBootstrap: () => ThinWorkerBootstrap,
52
56
  ThinWorkflowRegistrar: () => ThinWorkflowRegistrar,
@@ -60,7 +64,11 @@ __export(index_exports, {
60
64
  getWorkflowMeta: () => getWorkflowMeta,
61
65
  inAppWorkerProviders: () => inAppWorkerProviders,
62
66
  isDeadLetterHandler: () => isDeadLetterHandler,
63
- isStepInterceptor: () => isStepInterceptor
67
+ isDrivingOperator: () => isDrivingOperator,
68
+ isOperatorRole: () => isOperatorRole,
69
+ isStepInterceptor: () => isStepInterceptor,
70
+ thinWorkerProviders: () => thinWorkerProviders,
71
+ unavailableRunGateway: () => unavailableRunGateway
64
72
  });
65
73
  module.exports = __toCommonJS(index_exports);
66
74
 
@@ -96,12 +104,36 @@ function getWorkflowMeta(target) {
96
104
  }
97
105
  __name(getWorkflowMeta, "getWorkflowMeta");
98
106
  var DURABLE_STEP_METADATA = Symbol("nestjs-durable:step-handler");
99
- function Step(name) {
100
- return (_target, _propertyKey, descriptor) => {
107
+ function stepConfigFrom(options) {
108
+ const config = {
109
+ retries: options.retries,
110
+ backoff: options.backoff,
111
+ backoffMs: options.backoffMs,
112
+ backoffMaxMs: options.backoffMaxMs,
113
+ jitter: options.jitter,
114
+ timeoutMs: options.timeoutMs
115
+ };
116
+ const hasAnyField = Object.values(config).some((value) => value !== void 0);
117
+ return hasAnyField ? config : void 0;
118
+ }
119
+ __name(stepConfigFrom, "stepConfigFrom");
120
+ function Step(nameOrOptions) {
121
+ return (target, propertyKey, descriptor) => {
122
+ const options = typeof nameOrOptions === "string" ? {
123
+ name: nameOrOptions
124
+ } : nameOrOptions ?? {};
125
+ const derivedName = options.name ?? `${target.constructor.name}.${String(propertyKey)}`;
101
126
  const meta = {
102
- name
127
+ name: derivedName,
128
+ input: options.input,
129
+ output: options.output
103
130
  };
104
131
  Reflect.defineMetadata(DURABLE_STEP_METADATA, meta, descriptor.value);
132
+ descriptor.value[import_nestjs_durable_core.DURABLE_STEP_NAME] = derivedName;
133
+ const config = stepConfigFrom(options);
134
+ if (config !== void 0) {
135
+ descriptor.value[import_nestjs_durable_core.DURABLE_STEP_CONFIG] = config;
136
+ }
105
137
  return descriptor;
106
138
  };
107
139
  }
@@ -124,7 +156,7 @@ function isDeadLetterHandler(method) {
124
156
  }
125
157
  __name(isDeadLetterHandler, "isDeadLetterHandler");
126
158
  var ON_EVENT_METADATA = Symbol("nestjs-durable:on-event");
127
- function OnEvent(...events) {
159
+ function OnDurableEvent(...events) {
128
160
  return (target) => {
129
161
  const existing = Reflect.getMetadata(ON_EVENT_METADATA, target) ?? [];
130
162
  Reflect.defineMetadata(ON_EVENT_METADATA, [
@@ -133,7 +165,8 @@ function OnEvent(...events) {
133
165
  ], target);
134
166
  };
135
167
  }
136
- __name(OnEvent, "OnEvent");
168
+ __name(OnDurableEvent, "OnDurableEvent");
169
+ var OnEvent = OnDurableEvent;
137
170
  function getOnEvents(meta, target) {
138
171
  const fromDecorator = Reflect.getMetadata(ON_EVENT_METADATA, target) ?? [];
139
172
  return [
@@ -145,9 +178,105 @@ function getOnEvents(meta, target) {
145
178
  }
146
179
  __name(getOnEvents, "getOnEvents");
147
180
 
148
- // src/durable-worker.module.ts
181
+ // src/durable-start-client.ts
149
182
  var import_durable_worker = require("@dudousxd/durable-worker");
183
+ var import_nestjs_durable_core2 = require("@dudousxd/nestjs-durable-core");
150
184
  var import_common = require("@nestjs/common");
185
+ function _ts_decorate(decorators, target, key, desc) {
186
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
187
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
188
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
189
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
190
+ }
191
+ __name(_ts_decorate, "_ts_decorate");
192
+ function _ts_metadata(k, v) {
193
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
194
+ }
195
+ __name(_ts_metadata, "_ts_metadata");
196
+ var DurableStartClient = class {
197
+ static {
198
+ __name(this, "DurableStartClient");
199
+ }
200
+ options;
201
+ deps;
202
+ tenant;
203
+ constructor(options, deps) {
204
+ this.options = options;
205
+ this.deps = deps;
206
+ this.tenant = options.partition ?? "default";
207
+ }
208
+ async start(workflow, input, runId = globalThis.crypto.randomUUID(), opts) {
209
+ const name = (0, import_nestjs_durable_core2.workflowName)(workflow);
210
+ await (0, import_durable_worker.startRun)(this.options.connection, {
211
+ tenant: this.tenant,
212
+ workflow: name,
213
+ input,
214
+ runId,
215
+ // Option B: DO NOT pass `namespace` — the start-run queue stays the shared
216
+ // `durable-start-run` the operator consumes; tenant rides only as message data.
217
+ ...this.options.prefix !== void 0 ? {
218
+ prefix: this.options.prefix
219
+ } : {},
220
+ ...opts?.tags !== void 0 ? {
221
+ tags: opts.tags
222
+ } : {},
223
+ ...opts?.searchAttributes !== void 0 ? {
224
+ searchAttributes: opts.searchAttributes
225
+ } : {},
226
+ ...this.deps !== void 0 ? {
227
+ deps: this.deps
228
+ } : {}
229
+ });
230
+ return {
231
+ runId,
232
+ status: "pending"
233
+ };
234
+ }
235
+ cancel(_runId) {
236
+ return tenantUnsupported("cancel");
237
+ }
238
+ deleteRun(_runId) {
239
+ return tenantUnsupported("deleteRun");
240
+ }
241
+ // — everything below rejects: a tenant worker holds no store/driver, only the start channel. —
242
+ // The remaining WorkflowEngine surface WorkflowService delegates to (resume/waitForRun/signal/
243
+ // signalWithStart/publishEvent) all need the store or driver a tenant does not have. A tenant only
244
+ // ever calls `start`; these exist so a mistaken call fails with a CLEAR, named tenant error instead
245
+ // of a cryptic `this.engine.X is not a function` — the facade is honest about what it cannot do.
246
+ // Params mirror the WorkflowEngine surface being faced; every method rejects without reading them.
247
+ resume(_runId) {
248
+ return tenantUnsupported("resume");
249
+ }
250
+ waitForRun(_runId, _opts) {
251
+ return tenantUnsupported("waitForRun");
252
+ }
253
+ signal(_token, _payload) {
254
+ return tenantUnsupported("signal");
255
+ }
256
+ signalWithStart(_workflow, _input, _runId, _signal, _opts) {
257
+ return tenantUnsupported("signalWithStart");
258
+ }
259
+ publishEvent(_name, _payload, _opts) {
260
+ return tenantUnsupported("publishEvent");
261
+ }
262
+ };
263
+ DurableStartClient = _ts_decorate([
264
+ (0, import_common.Injectable)(),
265
+ _ts_metadata("design:type", Function),
266
+ _ts_metadata("design:paramtypes", [
267
+ typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions,
268
+ typeof StartRunDeps === "undefined" ? Object : StartRunDeps
269
+ ])
270
+ ], DurableStartClient);
271
+ function tenantUnsupported(method) {
272
+ return Promise.reject(new Error(`${method}() is not available on a tenant worker (no store). Use the control plane for it.`));
273
+ }
274
+ __name(tenantUnsupported, "tenantUnsupported");
275
+
276
+ // src/durable-worker.module.ts
277
+ var import_durable_worker2 = require("@dudousxd/durable-worker");
278
+ var import_nestjs_durable_core3 = require("@dudousxd/nestjs-durable-core");
279
+ var import_common2 = require("@nestjs/common");
151
280
  var import_core = require("@nestjs/core");
152
281
 
153
282
  // src/discovery-helpers.ts
@@ -175,7 +304,12 @@ function scanSteps(discovery, scanner, register) {
175
304
  if (typeof method !== "function") continue;
176
305
  const meta = getDurableStepMeta(method);
177
306
  if (!meta) continue;
178
- const handler = /* @__PURE__ */ __name((input, log) => method.call(instance, input, log), "handler");
307
+ const boundMethod = method;
308
+ const handler = /* @__PURE__ */ __name(async (input, log) => {
309
+ const validInput = meta.input ? meta.input.parse(input) : input;
310
+ const output = await boundMethod.call(instance, validInput, log);
311
+ return meta.output ? meta.output.parse(output) : output;
312
+ }, "handler");
179
313
  register(meta, handler);
180
314
  }
181
315
  }
@@ -183,46 +317,54 @@ function scanSteps(discovery, scanner, register) {
183
317
  __name(scanSteps, "scanSteps");
184
318
 
185
319
  // src/durable-worker.module.ts
186
- function _ts_decorate(decorators, target, key, desc) {
320
+ function _ts_decorate2(decorators, target, key, desc) {
187
321
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
188
322
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
189
323
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
190
324
  return c > 3 && r && Object.defineProperty(target, key, r), r;
191
325
  }
192
- __name(_ts_decorate, "_ts_decorate");
193
- function _ts_metadata(k, v) {
326
+ __name(_ts_decorate2, "_ts_decorate");
327
+ function _ts_metadata2(k, v) {
194
328
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
195
329
  }
196
- __name(_ts_metadata, "_ts_metadata");
330
+ __name(_ts_metadata2, "_ts_metadata");
197
331
  function _ts_param(paramIndex, decorator) {
198
332
  return function(target, key) {
199
333
  decorator(target, key, paramIndex);
200
334
  };
201
335
  }
202
336
  __name(_ts_param, "_ts_param");
203
- var DURABLE_WORKER_OPTIONS = Symbol("nestjs-durable:worker-options");
204
337
  var RUN_REDIS_WORKER = Symbol("nestjs-durable:run-redis-worker");
205
338
  var DURABLE_WORKER_RUNNERS = Symbol("nestjs-durable:worker-runners");
339
+ function isPureThinWorker(options) {
340
+ return options.store === void 0 && options.connection !== void 0;
341
+ }
342
+ __name(isPureThinWorker, "isPureThinWorker");
206
343
  var ThinWorkflowRegistrar = class {
207
344
  static {
208
345
  __name(this, "ThinWorkflowRegistrar");
209
346
  }
210
347
  discovery;
211
348
  runtime;
212
- constructor(discovery, runtime) {
349
+ options;
350
+ constructor(discovery, runtime, options) {
213
351
  this.discovery = discovery;
214
352
  this.runtime = runtime;
353
+ this.options = options;
215
354
  }
216
355
  onModuleInit() {
356
+ if (!isPureThinWorker(this.options)) return;
217
357
  scanWorkflows(this.discovery, (meta, instance) => this.runtime.registerWorkflow(meta.name, (ctx, input) => instance.run(ctx, input)));
218
358
  }
219
359
  };
220
- ThinWorkflowRegistrar = _ts_decorate([
221
- (0, import_common.Injectable)(),
222
- _ts_metadata("design:type", Function),
223
- _ts_metadata("design:paramtypes", [
360
+ ThinWorkflowRegistrar = _ts_decorate2([
361
+ (0, import_common2.Injectable)(),
362
+ _ts_param(2, (0, import_common2.Inject)(import_nestjs_durable_core3.DURABLE_OPTIONS_CANONICAL)),
363
+ _ts_metadata2("design:type", Function),
364
+ _ts_metadata2("design:paramtypes", [
224
365
  typeof import_core.DiscoveryService === "undefined" ? Object : import_core.DiscoveryService,
225
- typeof import_durable_worker.DurableWorkerRuntime === "undefined" ? Object : import_durable_worker.DurableWorkerRuntime
366
+ typeof import_durable_worker2.DurableWorkerRuntime === "undefined" ? Object : import_durable_worker2.DurableWorkerRuntime,
367
+ typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions
226
368
  ])
227
369
  ], ThinWorkflowRegistrar);
228
370
  var ThinStepRegistrar = class {
@@ -232,22 +374,27 @@ var ThinStepRegistrar = class {
232
374
  discovery;
233
375
  metadataScanner;
234
376
  runtime;
235
- constructor(discovery, metadataScanner, runtime) {
377
+ options;
378
+ constructor(discovery, metadataScanner, runtime, options) {
236
379
  this.discovery = discovery;
237
380
  this.metadataScanner = metadataScanner;
238
381
  this.runtime = runtime;
382
+ this.options = options;
239
383
  }
240
384
  onModuleInit() {
385
+ if (!isPureThinWorker(this.options)) return;
241
386
  scanSteps(this.discovery, this.metadataScanner, (meta, handler) => this.runtime.registerStep(meta.name, handler));
242
387
  }
243
388
  };
244
- ThinStepRegistrar = _ts_decorate([
245
- (0, import_common.Injectable)(),
246
- _ts_metadata("design:type", Function),
247
- _ts_metadata("design:paramtypes", [
389
+ ThinStepRegistrar = _ts_decorate2([
390
+ (0, import_common2.Injectable)(),
391
+ _ts_param(3, (0, import_common2.Inject)(import_nestjs_durable_core3.DURABLE_OPTIONS_CANONICAL)),
392
+ _ts_metadata2("design:type", Function),
393
+ _ts_metadata2("design:paramtypes", [
248
394
  typeof import_core.DiscoveryService === "undefined" ? Object : import_core.DiscoveryService,
249
395
  typeof import_core.MetadataScanner === "undefined" ? Object : import_core.MetadataScanner,
250
- typeof import_durable_worker.DurableWorkerRuntime === "undefined" ? Object : import_durable_worker.DurableWorkerRuntime
396
+ typeof import_durable_worker2.DurableWorkerRuntime === "undefined" ? Object : import_durable_worker2.DurableWorkerRuntime,
397
+ typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions
251
398
  ])
252
399
  ], ThinStepRegistrar);
253
400
  var ThinWorkerBootstrap = class {
@@ -266,113 +413,139 @@ var ThinWorkerBootstrap = class {
266
413
  this.runnersSink = runnersSink;
267
414
  }
268
415
  async onApplicationBootstrap() {
269
- for (const group of this.options.groups) {
270
- const handle = await this.runRedisWorker({
271
- runtime: this.runtime,
272
- group,
273
- connection: this.options.connection,
274
- ...this.options.prefix !== void 0 ? {
275
- prefix: this.options.prefix
276
- } : {},
277
- ...this.options.instanceId !== void 0 ? {
278
- instanceId: this.options.instanceId
279
- } : {},
280
- ...(this.options.concurrencyByGroup?.[group] ?? this.options.concurrency) !== void 0 ? {
281
- concurrency: this.options.concurrencyByGroup?.[group] ?? this.options.concurrency
282
- } : {}
283
- });
284
- this.runners.push(handle);
285
- this.runnersSink.push(handle);
286
- }
416
+ const options = this.options;
417
+ if (!isPureThinWorker(options) || options.connection === void 0) return;
418
+ const handle = await this.runRedisWorker({
419
+ runtime: this.runtime,
420
+ connection: options.connection,
421
+ ...options.partition !== void 0 ? {
422
+ partition: options.partition
423
+ } : {},
424
+ ...options.prefix !== void 0 ? {
425
+ prefix: options.prefix
426
+ } : {},
427
+ ...options.instanceId !== void 0 ? {
428
+ instanceId: options.instanceId
429
+ } : {},
430
+ ...options.concurrency !== void 0 ? {
431
+ concurrency: options.concurrency
432
+ } : {}
433
+ });
434
+ this.runners.push(handle);
435
+ this.runnersSink.push(handle);
287
436
  }
288
437
  async onApplicationShutdown() {
289
438
  await Promise.allSettled(this.runners.map((h) => h.close()));
290
439
  }
291
440
  };
292
- ThinWorkerBootstrap = _ts_decorate([
293
- (0, import_common.Injectable)(),
294
- _ts_param(1, (0, import_common.Inject)(DURABLE_WORKER_OPTIONS)),
295
- _ts_param(2, (0, import_common.Inject)(RUN_REDIS_WORKER)),
296
- _ts_param(3, (0, import_common.Inject)(DURABLE_WORKER_RUNNERS)),
297
- _ts_metadata("design:type", Function),
298
- _ts_metadata("design:paramtypes", [
299
- typeof import_durable_worker.DurableWorkerRuntime === "undefined" ? Object : import_durable_worker.DurableWorkerRuntime,
300
- typeof DurableWorkerModuleOptions === "undefined" ? Object : DurableWorkerModuleOptions,
441
+ ThinWorkerBootstrap = _ts_decorate2([
442
+ (0, import_common2.Injectable)(),
443
+ _ts_param(1, (0, import_common2.Inject)(import_nestjs_durable_core3.DURABLE_OPTIONS_CANONICAL)),
444
+ _ts_param(2, (0, import_common2.Inject)(RUN_REDIS_WORKER)),
445
+ _ts_param(3, (0, import_common2.Inject)(DURABLE_WORKER_RUNNERS)),
446
+ _ts_metadata2("design:type", Function),
447
+ _ts_metadata2("design:paramtypes", [
448
+ typeof import_durable_worker2.DurableWorkerRuntime === "undefined" ? Object : import_durable_worker2.DurableWorkerRuntime,
449
+ typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions,
301
450
  typeof RunRedisWorkerFn === "undefined" ? Object : RunRedisWorkerFn,
302
451
  Array
303
452
  ])
304
453
  ], ThinWorkerBootstrap);
305
- var DurableWorkerModule = class _DurableWorkerModule {
306
- static {
307
- __name(this, "DurableWorkerModule");
308
- }
309
- static forRoot(options) {
310
- return _DurableWorkerModule.build({
311
- provide: DURABLE_WORKER_OPTIONS,
312
- useValue: options
313
- });
314
- }
315
- static forRootAsync(options) {
316
- return _DurableWorkerModule.build({
317
- provide: DURABLE_WORKER_OPTIONS,
318
- useFactory: options.useFactory,
319
- inject: options.inject ?? []
320
- });
321
- }
322
- static build(optionsProvider) {
323
- return {
324
- module: _DurableWorkerModule,
325
- imports: [
326
- import_core.DiscoveryModule
327
- ],
328
- providers: [
329
- optionsProvider,
330
- {
331
- provide: import_durable_worker.DurableWorkerRuntime,
332
- useFactory: /* @__PURE__ */ __name(() => new import_durable_worker.DurableWorkerRuntime(), "useFactory")
333
- },
334
- {
335
- provide: RUN_REDIS_WORKER,
336
- useValue: import_durable_worker.runRedisWorker
337
- },
338
- {
339
- provide: DURABLE_WORKER_RUNNERS,
340
- useValue: []
341
- },
342
- ThinWorkflowRegistrar,
343
- ThinStepRegistrar,
344
- ThinWorkerBootstrap
345
- ],
346
- exports: [
347
- import_durable_worker.DurableWorkerRuntime
454
+ function thinWorkerProviders() {
455
+ return [
456
+ {
457
+ provide: import_durable_worker2.DurableWorkerRuntime,
458
+ // The runtime's `WorkflowWorker` falls back to its own `group` ctor param as the WORKFLOW's
459
+ // `workflowPartition` for any `ctx.step` call (see `workflow-context.ts`'s `resolveCallGroup`)
460
+ // — that fallback MUST equal this module's own `partition`, or a dispatched step's decision
461
+ // carries a mismatched token and the engine dispatches it to a queue nothing here subscribes
462
+ // to. Explicit `''` (never
463
+ // `undefined`) so it does NOT fall through to `WorkflowWorker`'s unrelated `'workflows'`
464
+ // default parameter.
465
+ useFactory: /* @__PURE__ */ __name((options) => new import_durable_worker2.DurableWorkerRuntime({
466
+ workflowGroup: options.partition ?? ""
467
+ }), "useFactory"),
468
+ inject: [
469
+ import_nestjs_durable_core3.DURABLE_OPTIONS_CANONICAL
348
470
  ]
349
- };
350
- }
351
- };
352
- DurableWorkerModule = _ts_decorate([
353
- (0, import_common.Module)({})
354
- ], DurableWorkerModule);
471
+ },
472
+ {
473
+ provide: RUN_REDIS_WORKER,
474
+ useValue: import_durable_worker2.runRedisWorker
475
+ },
476
+ {
477
+ provide: DURABLE_WORKER_RUNNERS,
478
+ useValue: []
479
+ },
480
+ ThinWorkflowRegistrar,
481
+ ThinStepRegistrar,
482
+ ThinWorkerBootstrap
483
+ ];
484
+ }
485
+ __name(thinWorkerProviders, "thinWorkerProviders");
486
+ function tenantGatewayUnavailable(method) {
487
+ return Promise.reject(new Error(`RunGateway.${method}() is not available \u2014 pass \`transport\` to use RunGateway.`));
488
+ }
489
+ __name(tenantGatewayUnavailable, "tenantGatewayUnavailable");
490
+ function unavailableRunGateway() {
491
+ return {
492
+ getRunDetail(_runId) {
493
+ return tenantGatewayUnavailable("getRunDetail");
494
+ },
495
+ listRuns(_query) {
496
+ return tenantGatewayUnavailable("listRuns");
497
+ },
498
+ cancel(_runId) {
499
+ return tenantGatewayUnavailable("cancel");
500
+ },
501
+ retry(_runId) {
502
+ return tenantGatewayUnavailable("retry");
503
+ },
504
+ continue(_runId) {
505
+ return tenantGatewayUnavailable("continue");
506
+ },
507
+ retryWithInput(_runId, _input) {
508
+ return tenantGatewayUnavailable("retryWithInput");
509
+ },
510
+ subscribe(_runId, _onEvent) {
511
+ throw new Error("RunGateway.subscribe() is not available \u2014 pass `transport` to use RunGateway.");
512
+ }
513
+ };
514
+ }
515
+ __name(unavailableRunGateway, "unavailableRunGateway");
355
516
 
356
517
  // src/durable.module.ts
357
- var import_nestjs_durable_core9 = require("@dudousxd/nestjs-durable-core");
358
- var import_common9 = require("@nestjs/common");
518
+ var import_nestjs_durable_core12 = require("@dudousxd/nestjs-durable-core");
519
+ var import_common12 = require("@nestjs/common");
359
520
  var import_core5 = require("@nestjs/core");
360
521
 
361
522
  // src/durable-step.registrar.ts
362
- var import_nestjs_durable_core2 = require("@dudousxd/nestjs-durable-core");
363
- var import_common2 = require("@nestjs/common");
523
+ var import_nestjs_durable_core4 = require("@dudousxd/nestjs-durable-core");
524
+ var import_common3 = require("@nestjs/common");
364
525
  var import_core2 = require("@nestjs/core");
365
- function _ts_decorate2(decorators, target, key, desc) {
526
+
527
+ // src/role.ts
528
+ function isOperatorRole(options) {
529
+ return options.store !== void 0;
530
+ }
531
+ __name(isOperatorRole, "isOperatorRole");
532
+ function isDrivingOperator(options) {
533
+ return isOperatorRole(options) && options.drive !== false;
534
+ }
535
+ __name(isDrivingOperator, "isDrivingOperator");
536
+
537
+ // src/durable-step.registrar.ts
538
+ function _ts_decorate3(decorators, target, key, desc) {
366
539
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
367
540
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
368
541
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
369
542
  return c > 3 && r && Object.defineProperty(target, key, r), r;
370
543
  }
371
- __name(_ts_decorate2, "_ts_decorate");
372
- function _ts_metadata2(k, v) {
544
+ __name(_ts_decorate3, "_ts_decorate");
545
+ function _ts_metadata3(k, v) {
373
546
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
374
547
  }
375
- __name(_ts_metadata2, "_ts_metadata");
548
+ __name(_ts_metadata3, "_ts_metadata");
376
549
  function _ts_param2(paramIndex, decorator) {
377
550
  return function(target, key) {
378
551
  decorator(target, key, paramIndex);
@@ -398,18 +571,18 @@ var DurableStepRegistrar = class {
398
571
  this.options = options;
399
572
  }
400
573
  onModuleInit() {
401
- if (this.options.worker === false) return;
574
+ if (!isDrivingOperator(this.options)) return;
402
575
  if (!supportsHandle(this.transport)) return;
403
576
  const transport = this.transport;
404
577
  scanSteps(this.discovery, this.metadataScanner, (meta, handler) => transport.handle(meta.name, handler));
405
578
  }
406
579
  };
407
- DurableStepRegistrar = _ts_decorate2([
408
- (0, import_common2.Injectable)(),
409
- _ts_param2(2, (0, import_common2.Inject)(import_nestjs_durable_core2.TRANSPORT_CANONICAL)),
410
- _ts_param2(3, (0, import_common2.Inject)(import_nestjs_durable_core2.DURABLE_OPTIONS_CANONICAL)),
411
- _ts_metadata2("design:type", Function),
412
- _ts_metadata2("design:paramtypes", [
580
+ DurableStepRegistrar = _ts_decorate3([
581
+ (0, import_common3.Injectable)(),
582
+ _ts_param2(2, (0, import_common3.Inject)(import_nestjs_durable_core4.TRANSPORT_CANONICAL)),
583
+ _ts_param2(3, (0, import_common3.Inject)(import_nestjs_durable_core4.DURABLE_OPTIONS_CANONICAL)),
584
+ _ts_metadata3("design:type", Function),
585
+ _ts_metadata3("design:paramtypes", [
413
586
  typeof import_core2.DiscoveryService === "undefined" ? Object : import_core2.DiscoveryService,
414
587
  typeof import_core2.MetadataScanner === "undefined" ? Object : import_core2.MetadataScanner,
415
588
  Object,
@@ -418,20 +591,20 @@ DurableStepRegistrar = _ts_decorate2([
418
591
  ], DurableStepRegistrar);
419
592
 
420
593
  // src/entity.ts
421
- var import_nestjs_durable_core3 = require("@dudousxd/nestjs-durable-core");
422
- var import_common3 = require("@nestjs/common");
594
+ var import_nestjs_durable_core5 = require("@dudousxd/nestjs-durable-core");
595
+ var import_common4 = require("@nestjs/common");
423
596
  var import_reflect_metadata2 = require("reflect-metadata");
424
- function _ts_decorate3(decorators, target, key, desc) {
597
+ function _ts_decorate4(decorators, target, key, desc) {
425
598
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
426
599
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
427
600
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
428
601
  return c > 3 && r && Object.defineProperty(target, key, r), r;
429
602
  }
430
- __name(_ts_decorate3, "_ts_decorate");
431
- function _ts_metadata3(k, v) {
603
+ __name(_ts_decorate4, "_ts_decorate");
604
+ function _ts_metadata4(k, v) {
432
605
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
433
606
  }
434
- __name(_ts_metadata3, "_ts_metadata");
607
+ __name(_ts_metadata4, "_ts_metadata");
435
608
  var ENTITY_METADATA = Symbol("nestjs-durable:entity");
436
609
  var ENTITY_ON_METADATA = Symbol("nestjs-durable:entity-on");
437
610
  function Entity(options) {
@@ -488,49 +661,54 @@ var EntityService = class {
488
661
  return this.engine.getEntityState(name, key);
489
662
  }
490
663
  };
491
- EntityService = _ts_decorate3([
492
- (0, import_common3.Injectable)(),
493
- _ts_metadata3("design:type", Function),
494
- _ts_metadata3("design:paramtypes", [
495
- typeof import_nestjs_durable_core3.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core3.WorkflowEngine
664
+ EntityService = _ts_decorate4([
665
+ (0, import_common4.Injectable)(),
666
+ _ts_metadata4("design:type", Function),
667
+ _ts_metadata4("design:paramtypes", [
668
+ typeof import_nestjs_durable_core5.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core5.WorkflowEngine
496
669
  ])
497
670
  ], EntityService);
498
671
 
499
672
  // src/in-app-worker.ts
500
- var import_durable_worker2 = require("@dudousxd/durable-worker");
501
- var import_nestjs_durable_core4 = require("@dudousxd/nestjs-durable-core");
502
- var import_common4 = require("@nestjs/common");
673
+ var import_durable_worker3 = require("@dudousxd/durable-worker");
674
+ var import_nestjs_durable_core6 = require("@dudousxd/nestjs-durable-core");
675
+ var import_common5 = require("@nestjs/common");
503
676
  var import_core3 = require("@nestjs/core");
504
- function _ts_decorate4(decorators, target, key, desc) {
677
+ function _ts_decorate5(decorators, target, key, desc) {
505
678
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
506
679
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
507
680
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
508
681
  return c > 3 && r && Object.defineProperty(target, key, r), r;
509
682
  }
510
- __name(_ts_decorate4, "_ts_decorate");
511
- function _ts_metadata4(k, v) {
683
+ __name(_ts_decorate5, "_ts_decorate");
684
+ function _ts_metadata5(k, v) {
512
685
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
513
686
  }
514
- __name(_ts_metadata4, "_ts_metadata");
687
+ __name(_ts_metadata5, "_ts_metadata");
515
688
  function _ts_param3(paramIndex, decorator) {
516
689
  return function(target, key) {
517
690
  decorator(target, key, paramIndex);
518
691
  };
519
692
  }
520
693
  __name(_ts_param3, "_ts_param");
521
- var IN_APP_WORKER_OPTIONS = Symbol("nestjs-durable:in-app-worker-options");
522
694
  var IN_APP_WORKER_BINDING = Symbol("nestjs-durable:in-app-worker-binding");
523
695
  var IN_APP_WORKER_RUNTIME = Symbol("nestjs-durable:in-app-worker-runtime");
524
696
  var IN_APP_RUN_REDIS_WORKER = Symbol("nestjs-durable:in-app-run-redis-worker");
525
697
  var IN_APP_WORKER_RUNNERS = Symbol("nestjs-durable:in-app-worker-runners");
698
+ function isCoLocatedWorker(options) {
699
+ return options.store !== void 0 && options.connection !== void 0;
700
+ }
701
+ __name(isCoLocatedWorker, "isCoLocatedWorker");
526
702
  function inAppWorkerBinding(transport, options) {
527
- if (!options) return null;
703
+ if (!isCoLocatedWorker(options)) return null;
528
704
  if (!transport?.dispatchWorkflowTask || !transport.onDecision) {
529
- throw new Error("inAppWorker requires a transport that carries workflow tasks (dispatchWorkflowTask + onDecision), e.g. BullMQTransport. An in-process transport cannot serve a group-served workflow.");
705
+ throw new Error("a co-located worker (store + connection) requires a transport that carries workflow tasks (dispatchWorkflowTask + onDecision), e.g. BullMQTransport. An in-process transport cannot serve a group-served workflow.");
530
706
  }
531
707
  return {
532
- group: options.group,
533
- executor: new import_nestjs_durable_core4.RemoteWorkflowExecutor(transport, options.group)
708
+ transport,
709
+ ...options.partition !== void 0 ? {
710
+ partition: options.partition
711
+ } : {}
534
712
  };
535
713
  }
536
714
  __name(inAppWorkerBinding, "inAppWorkerBinding");
@@ -554,24 +732,27 @@ var InAppWorkerBootstrap = class {
554
732
  this.runnersSink = runnersSink;
555
733
  }
556
734
  onModuleInit() {
557
- if (!this.options) return;
735
+ if (!isCoLocatedWorker(this.options)) return;
558
736
  scanWorkflows(this.discovery, (meta, instance) => this.runtime.registerWorkflow(meta.name, (ctx, input) => instance.run(ctx, input)));
559
737
  scanSteps(this.discovery, this.metadataScanner, (meta, handler) => this.runtime.registerStep(meta.name, handler));
560
738
  }
561
739
  async onApplicationBootstrap() {
562
- if (!this.options) return;
740
+ const options = this.options;
741
+ if (!isCoLocatedWorker(options) || options.connection === void 0) return;
563
742
  const handle = await this.runRedisWorker({
564
743
  runtime: this.runtime,
565
- group: this.options.group,
566
- connection: this.options.connection,
567
- ...this.options.prefix !== void 0 ? {
568
- prefix: this.options.prefix
744
+ connection: options.connection,
745
+ ...options.partition !== void 0 ? {
746
+ partition: options.partition
747
+ } : {},
748
+ ...options.prefix !== void 0 ? {
749
+ prefix: options.prefix
569
750
  } : {},
570
- ...this.options.instanceId !== void 0 ? {
571
- instanceId: this.options.instanceId
751
+ ...options.instanceId !== void 0 ? {
752
+ instanceId: options.instanceId
572
753
  } : {},
573
- ...this.options.concurrency !== void 0 ? {
574
- concurrency: this.options.concurrency
754
+ ...options.concurrency !== void 0 ? {
755
+ concurrency: options.concurrency
575
756
  } : {}
576
757
  });
577
758
  this.runners.push(handle);
@@ -581,18 +762,18 @@ var InAppWorkerBootstrap = class {
581
762
  await Promise.allSettled(this.runners.map((handle) => handle.close()));
582
763
  }
583
764
  };
584
- InAppWorkerBootstrap = _ts_decorate4([
585
- (0, import_common4.Injectable)(),
586
- _ts_param3(2, (0, import_common4.Inject)(IN_APP_WORKER_OPTIONS)),
587
- _ts_param3(3, (0, import_common4.Inject)(IN_APP_WORKER_RUNTIME)),
588
- _ts_param3(4, (0, import_common4.Inject)(IN_APP_RUN_REDIS_WORKER)),
589
- _ts_param3(5, (0, import_common4.Inject)(IN_APP_WORKER_RUNNERS)),
590
- _ts_metadata4("design:type", Function),
591
- _ts_metadata4("design:paramtypes", [
765
+ InAppWorkerBootstrap = _ts_decorate5([
766
+ (0, import_common5.Injectable)(),
767
+ _ts_param3(2, (0, import_common5.Inject)(import_nestjs_durable_core6.DURABLE_OPTIONS_CANONICAL)),
768
+ _ts_param3(3, (0, import_common5.Inject)(IN_APP_WORKER_RUNTIME)),
769
+ _ts_param3(4, (0, import_common5.Inject)(IN_APP_RUN_REDIS_WORKER)),
770
+ _ts_param3(5, (0, import_common5.Inject)(IN_APP_WORKER_RUNNERS)),
771
+ _ts_metadata5("design:type", Function),
772
+ _ts_metadata5("design:paramtypes", [
592
773
  typeof import_core3.DiscoveryService === "undefined" ? Object : import_core3.DiscoveryService,
593
774
  typeof import_core3.MetadataScanner === "undefined" ? Object : import_core3.MetadataScanner,
594
- Object,
595
- typeof import_durable_worker2.DurableWorkerRuntime === "undefined" ? Object : import_durable_worker2.DurableWorkerRuntime,
775
+ typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions,
776
+ typeof import_durable_worker3.DurableWorkerRuntime === "undefined" ? Object : import_durable_worker3.DurableWorkerRuntime,
596
777
  typeof RunRedisWorkerFn === "undefined" ? Object : RunRedisWorkerFn,
597
778
  Array
598
779
  ])
@@ -601,26 +782,31 @@ function inAppWorkerProviders() {
601
782
  return [
602
783
  {
603
784
  provide: IN_APP_WORKER_BINDING,
604
- useFactory: /* @__PURE__ */ __name((transport, options) => inAppWorkerBinding(transport, options.inAppWorker ?? null), "useFactory"),
785
+ useFactory: /* @__PURE__ */ __name((transport, options) => inAppWorkerBinding(transport, options), "useFactory"),
605
786
  inject: [
606
- import_nestjs_durable_core4.TRANSPORT_CANONICAL,
607
- import_nestjs_durable_core4.DURABLE_OPTIONS_CANONICAL
787
+ import_nestjs_durable_core6.TRANSPORT_CANONICAL,
788
+ import_nestjs_durable_core6.DURABLE_OPTIONS_CANONICAL
608
789
  ]
609
790
  },
610
791
  {
611
- provide: IN_APP_WORKER_OPTIONS,
612
- useFactory: /* @__PURE__ */ __name((options) => options.inAppWorker ?? null, "useFactory"),
792
+ provide: IN_APP_WORKER_RUNTIME,
793
+ // The runtime's `WorkflowWorker` uses its `group` ctor param as the WORKFLOW's
794
+ // `workflowPartition` for any `ctx.step` call (see `workflow-context.ts`'s `resolveCallGroup`)
795
+ // — that fallback MUST equal this app's own `partition`, or a dispatched step's decision
796
+ // carries a mismatched token and the engine dispatches it to a queue nothing here subscribes
797
+ // to. Explicit `''` (never
798
+ // `undefined`) so it does NOT fall through to `WorkflowWorker`'s unrelated `'workflows'`
799
+ // default parameter.
800
+ useFactory: /* @__PURE__ */ __name((options) => new import_durable_worker3.DurableWorkerRuntime({
801
+ workflowGroup: options.partition ?? ""
802
+ }), "useFactory"),
613
803
  inject: [
614
- import_nestjs_durable_core4.DURABLE_OPTIONS_CANONICAL
804
+ import_nestjs_durable_core6.DURABLE_OPTIONS_CANONICAL
615
805
  ]
616
806
  },
617
- {
618
- provide: IN_APP_WORKER_RUNTIME,
619
- useFactory: /* @__PURE__ */ __name(() => new import_durable_worker2.DurableWorkerRuntime(), "useFactory")
620
- },
621
807
  {
622
808
  provide: IN_APP_RUN_REDIS_WORKER,
623
- useValue: import_durable_worker2.runRedisWorker
809
+ useValue: import_durable_worker3.runRedisWorker
624
810
  },
625
811
  {
626
812
  provide: IN_APP_WORKER_RUNNERS,
@@ -631,20 +817,142 @@ function inAppWorkerProviders() {
631
817
  }
632
818
  __name(inAppWorkerProviders, "inAppWorkerProviders");
633
819
 
820
+ // src/proxy-run-gateway.ts
821
+ var import_common6 = require("@nestjs/common");
822
+ function _ts_decorate6(decorators, target, key, desc) {
823
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
824
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
825
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
826
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
827
+ }
828
+ __name(_ts_decorate6, "_ts_decorate");
829
+ function _ts_metadata6(k, v) {
830
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
831
+ }
832
+ __name(_ts_metadata6, "_ts_metadata");
833
+ var ProxyRunGateway = class {
834
+ static {
835
+ __name(this, "ProxyRunGateway");
836
+ }
837
+ transport;
838
+ tenant;
839
+ timeoutMs;
840
+ pending = /* @__PURE__ */ new Map();
841
+ constructor(transport, tenant, timeoutMs = 1e4) {
842
+ this.transport = transport;
843
+ this.tenant = tenant;
844
+ this.timeoutMs = timeoutMs;
845
+ this.transport.onRunReply?.((reply) => this.handleReply(reply));
846
+ }
847
+ handleReply(reply) {
848
+ const pending = this.pending.get(reply.requestId);
849
+ if (!pending) return;
850
+ clearTimeout(pending.timer);
851
+ this.pending.delete(reply.requestId);
852
+ if (reply.result.ok) {
853
+ pending.resolve(reply.result.data);
854
+ } else {
855
+ pending.reject(new Error(reply.result.error.message));
856
+ }
857
+ }
858
+ request(body) {
859
+ return new Promise((resolve, reject) => {
860
+ const requestId = globalThis.crypto.randomUUID();
861
+ const timer = setTimeout(() => {
862
+ this.pending.delete(requestId);
863
+ reject(new Error(`control plane did not respond to ${body.kind} within ${this.timeoutMs}ms`));
864
+ }, this.timeoutMs);
865
+ this.pending.set(requestId, {
866
+ resolve,
867
+ reject,
868
+ timer
869
+ });
870
+ this.transport.dispatchRunRequest?.({
871
+ requestId,
872
+ tenant: this.tenant,
873
+ body
874
+ }).catch((error) => {
875
+ const stillPending = this.pending.get(requestId);
876
+ if (!stillPending) return;
877
+ clearTimeout(stillPending.timer);
878
+ this.pending.delete(requestId);
879
+ stillPending.reject(error instanceof Error ? error : new Error(String(error)));
880
+ });
881
+ });
882
+ }
883
+ getRunDetail(runId) {
884
+ return this.request({
885
+ kind: "getRunDetail",
886
+ runId
887
+ });
888
+ }
889
+ listRuns(query) {
890
+ return this.request({
891
+ kind: "listRuns",
892
+ query
893
+ });
894
+ }
895
+ cancel(runId, opts) {
896
+ return this.request(opts === void 0 ? {
897
+ kind: "cancel",
898
+ runId
899
+ } : {
900
+ kind: "cancel",
901
+ runId,
902
+ opts
903
+ });
904
+ }
905
+ retry(runId) {
906
+ return this.request({
907
+ kind: "retry",
908
+ runId
909
+ });
910
+ }
911
+ continue(runId) {
912
+ return this.request({
913
+ kind: "continue",
914
+ runId
915
+ });
916
+ }
917
+ retryWithInput(runId, input) {
918
+ return this.request({
919
+ kind: "retryWithInput",
920
+ runId,
921
+ input
922
+ });
923
+ }
924
+ subscribe(runId, onEvent) {
925
+ const unsubscribe = this.transport.onTenantEvent?.(this.tenant, (evt) => {
926
+ if (evt.event.runId === runId) onEvent(evt.event);
927
+ });
928
+ return unsubscribe ?? (() => {
929
+ });
930
+ }
931
+ };
932
+ ProxyRunGateway = _ts_decorate6([
933
+ (0, import_common6.Injectable)(),
934
+ _ts_metadata6("design:type", Function),
935
+ _ts_metadata6("design:paramtypes", [
936
+ typeof Transport === "undefined" ? Object : Transport,
937
+ String,
938
+ void 0
939
+ ])
940
+ ], ProxyRunGateway);
941
+
634
942
  // src/retention-poller.ts
635
- var import_nestjs_durable_core5 = require("@dudousxd/nestjs-durable-core");
636
- var import_common5 = require("@nestjs/common");
637
- function _ts_decorate5(decorators, target, key, desc) {
943
+ var import_nestjs_durable_core7 = require("@dudousxd/nestjs-durable-core");
944
+ var import_common7 = require("@nestjs/common");
945
+ function _ts_decorate7(decorators, target, key, desc) {
638
946
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
639
947
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
640
948
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
641
949
  return c > 3 && r && Object.defineProperty(target, key, r), r;
642
950
  }
643
- __name(_ts_decorate5, "_ts_decorate");
644
- function _ts_metadata5(k, v) {
951
+ __name(_ts_decorate7, "_ts_decorate");
952
+ function _ts_metadata7(k, v) {
645
953
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
646
954
  }
647
- __name(_ts_metadata5, "_ts_metadata");
955
+ __name(_ts_metadata7, "_ts_metadata");
648
956
  function _ts_param4(paramIndex, decorator) {
649
957
  return function(target, key) {
650
958
  decorator(target, key, paramIndex);
@@ -663,10 +971,10 @@ function validateRetention(retention) {
663
971
  if (policy.maxAge == null && policy.maxCount == null) {
664
972
  throw new Error("durable retention: each policy must set maxAge and/or maxCount");
665
973
  }
666
- if (policy.maxAge != null) (0, import_nestjs_durable_core5.parseDuration)(policy.maxAge);
974
+ if (policy.maxAge != null) (0, import_nestjs_durable_core7.parseDuration)(policy.maxAge);
667
975
  for (const status of policy.statuses) {
668
- if (!import_nestjs_durable_core5.TERMINAL_RUN_STATUSES.includes(status)) {
669
- throw new Error(`durable retention: status "${status}" is not terminal; only ${import_nestjs_durable_core5.TERMINAL_RUN_STATUSES.join(", ")} can be pruned`);
976
+ if (!import_nestjs_durable_core7.TERMINAL_RUN_STATUSES.includes(status)) {
977
+ throw new Error(`durable retention: status "${status}" is not terminal; only ${import_nestjs_durable_core7.TERMINAL_RUN_STATUSES.join(", ")} can be pruned`);
670
978
  }
671
979
  if (seen.has(status)) {
672
980
  throw new Error(`durable retention: status "${status}" appears in more than one policy; status sets must be disjoint`);
@@ -688,17 +996,24 @@ var RetentionPoller = class {
688
996
  this.store = store;
689
997
  this.options = options;
690
998
  }
999
+ /** Non-null once past the `isDrivingOperator` guard (which requires `options.store` to be set). */
1000
+ requireStore() {
1001
+ if (!this.store) {
1002
+ throw new Error("unreachable: STATE_STORE_CANONICAL must resolve a store when options.store is set");
1003
+ }
1004
+ return this.store;
1005
+ }
691
1006
  async onApplicationBootstrap() {
692
- if (this.options.worker === false) return;
1007
+ if (!isDrivingOperator(this.options)) return;
693
1008
  const retention = this.options.retention;
694
1009
  if (!retention || retention.policies.length === 0) return;
695
1010
  validateRetention(retention);
696
- if (typeof this.store.pruneTerminalRuns !== "function") {
1011
+ if (typeof this.requireStore().pruneTerminalRuns !== "function") {
697
1012
  console.warn("[nestjs-durable] `retention` is configured but the store adapter does not implement pruneTerminalRuns; retention is disabled.");
698
1013
  return;
699
1014
  }
700
1015
  await this.sweep();
701
- const intervalMs = retention.sweepInterval != null ? (0, import_nestjs_durable_core5.parseDuration)(retention.sweepInterval) : DEFAULT_SWEEP_INTERVAL_MS;
1016
+ const intervalMs = retention.sweepInterval != null ? (0, import_nestjs_durable_core7.parseDuration)(retention.sweepInterval) : DEFAULT_SWEEP_INTERVAL_MS;
702
1017
  if (intervalMs > 0) {
703
1018
  this.timer = setInterval(() => void this.sweep(), intervalMs);
704
1019
  this.timer.unref?.();
@@ -710,7 +1025,8 @@ var RetentionPoller = class {
710
1025
  async sweep() {
711
1026
  if (this.sweeping) return;
712
1027
  const retention = this.options.retention;
713
- const prune = this.store.pruneTerminalRuns;
1028
+ const store = this.requireStore();
1029
+ const prune = store.pruneTerminalRuns;
714
1030
  if (!retention || typeof prune !== "function") return;
715
1031
  this.sweeping = true;
716
1032
  try {
@@ -718,7 +1034,7 @@ var RetentionPoller = class {
718
1034
  const now = Date.now();
719
1035
  for (const policy of retention.policies) {
720
1036
  for (let batch = 0; batch < MAX_BATCHES_PER_POLICY; batch++) {
721
- const deleted = await prune.call(this.store, policy, now, batchSize);
1037
+ const deleted = await prune.call(store, policy, now, batchSize);
722
1038
  if (deleted < batchSize) break;
723
1039
  }
724
1040
  }
@@ -727,37 +1043,244 @@ var RetentionPoller = class {
727
1043
  }
728
1044
  }
729
1045
  };
730
- RetentionPoller = _ts_decorate5([
731
- (0, import_common5.Injectable)(),
732
- _ts_param4(0, (0, import_common5.Inject)(import_nestjs_durable_core5.STATE_STORE_CANONICAL)),
733
- _ts_param4(1, (0, import_common5.Inject)(import_nestjs_durable_core5.DURABLE_OPTIONS_CANONICAL)),
734
- _ts_metadata5("design:type", Function),
735
- _ts_metadata5("design:paramtypes", [
736
- typeof StateStore === "undefined" ? Object : StateStore,
1046
+ RetentionPoller = _ts_decorate7([
1047
+ (0, import_common7.Injectable)(),
1048
+ _ts_param4(0, (0, import_common7.Inject)(import_nestjs_durable_core7.STATE_STORE_CANONICAL)),
1049
+ _ts_param4(1, (0, import_common7.Inject)(import_nestjs_durable_core7.DURABLE_OPTIONS_CANONICAL)),
1050
+ _ts_metadata7("design:type", Function),
1051
+ _ts_metadata7("design:paramtypes", [
1052
+ Object,
737
1053
  typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions
738
1054
  ])
739
1055
  ], RetentionPoller);
740
1056
 
741
- // src/timer-poller.ts
742
- var import_nestjs_durable_core6 = require("@dudousxd/nestjs-durable-core");
743
- var import_common6 = require("@nestjs/common");
744
- function _ts_decorate6(decorators, target, key, desc) {
1057
+ // src/run-request-responder.ts
1058
+ var RunRequestResponder = class {
1059
+ static {
1060
+ __name(this, "RunRequestResponder");
1061
+ }
1062
+ transport;
1063
+ gateway;
1064
+ constructor(transport, gateway) {
1065
+ this.transport = transport;
1066
+ this.gateway = gateway;
1067
+ }
1068
+ /** Register the consumer on the transport. Each request is answered independently; a handler
1069
+ * failure never throws back into the transport (errors are captured into an error reply). */
1070
+ start() {
1071
+ this.transport.onRunRequest(async (msg) => {
1072
+ const reply = await this.handle(msg);
1073
+ await this.transport.publishRunReply(reply);
1074
+ });
1075
+ }
1076
+ async handle(msg) {
1077
+ const { body } = msg;
1078
+ if (body.kind === "listRuns") {
1079
+ const data = await this.gateway.listRuns({
1080
+ ...body.query,
1081
+ namespace: msg.tenant
1082
+ });
1083
+ return {
1084
+ requestId: msg.requestId,
1085
+ result: {
1086
+ ok: true,
1087
+ data
1088
+ }
1089
+ };
1090
+ }
1091
+ const detail = await this.gateway.getRunDetail(body.runId);
1092
+ if (detail && detail.run.namespace !== msg.tenant) {
1093
+ return {
1094
+ requestId: msg.requestId,
1095
+ result: {
1096
+ ok: false,
1097
+ error: {
1098
+ message: "run belongs to another tenant",
1099
+ code: "cross-tenant"
1100
+ }
1101
+ }
1102
+ };
1103
+ }
1104
+ if (body.kind === "getRunDetail") {
1105
+ return {
1106
+ requestId: msg.requestId,
1107
+ result: {
1108
+ ok: true,
1109
+ data: detail
1110
+ }
1111
+ };
1112
+ }
1113
+ try {
1114
+ const data = await this.callVerb(body);
1115
+ return {
1116
+ requestId: msg.requestId,
1117
+ result: {
1118
+ ok: true,
1119
+ data
1120
+ }
1121
+ };
1122
+ } catch (err) {
1123
+ return {
1124
+ requestId: msg.requestId,
1125
+ result: {
1126
+ ok: false,
1127
+ error: {
1128
+ message: err instanceof Error ? err.message : String(err)
1129
+ }
1130
+ }
1131
+ };
1132
+ }
1133
+ }
1134
+ callVerb(body) {
1135
+ switch (body.kind) {
1136
+ case "cancel":
1137
+ return this.gateway.cancel(body.runId, body.opts);
1138
+ case "retry":
1139
+ return this.gateway.retry(body.runId);
1140
+ case "continue":
1141
+ return this.gateway.continue(body.runId);
1142
+ case "retryWithInput":
1143
+ return this.gateway.retryWithInput(body.runId, body.input);
1144
+ }
1145
+ }
1146
+ };
1147
+
1148
+ // src/store-run-gateway.ts
1149
+ var import_nestjs_durable_core8 = require("@dudousxd/nestjs-durable-core");
1150
+ var import_common8 = require("@nestjs/common");
1151
+ function _ts_decorate8(decorators, target, key, desc) {
745
1152
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
746
1153
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
747
1154
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
748
1155
  return c > 3 && r && Object.defineProperty(target, key, r), r;
749
1156
  }
750
- __name(_ts_decorate6, "_ts_decorate");
751
- function _ts_metadata6(k, v) {
1157
+ __name(_ts_decorate8, "_ts_decorate");
1158
+ function _ts_metadata8(k, v) {
752
1159
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
753
1160
  }
754
- __name(_ts_metadata6, "_ts_metadata");
1161
+ __name(_ts_metadata8, "_ts_metadata");
755
1162
  function _ts_param5(paramIndex, decorator) {
756
1163
  return function(target, key) {
757
1164
  decorator(target, key, paramIndex);
758
1165
  };
759
1166
  }
760
1167
  __name(_ts_param5, "_ts_param");
1168
+ var StoreRunGateway = class {
1169
+ static {
1170
+ __name(this, "StoreRunGateway");
1171
+ }
1172
+ store;
1173
+ engine;
1174
+ constructor(store, engine) {
1175
+ this.store = store;
1176
+ this.engine = engine;
1177
+ }
1178
+ async getRunDetail(runId) {
1179
+ const run = await this.store.getRun(runId);
1180
+ if (!run) return null;
1181
+ const [timeline, children] = await Promise.all([
1182
+ this.store.listCheckpoints(runId),
1183
+ this.engine.getRunChildren(runId)
1184
+ ]);
1185
+ return {
1186
+ run,
1187
+ timeline,
1188
+ children
1189
+ };
1190
+ }
1191
+ listRuns(query) {
1192
+ return this.store.listRuns(query);
1193
+ }
1194
+ cancel(runId, opts) {
1195
+ return this.engine.cancel(runId, opts);
1196
+ }
1197
+ /** Re-enqueue (dispatch model) instead of resuming inline — a worker picks the run up and replays it. */
1198
+ retry(runId) {
1199
+ return this.engine.requeue(runId);
1200
+ }
1201
+ continue(runId) {
1202
+ return this.engine.continue(runId);
1203
+ }
1204
+ retryWithInput(runId, input) {
1205
+ return this.engine.retryWithInput(runId, input);
1206
+ }
1207
+ subscribe(runId, onEvent) {
1208
+ return this.engine.subscribe((event) => {
1209
+ if (event.runId === runId) onEvent(event);
1210
+ });
1211
+ }
1212
+ };
1213
+ StoreRunGateway = _ts_decorate8([
1214
+ (0, import_common8.Injectable)(),
1215
+ _ts_param5(0, (0, import_common8.Inject)(import_nestjs_durable_core8.STATE_STORE_CANONICAL)),
1216
+ _ts_metadata8("design:type", Function),
1217
+ _ts_metadata8("design:paramtypes", [
1218
+ typeof StateStore === "undefined" ? Object : StateStore,
1219
+ typeof import_nestjs_durable_core8.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core8.WorkflowEngine
1220
+ ])
1221
+ ], StoreRunGateway);
1222
+
1223
+ // src/tenant-event-republisher.ts
1224
+ function isTerminalRunEvent(event) {
1225
+ return event.type === "run.completed" || event.type === "run.failed";
1226
+ }
1227
+ __name(isTerminalRunEvent, "isTerminalRunEvent");
1228
+ var TenantEventRepublisher = class {
1229
+ static {
1230
+ __name(this, "TenantEventRepublisher");
1231
+ }
1232
+ store;
1233
+ publish;
1234
+ runNamespaces = /* @__PURE__ */ new Map();
1235
+ constructor(store, publish) {
1236
+ this.store = store;
1237
+ this.publish = publish;
1238
+ }
1239
+ async handle(event) {
1240
+ const namespace = await this.namespaceFor(event);
1241
+ if (isTerminalRunEvent(event)) this.runNamespaces.delete(event.runId);
1242
+ if (!namespace || namespace === "default") return;
1243
+ await this.publish({
1244
+ tenant: namespace,
1245
+ event
1246
+ }).catch(() => void 0);
1247
+ }
1248
+ async namespaceFor(event) {
1249
+ if (this.runNamespaces.has(event.runId)) {
1250
+ const cached = this.runNamespaces.get(event.runId);
1251
+ return cached === null ? void 0 : cached;
1252
+ }
1253
+ if (event.namespace !== void 0) {
1254
+ this.runNamespaces.set(event.runId, event.namespace === "default" ? null : event.namespace);
1255
+ return event.namespace;
1256
+ }
1257
+ const run = await this.store.getRun(event.runId);
1258
+ const tenantNamespace = run?.namespace !== void 0 && run.namespace !== "default" ? run.namespace : null;
1259
+ this.runNamespaces.set(event.runId, tenantNamespace);
1260
+ return tenantNamespace === null ? void 0 : tenantNamespace;
1261
+ }
1262
+ };
1263
+
1264
+ // src/timer-poller.ts
1265
+ var import_nestjs_durable_core9 = require("@dudousxd/nestjs-durable-core");
1266
+ var import_common9 = require("@nestjs/common");
1267
+ function _ts_decorate9(decorators, target, key, desc) {
1268
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1269
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1270
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1271
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1272
+ }
1273
+ __name(_ts_decorate9, "_ts_decorate");
1274
+ function _ts_metadata9(k, v) {
1275
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1276
+ }
1277
+ __name(_ts_metadata9, "_ts_metadata");
1278
+ function _ts_param6(paramIndex, decorator) {
1279
+ return function(target, key) {
1280
+ decorator(target, key, paramIndex);
1281
+ };
1282
+ }
1283
+ __name(_ts_param6, "_ts_param");
761
1284
  var TimerPoller = class {
762
1285
  static {
763
1286
  __name(this, "TimerPoller");
@@ -772,7 +1295,7 @@ var TimerPoller = class {
772
1295
  this.options = options;
773
1296
  }
774
1297
  async onApplicationBootstrap() {
775
- if (this.options.worker === false) return;
1298
+ if (!isDrivingOperator(this.options)) return;
776
1299
  this.unsubscribeEnqueued = this.engine.onEnqueued((runId) => void this.engine.runOne(runId));
777
1300
  await this.poll();
778
1301
  const intervalMs = this.options.timerPollMs ?? 1e3;
@@ -795,29 +1318,30 @@ var TimerPoller = class {
795
1318
  await this.engine.sweepTimeouts();
796
1319
  const schedules = this.options.schedules;
797
1320
  if (schedules && schedules.length > 0) {
798
- await (0, import_nestjs_durable_core6.runSchedules)(this.engine, schedules, Date.now());
1321
+ await (0, import_nestjs_durable_core9.runSchedules)(this.engine, schedules, Date.now());
799
1322
  }
800
1323
  } finally {
801
1324
  this.polling = false;
802
1325
  }
803
1326
  }
804
1327
  };
805
- TimerPoller = _ts_decorate6([
806
- (0, import_common6.Injectable)(),
807
- _ts_param5(1, (0, import_common6.Inject)(import_nestjs_durable_core6.DURABLE_OPTIONS_CANONICAL)),
808
- _ts_metadata6("design:type", Function),
809
- _ts_metadata6("design:paramtypes", [
810
- typeof import_nestjs_durable_core6.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core6.WorkflowEngine,
1328
+ TimerPoller = _ts_decorate9([
1329
+ (0, import_common9.Injectable)(),
1330
+ _ts_param6(1, (0, import_common9.Inject)(import_nestjs_durable_core9.DURABLE_OPTIONS_CANONICAL)),
1331
+ _ts_metadata9("design:type", Function),
1332
+ _ts_metadata9("design:paramtypes", [
1333
+ typeof import_nestjs_durable_core9.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core9.WorkflowEngine,
811
1334
  typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions
812
1335
  ])
813
1336
  ], TimerPoller);
814
1337
 
815
1338
  // src/tokens.ts
816
1339
  var CONTEXT_ACCESSOR = Symbol.for("@dudousxd/nestjs-context:accessor");
1340
+ var RUN_GATEWAY = Symbol.for("nestjs-durable:run-gateway");
817
1341
 
818
1342
  // src/workflow.registrar.ts
819
- var import_nestjs_durable_core7 = require("@dudousxd/nestjs-durable-core");
820
- var import_common7 = require("@nestjs/common");
1343
+ var import_nestjs_durable_core10 = require("@dudousxd/nestjs-durable-core");
1344
+ var import_common10 = require("@nestjs/common");
821
1345
  var import_core4 = require("@nestjs/core");
822
1346
 
823
1347
  // src/input-validation.ts
@@ -860,23 +1384,23 @@ function isStepInterceptor(target) {
860
1384
  __name(isStepInterceptor, "isStepInterceptor");
861
1385
 
862
1386
  // src/workflow.registrar.ts
863
- function _ts_decorate7(decorators, target, key, desc) {
1387
+ function _ts_decorate10(decorators, target, key, desc) {
864
1388
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
865
1389
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
866
1390
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
867
1391
  return c > 3 && r && Object.defineProperty(target, key, r), r;
868
1392
  }
869
- __name(_ts_decorate7, "_ts_decorate");
870
- function _ts_metadata7(k, v) {
1393
+ __name(_ts_decorate10, "_ts_decorate");
1394
+ function _ts_metadata10(k, v) {
871
1395
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
872
1396
  }
873
- __name(_ts_metadata7, "_ts_metadata");
874
- function _ts_param6(paramIndex, decorator) {
1397
+ __name(_ts_metadata10, "_ts_metadata");
1398
+ function _ts_param7(paramIndex, decorator) {
875
1399
  return function(target, key) {
876
1400
  decorator(target, key, paramIndex);
877
1401
  };
878
1402
  }
879
- __name(_ts_param6, "_ts_param");
1403
+ __name(_ts_param7, "_ts_param");
880
1404
  var WorkflowRegistrar = class {
881
1405
  static {
882
1406
  __name(this, "WorkflowRegistrar");
@@ -896,13 +1420,15 @@ var WorkflowRegistrar = class {
896
1420
  this.inAppWorker = inAppWorker;
897
1421
  }
898
1422
  async onApplicationBootstrap() {
899
- if (this.options.worker === false) return;
1423
+ if (!isDrivingOperator(this.options)) return;
900
1424
  await this.engine.recoverIncomplete();
901
1425
  }
902
1426
  /** On deploy/shutdown: stop picking up new runs and wait for in-flight ones to settle, then close
903
1427
  * the transport(s) so the broker workers stop consuming and connections are released. Closing
904
- * AFTER the drain keeps the transport alive while in-flight runs dispatch/await their remote steps. */
1428
+ * AFTER the drain keeps the transport alive while in-flight runs dispatch/await their remote steps.
1429
+ * Operator only — a thin worker (no `store`) holds no engine to drain. */
905
1430
  async onApplicationShutdown() {
1431
+ if (!isOperatorRole(this.options)) return;
906
1432
  await this.engine.drain(this.options.shutdownTimeoutMs);
907
1433
  const transports = [
908
1434
  this.options.transport,
@@ -911,8 +1437,13 @@ var WorkflowRegistrar = class {
911
1437
  await Promise.allSettled(transports.map((t) => t?.close?.()));
912
1438
  }
913
1439
  async onModuleInit() {
1440
+ if (!isOperatorRole(this.options)) return;
1441
+ const store = this.store;
1442
+ if (!store) {
1443
+ throw new Error("unreachable: STATE_STORE_CANONICAL must resolve a store when options.store is set");
1444
+ }
914
1445
  if (this.options.autoSchema !== false) {
915
- await this.store.ensureSchema?.();
1446
+ await store.ensureSchema?.();
916
1447
  }
917
1448
  const deadLetterByWorkflow = /* @__PURE__ */ new Map();
918
1449
  for (const wrapper of this.discovery.getProviders()) {
@@ -931,11 +1462,11 @@ var WorkflowRegistrar = class {
931
1462
  const validateInput = meta.validateInput ?? (meta.inputSchema ? classValidatorInput(meta.inputSchema) : void 0);
932
1463
  const eventBatch = meta.debounce ? {
933
1464
  mode: "debounce",
934
- windowMs: (0, import_nestjs_durable_core7.parseDuration)(meta.debounce)
1465
+ windowMs: (0, import_nestjs_durable_core10.parseDuration)(meta.debounce)
935
1466
  } : meta.batch ? {
936
1467
  mode: "batch",
937
1468
  maxSize: meta.batch.maxSize,
938
- windowMs: (0, import_nestjs_durable_core7.parseDuration)(meta.batch.within)
1469
+ windowMs: (0, import_nestjs_durable_core10.parseDuration)(meta.batch.within)
939
1470
  } : void 0;
940
1471
  const workflowCtor = workflow.constructor;
941
1472
  this.engine.register(meta.name, meta.version, (ctx, input) => workflow.run(ctx, input), {
@@ -946,13 +1477,23 @@ var WorkflowRegistrar = class {
946
1477
  onEvent: getOnEvents(meta, workflowCtor),
947
1478
  eventBatch,
948
1479
  // Uniform dispatch (opt-in): when an in-app worker is configured, register the body GROUP-SERVED
949
- // so the engine dispatches its turns to the app's own group instead of running it inline; the
950
- // co-located worker consumer replays the same body. Absent → the inline fast path (unchanged).
1480
+ // so the engine dispatches its turns over the transport instead of running it inline; the
1481
+ // co-located worker consumer (Task 5: one queue PER REGISTERED NAME) replays the same body.
1482
+ // The routing token — and the executor that dispatches under it — MUST be keyed by THIS
1483
+ // workflow's own name (`tenantGroup(sanitizeQueueToken(meta.name), partition)`), not a single
1484
+ // group shared across every discovered `@Workflow`: a fixed shared token would dispatch every
1485
+ // workflow's turns to one queue while the co-located worker subscribes one queue per name,
1486
+ // so a turn dispatched under the wrong token would never be consumed. Absent → the inline fast
1487
+ // path (unchanged).
951
1488
  ...this.inAppWorker ? {
952
- group: this.inAppWorker.group,
953
- executor: this.inAppWorker.executor
1489
+ group: (0, import_nestjs_durable_core10.tenantGroup)((0, import_nestjs_durable_core10.sanitizeQueueToken)(meta.name), this.inAppWorker.partition),
1490
+ executor: new import_nestjs_durable_core10.RemoteWorkflowExecutor(this.inAppWorker.transport, meta.name, this.inAppWorker.partition)
954
1491
  } : {}
955
1492
  });
1493
+ (0, import_nestjs_durable_core10.bindWorkflowClass)(workflowCtor, {
1494
+ start: /* @__PURE__ */ __name((name, input, runId, opts) => this.engine.start(name, input, runId, opts), "start"),
1495
+ waitForRun: /* @__PURE__ */ __name((runId, opts) => this.engine.waitForRun(runId, opts), "waitForRun")
1496
+ });
956
1497
  const inline = this.findDeadLetterHandler(workflow);
957
1498
  if (inline && meta.deadLetterWorkflow) {
958
1499
  throw new Error(`@Workflow ${meta.name} declares both an inline @DeadLetter() method and a deadLetterWorkflow option. Use one: the inline handler, or the reference.`);
@@ -962,7 +1503,7 @@ var WorkflowRegistrar = class {
962
1503
  this.engine.register(dlqName, meta.version, inline);
963
1504
  deadLetterByWorkflow.set(meta.name, dlqName);
964
1505
  } else if (meta.deadLetterWorkflow) {
965
- deadLetterByWorkflow.set(meta.name, (0, import_nestjs_durable_core7.workflowName)(meta.deadLetterWorkflow));
1506
+ deadLetterByWorkflow.set(meta.name, (0, import_nestjs_durable_core10.workflowName)(meta.deadLetterWorkflow));
966
1507
  }
967
1508
  });
968
1509
  this.installDeadLetterRouting(deadLetterByWorkflow);
@@ -984,31 +1525,40 @@ var WorkflowRegistrar = class {
984
1525
  * a `dlq:<runId>` id, so re-recovery never double-dispatches.
985
1526
  */
986
1527
  installDeadLetterRouting(byWorkflow) {
987
- const fallback = this.options.deadLetterWorkflow ? (0, import_nestjs_durable_core7.workflowName)(this.options.deadLetterWorkflow) : void 0;
1528
+ const fallback = this.options.deadLetterWorkflow ? (0, import_nestjs_durable_core10.workflowName)(this.options.deadLetterWorkflow) : void 0;
988
1529
  if (byWorkflow.size === 0 && !fallback) return;
989
1530
  this.engine.onDead((run) => {
990
1531
  const target = byWorkflow.get(run.workflow) ?? fallback;
991
1532
  if (!target) return;
992
- void this.engine.start(target, {
993
- deadRunId: run.id,
994
- workflow: run.workflow,
995
- input: run.input,
996
- error: run.error
997
- }, `dlq:${run.id}`).catch(() => void 0);
1533
+ void this.engine.start(
1534
+ target,
1535
+ {
1536
+ deadRunId: run.id,
1537
+ workflow: run.workflow,
1538
+ input: run.input,
1539
+ error: run.error
1540
+ },
1541
+ `dlq:${run.id}`,
1542
+ // Route the dead-letter handler to the dead run's OWN tenant so an operator dispatches it to
1543
+ // that tenant's worker group (`target@<tenant>`), not the bare group.
1544
+ {
1545
+ namespace: run.namespace
1546
+ }
1547
+ ).catch(() => void 0);
998
1548
  });
999
1549
  }
1000
1550
  };
1001
- WorkflowRegistrar = _ts_decorate7([
1002
- (0, import_common7.Injectable)(),
1003
- _ts_param6(3, (0, import_common7.Inject)(import_nestjs_durable_core7.STATE_STORE_CANONICAL)),
1004
- _ts_param6(4, (0, import_common7.Inject)(import_nestjs_durable_core7.DURABLE_OPTIONS_CANONICAL)),
1005
- _ts_param6(5, (0, import_common7.Inject)(IN_APP_WORKER_BINDING)),
1006
- _ts_metadata7("design:type", Function),
1007
- _ts_metadata7("design:paramtypes", [
1551
+ WorkflowRegistrar = _ts_decorate10([
1552
+ (0, import_common10.Injectable)(),
1553
+ _ts_param7(3, (0, import_common10.Inject)(import_nestjs_durable_core10.STATE_STORE_CANONICAL)),
1554
+ _ts_param7(4, (0, import_common10.Inject)(import_nestjs_durable_core10.DURABLE_OPTIONS_CANONICAL)),
1555
+ _ts_param7(5, (0, import_common10.Inject)(IN_APP_WORKER_BINDING)),
1556
+ _ts_metadata10("design:type", Function),
1557
+ _ts_metadata10("design:paramtypes", [
1008
1558
  typeof import_core4.DiscoveryService === "undefined" ? Object : import_core4.DiscoveryService,
1009
1559
  typeof import_core4.MetadataScanner === "undefined" ? Object : import_core4.MetadataScanner,
1010
- typeof import_nestjs_durable_core7.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core7.WorkflowEngine,
1011
- typeof StateStore === "undefined" ? Object : StateStore,
1560
+ typeof import_nestjs_durable_core10.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core10.WorkflowEngine,
1561
+ Object,
1012
1562
  typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions,
1013
1563
  Object
1014
1564
  ])
@@ -1016,19 +1566,19 @@ WorkflowRegistrar = _ts_decorate7([
1016
1566
 
1017
1567
  // src/workflow.service.ts
1018
1568
  var import_node_crypto = require("crypto");
1019
- var import_nestjs_durable_core8 = require("@dudousxd/nestjs-durable-core");
1020
- var import_common8 = require("@nestjs/common");
1021
- function _ts_decorate8(decorators, target, key, desc) {
1569
+ var import_nestjs_durable_core11 = require("@dudousxd/nestjs-durable-core");
1570
+ var import_common11 = require("@nestjs/common");
1571
+ function _ts_decorate11(decorators, target, key, desc) {
1022
1572
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1023
1573
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1024
1574
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1025
1575
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1026
1576
  }
1027
- __name(_ts_decorate8, "_ts_decorate");
1028
- function _ts_metadata8(k, v) {
1577
+ __name(_ts_decorate11, "_ts_decorate");
1578
+ function _ts_metadata11(k, v) {
1029
1579
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1030
1580
  }
1031
- __name(_ts_metadata8, "_ts_metadata");
1581
+ __name(_ts_metadata11, "_ts_metadata");
1032
1582
  var WorkflowService = class {
1033
1583
  static {
1034
1584
  __name(this, "WorkflowService");
@@ -1060,7 +1610,7 @@ var WorkflowService = class {
1060
1610
  }
1061
1611
  /**
1062
1612
  * Publish a named event. Resumes runs waiting on it via `ctx.waitForEvent(name, { match })` and
1063
- * starts a fresh run of every workflow subscribed via `@Workflow({ onEvent })` / `@OnEvent` (the
1613
+ * starts a fresh run of every workflow subscribed via `@Workflow({ onEvent })` / `@OnDurableEvent` (the
1064
1614
  * payload becomes its input). Pass `opts.id` to dedupe redeliveries. Returns how many runs it
1065
1615
  * touched (resumed + started).
1066
1616
  */
@@ -1068,22 +1618,32 @@ var WorkflowService = class {
1068
1618
  return this.engine.publishEvent(name, payload, opts);
1069
1619
  }
1070
1620
  };
1071
- WorkflowService = _ts_decorate8([
1072
- (0, import_common8.Injectable)(),
1073
- _ts_metadata8("design:type", Function),
1074
- _ts_metadata8("design:paramtypes", [
1075
- typeof import_nestjs_durable_core8.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core8.WorkflowEngine
1621
+ WorkflowService = _ts_decorate11([
1622
+ (0, import_common11.Injectable)(),
1623
+ _ts_metadata11("design:type", Function),
1624
+ _ts_metadata11("design:paramtypes", [
1625
+ typeof import_nestjs_durable_core11.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core11.WorkflowEngine
1076
1626
  ])
1077
1627
  ], WorkflowService);
1078
1628
 
1079
1629
  // src/durable.module.ts
1080
- function _ts_decorate9(decorators, target, key, desc) {
1630
+ function _ts_decorate12(decorators, target, key, desc) {
1081
1631
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1082
1632
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1083
1633
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1084
1634
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1085
1635
  }
1086
- __name(_ts_decorate9, "_ts_decorate");
1636
+ __name(_ts_decorate12, "_ts_decorate");
1637
+ function _ts_metadata12(k, v) {
1638
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1639
+ }
1640
+ __name(_ts_metadata12, "_ts_metadata");
1641
+ function _ts_param8(paramIndex, decorator) {
1642
+ return function(target, key) {
1643
+ decorator(target, key, paramIndex);
1644
+ };
1645
+ }
1646
+ __name(_ts_param8, "_ts_param");
1087
1647
  function resolveAccessor(moduleRef) {
1088
1648
  try {
1089
1649
  return moduleRef.get(CONTEXT_ACCESSOR, {
@@ -1123,20 +1683,103 @@ function isControlPlane(x) {
1123
1683
  return !!x && typeof x.publishControl === "function" && typeof x.onControl === "function";
1124
1684
  }
1125
1685
  __name(isControlPlane, "isControlPlane");
1686
+ function isScopeableStore(store) {
1687
+ return typeof store.withScope === "function";
1688
+ }
1689
+ __name(isScopeableStore, "isScopeableStore");
1690
+ function scopedStore(store, options) {
1691
+ if (options.scopeReads !== true || options.namespace === void 0) return store;
1692
+ if (!isScopeableStore(store)) return store;
1693
+ return store.withScope({
1694
+ namespace: options.namespace
1695
+ });
1696
+ }
1697
+ __name(scopedStore, "scopedStore");
1698
+ function assertValidRole(options) {
1699
+ const hasStore = options.store !== void 0;
1700
+ const hasConnection = options.connection !== void 0;
1701
+ if (!hasStore && !hasConnection) {
1702
+ throw new Error("a durable module needs either a `store` (operator) or a `connection` (worker)");
1703
+ }
1704
+ if (hasStore && options.transport === void 0) {
1705
+ throw new Error("an operator (`store`) needs a `transport`");
1706
+ }
1707
+ }
1708
+ __name(assertValidRole, "assertValidRole");
1709
+ var RunGatewayBootstrap = class RunGatewayBootstrap2 {
1710
+ static {
1711
+ __name(this, "RunGatewayBootstrap");
1712
+ }
1713
+ engine;
1714
+ transport;
1715
+ gateway;
1716
+ store;
1717
+ options;
1718
+ unsubscribe;
1719
+ constructor(engine, transport, gateway, store, options) {
1720
+ this.engine = engine;
1721
+ this.transport = transport;
1722
+ this.gateway = gateway;
1723
+ this.store = store;
1724
+ this.options = options;
1725
+ }
1726
+ onApplicationBootstrap() {
1727
+ if (!isDrivingOperator(this.options) || !this.transport) return;
1728
+ const store = this.store;
1729
+ if (!store) return;
1730
+ const { onRunRequest, publishRunReply, publishTenantEvent } = this.transport;
1731
+ if (typeof onRunRequest === "function" && typeof publishRunReply === "function") {
1732
+ const runRequestTransport = {
1733
+ onRunRequest: onRunRequest.bind(this.transport),
1734
+ publishRunReply: publishRunReply.bind(this.transport)
1735
+ };
1736
+ new RunRequestResponder(runRequestTransport, this.gateway).start();
1737
+ }
1738
+ if (typeof publishTenantEvent === "function") {
1739
+ const republisher = new TenantEventRepublisher(store, publishTenantEvent.bind(this.transport));
1740
+ this.unsubscribe = this.engine.subscribe((event) => {
1741
+ void republisher.handle(event);
1742
+ });
1743
+ }
1744
+ }
1745
+ onModuleDestroy() {
1746
+ this.unsubscribe?.();
1747
+ }
1748
+ };
1749
+ RunGatewayBootstrap = _ts_decorate12([
1750
+ (0, import_common12.Injectable)(),
1751
+ _ts_param8(1, (0, import_common12.Inject)(import_nestjs_durable_core12.TRANSPORT_CANONICAL)),
1752
+ _ts_param8(2, (0, import_common12.Inject)(RUN_GATEWAY)),
1753
+ _ts_param8(3, (0, import_common12.Inject)(import_nestjs_durable_core12.STATE_STORE_CANONICAL)),
1754
+ _ts_param8(4, (0, import_common12.Inject)(import_nestjs_durable_core12.DURABLE_OPTIONS_CANONICAL)),
1755
+ _ts_metadata12("design:type", Function),
1756
+ _ts_metadata12("design:paramtypes", [
1757
+ typeof import_nestjs_durable_core12.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core12.WorkflowEngine,
1758
+ Object,
1759
+ typeof RunGateway === "undefined" ? Object : RunGateway,
1760
+ Object,
1761
+ typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions
1762
+ ])
1763
+ ], RunGatewayBootstrap);
1126
1764
  var DurableModule = class _DurableModule {
1127
1765
  static {
1128
1766
  __name(this, "DurableModule");
1129
1767
  }
1130
1768
  static forRoot(options) {
1769
+ assertValidRole(options);
1131
1770
  return _DurableModule.build({
1132
- provide: import_nestjs_durable_core9.DURABLE_OPTIONS_CANONICAL,
1771
+ provide: import_nestjs_durable_core12.DURABLE_OPTIONS_CANONICAL,
1133
1772
  useValue: options
1134
1773
  });
1135
1774
  }
1136
1775
  static forRootAsync(options) {
1137
1776
  return _DurableModule.build({
1138
- provide: import_nestjs_durable_core9.DURABLE_OPTIONS_CANONICAL,
1139
- useFactory: options.useFactory,
1777
+ provide: import_nestjs_durable_core12.DURABLE_OPTIONS_CANONICAL,
1778
+ useFactory: /* @__PURE__ */ __name(async (...args) => {
1779
+ const resolved = await options.useFactory(...args);
1780
+ assertValidRole(resolved);
1781
+ return resolved;
1782
+ }, "useFactory"),
1140
1783
  inject: options.inject ?? []
1141
1784
  });
1142
1785
  }
@@ -1150,71 +1793,83 @@ var DurableModule = class _DurableModule {
1150
1793
  providers: [
1151
1794
  optionsProvider,
1152
1795
  {
1153
- provide: import_nestjs_durable_core9.STATE_STORE_CANONICAL,
1154
- useFactory: /* @__PURE__ */ __name((options) => options.store, "useFactory"),
1796
+ provide: import_nestjs_durable_core12.STATE_STORE_CANONICAL,
1797
+ useFactory: /* @__PURE__ */ __name((options) => options.store !== void 0 ? scopedStore(options.store, options) : null, "useFactory"),
1155
1798
  inject: [
1156
- import_nestjs_durable_core9.DURABLE_OPTIONS_CANONICAL
1799
+ import_nestjs_durable_core12.DURABLE_OPTIONS_CANONICAL
1157
1800
  ]
1158
1801
  },
1159
1802
  {
1160
- provide: import_nestjs_durable_core9.TRANSPORT_CANONICAL,
1803
+ provide: import_nestjs_durable_core12.TRANSPORT_CANONICAL,
1161
1804
  useFactory: /* @__PURE__ */ __name((options) => options.transport ?? null, "useFactory"),
1162
1805
  inject: [
1163
- import_nestjs_durable_core9.DURABLE_OPTIONS_CANONICAL
1806
+ import_nestjs_durable_core12.DURABLE_OPTIONS_CANONICAL
1164
1807
  ]
1165
1808
  },
1166
1809
  // Legacy back-compat aliases (deprecated tokens still resolve to the same instances):
1167
1810
  {
1168
- provide: import_nestjs_durable_core9.STATE_STORE,
1169
- useExisting: import_nestjs_durable_core9.STATE_STORE_CANONICAL
1811
+ provide: import_nestjs_durable_core12.STATE_STORE,
1812
+ useExisting: import_nestjs_durable_core12.STATE_STORE_CANONICAL
1170
1813
  },
1171
1814
  {
1172
- provide: import_nestjs_durable_core9.TRANSPORT,
1173
- useExisting: import_nestjs_durable_core9.TRANSPORT_CANONICAL
1815
+ provide: import_nestjs_durable_core12.TRANSPORT,
1816
+ useExisting: import_nestjs_durable_core12.TRANSPORT_CANONICAL
1174
1817
  },
1175
1818
  {
1176
- provide: import_nestjs_durable_core9.DURABLE_OPTIONS,
1177
- useExisting: import_nestjs_durable_core9.DURABLE_OPTIONS_CANONICAL
1819
+ provide: import_nestjs_durable_core12.DURABLE_OPTIONS,
1820
+ useExisting: import_nestjs_durable_core12.DURABLE_OPTIONS_CANONICAL
1178
1821
  },
1179
1822
  {
1180
- provide: import_nestjs_durable_core9.WorkflowEngine,
1181
- useFactory: /* @__PURE__ */ __name(async (store, transport, opts, moduleRef) => {
1182
- const primary = transport ?? opts.transports?.[0]?.transport;
1823
+ // Shared token, bound EXACTLY once: a real engine for the operator role, or a store-less
1824
+ // `DurableStartClient` facade for a thin worker (no `store`) — either way, `WorkflowService`
1825
+ // and app code call `engine.start(...)` unchanged.
1826
+ provide: import_nestjs_durable_core12.WorkflowEngine,
1827
+ useFactory: /* @__PURE__ */ __name(async (options, store, transport, moduleRef) => {
1828
+ if (options.store === void 0) {
1829
+ return new DurableStartClient(options);
1830
+ }
1831
+ if (!store) {
1832
+ throw new Error("unreachable: STATE_STORE_CANONICAL must resolve a store when options.store is set");
1833
+ }
1834
+ const primary = transport ?? options.transports?.[0]?.transport;
1183
1835
  const accessor = resolveAccessor(moduleRef);
1184
- const context = opts.context ?? (accessor ? () => carrierFromAccessor(accessor) : void 0);
1836
+ const context = options.context ?? (accessor ? () => carrierFromAccessor(accessor) : void 0);
1185
1837
  const runtime = accessor ? await resolveContextRuntime() : void 0;
1186
1838
  const rehydrate = runtime && ((carrier, fn) => carrier && Object.keys(carrier).length > 0 ? runtime.deserialize(carrier, fn) : fn());
1187
- const engine = new import_nestjs_durable_core9.WorkflowEngine({
1839
+ const engine = new import_nestjs_durable_core12.WorkflowEngine({
1188
1840
  store,
1189
1841
  transport: transport ?? void 0,
1190
- transports: opts.transports,
1191
- controlPlane: opts.controlPlane ?? (isControlPlane(primary) ? primary : void 0),
1192
- leaseMs: opts.leaseMs,
1193
- admission: opts.admission,
1194
- maxRecoveryAttempts: opts.maxRecoveryAttempts,
1195
- remoteAdvanceSilenceMs: opts.remoteAdvanceSilenceMs,
1196
- instanceId: opts.instanceId,
1197
- namespace: opts.namespace,
1198
- webhookUrl: opts.webhookUrl,
1199
- traceparent: opts.traceparent,
1842
+ transports: options.transports,
1843
+ controlPlane: options.controlPlane ?? (isControlPlane(primary) ? primary : void 0),
1844
+ leaseMs: options.leaseMs,
1845
+ admission: options.admission,
1846
+ maxRecoveryAttempts: options.maxRecoveryAttempts,
1847
+ remoteAdvanceSilenceMs: options.remoteAdvanceSilenceMs,
1848
+ instanceId: options.instanceId,
1849
+ namespace: options.namespace,
1850
+ webhookUrl: options.webhookUrl,
1851
+ traceparent: options.traceparent,
1200
1852
  context,
1201
1853
  rehydrate: rehydrate || void 0,
1202
- compensationRetries: opts.compensationRetries,
1203
- // A non-worker (API/dashboard) instance must not run workflows: enqueue-only, leaving
1204
- // each `pending` run in the store for a worker's `runPending` poll. Workers use the
1205
- // default in-process dispatcher (execute locally).
1206
- runDispatcher: opts.worker === false ? {
1854
+ compensationRetries: options.compensationRetries,
1855
+ // A non-driving (dashboard/API) operator must not run workflows: enqueue-only, leaving
1856
+ // each `pending` run in the store for a DRIVING instance's poll. A driving operator gets
1857
+ // the engine's default in-process dispatcher: for a body registered inline, it runs
1858
+ // locally; for one registered GROUP-SERVED (co-located worker) or left unregistered, the
1859
+ // SAME default dispatcher routes it out remotely (group-served executor, or convention
1860
+ // dispatch — always on) instead.
1861
+ runDispatcher: options.drive === false ? {
1207
1862
  dispatch: /* @__PURE__ */ __name(() => {
1208
1863
  }, "dispatch")
1209
1864
  } : void 0
1210
1865
  });
1211
- for (const queue of opts.queues ?? []) engine.registerQueue(queue);
1866
+ for (const queue of options.queues ?? []) engine.registerQueue(queue);
1212
1867
  return engine;
1213
1868
  }, "useFactory"),
1214
1869
  inject: [
1215
- import_nestjs_durable_core9.STATE_STORE_CANONICAL,
1216
- import_nestjs_durable_core9.TRANSPORT_CANONICAL,
1217
- import_nestjs_durable_core9.DURABLE_OPTIONS_CANONICAL,
1870
+ import_nestjs_durable_core12.DURABLE_OPTIONS_CANONICAL,
1871
+ import_nestjs_durable_core12.STATE_STORE_CANONICAL,
1872
+ import_nestjs_durable_core12.TRANSPORT_CANONICAL,
1218
1873
  import_core5.ModuleRef
1219
1874
  ]
1220
1875
  },
@@ -1224,54 +1879,83 @@ var DurableModule = class _DurableModule {
1224
1879
  DurableStepRegistrar,
1225
1880
  TimerPoller,
1226
1881
  RetentionPoller,
1227
- // In-app worker (uniform dispatch, opt-in): inert when `inAppWorker` is unset — the binding
1228
- // resolves to null and the bootstrap no-ops, so a plain DurableModule is unchanged.
1229
- ...inAppWorkerProviders()
1882
+ // Tenant run gateway: bound EXACTLY once — the store-backed `StoreRunGateway` for an operator,
1883
+ // or (for a thin worker, no `store`) a `ProxyRunGateway` over `transport` when given, else a
1884
+ // gateway whose every method rejects with a clear tenant error.
1885
+ {
1886
+ provide: RUN_GATEWAY,
1887
+ useFactory: /* @__PURE__ */ __name((options, store, engine) => {
1888
+ if (options.store !== void 0) {
1889
+ if (!store) {
1890
+ throw new Error("unreachable: STATE_STORE_CANONICAL must resolve a store when options.store is set");
1891
+ }
1892
+ return new StoreRunGateway(store, engine);
1893
+ }
1894
+ return options.transport ? new ProxyRunGateway(options.transport, options.partition ?? "default", options.runGatewayTimeoutMs) : unavailableRunGateway();
1895
+ }, "useFactory"),
1896
+ inject: [
1897
+ import_nestjs_durable_core12.DURABLE_OPTIONS_CANONICAL,
1898
+ import_nestjs_durable_core12.STATE_STORE_CANONICAL,
1899
+ import_nestjs_durable_core12.WorkflowEngine
1900
+ ]
1901
+ },
1902
+ RunGatewayBootstrap,
1903
+ // Co-located in-app worker (uniform dispatch): inert unless BOTH `store` and `connection` are
1904
+ // set — see `in-app-worker.ts`.
1905
+ ...inAppWorkerProviders(),
1906
+ // Pure thin-worker consumer: inert unless `connection` is set WITHOUT `store` — see
1907
+ // `durable-worker.module.ts`.
1908
+ ...thinWorkerProviders()
1230
1909
  ],
1231
1910
  exports: [
1232
1911
  WorkflowService,
1233
1912
  EntityService,
1234
- import_nestjs_durable_core9.WorkflowEngine,
1235
- import_nestjs_durable_core9.STATE_STORE,
1236
- import_nestjs_durable_core9.STATE_STORE_CANONICAL,
1237
- import_nestjs_durable_core9.TRANSPORT,
1238
- import_nestjs_durable_core9.TRANSPORT_CANONICAL,
1239
- import_nestjs_durable_core9.DURABLE_OPTIONS_CANONICAL
1913
+ import_nestjs_durable_core12.WorkflowEngine,
1914
+ import_nestjs_durable_core12.STATE_STORE,
1915
+ import_nestjs_durable_core12.STATE_STORE_CANONICAL,
1916
+ import_nestjs_durable_core12.TRANSPORT,
1917
+ import_nestjs_durable_core12.TRANSPORT_CANONICAL,
1918
+ import_nestjs_durable_core12.DURABLE_OPTIONS_CANONICAL,
1919
+ RUN_GATEWAY
1240
1920
  ]
1241
1921
  };
1242
1922
  }
1243
1923
  };
1244
- DurableModule = _ts_decorate9([
1245
- (0, import_common9.Module)({})
1924
+ DurableModule = _ts_decorate12([
1925
+ (0, import_common12.Module)({})
1246
1926
  ], DurableModule);
1247
1927
  // Annotate the CommonJS export names for ESM import in node:
1248
1928
  0 && (module.exports = {
1249
1929
  CONTEXT_ACCESSOR,
1250
1930
  DEAD_LETTER_METADATA,
1251
1931
  DURABLE_STEP_METADATA,
1252
- DURABLE_WORKER_OPTIONS,
1253
1932
  DURABLE_WORKER_RUNNERS,
1254
1933
  DeadLetter,
1255
1934
  DurableModule,
1935
+ DurableStartClient,
1256
1936
  DurableStep,
1257
- DurableWorkerModule,
1258
1937
  ENTITY_METADATA,
1259
1938
  ENTITY_ON_METADATA,
1260
1939
  Entity,
1261
1940
  EntityService,
1262
1941
  IN_APP_RUN_REDIS_WORKER,
1263
1942
  IN_APP_WORKER_BINDING,
1264
- IN_APP_WORKER_OPTIONS,
1265
1943
  IN_APP_WORKER_RUNNERS,
1266
1944
  IN_APP_WORKER_RUNTIME,
1267
1945
  InAppWorkerBootstrap,
1268
1946
  ON_EVENT_METADATA,
1269
1947
  On,
1948
+ OnDurableEvent,
1270
1949
  OnEvent,
1950
+ ProxyRunGateway,
1951
+ RUN_GATEWAY,
1271
1952
  RUN_REDIS_WORKER,
1953
+ RunRequestResponder,
1272
1954
  STEP_INTERCEPTOR_METADATA,
1273
1955
  Step,
1274
1956
  StepInterceptor,
1957
+ StoreRunGateway,
1958
+ TenantEventRepublisher,
1275
1959
  ThinStepRegistrar,
1276
1960
  ThinWorkerBootstrap,
1277
1961
  ThinWorkflowRegistrar,
@@ -1285,6 +1969,10 @@ DurableModule = _ts_decorate9([
1285
1969
  getWorkflowMeta,
1286
1970
  inAppWorkerProviders,
1287
1971
  isDeadLetterHandler,
1288
- isStepInterceptor
1972
+ isDrivingOperator,
1973
+ isOperatorRole,
1974
+ isStepInterceptor,
1975
+ thinWorkerProviders,
1976
+ unavailableRunGateway
1289
1977
  });
1290
1978
  //# sourceMappingURL=index.cjs.map