diff options
Diffstat (limited to 'node_modules/@jet/environment/dispatching/base')
5 files changed, 311 insertions, 0 deletions
diff --git a/node_modules/@jet/environment/dispatching/base/dispatchable.js b/node_modules/@jet/environment/dispatching/base/dispatchable.js new file mode 100644 index 0000000..28a04b6 --- /dev/null +++ b/node_modules/@jet/environment/dispatching/base/dispatchable.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=dispatchable.js.map
\ No newline at end of file diff --git a/node_modules/@jet/environment/dispatching/base/dispatcher.js b/node_modules/@jet/environment/dispatching/base/dispatcher.js new file mode 100644 index 0000000..1b1e62d --- /dev/null +++ b/node_modules/@jet/environment/dispatching/base/dispatcher.js @@ -0,0 +1,97 @@ +"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<R> 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
\ No newline at end of file diff --git a/node_modules/@jet/environment/dispatching/base/index.js b/node_modules/@jet/environment/dispatching/base/index.js new file mode 100644 index 0000000..0baa3dd --- /dev/null +++ b/node_modules/@jet/environment/dispatching/base/index.js @@ -0,0 +1,21 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./intent-controller"), exports); +__exportStar(require("./dispatcher"), exports); +__exportStar(require("./dispatchable"), exports); +__exportStar(require("./intent"), exports); +//# sourceMappingURL=index.js.map
\ No newline at end of file diff --git a/node_modules/@jet/environment/dispatching/base/intent-controller.js b/node_modules/@jet/environment/dispatching/base/intent-controller.js new file mode 100644 index 0000000..81f4ba5 --- /dev/null +++ b/node_modules/@jet/environment/dispatching/base/intent-controller.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isIntentController = void 0; +const optional_1 = require("../../types/optional"); +function isIntentController(controller) { + if (typeof controller !== "object") { + return false; + } + return (0, optional_1.isSome)(controller === null || controller === void 0 ? void 0 : controller["perform"]); +} +exports.isIntentController = isIntentController; +//# sourceMappingURL=intent-controller.js.map
\ No newline at end of file diff --git a/node_modules/@jet/environment/dispatching/base/intent.js b/node_modules/@jet/environment/dispatching/base/intent.js new file mode 100644 index 0000000..b46bf79 --- /dev/null +++ b/node_modules/@jet/environment/dispatching/base/intent.js @@ -0,0 +1,178 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Continuous = exports.makeSidepackedIntent = exports.makeStaticContinuousIntentsOf = exports.makeStaticIntent = void 0; +/** + * Create a static intent. + * + * @param data - The data to wrap. + * @returns A new static intent ready for use. + */ +function makeStaticIntent(data) { + const intent = { + $kind: "$static", + $data: data, + }; + return intent; +} +exports.makeStaticIntent = makeStaticIntent; +/** + * Transform an array of data into an array of continuous static intents. + * + * @param elements - An array of data to wrap. + * @returns A new static intent ready for use. + */ +function makeStaticContinuousIntentsOf(elements) { + const intents = new Array(); + for (const element of elements) { + intents.push(makeStaticIntent(Continuous.of(element))); + } + return intents; +} +exports.makeStaticContinuousIntentsOf = makeStaticContinuousIntentsOf; +/** + * Create a sidepacked intent. + * + * @param data - The initial value to use before the provided intent is dispatched. + * @param intent - The intent that JetEngine should resolve when rendered. + * @returns A new sidepacked intent ready for use. + */ +function makeSidepackedIntent(initial, intent) { + const sidepackedIntent = { + $kind: "$sidepacked", + $initial: initial, + $intent: intent, + }; + return sidepackedIntent; +} +exports.makeSidepackedIntent = makeSidepackedIntent; +// MARK: - Continuous +/** + * A async iterable which allows an intent implementation to vend data + * which changes over time, such as the state of a buy button, + * or database-backed shelves on a page. + * + * Use `Continuous` to specify that an intent embedded in a model, + * or passed to a view, vends data which changes over time instead + * of being calculated once at the time the intent is dispatched. + * + * ```typescript + * export interface Page extends PageModel { + * readonly shelves: Intent<Continuous<Shelf>>[]; + * } + * ``` + * + * A continuous async iterable can be created with a single element. + * This allows a model built around continuous intents to still cleanly + * represent data which will not change after being displayed the first time. + * + * ```typescript + * const page: Page = { + * pageMetrics: notInstrumented(NotInstrumentedMetricsType.PageMetrics), + * shelves: [ + * makeStaticIntent(Continuous.of(Shelf(...))), + * ] + * }; + * ``` + * A continuous async iterable can be created with another `AsyncIterable` + * as a backing data source: + * + * ```typescript + * async function* timer( + * interval: number, + * start: number = 0, + * limit: number? = undefined, + * ): AsyncIterator<number> { + * for (let next = start; next != limit; next++) { + * yield next; + * await setTimeout(interval); + * } + * } + * + * const countToTen = Continuous.contentsOf(timer(1000, 0, 10)); + * ``` + * + * A single element continuous async iterable can be stringified to JSON + * as long the element itself has a valid JSON representation. This is + * especially useful when combined with `StaticIntent`. + * + * ```typescript + * const shelfIntent = makeStaticIntent(Continuous.of(Shelf(...))); + * const jsonData = JSON.stringify(shelfIntent); + * ``` + * + * __Important__: A continuous async iterable which wraps another + * async iterable cannot be directly JSON stringified. + */ +class Continuous { + // MARK: - Constructors + /** + * Create a continuous async iterable with a single pre-determined element. + * + * @param element - A single element to yield from the new async iterable. + * @returns A new continuous async iterable ready to use. + */ + static of(element) { + return new Continuous(new AsyncJust(element)); + } + /** + * Create a continuous async iterable by wrapping an async iterable. + * + * __Important__: A continuous async iterable which wraps another + * async iterable cannot be directly JSON stringified. + * + * @param base - The async iterable to wrap. + * @returns A new continuous async iterable ready to use. + */ + static contentsOf(base) { + return new Continuous(base); + } + /** + * Construct a continuous async iterable by wrapping an async iterable. + * + * @param base - The async iterable to wrap. + */ + constructor(base) { + this.base = base; + // Indicate to native that the true content of this object is in the base field under direct bridging where toJSON is not called. + this["$wrappedField"] = "base"; + } + // MARK: - JSON.stringify + toJSON() { + if (this.base instanceof AsyncJust) { + return this.base.toJSON(); + } + else { + throw new TypeError("Continuous was not created with a single element"); + } + } + // MARK: - AsyncIterable + async *[Symbol.asyncIterator]() { + yield* this.base; + } +} +exports.Continuous = Continuous; +/** + * An asynchronous iterable which yields a single element. + */ +class AsyncJust { + // MARK: - Constructors + /** + * Construct an async iterable containing just the given element. + * + * @param element - The only element to yield. + */ + constructor(element) { + this.element = element; + // Indicate to native that the true content of this object is in the element field under direct bridging where toJSON is not called. + this["$wrappedField"] = "element"; + } + // MARK: - JSON.stringify + toJSON() { + return this.element; + } + // MARK: - AsyncIterable + async *[Symbol.asyncIterator]() { + yield this.element; + } +} +//# sourceMappingURL=intent.js.map
\ No newline at end of file |
