UNPKG

entangle.ts

Version:

A declarative, event-driven framework for orchestrating business logic in TypeScript & Node.js applications.

310 lines (309 loc) 14 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Superposition = void 0; const HawkingRadiation_1 = require("../hawking-radiation/HawkingRadiation"); const ConsoleLogger_1 = require("../logging/ConsoleLogger"); const Logging_1 = require("../logging/Logging"); const QuantumPointer_1 = require("../quantum-pointer/QuantumPointer"); const Notation_1 = require("../shared/Notation"); const Logging_types_1 = require("../shared/types/Logging.types"); const Gateway_builder_1 = require("./builders/Gateway.builder"); /** * In quantum mechanics, Superposition is the principle that a system can exist in * multiple potential states at once, collapsing into a single reality upon observation. * * In Entangle.ts, the `Superposition` class is the embodiment of this principle. * It is the central orchestrator—the "laws of physics" for your application. * It listens for events from the Aether, consults the EventHorizon for historical * context, and executes rule-based interactions, creating and manipulating * particles within the HiggsField and its temporary scopes. * * @class Superposition * @param aether The communication medium, responsible for event transport. * @param higgs The foundational field, the main container for service particles. * @param horizon The historical record, providing context of all past events. */ class Superposition { constructor(aether, higgs, horizon, errorHandler) { this.aether = aether; this.higgs = higgs; this.horizon = horizon; this.errorHandler = errorHandler; this.particlesContracts = new Map(); // eslint-disable-next-line @typescript-eslint/no-explicit-any this.contracts = []; // eslint-disable-next-line @typescript-eslint/no-explicit-any this.interactions = []; this.logger = new Logging_1.Logging('custom', new ConsoleLogger_1.ConsoleLogger()); } /** * Begins the declarative definition of a rule that is triggered by a specific event. * This is the entry point for defining any "law" in the application. * @param event The name of the event that triggers the rule. * @returns A `GatewayBuilder` instance to continue defining the rule by choosing an * action (`.build()` or `.use()`). */ upon(event) { return new Gateway_builder_1.GatewayBuilder(this, event); } /** * Check if there are any particles that can be created */ checkForParticlesCreation(event, entanglement) { const filteredContracts = this.contracts.filter((contract) => contract.upon === event && contract.entanglement === entanglement); for (const contract of filteredContracts) { const shouldCreateAParticle = this.canCreateAParticle(contract); if (shouldCreateAParticle) { this.createAParticle(contract); } } } /** * Checks if a particle creation rule can be executed based on its `when` clause. * @internal */ canCreateAParticle(contract) { const { upon, when, is, requirements } = contract; // Checks if the 'when' clause is satisfied if (typeof when !== 'undefined') { const notation = Notation_1.Notation.create(when); const data = this.horizon.query().from(upon).using(notation).get(); const parsedData = notation.getData(data); if (parsedData !== is) { this.logger.log({ type: Logging_types_1.ELogType.CREATION, message: `Condition not met for particle creation: expected '${is}', got '${parsedData}'`, }); return false; } } // Checks if the requirements are satisfied. // If not, nothing happens if (requirements === null || requirements === void 0 ? void 0 : requirements.length) { for (const event of requirements) { const eventOcurred = this.horizon.query().from(event).using(Notation_1.Notation.create()).get(); if (eventOcurred === undefined) { this.logger.log({ type: Logging_types_1.ELogType.CREATION, message: `Requirement not met for particle creation: event '${event}' has not occurred`, }); return false; } } } return true; } /** * Creates a particle instance and registers it within the specified scope * (or the main HiggsField if no scope is provided), making it available for * other interactions. * @internal */ createAParticle(contract) { const { upon, build, using, then, scope, emit, lifecycle, destroyOnInteraction, errorHandler, entanglement, } = contract; const context = scope !== null && scope !== void 0 ? scope : this.higgs; const selectedErrorhandler = errorHandler !== null && errorHandler !== void 0 ? errorHandler : this.errorHandler; const parsedArgs = using ? using.map((arg) => { if (arg instanceof Notation_1.Notation) { return arg.getData(this.horizon.query().from(upon).get()); } if (arg instanceof QuantumPointer_1.QuantumPointer) { return arg.get(); } if (arg instanceof HawkingRadiation_1.HawkingRadiation) { return arg.get(); } return arg; }) : []; try { this.logger.log({ type: Logging_types_1.ELogType.CREATION, message: `Creating particle ${build.name} with arguments [${parsedArgs.join(',')}]`, }); context.register(build, () => new build(...parsedArgs), { destroyOnInteraction, lifecycle, }); const particle = new build(...parsedArgs); this.logger.log({ message: `Particle ${build.name} were built with arguments [${parsedArgs.join(',')}]`, type: Logging_types_1.ELogType.CREATION, }); if (then) { this.logger.log({ message: `Executing 'then' callback for particle ${build.name}`, type: Logging_types_1.ELogType.INTERACTION, }); Promise.resolve(particle).then((res) => then(res)); } if (emit) { this.logger.log({ message: `Emitting event '${emit}' with entanglement '${entanglement}' for particle ${build.name}`, type: Logging_types_1.ELogType.INTERACTION, }); this.aether.emit(emit, entanglement, particle); } } catch (err) { selectedErrorhandler === null || selectedErrorhandler === void 0 ? void 0 : selectedErrorhandler.handle(err, { rule: contract, event: upon, eventArgs: parsedArgs, }); } } /** * Registers a particle creation contract, setting up a listener for its trigger event. * This method is intended to be called by a builder. * @internal */ addContract(contract) { const { upon, once } = contract; const subscribeMethod = once ? 'once' : 'on'; this.aether[subscribeMethod](upon, (boson) => { const { payload, entanglement } = boson; this.logger.log({ type: Logging_types_1.ELogType.CREATION, message: `Event '${upon}' entangled to '${entanglement}' received payload: ${JSON.stringify(payload)}`, }); this.horizon.add(upon, payload); this.checkForParticlesCreation(upon, entanglement); this.checkForParticlesInteractions(upon, entanglement); }); this.contracts.push(contract); return this; } /** * Registers an interaction contract, setting up a listener if it's event-driven. * This method is intended to be called by a builder. * @internal */ addInteraction(interaction) { this.interactions.push(interaction); const { upon, once } = interaction; const subscribeMethod = once ? 'once' : 'on'; if (upon) { this.aether[subscribeMethod](upon, (boson) => { const { payload, entanglement } = boson; this.logger.log({ type: Logging_types_1.ELogType.INTERACTION, message: `Event '${upon}' entangled to '${entanglement}' received payload: ${JSON.stringify(payload)}`, }); this.horizon.add(upon, payload); this.checkForParticlesCreation(upon, entanglement); this.checkForParticlesInteractions(upon, entanglement); }); } return this; } /** * Checks for and executes all interaction rules triggered by a specific event. * @internal */ checkForParticlesInteractions(event, entanglement) { const filteredInteractions = this.interactions.filter((i) => i.upon === event && i.entanglement === entanglement); for (const interaction of filteredInteractions) { const { use: target } = interaction; let instance; if (target instanceof Notation_1.Notation) { instance = this.horizon.query().using(target).get(); } else if (target instanceof QuantumPointer_1.QuantumPointer) { instance = target.get(); } else { instance = this.higgs.get(target); } if (!instance) { this.logger.log({ type: Logging_types_1.ELogType.ERROR, message: `Could not resolve instance for target: ${JSON.stringify(target)}`, }); throw new Error('Instance could not be resolved from target.'); } this.interact(interaction, instance); } } interact(interaction, instance) { var _a; const { use: target, call, with: args, then, emit, errorHandler, upon, entanglement, } = interaction; const selectedErrorhandler = errorHandler !== null && errorHandler !== void 0 ? errorHandler : this.errorHandler; try { const _args = []; if (args) { for (const arg of args) { if (arg instanceof Notation_1.Notation) { _args.push(arg.getData(this.horizon.query().get())); continue; } if (arg instanceof HawkingRadiation_1.HawkingRadiation) { _args.push(arg.get()); } _args.push(arg); } } // eslint-disable-next-line @typescript-eslint/no-explicit-any const methodToCall = instance[call]; if (typeof methodToCall === 'function') { this.logger.log({ type: Logging_types_1.ELogType.INTERACTION, message: `Executing method '${String(call)}' on particle ${instance.constructor.name} with arguments [${_args.join(',')}]`, }); const result = Promise.resolve(methodToCall.bind(instance)(..._args)); this.logger.log({ message: `Executed method '${String(call)}' on particle ${instance.constructor.name} with arguments [${_args.join(',')}]`, type: Logging_types_1.ELogType.INTERACTION, }); result .then((res) => { if (then) { this.logger.log({ message: `Executing 'then' callback for particle ${instance.constructor.name}`, type: Logging_types_1.ELogType.INTERACTION, }); then(res); } }) .catch((err) => { selectedErrorhandler === null || selectedErrorhandler === void 0 ? void 0 : selectedErrorhandler.handle(err, { rule: interaction, event: upon, eventArgs: _args, }); }); if (emit) { this.logger.log({ message: `Emitting event '${emit}' with entanglement '${entanglement}' for particle ${instance.constructor.name}`, type: Logging_types_1.ELogType.INTERACTION, }); this.aether.emit(emit, entanglement, result); } } else { const errDesc = `Method "${String(call)}" does not exist or is not a function on particle "${instance.constructor.name}".`; this.logger.log({ type: Logging_types_1.ELogType.ERROR, message: errDesc, }); throw new Error(errDesc); } if (!((_a = this.higgs.getParticleOptions(target)) === null || _a === void 0 ? void 0 : _a.destroyOnInteraction)) { this.higgs.destroy(target); this.logger.log({ message: `Particle ${instance.constructor.name} destroyed`, type: Logging_types_1.ELogType.DESTRUCTION, }); } } catch (err) { selectedErrorhandler === null || selectedErrorhandler === void 0 ? void 0 : selectedErrorhandler.handle(err, { rule: interaction, event: upon, eventArgs: args, }); } } } exports.Superposition = Superposition;