arvo-event-handler 0.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/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ ## [0.0.1] - 2024-09-07
4
+
5
+ - Finalised version 0.0.1 of the event handlers for Arvo
package/LICENSE.md ADDED
@@ -0,0 +1,7 @@
1
+ The MIT License (MIT)
2
+ Copyright (c) 2024 Saad Ahmad
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # Arvo
2
+
3
+ ## What is Arvo
4
+
5
+ Arvo is an opinionated approach to building event-driven systems. It's designed as a pattern and methodology rather than a rigid framework.
6
+
7
+ ## Principal
8
+
9
+ The core principle of Arvo is to provide a solid foundation with enough flexibility for customization, allowing you to impose your own technical posture, including security measures, event brokerage, and telemetry. While Arvo offers a structured approach, it encourages developers to implement their own solutions if they believe they can improve upon or diverge from Arvo's principles.
10
+
11
+ If you're looking to focus on results without getting bogged down in the nitty-gritty of event creation, handling, system state management, and telemetry, while also avoiding vendor lock-in, Arvo provides an excellent starting point. I believe, it strikes a balance between opinionated design and customization, making it an ideal choice for developers who want a head start in building event-driven systems without sacrificing flexibility.
12
+
13
+ Key features of Arvo include:
14
+
15
+ - Lightweight and unopinionated core
16
+ - Extensible architecture
17
+ - Cloud-agnostic design
18
+ - Built-in primitives for event-driven patterns
19
+ - Easy integration with existing systems and tools
20
+
21
+ Whether you're building a small microservice or a large-scale distributed system, my hope with Arvo is to offers you some of the tools and patterns to help you succeed in the world of event-driven architecture.
22
+
23
+ # Arvo - Event Handler
24
+
25
+ ## Installation
26
+
27
+ You can install the core package via `npm` or `yarn`
28
+
29
+ ```bash
30
+ npm install arvo-event-handler
31
+ ```
32
+
33
+ ```bash
34
+ yarn add arvo-event-handler
35
+ ```
36
+
37
+ ## License
38
+
39
+ This package is available under the MIT License. For more details, refer to the [LICENSE.md](LICENSE.md) file in the project repository.
40
+
41
+ ## Change Logs
42
+
43
+ For a detailed list of changes and updates, please refer to the [document](CHANGELOG.md) file.
@@ -0,0 +1,31 @@
1
+ import { ArvoContract } from 'arvo-core';
2
+ import { IArvoEventHandler } from './types';
3
+ import ArvoEventHandler from '.';
4
+ /**
5
+ * Creates an ArvoEventHandler instance for a given ArvoContract.
6
+ *
7
+ * @template TContract - The type of ArvoContract this handler is associated with.
8
+ * @param param - The configuration parameters for the event handler.
9
+ * @returns A new instance of ArvoEventHandler<TContract>.
10
+ *
11
+ * @remarks
12
+ * This function is a factory for creating ArvoEventHandler instances.
13
+ * It encapsulates the creation process and provides a convenient way to instantiate
14
+ * handlers for specific Arvo contracts.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const myContract = new ArvoContract(...);
19
+ * const myHandler = createArvoEventHandler({
20
+ * contract: myContract,
21
+ * executionunits: 100,
22
+ * handler: async ({ event }) => {
23
+ * // Handler implementation
24
+ * }
25
+ * });
26
+ * ```
27
+ *
28
+ * @see {@link IArvoEventHandler} for the full configuration options
29
+ * @see {@link ArvoEventHandler} for the handler class implementation
30
+ */
31
+ export declare const createArvoEventHandler: <TContract extends ArvoContract>(param: IArvoEventHandler<TContract>) => ArvoEventHandler<TContract>;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createArvoEventHandler = void 0;
7
+ var _1 = __importDefault(require("."));
8
+ /**
9
+ * Creates an ArvoEventHandler instance for a given ArvoContract.
10
+ *
11
+ * @template TContract - The type of ArvoContract this handler is associated with.
12
+ * @param param - The configuration parameters for the event handler.
13
+ * @returns A new instance of ArvoEventHandler<TContract>.
14
+ *
15
+ * @remarks
16
+ * This function is a factory for creating ArvoEventHandler instances.
17
+ * It encapsulates the creation process and provides a convenient way to instantiate
18
+ * handlers for specific Arvo contracts.
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const myContract = new ArvoContract(...);
23
+ * const myHandler = createArvoEventHandler({
24
+ * contract: myContract,
25
+ * executionunits: 100,
26
+ * handler: async ({ event }) => {
27
+ * // Handler implementation
28
+ * }
29
+ * });
30
+ * ```
31
+ *
32
+ * @see {@link IArvoEventHandler} for the full configuration options
33
+ * @see {@link ArvoEventHandler} for the handler class implementation
34
+ */
35
+ var createArvoEventHandler = function (param) { return new _1.default(param); };
36
+ exports.createArvoEventHandler = createArvoEventHandler;
@@ -0,0 +1,91 @@
1
+ import { ArvoContract, ArvoEvent, ArvoExecutionSpanKind, OpenInferenceSpanKind, ResolveArvoContractRecord } from 'arvo-core';
2
+ import { IArvoEventHandler } from './types';
3
+ import { SpanKind } from '@opentelemetry/api';
4
+ /**
5
+ * Represents an event handler for Arvo contracts.
6
+ *
7
+ * @template TContract - The type of ArvoContract this handler is associated with.
8
+ *
9
+ * @remarks
10
+ * This class is the core component for handling Arvo events. It encapsulates the logic
11
+ * for executing event handlers, managing telemetry, and ensuring proper contract validation.
12
+ * It's designed to be flexible and reusable across different Arvo contract implementations.
13
+ */
14
+ export default class ArvoEventHandler<TContract extends ArvoContract> {
15
+ /** The contract of the handler to which it is bound */
16
+ readonly contract: TContract;
17
+ /** The default execution cost associated with this handler */
18
+ readonly executionunits: number;
19
+ /**
20
+ * The source identifier for events produced by this handler
21
+ *
22
+ * @remarks
23
+ * For all the events which are emitted by the handler, this is
24
+ * the source field value of them all.
25
+ */
26
+ readonly source: string;
27
+ readonly openInferenceSpanKind: OpenInferenceSpanKind;
28
+ readonly arvoExecutionSpanKind: ArvoExecutionSpanKind;
29
+ readonly openTelemetrySpanKind: SpanKind;
30
+ private readonly _handler;
31
+ /**
32
+ * Creates an instance of ArvoEventHandler.
33
+ *
34
+ * @param param - The configuration parameters for the event handler.
35
+ *
36
+ * @throws {Error} Throws an error if the provided source is invalid.
37
+ *
38
+ * @remarks
39
+ * The constructor validates the source parameter against the CloudEventContextSchema.
40
+ * If no source is provided, it defaults to the contract's accepted event type.
41
+ */
42
+ constructor(param: IArvoEventHandler<TContract>);
43
+ /**
44
+ * Executes the event handler for a given event.
45
+ *
46
+ * @param event - The event to handle.
47
+ * @returns A promise that resolves to the resulting ArvoEvent.
48
+ *
49
+ * @remarks
50
+ * This method performs the following steps:
51
+ * 1. Creates an OpenTelemetry span for the execution.
52
+ * 2. Validates the input event against the contract.
53
+ * 3. Executes the handler function.
54
+ * 4. Creates and returns the result event.
55
+ * 5. Handles any errors and creates an error event if necessary.
56
+ *
57
+ * All telemetry data is properly set and propagated throughout the execution.
58
+ */
59
+ execute(event: ArvoEvent<ResolveArvoContractRecord<TContract['accepts']>, Record<string, any>, TContract['accepts']['type']>): Promise<ArvoEvent | null>;
60
+ /**
61
+ * Provides the schema for system error events.
62
+ *
63
+ * @returns An object containing the error event type and schema.
64
+ *
65
+ * @remarks
66
+ * This getter defines the structure for system error events that may be emitted
67
+ * when an unexpected error occurs during event handling. The error event type
68
+ * is prefixed with 'sys.' followed by the contract's accepted event type and '.error'.
69
+ * The schema used for these error events is the standard ArvoErrorSchema.
70
+ *
71
+ * @example
72
+ * // If the contract's accepted event type is 'user.created'
73
+ * // The system error event type would be 'sys.user.created.error'
74
+ */
75
+ get systemErrorSchema(): {
76
+ type: string;
77
+ schema: import("zod").ZodObject<{
78
+ errorName: import("zod").ZodString;
79
+ errorMessage: import("zod").ZodString;
80
+ errorStack: import("zod").ZodNullable<import("zod").ZodString>;
81
+ }, "strip", import("zod").ZodTypeAny, {
82
+ errorName: string;
83
+ errorMessage: string;
84
+ errorStack: string | null;
85
+ }, {
86
+ errorName: string;
87
+ errorMessage: string;
88
+ errorStack: string | null;
89
+ }>;
90
+ };
91
+ }
@@ -0,0 +1,239 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ var __generator = (this && this.__generator) || function (thisArg, body) {
23
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
+ function verb(n) { return function (v) { return step([n, v]); }; }
26
+ function step(op) {
27
+ if (f) throw new TypeError("Generator is already executing.");
28
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
29
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
+ if (y = 0, t) op = [op[0] & 2, t.value];
31
+ switch (op[0]) {
32
+ case 0: case 1: t = op; break;
33
+ case 4: _.label++; return { value: op[1], done: false };
34
+ case 5: _.label++; y = op[1]; op = [0]; continue;
35
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
+ default:
37
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
+ if (t[2]) _.ops.pop();
42
+ _.trys.pop(); continue;
43
+ }
44
+ op = body.call(thisArg, _);
45
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
+ }
48
+ };
49
+ var __rest = (this && this.__rest) || function (s, e) {
50
+ var t = {};
51
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
52
+ t[p] = s[p];
53
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
54
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
55
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
56
+ t[p[i]] = s[p[i]];
57
+ }
58
+ return t;
59
+ };
60
+ Object.defineProperty(exports, "__esModule", { value: true });
61
+ var arvo_core_1 = require("arvo-core");
62
+ var schema_1 = require("arvo-core/dist/ArvoEvent/schema");
63
+ var OpenTelemetry_1 = require("../OpenTelemetry");
64
+ var api_1 = require("@opentelemetry/api");
65
+ /**
66
+ * Represents an event handler for Arvo contracts.
67
+ *
68
+ * @template TContract - The type of ArvoContract this handler is associated with.
69
+ *
70
+ * @remarks
71
+ * This class is the core component for handling Arvo events. It encapsulates the logic
72
+ * for executing event handlers, managing telemetry, and ensuring proper contract validation.
73
+ * It's designed to be flexible and reusable across different Arvo contract implementations.
74
+ */
75
+ var ArvoEventHandler = /** @class */ (function () {
76
+ /**
77
+ * Creates an instance of ArvoEventHandler.
78
+ *
79
+ * @param param - The configuration parameters for the event handler.
80
+ *
81
+ * @throws {Error} Throws an error if the provided source is invalid.
82
+ *
83
+ * @remarks
84
+ * The constructor validates the source parameter against the CloudEventContextSchema.
85
+ * If no source is provided, it defaults to the contract's accepted event type.
86
+ */
87
+ function ArvoEventHandler(param) {
88
+ var _a, _b, _c;
89
+ this.openInferenceSpanKind = arvo_core_1.OpenInferenceSpanKind.CHAIN;
90
+ this.arvoExecutionSpanKind = arvo_core_1.ArvoExecutionSpanKind.EVENT_HANDLER;
91
+ this.openTelemetrySpanKind = api_1.SpanKind.INTERNAL;
92
+ this.contract = param.contract;
93
+ this.executionunits = param.executionunits;
94
+ this._handler = param.handler;
95
+ if (param.source) {
96
+ var error = schema_1.CloudEventContextSchema.pick({
97
+ source: true,
98
+ }).safeParse({ source: param.source }).error;
99
+ if (error) {
100
+ throw new Error("The provided 'source' is not a valid string. Error: ".concat(error.message));
101
+ }
102
+ }
103
+ this.source = param.source || this.contract.accepts.type;
104
+ this.arvoExecutionSpanKind = ((_a = param.spanKind) === null || _a === void 0 ? void 0 : _a.arvoExecution) || this.arvoExecutionSpanKind;
105
+ this.openInferenceSpanKind = ((_b = param.spanKind) === null || _b === void 0 ? void 0 : _b.openInference) || this.openInferenceSpanKind;
106
+ this.openTelemetrySpanKind = ((_c = param.spanKind) === null || _c === void 0 ? void 0 : _c.openTelemetry) || this.openTelemetrySpanKind;
107
+ }
108
+ /**
109
+ * Executes the event handler for a given event.
110
+ *
111
+ * @param event - The event to handle.
112
+ * @returns A promise that resolves to the resulting ArvoEvent.
113
+ *
114
+ * @remarks
115
+ * This method performs the following steps:
116
+ * 1. Creates an OpenTelemetry span for the execution.
117
+ * 2. Validates the input event against the contract.
118
+ * 3. Executes the handler function.
119
+ * 4. Creates and returns the result event.
120
+ * 5. Handles any errors and creates an error event if necessary.
121
+ *
122
+ * All telemetry data is properly set and propagated throughout the execution.
123
+ */
124
+ ArvoEventHandler.prototype.execute = function (event) {
125
+ return __awaiter(this, void 0, void 0, function () {
126
+ var spanName, spanOptions, span, inheritedContext, eventFactory;
127
+ var _a;
128
+ var _this = this;
129
+ return __generator(this, function (_b) {
130
+ switch (_b.label) {
131
+ case 0:
132
+ spanName = "ArvoEventHandler<".concat(this.contract.uri, ">.execute<").concat(event.type, ">");
133
+ spanOptions = {
134
+ kind: this.openTelemetrySpanKind,
135
+ attributes: (_a = {},
136
+ _a[arvo_core_1.OpenInference.ATTR_SPAN_KIND] = this.openInferenceSpanKind,
137
+ _a[arvo_core_1.ArvoExecution.ATTR_SPAN_KIND] = this.arvoExecutionSpanKind,
138
+ _a)
139
+ };
140
+ if (event.traceparent) {
141
+ inheritedContext = (0, OpenTelemetry_1.extractContext)(event.traceparent, event.tracestate);
142
+ span = OpenTelemetry_1.ArvoEventHandlerTracer.startSpan(spanName, spanOptions, inheritedContext);
143
+ }
144
+ else {
145
+ span = OpenTelemetry_1.ArvoEventHandlerTracer.startSpan(spanName, spanOptions);
146
+ }
147
+ eventFactory = (0, arvo_core_1.createArvoEventFactory)(this.contract);
148
+ return [4 /*yield*/, api_1.context.with(api_1.trace.setSpan(api_1.context.active(), span), function () { return __awaiter(_this, void 0, void 0, function () {
149
+ var otelSpanHeaders, inputEventValidation, output, __extensions, handlerResult, result, error_1, result;
150
+ return __generator(this, function (_a) {
151
+ switch (_a.label) {
152
+ case 0:
153
+ otelSpanHeaders = (0, arvo_core_1.currentOpenTelemetryHeaders)();
154
+ _a.label = 1;
155
+ case 1:
156
+ _a.trys.push([1, 3, 4, 5]);
157
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
158
+ Object.entries(event.otelAttributes).forEach(function (_a) {
159
+ var key = _a[0], value = _a[1];
160
+ return span.setAttribute("to_process.".concat(key), value);
161
+ });
162
+ inputEventValidation = this.contract.validateInput(event.type, event.data);
163
+ if (inputEventValidation.error) {
164
+ throw new Error("Invalid event payload: ".concat(inputEventValidation.error));
165
+ }
166
+ return [4 /*yield*/, this._handler({ event: event })];
167
+ case 2:
168
+ output = _a.sent();
169
+ if (!output)
170
+ return [2 /*return*/, null];
171
+ __extensions = output.__extensions, handlerResult = __rest(output, ["__extensions"]);
172
+ result = eventFactory.emits(__assign(__assign({}, handlerResult), { traceparent: otelSpanHeaders.traceparent || undefined, tracestate: otelSpanHeaders.tracestate || undefined, source: this.source, subject: event.subject, to: handlerResult.to || event.source, executionunits: handlerResult.executionunits || this.executionunits }), __extensions);
173
+ span.setAttributes(result.otelAttributes);
174
+ Object.entries(result.otelAttributes).forEach(function (_a) {
175
+ var key = _a[0], value = _a[1];
176
+ return span.setAttribute("to_emit.".concat(key), value);
177
+ });
178
+ return [2 /*return*/, result];
179
+ case 3:
180
+ error_1 = _a.sent();
181
+ (0, arvo_core_1.exceptionToSpan)(error_1);
182
+ span.setStatus({
183
+ code: api_1.SpanStatusCode.ERROR,
184
+ message: error_1.message,
185
+ });
186
+ result = eventFactory.systemError({
187
+ source: this.source,
188
+ subject: event.subject,
189
+ to: event.source,
190
+ error: error_1,
191
+ executionunits: this.executionunits,
192
+ traceparent: otelSpanHeaders.traceparent || undefined,
193
+ tracestate: otelSpanHeaders.tracestate || undefined,
194
+ }, {});
195
+ Object.entries(result.otelAttributes).forEach(function (_a) {
196
+ var key = _a[0], value = _a[1];
197
+ return span.setAttribute("to_emit.".concat(key), value);
198
+ });
199
+ return [2 /*return*/, result];
200
+ case 4:
201
+ span.end();
202
+ return [7 /*endfinally*/];
203
+ case 5: return [2 /*return*/];
204
+ }
205
+ });
206
+ }); })];
207
+ case 1: return [2 /*return*/, _b.sent()];
208
+ }
209
+ });
210
+ });
211
+ };
212
+ Object.defineProperty(ArvoEventHandler.prototype, "systemErrorSchema", {
213
+ /**
214
+ * Provides the schema for system error events.
215
+ *
216
+ * @returns An object containing the error event type and schema.
217
+ *
218
+ * @remarks
219
+ * This getter defines the structure for system error events that may be emitted
220
+ * when an unexpected error occurs during event handling. The error event type
221
+ * is prefixed with 'sys.' followed by the contract's accepted event type and '.error'.
222
+ * The schema used for these error events is the standard ArvoErrorSchema.
223
+ *
224
+ * @example
225
+ * // If the contract's accepted event type is 'user.created'
226
+ * // The system error event type would be 'sys.user.created.error'
227
+ */
228
+ get: function () {
229
+ return {
230
+ type: "sys.".concat(this.contract.accepts.type, ".error"),
231
+ schema: arvo_core_1.ArvoErrorSchema
232
+ };
233
+ },
234
+ enumerable: false,
235
+ configurable: true
236
+ });
237
+ return ArvoEventHandler;
238
+ }());
239
+ exports.default = ArvoEventHandler;
@@ -0,0 +1,81 @@
1
+ import { SpanKind } from '@opentelemetry/api';
2
+ import { ArvoContract, ArvoEvent, ResolveArvoContractRecord, CreateArvoEvent, OpenInferenceSpanKind, ArvoExecutionSpanKind } from 'arvo-core';
3
+ import { z } from 'zod';
4
+ /**
5
+ * Represents the input for an ArvoEvent handler function.
6
+ * @template TAccepts - The type of ArvoContractRecord that the handler accepts.
7
+ */
8
+ export type ArvoEventHandlerFunctionInput<TContract extends ArvoContract> = {
9
+ /** The ArvoEvent object. */
10
+ event: ArvoEvent<ResolveArvoContractRecord<TContract['accepts']>, Record<string, any>, TContract['accepts']['type']>;
11
+ };
12
+ /**
13
+ * Represents the output of an ArvoEvent handler function.
14
+ * @template TContract - The type of ArvoContract that the handler is associated with.
15
+ */
16
+ export type ArvoEventHandlerFunctionOutput<TContract extends ArvoContract> = {
17
+ [K in keyof TContract['emits']]: Omit<CreateArvoEvent<z.infer<TContract['emits'][K]>, K & string>, 'subject' | 'source' | 'executionunits' | 'traceparent' | 'tracestate'> & {
18
+ /**
19
+ * An optional override for the execution units of this specific event.
20
+ *
21
+ * @remarks
22
+ * Execution units represent the computational cost or resources required to process this event.
23
+ * If not provided, the default value defined in the handler's constructor will be used.
24
+ */
25
+ executionunits?: number;
26
+ /** Optional extensions for the event. */
27
+ __extensions?: Record<string, string | number | boolean>;
28
+ };
29
+ }[keyof TContract['emits']];
30
+ /**
31
+ * Defines the structure of an ArvoEvent handler function.
32
+ * @template TContract - The type of ArvoContract that the handler is associated with.
33
+ */
34
+ export type ArvoEventHandlerFunction<TContract extends ArvoContract> = (params: ArvoEventHandlerFunctionInput<TContract>) => Promise<ArvoEventHandlerFunctionOutput<TContract> | void>;
35
+ /**
36
+ * Interface for an ArvoEvent handler.
37
+ * @template T - The type of the contract (defaults to string).
38
+ * @template TAccepts - The type of ArvoContractRecord that the handler accepts.
39
+ * @template TEmits - The type of ArvoContractRecord that the handler emits.
40
+ */
41
+ export interface IArvoEventHandler<TContract extends ArvoContract> {
42
+ /**
43
+ * An override source for emitted events.
44
+ * @deprecated This field is deprecated and should be used with caution.
45
+ * @remarks
46
+ * When provided, this value will be used as the source for emitted events
47
+ * instead of the `contract.accepts.type`. Use this very carefully as it may
48
+ * reduce system transparency and make event tracking more difficult.
49
+ *
50
+ * It's recommended to rely on the default source (`contract.accepts.type`)
51
+ * whenever possible to maintain consistent and traceable event chains.
52
+ */
53
+ source?: string;
54
+ /**
55
+ * The contract for the handler defining its input and outputs as well as the description.
56
+ */
57
+ contract: TContract;
58
+ /**
59
+ * The default execution cost of the function.
60
+ * This can represent a dollar value or some other number with a rate card.
61
+ */
62
+ executionunits: number;
63
+ /**
64
+ * The functional handler of the event which takes the input, performs an action, and returns the result.
65
+ * @param params - The input parameters for the handler function.
66
+ * @returns A promise of object containing the created ArvoEvent and optional extensions.
67
+ */
68
+ handler: ArvoEventHandlerFunction<TContract>;
69
+ /**
70
+ * The OpenTelemetry span kind attributes for the handler
71
+ * executor.
72
+ * @param [openInference] - The OpenInference span kind. Default is "CHAIN"
73
+ * @param [arvoExecution] - The ArvoExecution span kind. Default is "EVENT_HANDLER"
74
+ * @param [openTelemetry] - The OpenTelemetry span kind. Default is "INTERNAL"
75
+ */
76
+ spanKind?: {
77
+ openInference?: OpenInferenceSpanKind;
78
+ arvoExecution?: ArvoExecutionSpanKind;
79
+ openTelemetry?: SpanKind;
80
+ };
81
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,48 @@
1
+ import MultiArvoEventHandler from '.';
2
+ import { IMultiArvoEventHandler } from './types';
3
+ /**
4
+ * Creates a MultiArvoEventHandler instance capable of handling multiple event types across different ArvoContracts.
5
+ *
6
+ * @param param - The configuration parameters for the event handler.
7
+ * @returns A new instance of MultiArvoEventHandler.
8
+ *
9
+ * @remarks
10
+ * This factory function instantiates a MultiArvoEventHandler, which is designed to process
11
+ * multiple event types from various ArvoContracts. Unlike the more specialized ArvoEventHandler,
12
+ * MultiArvoEventHandler offers greater flexibility by not being bound to a specific contract
13
+ * or event type.
14
+ *
15
+ * Key features of MultiArvoEventHandler:
16
+ * - Handles multiple event types
17
+ * - Works across different ArvoContracts
18
+ * - Provides a unified interface for diverse event processing
19
+ *
20
+ * The handler's behavior and resource allocation are determined by the provided configuration
21
+ * parameters, including execution units and the event processing logic.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const multiEventHandler = createMultiArvoEventHandler({
26
+ * source: 'com.multi.handler',
27
+ * executionunits: 100,
28
+ * handler: async ({ event }) => {
29
+ * switch(event.type) {
30
+ * case 'com.user.registered':
31
+ * // Handle user registration event
32
+ * break;
33
+ * case 'com.transaction.complete':
34
+ * // Handle transaction completion event
35
+ * break;
36
+ * // ... handle other event types
37
+ * }
38
+ * }
39
+ * });
40
+ *
41
+ * // Use the handler
42
+ * await multiEventHandler.handleEvent(someEvent);
43
+ * ```
44
+ *
45
+ * @see {@link IMultiArvoEventHandler} for the full configuration options
46
+ * @see {@link MultiArvoEventHandler} for the handler class implementation
47
+ */
48
+ export declare const createMultiArvoEventHandler: (param: IMultiArvoEventHandler) => MultiArvoEventHandler;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createMultiArvoEventHandler = void 0;
7
+ var _1 = __importDefault(require("."));
8
+ /**
9
+ * Creates a MultiArvoEventHandler instance capable of handling multiple event types across different ArvoContracts.
10
+ *
11
+ * @param param - The configuration parameters for the event handler.
12
+ * @returns A new instance of MultiArvoEventHandler.
13
+ *
14
+ * @remarks
15
+ * This factory function instantiates a MultiArvoEventHandler, which is designed to process
16
+ * multiple event types from various ArvoContracts. Unlike the more specialized ArvoEventHandler,
17
+ * MultiArvoEventHandler offers greater flexibility by not being bound to a specific contract
18
+ * or event type.
19
+ *
20
+ * Key features of MultiArvoEventHandler:
21
+ * - Handles multiple event types
22
+ * - Works across different ArvoContracts
23
+ * - Provides a unified interface for diverse event processing
24
+ *
25
+ * The handler's behavior and resource allocation are determined by the provided configuration
26
+ * parameters, including execution units and the event processing logic.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * const multiEventHandler = createMultiArvoEventHandler({
31
+ * source: 'com.multi.handler',
32
+ * executionunits: 100,
33
+ * handler: async ({ event }) => {
34
+ * switch(event.type) {
35
+ * case 'com.user.registered':
36
+ * // Handle user registration event
37
+ * break;
38
+ * case 'com.transaction.complete':
39
+ * // Handle transaction completion event
40
+ * break;
41
+ * // ... handle other event types
42
+ * }
43
+ * }
44
+ * });
45
+ *
46
+ * // Use the handler
47
+ * await multiEventHandler.handleEvent(someEvent);
48
+ * ```
49
+ *
50
+ * @see {@link IMultiArvoEventHandler} for the full configuration options
51
+ * @see {@link MultiArvoEventHandler} for the handler class implementation
52
+ */
53
+ var createMultiArvoEventHandler = function (param) { return new _1.default(param); };
54
+ exports.createMultiArvoEventHandler = createMultiArvoEventHandler;
@@ -0,0 +1,84 @@
1
+ import { SpanKind } from '@opentelemetry/api';
2
+ import { ArvoEvent, ArvoExecutionSpanKind, OpenInferenceSpanKind } from "arvo-core";
3
+ import { IMultiArvoEventHandler } from "./types";
4
+ /**
5
+ * Represents a Multi ArvoEvent handler that can process multiple event types.
6
+ *
7
+ * @remarks
8
+ * Unlike ArvoEventHandler, which is bound to a specific ArvoContract and handles
9
+ * events of a single type, MultiArvoEventHandler can handle multiple event types
10
+ * without being tied to a specific contract. This makes it more flexible for
11
+ * scenarios where you need to process various event types with a single handler.
12
+ */
13
+ export default class MultiArvoEventHandler {
14
+ /** The default execution cost associated with this handler */
15
+ readonly executionunits: number;
16
+ /**
17
+ * The source identifier for events produced by this handler
18
+ *
19
+ * @remarks
20
+ * For all the events which are emitted by the handler, this is
21
+ * the source field value of them all.
22
+ */
23
+ readonly source: string;
24
+ readonly openInferenceSpanKind: OpenInferenceSpanKind;
25
+ readonly arvoExecutionSpanKind: ArvoExecutionSpanKind;
26
+ readonly openTelemetrySpanKind: SpanKind;
27
+ private readonly _handler;
28
+ /**
29
+ * Creates an instance of MultiArvoEventHandler.
30
+ *
31
+ * @param param - The configuration parameters for the event handler.
32
+ * @throws {Error} Throws an error if the provided source is invalid.
33
+ */
34
+ constructor(param: IMultiArvoEventHandler);
35
+ /**
36
+ * Executes the event handler for a given event.
37
+ *
38
+ * @param event - The event to handle.
39
+ * @returns A promise that resolves to the resulting ArvoEvent.
40
+ *
41
+ * @remarks
42
+ * This method performs the following steps:
43
+ * 1. Creates an OpenTelemetry span for the execution.
44
+ * 2. Executes the handler function.
45
+ * 3. Creates and returns the result event.
46
+ * 4. Handles any errors and creates an error event if necessary.
47
+ *
48
+ * All telemetry data is properly set and propagated throughout the execution.
49
+ * The method ensures that the resulting event has the correct source, subject,
50
+ * and execution units, and includes any necessary tracing information.
51
+ */
52
+ execute(event: ArvoEvent): Promise<ArvoEvent | null>;
53
+ /**
54
+ * Provides the schema for system error events.
55
+ *
56
+ * @returns An object containing the error event type and schema.
57
+ *
58
+ * @remarks
59
+ * This getter defines the structure for system error events that may be emitted
60
+ * when an unexpected error occurs during event handling. The error event type
61
+ * is prefixed with 'sys.' followed by the handler's source and '.error'.
62
+ * The schema used for these error events is the standard ArvoErrorSchema.
63
+ *
64
+ * @example
65
+ * // If the handler's source is 'user.service'
66
+ * // The system error event type would be 'sys.user.service.error'
67
+ */
68
+ get systemErrorSchema(): {
69
+ type: string;
70
+ schema: import("zod").ZodObject<{
71
+ errorName: import("zod").ZodString;
72
+ errorMessage: import("zod").ZodString;
73
+ errorStack: import("zod").ZodNullable<import("zod").ZodString>;
74
+ }, "strip", import("zod").ZodTypeAny, {
75
+ errorName: string;
76
+ errorMessage: string;
77
+ errorStack: string | null;
78
+ }, {
79
+ errorName: string;
80
+ errorMessage: string;
81
+ errorStack: string | null;
82
+ }>;
83
+ };
84
+ }
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ var __generator = (this && this.__generator) || function (thisArg, body) {
23
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
+ function verb(n) { return function (v) { return step([n, v]); }; }
26
+ function step(op) {
27
+ if (f) throw new TypeError("Generator is already executing.");
28
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
29
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
+ if (y = 0, t) op = [op[0] & 2, t.value];
31
+ switch (op[0]) {
32
+ case 0: case 1: t = op; break;
33
+ case 4: _.label++; return { value: op[1], done: false };
34
+ case 5: _.label++; y = op[1]; op = [0]; continue;
35
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
+ default:
37
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
+ if (t[2]) _.ops.pop();
42
+ _.trys.pop(); continue;
43
+ }
44
+ op = body.call(thisArg, _);
45
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
+ }
48
+ };
49
+ var __rest = (this && this.__rest) || function (s, e) {
50
+ var t = {};
51
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
52
+ t[p] = s[p];
53
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
54
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
55
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
56
+ t[p[i]] = s[p[i]];
57
+ }
58
+ return t;
59
+ };
60
+ Object.defineProperty(exports, "__esModule", { value: true });
61
+ var api_1 = require("@opentelemetry/api");
62
+ var arvo_core_1 = require("arvo-core");
63
+ var schema_1 = require("arvo-core/dist/ArvoEvent/schema");
64
+ var OpenTelemetry_1 = require("../OpenTelemetry");
65
+ /**
66
+ * Represents a Multi ArvoEvent handler that can process multiple event types.
67
+ *
68
+ * @remarks
69
+ * Unlike ArvoEventHandler, which is bound to a specific ArvoContract and handles
70
+ * events of a single type, MultiArvoEventHandler can handle multiple event types
71
+ * without being tied to a specific contract. This makes it more flexible for
72
+ * scenarios where you need to process various event types with a single handler.
73
+ */
74
+ var MultiArvoEventHandler = /** @class */ (function () {
75
+ /**
76
+ * Creates an instance of MultiArvoEventHandler.
77
+ *
78
+ * @param param - The configuration parameters for the event handler.
79
+ * @throws {Error} Throws an error if the provided source is invalid.
80
+ */
81
+ function MultiArvoEventHandler(param) {
82
+ var _a, _b, _c;
83
+ this.openInferenceSpanKind = arvo_core_1.OpenInferenceSpanKind.CHAIN;
84
+ this.arvoExecutionSpanKind = arvo_core_1.ArvoExecutionSpanKind.EVENT_HANDLER;
85
+ this.openTelemetrySpanKind = api_1.SpanKind.INTERNAL;
86
+ this.executionunits = param.executionunits;
87
+ this._handler = param.handler;
88
+ var error = schema_1.CloudEventContextSchema.pick({
89
+ source: true
90
+ }).safeParse({ source: param.source }).error;
91
+ if (error) {
92
+ throw new Error("The provided 'source' is not a valid string. Error: ".concat(error.message));
93
+ }
94
+ this.source = param.source;
95
+ this.arvoExecutionSpanKind = ((_a = param.spanKind) === null || _a === void 0 ? void 0 : _a.arvoExecution) || this.arvoExecutionSpanKind;
96
+ this.openInferenceSpanKind = ((_b = param.spanKind) === null || _b === void 0 ? void 0 : _b.openInference) || this.openInferenceSpanKind;
97
+ this.openTelemetrySpanKind = ((_c = param.spanKind) === null || _c === void 0 ? void 0 : _c.openTelemetry) || this.openTelemetrySpanKind;
98
+ }
99
+ /**
100
+ * Executes the event handler for a given event.
101
+ *
102
+ * @param event - The event to handle.
103
+ * @returns A promise that resolves to the resulting ArvoEvent.
104
+ *
105
+ * @remarks
106
+ * This method performs the following steps:
107
+ * 1. Creates an OpenTelemetry span for the execution.
108
+ * 2. Executes the handler function.
109
+ * 3. Creates and returns the result event.
110
+ * 4. Handles any errors and creates an error event if necessary.
111
+ *
112
+ * All telemetry data is properly set and propagated throughout the execution.
113
+ * The method ensures that the resulting event has the correct source, subject,
114
+ * and execution units, and includes any necessary tracing information.
115
+ */
116
+ MultiArvoEventHandler.prototype.execute = function (event) {
117
+ return __awaiter(this, void 0, void 0, function () {
118
+ var spanName, spanOptions, span, inheritedContext;
119
+ var _a;
120
+ var _this = this;
121
+ return __generator(this, function (_b) {
122
+ switch (_b.label) {
123
+ case 0:
124
+ spanName = "MutliArvoEventHandler.source<".concat(this.source, ">.execute<").concat(event.type, ">");
125
+ spanOptions = {
126
+ kind: this.openTelemetrySpanKind,
127
+ attributes: (_a = {},
128
+ _a[arvo_core_1.OpenInference.ATTR_SPAN_KIND] = this.openInferenceSpanKind,
129
+ _a[arvo_core_1.ArvoExecution.ATTR_SPAN_KIND] = this.arvoExecutionSpanKind,
130
+ _a)
131
+ };
132
+ if (event.traceparent) {
133
+ inheritedContext = (0, OpenTelemetry_1.extractContext)(event.traceparent, event.tracestate);
134
+ span = OpenTelemetry_1.ArvoEventHandlerTracer.startSpan(spanName, spanOptions, inheritedContext);
135
+ }
136
+ else {
137
+ span = OpenTelemetry_1.ArvoEventHandlerTracer.startSpan(spanName, spanOptions);
138
+ }
139
+ return [4 /*yield*/, api_1.context.with(api_1.trace.setSpan(api_1.context.active(), span), function () { return __awaiter(_this, void 0, void 0, function () {
140
+ var otelSpanHeaders, output, __extensions, handlerResult, result, error_1, result;
141
+ return __generator(this, function (_a) {
142
+ switch (_a.label) {
143
+ case 0:
144
+ otelSpanHeaders = (0, arvo_core_1.currentOpenTelemetryHeaders)();
145
+ _a.label = 1;
146
+ case 1:
147
+ _a.trys.push([1, 3, 4, 5]);
148
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
149
+ Object.entries(event.otelAttributes).forEach(function (_a) {
150
+ var key = _a[0], value = _a[1];
151
+ return span.setAttribute("to_process.".concat(key), value);
152
+ });
153
+ return [4 /*yield*/, this._handler({ event: event })];
154
+ case 2:
155
+ output = _a.sent();
156
+ if (!output)
157
+ return [2 /*return*/, null];
158
+ __extensions = output.__extensions, handlerResult = __rest(output, ["__extensions"]);
159
+ result = (0, arvo_core_1.createArvoEvent)(__assign(__assign({}, handlerResult), { traceparent: otelSpanHeaders.traceparent || undefined, tracestate: otelSpanHeaders.tracestate || undefined, source: this.source, subject: event.subject, to: handlerResult.to || event.source, executionunits: handlerResult.executionunits || this.executionunits }), __extensions);
160
+ span.setAttributes(result.otelAttributes);
161
+ Object.entries(result.otelAttributes).forEach(function (_a) {
162
+ var key = _a[0], value = _a[1];
163
+ return span.setAttribute("to_emit.".concat(key), value);
164
+ });
165
+ return [2 /*return*/, result];
166
+ case 3:
167
+ error_1 = _a.sent();
168
+ (0, arvo_core_1.exceptionToSpan)(error_1);
169
+ span.setStatus({
170
+ code: api_1.SpanStatusCode.ERROR,
171
+ message: error_1.message,
172
+ });
173
+ result = (0, arvo_core_1.createArvoEvent)({
174
+ type: "sys.".concat(this.source, ".error"),
175
+ source: this.source,
176
+ subject: event.subject,
177
+ to: event.source,
178
+ executionunits: this.executionunits,
179
+ traceparent: otelSpanHeaders.traceparent || undefined,
180
+ tracestate: otelSpanHeaders.tracestate || undefined,
181
+ data: {
182
+ errorName: error_1.name,
183
+ errorMessage: error_1.message,
184
+ errorStack: error_1.stack || null
185
+ }
186
+ });
187
+ Object.entries(result.otelAttributes).forEach(function (_a) {
188
+ var key = _a[0], value = _a[1];
189
+ return span.setAttribute("to_emit.".concat(key), value);
190
+ });
191
+ return [2 /*return*/, result];
192
+ case 4:
193
+ span.end();
194
+ return [7 /*endfinally*/];
195
+ case 5: return [2 /*return*/];
196
+ }
197
+ });
198
+ }); })];
199
+ case 1: return [2 /*return*/, _b.sent()];
200
+ }
201
+ });
202
+ });
203
+ };
204
+ Object.defineProperty(MultiArvoEventHandler.prototype, "systemErrorSchema", {
205
+ /**
206
+ * Provides the schema for system error events.
207
+ *
208
+ * @returns An object containing the error event type and schema.
209
+ *
210
+ * @remarks
211
+ * This getter defines the structure for system error events that may be emitted
212
+ * when an unexpected error occurs during event handling. The error event type
213
+ * is prefixed with 'sys.' followed by the handler's source and '.error'.
214
+ * The schema used for these error events is the standard ArvoErrorSchema.
215
+ *
216
+ * @example
217
+ * // If the handler's source is 'user.service'
218
+ * // The system error event type would be 'sys.user.service.error'
219
+ */
220
+ get: function () {
221
+ return {
222
+ type: "sys.".concat(this.source, ".error"),
223
+ schema: arvo_core_1.ArvoErrorSchema
224
+ };
225
+ },
226
+ enumerable: false,
227
+ configurable: true
228
+ });
229
+ return MultiArvoEventHandler;
230
+ }());
231
+ exports.default = MultiArvoEventHandler;
@@ -0,0 +1,65 @@
1
+ import { SpanKind } from "@opentelemetry/api";
2
+ import { ArvoEvent, ArvoExecutionSpanKind, CreateArvoEvent, OpenInferenceSpanKind } from "arvo-core";
3
+ /**
4
+ * Represents the input for a Multi ArvoEvent handler function.
5
+ */
6
+ export type MultiArvoEventHandlerFunctionInput = {
7
+ event: ArvoEvent;
8
+ };
9
+ /**
10
+ * Represents the output of a Multi ArvoEvent handler function.
11
+ * @template TContract - The type of ArvoContract that the handler is associated with.
12
+ */
13
+ export type MultiArvoEventHandlerFunctionOutput = Omit<CreateArvoEvent<Record<string, any>, string>, 'subject' | 'source' | 'executionunits' | 'traceparent' | 'tracestate'> & {
14
+ /**
15
+ * An optional override for the execution units of this specific event.
16
+ *
17
+ * @remarks
18
+ * Execution units represent the computational cost or resources required to process this event.
19
+ * If not provided, the default value defined in the handler's constructor will be used.
20
+ */
21
+ executionunits?: number;
22
+ /** Optional extensions for the event. */
23
+ __extensions?: Record<string, string | number | boolean>;
24
+ };
25
+ /**
26
+ * Defines the structure of a Multi ArvoEvent handler function.
27
+ * @template TContract - The type of ArvoContract that the handler is associated with.
28
+ */
29
+ export type MultiArvoEventHandlerFunction = (param: MultiArvoEventHandlerFunctionInput) => Promise<MultiArvoEventHandlerFunctionOutput | void>;
30
+ /**
31
+ * Interface for an Multi ArvoEvent handler.
32
+ */
33
+ export interface IMultiArvoEventHandler {
34
+ /**
35
+ * The source definition of the MultiArvoEventHanlder.
36
+ *
37
+ * @remarks
38
+ * For all the events which are emitted by the handler, this will be the source
39
+ * field value of them all.
40
+ */
41
+ source: string;
42
+ /**
43
+ * The default execution cost of the function.
44
+ * This can represent a dollar value or some other number with a rate card.
45
+ */
46
+ executionunits: number;
47
+ /**
48
+ * The functional handler of the event which takes the input, performs an action, and returns the result.
49
+ * @param params - The input parameters for the handler function.
50
+ * @returns A promise of object containing the created ArvoEvent and optional extensions.
51
+ */
52
+ handler: MultiArvoEventHandlerFunction;
53
+ /**
54
+ * The OpenTelemetry span kind attributes for the handler
55
+ * executor.
56
+ * @param [openInference] - The OpenInference span kind. Default is "CHAIN"
57
+ * @param [arvoExecution] - The ArvoExecution span kind. Default is "EVENT_HANDLER"
58
+ * @param [openTelemetry] - The OpenTelemetry span kind. Default is "INTERNAL"
59
+ */
60
+ spanKind?: {
61
+ openInference?: OpenInferenceSpanKind;
62
+ arvoExecution?: ArvoExecutionSpanKind;
63
+ openTelemetry?: SpanKind;
64
+ };
65
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,6 @@
1
+ import { Context } from '@opentelemetry/api';
2
+ /**
3
+ * A tracer instance for the ArvoEventHandler package.
4
+ */
5
+ export declare const ArvoEventHandlerTracer: import("@opentelemetry/api").Tracer;
6
+ export declare const extractContext: (traceparent: string, tracestate: string | null) => Context;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractContext = exports.ArvoEventHandlerTracer = void 0;
4
+ var api_1 = require("@opentelemetry/api");
5
+ var utils_1 = require("./utils");
6
+ var pkg = (0, utils_1.getPackageInfo)();
7
+ /**
8
+ * A tracer instance for the ArvoEventHandler package.
9
+ */
10
+ exports.ArvoEventHandlerTracer = api_1.trace.getTracer(pkg.name, pkg.version);
11
+ // Helper function to extract context from traceparent and tracestate
12
+ var extractContext = function (traceparent, tracestate) {
13
+ var extractedContext = api_1.propagation.extract(api_1.context.active(), {
14
+ traceparent: traceparent,
15
+ tracestate: tracestate || undefined,
16
+ });
17
+ return extractedContext;
18
+ };
19
+ exports.extractContext = extractContext;
@@ -0,0 +1,4 @@
1
+ export declare function getPackageInfo(): {
2
+ name: string;
3
+ version: string;
4
+ };
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.getPackageInfo = getPackageInfo;
27
+ var fs = __importStar(require("fs"));
28
+ var path = __importStar(require("path"));
29
+ function getPackageInfo() {
30
+ try {
31
+ // Read the package.json file
32
+ var packageJsonPath = path.resolve(__dirname, '../../package.json');
33
+ var packageJsonContent = fs.readFileSync(packageJsonPath, 'utf-8');
34
+ // Parse the JSON content
35
+ var packageJson = JSON.parse(packageJsonContent);
36
+ // Extract name and version
37
+ var name_1 = packageJson.name, version = packageJson.version;
38
+ return { name: name_1, version: version };
39
+ }
40
+ catch (error) {
41
+ console.error('Error reading package.json:', error);
42
+ return { name: 'Unknown', version: 'Unknown' };
43
+ }
44
+ }
@@ -0,0 +1,8 @@
1
+ import ArvoEventHandler from './ArvoEventHandler';
2
+ import { ArvoEventHandlerFunctionInput, ArvoEventHandlerFunctionOutput, ArvoEventHandlerFunction, IArvoEventHandler } from './ArvoEventHandler/types';
3
+ import { createArvoEventHandler } from './ArvoEventHandler/helpers';
4
+ import { PartialExcept } from './types';
5
+ import MultiArvoEventHandler from './MultiArvoEventHandler';
6
+ import { MultiArvoEventHandlerFunctionInput, MultiArvoEventHandlerFunctionOutput, MultiArvoEventHandlerFunction, IMultiArvoEventHandler } from './MultiArvoEventHandler/types';
7
+ import { createMultiArvoEventHandler } from './MultiArvoEventHandler/helpers';
8
+ export { ArvoEventHandler, createArvoEventHandler, IArvoEventHandler, ArvoEventHandlerFunctionOutput, ArvoEventHandlerFunctionInput, ArvoEventHandlerFunction, PartialExcept, MultiArvoEventHandler, MultiArvoEventHandlerFunctionInput, MultiArvoEventHandlerFunctionOutput, MultiArvoEventHandlerFunction, IMultiArvoEventHandler, createMultiArvoEventHandler, };
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createMultiArvoEventHandler = exports.MultiArvoEventHandler = exports.createArvoEventHandler = exports.ArvoEventHandler = void 0;
7
+ var ArvoEventHandler_1 = __importDefault(require("./ArvoEventHandler"));
8
+ exports.ArvoEventHandler = ArvoEventHandler_1.default;
9
+ var helpers_1 = require("./ArvoEventHandler/helpers");
10
+ Object.defineProperty(exports, "createArvoEventHandler", { enumerable: true, get: function () { return helpers_1.createArvoEventHandler; } });
11
+ var MultiArvoEventHandler_1 = __importDefault(require("./MultiArvoEventHandler"));
12
+ exports.MultiArvoEventHandler = MultiArvoEventHandler_1.default;
13
+ var helpers_2 = require("./MultiArvoEventHandler/helpers");
14
+ Object.defineProperty(exports, "createMultiArvoEventHandler", { enumerable: true, get: function () { return helpers_2.createMultiArvoEventHandler; } });
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Creates a new type based on T where all properties are optional except for those specified in K.
3
+ *
4
+ * @template T - The original type.
5
+ * @template K - A union of keys from T that should remain required.
6
+ *
7
+ * @example
8
+ * interface User {
9
+ * id: number;
10
+ * name: string;
11
+ * email: string;
12
+ * }
13
+ *
14
+ * type PartialUserExceptId = PartialExcept<User, 'id'>;
15
+ * // Equivalent to: { id: number; name?: string; email?: string; }
16
+ */
17
+ export type PartialExcept<T, K extends keyof T> = Partial<Omit<T, K>> & Pick<T, K>;
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "arvo-event-handler",
3
+ "version": "0.0.1",
4
+ "description": "This package contains class and function for event handlers in an Arvo Event Driven system",
5
+ "main": "dist/index.js",
6
+ "scripts": {
7
+ "build": "tsc",
8
+ "start": "node ./dist/index.js",
9
+ "dev": "ts-node ./src/index.ts",
10
+ "test": "jest --passWithNoTests --runInBand --detectOpenHandles --forceExit",
11
+ "format": "npx prettier --write .",
12
+ "doc": "npx typedoc"
13
+ },
14
+ "keywords": [
15
+ "arvo",
16
+ "event-driven architecture",
17
+ "xorca",
18
+ "core",
19
+ "cloudevent",
20
+ "opentelemetry",
21
+ "orchestrator"
22
+ ],
23
+ "author": "Saad Ahmad <saadkwi12@hotmail.com>",
24
+ "license": "MIT",
25
+ "devDependencies": {
26
+ "@jest/globals": "^29.7.0",
27
+ "@opentelemetry/auto-instrumentations-node": "^0.49.1",
28
+ "@opentelemetry/exporter-metrics-otlp-proto": "^0.52.1",
29
+ "@opentelemetry/exporter-trace-otlp-grpc": "^0.53.0",
30
+ "@opentelemetry/exporter-trace-otlp-proto": "^0.52.1",
31
+ "@opentelemetry/resources": "^1.25.1",
32
+ "@opentelemetry/sdk-metrics": "^1.25.1",
33
+ "@opentelemetry/sdk-node": "^0.52.1",
34
+ "@opentelemetry/sdk-trace-node": "^1.25.1",
35
+ "@opentelemetry/semantic-conventions": "^1.25.1",
36
+ "@types/jest": "^29.5.12",
37
+ "@types/node": "^22.5.0",
38
+ "@types/uuid": "^10.0.0",
39
+ "dotenv": "^16.4.5",
40
+ "jest": "^29.7.0",
41
+ "prettier": "^3.3.3",
42
+ "ts-jest": "^29.2.5",
43
+ "ts-node": "^10.9.2",
44
+ "typedoc": "^0.26.6",
45
+ "typedoc-plugin-zod": "^1.2.1",
46
+ "typescript": "^5.5.4"
47
+ },
48
+ "dependencies": {
49
+ "@opentelemetry/api": "^1.9.0",
50
+ "arvo-core": "^1.0.26",
51
+ "uuid": "^10.0.0",
52
+ "zod": "^3.23.8"
53
+ }
54
+ }