"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.IntentDispatcher = void 0; const optional_1 = require("../../types/optional"); const intent_controller_1 = require("./intent-controller"); const net_1 = require("../../types/globals/net"); const types_1 = require("../../types/globals/types"); /** * A dispatcher is responsible for taking an intent and invoking the controller * registered to handle the intent's kind. * * Adopters can create a project specific dispatcher that composes `IntentDispatcher` * to add additional functionality. * * @example * ``` * const intent: SomeIntent = { * $kind: "SomeIntent", * field: "some value" * }; * const dispatcher = new IntentDispatcher(); * const promise = dispatcher.dispatch(intent) * ``` */ class IntentDispatcher { constructor() { this.dispatchableMap = {}; } /** * Registers a controller to handle the intent specified in the `$intentKind` property. * Only one controller can be registered per intent. If register is called multiple times * with controllers for the same intent kind, the dispatcher will use the last registered * controller. * @param intentController - The controller to register. */ register(dispatchable) { if ((0, optional_1.isNothing)(dispatchable.$intentKind)) { throw new Error(`Dispatcher cannot register a controller without an $intentKind`); } if (dispatchable.$intentKind in this.dispatchableMap) { throw new Error(`Dispatcher already has a controller registered for ${dispatchable.$intentKind}`); } this.dispatchableMap[dispatchable.$intentKind] = dispatchable; } /** * Performs an intent using the controller registered to handle the provided intent. * Returns a rejected promise if no controller is registered to handle the intent. * @param intent - The intent to perform. * @param objectGraph - An object graph for dependency injection. */ async dispatch(intent, objectGraph) { if (intent.$kind === "$static") { // MAINTAINER'S NOTE: We specially handle static intents here to cover two cases: // 1) static intents created and dispatched wholly inside an app's // JavaScript business layer; // 2) static intents created from JavaScript running on an older // version of native JetEngine that does not support static intents // where the intent is boxed in an opaque intent in the platform layer. // Static intents are normally not dispatched across an app's layers. const data = Reflect.get(intent, "$data"); if ((0, optional_1.isNothing)(data)) { throw new Error("StaticIntent contains no data"); } return data; } const controller = this.dispatchableMap[intent.$kind]; if ((0, optional_1.isNothing)(controller) || !(0, intent_controller_1.isIntentController)(controller)) { throw new Error(`No controller registered to handle ${intent.$kind}`); } // Replace the `net` dependency with a proxy which includes instrumentation. const pageIntentInstrumentation = intent.$pageIntentInstrumentation; const network = objectGraph.optional(types_1.net); if ((0, optional_1.isSome)(pageIntentInstrumentation) && (0, optional_1.isSome)(network)) { const proxiedNetwork = new net_1.ProxiedNetwork(network, pageIntentInstrumentation); const modifiedObjectGraph = objectGraph.adding(types_1.net, proxiedNetwork); return await controller.perform(intent, modifiedObjectGraph); } else { return await controller.perform(intent, objectGraph); } } /** * Returns the controller registered for the provided intent. * @param intent - An intent to find the controller for. */ controller(intent) { return this.dispatchableMap[intent.$kind]; } /** * An array of all registered controllers. */ get registeredControllers() { return Object.values(this.dispatchableMap); } } exports.IntentDispatcher = IntentDispatcher; //# sourceMappingURL=dispatcher.js.map