arvo-event-handler 2.3.3 → 3.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/AbstractArvoEventHandler/index.d.ts +1 -1
- package/dist/ArvoEventHandler/helpers.d.ts +40 -6
- package/dist/ArvoEventHandler/helpers.js +40 -6
- package/dist/ArvoEventHandler/index.d.ts +78 -49
- package/dist/ArvoEventHandler/index.js +151 -82
- package/dist/ArvoEventHandler/types.d.ts +25 -2
- package/dist/ArvoMachine/createMachine.d.ts +208 -0
- package/dist/ArvoMachine/createMachine.js +283 -0
- package/dist/ArvoMachine/index.d.ts +93 -0
- package/dist/ArvoMachine/index.js +160 -0
- package/dist/ArvoMachine/types.d.ts +194 -0
- package/dist/ArvoMachine/utils.d.ts +40 -0
- package/dist/ArvoMachine/utils.js +70 -0
- package/dist/ArvoOrchestrator/error.d.ts +16 -0
- package/dist/ArvoOrchestrator/error.js +43 -0
- package/dist/ArvoOrchestrator/factory.d.ts +28 -0
- package/dist/ArvoOrchestrator/factory.js +56 -0
- package/dist/ArvoOrchestrator/index.d.ts +69 -0
- package/dist/ArvoOrchestrator/index.js +597 -0
- package/dist/ArvoOrchestrator/types.d.ts +98 -0
- package/dist/ArvoResumable/factory.d.ts +50 -0
- package/dist/ArvoResumable/factory.js +70 -0
- package/dist/ArvoResumable/index.d.ts +141 -0
- package/dist/ArvoResumable/index.js +694 -0
- package/dist/ArvoResumable/types.d.ts +147 -0
- package/dist/ArvoResumable/types.js +2 -0
- package/dist/MachineExecutionEngine/index.d.ts +29 -0
- package/dist/MachineExecutionEngine/index.js +132 -0
- package/dist/MachineExecutionEngine/interface.d.ts +14 -0
- package/dist/MachineExecutionEngine/interface.js +2 -0
- package/dist/MachineExecutionEngine/types.d.ts +14 -0
- package/dist/MachineExecutionEngine/types.js +2 -0
- package/dist/MachineMemory/Simple.d.ts +51 -0
- package/dist/MachineMemory/Simple.js +158 -0
- package/dist/MachineMemory/TelemetredSimple.d.ts +51 -0
- package/dist/MachineMemory/TelemetredSimple.js +230 -0
- package/dist/MachineMemory/interface.d.ts +57 -0
- package/dist/MachineMemory/interface.js +2 -0
- package/dist/MachineMemory/utils.d.ts +1 -0
- package/dist/MachineMemory/utils.js +18 -0
- package/dist/MachineRegistry/index.d.ts +37 -0
- package/dist/MachineRegistry/index.js +87 -0
- package/dist/MachineRegistry/interface.d.ts +21 -0
- package/dist/MachineRegistry/interface.js +2 -0
- package/dist/SyncEventResource/index.d.ts +110 -0
- package/dist/SyncEventResource/index.js +280 -0
- package/dist/SyncEventResource/types.d.ts +2 -0
- package/dist/SyncEventResource/types.js +2 -0
- package/dist/index.d.ts +26 -8
- package/dist/index.js +39 -16
- package/dist/utils/SimpleEventBroker/helper.d.ts +166 -0
- package/dist/utils/SimpleEventBroker/helper.js +276 -0
- package/dist/utils/SimpleEventBroker/index.d.ts +96 -0
- package/dist/utils/SimpleEventBroker/index.js +259 -0
- package/dist/utils/SimpleEventBroker/types.d.ts +6 -0
- package/dist/utils/SimpleEventBroker/types.js +2 -0
- package/dist/utils/SimpleEventBroker/utils.d.ts +1 -0
- package/dist/utils/SimpleEventBroker/utils.js +10 -0
- package/dist/{utils.d.ts → utils/index.d.ts} +3 -36
- package/dist/utils/index.js +91 -0
- package/dist/utils/object/index.d.ts +37 -0
- package/dist/utils/object/index.js +63 -0
- package/package.json +5 -3
- package/dist/ArvoEventRouter/helpers.d.ts +0 -19
- package/dist/ArvoEventRouter/helpers.js +0 -22
- package/dist/ArvoEventRouter/index.d.ts +0 -89
- package/dist/ArvoEventRouter/index.js +0 -268
- package/dist/ArvoEventRouter/types.d.ts +0 -36
- package/dist/ArvoEventRouter/utils.d.ts +0 -30
- package/dist/ArvoEventRouter/utils.js +0 -43
- package/dist/MultiArvoEventHandler/helpers.d.ts +0 -48
- package/dist/MultiArvoEventHandler/helpers.js +0 -56
- package/dist/MultiArvoEventHandler/index.d.ts +0 -68
- package/dist/MultiArvoEventHandler/index.js +0 -205
- package/dist/MultiArvoEventHandler/types.d.ts +0 -64
- package/dist/utils.js +0 -191
- /package/dist/{ArvoEventRouter → ArvoMachine}/types.js +0 -0
- /package/dist/{MultiArvoEventHandler → ArvoOrchestrator}/types.js +0 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
3
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
4
|
+
if (ar || !(i in from)) {
|
|
5
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
6
|
+
ar[i] = from[i];
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
var arvo_core_1 = require("arvo-core");
|
|
13
|
+
/**
|
|
14
|
+
* Represents an ArvoMachine object that can be consumed by an Arvo orchestrator.
|
|
15
|
+
* ArvoMachine encapsulates the logic and metadata required for an Arvo-compatible
|
|
16
|
+
* state machine. It combines XState's actor logic with Arvo-specific contracts
|
|
17
|
+
* and versioning information.
|
|
18
|
+
*
|
|
19
|
+
* @remarks
|
|
20
|
+
* It is strongly recommended to use `setupArvoMachine(...).createMachine(...)`
|
|
21
|
+
* instead of creating this object directly. The setup function provides additional
|
|
22
|
+
* type safety and validation that helps prevent runtime errors.
|
|
23
|
+
*/
|
|
24
|
+
var ArvoMachine = /** @class */ (function () {
|
|
25
|
+
/**
|
|
26
|
+
* Creates a new ArvoMachine instance.
|
|
27
|
+
*
|
|
28
|
+
* @param id - A unique identifier for the machine. This ID must be unique within
|
|
29
|
+
* the scope of an orchestrator and is used for routing and logging.
|
|
30
|
+
*
|
|
31
|
+
* @param version - The semantic version of the machine. Must follow semver format
|
|
32
|
+
* and match the version specified in the contract.
|
|
33
|
+
*
|
|
34
|
+
* @param contracts - Configuration object containing contract definitions
|
|
35
|
+
* @param contracts.self - The contract defining this machine's interface and capabilities
|
|
36
|
+
* @param contracts.services - Record of contracts for services this machine can interact with
|
|
37
|
+
*
|
|
38
|
+
* @param logic - The XState actor logic that defines the machine's behavior,
|
|
39
|
+
* including states, transitions, and actions.
|
|
40
|
+
* @param [requiresResourceLocking] - Optional flag indicating if the machine needs distributed locks.
|
|
41
|
+
* False when machine has no parallel states and executes sequentially.
|
|
42
|
+
* Defaults to true.
|
|
43
|
+
*
|
|
44
|
+
* @throws {Error} When contracts are invalid or incompatible with the specified version
|
|
45
|
+
*/
|
|
46
|
+
function ArvoMachine(id, version, contracts, logic, requiresResourceLocking) {
|
|
47
|
+
if (requiresResourceLocking === void 0) { requiresResourceLocking = true; }
|
|
48
|
+
this.id = id;
|
|
49
|
+
this.version = version;
|
|
50
|
+
this.contracts = contracts;
|
|
51
|
+
this.logic = logic;
|
|
52
|
+
this.requiresResourceLocking = requiresResourceLocking;
|
|
53
|
+
}
|
|
54
|
+
Object.defineProperty(ArvoMachine.prototype, "source", {
|
|
55
|
+
/**
|
|
56
|
+
* Gets the event type that this machine accepts, as defined in its contract.
|
|
57
|
+
*/
|
|
58
|
+
get: function () {
|
|
59
|
+
return this.contracts.self.accepts.type;
|
|
60
|
+
},
|
|
61
|
+
enumerable: false,
|
|
62
|
+
configurable: true
|
|
63
|
+
});
|
|
64
|
+
/**
|
|
65
|
+
* Validates an event against the machine's contracts and data schemas.
|
|
66
|
+
* Performs validation for both self-contract events and service contract events.
|
|
67
|
+
*
|
|
68
|
+
* @param event - The event to validate
|
|
69
|
+
* @returns A validation result object:
|
|
70
|
+
* - "VALID" - Event is valid and can be processed
|
|
71
|
+
* - "CONTRACT_UNRESOLVED" - No matching contract found for the event
|
|
72
|
+
* - "INVALID" - Event dataschema conflict with contract
|
|
73
|
+
* - "INVALID_DATA" - Event data conflicts with contract
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* const result = machine.validateInput(event);
|
|
78
|
+
* if (result.type === "VALID") {
|
|
79
|
+
* // Process the event
|
|
80
|
+
* } else if (result.type === "INVALID") {
|
|
81
|
+
* console.error(result.error);
|
|
82
|
+
* } else {
|
|
83
|
+
* // Handle unresolved contract
|
|
84
|
+
* }
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* @remarks
|
|
88
|
+
* The validation process includes:
|
|
89
|
+
* - Finding a matching contract (self or service)
|
|
90
|
+
* - Validating dataschema URI and version if present
|
|
91
|
+
* - Validating event data against the contract schema
|
|
92
|
+
*/
|
|
93
|
+
ArvoMachine.prototype.validateInput = function (event) {
|
|
94
|
+
var _a, _b, _c;
|
|
95
|
+
var resovledContract = null;
|
|
96
|
+
var contractType;
|
|
97
|
+
if (event.type === this.contracts.self.accepts.type) {
|
|
98
|
+
resovledContract = this.contracts.self;
|
|
99
|
+
contractType = 'self';
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
resovledContract =
|
|
103
|
+
(_a = Object.fromEntries(Object.values(this.contracts.services).reduce(function (acc, cur) { return __spreadArray(__spreadArray([], acc, true), __spreadArray(__spreadArray([], cur.emitList, true), [cur.systemError], false).map(function (item) { return [item.type, cur]; }), true); }, []))[event.type]) !== null && _a !== void 0 ? _a : null;
|
|
104
|
+
contractType = 'service';
|
|
105
|
+
}
|
|
106
|
+
if (!resovledContract) {
|
|
107
|
+
(0, arvo_core_1.logToSpan)({
|
|
108
|
+
level: 'WARNING',
|
|
109
|
+
message: "Contract resolution failed: No matching contract found for event (id='".concat(event.id, "', type='").concat(event.type, "')"),
|
|
110
|
+
});
|
|
111
|
+
return {
|
|
112
|
+
type: 'CONTRACT_UNRESOLVED',
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
(0, arvo_core_1.logToSpan)({
|
|
116
|
+
level: 'INFO',
|
|
117
|
+
message: "Contract resolved: Contract(uri='".concat(resovledContract.uri, "', version='").concat(resovledContract.version, "', type='").concat(resovledContract.accepts.type, "') for the event(id='").concat(event.id, "', type='").concat(event.type, "')"),
|
|
118
|
+
});
|
|
119
|
+
var dataschema = arvo_core_1.EventDataschemaUtil.parse(event);
|
|
120
|
+
if (!dataschema) {
|
|
121
|
+
(0, arvo_core_1.logToSpan)({
|
|
122
|
+
level: 'WARNING',
|
|
123
|
+
message: "Dataschema resolution failed: Unable to parse dataschema='".concat(event.dataschema, "' for event(id='").concat(event.id, "', type='").concat(event.type, "')"),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
(0, arvo_core_1.logToSpan)({
|
|
128
|
+
level: 'INFO',
|
|
129
|
+
message: "Dataschema resolved: ".concat(event.dataschema, " matches contract(uri='").concat(resovledContract.uri, "', version='").concat(resovledContract.version, "')"),
|
|
130
|
+
});
|
|
131
|
+
if (dataschema.uri !== resovledContract.uri) {
|
|
132
|
+
return {
|
|
133
|
+
type: 'INVALID',
|
|
134
|
+
error: new Error("Contract URI mismatch: ".concat(contractType, " Contract(uri='").concat(resovledContract.uri, "', type='").concat(resovledContract.accepts.type, "') does not match Event(dataschema='").concat(event.dataschema, "', type='").concat(event.type, "')")),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
if (!(0, arvo_core_1.isWildCardArvoSematicVersion)(dataschema.version) && dataschema.version !== resovledContract.version) {
|
|
138
|
+
return {
|
|
139
|
+
type: 'INVALID',
|
|
140
|
+
error: new Error("Contract version mismatch: ".concat(contractType, " Contract(version='").concat(resovledContract.version, "', type='").concat(resovledContract.accepts.type, "', uri=").concat(resovledContract.uri, ") does not match Event(dataschema='").concat(event.dataschema, "', type='").concat(event.type, "')")),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
var validationSchema = contractType === 'self'
|
|
145
|
+
? resovledContract.accepts.schema
|
|
146
|
+
: ((_b = resovledContract.emits[event.type]) !== null && _b !== void 0 ? _b : resovledContract.systemError.schema);
|
|
147
|
+
var error = (_c = validationSchema.safeParse(event.data).error) !== null && _c !== void 0 ? _c : null;
|
|
148
|
+
if (error) {
|
|
149
|
+
return {
|
|
150
|
+
type: 'INVALID_DATA',
|
|
151
|
+
error: error,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
type: 'VALID',
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
return ArvoMachine;
|
|
159
|
+
}());
|
|
160
|
+
exports.default = ArvoMachine;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import type { ArvoContract, ArvoEventData, ArvoOrchestratorEventTypeGen, ArvoSemanticVersion, CloudEventExtension, InferVersionedArvoContract, VersionedArvoContract } from 'arvo-core';
|
|
2
|
+
import type { Invert, IsNever, ParameterizedObject, UnknownActorLogic, Values } from 'xstate';
|
|
3
|
+
import type { z } from 'zod';
|
|
4
|
+
/**
|
|
5
|
+
* Represents an extended context for Arvo XState machines, including additional properties
|
|
6
|
+
* for volatile and internal data.
|
|
7
|
+
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* This type extends the base XState MachineContext with additional properties
|
|
10
|
+
* to provide more flexibility and organization in storing machine-related data.
|
|
11
|
+
*
|
|
12
|
+
* The `$$` suffix in property names is used to indicate special storage objects within the context.
|
|
13
|
+
*
|
|
14
|
+
* @note
|
|
15
|
+
* To avoid runtime errors, it is recommended not to use `arvo$$` object at all in the
|
|
16
|
+
* machine context
|
|
17
|
+
*/
|
|
18
|
+
export type ArvoMachineContext = {
|
|
19
|
+
arvo$$?: {
|
|
20
|
+
volatile$$?: {
|
|
21
|
+
[key: string]: any;
|
|
22
|
+
eventQueue$$?: EnqueueArvoEventActionParam[];
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Represents the parameters for the emitArvoEvent action in ArvoXState.
|
|
28
|
+
* This type defines a subset of properties from the CreateArvoEvent type,
|
|
29
|
+
* specifically tailored for emitting an ArvoEvent within the state machine context.
|
|
30
|
+
*
|
|
31
|
+
* @remarks
|
|
32
|
+
* The EmitArvoEventActionParam type is crucial for maintaining consistency and
|
|
33
|
+
* type safety when emitting events in an ArvoXState machine. It ensures that
|
|
34
|
+
* only relevant properties are included and properly typed.
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export type EnqueueArvoEventActionParam<TData extends ArvoEventData = ArvoEventData, TType extends string = string, TExtension extends CloudEventExtension = CloudEventExtension> = {
|
|
38
|
+
/**
|
|
39
|
+
* The event domain configuration for multi-domain broadcasting.
|
|
40
|
+
*
|
|
41
|
+
* **Domain Broadcasting Rules:**
|
|
42
|
+
* - Each element in the array creates a separate ArvoEvent instance
|
|
43
|
+
* - `undefined` elements resolve using inheritance: `event.domain ?? contract.domain ?? null`
|
|
44
|
+
* - Duplicate domains are automatically removed to prevent redundant events
|
|
45
|
+
* - Omitting this field (or setting to `undefined`) defaults to `[null]`
|
|
46
|
+
*
|
|
47
|
+
* **Domain Broadcasting Patterns:**
|
|
48
|
+
* - `['domain1', 'domain2']` → Creates 2 events for different processing contexts
|
|
49
|
+
* - `['analytics', undefined, 'audit']` → Creates events for analytics, inherited context, and audit
|
|
50
|
+
* - `[null]` → Creates single event with no domain routing (standard processing)
|
|
51
|
+
* - `undefined` (or omitted) → Creates single event with `domain: null`
|
|
52
|
+
*/
|
|
53
|
+
domain?: (string | null | undefined)[];
|
|
54
|
+
/**
|
|
55
|
+
* Custom extensions for the CloudEvent.
|
|
56
|
+
* Allows for additional metadata to be attached to the event.
|
|
57
|
+
*
|
|
58
|
+
* @remarks
|
|
59
|
+
* Use this field to include any non-standard attributes that are not
|
|
60
|
+
* covered by the core CloudEvent specification or Arvo extensions.
|
|
61
|
+
*/
|
|
62
|
+
__extensions?: TExtension;
|
|
63
|
+
/**
|
|
64
|
+
* Defines access controls for the event.
|
|
65
|
+
* Can be a UserID, encrypted string, or key-value pairs.
|
|
66
|
+
*
|
|
67
|
+
* @remarks
|
|
68
|
+
* This field is used to implement fine-grained access control on event
|
|
69
|
+
* consumption. The exact format and interpretation may depend on your
|
|
70
|
+
* system's access control mechanisms.
|
|
71
|
+
*/
|
|
72
|
+
accesscontrol?: string;
|
|
73
|
+
/**
|
|
74
|
+
* The event payload. This payload must be JSON serializable.
|
|
75
|
+
*
|
|
76
|
+
* @remarks
|
|
77
|
+
* The data field contains the event-specific information. Ensure that
|
|
78
|
+
* the structure of this data conforms to the schema specified in the
|
|
79
|
+
* `dataschema` field, if provided.
|
|
80
|
+
*/
|
|
81
|
+
data: TData;
|
|
82
|
+
/**
|
|
83
|
+
* Identifies the schema that the `data` adheres to.
|
|
84
|
+
* Must be a valid URI if present.
|
|
85
|
+
*
|
|
86
|
+
* @remarks
|
|
87
|
+
* Use this field to provide a link to the schema definition for the
|
|
88
|
+
* event data. This helps consumers understand and validate the event structure.
|
|
89
|
+
*/
|
|
90
|
+
dataschema?: string;
|
|
91
|
+
/**
|
|
92
|
+
* Indicates alternative recipients or destinations for events.
|
|
93
|
+
* Must be a valid URI if present.
|
|
94
|
+
*
|
|
95
|
+
* @remarks
|
|
96
|
+
* Use this field to implement event forwarding or to specify secondary
|
|
97
|
+
* event consumers in addition to the primary one specified in the `to` field.
|
|
98
|
+
*/
|
|
99
|
+
redirectto?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Defines the consumer machine of the event. Used for event routing.
|
|
102
|
+
* Must be a valid URI if present. If not available, the `type` field
|
|
103
|
+
* is used as a default.
|
|
104
|
+
*
|
|
105
|
+
* @remarks
|
|
106
|
+
* This field is crucial for directing events to specific services or
|
|
107
|
+
* components in your system. Ensure the URI is correctly formatted and
|
|
108
|
+
* recognized by your event routing infrastructure.
|
|
109
|
+
*/
|
|
110
|
+
to?: string;
|
|
111
|
+
/**
|
|
112
|
+
* Describes the type of event.
|
|
113
|
+
* Should be prefixed with a reverse-DNS name.
|
|
114
|
+
*
|
|
115
|
+
* @remarks
|
|
116
|
+
* The event type is a key field for consumers to understand the nature
|
|
117
|
+
* of the event without inspecting its data. Use a consistent naming convention
|
|
118
|
+
* to enhance system-wide event comprehension.
|
|
119
|
+
*/
|
|
120
|
+
type: TType;
|
|
121
|
+
/**
|
|
122
|
+
* Represents the cost associated with generating the cloudevent.
|
|
123
|
+
*
|
|
124
|
+
* @remarks
|
|
125
|
+
* By default, it uses the actor's executionunits. This field can be used for
|
|
126
|
+
* resource accounting or billing purposes. Only override this if you have a specific
|
|
127
|
+
* reason to assign a different cost to this particular event emission.
|
|
128
|
+
*/
|
|
129
|
+
executionunits?: number;
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* @remarks
|
|
133
|
+
* This is an internal type. Copied as it is from the
|
|
134
|
+
* xstate core [here](https://github.com/statelyai/xstate/blob/main/packages/core/src/setup.ts#L26)
|
|
135
|
+
*/
|
|
136
|
+
export type ToParameterizedObject<TParameterizedMap extends Record<string, ParameterizedObject['params'] | undefined>> = IsNever<TParameterizedMap> extends true ? never : Values<{
|
|
137
|
+
[K in keyof TParameterizedMap & string]: {
|
|
138
|
+
type: K;
|
|
139
|
+
params: TParameterizedMap[K];
|
|
140
|
+
};
|
|
141
|
+
}>;
|
|
142
|
+
/**
|
|
143
|
+
* @remarks
|
|
144
|
+
* This is an internal type. Copied as it is from the
|
|
145
|
+
* xstate core [here](https://github.com/statelyai/xstate/blob/main/packages/core/src/setup.ts#L43)
|
|
146
|
+
*/
|
|
147
|
+
export type ToProvidedActor<TChildrenMap extends Record<string, string>, TActors extends Record<string, UnknownActorLogic>> = IsNever<TActors> extends true ? never : Values<{
|
|
148
|
+
[K in keyof TActors & string]: {
|
|
149
|
+
src: K;
|
|
150
|
+
logic: TActors[K];
|
|
151
|
+
id: IsNever<TChildrenMap> extends true ? string | undefined : K extends keyof Invert<TChildrenMap> ? Invert<TChildrenMap>[K] & string : string | undefined;
|
|
152
|
+
};
|
|
153
|
+
}>;
|
|
154
|
+
/**
|
|
155
|
+
* Infers emittable events from a versioned Arvo contract.
|
|
156
|
+
*
|
|
157
|
+
* @template T - Versioned Arvo contract type
|
|
158
|
+
*
|
|
159
|
+
* @remarks
|
|
160
|
+
* Extracts all possible events that can be emitted by a contract,
|
|
161
|
+
* including system error events.
|
|
162
|
+
*/
|
|
163
|
+
export type InferEmittableEventsFromVersionedArvoContract<T extends VersionedArvoContract<ArvoContract, ArvoSemanticVersion>> = {
|
|
164
|
+
[K in keyof InferVersionedArvoContract<T>['emits']]: InferVersionedArvoContract<T>['emits'][K];
|
|
165
|
+
}[keyof InferVersionedArvoContract<T>['emits']] | InferVersionedArvoContract<T>['systemError'];
|
|
166
|
+
/**
|
|
167
|
+
* Extracts the orchestrator type from an event type string.
|
|
168
|
+
*
|
|
169
|
+
* @template T - Event type string
|
|
170
|
+
*
|
|
171
|
+
* @remarks
|
|
172
|
+
* Parses the specific orchestrator type from a fully qualified event type string.
|
|
173
|
+
*/
|
|
174
|
+
export type ExtractOrchestratorType<T extends string> = T extends `${typeof ArvoOrchestratorEventTypeGen.prefix}.${infer Type}` ? Type : never;
|
|
175
|
+
/**
|
|
176
|
+
* Infers the complete service contract from a record of versioned Arvo contracts.
|
|
177
|
+
*
|
|
178
|
+
* @template T - Record of versioned Arvo contracts
|
|
179
|
+
*
|
|
180
|
+
* @remarks
|
|
181
|
+
* Generates a comprehensive type definition including both emitted and received events
|
|
182
|
+
* for all services in the contract.
|
|
183
|
+
*
|
|
184
|
+
* @property emitted - Events that can be emitted by the orchestrator
|
|
185
|
+
* @property events - Events that can be received by the orchestrator
|
|
186
|
+
*/
|
|
187
|
+
export type InferServiceContract<T extends Record<string, VersionedArvoContract<ArvoContract, ArvoSemanticVersion>>> = {
|
|
188
|
+
emitted: {
|
|
189
|
+
[K in keyof T]: EnqueueArvoEventActionParam<z.input<T[K]['accepts']['schema']>, T[K]['accepts']['type']>;
|
|
190
|
+
}[keyof T];
|
|
191
|
+
events: {
|
|
192
|
+
[K in keyof T]: InferEmittableEventsFromVersionedArvoContract<T[K]>;
|
|
193
|
+
}[keyof T];
|
|
194
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ArvoContract, VersionedArvoContract } from 'arvo-core';
|
|
2
|
+
import type { MachineConfig } from 'xstate';
|
|
3
|
+
/**
|
|
4
|
+
* Detects if an XState machine configuration contains any parallel states.
|
|
5
|
+
* Uses a stack-based approach for efficient traversal of the state hierarchy.
|
|
6
|
+
*
|
|
7
|
+
* @param config - XState machine configuration
|
|
8
|
+
* @returns True if the machine contains at least one parallel state, false otherwise
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* const machine = {
|
|
12
|
+
* states: {
|
|
13
|
+
* processing: {
|
|
14
|
+
* type: 'parallel',
|
|
15
|
+
* states: {
|
|
16
|
+
* upload: { ... },
|
|
17
|
+
* scan: { ... }
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
* const hasParallel = detectParallelStates(machine) // Returns true
|
|
23
|
+
*/
|
|
24
|
+
export declare const detectParallelStates: (config?: MachineConfig<any, any, any, any, any, any, any, any, any, any, any>) => boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Validates that all service contracts in a collection have unique URIs.
|
|
27
|
+
*
|
|
28
|
+
* Iterates through the provided contracts and checks if any URI appears more than once.
|
|
29
|
+
* Multiple versions of the same contract (with the same URI) are not allowed.
|
|
30
|
+
*
|
|
31
|
+
* @param contracts - A record mapping contract keys to their respective ArvoContract objects
|
|
32
|
+
* @returns An object with a boolean result indicating if all contracts are unique, and the error keys if not
|
|
33
|
+
*/
|
|
34
|
+
export declare const areServiceContractsUnique: (contracts: Record<string, ArvoContract | VersionedArvoContract<any, any>>) => {
|
|
35
|
+
result: false;
|
|
36
|
+
keys: [string, string];
|
|
37
|
+
contractUri: string;
|
|
38
|
+
} | {
|
|
39
|
+
result: true;
|
|
40
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.areServiceContractsUnique = exports.detectParallelStates = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Detects if an XState machine configuration contains any parallel states.
|
|
6
|
+
* Uses a stack-based approach for efficient traversal of the state hierarchy.
|
|
7
|
+
*
|
|
8
|
+
* @param config - XState machine configuration
|
|
9
|
+
* @returns True if the machine contains at least one parallel state, false otherwise
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* const machine = {
|
|
13
|
+
* states: {
|
|
14
|
+
* processing: {
|
|
15
|
+
* type: 'parallel',
|
|
16
|
+
* states: {
|
|
17
|
+
* upload: { ... },
|
|
18
|
+
* scan: { ... }
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
* const hasParallel = detectParallelStates(machine) // Returns true
|
|
24
|
+
*/
|
|
25
|
+
var detectParallelStates = function (config) {
|
|
26
|
+
if (!(config === null || config === void 0 ? void 0 : config.states)) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
var stack = [config];
|
|
30
|
+
while (stack.length) {
|
|
31
|
+
var currentConfig = stack.pop();
|
|
32
|
+
if (!(currentConfig === null || currentConfig === void 0 ? void 0 : currentConfig.states))
|
|
33
|
+
continue;
|
|
34
|
+
if (currentConfig.type === 'parallel')
|
|
35
|
+
return true;
|
|
36
|
+
for (var _i = 0, _a = Object.values(currentConfig.states); _i < _a.length; _i++) {
|
|
37
|
+
var state = _a[_i];
|
|
38
|
+
stack.push(state);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
};
|
|
43
|
+
exports.detectParallelStates = detectParallelStates;
|
|
44
|
+
/**
|
|
45
|
+
* Validates that all service contracts in a collection have unique URIs.
|
|
46
|
+
*
|
|
47
|
+
* Iterates through the provided contracts and checks if any URI appears more than once.
|
|
48
|
+
* Multiple versions of the same contract (with the same URI) are not allowed.
|
|
49
|
+
*
|
|
50
|
+
* @param contracts - A record mapping contract keys to their respective ArvoContract objects
|
|
51
|
+
* @returns An object with a boolean result indicating if all contracts are unique, and the error keys if not
|
|
52
|
+
*/
|
|
53
|
+
var areServiceContractsUnique = function (contracts) {
|
|
54
|
+
var uriToKeyMap = {};
|
|
55
|
+
for (var _i = 0, _a = Object.entries(contracts); _i < _a.length; _i++) {
|
|
56
|
+
var _b = _a[_i], key = _b[0], contract = _b[1];
|
|
57
|
+
if (uriToKeyMap[contract.uri]) {
|
|
58
|
+
return {
|
|
59
|
+
result: false,
|
|
60
|
+
keys: [key, uriToKeyMap[contract.uri]],
|
|
61
|
+
contractUri: contract.uri,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
uriToKeyMap[contract.uri] = key;
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
result: true,
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
exports.areServiceContractsUnique = areServiceContractsUnique;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type ArvoEvent, ViolationError } from 'arvo-core';
|
|
2
|
+
export declare enum TransactionViolationCause {
|
|
3
|
+
READ_FAILURE = "READ_MACHINE_MEMORY_FAILURE",
|
|
4
|
+
LOCK_FAILURE = "LOCK_MACHINE_MEMORY_FAILURE",
|
|
5
|
+
WRITE_FAILURE = "WRITE_MACHINE_MEMORY_FAILURE",
|
|
6
|
+
LOCK_UNACQUIRED = "LOCK_UNACQUIRED",
|
|
7
|
+
INVALID_SUBJECT = "INVALID_SUBJECT"
|
|
8
|
+
}
|
|
9
|
+
export declare class TransactionViolation extends ViolationError<'OrchestratorTransaction'> {
|
|
10
|
+
readonly cause: TransactionViolationCause;
|
|
11
|
+
constructor(param: {
|
|
12
|
+
cause: TransactionViolationCause;
|
|
13
|
+
message: string;
|
|
14
|
+
initiatingEvent: ArvoEvent;
|
|
15
|
+
});
|
|
16
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __extends = (this && this.__extends) || (function () {
|
|
3
|
+
var extendStatics = function (d, b) {
|
|
4
|
+
extendStatics = Object.setPrototypeOf ||
|
|
5
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
7
|
+
return extendStatics(d, b);
|
|
8
|
+
};
|
|
9
|
+
return function (d, b) {
|
|
10
|
+
if (typeof b !== "function" && b !== null)
|
|
11
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
12
|
+
extendStatics(d, b);
|
|
13
|
+
function __() { this.constructor = d; }
|
|
14
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
15
|
+
};
|
|
16
|
+
})();
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.TransactionViolation = exports.TransactionViolationCause = void 0;
|
|
19
|
+
var arvo_core_1 = require("arvo-core");
|
|
20
|
+
var TransactionViolationCause;
|
|
21
|
+
(function (TransactionViolationCause) {
|
|
22
|
+
TransactionViolationCause["READ_FAILURE"] = "READ_MACHINE_MEMORY_FAILURE";
|
|
23
|
+
TransactionViolationCause["LOCK_FAILURE"] = "LOCK_MACHINE_MEMORY_FAILURE";
|
|
24
|
+
TransactionViolationCause["WRITE_FAILURE"] = "WRITE_MACHINE_MEMORY_FAILURE";
|
|
25
|
+
TransactionViolationCause["LOCK_UNACQUIRED"] = "LOCK_UNACQUIRED";
|
|
26
|
+
TransactionViolationCause["INVALID_SUBJECT"] = "INVALID_SUBJECT";
|
|
27
|
+
})(TransactionViolationCause || (exports.TransactionViolationCause = TransactionViolationCause = {}));
|
|
28
|
+
var TransactionViolation = /** @class */ (function (_super) {
|
|
29
|
+
__extends(TransactionViolation, _super);
|
|
30
|
+
function TransactionViolation(param) {
|
|
31
|
+
var _this = _super.call(this, {
|
|
32
|
+
type: 'OrchestratorTransaction',
|
|
33
|
+
message: "[".concat(param.cause, "] ").concat(param.message),
|
|
34
|
+
metadata: {
|
|
35
|
+
initiatingEvent: param.initiatingEvent,
|
|
36
|
+
},
|
|
37
|
+
}) || this;
|
|
38
|
+
_this.cause = param.cause;
|
|
39
|
+
return _this;
|
|
40
|
+
}
|
|
41
|
+
return TransactionViolation;
|
|
42
|
+
}(arvo_core_1.ViolationError));
|
|
43
|
+
exports.TransactionViolation = TransactionViolation;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ArvoOrchestrator } from '.';
|
|
2
|
+
import type { ICreateArvoOrchestrator } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a new Arvo orchestrator instance with default components.
|
|
5
|
+
* For custom components, use ArvoOrchestrator constructor directly.
|
|
6
|
+
*
|
|
7
|
+
* @param config - Orchestrator configuration
|
|
8
|
+
* @param config.memory - State persistence interface for storing machine states
|
|
9
|
+
* @param config.executionunits - Cost units for execution tracking
|
|
10
|
+
* @param config.machines - Array of state machines to manage. Their resource locking flags determine orchestrator's locking behavior
|
|
11
|
+
* @returns Configured ArvoOrchestrator instance with default registry and execution engine
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* The orchestrator's resource locking is enabled if any machine requires it. Locking is needed when:
|
|
15
|
+
* - Machine contains parallel states where multiple states can be active simultaneously
|
|
16
|
+
* - Race conditions need to be prevented in concurrent processing
|
|
17
|
+
* - State consistency must be maintained across distributed executions
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const orchestrator = createArvoOrchestrator({
|
|
22
|
+
* memory: new MyMemoryImplementation(),
|
|
23
|
+
* executionunits: 1,
|
|
24
|
+
* machines: [machineA, machineB]
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare const createArvoOrchestrator: ({ executionunits, memory, machines, }: ICreateArvoOrchestrator) => ArvoOrchestrator;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
3
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
4
|
+
if (ar || !(i in from)) {
|
|
5
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
6
|
+
ar[i] = from[i];
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.createArvoOrchestrator = void 0;
|
|
13
|
+
var _1 = require(".");
|
|
14
|
+
var MachineExecutionEngine_1 = require("../MachineExecutionEngine");
|
|
15
|
+
var MachineRegistry_1 = require("../MachineRegistry");
|
|
16
|
+
/**
|
|
17
|
+
* Creates a new Arvo orchestrator instance with default components.
|
|
18
|
+
* For custom components, use ArvoOrchestrator constructor directly.
|
|
19
|
+
*
|
|
20
|
+
* @param config - Orchestrator configuration
|
|
21
|
+
* @param config.memory - State persistence interface for storing machine states
|
|
22
|
+
* @param config.executionunits - Cost units for execution tracking
|
|
23
|
+
* @param config.machines - Array of state machines to manage. Their resource locking flags determine orchestrator's locking behavior
|
|
24
|
+
* @returns Configured ArvoOrchestrator instance with default registry and execution engine
|
|
25
|
+
*
|
|
26
|
+
* @remarks
|
|
27
|
+
* The orchestrator's resource locking is enabled if any machine requires it. Locking is needed when:
|
|
28
|
+
* - Machine contains parallel states where multiple states can be active simultaneously
|
|
29
|
+
* - Race conditions need to be prevented in concurrent processing
|
|
30
|
+
* - State consistency must be maintained across distributed executions
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* const orchestrator = createArvoOrchestrator({
|
|
35
|
+
* memory: new MyMemoryImplementation(),
|
|
36
|
+
* executionunits: 1,
|
|
37
|
+
* machines: [machineA, machineB]
|
|
38
|
+
* });
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
var createArvoOrchestrator = function (_a) {
|
|
42
|
+
var executionunits = _a.executionunits, memory = _a.memory, machines = _a.machines;
|
|
43
|
+
if (!(machines === null || machines === void 0 ? void 0 : machines.length)) {
|
|
44
|
+
throw new Error('At least one machine must be provided');
|
|
45
|
+
}
|
|
46
|
+
var registry = new (MachineRegistry_1.MachineRegistry.bind.apply(MachineRegistry_1.MachineRegistry, __spreadArray([void 0], machines, false)))();
|
|
47
|
+
var requiresResourceLocking = machines.some(function (machine) { return machine.requiresResourceLocking; });
|
|
48
|
+
return new _1.ArvoOrchestrator({
|
|
49
|
+
executionunits: executionunits,
|
|
50
|
+
memory: memory,
|
|
51
|
+
registry: registry,
|
|
52
|
+
executionEngine: new MachineExecutionEngine_1.MachineExecutionEngine(),
|
|
53
|
+
requiresResourceLocking: requiresResourceLocking,
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
exports.createArvoOrchestrator = createArvoOrchestrator;
|