@adonis-agora/durable 0.3.0 → 0.5.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.
Files changed (51) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +47 -0
  3. package/dist/commands/main.d.ts +3 -2
  4. package/dist/commands/main.d.ts.map +1 -1
  5. package/dist/commands/main.js +2 -1
  6. package/dist/commands/main.js.map +1 -1
  7. package/dist/commands/make_workflow.d.ts +16 -0
  8. package/dist/commands/make_workflow.d.ts.map +1 -0
  9. package/dist/commands/make_workflow.js +30 -0
  10. package/dist/commands/make_workflow.js.map +1 -0
  11. package/dist/configure.d.ts +5 -2
  12. package/dist/configure.d.ts.map +1 -1
  13. package/dist/configure.js +7 -2
  14. package/dist/configure.js.map +1 -1
  15. package/dist/providers/durable_provider.d.ts +12 -0
  16. package/dist/providers/durable_provider.d.ts.map +1 -1
  17. package/dist/providers/durable_provider.js +50 -2
  18. package/dist/providers/durable_provider.js.map +1 -1
  19. package/dist/src/define_config.d.ts +11 -3
  20. package/dist/src/define_config.d.ts.map +1 -1
  21. package/dist/src/define_config.js.map +1 -1
  22. package/dist/src/hooks/workflows.d.ts +53 -0
  23. package/dist/src/hooks/workflows.d.ts.map +1 -0
  24. package/dist/src/hooks/workflows.js +55 -0
  25. package/dist/src/hooks/workflows.js.map +1 -0
  26. package/dist/src/index.d.ts +3 -1
  27. package/dist/src/index.d.ts.map +1 -1
  28. package/dist/src/index.js +2 -0
  29. package/dist/src/index.js.map +1 -1
  30. package/dist/src/protocol.d.ts.map +1 -1
  31. package/dist/src/protocol.js +50 -18
  32. package/dist/src/protocol.js.map +1 -1
  33. package/dist/src/transports/event-emitter.d.ts +60 -0
  34. package/dist/src/transports/event-emitter.d.ts.map +1 -0
  35. package/dist/src/transports/event-emitter.js +103 -0
  36. package/dist/src/transports/event-emitter.js.map +1 -0
  37. package/dist/src/transports/factory.d.ts +23 -2
  38. package/dist/src/transports/factory.d.ts.map +1 -1
  39. package/dist/src/transports/factory.js +20 -1
  40. package/dist/src/transports/factory.js.map +1 -1
  41. package/dist/src/workflow-discovery.d.ts +45 -0
  42. package/dist/src/workflow-discovery.d.ts.map +1 -0
  43. package/dist/src/workflow-discovery.js +103 -0
  44. package/dist/src/workflow-discovery.js.map +1 -0
  45. package/dist/src/workflow-ref.d.ts +41 -5
  46. package/dist/src/workflow-ref.d.ts.map +1 -1
  47. package/dist/src/workflow-ref.js +37 -6
  48. package/dist/src/workflow-ref.js.map +1 -1
  49. package/dist/stubs/config/durable.stub +6 -1
  50. package/dist/stubs/make/workflow/main.stub +22 -0
  51. package/package.json +11 -2
@@ -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"}
@@ -8,6 +8,10 @@ import { defineConfig, transports } from '@adonis-agora/durable'
8
8
  * maps below; each driver's peer dependency is imported lazily, only when selected. The default is
9
9
  * the in-process `memory` transport + the in-memory store — single-process, no extra infrastructure.
10
10
  *
11
+ * For a single-process PRODUCTION app with NO external infra, select the `event-emitter` transport:
12
+ * step handlers run in this same process over a Node EventEmitter (no DB, no Redis, no broker). The
13
+ * `memory` transport is test-only.
14
+ *
11
15
  * For cross-process / production, select the `queue` (@adonisjs/queue) or `db` (@adonisjs/lucid)
12
16
  * transport, and the `lucid` store, then run `node ace migration:run`:
13
17
  *
@@ -17,7 +21,8 @@ import { defineConfig, transports } from '@adonis-agora/durable'
17
21
  * export default defineConfig({
18
22
  * transport: 'queue',
19
23
  * transports: {
20
- * memory: transports.memory(),
24
+ * // single-process production, no external infra:
25
+ * 'event-emitter': transports.eventEmitter(),
21
26
  * // `connection` names an adapter from config/queue.ts (configure @adonisjs/queue first):
22
27
  * queue: transports.queue({ connection: 'redis', group: 'durable' }),
23
28
  * db: transports.db(),
@@ -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.3.0",
3
+ "version": "0.5.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": {
@@ -53,6 +53,11 @@
53
53
  "import": "./dist/src/testing-kit/index.js",
54
54
  "default": "./dist/src/testing-kit/index.js"
55
55
  },
56
+ "./hooks/workflows": {
57
+ "types": "./dist/src/hooks/workflows.d.ts",
58
+ "import": "./dist/src/hooks/workflows.js",
59
+ "default": "./dist/src/hooks/workflows.js"
60
+ },
56
61
  "./admission-redis": {
57
62
  "types": "./dist/src/admission-redis/index.d.ts",
58
63
  "import": "./dist/src/admission-redis/index.js",
@@ -84,6 +89,7 @@
84
89
  "zod": "^3.23.0"
85
90
  },
86
91
  "peerDependencies": {
92
+ "@adonisjs/assembler": "^8.4.0",
87
93
  "@adonisjs/core": "^7.3.0",
88
94
  "@adonisjs/lucid": "^22.4.0",
89
95
  "@adonisjs/queue": "^0.6.0",
@@ -94,6 +100,9 @@
94
100
  "vitest": "^3.0.0"
95
101
  },
96
102
  "peerDependenciesMeta": {
103
+ "@adonisjs/assembler": {
104
+ "optional": true
105
+ },
97
106
  "@adonisjs/lucid": {
98
107
  "optional": true
99
108
  },
@@ -151,7 +160,7 @@
151
160
  ],
152
161
  "scripts": {
153
162
  "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",
163
+ "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
164
  "test": "vitest run --passWithNoTests",
156
165
  "test:watch": "vitest",
157
166
  "typecheck": "tsc -p tsconfig.json --noEmit"