diff options
| author | rxliuli <rxliuli@gmail.com> | 2025-11-04 05:03:50 +0800 |
|---|---|---|
| committer | rxliuli <rxliuli@gmail.com> | 2025-11-04 05:03:50 +0800 |
| commit | bce557cc2dc767628bed6aac87301a1be7c5431b (patch) | |
| tree | b51a051228d01fe3306cd7626d4a96768aadb944 /node_modules/@jet/environment/routing | |
init commit
Diffstat (limited to 'node_modules/@jet/environment/routing')
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 |
