@adonis-agora/durable 0.2.0 → 0.4.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/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @adonis-agora/durable
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`d2591d0`](https://github.com/DavideCarvalho/adonis-durable/commit/d2591d0040bafb2301b41250e91a5d2961d9ad13) - Automatic cross-process context propagation + `app/workflows` auto-discovery and `make:workflow`.
8
+
9
+ - The full Agora request context (userRef / tenant / traceId) now rides each remote task automatically and is restored on the worker before the step handler runs — `ctx.call(remoteStep, input)` sees the originating request's context with zero manual serialize/deserialize. Best-effort, no-op when `@adonis-agora/context` is not installed.
10
+ - New class-based authoring convention mirroring `@adonisjs/queue`'s `app/jobs`: a `@Workflow` class per file under `app/workflows/` is auto-registered on the engine at boot (configurable via `workflowsPath`, opt-out with `false`), plus a `node ace make:workflow <name>` scaffold. `engine.register(name, version, fn)` remains the low-level escape hatch.
11
+
12
+ - [`6c31452`](https://github.com/DavideCarvalho/adonis-durable/commit/6c31452f14789fa98f20ea5f6164f421d76fc2df) - Scoped automatic cross-process context restore (was a no-op on db/queue workers); recursive workflow discovery; single-extension import.
13
+
14
+ - Workers now restore the originating request's context by running each step handler INSIDE an active context store seeded from the task snapshot, via the new `Symbol.for('@agora/context:scope')` slot. The previous `@agora/context:set` path only populated an already-active store, so restore was inert on the db/queue workers (no active scope) — automatic propagation now actually works, and each task runs in its own scope (no cross-task bleed on a long-lived worker). Clean no-op when `@adonis-agora/context` is not installed.
15
+ - The dispatch carrier is passed through opaquely (`context: () => accessor.get()`) instead of merging structured `userRef`/`tenantId`/`traceId` into it — the scope slot round-trips the whole snapshot, so the producer-owned carrier stays shape-opaque.
16
+ - `app/workflows` discovery is now recursive, so nested `app/workflows/billing/charge_workflow.ts` is found (matching `make:workflow`'s nested-path scaffolding). Only the environment-appropriate module extension is imported, so a built app (`.js`) and a dev app (`.ts`) never double-register the same workflow.
17
+
18
+ ## 0.3.0
19
+
20
+ ### Minor Changes
21
+
22
+ - [`6b47d1a`](https://github.com/DavideCarvalho/adonis-durable/commit/6b47d1a7d0bc6f76e5b6ebe704c3ea8cfe025d53) - Require AdonisJS v7 (bump @adonisjs/\* peers; Lucid 22, Queue 0.6)
23
+
3
24
  ## 0.2.0
4
25
 
5
26
  ### Minor Changes
@@ -1,4 +1,5 @@
1
1
  import { ListLoader } from '@adonisjs/core/ace';
2
+ import MakeWorkflow from './make_workflow.js';
2
3
  import DurableRetry from './retry.js';
3
4
  import DurableRuns from './runs.js';
4
5
  import DurableWork from './work.js';
@@ -8,8 +9,8 @@ import DurableWork from './work.js';
8
9
  * kernel imports this module and treats it as a commands loader: a {@link ListLoader} over the three
9
10
  * durable commands provides their metadata and constructors.
10
11
  */
11
- declare const loader: ListLoader<typeof DurableRetry | typeof DurableRuns | typeof DurableWork>;
12
+ declare const loader: ListLoader<typeof MakeWorkflow | typeof DurableRetry | typeof DurableRuns | typeof DurableWork>;
12
13
  export declare const getMetaData: () => Promise<import("@adonisjs/core/types/ace").CommandMetaData[]>;
13
- export declare const getCommand: (metaData: import("@adonisjs/core/types/ace").CommandMetaData) => Promise<typeof DurableRetry | typeof DurableRuns | typeof DurableWork | null>;
14
+ export declare const getCommand: (metaData: import("@adonisjs/core/types/ace").CommandMetaData) => Promise<typeof MakeWorkflow | typeof DurableRetry | typeof DurableRuns | typeof DurableWork | null>;
14
15
  export default loader;
15
16
  //# sourceMappingURL=main.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../commands/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,YAAY,MAAM,YAAY,CAAC;AACtC,OAAO,WAAW,MAAM,WAAW,CAAC;AACpC,OAAO,WAAW,MAAM,WAAW,CAAC;AAEpC;;;;;GAKG;AACH,QAAA,MAAM,MAAM,2EAA2D,CAAC;AAExE,eAAO,MAAM,WAAW,qEAAkC,CAAC;AAC3D,eAAO,MAAM,UAAU,iJAAiC,CAAC;AAEzD,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../commands/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,YAAY,MAAM,oBAAoB,CAAC;AAC9C,OAAO,YAAY,MAAM,YAAY,CAAC;AACtC,OAAO,WAAW,MAAM,WAAW,CAAC;AACpC,OAAO,WAAW,MAAM,WAAW,CAAC;AAEpC;;;;;GAKG;AACH,QAAA,MAAM,MAAM,iGAAyE,CAAC;AAEtF,eAAO,MAAM,WAAW,qEAAkC,CAAC;AAC3D,eAAO,MAAM,UAAU,uKAAiC,CAAC;AAEzD,eAAe,MAAM,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { ListLoader } from '@adonisjs/core/ace';
2
+ import MakeWorkflow from './make_workflow.js';
2
3
  import DurableRetry from './retry.js';
3
4
  import DurableRuns from './runs.js';
4
5
  import DurableWork from './work.js';
@@ -8,7 +9,7 @@ import DurableWork from './work.js';
8
9
  * kernel imports this module and treats it as a commands loader: a {@link ListLoader} over the three
9
10
  * durable commands provides their metadata and constructors.
10
11
  */
11
- const loader = new ListLoader([DurableWork, DurableRuns, DurableRetry]);
12
+ const loader = new ListLoader([DurableWork, DurableRuns, DurableRetry, MakeWorkflow]);
12
13
  export const getMetaData = loader.getMetaData.bind(loader);
13
14
  export const getCommand = loader.getCommand.bind(loader);
14
15
  export default loader;
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../../commands/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,YAAY,MAAM,YAAY,CAAC;AACtC,OAAO,WAAW,MAAM,WAAW,CAAC;AACpC,OAAO,WAAW,MAAM,WAAW,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC;AAExE,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC3D,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAEzD,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../commands/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,YAAY,MAAM,oBAAoB,CAAC;AAC9C,OAAO,YAAY,MAAM,YAAY,CAAC;AACtC,OAAO,WAAW,MAAM,WAAW,CAAC;AACpC,OAAO,WAAW,MAAM,WAAW,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC;AAEtF,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC3D,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAEzD,eAAe,MAAM,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { BaseCommand } from '@adonisjs/core/ace';
2
+ import type { CommandOptions } from '@adonisjs/core/types/ace';
3
+ /**
4
+ * `node ace make:workflow <name>` — scaffold a durable workflow class under `app/workflows/`, the
5
+ * parallel to `@adonisjs/queue`'s `make:job` (which scaffolds `app/jobs/`). The generated class is
6
+ * `@Workflow`-decorated with a `run(ctx, input)` method and is auto-registered on the engine at boot
7
+ * by the durable provider — no manual `engine.register(...)`.
8
+ */
9
+ export default class MakeWorkflow extends BaseCommand {
10
+ static commandName: string;
11
+ static description: string;
12
+ static options: CommandOptions;
13
+ name: string;
14
+ run(): Promise<void>;
15
+ }
16
+ //# sourceMappingURL=make_workflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"make_workflow.d.ts","sourceRoot":"","sources":["../../commands/make_workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAQ,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG/D;;;;;GAKG;AACH,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,WAAW;IACnD,OAAgB,WAAW,SAAmB;IAC9C,OAAgB,WAAW,SAAyC;IACpE,OAAgB,OAAO,EAAE,cAAc,CAA+B;IAG9D,IAAI,EAAE,MAAM,CAAC;IAEN,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAOpC"}
@@ -0,0 +1,30 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { BaseCommand, args } from '@adonisjs/core/ace';
8
+ import { stubsRoot } from '../stubs/main.js';
9
+ /**
10
+ * `node ace make:workflow <name>` — scaffold a durable workflow class under `app/workflows/`, the
11
+ * parallel to `@adonisjs/queue`'s `make:job` (which scaffolds `app/jobs/`). The generated class is
12
+ * `@Workflow`-decorated with a `run(ctx, input)` method and is auto-registered on the engine at boot
13
+ * by the durable provider — no manual `engine.register(...)`.
14
+ */
15
+ export default class MakeWorkflow extends BaseCommand {
16
+ static commandName = 'make:workflow';
17
+ static description = 'Create a new durable workflow class';
18
+ static options = { allowUnknownFlags: true };
19
+ async run() {
20
+ const codemods = await this.createCodemods();
21
+ await codemods.makeUsingStub(stubsRoot, 'make/workflow/main.stub', {
22
+ flags: this.parsed.flags,
23
+ entity: this.app.generators.createEntity(this.name),
24
+ });
25
+ }
26
+ }
27
+ __decorate([
28
+ args.string({ description: 'Name of the workflow' })
29
+ ], MakeWorkflow.prototype, "name", void 0);
30
+ //# sourceMappingURL=make_workflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"make_workflow.js","sourceRoot":"","sources":["../../commands/make_workflow.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,WAAW;IACnD,MAAM,CAAU,WAAW,GAAG,eAAe,CAAC;IAC9C,MAAM,CAAU,WAAW,GAAG,qCAAqC,CAAC;IACpE,MAAM,CAAU,OAAO,GAAmB,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC;IAK7D,KAAK,CAAC,GAAG;QAChB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAC7C,MAAM,QAAQ,CAAC,aAAa,CAAC,SAAS,EAAE,yBAAyB,EAAE;YACjE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK;YACxB,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;SACpD,CAAC,CAAC;IACL,CAAC;;AARO;IADP,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,sBAAsB,EAAE,CAAC;0CAChC"}
@@ -23,6 +23,14 @@ export default class DurableProvider {
23
23
  protected app: ApplicationService;
24
24
  constructor(app: ApplicationService);
25
25
  register(): void;
26
+ /**
27
+ * Auto-register the `app/workflows` convention: scan the configured directory for
28
+ * `@Workflow`-decorated classes and register each on the engine — so users never call
29
+ * `engine.register(...)` by hand (mirrors `@adonisjs/queue`'s `app/jobs`). Opt-out with
30
+ * `config.workflowsPath = false`; a missing directory is a no-op. The low-level
31
+ * `engine.register(name, version, fn)` remains the escape hatch.
32
+ */
33
+ boot(): Promise<void>;
26
34
  /**
27
35
  * Once everything is booted, bridge engine lifecycle events onto the `@adonis-agora/diagnostics` bus —
28
36
  * but only when diagnostics is actually installed (its emit slot is populated at module load).
@@ -1 +1 @@
1
- {"version":3,"file":"durable_provider.d.ts","sourceRoot":"","sources":["../../providers/durable_provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAkC/D;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,OAAO,OAAO,eAAe;;IAKtB,SAAS,CAAC,GAAG,EAAE,kBAAkB;gBAAvB,GAAG,EAAE,kBAAkB;IAE7C,QAAQ;IAkFR;;;;;;OAMG;IACG,KAAK;IAOL,QAAQ;CAUf"}
1
+ {"version":3,"file":"durable_provider.d.ts","sourceRoot":"","sources":["../../providers/durable_provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAkC/D;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,OAAO,OAAO,eAAe;;IAKtB,SAAS,CAAC,GAAG,EAAE,kBAAkB;gBAAvB,GAAG,EAAE,kBAAkB;IAE7C,QAAQ;IA4CR;;;;;;OAMG;IACG,IAAI;IAgDV;;;;;;OAMG;IACG,KAAK;IAOL,QAAQ;CAUf"}
@@ -1,4 +1,4 @@
1
- import { InMemoryStateStore, InMemoryTransport, WorkflowEngine, attachDurableDiagnostics, } from '../src/index.js';
1
+ import { InMemoryStateStore, InMemoryTransport, WorkflowEngine, attachDurableDiagnostics, registerWorkflowsFromDir, } from '../src/index.js';
2
2
  const CONTEXT_ACCESSOR = Symbol.for('@agora/context:accessor');
3
3
  /**
4
4
  * Global slot `@adonis-agora/diagnostics-otel` publishes its `otelTraceparent` under: a
@@ -62,7 +62,9 @@ export default class DurableProvider {
62
62
  ? { compensationRetries: config.compensationRetries }
63
63
  : {}),
64
64
  ...(config.runDispatcher ? { runDispatcher: config.runDispatcher } : {}),
65
- // Best-effort context propagation from @adonis-agora/context (no hard dep).
65
+ // Best-effort context propagation from @adonis-agora/context (no hard dep): pass the opaque
66
+ // carrier through verbatim. The carrier is producer-owned and shape-opaque; the worker's
67
+ // scope slot round-trips the whole snapshot via Context.run, so no field-picking is needed.
66
68
  ...(accessor ? { context: () => accessor.get() } : {}),
67
69
  // Best-effort OTel trace continuation from @adonis-agora/diagnostics-otel (no hard dep).
68
70
  ...(otelTraceparent ? { traceparent: otelTraceparent } : {}),
@@ -70,6 +72,21 @@ export default class DurableProvider {
70
72
  return new WorkflowEngine(deps);
71
73
  });
72
74
  }
75
+ /**
76
+ * Auto-register the `app/workflows` convention: scan the configured directory for
77
+ * `@Workflow`-decorated classes and register each on the engine — so users never call
78
+ * `engine.register(...)` by hand (mirrors `@adonisjs/queue`'s `app/jobs`). Opt-out with
79
+ * `config.workflowsPath = false`; a missing directory is a no-op. The low-level
80
+ * `engine.register(name, version, fn)` remains the escape hatch.
81
+ */
82
+ async boot() {
83
+ const config = this.app.config.get('durable', {});
84
+ if (config.workflowsPath === false)
85
+ return;
86
+ const dir = this.app.makePath(config.workflowsPath ?? 'app/workflows');
87
+ const engine = await this.app.container.make(WorkflowEngine);
88
+ await registerWorkflowsFromDir(engine, dir);
89
+ }
73
90
  /** Resolve the configured state store (a key of `config.stores`), or the in-memory default. */
74
91
  async #resolveStore(config, ctx) {
75
92
  const name = config.store;
@@ -1 +1 @@
1
- {"version":3,"file":"durable_provider.js","sourceRoot":"","sources":["../../providers/durable_provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"durable_provider.js","sourceRoot":"","sources":["../../providers/durable_provider.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,kBAAkB,EAClB,iBAAiB,EAKjB,cAAc,EAEd,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,iBAAiB,CAAC;AAMzB,MAAM,gBAAgB,GAAG,MAAM,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,gBAAgB,GAAG,MAAM,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAE/D,6GAA6G;AAC7G,MAAM,gBAAgB,GAAG,MAAM,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAE/D;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,OAAO,OAAO,eAAe;IAKZ;IAJtB,kBAAkB,GAAwB,IAAI,CAAC;IAC/C,UAAU,GAAyD,IAAI,CAAC;IACxE,aAAa,GAA4D,IAAI,CAAC;IAE9E,YAAsB,GAAuB;QAAvB,QAAG,GAAH,GAAG,CAAoB;IAAG,CAAC;IAEjD,QAAQ;QACN,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,cAAc,EAAE,KAAK,IAAI,EAAE;YACtD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAgB,SAAS,EAAE,EAAE,CAAC,CAAC;YACjE,MAAM,QAAQ,GAAI,UAAsC,CAAC,gBAAgB,CAE5D,CAAC;YACd,MAAM,eAAe,GAAI,UAAsC,CAAC,gBAAgB,CAEnE,CAAC;YAEd,MAAM,GAAG,GAA0D,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;YACrF,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YACpD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAC5D,qFAAqF;YACrF,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;YAC5B,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAClE,0FAA0F;YAC1F,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;YAElC,MAAM,IAAI,GAAuB;gBAC/B,KAAK;gBACL,SAAS;gBACT,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzC,GAAG,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpE,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/D,GAAG,CAAC,MAAM,CAAC,mBAAmB,KAAK,SAAS;oBAC1C,CAAC,CAAC,EAAE,mBAAmB,EAAE,MAAM,CAAC,mBAAmB,EAAE;oBACrD,CAAC,CAAC,EAAE,CAAC;gBACP,GAAG,CAAC,MAAM,CAAC,mBAAmB,KAAK,SAAS;oBAC1C,CAAC,CAAC,EAAE,mBAAmB,EAAE,MAAM,CAAC,mBAAmB,EAAE;oBACrD,CAAC,CAAC,EAAE,CAAC;gBACP,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxE,4FAA4F;gBAC5F,yFAAyF;gBACzF,4FAA4F;gBAC5F,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtD,yFAAyF;gBACzF,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC7D,CAAC;YAEF,OAAO,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,IAAI;QACR,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAgB,SAAS,EAAE,EAAE,CAAC,CAAC;QACjE,IAAI,MAAM,CAAC,aAAa,KAAK,KAAK;YAAE,OAAO;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,aAAa,IAAI,eAAe,CAAC,CAAC;QACvE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC7D,MAAM,wBAAwB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9C,CAAC;IAED,+FAA+F;IAC/F,KAAK,CAAC,aAAa,CAAC,MAAqB,EAAE,GAAiB;QAC1D,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,kBAAkB,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,oCAAoC,IAAI,wBAAwB,IAAI,iBAAiB,CACtF,CAAC;QACJ,CAAC;QACD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IAED,iGAAiG;IACjG,KAAK,CAAC,iBAAiB,CAAC,MAAqB,EAAE,GAAqB;QAClE,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC;QAC9B,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,iBAAiB,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,wCAAwC,IAAI,4BAA4B,IAAI,iBAAiB,CAC9F,CAAC;QACJ,CAAC;QACD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,oBAAoB,CACxB,MAAqB,EACrB,GAAwB;QAExB,MAAM,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC;QAC/B,IAAI,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QACrB,OAAO,OAAO,EAAE,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACjD,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,GAAI,UAAsC,CAAC,gBAAgB,CAAC,CAAC;QACvE,IAAI,OAAO,IAAI,KAAK,UAAU;YAAE,OAAO;QACvC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC7D,IAAI,CAAC,kBAAkB,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAC7D,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC,kBAAkB,EAAE,EAAE,CAAC;QAC5B,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAC/B,+FAA+F;QAC/F,MAAM,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE,CAAC;QACjC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,sFAAsF;QACtF,MAAM,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,EAAE,CAAC;QACpC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;IAC5B,CAAC;CACF"}
@@ -71,6 +71,13 @@ export interface DurableConfig {
71
71
  * `cron-parser` peer dependency. Omit (or leave empty) to register no schedules.
72
72
  */
73
73
  schedules?: ScheduledWorkflow[];
74
+ /**
75
+ * Directory (relative to the app root) the provider scans at boot for `@Workflow`-decorated classes
76
+ * to auto-register on the engine — the `app/workflows` convention, mirroring `@adonisjs/queue`'s
77
+ * `app/jobs`. Default `'app/workflows'`. Set `false` to disable discovery entirely (register by
78
+ * hand with `engine.register(...)`). A missing directory is fine — nothing to register.
79
+ */
80
+ workflowsPath?: string | false;
74
81
  }
75
82
  /** Identity helper giving `config/durable.ts` full type-checking. */
76
83
  export declare function defineConfig(config?: DurableConfig): DurableConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"define_config.d.ts","sourceRoot":"","sources":["../../src/define_config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,KAAK,EACV,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC9C;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACtC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,YAAY,GAAG,mBAAmB,CAAC;IAClD,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yFAAyF;IACzF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,gEAAgE;IAChE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,gFAAgF;IAChF,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAC;CACjC;AAED,qEAAqE;AACrE,wBAAgB,YAAY,CAAC,MAAM,GAAE,aAAkB,GAAG,aAAa,CAEtE;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;AAC7C,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,GACxB,CAAC"}
1
+ {"version":3,"file":"define_config.d.ts","sourceRoot":"","sources":["../../src/define_config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,KAAK,EACV,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC9C;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACtC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,YAAY,GAAG,mBAAmB,CAAC;IAClD,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yFAAyF;IACzF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,gEAAgE;IAChE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,gFAAgF;IAChF,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAChC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAChC;AAED,qEAAqE;AACrE,wBAAgB,YAAY,CAAC,MAAM,GAAE,aAAkB,GAAG,aAAa,CAEtE;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;AAC7C,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,GACxB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"define_config.js","sourceRoot":"","sources":["../../src/define_config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAQ5D,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AA4ErD,qEAAqE;AACrE,MAAM,UAAU,YAAY,CAAC,SAAwB,EAAE;IACrD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"define_config.js","sourceRoot":"","sources":["../../src/define_config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAQ5D,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAmFrD,qEAAqE;AACrE,MAAM,UAAU,YAAY,CAAC,SAAwB,EAAE;IACrD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC"}
@@ -20,6 +20,7 @@ export * from './scheduler.js';
20
20
  export * from './search-attributes.js';
21
21
  export * from './tokens.js';
22
22
  export * from './workflow-ref.js';
23
+ export * from './workflow-discovery.js';
23
24
  export { InMemoryStateStore } from './testing/in-memory-state-store.js';
24
25
  export { InMemoryTransport } from './testing/in-memory-transport.js';
25
26
  export { transports } from './transports/factory.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,eAAO,MAAM,OAAO,UAAU,CAAC;AAG/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAGrE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EACL,gBAAgB,EAChB,4BAA4B,EAC5B,0BAA0B,GAC3B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGlG,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,YAAY,EACV,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,WAAW,GACjB,MAAM,8CAA8C,CAAC;AAGtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,eAAO,MAAM,OAAO,UAAU,CAAC;AAG/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAGrE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EACL,gBAAgB,EAChB,4BAA4B,EAC5B,0BAA0B,GAC3B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGlG,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,YAAY,EACV,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,WAAW,GACjB,MAAM,8CAA8C,CAAC;AAGtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/src/index.js CHANGED
@@ -21,6 +21,7 @@ export * from './scheduler.js';
21
21
  export * from './search-attributes.js';
22
22
  export * from './tokens.js';
23
23
  export * from './workflow-ref.js';
24
+ export * from './workflow-discovery.js';
24
25
  export { InMemoryStateStore } from './testing/in-memory-state-store.js';
25
26
  export { InMemoryTransport } from './testing/in-memory-transport.js';
26
27
  // --- config-driven transport drivers ----------------------------------------
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,+EAA+E;AAC/E,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAErE,+EAA+E;AAC/E,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAQrD,OAAO,EAAE,cAAc,EAA8B,MAAM,uBAAuB,CAAC;AACnF,OAAO,EAAE,WAAW,EAA2B,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EACL,gBAAgB,EAChB,4BAA4B,EAC5B,0BAA0B,GAC3B,MAAM,2BAA2B,CAAC;AAEnC,+EAA+E;AAC/E,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,eAAe,EAA+B,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElG,+EAA+E;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAM5D,OAAO,EACL,iBAAiB,GAGlB,MAAM,8CAA8C,CAAC;AAEtD,+EAA+E;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,+EAA+E;AAC/E,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAErE,+EAA+E;AAC/E,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAQrD,OAAO,EAAE,cAAc,EAA8B,MAAM,uBAAuB,CAAC;AACnF,OAAO,EAAE,WAAW,EAA2B,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EACL,gBAAgB,EAChB,4BAA4B,EAC5B,0BAA0B,GAC3B,MAAM,2BAA2B,CAAC;AAEnC,+EAA+E;AAC/E,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,eAAe,EAA+B,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElG,+EAA+E;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAM5D,OAAO,EACL,iBAAiB,GAGlB,MAAM,8CAA8C,CAAC;AAEtD,+EAA+E;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAa,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGrF;oGACoG;AACpG,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;6FAC6F;AAC7F,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,EAAE,KAAK,MAAM,KAAG,MAA8B,CAAC;AAE5F;kGACkG;AAClG,MAAM,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;AAE1F;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,WAAW,GAAG,SAAS,GAC/B,OAAO,CAAC,UAAU,CAAC,CA+BrB"}
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAa,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAgCrF;oGACoG;AACpG,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;6FAC6F;AAC7F,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,EAAE,KAAK,MAAM,KAAG,MAA8B,CAAC;AAE5F;kGACkG;AAClG,MAAM,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;AAE1F;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,WAAW,GAAG,SAAS,GAC/B,OAAO,CAAC,UAAU,CAAC,CAqCrB"}
@@ -1,4 +1,30 @@
1
1
  import { createStepLogger } from './step-logger.js';
2
+ /**
3
+ * The scoped-restore slot `@adonis-agora/context` exposes:
4
+ * `<T>(snapshot: Record<string, unknown> | undefined, fn: () => T) => T`. It runs `fn` INSIDE a
5
+ * freshly-activated context store seeded from `snapshot` (or just `fn()` when snapshot/slot is
6
+ * absent). Read structurally so a worker restores the originating request's userRef/tenant/traceId
7
+ * around a step handler with zero config when context is installed — and a clean no-op (`fn()`) when
8
+ * it is not. Wrapping (rather than the old `:set`, which only populates an already-active store) gives
9
+ * both correct propagation AND per-task isolation on a long-lived worker: each task runs in its own
10
+ * scope, so context never bleeds between tasks. The key is a global-registry symbol so it survives
11
+ * duplicate copies of either package in a dependency tree.
12
+ */
13
+ const CONTEXT_SCOPE = Symbol.for('@agora/context:scope');
14
+ /**
15
+ * Run `fn` inside the originating request's context (userRef/tenant/traceId), restored from the
16
+ * task's snapshot (stamped at dispatch by the originating engine, see {@link RemoteTask.context}),
17
+ * so a step handler sees it with no manual code. When `@adonis-agora/context` is not installed (slot
18
+ * absent) the body runs directly — a clean no-op fallback. Never throws from the propagation path: a
19
+ * non-function slot is ignored; errors inside `fn` propagate as the step's own failure (the scope
20
+ * helper itself re-throws nothing of its own).
21
+ */
22
+ function withRestoredContext(snapshot, fn) {
23
+ const scope = globalThis[CONTEXT_SCOPE];
24
+ if (typeof scope !== 'function')
25
+ return fn();
26
+ return scope(snapshot, fn);
27
+ }
2
28
  /** Canonical step id — the stable identity of a step within a run, used for dedupe and
3
29
  * correlation. The format is part of the cross-language wire contract (Python builds the same). */
4
30
  export function stepId(runId, seq) {
@@ -25,23 +51,29 @@ export async function runStepHandler(task, handler) {
25
51
  }
26
52
  const events = [];
27
53
  const withEvents = (result) => events.length > 0 ? { ...result, events } : result;
28
- try {
29
- const output = await handler(task.input, createStepLogger(events, Date.now));
30
- return withEvents({ ...base, status: 'completed', output });
31
- }
32
- catch (err) {
33
- // Carry `code`/`retryable` off the thrown error if present, so the engine's durable retry can
34
- // honour a worker's "don't retry this" verdict (e.g. a declined card).
35
- const e = err;
36
- return withEvents({
37
- ...base,
38
- status: 'failed',
39
- error: {
40
- message: err instanceof Error ? err.message : String(err),
41
- ...(typeof e?.code === 'string' ? { code: e.code } : {}),
42
- ...(typeof e?.retryable === 'boolean' ? { retryable: e.retryable } : {}),
43
- },
44
- });
45
- }
54
+ // Run the handler INSIDE the originating request's context (userRef/tenant/traceId), restored from
55
+ // the task snapshot, so cross-process propagation is automatic — `ctx.call(remoteStep, input)`
56
+ // carries the caller's context with zero manual serialize/deserialize, and each task runs in its
57
+ // own scope (no cross-task bleed on a long-lived worker). No-op without `@adonis-agora/context`.
58
+ return withRestoredContext(task.context, async () => {
59
+ try {
60
+ const output = await handler(task.input, createStepLogger(events, Date.now));
61
+ return withEvents({ ...base, status: 'completed', output });
62
+ }
63
+ catch (err) {
64
+ // Carry `code`/`retryable` off the thrown error if present, so the engine's durable retry can
65
+ // honour a worker's "don't retry this" verdict (e.g. a declined card).
66
+ const e = err;
67
+ return withEvents({
68
+ ...base,
69
+ status: 'failed',
70
+ error: {
71
+ message: err instanceof Error ? err.message : String(err),
72
+ ...(typeof e?.code === 'string' ? { code: e.code } : {}),
73
+ ...(typeof e?.retryable === 'boolean' ? { retryable: e.retryable } : {}),
74
+ },
75
+ });
76
+ }
77
+ });
46
78
  }
47
79
  //# sourceMappingURL=protocol.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/protocol.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD;oGACoG;AACpG,MAAM,UAAU,MAAM,CAAC,KAAa,EAAE,GAAW;IAC/C,OAAO,GAAG,KAAK,IAAI,GAAG,EAAE,CAAC;AAC3B,CAAC;AAED;6FAC6F;AAC7F,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,KAAa,EAAE,GAAW,EAAU,EAAE,CAAC,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;AAM5F;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAgB,EAChB,OAAgC;IAEhC,+FAA+F;IAC/F,8FAA8F;IAC9F,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IAC9F,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE,EAAE,OAAO,EAAE,kBAAkB,IAAI,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE;SACpE,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,CAAC,MAAkB,EAAc,EAAE,CACpD,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACrD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7E,OAAO,UAAU,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;IAC9D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,8FAA8F;QAC9F,uEAAuE;QACvE,MAAM,CAAC,GAAG,GAA+D,CAAC;QAC1E,OAAO,UAAU,CAAC;YAChB,GAAG,IAAI;YACP,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE;gBACL,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;gBACzD,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxD,GAAG,CAAC,OAAO,CAAC,EAAE,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACzE;SACF,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { WorkflowEngine } from './engine.js';
2
+ import { type WorkflowClass, type WorkflowMeta } from './workflow-ref.js';
3
+ /** A discovered, decorated workflow class plus the metadata its `@Workflow` decorator stamped. */
4
+ export interface DiscoveredWorkflow {
5
+ meta: WorkflowMeta;
6
+ cls: WorkflowClass;
7
+ }
8
+ /**
9
+ * Register a single `@Workflow`-decorated class on the engine: instantiate it once and bind its
10
+ * `run(ctx, input)` as the workflow body via `engine.register`. The low-level
11
+ * `engine.register(name, version, fn)` stays the escape hatch — this is the convenience the
12
+ * `app/workflows` convention builds on. No-op (returns `false`) for an undecorated class.
13
+ */
14
+ export declare function registerWorkflowClass(engine: WorkflowEngine, cls: unknown): boolean;
15
+ /**
16
+ * Scan a directory RECURSIVELY for modules and collect every exported `@Workflow`-decorated class
17
+ * (the default export and any named export are considered) — so nested conventions like
18
+ * `app/workflows/billing/charge_workflow.ts` are found, matching `make:workflow`'s nested-path
19
+ * scaffolding. Only the environment-appropriate extension is imported (see {@link MODULE_EXT}), and
20
+ * each module path is visited once, so a built `.js` and a dev `.ts` of the same module never both
21
+ * register. Missing directory → empty list (the convention is opt-in: no `app/workflows`, nothing to
22
+ * register).
23
+ */
24
+ export declare function discoverWorkflows(dir: string): Promise<DiscoveredWorkflow[]>;
25
+ /**
26
+ * Discover every `@Workflow` class under `dir` and register each on the engine. Returns the
27
+ * registered metadata so the caller can log what was wired. Best-effort over a missing directory.
28
+ */
29
+ export declare function registerWorkflowsFromDir(engine: WorkflowEngine, dir: string): Promise<WorkflowMeta[]>;
30
+ //# sourceMappingURL=workflow-discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow-discovery.d.ts","sourceRoot":"","sources":["../../src/workflow-discovery.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAgB,MAAM,mBAAmB,CAAC;AAExF,kGAAkG;AAClG,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,YAAY,CAAC;IACnB,GAAG,EAAE,aAAa,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAgBnF;AAUD;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAuBlF;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,YAAY,EAAE,CAAC,CAIzB"}
@@ -0,0 +1,78 @@
1
+ import { readdir } from 'node:fs/promises';
2
+ import { extname, join } from 'node:path';
3
+ import { pathToFileURL } from 'node:url';
4
+ import { workflowMeta } from './workflow-ref.js';
5
+ /**
6
+ * Register a single `@Workflow`-decorated class on the engine: instantiate it once and bind its
7
+ * `run(ctx, input)` as the workflow body via `engine.register`. The low-level
8
+ * `engine.register(name, version, fn)` stays the escape hatch — this is the convenience the
9
+ * `app/workflows` convention builds on. No-op (returns `false`) for an undecorated class.
10
+ */
11
+ export function registerWorkflowClass(engine, cls) {
12
+ const meta = workflowMeta(cls);
13
+ if (!meta)
14
+ return false;
15
+ const Ctor = cls;
16
+ const instance = new Ctor();
17
+ engine.register(meta.name, meta.version, (ctx, input) => Promise.resolve(instance.run(ctx, input)), {
18
+ ...(meta.tags ? { tags: meta.tags } : {}),
19
+ ...(meta.executionTimeout !== undefined ? { executionTimeout: meta.executionTimeout } : {}),
20
+ ...(meta.onEvent ? { onEvent: meta.onEvent } : {}),
21
+ });
22
+ return true;
23
+ }
24
+ /**
25
+ * Pick the module extension for the running environment so a built app (`.js`) and a dev/ts app
26
+ * (`.ts`, run under a loader) never double-register the same workflow. We import only files whose
27
+ * extension matches `import.meta.url`'s own (`.ts` when running from source, `.js` from `dist`),
28
+ * which keeps scanner and `make:workflow` (it scaffolds `.ts`) in agreement under both setups.
29
+ */
30
+ const MODULE_EXT = extname(import.meta.url || '') === '.ts' ? '.ts' : '.js';
31
+ /**
32
+ * Scan a directory RECURSIVELY for modules and collect every exported `@Workflow`-decorated class
33
+ * (the default export and any named export are considered) — so nested conventions like
34
+ * `app/workflows/billing/charge_workflow.ts` are found, matching `make:workflow`'s nested-path
35
+ * scaffolding. Only the environment-appropriate extension is imported (see {@link MODULE_EXT}), and
36
+ * each module path is visited once, so a built `.js` and a dev `.ts` of the same module never both
37
+ * register. Missing directory → empty list (the convention is opt-in: no `app/workflows`, nothing to
38
+ * register).
39
+ */
40
+ export async function discoverWorkflows(dir) {
41
+ let entries;
42
+ try {
43
+ entries = await readdir(dir, { recursive: true });
44
+ }
45
+ catch (err) {
46
+ if (err.code === 'ENOENT')
47
+ return [];
48
+ throw err;
49
+ }
50
+ const found = [];
51
+ const seen = new Set();
52
+ for (const entry of entries.sort()) {
53
+ if (extname(entry) !== MODULE_EXT || entry.endsWith(`.d${MODULE_EXT}`))
54
+ continue;
55
+ const mod = (await import(pathToFileURL(join(dir, entry)).href));
56
+ for (const exported of Object.values(mod)) {
57
+ if (seen.has(exported))
58
+ continue;
59
+ const meta = workflowMeta(exported);
60
+ if (!meta)
61
+ continue;
62
+ seen.add(exported);
63
+ found.push({ meta, cls: exported });
64
+ }
65
+ }
66
+ return found;
67
+ }
68
+ /**
69
+ * Discover every `@Workflow` class under `dir` and register each on the engine. Returns the
70
+ * registered metadata so the caller can log what was wired. Best-effort over a missing directory.
71
+ */
72
+ export async function registerWorkflowsFromDir(engine, dir) {
73
+ const discovered = await discoverWorkflows(dir);
74
+ for (const { cls } of discovered)
75
+ registerWorkflowClass(engine, cls);
76
+ return discovered.map((d) => d.meta);
77
+ }
78
+ //# sourceMappingURL=workflow-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow-discovery.js","sourceRoot":"","sources":["../../src/workflow-discovery.ts"],"names":[],"mappings":"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"}
@@ -6,11 +6,47 @@
6
6
  * string stays available for the cross-runtime case.
7
7
  */
8
8
  /**
9
- * The symbol the `@Workflow` decorator stamps a workflow's registered name onto, so a class ref can
10
- * be resolved back to its name. A global-registry symbol (`Symbol.for`) so it survives duplicate
9
+ * The symbol the `@Workflow` decorator stamps the full options onto (name + version + tags …), so
10
+ * auto-discovery can register the class against the engine and a class ref can be resolved back to
11
+ * its name via {@link workflowName}. A global-registry symbol (`Symbol.for`) so it survives duplicate
11
12
  * copies of this package in a dependency tree.
12
13
  */
13
- export declare const WORKFLOW_NAME_KEY: unique symbol;
14
+ export declare const WORKFLOW_META_KEY: unique symbol;
15
+ /** Options passed to `@Workflow({ name, version, … })`. */
16
+ export interface WorkflowOptions {
17
+ /** The registered workflow name (the cross-runtime identity, e.g. `order`). */
18
+ name: string;
19
+ /** Workflow version. Defaults to `'1'`. Register a new version for a breaking change. */
20
+ version?: string;
21
+ /** Searchable labels merged onto every run of this workflow. */
22
+ tags?: string[];
23
+ /** Wall-clock budget for the whole run (a duration string like `'5m'`, or ms). */
24
+ executionTimeout?: string | number;
25
+ /** Event names that start a run of this workflow when published (see `onEvent`). */
26
+ onEvent?: string[];
27
+ }
28
+ /** The metadata the `@Workflow` decorator stamps onto a class for discovery + registration. */
29
+ export interface WorkflowMeta extends WorkflowOptions {
30
+ version: string;
31
+ }
32
+ /**
33
+ * Class decorator marking a class as a durable workflow. Stamps the full options (name + version +
34
+ * tags …) so a class ref resolves via {@link workflowName} and the provider's `app/workflows`
35
+ * auto-discovery can register it on the engine — no manual `engine.register(...)`. The class must
36
+ * expose `run(ctx, input)`; that method becomes the workflow body.
37
+ *
38
+ * ```ts
39
+ * @Workflow({ name: 'order', version: '1' })
40
+ * export default class OrderWorkflow {
41
+ * async run(ctx: WorkflowCtx, input: { id: string }) { ... }
42
+ * }
43
+ * ```
44
+ */
45
+ export declare function Workflow(options: WorkflowOptions): <T extends abstract new (...args: never[]) => {
46
+ run(ctx: never, input: never): unknown;
47
+ }>(target: T) => T;
48
+ /** Read the {@link WorkflowMeta} a `@Workflow` decorator stamped on a class, or `undefined`. */
49
+ export declare function workflowMeta(target: unknown): WorkflowMeta | undefined;
14
50
  /** Structural shape of a `@Workflow` class — its `run(ctx, input)` carries the input/output types. */
15
51
  export type WorkflowClass<TInput = unknown, TOutput = unknown> = abstract new (...args: never[]) => {
16
52
  run(ctx: never, input: TInput): Promise<TOutput> | TOutput;
@@ -27,8 +63,8 @@ export type WorkflowOutputOf<C> = C extends abstract new (...args: never[]) => {
27
63
  } ? Awaited<R> : unknown;
28
64
  /**
29
65
  * Resolve a {@link WorkflowRef} to its registered workflow name: a string is returned as-is; a
30
- * `@Workflow` class is resolved via the name the decorator stamped on it. Throws if a class was
31
- * never decorated (so it carries no registered name).
66
+ * `@Workflow` class is resolved via the name the decorator stamped in its metadata. Throws if a
67
+ * class was never decorated (so it carries no registered name).
32
68
  */
33
69
  export declare function workflowName(ref: WorkflowRef): string;
34
70
  //# sourceMappingURL=workflow-ref.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-ref.d.ts","sourceRoot":"","sources":["../../src/workflow-ref.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,OAAO,MAAmD,CAAC;AAE3F,sGAAsG;AACtG,MAAM,MAAM,aAAa,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,QAAQ,MACvE,GAAG,IAAI,EAAE,KAAK,EAAE,KACb;IACH,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;CAC5D,CAAC;AAEF,yGAAyG;AACzG,MAAM,MAAM,WAAW,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,IACvD,MAAM,GACN,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEnC,uDAAuD;AACvD,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,CAAC,SAAS,QAAQ,MACjD,GAAG,IAAI,EAAE,KAAK,EAAE,KACb;IACH,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC;CAC1C,GACG,CAAC,GACD,OAAO,CAAC;AAEZ,gFAAgF;AAChF,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI,CAAC,SAAS,QAAQ,MAClD,GAAG,IAAI,EAAE,KAAK,EAAE,KACb;IACH,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,CAAC;CACxC,GACG,OAAO,CAAC,CAAC,CAAC,GACV,OAAO,CAAC;AAEZ;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CASrD"}
1
+ {"version":3,"file":"workflow-ref.d.ts","sourceRoot":"","sources":["../../src/workflow-ref.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,OAAO,MAAmD,CAAC;AAE3F,2DAA2D;AAC3D,MAAM,WAAW,eAAe;IAC9B,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb,yFAAyF;IACzF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,kFAAkF;IAClF,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACnC,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,+FAA+F;AAC/F,MAAM,WAAW,YAAa,SAAQ,eAAe;IACnD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,eAAe,IACvC,CAAC,SAAS,QAAQ,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK;IAAE,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAA;CAAE,EAC7F,QAAQ,CAAC,KACR,CAAC,CASL;AAED,gGAAgG;AAChG,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,YAAY,GAAG,SAAS,CAGtE;AAED,sGAAsG;AACtG,MAAM,MAAM,aAAa,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,QAAQ,MACvE,GAAG,IAAI,EAAE,KAAK,EAAE,KACb;IACH,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;CAC5D,CAAC;AAEF,yGAAyG;AACzG,MAAM,MAAM,WAAW,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,IACvD,MAAM,GACN,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEnC,uDAAuD;AACvD,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,CAAC,SAAS,QAAQ,MACjD,GAAG,IAAI,EAAE,KAAK,EAAE,KACb;IACH,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC;CAC1C,GACG,CAAC,GACD,OAAO,CAAC;AAEZ,gFAAgF;AAChF,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI,CAAC,SAAS,QAAQ,MAClD,GAAG,IAAI,EAAE,KAAK,EAAE,KACb;IACH,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,CAAC;CACxC,GACG,OAAO,CAAC,CAAC,CAAC,GACV,OAAO,CAAC;AAEZ;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CASrD"}
@@ -6,20 +6,51 @@
6
6
  * string stays available for the cross-runtime case.
7
7
  */
8
8
  /**
9
- * The symbol the `@Workflow` decorator stamps a workflow's registered name onto, so a class ref can
10
- * be resolved back to its name. A global-registry symbol (`Symbol.for`) so it survives duplicate
9
+ * The symbol the `@Workflow` decorator stamps the full options onto (name + version + tags …), so
10
+ * auto-discovery can register the class against the engine and a class ref can be resolved back to
11
+ * its name via {@link workflowName}. A global-registry symbol (`Symbol.for`) so it survives duplicate
11
12
  * copies of this package in a dependency tree.
12
13
  */
13
- export const WORKFLOW_NAME_KEY = Symbol.for('@agora/durable:workflow-name');
14
+ export const WORKFLOW_META_KEY = Symbol.for('@agora/durable:workflow-meta');
15
+ /**
16
+ * Class decorator marking a class as a durable workflow. Stamps the full options (name + version +
17
+ * tags …) so a class ref resolves via {@link workflowName} and the provider's `app/workflows`
18
+ * auto-discovery can register it on the engine — no manual `engine.register(...)`. The class must
19
+ * expose `run(ctx, input)`; that method becomes the workflow body.
20
+ *
21
+ * ```ts
22
+ * @Workflow({ name: 'order', version: '1' })
23
+ * export default class OrderWorkflow {
24
+ * async run(ctx: WorkflowCtx, input: { id: string }) { ... }
25
+ * }
26
+ * ```
27
+ */
28
+ export function Workflow(options) {
29
+ return (target) => {
30
+ const meta = { ...options, version: options.version ?? '1' };
31
+ Object.defineProperty(target, WORKFLOW_META_KEY, {
32
+ value: meta,
33
+ enumerable: false,
34
+ configurable: true,
35
+ });
36
+ return target;
37
+ };
38
+ }
39
+ /** Read the {@link WorkflowMeta} a `@Workflow` decorator stamped on a class, or `undefined`. */
40
+ export function workflowMeta(target) {
41
+ if (typeof target !== 'function')
42
+ return undefined;
43
+ return target[WORKFLOW_META_KEY];
44
+ }
14
45
  /**
15
46
  * Resolve a {@link WorkflowRef} to its registered workflow name: a string is returned as-is; a
16
- * `@Workflow` class is resolved via the name the decorator stamped on it. Throws if a class was
17
- * never decorated (so it carries no registered name).
47
+ * `@Workflow` class is resolved via the name the decorator stamped in its metadata. Throws if a
48
+ * class was never decorated (so it carries no registered name).
18
49
  */
19
50
  export function workflowName(ref) {
20
51
  if (typeof ref === 'string')
21
52
  return ref;
22
- const name = ref[WORKFLOW_NAME_KEY];
53
+ const name = workflowMeta(ref)?.name;
23
54
  if (!name) {
24
55
  throw new Error(`workflow class ${ref.name} has no registered name — is it decorated with @Workflow({ name })?`);
25
56
  }
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-ref.js","sourceRoot":"","sources":["../../src/workflow-ref.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAkB,MAAM,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;AAgC3F;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,GAAgB;IAC3C,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IACxC,MAAM,IAAI,GAAI,GAAwC,CAAC,iBAAiB,CAAC,CAAC;IAC1E,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CACb,kBAAkB,GAAG,CAAC,IAAI,qEAAqE,CAChG,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"workflow-ref.js","sourceRoot":"","sources":["../../src/workflow-ref.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAkB,MAAM,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;AAqB3F;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAwB;IAC/C,OAAO,CACL,MAAS,EACN,EAAE;QACL,MAAM,IAAI,GAAiB,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,GAAG,EAAE,CAAC;QAC3E,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,iBAAiB,EAAE;YAC/C,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,KAAK;YACjB,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,YAAY,CAAC,MAAe;IAC1C,IAAI,OAAO,MAAM,KAAK,UAAU;QAAE,OAAO,SAAS,CAAC;IACnD,OAAQ,MAAiD,CAAC,iBAAiB,CAAC,CAAC;AAC/E,CAAC;AAgCD;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,GAAgB;IAC3C,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IACxC,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;IACrC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CACb,kBAAkB,GAAG,CAAC,IAAI,qEAAqE,CAChG,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,22 @@
1
+ {{#var workflowName = string(entity.name).pascalCase().toString()}}
2
+ {{#var workflowFileName = string(entity.name).snakeCase().removeSuffix('workflow').toString() + '_workflow'}}
3
+ {{#var registeredName = string(entity.name).snakeCase().removeSuffix('workflow').toString()}}
4
+ {{{
5
+ exports({
6
+ to: app.makePath('app/workflows', entity.path, workflowFileName + '.ts')
7
+ })
8
+ }}}
9
+ import { Workflow } from '@adonis-agora/durable'
10
+ import type { WorkflowCtx } from '@adonis-agora/durable'
11
+
12
+ interface {{ workflowName }}Input {
13
+ // Define your workflow input here
14
+ }
15
+
16
+ @Workflow({ name: '{{ registeredName }}', version: '1' })
17
+ export default class {{ workflowName }}Workflow {
18
+ async run(ctx: WorkflowCtx, input: {{ workflowName }}Input) {
19
+ // Your workflow logic here — compose ctx.step / ctx.call / ctx.child / ctx.sleep …
20
+ return input
21
+ }
22
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adonis-agora/durable",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Durable cross-app workflows for AdonisJS — deterministic replay engine, AdonisJS binding, ace commands, dashboard, OpenTelemetry, Telescope, testing harness and Redis admission, all in one package. Part of the Agora ecosystem.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -84,10 +84,10 @@
84
84
  "zod": "^3.23.0"
85
85
  },
86
86
  "peerDependencies": {
87
- "@adonisjs/core": "^6.12.0",
88
- "@adonisjs/lucid": "^20.0.0 || ^21.0.0",
87
+ "@adonisjs/core": "^7.3.0",
88
+ "@adonisjs/lucid": "^22.4.0",
89
89
  "@adonisjs/queue": "^0.6.0",
90
- "@adonisjs/redis": "^9.0.0",
90
+ "@adonisjs/redis": "^9.2.0",
91
91
  "@opentelemetry/api": "^1.0.0",
92
92
  "cron-parser": "^4.0.0 || ^5.0.0",
93
93
  "ioredis": "^5.0.0",
@@ -117,11 +117,11 @@
117
117
  }
118
118
  },
119
119
  "devDependencies": {
120
- "@adonisjs/assembler": "^7.8.0",
121
- "@adonisjs/core": "^6.17.0",
122
- "@adonisjs/lucid": "^21.6.0",
120
+ "@adonisjs/assembler": "^8.4.0",
121
+ "@adonisjs/core": "^7.3.0",
122
+ "@adonisjs/lucid": "^22.4.0",
123
123
  "@adonisjs/queue": "^0.6.1",
124
- "@adonisjs/redis": "^9.0.0",
124
+ "@adonisjs/redis": "^9.2.0",
125
125
  "@opentelemetry/api": "^1.9.0",
126
126
  "@opentelemetry/context-async-hooks": "^1.30.0",
127
127
  "@opentelemetry/sdk-trace-base": "^1.30.0",
@@ -151,7 +151,7 @@
151
151
  ],
152
152
  "scripts": {
153
153
  "build": "tsc -p tsconfig.json && pnpm run copy:stubs",
154
- "copy:stubs": "mkdir -p dist/stubs/config dist/stubs/database/migrations dist/assets && cp stubs/config/durable.stub dist/stubs/config/durable.stub && cp stubs/config/durable_dashboard.stub dist/stubs/config/durable_dashboard.stub && cp -r stubs/database/migrations/. dist/stubs/database/migrations/ && cp assets/dashboard.html dist/assets/dashboard.html",
154
+ "copy:stubs": "mkdir -p dist/stubs/config dist/stubs/database/migrations dist/stubs/make/workflow dist/assets && cp stubs/config/durable.stub dist/stubs/config/durable.stub && cp stubs/config/durable_dashboard.stub dist/stubs/config/durable_dashboard.stub && cp -r stubs/database/migrations/. dist/stubs/database/migrations/ && cp stubs/make/workflow/main.stub dist/stubs/make/workflow/main.stub && cp assets/dashboard.html dist/assets/dashboard.html",
155
155
  "test": "vitest run --passWithNoTests",
156
156
  "test:watch": "vitest",
157
157
  "typecheck": "tsc -p tsconfig.json --noEmit"