UNPKG

arvo-core

Version:

The core Arvo package which provides application tier core primitives and contract system for building production-grade event-driven application. Provides ArvoEvent (CloudEvents-compliant), ArvoContract for type-safe service interfaces, event factories, O

248 lines (247 loc) 10.3 kB
import type { InferArvoEvent } from '../types'; import type { ArvoEventData, ArvoExtension, CloudEventContext, CloudEventExtension, OpenTelemetryExtension } from './types'; /** * Represents an ArvoEvent, which extends the CloudEvent specification with * Arvo-specific extensions for event routing, access control, execution metrics, * and OpenTelemetry distributed tracing support. */ export default class ArvoEvent<TData extends ArvoEventData = ArvoEventData, TExtension extends CloudEventExtension = CloudEventExtension, TType extends string = string> { /** Unique identifier of the event */ readonly id: string; /** * URI reference identifying the context in which the event happened. * Must be a properly encoded URI representing the event producer. */ readonly source: string; /** * The version of the CloudEvents specification which the event uses. * Must be '1.0' for this version of the specification. */ readonly specversion: string; /** * Describes the type of event related to the originating occurrence. * Must follow reverse-DNS naming convention (e.g., 'com.example.service.eventtype'). */ readonly type: TType; /** * Identifies the subject of the event in the context of the event producer. * In Arvo, this must be the Process ID and must be a properly encoded URI. */ readonly subject: string; /** * Content type of the data value following RFC 2046 format. * Must contain 'application/cloudevents+json' or 'application/json'. * Defaults to 'application/cloudevents+json;charset=UTF-8;profile=arvo'. */ readonly datacontenttype: string; /** * URI identifying the schema that the data adheres to. * Must be a properly encoded URI if present, null otherwise. */ readonly dataschema: string | null; /** The event data payload as a JSON serializable object */ readonly data: TData; /** * Timestamp of when the occurrence happened in RFC 3339 format. * If the actual occurrence time cannot be determined, this may be set * to another time (such as current time) by the producer. */ readonly time: string; private readonly _extensions; /** * Creates an instance of ArvoEvent with CloudEvent context, data, and optional extensions. * * @param context - The CloudEvent context combined with required Arvo and OpenTelemetry extensions * @param data - The event data payload (must be JSON serializable) * @param extensions - Optional additional custom extensions with lowercase alphanumeric keys * * @throws {Error} If datacontenttype is "application/cloudevents+json;charset=UTF-8;profile=arvo" but the 'to' field is not defined * @throws {Error} If any validation fails according to the respective schemas * * @example * ```typescript * const event = new ArvoEvent( * { * id: 'event-123', * source: 'https://example.com/service', * type: 'com.example.user.created', * subject: 'https://example.com/users/123', * time: new Date().toISOString(), * specversion: '1.0', * datacontenttype: 'application/cloudevents+json;charset=UTF-8;profile=arvo', * dataschema: null, * to: 'com.example.user.processor', * accesscontrol: 'role:admin;department:hr', * redirectto: null, * executionunits: 10, * parentid: 'parent-event-456', * domain: 'analytics', * traceparent: '00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01', * tracestate: 'vendor=trace-data' * }, * { userId: '123', name: 'John Doe' } * ); * ``` */ constructor(context: CloudEventContext & ArvoExtension & OpenTelemetryExtension, data: TData, extensions?: TExtension); /** * Gets the CloudEvent-specified fields separated into default attributes and extensions. * * @returns An object containing: * - `default`: Standard CloudEvent attributes (id, source, specversion, type, subject, datacontenttype, dataschema, data, time) * - `extensions`: All extension attributes including: * - Arvo extensions * - OpenTelemetry extensions * - Custom extensions * * @example * ```typescript * const { default: defaults, extensions } = event.cloudevent; * console.log(defaults.id); // Event ID * console.log(extensions.to); // Arvo 'to' field * ``` */ get cloudevent(): { default: { id: string; source: string; specversion: string; type: TType; subject: string; datacontenttype: string; dataschema: string | null; data: TData; time: string; }; extensions: TExtension & { to: string | null; accesscontrol: string | null; redirectto: string | null; executionunits: number | null; parentid: string | null; domain: string | null; } & { traceparent: string | null; tracestate: string | null; }; }; /** * Converts the ArvoEvent to a JSON-serializable object by combining * all CloudEvent default fields with all extensions into a single flat object. * * @returns A flat object containing all CloudEvent fields and extensions, * suitable for JSON serialization and network transmission * * @remarks * This method creates a flattened representation where both standard CloudEvent * fields and all extensions (Arvo, OpenTelemetry, and custom) are at the same level. * For separated access to defaults and extensions, use the `cloudevent` getter instead. * * @example * ```typescript * const jsonObj = event.toJSON(); * // Contains: id, source, type, subject, data, time, to, traceparent, etc. * ``` */ toJSON(): InferArvoEvent<typeof this>; /** * Converts the ArvoEvent to a JSON string representation. * * @param spacing - The number of spaces to use for indentation (default: 0 for compact output) * @returns A JSON string representation of the complete ArvoEvent * * @example * ```typescript * const compactJson = event.toString(); // Compact JSON * const prettyJson = event.toString(2); // Pretty-printed with 2-space indentation * ``` */ toString(spacing?: number): string; /** * Gets OpenTelemetry attributes derived from the ArvoEvent for distributed tracing. * * @returns An object containing OpenTelemetry semantic convention attributes: * - Standard CloudEvent attributes prefixed with 'cloudevents.event_*' * - Arvo-specific attributes prefixed with 'cloudevents.arvo.*' * - Uses 'N/A' for undefined/null values to maintain telemetry consistency * * @remarks * The attributes follow the OpenTelemetry semantic conventions for CloudEvents * as specified in the official documentation: * https://opentelemetry.io/docs/specs/semconv/attributes-registry/cloudevents/ */ get otelAttributes(): { 'cloudevents.event_id': string; 'cloudevents.event_source': string; 'cloudevents.event_spec_version': string; 'cloudevents.event_subject': string; 'cloudevents.event_type': string | TType; 'cloudevents.event_time': string; 'cloudevents.event_datacontenttype': string; 'cloudevents.event_dataschema': string; 'cloudevents.arvo.event_redirectto': string; 'cloudevents.arvo.event_to': string; 'cloudevents.arvo.event_executionunits': string | number; 'cloudevents.arvo.event_parentid': string; 'cloudevents.arvo.event_domain': string; }; /** * Gets the target consumer machine for event routing. */ get to(): string | null; /** * Gets the access control information for the event. * Can contain: * - A UserID (valid UUID) * - An encrypted base64 string with access control data * - Key-value pairs (semicolon-separated, colon-delimited) * Example: "role:admin;department:finance;clearance:top-secret" */ get accesscontrol(): string | null; /** * Gets the alternative recipient or destination for dynamic routing. * Enables complex workflows and conditional event routing. */ get redirectto(): string | null; /** * Gets the execution units representing the cost associated with * generating this event. Used for tracking financial impact and * resource utilization in cloud-based systems. */ get executionunits(): number | null; /** * Gets the OpenTelemetry traceparent header containing trace context * information including trace ID, parent span ID, and trace flags * for distributed tracing across services. */ get traceparent(): string | null; /** * Gets the OpenTelemetry tracestate header containing vendor-specific * trace information as key-value pairs propagated alongside traceparent * in distributed tracing scenarios. */ get tracestate(): string | null; /** * Gets the unique identifier of the event that directly triggered * the creation of this event within the Arvo ecosystem. * Establishes direct causal relationships for event lineage tracking. * Null indicates an initiating event or generation outside direct causation. */ get parentid(): string | null; /** * Gets the processing domain for event routing and workflow orchestration. */ get domain(): string | null; /** * Gets only the custom extensions (TExtension) added to the ArvoEvent, * excluding the standard Arvo and OpenTelemetry extensions. * * @returns The custom extensions object with Arvo and OpenTelemetry fields removed * * @remarks * For accessing all extensions including Arvo and OpenTelemetry, use `cloudevent.extensions`. * For accessing basic CloudEvent fields, use `cloudevent.default`. * Custom extension keys must follow lowercase alphanumeric naming (a-z, 0-9 only). */ get extensions(): TExtension; }