arvo-event-handler 2.3.1 → 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.
Files changed (78) hide show
  1. package/dist/AbstractArvoEventHandler/index.d.ts +1 -1
  2. package/dist/ArvoEventHandler/helpers.d.ts +40 -6
  3. package/dist/ArvoEventHandler/helpers.js +40 -6
  4. package/dist/ArvoEventHandler/index.d.ts +78 -49
  5. package/dist/ArvoEventHandler/index.js +151 -81
  6. package/dist/ArvoEventHandler/types.d.ts +25 -2
  7. package/dist/ArvoMachine/createMachine.d.ts +208 -0
  8. package/dist/ArvoMachine/createMachine.js +283 -0
  9. package/dist/ArvoMachine/index.d.ts +93 -0
  10. package/dist/ArvoMachine/index.js +160 -0
  11. package/dist/ArvoMachine/types.d.ts +194 -0
  12. package/dist/ArvoMachine/utils.d.ts +40 -0
  13. package/dist/ArvoMachine/utils.js +70 -0
  14. package/dist/ArvoOrchestrator/error.d.ts +16 -0
  15. package/dist/ArvoOrchestrator/error.js +43 -0
  16. package/dist/ArvoOrchestrator/factory.d.ts +28 -0
  17. package/dist/ArvoOrchestrator/factory.js +56 -0
  18. package/dist/ArvoOrchestrator/index.d.ts +69 -0
  19. package/dist/ArvoOrchestrator/index.js +597 -0
  20. package/dist/ArvoOrchestrator/types.d.ts +98 -0
  21. package/dist/ArvoResumable/factory.d.ts +50 -0
  22. package/dist/ArvoResumable/factory.js +70 -0
  23. package/dist/ArvoResumable/index.d.ts +141 -0
  24. package/dist/ArvoResumable/index.js +694 -0
  25. package/dist/ArvoResumable/types.d.ts +147 -0
  26. package/dist/ArvoResumable/types.js +2 -0
  27. package/dist/MachineExecutionEngine/index.d.ts +29 -0
  28. package/dist/MachineExecutionEngine/index.js +132 -0
  29. package/dist/MachineExecutionEngine/interface.d.ts +14 -0
  30. package/dist/MachineExecutionEngine/interface.js +2 -0
  31. package/dist/MachineExecutionEngine/types.d.ts +14 -0
  32. package/dist/MachineExecutionEngine/types.js +2 -0
  33. package/dist/MachineMemory/Simple.d.ts +51 -0
  34. package/dist/MachineMemory/Simple.js +158 -0
  35. package/dist/MachineMemory/TelemetredSimple.d.ts +51 -0
  36. package/dist/MachineMemory/TelemetredSimple.js +230 -0
  37. package/dist/MachineMemory/interface.d.ts +57 -0
  38. package/dist/MachineMemory/interface.js +2 -0
  39. package/dist/MachineMemory/utils.d.ts +1 -0
  40. package/dist/MachineMemory/utils.js +18 -0
  41. package/dist/MachineRegistry/index.d.ts +37 -0
  42. package/dist/MachineRegistry/index.js +87 -0
  43. package/dist/MachineRegistry/interface.d.ts +21 -0
  44. package/dist/MachineRegistry/interface.js +2 -0
  45. package/dist/SyncEventResource/index.d.ts +110 -0
  46. package/dist/SyncEventResource/index.js +280 -0
  47. package/dist/SyncEventResource/types.d.ts +2 -0
  48. package/dist/SyncEventResource/types.js +2 -0
  49. package/dist/index.d.ts +26 -8
  50. package/dist/index.js +39 -16
  51. package/dist/utils/SimpleEventBroker/helper.d.ts +166 -0
  52. package/dist/utils/SimpleEventBroker/helper.js +276 -0
  53. package/dist/utils/SimpleEventBroker/index.d.ts +96 -0
  54. package/dist/utils/SimpleEventBroker/index.js +259 -0
  55. package/dist/utils/SimpleEventBroker/types.d.ts +6 -0
  56. package/dist/utils/SimpleEventBroker/types.js +2 -0
  57. package/dist/utils/SimpleEventBroker/utils.d.ts +1 -0
  58. package/dist/utils/SimpleEventBroker/utils.js +10 -0
  59. package/dist/{utils.d.ts → utils/index.d.ts} +3 -36
  60. package/dist/utils/index.js +91 -0
  61. package/dist/utils/object/index.d.ts +37 -0
  62. package/dist/utils/object/index.js +63 -0
  63. package/package.json +6 -12
  64. package/dist/ArvoEventRouter/helpers.d.ts +0 -19
  65. package/dist/ArvoEventRouter/helpers.js +0 -22
  66. package/dist/ArvoEventRouter/index.d.ts +0 -89
  67. package/dist/ArvoEventRouter/index.js +0 -267
  68. package/dist/ArvoEventRouter/types.d.ts +0 -36
  69. package/dist/ArvoEventRouter/utils.d.ts +0 -29
  70. package/dist/ArvoEventRouter/utils.js +0 -42
  71. package/dist/MultiArvoEventHandler/helpers.d.ts +0 -48
  72. package/dist/MultiArvoEventHandler/helpers.js +0 -56
  73. package/dist/MultiArvoEventHandler/index.d.ts +0 -68
  74. package/dist/MultiArvoEventHandler/index.js +0 -205
  75. package/dist/MultiArvoEventHandler/types.d.ts +0 -64
  76. package/dist/utils.js +0 -190
  77. /package/dist/{ArvoEventRouter → ArvoMachine}/types.js +0 -0
  78. /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;