@orieljs/routing 0.1.0-alpha.6 → 0.1.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/NOTICE CHANGED
@@ -10,3 +10,7 @@ The Oriel name and logo are not covered by that license; see TRADEMARKS.md
10
10
 
11
11
  @orieljs/support (and @orieljs/framework, which bundles it) includes transliteration data from
12
12
  voku/portable-ascii (https://github.com/voku/portable-ascii), Copyright (C) 2019 Lars Moelleken, MIT License.
13
+
14
+ @orieljs/notifications (and @orieljs/framework, which bundles it) includes the HTML and CSS of
15
+ Laravel's default notification mail (laravel/framework, https://github.com/laravel/framework),
16
+ Copyright (c) Taylor Otwell, MIT License.
package/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # @orieljs/routing
2
+
3
+ The Oriel router: it maps a URL and an HTTP method to a closure or a controller action, as Laravel's routing. It is part of `@orieljs/framework`, which every Oriel app already installs, and is re-exported from it. In an app, import it from `@orieljs/framework`; `@orieljs/routing` is also published on its own.
4
+
5
+ ```bash
6
+ npm install @orieljs/framework
7
+ ```
8
+
9
+ ```ts title="routes/web.ts"
10
+ import { Route, view } from '@orieljs/framework'
11
+ import { PostController } from '../app/Http/Controllers/PostController'
12
+
13
+ Route.get('/', () => view('welcome')).name('home')
14
+
15
+ Route.middleware(['auth', 'verified']).group(() => {
16
+ Route.get('/posts', [PostController, 'index']).name('posts.index')
17
+ Route.get('/posts/{post}', [PostController, 'show']).name('posts.show')
18
+ Route.post('/posts', [PostController, 'store']).middleware('throttle:10,1')
19
+ })
20
+ ```
21
+
22
+ `Route` has a method for each HTTP verb, plus `match()`, `any()`, `redirect()`, `view()`, `inertia()`, `resource()` and `fallback()`. A route takes a `name()`, `middleware()` and parameter constraints with `where()`, and groups share `middleware()`, `prefix()`, `name()` or `controller()`. A parameter named after a model, like `{post}`, receives the model, and `route('posts.show', post)` builds its URL.
23
+
24
+ Documentation: https://orieljs.vercel.app/docs/routing
25
+
26
+ Status: early alpha. APIs will change.
27
+
28
+ ## License
29
+
30
+ Oriel is open-source software licensed under the Apache License 2.0 (Apache-2.0; see `LICENSE` and `NOTICE`). The Oriel name and logo are trademarks; see `TRADEMARKS.md`.
31
+
32
+ Website: https://orieljs.vercel.app
package/TRADEMARKS.md ADDED
@@ -0,0 +1,33 @@
1
+ # Oriel trademark policy
2
+
3
+ The Oriel code is open source under the Apache License 2.0. The **Oriel name and logo** are not: the license covers
4
+ the code only (section 6 of the license says so), and the name and logo stay with the project. This page explains
5
+ what you can and can't do with them. The goal is simple: people should always be able to tell what is the real Oriel
6
+ and what isn't.
7
+
8
+ ## You can, without asking
9
+
10
+ - Use, change, ship and sell the code, as the license allows.
11
+ - Say that your app or package is "built with Oriel", "for Oriel" or "compatible with Oriel".
12
+ - Name a package `oriel-<something>` or `<something>-for-oriel` when it works with Oriel, as long as it is clear that
13
+ it is not official (for example, don't publish it under the `@orieljs` npm scope).
14
+ - Use the name and logo to write about Oriel, teach it, or link to it, in articles, talks, videos and courses.
15
+ - Use the unmodified logo to point to the project, as it is (no recolouring, cropping or
16
+ distortion).
17
+
18
+ ## You can't, without written permission
19
+
20
+ - Call a fork, a modified copy or a competing product "Oriel", or anything likely to be confused with it.
21
+ - Use the name or logo as the name, logo or domain of your own product, company or service.
22
+ - Suggest that the Oriel project made, endorses or supports your work when it doesn't.
23
+ - Sell merchandise with the name or logo.
24
+
25
+ ## Forks
26
+
27
+ Forks are welcome. Please give yours a different name and logo, keep the `LICENSE` and `NOTICE` files, and say that
28
+ it is based on Oriel.
29
+
30
+ ## Questions
31
+
32
+ Open an issue at https://github.com/orieljs/framework or email meeeet.dev@gmail.com. If you're unsure whether a use
33
+ is fine, ask; the answer is usually yes.
package/dist/index.d.ts CHANGED
@@ -433,7 +433,7 @@ declare class RoutingServiceProvider extends ServiceProvider {
433
433
  declare class ThrottleRequests implements Middleware {
434
434
  handle(request: HttpRequest, next: Next, maxAttempts?: string, decayMinutes?: string, prefix?: string): Promise<Response>;
435
435
  /** The signed-in user's identifier, else the client IP, hashed (Laravel's resolveRequestSignature()). */
436
- protected resolveRequestSignature(request: HttpRequest): string;
436
+ protected resolveRequestSignature(request: HttpRequest): Promise<string>;
437
437
  }
438
438
 
439
439
  /**
package/dist/index.js CHANGED
@@ -1152,7 +1152,7 @@ var ThrottleRequests = class {
1152
1152
  );
1153
1153
  }
1154
1154
  const limiter = inject(RateLimiter);
1155
- const key = prefix + this.resolveRequestSignature(request);
1155
+ const key = prefix + await this.resolveRequestSignature(request);
1156
1156
  if (await limiter.tooManyAttempts(key, max)) {
1157
1157
  const retryAfter = await limiter.availableIn(key);
1158
1158
  throw new ThrottleRequestsError({
@@ -1170,8 +1170,8 @@ var ThrottleRequests = class {
1170
1170
  });
1171
1171
  }
1172
1172
  /** The signed-in user's identifier, else the client IP, hashed (Laravel's resolveRequestSignature()). */
1173
- resolveRequestSignature(request) {
1174
- const user = request.user();
1173
+ async resolveRequestSignature(request) {
1174
+ const user = await request.user();
1175
1175
  if (user !== void 0 && user !== null && typeof user.getAuthIdentifier === "function") {
1176
1176
  return sha1(String(user.getAuthIdentifier()));
1177
1177
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../BaseRouter.ts","../bindings.ts","../errors.ts","../middleware.ts","../toResponse.ts","../dispatch.ts","../RouteDefinition.ts","../GroupRegistrar.ts","../resource.ts","../BaseUrlGenerator.ts","../facade.ts","../health.ts","../routeFiles.ts","../RoutingServiceProvider.ts","../ThrottleRequests.ts","../ValidateSignature.ts"],"sourcesContent":["import {\n CurrentRoute,\n InertiaFactory,\n UrlGenerator,\n ViewFactory,\n type Class,\n type Container,\n type ControllerAction,\n type HttpRequest,\n type InvokableClass,\n type MiddlewareClass,\n type MiddlewareReference,\n type ResourceOptions,\n type RouteAction,\n type RouteClosure,\n type Router,\n} from '@orieljs/contracts'\nimport { currentContainer } from '@orieljs/container'\nimport { substituteBindings } from './bindings'\nimport { dispatchRoute } from './dispatch'\nimport { RoutingError } from './errors'\nimport { ALL_VERBS, GroupRegistrar, mergeGroup, type GroupAttributes } from './GroupRegistrar'\nimport { resourceRoutes } from './resource'\nimport { compareRoutes, RouteDefinition, type RouteHandler } from './RouteDefinition'\n\nexport type RouteBinder = (value: string) => unknown | Promise<unknown>\n\n/** Laravel's Illuminate\\Routing\\Router: registration, groups, patterns, bindings, middleware aliases/groups and dispatch. */\nexport class BaseRouter implements Router {\n readonly #routes: RouteDefinition[] = []\n #sorted: RouteDefinition[] | undefined\n readonly #groupStack: GroupAttributes[] = []\n readonly #patterns: Record<string, string> = {}\n #patternVersion = 0\n readonly #aliases: Record<string, MiddlewareClass> = {}\n readonly #groups: Record<string, MiddlewareReference[]> = { web: [], api: [] }\n readonly #binders = new Map<string, RouteBinder>()\n readonly #models = new Map<string, Class<unknown>>()\n\n /** `container` is the application; request-time lookups use the current (request) container first. */\n constructor(protected readonly container?: Container) {}\n\n get<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.addRoute(['GET', 'HEAD'], uri, action)\n }\n\n post<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.addRoute(['POST'], uri, action)\n }\n\n put<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.addRoute(['PUT'], uri, action)\n }\n\n patch<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.addRoute(['PATCH'], uri, action)\n }\n\n delete<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.addRoute(['DELETE'], uri, action)\n }\n\n options<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.addRoute(['OPTIONS'], uri, action)\n }\n\n any<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.addRoute(ALL_VERBS, uri, action)\n }\n\n match<C>(methods: string[], uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.addRoute(methods, uri, action)\n }\n\n /** Registers a route with the current group's prefix, name prefix, middleware and controller. GET implies HEAD. */\n addRoute(methods: readonly string[], uri: string, action: RouteHandler, options: { fallback?: boolean } = {}): RouteDefinition {\n const group = this.#groupStack.at(-1) ?? {}\n const verbs = methods.map((method) => method.toUpperCase())\n if (verbs.includes('GET') && !verbs.includes('HEAD')) verbs.push('HEAD')\n if (typeof action === 'string' && group.controller === undefined) {\n throw new RoutingError(\n `Route action [${action}] needs a controller. Use Route.controller(X).group(...) or pass [Controller, '${action}'].`,\n )\n }\n const prefix = (group.prefix ?? '').replace(/^\\/+|\\/+$/g, '')\n const path = uri.replace(/^\\/+|\\/+$/g, '')\n const route = new RouteDefinition(verbs, [prefix, path].filter((part) => part !== '').join('/'), action, {\n ...(group.as !== undefined && { namePrefix: group.as }),\n ...(group.middleware !== undefined && { middleware: group.middleware }),\n ...(group.controller !== undefined && { controller: group.controller }),\n ...(options.fallback === true && { fallback: true }),\n })\n this.#routes.push(route)\n this.#sorted = undefined\n return route\n }\n\n /** Route.redirect('/here', '/there'): any verb, 302 by default; '{param}' in the target is filled from the URI. */\n redirect(from: string, to: string, status = 302): RouteDefinition {\n const holder: { route?: RouteDefinition } = {}\n const action = (...values: unknown[]) => {\n const parameters = new Map(holder.route!.parameters.map((parameter, index) => [parameter.name, values[index]]))\n const target = to.replace(/\\{(\\w+)\\??\\}/g, (_match, name: string) => {\n const value = parameters.get(name)\n return value === undefined || value === null ? '' : encodeURIComponent(String(value))\n })\n const container = currentContainer() ?? this.container\n const location = container?.bound(UrlGenerator) ? container.make(UrlGenerator).to(target) : target\n return new Response(null, { status, headers: { Location: location } })\n }\n holder.route = this.any(from, action)\n return holder.route\n }\n\n permanentRedirect(from: string, to: string): RouteDefinition {\n return this.redirect(from, to, 301)\n }\n\n /** Route.view('/about', 'pages.about', data): GET/HEAD; route parameters are merged into the view data. */\n view(uri: string, view: string, data: Record<string, unknown> = {}): RouteDefinition {\n const holder: { route?: RouteDefinition } = {}\n const action = (...values: unknown[]) => {\n const parameters = Object.fromEntries(holder.route!.parameters.map((parameter, index) => [parameter.name, values[index]]))\n const container = currentContainer() ?? this.container\n if (container === undefined) throw new RoutingError(`Cannot render view [${view}]: no container is available.`)\n return container.make(ViewFactory).make(view, { ...data, ...parameters })\n }\n holder.route = this.addRoute(['GET', 'HEAD'], uri, action)\n return holder.route\n }\n\n /**\n * Route.inertia('/about', 'About', props): GET/HEAD; renders the page through the InertiaFactory (resolved when\n * the route runs, so Routing needs no Inertia import). Route parameters are merged into the props.\n */\n inertia(uri: string, component: string, props: Record<string, unknown> = {}): RouteDefinition {\n const holder: { route?: RouteDefinition } = {}\n const action = (...values: unknown[]) => {\n const parameters = Object.fromEntries(holder.route!.parameters.map((parameter, index) => [parameter.name, values[index]]))\n const container = currentContainer() ?? this.container\n if (container === undefined || !container.bound(InertiaFactory)) {\n throw new RoutingError(`Cannot render Inertia page [${component}]: no InertiaFactory is bound.`)\n }\n return container.make(InertiaFactory).render(component, { ...props, ...parameters })\n }\n holder.route = this.addRoute(['GET', 'HEAD'], uri, action)\n return holder.route\n }\n\n resource(name: string, controller: Class<unknown>, options: ResourceOptions = {}): void {\n this.#registerResource(name, controller, options, false)\n }\n\n apiResource(name: string, controller: Class<unknown>, options: ResourceOptions = {}): void {\n this.#registerResource(name, controller, options, true)\n }\n\n /** Matches any GET path no other route matches. Always tried last. */\n fallback(action: RouteAction): RouteDefinition {\n return this.addRoute(['GET', 'HEAD'], '{fallbackPlaceholder}', action, { fallback: true })\n }\n\n prefix(prefix: string): GroupRegistrar {\n return new GroupRegistrar(this).prefix(prefix)\n }\n\n name(prefix: string): GroupRegistrar {\n return new GroupRegistrar(this).name(prefix)\n }\n\n middleware(...middleware: Array<MiddlewareReference | readonly MiddlewareReference[]>): GroupRegistrar {\n return new GroupRegistrar(this).middleware(...middleware)\n }\n\n controller(controller: Class<unknown>): GroupRegistrar {\n return new GroupRegistrar(this).controller(controller)\n }\n\n /**\n * Laravel's Route::group(attributes, callback). A synchronous callback's attributes are popped before this\n * returns, so an unawaited group never leaks into later routes; an async callback keeps them until it settles.\n */\n group(attributes: GroupAttributes, routes: () => void | Promise<void>): Promise<void> {\n const entry = mergeGroup(this.#groupStack.at(-1) ?? {}, attributes)\n this.#groupStack.push(entry)\n const pop = () => {\n const index = this.#groupStack.lastIndexOf(entry)\n if (index !== -1) this.#groupStack.splice(index, 1)\n }\n let result: void | Promise<void>\n try {\n result = routes()\n } catch (error) {\n pop()\n throw error\n }\n if (result instanceof Promise) return result.finally(pop)\n pop()\n return Promise.resolve()\n }\n\n model(parameter: string, model: Class<unknown>): void {\n this.#models.set(parameter, model)\n }\n\n bind(parameter: string, resolver: RouteBinder): void {\n this.#binders.set(parameter, resolver)\n }\n\n pattern(parameter: string, pattern: string): void {\n this.#patterns[parameter] = pattern\n this.#patternVersion++\n }\n\n patterns(patterns: Record<string, string>): void {\n for (const [parameter, pattern] of Object.entries(patterns)) this.pattern(parameter, pattern)\n }\n\n getPatterns(): Readonly<Record<string, string>> {\n return { ...this.#patterns }\n }\n\n /** Bumped by pattern(); routes recompile their matcher when it changes. */\n getPatternVersion(): number {\n return this.#patternVersion\n }\n\n getBinder(parameter: string): RouteBinder | undefined {\n return this.#binders.get(parameter)\n }\n\n getModel(parameter: string): Class<unknown> | undefined {\n return this.#models.get(parameter)\n }\n\n /**\n * Binds a matched route's raw parameter values as a request to it would: Route.bind() callbacks, Route.model(),\n * then implicit binding through the RouteModelResolver of `container`. A missing model throws\n * RouteModelNotFoundError (404). Live uses it to check a page route's `can:` middleware again on each update.\n */\n substituteBindings(route: RouteDefinition, values: Readonly<Record<string, string | undefined>>, container: Container): Promise<Record<string, unknown>> {\n return substituteBindings(this, route, values, container)\n }\n\n aliasMiddleware(name: string, middleware: MiddlewareClass): this {\n this.#aliases[name] = middleware\n return this\n }\n\n /** The middleware aliases (Laravel's Router::getMiddleware()). */\n getMiddleware(): Record<string, MiddlewareClass> {\n return { ...this.#aliases }\n }\n\n middlewareGroup(name: string, middleware: MiddlewareReference[]): this {\n this.#groups[name] = [...middleware]\n return this\n }\n\n pushMiddlewareToGroup(group: string, middleware: MiddlewareReference): this {\n const list = (this.#groups[group] ??= [])\n if (!list.includes(middleware)) list.push(middleware)\n return this\n }\n\n prependMiddlewareToGroup(group: string, middleware: MiddlewareReference): this {\n const list = (this.#groups[group] ??= [])\n if (!list.includes(middleware)) list.unshift(middleware)\n return this\n }\n\n hasMiddlewareGroup(name: string): boolean {\n return Object.hasOwn(this.#groups, name)\n }\n\n getMiddlewareGroups(): Record<string, MiddlewareReference[]> {\n return Object.fromEntries(Object.entries(this.#groups).map(([name, list]) => [name, [...list]]))\n }\n\n /** Every route, in registration order. */\n getRoutes(): readonly RouteDefinition[] {\n return [...this.#routes]\n }\n\n /** Routes in matching order: static segments first, fallbacks last (cached until a route is added). */\n getRoutesByMatchOrder(): readonly RouteDefinition[] {\n return (this.#sorted ??= [...this.#routes].sort(compareRoutes))\n }\n\n /** The last route registered with this name wins, as in Laravel. */\n getByName(name: string): RouteDefinition | undefined {\n return this.#routes.findLast((route) => route.getName() === name)\n }\n\n has(...names: string[]): boolean {\n return names.every((name) => this.getByName(name) !== undefined)\n }\n\n /** The route matched for the current request (read from the request scope). */\n current(): RouteDefinition | undefined {\n const container = currentContainer()\n if (container === undefined || !container.bound(CurrentRoute)) return undefined\n return container.make(CurrentRoute).route as RouteDefinition\n }\n\n currentRouteName(): string | undefined {\n return this.current()?.getName()\n }\n\n /** Match, bind and run the route middleware and action (Router.dispatch; called by the Http kernel). */\n dispatch(request: HttpRequest): Promise<Response> {\n return dispatchRoute(this, request, this.container)\n }\n\n #registerResource(name: string, controller: Class<unknown>, options: ResourceOptions, api: boolean): void {\n for (const entry of resourceRoutes(name, options, api)) {\n this.addRoute(entry.verbs, entry.uri, [controller, entry.method] as RouteAction).name(entry.name)\n }\n }\n}\n","import { RouteModelResolver, type Container, type MiddlewareClass } from '@orieljs/contracts'\nimport { BindingResolutionError } from '@orieljs/container'\nimport { Str } from '@orieljs/support'\nimport type { BaseRouter } from './BaseRouter'\nimport { RouteModelNotFoundError } from './errors'\nimport { resolveMiddleware, type ResolvedMiddleware } from './middleware'\nimport type { RouteDefinition } from './RouteDefinition'\n\n/**\n * Laravel's $middlewarePriority around SubstituteBindings: the `web`/`api` group middleware and the `auth`/`guest`\n * aliases run before binding, every other route middleware after it (so `can:` sees the models, and a guest is\n * redirected before any lookup). Returns the middleware in that order (stable within each part) and the index\n * where the binding stage runs.\n */\nexport function orderForBindings(\n router: BaseRouter,\n middleware: readonly ResolvedMiddleware[],\n): { middleware: ResolvedMiddleware[]; at: number } {\n const aliases = router.getMiddleware()\n const groups = router.getMiddlewareGroups()\n const early = new Set<MiddlewareClass>()\n for (const name of ['auth', 'guest']) if (Object.hasOwn(aliases, name)) early.add(aliases[name]!)\n for (const group of ['web', 'api']) {\n try {\n for (const entry of resolveMiddleware([group], [], aliases, groups)) early.add(entry.cls)\n } catch {\n // A group naming an unknown alias fails the routes that use it, when they resolve their middleware.\n }\n }\n const before = middleware.filter((entry) => early.has(entry.cls))\n const after = middleware.filter((entry) => !early.has(entry.cls))\n return { middleware: [...before, ...after], at: before.length }\n}\n\n/**\n * Laravel's SubstituteBindings, run as a route stage (see orderForBindings), in URI order:\n * 1. Route.bind(name, fn): the callback's result, whatever it is\n * 2. Route.model(name, Model): RouteModelResolver.resolveExplicit(); nothing found → 404\n * 3. implicit: RouteModelResolver.resolve(name, value, field); undefined keeps the string, null → 404\n * Missing optional parameters stay undefined. Without a resolver, implicit binding is skipped.\n */\nexport async function substituteBindings(\n router: BaseRouter,\n route: RouteDefinition,\n values: Readonly<Record<string, string | undefined>>,\n container: Container,\n): Promise<Record<string, unknown>> {\n const resolver = container.bound(RouteModelResolver) ? container.make(RouteModelResolver) : undefined\n const bound: Record<string, unknown> = {}\n for (const { name, field } of route.parameters) {\n const value = values[name]\n if (value === undefined) {\n bound[name] = undefined\n continue\n }\n const binder = router.getBinder(name)\n if (binder !== undefined) {\n bound[name] = await binder(value)\n continue\n }\n const model = router.getModel(name)\n if (model !== undefined) {\n if (resolver === undefined) {\n throw new BindingResolutionError(\n `Route.model('${name}', ${model.name}) needs a RouteModelResolver. Is the Database service provider registered?`,\n )\n }\n const found = await resolver.resolveExplicit(model, value, field)\n if (found === null || found === undefined) throw new RouteModelNotFoundError(model.name, value)\n bound[name] = found\n continue\n }\n if (resolver !== undefined) {\n const found = await resolver.resolve(name, value, field)\n if (found === null) throw new RouteModelNotFoundError(Str.studly(name), value)\n bound[name] = found === undefined ? value : found\n continue\n }\n bound[name] = value\n }\n return bound\n}\n","import type { ModelNotFoundError, OrielError } from '@orieljs/contracts'\n\n/** No route matches the path (Symfony's NotFoundHttpException). */\nexport class NotFoundHttpError extends Error implements OrielError {\n readonly kind = 'Http' as const\n readonly status = 404\n override readonly name = 'NotFoundHttpError'\n constructor(path: string) {\n super(`The route ${path} could not be found.`)\n }\n}\n\n/** The path exists, but not for this method. */\nexport class MethodNotAllowedHttpError extends Error implements OrielError {\n readonly kind = 'Http' as const\n readonly status = 405\n readonly headers: Record<string, string>\n override readonly name = 'MethodNotAllowedHttpError'\n constructor(method: string, path: string, allowed: string[]) {\n super(`The ${method} method is not supported for route ${path}. Supported methods: ${allowed.join(', ')}.`)\n this.headers = { Allow: allowed.join(', ') }\n }\n}\n\n/** route('x') for a name no route has (Symfony's RouteNotFoundException). */\nexport class RouteNotDefinedError extends Error implements OrielError {\n readonly kind = 'Server' as const\n readonly status = 500\n override readonly name = 'RouteNotDefinedError'\n constructor(readonly routeName: string) {\n super(`Route [${routeName}] not defined.`)\n }\n}\n\n/** route('posts.show') without a required parameter. */\nexport class UrlGenerationError extends Error implements OrielError {\n readonly kind = 'Server' as const\n readonly status = 500\n override readonly name = 'UrlGenerationError'\n constructor(routeName: string, uri: string, missing: string[]) {\n super(`Missing required parameter for [Route: ${routeName}] [URI: ${uri}] [Missing parameter: ${missing.join(', ')}].`)\n }\n}\n\n/** Thrown by the router when a binding finds no row, so a missing model is always a 404. */\nexport class RouteModelNotFoundError extends Error implements ModelNotFoundError {\n readonly kind = 'ModelNotFound' as const\n readonly status = 404\n readonly ids: unknown[]\n override readonly name = 'RouteModelNotFoundError'\n constructor(readonly model: string, value: unknown) {\n super(`No query results for model [${model}] ${String(value)}`)\n this.ids = [value]\n }\n}\n\n/** Internal routing failures (a string action with no controller, a view route with no container, etc). */\nexport class RoutingError extends Error implements OrielError {\n readonly kind = 'Server' as const\n readonly status = 500\n override readonly name = 'RoutingError'\n}\n\n/** A signed URL whose signature is missing, wrong or expired (Laravel's InvalidSignatureException). */\nexport class InvalidUrlSignatureError extends Error implements OrielError {\n readonly kind = 'Http' as const\n readonly status = 403\n override readonly name = 'InvalidUrlSignatureError'\n constructor() {\n super('Invalid signature.')\n }\n}\n\n/** Too many requests in the window (Laravel's ThrottleRequestsException): 429 with Retry-After and X-RateLimit-*. */\nexport class ThrottleRequestsError extends Error implements OrielError {\n readonly kind = 'Http' as const\n readonly status = 429\n override readonly name = 'ThrottleRequestsError'\n constructor(readonly headers: Record<string, string> = {}) {\n super('Too Many Attempts.')\n }\n}\n","import {\n ExceptionHandler,\n PipelineFactory,\n type Container,\n type HttpRequest,\n type Middleware,\n type MiddlewareClass,\n type MiddlewareReference,\n type OrielError,\n} from '@orieljs/contracts'\nimport { RoutingError } from './errors'\nimport { toResponse } from './toResponse'\n\n/** A middleware reference after alias and group expansion: 'throttle:60,1' → { cls: Throttle, parameters: ['60', '1'] }. */\nexport interface ResolvedMiddleware {\n readonly cls: MiddlewareClass\n readonly parameters: readonly string[]\n}\n\n/** A string middleware that is neither an alias nor a group. */\nexport class MiddlewareNotFoundError extends Error implements OrielError {\n readonly kind = 'Server' as const\n readonly status = 500\n override readonly name = 'MiddlewareNotFoundError'\n constructor(readonly middleware: string) {\n super(\n `Middleware [${middleware}] is not defined. Register it with Route.aliasMiddleware() or ` +\n `withMiddleware((m) => m.alias({ ... })).`,\n )\n }\n}\n\nfunction expand(\n references: readonly MiddlewareReference[],\n aliases: Readonly<Record<string, MiddlewareClass>>,\n groups: Readonly<Record<string, readonly MiddlewareReference[]>>,\n visiting: Set<string>,\n out: ResolvedMiddleware[],\n): void {\n for (const reference of references) {\n if (typeof reference === 'function') {\n out.push({ cls: reference, parameters: [] })\n continue\n }\n const index = reference.indexOf(':')\n const name = index === -1 ? reference : reference.slice(0, index)\n const parameters = index === -1 ? [] : reference.slice(index + 1).split(',')\n if (index === -1 && Object.hasOwn(groups, name)) {\n if (visiting.has(name)) throw new RoutingError(`Middleware group [${name}] includes itself.`)\n visiting.add(name)\n expand(groups[name]!, aliases, groups, visiting, out)\n visiting.delete(name)\n continue\n }\n if (!Object.hasOwn(aliases, name)) throw new MiddlewareNotFoundError(reference)\n out.push({ cls: aliases[name]!, parameters })\n }\n}\n\n/**\n * Expands aliases and groups (recursively), drops anything `excluded` resolves to (withoutMiddleware), and\n * removes duplicates (same class and parameters), keeping the first occurrence like Laravel's uniqueMiddleware.\n */\nexport function resolveMiddleware(\n references: readonly MiddlewareReference[],\n excluded: readonly MiddlewareReference[],\n aliases: Readonly<Record<string, MiddlewareClass>>,\n groups: Readonly<Record<string, readonly MiddlewareReference[]>>,\n): ResolvedMiddleware[] {\n const all: ResolvedMiddleware[] = []\n expand(references, aliases, groups, new Set(), all)\n const skipped: ResolvedMiddleware[] = []\n expand(excluded, aliases, groups, new Set(), skipped)\n const skippedClasses = new Set(skipped.map((entry) => entry.cls))\n const seen = new Set<string>()\n const classIds = new Map<MiddlewareClass, number>()\n return all.filter((entry) => {\n if (skippedClasses.has(entry.cls)) return false\n if (!classIds.has(entry.cls)) classIds.set(entry.cls, classIds.size)\n const key = `${classIds.get(entry.cls)}:${entry.parameters.join(',')}`\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n}\n\n/**\n * Renders an error as a Response through the bound ExceptionHandler (reporting it first), like Laravel's\n * Routing\\Pipeline::handleException. Without a handler the error is rethrown.\n */\nexport async function renderError(container: Container, request: HttpRequest, error: unknown): Promise<Response> {\n if (!container.bound(ExceptionHandler)) throw error\n const handler = container.make(ExceptionHandler)\n await handler.report(error)\n return handler.render(request, error)\n}\n\nasync function guard(container: Container, request: HttpRequest, run: () => Promise<unknown>): Promise<Response> {\n try {\n const result = await run()\n return result instanceof Response ? result : await toResponse(request, result)\n } catch (error) {\n return renderError(container, request, error)\n }\n}\n\n/** An extra pipeline stage that runs before `middleware[at]` (route model binding uses it). */\nexport interface RouteStage {\n readonly at: number\n run(request: HttpRequest): Promise<void>\n}\n\ntype RoutePipe = (passable: HttpRequest, next: (passable: HttpRequest) => Promise<unknown>) => Promise<Response>\n\n/**\n * Sends the request through the middleware (built from `container`, the request scope) to `destination`.\n * Every stage converts its own errors into a response, so outer middleware always get a Response back.\n * Built instances are pushed onto `instances` (for terminate()). `stage`, when given, runs at its position.\n */\nexport async function runMiddleware(\n container: Container,\n request: HttpRequest,\n middleware: readonly ResolvedMiddleware[],\n instances: Middleware[],\n destination: (request: HttpRequest) => Promise<unknown>,\n stage?: RouteStage,\n): Promise<Response> {\n const pipes: RoutePipe[] = middleware.map(({ cls, parameters }) => {\n const instance = container.make(cls)\n instances.push(instance)\n return (passable, next) =>\n guard(container, passable, () => instance.handle(passable, next as (r: HttpRequest) => Promise<Response>, ...parameters))\n })\n if (stage !== undefined) {\n pipes.splice(stage.at, 0, (passable, next) =>\n guard(container, passable, async () => {\n await stage.run(passable)\n return next(passable)\n }),\n )\n }\n return container\n .make(PipelineFactory)\n .make<HttpRequest>()\n .send(request)\n .through(pipes)\n .then((passable) => guard(container, passable, () => destination(passable)))\n}\n","/** Laravel's Router::toResponse: turns whatever an action returned into a Response. */\nexport async function toResponse(request: unknown, value: unknown): Promise<Response> {\n if (value instanceof Response) return value\n if (value === null || value === undefined) return new Response(null, { status: 204 })\n if (typeof value === 'string') return html(value)\n if (typeof value !== 'object') return html(String(value))\n\n const candidate = value as Record<string, unknown>\n // Responsable (redirects, Inertia responses, …)\n if (typeof candidate.toResponse === 'function') {\n return toResponse(request, await (candidate.toResponse as (request: unknown) => unknown).call(value, request))\n }\n // Renderable (a View from ViewFactory.make())\n if (typeof candidate.render === 'function') return html(String(await (candidate.render as () => unknown).call(value)))\n // Htmlable\n if (typeof candidate.toHtml === 'function') return html(String((candidate.toHtml as () => unknown).call(value)))\n if (typeof candidate.toJSON !== 'function') {\n // Jsonable, then Arrayable\n if (typeof candidate.toJson === 'function') return json(String((candidate.toJson as () => unknown).call(value)))\n if (typeof candidate.toArray === 'function') return json(JSON.stringify((candidate.toArray as () => unknown).call(value)))\n }\n // Plain objects, arrays, models and collections (via toJSON)\n return json(JSON.stringify(value))\n}\n\nfunction html(body: string): Response {\n return new Response(body, { headers: { 'content-type': 'text/html; charset=utf-8' } })\n}\n\n/** Explicit header: Response.json() says 'application/json' on Node but adds ';charset=utf-8' on Bun. */\nfunction json(body: string): Response {\n return new Response(body, { headers: { 'content-type': 'application/json' } })\n}\n","import { CurrentRoute, type Class, type Container, type HttpRequest, type OrielError } from '@orieljs/contracts'\nimport { currentContainer } from '@orieljs/container'\nimport type { BaseRouter } from './BaseRouter'\nimport { orderForBindings, substituteBindings } from './bindings'\nimport { MethodNotAllowedHttpError, NotFoundHttpError, RoutingError } from './errors'\nimport { resolveMiddleware, runMiddleware } from './middleware'\nimport { normalizePath, type RouteDefinition } from './RouteDefinition'\n\n/** [Controller, 'missing'] (Laravel's BadMethodCallException). */\nexport class ControllerMethodNotFoundError extends Error implements OrielError {\n readonly kind = 'Server' as const\n readonly status = 500\n override readonly name = 'ControllerMethodNotFoundError'\n constructor(controller: string, method: string) {\n super(`Method ${controller}::${method} does not exist.`)\n }\n}\n\n// Duplicated in Pipeline's BasePipeline.ts on purpose: Http, Routing and Pipeline may not import each other.\nconst isClass = (value: unknown): value is Class<object> =>\n typeof value === 'function' && /^class[\\s{]/.test(Function.prototype.toString.call(value))\n\ntype Match = { route: RouteDefinition; values: Record<string, string | undefined> } | { response: Response }\n\nfunction findRoute(router: BaseRouter, request: HttpRequest): Match {\n const method = request.method().toUpperCase()\n const path = normalizePath(new URL(request.raw.url).pathname)\n const patterns = router.getPatterns()\n const version = router.getPatternVersion()\n const allowed = new Set<string>()\n for (const route of router.getRoutesByMatchOrder()) {\n const values = route.match(path, patterns, version)\n if (values === undefined) continue\n if (route.methods.includes(method)) return { route, values }\n // A fallback never turns an unknown POST into a 405.\n if (!route.isFallback) for (const verb of route.methods) allowed.add(verb)\n }\n if (allowed.size > 0) {\n // Laravel's automatic OPTIONS response.\n if (method === 'OPTIONS') return { response: new Response(null, { status: 200, headers: { Allow: [...allowed].join(', ') } }) }\n throw new MethodNotAllowedHttpError(method, request.path(), [...allowed])\n }\n throw new NotFoundHttpError(request.path())\n}\n\n/** Calls the route action with the parameters in URI order. Controllers are built by the request scope. */\nasync function runAction(scope: Container, route: RouteDefinition, parameters: Record<string, unknown>): Promise<unknown> {\n const args = route.parameters.map((parameter) => parameters[parameter.name])\n const action = route.action\n if (typeof action === 'function' && !isClass(action)) return (action as (...values: unknown[]) => unknown)(...args)\n const [cls, method] =\n typeof action === 'string'\n ? [route.controller as Class<object>, action]\n : isClass(action)\n ? [action, '__invoke']\n : [action[0] as Class<object>, String(action[1])]\n const controller = scope.make(cls) as Record<string, unknown>\n const handler = controller[method]\n if (typeof handler !== 'function') throw new ControllerMethodNotFoundError(cls.name, method)\n return (handler as (...values: unknown[]) => unknown).apply(controller, args)\n}\n\n/**\n * Router::dispatch: match, record the current route in the request scope, then run the route middleware and the\n * action. Matching errors (404/405) are thrown for the kernel's stage to render.\n */\nexport async function dispatchRoute(router: BaseRouter, request: HttpRequest, container?: Container): Promise<Response> {\n const scope = currentContainer() ?? container\n if (scope === undefined) throw new RoutingError('Cannot dispatch a request: no container is available.')\n const match = findRoute(router, request)\n if ('response' in match) return match.response\n const { route, values } = match\n\n const state: CurrentRoute = { route, parameters: { ...values }, middleware: [] }\n scope.instance(CurrentRoute, state)\n\n const middleware = resolveMiddleware(\n route.gatherMiddleware(),\n route.excludedMiddleware(),\n router.getMiddleware(),\n router.getMiddlewareGroups(),\n )\n const ordered = orderForBindings(router, middleware)\n return runMiddleware(scope, request, ordered.middleware, state.middleware, () => runAction(scope, route, state.parameters), {\n at: ordered.at,\n run: async () => void Object.assign(state.parameters, await substituteBindings(router, route, values, scope)),\n })\n}\n","import type { Class, MiddlewareReference, Route, RouteAction } from '@orieljs/contracts'\n\n/** A closure, a [Controller, 'method'] tuple, or a method name inside Route.controller(X).group(). */\nexport type RouteHandler = RouteAction | string\n\nexport interface RouteAttributes {\n /** The group's name prefix ('admin.'); name() appends to it. */\n namePrefix?: string\n /** Group middleware; the route's own middleware() is appended after it. */\n middleware?: MiddlewareReference[]\n /** The group controller that string actions call. */\n controller?: Class<unknown>\n fallback?: boolean\n}\n\nexport interface UriParameter {\n readonly name: string\n readonly optional: boolean\n /** The binding column from '{post:slug}'. */\n readonly field: string | undefined\n}\n\n/** Exported for the URL generator, which reuses these instead of redeclaring them. */\nexport const PARAMETER = /\\{(\\w+)(?::(\\w+))?(\\?)?\\}/g\nexport const WHOLE_OPTIONAL = /^\\{(\\w+)(?::\\w+)?\\?\\}$/\nconst escapeRegex = (value: string) => value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n\nexport function parseParameters(uri: string): UriParameter[] {\n return [...uri.matchAll(PARAMETER)].map((match) => ({ name: match[1]!, optional: match[3] === '?', field: match[2] }))\n}\n\n/** Laravel stores URIs without surrounding slashes, and '/' for the root. */\nexport function normalizeUri(uri: string): string {\n const trimmed = uri.replace(/^\\/+|\\/+$/g, '')\n return trimmed === '' ? '/' : trimmed\n}\n\n/** The form compiled patterns match against: '/posts/1/' → '/posts/1', '/' → ''. */\nexport function normalizePath(pathname: string): string {\n const trimmed = pathname.replace(/^\\/+|\\/+$/g, '').replace(/\\/{2,}/g, '/')\n return trimmed === '' ? '' : `/${trimmed}`\n}\n\nfunction decode(value: string): string {\n try {\n return decodeURIComponent(value)\n } catch {\n return value\n }\n}\n\n/** The pattern body (no anchors) for a normalised uri; '' for the root. */\nfunction compileBody(uri: string, wheres: Readonly<Record<string, string>>): string {\n if (uri === '/') return ''\n const group = (name: string) => `(?<p_${name}>${wheres[name] ?? '[^/]+'})`\n let body = ''\n for (const segment of uri.split('/')) {\n const whole = WHOLE_OPTIONAL.exec(segment)\n if (whole) {\n body += `(?:/${group(whole[1]!)})?`\n continue\n }\n let piece = ''\n let last = 0\n for (const match of segment.matchAll(PARAMETER)) {\n piece += escapeRegex(segment.slice(last, match.index)) + group(match[1]!) + (match[3] === '?' ? '?' : '')\n last = match.index + match[0].length\n }\n body += `/${piece}${escapeRegex(segment.slice(last))}`\n }\n return body\n}\n\nconst FALLBACK_SEGMENT = '{fallbackPlaceholder}'\n\n/**\n * Laravel's fallback is '{fallbackPlaceholder}' with where('.*') under the group prefix, so it stays scoped to it:\n * 'api/{fallbackPlaceholder}' matches /api and /api/any/depth but not /about; at the root it matches every path.\n */\nfunction compileFallback(uri: string, wheres: Readonly<Record<string, string>>): RegExp {\n const tail = '(?:/(?<p_fallbackPlaceholder>.*))?'\n if (uri === FALLBACK_SEGMENT) return new RegExp(`^${tail}$`, 's')\n if (!uri.endsWith(`/${FALLBACK_SEGMENT}`)) return new RegExp(`^${compileBody(uri, { ...wheres, fallbackPlaceholder: '.*' })}$`, 's')\n return new RegExp(`^${compileBody(uri.slice(0, -FALLBACK_SEGMENT.length - 1), wheres)}${tail}$`, 's')\n}\n\n/** Sort order for matching: fallbacks last, then per-segment specificity; ties keep registration order. */\nexport function compareRoutes(a: RouteDefinition, b: RouteDefinition): number {\n if (a.isFallback !== b.isFallback) return a.isFallback ? 1 : -1\n const left = a.rank()\n const right = b.rank()\n for (let i = 0; i < Math.max(left.length, right.length); i++) {\n const x = left[i] ?? -1\n const y = right[i] ?? -1\n if (x !== y) return x - y\n }\n return 0\n}\n\nexport class RouteDefinition implements Route {\n readonly methods: readonly string[]\n readonly uri: string\n readonly action: RouteHandler\n readonly controller: Class<unknown> | undefined\n readonly isFallback: boolean\n readonly parameters: readonly UriParameter[]\n #name: string | undefined\n readonly #middleware: MiddlewareReference[]\n readonly #excluded: MiddlewareReference[] = []\n readonly #wheres: Record<string, string> = {}\n #compiled: { regex: RegExp; version: number } | undefined\n\n constructor(methods: readonly string[], uri: string, action: RouteHandler, attributes: RouteAttributes = {}) {\n this.methods = [...new Set(methods.map((method) => method.toUpperCase()))]\n this.uri = normalizeUri(uri)\n this.action = action\n this.controller = attributes.controller\n this.isFallback = attributes.fallback ?? false\n this.parameters = parseParameters(this.uri)\n this.#name = attributes.namePrefix === undefined || attributes.namePrefix === '' ? undefined : attributes.namePrefix\n this.#middleware = [...(attributes.middleware ?? [])]\n }\n\n getName(): string | undefined {\n return this.#name\n }\n\n /** Appends, like Laravel's $action['as'] .= $name. */\n name(name: string): this {\n this.#name = (this.#name ?? '') + name\n return this\n }\n\n /** middleware('auth', 'verified') or middleware(['auth', 'verified']). */\n middleware(...middleware: Array<MiddlewareReference | readonly MiddlewareReference[]>): this {\n this.#middleware.push(...middleware.flat())\n return this\n }\n\n withoutMiddleware(...middleware: MiddlewareReference[]): this {\n this.#excluded.push(...middleware.flat())\n return this\n }\n\n where(parameter: string | Record<string, string>, pattern?: string): this {\n if (typeof parameter === 'string') this.#wheres[parameter] = pattern ?? '[^/]+'\n else Object.assign(this.#wheres, parameter)\n this.#compiled = undefined\n return this\n }\n\n /** Laravel's whereAlpha(): ASCII letters only. One parameter name or several. */\n whereAlpha(parameters: string | readonly string[]): this {\n return this.#assign(parameters, '[a-zA-Z]+')\n }\n\n /** Laravel's whereAlphaNumeric(): ASCII letters and digits. */\n whereAlphaNumeric(parameters: string | readonly string[]): this {\n return this.#assign(parameters, '[a-zA-Z0-9]+')\n }\n\n /** Laravel's whereNumber(): digits only. */\n whereNumber(parameters: string | readonly string[]): this {\n return this.#assign(parameters, '[0-9]+')\n }\n\n /** Laravel's whereUlid(): 26 Crockford base-32 characters, the first at most 7. */\n whereUlid(parameters: string | readonly string[]): this {\n return this.#assign(parameters, '[0-7][0-9a-hjkmnp-tv-zA-HJKMNP-TV-Z]{25}')\n }\n\n /** Laravel's whereUuid(): five groups of hex digits (8-4-4-4-12), any version. */\n whereUuid(parameters: string | readonly string[]): this {\n return this.#assign(parameters, '[\\\\da-fA-F]{8}-[\\\\da-fA-F]{4}-[\\\\da-fA-F]{4}-[\\\\da-fA-F]{4}-[\\\\da-fA-F]{12}')\n }\n\n /** Laravel's whereIn(): one of the values. Unlike Laravel, each value is matched literally (`c++` is not a pattern). */\n whereIn(parameters: string | readonly string[], values: ReadonlyArray<string | number>): this {\n const first = typeof parameters === 'string' ? parameters : parameters[0]\n if (values.length === 0 && first !== undefined) throw new Error(`Routing requirement for \"${first}\" cannot be empty.`)\n return this.#assign(parameters, values.map((value) => escapeRegex(String(value))).join('|'))\n }\n\n gatherMiddleware(): MiddlewareReference[] {\n return [...this.#middleware]\n }\n\n excludedMiddleware(): MiddlewareReference[] {\n return [...this.#excluded]\n }\n\n wheres(): Record<string, string> {\n return { ...this.#wheres }\n }\n\n getActionName(): string {\n if (typeof this.action === 'string') return `${this.controller?.name ?? 'Controller'}@${this.action}`\n if (Array.isArray(this.action)) return `${(this.action[0] as Class<unknown>).name}@${String(this.action[1])}`\n return 'Closure'\n }\n\n /** Decoded parameter values when `path` (normalizePath output) matches, else undefined. */\n match(\n path: string,\n patterns: Readonly<Record<string, string>> = {},\n version = 0,\n ): Record<string, string | undefined> | undefined {\n const found = this.#regex(patterns, version).exec(path)\n if (found === null) return undefined\n const values: Record<string, string | undefined> = {}\n for (const { name } of this.parameters) {\n const raw = found.groups?.[`p_${name}`]\n values[name] = raw === undefined ? undefined : decode(raw)\n }\n return values\n }\n\n /** Per-segment specificity: static 0, parameter 1, optional parameter 2. Lower sorts first. */\n rank(): number[] {\n if (this.uri === '/') return []\n return this.uri.split('/').map((segment) => (WHOLE_OPTIONAL.test(segment) ? 2 : segment.includes('{') ? 1 : 0))\n }\n\n #assign(parameters: string | readonly string[], pattern: string): this {\n const names: readonly string[] = typeof parameters === 'string' ? [parameters] : parameters\n return this.where(Object.fromEntries(names.map((name) => [name, pattern])))\n }\n\n #regex(patterns: Readonly<Record<string, string>>, version: number): RegExp {\n if (this.#compiled !== undefined && this.#compiled.version === version) return this.#compiled.regex\n const wheres = { ...patterns, ...this.#wheres }\n const regex = this.isFallback ? compileFallback(this.uri, wheres) : new RegExp(`^${compileBody(this.uri, wheres)}$`)\n this.#compiled = { regex, version }\n return regex\n }\n}\n","import type { Class, ControllerAction, InvokableClass, MiddlewareReference, ResourceOptions, RouteClosure, RouteRegistrar } from '@orieljs/contracts'\nimport type { RouteDefinition, RouteHandler } from './RouteDefinition'\n\n/** Attributes shared by the routes of a group (Laravel's group attribute array). */\nexport interface GroupAttributes {\n prefix?: string\n /** Name prefix ('admin.'). */\n as?: string\n middleware?: MiddlewareReference[]\n controller?: Class<unknown>\n}\n\n/** What a GroupRegistrar needs from the router. */\nexport interface GroupHost {\n group(attributes: GroupAttributes, routes: () => void | Promise<void>): Promise<void>\n addRoute(methods: readonly string[], uri: string, action: RouteHandler): RouteDefinition\n resource(name: string, controller: Class<unknown>, options?: ResourceOptions): void\n apiResource(name: string, controller: Class<unknown>, options?: ResourceOptions): void\n}\n\n/** Every HTTP verb a route can respond to. BaseRouter reuses this instead of redeclaring it. */\nexport const ALL_VERBS = ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']\n\n/** Merges a nested group's attributes into its parent's, like Laravel's RouteGroup::merge. */\nexport function mergeGroup(parent: GroupAttributes, child: GroupAttributes): GroupAttributes {\n const prefix = [parent.prefix, child.prefix]\n .map((part) => (part ?? '').replace(/^\\/+|\\/+$/g, ''))\n .filter((part) => part !== '')\n .join('/')\n const merged: GroupAttributes = {\n middleware: [...(parent.middleware ?? []), ...(child.middleware ?? [])],\n }\n if (prefix !== '') merged.prefix = prefix\n const as = (parent.as ?? '') + (child.as ?? '')\n if (as !== '') merged.as = as\n const controller = child.controller ?? parent.controller\n if (controller !== undefined) merged.controller = controller\n return merged\n}\n\n/**\n * Route.prefix('admin').name('admin.').middleware('auth').group(() => …), and the one-route form\n * Route.middleware('auth').get('/x', action) (Laravel's RouteRegistrar).\n */\nexport class GroupRegistrar implements RouteRegistrar {\n readonly #attributes: GroupAttributes = {}\n\n constructor(private readonly router: GroupHost) {}\n\n prefix(prefix: string): this {\n this.#attributes.prefix = prefix\n return this\n }\n\n name(prefix: string): this {\n this.#attributes.as = prefix\n return this\n }\n\n middleware(...middleware: Array<MiddlewareReference | readonly MiddlewareReference[]>): this {\n this.#attributes.middleware = [...(this.#attributes.middleware ?? []), ...middleware.flat()]\n return this\n }\n\n controller(controller: Class<unknown>): this {\n this.#attributes.controller = controller\n return this\n }\n\n group(routes: () => void | Promise<void>): Promise<void> {\n return this.router.group({ ...this.#attributes }, routes)\n }\n\n get<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.#one(['GET', 'HEAD'], uri, action)\n }\n\n post<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.#one(['POST'], uri, action)\n }\n\n put<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.#one(['PUT'], uri, action)\n }\n\n patch<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.#one(['PATCH'], uri, action)\n }\n\n delete<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.#one(['DELETE'], uri, action)\n }\n\n options<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.#one(['OPTIONS'], uri, action)\n }\n\n any<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.#one(ALL_VERBS, uri, action)\n }\n\n match<C>(methods: string[], uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.#one(methods, uri, action)\n }\n\n resource(name: string, controller: Class<unknown>, options?: ResourceOptions): void {\n void this.router.group({ ...this.#attributes }, () => this.router.resource(name, controller, options))\n }\n\n apiResource(name: string, controller: Class<unknown>, options?: ResourceOptions): void {\n void this.router.group({ ...this.#attributes }, () => this.router.apiResource(name, controller, options))\n }\n\n #one(methods: readonly string[], uri: string, action: RouteHandler): RouteDefinition {\n let route: RouteDefinition | undefined\n void this.router.group({ ...this.#attributes }, () => {\n route = this.router.addRoute(methods, uri, action)\n })\n return route!\n }\n}\n","import type { ResourceOptions } from '@orieljs/contracts'\nimport { Str } from '@orieljs/support'\n\nexport type ResourceMethod = 'index' | 'create' | 'store' | 'show' | 'edit' | 'update' | 'destroy'\n\nexport interface ResourceRoute {\n readonly method: ResourceMethod\n readonly verbs: readonly string[]\n readonly uri: string\n readonly name: string\n}\n\n/** Laravel's order (ResourceRegistrar::$resourceDefaults). */\nconst DEFAULTS: readonly ResourceMethod[] = ['index', 'create', 'store', 'show', 'edit', 'update', 'destroy']\nconst API_DEFAULTS: readonly ResourceMethod[] = ['index', 'store', 'show', 'update', 'destroy']\n\n/** 'blog-posts' → 'blog_post' (Laravel's getResourceWildcard), unless options.parameters renames it. */\nfunction wildcard(segment: string, options: ResourceOptions): string {\n const renamed = options.parameters?.[segment]\n return (renamed ?? Str.singular(segment)).replace(/-/g, '_')\n}\n\n/**\n * The routes Route.resource()/apiResource() register. 'photos.comments' nests:\n * photos/{photo}/comments/{comment}, named photos.comments.*.\n */\nexport function resourceRoutes(name: string, options: ResourceOptions = {}, api = false): ResourceRoute[] {\n const segments = name.split('.')\n const last = segments.at(-1)!\n const base = [...segments.slice(0, -1).map((segment) => `${segment}/{${wildcard(segment, options)}}`), last].join('/')\n const member = `${base}/{${wildcard(last, options)}}`\n\n let methods = api ? API_DEFAULTS : DEFAULTS\n if (options.only !== undefined) methods = methods.filter((method) => options.only!.includes(method))\n if (options.except !== undefined) methods = methods.filter((method) => !options.except!.includes(method))\n\n const table: Record<ResourceMethod, { verbs: string[]; uri: string }> = {\n index: { verbs: ['GET', 'HEAD'], uri: base },\n create: { verbs: ['GET', 'HEAD'], uri: `${base}/create` },\n store: { verbs: ['POST'], uri: base },\n show: { verbs: ['GET', 'HEAD'], uri: member },\n edit: { verbs: ['GET', 'HEAD'], uri: `${member}/edit` },\n update: { verbs: ['PUT', 'PATCH'], uri: member },\n destroy: { verbs: ['DELETE'], uri: member },\n }\n return methods.map((method) => ({\n method,\n verbs: table[method].verbs,\n uri: table[method].uri,\n name: options.names?.[method] ?? `${name}.${method}`,\n }))\n}\n","import { createHmac, timingSafeEqual } from 'node:crypto'\nimport { ConfigRepository, Encrypter, HttpRequest, Session, type Container, type UrlGenerator } from '@orieljs/contracts'\nimport { currentContainer } from '@orieljs/container'\nimport type { BaseRouter } from './BaseRouter'\nimport { RouteNotDefinedError, RoutingError, UrlGenerationError } from './errors'\nimport { PARAMETER, WHOLE_OPTIONAL } from './RouteDefinition'\n\nconst VALID_URL = /^(#|\\/\\/|https?:\\/\\/|(mailto|tel|sms):)/i\n\n// Duplicated in Http's input.ts on purpose: Http, Routing and Pipeline may not import each other.\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false\n const prototype = Object.getPrototypeOf(value) as unknown\n return prototype === Object.prototype || prototype === null\n}\n\n/** PHP's http_build_query: nested objects and arrays become a[b]=1&a[0]=2; null/undefined are skipped. */\nexport function buildQuery(values: Record<string, unknown>): string {\n const pairs: string[] = []\n const add = (key: string, value: unknown): void => {\n if (value === null || value === undefined) return\n if (typeof value === 'object' && (Array.isArray(value) || isPlainObject(value))) {\n for (const [child, nested] of Object.entries(value)) add(`${key}[${child}]`, nested)\n return\n }\n const text = value === true ? '1' : value === false ? '0' : String(value)\n pairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(text)}`)\n }\n for (const [key, value] of Object.entries(values)) add(key, value)\n return pairs.join('&')\n}\n\n/** A model's URL value: the {post:slug} field when given, else getRouteKey(), else the value itself. */\nfunction routeKey(value: unknown, field: string | undefined): unknown {\n if (typeof value !== 'object' || value === null) return value\n const model = value as { getRouteKey?: () => unknown; getAttribute?: (key: string) => unknown } & Record<string, unknown>\n if (field !== undefined) return typeof model.getAttribute === 'function' ? model.getAttribute(field) : model[field]\n return typeof model.getRouteKey === 'function' ? model.getRouteKey() : value\n}\n\n/** HMAC-SHA256 of a URL, hex (Laravel's hash_hmac('sha256', $url, $key)). */\nfunction sign(url: string, key: Uint8Array): string {\n return createHmac('sha256', key).update(url).digest('hex')\n}\n\n/** Constant-time string comparison. */\nfunction safeEquals(expected: string, given: string): boolean {\n const a = Buffer.from(expected)\n const b = Buffer.from(given)\n return a.length === b.length && timingSafeEqual(a, b)\n}\n\n/** Unix seconds: a Date, or a number of seconds from now (Laravel's availableAt()). */\nfunction availableAt(expiration: Date | number): number {\n return expiration instanceof Date ? Math.floor(expiration.getTime() / 1000) : Math.floor(Date.now() / 1000) + expiration\n}\n\n/** Laravel's UrlGenerator. The root is the current request's origin, else config('app.url'). */\nexport class BaseUrlGenerator implements UrlGenerator {\n constructor(\n private readonly router: BaseRouter,\n private readonly container?: Container,\n ) {}\n\n /** 'http://localhost' (no trailing slash). */\n root(): string {\n const request = this.#request()\n if (request !== undefined) return new URL(request.url()).origin\n const configured = this.#config<string | undefined>('app.url', undefined)\n return (configured ?? 'http://localhost').replace(/\\/+$/, '')\n }\n\n to(path: string, query: Record<string, unknown> = {}, absolute = true): string {\n const queryString = buildQuery(query)\n const base = VALID_URL.test(path) ? path : this.#join(path, absolute)\n if (queryString === '') return base\n return `${base}${base.includes('?') ? '&' : '?'}${queryString}`\n }\n\n /**\n * route('posts.show', post) / route('posts.show', [post, comment]) / route('posts.show', { post: 1, page: 2 }).\n * Named values fill their parameters, positional values fill the rest in URI order; extra named values become\n * the query string, extra positional ones are dropped.\n */\n route(name: string, parameters?: unknown, absolute = true): string {\n const route = this.router.getByName(name)\n if (route === undefined) throw new RouteNotDefinedError(name)\n const named: Record<string, unknown> = isPlainObject(parameters) ? { ...parameters } : {}\n const positional: unknown[] = Array.isArray(parameters)\n ? [...parameters]\n : parameters === undefined || parameters === null || isPlainObject(parameters)\n ? []\n : [parameters]\n\n const values = new Map<string, string | undefined>()\n const missing: string[] = []\n for (const parameter of route.parameters) {\n let value: unknown\n if (Object.hasOwn(named, parameter.name)) {\n value = named[parameter.name]\n delete named[parameter.name]\n } else if (positional.length > 0) {\n value = positional.shift()\n }\n const key = routeKey(value, parameter.field)\n const text = key === undefined || key === null ? undefined : String(key)\n if (text === undefined && !parameter.optional) missing.push(parameter.name)\n values.set(parameter.name, text)\n }\n if (missing.length > 0) throw new UrlGenerationError(name, route.uri, missing)\n\n const path =\n route.uri === '/'\n ? ''\n : route.uri\n .split('/')\n .filter((segment) => {\n const whole = WHOLE_OPTIONAL.exec(segment)\n return whole === null || values.get(whole[1]!) !== undefined\n })\n .map((segment) =>\n segment.replace(PARAMETER, (_match, parameter: string) => {\n const value = values.get(parameter)\n return value === undefined ? '' : encodeURIComponent(value)\n }),\n )\n .join('/')\n const query = Object.fromEntries(Object.entries(named).map(([key, value]) => [key, routeKey(value, undefined)]))\n return this.to(path, query, absolute)\n }\n\n asset(path: string): string {\n if (VALID_URL.test(path)) return path\n const base = this.#config<string | undefined>('app.asset_url', undefined)?.replace(/\\/+$/, '') ?? this.root()\n const trimmed = path.replace(/^\\/+/, '')\n return trimmed === '' ? base : `${base}/${trimmed}`\n }\n\n /** The current URL without the query string. */\n current(): string {\n return this.#request()?.url() ?? this.root()\n }\n\n /** The current URL with the query string. */\n full(): string {\n return this.#request()?.fullUrl() ?? this.root()\n }\n\n /** The Referer header, then the session's previous URL, then `fallback`, then the root (Laravel's order). */\n previous(fallback?: string): string {\n const scope = this.#scope()\n const request = this.#request()\n const referer = request?.header('referer')\n if (referer !== undefined && referer !== '') return this.to(referer)\n if (request !== undefined && scope?.bound(Session)) {\n const previous = scope.make(Session).previousUrl()\n if (previous !== undefined && previous !== '') return this.to(previous)\n }\n return this.to(fallback ?? '/')\n }\n\n hasRoute(name: string): boolean {\n return this.router.getByName(name) !== undefined\n }\n\n /**\n * Laravel's URL::signedRoute(): the route URL with its parameters sorted by name, then a `signature` query (the\n * HMAC-SHA256 of that URL, keyed by APP_KEY). `expiration` (a Date, or seconds from now) adds `expires`.\n * `absolute: false` signs the path only (checked by `signed:relative`).\n */\n signedRoute(name: string, parameters?: unknown, expiration?: Date | number, absolute = true): string {\n const named = this.#namedParameters(name, parameters)\n for (const reserved of ['signature', 'expires']) {\n if (Object.hasOwn(named, reserved)) {\n throw new RoutingError(`\"${reserved}\" is a reserved parameter when generating signed routes. Please rename your route parameter.`)\n }\n }\n if (expiration !== undefined) named.expires = availableAt(expiration)\n const sorted = Object.fromEntries(Object.keys(named).sort().map((key) => [key, named[key]]))\n const signature = sign(this.route(name, sorted, absolute), this.#signingKeys()[0]!)\n return this.route(name, { ...sorted, signature }, absolute)\n }\n\n /** Laravel's URL::temporarySignedRoute(): a signed URL that expires at `expiration` (a Date, or seconds from now). */\n temporarySignedRoute(name: string, expiration: Date | number, parameters?: unknown, absolute = true): string {\n return this.signedRoute(name, parameters, expiration, absolute)\n }\n\n /** The request URL carries a correct signature (current or previous APP_KEY) that hasn't expired. */\n hasValidSignature(request: HttpRequest, absolute = true): boolean {\n return this.hasCorrectSignature(request, absolute) && this.signatureHasNotExpired(request)\n }\n\n /** The signature matches the URL without its `signature` query, in a constant-time comparison. */\n hasCorrectSignature(request: HttpRequest, absolute = true): boolean {\n const full = new URL(request.fullUrl())\n const path = request.path()\n const url = absolute ? request.url() : path === '/' ? '/' : `/${path}`\n const query = full.search\n .slice(1)\n .split('&')\n .filter((pair) => pair !== '' && pair.split('=')[0] !== 'signature')\n .join('&')\n const original = query === '' ? url : `${url}?${query}`\n const given = full.searchParams.get('signature') ?? ''\n return this.#signingKeys().some((key) => safeEquals(sign(original, key), given))\n }\n\n /** No `expires` query, or one that is still in the future. */\n signatureHasNotExpired(request: HttpRequest): boolean {\n const expires = new URL(request.fullUrl()).searchParams.get('expires')\n if (expires === null || expires === '') return true\n const at = Number(expires)\n return Number.isFinite(at) && Math.floor(Date.now() / 1000) <= at\n }\n\n /** Named parameters: an object as is, positional values (a list or one value) by the route's parameter names. */\n #namedParameters(name: string, parameters: unknown): Record<string, unknown> {\n if (isPlainObject(parameters)) return { ...parameters }\n const route = this.router.getByName(name)\n if (route === undefined) throw new RouteNotDefinedError(name)\n const values = parameters === undefined || parameters === null ? [] : Array.isArray(parameters) ? parameters : [parameters]\n const named: Record<string, unknown> = {}\n route.parameters.forEach((parameter, index) => {\n if (index < values.length) named[parameter.name] = values[index]\n })\n return named\n }\n\n /** The Encrypter's key, then its previous keys (config app.previous_keys), so rotated keys still verify. */\n #signingKeys(): Uint8Array[] {\n const scope = this.#scope()\n if (scope === undefined || !scope.bound(Encrypter)) {\n throw new RoutingError('Signed URLs need the Encrypter: set APP_KEY (oriel key:generate).')\n }\n const encrypter = scope.make(Encrypter) as Encrypter & { getAllKeys?(): Uint8Array[] }\n return typeof encrypter.getAllKeys === 'function' ? encrypter.getAllKeys() : [encrypter.getKey()]\n }\n\n #join(path: string, absolute: boolean): string {\n const trimmed = path.replace(/^\\/+|\\/+$/g, '')\n if (!absolute) return `/${trimmed}`\n return trimmed === '' ? this.root() : `${this.root()}/${trimmed}`\n }\n\n #scope(): Container | undefined {\n return currentContainer() ?? this.container\n }\n\n /** The HttpRequest, only when running inside a request scope. */\n #request(): HttpRequest | undefined {\n const scope = this.#scope()\n return scope?.bound(HttpRequest) ? scope.make(HttpRequest) : undefined\n }\n\n #config<T>(key: string, fallback: T): T {\n const scope = this.#scope()\n return scope?.bound(ConfigRepository) ? scope.make(ConfigRepository).get<T>(key, fallback) : fallback\n }\n}\n","import { Router, type Abstract } from '@orieljs/contracts'\nimport { facade } from '@orieljs/support'\nimport type { BaseRouter } from './BaseRouter'\n\n/**\n * The Route facade: Route.get('/', …), Route.prefix('admin').group(…), Route.resource(…). Typed as the BaseRouter\n * so the extras (permanentRedirect, patterns, has, currentRouteName, …) are available too.\n */\nexport const Route = facade<BaseRouter>(Router as Abstract<BaseRouter>)\n","import { ConfigRepository, EventDispatcher, ExceptionHandler, type Container } from '@orieljs/contracts'\n\n/**\n * Dispatched by the health route (`/up`) on every request (Laravel's DiagnosingHealth event). A listener checks\n * something the application needs, such as the database or the cache, and throws when it fails: `/up` then answers\n * 500 with \"Application experiencing problems\", and the exception is reported.\n *\n * Event.listen(DiagnosingHealth, async () => { await DB.select('select 1') })\n */\nexport class DiagnosingHealth {}\n\nexport interface HealthPage {\n /** False when a check failed: the page says so and the status is 500 (default true). */\n healthy?: boolean\n /** How long the request took, shown when given. */\n milliseconds?: number\n /** The page title (default \"Oriel\"). */\n appName?: string\n}\n\nconst escapeHtml = (value: string): string => value.replace(/[&<>\"']/g, (char) => `&#${char.charCodeAt(0)};`)\n\n// The Oriel style: dark canvas, one Graphite block, the system fonts, flat. Green and red are the status dot only.\nconst STYLE =\n ':root{color-scheme:dark}*{box-sizing:border-box;margin:0}html{background:#05050b}' +\n 'body{min-height:100vh;display:grid;place-items:center;padding:20px;background:#1a1a1a;color:#fff;' +\n 'font:400 16px/1.7 system-ui,-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,sans-serif}' +\n 'main{display:flex;align-items:center;gap:20px;width:100%;max-width:640px;padding:20px 32px;border-radius:18px;background:#212121}' +\n '.dot{flex:none;width:12px;height:12px;border-radius:50%;background:#74ec5a}.dot.down{background:#ff3543}' +\n 'h1{font-size:21px;line-height:1.4;font-weight:600}p{color:#a3a3a3}.time{color:#ba94ff}'\n\n/**\n * The health route's page (Laravel's health-up view): \"Application up\", or \"Application experiencing problems\" with\n * status 500. Self-contained HTML with inline CSS: it loads nothing, so it answers even when the assets don't.\n */\nexport function healthResponse(page: HealthPage = {}): Response {\n const healthy = page.healthy ?? true\n const time = page.milliseconds === undefined ? '' : ` Response rendered in <span class=\"time\">${Math.round(page.milliseconds)} ms</span>.`\n const html =\n '<!DOCTYPE html>\\n<html lang=\"en\">\\n<head>\\n<meta charset=\"utf-8\">\\n' +\n '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\\n' +\n `<title>${escapeHtml(page.appName ?? 'Oriel')}</title>\\n<style>${STYLE}</style>\\n</head>\\n<body>\\n<main>\\n` +\n `<span class=\"${healthy ? 'dot' : 'dot down'}\" aria-hidden=\"true\"></span>\\n` +\n `<div>\\n<h1>Application ${healthy ? 'up' : 'experiencing problems'}</h1>\\n<p>HTTP request received.${time}</p>\\n</div>\\n` +\n '</main>\\n</body>\\n</html>\\n'\n return new Response(html, { status: healthy ? 200 : 500, headers: { 'content-type': 'text/html; charset=utf-8' } })\n}\n\n/**\n * The `/up` action: dispatches DiagnosingHealth, then renders the page. A listener's exception is rethrown in debug\n * mode (the error page shows it); otherwise it is reported, and the page answers 500 without its message.\n */\nexport async function diagnoseHealth(app: Container): Promise<Response> {\n const started = performance.now()\n const config = app.bound(ConfigRepository) ? app.make(ConfigRepository) : undefined\n let healthy = true\n try {\n if (app.bound(EventDispatcher)) await app.make(EventDispatcher).dispatch(new DiagnosingHealth())\n } catch (error) {\n if (config?.get<unknown>('app.debug', false) === true) throw error\n if (app.bound(ExceptionHandler)) await app.make(ExceptionHandler).report(error)\n healthy = false\n }\n const appName = String(config?.get('app.name', 'Oriel') ?? 'Oriel')\n return healthResponse({ healthy, appName, milliseconds: performance.now() - started })\n}\n","import { pathToFileURL } from 'node:url'\nimport type { Application, Router } from '@orieljs/contracts'\n\n/** A route file may export a function instead of (or as well as) calling the Route facade at the top level. */\nexport type RouteFileCallback = (router: Router) => void | Promise<void>\n\nlet generation = 0\n\n/**\n * Imports a route file inside app.run(), so the Route facade in it resolves this application. Each load adds a\n * fresh `?oriel-routes=<n>` query: ESM caches modules, and a fresh app per test must register its routes again.\n * A default export that is a function is called with the router.\n */\nexport async function loadRoutesFrom(app: Application, router: Router, file: string): Promise<void> {\n const url = `${pathToFileURL(file).href}?oriel-routes=${++generation}`\n const module = (await app.run(() => import(/* @vite-ignore */ url))) as { default?: unknown }\n if (typeof module.default === 'function') await app.run(() => (module.default as RouteFileCallback)(router))\n}\n\n","import { Router, RoutingPaths, UrlGenerator } from '@orieljs/contracts'\nimport { ServiceProvider } from '@orieljs/support'\nimport { BaseRouter } from './BaseRouter'\nimport { BaseUrlGenerator } from './BaseUrlGenerator'\nimport { RoutingError } from './errors'\nimport { diagnoseHealth } from './health'\nimport { loadRoutesFrom } from './routeFiles'\nimport { ThrottleRequests } from './ThrottleRequests'\nimport { ValidateSignature } from './ValidateSignature'\n\n/**\n * Binds the Router and the UrlGenerator, registers the `signed` and `throttle` middleware, and once the app has booted\n * loads the files given to withRouting(): the health URI (which dispatches DiagnosingHealth), then the web files in the\n * `web` middleware group, then the api files under the api prefix in the `api` group (Laravel's\n * ApplicationBuilder::withRouting).\n */\nexport class RoutingServiceProvider extends ServiceProvider {\n override register(): void {\n this.app.singleton(Router, () => new BaseRouter(this.app))\n this.app.singleton(UrlGenerator, () => {\n const router = this.app.make(Router)\n if (!(router instanceof BaseRouter)) {\n throw new RoutingError('The UrlGenerator needs the BaseRouter: the bound Router was replaced by another implementation.')\n }\n return new BaseUrlGenerator(router, this.app)\n })\n }\n\n /**\n * The files load in a booted() callback, after every provider's boot() (Laravel's withRouting does the same), so\n * what the app's own providers set up at boot (Route.pattern/bind/model, gates, shared view data) is in place\n * when the route files run.\n */\n override boot(): void {\n this.app.make(Router).aliasMiddleware('signed', ValidateSignature).aliasMiddleware('throttle', ThrottleRequests)\n this.app.booted(async () => {\n if (!this.app.bound(RoutingPaths)) return\n const { web, api, health, apiPrefix } = this.app.make(RoutingPaths)\n const router = this.app.make(Router)\n if (health !== undefined) router.get(health, () => diagnoseHealth(this.app))\n if (web !== undefined) await router.middleware('web').group(() => this.#load(router, web))\n if (api !== undefined) await router.prefix(apiPrefix).middleware('api').group(() => this.#load(router, api))\n })\n }\n\n /** One file or several, in order: each is imported afresh for this application (a nested import is not). */\n async #load(router: Router, files: string | string[]): Promise<void> {\n for (const file of [files].flat()) await loadRoutesFrom(this.app, router, file)\n }\n}\n","import { createHash } from 'node:crypto'\nimport { RateLimiter, type HttpRequest, type Middleware, type Next } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport { RoutingError, ThrottleRequestsError } from './errors'\n\nconst sha1 = (value: string): string => createHash('sha1').update(value).digest('hex')\n\n/** Sets headers, copying the response first when its headers are immutable (Response.redirect()). */\nfunction withHeaders(response: Response, headers: Record<string, string>): Response {\n try {\n for (const [name, value] of Object.entries(headers)) response.headers.set(name, value)\n return response\n } catch {\n const copy = new Headers(response.headers)\n for (const [name, value] of Object.entries(headers)) copy.set(name, value)\n return new Response(response.body, { status: response.status, statusText: response.statusText, headers: copy })\n }\n}\n\n/**\n * Laravel's ThrottleRequests (`throttle:<maxAttempts>,<decayMinutes>[,<prefix>]`): counts the client's requests\n * (the signed-in user, else the IP) in a window and answers 429 once there are too many. Responses carry\n * X-RateLimit-Limit and X-RateLimit-Remaining; the 429 adds Retry-After and X-RateLimit-Reset.\n */\nexport class ThrottleRequests implements Middleware {\n async handle(request: HttpRequest, next: Next, maxAttempts = '60', decayMinutes = '1', prefix = ''): Promise<Response> {\n const max = Number(maxAttempts)\n const decay = Number(decayMinutes)\n if (maxAttempts.trim() === '' || !Number.isInteger(max) || max < 0 || decayMinutes.trim() === '' || !Number.isFinite(decay) || decay <= 0) {\n throw new RoutingError(\n `Invalid throttle parameters \"${maxAttempts},${decayMinutes}\": use throttle:<maxAttempts>,<decayMinutes>[,<prefix>] (named rate limiters are not supported).`,\n )\n }\n const limiter = inject(RateLimiter)\n const key = prefix + this.resolveRequestSignature(request)\n if (await limiter.tooManyAttempts(key, max)) {\n const retryAfter = await limiter.availableIn(key)\n throw new ThrottleRequestsError({\n 'X-RateLimit-Limit': String(max),\n 'X-RateLimit-Remaining': '0',\n 'Retry-After': String(retryAfter),\n 'X-RateLimit-Reset': String(Math.floor(Date.now() / 1000) + retryAfter),\n })\n }\n await limiter.hit(key, Math.round(decay * 60))\n const response = await next(request)\n return withHeaders(response, {\n 'X-RateLimit-Limit': String(max),\n 'X-RateLimit-Remaining': String(await limiter.remaining(key, max)),\n })\n }\n\n /** The signed-in user's identifier, else the client IP, hashed (Laravel's resolveRequestSignature()). */\n protected resolveRequestSignature(request: HttpRequest): string {\n const user = request.user<{ getAuthIdentifier?(): unknown }>()\n if (user !== undefined && user !== null && typeof user.getAuthIdentifier === 'function') {\n return sha1(String(user.getAuthIdentifier()))\n }\n return sha1(`|${request.ip() ?? ''}`)\n }\n}\n","import { UrlGenerator, type HttpRequest, type Middleware, type Next } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport { InvalidUrlSignatureError } from './errors'\n\n/**\n * Laravel's ValidateSignature (`signed`, `signed:relative`): the request URL must carry a valid, unexpired\n * signature from URL.signedRoute()/temporarySignedRoute(), else 403. `relative` checks a path-only signature.\n */\nexport class ValidateSignature implements Middleware {\n async handle(request: HttpRequest, next: Next, ...parameters: string[]): Promise<Response> {\n const absolute = parameters[0] !== 'relative'\n if (inject(UrlGenerator).hasValidSignature(request, absolute)) return next(request)\n throw new InvalidUrlSignatureError()\n }\n}\n"],"mappings":"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","names":["CurrentRoute","currentContainer","Str","currentContainer","CurrentRoute","currentContainer","currentContainer","ConfigRepository","ExceptionHandler","html","Router","UrlGenerator","UrlGenerator","inject","inject","UrlGenerator","Router","UrlGenerator"]}
1
+ {"version":3,"sources":["../BaseRouter.ts","../bindings.ts","../errors.ts","../middleware.ts","../toResponse.ts","../dispatch.ts","../RouteDefinition.ts","../GroupRegistrar.ts","../resource.ts","../BaseUrlGenerator.ts","../facade.ts","../health.ts","../routeFiles.ts","../RoutingServiceProvider.ts","../ThrottleRequests.ts","../ValidateSignature.ts"],"sourcesContent":["import {\n CurrentRoute,\n InertiaFactory,\n UrlGenerator,\n ViewFactory,\n type Class,\n type Container,\n type ControllerAction,\n type HttpRequest,\n type InvokableClass,\n type MiddlewareClass,\n type MiddlewareReference,\n type ResourceOptions,\n type RouteAction,\n type RouteClosure,\n type Router,\n} from '@orieljs/contracts'\nimport { currentContainer } from '@orieljs/container'\nimport { substituteBindings } from './bindings'\nimport { dispatchRoute } from './dispatch'\nimport { RoutingError } from './errors'\nimport { ALL_VERBS, GroupRegistrar, mergeGroup, type GroupAttributes } from './GroupRegistrar'\nimport { resourceRoutes } from './resource'\nimport { compareRoutes, RouteDefinition, type RouteHandler } from './RouteDefinition'\n\nexport type RouteBinder = (value: string) => unknown | Promise<unknown>\n\n/** Laravel's Illuminate\\Routing\\Router: registration, groups, patterns, bindings, middleware aliases/groups and dispatch. */\nexport class BaseRouter implements Router {\n readonly #routes: RouteDefinition[] = []\n #sorted: RouteDefinition[] | undefined\n readonly #groupStack: GroupAttributes[] = []\n readonly #patterns: Record<string, string> = {}\n #patternVersion = 0\n readonly #aliases: Record<string, MiddlewareClass> = {}\n readonly #groups: Record<string, MiddlewareReference[]> = { web: [], api: [] }\n readonly #binders = new Map<string, RouteBinder>()\n readonly #models = new Map<string, Class<unknown>>()\n\n /** `container` is the application; request-time lookups use the current (request) container first. */\n constructor(protected readonly container?: Container) {}\n\n get<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.addRoute(['GET', 'HEAD'], uri, action)\n }\n\n post<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.addRoute(['POST'], uri, action)\n }\n\n put<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.addRoute(['PUT'], uri, action)\n }\n\n patch<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.addRoute(['PATCH'], uri, action)\n }\n\n delete<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.addRoute(['DELETE'], uri, action)\n }\n\n options<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.addRoute(['OPTIONS'], uri, action)\n }\n\n any<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.addRoute(ALL_VERBS, uri, action)\n }\n\n match<C>(methods: string[], uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.addRoute(methods, uri, action)\n }\n\n /** Registers a route with the current group's prefix, name prefix, middleware and controller. GET implies HEAD. */\n addRoute(methods: readonly string[], uri: string, action: RouteHandler, options: { fallback?: boolean } = {}): RouteDefinition {\n const group = this.#groupStack.at(-1) ?? {}\n const verbs = methods.map((method) => method.toUpperCase())\n if (verbs.includes('GET') && !verbs.includes('HEAD')) verbs.push('HEAD')\n if (typeof action === 'string' && group.controller === undefined) {\n throw new RoutingError(\n `Route action [${action}] needs a controller. Use Route.controller(X).group(...) or pass [Controller, '${action}'].`,\n )\n }\n const prefix = (group.prefix ?? '').replace(/^\\/+|\\/+$/g, '')\n const path = uri.replace(/^\\/+|\\/+$/g, '')\n const route = new RouteDefinition(verbs, [prefix, path].filter((part) => part !== '').join('/'), action, {\n ...(group.as !== undefined && { namePrefix: group.as }),\n ...(group.middleware !== undefined && { middleware: group.middleware }),\n ...(group.controller !== undefined && { controller: group.controller }),\n ...(options.fallback === true && { fallback: true }),\n })\n this.#routes.push(route)\n this.#sorted = undefined\n return route\n }\n\n /** Route.redirect('/here', '/there'): any verb, 302 by default; '{param}' in the target is filled from the URI. */\n redirect(from: string, to: string, status = 302): RouteDefinition {\n const holder: { route?: RouteDefinition } = {}\n const action = (...values: unknown[]) => {\n const parameters = new Map(holder.route!.parameters.map((parameter, index) => [parameter.name, values[index]]))\n const target = to.replace(/\\{(\\w+)\\??\\}/g, (_match, name: string) => {\n const value = parameters.get(name)\n return value === undefined || value === null ? '' : encodeURIComponent(String(value))\n })\n const container = currentContainer() ?? this.container\n const location = container?.bound(UrlGenerator) ? container.make(UrlGenerator).to(target) : target\n return new Response(null, { status, headers: { Location: location } })\n }\n holder.route = this.any(from, action)\n return holder.route\n }\n\n permanentRedirect(from: string, to: string): RouteDefinition {\n return this.redirect(from, to, 301)\n }\n\n /** Route.view('/about', 'pages.about', data): GET/HEAD; route parameters are merged into the view data. */\n view(uri: string, view: string, data: Record<string, unknown> = {}): RouteDefinition {\n const holder: { route?: RouteDefinition } = {}\n const action = (...values: unknown[]) => {\n const parameters = Object.fromEntries(holder.route!.parameters.map((parameter, index) => [parameter.name, values[index]]))\n const container = currentContainer() ?? this.container\n if (container === undefined) throw new RoutingError(`Cannot render view [${view}]: no container is available.`)\n return container.make(ViewFactory).make(view, { ...data, ...parameters })\n }\n holder.route = this.addRoute(['GET', 'HEAD'], uri, action)\n return holder.route\n }\n\n /**\n * Route.inertia('/about', 'About', props): GET/HEAD; renders the page through the InertiaFactory (resolved when\n * the route runs, so Routing needs no Inertia import). Route parameters are merged into the props.\n */\n inertia(uri: string, component: string, props: Record<string, unknown> = {}): RouteDefinition {\n const holder: { route?: RouteDefinition } = {}\n const action = (...values: unknown[]) => {\n const parameters = Object.fromEntries(holder.route!.parameters.map((parameter, index) => [parameter.name, values[index]]))\n const container = currentContainer() ?? this.container\n if (container === undefined || !container.bound(InertiaFactory)) {\n throw new RoutingError(`Cannot render Inertia page [${component}]: no InertiaFactory is bound.`)\n }\n return container.make(InertiaFactory).render(component, { ...props, ...parameters })\n }\n holder.route = this.addRoute(['GET', 'HEAD'], uri, action)\n return holder.route\n }\n\n resource(name: string, controller: Class<unknown>, options: ResourceOptions = {}): void {\n this.#registerResource(name, controller, options, false)\n }\n\n apiResource(name: string, controller: Class<unknown>, options: ResourceOptions = {}): void {\n this.#registerResource(name, controller, options, true)\n }\n\n /** Matches any GET path no other route matches. Always tried last. */\n fallback(action: RouteAction): RouteDefinition {\n return this.addRoute(['GET', 'HEAD'], '{fallbackPlaceholder}', action, { fallback: true })\n }\n\n prefix(prefix: string): GroupRegistrar {\n return new GroupRegistrar(this).prefix(prefix)\n }\n\n name(prefix: string): GroupRegistrar {\n return new GroupRegistrar(this).name(prefix)\n }\n\n middleware(...middleware: Array<MiddlewareReference | readonly MiddlewareReference[]>): GroupRegistrar {\n return new GroupRegistrar(this).middleware(...middleware)\n }\n\n controller(controller: Class<unknown>): GroupRegistrar {\n return new GroupRegistrar(this).controller(controller)\n }\n\n /**\n * Laravel's Route::group(attributes, callback). A synchronous callback's attributes are popped before this\n * returns, so an unawaited group never leaks into later routes; an async callback keeps them until it settles.\n */\n group(attributes: GroupAttributes, routes: () => void | Promise<void>): Promise<void> {\n const entry = mergeGroup(this.#groupStack.at(-1) ?? {}, attributes)\n this.#groupStack.push(entry)\n const pop = () => {\n const index = this.#groupStack.lastIndexOf(entry)\n if (index !== -1) this.#groupStack.splice(index, 1)\n }\n let result: void | Promise<void>\n try {\n result = routes()\n } catch (error) {\n pop()\n throw error\n }\n if (result instanceof Promise) return result.finally(pop)\n pop()\n return Promise.resolve()\n }\n\n model(parameter: string, model: Class<unknown>): void {\n this.#models.set(parameter, model)\n }\n\n bind(parameter: string, resolver: RouteBinder): void {\n this.#binders.set(parameter, resolver)\n }\n\n pattern(parameter: string, pattern: string): void {\n this.#patterns[parameter] = pattern\n this.#patternVersion++\n }\n\n patterns(patterns: Record<string, string>): void {\n for (const [parameter, pattern] of Object.entries(patterns)) this.pattern(parameter, pattern)\n }\n\n getPatterns(): Readonly<Record<string, string>> {\n return { ...this.#patterns }\n }\n\n /** Bumped by pattern(); routes recompile their matcher when it changes. */\n getPatternVersion(): number {\n return this.#patternVersion\n }\n\n getBinder(parameter: string): RouteBinder | undefined {\n return this.#binders.get(parameter)\n }\n\n getModel(parameter: string): Class<unknown> | undefined {\n return this.#models.get(parameter)\n }\n\n /**\n * Binds a matched route's raw parameter values as a request to it would: Route.bind() callbacks, Route.model(),\n * then implicit binding through the RouteModelResolver of `container`. A missing model throws\n * RouteModelNotFoundError (404). Live uses it to check a page route's `can:` middleware again on each update.\n */\n substituteBindings(route: RouteDefinition, values: Readonly<Record<string, string | undefined>>, container: Container): Promise<Record<string, unknown>> {\n return substituteBindings(this, route, values, container)\n }\n\n aliasMiddleware(name: string, middleware: MiddlewareClass): this {\n this.#aliases[name] = middleware\n return this\n }\n\n /** The middleware aliases (Laravel's Router::getMiddleware()). */\n getMiddleware(): Record<string, MiddlewareClass> {\n return { ...this.#aliases }\n }\n\n middlewareGroup(name: string, middleware: MiddlewareReference[]): this {\n this.#groups[name] = [...middleware]\n return this\n }\n\n pushMiddlewareToGroup(group: string, middleware: MiddlewareReference): this {\n const list = (this.#groups[group] ??= [])\n if (!list.includes(middleware)) list.push(middleware)\n return this\n }\n\n prependMiddlewareToGroup(group: string, middleware: MiddlewareReference): this {\n const list = (this.#groups[group] ??= [])\n if (!list.includes(middleware)) list.unshift(middleware)\n return this\n }\n\n hasMiddlewareGroup(name: string): boolean {\n return Object.hasOwn(this.#groups, name)\n }\n\n getMiddlewareGroups(): Record<string, MiddlewareReference[]> {\n return Object.fromEntries(Object.entries(this.#groups).map(([name, list]) => [name, [...list]]))\n }\n\n /** Every route, in registration order. */\n getRoutes(): readonly RouteDefinition[] {\n return [...this.#routes]\n }\n\n /** Routes in matching order: static segments first, fallbacks last (cached until a route is added). */\n getRoutesByMatchOrder(): readonly RouteDefinition[] {\n return (this.#sorted ??= [...this.#routes].sort(compareRoutes))\n }\n\n /** The last route registered with this name wins, as in Laravel. */\n getByName(name: string): RouteDefinition | undefined {\n return this.#routes.findLast((route) => route.getName() === name)\n }\n\n has(...names: string[]): boolean {\n return names.every((name) => this.getByName(name) !== undefined)\n }\n\n /** The route matched for the current request (read from the request scope). */\n current(): RouteDefinition | undefined {\n const container = currentContainer()\n if (container === undefined || !container.bound(CurrentRoute)) return undefined\n return container.make(CurrentRoute).route as RouteDefinition\n }\n\n currentRouteName(): string | undefined {\n return this.current()?.getName()\n }\n\n /** Match, bind and run the route middleware and action (Router.dispatch; called by the Http kernel). */\n dispatch(request: HttpRequest): Promise<Response> {\n return dispatchRoute(this, request, this.container)\n }\n\n #registerResource(name: string, controller: Class<unknown>, options: ResourceOptions, api: boolean): void {\n for (const entry of resourceRoutes(name, options, api)) {\n this.addRoute(entry.verbs, entry.uri, [controller, entry.method] as RouteAction).name(entry.name)\n }\n }\n}\n","import { RouteModelResolver, type Container, type MiddlewareClass } from '@orieljs/contracts'\nimport { BindingResolutionError } from '@orieljs/container'\nimport { Str } from '@orieljs/support'\nimport type { BaseRouter } from './BaseRouter'\nimport { RouteModelNotFoundError } from './errors'\nimport { resolveMiddleware, type ResolvedMiddleware } from './middleware'\nimport type { RouteDefinition } from './RouteDefinition'\n\n/**\n * Laravel's $middlewarePriority around SubstituteBindings: the `web`/`api` group middleware and the `auth`/`guest`\n * aliases run before binding, every other route middleware after it (so `can:` sees the models, and a guest is\n * redirected before any lookup). Returns the middleware in that order (stable within each part) and the index\n * where the binding stage runs.\n */\nexport function orderForBindings(\n router: BaseRouter,\n middleware: readonly ResolvedMiddleware[],\n): { middleware: ResolvedMiddleware[]; at: number } {\n const aliases = router.getMiddleware()\n const groups = router.getMiddlewareGroups()\n const early = new Set<MiddlewareClass>()\n for (const name of ['auth', 'guest']) if (Object.hasOwn(aliases, name)) early.add(aliases[name]!)\n for (const group of ['web', 'api']) {\n try {\n for (const entry of resolveMiddleware([group], [], aliases, groups)) early.add(entry.cls)\n } catch {\n // A group naming an unknown alias fails the routes that use it, when they resolve their middleware.\n }\n }\n const before = middleware.filter((entry) => early.has(entry.cls))\n const after = middleware.filter((entry) => !early.has(entry.cls))\n return { middleware: [...before, ...after], at: before.length }\n}\n\n/**\n * Laravel's SubstituteBindings, run as a route stage (see orderForBindings), in URI order:\n * 1. Route.bind(name, fn): the callback's result, whatever it is\n * 2. Route.model(name, Model): RouteModelResolver.resolveExplicit(); nothing found → 404\n * 3. implicit: RouteModelResolver.resolve(name, value, field); undefined keeps the string, null → 404\n * Missing optional parameters stay undefined. Without a resolver, implicit binding is skipped.\n */\nexport async function substituteBindings(\n router: BaseRouter,\n route: RouteDefinition,\n values: Readonly<Record<string, string | undefined>>,\n container: Container,\n): Promise<Record<string, unknown>> {\n const resolver = container.bound(RouteModelResolver) ? container.make(RouteModelResolver) : undefined\n const bound: Record<string, unknown> = {}\n for (const { name, field } of route.parameters) {\n const value = values[name]\n if (value === undefined) {\n bound[name] = undefined\n continue\n }\n const binder = router.getBinder(name)\n if (binder !== undefined) {\n bound[name] = await binder(value)\n continue\n }\n const model = router.getModel(name)\n if (model !== undefined) {\n if (resolver === undefined) {\n throw new BindingResolutionError(\n `Route.model('${name}', ${model.name}) needs a RouteModelResolver. Is the Database service provider registered?`,\n )\n }\n const found = await resolver.resolveExplicit(model, value, field)\n if (found === null || found === undefined) throw new RouteModelNotFoundError(model.name, value)\n bound[name] = found\n continue\n }\n if (resolver !== undefined) {\n const found = await resolver.resolve(name, value, field)\n if (found === null) throw new RouteModelNotFoundError(Str.studly(name), value)\n bound[name] = found === undefined ? value : found\n continue\n }\n bound[name] = value\n }\n return bound\n}\n","import type { ModelNotFoundError, OrielError } from '@orieljs/contracts'\n\n/** No route matches the path (Symfony's NotFoundHttpException). */\nexport class NotFoundHttpError extends Error implements OrielError {\n readonly kind = 'Http' as const\n readonly status = 404\n override readonly name = 'NotFoundHttpError'\n constructor(path: string) {\n super(`The route ${path} could not be found.`)\n }\n}\n\n/** The path exists, but not for this method. */\nexport class MethodNotAllowedHttpError extends Error implements OrielError {\n readonly kind = 'Http' as const\n readonly status = 405\n readonly headers: Record<string, string>\n override readonly name = 'MethodNotAllowedHttpError'\n constructor(method: string, path: string, allowed: string[]) {\n super(`The ${method} method is not supported for route ${path}. Supported methods: ${allowed.join(', ')}.`)\n this.headers = { Allow: allowed.join(', ') }\n }\n}\n\n/** route('x') for a name no route has (Symfony's RouteNotFoundException). */\nexport class RouteNotDefinedError extends Error implements OrielError {\n readonly kind = 'Server' as const\n readonly status = 500\n override readonly name = 'RouteNotDefinedError'\n constructor(readonly routeName: string) {\n super(`Route [${routeName}] not defined.`)\n }\n}\n\n/** route('posts.show') without a required parameter. */\nexport class UrlGenerationError extends Error implements OrielError {\n readonly kind = 'Server' as const\n readonly status = 500\n override readonly name = 'UrlGenerationError'\n constructor(routeName: string, uri: string, missing: string[]) {\n super(`Missing required parameter for [Route: ${routeName}] [URI: ${uri}] [Missing parameter: ${missing.join(', ')}].`)\n }\n}\n\n/** Thrown by the router when a binding finds no row, so a missing model is always a 404. */\nexport class RouteModelNotFoundError extends Error implements ModelNotFoundError {\n readonly kind = 'ModelNotFound' as const\n readonly status = 404\n readonly ids: unknown[]\n override readonly name = 'RouteModelNotFoundError'\n constructor(readonly model: string, value: unknown) {\n super(`No query results for model [${model}] ${String(value)}`)\n this.ids = [value]\n }\n}\n\n/** Internal routing failures (a string action with no controller, a view route with no container, etc). */\nexport class RoutingError extends Error implements OrielError {\n readonly kind = 'Server' as const\n readonly status = 500\n override readonly name = 'RoutingError'\n}\n\n/** A signed URL whose signature is missing, wrong or expired (Laravel's InvalidSignatureException). */\nexport class InvalidUrlSignatureError extends Error implements OrielError {\n readonly kind = 'Http' as const\n readonly status = 403\n override readonly name = 'InvalidUrlSignatureError'\n constructor() {\n super('Invalid signature.')\n }\n}\n\n/** Too many requests in the window (Laravel's ThrottleRequestsException): 429 with Retry-After and X-RateLimit-*. */\nexport class ThrottleRequestsError extends Error implements OrielError {\n readonly kind = 'Http' as const\n readonly status = 429\n override readonly name = 'ThrottleRequestsError'\n constructor(readonly headers: Record<string, string> = {}) {\n super('Too Many Attempts.')\n }\n}\n","import {\n ExceptionHandler,\n PipelineFactory,\n type Container,\n type HttpRequest,\n type Middleware,\n type MiddlewareClass,\n type MiddlewareReference,\n type OrielError,\n} from '@orieljs/contracts'\nimport { RoutingError } from './errors'\nimport { toResponse } from './toResponse'\n\n/** A middleware reference after alias and group expansion: 'throttle:60,1' → { cls: Throttle, parameters: ['60', '1'] }. */\nexport interface ResolvedMiddleware {\n readonly cls: MiddlewareClass\n readonly parameters: readonly string[]\n}\n\n/** A string middleware that is neither an alias nor a group. */\nexport class MiddlewareNotFoundError extends Error implements OrielError {\n readonly kind = 'Server' as const\n readonly status = 500\n override readonly name = 'MiddlewareNotFoundError'\n constructor(readonly middleware: string) {\n super(\n `Middleware [${middleware}] is not defined. Register it with Route.aliasMiddleware() or ` +\n `withMiddleware((m) => m.alias({ ... })).`,\n )\n }\n}\n\nfunction expand(\n references: readonly MiddlewareReference[],\n aliases: Readonly<Record<string, MiddlewareClass>>,\n groups: Readonly<Record<string, readonly MiddlewareReference[]>>,\n visiting: Set<string>,\n out: ResolvedMiddleware[],\n): void {\n for (const reference of references) {\n if (typeof reference === 'function') {\n out.push({ cls: reference, parameters: [] })\n continue\n }\n const index = reference.indexOf(':')\n const name = index === -1 ? reference : reference.slice(0, index)\n const parameters = index === -1 ? [] : reference.slice(index + 1).split(',')\n if (index === -1 && Object.hasOwn(groups, name)) {\n if (visiting.has(name)) throw new RoutingError(`Middleware group [${name}] includes itself.`)\n visiting.add(name)\n expand(groups[name]!, aliases, groups, visiting, out)\n visiting.delete(name)\n continue\n }\n if (!Object.hasOwn(aliases, name)) throw new MiddlewareNotFoundError(reference)\n out.push({ cls: aliases[name]!, parameters })\n }\n}\n\n/**\n * Expands aliases and groups (recursively), drops anything `excluded` resolves to (withoutMiddleware), and\n * removes duplicates (same class and parameters), keeping the first occurrence like Laravel's uniqueMiddleware.\n */\nexport function resolveMiddleware(\n references: readonly MiddlewareReference[],\n excluded: readonly MiddlewareReference[],\n aliases: Readonly<Record<string, MiddlewareClass>>,\n groups: Readonly<Record<string, readonly MiddlewareReference[]>>,\n): ResolvedMiddleware[] {\n const all: ResolvedMiddleware[] = []\n expand(references, aliases, groups, new Set(), all)\n const skipped: ResolvedMiddleware[] = []\n expand(excluded, aliases, groups, new Set(), skipped)\n const skippedClasses = new Set(skipped.map((entry) => entry.cls))\n const seen = new Set<string>()\n const classIds = new Map<MiddlewareClass, number>()\n return all.filter((entry) => {\n if (skippedClasses.has(entry.cls)) return false\n if (!classIds.has(entry.cls)) classIds.set(entry.cls, classIds.size)\n const key = `${classIds.get(entry.cls)}:${entry.parameters.join(',')}`\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n}\n\n/**\n * Renders an error as a Response through the bound ExceptionHandler (reporting it first), like Laravel's\n * Routing\\Pipeline::handleException. Without a handler the error is rethrown.\n */\nexport async function renderError(container: Container, request: HttpRequest, error: unknown): Promise<Response> {\n if (!container.bound(ExceptionHandler)) throw error\n const handler = container.make(ExceptionHandler)\n await handler.report(error)\n return handler.render(request, error)\n}\n\nasync function guard(container: Container, request: HttpRequest, run: () => Promise<unknown>): Promise<Response> {\n try {\n const result = await run()\n return result instanceof Response ? result : await toResponse(request, result)\n } catch (error) {\n return renderError(container, request, error)\n }\n}\n\n/** An extra pipeline stage that runs before `middleware[at]` (route model binding uses it). */\nexport interface RouteStage {\n readonly at: number\n run(request: HttpRequest): Promise<void>\n}\n\ntype RoutePipe = (passable: HttpRequest, next: (passable: HttpRequest) => Promise<unknown>) => Promise<Response>\n\n/**\n * Sends the request through the middleware (built from `container`, the request scope) to `destination`.\n * Every stage converts its own errors into a response, so outer middleware always get a Response back.\n * Built instances are pushed onto `instances` (for terminate()). `stage`, when given, runs at its position.\n */\nexport async function runMiddleware(\n container: Container,\n request: HttpRequest,\n middleware: readonly ResolvedMiddleware[],\n instances: Middleware[],\n destination: (request: HttpRequest) => Promise<unknown>,\n stage?: RouteStage,\n): Promise<Response> {\n const pipes: RoutePipe[] = middleware.map(({ cls, parameters }) => {\n const instance = container.make(cls)\n instances.push(instance)\n return (passable, next) =>\n guard(container, passable, () => instance.handle(passable, next as (r: HttpRequest) => Promise<Response>, ...parameters))\n })\n if (stage !== undefined) {\n pipes.splice(stage.at, 0, (passable, next) =>\n guard(container, passable, async () => {\n await stage.run(passable)\n return next(passable)\n }),\n )\n }\n return container\n .make(PipelineFactory)\n .make<HttpRequest>()\n .send(request)\n .through(pipes)\n .then((passable) => guard(container, passable, () => destination(passable)))\n}\n","/** Laravel's Router::toResponse: turns whatever an action returned into a Response. */\nexport async function toResponse(request: unknown, value: unknown): Promise<Response> {\n if (value instanceof Response) return value\n if (value === null || value === undefined) return new Response(null, { status: 204 })\n if (typeof value === 'string') return html(value)\n if (typeof value !== 'object') return html(String(value))\n\n const candidate = value as Record<string, unknown>\n // Responsable (redirects, Inertia responses, …)\n if (typeof candidate.toResponse === 'function') {\n return toResponse(request, await (candidate.toResponse as (request: unknown) => unknown).call(value, request))\n }\n // Renderable (a View from ViewFactory.make())\n if (typeof candidate.render === 'function') return html(String(await (candidate.render as () => unknown).call(value)))\n // Htmlable\n if (typeof candidate.toHtml === 'function') return html(String((candidate.toHtml as () => unknown).call(value)))\n if (typeof candidate.toJSON !== 'function') {\n // Jsonable, then Arrayable\n if (typeof candidate.toJson === 'function') return json(String((candidate.toJson as () => unknown).call(value)))\n if (typeof candidate.toArray === 'function') return json(JSON.stringify((candidate.toArray as () => unknown).call(value)))\n }\n // Plain objects, arrays, models and collections (via toJSON)\n return json(JSON.stringify(value))\n}\n\nfunction html(body: string): Response {\n return new Response(body, { headers: { 'content-type': 'text/html; charset=utf-8' } })\n}\n\n/** Explicit header: Response.json() says 'application/json' on Node but adds ';charset=utf-8' on Bun. */\nfunction json(body: string): Response {\n return new Response(body, { headers: { 'content-type': 'application/json' } })\n}\n","import { CurrentRoute, type Class, type Container, type HttpRequest, type OrielError } from '@orieljs/contracts'\nimport { currentContainer } from '@orieljs/container'\nimport type { BaseRouter } from './BaseRouter'\nimport { orderForBindings, substituteBindings } from './bindings'\nimport { MethodNotAllowedHttpError, NotFoundHttpError, RoutingError } from './errors'\nimport { resolveMiddleware, runMiddleware } from './middleware'\nimport { normalizePath, type RouteDefinition } from './RouteDefinition'\n\n/** [Controller, 'missing'] (Laravel's BadMethodCallException). */\nexport class ControllerMethodNotFoundError extends Error implements OrielError {\n readonly kind = 'Server' as const\n readonly status = 500\n override readonly name = 'ControllerMethodNotFoundError'\n constructor(controller: string, method: string) {\n super(`Method ${controller}::${method} does not exist.`)\n }\n}\n\n// Duplicated in Pipeline's BasePipeline.ts on purpose: Http, Routing and Pipeline may not import each other.\nconst isClass = (value: unknown): value is Class<object> =>\n typeof value === 'function' && /^class[\\s{]/.test(Function.prototype.toString.call(value))\n\ntype Match = { route: RouteDefinition; values: Record<string, string | undefined> } | { response: Response }\n\nfunction findRoute(router: BaseRouter, request: HttpRequest): Match {\n const method = request.method().toUpperCase()\n const path = normalizePath(new URL(request.raw.url).pathname)\n const patterns = router.getPatterns()\n const version = router.getPatternVersion()\n const allowed = new Set<string>()\n for (const route of router.getRoutesByMatchOrder()) {\n const values = route.match(path, patterns, version)\n if (values === undefined) continue\n if (route.methods.includes(method)) return { route, values }\n // A fallback never turns an unknown POST into a 405.\n if (!route.isFallback) for (const verb of route.methods) allowed.add(verb)\n }\n if (allowed.size > 0) {\n // Laravel's automatic OPTIONS response.\n if (method === 'OPTIONS') return { response: new Response(null, { status: 200, headers: { Allow: [...allowed].join(', ') } }) }\n throw new MethodNotAllowedHttpError(method, request.path(), [...allowed])\n }\n throw new NotFoundHttpError(request.path())\n}\n\n/** Calls the route action with the parameters in URI order. Controllers are built by the request scope. */\nasync function runAction(scope: Container, route: RouteDefinition, parameters: Record<string, unknown>): Promise<unknown> {\n const args = route.parameters.map((parameter) => parameters[parameter.name])\n const action = route.action\n if (typeof action === 'function' && !isClass(action)) return (action as (...values: unknown[]) => unknown)(...args)\n const [cls, method] =\n typeof action === 'string'\n ? [route.controller as Class<object>, action]\n : isClass(action)\n ? [action, '__invoke']\n : [action[0] as Class<object>, String(action[1])]\n const controller = scope.make(cls) as Record<string, unknown>\n const handler = controller[method]\n if (typeof handler !== 'function') throw new ControllerMethodNotFoundError(cls.name, method)\n return (handler as (...values: unknown[]) => unknown).apply(controller, args)\n}\n\n/**\n * Router::dispatch: match, record the current route in the request scope, then run the route middleware and the\n * action. Matching errors (404/405) are thrown for the kernel's stage to render.\n */\nexport async function dispatchRoute(router: BaseRouter, request: HttpRequest, container?: Container): Promise<Response> {\n const scope = currentContainer() ?? container\n if (scope === undefined) throw new RoutingError('Cannot dispatch a request: no container is available.')\n const match = findRoute(router, request)\n if ('response' in match) return match.response\n const { route, values } = match\n\n const state: CurrentRoute = { route, parameters: { ...values }, middleware: [] }\n scope.instance(CurrentRoute, state)\n\n const middleware = resolveMiddleware(\n route.gatherMiddleware(),\n route.excludedMiddleware(),\n router.getMiddleware(),\n router.getMiddlewareGroups(),\n )\n const ordered = orderForBindings(router, middleware)\n return runMiddleware(scope, request, ordered.middleware, state.middleware, () => runAction(scope, route, state.parameters), {\n at: ordered.at,\n run: async () => void Object.assign(state.parameters, await substituteBindings(router, route, values, scope)),\n })\n}\n","import type { Class, MiddlewareReference, Route, RouteAction } from '@orieljs/contracts'\n\n/** A closure, a [Controller, 'method'] tuple, or a method name inside Route.controller(X).group(). */\nexport type RouteHandler = RouteAction | string\n\nexport interface RouteAttributes {\n /** The group's name prefix ('admin.'); name() appends to it. */\n namePrefix?: string\n /** Group middleware; the route's own middleware() is appended after it. */\n middleware?: MiddlewareReference[]\n /** The group controller that string actions call. */\n controller?: Class<unknown>\n fallback?: boolean\n}\n\nexport interface UriParameter {\n readonly name: string\n readonly optional: boolean\n /** The binding column from '{post:slug}'. */\n readonly field: string | undefined\n}\n\n/** Exported for the URL generator, which reuses these instead of redeclaring them. */\nexport const PARAMETER = /\\{(\\w+)(?::(\\w+))?(\\?)?\\}/g\nexport const WHOLE_OPTIONAL = /^\\{(\\w+)(?::\\w+)?\\?\\}$/\nconst escapeRegex = (value: string) => value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n\nexport function parseParameters(uri: string): UriParameter[] {\n return [...uri.matchAll(PARAMETER)].map((match) => ({ name: match[1]!, optional: match[3] === '?', field: match[2] }))\n}\n\n/** Laravel stores URIs without surrounding slashes, and '/' for the root. */\nexport function normalizeUri(uri: string): string {\n const trimmed = uri.replace(/^\\/+|\\/+$/g, '')\n return trimmed === '' ? '/' : trimmed\n}\n\n/** The form compiled patterns match against: '/posts/1/' → '/posts/1', '/' → ''. */\nexport function normalizePath(pathname: string): string {\n const trimmed = pathname.replace(/^\\/+|\\/+$/g, '').replace(/\\/{2,}/g, '/')\n return trimmed === '' ? '' : `/${trimmed}`\n}\n\nfunction decode(value: string): string {\n try {\n return decodeURIComponent(value)\n } catch {\n return value\n }\n}\n\n/** The pattern body (no anchors) for a normalised uri; '' for the root. */\nfunction compileBody(uri: string, wheres: Readonly<Record<string, string>>): string {\n if (uri === '/') return ''\n const group = (name: string) => `(?<p_${name}>${wheres[name] ?? '[^/]+'})`\n let body = ''\n for (const segment of uri.split('/')) {\n const whole = WHOLE_OPTIONAL.exec(segment)\n if (whole) {\n body += `(?:/${group(whole[1]!)})?`\n continue\n }\n let piece = ''\n let last = 0\n for (const match of segment.matchAll(PARAMETER)) {\n piece += escapeRegex(segment.slice(last, match.index)) + group(match[1]!) + (match[3] === '?' ? '?' : '')\n last = match.index + match[0].length\n }\n body += `/${piece}${escapeRegex(segment.slice(last))}`\n }\n return body\n}\n\nconst FALLBACK_SEGMENT = '{fallbackPlaceholder}'\n\n/**\n * Laravel's fallback is '{fallbackPlaceholder}' with where('.*') under the group prefix, so it stays scoped to it:\n * 'api/{fallbackPlaceholder}' matches /api and /api/any/depth but not /about; at the root it matches every path.\n */\nfunction compileFallback(uri: string, wheres: Readonly<Record<string, string>>): RegExp {\n const tail = '(?:/(?<p_fallbackPlaceholder>.*))?'\n if (uri === FALLBACK_SEGMENT) return new RegExp(`^${tail}$`, 's')\n if (!uri.endsWith(`/${FALLBACK_SEGMENT}`)) return new RegExp(`^${compileBody(uri, { ...wheres, fallbackPlaceholder: '.*' })}$`, 's')\n return new RegExp(`^${compileBody(uri.slice(0, -FALLBACK_SEGMENT.length - 1), wheres)}${tail}$`, 's')\n}\n\n/** Sort order for matching: fallbacks last, then per-segment specificity; ties keep registration order. */\nexport function compareRoutes(a: RouteDefinition, b: RouteDefinition): number {\n if (a.isFallback !== b.isFallback) return a.isFallback ? 1 : -1\n const left = a.rank()\n const right = b.rank()\n for (let i = 0; i < Math.max(left.length, right.length); i++) {\n const x = left[i] ?? -1\n const y = right[i] ?? -1\n if (x !== y) return x - y\n }\n return 0\n}\n\nexport class RouteDefinition implements Route {\n readonly methods: readonly string[]\n readonly uri: string\n readonly action: RouteHandler\n readonly controller: Class<unknown> | undefined\n readonly isFallback: boolean\n readonly parameters: readonly UriParameter[]\n #name: string | undefined\n readonly #middleware: MiddlewareReference[]\n readonly #excluded: MiddlewareReference[] = []\n readonly #wheres: Record<string, string> = {}\n #compiled: { regex: RegExp; version: number } | undefined\n\n constructor(methods: readonly string[], uri: string, action: RouteHandler, attributes: RouteAttributes = {}) {\n this.methods = [...new Set(methods.map((method) => method.toUpperCase()))]\n this.uri = normalizeUri(uri)\n this.action = action\n this.controller = attributes.controller\n this.isFallback = attributes.fallback ?? false\n this.parameters = parseParameters(this.uri)\n this.#name = attributes.namePrefix === undefined || attributes.namePrefix === '' ? undefined : attributes.namePrefix\n this.#middleware = [...(attributes.middleware ?? [])]\n }\n\n getName(): string | undefined {\n return this.#name\n }\n\n /** Appends, like Laravel's $action['as'] .= $name. */\n name(name: string): this {\n this.#name = (this.#name ?? '') + name\n return this\n }\n\n /** middleware('auth', 'verified') or middleware(['auth', 'verified']). */\n middleware(...middleware: Array<MiddlewareReference | readonly MiddlewareReference[]>): this {\n this.#middleware.push(...middleware.flat())\n return this\n }\n\n withoutMiddleware(...middleware: MiddlewareReference[]): this {\n this.#excluded.push(...middleware.flat())\n return this\n }\n\n where(parameter: string | Record<string, string>, pattern?: string): this {\n if (typeof parameter === 'string') this.#wheres[parameter] = pattern ?? '[^/]+'\n else Object.assign(this.#wheres, parameter)\n this.#compiled = undefined\n return this\n }\n\n /** Laravel's whereAlpha(): ASCII letters only. One parameter name or several. */\n whereAlpha(parameters: string | readonly string[]): this {\n return this.#assign(parameters, '[a-zA-Z]+')\n }\n\n /** Laravel's whereAlphaNumeric(): ASCII letters and digits. */\n whereAlphaNumeric(parameters: string | readonly string[]): this {\n return this.#assign(parameters, '[a-zA-Z0-9]+')\n }\n\n /** Laravel's whereNumber(): digits only. */\n whereNumber(parameters: string | readonly string[]): this {\n return this.#assign(parameters, '[0-9]+')\n }\n\n /** Laravel's whereUlid(): 26 Crockford base-32 characters, the first at most 7. */\n whereUlid(parameters: string | readonly string[]): this {\n return this.#assign(parameters, '[0-7][0-9a-hjkmnp-tv-zA-HJKMNP-TV-Z]{25}')\n }\n\n /** Laravel's whereUuid(): five groups of hex digits (8-4-4-4-12), any version. */\n whereUuid(parameters: string | readonly string[]): this {\n return this.#assign(parameters, '[\\\\da-fA-F]{8}-[\\\\da-fA-F]{4}-[\\\\da-fA-F]{4}-[\\\\da-fA-F]{4}-[\\\\da-fA-F]{12}')\n }\n\n /** Laravel's whereIn(): one of the values. Unlike Laravel, each value is matched literally (`c++` is not a pattern). */\n whereIn(parameters: string | readonly string[], values: ReadonlyArray<string | number>): this {\n const first = typeof parameters === 'string' ? parameters : parameters[0]\n if (values.length === 0 && first !== undefined) throw new Error(`Routing requirement for \"${first}\" cannot be empty.`)\n return this.#assign(parameters, values.map((value) => escapeRegex(String(value))).join('|'))\n }\n\n gatherMiddleware(): MiddlewareReference[] {\n return [...this.#middleware]\n }\n\n excludedMiddleware(): MiddlewareReference[] {\n return [...this.#excluded]\n }\n\n wheres(): Record<string, string> {\n return { ...this.#wheres }\n }\n\n getActionName(): string {\n if (typeof this.action === 'string') return `${this.controller?.name ?? 'Controller'}@${this.action}`\n if (Array.isArray(this.action)) return `${(this.action[0] as Class<unknown>).name}@${String(this.action[1])}`\n return 'Closure'\n }\n\n /** Decoded parameter values when `path` (normalizePath output) matches, else undefined. */\n match(\n path: string,\n patterns: Readonly<Record<string, string>> = {},\n version = 0,\n ): Record<string, string | undefined> | undefined {\n const found = this.#regex(patterns, version).exec(path)\n if (found === null) return undefined\n const values: Record<string, string | undefined> = {}\n for (const { name } of this.parameters) {\n const raw = found.groups?.[`p_${name}`]\n values[name] = raw === undefined ? undefined : decode(raw)\n }\n return values\n }\n\n /** Per-segment specificity: static 0, parameter 1, optional parameter 2. Lower sorts first. */\n rank(): number[] {\n if (this.uri === '/') return []\n return this.uri.split('/').map((segment) => (WHOLE_OPTIONAL.test(segment) ? 2 : segment.includes('{') ? 1 : 0))\n }\n\n #assign(parameters: string | readonly string[], pattern: string): this {\n const names: readonly string[] = typeof parameters === 'string' ? [parameters] : parameters\n return this.where(Object.fromEntries(names.map((name) => [name, pattern])))\n }\n\n #regex(patterns: Readonly<Record<string, string>>, version: number): RegExp {\n if (this.#compiled !== undefined && this.#compiled.version === version) return this.#compiled.regex\n const wheres = { ...patterns, ...this.#wheres }\n const regex = this.isFallback ? compileFallback(this.uri, wheres) : new RegExp(`^${compileBody(this.uri, wheres)}$`)\n this.#compiled = { regex, version }\n return regex\n }\n}\n","import type { Class, ControllerAction, InvokableClass, MiddlewareReference, ResourceOptions, RouteClosure, RouteRegistrar } from '@orieljs/contracts'\nimport type { RouteDefinition, RouteHandler } from './RouteDefinition'\n\n/** Attributes shared by the routes of a group (Laravel's group attribute array). */\nexport interface GroupAttributes {\n prefix?: string\n /** Name prefix ('admin.'). */\n as?: string\n middleware?: MiddlewareReference[]\n controller?: Class<unknown>\n}\n\n/** What a GroupRegistrar needs from the router. */\nexport interface GroupHost {\n group(attributes: GroupAttributes, routes: () => void | Promise<void>): Promise<void>\n addRoute(methods: readonly string[], uri: string, action: RouteHandler): RouteDefinition\n resource(name: string, controller: Class<unknown>, options?: ResourceOptions): void\n apiResource(name: string, controller: Class<unknown>, options?: ResourceOptions): void\n}\n\n/** Every HTTP verb a route can respond to. BaseRouter reuses this instead of redeclaring it. */\nexport const ALL_VERBS = ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']\n\n/** Merges a nested group's attributes into its parent's, like Laravel's RouteGroup::merge. */\nexport function mergeGroup(parent: GroupAttributes, child: GroupAttributes): GroupAttributes {\n const prefix = [parent.prefix, child.prefix]\n .map((part) => (part ?? '').replace(/^\\/+|\\/+$/g, ''))\n .filter((part) => part !== '')\n .join('/')\n const merged: GroupAttributes = {\n middleware: [...(parent.middleware ?? []), ...(child.middleware ?? [])],\n }\n if (prefix !== '') merged.prefix = prefix\n const as = (parent.as ?? '') + (child.as ?? '')\n if (as !== '') merged.as = as\n const controller = child.controller ?? parent.controller\n if (controller !== undefined) merged.controller = controller\n return merged\n}\n\n/**\n * Route.prefix('admin').name('admin.').middleware('auth').group(() => …), and the one-route form\n * Route.middleware('auth').get('/x', action) (Laravel's RouteRegistrar).\n */\nexport class GroupRegistrar implements RouteRegistrar {\n readonly #attributes: GroupAttributes = {}\n\n constructor(private readonly router: GroupHost) {}\n\n prefix(prefix: string): this {\n this.#attributes.prefix = prefix\n return this\n }\n\n name(prefix: string): this {\n this.#attributes.as = prefix\n return this\n }\n\n middleware(...middleware: Array<MiddlewareReference | readonly MiddlewareReference[]>): this {\n this.#attributes.middleware = [...(this.#attributes.middleware ?? []), ...middleware.flat()]\n return this\n }\n\n controller(controller: Class<unknown>): this {\n this.#attributes.controller = controller\n return this\n }\n\n group(routes: () => void | Promise<void>): Promise<void> {\n return this.router.group({ ...this.#attributes }, routes)\n }\n\n get<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.#one(['GET', 'HEAD'], uri, action)\n }\n\n post<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.#one(['POST'], uri, action)\n }\n\n put<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.#one(['PUT'], uri, action)\n }\n\n patch<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.#one(['PATCH'], uri, action)\n }\n\n delete<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.#one(['DELETE'], uri, action)\n }\n\n options<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.#one(['OPTIONS'], uri, action)\n }\n\n any<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.#one(ALL_VERBS, uri, action)\n }\n\n match<C>(methods: string[], uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition {\n return this.#one(methods, uri, action)\n }\n\n resource(name: string, controller: Class<unknown>, options?: ResourceOptions): void {\n void this.router.group({ ...this.#attributes }, () => this.router.resource(name, controller, options))\n }\n\n apiResource(name: string, controller: Class<unknown>, options?: ResourceOptions): void {\n void this.router.group({ ...this.#attributes }, () => this.router.apiResource(name, controller, options))\n }\n\n #one(methods: readonly string[], uri: string, action: RouteHandler): RouteDefinition {\n let route: RouteDefinition | undefined\n void this.router.group({ ...this.#attributes }, () => {\n route = this.router.addRoute(methods, uri, action)\n })\n return route!\n }\n}\n","import type { ResourceOptions } from '@orieljs/contracts'\nimport { Str } from '@orieljs/support'\n\nexport type ResourceMethod = 'index' | 'create' | 'store' | 'show' | 'edit' | 'update' | 'destroy'\n\nexport interface ResourceRoute {\n readonly method: ResourceMethod\n readonly verbs: readonly string[]\n readonly uri: string\n readonly name: string\n}\n\n/** Laravel's order (ResourceRegistrar::$resourceDefaults). */\nconst DEFAULTS: readonly ResourceMethod[] = ['index', 'create', 'store', 'show', 'edit', 'update', 'destroy']\nconst API_DEFAULTS: readonly ResourceMethod[] = ['index', 'store', 'show', 'update', 'destroy']\n\n/** 'blog-posts' → 'blog_post' (Laravel's getResourceWildcard), unless options.parameters renames it. */\nfunction wildcard(segment: string, options: ResourceOptions): string {\n const renamed = options.parameters?.[segment]\n return (renamed ?? Str.singular(segment)).replace(/-/g, '_')\n}\n\n/**\n * The routes Route.resource()/apiResource() register. 'photos.comments' nests:\n * photos/{photo}/comments/{comment}, named photos.comments.*.\n */\nexport function resourceRoutes(name: string, options: ResourceOptions = {}, api = false): ResourceRoute[] {\n const segments = name.split('.')\n const last = segments.at(-1)!\n const base = [...segments.slice(0, -1).map((segment) => `${segment}/{${wildcard(segment, options)}}`), last].join('/')\n const member = `${base}/{${wildcard(last, options)}}`\n\n let methods = api ? API_DEFAULTS : DEFAULTS\n if (options.only !== undefined) methods = methods.filter((method) => options.only!.includes(method))\n if (options.except !== undefined) methods = methods.filter((method) => !options.except!.includes(method))\n\n const table: Record<ResourceMethod, { verbs: string[]; uri: string }> = {\n index: { verbs: ['GET', 'HEAD'], uri: base },\n create: { verbs: ['GET', 'HEAD'], uri: `${base}/create` },\n store: { verbs: ['POST'], uri: base },\n show: { verbs: ['GET', 'HEAD'], uri: member },\n edit: { verbs: ['GET', 'HEAD'], uri: `${member}/edit` },\n update: { verbs: ['PUT', 'PATCH'], uri: member },\n destroy: { verbs: ['DELETE'], uri: member },\n }\n return methods.map((method) => ({\n method,\n verbs: table[method].verbs,\n uri: table[method].uri,\n name: options.names?.[method] ?? `${name}.${method}`,\n }))\n}\n","import { createHmac, timingSafeEqual } from 'node:crypto'\nimport { ConfigRepository, Encrypter, HttpRequest, Session, type Container, type UrlGenerator } from '@orieljs/contracts'\nimport { currentContainer } from '@orieljs/container'\nimport type { BaseRouter } from './BaseRouter'\nimport { RouteNotDefinedError, RoutingError, UrlGenerationError } from './errors'\nimport { PARAMETER, WHOLE_OPTIONAL } from './RouteDefinition'\n\nconst VALID_URL = /^(#|\\/\\/|https?:\\/\\/|(mailto|tel|sms):)/i\n\n// Duplicated in Http's input.ts on purpose: Http, Routing and Pipeline may not import each other.\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false\n const prototype = Object.getPrototypeOf(value) as unknown\n return prototype === Object.prototype || prototype === null\n}\n\n/** PHP's http_build_query: nested objects and arrays become a[b]=1&a[0]=2; null/undefined are skipped. */\nexport function buildQuery(values: Record<string, unknown>): string {\n const pairs: string[] = []\n const add = (key: string, value: unknown): void => {\n if (value === null || value === undefined) return\n if (typeof value === 'object' && (Array.isArray(value) || isPlainObject(value))) {\n for (const [child, nested] of Object.entries(value)) add(`${key}[${child}]`, nested)\n return\n }\n const text = value === true ? '1' : value === false ? '0' : String(value)\n pairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(text)}`)\n }\n for (const [key, value] of Object.entries(values)) add(key, value)\n return pairs.join('&')\n}\n\n/** A model's URL value: the {post:slug} field when given, else getRouteKey(), else the value itself. */\nfunction routeKey(value: unknown, field: string | undefined): unknown {\n if (typeof value !== 'object' || value === null) return value\n const model = value as { getRouteKey?: () => unknown; getAttribute?: (key: string) => unknown } & Record<string, unknown>\n if (field !== undefined) return typeof model.getAttribute === 'function' ? model.getAttribute(field) : model[field]\n return typeof model.getRouteKey === 'function' ? model.getRouteKey() : value\n}\n\n/** HMAC-SHA256 of a URL, hex (Laravel's hash_hmac('sha256', $url, $key)). */\nfunction sign(url: string, key: Uint8Array): string {\n return createHmac('sha256', key).update(url).digest('hex')\n}\n\n/** Constant-time string comparison. */\nfunction safeEquals(expected: string, given: string): boolean {\n const a = Buffer.from(expected)\n const b = Buffer.from(given)\n return a.length === b.length && timingSafeEqual(a, b)\n}\n\n/** Unix seconds: a Date, or a number of seconds from now (Laravel's availableAt()). */\nfunction availableAt(expiration: Date | number): number {\n return expiration instanceof Date ? Math.floor(expiration.getTime() / 1000) : Math.floor(Date.now() / 1000) + expiration\n}\n\n/** Laravel's UrlGenerator. The root is the current request's origin, else config('app.url'). */\nexport class BaseUrlGenerator implements UrlGenerator {\n constructor(\n private readonly router: BaseRouter,\n private readonly container?: Container,\n ) {}\n\n /** 'http://localhost' (no trailing slash). */\n root(): string {\n const request = this.#request()\n if (request !== undefined) return new URL(request.url()).origin\n const configured = this.#config<string | undefined>('app.url', undefined)\n return (configured ?? 'http://localhost').replace(/\\/+$/, '')\n }\n\n to(path: string, query: Record<string, unknown> = {}, absolute = true): string {\n const queryString = buildQuery(query)\n const base = VALID_URL.test(path) ? path : this.#join(path, absolute)\n if (queryString === '') return base\n return `${base}${base.includes('?') ? '&' : '?'}${queryString}`\n }\n\n /**\n * route('posts.show', post) / route('posts.show', [post, comment]) / route('posts.show', { post: 1, page: 2 }).\n * Named values fill their parameters, positional values fill the rest in URI order; extra named values become\n * the query string, extra positional ones are dropped.\n */\n route(name: string, parameters?: unknown, absolute = true): string {\n const route = this.router.getByName(name)\n if (route === undefined) throw new RouteNotDefinedError(name)\n const named: Record<string, unknown> = isPlainObject(parameters) ? { ...parameters } : {}\n const positional: unknown[] = Array.isArray(parameters)\n ? [...parameters]\n : parameters === undefined || parameters === null || isPlainObject(parameters)\n ? []\n : [parameters]\n\n const values = new Map<string, string | undefined>()\n const missing: string[] = []\n for (const parameter of route.parameters) {\n let value: unknown\n if (Object.hasOwn(named, parameter.name)) {\n value = named[parameter.name]\n delete named[parameter.name]\n } else if (positional.length > 0) {\n value = positional.shift()\n }\n const key = routeKey(value, parameter.field)\n const text = key === undefined || key === null ? undefined : String(key)\n if (text === undefined && !parameter.optional) missing.push(parameter.name)\n values.set(parameter.name, text)\n }\n if (missing.length > 0) throw new UrlGenerationError(name, route.uri, missing)\n\n const path =\n route.uri === '/'\n ? ''\n : route.uri\n .split('/')\n .filter((segment) => {\n const whole = WHOLE_OPTIONAL.exec(segment)\n return whole === null || values.get(whole[1]!) !== undefined\n })\n .map((segment) =>\n segment.replace(PARAMETER, (_match, parameter: string) => {\n const value = values.get(parameter)\n return value === undefined ? '' : encodeURIComponent(value)\n }),\n )\n .join('/')\n const query = Object.fromEntries(Object.entries(named).map(([key, value]) => [key, routeKey(value, undefined)]))\n return this.to(path, query, absolute)\n }\n\n asset(path: string): string {\n if (VALID_URL.test(path)) return path\n const base = this.#config<string | undefined>('app.asset_url', undefined)?.replace(/\\/+$/, '') ?? this.root()\n const trimmed = path.replace(/^\\/+/, '')\n return trimmed === '' ? base : `${base}/${trimmed}`\n }\n\n /** The current URL without the query string. */\n current(): string {\n return this.#request()?.url() ?? this.root()\n }\n\n /** The current URL with the query string. */\n full(): string {\n return this.#request()?.fullUrl() ?? this.root()\n }\n\n /** The Referer header, then the session's previous URL, then `fallback`, then the root (Laravel's order). */\n previous(fallback?: string): string {\n const scope = this.#scope()\n const request = this.#request()\n const referer = request?.header('referer')\n if (referer !== undefined && referer !== '') return this.to(referer)\n if (request !== undefined && scope?.bound(Session)) {\n const previous = scope.make(Session).previousUrl()\n if (previous !== undefined && previous !== '') return this.to(previous)\n }\n return this.to(fallback ?? '/')\n }\n\n hasRoute(name: string): boolean {\n return this.router.getByName(name) !== undefined\n }\n\n /**\n * Laravel's URL::signedRoute(): the route URL with its parameters sorted by name, then a `signature` query (the\n * HMAC-SHA256 of that URL, keyed by APP_KEY). `expiration` (a Date, or seconds from now) adds `expires`.\n * `absolute: false` signs the path only (checked by `signed:relative`).\n */\n signedRoute(name: string, parameters?: unknown, expiration?: Date | number, absolute = true): string {\n const named = this.#namedParameters(name, parameters)\n for (const reserved of ['signature', 'expires']) {\n if (Object.hasOwn(named, reserved)) {\n throw new RoutingError(`\"${reserved}\" is a reserved parameter when generating signed routes. Please rename your route parameter.`)\n }\n }\n if (expiration !== undefined) named.expires = availableAt(expiration)\n const sorted = Object.fromEntries(Object.keys(named).sort().map((key) => [key, named[key]]))\n const signature = sign(this.route(name, sorted, absolute), this.#signingKeys()[0]!)\n return this.route(name, { ...sorted, signature }, absolute)\n }\n\n /** Laravel's URL::temporarySignedRoute(): a signed URL that expires at `expiration` (a Date, or seconds from now). */\n temporarySignedRoute(name: string, expiration: Date | number, parameters?: unknown, absolute = true): string {\n return this.signedRoute(name, parameters, expiration, absolute)\n }\n\n /** The request URL carries a correct signature (current or previous APP_KEY) that hasn't expired. */\n hasValidSignature(request: HttpRequest, absolute = true): boolean {\n return this.hasCorrectSignature(request, absolute) && this.signatureHasNotExpired(request)\n }\n\n /** The signature matches the URL without its `signature` query, in a constant-time comparison. */\n hasCorrectSignature(request: HttpRequest, absolute = true): boolean {\n const full = new URL(request.fullUrl())\n const path = request.path()\n const url = absolute ? request.url() : path === '/' ? '/' : `/${path}`\n const query = full.search\n .slice(1)\n .split('&')\n .filter((pair) => pair !== '' && pair.split('=')[0] !== 'signature')\n .join('&')\n const original = query === '' ? url : `${url}?${query}`\n const given = full.searchParams.get('signature') ?? ''\n return this.#signingKeys().some((key) => safeEquals(sign(original, key), given))\n }\n\n /** No `expires` query, or one that is still in the future. */\n signatureHasNotExpired(request: HttpRequest): boolean {\n const expires = new URL(request.fullUrl()).searchParams.get('expires')\n if (expires === null || expires === '') return true\n const at = Number(expires)\n return Number.isFinite(at) && Math.floor(Date.now() / 1000) <= at\n }\n\n /** Named parameters: an object as is, positional values (a list or one value) by the route's parameter names. */\n #namedParameters(name: string, parameters: unknown): Record<string, unknown> {\n if (isPlainObject(parameters)) return { ...parameters }\n const route = this.router.getByName(name)\n if (route === undefined) throw new RouteNotDefinedError(name)\n const values = parameters === undefined || parameters === null ? [] : Array.isArray(parameters) ? parameters : [parameters]\n const named: Record<string, unknown> = {}\n route.parameters.forEach((parameter, index) => {\n if (index < values.length) named[parameter.name] = values[index]\n })\n return named\n }\n\n /** The Encrypter's key, then its previous keys (config app.previous_keys), so rotated keys still verify. */\n #signingKeys(): Uint8Array[] {\n const scope = this.#scope()\n if (scope === undefined || !scope.bound(Encrypter)) {\n throw new RoutingError('Signed URLs need the Encrypter: set APP_KEY (oriel key:generate).')\n }\n const encrypter = scope.make(Encrypter) as Encrypter & { getAllKeys?(): Uint8Array[] }\n return typeof encrypter.getAllKeys === 'function' ? encrypter.getAllKeys() : [encrypter.getKey()]\n }\n\n #join(path: string, absolute: boolean): string {\n const trimmed = path.replace(/^\\/+|\\/+$/g, '')\n if (!absolute) return `/${trimmed}`\n return trimmed === '' ? this.root() : `${this.root()}/${trimmed}`\n }\n\n #scope(): Container | undefined {\n return currentContainer() ?? this.container\n }\n\n /** The HttpRequest, only when running inside a request scope. */\n #request(): HttpRequest | undefined {\n const scope = this.#scope()\n return scope?.bound(HttpRequest) ? scope.make(HttpRequest) : undefined\n }\n\n #config<T>(key: string, fallback: T): T {\n const scope = this.#scope()\n return scope?.bound(ConfigRepository) ? scope.make(ConfigRepository).get<T>(key, fallback) : fallback\n }\n}\n","import { Router, type Abstract } from '@orieljs/contracts'\nimport { facade } from '@orieljs/support'\nimport type { BaseRouter } from './BaseRouter'\n\n/**\n * The Route facade: Route.get('/', …), Route.prefix('admin').group(…), Route.resource(…). Typed as the BaseRouter\n * so the extras (permanentRedirect, patterns, has, currentRouteName, …) are available too.\n */\nexport const Route = facade<BaseRouter>(Router as Abstract<BaseRouter>)\n","import { ConfigRepository, EventDispatcher, ExceptionHandler, type Container } from '@orieljs/contracts'\n\n/**\n * Dispatched by the health route (`/up`) on every request (Laravel's DiagnosingHealth event). A listener checks\n * something the application needs, such as the database or the cache, and throws when it fails: `/up` then answers\n * 500 with \"Application experiencing problems\", and the exception is reported.\n *\n * Event.listen(DiagnosingHealth, async () => { await DB.select('select 1') })\n */\nexport class DiagnosingHealth {}\n\nexport interface HealthPage {\n /** False when a check failed: the page says so and the status is 500 (default true). */\n healthy?: boolean\n /** How long the request took, shown when given. */\n milliseconds?: number\n /** The page title (default \"Oriel\"). */\n appName?: string\n}\n\nconst escapeHtml = (value: string): string => value.replace(/[&<>\"']/g, (char) => `&#${char.charCodeAt(0)};`)\n\n// The Oriel style: dark canvas, one Graphite block, the system fonts, flat. Green and red are the status dot only.\nconst STYLE =\n ':root{color-scheme:dark}*{box-sizing:border-box;margin:0}html{background:#05050b}' +\n 'body{min-height:100vh;display:grid;place-items:center;padding:20px;background:#1a1a1a;color:#fff;' +\n 'font:400 16px/1.7 system-ui,-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,sans-serif}' +\n 'main{display:flex;align-items:center;gap:20px;width:100%;max-width:640px;padding:20px 32px;border-radius:18px;background:#212121}' +\n '.dot{flex:none;width:12px;height:12px;border-radius:50%;background:#74ec5a}.dot.down{background:#ff3543}' +\n 'h1{font-size:21px;line-height:1.4;font-weight:600}p{color:#a3a3a3}.time{color:#ba94ff}'\n\n/**\n * The health route's page (Laravel's health-up view): \"Application up\", or \"Application experiencing problems\" with\n * status 500. Self-contained HTML with inline CSS: it loads nothing, so it answers even when the assets don't.\n */\nexport function healthResponse(page: HealthPage = {}): Response {\n const healthy = page.healthy ?? true\n const time = page.milliseconds === undefined ? '' : ` Response rendered in <span class=\"time\">${Math.round(page.milliseconds)} ms</span>.`\n const html =\n '<!DOCTYPE html>\\n<html lang=\"en\">\\n<head>\\n<meta charset=\"utf-8\">\\n' +\n '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\\n' +\n `<title>${escapeHtml(page.appName ?? 'Oriel')}</title>\\n<style>${STYLE}</style>\\n</head>\\n<body>\\n<main>\\n` +\n `<span class=\"${healthy ? 'dot' : 'dot down'}\" aria-hidden=\"true\"></span>\\n` +\n `<div>\\n<h1>Application ${healthy ? 'up' : 'experiencing problems'}</h1>\\n<p>HTTP request received.${time}</p>\\n</div>\\n` +\n '</main>\\n</body>\\n</html>\\n'\n return new Response(html, { status: healthy ? 200 : 500, headers: { 'content-type': 'text/html; charset=utf-8' } })\n}\n\n/**\n * The `/up` action: dispatches DiagnosingHealth, then renders the page. A listener's exception is rethrown in debug\n * mode (the error page shows it); otherwise it is reported, and the page answers 500 without its message.\n */\nexport async function diagnoseHealth(app: Container): Promise<Response> {\n const started = performance.now()\n const config = app.bound(ConfigRepository) ? app.make(ConfigRepository) : undefined\n let healthy = true\n try {\n if (app.bound(EventDispatcher)) await app.make(EventDispatcher).dispatch(new DiagnosingHealth())\n } catch (error) {\n if (config?.get<unknown>('app.debug', false) === true) throw error\n if (app.bound(ExceptionHandler)) await app.make(ExceptionHandler).report(error)\n healthy = false\n }\n const appName = String(config?.get('app.name', 'Oriel') ?? 'Oriel')\n return healthResponse({ healthy, appName, milliseconds: performance.now() - started })\n}\n","import { pathToFileURL } from 'node:url'\nimport type { Application, Router } from '@orieljs/contracts'\n\n/** A route file may export a function instead of (or as well as) calling the Route facade at the top level. */\nexport type RouteFileCallback = (router: Router) => void | Promise<void>\n\nlet generation = 0\n\n/**\n * Imports a route file inside app.run(), so the Route facade in it resolves this application. Each load adds a\n * fresh `?oriel-routes=<n>` query: ESM caches modules, and a fresh app per test must register its routes again.\n * A default export that is a function is called with the router.\n */\nexport async function loadRoutesFrom(app: Application, router: Router, file: string): Promise<void> {\n const url = `${pathToFileURL(file).href}?oriel-routes=${++generation}`\n const module = (await app.run(() => import(/* @vite-ignore */ url))) as { default?: unknown }\n if (typeof module.default === 'function') await app.run(() => (module.default as RouteFileCallback)(router))\n}\n\n","import { Router, RoutingPaths, UrlGenerator } from '@orieljs/contracts'\nimport { ServiceProvider } from '@orieljs/support'\nimport { BaseRouter } from './BaseRouter'\nimport { BaseUrlGenerator } from './BaseUrlGenerator'\nimport { RoutingError } from './errors'\nimport { diagnoseHealth } from './health'\nimport { loadRoutesFrom } from './routeFiles'\nimport { ThrottleRequests } from './ThrottleRequests'\nimport { ValidateSignature } from './ValidateSignature'\n\n/**\n * Binds the Router and the UrlGenerator, registers the `signed` and `throttle` middleware, and once the app has booted\n * loads the files given to withRouting(): the health URI (which dispatches DiagnosingHealth), then the web files in the\n * `web` middleware group, then the api files under the api prefix in the `api` group (Laravel's\n * ApplicationBuilder::withRouting).\n */\nexport class RoutingServiceProvider extends ServiceProvider {\n override register(): void {\n this.app.singleton(Router, () => new BaseRouter(this.app))\n this.app.singleton(UrlGenerator, () => {\n const router = this.app.make(Router)\n if (!(router instanceof BaseRouter)) {\n throw new RoutingError('The UrlGenerator needs the BaseRouter: the bound Router was replaced by another implementation.')\n }\n return new BaseUrlGenerator(router, this.app)\n })\n }\n\n /**\n * The files load in a booted() callback, after every provider's boot() (Laravel's withRouting does the same), so\n * what the app's own providers set up at boot (Route.pattern/bind/model, gates, shared view data) is in place\n * when the route files run.\n */\n override boot(): void {\n this.app.make(Router).aliasMiddleware('signed', ValidateSignature).aliasMiddleware('throttle', ThrottleRequests)\n this.app.booted(async () => {\n if (!this.app.bound(RoutingPaths)) return\n const { web, api, health, apiPrefix } = this.app.make(RoutingPaths)\n const router = this.app.make(Router)\n if (health !== undefined) router.get(health, () => diagnoseHealth(this.app))\n if (web !== undefined) await router.middleware('web').group(() => this.#load(router, web))\n if (api !== undefined) await router.prefix(apiPrefix).middleware('api').group(() => this.#load(router, api))\n })\n }\n\n /** One file or several, in order: each is imported afresh for this application (a nested import is not). */\n async #load(router: Router, files: string | string[]): Promise<void> {\n for (const file of [files].flat()) await loadRoutesFrom(this.app, router, file)\n }\n}\n","import { createHash } from 'node:crypto'\nimport { RateLimiter, type HttpRequest, type Middleware, type Next } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport { RoutingError, ThrottleRequestsError } from './errors'\n\nconst sha1 = (value: string): string => createHash('sha1').update(value).digest('hex')\n\n/** Sets headers, copying the response first when its headers are immutable (Response.redirect()). */\nfunction withHeaders(response: Response, headers: Record<string, string>): Response {\n try {\n for (const [name, value] of Object.entries(headers)) response.headers.set(name, value)\n return response\n } catch {\n const copy = new Headers(response.headers)\n for (const [name, value] of Object.entries(headers)) copy.set(name, value)\n return new Response(response.body, { status: response.status, statusText: response.statusText, headers: copy })\n }\n}\n\n/**\n * Laravel's ThrottleRequests (`throttle:<maxAttempts>,<decayMinutes>[,<prefix>]`): counts the client's requests\n * (the signed-in user, else the IP) in a window and answers 429 once there are too many. Responses carry\n * X-RateLimit-Limit and X-RateLimit-Remaining; the 429 adds Retry-After and X-RateLimit-Reset.\n */\nexport class ThrottleRequests implements Middleware {\n async handle(request: HttpRequest, next: Next, maxAttempts = '60', decayMinutes = '1', prefix = ''): Promise<Response> {\n const max = Number(maxAttempts)\n const decay = Number(decayMinutes)\n if (maxAttempts.trim() === '' || !Number.isInteger(max) || max < 0 || decayMinutes.trim() === '' || !Number.isFinite(decay) || decay <= 0) {\n throw new RoutingError(\n `Invalid throttle parameters \"${maxAttempts},${decayMinutes}\": use throttle:<maxAttempts>,<decayMinutes>[,<prefix>] (named rate limiters are not supported).`,\n )\n }\n const limiter = inject(RateLimiter)\n const key = prefix + (await this.resolveRequestSignature(request))\n if (await limiter.tooManyAttempts(key, max)) {\n const retryAfter = await limiter.availableIn(key)\n throw new ThrottleRequestsError({\n 'X-RateLimit-Limit': String(max),\n 'X-RateLimit-Remaining': '0',\n 'Retry-After': String(retryAfter),\n 'X-RateLimit-Reset': String(Math.floor(Date.now() / 1000) + retryAfter),\n })\n }\n await limiter.hit(key, Math.round(decay * 60))\n const response = await next(request)\n return withHeaders(response, {\n 'X-RateLimit-Limit': String(max),\n 'X-RateLimit-Remaining': String(await limiter.remaining(key, max)),\n })\n }\n\n /** The signed-in user's identifier, else the client IP, hashed (Laravel's resolveRequestSignature()). */\n protected async resolveRequestSignature(request: HttpRequest): Promise<string> {\n const user = await request.user<{ getAuthIdentifier?(): unknown }>()\n if (user !== undefined && user !== null && typeof user.getAuthIdentifier === 'function') {\n return sha1(String(user.getAuthIdentifier()))\n }\n return sha1(`|${request.ip() ?? ''}`)\n }\n}\n","import { UrlGenerator, type HttpRequest, type Middleware, type Next } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport { InvalidUrlSignatureError } from './errors'\n\n/**\n * Laravel's ValidateSignature (`signed`, `signed:relative`): the request URL must carry a valid, unexpired\n * signature from URL.signedRoute()/temporarySignedRoute(), else 403. `relative` checks a path-only signature.\n */\nexport class ValidateSignature implements Middleware {\n async handle(request: HttpRequest, next: Next, ...parameters: string[]): Promise<Response> {\n const absolute = parameters[0] !== 'relative'\n if (inject(UrlGenerator).hasValidSignature(request, absolute)) return next(request)\n throw new InvalidUrlSignatureError()\n }\n}\n"],"mappings":";AAAA;AAAA,EACE,gBAAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAYK;AACP,SAAS,oBAAAC,yBAAwB;;;ACjBjC,SAAS,0BAAgE;AACzE,SAAS,8BAA8B;AACvC,SAAS,WAAW;;;ACCb,IAAM,oBAAN,cAAgC,MAA4B;AAAA,EACxD,OAAO;AAAA,EACP,SAAS;AAAA,EACA,OAAO;AAAA,EACzB,YAAY,MAAc;AACxB,UAAM,aAAa,IAAI,sBAAsB;AAAA,EAC/C;AACF;AAGO,IAAM,4BAAN,cAAwC,MAA4B;AAAA,EAChE,OAAO;AAAA,EACP,SAAS;AAAA,EACT;AAAA,EACS,OAAO;AAAA,EACzB,YAAY,QAAgB,MAAc,SAAmB;AAC3D,UAAM,OAAO,MAAM,sCAAsC,IAAI,wBAAwB,QAAQ,KAAK,IAAI,CAAC,GAAG;AAC1G,SAAK,UAAU,EAAE,OAAO,QAAQ,KAAK,IAAI,EAAE;AAAA,EAC7C;AACF;AAGO,IAAM,uBAAN,cAAmC,MAA4B;AAAA,EAIpE,YAAqB,WAAmB;AACtC,UAAM,UAAU,SAAS,gBAAgB;AADtB;AAAA,EAErB;AAAA,EAFqB;AAAA,EAHZ,OAAO;AAAA,EACP,SAAS;AAAA,EACA,OAAO;AAI3B;AAGO,IAAM,qBAAN,cAAiC,MAA4B;AAAA,EACzD,OAAO;AAAA,EACP,SAAS;AAAA,EACA,OAAO;AAAA,EACzB,YAAY,WAAmB,KAAa,SAAmB;AAC7D,UAAM,0CAA0C,SAAS,WAAW,GAAG,yBAAyB,QAAQ,KAAK,IAAI,CAAC,IAAI;AAAA,EACxH;AACF;AAGO,IAAM,0BAAN,cAAsC,MAAoC;AAAA,EAK/E,YAAqB,OAAe,OAAgB;AAClD,UAAM,+BAA+B,KAAK,KAAK,OAAO,KAAK,CAAC,EAAE;AAD3C;AAEnB,SAAK,MAAM,CAAC,KAAK;AAAA,EACnB;AAAA,EAHqB;AAAA,EAJZ,OAAO;AAAA,EACP,SAAS;AAAA,EACT;AAAA,EACS,OAAO;AAK3B;AAGO,IAAM,eAAN,cAA2B,MAA4B;AAAA,EACnD,OAAO;AAAA,EACP,SAAS;AAAA,EACA,OAAO;AAC3B;AAGO,IAAM,2BAAN,cAAuC,MAA4B;AAAA,EAC/D,OAAO;AAAA,EACP,SAAS;AAAA,EACA,OAAO;AAAA,EACzB,cAAc;AACZ,UAAM,oBAAoB;AAAA,EAC5B;AACF;AAGO,IAAM,wBAAN,cAAoC,MAA4B;AAAA,EAIrE,YAAqB,UAAkC,CAAC,GAAG;AACzD,UAAM,oBAAoB;AADP;AAAA,EAErB;AAAA,EAFqB;AAAA,EAHZ,OAAO;AAAA,EACP,SAAS;AAAA,EACA,OAAO;AAI3B;;;ACjFA;AAAA,EACE;AAAA,EACA;AAAA,OAOK;;;ACRP,eAAsB,WAAW,SAAkB,OAAmC;AACpF,MAAI,iBAAiB,SAAU,QAAO;AACtC,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,IAAI,CAAC;AACpF,MAAI,OAAO,UAAU,SAAU,QAAO,KAAK,KAAK;AAChD,MAAI,OAAO,UAAU,SAAU,QAAO,KAAK,OAAO,KAAK,CAAC;AAExD,QAAM,YAAY;AAElB,MAAI,OAAO,UAAU,eAAe,YAAY;AAC9C,WAAO,WAAW,SAAS,MAAO,UAAU,WAA6C,KAAK,OAAO,OAAO,CAAC;AAAA,EAC/G;AAEA,MAAI,OAAO,UAAU,WAAW,WAAY,QAAO,KAAK,OAAO,MAAO,UAAU,OAAyB,KAAK,KAAK,CAAC,CAAC;AAErH,MAAI,OAAO,UAAU,WAAW,WAAY,QAAO,KAAK,OAAQ,UAAU,OAAyB,KAAK,KAAK,CAAC,CAAC;AAC/G,MAAI,OAAO,UAAU,WAAW,YAAY;AAE1C,QAAI,OAAO,UAAU,WAAW,WAAY,QAAO,KAAK,OAAQ,UAAU,OAAyB,KAAK,KAAK,CAAC,CAAC;AAC/G,QAAI,OAAO,UAAU,YAAY,WAAY,QAAO,KAAK,KAAK,UAAW,UAAU,QAA0B,KAAK,KAAK,CAAC,CAAC;AAAA,EAC3H;AAEA,SAAO,KAAK,KAAK,UAAU,KAAK,CAAC;AACnC;AAEA,SAAS,KAAK,MAAwB;AACpC,SAAO,IAAI,SAAS,MAAM,EAAE,SAAS,EAAE,gBAAgB,2BAA2B,EAAE,CAAC;AACvF;AAGA,SAAS,KAAK,MAAwB;AACpC,SAAO,IAAI,SAAS,MAAM,EAAE,SAAS,EAAE,gBAAgB,mBAAmB,EAAE,CAAC;AAC/E;;;ADZO,IAAM,0BAAN,cAAsC,MAA4B;AAAA,EAIvE,YAAqB,YAAoB;AACvC;AAAA,MACE,eAAe,UAAU;AAAA,IAE3B;AAJmB;AAAA,EAKrB;AAAA,EALqB;AAAA,EAHZ,OAAO;AAAA,EACP,SAAS;AAAA,EACA,OAAO;AAO3B;AAEA,SAAS,OACP,YACA,SACA,QACA,UACA,KACM;AACN,aAAW,aAAa,YAAY;AAClC,QAAI,OAAO,cAAc,YAAY;AACnC,UAAI,KAAK,EAAE,KAAK,WAAW,YAAY,CAAC,EAAE,CAAC;AAC3C;AAAA,IACF;AACA,UAAM,QAAQ,UAAU,QAAQ,GAAG;AACnC,UAAM,OAAO,UAAU,KAAK,YAAY,UAAU,MAAM,GAAG,KAAK;AAChE,UAAM,aAAa,UAAU,KAAK,CAAC,IAAI,UAAU,MAAM,QAAQ,CAAC,EAAE,MAAM,GAAG;AAC3E,QAAI,UAAU,MAAM,OAAO,OAAO,QAAQ,IAAI,GAAG;AAC/C,UAAI,SAAS,IAAI,IAAI,EAAG,OAAM,IAAI,aAAa,qBAAqB,IAAI,oBAAoB;AAC5F,eAAS,IAAI,IAAI;AACjB,aAAO,OAAO,IAAI,GAAI,SAAS,QAAQ,UAAU,GAAG;AACpD,eAAS,OAAO,IAAI;AACpB;AAAA,IACF;AACA,QAAI,CAAC,OAAO,OAAO,SAAS,IAAI,EAAG,OAAM,IAAI,wBAAwB,SAAS;AAC9E,QAAI,KAAK,EAAE,KAAK,QAAQ,IAAI,GAAI,WAAW,CAAC;AAAA,EAC9C;AACF;AAMO,SAAS,kBACd,YACA,UACA,SACA,QACsB;AACtB,QAAM,MAA4B,CAAC;AACnC,SAAO,YAAY,SAAS,QAAQ,oBAAI,IAAI,GAAG,GAAG;AAClD,QAAM,UAAgC,CAAC;AACvC,SAAO,UAAU,SAAS,QAAQ,oBAAI,IAAI,GAAG,OAAO;AACpD,QAAM,iBAAiB,IAAI,IAAI,QAAQ,IAAI,CAAC,UAAU,MAAM,GAAG,CAAC;AAChE,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,WAAW,oBAAI,IAA6B;AAClD,SAAO,IAAI,OAAO,CAAC,UAAU;AAC3B,QAAI,eAAe,IAAI,MAAM,GAAG,EAAG,QAAO;AAC1C,QAAI,CAAC,SAAS,IAAI,MAAM,GAAG,EAAG,UAAS,IAAI,MAAM,KAAK,SAAS,IAAI;AACnE,UAAM,MAAM,GAAG,SAAS,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM,WAAW,KAAK,GAAG,CAAC;AACpE,QAAI,KAAK,IAAI,GAAG,EAAG,QAAO;AAC1B,SAAK,IAAI,GAAG;AACZ,WAAO;AAAA,EACT,CAAC;AACH;AAMA,eAAsB,YAAY,WAAsB,SAAsB,OAAmC;AAC/G,MAAI,CAAC,UAAU,MAAM,gBAAgB,EAAG,OAAM;AAC9C,QAAM,UAAU,UAAU,KAAK,gBAAgB;AAC/C,QAAM,QAAQ,OAAO,KAAK;AAC1B,SAAO,QAAQ,OAAO,SAAS,KAAK;AACtC;AAEA,eAAe,MAAM,WAAsB,SAAsB,KAAgD;AAC/G,MAAI;AACF,UAAM,SAAS,MAAM,IAAI;AACzB,WAAO,kBAAkB,WAAW,SAAS,MAAM,WAAW,SAAS,MAAM;AAAA,EAC/E,SAAS,OAAO;AACd,WAAO,YAAY,WAAW,SAAS,KAAK;AAAA,EAC9C;AACF;AAeA,eAAsB,cACpB,WACA,SACA,YACA,WACA,aACA,OACmB;AACnB,QAAM,QAAqB,WAAW,IAAI,CAAC,EAAE,KAAK,WAAW,MAAM;AACjE,UAAM,WAAW,UAAU,KAAK,GAAG;AACnC,cAAU,KAAK,QAAQ;AACvB,WAAO,CAAC,UAAU,SAChB,MAAM,WAAW,UAAU,MAAM,SAAS,OAAO,UAAU,MAA+C,GAAG,UAAU,CAAC;AAAA,EAC5H,CAAC;AACD,MAAI,UAAU,QAAW;AACvB,UAAM;AAAA,MAAO,MAAM;AAAA,MAAI;AAAA,MAAG,CAAC,UAAU,SACnC,MAAM,WAAW,UAAU,YAAY;AACrC,cAAM,MAAM,IAAI,QAAQ;AACxB,eAAO,KAAK,QAAQ;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO,UACJ,KAAK,eAAe,EACpB,KAAkB,EAClB,KAAK,OAAO,EACZ,QAAQ,KAAK,EACb,KAAK,CAAC,aAAa,MAAM,WAAW,UAAU,MAAM,YAAY,QAAQ,CAAC,CAAC;AAC/E;;;AFrIO,SAAS,iBACd,QACA,YACkD;AAClD,QAAM,UAAU,OAAO,cAAc;AACrC,QAAM,SAAS,OAAO,oBAAoB;AAC1C,QAAM,QAAQ,oBAAI,IAAqB;AACvC,aAAW,QAAQ,CAAC,QAAQ,OAAO,EAAG,KAAI,OAAO,OAAO,SAAS,IAAI,EAAG,OAAM,IAAI,QAAQ,IAAI,CAAE;AAChG,aAAW,SAAS,CAAC,OAAO,KAAK,GAAG;AAClC,QAAI;AACF,iBAAW,SAAS,kBAAkB,CAAC,KAAK,GAAG,CAAC,GAAG,SAAS,MAAM,EAAG,OAAM,IAAI,MAAM,GAAG;AAAA,IAC1F,QAAQ;AAAA,IAER;AAAA,EACF;AACA,QAAM,SAAS,WAAW,OAAO,CAAC,UAAU,MAAM,IAAI,MAAM,GAAG,CAAC;AAChE,QAAM,QAAQ,WAAW,OAAO,CAAC,UAAU,CAAC,MAAM,IAAI,MAAM,GAAG,CAAC;AAChE,SAAO,EAAE,YAAY,CAAC,GAAG,QAAQ,GAAG,KAAK,GAAG,IAAI,OAAO,OAAO;AAChE;AASA,eAAsB,mBACpB,QACA,OACA,QACA,WACkC;AAClC,QAAM,WAAW,UAAU,MAAM,kBAAkB,IAAI,UAAU,KAAK,kBAAkB,IAAI;AAC5F,QAAM,QAAiC,CAAC;AACxC,aAAW,EAAE,MAAM,MAAM,KAAK,MAAM,YAAY;AAC9C,UAAM,QAAQ,OAAO,IAAI;AACzB,QAAI,UAAU,QAAW;AACvB,YAAM,IAAI,IAAI;AACd;AAAA,IACF;AACA,UAAM,SAAS,OAAO,UAAU,IAAI;AACpC,QAAI,WAAW,QAAW;AACxB,YAAM,IAAI,IAAI,MAAM,OAAO,KAAK;AAChC;AAAA,IACF;AACA,UAAM,QAAQ,OAAO,SAAS,IAAI;AAClC,QAAI,UAAU,QAAW;AACvB,UAAI,aAAa,QAAW;AAC1B,cAAM,IAAI;AAAA,UACR,gBAAgB,IAAI,MAAM,MAAM,IAAI;AAAA,QACtC;AAAA,MACF;AACA,YAAM,QAAQ,MAAM,SAAS,gBAAgB,OAAO,OAAO,KAAK;AAChE,UAAI,UAAU,QAAQ,UAAU,OAAW,OAAM,IAAI,wBAAwB,MAAM,MAAM,KAAK;AAC9F,YAAM,IAAI,IAAI;AACd;AAAA,IACF;AACA,QAAI,aAAa,QAAW;AAC1B,YAAM,QAAQ,MAAM,SAAS,QAAQ,MAAM,OAAO,KAAK;AACvD,UAAI,UAAU,KAAM,OAAM,IAAI,wBAAwB,IAAI,OAAO,IAAI,GAAG,KAAK;AAC7E,YAAM,IAAI,IAAI,UAAU,SAAY,QAAQ;AAC5C;AAAA,IACF;AACA,UAAM,IAAI,IAAI;AAAA,EAChB;AACA,SAAO;AACT;;;AIjFA,SAAS,oBAAmF;AAC5F,SAAS,wBAAwB;;;ACsB1B,IAAM,YAAY;AAClB,IAAM,iBAAiB;AAC9B,IAAM,cAAc,CAAC,UAAkB,MAAM,QAAQ,uBAAuB,MAAM;AAE3E,SAAS,gBAAgB,KAA6B;AAC3D,SAAO,CAAC,GAAG,IAAI,SAAS,SAAS,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,MAAM,CAAC,GAAI,UAAU,MAAM,CAAC,MAAM,KAAK,OAAO,MAAM,CAAC,EAAE,EAAE;AACvH;AAGO,SAAS,aAAa,KAAqB;AAChD,QAAM,UAAU,IAAI,QAAQ,cAAc,EAAE;AAC5C,SAAO,YAAY,KAAK,MAAM;AAChC;AAGO,SAAS,cAAc,UAA0B;AACtD,QAAM,UAAU,SAAS,QAAQ,cAAc,EAAE,EAAE,QAAQ,WAAW,GAAG;AACzE,SAAO,YAAY,KAAK,KAAK,IAAI,OAAO;AAC1C;AAEA,SAAS,OAAO,OAAuB;AACrC,MAAI;AACF,WAAO,mBAAmB,KAAK;AAAA,EACjC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,SAAS,YAAY,KAAa,QAAkD;AAClF,MAAI,QAAQ,IAAK,QAAO;AACxB,QAAM,QAAQ,CAAC,SAAiB,QAAQ,IAAI,IAAI,OAAO,IAAI,KAAK,OAAO;AACvE,MAAI,OAAO;AACX,aAAW,WAAW,IAAI,MAAM,GAAG,GAAG;AACpC,UAAM,QAAQ,eAAe,KAAK,OAAO;AACzC,QAAI,OAAO;AACT,cAAQ,OAAO,MAAM,MAAM,CAAC,CAAE,CAAC;AAC/B;AAAA,IACF;AACA,QAAI,QAAQ;AACZ,QAAI,OAAO;AACX,eAAW,SAAS,QAAQ,SAAS,SAAS,GAAG;AAC/C,eAAS,YAAY,QAAQ,MAAM,MAAM,MAAM,KAAK,CAAC,IAAI,MAAM,MAAM,CAAC,CAAE,KAAK,MAAM,CAAC,MAAM,MAAM,MAAM;AACtG,aAAO,MAAM,QAAQ,MAAM,CAAC,EAAE;AAAA,IAChC;AACA,YAAQ,IAAI,KAAK,GAAG,YAAY,QAAQ,MAAM,IAAI,CAAC,CAAC;AAAA,EACtD;AACA,SAAO;AACT;AAEA,IAAM,mBAAmB;AAMzB,SAAS,gBAAgB,KAAa,QAAkD;AACtF,QAAM,OAAO;AACb,MAAI,QAAQ,iBAAkB,QAAO,IAAI,OAAO,IAAI,IAAI,KAAK,GAAG;AAChE,MAAI,CAAC,IAAI,SAAS,IAAI,gBAAgB,EAAE,EAAG,QAAO,IAAI,OAAO,IAAI,YAAY,KAAK,EAAE,GAAG,QAAQ,qBAAqB,KAAK,CAAC,CAAC,KAAK,GAAG;AACnI,SAAO,IAAI,OAAO,IAAI,YAAY,IAAI,MAAM,GAAG,CAAC,iBAAiB,SAAS,CAAC,GAAG,MAAM,CAAC,GAAG,IAAI,KAAK,GAAG;AACtG;AAGO,SAAS,cAAc,GAAoB,GAA4B;AAC5E,MAAI,EAAE,eAAe,EAAE,WAAY,QAAO,EAAE,aAAa,IAAI;AAC7D,QAAM,OAAO,EAAE,KAAK;AACpB,QAAM,QAAQ,EAAE,KAAK;AACrB,WAAS,IAAI,GAAG,IAAI,KAAK,IAAI,KAAK,QAAQ,MAAM,MAAM,GAAG,KAAK;AAC5D,UAAM,IAAI,KAAK,CAAC,KAAK;AACrB,UAAM,IAAI,MAAM,CAAC,KAAK;AACtB,QAAI,MAAM,EAAG,QAAO,IAAI;AAAA,EAC1B;AACA,SAAO;AACT;AAEO,IAAM,kBAAN,MAAuC;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EACS;AAAA,EACA,YAAmC,CAAC;AAAA,EACpC,UAAkC,CAAC;AAAA,EAC5C;AAAA,EAEA,YAAY,SAA4B,KAAa,QAAsB,aAA8B,CAAC,GAAG;AAC3G,SAAK,UAAU,CAAC,GAAG,IAAI,IAAI,QAAQ,IAAI,CAAC,WAAW,OAAO,YAAY,CAAC,CAAC,CAAC;AACzE,SAAK,MAAM,aAAa,GAAG;AAC3B,SAAK,SAAS;AACd,SAAK,aAAa,WAAW;AAC7B,SAAK,aAAa,WAAW,YAAY;AACzC,SAAK,aAAa,gBAAgB,KAAK,GAAG;AAC1C,SAAK,QAAQ,WAAW,eAAe,UAAa,WAAW,eAAe,KAAK,SAAY,WAAW;AAC1G,SAAK,cAAc,CAAC,GAAI,WAAW,cAAc,CAAC,CAAE;AAAA,EACtD;AAAA,EAEA,UAA8B;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,KAAK,MAAoB;AACvB,SAAK,SAAS,KAAK,SAAS,MAAM;AAClC,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,cAAc,YAA+E;AAC3F,SAAK,YAAY,KAAK,GAAG,WAAW,KAAK,CAAC;AAC1C,WAAO;AAAA,EACT;AAAA,EAEA,qBAAqB,YAAyC;AAC5D,SAAK,UAAU,KAAK,GAAG,WAAW,KAAK,CAAC;AACxC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,WAA4C,SAAwB;AACxE,QAAI,OAAO,cAAc,SAAU,MAAK,QAAQ,SAAS,IAAI,WAAW;AAAA,QACnE,QAAO,OAAO,KAAK,SAAS,SAAS;AAC1C,SAAK,YAAY;AACjB,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,WAAW,YAA8C;AACvD,WAAO,KAAK,QAAQ,YAAY,WAAW;AAAA,EAC7C;AAAA;AAAA,EAGA,kBAAkB,YAA8C;AAC9D,WAAO,KAAK,QAAQ,YAAY,cAAc;AAAA,EAChD;AAAA;AAAA,EAGA,YAAY,YAA8C;AACxD,WAAO,KAAK,QAAQ,YAAY,QAAQ;AAAA,EAC1C;AAAA;AAAA,EAGA,UAAU,YAA8C;AACtD,WAAO,KAAK,QAAQ,YAAY,0CAA0C;AAAA,EAC5E;AAAA;AAAA,EAGA,UAAU,YAA8C;AACtD,WAAO,KAAK,QAAQ,YAAY,6EAA6E;AAAA,EAC/G;AAAA;AAAA,EAGA,QAAQ,YAAwC,QAA8C;AAC5F,UAAM,QAAQ,OAAO,eAAe,WAAW,aAAa,WAAW,CAAC;AACxE,QAAI,OAAO,WAAW,KAAK,UAAU,OAAW,OAAM,IAAI,MAAM,4BAA4B,KAAK,oBAAoB;AACrH,WAAO,KAAK,QAAQ,YAAY,OAAO,IAAI,CAAC,UAAU,YAAY,OAAO,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC;AAAA,EAC7F;AAAA,EAEA,mBAA0C;AACxC,WAAO,CAAC,GAAG,KAAK,WAAW;AAAA,EAC7B;AAAA,EAEA,qBAA4C;AAC1C,WAAO,CAAC,GAAG,KAAK,SAAS;AAAA,EAC3B;AAAA,EAEA,SAAiC;AAC/B,WAAO,EAAE,GAAG,KAAK,QAAQ;AAAA,EAC3B;AAAA,EAEA,gBAAwB;AACtB,QAAI,OAAO,KAAK,WAAW,SAAU,QAAO,GAAG,KAAK,YAAY,QAAQ,YAAY,IAAI,KAAK,MAAM;AACnG,QAAI,MAAM,QAAQ,KAAK,MAAM,EAAG,QAAO,GAAI,KAAK,OAAO,CAAC,EAAqB,IAAI,IAAI,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC;AAC3G,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MACE,MACA,WAA6C,CAAC,GAC9C,UAAU,GACsC;AAChD,UAAM,QAAQ,KAAK,OAAO,UAAU,OAAO,EAAE,KAAK,IAAI;AACtD,QAAI,UAAU,KAAM,QAAO;AAC3B,UAAM,SAA6C,CAAC;AACpD,eAAW,EAAE,KAAK,KAAK,KAAK,YAAY;AACtC,YAAM,MAAM,MAAM,SAAS,KAAK,IAAI,EAAE;AACtC,aAAO,IAAI,IAAI,QAAQ,SAAY,SAAY,OAAO,GAAG;AAAA,IAC3D;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,OAAiB;AACf,QAAI,KAAK,QAAQ,IAAK,QAAO,CAAC;AAC9B,WAAO,KAAK,IAAI,MAAM,GAAG,EAAE,IAAI,CAAC,YAAa,eAAe,KAAK,OAAO,IAAI,IAAI,QAAQ,SAAS,GAAG,IAAI,IAAI,CAAE;AAAA,EAChH;AAAA,EAEA,QAAQ,YAAwC,SAAuB;AACrE,UAAM,QAA2B,OAAO,eAAe,WAAW,CAAC,UAAU,IAAI;AACjF,WAAO,KAAK,MAAM,OAAO,YAAY,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC;AAAA,EAC5E;AAAA,EAEA,OAAO,UAA4C,SAAyB;AAC1E,QAAI,KAAK,cAAc,UAAa,KAAK,UAAU,YAAY,QAAS,QAAO,KAAK,UAAU;AAC9F,UAAM,SAAS,EAAE,GAAG,UAAU,GAAG,KAAK,QAAQ;AAC9C,UAAM,QAAQ,KAAK,aAAa,gBAAgB,KAAK,KAAK,MAAM,IAAI,IAAI,OAAO,IAAI,YAAY,KAAK,KAAK,MAAM,CAAC,GAAG;AACnH,SAAK,YAAY,EAAE,OAAO,QAAQ;AAClC,WAAO;AAAA,EACT;AACF;;;ADlOO,IAAM,gCAAN,cAA4C,MAA4B;AAAA,EACpE,OAAO;AAAA,EACP,SAAS;AAAA,EACA,OAAO;AAAA,EACzB,YAAY,YAAoB,QAAgB;AAC9C,UAAM,UAAU,UAAU,KAAK,MAAM,kBAAkB;AAAA,EACzD;AACF;AAGA,IAAM,UAAU,CAAC,UACf,OAAO,UAAU,cAAc,cAAc,KAAK,SAAS,UAAU,SAAS,KAAK,KAAK,CAAC;AAI3F,SAAS,UAAU,QAAoB,SAA6B;AAClE,QAAM,SAAS,QAAQ,OAAO,EAAE,YAAY;AAC5C,QAAM,OAAO,cAAc,IAAI,IAAI,QAAQ,IAAI,GAAG,EAAE,QAAQ;AAC5D,QAAM,WAAW,OAAO,YAAY;AACpC,QAAM,UAAU,OAAO,kBAAkB;AACzC,QAAM,UAAU,oBAAI,IAAY;AAChC,aAAW,SAAS,OAAO,sBAAsB,GAAG;AAClD,UAAM,SAAS,MAAM,MAAM,MAAM,UAAU,OAAO;AAClD,QAAI,WAAW,OAAW;AAC1B,QAAI,MAAM,QAAQ,SAAS,MAAM,EAAG,QAAO,EAAE,OAAO,OAAO;AAE3D,QAAI,CAAC,MAAM,WAAY,YAAW,QAAQ,MAAM,QAAS,SAAQ,IAAI,IAAI;AAAA,EAC3E;AACA,MAAI,QAAQ,OAAO,GAAG;AAEpB,QAAI,WAAW,UAAW,QAAO,EAAE,UAAU,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,SAAS,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC,EAAE;AAC9H,UAAM,IAAI,0BAA0B,QAAQ,QAAQ,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC;AAAA,EAC1E;AACA,QAAM,IAAI,kBAAkB,QAAQ,KAAK,CAAC;AAC5C;AAGA,eAAe,UAAU,OAAkB,OAAwB,YAAuD;AACxH,QAAM,OAAO,MAAM,WAAW,IAAI,CAAC,cAAc,WAAW,UAAU,IAAI,CAAC;AAC3E,QAAM,SAAS,MAAM;AACrB,MAAI,OAAO,WAAW,cAAc,CAAC,QAAQ,MAAM,EAAG,QAAQ,OAA6C,GAAG,IAAI;AAClH,QAAM,CAAC,KAAK,MAAM,IAChB,OAAO,WAAW,WACd,CAAC,MAAM,YAA6B,MAAM,IAC1C,QAAQ,MAAM,IACZ,CAAC,QAAQ,UAAU,IACnB,CAAC,OAAO,CAAC,GAAoB,OAAO,OAAO,CAAC,CAAC,CAAC;AACtD,QAAM,aAAa,MAAM,KAAK,GAAG;AACjC,QAAM,UAAU,WAAW,MAAM;AACjC,MAAI,OAAO,YAAY,WAAY,OAAM,IAAI,8BAA8B,IAAI,MAAM,MAAM;AAC3F,SAAQ,QAA8C,MAAM,YAAY,IAAI;AAC9E;AAMA,eAAsB,cAAc,QAAoB,SAAsB,WAA0C;AACtH,QAAM,QAAQ,iBAAiB,KAAK;AACpC,MAAI,UAAU,OAAW,OAAM,IAAI,aAAa,uDAAuD;AACvG,QAAM,QAAQ,UAAU,QAAQ,OAAO;AACvC,MAAI,cAAc,MAAO,QAAO,MAAM;AACtC,QAAM,EAAE,OAAO,OAAO,IAAI;AAE1B,QAAM,QAAsB,EAAE,OAAO,YAAY,EAAE,GAAG,OAAO,GAAG,YAAY,CAAC,EAAE;AAC/E,QAAM,SAAS,cAAc,KAAK;AAElC,QAAM,aAAa;AAAA,IACjB,MAAM,iBAAiB;AAAA,IACvB,MAAM,mBAAmB;AAAA,IACzB,OAAO,cAAc;AAAA,IACrB,OAAO,oBAAoB;AAAA,EAC7B;AACA,QAAM,UAAU,iBAAiB,QAAQ,UAAU;AACnD,SAAO,cAAc,OAAO,SAAS,QAAQ,YAAY,MAAM,YAAY,MAAM,UAAU,OAAO,OAAO,MAAM,UAAU,GAAG;AAAA,IAC1H,IAAI,QAAQ;AAAA,IACZ,KAAK,YAAY,KAAK,OAAO,OAAO,MAAM,YAAY,MAAM,mBAAmB,QAAQ,OAAO,QAAQ,KAAK,CAAC;AAAA,EAC9G,CAAC;AACH;;;AElEO,IAAM,YAAY,CAAC,OAAO,QAAQ,QAAQ,OAAO,SAAS,UAAU,SAAS;AAG7E,SAAS,WAAW,QAAyB,OAAyC;AAC3F,QAAM,SAAS,CAAC,OAAO,QAAQ,MAAM,MAAM,EACxC,IAAI,CAAC,UAAU,QAAQ,IAAI,QAAQ,cAAc,EAAE,CAAC,EACpD,OAAO,CAAC,SAAS,SAAS,EAAE,EAC5B,KAAK,GAAG;AACX,QAAM,SAA0B;AAAA,IAC9B,YAAY,CAAC,GAAI,OAAO,cAAc,CAAC,GAAI,GAAI,MAAM,cAAc,CAAC,CAAE;AAAA,EACxE;AACA,MAAI,WAAW,GAAI,QAAO,SAAS;AACnC,QAAM,MAAM,OAAO,MAAM,OAAO,MAAM,MAAM;AAC5C,MAAI,OAAO,GAAI,QAAO,KAAK;AAC3B,QAAM,aAAa,MAAM,cAAc,OAAO;AAC9C,MAAI,eAAe,OAAW,QAAO,aAAa;AAClD,SAAO;AACT;AAMO,IAAM,iBAAN,MAA+C;AAAA,EAGpD,YAA6B,QAAmB;AAAnB;AAAA,EAAoB;AAAA,EAApB;AAAA,EAFpB,cAA+B,CAAC;AAAA,EAIzC,OAAO,QAAsB;AAC3B,SAAK,YAAY,SAAS;AAC1B,WAAO;AAAA,EACT;AAAA,EAEA,KAAK,QAAsB;AACzB,SAAK,YAAY,KAAK;AACtB,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,YAA+E;AAC3F,SAAK,YAAY,aAAa,CAAC,GAAI,KAAK,YAAY,cAAc,CAAC,GAAI,GAAG,WAAW,KAAK,CAAC;AAC3F,WAAO;AAAA,EACT;AAAA,EAEA,WAAW,YAAkC;AAC3C,SAAK,YAAY,aAAa;AAC9B,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAAmD;AACvD,WAAO,KAAK,OAAO,MAAM,EAAE,GAAG,KAAK,YAAY,GAAG,MAAM;AAAA,EAC1D;AAAA,EAEA,IAAO,KAAa,QAAuF;AACzG,WAAO,KAAK,KAAK,CAAC,OAAO,MAAM,GAAG,KAAK,MAAM;AAAA,EAC/C;AAAA,EAEA,KAAQ,KAAa,QAAuF;AAC1G,WAAO,KAAK,KAAK,CAAC,MAAM,GAAG,KAAK,MAAM;AAAA,EACxC;AAAA,EAEA,IAAO,KAAa,QAAuF;AACzG,WAAO,KAAK,KAAK,CAAC,KAAK,GAAG,KAAK,MAAM;AAAA,EACvC;AAAA,EAEA,MAAS,KAAa,QAAuF;AAC3G,WAAO,KAAK,KAAK,CAAC,OAAO,GAAG,KAAK,MAAM;AAAA,EACzC;AAAA,EAEA,OAAU,KAAa,QAAuF;AAC5G,WAAO,KAAK,KAAK,CAAC,QAAQ,GAAG,KAAK,MAAM;AAAA,EAC1C;AAAA,EAEA,QAAW,KAAa,QAAuF;AAC7G,WAAO,KAAK,KAAK,CAAC,SAAS,GAAG,KAAK,MAAM;AAAA,EAC3C;AAAA,EAEA,IAAO,KAAa,QAAuF;AACzG,WAAO,KAAK,KAAK,WAAW,KAAK,MAAM;AAAA,EACzC;AAAA,EAEA,MAAS,SAAmB,KAAa,QAAuF;AAC9H,WAAO,KAAK,KAAK,SAAS,KAAK,MAAM;AAAA,EACvC;AAAA,EAEA,SAAS,MAAc,YAA4B,SAAiC;AAClF,SAAK,KAAK,OAAO,MAAM,EAAE,GAAG,KAAK,YAAY,GAAG,MAAM,KAAK,OAAO,SAAS,MAAM,YAAY,OAAO,CAAC;AAAA,EACvG;AAAA,EAEA,YAAY,MAAc,YAA4B,SAAiC;AACrF,SAAK,KAAK,OAAO,MAAM,EAAE,GAAG,KAAK,YAAY,GAAG,MAAM,KAAK,OAAO,YAAY,MAAM,YAAY,OAAO,CAAC;AAAA,EAC1G;AAAA,EAEA,KAAK,SAA4B,KAAa,QAAuC;AACnF,QAAI;AACJ,SAAK,KAAK,OAAO,MAAM,EAAE,GAAG,KAAK,YAAY,GAAG,MAAM;AACpD,cAAQ,KAAK,OAAO,SAAS,SAAS,KAAK,MAAM;AAAA,IACnD,CAAC;AACD,WAAO;AAAA,EACT;AACF;;;ACvHA,SAAS,OAAAC,YAAW;AAYpB,IAAM,WAAsC,CAAC,SAAS,UAAU,SAAS,QAAQ,QAAQ,UAAU,SAAS;AAC5G,IAAM,eAA0C,CAAC,SAAS,SAAS,QAAQ,UAAU,SAAS;AAG9F,SAAS,SAAS,SAAiB,SAAkC;AACnE,QAAM,UAAU,QAAQ,aAAa,OAAO;AAC5C,UAAQ,WAAWA,KAAI,SAAS,OAAO,GAAG,QAAQ,MAAM,GAAG;AAC7D;AAMO,SAAS,eAAe,MAAc,UAA2B,CAAC,GAAG,MAAM,OAAwB;AACxG,QAAM,WAAW,KAAK,MAAM,GAAG;AAC/B,QAAM,OAAO,SAAS,GAAG,EAAE;AAC3B,QAAM,OAAO,CAAC,GAAG,SAAS,MAAM,GAAG,EAAE,EAAE,IAAI,CAAC,YAAY,GAAG,OAAO,KAAK,SAAS,SAAS,OAAO,CAAC,GAAG,GAAG,IAAI,EAAE,KAAK,GAAG;AACrH,QAAM,SAAS,GAAG,IAAI,KAAK,SAAS,MAAM,OAAO,CAAC;AAElD,MAAI,UAAU,MAAM,eAAe;AACnC,MAAI,QAAQ,SAAS,OAAW,WAAU,QAAQ,OAAO,CAAC,WAAW,QAAQ,KAAM,SAAS,MAAM,CAAC;AACnG,MAAI,QAAQ,WAAW,OAAW,WAAU,QAAQ,OAAO,CAAC,WAAW,CAAC,QAAQ,OAAQ,SAAS,MAAM,CAAC;AAExG,QAAM,QAAkE;AAAA,IACtE,OAAO,EAAE,OAAO,CAAC,OAAO,MAAM,GAAG,KAAK,KAAK;AAAA,IAC3C,QAAQ,EAAE,OAAO,CAAC,OAAO,MAAM,GAAG,KAAK,GAAG,IAAI,UAAU;AAAA,IACxD,OAAO,EAAE,OAAO,CAAC,MAAM,GAAG,KAAK,KAAK;AAAA,IACpC,MAAM,EAAE,OAAO,CAAC,OAAO,MAAM,GAAG,KAAK,OAAO;AAAA,IAC5C,MAAM,EAAE,OAAO,CAAC,OAAO,MAAM,GAAG,KAAK,GAAG,MAAM,QAAQ;AAAA,IACtD,QAAQ,EAAE,OAAO,CAAC,OAAO,OAAO,GAAG,KAAK,OAAO;AAAA,IAC/C,SAAS,EAAE,OAAO,CAAC,QAAQ,GAAG,KAAK,OAAO;AAAA,EAC5C;AACA,SAAO,QAAQ,IAAI,CAAC,YAAY;AAAA,IAC9B;AAAA,IACA,OAAO,MAAM,MAAM,EAAE;AAAA,IACrB,KAAK,MAAM,MAAM,EAAE;AAAA,IACnB,MAAM,QAAQ,QAAQ,MAAM,KAAK,GAAG,IAAI,IAAI,MAAM;AAAA,EACpD,EAAE;AACJ;;;ARvBO,IAAM,aAAN,MAAmC;AAAA;AAAA,EAYxC,YAA+B,WAAuB;AAAvB;AAAA,EAAwB;AAAA,EAAxB;AAAA,EAXtB,UAA6B,CAAC;AAAA,EACvC;AAAA,EACS,cAAiC,CAAC;AAAA,EAClC,YAAoC,CAAC;AAAA,EAC9C,kBAAkB;AAAA,EACT,WAA4C,CAAC;AAAA,EAC7C,UAAiD,EAAE,KAAK,CAAC,GAAG,KAAK,CAAC,EAAE;AAAA,EACpE,WAAW,oBAAI,IAAyB;AAAA,EACxC,UAAU,oBAAI,IAA4B;AAAA,EAKnD,IAAO,KAAa,QAAuF;AACzG,WAAO,KAAK,SAAS,CAAC,OAAO,MAAM,GAAG,KAAK,MAAM;AAAA,EACnD;AAAA,EAEA,KAAQ,KAAa,QAAuF;AAC1G,WAAO,KAAK,SAAS,CAAC,MAAM,GAAG,KAAK,MAAM;AAAA,EAC5C;AAAA,EAEA,IAAO,KAAa,QAAuF;AACzG,WAAO,KAAK,SAAS,CAAC,KAAK,GAAG,KAAK,MAAM;AAAA,EAC3C;AAAA,EAEA,MAAS,KAAa,QAAuF;AAC3G,WAAO,KAAK,SAAS,CAAC,OAAO,GAAG,KAAK,MAAM;AAAA,EAC7C;AAAA,EAEA,OAAU,KAAa,QAAuF;AAC5G,WAAO,KAAK,SAAS,CAAC,QAAQ,GAAG,KAAK,MAAM;AAAA,EAC9C;AAAA,EAEA,QAAW,KAAa,QAAuF;AAC7G,WAAO,KAAK,SAAS,CAAC,SAAS,GAAG,KAAK,MAAM;AAAA,EAC/C;AAAA,EAEA,IAAO,KAAa,QAAuF;AACzG,WAAO,KAAK,SAAS,WAAW,KAAK,MAAM;AAAA,EAC7C;AAAA,EAEA,MAAS,SAAmB,KAAa,QAAuF;AAC9H,WAAO,KAAK,SAAS,SAAS,KAAK,MAAM;AAAA,EAC3C;AAAA;AAAA,EAGA,SAAS,SAA4B,KAAa,QAAsB,UAAkC,CAAC,GAAoB;AAC7H,UAAM,QAAQ,KAAK,YAAY,GAAG,EAAE,KAAK,CAAC;AAC1C,UAAM,QAAQ,QAAQ,IAAI,CAAC,WAAW,OAAO,YAAY,CAAC;AAC1D,QAAI,MAAM,SAAS,KAAK,KAAK,CAAC,MAAM,SAAS,MAAM,EAAG,OAAM,KAAK,MAAM;AACvE,QAAI,OAAO,WAAW,YAAY,MAAM,eAAe,QAAW;AAChE,YAAM,IAAI;AAAA,QACR,iBAAiB,MAAM,kFAAkF,MAAM;AAAA,MACjH;AAAA,IACF;AACA,UAAM,UAAU,MAAM,UAAU,IAAI,QAAQ,cAAc,EAAE;AAC5D,UAAM,OAAO,IAAI,QAAQ,cAAc,EAAE;AACzC,UAAM,QAAQ,IAAI,gBAAgB,OAAO,CAAC,QAAQ,IAAI,EAAE,OAAO,CAAC,SAAS,SAAS,EAAE,EAAE,KAAK,GAAG,GAAG,QAAQ;AAAA,MACvG,GAAI,MAAM,OAAO,UAAa,EAAE,YAAY,MAAM,GAAG;AAAA,MACrD,GAAI,MAAM,eAAe,UAAa,EAAE,YAAY,MAAM,WAAW;AAAA,MACrE,GAAI,MAAM,eAAe,UAAa,EAAE,YAAY,MAAM,WAAW;AAAA,MACrE,GAAI,QAAQ,aAAa,QAAQ,EAAE,UAAU,KAAK;AAAA,IACpD,CAAC;AACD,SAAK,QAAQ,KAAK,KAAK;AACvB,SAAK,UAAU;AACf,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,SAAS,MAAc,IAAY,SAAS,KAAsB;AAChE,UAAM,SAAsC,CAAC;AAC7C,UAAM,SAAS,IAAI,WAAsB;AACvC,YAAM,aAAa,IAAI,IAAI,OAAO,MAAO,WAAW,IAAI,CAAC,WAAW,UAAU,CAAC,UAAU,MAAM,OAAO,KAAK,CAAC,CAAC,CAAC;AAC9G,YAAM,SAAS,GAAG,QAAQ,iBAAiB,CAAC,QAAQ,SAAiB;AACnE,cAAM,QAAQ,WAAW,IAAI,IAAI;AACjC,eAAO,UAAU,UAAa,UAAU,OAAO,KAAK,mBAAmB,OAAO,KAAK,CAAC;AAAA,MACtF,CAAC;AACD,YAAM,YAAYC,kBAAiB,KAAK,KAAK;AAC7C,YAAM,WAAW,WAAW,MAAM,YAAY,IAAI,UAAU,KAAK,YAAY,EAAE,GAAG,MAAM,IAAI;AAC5F,aAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,SAAS,EAAE,UAAU,SAAS,EAAE,CAAC;AAAA,IACvE;AACA,WAAO,QAAQ,KAAK,IAAI,MAAM,MAAM;AACpC,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,kBAAkB,MAAc,IAA6B;AAC3D,WAAO,KAAK,SAAS,MAAM,IAAI,GAAG;AAAA,EACpC;AAAA;AAAA,EAGA,KAAK,KAAa,MAAc,OAAgC,CAAC,GAAoB;AACnF,UAAM,SAAsC,CAAC;AAC7C,UAAM,SAAS,IAAI,WAAsB;AACvC,YAAM,aAAa,OAAO,YAAY,OAAO,MAAO,WAAW,IAAI,CAAC,WAAW,UAAU,CAAC,UAAU,MAAM,OAAO,KAAK,CAAC,CAAC,CAAC;AACzH,YAAM,YAAYA,kBAAiB,KAAK,KAAK;AAC7C,UAAI,cAAc,OAAW,OAAM,IAAI,aAAa,uBAAuB,IAAI,+BAA+B;AAC9G,aAAO,UAAU,KAAK,WAAW,EAAE,KAAK,MAAM,EAAE,GAAG,MAAM,GAAG,WAAW,CAAC;AAAA,IAC1E;AACA,WAAO,QAAQ,KAAK,SAAS,CAAC,OAAO,MAAM,GAAG,KAAK,MAAM;AACzD,WAAO,OAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,KAAa,WAAmB,QAAiC,CAAC,GAAoB;AAC5F,UAAM,SAAsC,CAAC;AAC7C,UAAM,SAAS,IAAI,WAAsB;AACvC,YAAM,aAAa,OAAO,YAAY,OAAO,MAAO,WAAW,IAAI,CAAC,WAAW,UAAU,CAAC,UAAU,MAAM,OAAO,KAAK,CAAC,CAAC,CAAC;AACzH,YAAM,YAAYA,kBAAiB,KAAK,KAAK;AAC7C,UAAI,cAAc,UAAa,CAAC,UAAU,MAAM,cAAc,GAAG;AAC/D,cAAM,IAAI,aAAa,+BAA+B,SAAS,gCAAgC;AAAA,MACjG;AACA,aAAO,UAAU,KAAK,cAAc,EAAE,OAAO,WAAW,EAAE,GAAG,OAAO,GAAG,WAAW,CAAC;AAAA,IACrF;AACA,WAAO,QAAQ,KAAK,SAAS,CAAC,OAAO,MAAM,GAAG,KAAK,MAAM;AACzD,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,SAAS,MAAc,YAA4B,UAA2B,CAAC,GAAS;AACtF,SAAK,kBAAkB,MAAM,YAAY,SAAS,KAAK;AAAA,EACzD;AAAA,EAEA,YAAY,MAAc,YAA4B,UAA2B,CAAC,GAAS;AACzF,SAAK,kBAAkB,MAAM,YAAY,SAAS,IAAI;AAAA,EACxD;AAAA;AAAA,EAGA,SAAS,QAAsC;AAC7C,WAAO,KAAK,SAAS,CAAC,OAAO,MAAM,GAAG,yBAAyB,QAAQ,EAAE,UAAU,KAAK,CAAC;AAAA,EAC3F;AAAA,EAEA,OAAO,QAAgC;AACrC,WAAO,IAAI,eAAe,IAAI,EAAE,OAAO,MAAM;AAAA,EAC/C;AAAA,EAEA,KAAK,QAAgC;AACnC,WAAO,IAAI,eAAe,IAAI,EAAE,KAAK,MAAM;AAAA,EAC7C;AAAA,EAEA,cAAc,YAAyF;AACrG,WAAO,IAAI,eAAe,IAAI,EAAE,WAAW,GAAG,UAAU;AAAA,EAC1D;AAAA,EAEA,WAAW,YAA4C;AACrD,WAAO,IAAI,eAAe,IAAI,EAAE,WAAW,UAAU;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YAA6B,QAAmD;AACpF,UAAM,QAAQ,WAAW,KAAK,YAAY,GAAG,EAAE,KAAK,CAAC,GAAG,UAAU;AAClE,SAAK,YAAY,KAAK,KAAK;AAC3B,UAAM,MAAM,MAAM;AAChB,YAAM,QAAQ,KAAK,YAAY,YAAY,KAAK;AAChD,UAAI,UAAU,GAAI,MAAK,YAAY,OAAO,OAAO,CAAC;AAAA,IACpD;AACA,QAAI;AACJ,QAAI;AACF,eAAS,OAAO;AAAA,IAClB,SAAS,OAAO;AACd,UAAI;AACJ,YAAM;AAAA,IACR;AACA,QAAI,kBAAkB,QAAS,QAAO,OAAO,QAAQ,GAAG;AACxD,QAAI;AACJ,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA,EAEA,MAAM,WAAmB,OAA6B;AACpD,SAAK,QAAQ,IAAI,WAAW,KAAK;AAAA,EACnC;AAAA,EAEA,KAAK,WAAmB,UAA6B;AACnD,SAAK,SAAS,IAAI,WAAW,QAAQ;AAAA,EACvC;AAAA,EAEA,QAAQ,WAAmB,SAAuB;AAChD,SAAK,UAAU,SAAS,IAAI;AAC5B,SAAK;AAAA,EACP;AAAA,EAEA,SAAS,UAAwC;AAC/C,eAAW,CAAC,WAAW,OAAO,KAAK,OAAO,QAAQ,QAAQ,EAAG,MAAK,QAAQ,WAAW,OAAO;AAAA,EAC9F;AAAA,EAEA,cAAgD;AAC9C,WAAO,EAAE,GAAG,KAAK,UAAU;AAAA,EAC7B;AAAA;AAAA,EAGA,oBAA4B;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,UAAU,WAA4C;AACpD,WAAO,KAAK,SAAS,IAAI,SAAS;AAAA,EACpC;AAAA,EAEA,SAAS,WAA+C;AACtD,WAAO,KAAK,QAAQ,IAAI,SAAS;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,mBAAmB,OAAwB,QAAsD,WAAwD;AACvJ,WAAO,mBAAmB,MAAM,OAAO,QAAQ,SAAS;AAAA,EAC1D;AAAA,EAEA,gBAAgB,MAAc,YAAmC;AAC/D,SAAK,SAAS,IAAI,IAAI;AACtB,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,gBAAiD;AAC/C,WAAO,EAAE,GAAG,KAAK,SAAS;AAAA,EAC5B;AAAA,EAEA,gBAAgB,MAAc,YAAyC;AACrE,SAAK,QAAQ,IAAI,IAAI,CAAC,GAAG,UAAU;AACnC,WAAO;AAAA,EACT;AAAA,EAEA,sBAAsB,OAAe,YAAuC;AAC1E,UAAM,OAAQ,KAAK,QAAQ,KAAK,MAAM,CAAC;AACvC,QAAI,CAAC,KAAK,SAAS,UAAU,EAAG,MAAK,KAAK,UAAU;AACpD,WAAO;AAAA,EACT;AAAA,EAEA,yBAAyB,OAAe,YAAuC;AAC7E,UAAM,OAAQ,KAAK,QAAQ,KAAK,MAAM,CAAC;AACvC,QAAI,CAAC,KAAK,SAAS,UAAU,EAAG,MAAK,QAAQ,UAAU;AACvD,WAAO;AAAA,EACT;AAAA,EAEA,mBAAmB,MAAuB;AACxC,WAAO,OAAO,OAAO,KAAK,SAAS,IAAI;AAAA,EACzC;AAAA,EAEA,sBAA6D;AAC3D,WAAO,OAAO,YAAY,OAAO,QAAQ,KAAK,OAAO,EAAE,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;AAAA,EACjG;AAAA;AAAA,EAGA,YAAwC;AACtC,WAAO,CAAC,GAAG,KAAK,OAAO;AAAA,EACzB;AAAA;AAAA,EAGA,wBAAoD;AAClD,WAAQ,KAAK,YAAY,CAAC,GAAG,KAAK,OAAO,EAAE,KAAK,aAAa;AAAA,EAC/D;AAAA;AAAA,EAGA,UAAU,MAA2C;AACnD,WAAO,KAAK,QAAQ,SAAS,CAAC,UAAU,MAAM,QAAQ,MAAM,IAAI;AAAA,EAClE;AAAA,EAEA,OAAO,OAA0B;AAC/B,WAAO,MAAM,MAAM,CAAC,SAAS,KAAK,UAAU,IAAI,MAAM,MAAS;AAAA,EACjE;AAAA;AAAA,EAGA,UAAuC;AACrC,UAAM,YAAYA,kBAAiB;AACnC,QAAI,cAAc,UAAa,CAAC,UAAU,MAAMC,aAAY,EAAG,QAAO;AACtE,WAAO,UAAU,KAAKA,aAAY,EAAE;AAAA,EACtC;AAAA,EAEA,mBAAuC;AACrC,WAAO,KAAK,QAAQ,GAAG,QAAQ;AAAA,EACjC;AAAA;AAAA,EAGA,SAAS,SAAyC;AAChD,WAAO,cAAc,MAAM,SAAS,KAAK,SAAS;AAAA,EACpD;AAAA,EAEA,kBAAkB,MAAc,YAA4B,SAA0B,KAAoB;AACxG,eAAW,SAAS,eAAe,MAAM,SAAS,GAAG,GAAG;AACtD,WAAK,SAAS,MAAM,OAAO,MAAM,KAAK,CAAC,YAAY,MAAM,MAAM,CAAgB,EAAE,KAAK,MAAM,IAAI;AAAA,IAClG;AAAA,EACF;AACF;;;AS/TA,SAAS,YAAY,uBAAuB;AAC5C,SAAS,kBAAkB,WAAW,aAAa,eAAkD;AACrG,SAAS,oBAAAC,yBAAwB;AAKjC,IAAM,YAAY;AAGlB,IAAM,gBAAgB,CAAC,UAAqD;AAC1E,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,YAAY,OAAO,eAAe,KAAK;AAC7C,SAAO,cAAc,OAAO,aAAa,cAAc;AACzD;AAGO,SAAS,WAAW,QAAyC;AAClE,QAAM,QAAkB,CAAC;AACzB,QAAM,MAAM,CAAC,KAAa,UAAyB;AACjD,QAAI,UAAU,QAAQ,UAAU,OAAW;AAC3C,QAAI,OAAO,UAAU,aAAa,MAAM,QAAQ,KAAK,KAAK,cAAc,KAAK,IAAI;AAC/E,iBAAW,CAAC,OAAO,MAAM,KAAK,OAAO,QAAQ,KAAK,EAAG,KAAI,GAAG,GAAG,IAAI,KAAK,KAAK,MAAM;AACnF;AAAA,IACF;AACA,UAAM,OAAO,UAAU,OAAO,MAAM,UAAU,QAAQ,MAAM,OAAO,KAAK;AACxE,UAAM,KAAK,GAAG,mBAAmB,GAAG,CAAC,IAAI,mBAAmB,IAAI,CAAC,EAAE;AAAA,EACrE;AACA,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,EAAG,KAAI,KAAK,KAAK;AACjE,SAAO,MAAM,KAAK,GAAG;AACvB;AAGA,SAAS,SAAS,OAAgB,OAAoC;AACpE,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,QAAQ;AACd,MAAI,UAAU,OAAW,QAAO,OAAO,MAAM,iBAAiB,aAAa,MAAM,aAAa,KAAK,IAAI,MAAM,KAAK;AAClH,SAAO,OAAO,MAAM,gBAAgB,aAAa,MAAM,YAAY,IAAI;AACzE;AAGA,SAAS,KAAK,KAAa,KAAyB;AAClD,SAAO,WAAW,UAAU,GAAG,EAAE,OAAO,GAAG,EAAE,OAAO,KAAK;AAC3D;AAGA,SAAS,WAAW,UAAkB,OAAwB;AAC5D,QAAM,IAAI,OAAO,KAAK,QAAQ;AAC9B,QAAM,IAAI,OAAO,KAAK,KAAK;AAC3B,SAAO,EAAE,WAAW,EAAE,UAAU,gBAAgB,GAAG,CAAC;AACtD;AAGA,SAAS,YAAY,YAAmC;AACtD,SAAO,sBAAsB,OAAO,KAAK,MAAM,WAAW,QAAQ,IAAI,GAAI,IAAI,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAI;AAChH;AAGO,IAAM,mBAAN,MAA+C;AAAA,EACpD,YACmB,QACA,WACjB;AAFiB;AACA;AAAA,EAChB;AAAA,EAFgB;AAAA,EACA;AAAA;AAAA,EAInB,OAAe;AACb,UAAM,UAAU,KAAK,SAAS;AAC9B,QAAI,YAAY,OAAW,QAAO,IAAI,IAAI,QAAQ,IAAI,CAAC,EAAE;AACzD,UAAM,aAAa,KAAK,QAA4B,WAAW,MAAS;AACxE,YAAQ,cAAc,oBAAoB,QAAQ,QAAQ,EAAE;AAAA,EAC9D;AAAA,EAEA,GAAG,MAAc,QAAiC,CAAC,GAAG,WAAW,MAAc;AAC7E,UAAM,cAAc,WAAW,KAAK;AACpC,UAAM,OAAO,UAAU,KAAK,IAAI,IAAI,OAAO,KAAK,MAAM,MAAM,QAAQ;AACpE,QAAI,gBAAgB,GAAI,QAAO;AAC/B,WAAO,GAAG,IAAI,GAAG,KAAK,SAAS,GAAG,IAAI,MAAM,GAAG,GAAG,WAAW;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,MAAc,YAAsB,WAAW,MAAc;AACjE,UAAM,QAAQ,KAAK,OAAO,UAAU,IAAI;AACxC,QAAI,UAAU,OAAW,OAAM,IAAI,qBAAqB,IAAI;AAC5D,UAAM,QAAiC,cAAc,UAAU,IAAI,EAAE,GAAG,WAAW,IAAI,CAAC;AACxF,UAAM,aAAwB,MAAM,QAAQ,UAAU,IAClD,CAAC,GAAG,UAAU,IACd,eAAe,UAAa,eAAe,QAAQ,cAAc,UAAU,IACzE,CAAC,IACD,CAAC,UAAU;AAEjB,UAAM,SAAS,oBAAI,IAAgC;AACnD,UAAM,UAAoB,CAAC;AAC3B,eAAW,aAAa,MAAM,YAAY;AACxC,UAAI;AACJ,UAAI,OAAO,OAAO,OAAO,UAAU,IAAI,GAAG;AACxC,gBAAQ,MAAM,UAAU,IAAI;AAC5B,eAAO,MAAM,UAAU,IAAI;AAAA,MAC7B,WAAW,WAAW,SAAS,GAAG;AAChC,gBAAQ,WAAW,MAAM;AAAA,MAC3B;AACA,YAAM,MAAM,SAAS,OAAO,UAAU,KAAK;AAC3C,YAAM,OAAO,QAAQ,UAAa,QAAQ,OAAO,SAAY,OAAO,GAAG;AACvE,UAAI,SAAS,UAAa,CAAC,UAAU,SAAU,SAAQ,KAAK,UAAU,IAAI;AAC1E,aAAO,IAAI,UAAU,MAAM,IAAI;AAAA,IACjC;AACA,QAAI,QAAQ,SAAS,EAAG,OAAM,IAAI,mBAAmB,MAAM,MAAM,KAAK,OAAO;AAE7E,UAAM,OACJ,MAAM,QAAQ,MACV,KACA,MAAM,IACH,MAAM,GAAG,EACT,OAAO,CAAC,YAAY;AACnB,YAAM,QAAQ,eAAe,KAAK,OAAO;AACzC,aAAO,UAAU,QAAQ,OAAO,IAAI,MAAM,CAAC,CAAE,MAAM;AAAA,IACrD,CAAC,EACA;AAAA,MAAI,CAAC,YACJ,QAAQ,QAAQ,WAAW,CAAC,QAAQ,cAAsB;AACxD,cAAM,QAAQ,OAAO,IAAI,SAAS;AAClC,eAAO,UAAU,SAAY,KAAK,mBAAmB,KAAK;AAAA,MAC5D,CAAC;AAAA,IACH,EACC,KAAK,GAAG;AACjB,UAAM,QAAQ,OAAO,YAAY,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,SAAS,OAAO,MAAS,CAAC,CAAC,CAAC;AAC/G,WAAO,KAAK,GAAG,MAAM,OAAO,QAAQ;AAAA,EACtC;AAAA,EAEA,MAAM,MAAsB;AAC1B,QAAI,UAAU,KAAK,IAAI,EAAG,QAAO;AACjC,UAAM,OAAO,KAAK,QAA4B,iBAAiB,MAAS,GAAG,QAAQ,QAAQ,EAAE,KAAK,KAAK,KAAK;AAC5G,UAAM,UAAU,KAAK,QAAQ,QAAQ,EAAE;AACvC,WAAO,YAAY,KAAK,OAAO,GAAG,IAAI,IAAI,OAAO;AAAA,EACnD;AAAA;AAAA,EAGA,UAAkB;AAChB,WAAO,KAAK,SAAS,GAAG,IAAI,KAAK,KAAK,KAAK;AAAA,EAC7C;AAAA;AAAA,EAGA,OAAe;AACb,WAAO,KAAK,SAAS,GAAG,QAAQ,KAAK,KAAK,KAAK;AAAA,EACjD;AAAA;AAAA,EAGA,SAAS,UAA2B;AAClC,UAAM,QAAQ,KAAK,OAAO;AAC1B,UAAM,UAAU,KAAK,SAAS;AAC9B,UAAM,UAAU,SAAS,OAAO,SAAS;AACzC,QAAI,YAAY,UAAa,YAAY,GAAI,QAAO,KAAK,GAAG,OAAO;AACnE,QAAI,YAAY,UAAa,OAAO,MAAM,OAAO,GAAG;AAClD,YAAM,WAAW,MAAM,KAAK,OAAO,EAAE,YAAY;AACjD,UAAI,aAAa,UAAa,aAAa,GAAI,QAAO,KAAK,GAAG,QAAQ;AAAA,IACxE;AACA,WAAO,KAAK,GAAG,YAAY,GAAG;AAAA,EAChC;AAAA,EAEA,SAAS,MAAuB;AAC9B,WAAO,KAAK,OAAO,UAAU,IAAI,MAAM;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,MAAc,YAAsB,YAA4B,WAAW,MAAc;AACnG,UAAM,QAAQ,KAAK,iBAAiB,MAAM,UAAU;AACpD,eAAW,YAAY,CAAC,aAAa,SAAS,GAAG;AAC/C,UAAI,OAAO,OAAO,OAAO,QAAQ,GAAG;AAClC,cAAM,IAAI,aAAa,IAAI,QAAQ,8FAA8F;AAAA,MACnI;AAAA,IACF;AACA,QAAI,eAAe,OAAW,OAAM,UAAU,YAAY,UAAU;AACpE,UAAM,SAAS,OAAO,YAAY,OAAO,KAAK,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC;AAC3F,UAAM,YAAY,KAAK,KAAK,MAAM,MAAM,QAAQ,QAAQ,GAAG,KAAK,aAAa,EAAE,CAAC,CAAE;AAClF,WAAO,KAAK,MAAM,MAAM,EAAE,GAAG,QAAQ,UAAU,GAAG,QAAQ;AAAA,EAC5D;AAAA;AAAA,EAGA,qBAAqB,MAAc,YAA2B,YAAsB,WAAW,MAAc;AAC3G,WAAO,KAAK,YAAY,MAAM,YAAY,YAAY,QAAQ;AAAA,EAChE;AAAA;AAAA,EAGA,kBAAkB,SAAsB,WAAW,MAAe;AAChE,WAAO,KAAK,oBAAoB,SAAS,QAAQ,KAAK,KAAK,uBAAuB,OAAO;AAAA,EAC3F;AAAA;AAAA,EAGA,oBAAoB,SAAsB,WAAW,MAAe;AAClE,UAAM,OAAO,IAAI,IAAI,QAAQ,QAAQ,CAAC;AACtC,UAAM,OAAO,QAAQ,KAAK;AAC1B,UAAM,MAAM,WAAW,QAAQ,IAAI,IAAI,SAAS,MAAM,MAAM,IAAI,IAAI;AACpE,UAAM,QAAQ,KAAK,OAChB,MAAM,CAAC,EACP,MAAM,GAAG,EACT,OAAO,CAAC,SAAS,SAAS,MAAM,KAAK,MAAM,GAAG,EAAE,CAAC,MAAM,WAAW,EAClE,KAAK,GAAG;AACX,UAAM,WAAW,UAAU,KAAK,MAAM,GAAG,GAAG,IAAI,KAAK;AACrD,UAAM,QAAQ,KAAK,aAAa,IAAI,WAAW,KAAK;AACpD,WAAO,KAAK,aAAa,EAAE,KAAK,CAAC,QAAQ,WAAW,KAAK,UAAU,GAAG,GAAG,KAAK,CAAC;AAAA,EACjF;AAAA;AAAA,EAGA,uBAAuB,SAA+B;AACpD,UAAM,UAAU,IAAI,IAAI,QAAQ,QAAQ,CAAC,EAAE,aAAa,IAAI,SAAS;AACrE,QAAI,YAAY,QAAQ,YAAY,GAAI,QAAO;AAC/C,UAAM,KAAK,OAAO,OAAO;AACzB,WAAO,OAAO,SAAS,EAAE,KAAK,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,KAAK;AAAA,EACjE;AAAA;AAAA,EAGA,iBAAiB,MAAc,YAA8C;AAC3E,QAAI,cAAc,UAAU,EAAG,QAAO,EAAE,GAAG,WAAW;AACtD,UAAM,QAAQ,KAAK,OAAO,UAAU,IAAI;AACxC,QAAI,UAAU,OAAW,OAAM,IAAI,qBAAqB,IAAI;AAC5D,UAAM,SAAS,eAAe,UAAa,eAAe,OAAO,CAAC,IAAI,MAAM,QAAQ,UAAU,IAAI,aAAa,CAAC,UAAU;AAC1H,UAAM,QAAiC,CAAC;AACxC,UAAM,WAAW,QAAQ,CAAC,WAAW,UAAU;AAC7C,UAAI,QAAQ,OAAO,OAAQ,OAAM,UAAU,IAAI,IAAI,OAAO,KAAK;AAAA,IACjE,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,eAA6B;AAC3B,UAAM,QAAQ,KAAK,OAAO;AAC1B,QAAI,UAAU,UAAa,CAAC,MAAM,MAAM,SAAS,GAAG;AAClD,YAAM,IAAI,aAAa,mEAAmE;AAAA,IAC5F;AACA,UAAM,YAAY,MAAM,KAAK,SAAS;AACtC,WAAO,OAAO,UAAU,eAAe,aAAa,UAAU,WAAW,IAAI,CAAC,UAAU,OAAO,CAAC;AAAA,EAClG;AAAA,EAEA,MAAM,MAAc,UAA2B;AAC7C,UAAM,UAAU,KAAK,QAAQ,cAAc,EAAE;AAC7C,QAAI,CAAC,SAAU,QAAO,IAAI,OAAO;AACjC,WAAO,YAAY,KAAK,KAAK,KAAK,IAAI,GAAG,KAAK,KAAK,CAAC,IAAI,OAAO;AAAA,EACjE;AAAA,EAEA,SAAgC;AAC9B,WAAOC,kBAAiB,KAAK,KAAK;AAAA,EACpC;AAAA;AAAA,EAGA,WAAoC;AAClC,UAAM,QAAQ,KAAK,OAAO;AAC1B,WAAO,OAAO,MAAM,WAAW,IAAI,MAAM,KAAK,WAAW,IAAI;AAAA,EAC/D;AAAA,EAEA,QAAW,KAAa,UAAgB;AACtC,UAAM,QAAQ,KAAK,OAAO;AAC1B,WAAO,OAAO,MAAM,gBAAgB,IAAI,MAAM,KAAK,gBAAgB,EAAE,IAAO,KAAK,QAAQ,IAAI;AAAA,EAC/F;AACF;;;ACnQA,SAAS,cAA6B;AACtC,SAAS,cAAc;AAOhB,IAAM,QAAQ,OAAmB,MAA8B;;;ACRtE,SAAS,oBAAAC,mBAAkB,iBAAiB,oBAAAC,yBAAwC;AAS7E,IAAM,mBAAN,MAAuB;AAAC;AAW/B,IAAM,aAAa,CAAC,UAA0B,MAAM,QAAQ,YAAY,CAAC,SAAS,KAAK,KAAK,WAAW,CAAC,CAAC,GAAG;AAG5G,IAAM,QACJ;AAWK,SAAS,eAAe,OAAmB,CAAC,GAAa;AAC9D,QAAM,UAAU,KAAK,WAAW;AAChC,QAAM,OAAO,KAAK,iBAAiB,SAAY,KAAK,4CAA4C,KAAK,MAAM,KAAK,YAAY,CAAC;AAC7H,QAAMC,QACJ;AAAA;AAAA;AAAA;AAAA;AAAA,SAEU,WAAW,KAAK,WAAW,OAAO,CAAC;AAAA,SAAoB,KAAK;AAAA;AAAA;AAAA;AAAA,eACtD,UAAU,QAAQ,UAAU;AAAA;AAAA,kBAClB,UAAU,OAAO,uBAAuB;AAAA,2BAAmC,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAE3G,SAAO,IAAI,SAASA,OAAM,EAAE,QAAQ,UAAU,MAAM,KAAK,SAAS,EAAE,gBAAgB,2BAA2B,EAAE,CAAC;AACpH;AAMA,eAAsB,eAAe,KAAmC;AACtE,QAAM,UAAU,YAAY,IAAI;AAChC,QAAM,SAAS,IAAI,MAAMF,iBAAgB,IAAI,IAAI,KAAKA,iBAAgB,IAAI;AAC1E,MAAI,UAAU;AACd,MAAI;AACF,QAAI,IAAI,MAAM,eAAe,EAAG,OAAM,IAAI,KAAK,eAAe,EAAE,SAAS,IAAI,iBAAiB,CAAC;AAAA,EACjG,SAAS,OAAO;AACd,QAAI,QAAQ,IAAa,aAAa,KAAK,MAAM,KAAM,OAAM;AAC7D,QAAI,IAAI,MAAMC,iBAAgB,EAAG,OAAM,IAAI,KAAKA,iBAAgB,EAAE,OAAO,KAAK;AAC9E,cAAU;AAAA,EACZ;AACA,QAAM,UAAU,OAAO,QAAQ,IAAI,YAAY,OAAO,KAAK,OAAO;AAClE,SAAO,eAAe,EAAE,SAAS,SAAS,cAAc,YAAY,IAAI,IAAI,QAAQ,CAAC;AACvF;;;ACjEA,SAAS,qBAAqB;AAM9B,IAAI,aAAa;AAOjB,eAAsB,eAAe,KAAkB,QAAgB,MAA6B;AAClG,QAAM,MAAM,GAAG,cAAc,IAAI,EAAE,IAAI,iBAAiB,EAAE,UAAU;AACpE,QAAM,SAAU,MAAM,IAAI,IAAI,MAAM;AAAA;AAAA,IAA0B;AAAA,GAAI;AAClE,MAAI,OAAO,OAAO,YAAY,WAAY,OAAM,IAAI,IAAI,MAAO,OAAO,QAA8B,MAAM,CAAC;AAC7G;;;ACjBA,SAAS,UAAAE,SAAQ,cAAc,gBAAAC,qBAAoB;AACnD,SAAS,uBAAuB;;;ACDhC,SAAS,kBAAkB;AAC3B,SAAS,mBAAiE;AAC1E,SAAS,cAAc;AAGvB,IAAM,OAAO,CAAC,UAA0B,WAAW,MAAM,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK;AAGrF,SAAS,YAAY,UAAoB,SAA2C;AAClF,MAAI;AACF,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,OAAO,EAAG,UAAS,QAAQ,IAAI,MAAM,KAAK;AACrF,WAAO;AAAA,EACT,QAAQ;AACN,UAAM,OAAO,IAAI,QAAQ,SAAS,OAAO;AACzC,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,OAAO,EAAG,MAAK,IAAI,MAAM,KAAK;AACzE,WAAO,IAAI,SAAS,SAAS,MAAM,EAAE,QAAQ,SAAS,QAAQ,YAAY,SAAS,YAAY,SAAS,KAAK,CAAC;AAAA,EAChH;AACF;AAOO,IAAM,mBAAN,MAA6C;AAAA,EAClD,MAAM,OAAO,SAAsB,MAAY,cAAc,MAAM,eAAe,KAAK,SAAS,IAAuB;AACrH,UAAM,MAAM,OAAO,WAAW;AAC9B,UAAM,QAAQ,OAAO,YAAY;AACjC,QAAI,YAAY,KAAK,MAAM,MAAM,CAAC,OAAO,UAAU,GAAG,KAAK,MAAM,KAAK,aAAa,KAAK,MAAM,MAAM,CAAC,OAAO,SAAS,KAAK,KAAK,SAAS,GAAG;AACzI,YAAM,IAAI;AAAA,QACR,gCAAgC,WAAW,IAAI,YAAY;AAAA,MAC7D;AAAA,IACF;AACA,UAAM,UAAU,OAAO,WAAW;AAClC,UAAM,MAAM,SAAU,MAAM,KAAK,wBAAwB,OAAO;AAChE,QAAI,MAAM,QAAQ,gBAAgB,KAAK,GAAG,GAAG;AAC3C,YAAM,aAAa,MAAM,QAAQ,YAAY,GAAG;AAChD,YAAM,IAAI,sBAAsB;AAAA,QAC9B,qBAAqB,OAAO,GAAG;AAAA,QAC/B,yBAAyB;AAAA,QACzB,eAAe,OAAO,UAAU;AAAA,QAChC,qBAAqB,OAAO,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAI,UAAU;AAAA,MACxE,CAAC;AAAA,IACH;AACA,UAAM,QAAQ,IAAI,KAAK,KAAK,MAAM,QAAQ,EAAE,CAAC;AAC7C,UAAM,WAAW,MAAM,KAAK,OAAO;AACnC,WAAO,YAAY,UAAU;AAAA,MAC3B,qBAAqB,OAAO,GAAG;AAAA,MAC/B,yBAAyB,OAAO,MAAM,QAAQ,UAAU,KAAK,GAAG,CAAC;AAAA,IACnE,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAgB,wBAAwB,SAAuC;AAC7E,UAAM,OAAO,MAAM,QAAQ,KAAwC;AACnE,QAAI,SAAS,UAAa,SAAS,QAAQ,OAAO,KAAK,sBAAsB,YAAY;AACvF,aAAO,KAAK,OAAO,KAAK,kBAAkB,CAAC,CAAC;AAAA,IAC9C;AACA,WAAO,KAAK,IAAI,QAAQ,GAAG,KAAK,EAAE,EAAE;AAAA,EACtC;AACF;;;AC5DA,SAAS,gBAAAC,qBAAkE;AAC3E,SAAS,UAAAC,eAAc;AAOhB,IAAM,oBAAN,MAA8C;AAAA,EACnD,MAAM,OAAO,SAAsB,SAAe,YAAyC;AACzF,UAAM,WAAW,WAAW,CAAC,MAAM;AACnC,QAAIC,QAAOC,aAAY,EAAE,kBAAkB,SAAS,QAAQ,EAAG,QAAO,KAAK,OAAO;AAClF,UAAM,IAAI,yBAAyB;AAAA,EACrC;AACF;;;AFEO,IAAM,yBAAN,cAAqC,gBAAgB;AAAA,EACjD,WAAiB;AACxB,SAAK,IAAI,UAAUC,SAAQ,MAAM,IAAI,WAAW,KAAK,GAAG,CAAC;AACzD,SAAK,IAAI,UAAUC,eAAc,MAAM;AACrC,YAAM,SAAS,KAAK,IAAI,KAAKD,OAAM;AACnC,UAAI,EAAE,kBAAkB,aAAa;AACnC,cAAM,IAAI,aAAa,iGAAiG;AAAA,MAC1H;AACA,aAAO,IAAI,iBAAiB,QAAQ,KAAK,GAAG;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOS,OAAa;AACpB,SAAK,IAAI,KAAKA,OAAM,EAAE,gBAAgB,UAAU,iBAAiB,EAAE,gBAAgB,YAAY,gBAAgB;AAC/G,SAAK,IAAI,OAAO,YAAY;AAC1B,UAAI,CAAC,KAAK,IAAI,MAAM,YAAY,EAAG;AACnC,YAAM,EAAE,KAAK,KAAK,QAAQ,UAAU,IAAI,KAAK,IAAI,KAAK,YAAY;AAClE,YAAM,SAAS,KAAK,IAAI,KAAKA,OAAM;AACnC,UAAI,WAAW,OAAW,QAAO,IAAI,QAAQ,MAAM,eAAe,KAAK,GAAG,CAAC;AAC3E,UAAI,QAAQ,OAAW,OAAM,OAAO,WAAW,KAAK,EAAE,MAAM,MAAM,KAAK,MAAM,QAAQ,GAAG,CAAC;AACzF,UAAI,QAAQ,OAAW,OAAM,OAAO,OAAO,SAAS,EAAE,WAAW,KAAK,EAAE,MAAM,MAAM,KAAK,MAAM,QAAQ,GAAG,CAAC;AAAA,IAC7G,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,MAAM,QAAgB,OAAyC;AACnE,eAAW,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAG,OAAM,eAAe,KAAK,KAAK,QAAQ,IAAI;AAAA,EAChF;AACF;","names":["CurrentRoute","currentContainer","Str","currentContainer","CurrentRoute","currentContainer","currentContainer","ConfigRepository","ExceptionHandler","html","Router","UrlGenerator","UrlGenerator","inject","inject","UrlGenerator","Router","UrlGenerator"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orieljs/routing",
3
- "version": "0.1.0-alpha.6",
3
+ "version": "0.1.0-alpha.8",
4
4
  "description": "The Oriel Routing component.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -27,12 +27,13 @@
27
27
  "files": [
28
28
  "dist",
29
29
  "LICENSE",
30
- "NOTICE"
30
+ "NOTICE",
31
+ "TRADEMARKS.md"
31
32
  ],
32
33
  "dependencies": {
33
- "@orieljs/contracts": "0.1.0-alpha.6",
34
- "@orieljs/container": "0.1.0-alpha.6",
35
- "@orieljs/support": "0.1.0-alpha.6"
34
+ "@orieljs/contracts": "0.1.0-alpha.8",
35
+ "@orieljs/container": "0.1.0-alpha.8",
36
+ "@orieljs/support": "0.1.0-alpha.8"
36
37
  },
37
38
  "scripts": {
38
39
  "build": "tsup && node ../../../scripts/copy-license.mjs"