@orieljs/routing 0.1.0-alpha.3 → 0.1.0-alpha.5

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/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Route as Route$1, RouteAction, Class, MiddlewareReference, RouteRegistrar, ResourceOptions, ControllerAction, RouteClosure, InvokableClass, Router, Container, MiddlewareClass, HttpRequest, UrlGenerator, OrielError, Middleware, ModelNotFoundError, Application } from '@orieljs/contracts';
1
+ import { Route as Route$1, RouteAction, Class, MiddlewareReference, RouteRegistrar, ResourceOptions, ControllerAction, RouteClosure, InvokableClass, Router, Container, MiddlewareClass, HttpRequest, UrlGenerator, OrielError, Middleware, ModelNotFoundError, Application, Next } from '@orieljs/contracts';
2
2
  import * as _orieljs_support from '@orieljs/support';
3
3
  import { ServiceProvider } from '@orieljs/support';
4
4
 
@@ -38,7 +38,8 @@ declare class RouteDefinition implements Route$1 {
38
38
  getName(): string | undefined;
39
39
  /** Appends, like Laravel's $action['as'] .= $name. */
40
40
  name(name: string): this;
41
- middleware(...middleware: MiddlewareReference[]): this;
41
+ /** middleware('auth', 'verified') or middleware(['auth', 'verified']). */
42
+ middleware(...middleware: Array<MiddlewareReference | readonly MiddlewareReference[]>): this;
42
43
  withoutMiddleware(...middleware: MiddlewareReference[]): this;
43
44
  where(parameter: string | Record<string, string>, pattern?: string): this;
44
45
  gatherMiddleware(): MiddlewareReference[];
@@ -78,7 +79,7 @@ declare class GroupRegistrar implements RouteRegistrar {
78
79
  constructor(router: GroupHost);
79
80
  prefix(prefix: string): this;
80
81
  name(prefix: string): this;
81
- middleware(...middleware: MiddlewareReference[]): this;
82
+ middleware(...middleware: Array<MiddlewareReference | readonly MiddlewareReference[]>): this;
82
83
  controller(controller: Class<unknown>): this;
83
84
  group(routes: () => void | Promise<void>): Promise<void>;
84
85
  get<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): RouteDefinition;
@@ -128,7 +129,7 @@ declare class BaseRouter implements Router {
128
129
  fallback(action: RouteAction): RouteDefinition;
129
130
  prefix(prefix: string): GroupRegistrar;
130
131
  name(prefix: string): GroupRegistrar;
131
- middleware(...middleware: MiddlewareReference[]): GroupRegistrar;
132
+ middleware(...middleware: Array<MiddlewareReference | readonly MiddlewareReference[]>): GroupRegistrar;
132
133
  controller(controller: Class<unknown>): GroupRegistrar;
133
134
  /**
134
135
  * Laravel's Route::group(attributes, callback). A synchronous callback's attributes are popped before this
@@ -144,6 +145,12 @@ declare class BaseRouter implements Router {
144
145
  getPatternVersion(): number;
145
146
  getBinder(parameter: string): RouteBinder | undefined;
146
147
  getModel(parameter: string): Class<unknown> | undefined;
148
+ /**
149
+ * Binds a matched route's raw parameter values as a request to it would: Route.bind() callbacks, Route.model(),
150
+ * then implicit binding through the RouteModelResolver of `container`. A missing model throws
151
+ * RouteModelNotFoundError (404). Live uses it to check a page route's `can:` middleware again on each update.
152
+ */
153
+ substituteBindings(route: RouteDefinition, values: Readonly<Record<string, string | undefined>>, container: Container): Promise<Record<string, unknown>>;
147
154
  aliasMiddleware(name: string, middleware: MiddlewareClass): this;
148
155
  /** The middleware aliases (Laravel's Router::getMiddleware()). */
149
156
  getMiddleware(): Record<string, MiddlewareClass>;
@@ -191,6 +198,20 @@ declare class BaseUrlGenerator implements UrlGenerator {
191
198
  /** The Referer header, then the session's previous URL, then `fallback`, then the root (Laravel's order). */
192
199
  previous(fallback?: string): string;
193
200
  hasRoute(name: string): boolean;
201
+ /**
202
+ * Laravel's URL::signedRoute(): the route URL with its parameters sorted by name, then a `signature` query (the
203
+ * HMAC-SHA256 of that URL, keyed by APP_KEY). `expiration` (a Date, or seconds from now) adds `expires`.
204
+ * `absolute: false` signs the path only (checked by `signed:relative`).
205
+ */
206
+ signedRoute(name: string, parameters?: unknown, expiration?: Date | number, absolute?: boolean): string;
207
+ /** Laravel's URL::temporarySignedRoute(): a signed URL that expires at `expiration` (a Date, or seconds from now). */
208
+ temporarySignedRoute(name: string, expiration: Date | number, parameters?: unknown, absolute?: boolean): string;
209
+ /** The request URL carries a correct signature (current or previous APP_KEY) that hasn't expired. */
210
+ hasValidSignature(request: HttpRequest, absolute?: boolean): boolean;
211
+ /** The signature matches the URL without its `signature` query, in a constant-time comparison. */
212
+ hasCorrectSignature(request: HttpRequest, absolute?: boolean): boolean;
213
+ /** No `expires` query, or one that is still in the future. */
214
+ signatureHasNotExpired(request: HttpRequest): boolean;
194
215
  }
195
216
 
196
217
  /** A middleware reference after alias and group expansion: 'throttle:60,1' → { cls: Throttle, parameters: ['60', '1'] }. */
@@ -305,6 +326,21 @@ declare class RoutingError extends Error implements OrielError {
305
326
  readonly status = 500;
306
327
  readonly name = "RoutingError";
307
328
  }
329
+ /** A signed URL whose signature is missing, wrong or expired (Laravel's InvalidSignatureException). */
330
+ declare class InvalidUrlSignatureError extends Error implements OrielError {
331
+ readonly kind: "Http";
332
+ readonly status = 403;
333
+ readonly name = "InvalidUrlSignatureError";
334
+ constructor();
335
+ }
336
+ /** Too many requests in the window (Laravel's ThrottleRequestsException): 429 with Retry-After and X-RateLimit-*. */
337
+ declare class ThrottleRequestsError extends Error implements OrielError {
338
+ readonly headers: Record<string, string>;
339
+ readonly kind: "Http";
340
+ readonly status = 429;
341
+ readonly name = "ThrottleRequestsError";
342
+ constructor(headers?: Record<string, string>);
343
+ }
308
344
 
309
345
  type ResourceMethod = 'index' | 'create' | 'store' | 'show' | 'edit' | 'update' | 'destroy';
310
346
  interface ResourceRoute {
@@ -328,6 +364,29 @@ declare function toResponse(request: unknown, value: unknown): Promise<Response>
328
364
  */
329
365
  declare const Route: _orieljs_support.Facade<BaseRouter, object>;
330
366
 
367
+ /**
368
+ * Dispatched by the health route (`/up`) on every request (Laravel's DiagnosingHealth event). A listener checks
369
+ * something the application needs, such as the database or the cache, and throws when it fails: `/up` then answers
370
+ * 500 with "Application experiencing problems", and the exception is reported.
371
+ *
372
+ * Event.listen(DiagnosingHealth, async () => { await DB.select('select 1') })
373
+ */
374
+ declare class DiagnosingHealth {
375
+ }
376
+ interface HealthPage {
377
+ /** False when a check failed: the page says so and the status is 500 (default true). */
378
+ healthy?: boolean;
379
+ /** How long the request took, shown when given. */
380
+ milliseconds?: number;
381
+ /** The page title (default "Oriel"). */
382
+ appName?: string;
383
+ }
384
+ /**
385
+ * The health route's page (Laravel's health-up view): "Application up", or "Application experiencing problems" with
386
+ * status 500. Self-contained HTML with inline CSS: it loads nothing, so it answers even when the assets don't.
387
+ */
388
+ declare function healthResponse(page?: HealthPage): Response;
389
+
331
390
  /** A route file may export a function instead of (or as well as) calling the Route facade at the top level. */
332
391
  type RouteFileCallback = (router: Router) => void | Promise<void>;
333
392
  /**
@@ -336,15 +395,15 @@ type RouteFileCallback = (router: Router) => void | Promise<void>;
336
395
  * A default export that is a function is called with the router.
337
396
  */
338
397
  declare function loadRoutesFrom(app: Application, router: Router, file: string): Promise<void>;
339
- /** The health route's page (Laravel's `/up`): 200 as long as the application boots and handles requests. */
340
- declare function healthResponse(): Response;
341
398
 
342
399
  /**
343
- * Binds the Router and the UrlGenerator, and once the app has booted loads the files given to withRouting(): the health URI,
344
- * then routes/web.ts in the `web` middleware group, then routes/api.ts under the api prefix in the `api` group
345
- * (Laravel's ApplicationBuilder::withRouting).
400
+ * Binds the Router and the UrlGenerator, registers the `signed` and `throttle` middleware, and once the app has booted
401
+ * loads the files given to withRouting(): the health URI (which dispatches DiagnosingHealth), then the web files in the
402
+ * `web` middleware group, then the api files under the api prefix in the `api` group (Laravel's
403
+ * ApplicationBuilder::withRouting).
346
404
  */
347
405
  declare class RoutingServiceProvider extends ServiceProvider {
406
+ #private;
348
407
  register(): void;
349
408
  /**
350
409
  * The files load in a booted() callback, after every provider's boot() (Laravel's withRouting does the same), so
@@ -354,4 +413,23 @@ declare class RoutingServiceProvider extends ServiceProvider {
354
413
  boot(): void;
355
414
  }
356
415
 
357
- export { BaseRouter, BaseUrlGenerator, ControllerMethodNotFoundError, type GroupAttributes, type GroupHost, GroupRegistrar, MethodNotAllowedHttpError, MiddlewareNotFoundError, NotFoundHttpError, type ResolvedMiddleware, type ResourceMethod, type ResourceRoute, Route, type RouteAttributes, type RouteBinder, RouteDefinition, type RouteFileCallback, type RouteHandler, RouteModelNotFoundError, RouteNotDefinedError, type RouteStage, RoutingError, RoutingServiceProvider, type UriParameter, UrlGenerationError, buildQuery, compareRoutes, dispatchRoute, healthResponse, loadRoutesFrom, mergeGroup, normalizePath, normalizeUri, orderForBindings, parseParameters, renderError, resolveMiddleware, resourceRoutes, runMiddleware, substituteBindings, toResponse };
416
+ /**
417
+ * Laravel's ThrottleRequests (`throttle:<maxAttempts>,<decayMinutes>[,<prefix>]`): counts the client's requests
418
+ * (the signed-in user, else the IP) in a window and answers 429 once there are too many. Responses carry
419
+ * X-RateLimit-Limit and X-RateLimit-Remaining; the 429 adds Retry-After and X-RateLimit-Reset.
420
+ */
421
+ declare class ThrottleRequests implements Middleware {
422
+ handle(request: HttpRequest, next: Next, maxAttempts?: string, decayMinutes?: string, prefix?: string): Promise<Response>;
423
+ /** The signed-in user's identifier, else the client IP, hashed (Laravel's resolveRequestSignature()). */
424
+ protected resolveRequestSignature(request: HttpRequest): string;
425
+ }
426
+
427
+ /**
428
+ * Laravel's ValidateSignature (`signed`, `signed:relative`): the request URL must carry a valid, unexpired
429
+ * signature from URL.signedRoute()/temporarySignedRoute(), else 403. `relative` checks a path-only signature.
430
+ */
431
+ declare class ValidateSignature implements Middleware {
432
+ handle(request: HttpRequest, next: Next, ...parameters: string[]): Promise<Response>;
433
+ }
434
+
435
+ export { BaseRouter, BaseUrlGenerator, ControllerMethodNotFoundError, DiagnosingHealth, type GroupAttributes, type GroupHost, GroupRegistrar, type HealthPage, InvalidUrlSignatureError, MethodNotAllowedHttpError, MiddlewareNotFoundError, NotFoundHttpError, type ResolvedMiddleware, type ResourceMethod, type ResourceRoute, Route, type RouteAttributes, type RouteBinder, RouteDefinition, type RouteFileCallback, type RouteHandler, RouteModelNotFoundError, RouteNotDefinedError, type RouteStage, RoutingError, RoutingServiceProvider, ThrottleRequests, ThrottleRequestsError, type UriParameter, UrlGenerationError, ValidateSignature, buildQuery, compareRoutes, dispatchRoute, healthResponse, loadRoutesFrom, mergeGroup, normalizePath, normalizeUri, orderForBindings, parseParameters, renderError, resolveMiddleware, resourceRoutes, runMiddleware, substituteBindings, toResponse };
package/dist/index.js CHANGED
@@ -7,10 +7,6 @@ import {
7
7
  } from "@orieljs/contracts";
8
8
  import { currentContainer as currentContainer2 } from "@orieljs/container";
9
9
 
10
- // dispatch.ts
11
- import { CurrentRoute } from "@orieljs/contracts";
12
- import { currentContainer } from "@orieljs/container";
13
-
14
10
  // bindings.ts
15
11
  import { RouteModelResolver } from "@orieljs/contracts";
16
12
  import { BindingResolutionError } from "@orieljs/container";
@@ -70,6 +66,24 @@ var RoutingError = class extends Error {
70
66
  status = 500;
71
67
  name = "RoutingError";
72
68
  };
69
+ var InvalidUrlSignatureError = class extends Error {
70
+ kind = "Http";
71
+ status = 403;
72
+ name = "InvalidUrlSignatureError";
73
+ constructor() {
74
+ super("Invalid signature.");
75
+ }
76
+ };
77
+ var ThrottleRequestsError = class extends Error {
78
+ constructor(headers = {}) {
79
+ super("Too Many Attempts.");
80
+ this.headers = headers;
81
+ }
82
+ headers;
83
+ kind = "Http";
84
+ status = 429;
85
+ name = "ThrottleRequestsError";
86
+ };
73
87
 
74
88
  // middleware.ts
75
89
  import {
@@ -238,6 +252,10 @@ async function substituteBindings(router, route, values, container) {
238
252
  return bound;
239
253
  }
240
254
 
255
+ // dispatch.ts
256
+ import { CurrentRoute } from "@orieljs/contracts";
257
+ import { currentContainer } from "@orieljs/container";
258
+
241
259
  // RouteDefinition.ts
242
260
  var PARAMETER = /\{(\w+)(?::(\w+))?(\?)?\}/g;
243
261
  var WHOLE_OPTIONAL = /^\{(\w+)(?::\w+)?\?\}$/;
@@ -328,6 +346,7 @@ var RouteDefinition = class {
328
346
  this.#name = (this.#name ?? "") + name;
329
347
  return this;
330
348
  }
349
+ /** middleware('auth', 'verified') or middleware(['auth', 'verified']). */
331
350
  middleware(...middleware) {
332
351
  this.#middleware.push(...middleware.flat());
333
352
  return this;
@@ -731,6 +750,14 @@ var BaseRouter = class {
731
750
  getModel(parameter) {
732
751
  return this.#models.get(parameter);
733
752
  }
753
+ /**
754
+ * Binds a matched route's raw parameter values as a request to it would: Route.bind() callbacks, Route.model(),
755
+ * then implicit binding through the RouteModelResolver of `container`. A missing model throws
756
+ * RouteModelNotFoundError (404). Live uses it to check a page route's `can:` middleware again on each update.
757
+ */
758
+ substituteBindings(route, values, container) {
759
+ return substituteBindings(this, route, values, container);
760
+ }
734
761
  aliasMiddleware(name, middleware) {
735
762
  this.#aliases[name] = middleware;
736
763
  return this;
@@ -795,7 +822,8 @@ var BaseRouter = class {
795
822
  };
796
823
 
797
824
  // BaseUrlGenerator.ts
798
- import { ConfigRepository, HttpRequest, Session } from "@orieljs/contracts";
825
+ import { createHmac, timingSafeEqual } from "crypto";
826
+ import { ConfigRepository, Encrypter, HttpRequest, Session } from "@orieljs/contracts";
799
827
  import { currentContainer as currentContainer3 } from "@orieljs/container";
800
828
  var VALID_URL = /^(#|\/\/|https?:\/\/|(mailto|tel|sms):)/i;
801
829
  var isPlainObject = (value) => {
@@ -823,6 +851,17 @@ function routeKey(value, field) {
823
851
  if (field !== void 0) return typeof model.getAttribute === "function" ? model.getAttribute(field) : model[field];
824
852
  return typeof model.getRouteKey === "function" ? model.getRouteKey() : value;
825
853
  }
854
+ function sign(url, key) {
855
+ return createHmac("sha256", key).update(url).digest("hex");
856
+ }
857
+ function safeEquals(expected, given) {
858
+ const a = Buffer.from(expected);
859
+ const b = Buffer.from(given);
860
+ return a.length === b.length && timingSafeEqual(a, b);
861
+ }
862
+ function availableAt(expiration) {
863
+ return expiration instanceof Date ? Math.floor(expiration.getTime() / 1e3) : Math.floor(Date.now() / 1e3) + expiration;
864
+ }
826
865
  var BaseUrlGenerator = class {
827
866
  constructor(router, container) {
828
867
  this.router = router;
@@ -910,6 +949,69 @@ var BaseUrlGenerator = class {
910
949
  hasRoute(name) {
911
950
  return this.router.getByName(name) !== void 0;
912
951
  }
952
+ /**
953
+ * Laravel's URL::signedRoute(): the route URL with its parameters sorted by name, then a `signature` query (the
954
+ * HMAC-SHA256 of that URL, keyed by APP_KEY). `expiration` (a Date, or seconds from now) adds `expires`.
955
+ * `absolute: false` signs the path only (checked by `signed:relative`).
956
+ */
957
+ signedRoute(name, parameters, expiration, absolute = true) {
958
+ const named = this.#namedParameters(name, parameters);
959
+ for (const reserved of ["signature", "expires"]) {
960
+ if (Object.hasOwn(named, reserved)) {
961
+ throw new RoutingError(`"${reserved}" is a reserved parameter when generating signed routes. Please rename your route parameter.`);
962
+ }
963
+ }
964
+ if (expiration !== void 0) named.expires = availableAt(expiration);
965
+ const sorted = Object.fromEntries(Object.keys(named).sort().map((key) => [key, named[key]]));
966
+ const signature = sign(this.route(name, sorted, absolute), this.#signingKeys()[0]);
967
+ return this.route(name, { ...sorted, signature }, absolute);
968
+ }
969
+ /** Laravel's URL::temporarySignedRoute(): a signed URL that expires at `expiration` (a Date, or seconds from now). */
970
+ temporarySignedRoute(name, expiration, parameters, absolute = true) {
971
+ return this.signedRoute(name, parameters, expiration, absolute);
972
+ }
973
+ /** The request URL carries a correct signature (current or previous APP_KEY) that hasn't expired. */
974
+ hasValidSignature(request, absolute = true) {
975
+ return this.hasCorrectSignature(request, absolute) && this.signatureHasNotExpired(request);
976
+ }
977
+ /** The signature matches the URL without its `signature` query, in a constant-time comparison. */
978
+ hasCorrectSignature(request, absolute = true) {
979
+ const full = new URL(request.fullUrl());
980
+ const path = request.path();
981
+ const url = absolute ? request.url() : path === "/" ? "/" : `/${path}`;
982
+ const query = full.search.slice(1).split("&").filter((pair) => pair !== "" && pair.split("=")[0] !== "signature").join("&");
983
+ const original = query === "" ? url : `${url}?${query}`;
984
+ const given = full.searchParams.get("signature") ?? "";
985
+ return this.#signingKeys().some((key) => safeEquals(sign(original, key), given));
986
+ }
987
+ /** No `expires` query, or one that is still in the future. */
988
+ signatureHasNotExpired(request) {
989
+ const expires = new URL(request.fullUrl()).searchParams.get("expires");
990
+ if (expires === null || expires === "") return true;
991
+ const at = Number(expires);
992
+ return Number.isFinite(at) && Math.floor(Date.now() / 1e3) <= at;
993
+ }
994
+ /** Named parameters: an object as is, positional values (a list or one value) by the route's parameter names. */
995
+ #namedParameters(name, parameters) {
996
+ if (isPlainObject(parameters)) return { ...parameters };
997
+ const route = this.router.getByName(name);
998
+ if (route === void 0) throw new RouteNotDefinedError(name);
999
+ const values = parameters === void 0 || parameters === null ? [] : Array.isArray(parameters) ? parameters : [parameters];
1000
+ const named = {};
1001
+ route.parameters.forEach((parameter, index) => {
1002
+ if (index < values.length) named[parameter.name] = values[index];
1003
+ });
1004
+ return named;
1005
+ }
1006
+ /** The Encrypter's key, then its previous keys (config app.previous_keys), so rotated keys still verify. */
1007
+ #signingKeys() {
1008
+ const scope = this.#scope();
1009
+ if (scope === void 0 || !scope.bound(Encrypter)) {
1010
+ throw new RoutingError("Signed URLs need the Encrypter: set APP_KEY (oriel key:generate).");
1011
+ }
1012
+ const encrypter = scope.make(Encrypter);
1013
+ return typeof encrypter.getAllKeys === "function" ? encrypter.getAllKeys() : [encrypter.getKey()];
1014
+ }
913
1015
  #join(path, absolute) {
914
1016
  const trimmed = path.replace(/^\/+|\/+$/g, "");
915
1017
  if (!absolute) return `/${trimmed}`;
@@ -934,6 +1036,51 @@ import { Router } from "@orieljs/contracts";
934
1036
  import { facade } from "@orieljs/support";
935
1037
  var Route = facade(Router);
936
1038
 
1039
+ // health.ts
1040
+ import { ConfigRepository as ConfigRepository2, EventDispatcher, ExceptionHandler as ExceptionHandler2 } from "@orieljs/contracts";
1041
+ var DiagnosingHealth = class {
1042
+ };
1043
+ var escapeHtml = (value) => value.replace(/[&<>"']/g, (char) => `&#${char.charCodeAt(0)};`);
1044
+ var STYLE = ':root{color-scheme:dark}*{box-sizing:border-box;margin:0}html{background:#05050b}body{min-height:100vh;display:grid;place-items:center;padding:20px;background:#1a1a1a;color:#fff;font:400 16px/1.7 system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif}main{display:flex;align-items:center;gap:20px;width:100%;max-width:640px;padding:20px 32px;border-radius:18px;background:#212121}.dot{flex:none;width:12px;height:12px;border-radius:50%;background:#74ec5a}.dot.down{background:#ff3543}h1{font-size:21px;line-height:1.4;font-weight:600}p{color:#a3a3a3}.time{color:#ba94ff}';
1045
+ function healthResponse(page = {}) {
1046
+ const healthy = page.healthy ?? true;
1047
+ const time = page.milliseconds === void 0 ? "" : ` Response rendered in <span class="time">${Math.round(page.milliseconds)} ms</span>.`;
1048
+ const html2 = `<!DOCTYPE html>
1049
+ <html lang="en">
1050
+ <head>
1051
+ <meta charset="utf-8">
1052
+ <meta name="viewport" content="width=device-width, initial-scale=1">
1053
+ <title>${escapeHtml(page.appName ?? "Oriel")}</title>
1054
+ <style>${STYLE}</style>
1055
+ </head>
1056
+ <body>
1057
+ <main>
1058
+ <span class="${healthy ? "dot" : "dot down"}" aria-hidden="true"></span>
1059
+ <div>
1060
+ <h1>Application ${healthy ? "up" : "experiencing problems"}</h1>
1061
+ <p>HTTP request received.${time}</p>
1062
+ </div>
1063
+ </main>
1064
+ </body>
1065
+ </html>
1066
+ `;
1067
+ return new Response(html2, { status: healthy ? 200 : 500, headers: { "content-type": "text/html; charset=utf-8" } });
1068
+ }
1069
+ async function diagnoseHealth(app) {
1070
+ const started = performance.now();
1071
+ const config = app.bound(ConfigRepository2) ? app.make(ConfigRepository2) : void 0;
1072
+ let healthy = true;
1073
+ try {
1074
+ if (app.bound(EventDispatcher)) await app.make(EventDispatcher).dispatch(new DiagnosingHealth());
1075
+ } catch (error) {
1076
+ if (config?.get("app.debug", false) === true) throw error;
1077
+ if (app.bound(ExceptionHandler2)) await app.make(ExceptionHandler2).report(error);
1078
+ healthy = false;
1079
+ }
1080
+ const appName = String(config?.get("app.name", "Oriel") ?? "Oriel");
1081
+ return healthResponse({ healthy, appName, milliseconds: performance.now() - started });
1082
+ }
1083
+
937
1084
  // routeFiles.ts
938
1085
  import { pathToFileURL } from "url";
939
1086
  var generation = 0;
@@ -945,18 +1092,79 @@ async function loadRoutesFrom(app, router, file) {
945
1092
  ));
946
1093
  if (typeof module.default === "function") await app.run(() => module.default(router));
947
1094
  }
948
- function healthResponse() {
949
- const html2 = '<!DOCTYPE html>\n<html lang="en">\n<head>\n<meta charset="utf-8">\n<title>Application up</title>\n</head>\n<body><h1>Application up</h1></body>\n</html>';
950
- return new Response(html2, { status: 200, headers: { "content-type": "text/html; charset=utf-8" } });
951
- }
952
1095
 
953
1096
  // RoutingServiceProvider.ts
954
- import { Router as Router2, RoutingPaths, UrlGenerator as UrlGenerator2 } from "@orieljs/contracts";
1097
+ import { Router as Router2, RoutingPaths, UrlGenerator as UrlGenerator3 } from "@orieljs/contracts";
955
1098
  import { ServiceProvider } from "@orieljs/support";
1099
+
1100
+ // ThrottleRequests.ts
1101
+ import { createHash } from "crypto";
1102
+ import { RateLimiter } from "@orieljs/contracts";
1103
+ import { inject } from "@orieljs/container";
1104
+ var sha1 = (value) => createHash("sha1").update(value).digest("hex");
1105
+ function withHeaders(response, headers) {
1106
+ try {
1107
+ for (const [name, value] of Object.entries(headers)) response.headers.set(name, value);
1108
+ return response;
1109
+ } catch {
1110
+ const copy = new Headers(response.headers);
1111
+ for (const [name, value] of Object.entries(headers)) copy.set(name, value);
1112
+ return new Response(response.body, { status: response.status, statusText: response.statusText, headers: copy });
1113
+ }
1114
+ }
1115
+ var ThrottleRequests = class {
1116
+ async handle(request, next, maxAttempts = "60", decayMinutes = "1", prefix = "") {
1117
+ const max = Number(maxAttempts);
1118
+ const decay = Number(decayMinutes);
1119
+ if (maxAttempts.trim() === "" || !Number.isInteger(max) || max < 0 || decayMinutes.trim() === "" || !Number.isFinite(decay) || decay <= 0) {
1120
+ throw new RoutingError(
1121
+ `Invalid throttle parameters "${maxAttempts},${decayMinutes}": use throttle:<maxAttempts>,<decayMinutes>[,<prefix>] (named rate limiters are not supported).`
1122
+ );
1123
+ }
1124
+ const limiter = inject(RateLimiter);
1125
+ const key = prefix + this.resolveRequestSignature(request);
1126
+ if (await limiter.tooManyAttempts(key, max)) {
1127
+ const retryAfter = await limiter.availableIn(key);
1128
+ throw new ThrottleRequestsError({
1129
+ "X-RateLimit-Limit": String(max),
1130
+ "X-RateLimit-Remaining": "0",
1131
+ "Retry-After": String(retryAfter),
1132
+ "X-RateLimit-Reset": String(Math.floor(Date.now() / 1e3) + retryAfter)
1133
+ });
1134
+ }
1135
+ await limiter.hit(key, Math.round(decay * 60));
1136
+ const response = await next(request);
1137
+ return withHeaders(response, {
1138
+ "X-RateLimit-Limit": String(max),
1139
+ "X-RateLimit-Remaining": String(await limiter.remaining(key, max))
1140
+ });
1141
+ }
1142
+ /** The signed-in user's identifier, else the client IP, hashed (Laravel's resolveRequestSignature()). */
1143
+ resolveRequestSignature(request) {
1144
+ const user = request.user();
1145
+ if (user !== void 0 && user !== null && typeof user.getAuthIdentifier === "function") {
1146
+ return sha1(String(user.getAuthIdentifier()));
1147
+ }
1148
+ return sha1(`|${request.ip() ?? ""}`);
1149
+ }
1150
+ };
1151
+
1152
+ // ValidateSignature.ts
1153
+ import { UrlGenerator as UrlGenerator2 } from "@orieljs/contracts";
1154
+ import { inject as inject2 } from "@orieljs/container";
1155
+ var ValidateSignature = class {
1156
+ async handle(request, next, ...parameters) {
1157
+ const absolute = parameters[0] !== "relative";
1158
+ if (inject2(UrlGenerator2).hasValidSignature(request, absolute)) return next(request);
1159
+ throw new InvalidUrlSignatureError();
1160
+ }
1161
+ };
1162
+
1163
+ // RoutingServiceProvider.ts
956
1164
  var RoutingServiceProvider = class extends ServiceProvider {
957
1165
  register() {
958
1166
  this.app.singleton(Router2, () => new BaseRouter(this.app));
959
- this.app.singleton(UrlGenerator2, () => {
1167
+ this.app.singleton(UrlGenerator3, () => {
960
1168
  const router = this.app.make(Router2);
961
1169
  if (!(router instanceof BaseRouter)) {
962
1170
  throw new RoutingError("The UrlGenerator needs the BaseRouter: the bound Router was replaced by another implementation.");
@@ -970,21 +1178,28 @@ var RoutingServiceProvider = class extends ServiceProvider {
970
1178
  * when the route files run.
971
1179
  */
972
1180
  boot() {
1181
+ this.app.make(Router2).aliasMiddleware("signed", ValidateSignature).aliasMiddleware("throttle", ThrottleRequests);
973
1182
  this.app.booted(async () => {
974
1183
  if (!this.app.bound(RoutingPaths)) return;
975
1184
  const { web, api, health, apiPrefix } = this.app.make(RoutingPaths);
976
1185
  const router = this.app.make(Router2);
977
- if (health !== void 0) router.get(health, () => healthResponse());
978
- if (web !== void 0) await router.middleware("web").group(() => loadRoutesFrom(this.app, router, web));
979
- if (api !== void 0) await router.prefix(apiPrefix).middleware("api").group(() => loadRoutesFrom(this.app, router, api));
1186
+ if (health !== void 0) router.get(health, () => diagnoseHealth(this.app));
1187
+ if (web !== void 0) await router.middleware("web").group(() => this.#load(router, web));
1188
+ if (api !== void 0) await router.prefix(apiPrefix).middleware("api").group(() => this.#load(router, api));
980
1189
  });
981
1190
  }
1191
+ /** One file or several, in order: each is imported afresh for this application (a nested import is not). */
1192
+ async #load(router, files) {
1193
+ for (const file of [files].flat()) await loadRoutesFrom(this.app, router, file);
1194
+ }
982
1195
  };
983
1196
  export {
984
1197
  BaseRouter,
985
1198
  BaseUrlGenerator,
986
1199
  ControllerMethodNotFoundError,
1200
+ DiagnosingHealth,
987
1201
  GroupRegistrar,
1202
+ InvalidUrlSignatureError,
988
1203
  MethodNotAllowedHttpError,
989
1204
  MiddlewareNotFoundError,
990
1205
  NotFoundHttpError,
@@ -994,7 +1209,10 @@ export {
994
1209
  RouteNotDefinedError,
995
1210
  RoutingError,
996
1211
  RoutingServiceProvider,
1212
+ ThrottleRequests,
1213
+ ThrottleRequestsError,
997
1214
  UrlGenerationError,
1215
+ ValidateSignature,
998
1216
  buildQuery,
999
1217
  compareRoutes,
1000
1218
  dispatchRoute,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../BaseRouter.ts","../dispatch.ts","../bindings.ts","../errors.ts","../middleware.ts","../toResponse.ts","../RouteDefinition.ts","../GroupRegistrar.ts","../resource.ts","../BaseUrlGenerator.ts","../facade.ts","../routeFiles.ts","../RoutingServiceProvider.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 { 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: 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 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 { 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 { 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","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 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(...middleware: 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 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 #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: 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 { ConfigRepository, HttpRequest, Session, type Container, type UrlGenerator } from '@orieljs/contracts'\nimport { currentContainer } from '@orieljs/container'\nimport type { BaseRouter } from './BaseRouter'\nimport { RouteNotDefinedError, 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/** 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 #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 { 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/** The health route's page (Laravel's `/up`): 200 as long as the application boots and handles requests. */\nexport function healthResponse(): Response {\n const html =\n '<!DOCTYPE html>\\n<html lang=\"en\">\\n<head>\\n<meta charset=\"utf-8\">\\n<title>Application up</title>\\n</head>\\n' +\n '<body><h1>Application up</h1></body>\\n</html>'\n return new Response(html, { status: 200, headers: { 'content-type': 'text/html; charset=utf-8' } })\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 { healthResponse, loadRoutesFrom } from './routeFiles'\n\n/**\n * Binds the Router and the UrlGenerator, and once the app has booted loads the files given to withRouting(): the health URI,\n * then routes/web.ts in the `web` middleware group, then routes/api.ts under the api prefix in the `api` group\n * (Laravel's 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.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, () => healthResponse())\n if (web !== undefined) await router.middleware('web').group(() => loadRoutesFrom(this.app, router, web))\n if (api !== undefined) await router.prefix(apiPrefix).middleware('api').group(() => loadRoutesFrom(this.app, router, api))\n })\n }\n}\n"],"mappings":";AAAA;AAAA,EACE,gBAAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAYK;AACP,SAAS,oBAAAC,yBAAwB;;;ACjBjC,SAAS,oBAAmF;AAC5F,SAAS,wBAAwB;;;ACDjC,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;;;AC7DA;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;;;AI1DO,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,EAEA,cAAc,YAAyC;AACrD,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,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,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;;;AL5LO,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;;;AMlEO,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,YAAyC;AACrD,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;;;ARxBO,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,YAAmD;AAC/D,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,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;;;ASrTA,SAAS,kBAAkB,aAAa,eAAkD;AAC1F,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;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,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;;;ACvKA,SAAS,cAA6B;AACtC,SAAS,cAAc;AAOhB,IAAM,QAAQ,OAAmB,MAA8B;;;ACRtE,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;AAGO,SAAS,iBAA2B;AACzC,QAAMC,QACJ;AAEF,SAAO,IAAI,SAASA,OAAM,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,2BAA2B,EAAE,CAAC;AACpG;;;ACzBA,SAAS,UAAAC,SAAQ,cAAc,gBAAAC,qBAAoB;AACnD,SAAS,uBAAuB;AAWzB,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,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,CAAC;AACnE,UAAI,QAAQ,OAAW,OAAM,OAAO,WAAW,KAAK,EAAE,MAAM,MAAM,eAAe,KAAK,KAAK,QAAQ,GAAG,CAAC;AACvG,UAAI,QAAQ,OAAW,OAAM,OAAO,OAAO,SAAS,EAAE,WAAW,KAAK,EAAE,MAAM,MAAM,eAAe,KAAK,KAAK,QAAQ,GAAG,CAAC;AAAA,IAC3H,CAAC;AAAA,EACH;AACF;","names":["CurrentRoute","currentContainer","Str","currentContainer","CurrentRoute","currentContainer","currentContainer","html","Router","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 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 #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":";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,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,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;;;AD7LO,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,SAAS,KAAK,wBAAwB,OAAO;AACzD,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,EAGU,wBAAwB,SAA8B;AAC9D,UAAM,OAAO,QAAQ,KAAwC;AAC7D,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.3",
3
+ "version": "0.1.0-alpha.5",
4
4
  "description": "The Oriel Routing component.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -30,9 +30,9 @@
30
30
  "NOTICE"
31
31
  ],
32
32
  "dependencies": {
33
- "@orieljs/contracts": "0.1.0-alpha.3",
34
- "@orieljs/container": "0.1.0-alpha.3",
35
- "@orieljs/support": "0.1.0-alpha.3"
33
+ "@orieljs/contracts": "0.1.0-alpha.5",
34
+ "@orieljs/container": "0.1.0-alpha.5",
35
+ "@orieljs/support": "0.1.0-alpha.5"
36
36
  },
37
37
  "scripts": {
38
38
  "build": "tsup && node ../../../scripts/copy-license.mjs"