@duraflows/nestjs 3.1.0 → 4.0.1
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/cjs/filters/workflow-exception.filter.js +8 -0
- package/dist/cjs/providers/injection-tokens.d.ts +7 -0
- package/dist/cjs/providers/injection-tokens.js +8 -1
- package/dist/cjs/services/workflow.service.js +3 -3
- package/dist/cjs/workflow.module.js +141 -207
- package/dist/filters/workflow-exception.filter.js +9 -1
- package/dist/providers/injection-tokens.d.ts +7 -0
- package/dist/providers/injection-tokens.js +7 -0
- package/dist/services/workflow.service.js +3 -3
- package/dist/workflow.module.js +142 -208
- package/package.json +6 -6
|
@@ -36,6 +36,14 @@ let WorkflowExceptionFilter = WorkflowExceptionFilter_1 = class WorkflowExceptio
|
|
|
36
36
|
});
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
|
+
if (exception instanceof core_1.InvalidArgumentError) {
|
|
40
|
+
response.status(common_1.HttpStatus.BAD_REQUEST).send({
|
|
41
|
+
statusCode: common_1.HttpStatus.BAD_REQUEST,
|
|
42
|
+
error: "Bad Request",
|
|
43
|
+
message: exception.message,
|
|
44
|
+
});
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
39
47
|
// The response body is sanitized, so log the real cause here — otherwise
|
|
40
48
|
// unmapped domain errors (e.g. optimistic-locking conflicts under
|
|
41
49
|
// concurrency) become undiagnosable silent 500s. `WorkflowError` wraps the
|
|
@@ -6,4 +6,11 @@ export declare const WORKFLOW_DEFINITION_REGISTRY: unique symbol;
|
|
|
6
6
|
export declare const WORKFLOW_TRANSACTION_RUNNER: unique symbol;
|
|
7
7
|
export declare const WORKFLOW_CLOCK: unique symbol;
|
|
8
8
|
export declare const WORKFLOW_GUARD_REGISTRY: unique symbol;
|
|
9
|
+
/**
|
|
10
|
+
* The resolved module configuration. Deliberately not re-exported from the
|
|
11
|
+
* package barrel: it exists so `forRoot` and `forRootAsync` can publish their
|
|
12
|
+
* config under one token and share a single provider graph, not as a supported
|
|
13
|
+
* extension point.
|
|
14
|
+
*/
|
|
15
|
+
export declare const WORKFLOW_MODULE_OPTIONS: unique symbol;
|
|
9
16
|
//# sourceMappingURL=injection-tokens.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.WORKFLOW_GUARD_REGISTRY = exports.WORKFLOW_CLOCK = exports.WORKFLOW_TRANSACTION_RUNNER = exports.WORKFLOW_DEFINITION_REGISTRY = exports.WORKFLOW_COMMAND_REGISTRY = exports.WORKFLOW_HISTORY_STORE = exports.WORKFLOW_INSTANCE_STORE = exports.WORKFLOW_RUNTIME = void 0;
|
|
3
|
+
exports.WORKFLOW_MODULE_OPTIONS = exports.WORKFLOW_GUARD_REGISTRY = exports.WORKFLOW_CLOCK = exports.WORKFLOW_TRANSACTION_RUNNER = exports.WORKFLOW_DEFINITION_REGISTRY = exports.WORKFLOW_COMMAND_REGISTRY = exports.WORKFLOW_HISTORY_STORE = exports.WORKFLOW_INSTANCE_STORE = exports.WORKFLOW_RUNTIME = void 0;
|
|
4
4
|
exports.WORKFLOW_RUNTIME = Symbol("WORKFLOW_RUNTIME");
|
|
5
5
|
exports.WORKFLOW_INSTANCE_STORE = Symbol("WORKFLOW_INSTANCE_STORE");
|
|
6
6
|
exports.WORKFLOW_HISTORY_STORE = Symbol("WORKFLOW_HISTORY_STORE");
|
|
@@ -9,4 +9,11 @@ exports.WORKFLOW_DEFINITION_REGISTRY = Symbol("WORKFLOW_DEFINITION_REGISTRY");
|
|
|
9
9
|
exports.WORKFLOW_TRANSACTION_RUNNER = Symbol("WORKFLOW_TRANSACTION_RUNNER");
|
|
10
10
|
exports.WORKFLOW_CLOCK = Symbol("WORKFLOW_CLOCK");
|
|
11
11
|
exports.WORKFLOW_GUARD_REGISTRY = Symbol("WORKFLOW_GUARD_REGISTRY");
|
|
12
|
+
/**
|
|
13
|
+
* The resolved module configuration. Deliberately not re-exported from the
|
|
14
|
+
* package barrel: it exists so `forRoot` and `forRootAsync` can publish their
|
|
15
|
+
* config under one token and share a single provider graph, not as a supported
|
|
16
|
+
* extension point.
|
|
17
|
+
*/
|
|
18
|
+
exports.WORKFLOW_MODULE_OPTIONS = Symbol("WORKFLOW_MODULE_OPTIONS");
|
|
12
19
|
//# sourceMappingURL=injection-tokens.js.map
|
|
@@ -56,9 +56,9 @@ let WorkflowService = class WorkflowService {
|
|
|
56
56
|
* upstream when the instance was created via `createInstanceFor`).
|
|
57
57
|
*/
|
|
58
58
|
async triggerEventFor(definition, input) {
|
|
59
|
-
// `definition` is consumed at type
|
|
60
|
-
// the instance by uuid and reads its workflowName from
|
|
61
|
-
|
|
59
|
+
// `definition` is consumed at type level only -- it is what infers TState.
|
|
60
|
+
// The runtime resolves the instance by uuid and reads its workflowName from
|
|
61
|
+
// the live row, so there is nothing to do with the value at runtime.
|
|
62
62
|
const result = await this.runtime.triggerEvent(input);
|
|
63
63
|
return result;
|
|
64
64
|
}
|
|
@@ -38,227 +38,161 @@ const EXPORTED_TOKENS = [
|
|
|
38
38
|
injection_tokens_js_1.WORKFLOW_TRANSACTION_RUNNER,
|
|
39
39
|
injection_tokens_js_1.WORKFLOW_CLOCK,
|
|
40
40
|
];
|
|
41
|
+
const CONTROLLERS = [
|
|
42
|
+
workflow_instance_controller_js_1.WorkflowInstanceController,
|
|
43
|
+
workflow_event_controller_js_1.WorkflowEventController,
|
|
44
|
+
workflow_query_controller_js_1.WorkflowQueryController,
|
|
45
|
+
workflow_timeout_controller_js_1.WorkflowTimeoutController,
|
|
46
|
+
];
|
|
47
|
+
/**
|
|
48
|
+
* `guards` and `guardRegistry` are mutually exclusive: with a custom registry
|
|
49
|
+
* duraflows cannot enumerate guard names, so it can neither merge the array in
|
|
50
|
+
* nor validate definition refs against it.
|
|
51
|
+
*
|
|
52
|
+
* forRoot calls this eagerly, so the error surfaces at module definition.
|
|
53
|
+
* forRootAsync only learns its config once the factory resolves, so it calls
|
|
54
|
+
* this from inside the guard-registry provider instead. Same message, and each
|
|
55
|
+
* entry point keeps the failure timing it has always had.
|
|
56
|
+
*/
|
|
57
|
+
function assertGuardConfigExclusive(config) {
|
|
58
|
+
if (config.guardRegistry && config.guards && config.guards.length > 0) {
|
|
59
|
+
throw new Error("WorkflowModule: cannot supply both `guards` and `guardRegistry` — they are mutually exclusive. Pass guards or a custom registry, not both.");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The provider graph shared by both entry points. Every factory reads its
|
|
64
|
+
* configuration from WORKFLOW_MODULE_OPTIONS — supplied as a value by forRoot
|
|
65
|
+
* and as the caller's factory by forRootAsync — so the wiring downstream is
|
|
66
|
+
* identical and cannot drift between the sync and async paths.
|
|
67
|
+
*/
|
|
68
|
+
function buildWorkflowProviders(explicitCommands) {
|
|
69
|
+
return [
|
|
70
|
+
...explicitCommands.map((c) => c.useClass),
|
|
71
|
+
{
|
|
72
|
+
provide: injection_tokens_js_1.WORKFLOW_COMMAND_REGISTRY,
|
|
73
|
+
useFactory: (moduleRef, discoveryService) => {
|
|
74
|
+
const discovered = (0, command_discovery_js_1.discoverDecoratedCommands)(discoveryService);
|
|
75
|
+
const merged = (0, command_discovery_js_1.mergeCommandRegistrations)(explicitCommands, discovered);
|
|
76
|
+
return new nest_command_registry_js_1.NestCommandRegistry(moduleRef, merged);
|
|
77
|
+
},
|
|
78
|
+
inject: [core_1.ModuleRef, core_1.DiscoveryService],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
provide: injection_tokens_js_1.WORKFLOW_GUARD_REGISTRY,
|
|
82
|
+
useFactory: (config) => {
|
|
83
|
+
// Redundant on the forRoot path, which already threw at module
|
|
84
|
+
// definition, but this is forRootAsync's only opportunity to check.
|
|
85
|
+
assertGuardConfigExclusive(config);
|
|
86
|
+
if (config.guardRegistry)
|
|
87
|
+
return config.guardRegistry;
|
|
88
|
+
const registry = new core_2.InMemoryGuardRegistry();
|
|
89
|
+
for (const guard of config.guards ?? []) {
|
|
90
|
+
registry.register(guard.name, guard);
|
|
91
|
+
}
|
|
92
|
+
return registry;
|
|
93
|
+
},
|
|
94
|
+
inject: [injection_tokens_js_1.WORKFLOW_MODULE_OPTIONS],
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
provide: injection_tokens_js_1.WORKFLOW_DEFINITION_REGISTRY,
|
|
98
|
+
useFactory: (config, commandRegistry) => {
|
|
99
|
+
const knownCommandNames = commandRegistry.getRegisteredNames();
|
|
100
|
+
// Validate guard refs only when we own the registry (built-in path).
|
|
101
|
+
// With a custom guardRegistry we can't enumerate names, so skip;
|
|
102
|
+
// unresolved refs surface at runtime as WorkflowError.
|
|
103
|
+
const knownGuardNames = config.guardRegistry !== undefined ? undefined : new Set((config.guards ?? []).map((g) => g.name));
|
|
104
|
+
const registry = new core_2.InMemoryDefinitionRegistry({
|
|
105
|
+
validator: new core_2.WorkflowValidator(),
|
|
106
|
+
compiler: new core_2.WorkflowCompiler(),
|
|
107
|
+
validationOptions: { knownCommandNames, knownGuardNames },
|
|
108
|
+
onValidationWarning: logValidationWarning,
|
|
109
|
+
});
|
|
110
|
+
for (const workflow of config.workflows) {
|
|
111
|
+
registry.register(workflow);
|
|
112
|
+
}
|
|
113
|
+
return registry;
|
|
114
|
+
},
|
|
115
|
+
inject: [injection_tokens_js_1.WORKFLOW_MODULE_OPTIONS, injection_tokens_js_1.WORKFLOW_COMMAND_REGISTRY],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
provide: injection_tokens_js_1.WORKFLOW_INSTANCE_STORE,
|
|
119
|
+
useFactory: (config) => config.persistence.instanceStore,
|
|
120
|
+
inject: [injection_tokens_js_1.WORKFLOW_MODULE_OPTIONS],
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
provide: injection_tokens_js_1.WORKFLOW_HISTORY_STORE,
|
|
124
|
+
useFactory: (config) => config.persistence.historyStore,
|
|
125
|
+
inject: [injection_tokens_js_1.WORKFLOW_MODULE_OPTIONS],
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
provide: injection_tokens_js_1.WORKFLOW_TRANSACTION_RUNNER,
|
|
129
|
+
useFactory: (config) => config.persistence.transactionRunner,
|
|
130
|
+
inject: [injection_tokens_js_1.WORKFLOW_MODULE_OPTIONS],
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
provide: injection_tokens_js_1.WORKFLOW_CLOCK,
|
|
134
|
+
useFactory: (config) => config.clock ?? { now: () => new Date() },
|
|
135
|
+
inject: [injection_tokens_js_1.WORKFLOW_MODULE_OPTIONS],
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
provide: injection_tokens_js_1.WORKFLOW_RUNTIME,
|
|
139
|
+
useFactory: (config, definitionRegistry, commandRegistry, guardRegistry, instanceStore, historyStore, transactionRunner, clock) => new core_2.WorkflowRuntime({
|
|
140
|
+
definitionRegistry,
|
|
141
|
+
commandRegistry,
|
|
142
|
+
guardRegistry,
|
|
143
|
+
instanceStore,
|
|
144
|
+
historyStore,
|
|
145
|
+
transactionRunner,
|
|
146
|
+
clock,
|
|
147
|
+
observers: config.observers,
|
|
148
|
+
onObserverError: config.onObserverError,
|
|
149
|
+
}),
|
|
150
|
+
inject: [
|
|
151
|
+
injection_tokens_js_1.WORKFLOW_MODULE_OPTIONS,
|
|
152
|
+
injection_tokens_js_1.WORKFLOW_DEFINITION_REGISTRY,
|
|
153
|
+
injection_tokens_js_1.WORKFLOW_COMMAND_REGISTRY,
|
|
154
|
+
injection_tokens_js_1.WORKFLOW_GUARD_REGISTRY,
|
|
155
|
+
injection_tokens_js_1.WORKFLOW_INSTANCE_STORE,
|
|
156
|
+
injection_tokens_js_1.WORKFLOW_HISTORY_STORE,
|
|
157
|
+
injection_tokens_js_1.WORKFLOW_TRANSACTION_RUNNER,
|
|
158
|
+
injection_tokens_js_1.WORKFLOW_CLOCK,
|
|
159
|
+
],
|
|
160
|
+
},
|
|
161
|
+
workflow_service_js_1.WorkflowService,
|
|
162
|
+
workflow_timeout_service_js_1.WorkflowTimeoutService,
|
|
163
|
+
];
|
|
164
|
+
}
|
|
41
165
|
let WorkflowModule = WorkflowModule_1 = class WorkflowModule {
|
|
42
166
|
static forRoot(options) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const controllers = options.enableControllers
|
|
47
|
-
? [workflow_instance_controller_js_1.WorkflowInstanceController, workflow_event_controller_js_1.WorkflowEventController, workflow_query_controller_js_1.WorkflowQueryController, workflow_timeout_controller_js_1.WorkflowTimeoutController]
|
|
48
|
-
: [];
|
|
49
|
-
const explicitCommands = options.commands ?? [];
|
|
50
|
-
const commandClasses = explicitCommands.map((c) => c.useClass);
|
|
51
|
-
const clock = options.clock ?? { now: () => new Date() };
|
|
52
|
-
const providers = [
|
|
53
|
-
...commandClasses,
|
|
54
|
-
{
|
|
55
|
-
provide: injection_tokens_js_1.WORKFLOW_COMMAND_REGISTRY,
|
|
56
|
-
useFactory: (moduleRef, discoveryService) => {
|
|
57
|
-
const discovered = (0, command_discovery_js_1.discoverDecoratedCommands)(discoveryService);
|
|
58
|
-
const merged = (0, command_discovery_js_1.mergeCommandRegistrations)(explicitCommands, discovered);
|
|
59
|
-
return new nest_command_registry_js_1.NestCommandRegistry(moduleRef, merged);
|
|
60
|
-
},
|
|
61
|
-
inject: [core_1.ModuleRef, core_1.DiscoveryService],
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
provide: injection_tokens_js_1.WORKFLOW_GUARD_REGISTRY,
|
|
65
|
-
// guards/guardRegistry mutual exclusion is enforced synchronously at
|
|
66
|
-
// the top of forRoot, before this factory can ever run.
|
|
67
|
-
useFactory: () => {
|
|
68
|
-
if (options.guardRegistry)
|
|
69
|
-
return options.guardRegistry;
|
|
70
|
-
const registry = new core_2.InMemoryGuardRegistry();
|
|
71
|
-
for (const guard of options.guards ?? []) {
|
|
72
|
-
registry.register(guard.name, guard);
|
|
73
|
-
}
|
|
74
|
-
return registry;
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
provide: injection_tokens_js_1.WORKFLOW_DEFINITION_REGISTRY,
|
|
79
|
-
useFactory: (commandRegistry) => {
|
|
80
|
-
const knownCommandNames = commandRegistry.getRegisteredNames();
|
|
81
|
-
// Validate guard refs only when we own the registry (built-in path).
|
|
82
|
-
// With a custom guardRegistry we can't enumerate names, so skip;
|
|
83
|
-
// unresolved refs surface at runtime as WorkflowError.
|
|
84
|
-
const knownGuardNames = options.guardRegistry !== undefined ? undefined : new Set((options.guards ?? []).map((g) => g.name));
|
|
85
|
-
const registry = new core_2.InMemoryDefinitionRegistry({
|
|
86
|
-
validator: new core_2.WorkflowValidator(),
|
|
87
|
-
compiler: new core_2.WorkflowCompiler(),
|
|
88
|
-
validationOptions: { knownCommandNames, knownGuardNames },
|
|
89
|
-
onValidationWarning: logValidationWarning,
|
|
90
|
-
});
|
|
91
|
-
for (const workflow of options.workflows) {
|
|
92
|
-
registry.register(workflow);
|
|
93
|
-
}
|
|
94
|
-
return registry;
|
|
95
|
-
},
|
|
96
|
-
inject: [injection_tokens_js_1.WORKFLOW_COMMAND_REGISTRY],
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
provide: injection_tokens_js_1.WORKFLOW_INSTANCE_STORE,
|
|
100
|
-
useValue: options.persistence.instanceStore,
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
provide: injection_tokens_js_1.WORKFLOW_HISTORY_STORE,
|
|
104
|
-
useValue: options.persistence.historyStore,
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
provide: injection_tokens_js_1.WORKFLOW_TRANSACTION_RUNNER,
|
|
108
|
-
useValue: options.persistence.transactionRunner,
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
provide: injection_tokens_js_1.WORKFLOW_CLOCK,
|
|
112
|
-
useValue: clock,
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
provide: injection_tokens_js_1.WORKFLOW_RUNTIME,
|
|
116
|
-
useFactory: (definitionRegistry, commandRegistry, guardRegistry, instanceStore, historyStore, transactionRunner, wfClock) => new core_2.WorkflowRuntime({
|
|
117
|
-
definitionRegistry,
|
|
118
|
-
commandRegistry,
|
|
119
|
-
guardRegistry,
|
|
120
|
-
instanceStore,
|
|
121
|
-
historyStore,
|
|
122
|
-
transactionRunner,
|
|
123
|
-
clock: wfClock,
|
|
124
|
-
observers: options.observers,
|
|
125
|
-
onObserverError: options.onObserverError,
|
|
126
|
-
}),
|
|
127
|
-
inject: [
|
|
128
|
-
injection_tokens_js_1.WORKFLOW_DEFINITION_REGISTRY,
|
|
129
|
-
injection_tokens_js_1.WORKFLOW_COMMAND_REGISTRY,
|
|
130
|
-
injection_tokens_js_1.WORKFLOW_GUARD_REGISTRY,
|
|
131
|
-
injection_tokens_js_1.WORKFLOW_INSTANCE_STORE,
|
|
132
|
-
injection_tokens_js_1.WORKFLOW_HISTORY_STORE,
|
|
133
|
-
injection_tokens_js_1.WORKFLOW_TRANSACTION_RUNNER,
|
|
134
|
-
injection_tokens_js_1.WORKFLOW_CLOCK,
|
|
135
|
-
],
|
|
136
|
-
},
|
|
137
|
-
workflow_service_js_1.WorkflowService,
|
|
138
|
-
workflow_timeout_service_js_1.WorkflowTimeoutService,
|
|
139
|
-
];
|
|
167
|
+
// Eager, so a misconfiguration fails where it was written rather than at
|
|
168
|
+
// container bootstrap.
|
|
169
|
+
assertGuardConfigExclusive(options);
|
|
140
170
|
return {
|
|
141
171
|
module: WorkflowModule_1,
|
|
142
172
|
global: true, // allow downstream feature modules to inject WorkflowService without re-importing forRoot
|
|
143
173
|
imports: [core_1.DiscoveryModule],
|
|
144
|
-
controllers,
|
|
145
|
-
providers
|
|
174
|
+
controllers: options.enableControllers ? [...CONTROLLERS] : [],
|
|
175
|
+
providers: [
|
|
176
|
+
{ provide: injection_tokens_js_1.WORKFLOW_MODULE_OPTIONS, useValue: options },
|
|
177
|
+
...buildWorkflowProviders(options.commands ?? []),
|
|
178
|
+
],
|
|
146
179
|
exports: EXPORTED_TOKENS,
|
|
147
180
|
};
|
|
148
181
|
}
|
|
149
182
|
static forRootAsync(options) {
|
|
150
|
-
const controllers = options.enableControllers
|
|
151
|
-
? [workflow_instance_controller_js_1.WorkflowInstanceController, workflow_event_controller_js_1.WorkflowEventController, workflow_query_controller_js_1.WorkflowQueryController, workflow_timeout_controller_js_1.WorkflowTimeoutController]
|
|
152
|
-
: [];
|
|
153
|
-
const explicitCommands = options.commands ?? [];
|
|
154
|
-
const commandClasses = explicitCommands.map((c) => c.useClass);
|
|
155
|
-
const configProvider = {
|
|
156
|
-
provide: "WORKFLOW_MODULE_OPTIONS",
|
|
157
|
-
useFactory: options.useFactory,
|
|
158
|
-
inject: (options.inject ?? []),
|
|
159
|
-
};
|
|
160
|
-
const providers = [
|
|
161
|
-
configProvider,
|
|
162
|
-
...commandClasses,
|
|
163
|
-
{
|
|
164
|
-
provide: injection_tokens_js_1.WORKFLOW_COMMAND_REGISTRY,
|
|
165
|
-
useFactory: (moduleRef, discoveryService) => {
|
|
166
|
-
const discovered = (0, command_discovery_js_1.discoverDecoratedCommands)(discoveryService);
|
|
167
|
-
const merged = (0, command_discovery_js_1.mergeCommandRegistrations)(explicitCommands, discovered);
|
|
168
|
-
return new nest_command_registry_js_1.NestCommandRegistry(moduleRef, merged);
|
|
169
|
-
},
|
|
170
|
-
inject: [core_1.ModuleRef, core_1.DiscoveryService],
|
|
171
|
-
},
|
|
172
|
-
{
|
|
173
|
-
provide: injection_tokens_js_1.WORKFLOW_GUARD_REGISTRY,
|
|
174
|
-
useFactory: (config) => {
|
|
175
|
-
if (config.guardRegistry && config.guards && config.guards.length > 0) {
|
|
176
|
-
throw new Error("WorkflowModule: cannot supply both `guards` and `guardRegistry` — they are mutually exclusive. Pass guards or a custom registry, not both.");
|
|
177
|
-
}
|
|
178
|
-
if (config.guardRegistry)
|
|
179
|
-
return config.guardRegistry;
|
|
180
|
-
const registry = new core_2.InMemoryGuardRegistry();
|
|
181
|
-
for (const guard of config.guards ?? []) {
|
|
182
|
-
registry.register(guard.name, guard);
|
|
183
|
-
}
|
|
184
|
-
return registry;
|
|
185
|
-
},
|
|
186
|
-
inject: ["WORKFLOW_MODULE_OPTIONS"],
|
|
187
|
-
},
|
|
188
|
-
{
|
|
189
|
-
provide: injection_tokens_js_1.WORKFLOW_DEFINITION_REGISTRY,
|
|
190
|
-
useFactory: (config, commandRegistry) => {
|
|
191
|
-
const knownCommandNames = commandRegistry.getRegisteredNames();
|
|
192
|
-
// Validate guard refs only when we own the registry (built-in path).
|
|
193
|
-
// With a custom guardRegistry we can't enumerate names, so skip;
|
|
194
|
-
// unresolved refs surface at runtime as WorkflowError.
|
|
195
|
-
const knownGuardNames = config.guardRegistry !== undefined ? undefined : new Set((config.guards ?? []).map((g) => g.name));
|
|
196
|
-
const registry = new core_2.InMemoryDefinitionRegistry({
|
|
197
|
-
validator: new core_2.WorkflowValidator(),
|
|
198
|
-
compiler: new core_2.WorkflowCompiler(),
|
|
199
|
-
validationOptions: { knownCommandNames, knownGuardNames },
|
|
200
|
-
onValidationWarning: logValidationWarning,
|
|
201
|
-
});
|
|
202
|
-
for (const workflow of config.workflows) {
|
|
203
|
-
registry.register(workflow);
|
|
204
|
-
}
|
|
205
|
-
return registry;
|
|
206
|
-
},
|
|
207
|
-
inject: ["WORKFLOW_MODULE_OPTIONS", injection_tokens_js_1.WORKFLOW_COMMAND_REGISTRY],
|
|
208
|
-
},
|
|
209
|
-
{
|
|
210
|
-
provide: injection_tokens_js_1.WORKFLOW_INSTANCE_STORE,
|
|
211
|
-
useFactory: (config) => config.persistence.instanceStore,
|
|
212
|
-
inject: ["WORKFLOW_MODULE_OPTIONS"],
|
|
213
|
-
},
|
|
214
|
-
{
|
|
215
|
-
provide: injection_tokens_js_1.WORKFLOW_HISTORY_STORE,
|
|
216
|
-
useFactory: (config) => config.persistence.historyStore,
|
|
217
|
-
inject: ["WORKFLOW_MODULE_OPTIONS"],
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
provide: injection_tokens_js_1.WORKFLOW_TRANSACTION_RUNNER,
|
|
221
|
-
useFactory: (config) => config.persistence.transactionRunner,
|
|
222
|
-
inject: ["WORKFLOW_MODULE_OPTIONS"],
|
|
223
|
-
},
|
|
224
|
-
{
|
|
225
|
-
provide: injection_tokens_js_1.WORKFLOW_CLOCK,
|
|
226
|
-
useFactory: (config) => config.clock ?? { now: () => new Date() },
|
|
227
|
-
inject: ["WORKFLOW_MODULE_OPTIONS"],
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
provide: injection_tokens_js_1.WORKFLOW_RUNTIME,
|
|
231
|
-
useFactory: (config, definitionRegistry, commandRegistry, guardRegistry, instanceStore, historyStore, transactionRunner, clock) => new core_2.WorkflowRuntime({
|
|
232
|
-
definitionRegistry,
|
|
233
|
-
commandRegistry,
|
|
234
|
-
guardRegistry,
|
|
235
|
-
instanceStore,
|
|
236
|
-
historyStore,
|
|
237
|
-
transactionRunner,
|
|
238
|
-
clock,
|
|
239
|
-
observers: config.observers,
|
|
240
|
-
onObserverError: config.onObserverError,
|
|
241
|
-
}),
|
|
242
|
-
inject: [
|
|
243
|
-
"WORKFLOW_MODULE_OPTIONS",
|
|
244
|
-
injection_tokens_js_1.WORKFLOW_DEFINITION_REGISTRY,
|
|
245
|
-
injection_tokens_js_1.WORKFLOW_COMMAND_REGISTRY,
|
|
246
|
-
injection_tokens_js_1.WORKFLOW_GUARD_REGISTRY,
|
|
247
|
-
injection_tokens_js_1.WORKFLOW_INSTANCE_STORE,
|
|
248
|
-
injection_tokens_js_1.WORKFLOW_HISTORY_STORE,
|
|
249
|
-
injection_tokens_js_1.WORKFLOW_TRANSACTION_RUNNER,
|
|
250
|
-
injection_tokens_js_1.WORKFLOW_CLOCK,
|
|
251
|
-
],
|
|
252
|
-
},
|
|
253
|
-
workflow_service_js_1.WorkflowService,
|
|
254
|
-
workflow_timeout_service_js_1.WorkflowTimeoutService,
|
|
255
|
-
];
|
|
256
183
|
return {
|
|
257
184
|
module: WorkflowModule_1,
|
|
258
185
|
global: true, // allow downstream feature modules to inject WorkflowService without re-importing forRootAsync
|
|
259
186
|
imports: [core_1.DiscoveryModule, ...(options.imports ?? [])],
|
|
260
|
-
controllers,
|
|
261
|
-
providers
|
|
187
|
+
controllers: options.enableControllers ? [...CONTROLLERS] : [],
|
|
188
|
+
providers: [
|
|
189
|
+
{
|
|
190
|
+
provide: injection_tokens_js_1.WORKFLOW_MODULE_OPTIONS,
|
|
191
|
+
useFactory: options.useFactory,
|
|
192
|
+
inject: (options.inject ?? []),
|
|
193
|
+
},
|
|
194
|
+
...buildWorkflowProviders(options.commands ?? []),
|
|
195
|
+
],
|
|
262
196
|
exports: EXPORTED_TOKENS,
|
|
263
197
|
};
|
|
264
198
|
}
|
|
@@ -6,7 +6,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
6
6
|
};
|
|
7
7
|
var WorkflowExceptionFilter_1;
|
|
8
8
|
import { Catch, HttpStatus, Logger } from "@nestjs/common";
|
|
9
|
-
import { WorkflowError, WorkflowInstanceNotFoundError, InvalidEventError } from "@duraflows/core";
|
|
9
|
+
import { WorkflowError, WorkflowInstanceNotFoundError, InvalidEventError, InvalidArgumentError } from "@duraflows/core";
|
|
10
10
|
/**
|
|
11
11
|
* Maps duraflows domain errors to HTTP statuses for the optional REST
|
|
12
12
|
* controllers. Without this filter, a missing instance or an event invalid
|
|
@@ -33,6 +33,14 @@ let WorkflowExceptionFilter = WorkflowExceptionFilter_1 = class WorkflowExceptio
|
|
|
33
33
|
});
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
36
|
+
if (exception instanceof InvalidArgumentError) {
|
|
37
|
+
response.status(HttpStatus.BAD_REQUEST).send({
|
|
38
|
+
statusCode: HttpStatus.BAD_REQUEST,
|
|
39
|
+
error: "Bad Request",
|
|
40
|
+
message: exception.message,
|
|
41
|
+
});
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
36
44
|
// The response body is sanitized, so log the real cause here — otherwise
|
|
37
45
|
// unmapped domain errors (e.g. optimistic-locking conflicts under
|
|
38
46
|
// concurrency) become undiagnosable silent 500s. `WorkflowError` wraps the
|
|
@@ -6,4 +6,11 @@ export declare const WORKFLOW_DEFINITION_REGISTRY: unique symbol;
|
|
|
6
6
|
export declare const WORKFLOW_TRANSACTION_RUNNER: unique symbol;
|
|
7
7
|
export declare const WORKFLOW_CLOCK: unique symbol;
|
|
8
8
|
export declare const WORKFLOW_GUARD_REGISTRY: unique symbol;
|
|
9
|
+
/**
|
|
10
|
+
* The resolved module configuration. Deliberately not re-exported from the
|
|
11
|
+
* package barrel: it exists so `forRoot` and `forRootAsync` can publish their
|
|
12
|
+
* config under one token and share a single provider graph, not as a supported
|
|
13
|
+
* extension point.
|
|
14
|
+
*/
|
|
15
|
+
export declare const WORKFLOW_MODULE_OPTIONS: unique symbol;
|
|
9
16
|
//# sourceMappingURL=injection-tokens.d.ts.map
|
|
@@ -6,4 +6,11 @@ export const WORKFLOW_DEFINITION_REGISTRY = Symbol("WORKFLOW_DEFINITION_REGISTRY
|
|
|
6
6
|
export const WORKFLOW_TRANSACTION_RUNNER = Symbol("WORKFLOW_TRANSACTION_RUNNER");
|
|
7
7
|
export const WORKFLOW_CLOCK = Symbol("WORKFLOW_CLOCK");
|
|
8
8
|
export const WORKFLOW_GUARD_REGISTRY = Symbol("WORKFLOW_GUARD_REGISTRY");
|
|
9
|
+
/**
|
|
10
|
+
* The resolved module configuration. Deliberately not re-exported from the
|
|
11
|
+
* package barrel: it exists so `forRoot` and `forRootAsync` can publish their
|
|
12
|
+
* config under one token and share a single provider graph, not as a supported
|
|
13
|
+
* extension point.
|
|
14
|
+
*/
|
|
15
|
+
export const WORKFLOW_MODULE_OPTIONS = Symbol("WORKFLOW_MODULE_OPTIONS");
|
|
9
16
|
//# sourceMappingURL=injection-tokens.js.map
|
|
@@ -53,9 +53,9 @@ let WorkflowService = class WorkflowService {
|
|
|
53
53
|
* upstream when the instance was created via `createInstanceFor`).
|
|
54
54
|
*/
|
|
55
55
|
async triggerEventFor(definition, input) {
|
|
56
|
-
// `definition` is consumed at type
|
|
57
|
-
// the instance by uuid and reads its workflowName from
|
|
58
|
-
|
|
56
|
+
// `definition` is consumed at type level only -- it is what infers TState.
|
|
57
|
+
// The runtime resolves the instance by uuid and reads its workflowName from
|
|
58
|
+
// the live row, so there is nothing to do with the value at runtime.
|
|
59
59
|
const result = await this.runtime.triggerEvent(input);
|
|
60
60
|
return result;
|
|
61
61
|
}
|
package/dist/workflow.module.js
CHANGED
|
@@ -10,7 +10,7 @@ import { DiscoveryModule, DiscoveryService, ModuleRef } from "@nestjs/core";
|
|
|
10
10
|
import { InMemoryDefinitionRegistry, WorkflowRuntime, WorkflowValidator, WorkflowCompiler, InMemoryGuardRegistry, } from "@duraflows/core";
|
|
11
11
|
import { NestCommandRegistry } from "./providers/nest-command-registry.js";
|
|
12
12
|
import { discoverDecoratedCommands, mergeCommandRegistrations } from "./providers/command-discovery.js";
|
|
13
|
-
import { WORKFLOW_RUNTIME, WORKFLOW_INSTANCE_STORE, WORKFLOW_HISTORY_STORE, WORKFLOW_COMMAND_REGISTRY, WORKFLOW_DEFINITION_REGISTRY, WORKFLOW_TRANSACTION_RUNNER, WORKFLOW_CLOCK, WORKFLOW_GUARD_REGISTRY, } from "./providers/injection-tokens.js";
|
|
13
|
+
import { WORKFLOW_RUNTIME, WORKFLOW_INSTANCE_STORE, WORKFLOW_HISTORY_STORE, WORKFLOW_COMMAND_REGISTRY, WORKFLOW_DEFINITION_REGISTRY, WORKFLOW_TRANSACTION_RUNNER, WORKFLOW_CLOCK, WORKFLOW_GUARD_REGISTRY, WORKFLOW_MODULE_OPTIONS, } from "./providers/injection-tokens.js";
|
|
14
14
|
import { WorkflowService } from "./services/workflow.service.js";
|
|
15
15
|
import { WorkflowTimeoutService } from "./services/workflow-timeout.service.js";
|
|
16
16
|
import { WorkflowEventController } from "./controllers/workflow-event.controller.js";
|
|
@@ -35,227 +35,161 @@ const EXPORTED_TOKENS = [
|
|
|
35
35
|
WORKFLOW_TRANSACTION_RUNNER,
|
|
36
36
|
WORKFLOW_CLOCK,
|
|
37
37
|
];
|
|
38
|
+
const CONTROLLERS = [
|
|
39
|
+
WorkflowInstanceController,
|
|
40
|
+
WorkflowEventController,
|
|
41
|
+
WorkflowQueryController,
|
|
42
|
+
WorkflowTimeoutController,
|
|
43
|
+
];
|
|
44
|
+
/**
|
|
45
|
+
* `guards` and `guardRegistry` are mutually exclusive: with a custom registry
|
|
46
|
+
* duraflows cannot enumerate guard names, so it can neither merge the array in
|
|
47
|
+
* nor validate definition refs against it.
|
|
48
|
+
*
|
|
49
|
+
* forRoot calls this eagerly, so the error surfaces at module definition.
|
|
50
|
+
* forRootAsync only learns its config once the factory resolves, so it calls
|
|
51
|
+
* this from inside the guard-registry provider instead. Same message, and each
|
|
52
|
+
* entry point keeps the failure timing it has always had.
|
|
53
|
+
*/
|
|
54
|
+
function assertGuardConfigExclusive(config) {
|
|
55
|
+
if (config.guardRegistry && config.guards && config.guards.length > 0) {
|
|
56
|
+
throw new Error("WorkflowModule: cannot supply both `guards` and `guardRegistry` — they are mutually exclusive. Pass guards or a custom registry, not both.");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The provider graph shared by both entry points. Every factory reads its
|
|
61
|
+
* configuration from WORKFLOW_MODULE_OPTIONS — supplied as a value by forRoot
|
|
62
|
+
* and as the caller's factory by forRootAsync — so the wiring downstream is
|
|
63
|
+
* identical and cannot drift between the sync and async paths.
|
|
64
|
+
*/
|
|
65
|
+
function buildWorkflowProviders(explicitCommands) {
|
|
66
|
+
return [
|
|
67
|
+
...explicitCommands.map((c) => c.useClass),
|
|
68
|
+
{
|
|
69
|
+
provide: WORKFLOW_COMMAND_REGISTRY,
|
|
70
|
+
useFactory: (moduleRef, discoveryService) => {
|
|
71
|
+
const discovered = discoverDecoratedCommands(discoveryService);
|
|
72
|
+
const merged = mergeCommandRegistrations(explicitCommands, discovered);
|
|
73
|
+
return new NestCommandRegistry(moduleRef, merged);
|
|
74
|
+
},
|
|
75
|
+
inject: [ModuleRef, DiscoveryService],
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
provide: WORKFLOW_GUARD_REGISTRY,
|
|
79
|
+
useFactory: (config) => {
|
|
80
|
+
// Redundant on the forRoot path, which already threw at module
|
|
81
|
+
// definition, but this is forRootAsync's only opportunity to check.
|
|
82
|
+
assertGuardConfigExclusive(config);
|
|
83
|
+
if (config.guardRegistry)
|
|
84
|
+
return config.guardRegistry;
|
|
85
|
+
const registry = new InMemoryGuardRegistry();
|
|
86
|
+
for (const guard of config.guards ?? []) {
|
|
87
|
+
registry.register(guard.name, guard);
|
|
88
|
+
}
|
|
89
|
+
return registry;
|
|
90
|
+
},
|
|
91
|
+
inject: [WORKFLOW_MODULE_OPTIONS],
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
provide: WORKFLOW_DEFINITION_REGISTRY,
|
|
95
|
+
useFactory: (config, commandRegistry) => {
|
|
96
|
+
const knownCommandNames = commandRegistry.getRegisteredNames();
|
|
97
|
+
// Validate guard refs only when we own the registry (built-in path).
|
|
98
|
+
// With a custom guardRegistry we can't enumerate names, so skip;
|
|
99
|
+
// unresolved refs surface at runtime as WorkflowError.
|
|
100
|
+
const knownGuardNames = config.guardRegistry !== undefined ? undefined : new Set((config.guards ?? []).map((g) => g.name));
|
|
101
|
+
const registry = new InMemoryDefinitionRegistry({
|
|
102
|
+
validator: new WorkflowValidator(),
|
|
103
|
+
compiler: new WorkflowCompiler(),
|
|
104
|
+
validationOptions: { knownCommandNames, knownGuardNames },
|
|
105
|
+
onValidationWarning: logValidationWarning,
|
|
106
|
+
});
|
|
107
|
+
for (const workflow of config.workflows) {
|
|
108
|
+
registry.register(workflow);
|
|
109
|
+
}
|
|
110
|
+
return registry;
|
|
111
|
+
},
|
|
112
|
+
inject: [WORKFLOW_MODULE_OPTIONS, WORKFLOW_COMMAND_REGISTRY],
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
provide: WORKFLOW_INSTANCE_STORE,
|
|
116
|
+
useFactory: (config) => config.persistence.instanceStore,
|
|
117
|
+
inject: [WORKFLOW_MODULE_OPTIONS],
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
provide: WORKFLOW_HISTORY_STORE,
|
|
121
|
+
useFactory: (config) => config.persistence.historyStore,
|
|
122
|
+
inject: [WORKFLOW_MODULE_OPTIONS],
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
provide: WORKFLOW_TRANSACTION_RUNNER,
|
|
126
|
+
useFactory: (config) => config.persistence.transactionRunner,
|
|
127
|
+
inject: [WORKFLOW_MODULE_OPTIONS],
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
provide: WORKFLOW_CLOCK,
|
|
131
|
+
useFactory: (config) => config.clock ?? { now: () => new Date() },
|
|
132
|
+
inject: [WORKFLOW_MODULE_OPTIONS],
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
provide: WORKFLOW_RUNTIME,
|
|
136
|
+
useFactory: (config, definitionRegistry, commandRegistry, guardRegistry, instanceStore, historyStore, transactionRunner, clock) => new WorkflowRuntime({
|
|
137
|
+
definitionRegistry,
|
|
138
|
+
commandRegistry,
|
|
139
|
+
guardRegistry,
|
|
140
|
+
instanceStore,
|
|
141
|
+
historyStore,
|
|
142
|
+
transactionRunner,
|
|
143
|
+
clock,
|
|
144
|
+
observers: config.observers,
|
|
145
|
+
onObserverError: config.onObserverError,
|
|
146
|
+
}),
|
|
147
|
+
inject: [
|
|
148
|
+
WORKFLOW_MODULE_OPTIONS,
|
|
149
|
+
WORKFLOW_DEFINITION_REGISTRY,
|
|
150
|
+
WORKFLOW_COMMAND_REGISTRY,
|
|
151
|
+
WORKFLOW_GUARD_REGISTRY,
|
|
152
|
+
WORKFLOW_INSTANCE_STORE,
|
|
153
|
+
WORKFLOW_HISTORY_STORE,
|
|
154
|
+
WORKFLOW_TRANSACTION_RUNNER,
|
|
155
|
+
WORKFLOW_CLOCK,
|
|
156
|
+
],
|
|
157
|
+
},
|
|
158
|
+
WorkflowService,
|
|
159
|
+
WorkflowTimeoutService,
|
|
160
|
+
];
|
|
161
|
+
}
|
|
38
162
|
let WorkflowModule = WorkflowModule_1 = class WorkflowModule {
|
|
39
163
|
static forRoot(options) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const controllers = options.enableControllers
|
|
44
|
-
? [WorkflowInstanceController, WorkflowEventController, WorkflowQueryController, WorkflowTimeoutController]
|
|
45
|
-
: [];
|
|
46
|
-
const explicitCommands = options.commands ?? [];
|
|
47
|
-
const commandClasses = explicitCommands.map((c) => c.useClass);
|
|
48
|
-
const clock = options.clock ?? { now: () => new Date() };
|
|
49
|
-
const providers = [
|
|
50
|
-
...commandClasses,
|
|
51
|
-
{
|
|
52
|
-
provide: WORKFLOW_COMMAND_REGISTRY,
|
|
53
|
-
useFactory: (moduleRef, discoveryService) => {
|
|
54
|
-
const discovered = discoverDecoratedCommands(discoveryService);
|
|
55
|
-
const merged = mergeCommandRegistrations(explicitCommands, discovered);
|
|
56
|
-
return new NestCommandRegistry(moduleRef, merged);
|
|
57
|
-
},
|
|
58
|
-
inject: [ModuleRef, DiscoveryService],
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
provide: WORKFLOW_GUARD_REGISTRY,
|
|
62
|
-
// guards/guardRegistry mutual exclusion is enforced synchronously at
|
|
63
|
-
// the top of forRoot, before this factory can ever run.
|
|
64
|
-
useFactory: () => {
|
|
65
|
-
if (options.guardRegistry)
|
|
66
|
-
return options.guardRegistry;
|
|
67
|
-
const registry = new InMemoryGuardRegistry();
|
|
68
|
-
for (const guard of options.guards ?? []) {
|
|
69
|
-
registry.register(guard.name, guard);
|
|
70
|
-
}
|
|
71
|
-
return registry;
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
provide: WORKFLOW_DEFINITION_REGISTRY,
|
|
76
|
-
useFactory: (commandRegistry) => {
|
|
77
|
-
const knownCommandNames = commandRegistry.getRegisteredNames();
|
|
78
|
-
// Validate guard refs only when we own the registry (built-in path).
|
|
79
|
-
// With a custom guardRegistry we can't enumerate names, so skip;
|
|
80
|
-
// unresolved refs surface at runtime as WorkflowError.
|
|
81
|
-
const knownGuardNames = options.guardRegistry !== undefined ? undefined : new Set((options.guards ?? []).map((g) => g.name));
|
|
82
|
-
const registry = new InMemoryDefinitionRegistry({
|
|
83
|
-
validator: new WorkflowValidator(),
|
|
84
|
-
compiler: new WorkflowCompiler(),
|
|
85
|
-
validationOptions: { knownCommandNames, knownGuardNames },
|
|
86
|
-
onValidationWarning: logValidationWarning,
|
|
87
|
-
});
|
|
88
|
-
for (const workflow of options.workflows) {
|
|
89
|
-
registry.register(workflow);
|
|
90
|
-
}
|
|
91
|
-
return registry;
|
|
92
|
-
},
|
|
93
|
-
inject: [WORKFLOW_COMMAND_REGISTRY],
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
provide: WORKFLOW_INSTANCE_STORE,
|
|
97
|
-
useValue: options.persistence.instanceStore,
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
provide: WORKFLOW_HISTORY_STORE,
|
|
101
|
-
useValue: options.persistence.historyStore,
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
provide: WORKFLOW_TRANSACTION_RUNNER,
|
|
105
|
-
useValue: options.persistence.transactionRunner,
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
provide: WORKFLOW_CLOCK,
|
|
109
|
-
useValue: clock,
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
provide: WORKFLOW_RUNTIME,
|
|
113
|
-
useFactory: (definitionRegistry, commandRegistry, guardRegistry, instanceStore, historyStore, transactionRunner, wfClock) => new WorkflowRuntime({
|
|
114
|
-
definitionRegistry,
|
|
115
|
-
commandRegistry,
|
|
116
|
-
guardRegistry,
|
|
117
|
-
instanceStore,
|
|
118
|
-
historyStore,
|
|
119
|
-
transactionRunner,
|
|
120
|
-
clock: wfClock,
|
|
121
|
-
observers: options.observers,
|
|
122
|
-
onObserverError: options.onObserverError,
|
|
123
|
-
}),
|
|
124
|
-
inject: [
|
|
125
|
-
WORKFLOW_DEFINITION_REGISTRY,
|
|
126
|
-
WORKFLOW_COMMAND_REGISTRY,
|
|
127
|
-
WORKFLOW_GUARD_REGISTRY,
|
|
128
|
-
WORKFLOW_INSTANCE_STORE,
|
|
129
|
-
WORKFLOW_HISTORY_STORE,
|
|
130
|
-
WORKFLOW_TRANSACTION_RUNNER,
|
|
131
|
-
WORKFLOW_CLOCK,
|
|
132
|
-
],
|
|
133
|
-
},
|
|
134
|
-
WorkflowService,
|
|
135
|
-
WorkflowTimeoutService,
|
|
136
|
-
];
|
|
164
|
+
// Eager, so a misconfiguration fails where it was written rather than at
|
|
165
|
+
// container bootstrap.
|
|
166
|
+
assertGuardConfigExclusive(options);
|
|
137
167
|
return {
|
|
138
168
|
module: WorkflowModule_1,
|
|
139
169
|
global: true, // allow downstream feature modules to inject WorkflowService without re-importing forRoot
|
|
140
170
|
imports: [DiscoveryModule],
|
|
141
|
-
controllers,
|
|
142
|
-
providers
|
|
171
|
+
controllers: options.enableControllers ? [...CONTROLLERS] : [],
|
|
172
|
+
providers: [
|
|
173
|
+
{ provide: WORKFLOW_MODULE_OPTIONS, useValue: options },
|
|
174
|
+
...buildWorkflowProviders(options.commands ?? []),
|
|
175
|
+
],
|
|
143
176
|
exports: EXPORTED_TOKENS,
|
|
144
177
|
};
|
|
145
178
|
}
|
|
146
179
|
static forRootAsync(options) {
|
|
147
|
-
const controllers = options.enableControllers
|
|
148
|
-
? [WorkflowInstanceController, WorkflowEventController, WorkflowQueryController, WorkflowTimeoutController]
|
|
149
|
-
: [];
|
|
150
|
-
const explicitCommands = options.commands ?? [];
|
|
151
|
-
const commandClasses = explicitCommands.map((c) => c.useClass);
|
|
152
|
-
const configProvider = {
|
|
153
|
-
provide: "WORKFLOW_MODULE_OPTIONS",
|
|
154
|
-
useFactory: options.useFactory,
|
|
155
|
-
inject: (options.inject ?? []),
|
|
156
|
-
};
|
|
157
|
-
const providers = [
|
|
158
|
-
configProvider,
|
|
159
|
-
...commandClasses,
|
|
160
|
-
{
|
|
161
|
-
provide: WORKFLOW_COMMAND_REGISTRY,
|
|
162
|
-
useFactory: (moduleRef, discoveryService) => {
|
|
163
|
-
const discovered = discoverDecoratedCommands(discoveryService);
|
|
164
|
-
const merged = mergeCommandRegistrations(explicitCommands, discovered);
|
|
165
|
-
return new NestCommandRegistry(moduleRef, merged);
|
|
166
|
-
},
|
|
167
|
-
inject: [ModuleRef, DiscoveryService],
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
provide: WORKFLOW_GUARD_REGISTRY,
|
|
171
|
-
useFactory: (config) => {
|
|
172
|
-
if (config.guardRegistry && config.guards && config.guards.length > 0) {
|
|
173
|
-
throw new Error("WorkflowModule: cannot supply both `guards` and `guardRegistry` — they are mutually exclusive. Pass guards or a custom registry, not both.");
|
|
174
|
-
}
|
|
175
|
-
if (config.guardRegistry)
|
|
176
|
-
return config.guardRegistry;
|
|
177
|
-
const registry = new InMemoryGuardRegistry();
|
|
178
|
-
for (const guard of config.guards ?? []) {
|
|
179
|
-
registry.register(guard.name, guard);
|
|
180
|
-
}
|
|
181
|
-
return registry;
|
|
182
|
-
},
|
|
183
|
-
inject: ["WORKFLOW_MODULE_OPTIONS"],
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
provide: WORKFLOW_DEFINITION_REGISTRY,
|
|
187
|
-
useFactory: (config, commandRegistry) => {
|
|
188
|
-
const knownCommandNames = commandRegistry.getRegisteredNames();
|
|
189
|
-
// Validate guard refs only when we own the registry (built-in path).
|
|
190
|
-
// With a custom guardRegistry we can't enumerate names, so skip;
|
|
191
|
-
// unresolved refs surface at runtime as WorkflowError.
|
|
192
|
-
const knownGuardNames = config.guardRegistry !== undefined ? undefined : new Set((config.guards ?? []).map((g) => g.name));
|
|
193
|
-
const registry = new InMemoryDefinitionRegistry({
|
|
194
|
-
validator: new WorkflowValidator(),
|
|
195
|
-
compiler: new WorkflowCompiler(),
|
|
196
|
-
validationOptions: { knownCommandNames, knownGuardNames },
|
|
197
|
-
onValidationWarning: logValidationWarning,
|
|
198
|
-
});
|
|
199
|
-
for (const workflow of config.workflows) {
|
|
200
|
-
registry.register(workflow);
|
|
201
|
-
}
|
|
202
|
-
return registry;
|
|
203
|
-
},
|
|
204
|
-
inject: ["WORKFLOW_MODULE_OPTIONS", WORKFLOW_COMMAND_REGISTRY],
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
provide: WORKFLOW_INSTANCE_STORE,
|
|
208
|
-
useFactory: (config) => config.persistence.instanceStore,
|
|
209
|
-
inject: ["WORKFLOW_MODULE_OPTIONS"],
|
|
210
|
-
},
|
|
211
|
-
{
|
|
212
|
-
provide: WORKFLOW_HISTORY_STORE,
|
|
213
|
-
useFactory: (config) => config.persistence.historyStore,
|
|
214
|
-
inject: ["WORKFLOW_MODULE_OPTIONS"],
|
|
215
|
-
},
|
|
216
|
-
{
|
|
217
|
-
provide: WORKFLOW_TRANSACTION_RUNNER,
|
|
218
|
-
useFactory: (config) => config.persistence.transactionRunner,
|
|
219
|
-
inject: ["WORKFLOW_MODULE_OPTIONS"],
|
|
220
|
-
},
|
|
221
|
-
{
|
|
222
|
-
provide: WORKFLOW_CLOCK,
|
|
223
|
-
useFactory: (config) => config.clock ?? { now: () => new Date() },
|
|
224
|
-
inject: ["WORKFLOW_MODULE_OPTIONS"],
|
|
225
|
-
},
|
|
226
|
-
{
|
|
227
|
-
provide: WORKFLOW_RUNTIME,
|
|
228
|
-
useFactory: (config, definitionRegistry, commandRegistry, guardRegistry, instanceStore, historyStore, transactionRunner, clock) => new WorkflowRuntime({
|
|
229
|
-
definitionRegistry,
|
|
230
|
-
commandRegistry,
|
|
231
|
-
guardRegistry,
|
|
232
|
-
instanceStore,
|
|
233
|
-
historyStore,
|
|
234
|
-
transactionRunner,
|
|
235
|
-
clock,
|
|
236
|
-
observers: config.observers,
|
|
237
|
-
onObserverError: config.onObserverError,
|
|
238
|
-
}),
|
|
239
|
-
inject: [
|
|
240
|
-
"WORKFLOW_MODULE_OPTIONS",
|
|
241
|
-
WORKFLOW_DEFINITION_REGISTRY,
|
|
242
|
-
WORKFLOW_COMMAND_REGISTRY,
|
|
243
|
-
WORKFLOW_GUARD_REGISTRY,
|
|
244
|
-
WORKFLOW_INSTANCE_STORE,
|
|
245
|
-
WORKFLOW_HISTORY_STORE,
|
|
246
|
-
WORKFLOW_TRANSACTION_RUNNER,
|
|
247
|
-
WORKFLOW_CLOCK,
|
|
248
|
-
],
|
|
249
|
-
},
|
|
250
|
-
WorkflowService,
|
|
251
|
-
WorkflowTimeoutService,
|
|
252
|
-
];
|
|
253
180
|
return {
|
|
254
181
|
module: WorkflowModule_1,
|
|
255
182
|
global: true, // allow downstream feature modules to inject WorkflowService without re-importing forRootAsync
|
|
256
183
|
imports: [DiscoveryModule, ...(options.imports ?? [])],
|
|
257
|
-
controllers,
|
|
258
|
-
providers
|
|
184
|
+
controllers: options.enableControllers ? [...CONTROLLERS] : [],
|
|
185
|
+
providers: [
|
|
186
|
+
{
|
|
187
|
+
provide: WORKFLOW_MODULE_OPTIONS,
|
|
188
|
+
useFactory: options.useFactory,
|
|
189
|
+
inject: (options.inject ?? []),
|
|
190
|
+
},
|
|
191
|
+
...buildWorkflowProviders(options.commands ?? []),
|
|
192
|
+
],
|
|
259
193
|
exports: EXPORTED_TOKENS,
|
|
260
194
|
};
|
|
261
195
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@duraflows/nestjs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "NestJS integration for duraflows: dependency injection, services, optional REST controllers, and @WorkflowCommand decorator for DI-backed command handlers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"duraflows",
|
|
@@ -54,17 +54,17 @@
|
|
|
54
54
|
"class-validator": "^0.15.1"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"@duraflows/core": "^
|
|
57
|
+
"@duraflows/core": "^4.0.1",
|
|
58
58
|
"@nestjs/common": "^11.0.0",
|
|
59
59
|
"@nestjs/core": "^11.0.0",
|
|
60
60
|
"reflect-metadata": "^0.2.0",
|
|
61
61
|
"rxjs": "^7.0.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"@nestjs/common": "^11.1.
|
|
65
|
-
"@nestjs/core": "^11.1.
|
|
66
|
-
"@nestjs/testing": "^11.1.
|
|
67
|
-
"@duraflows/core": "
|
|
64
|
+
"@nestjs/common": "^11.1.28",
|
|
65
|
+
"@nestjs/core": "^11.1.28",
|
|
66
|
+
"@nestjs/testing": "^11.1.28",
|
|
67
|
+
"@duraflows/core": "4.0.1"
|
|
68
68
|
},
|
|
69
69
|
"scripts": {
|
|
70
70
|
"build": "tsc --build"
|