summaryrefslogtreecommitdiff
path: root/node_modules/@jet/environment/routing
diff options
context:
space:
mode:
authorrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
committerrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
commitbce557cc2dc767628bed6aac87301a1be7c5431b (patch)
treeb51a051228d01fe3306cd7626d4a96768aadb944 /node_modules/@jet/environment/routing
init commit
Diffstat (limited to 'node_modules/@jet/environment/routing')
-rw-r--r--node_modules/@jet/environment/routing/index.js20
-rw-r--r--node_modules/@jet/environment/routing/route-provider.js29
-rw-r--r--node_modules/@jet/environment/routing/router-factory.js22
-rw-r--r--node_modules/@jet/environment/routing/router.js39
-rw-r--r--node_modules/@jet/environment/routing/routing-components.js295
5 files changed, 405 insertions, 0 deletions
diff --git a/node_modules/@jet/environment/routing/index.js b/node_modules/@jet/environment/routing/index.js
new file mode 100644
index 0000000..7bd8113
--- /dev/null
+++ b/node_modules/@jet/environment/routing/index.js
@@ -0,0 +1,20 @@
+"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("./router"), exports);
+__exportStar(require("./route-provider"), exports);
+__exportStar(require("./router-factory"), exports);
+//# sourceMappingURL=index.js.map \ No newline at end of file
diff --git a/node_modules/@jet/environment/routing/route-provider.js b/node_modules/@jet/environment/routing/route-provider.js
new file mode 100644
index 0000000..9ab3040
--- /dev/null
+++ b/node_modules/@jet/environment/routing/route-provider.js
@@ -0,0 +1,29 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.registerRoutesProvider = exports.isRouteProvider = void 0;
+const optional_1 = require("../types/optional");
+/**
+ * Checks if an object conforms to `RouteProvider`.
+ * @remarks This function does not perform any checking for the generic types.
+ * @param provider - The object that may be a route provider.
+ */
+function isRouteProvider(provider) {
+ if (typeof provider !== "object") {
+ return false;
+ }
+ return (0, optional_1.isSome)(provider === null || provider === void 0 ? void 0 : provider["routes"]);
+}
+exports.isRouteProvider = isRouteProvider;
+/**
+ * Registers all routes provided by a `RouteProvider` to a router.
+ * @param router - The router to register routes on.
+ * @param provider - The route provider to get the routes from.
+ * @param objectGraph - An object graph for dependency injection.
+ */
+function registerRoutesProvider(router, provider, objectGraph) {
+ provider.routes(objectGraph).forEach((definition) => {
+ router.associate(definition.rules, definition.handler);
+ });
+}
+exports.registerRoutesProvider = registerRoutesProvider;
+//# sourceMappingURL=route-provider.js.map \ No newline at end of file
diff --git a/node_modules/@jet/environment/routing/router-factory.js b/node_modules/@jet/environment/routing/router-factory.js
new file mode 100644
index 0000000..10784ad
--- /dev/null
+++ b/node_modules/@jet/environment/routing/router-factory.js
@@ -0,0 +1,22 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.makeRouterUsingRegisteredControllers = void 0;
+const route_provider_1 = require("./route-provider");
+const router_1 = require("./router");
+/**
+ * Creates a new router using the routes from any controller registered on the provided
+ * dispatcher that conforms to `RouteProvider`.
+ * @param dispatcher - The dispatcher to get the controllers from.
+ * @param objectGraph - An object graph for dependency injection.
+ */
+function makeRouterUsingRegisteredControllers(dispatcher, objectGraph) {
+ const router = new router_1.Router();
+ for (const controller of dispatcher.registeredControllers) {
+ if ((0, route_provider_1.isRouteProvider)(controller)) {
+ (0, route_provider_1.registerRoutesProvider)(router, controller, objectGraph);
+ }
+ }
+ return router;
+}
+exports.makeRouterUsingRegisteredControllers = makeRouterUsingRegisteredControllers;
+//# sourceMappingURL=router-factory.js.map \ No newline at end of file
diff --git a/node_modules/@jet/environment/routing/router.js b/node_modules/@jet/environment/routing/router.js
new file mode 100644
index 0000000..db2e2cb
--- /dev/null
+++ b/node_modules/@jet/environment/routing/router.js
@@ -0,0 +1,39 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.Router = void 0;
+const optional_1 = require("../types/optional");
+const routing_components_1 = require("./routing-components");
+/**
+ * Converts a URL into an intent. This intent can then be dispatched using a dispatcher
+ * (see `IntentDispatcher`).
+ *
+ * Routes can be registered using either the `associate` function or using route providers
+ * (see `RouteProvider`).
+ */
+class Router {
+ constructor() {
+ this.router = new routing_components_1.UrlRouter();
+ }
+ /**
+ * Registers a new implementation that will be invoked when any of the provided
+ * URL rules are matched.
+ * @param urlRules - The rules that will be registered.
+ * @param implementation - The implementation to invoke if any of the rules are matched.
+ */
+ associate(urlRules, implementation) {
+ this.router.associate(urlRules, implementation);
+ }
+ /**
+ * Uses the registered routing rules to produce an intent for the provided URL.
+ * @param url - The URL to route;
+ */
+ intentFor(url) {
+ const routerResult = this.router.routedObjectForUrl(url);
+ if ((0, optional_1.isSome)(routerResult.object) && (0, optional_1.isSome)(routerResult.parameters)) {
+ return routerResult.object(routerResult.normalizedUrl, routerResult.parameters, routerResult);
+ }
+ return null;
+ }
+}
+exports.Router = Router;
+//# sourceMappingURL=router.js.map \ No newline at end of file
diff --git a/node_modules/@jet/environment/routing/routing-components.js b/node_modules/@jet/environment/routing/routing-components.js
new file mode 100644
index 0000000..29fa1f9
--- /dev/null
+++ b/node_modules/@jet/environment/routing/routing-components.js
@@ -0,0 +1,295 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.UrlRouter = exports.UrlRule = void 0;
+const optional_1 = require("../types/optional");
+const urls = require("../util/urls");
+// endregion
+// region private URLRule helpers.
+/**
+ * Checks whether or not a given pathComponents component contains a parameter.
+ * @param pathComponent - The pathComponents component to check.
+ * @returns true if the pathComponents component is surrounded by curly braces; false otherwise.
+ */
+function isPathComponentParameter(pathComponent) {
+ return pathComponent.startsWith("{") && pathComponent.endsWith("}");
+}
+/**
+ * Extracts the parameter contained in a pathComponents component.
+ * @param pathComponent - A pathComponents component surrounded by curly braces.
+ * @returns The parameter contained in the component.
+ */
+function getPathComponentParameter(pathComponent) {
+ return pathComponent.replace("{", "").replace("}", "");
+}
+/**
+ * Creates a mapping from key to pathComponents component index
+ * for efficiently extracting parameters from a pathComponents.
+ * @param rulePath - The pathComponents to create a mapping for.
+ * @returns A map of keys to pathComponents component indexes.
+ */
+function makePathParameterMapping(rulePath) {
+ const mapping = {};
+ rulePath.forEach((ruleComponent, index) => {
+ if (isPathComponentParameter(ruleComponent)) {
+ mapping[ruleComponent] = index;
+ }
+ });
+ return mapping;
+}
+/**
+ * Creates `UrlRouteQuery` objects from substring of url.
+ * @param parameters - strings of form `<key>[?]=<value>`.
+ * @returns Array of `UrlRouteQuery` objects.
+ */
+function parseQuery(parameters) {
+ const parsedQuery = [];
+ if ((0, optional_1.isNothing)(parameters)) {
+ return parsedQuery;
+ }
+ for (const param of parameters) {
+ const parts = param.split("=");
+ let key = parts[0];
+ const optional = key.includes("?");
+ key = key.replace("?", "");
+ let value = null;
+ if (parts.length > 1) {
+ value = decodeURIComponent(parts[1]);
+ }
+ parsedQuery.push({
+ key,
+ value,
+ optional,
+ });
+ }
+ return parsedQuery;
+}
+/**
+ * The `UrlRule` class extracts the pattern format from `UrlRuleDefinition`s, and encapsulates
+ * the information needed to match against a candidate URL and extract parameters from it.
+ *
+ * The terminology here is:
+ * - rule: A specific url pattern.
+ * - route: A group of rules that together form a single route, i.e. UrlRule[].
+ */
+class UrlRule {
+ /**
+ * Construct the route with all required properties.
+ * @param rule - The rule to match.
+ */
+ constructor(rule) {
+ this.identifier = rule.identifier;
+ this.protocol = rule.protocol;
+ this.hostName = rule.hostName;
+ if ((0, optional_1.isSome)(rule.path)) {
+ this.pathComponents = rule.path.split("/").filter((component) => component.length > 0);
+ this.pathParameterMap = makePathParameterMapping(this.pathComponents);
+ }
+ else {
+ this.pathComponents = undefined;
+ this.pathParameterMap = undefined;
+ }
+ this.pathExtension = rule.pathExtension;
+ this.query = parseQuery(rule.query);
+ this.hash = rule.hash;
+ this.regex = rule.regex;
+ if ((0, optional_1.isSome)(rule.exclusions)) {
+ this.exclusions = rule.exclusions.map(function (ex) {
+ return new UrlRule(ex);
+ });
+ }
+ else {
+ this.exclusions = undefined;
+ }
+ }
+ /**
+ * Checks whether or not the route matches a given URL.
+ * @param url - The URL to check against.
+ * @returns true if the route matches `urls`; false otherwise.
+ *
+ * @deprecated prefer `match` to have access to regex match groups
+ */
+ matches(url) {
+ return (0, optional_1.isSome)(this.match(url));
+ }
+ /**
+ * Extract information from a matching url.
+ * @param matchingUrl - The url to extract parameters from.
+ * @returns `Parameters` extracted from `matchingUrl`
+ * @remarks This function is only valid when `this.matches(matchingUrl) === true`.
+ */
+ extractParameters(matchingUrl) {
+ var _a;
+ const parameters = {};
+ if ((0, optional_1.isSome)(this.pathComponents) && (0, optional_1.isSome)(this.pathParameterMap)) {
+ const urlPathComponents = matchingUrl.pathComponents();
+ for (const internalKey of Object.keys(this.pathParameterMap)) {
+ const externalKey = getPathComponentParameter(internalKey);
+ const index = this.pathParameterMap[internalKey];
+ parameters[externalKey] = decodeURIComponent(urlPathComponents[index]);
+ }
+ }
+ if ((0, optional_1.isSome)(this.query)) {
+ for (const param of this.query) {
+ const queryParam = (_a = matchingUrl.query) === null || _a === void 0 ? void 0 : _a[param.key];
+ if ((0, optional_1.isSome)(queryParam)) {
+ parameters[param.key] = queryParam;
+ }
+ }
+ }
+ return parameters;
+ }
+ /**
+ * Checks whether or not the route matches a given URL.
+ * @param url - The URL to check against.
+ * @returns an optional `UrlRuleMatchResult` if the route matches `url`.
+ */
+ match(url) {
+ var _a, _b;
+ let matchGroups = null;
+ if ((0, optional_1.isSome)(this.regex)) {
+ if (this.regex.length === 0) {
+ // If the rule specifies regex but does not supply patterns, we need to return false. Otherwise, we will
+ // risk matching against everything. This is because an empty regex with no other rule parameters will
+ // cause us to fallthrough to the end and match against all URLs.
+ return null;
+ }
+ let didMatchRegex = false;
+ for (const regexPattern of this.regex) {
+ const execResult = regexPattern.exec(url.toString());
+ if (execResult !== null) {
+ // If we match against any of regex patterns, then we should proceed.
+ // If no matches are found, then this rule is not matched.
+ didMatchRegex = true;
+ matchGroups = (_a = execResult.groups) !== null && _a !== void 0 ? _a : null;
+ break;
+ }
+ }
+ if (!didMatchRegex) {
+ return null;
+ }
+ }
+ if ((0, optional_1.isSome)(this.protocol) && url.protocol !== this.protocol) {
+ return null;
+ }
+ if ((0, optional_1.isSome)(this.hostName) && url.host !== this.hostName) {
+ return null;
+ }
+ if ((0, optional_1.isSome)(this.pathComponents)) {
+ const rulePathComponents = this.pathComponents;
+ const urlPathComponents = url.pathComponents();
+ if (rulePathComponents.length !== urlPathComponents.length) {
+ return null;
+ }
+ // We're iterating two arrays here, an old style for-loop is appropriate
+ const length = rulePathComponents.length;
+ for (let i = 0; i < length; i += 1) {
+ const ruleComponent = rulePathComponents[i];
+ if (isPathComponentParameter(ruleComponent)) {
+ // component parameters always match
+ continue;
+ }
+ const urlComponent = urlPathComponents[i];
+ if (ruleComponent !== urlComponent) {
+ return null;
+ }
+ }
+ }
+ if ((0, optional_1.isSome)(this.pathExtension)) {
+ if (url.pathExtension() !== this.pathExtension) {
+ return null;
+ }
+ }
+ if ((0, optional_1.isSome)(this.query)) {
+ for (const param of this.query) {
+ const value = (_b = url.query) === null || _b === void 0 ? void 0 : _b[param.key];
+ if ((0, optional_1.isNothing)(value) && !param.optional) {
+ return null;
+ }
+ if ((0, optional_1.isSome)(param.value) && param.value !== value) {
+ return null;
+ }
+ }
+ }
+ if ((0, optional_1.isSome)(this.hash) && url.hash !== this.hash) {
+ return null;
+ }
+ if ((0, optional_1.isSome)(this.exclusions)) {
+ for (const exclusionRule of this.exclusions) {
+ if ((0, optional_1.isSome)(exclusionRule.exclusions)) {
+ throw Error("Matching exclusion rules with further exclusion rules may introduce significant code-complexity and/or reduce the ease with which developers are able to reason about your desired goals. Are there any simpler options?");
+ }
+ if ((0, optional_1.isSome)(exclusionRule.match(url))) {
+ return null;
+ }
+ }
+ }
+ const parameters = this.extractParameters(url);
+ return {
+ parameters,
+ matchGroups,
+ };
+ }
+}
+exports.UrlRule = UrlRule;
+/**
+ * `UrlRouter` manages a set of url rule templates to allow `urls` to serve as keys for different associated objects (like Builders).
+ *
+ * @remarks This is replaces old `UrlRouter` as a synchronous way match route URLs to handlers. In contrast to the previous implementation,
+ * it maps entire objects (containing related async handlers and properties) to urls.
+ */
+class UrlRouter {
+ /**
+ * Constructs an empty URL router object.
+ */
+ constructor() {
+ this.routeMappings = [];
+ }
+ /**
+ * Register a new route defined by a set of definitions and object on the router.
+ * @param routeDefinitions - The definitions of rules to register.
+ * @param object - The object for the rule.
+ */
+ associate(routeDefinitions, object) {
+ const route = [];
+ for (const definition of routeDefinitions) {
+ route.push(new UrlRule(definition));
+ }
+ this.routeMappings.push({ route: route, object: object });
+ }
+ /**
+ * Resolve given url to associated object, if any exist. Rules will be evaluated
+ * in the order they are added using the `associate` function. Evaluation will stop
+ * after any rule matches.
+ * @param urlOrString - URL or string representation of url to resolve objects for.
+ * @returns `UrlRouterResult` containing url, extracted parameters, and associated object, or `null` if no match was found.
+ */
+ routedObjectForUrl(urlOrString) {
+ var _a;
+ const url = typeof urlOrString === "string" ? new urls.URL(urlOrString) : urlOrString;
+ for (const mapping of this.routeMappings) {
+ for (const rule of mapping.route) {
+ const matchResult = rule.match(url);
+ if ((0, optional_1.isSome)(matchResult)) {
+ return {
+ normalizedUrl: url,
+ parameters: matchResult.parameters,
+ object: mapping.object,
+ matchedRuleIdentifier: (_a = rule.identifier) !== null && _a !== void 0 ? _a : null,
+ regexMatchGroups: matchResult.matchGroups,
+ };
+ }
+ }
+ }
+ // No match. Still return a result with normalized url.
+ return {
+ normalizedUrl: url,
+ parameters: null,
+ object: null,
+ matchedRuleIdentifier: null,
+ regexMatchGroups: null,
+ };
+ }
+}
+exports.UrlRouter = UrlRouter;
+// endregion
+//# sourceMappingURL=routing-components.js.map \ No newline at end of file