arvo-event-handler 3.0.14 → 3.0.15
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/ArvoEventHandler/index.d.ts +20 -123
- package/dist/ArvoEventHandler/index.js +5 -112
- package/dist/ArvoMachine/createMachine.d.ts +103 -158
- package/dist/ArvoMachine/createMachine.js +59 -181
- package/dist/ArvoMachine/index.d.ts +5 -57
- package/dist/ArvoMachine/index.js +8 -117
- package/dist/ArvoMachine/types.d.ts +0 -82
- package/dist/ArvoMachine/utils.d.ts +0 -15
- package/dist/ArvoMachine/utils.js +0 -15
- package/dist/ArvoOrchestrationUtils/createEmitableEvent.d.ts +31 -0
- package/dist/ArvoOrchestrationUtils/createEmitableEvent.js +18 -0
- package/dist/ArvoOrchestrationUtils/error.d.ts +22 -0
- package/dist/ArvoOrchestrationUtils/error.js +21 -0
- package/dist/ArvoOrchestrationUtils/handlerErrors.d.ts +30 -2
- package/dist/ArvoOrchestrationUtils/handlerErrors.js +19 -2
- package/dist/ArvoOrchestrationUtils/inputValidation.d.ts +47 -0
- package/dist/ArvoOrchestrationUtils/inputValidation.js +120 -0
- package/dist/ArvoOrchestrationUtils/orchestrationExecutionState.d.ts +24 -1
- package/dist/ArvoOrchestrationUtils/orchestrationExecutionState.js +9 -1
- package/dist/ArvoOrchestrationUtils/orchestrationExecutionWrapper/acquireLockWithValidation.d.ts +5 -1
- package/dist/ArvoOrchestrationUtils/orchestrationExecutionWrapper/acquireLockWithValidation.js +5 -1
- package/dist/ArvoOrchestrationUtils/orchestrationExecutionWrapper/index.d.ts +44 -5
- package/dist/ArvoOrchestrationUtils/orchestrationExecutionWrapper/index.js +17 -5
- package/dist/ArvoOrchestrationUtils/orchestrationExecutionWrapper/validateAndParseSubject.d.ts +6 -1
- package/dist/ArvoOrchestrationUtils/orchestrationExecutionWrapper/validateAndParseSubject.js +6 -1
- package/dist/ArvoOrchestrationUtils/servicesValidation.d.ts +14 -6
- package/dist/ArvoOrchestrationUtils/servicesValidation.js +14 -6
- package/dist/ArvoOrchestrator/factory.d.ts +18 -15
- package/dist/ArvoOrchestrator/factory.js +19 -16
- package/dist/ArvoOrchestrator/index.d.ts +51 -19
- package/dist/ArvoOrchestrator/index.js +29 -17
- package/dist/ArvoOrchestrator/types.d.ts +74 -49
- package/dist/ArvoResumable/factory.d.ts +31 -36
- package/dist/ArvoResumable/factory.js +29 -18
- package/dist/ArvoResumable/index.d.ts +69 -65
- package/dist/ArvoResumable/index.js +49 -92
- package/dist/ArvoResumable/types.d.ts +177 -72
- package/dist/IArvoEventHandler/index.d.ts +29 -15
- package/package.json +2 -2
|
@@ -3,84 +3,8 @@ import type IArvoEventHandler from '../IArvoEventHandler';
|
|
|
3
3
|
import type { ArvoEventHandlerOpenTelemetryOptions, ArvoEventHandlerOtelSpanOptions } from '../types';
|
|
4
4
|
import type { ArvoEventHandlerFunction, ArvoEventHandlerParam } from './types';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* The foundational component for building stateless,
|
|
7
7
|
* contract-bound services in the Arvo system.
|
|
8
|
-
*
|
|
9
|
-
* It enforces strict contract validation, version-aware handler resolution,
|
|
10
|
-
* and safe, observable event emission — all while maintaining type safety,
|
|
11
|
-
* traceability, and support for multi-domain workflows.
|
|
12
|
-
*
|
|
13
|
-
* ## What It Does
|
|
14
|
-
* - Ensures incoming events match the contract's `type` and `dataschema`
|
|
15
|
-
* - Resolves the correct contract version using `dataschema`
|
|
16
|
-
* - Validates input and output data via Zod schemas
|
|
17
|
-
* - Executes the version-specific handler function
|
|
18
|
-
* - Emits one or more response events based on the handler result
|
|
19
|
-
* - Supports multi-domain broadcasting via `domain[]` on the emitted events
|
|
20
|
-
* - Automatically emits system error events (`sys.*.error`) on failure
|
|
21
|
-
* - Integrates deeply with OpenTelemetry for tracing and observability
|
|
22
|
-
*
|
|
23
|
-
* ## Error Boundaries
|
|
24
|
-
* ArvoEventHandler enforces a clear separation between:
|
|
25
|
-
*
|
|
26
|
-
* - **Violations** — structural, schema, or config errors that break the contract.
|
|
27
|
-
* These are thrown and must be handled explicitly by the caller.
|
|
28
|
-
*
|
|
29
|
-
* - **System Errors** — runtime exceptions during execution that are caught and
|
|
30
|
-
* emitted as standardized `sys.<contract>.error` events.
|
|
31
|
-
*
|
|
32
|
-
* ## Domain Broadcasting
|
|
33
|
-
* The handler supports multi-domain event distribution. When the handler
|
|
34
|
-
* returns an event with a `domain` array, it is broadcast to one or more
|
|
35
|
-
* routing contexts.
|
|
36
|
-
*
|
|
37
|
-
* ### System Error Domain Control
|
|
38
|
-
* By default, system error events are broadcast into the source event’s domain,
|
|
39
|
-
* the handler’s contract domain, and the `null` domain. This fallback ensures errors
|
|
40
|
-
* are visible across all relevant contexts. Developers can override this behavior
|
|
41
|
-
* using the optional `systemErrorDomain` field to specify an explicit set of
|
|
42
|
-
* domain values, including symbolic constants from {@link ArvoDomain}.
|
|
43
|
-
*
|
|
44
|
-
* ### Supported Domain Values:
|
|
45
|
-
* - A **concrete domain string** like `'audit.orders'` or `'human.review'`
|
|
46
|
-
* - `null` to emit with no domain (standard internal flow)
|
|
47
|
-
* - A **symbolic reference** from {@link ArvoDomain}
|
|
48
|
-
*
|
|
49
|
-
* ### Domain Resolution Rules:
|
|
50
|
-
* - Each item in the `domain` array is resolved via {@link resolveEventDomain}
|
|
51
|
-
* - Duplicate domains are deduplicated before emitting
|
|
52
|
-
* - If `domain` is omitted entirely, Arvo defaults to `[null]`
|
|
53
|
-
*
|
|
54
|
-
* ### Example:
|
|
55
|
-
* ```ts
|
|
56
|
-
* return {
|
|
57
|
-
* type: 'evt.user.registered',
|
|
58
|
-
* data: { ... },
|
|
59
|
-
* domain: ['analytics', ArvoDomain.FROM_TRIGGERING_EVENT, null]
|
|
60
|
-
* };
|
|
61
|
-
* ```
|
|
62
|
-
* This would emit at most 3 copies of the event, domained to:
|
|
63
|
-
* - `'analytics'`
|
|
64
|
-
* - the domain of the incoming event
|
|
65
|
-
* - no domain (default)
|
|
66
|
-
*
|
|
67
|
-
* ### Domain Usage Guidance
|
|
68
|
-
*
|
|
69
|
-
* > **Avoid setting `contract.domain` unless fully intentional.**
|
|
70
|
-
* 99% emitted event should default to `null` (standard processing pipeline).
|
|
71
|
-
*
|
|
72
|
-
* Contract-level domains enforce implicit routing for every emitted event
|
|
73
|
-
* in that handler, making the behavior harder to override and debug.
|
|
74
|
-
*
|
|
75
|
-
* Prefer:
|
|
76
|
-
* - Explicit per-event `domain` values in handler output
|
|
77
|
-
* - Using `null` or symbolic constants to control domain cleanly
|
|
78
|
-
*
|
|
79
|
-
* ## When to Use Domains
|
|
80
|
-
* Use domains when handling for specialized contexts:
|
|
81
|
-
* - `'human.review'` → for human-in-the-loop steps
|
|
82
|
-
* - `'analytics.workflow'` → to pipe events into observability systems
|
|
83
|
-
* - `'external.partner.sync'` → to route to external services
|
|
84
8
|
*/
|
|
85
9
|
export default class ArvoEventHandler<TContract extends ArvoContract> implements IArvoEventHandler {
|
|
86
10
|
/** Contract instance that defines the event schema and validation rules */
|
|
@@ -93,35 +17,16 @@ export default class ArvoEventHandler<TContract extends ArvoContract> implements
|
|
|
93
17
|
readonly handler: ArvoEventHandlerFunction<TContract>;
|
|
94
18
|
/** The source identifier for events produced by this handler */
|
|
95
19
|
get source(): TContract['type'];
|
|
20
|
+
/** Optional domains for routing system error events */
|
|
96
21
|
readonly systemErrorDomain?: (string | null)[];
|
|
97
|
-
/**
|
|
98
|
-
* The contract-defined domain for this handler, used as the default domain for emitted events.
|
|
99
|
-
* Can be overridden by individual handler implementations for cross-domain workflows.
|
|
100
|
-
* Returns null if no domain is specified, indicating standard processing context.
|
|
101
|
-
*/
|
|
22
|
+
/** The contract-defined domain for the handler */
|
|
102
23
|
get domain(): string | null;
|
|
103
|
-
/**
|
|
104
|
-
* Initializes a new ArvoEventHandler instance with the specified contract and configuration.
|
|
105
|
-
* Validates handler implementations against contract versions during initialization.
|
|
106
|
-
*
|
|
107
|
-
* The constructor ensures that handler implementations exist for all supported contract
|
|
108
|
-
* versions and configures OpenTelemetry span attributes for monitoring event handling.
|
|
109
|
-
*
|
|
110
|
-
* @param param - Handler configuration including contract, execution units, and handler implementations
|
|
111
|
-
* @throws When handler implementations are missing for any contract version
|
|
112
|
-
*/
|
|
113
24
|
constructor(param: ArvoEventHandlerParam<TContract>);
|
|
114
25
|
/**
|
|
115
26
|
* Processes an incoming event according to the handler's contract specifications. This method
|
|
116
27
|
* handles the complete lifecycle of event processing including validation, execution, error
|
|
117
28
|
* handling, and multi-domain event broadcasting, while maintaining detailed telemetry through OpenTelemetry.
|
|
118
29
|
*
|
|
119
|
-
* @param event - The incoming event to process
|
|
120
|
-
* @param opentelemetry - Configuration for OpenTelemetry context inheritance, defaults to inheriting from the event
|
|
121
|
-
* @returns Promise resolving to a structured result containing an array of output events
|
|
122
|
-
* @returns Structured response containing:
|
|
123
|
-
* - `events`: Array of events to be emitted (may contain multiple events per handler output due to domain broadcasting)
|
|
124
|
-
*
|
|
125
30
|
* @throws {ContractViolation} when input or output event data violates the contract schema,
|
|
126
31
|
* or when event emission fails due to invalid data
|
|
127
32
|
* @throws {ConfigViolation} when event type doesn't match contract type, when the
|
|
@@ -134,30 +39,22 @@ export default class ArvoEventHandler<TContract extends ArvoContract> implements
|
|
|
134
39
|
}>;
|
|
135
40
|
/**
|
|
136
41
|
* Provides access to the system error event schema configuration.
|
|
137
|
-
*
|
|
138
|
-
* The schema defines the structure of error events emitted during execution failures.
|
|
139
|
-
* These events are automatically generated when runtime errors occur and follow a
|
|
140
|
-
* standardized format for consistent error handling across the system.
|
|
141
|
-
*
|
|
142
|
-
* Error events follow the naming convention: `sys.<contract-type>.error`
|
|
143
|
-
*
|
|
144
|
-
* @example
|
|
145
|
-
* For a contract handling 'com.user.create' events, system error events
|
|
146
|
-
* will have the type 'sys.com.user.create.error'
|
|
147
|
-
*
|
|
148
|
-
* @returns The error event schema containing type and validation rules
|
|
149
42
|
*/
|
|
150
|
-
get systemErrorSchema():
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
43
|
+
get systemErrorSchema(): {
|
|
44
|
+
domain: (string | null)[] | undefined;
|
|
45
|
+
type: `sys.${string}.error`;
|
|
46
|
+
schema: import("zod").ZodObject<{
|
|
47
|
+
errorName: import("zod").ZodString;
|
|
48
|
+
errorMessage: import("zod").ZodString;
|
|
49
|
+
errorStack: import("zod").ZodNullable<import("zod").ZodString>;
|
|
50
|
+
}, "strip", import("zod").ZodTypeAny, {
|
|
51
|
+
errorName: string;
|
|
52
|
+
errorMessage: string;
|
|
53
|
+
errorStack: string | null;
|
|
54
|
+
}, {
|
|
55
|
+
errorName: string;
|
|
56
|
+
errorMessage: string;
|
|
57
|
+
errorStack: string | null;
|
|
58
|
+
}>;
|
|
59
|
+
};
|
|
163
60
|
}
|
|
@@ -66,99 +66,14 @@ var orchestrationExecutionWrapper_1 = require("../ArvoOrchestrationUtils/orchest
|
|
|
66
66
|
var errors_1 = require("../errors");
|
|
67
67
|
var utils_1 = require("../utils");
|
|
68
68
|
/**
|
|
69
|
-
*
|
|
69
|
+
* The foundational component for building stateless,
|
|
70
70
|
* contract-bound services in the Arvo system.
|
|
71
|
-
*
|
|
72
|
-
* It enforces strict contract validation, version-aware handler resolution,
|
|
73
|
-
* and safe, observable event emission — all while maintaining type safety,
|
|
74
|
-
* traceability, and support for multi-domain workflows.
|
|
75
|
-
*
|
|
76
|
-
* ## What It Does
|
|
77
|
-
* - Ensures incoming events match the contract's `type` and `dataschema`
|
|
78
|
-
* - Resolves the correct contract version using `dataschema`
|
|
79
|
-
* - Validates input and output data via Zod schemas
|
|
80
|
-
* - Executes the version-specific handler function
|
|
81
|
-
* - Emits one or more response events based on the handler result
|
|
82
|
-
* - Supports multi-domain broadcasting via `domain[]` on the emitted events
|
|
83
|
-
* - Automatically emits system error events (`sys.*.error`) on failure
|
|
84
|
-
* - Integrates deeply with OpenTelemetry for tracing and observability
|
|
85
|
-
*
|
|
86
|
-
* ## Error Boundaries
|
|
87
|
-
* ArvoEventHandler enforces a clear separation between:
|
|
88
|
-
*
|
|
89
|
-
* - **Violations** — structural, schema, or config errors that break the contract.
|
|
90
|
-
* These are thrown and must be handled explicitly by the caller.
|
|
91
|
-
*
|
|
92
|
-
* - **System Errors** — runtime exceptions during execution that are caught and
|
|
93
|
-
* emitted as standardized `sys.<contract>.error` events.
|
|
94
|
-
*
|
|
95
|
-
* ## Domain Broadcasting
|
|
96
|
-
* The handler supports multi-domain event distribution. When the handler
|
|
97
|
-
* returns an event with a `domain` array, it is broadcast to one or more
|
|
98
|
-
* routing contexts.
|
|
99
|
-
*
|
|
100
|
-
* ### System Error Domain Control
|
|
101
|
-
* By default, system error events are broadcast into the source event’s domain,
|
|
102
|
-
* the handler’s contract domain, and the `null` domain. This fallback ensures errors
|
|
103
|
-
* are visible across all relevant contexts. Developers can override this behavior
|
|
104
|
-
* using the optional `systemErrorDomain` field to specify an explicit set of
|
|
105
|
-
* domain values, including symbolic constants from {@link ArvoDomain}.
|
|
106
|
-
*
|
|
107
|
-
* ### Supported Domain Values:
|
|
108
|
-
* - A **concrete domain string** like `'audit.orders'` or `'human.review'`
|
|
109
|
-
* - `null` to emit with no domain (standard internal flow)
|
|
110
|
-
* - A **symbolic reference** from {@link ArvoDomain}
|
|
111
|
-
*
|
|
112
|
-
* ### Domain Resolution Rules:
|
|
113
|
-
* - Each item in the `domain` array is resolved via {@link resolveEventDomain}
|
|
114
|
-
* - Duplicate domains are deduplicated before emitting
|
|
115
|
-
* - If `domain` is omitted entirely, Arvo defaults to `[null]`
|
|
116
|
-
*
|
|
117
|
-
* ### Example:
|
|
118
|
-
* ```ts
|
|
119
|
-
* return {
|
|
120
|
-
* type: 'evt.user.registered',
|
|
121
|
-
* data: { ... },
|
|
122
|
-
* domain: ['analytics', ArvoDomain.FROM_TRIGGERING_EVENT, null]
|
|
123
|
-
* };
|
|
124
|
-
* ```
|
|
125
|
-
* This would emit at most 3 copies of the event, domained to:
|
|
126
|
-
* - `'analytics'`
|
|
127
|
-
* - the domain of the incoming event
|
|
128
|
-
* - no domain (default)
|
|
129
|
-
*
|
|
130
|
-
* ### Domain Usage Guidance
|
|
131
|
-
*
|
|
132
|
-
* > **Avoid setting `contract.domain` unless fully intentional.**
|
|
133
|
-
* 99% emitted event should default to `null` (standard processing pipeline).
|
|
134
|
-
*
|
|
135
|
-
* Contract-level domains enforce implicit routing for every emitted event
|
|
136
|
-
* in that handler, making the behavior harder to override and debug.
|
|
137
|
-
*
|
|
138
|
-
* Prefer:
|
|
139
|
-
* - Explicit per-event `domain` values in handler output
|
|
140
|
-
* - Using `null` or symbolic constants to control domain cleanly
|
|
141
|
-
*
|
|
142
|
-
* ## When to Use Domains
|
|
143
|
-
* Use domains when handling for specialized contexts:
|
|
144
|
-
* - `'human.review'` → for human-in-the-loop steps
|
|
145
|
-
* - `'analytics.workflow'` → to pipe events into observability systems
|
|
146
|
-
* - `'external.partner.sync'` → to route to external services
|
|
147
71
|
*/
|
|
148
72
|
var ArvoEventHandler = /** @class */ (function () {
|
|
149
|
-
/**
|
|
150
|
-
* Initializes a new ArvoEventHandler instance with the specified contract and configuration.
|
|
151
|
-
* Validates handler implementations against contract versions during initialization.
|
|
152
|
-
*
|
|
153
|
-
* The constructor ensures that handler implementations exist for all supported contract
|
|
154
|
-
* versions and configures OpenTelemetry span attributes for monitoring event handling.
|
|
155
|
-
*
|
|
156
|
-
* @param param - Handler configuration including contract, execution units, and handler implementations
|
|
157
|
-
* @throws When handler implementations are missing for any contract version
|
|
158
|
-
*/
|
|
159
73
|
function ArvoEventHandler(param) {
|
|
160
74
|
var _a;
|
|
161
75
|
var _b, _c;
|
|
76
|
+
/** Optional domains for routing system error events */
|
|
162
77
|
this.systemErrorDomain = undefined;
|
|
163
78
|
this.contract = param.contract;
|
|
164
79
|
this.executionunits = param.executionunits;
|
|
@@ -181,11 +96,7 @@ var ArvoEventHandler = /** @class */ (function () {
|
|
|
181
96
|
configurable: true
|
|
182
97
|
});
|
|
183
98
|
Object.defineProperty(ArvoEventHandler.prototype, "domain", {
|
|
184
|
-
/**
|
|
185
|
-
* The contract-defined domain for this handler, used as the default domain for emitted events.
|
|
186
|
-
* Can be overridden by individual handler implementations for cross-domain workflows.
|
|
187
|
-
* Returns null if no domain is specified, indicating standard processing context.
|
|
188
|
-
*/
|
|
99
|
+
/** The contract-defined domain for the handler */
|
|
189
100
|
get: function () {
|
|
190
101
|
return this.contract.domain;
|
|
191
102
|
},
|
|
@@ -197,12 +108,6 @@ var ArvoEventHandler = /** @class */ (function () {
|
|
|
197
108
|
* handles the complete lifecycle of event processing including validation, execution, error
|
|
198
109
|
* handling, and multi-domain event broadcasting, while maintaining detailed telemetry through OpenTelemetry.
|
|
199
110
|
*
|
|
200
|
-
* @param event - The incoming event to process
|
|
201
|
-
* @param opentelemetry - Configuration for OpenTelemetry context inheritance, defaults to inheriting from the event
|
|
202
|
-
* @returns Promise resolving to a structured result containing an array of output events
|
|
203
|
-
* @returns Structured response containing:
|
|
204
|
-
* - `events`: Array of events to be emitted (may contain multiple events per handler output due to domain broadcasting)
|
|
205
|
-
*
|
|
206
111
|
* @throws {ContractViolation} when input or output event data violates the contract schema,
|
|
207
112
|
* or when event emission fails due to invalid data
|
|
208
113
|
* @throws {ConfigViolation} when event type doesn't match contract type, when the
|
|
@@ -351,7 +256,7 @@ var ArvoEventHandler = /** @class */ (function () {
|
|
|
351
256
|
orchestrationParentSubject: null,
|
|
352
257
|
initEventId: event.id,
|
|
353
258
|
selfContract: this.contract.version('any'),
|
|
354
|
-
systemErrorDomain:
|
|
259
|
+
systemErrorDomain: this.systemErrorDomain,
|
|
355
260
|
executionunits: this.executionunits,
|
|
356
261
|
source: this.source,
|
|
357
262
|
domain: this.domain,
|
|
@@ -382,21 +287,9 @@ var ArvoEventHandler = /** @class */ (function () {
|
|
|
382
287
|
Object.defineProperty(ArvoEventHandler.prototype, "systemErrorSchema", {
|
|
383
288
|
/**
|
|
384
289
|
* Provides access to the system error event schema configuration.
|
|
385
|
-
*
|
|
386
|
-
* The schema defines the structure of error events emitted during execution failures.
|
|
387
|
-
* These events are automatically generated when runtime errors occur and follow a
|
|
388
|
-
* standardized format for consistent error handling across the system.
|
|
389
|
-
*
|
|
390
|
-
* Error events follow the naming convention: `sys.<contract-type>.error`
|
|
391
|
-
*
|
|
392
|
-
* @example
|
|
393
|
-
* For a contract handling 'com.user.create' events, system error events
|
|
394
|
-
* will have the type 'sys.com.user.create.error'
|
|
395
|
-
*
|
|
396
|
-
* @returns The error event schema containing type and validation rules
|
|
397
290
|
*/
|
|
398
291
|
get: function () {
|
|
399
|
-
return this.contract.systemError;
|
|
292
|
+
return __assign(__assign({}, this.contract.systemError), { domain: this.systemErrorDomain });
|
|
400
293
|
},
|
|
401
294
|
enumerable: false,
|
|
402
295
|
configurable: true
|
|
@@ -6,176 +6,85 @@ import type { EnqueueArvoEventActionParam, ExtractOrchestratorType, InferService
|
|
|
6
6
|
/**
|
|
7
7
|
* Establishes the foundation for creating Arvo-compatible state machines.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* to ensure compatibility with the Arvo event-driven system.
|
|
9
|
+
* Designed for synchronous state machine orchestrations in Arvo's event-driven architecture.
|
|
10
|
+
* Builds upon XState with Arvo-specific constraints to enforce predictable state transitions.
|
|
12
11
|
*
|
|
13
|
-
* @
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* It builds upon XState, providing a tailored implementation that:
|
|
21
|
-
*
|
|
22
|
-
* 1. Enforces synchronous behavior to maintain predictable state transitions
|
|
23
|
-
* 3. Implements Arvo-specific constraints and features
|
|
24
|
-
*
|
|
25
|
-
* Key features:
|
|
26
|
-
* - Synchronous execution: Ensures deterministic behavior in event-driven systems
|
|
27
|
-
* - Built-in actions: Includes `enqueueArvoEvent` for Arvo event handling
|
|
28
|
-
* - Constraint checking: Prevents usage of asynchronous features like 'actors' or 'delays'
|
|
29
|
-
*
|
|
30
|
-
* @remarks
|
|
31
|
-
* While `setupArvoMachine` is based on XState's `setup` and `createMachine` functions,
|
|
32
|
-
* it includes Arvo-specific modifications and restrictions. For a deeper understanding
|
|
33
|
-
* of the underlying XState concepts, refer to the official XState documentation:
|
|
34
|
-
* - XState setup: https://stately.ai/docs/setup
|
|
35
|
-
* - XState createMachine: https://stately.ai/docs/machines
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* Here's a comprehensive example demonstrating how to use `setupArvoMachine`:
|
|
39
|
-
*
|
|
40
|
-
* ```typescript
|
|
41
|
-
* import { setupArvoMachine } from 'arvo-xstate'
|
|
42
|
-
* import { createArvoOrchestratorContract, ArvoErrorSchema, createArvoContract } from 'arvo-core'
|
|
43
|
-
* import { z } from 'zod'
|
|
44
|
-
*
|
|
45
|
-
* // Define the LLM orchestrator contract
|
|
46
|
-
* const llmContract = createArvoOrchestratorContract({
|
|
47
|
-
* uri: `#/orchestrators/llm/`,
|
|
48
|
-
* type: 'llm',
|
|
49
|
-
* versions: {
|
|
50
|
-
* '0.0.1': {
|
|
51
|
-
* init: z.object({
|
|
52
|
-
* request: z.string(),
|
|
53
|
-
* llm: z.enum(['gpt-4', 'gpt-4o']),
|
|
54
|
-
* }),
|
|
55
|
-
* complete: z.object({
|
|
56
|
-
* response: z.string(),
|
|
57
|
-
* })
|
|
58
|
-
* }
|
|
59
|
-
* }
|
|
60
|
-
* })
|
|
61
|
-
*
|
|
62
|
-
* // Define the OpenAI service contract
|
|
63
|
-
* const openAiContract = createArvoContract({
|
|
64
|
-
* uri: `#/services/openai`,
|
|
65
|
-
* type: 'com.openai.completions',
|
|
66
|
-
* versions: {
|
|
67
|
-
* '0.0.1': {
|
|
68
|
-
* accepts: z.object({
|
|
69
|
-
* request: z.string()
|
|
70
|
-
* }),
|
|
71
|
-
* emits: {
|
|
72
|
-
* 'evt.openai.completions.success': z.object({
|
|
73
|
-
* response: z.string(),
|
|
74
|
-
* })
|
|
75
|
-
* }
|
|
76
|
-
* }
|
|
77
|
-
* }
|
|
78
|
-
* })
|
|
79
|
-
*
|
|
80
|
-
* const machineId = 'machineV100'
|
|
81
|
-
*
|
|
82
|
-
* // Set up the Arvo machine
|
|
83
|
-
* const llmMachine = setupArvoMachine({
|
|
84
|
-
* contracts: {
|
|
85
|
-
* self: llmContract.version('0.0.1'),
|
|
86
|
-
* services: {
|
|
87
|
-
* openAiContract.version('0.0.1'),
|
|
88
|
-
* }
|
|
89
|
-
* },
|
|
90
|
-
* types: {
|
|
91
|
-
* context: {} as {
|
|
92
|
-
* request: string,
|
|
93
|
-
* llm: string,
|
|
94
|
-
* response: string | null,
|
|
95
|
-
* errors: z.infer<typeof ArvoErrorSchema>[]
|
|
96
|
-
* },
|
|
97
|
-
* tags: {} as 'pending' | 'success' | 'error',
|
|
98
|
-
* },
|
|
99
|
-
* actions: {
|
|
100
|
-
* log: ({context, event}) => console.log({context, event})
|
|
101
|
-
* },
|
|
102
|
-
* guards: {
|
|
103
|
-
* isValid: ({context, event}) => Boolean(context.request)
|
|
104
|
-
* }
|
|
105
|
-
* }).createMachine({
|
|
106
|
-
* id: machineId,
|
|
107
|
-
* context: ({input}) => ({
|
|
108
|
-
* request: input.request,
|
|
109
|
-
* llm: input.llm,
|
|
110
|
-
* response: null,
|
|
111
|
-
* errors: [],
|
|
112
|
-
* }),
|
|
113
|
-
* initial: 'validate',
|
|
114
|
-
* states: {
|
|
115
|
-
* validate: {
|
|
116
|
-
* always: [
|
|
117
|
-
* {
|
|
118
|
-
* guard: 'isValid',
|
|
119
|
-
* target: 'llm',
|
|
120
|
-
* },
|
|
121
|
-
* {
|
|
122
|
-
* target: 'error',
|
|
123
|
-
* }
|
|
124
|
-
* ]
|
|
125
|
-
* },
|
|
126
|
-
* llm: {
|
|
127
|
-
* entry: [
|
|
128
|
-
* {
|
|
129
|
-
* type: 'log',
|
|
130
|
-
* },
|
|
131
|
-
* emit(({context}) => ({
|
|
132
|
-
* type: 'com.openai.completions',
|
|
133
|
-
* data: {
|
|
134
|
-
* request: context.request,
|
|
135
|
-
* },
|
|
136
|
-
* }))
|
|
137
|
-
* ],
|
|
138
|
-
* on: {
|
|
139
|
-
* 'evt.openai.completions.success': {
|
|
140
|
-
* actions: [
|
|
141
|
-
* assign({response: ({event}) => event.response})
|
|
142
|
-
* ],
|
|
143
|
-
* target: 'done'
|
|
144
|
-
* },
|
|
145
|
-
* 'sys.com.openai.completions.error': {
|
|
146
|
-
* actions: [
|
|
147
|
-
* assign({errors: ({context, event}) => [...context.errors, event.body]})
|
|
148
|
-
* ],
|
|
149
|
-
* target: 'error'
|
|
150
|
-
* }
|
|
151
|
-
* }
|
|
152
|
-
* },
|
|
153
|
-
* done: {
|
|
154
|
-
* type: 'final'
|
|
155
|
-
* },
|
|
156
|
-
* error: {
|
|
157
|
-
* type: 'final'
|
|
158
|
-
* },
|
|
159
|
-
* }
|
|
160
|
-
* });
|
|
161
|
-
* ```
|
|
162
|
-
*
|
|
163
|
-
* This example demonstrates:
|
|
164
|
-
* 1. Defining Arvo contracts for the orchestrator and a service
|
|
165
|
-
* 2. Setting up an Arvo machine with contracts, types, actions, and guards
|
|
166
|
-
* 3. Creating a machine with states for validation, LLM interaction, and error handling
|
|
167
|
-
* 4. Using XState features like `emit` bound with Arvo contracts for event emitting and event handling via transitions
|
|
12
|
+
* @throws {ConfigViolation} When configuration violates Arvo constraints:
|
|
13
|
+
* - Using `actors` or `delays` (async behavior not supported)
|
|
14
|
+
* - Overriding reserved `enqueueArvoEvent` action name
|
|
15
|
+
* - Machine version mismatch with contract version
|
|
16
|
+
* - Using `invoke` or `after` in state configurations
|
|
17
|
+
* - Service contracts with duplicate URIs (multiple versions of same contract)
|
|
18
|
+
* - Circular dependency (self contract URI matches a service contract URI)
|
|
168
19
|
*/
|
|
169
20
|
export declare function setupArvoMachine<TContext extends MachineContext, TSelfContract extends VersionedArvoContract<any, any>, TServiceContracts extends Record<string, VersionedArvoContract<any, any>>, TActions extends Record<string, ParameterizedObject['params'] | undefined> = {}, TGuards extends Record<string, ParameterizedObject['params'] | undefined> = {}, TTag extends string = string, TMeta extends MetaObject = MetaObject>(param: {
|
|
170
21
|
schemas?: unknown;
|
|
22
|
+
/**
|
|
23
|
+
* Contract definitions for the machine's event interface.
|
|
24
|
+
* Defines what events the machine accepts, emits, and exchanges with services.
|
|
25
|
+
*/
|
|
171
26
|
contracts: {
|
|
27
|
+
/**
|
|
28
|
+
* Self contract defining the machine's initialization input structure
|
|
29
|
+
* and the completion output structure when the machine finishes execution.
|
|
30
|
+
*/
|
|
172
31
|
self: TSelfContract;
|
|
32
|
+
/**
|
|
33
|
+
* Service contracts defining the event interfaces for external services.
|
|
34
|
+
* Each service specifies the events it accepts and emits, enabling
|
|
35
|
+
* type-safe communication between the machine and its dependencies.
|
|
36
|
+
*/
|
|
173
37
|
services: TServiceContracts;
|
|
174
38
|
};
|
|
39
|
+
/**
|
|
40
|
+
* Type definitions for the machine's internal structure.
|
|
41
|
+
* Specifies the shape of context and other variables used throughout
|
|
42
|
+
* the machine's lifecycle. These types enable full type inference and safety.
|
|
43
|
+
*/
|
|
175
44
|
types?: Omit<SetupTypes<TContext, InferServiceContract<TServiceContracts>['events'], {}, TTag, InferVersionedArvoContract<TSelfContract>['accepts']['data'], InferVersionedArvoContract<TSelfContract>['emits'][ReturnType<typeof ArvoOrchestratorEventTypeGen.complete<ExtractOrchestratorType<TSelfContract['accepts']['type']>>>]['data'], InferServiceContract<TServiceContracts>['emitted'], TMeta>, 'input' | 'output' | 'children' | 'emitted'>;
|
|
45
|
+
/**
|
|
46
|
+
* Named action implementations that can be referenced throughout the machine.
|
|
47
|
+
* Actions perform side effects like data transformations, context updates,
|
|
48
|
+
* and event emissions. Each action receives the current context and event,
|
|
49
|
+
* along with any parameters defined in its type.
|
|
50
|
+
*
|
|
51
|
+
* For more information, see [xstate action docs](https://stately.ai/docs/actions)
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* actions: {
|
|
56
|
+
* updateUser: ({ context, event }, params) => {
|
|
57
|
+
* // Transform and update context
|
|
58
|
+
* },
|
|
59
|
+
* logEvent: ({ event }) => {
|
|
60
|
+
* // Log for debugging
|
|
61
|
+
* }
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
176
65
|
actions?: {
|
|
177
66
|
[K in keyof TActions]: ActionFunction<TContext, InferServiceContract<TServiceContracts>['events'], InferServiceContract<TServiceContracts>['events'], TActions[K], never, ToParameterizedObject<TActions>, ToParameterizedObject<TGuards>, never, InferServiceContract<TServiceContracts>['emitted']>;
|
|
178
67
|
};
|
|
68
|
+
/**
|
|
69
|
+
* Named guard implementations that control conditional state transitions.
|
|
70
|
+
* Guards are boolean functions that determine whether a transition should occur
|
|
71
|
+
* based on the current context and event. They enable dynamic flow control
|
|
72
|
+
* without side effects.
|
|
73
|
+
*
|
|
74
|
+
* For more information, see [xstate guard docs](https://stately.ai/docs/guards)
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* guards: {
|
|
79
|
+
* isAuthorized: ({ context, event }, params) => {
|
|
80
|
+
* return context.user.role === 'admin';
|
|
81
|
+
* },
|
|
82
|
+
* hasRequiredData: ({ context }) => {
|
|
83
|
+
* return context.data !== null;
|
|
84
|
+
* }
|
|
85
|
+
* }
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
179
88
|
guards?: {
|
|
180
89
|
[K in keyof TGuards]: (args: {
|
|
181
90
|
context: TContext;
|
|
@@ -183,6 +92,42 @@ export declare function setupArvoMachine<TContext extends MachineContext, TSelfC
|
|
|
183
92
|
}, params: TGuards[K]) => boolean;
|
|
184
93
|
};
|
|
185
94
|
}): {
|
|
95
|
+
/**
|
|
96
|
+
* Creates an Arvo-compatible state machine with the specified configuration.
|
|
97
|
+
*
|
|
98
|
+
* Constructs a fully-typed state machine that orchestrates event-driven workflows
|
|
99
|
+
* using the contracts and types defined in setup. The machine enforces synchronous
|
|
100
|
+
* execution and validates configuration against Arvo constraints.
|
|
101
|
+
*
|
|
102
|
+
* For more information, see [xstate state machine docs](https://stately.ai/docs/states)
|
|
103
|
+
* @returns {ArvoMachine} A configured Arvo machine ready for execution
|
|
104
|
+
* @throws {ConfigViolation} When configuration violates Arvo constraints (see {@link setupArvoMachine} docs)
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* const machine = setup.createMachine({
|
|
109
|
+
* id: 'machineV100',
|
|
110
|
+
* initial: 'verifying',
|
|
111
|
+
* context: ({ input }) => ({
|
|
112
|
+
* userId: input.data.userId,
|
|
113
|
+
* verified: false
|
|
114
|
+
* }),
|
|
115
|
+
* states: {
|
|
116
|
+
* verifying: {
|
|
117
|
+
* on: {
|
|
118
|
+
* 'com.user.verified': {
|
|
119
|
+
* target: 'active',
|
|
120
|
+
* actions: { type: 'updateUser' }
|
|
121
|
+
* }
|
|
122
|
+
* }
|
|
123
|
+
* },
|
|
124
|
+
* active: {
|
|
125
|
+
* type: 'final'
|
|
126
|
+
* }
|
|
127
|
+
* }
|
|
128
|
+
* });
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
186
131
|
createMachine: <const TConfig extends MachineConfig<TContext, InferServiceContract<TServiceContracts>["events"], ToProvidedActor<{}, {}>, ToParameterizedObject<TActions & {
|
|
187
132
|
enqueueArvoEvent: EnqueueArvoEventActionParam;
|
|
188
133
|
}>, ToParameterizedObject<TGuards>, never, TTag, InferVersionedArvoContract<TSelfContract>["accepts"], z.input<TSelfContract["emits"][ReturnType<typeof ArvoOrchestratorEventTypeGen.complete<ExtractOrchestratorType<TSelfContract["accepts"]["type"]>>>]> & {
|