summaryrefslogtreecommitdiff
path: root/node_modules/@jet/environment/dispatching/base
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/@jet/environment/dispatching/base')
-rw-r--r--node_modules/@jet/environment/dispatching/base/dispatchable.js3
-rw-r--r--node_modules/@jet/environment/dispatching/base/dispatcher.js97
-rw-r--r--node_modules/@jet/environment/dispatching/base/index.js21
-rw-r--r--node_modules/@jet/environment/dispatching/base/intent-controller.js12
-rw-r--r--node_modules/@jet/environment/dispatching/base/intent.js178
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