@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.
- package/CHANGELOG.md +24 -0
- package/README.md +47 -0
- package/dist/commands/main.d.ts +3 -2
- package/dist/commands/main.d.ts.map +1 -1
- package/dist/commands/main.js +2 -1
- package/dist/commands/main.js.map +1 -1
- package/dist/commands/make_workflow.d.ts +16 -0
- package/dist/commands/make_workflow.d.ts.map +1 -0
- package/dist/commands/make_workflow.js +30 -0
- package/dist/commands/make_workflow.js.map +1 -0
- package/dist/configure.d.ts +5 -2
- package/dist/configure.d.ts.map +1 -1
- package/dist/configure.js +7 -2
- package/dist/configure.js.map +1 -1
- package/dist/providers/durable_provider.d.ts +12 -0
- package/dist/providers/durable_provider.d.ts.map +1 -1
- package/dist/providers/durable_provider.js +50 -2
- package/dist/providers/durable_provider.js.map +1 -1
- package/dist/src/define_config.d.ts +11 -3
- package/dist/src/define_config.d.ts.map +1 -1
- package/dist/src/define_config.js.map +1 -1
- package/dist/src/hooks/workflows.d.ts +53 -0
- package/dist/src/hooks/workflows.d.ts.map +1 -0
- package/dist/src/hooks/workflows.js +55 -0
- package/dist/src/hooks/workflows.js.map +1 -0
- package/dist/src/index.d.ts +3 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/protocol.d.ts.map +1 -1
- package/dist/src/protocol.js +50 -18
- package/dist/src/protocol.js.map +1 -1
- package/dist/src/transports/event-emitter.d.ts +60 -0
- package/dist/src/transports/event-emitter.d.ts.map +1 -0
- package/dist/src/transports/event-emitter.js +103 -0
- package/dist/src/transports/event-emitter.js.map +1 -0
- package/dist/src/transports/factory.d.ts +23 -2
- package/dist/src/transports/factory.d.ts.map +1 -1
- package/dist/src/transports/factory.js +20 -1
- package/dist/src/transports/factory.js.map +1 -1
- package/dist/src/workflow-discovery.d.ts +45 -0
- package/dist/src/workflow-discovery.d.ts.map +1 -0
- package/dist/src/workflow-discovery.js +103 -0
- package/dist/src/workflow-discovery.js.map +1 -0
- package/dist/src/workflow-ref.d.ts +41 -5
- package/dist/src/workflow-ref.d.ts.map +1 -1
- package/dist/src/workflow-ref.js +37 -6
- package/dist/src/workflow-ref.js.map +1 -1
- package/dist/stubs/config/durable.stub +6 -1
- package/dist/stubs/make/workflow/main.stub +22 -0
- package/package.json +11 -2
package/dist/src/workflow-ref.js
CHANGED
|
@@ -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
|
|
10
|
-
*
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
*
|
|
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
|
+
"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"
|