@orieljs/http 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,7 +1,13 @@
1
1
  import { HttpRequest, CookieJar, Session, Container, RedirectResponse, HeadersInit, Redirector, UploadedFile, Rules, OrielError, RouteName, ResponseFactory, BodyInit, UrlGenerator, HttpKernel, Application, MiddlewareClass, Middleware, Next, MiddlewareConfigurator, Router, ConfigRepository, ExceptionHandler, ExceptionsConfigurator, ConsoleKernel, Route } from '@orieljs/contracts';
2
+ import { FileType, ServiceProvider } from '@orieljs/support';
2
3
  import { IncomingMessage, ServerResponse } from 'node:http';
3
- import { ServiceProvider } from '@orieljs/support';
4
4
 
5
+ /**
6
+ * Whether a JSON text nests objects and arrays deeper than `maxDepth`, found by scanning (no parsing, no recursion):
7
+ * brackets inside strings don't count. The kernel answers 400 for such bodies (http.max_json_depth) before the
8
+ * recursive input handling (sanitizing, TrimStrings, validation) could overflow the stack.
9
+ */
10
+ declare function exceedsJsonDepth(text: string, maxDepth: number): boolean;
5
11
  /** Reads a request body into memory, refusing more than `limit` bytes (413), like PHP's post_max_size. */
6
12
  declare function readBody(raw: Request, limit: number | null): Promise<Uint8Array>;
7
13
 
@@ -46,7 +52,10 @@ declare class HttpRedirector implements Redirector {
46
52
  /** Pulls url.intended from the session (put there by guest()), else goes to `fallback`. */
47
53
  intended(fallback?: string, status?: number): HttpRedirectResponse;
48
54
  away(url: string, status?: number): HttpRedirectResponse;
49
- /** Remembers where a guest was going (a GET page, else the previous URL), then redirects to `path`. */
55
+ /**
56
+ * Remembers where a guest was going (a GET page, else the previous URL), then redirects to `path`. Only the path
57
+ * is stored, so intended() goes back on whichever host serves the app, and never to another site's Referer.
58
+ */
50
59
  guest(path: string, status?: number): HttpRedirectResponse;
51
60
  setIntendedUrl(url: string): void;
52
61
  refresh(status?: number): HttpRedirectResponse;
@@ -58,13 +67,26 @@ declare function clientAddress(request: Request): string | undefined;
58
67
  /** An uploaded file from a multipart body. store()/storeAs() go through the FilesystemManager. */
59
68
  declare class FormUploadedFile implements UploadedFile {
60
69
  private readonly file;
70
+ private readonly detected?;
61
71
  readonly clientName: string;
62
72
  readonly mimeType: string;
63
73
  readonly size: number;
74
+ /**
75
+ * Reads the leading bytes first, so extension(), hashName() and store() name the file by its content. The request
76
+ * builds its uploads this way.
77
+ */
78
+ static fromFile(file: Blob & {
79
+ readonly name?: string;
80
+ }): Promise<FormUploadedFile>;
64
81
  constructor(file: Blob & {
65
82
  readonly name?: string;
66
- });
67
- /** Guessed from the MIME type, falling back to the client's extension (Laravel's extension()). */
83
+ }, detected?: FileType.DetectedType | undefined);
84
+ /**
85
+ * Laravel's extension(): the type the bytes show (guessExtension()), when they were read and match a known format.
86
+ * Text and bytes no format matches keep the client's claim (its MIME type, else its file name) when it is a plain
87
+ * extension, unless it names a format the bytes would have shown or one a browser renders or runs: otherwise 'txt'
88
+ * for text, '' for the rest. Unread (built directly), the client's claim when it is a plain extension, else ''.
89
+ */
68
90
  extension(): string;
69
91
  clientExtension(): string;
70
92
  /** A random 40-character name with the guessed extension. */
@@ -81,6 +103,8 @@ interface IncomingRequestOptions {
81
103
  trustedProxies?: readonly string[];
82
104
  /** Largest request body in bytes before a 413 (config http.max_body_size); null is unlimited. Default 8 MB. */
83
105
  maxBodySize?: number | null;
106
+ /** Deepest nesting of objects and arrays in a JSON body before a 400 (config http.max_json_depth); null is unlimited. Default 512. */
107
+ maxJsonDepth?: number | null;
84
108
  }
85
109
  /** Exact match, IPv4 CIDR ('10.0.0.0/8') or '*'. */
86
110
  declare function ipMatches(ip: string, patterns: readonly string[]): boolean;
@@ -316,6 +340,7 @@ declare function applyMiddlewareCallbacks(app: Application, kernel: Kernel): voi
316
340
  type ReportCallback = (error: unknown) => void | boolean | Promise<void | boolean>;
317
341
  type RenderCallback = (error: unknown, request: unknown) => Response | undefined | Promise<Response | undefined>;
318
342
  type ErrorClass = abstract new (...args: never[]) => Error;
343
+ type JsonWhenCallback = (request: HttpRequest, error: unknown) => boolean;
319
344
  /** HTTP status for an error (spec §7). */
320
345
  declare function statusFor(error: unknown): number;
321
346
  /** "The title field is required. (and 2 more errors)" (Laravel's ValidationException::summarize). */
@@ -330,6 +355,10 @@ declare class ErrorHandler implements ExceptionHandler {
330
355
  reportUsing(callback: ReportCallback): void;
331
356
  renderUsing(callback: RenderCallback): void;
332
357
  ignore(...classes: ErrorClass[]): void;
358
+ /** Laravel's shouldRenderJsonWhen(): the callback decides JSON or HTML instead of the Accept header. */
359
+ shouldRenderJsonWhen(callback: JsonWhenCallback): void;
360
+ /** Laravel's shouldReturnJson(): the shouldRenderJsonWhen() callback when set, else request.expectsJson(). */
361
+ protected shouldReturnJson(request: HttpRequest, error: unknown): boolean;
333
362
  shouldReport(error: unknown): boolean;
334
363
  /** Report callbacks first (returning false stops the default log), then LogManager.error(), else console.error. Once per error. */
335
364
  report(error: unknown): Promise<void>;
@@ -343,6 +372,8 @@ declare class ExceptionsConfiguration implements ExceptionsConfigurator {
343
372
  report(callback: ReportCallback): this;
344
373
  render(callback: RenderCallback): this;
345
374
  dontReport(...classes: ErrorClass[]): this;
375
+ /** shouldRenderJsonWhen((request) => request.is('api/*')): JSON errors for those requests, whatever they accept. */
376
+ shouldRenderJsonWhen(callback: (request: HttpRequest, error: unknown) => boolean): this;
346
377
  }
347
378
  /** Runs the withExceptions() callbacks against a handler (the provider does this when the handler is built). */
348
379
  declare function applyExceptionCallbacks(app: Application, handler: ErrorHandler): void;
@@ -492,4 +523,4 @@ declare class HttpServiceProvider extends ServiceProvider {
492
523
  boot(): void;
493
524
  }
494
525
 
495
- export { API_ROUTES_STUB, ConvertEmptyStringsToNull, type ErrorClass, ErrorHandler, ExceptionsConfiguration, FormUploadedFile, type HttpCommandOptions, HttpException, HttpRedirectResponse, HttpRedirector, HttpResponseException, HttpResponseFactory, HttpServerError, HttpServiceProvider, IncomingRequest, type IncomingRequestOptions, Kernel, MiddlewareConfiguration, type RenderCallback, type ReportCallback, type ResolvedServeOptions, type RouteListFilters, type RouteListRow, type RunningServer, type Runtime, type ServeOptions, type StackFrame, TrimStrings, type TypedRedirector, abort, abortIf, abortUnless, addApiRouting, applyExceptionCallbacks, applyMiddlewareCallbacks, back, bunRuntime, clientAddress, contentDisposition, currentRequest, debugPage, detectRuntime, escapeHtml, extensionFromMime, filterRouteList, formatRouteList, fromEntries, ipMatches, isBlank, mergeRecursive, mimeFromExtension, minimalPage, normalizeLists, optionalCookieJar, optionalSession, parseBracketKey, readBody, redirect, registerHttpCommands, request, requestScope, response, route, routeListRows, sanitize, serve, serveBun, serveNode, servePublicFile, setClientAddress, stackFrames, statusFor, statusText, summarizeValidation, toWebRequest, transformLeaves, url, writeResponse };
526
+ export { API_ROUTES_STUB, ConvertEmptyStringsToNull, type ErrorClass, ErrorHandler, ExceptionsConfiguration, FormUploadedFile, type HttpCommandOptions, HttpException, HttpRedirectResponse, HttpRedirector, HttpResponseException, HttpResponseFactory, HttpServerError, HttpServiceProvider, IncomingRequest, type IncomingRequestOptions, type JsonWhenCallback, Kernel, MiddlewareConfiguration, type RenderCallback, type ReportCallback, type ResolvedServeOptions, type RouteListFilters, type RouteListRow, type RunningServer, type Runtime, type ServeOptions, type StackFrame, TrimStrings, type TypedRedirector, abort, abortIf, abortUnless, addApiRouting, applyExceptionCallbacks, applyMiddlewareCallbacks, back, bunRuntime, clientAddress, contentDisposition, currentRequest, debugPage, detectRuntime, escapeHtml, exceedsJsonDepth, extensionFromMime, filterRouteList, formatRouteList, fromEntries, ipMatches, isBlank, mergeRecursive, mimeFromExtension, minimalPage, normalizeLists, optionalCookieJar, optionalSession, parseBracketKey, readBody, redirect, registerHttpCommands, request, requestScope, response, route, routeListRows, sanitize, serve, serveBun, serveNode, servePublicFile, setClientAddress, stackFrames, statusFor, statusText, summarizeValidation, toWebRequest, transformLeaves, url, writeResponse };
package/dist/index.js CHANGED
@@ -28,6 +28,21 @@ var HttpServerError = class extends Error {
28
28
  };
29
29
 
30
30
  // body.ts
31
+ function exceedsJsonDepth(text, maxDepth) {
32
+ let depth = 0;
33
+ let inString = false;
34
+ for (let i = 0; i < text.length; i++) {
35
+ const code = text.charCodeAt(i);
36
+ if (inString) {
37
+ if (code === 92) i++;
38
+ else if (code === 34) inString = false;
39
+ } else if (code === 34) inString = true;
40
+ else if (code === 123 || code === 91) {
41
+ if (++depth > maxDepth) return true;
42
+ } else if (code === 125 || code === 93) depth--;
43
+ }
44
+ return false;
45
+ }
31
46
  async function readBody(raw, limit) {
32
47
  if (raw.body === null) return new Uint8Array(0);
33
48
  const declared = Number(raw.headers.get("content-length") ?? NaN);
@@ -146,6 +161,15 @@ var HttpRedirectResponse = class {
146
161
  // HttpRedirector.ts
147
162
  import { UrlGenerator } from "@orieljs/contracts";
148
163
  import { inject } from "@orieljs/container";
164
+ function pathOf(url2) {
165
+ let parsed;
166
+ try {
167
+ parsed = new URL(url2, "http://localhost");
168
+ } catch {
169
+ return "/";
170
+ }
171
+ return `${parsed.pathname.replace(/^\/+/, "/")}${parsed.search}${parsed.hash}`;
172
+ }
149
173
  var HttpRedirector = class {
150
174
  to(path, status = 302, headers) {
151
175
  return new HttpRedirectResponse(inject(UrlGenerator).to(path), status, headers);
@@ -164,13 +188,16 @@ var HttpRedirector = class {
164
188
  away(url2, status = 302) {
165
189
  return new HttpRedirectResponse(url2, status);
166
190
  }
167
- /** Remembers where a guest was going (a GET page, else the previous URL), then redirects to `path`. */
191
+ /**
192
+ * Remembers where a guest was going (a GET page, else the previous URL), then redirects to `path`. Only the path
193
+ * is stored, so intended() goes back on whichever host serves the app, and never to another site's Referer.
194
+ */
168
195
  guest(path, status = 302) {
169
196
  const session = optionalSession();
170
197
  const request2 = currentRequest();
171
198
  if (session !== void 0) {
172
199
  const intended = request2 !== void 0 && request2.method() === "GET" && !request2.expectsJson() ? request2.fullUrl() : inject(UrlGenerator).previous();
173
- session.put("url.intended", intended);
200
+ session.put("url.intended", pathOf(intended));
174
201
  }
175
202
  return this.to(path, status);
176
203
  }
@@ -195,7 +222,7 @@ function clientAddress(request2) {
195
222
  // FormUploadedFile.ts
196
223
  import { FilesystemManager } from "@orieljs/contracts";
197
224
  import { inject as inject2 } from "@orieljs/container";
198
- import { Str } from "@orieljs/support";
225
+ import { FileType, Str } from "@orieljs/support";
199
226
 
200
227
  // mime.ts
201
228
  var TYPES = {
@@ -242,20 +269,60 @@ function extensionFromMime(type) {
242
269
  }
243
270
 
244
271
  // FormUploadedFile.ts
245
- var FormUploadedFile = class {
246
- constructor(file) {
272
+ var NEVER_CLAIMED = /* @__PURE__ */ new Set([
273
+ ...FileType.BINARY_AND_MARKUP_TYPES.flatMap(({ extensions }) => extensions),
274
+ "jpe",
275
+ "svgz",
276
+ "xhtml",
277
+ "xht",
278
+ "shtml",
279
+ "xsl",
280
+ "xslt",
281
+ "mht",
282
+ "mhtml",
283
+ "js",
284
+ "mjs",
285
+ "rss",
286
+ "atom",
287
+ "rdf",
288
+ "mathml",
289
+ "mml",
290
+ "xul"
291
+ ]);
292
+ var PLAIN_EXTENSION = /^[a-z0-9]+$/;
293
+ var FormUploadedFile = class _FormUploadedFile {
294
+ constructor(file, detected) {
247
295
  this.file = file;
296
+ this.detected = detected;
248
297
  this.clientName = file.name ?? "";
249
298
  this.mimeType = file.type === "" ? "application/octet-stream" : file.type;
250
299
  this.size = file.size;
251
300
  }
252
301
  file;
302
+ detected;
253
303
  clientName;
254
304
  mimeType;
255
305
  size;
256
- /** Guessed from the MIME type, falling back to the client's extension (Laravel's extension()). */
306
+ /**
307
+ * Reads the leading bytes first, so extension(), hashName() and store() name the file by its content. The request
308
+ * builds its uploads this way.
309
+ */
310
+ static async fromFile(file) {
311
+ return new _FormUploadedFile(file, FileType.detectFileType(new Uint8Array(await file.slice(0, FileType.SNIFF_BYTES).arrayBuffer())));
312
+ }
313
+ /**
314
+ * Laravel's extension(): the type the bytes show (guessExtension()), when they were read and match a known format.
315
+ * Text and bytes no format matches keep the client's claim (its MIME type, else its file name) when it is a plain
316
+ * extension, unless it names a format the bytes would have shown or one a browser renders or runs: otherwise 'txt'
317
+ * for text, '' for the rest. Unread (built directly), the client's claim when it is a plain extension, else ''.
318
+ */
257
319
  extension() {
258
- return extensionFromMime(this.mimeType) ?? this.clientExtension();
320
+ const claimed = extensionFromMime(this.mimeType) ?? this.clientExtension();
321
+ const detected = this.detected;
322
+ if (detected === void 0) return PLAIN_EXTENSION.test(claimed) ? claimed : "";
323
+ if (detected !== FileType.TEXT && detected.extensions.length > 0) return detected.extensions[0];
324
+ if (PLAIN_EXTENSION.test(claimed) && !NEVER_CLAIMED.has(claimed)) return claimed;
325
+ return detected === FileType.TEXT ? "txt" : "";
259
326
  }
260
327
  clientExtension() {
261
328
  const dot = this.clientName.lastIndexOf(".");
@@ -407,6 +474,7 @@ var IncomingRequest = class {
407
474
  this.#url = new URL(raw.url);
408
475
  this.#trustedProxies = options.trustedProxies ?? [];
409
476
  this.#maxBodySize = options.maxBodySize === void 0 ? 8 * 1024 * 1024 : options.maxBodySize;
477
+ this.#maxJsonDepth = options.maxJsonDepth === void 0 ? 512 : options.maxJsonDepth;
410
478
  this.#query = fromEntries(this.#url.searchParams.entries());
411
479
  this.#method = raw.method.toUpperCase();
412
480
  }
@@ -414,6 +482,7 @@ var IncomingRequest = class {
414
482
  #url;
415
483
  #trustedProxies;
416
484
  #maxBodySize;
485
+ #maxJsonDepth;
417
486
  #query;
418
487
  #body = {};
419
488
  #files = {};
@@ -435,6 +504,9 @@ var IncomingRequest = class {
435
504
  const isMultipart = type.startsWith("multipart/form-data");
436
505
  if (isJson || isUrlencoded || isMultipart) {
437
506
  const bytes = await readBody(this.raw, this.#maxBodySize);
507
+ if (isJson && this.#maxJsonDepth !== null && exceedsJsonDepth(new TextDecoder().decode(bytes), this.#maxJsonDepth)) {
508
+ throw new HttpException(400, "The request body is nested too deeply.");
509
+ }
438
510
  try {
439
511
  if (isJson) {
440
512
  this.#content = new TextDecoder().decode(bytes);
@@ -443,7 +515,7 @@ var IncomingRequest = class {
443
515
  this.#content = new TextDecoder().decode(bytes);
444
516
  this.#body = fromEntries(new URLSearchParams(this.#content).entries());
445
517
  } else {
446
- this.#parseForm(await new Response(bytes, { headers: { "content-type": this.raw.headers.get("content-type") ?? "" } }).formData());
518
+ await this.#parseForm(await new Response(bytes, { headers: { "content-type": this.raw.headers.get("content-type") ?? "" } }).formData());
447
519
  }
448
520
  } catch {
449
521
  }
@@ -468,12 +540,12 @@ var IncomingRequest = class {
468
540
  if (Array.isArray(parsed)) return sanitize({ ...parsed });
469
541
  return isPlainObject(parsed) ? sanitize(parsed) : {};
470
542
  }
471
- #parseForm(form) {
543
+ async #parseForm(form) {
472
544
  const fields = [];
473
545
  const files = [];
474
546
  for (const [name, value] of form.entries()) {
475
547
  if (typeof value === "string") fields.push([name, value]);
476
- else if (!((value.name ?? "") === "" && value.size === 0)) files.push([name, new FormUploadedFile(value)]);
548
+ else if (!((value.name ?? "") === "" && value.size === 0)) files.push([name, await FormUploadedFile.fromFile(value)]);
477
549
  }
478
550
  this.#body = fromEntries(fields);
479
551
  this.#files = fromEntries(files);
@@ -881,7 +953,11 @@ var Kernel = class {
881
953
  let request2;
882
954
  let response2;
883
955
  try {
884
- request2 = new IncomingRequest(raw, { trustedProxies: this.#trustedProxies(), maxBodySize: this.#maxBodySize() });
956
+ request2 = new IncomingRequest(raw, {
957
+ trustedProxies: this.#trustedProxies(),
958
+ maxBodySize: this.#maxBodySize(),
959
+ maxJsonDepth: this.#maxJsonDepth()
960
+ });
885
961
  scope.instance(HttpRequest3, request2);
886
962
  const state = { scope, request: request2, middleware: [] };
887
963
  this.#requests.set(raw, state);
@@ -993,6 +1069,16 @@ var Kernel = class {
993
1069
  `Invalid http.max_body_size ${JSON.stringify(value) ?? String(value)}: use a number of bytes (0 or more), or null for no limit.`
994
1070
  );
995
1071
  }
1072
+ /** config('http.max_json_depth'): how deep a JSON body may nest, or null for no limit. */
1073
+ #maxJsonDepth() {
1074
+ if (!this.app.bound(ConfigRepository)) return 512;
1075
+ const value = this.app.make(ConfigRepository).get("http.max_json_depth", 512);
1076
+ if (value === null) return null;
1077
+ if (typeof value === "number" && Number.isInteger(value) && value >= 1) return value;
1078
+ throw new HttpServerError(
1079
+ `Invalid http.max_json_depth ${JSON.stringify(value) ?? String(value)}: use a whole number (1 or more), or null for no limit.`
1080
+ );
1081
+ }
996
1082
  /** config('http.trusted_proxies'): an array, or a comma-separated string such as '*' or '10.0.0.0/8,::1'. */
997
1083
  #trustedProxies() {
998
1084
  if (!this.app.bound(ConfigRepository)) return [];
@@ -1220,6 +1306,7 @@ var ErrorHandler = class {
1220
1306
  #renderCallbacks = [];
1221
1307
  #dontReport = [];
1222
1308
  #reported = /* @__PURE__ */ new WeakSet();
1309
+ #jsonWhen;
1223
1310
  reportUsing(callback) {
1224
1311
  this.#reportCallbacks.push(callback);
1225
1312
  }
@@ -1229,6 +1316,14 @@ var ErrorHandler = class {
1229
1316
  ignore(...classes) {
1230
1317
  this.#dontReport.push(...classes);
1231
1318
  }
1319
+ /** Laravel's shouldRenderJsonWhen(): the callback decides JSON or HTML instead of the Accept header. */
1320
+ shouldRenderJsonWhen(callback) {
1321
+ this.#jsonWhen = callback;
1322
+ }
1323
+ /** Laravel's shouldReturnJson(): the shouldRenderJsonWhen() callback when set, else request.expectsJson(). */
1324
+ shouldReturnJson(request2, error) {
1325
+ return this.#jsonWhen !== void 0 ? this.#jsonWhen(request2, error) : request2.expectsJson();
1326
+ }
1232
1327
  shouldReport(error) {
1233
1328
  const kind = kindOf(error);
1234
1329
  if (kind !== void 0 && NOT_REPORTED.has(kind)) return false;
@@ -1267,7 +1362,7 @@ var ErrorHandler = class {
1267
1362
  let response2;
1268
1363
  if (kind === "Validation") response2 = await this.#renderValidation(http, error);
1269
1364
  else if (kind === "Authentication") response2 = await this.#renderAuthentication(http, error);
1270
- else if (http.expectsJson()) response2 = this.#renderJson(error);
1365
+ else if (this.shouldReturnJson(http, error)) response2 = this.#renderJson(error);
1271
1366
  else response2 = await this.#renderHtml(http, error);
1272
1367
  const headers = error?.headers;
1273
1368
  if (headers !== void 0) for (const [name, value] of Object.entries(headers)) response2.headers.set(name, value);
@@ -1285,7 +1380,7 @@ var ErrorHandler = class {
1285
1380
  return void 0;
1286
1381
  }
1287
1382
  async #renderValidation(request2, error) {
1288
- if (request2.expectsJson()) {
1383
+ if (this.shouldReturnJson(request2, error)) {
1289
1384
  return this.#json({ message: summarizeValidation(error.errors), errors: error.errors }, statusFor(error));
1290
1385
  }
1291
1386
  const input = { ...request2.input() };
@@ -1300,7 +1395,7 @@ var ErrorHandler = class {
1300
1395
  return response2;
1301
1396
  }
1302
1397
  async #renderAuthentication(request2, error) {
1303
- if (request2.expectsJson()) return this.#json({ message: error.message || "Unauthenticated." }, 401);
1398
+ if (this.shouldReturnJson(request2, error)) return this.#json({ message: error.message || "Unauthenticated." }, 401);
1304
1399
  const target = error.redirectTo ?? this.#guestRedirect(request2);
1305
1400
  const container = this.#container();
1306
1401
  if (!container.bound(Redirector2)) return this.#redirect(target);
@@ -1411,6 +1506,11 @@ var ExceptionsConfiguration = class {
1411
1506
  this.handler.ignore(...classes);
1412
1507
  return this;
1413
1508
  }
1509
+ /** shouldRenderJsonWhen((request) => request.is('api/*')): JSON errors for those requests, whatever they accept. */
1510
+ shouldRenderJsonWhen(callback) {
1511
+ this.handler.shouldRenderJsonWhen(callback);
1512
+ return this;
1513
+ }
1414
1514
  };
1415
1515
  function applyExceptionCallbacks(app, handler) {
1416
1516
  if (!app.bound(ExceptionCallbacks)) return;
@@ -1859,6 +1959,7 @@ var HttpServiceProvider = class extends ServiceProvider {
1859
1959
  {
1860
1960
  trusted_proxies: [],
1861
1961
  max_body_size: 8 * 1024 * 1024,
1962
+ max_json_depth: 512,
1862
1963
  csrf_except: [],
1863
1964
  redirect_guests_to: void 0,
1864
1965
  redirect_users_to: void 0
@@ -1913,6 +2014,7 @@ export {
1913
2014
  debugPage,
1914
2015
  detectRuntime,
1915
2016
  escapeHtml,
2017
+ exceedsJsonDepth,
1916
2018
  extensionFromMime,
1917
2019
  filterRouteList,
1918
2020
  formatRouteList,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../errors.ts","../body.ts","../context.ts","../HttpRedirectResponse.ts","../HttpRedirector.ts","../clientAddress.ts","../FormUploadedFile.ts","../mime.ts","../IncomingRequest.ts","../input.ts","../helpers.ts","../HttpResponseFactory.ts","../Kernel.ts","../middleware/ConvertEmptyStringsToNull.ts","../middleware/TrimStrings.ts","../MiddlewareConfiguration.ts","../ErrorHandler.ts","../errorPages.ts","../ExceptionsConfiguration.ts","../server/types.ts","../server/static.ts","../server/bun.ts","../server/node.ts","../server/serve.ts","../commands.ts","../HttpServiceProvider.ts"],"sourcesContent":["import type { OrielError } from '@orieljs/contracts'\n\n/** Symfony's HttpException: abort(404), abort(403, 'Nope'). An empty message renders as the status text. */\nexport class HttpException extends Error implements OrielError {\n readonly kind = 'Http' as const\n override readonly name = 'HttpException'\n constructor(\n readonly status: number,\n message = '',\n readonly headers: Record<string, string> = {},\n ) {\n super(message)\n }\n}\n\n/** Carries a ready Response out of deep code: abort(response). The handler returns it as is. */\nexport class HttpResponseException extends Error implements OrielError {\n readonly kind = 'Http' as const\n override readonly name = 'HttpResponseException'\n readonly status: number\n constructor(readonly response: Response) {\n super(`HTTP response exception (${response.status}).`)\n this.status = response.status\n }\n}\n\n/** Http's internal failures (not thrown by this package itself; used by the kernel and error rendering). */\nexport class HttpServerError extends Error implements OrielError {\n readonly kind = 'Server' as const\n readonly status = 500\n override readonly name = 'HttpServerError'\n}\n","import { HttpException } from './errors'\n\n/** Reads a request body into memory, refusing more than `limit` bytes (413), like PHP's post_max_size. */\nexport async function readBody(raw: Request, limit: number | null): Promise<Uint8Array> {\n if (raw.body === null) return new Uint8Array(0)\n const declared = Number(raw.headers.get('content-length') ?? NaN)\n if (limit !== null && Number.isFinite(declared) && declared > limit) {\n await raw.body.cancel()\n throw new HttpException(413, 'Content Too Large')\n }\n const reader = raw.body.getReader()\n const chunks: Uint8Array[] = []\n let size = 0\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n size += value.byteLength\n if (limit !== null && size > limit) {\n await reader.cancel()\n throw new HttpException(413, 'Content Too Large')\n }\n chunks.push(value)\n }\n const out = new Uint8Array(size)\n let offset = 0\n for (const chunk of chunks) {\n out.set(chunk, offset)\n offset += chunk.byteLength\n }\n return out\n}\n","import { CookieJar, HttpRequest, Session, type Container } from '@orieljs/contracts'\nimport { currentContainer } from '@orieljs/container'\n\n/** The current container, only when it is a request scope (the kernel binds HttpRequest there). */\nexport function requestScope(): Container | undefined {\n const container = currentContainer()\n return container !== undefined && container.bound(HttpRequest) ? container : undefined\n}\n\nexport function currentRequest(): HttpRequest | undefined {\n return requestScope()?.make(HttpRequest)\n}\n\n/** The request's session, or undefined outside a request or when no Session provider is registered. */\nexport function optionalSession(): Session | undefined {\n const scope = requestScope()\n return scope?.bound(Session) ? scope.make(Session) : undefined\n}\n\nexport function optionalCookieJar(): CookieJar | undefined {\n const scope = requestScope()\n return scope?.bound(CookieJar) ? scope.make(CookieJar) : undefined\n}\n","import type { Cookie, HeadersInit, RedirectResponse } from '@orieljs/contracts'\nimport { currentRequest, optionalCookieJar, optionalSession } from './context'\n\ntype ErrorsInput = Record<string, string | string[]> | { toObject(): Record<string, string[]> }\n\n/** A Set-Cookie value. `minutes` 0 is a session cookie; a negative value deletes the cookie. */\nfunction serializeCookie(cookie: Cookie): string {\n const parts = [`${encodeURIComponent(cookie.name)}=${encodeURIComponent(cookie.value)}`, `Path=${cookie.path}`]\n if (cookie.domain !== undefined) parts.push(`Domain=${cookie.domain}`)\n if (cookie.secure) parts.push('Secure')\n if (cookie.httpOnly) parts.push('HttpOnly')\n parts.push(`SameSite=${cookie.sameSite.charAt(0).toUpperCase()}${cookie.sameSite.slice(1)}`)\n if (cookie.minutes < 0) parts.push('Max-Age=0', 'Expires=Thu, 01 Jan 1970 00:00:00 GMT')\n else if (cookie.minutes > 0) parts.push(`Max-Age=${Math.round(cookie.minutes * 60)}`)\n return parts.join('; ')\n}\n\n/**\n * Laravel's RedirectResponse. with()/withErrors()/withInput() flash to the request's Session immediately, like\n * Laravel; without a bound Session (an API-only app) they are skipped silently.\n */\nexport class HttpRedirectResponse implements RedirectResponse {\n readonly #headers: Headers\n\n constructor(\n readonly targetUrl: string,\n readonly status = 302,\n headers?: HeadersInit,\n ) {\n this.#headers = new Headers(headers)\n }\n\n with(key: string | Record<string, unknown>, value?: unknown): this {\n const session = optionalSession()\n if (session === undefined) return this\n if (typeof key === 'string') session.flash(key, value)\n else for (const [name, item] of Object.entries(key)) session.flash(name, item)\n return this\n }\n\n /** Flashes `errors` as { [bag]: { field: string[] } }, keeping the other bags already flashed. */\n withErrors(errors: ErrorsInput, bag = 'default'): this {\n const session = optionalSession()\n if (session === undefined) return this\n const source =\n typeof (errors as { toObject?: unknown }).toObject === 'function'\n ? (errors as { toObject(): Record<string, string[]> }).toObject()\n : (errors as Record<string, string | string[]>)\n const normalized = Object.fromEntries(\n Object.entries(source).map(([field, messages]) => [field, Array.isArray(messages) ? [...messages] : [messages]]),\n )\n const existing = session.get<Record<string, Record<string, string[]>>>('errors', {})\n session.flash('errors', { ...existing, [bag]: normalized })\n return this\n }\n\n /** Flashes `input`, or the current request's input (files are never part of input()). */\n withInput(input?: Record<string, unknown>): this {\n const session = optionalSession()\n if (session === undefined) return this\n session.flashInput(input ?? currentRequest()?.input<Record<string, unknown>>() ?? {})\n return this\n }\n\n /**\n * Always a Set-Cookie header on this response (Laravel's RedirectResponse::withCookie). A bound CookieJar only\n * supplies the defaults (path, domain, secure, same-site); queueing would lose the cookie outside the web group.\n */\n withCookie(name: string, value: string, minutes = 0): this {\n const jar = optionalCookieJar()\n const cookie: Cookie =\n jar !== undefined\n ? jar.make(name, value, minutes)\n : { name, value, minutes, path: '/', secure: false, httpOnly: true, sameSite: 'lax' }\n this.#headers.append('Set-Cookie', serializeCookie(cookie))\n return this\n }\n\n header(name: string, value: string): this {\n this.#headers.set(name, value)\n return this\n }\n\n toResponse(): Response {\n const headers = new Headers(this.#headers)\n headers.set('Location', this.targetUrl)\n return new Response(null, { status: this.status, headers })\n }\n}\n","import { UrlGenerator, type HeadersInit, type Redirector } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport { currentRequest, optionalSession } from './context'\nimport { HttpRedirectResponse } from './HttpRedirectResponse'\n\n/** Laravel's Redirector. Stateless: the URL generator and session come from the current container. */\nexport class HttpRedirector implements Redirector {\n to(path: string, status = 302, headers?: HeadersInit): HttpRedirectResponse {\n return new HttpRedirectResponse(inject(UrlGenerator).to(path), status, headers)\n }\n\n route(name: string, parameters?: unknown, status = 302): HttpRedirectResponse {\n return new HttpRedirectResponse(inject(UrlGenerator).route(name, parameters), status)\n }\n\n back(fallback?: string, status = 302): HttpRedirectResponse {\n return new HttpRedirectResponse(inject(UrlGenerator).previous(fallback), status)\n }\n\n /** Pulls url.intended from the session (put there by guest()), else goes to `fallback`. */\n intended(fallback = '/', status = 302): HttpRedirectResponse {\n const path = optionalSession()?.pull<string | undefined>('url.intended') ?? fallback\n return this.to(path, status)\n }\n\n away(url: string, status = 302): HttpRedirectResponse {\n return new HttpRedirectResponse(url, status)\n }\n\n /** Remembers where a guest was going (a GET page, else the previous URL), then redirects to `path`. */\n guest(path: string, status = 302): HttpRedirectResponse {\n const session = optionalSession()\n const request = currentRequest()\n if (session !== undefined) {\n const intended =\n request !== undefined && request.method() === 'GET' && !request.expectsJson()\n ? request.fullUrl()\n : inject(UrlGenerator).previous()\n session.put('url.intended', intended)\n }\n return this.to(path, status)\n }\n\n setIntendedUrl(url: string): void {\n optionalSession()?.put('url.intended', url)\n }\n\n refresh(status = 302): HttpRedirectResponse {\n return this.to(currentRequest()?.fullUrl() ?? inject(UrlGenerator).current(), status)\n }\n}\n","/**\n * The socket address of each incoming Request, filled by the server adapters (and by test clients).\n * Kept on globalThis under a Symbol.for key, so a package that can't import @orieljs/http (Testing) can set it.\n */\nconst KEY = Symbol.for('oriel:http.client-address')\nconst store = ((globalThis as unknown as Record<symbol, WeakMap<Request, string> | undefined>)[KEY] ??= new WeakMap<Request, string>())\n\nexport function setClientAddress(request: Request, address: string | undefined): void {\n if (address !== undefined && address !== '') store.set(request, address)\n}\n\nexport function clientAddress(request: Request): string | undefined {\n return store.get(request)\n}\n","import { FilesystemManager, type UploadedFile } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport { Str } from '@orieljs/support'\nimport { extensionFromMime } from './mime'\n\n/** An uploaded file from a multipart body. store()/storeAs() go through the FilesystemManager. */\nexport class FormUploadedFile implements UploadedFile {\n readonly clientName: string\n readonly mimeType: string\n readonly size: number\n\n constructor(private readonly file: Blob & { readonly name?: string }) {\n this.clientName = file.name ?? ''\n this.mimeType = file.type === '' ? 'application/octet-stream' : file.type\n this.size = file.size\n }\n\n /** Guessed from the MIME type, falling back to the client's extension (Laravel's extension()). */\n extension(): string {\n return extensionFromMime(this.mimeType) ?? this.clientExtension()\n }\n\n clientExtension(): string {\n const dot = this.clientName.lastIndexOf('.')\n return dot === -1 ? '' : this.clientName.slice(dot + 1).toLowerCase()\n }\n\n /** A random 40-character name with the guessed extension. */\n hashName(): string {\n const extension = this.extension()\n return extension === '' ? Str.random(40) : `${Str.random(40)}.${extension}`\n }\n\n arrayBuffer(): Promise<ArrayBuffer> {\n return this.file.arrayBuffer()\n }\n\n text(): Promise<string> {\n return this.file.text()\n }\n\n stream(): ReadableStream<Uint8Array> {\n return this.file.stream() as ReadableStream<Uint8Array>\n }\n\n store(directory: string, disk?: string): Promise<string> {\n return inject(FilesystemManager).disk(disk).putFile(directory, this)\n }\n\n storeAs(directory: string, name: string, disk?: string): Promise<string> {\n return inject(FilesystemManager).disk(disk).putFileAs(directory, this, name)\n }\n}\n","/** A small extension ↔ MIME map for uploads and downloads (not exhaustive on purpose). */\nconst TYPES: Record<string, string> = {\n avif: 'image/avif',\n css: 'text/css',\n csv: 'text/csv',\n doc: 'application/msword',\n docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n gif: 'image/gif',\n gz: 'application/gzip',\n html: 'text/html',\n ico: 'image/vnd.microsoft.icon',\n jpg: 'image/jpeg',\n js: 'text/javascript',\n map: 'application/json',\n json: 'application/json',\n md: 'text/markdown',\n mp3: 'audio/mpeg',\n mp4: 'video/mp4',\n otf: 'font/otf',\n pdf: 'application/pdf',\n png: 'image/png',\n svg: 'image/svg+xml',\n ttf: 'font/ttf',\n txt: 'text/plain',\n wasm: 'application/wasm',\n webm: 'video/webm',\n webp: 'image/webp',\n woff: 'font/woff',\n woff2: 'font/woff2',\n xls: 'application/vnd.ms-excel',\n xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n xml: 'application/xml',\n zip: 'application/zip',\n}\nconst ALIASES: Record<string, string> = { jpeg: 'jpg', htm: 'html', mjs: 'js', text: 'txt' }\nconst EXTENSIONS = Object.fromEntries(Object.entries(TYPES).map(([extension, type]) => [type, extension]))\n\n/** 'report.PDF' or 'pdf' → 'application/pdf'; unknown → 'application/octet-stream'. */\nexport function mimeFromExtension(pathOrExtension: string): string {\n const extension = pathOrExtension.slice(pathOrExtension.lastIndexOf('.') + 1).toLowerCase()\n return TYPES[ALIASES[extension] ?? extension] ?? 'application/octet-stream'\n}\n\n/** 'image/jpeg; charset=…' → 'jpg'; unknown → undefined. */\nexport function extensionFromMime(type: string): string | undefined {\n return EXTENSIONS[type.split(';')[0]!.trim().toLowerCase()]\n}\n","import {\n CurrentRoute,\n Session,\n ValidationFactory,\n type HttpRequest,\n type Rules,\n type UploadedFile,\n} from '@orieljs/contracts'\nimport { currentContainer, inject } from '@orieljs/container'\nimport { Arr, Str } from '@orieljs/support'\nimport { readBody } from './body'\nimport { clientAddress } from './clientAddress'\nimport { FormUploadedFile } from './FormUploadedFile'\nimport { fromEntries, isBlank, isPlainObject, mergeRecursive, sanitize, transformLeaves } from './input'\n\ntype Tree = Record<string, unknown>\n\nexport interface IncomingRequestOptions {\n /** Proxy addresses whose X-Forwarded-* headers are believed: exact IPs, IPv4 CIDRs, or '*'. */\n trustedProxies?: readonly string[]\n /** Largest request body in bytes before a 413 (config http.max_body_size); null is unlimited. Default 8 MB. */\n maxBodySize?: number | null\n}\n\nconst TRUE_VALUES = new Set(['1', 'true', 'on', 'yes'])\n\nconst normalizeIp = (ip: string): string => ip.trim().replace(/^::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/i, '$1')\n\nfunction ipv4ToNumber(ip: string): number | undefined {\n const parts = ip.split('.')\n if (parts.length !== 4 || parts.some((part) => !/^\\d{1,3}$/.test(part) || Number(part) > 255)) return undefined\n return parts.reduce((total, part) => total * 256 + Number(part), 0)\n}\n\n/** Exact match, IPv4 CIDR ('10.0.0.0/8') or '*'. */\nexport function ipMatches(ip: string, patterns: readonly string[]): boolean {\n const address = normalizeIp(ip)\n return patterns.some((pattern) => {\n if (pattern === '*') return true\n if (!pattern.includes('/')) return normalizeIp(pattern) === address\n const [range, bits] = pattern.split('/') as [string, string]\n const base = ipv4ToNumber(range)\n const value = ipv4ToNumber(address)\n const size = Number(bits)\n if (base === undefined || value === undefined || !(size >= 0 && size <= 32)) return false\n const mask = size === 0 ? 0 : (~0 << (32 - size)) >>> 0\n return ((base & mask) >>> 0) === ((value & mask) >>> 0)\n })\n}\n\n/**\n * The HttpRequest implementation (Laravel's Illuminate\\Http\\Request). The kernel calls load() once, before any\n * middleware, so every accessor below is synchronous.\n *\n * `http.max_body_size` applies to the bodies this class parses (JSON, urlencoded and multipart). A handler that reads\n * `request.raw` directly bypasses it and must enforce its own limit.\n */\nexport class IncomingRequest implements HttpRequest {\n readonly #url: URL\n readonly #trustedProxies: readonly string[]\n readonly #maxBodySize: number | null\n #query: Tree\n #body: Tree = {}\n #files: Tree = {}\n #content = ''\n #method: string\n #cookies: Record<string, string> | undefined\n #loading: Promise<this> | undefined\n #userResolver: ((guard?: string) => unknown) | undefined\n\n constructor(\n readonly raw: Request,\n options: IncomingRequestOptions = {},\n ) {\n this.#url = new URL(raw.url)\n this.#trustedProxies = options.trustedProxies ?? []\n this.#maxBodySize = options.maxBodySize === undefined ? 8 * 1024 * 1024 : options.maxBodySize\n this.#query = fromEntries(this.#url.searchParams.entries())\n this.#method = raw.method.toUpperCase()\n }\n\n /** Reads and parses the body (JSON, urlencoded or multipart) once, then applies method spoofing. */\n load(): Promise<this> {\n return (this.#loading ??= this.#load())\n }\n\n async #load(): Promise<this> {\n const method = this.raw.method.toUpperCase()\n if (method !== 'GET' && method !== 'HEAD' && this.raw.body !== null) {\n const type = (this.raw.headers.get('content-type') ?? '').toLowerCase()\n const isJson = type.includes('/json') || type.includes('+json')\n const isUrlencoded = type.startsWith('application/x-www-form-urlencoded')\n const isMultipart = type.startsWith('multipart/form-data')\n if (isJson || isUrlencoded || isMultipart) {\n // Size errors (413) must reach the caller; only a malformed body reads as empty input, as in Laravel.\n const bytes = await readBody(this.raw, this.#maxBodySize)\n try {\n if (isJson) {\n this.#content = new TextDecoder().decode(bytes)\n this.#body = this.#parseJson(this.#content)\n } else if (isUrlencoded) {\n this.#content = new TextDecoder().decode(bytes)\n this.#body = fromEntries(new URLSearchParams(this.#content).entries())\n } else {\n this.#parseForm(await new Response(bytes as Uint8Array<ArrayBuffer>, { headers: { 'content-type': this.raw.headers.get('content-type') ?? '' } }).formData())\n }\n } catch {\n // A malformed body reads as empty input, as in Laravel.\n }\n }\n }\n if (method === 'POST') {\n const override =\n this.raw.headers.get('x-http-method-override') ?? this.#string(this.#body._method) ?? this.#string(this.#query._method)\n const spoofed = override?.toUpperCase()\n if (spoofed !== undefined && /^[A-Z]+$/.test(spoofed) && !['GET', 'HEAD', 'CONNECT', 'TRACE'].includes(spoofed)) {\n this.#method = spoofed\n }\n }\n return this\n }\n\n #parseJson(text: string): Tree {\n let parsed: unknown\n try {\n parsed = JSON.parse(text)\n } catch {\n return {}\n }\n if (Array.isArray(parsed)) return sanitize({ ...parsed }) as Tree\n return isPlainObject(parsed) ? (sanitize(parsed) as Tree) : {}\n }\n\n #parseForm(form: FormData): void {\n const fields: Array<[string, unknown]> = []\n const files: Array<[string, unknown]> = []\n for (const [name, value] of form.entries()) {\n if (typeof value === 'string') fields.push([name, value])\n // A file input left empty arrives as filename=\"\" with no bytes (PHP's UPLOAD_ERR_NO_FILE).\n else if (!((value.name ?? '') === '' && value.size === 0)) files.push([name, new FormUploadedFile(value)])\n }\n this.#body = fromEntries(fields)\n this.#files = fromEntries(files)\n }\n\n #string(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined\n }\n\n method(): string {\n return this.#method\n }\n\n isMethod(method: string): boolean {\n return this.#method === method.toUpperCase()\n }\n\n /** The scheme and host, honouring X-Forwarded-Proto/Host from trusted proxies. */\n root(): string {\n const trusted = this.#fromTrustedProxy()\n const proto = trusted ? this.raw.headers.get('x-forwarded-proto')?.split(',')[0]?.trim() : undefined\n const host = trusted ? this.raw.headers.get('x-forwarded-host')?.split(',')[0]?.trim() : undefined\n const scheme = proto === 'https' || proto === 'http' ? proto : this.#url.protocol.slice(0, -1)\n return `${scheme}://${host !== undefined && host !== '' ? host : this.#url.host}`\n }\n\n /** The URL without the query string or a trailing slash. */\n url(): string {\n return `${this.root()}${this.#url.pathname}`.replace(/\\/+$/, '')\n }\n\n fullUrl(): string {\n return this.#url.search === '' ? this.url() : `${this.url()}${this.#url.search}`\n }\n\n /** 'posts/1', or '/' for the root. */\n path(): string {\n const trimmed = this.#url.pathname.replace(/^\\/+|\\/+$/g, '')\n return trimmed === '' ? '/' : trimmed\n }\n\n decodedPath(): string {\n try {\n return decodeURIComponent(this.path())\n } catch {\n return this.path()\n }\n }\n\n secure(): boolean {\n return this.root().startsWith('https:')\n }\n\n /** request.is('admin/*'): wildcard match against the decoded path. */\n is(...patterns: string[]): boolean {\n const path = this.decodedPath()\n return patterns.some((pattern) => {\n const trimmed = pattern.replace(/^\\/+|\\/+$/g, '')\n return Str.is(trimmed === '' ? '/' : trimmed, path)\n })\n }\n\n routeIs(...names: string[]): boolean {\n const name = this.#currentRoute()?.route.getName()\n return name !== undefined && names.some((pattern) => Str.is(pattern, name))\n }\n\n header(name: string): string | undefined\n header(name: string, defaultValue: string): string\n header(name: string, defaultValue?: string): string | undefined {\n return this.raw.headers.get(name) ?? defaultValue\n }\n\n bearerToken(): string | undefined {\n const header = this.header('authorization', '')\n const position = header.toLowerCase().lastIndexOf('bearer ')\n if (position === -1) return undefined\n const token = header.slice(position + 7).split(',')[0]!.trim()\n return token === '' ? undefined : token\n }\n\n userAgent(): string | undefined {\n return this.header('user-agent')\n }\n\n /** The socket address, or the right-most untrusted X-Forwarded-For entry when the socket is a trusted proxy. */\n ip(): string | undefined {\n const socket = clientAddress(this.raw)\n if (socket === undefined) return undefined\n const address = normalizeIp(socket)\n if (!this.#fromTrustedProxy()) return address\n const chain = (this.raw.headers.get('x-forwarded-for') ?? '')\n .split(',')\n .map((entry) => normalizeIp(entry))\n .filter((entry) => entry !== '')\n for (let i = chain.length - 1; i >= 0; i--) if (!ipMatches(chain[i]!, this.#trustedProxies)) return chain[i]\n return chain[0] ?? address\n }\n\n #fromTrustedProxy(): boolean {\n const socket = clientAddress(this.raw)\n return socket !== undefined && this.#trustedProxies.length > 0 && ipMatches(socket, this.#trustedProxies)\n }\n\n ajax(): boolean {\n return this.header('x-requested-with') === 'XMLHttpRequest'\n }\n\n pjax(): boolean {\n return this.header('x-pjax') === 'true'\n }\n\n /** The first Accept type is JSON. */\n wantsJson(): boolean {\n const first = this.header('accept', '').split(',')[0]!.trim()\n return first.includes('/json') || first.includes('+json')\n }\n\n /** Laravel: (ajax and not pjax and accepts anything) or wantsJson. */\n expectsJson(): boolean {\n const first = this.header('accept', '').split(',')[0]!.split(';')[0]!.trim()\n const acceptsAny = first === '' || first === '*/*' || first === '*'\n return (this.ajax() && !this.pjax() && acceptsAny) || this.wantsJson()\n }\n\n /** The raw body text for JSON and urlencoded requests ('' otherwise; the raw stream stays unread for other types). */\n content(): string {\n return this.#content\n }\n\n query<T = unknown>(key?: string, defaultValue?: T): T {\n return Arr.get<T>(this.#query, key, defaultValue)\n }\n\n /** Body wins over the query string (PHP's $body + $query). Files are not input. */\n input<T = unknown>(key?: string, defaultValue?: T): T {\n return Arr.get<T>({ ...this.#query, ...this.#body }, key, defaultValue)\n }\n\n /** Input plus files (array_replace_recursive). */\n all(): Record<string, unknown> {\n return mergeRecursive({ ...this.#query, ...this.#body }, this.#files)\n }\n\n only(...keys: Array<string | string[]>): Record<string, unknown> {\n const all = this.all()\n const out: Tree = {}\n for (const key of keys.flat()) if (Arr.has(all, key)) Arr.set(out, key, Arr.get(all, key))\n return out\n }\n\n except(...keys: Array<string | string[]>): Record<string, unknown> {\n const all = structuredCloneInput(this.all())\n for (const key of keys.flat()) Arr.forget(all, key)\n return all\n }\n\n has(...keys: Array<string | string[]>): boolean {\n const all = this.all()\n return keys.flat().every((key) => Arr.has(all, key))\n }\n\n hasAny(...keys: Array<string | string[]>): boolean {\n const all = this.all()\n return keys.flat().some((key) => Arr.has(all, key))\n }\n\n missing(...keys: Array<string | string[]>): boolean {\n return !this.has(...keys)\n }\n\n filled(key: string): boolean {\n return !isBlank(Arr.get(this.all(), key))\n }\n\n string(key: string, defaultValue = ''): string {\n const value = this.input<unknown>(key)\n return value === undefined || value === null ? defaultValue : String(value)\n }\n\n /** PHP's FILTER_VALIDATE_BOOLEAN: '1', 'true', 'on', 'yes' (any case) and true are true. */\n boolean(key: string, defaultValue = false): boolean {\n const value = this.input<unknown>(key)\n if (value === undefined) return defaultValue\n if (typeof value === 'boolean') return value\n if (typeof value === 'number') return value === 1\n return typeof value === 'string' && TRUE_VALUES.has(value.trim().toLowerCase())\n }\n\n /** PHP's intval: leading digits, else 0. */\n integer(key: string, defaultValue = 0): number {\n const value = this.input<unknown>(key)\n if (value === undefined) return defaultValue\n if (typeof value === 'number') return Number.isFinite(value) ? Math.trunc(value) : 0\n if (typeof value === 'boolean') return value ? 1 : 0\n const parsed = Number.parseInt(String(value).trim(), 10)\n return Number.isNaN(parsed) ? 0 : parsed\n }\n\n /** Adds or replaces top-level body values. */\n merge(values: Record<string, unknown>): this {\n this.#body = { ...this.#body, ...(sanitize(values) as Tree) }\n return this\n }\n\n /** Rewrites every scalar in the query and the body (TrimStrings and ConvertEmptyStringsToNull use this). */\n transformInput(transform: (key: string, value: unknown) => unknown): this {\n this.#query = transformLeaves(this.#query, transform)\n this.#body = transformLeaves(this.#body, transform)\n return this\n }\n\n file(key: string): UploadedFile | undefined {\n const value = Arr.get<unknown>(this.#files, key)\n return value instanceof FormUploadedFile ? value : undefined\n }\n\n hasFile(key: string): boolean {\n const value = Arr.get<unknown>(this.#files, key)\n return value instanceof FormUploadedFile || (Array.isArray(value) && value.some((item) => item instanceof FormUploadedFile))\n }\n\n allFiles(): Record<string, unknown> {\n return { ...this.#files }\n }\n\n cookie(name: string): string | undefined {\n return this.cookies()[name]\n }\n\n cookies(): Record<string, string> {\n if (this.#cookies === undefined) {\n const cookies: Record<string, string> = {}\n for (const part of (this.raw.headers.get('cookie') ?? '').split(';')) {\n const index = part.indexOf('=')\n if (index === -1) continue\n const name = part.slice(0, index).trim()\n if (name === '' || Object.hasOwn(cookies, name)) continue\n let value = part.slice(index + 1).trim()\n if (value.startsWith('\"') && value.endsWith('\"')) value = value.slice(1, -1)\n try {\n cookies[name] = decodeURIComponent(value)\n } catch {\n cookies[name] = value\n }\n }\n this.#cookies = cookies\n }\n return { ...this.#cookies }\n }\n\n /** Replaces the parsed cookies (EncryptCookies calls this after decrypting). */\n setCookies(cookies: Record<string, string>): void {\n this.#cookies = { ...cookies }\n }\n\n /** One route parameter (after model binding), or all of them. */\n route<T = unknown>(key?: string): T {\n const parameters = this.#currentRoute()?.parameters ?? {}\n return (key === undefined ? { ...parameters } : parameters[key]) as T\n }\n\n session(): Session {\n return inject(Session)\n }\n\n user<T = unknown>(guard?: string): T | undefined {\n return this.#userResolver?.(guard) as T | undefined\n }\n\n setUserResolver(resolver: (guard?: string) => unknown): void {\n this.#userResolver = resolver\n }\n\n /** Validates all() through the ValidationFactory; throws its Validation error on failure. */\n validate<T = Record<string, unknown>>(\n rules: Rules,\n messages?: Record<string, string>,\n attributes?: Record<string, string>,\n ): Promise<T> {\n return inject(ValidationFactory).make(this.all(), rules, messages, attributes).validated<T>()\n }\n\n #currentRoute() {\n const container = currentContainer()\n return container?.bound(CurrentRoute) ? container.make(CurrentRoute) : undefined\n }\n}\n\n/** A copy deep enough for except() to forget nested keys without touching the request. */\nfunction structuredCloneInput(tree: Tree): Tree {\n const out: Tree = {}\n for (const [key, value] of Object.entries(tree)) {\n out[key] = isPlainObject(value) ? structuredCloneInput(value) : Array.isArray(value) ? [...value] : value\n }\n return out\n}\n","/** Helpers for request input: PHP-style bracket keys, safe cloning (no prototype pollution) and blank checks. */\n\ntype Tree = Record<string, unknown>\n\nconst FORBIDDEN = new Set(['__proto__', 'prototype', 'constructor'])\n\n/** Keys PHP treats as integers: '0', '7', '42' (not '07' or '-1'). */\nconst INTEGER_KEY = /^(?:0|[1-9]\\d*)$/\n\n// Duplicated in Routing's BaseUrlGenerator.ts on purpose: Http, Routing and Pipeline may not import each other.\nexport const isPlainObject = (value: unknown): value is Tree => {\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/** 'user[name]' → ['user', 'name']; 'tags[]' → ['tags', '']; a malformed key stays whole. */\nexport function parseBracketKey(name: string): string[] {\n const open = name.indexOf('[')\n if (open <= 0 || !name.endsWith(']')) return [name]\n const segments = [name.slice(0, open)]\n const rest = name.slice(open)\n const matches = rest.match(/\\[[^[\\]]*\\]/g)\n if (matches === null || matches.join('') !== rest) return [name]\n for (const match of matches) segments.push(match.slice(1, -1))\n return segments\n}\n\n/** Objects whose keys are exactly 0..n-1 become arrays, recursively (PHP arrays → JS lists). */\nexport function normalizeLists(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(normalizeLists)\n if (!isPlainObject(value)) return value\n const keys = Object.keys(value)\n const out: Tree = {}\n for (const key of keys) out[key] = normalizeLists(value[key])\n if (keys.length > 0 && keys.every((key, index) => key === String(index))) return keys.map((key) => out[key])\n return out\n}\n\n/**\n * Builds nested input from flat form entries, PHP style: 'user[name]', 'tags[]', 'a[b][]'.\n * Keys containing __proto__/prototype/constructor are dropped.\n */\nexport function fromEntries(entries: Iterable<readonly [string, unknown]>): Tree {\n const root: Tree = {}\n // The next '[]' index per node, kept as PHP does (one past the highest integer key) so appending stays O(1).\n const nextIndex = new WeakMap<Tree, number>()\n for (const [name, value] of entries) {\n const segments = parseBracketKey(name)\n if (segments.some((segment) => FORBIDDEN.has(segment))) continue\n let node = root\n for (let i = 0; i < segments.length; i++) {\n let segment = segments[i]!\n const next = nextIndex.get(node) ?? 0\n if (segment === '') {\n segment = String(next)\n nextIndex.set(node, next + 1)\n } else if (INTEGER_KEY.test(segment) && Number(segment) >= next) {\n nextIndex.set(node, Number(segment) + 1)\n }\n if (i === segments.length - 1) {\n node[segment] = value\n break\n }\n if (!isPlainObject(node[segment])) node[segment] = {}\n node = node[segment] as Tree\n }\n }\n return normalizeLists(root) as Tree\n}\n\n/** Deep copy of parsed JSON without dangerous keys (JSON.parse creates an own \"__proto__\" property). */\nexport function sanitize(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sanitize)\n if (!isPlainObject(value)) return value\n const out: Tree = {}\n for (const [key, item] of Object.entries(value)) if (!FORBIDDEN.has(key)) out[key] = sanitize(item)\n return out\n}\n\n/** array_replace_recursive: `override` wins, nested plain objects merge. */\nexport function mergeRecursive(base: Tree, override: Tree): Tree {\n const out: Tree = { ...base }\n for (const [key, value] of Object.entries(override)) {\n if (FORBIDDEN.has(key)) continue\n const current = out[key]\n out[key] =\n (isPlainObject(current) || Array.isArray(current)) && (isPlainObject(value) || Array.isArray(value))\n ? normalizeLists(mergeRecursive({ ...current } as Tree, { ...value } as Tree))\n : value\n }\n return out\n}\n\n/** Laravel's blank(): null, undefined, whitespace-only strings, and empty arrays/objects. */\nexport function isBlank(value: unknown): boolean {\n if (value === null || value === undefined) return true\n if (typeof value === 'string') return value.trim() === ''\n if (Array.isArray(value)) return value.length === 0\n if (isPlainObject(value)) return Object.keys(value).length === 0\n return false\n}\n\n/** Applies `transform(dottedKey, value)` to every scalar leaf, inside nested objects and lists; the result replaces the leaf. */\nexport function transformLeaves(tree: Tree, transform: (key: string, value: unknown) => unknown, prefix = ''): Tree {\n const out: Tree = {}\n for (const [key, value] of Object.entries(tree)) out[key] = transformValue(`${prefix}${key}`, value, transform)\n return out\n}\n\nfunction transformValue(path: string, value: unknown, transform: (key: string, value: unknown) => unknown): unknown {\n if (Array.isArray(value)) return value.map((item, index) => transformValue(`${path}.${index}`, item, transform))\n if (isPlainObject(value)) return transformLeaves(value, transform, `${path}.`)\n return transform(path, value)\n}\n","import {\n HttpRequest,\n Redirector,\n ResponseFactory,\n UrlGenerator,\n type BodyInit,\n type HeadersInit,\n type RedirectResponse,\n type RouteName,\n} from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport { HttpException, HttpResponseException } from './errors'\n\n/** request() → the current HttpRequest; request('key', default) → its input. */\nexport function request(): HttpRequest\nexport function request<T = unknown>(key: string, defaultValue?: T): T\nexport function request(key?: string, defaultValue?: unknown): unknown {\n const current = inject(HttpRequest)\n return key === undefined ? current : current.input(key, defaultValue)\n}\n\n/** response() → the ResponseFactory; response(content, status, headers) → a Response. */\nexport function response(): ResponseFactory\nexport function response(content: BodyInit | null, status?: number, headers?: HeadersInit): Response\nexport function response(content?: BodyInit | null, status?: number, headers?: HeadersInit): ResponseFactory | Response {\n const factory = inject(ResponseFactory)\n return content === undefined ? factory : factory.make(content, status, headers)\n}\n\n/** The Redirector with its route() typed by the generated route names. */\nexport type TypedRedirector = Omit<Redirector, 'route'> & {\n route(name: RouteName, parameters?: unknown, status?: number): RedirectResponse\n}\n\n/** redirect() → the Redirector; redirect('/path', status) → a RedirectResponse. */\nexport function redirect(): TypedRedirector\nexport function redirect(to: string, status?: number): RedirectResponse\nexport function redirect(to?: string, status?: number): TypedRedirector | RedirectResponse {\n const redirector = inject(Redirector)\n return to === undefined ? redirector : redirector.to(to, status)\n}\n\n/** Redirect to the previous URL (same argument order as Redirector.back()). */\nexport function back(fallback?: string, status?: number): RedirectResponse {\n return inject(Redirector).back(fallback, status)\n}\n\n/** url() → the UrlGenerator; url('/path', query, absolute) → a URL. */\nexport function url(): UrlGenerator\nexport function url(path: string, query?: Record<string, unknown>, absolute?: boolean): string\nexport function url(path?: string, query?: Record<string, unknown>, absolute?: boolean): UrlGenerator | string {\n const generator = inject(UrlGenerator)\n return path === undefined ? generator : generator.to(path, query, absolute)\n}\n\n/** The URL of a named route. */\nexport function route(name: RouteName, parameters?: unknown, absolute?: boolean): string {\n return inject(UrlGenerator).route(name, parameters, absolute)\n}\n\n/** abort(404), abort(403, 'Nope', headers), or abort(response) to send a ready response. */\nexport function abort(status: number | Response, message = '', headers: Record<string, string> = {}): never {\n if (status instanceof Response) throw new HttpResponseException(status)\n throw new HttpException(status, message, headers)\n}\n\nexport function abortIf(condition: unknown, status: number | Response, message = '', headers: Record<string, string> = {}): void {\n if (condition) abort(status, message, headers)\n}\n\nexport function abortUnless(condition: unknown, status: number | Response, message = '', headers: Record<string, string> = {}): void {\n if (!condition) abort(status, message, headers)\n}\n","import { createReadStream } from 'node:fs'\nimport { stat } from 'node:fs/promises'\nimport { basename } from 'node:path'\nimport { Readable } from 'node:stream'\nimport { ViewFactory, type BodyInit, type HeadersInit, type ResponseFactory } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport { HttpException } from './errors'\nimport { mimeFromExtension } from './mime'\n\n/** 'attachment; filename=\"report.pdf\"' plus filename* for non-ASCII names (RFC 6266). */\nexport function contentDisposition(type: 'attachment' | 'inline', name: string): string {\n const fallback = name.replace(/[^\\x20-\\x7e]/g, '_').replace(/[\"\\\\]/g, '\\\\$&')\n const header = `${type}; filename=\"${fallback}\"`\n return /^[\\x20-\\x7e]*$/.test(name) ? header : `${header}; filename*=UTF-8''${encodeURIComponent(name)}`\n}\n\n/** Laravel's ResponseFactory (the response() helper). */\nexport class HttpResponseFactory implements ResponseFactory {\n /** Strings default to text/html; charset=utf-8, as in Laravel. */\n make(content: BodyInit | null = null, status = 200, headers?: HeadersInit): Response {\n const merged = new Headers(headers)\n if (typeof content === 'string' && !merged.has('content-type')) merged.set('content-type', 'text/html; charset=utf-8')\n return new Response(content, { status, headers: merged })\n }\n\n json(data: unknown, status = 200, headers?: HeadersInit): Response {\n const merged = new Headers(headers)\n if (!merged.has('content-type')) merged.set('content-type', 'application/json')\n return new Response(JSON.stringify(data === undefined ? null : data), { status, headers: merged })\n }\n\n noContent(status = 204): Response {\n return new Response(null, { status })\n }\n\n /** Renders a view (through the ViewFactory) into an HTML response. */\n async view(name: string, data: Record<string, unknown> = {}, status = 200, headers?: HeadersInit): Promise<Response> {\n const html = await inject(ViewFactory).make(name, data).render()\n return this.make(html, status, headers)\n }\n\n /** Streams a file as an attachment. A missing file is a 404. */\n download(path: string, name = basename(path), headers?: HeadersInit): Promise<Response> {\n return this.#file(path, 'attachment', name, headers)\n }\n\n /** Streams a file for the browser to display (Laravel's response()->file()). */\n file(path: string, headers?: HeadersInit): Promise<Response> {\n return this.#file(path, 'inline', basename(path), headers)\n }\n\n stream(body: ReadableStream, status = 200, headers?: HeadersInit): Response {\n return new Response(body, { status, headers })\n }\n\n async #file(path: string, disposition: 'attachment' | 'inline', name: string, headers?: HeadersInit): Promise<Response> {\n const info = await stat(path).catch(() => undefined)\n // No file path in the message: HTTP error messages are shown to clients.\n if (info === undefined || !info.isFile()) throw new HttpException(404)\n const merged = new Headers(headers)\n if (!merged.has('content-type')) merged.set('content-type', mimeFromExtension(name))\n merged.set('content-length', String(info.size))\n merged.set('content-disposition', contentDisposition(disposition, name))\n const body = Readable.toWeb(createReadStream(path)) as ReadableStream<Uint8Array>\n return new Response(body, { status: 200, headers: merged })\n }\n}\n","import {\n ConfigRepository,\n CurrentRoute,\n ExceptionHandler,\n HttpRequest,\n PipelineFactory,\n Router,\n type Application,\n type Container,\n type HttpKernel,\n type Middleware,\n type MiddlewareClass,\n} from '@orieljs/contracts'\nimport { currentContainer } from '@orieljs/container'\nimport { HttpServerError } from './errors'\nimport { IncomingRequest } from './IncomingRequest'\nimport { ConvertEmptyStringsToNull } from './middleware/ConvertEmptyStringsToNull'\nimport { TrimStrings } from './middleware/TrimStrings'\n\ninterface RequestState {\n readonly scope: Container\n readonly request: IncomingRequest\n readonly middleware: Middleware[]\n}\n\n/** The plain-text 500 the kernel falls back to. Exported so the server adapters can reuse it. */\nexport const plainServerError = (): Response =>\n new Response('Server Error', { status: 500, headers: { 'content-type': 'text/plain; charset=utf-8' } })\n\n/**\n * Laravel's Http Kernel: wraps the raw Request, binds it in the request scope, loads the body, then sends it through\n * the global middleware to the router. Every stage renders its own errors through the ExceptionHandler.\n */\nexport class Kernel implements HttpKernel {\n #middleware: MiddlewareClass[] = [TrimStrings, ConvertEmptyStringsToNull]\n readonly #requests = new WeakMap<Request, RequestState>()\n\n constructor(protected readonly app: Application) {}\n\n getGlobalMiddleware(): MiddlewareClass[] {\n return [...this.#middleware]\n }\n\n setGlobalMiddleware(middleware: MiddlewareClass[]): this {\n this.#middleware = [...middleware]\n return this\n }\n\n appendMiddleware(...middleware: MiddlewareClass[]): this {\n for (const cls of middleware) if (!this.#middleware.includes(cls)) this.#middleware.push(cls)\n return this\n }\n\n prependMiddleware(...middleware: MiddlewareClass[]): this {\n for (const cls of [...middleware].reverse()) if (!this.#middleware.includes(cls)) this.#middleware.unshift(cls)\n return this\n }\n\n hasMiddleware(middleware: MiddlewareClass): boolean {\n return this.#middleware.includes(middleware)\n }\n\n /** Runs in the current request scope (Application.handle() opens one); called directly, it opens its own. */\n handle(raw: Request): Promise<Response> {\n const current = currentContainer()\n const scope = current !== undefined && current !== this.app ? current : this.app.createScope()\n return scope.run(() => this.#handle(raw, scope))\n }\n\n async #handle(raw: Request, scope: Container): Promise<Response> {\n let request: IncomingRequest | undefined\n let response: Response\n try {\n request = new IncomingRequest(raw, { trustedProxies: this.#trustedProxies(), maxBodySize: this.#maxBodySize() })\n scope.instance(HttpRequest, request)\n const state: RequestState = { scope, request, middleware: [] }\n this.#requests.set(raw, state)\n await request.load()\n response = await this.#sendThroughGlobal(state)\n } catch (error) {\n request ??= this.#bareRequest(scope, raw)\n if (request !== undefined) {\n response = await this.#renderLast(scope, request, error)\n } else {\n await this.#report(scope, error)\n response = plainServerError()\n }\n }\n // HEAD: same status and headers as GET, no body. Cancel the dropped body so an open file stream is released.\n if (raw.method.toUpperCase() === 'HEAD' && response.body !== null) {\n await response.body.cancel().catch(() => undefined)\n response = new Response(null, { status: response.status, statusText: response.statusText, headers: response.headers })\n }\n return response\n }\n\n /** The request without options, for rendering an error raised while the real one was being built. */\n #bareRequest(scope: Container, raw: Request): IncomingRequest | undefined {\n try {\n const request = new IncomingRequest(raw)\n scope.instance(HttpRequest, request)\n return request\n } catch {\n return undefined\n }\n }\n\n /** Runs terminate() on the global and route middleware (inside the request's scope), then Application.terminate(), inside the same scope, so terminating callbacks see the request's bindings. */\n async terminate(raw: Request, response: Response): Promise<void> {\n const state = this.#requests.get(raw)\n if (state !== undefined) {\n this.#requests.delete(raw)\n await state.scope.run(async () => {\n const route = state.scope.bound(CurrentRoute) ? state.scope.make(CurrentRoute).middleware : []\n for (const middleware of [...state.middleware, ...route]) {\n if (typeof middleware.terminate !== 'function') continue\n try {\n await middleware.terminate(state.request, response)\n } catch (error) {\n await this.#report(state.scope, error)\n }\n }\n await this.app.terminate()\n })\n return\n }\n await this.app.terminate()\n }\n\n #sendThroughGlobal(state: RequestState): Promise<Response> {\n const { scope, request } = state\n const pipes = this.#middleware.map((cls) => {\n const instance = scope.make(cls)\n state.middleware.push(instance)\n return (passable: HttpRequest, next: (passable: HttpRequest) => Promise<unknown>) =>\n this.#guard(scope, passable, () => instance.handle(passable, next as (r: HttpRequest) => Promise<Response>))\n })\n return scope\n .make(PipelineFactory)\n .make<HttpRequest>()\n .send(request)\n .through(pipes)\n .then((passable) => this.#guard(scope, passable, () => this.#dispatch(scope, passable)))\n }\n\n #dispatch(scope: Container, request: HttpRequest): Promise<Response> {\n return scope.make(Router).dispatch(request)\n }\n\n /** Converts a Responsable result, and renders a thrown error at this stage (Laravel's Routing\\Pipeline). */\n async #guard(scope: Container, request: HttpRequest, run: () => Promise<unknown>): Promise<Response> {\n try {\n const result = await run()\n if (result instanceof Response) return result\n const responsable = result as { toResponse?: (request: unknown) => Response | Promise<Response> } | null\n if (typeof responsable?.toResponse === 'function') return await responsable.toResponse(request)\n throw new HttpServerError('Middleware must return a Response.')\n } catch (error) {\n if (!scope.bound(ExceptionHandler)) throw error\n const handler = scope.make(ExceptionHandler)\n await handler.report(error)\n return handler.render(request, error)\n }\n }\n\n /** Last resort: the handler failed or isn't bound. Never throws. */\n async #renderLast(scope: Container, request: HttpRequest, error: unknown): Promise<Response> {\n if (scope.bound(ExceptionHandler)) {\n try {\n const handler = scope.make(ExceptionHandler)\n await handler.report(error)\n return await handler.render(request, error)\n } catch (renderError) {\n console.error(renderError)\n }\n } else {\n console.error(error)\n }\n return plainServerError()\n }\n\n async #report(scope: Container, error: unknown): Promise<void> {\n try {\n if (scope.bound(ExceptionHandler)) await scope.make(ExceptionHandler).report(error)\n else console.error(error)\n } catch (reportError) {\n console.error(reportError)\n }\n }\n\n /** config('http.max_body_size'): bytes, or null for no limit. Anything else is a configuration error. */\n #maxBodySize(): number | null {\n if (!this.app.bound(ConfigRepository)) return 8 * 1024 * 1024\n const value = this.app.make(ConfigRepository).get<unknown>('http.max_body_size', 8 * 1024 * 1024)\n if (value === null) return null\n if (typeof value === 'number' && Number.isFinite(value) && value >= 0) return value\n throw new HttpServerError(\n `Invalid http.max_body_size ${JSON.stringify(value) ?? String(value)}: use a number of bytes (0 or more), or null for no limit.`,\n )\n }\n\n /** config('http.trusted_proxies'): an array, or a comma-separated string such as '*' or '10.0.0.0/8,::1'. */\n #trustedProxies(): string[] {\n if (!this.app.bound(ConfigRepository)) return []\n const value = this.app.make(ConfigRepository).get<unknown>('http.trusted_proxies', [])\n if (typeof value === 'string') return value.split(',').map((entry) => entry.trim()).filter((entry) => entry !== '')\n return Array.isArray(value) ? value.map(String) : []\n }\n}\n","import type { HttpRequest, Middleware, Next } from '@orieljs/contracts'\nimport { IncomingRequest } from '../IncomingRequest'\n\n/** '' becomes null in the query and body, so `nullable` validation behaves as in Laravel. */\nexport class ConvertEmptyStringsToNull implements Middleware {\n async handle(request: HttpRequest, next: Next): Promise<Response> {\n if (request instanceof IncomingRequest) request.transformInput((_key, value) => (value === '' ? null : value))\n return next(request)\n }\n}\n","import type { HttpRequest, Middleware, Next } from '@orieljs/contracts'\nimport { IncomingRequest } from '../IncomingRequest'\n\n/** Laravel's trim: whitespace plus BOM, zero-width space and left-to-right mark. */\nconst TRIM = /^[\\s\\uFEFF\\u200B\\u200E]+|[\\s\\uFEFF\\u200B\\u200E]+$/g\n\n/** Trims every string in the query and body, except password fields (Laravel's TrimStrings). */\nexport class TrimStrings implements Middleware {\n /** Dotted input keys left untouched. Override in a subclass to change. */\n protected except: string[] = ['current_password', 'password', 'password_confirmation']\n\n async handle(request: HttpRequest, next: Next): Promise<Response> {\n if (request instanceof IncomingRequest) {\n request.transformInput((key, value) =>\n typeof value === 'string' && !this.except.includes(key) ? value.replace(TRIM, '') : value,\n )\n }\n return next(request)\n }\n}\n","import {\n ConfigRepository,\n MiddlewareCallbacks,\n Router,\n type Application,\n type HttpRequest,\n type MiddlewareClass,\n type MiddlewareConfigurator,\n type MiddlewareReference,\n} from '@orieljs/contracts'\nimport type { Kernel } from './Kernel'\n\ninterface GroupOptions {\n append?: MiddlewareClass[]\n prepend?: MiddlewareClass[]\n remove?: MiddlewareClass[]\n}\n\n/** The `m` in withMiddleware((m) => …): edits the kernel's global middleware and the router's groups and aliases. */\nexport class MiddlewareConfiguration implements MiddlewareConfigurator {\n constructor(\n private readonly kernel: Kernel,\n private readonly router: Router,\n private readonly config?: ConfigRepository,\n ) {}\n\n append(...middleware: MiddlewareClass[]): this {\n this.kernel.appendMiddleware(...middleware)\n return this\n }\n\n prepend(...middleware: MiddlewareClass[]): this {\n this.kernel.prependMiddleware(...middleware)\n return this\n }\n\n web(options: GroupOptions): this {\n return this.#modifyGroup('web', options)\n }\n\n api(options: GroupOptions): this {\n return this.#modifyGroup('api', options)\n }\n\n alias(aliases: Record<string, MiddlewareClass>): this {\n for (const [name, middleware] of Object.entries(aliases)) this.router.aliasMiddleware(name, middleware)\n return this\n }\n\n group(name: string, middleware: Array<MiddlewareClass | string>): this {\n this.router.middlewareGroup(name, middleware)\n return this\n }\n\n /** Stored in config('http.csrf_except'), which the Session component's VerifyCsrfToken reads. */\n validateCsrfTokens(options: { except: string[] }): this {\n const current = this.config?.get<string[]>('http.csrf_except', []) ?? []\n this.config?.set('http.csrf_except', [...current, ...options.except])\n return this\n }\n\n /** Stored in config('http.redirect_guests_to'), which the Auth middleware and the exception handler read. */\n redirectGuestsTo(url: string | ((request: HttpRequest) => string)): this {\n this.config?.set('http.redirect_guests_to', url)\n return this\n }\n\n /** Laravel 11's redirectUsersTo(): stored in config('http.redirect_users_to') for Auth's RedirectIfAuthenticated. */\n redirectUsersTo(url: string | ((request: HttpRequest) => string)): this {\n this.config?.set('http.redirect_users_to', url)\n return this\n }\n\n /** Laravel's order: prepends, then the group minus removals, then appends. */\n #modifyGroup(name: string, { append = [], prepend = [], remove = [] }: GroupOptions): this {\n const current: MiddlewareReference[] = this.router.getMiddlewareGroups()[name] ?? []\n const moved = new Set<MiddlewareReference>([...append, ...prepend, ...remove])\n this.router.middlewareGroup(name, [...prepend, ...current.filter((entry) => !moved.has(entry)), ...append])\n return this\n }\n}\n\n/** Runs the withMiddleware() callbacks collected by the ApplicationBuilder (HttpServiceProvider calls this once booted). */\nexport function applyMiddlewareCallbacks(app: Application, kernel: Kernel): void {\n if (!app.bound(MiddlewareCallbacks)) return\n const callbacks = app.make(MiddlewareCallbacks) as Array<(configurator: MiddlewareConfigurator) => void>\n if (callbacks.length === 0) return\n const config = app.bound(ConfigRepository) ? app.make(ConfigRepository) : undefined\n const configurator = new MiddlewareConfiguration(kernel, app.make(Router), config)\n for (const callback of callbacks) callback(configurator)\n}\n","import {\n ConfigRepository,\n LogManager,\n Redirector,\n UrlGenerator,\n ViewFactory,\n type Application,\n type AuthenticationError,\n type Container,\n type ErrorKind,\n type ExceptionHandler,\n type HttpRequest,\n type OrielError,\n type ValidationError,\n} from '@orieljs/contracts'\nimport { currentContainer } from '@orieljs/container'\nimport { debugPage, minimalPage, stackFrames, statusText } from './errorPages'\nimport { HttpResponseException } from './errors'\nimport { IncomingRequest } from './IncomingRequest'\n\nexport type ReportCallback = (error: unknown) => void | boolean | Promise<void | boolean>\nexport type RenderCallback = (error: unknown, request: unknown) => Response | undefined | Promise<Response | undefined>\nexport type ErrorClass = abstract new (...args: never[]) => Error\n\n/** Laravel's $internalDontReport: expected errors that are rendered, never logged ('Server' is not here). */\nconst NOT_REPORTED = new Set<ErrorKind>(['Http', 'ModelNotFound', 'Validation', 'Authentication', 'Authorization', 'TokenMismatch'])\n/** Kinds whose message is safe to show to users, at any status (Laravel's HttpException rendering). */\nconst HTTP_KINDS = new Set<ErrorKind>(['Http', 'ModelNotFound', 'Authorization', 'TokenMismatch'])\n\nconst kindOf = (error: unknown): ErrorKind | undefined =>\n typeof error === 'object' && error !== null && typeof (error as OrielError).kind === 'string' ? (error as OrielError).kind : undefined\n\n/** HTTP status for an error (spec §7). */\nexport function statusFor(error: unknown): number {\n const status = (error as Partial<OrielError> | null)?.status\n switch (kindOf(error)) {\n case 'Http':\n return status ?? 500\n case 'ModelNotFound':\n return 404\n case 'Authorization':\n return status ?? 403\n case 'TokenMismatch':\n return 419\n case 'Authentication':\n return 401\n case 'Validation':\n return status ?? 422\n case 'Server':\n return status ?? 500\n default:\n return 500\n }\n}\n\n/** \"The title field is required. (and 2 more errors)\" (Laravel's ValidationException::summarize). */\nexport function summarizeValidation(errors: Record<string, string[]>): string {\n const messages = Object.values(errors).flat()\n if (messages.length === 0) return 'The given data was invalid.'\n const more = messages.length - 1\n return more === 0 ? messages[0]! : `${messages[0]!} (and ${more} more ${more === 1 ? 'error' : 'errors'})`\n}\n\n/** An HTTP-like error: its message may be shown and it doesn't get the debug page. */\nconst isHttpLike = (error: unknown): boolean => {\n const kind = kindOf(error)\n return kind !== undefined && HTTP_KINDS.has(kind)\n}\n\n/** The exception handler (spec §7): report through the LogManager, render by error kind. */\nexport class ErrorHandler implements ExceptionHandler {\n /** Input keys never flashed back on a validation redirect. */\n protected dontFlash = ['current_password', 'password', 'password_confirmation']\n readonly #reportCallbacks: ReportCallback[] = []\n readonly #renderCallbacks: RenderCallback[] = []\n readonly #dontReport: ErrorClass[] = []\n readonly #reported = new WeakSet<object>()\n\n constructor(protected readonly app: Application) {}\n\n reportUsing(callback: ReportCallback): void {\n this.#reportCallbacks.push(callback)\n }\n\n renderUsing(callback: RenderCallback): void {\n this.#renderCallbacks.push(callback)\n }\n\n ignore(...classes: ErrorClass[]): void {\n this.#dontReport.push(...classes)\n }\n\n shouldReport(error: unknown): boolean {\n const kind = kindOf(error)\n if (kind !== undefined && NOT_REPORTED.has(kind)) return false\n return !this.#dontReport.some((cls) => error instanceof cls)\n }\n\n /** Report callbacks first (returning false stops the default log), then LogManager.error(), else console.error. Once per error. */\n async report(error: unknown): Promise<void> {\n if (!this.shouldReport(error)) return\n if (typeof error === 'object' && error !== null) {\n if (this.#reported.has(error)) return\n this.#reported.add(error)\n }\n try {\n for (const callback of this.#reportCallbacks) if ((await callback(error)) === false) return\n const container = this.#container()\n if (container.bound(LogManager)) {\n const message = error instanceof Error ? error.message : String(error)\n container.make(LogManager).error(message, { exception: error })\n } else {\n console.error(error)\n }\n } catch (reportError) {\n console.error(reportError)\n }\n }\n\n async render(request: unknown, error: unknown): Promise<Response> {\n for (const callback of this.#renderCallbacks) {\n const response = await callback(error, request)\n if (response instanceof Response) return response\n }\n if (error instanceof HttpResponseException) return error.response\n const custom = await this.#renderCustom(request, error)\n if (custom !== undefined) return custom\n\n const http = this.#httpRequest(request)\n const kind = kindOf(error)\n let response: Response\n if (kind === 'Validation') response = await this.#renderValidation(http, error as ValidationError)\n else if (kind === 'Authentication') response = await this.#renderAuthentication(http, error as AuthenticationError)\n else if (http.expectsJson()) response = this.#renderJson(error)\n else response = await this.#renderHtml(http, error)\n\n const headers = (error as Partial<OrielError> | null)?.headers\n if (headers !== undefined) for (const [name, value] of Object.entries(headers)) response.headers.set(name, value)\n return response\n }\n\n /** An error with its own render(request) or toResponse(request) (Laravel's renderable exceptions / Responsable). */\n async #renderCustom(request: unknown, error: unknown): Promise<Response | undefined> {\n if (typeof error !== 'object' || error === null) return undefined\n const candidate = error as { render?: (request: unknown) => unknown; toResponse?: (request: unknown) => unknown }\n for (const method of [candidate.render, candidate.toResponse]) {\n if (typeof method !== 'function') continue\n const response = await method.call(error, request)\n if (response instanceof Response) return response\n }\n return undefined\n }\n\n async #renderValidation(request: HttpRequest, error: ValidationError): Promise<Response> {\n if (request.expectsJson()) {\n return this.#json({ message: summarizeValidation(error.errors), errors: error.errors }, statusFor(error))\n }\n const input = { ...request.input<Record<string, unknown>>() }\n for (const key of this.dontFlash) delete input[key]\n const container = this.#container()\n if (!container.bound(Redirector)) {\n return this.#redirect(error.redirectTo ?? request.header('referer') ?? '/')\n }\n const redirector = container.make(Redirector)\n const redirect = error.redirectTo !== undefined ? redirector.to(error.redirectTo) : redirector.back()\n // toResponse(request) may return a Promise per the Responsable contract; await it.\n const response = await redirect.withInput(input).withErrors(error.errors, error.errorBag).toResponse(request)\n return response\n }\n\n async #renderAuthentication(request: HttpRequest, error: AuthenticationError): Promise<Response> {\n if (request.expectsJson()) return this.#json({ message: error.message || 'Unauthenticated.' }, 401)\n const target = error.redirectTo ?? this.#guestRedirect(request)\n const container = this.#container()\n if (!container.bound(Redirector)) return this.#redirect(target)\n const redirector = container.make(Redirector) as Redirector & { guest?: (path: string) => { toResponse(r: unknown): unknown } }\n const redirect = typeof redirector.guest === 'function' ? redirector.guest(target) : redirector.to(target)\n // toResponse(request) may return a Promise per the Responsable contract; await it.\n return (await redirect.toResponse(request)) as Response\n }\n\n /** config('http.redirect_guests_to'), then route('login'), then '/login'. */\n #guestRedirect(request: HttpRequest): string {\n const configured = this.#config<unknown>('http.redirect_guests_to', undefined)\n if (typeof configured === 'function') return String((configured as (request: HttpRequest) => string)(request))\n if (typeof configured === 'string' && configured !== '') return configured\n const container = this.#container()\n if (container.bound(UrlGenerator)) {\n const url = container.make(UrlGenerator)\n if (url.hasRoute('login')) return url.route('login')\n }\n return '/login'\n }\n\n #renderJson(error: unknown): Response {\n const status = statusFor(error)\n if (isHttpLike(error)) {\n const message = error instanceof Error && error.message !== '' ? error.message : statusText(status)\n return this.#json({ message }, status)\n }\n if (!this.#debug()) return this.#json({ message: 'Server Error' }, status)\n const err = error instanceof Error ? error : new Error(String(error))\n const [frame] = stackFrames(err)\n return this.#json(\n {\n message: err.message,\n exception: err.name,\n file: frame?.file,\n line: frame?.line,\n trace: stackFrames(err).map((entry) => entry.text),\n },\n status,\n )\n }\n\n async #renderHtml(request: HttpRequest, error: unknown): Promise<Response> {\n const status = statusFor(error)\n if (!isHttpLike(error) && this.#debug()) {\n return this.#html(await debugPage(error, request.method(), request.fullUrl()), status)\n }\n const message = status === 403 && error instanceof Error && error.message !== '' ? error.message : statusText(status)\n const view = await this.#errorView(status, error, message)\n return this.#html(view ?? minimalPage(status, message), status)\n }\n\n /** resources/views/errors/{status}.tsx, then errors/4xx or errors/5xx, through the ViewFactory. */\n async #errorView(status: number, error: unknown, message: string): Promise<string | undefined> {\n const container = this.#container()\n if (!container.bound(ViewFactory)) return undefined\n const views = container.make(ViewFactory)\n for (const name of [`errors.${status}`, `errors.${Math.floor(status / 100)}xx`]) {\n if (!views.exists(name)) continue\n try {\n return await views.make(name, { exception: error, status, message }).render()\n } catch (viewError) {\n await this.report(viewError)\n return undefined\n }\n }\n return undefined\n }\n\n #httpRequest(request: unknown): HttpRequest {\n if (typeof request === 'object' && request !== null && typeof (request as HttpRequest).expectsJson === 'function') {\n return request as HttpRequest\n }\n return new IncomingRequest(request instanceof Request ? request : new Request('http://localhost/'))\n }\n\n #json(body: unknown, status: number): Response {\n return new Response(JSON.stringify(body), { status, headers: { 'content-type': 'application/json' } })\n }\n\n #html(body: string, status: number): Response {\n return new Response(body, { status, headers: { 'content-type': 'text/html; charset=utf-8' } })\n }\n\n #redirect(location: string): Response {\n return new Response(null, { status: 302, headers: { Location: location } })\n }\n\n #debug(): boolean {\n return this.#config<unknown>('app.debug', false) === true\n }\n\n #config<T>(key: string, fallback: T): T {\n return this.app.bound(ConfigRepository) ? this.app.make(ConfigRepository).get<T>(key, fallback) : fallback\n }\n\n /** The request scope while handling a request (so scoped services resolve), else the application. */\n #container(): Container {\n return currentContainer() ?? this.app\n }\n}\n","import { readFile } from 'node:fs/promises'\nimport { fileURLToPath } from 'node:url'\n\nconst STATUS_TEXTS: Record<number, string> = {\n 400: 'Bad Request',\n 401: 'Unauthorized',\n 402: 'Payment Required',\n 403: 'Forbidden',\n 404: 'Not Found',\n 405: 'Method Not Allowed',\n 408: 'Request Timeout',\n 409: 'Conflict',\n 410: 'Gone',\n 413: 'Content Too Large',\n 415: 'Unsupported Media Type',\n 419: 'Page Expired',\n 422: 'Unprocessable Content',\n 429: 'Too Many Requests',\n 500: 'Server Error',\n 502: 'Bad Gateway',\n 503: 'Service Unavailable',\n 504: 'Gateway Timeout',\n}\n\n/** Laravel's wording for the status (its error pages say \"Server Error\" and \"Page Expired\"). */\nexport function statusText(status: number): string {\n return STATUS_TEXTS[status] ?? (status >= 500 ? 'Server Error' : 'Error')\n}\n\nexport function escapeHtml(value: string): string {\n return value.replace(/[&<>\"']/g, (char) => `&#${char.charCodeAt(0)};`)\n}\n\n/** Laravel's minimal error page: \"404 | Not Found\". */\nexport function minimalPage(status: number, message: string): string {\n const title = escapeHtml(message)\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>${title}</title>\n<style>body{margin:0;font-family:ui-sans-serif,system-ui,sans-serif;background:#f7fafc;color:#1a202c;display:flex;align-items:center;justify-content:center;min-height:100vh}.code{padding:0 1rem;border-right:1px solid #a0aec0;font-size:1.125rem}.message{padding:0 1rem;font-size:1.125rem;text-transform:uppercase;letter-spacing:.05em}</style>\n</head>\n<body><div class=\"code\">${status}</div><div class=\"message\">${title}</div></body>\n</html>`\n}\n\nexport interface StackFrame {\n readonly file: string\n readonly line: number\n readonly column: number\n readonly text: string\n}\n\n/** Parses V8/JavaScriptCore stack lines into frames that point at files. */\nexport function stackFrames(error: Error): StackFrame[] {\n const frames: StackFrame[] = []\n for (const raw of (error.stack ?? '').split('\\n').slice(1)) {\n const text = raw.trim()\n const match = /(?:\\(|@|at )((?:file:\\/\\/)?(?:\\/|[A-Za-z]:\\\\)[^()]*?):(\\d+):(\\d+)\\)?$/.exec(text)\n if (match === null) continue\n const location = match[1]!\n const file = location.startsWith('file://') ? fileURLToPath(location) : location\n frames.push({ file, line: Number(match[2]), column: Number(match[3]), text })\n }\n return frames\n}\n\n/** Up to `radius` lines either side of the frame's line, or undefined when the file can't be read. */\nasync function excerpt(frame: StackFrame, radius = 5): Promise<string | undefined> {\n const source = await readFile(frame.file, 'utf8').catch(() => undefined)\n if (source === undefined) return undefined\n const lines = source.split('\\n')\n const start = Math.max(1, frame.line - radius)\n const end = Math.min(lines.length, frame.line + radius)\n const rows: string[] = []\n for (let number = start; number <= end; number++) {\n const current = number === frame.line ? ' class=\"current\"' : ''\n rows.push(`<tr${current}><td class=\"n\">${number}</td><td><code>${escapeHtml(lines[number - 1] ?? '')}</code></td></tr>`)\n }\n return `<table class=\"source\">${rows.join('')}</table>`\n}\n\n/** The APP_DEBUG page: class, message, request, a source excerpt of the first app frame, the stack and causes. */\nexport async function debugPage(error: unknown, method: string, url: string): Promise<string> {\n const err = error instanceof Error ? error : new Error(String(error))\n const frames = stackFrames(err)\n const appFrame = frames.find((frame) => !frame.file.includes('node_modules') && !frame.file.startsWith('node:')) ?? frames[0]\n const source = appFrame === undefined ? undefined : await excerpt(appFrame)\n const causes: string[] = []\n for (let cause = err.cause, depth = 0; cause !== undefined && depth < 5; cause = (cause as Error).cause, depth++) {\n causes.push(`<li>${escapeHtml(cause instanceof Error ? `${cause.name}: ${cause.message}` : String(cause))}</li>`)\n }\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>${escapeHtml(err.message || err.name)}</title>\n<style>body{margin:0;font-family:ui-sans-serif,system-ui,sans-serif;background:#f3f4f6;color:#111827}main{max-width:1100px;margin:2rem auto;padding:0 1rem}header{background:#fff;border-radius:.5rem;padding:1.5rem;box-shadow:0 1px 3px #0001}.class{color:#dc2626;font-weight:600}.message{font-size:1.5rem;margin:.5rem 0}.request{color:#6b7280}section{background:#fff;border-radius:.5rem;padding:1rem;margin-top:1rem;box-shadow:0 1px 3px #0001;overflow:auto}.source td{padding:0 .5rem;white-space:pre;font-size:.85rem}.source .n{color:#9ca3af;text-align:right}.source .current{background:#fee2e2}ol{font-family:ui-monospace,monospace;font-size:.85rem}</style>\n</head>\n<body><main>\n<header><div class=\"class\">${escapeHtml(err.name)}</div><div class=\"message\">${escapeHtml(err.message)}</div><div class=\"request\">${escapeHtml(method)} ${escapeHtml(url)}</div></header>\n${appFrame === undefined ? '' : `<section><div>${escapeHtml(appFrame.file)}:${appFrame.line}</div>${source ?? ''}</section>`}\n<section><ol>${frames.map((frame) => `<li>${escapeHtml(frame.text)}</li>`).join('')}</ol></section>\n${causes.length === 0 ? '' : `<section><div>Caused by</div><ul>${causes.join('')}</ul></section>`}\n</main></body>\n</html>`\n}\n","import { ExceptionCallbacks, type Application, type ExceptionsConfigurator } from '@orieljs/contracts'\nimport type { ErrorClass, ErrorHandler, RenderCallback, ReportCallback } from './ErrorHandler'\n\n/** The `e` in withExceptions((e) => …). */\nexport class ExceptionsConfiguration implements ExceptionsConfigurator {\n constructor(private readonly handler: ErrorHandler) {}\n\n report(callback: ReportCallback): this {\n this.handler.reportUsing(callback)\n return this\n }\n\n render(callback: RenderCallback): this {\n this.handler.renderUsing(callback)\n return this\n }\n\n dontReport(...classes: ErrorClass[]): this {\n this.handler.ignore(...classes)\n return this\n }\n}\n\n/** Runs the withExceptions() callbacks against a handler (the provider does this when the handler is built). */\nexport function applyExceptionCallbacks(app: Application, handler: ErrorHandler): void {\n if (!app.bound(ExceptionCallbacks)) return\n const configurator = new ExceptionsConfiguration(handler)\n for (const callback of app.make(ExceptionCallbacks)) callback(configurator)\n}\n","import { HttpKernel, type Application } from '@orieljs/contracts'\nimport { plainServerError } from '../Kernel'\nimport { servePublicFile } from './static'\n\nexport type Runtime = 'node' | 'bun'\n\nexport interface ServeOptions {\n /** Default: PORT, then SERVER_PORT, then 8000 (Laravel's serve). 0 picks a free port. */\n port?: number\n /** Default: 127.0.0.1. */\n hostname?: string\n /** Close gracefully on SIGINT/SIGTERM, then exit. Default: true. */\n signals?: boolean\n /** How long close() waits for in-flight requests before cutting connections (ms). Default: 10000. */\n shutdownTimeout?: number\n /** Default: detected (Bun when globalThis.Bun exists). */\n runtime?: Runtime\n /** Called once listening. Default: prints \"Server running on [url].\" */\n onListen?: (server: RunningServer) => void\n /** Serve existing files from this directory before the app (Laravel's server.php). Default: app.publicPath(); false turns it off. */\n publicPath?: string | false\n}\n\nexport interface ResolvedServeOptions {\n readonly port: number\n readonly hostname: string\n readonly signals: boolean\n readonly shutdownTimeout: number\n /** Where public files are served from, or undefined when turned off. */\n readonly publicPath?: string\n}\n\nexport interface RunningServer {\n readonly runtime: Runtime\n readonly hostname: string\n readonly port: number\n /** 'http://127.0.0.1:8000' */\n readonly url: string\n /** Stops accepting connections, waits for in-flight requests (up to shutdownTimeout), then resolves. */\n close(): Promise<void>\n /** Resolves once the server has closed. */\n readonly closed: Promise<void>\n}\n\n/** HttpKernel.terminate() after the response went out (Laravel's terminable middleware). Never throws. */\nexport async function terminateRequest(app: Application, request: Request, response: Response): Promise<void> {\n try {\n if (app.bound(HttpKernel)) await app.make(HttpKernel).terminate?.(request, response)\n } catch (error) {\n console.error(error)\n }\n}\n\n/** A public file when one matches, else app.handle(), turning a crash outside the kernel into a plain 500. */\nexport async function handleSafely(app: Application, request: Request, publicPath?: string): Promise<Response> {\n try {\n if (publicPath !== undefined) {\n const file = await servePublicFile(publicPath, request)\n if (file !== undefined) return file\n }\n return await app.handle(request)\n } catch (error) {\n console.error(error)\n return plainServerError()\n }\n}\n\n/** SIGINT/SIGTERM → close() → process.exit(0). The listeners go away when the server closes. */\nexport function exitOnSignals(close: () => Promise<void>, closed: Promise<void>): void {\n const onSignal = () => {\n void close().then(() => process.exit(0))\n }\n process.once('SIGINT', onSignal)\n process.once('SIGTERM', onSignal)\n void closed.then(() => {\n process.off('SIGINT', onSignal)\n process.off('SIGTERM', onSignal)\n })\n}\n\nexport const displayHost = (hostname: string): string => (hostname.includes(':') ? `[${hostname}]` : hostname)\n","import { createReadStream } from 'node:fs'\nimport { stat } from 'node:fs/promises'\nimport { Readable } from 'node:stream'\nimport { relative, resolve, sep } from 'node:path'\nimport { mimeFromExtension } from '../mime'\n\n/**\n * Source files and dotfiles in public/ are never served (public/index.ts is the entry point, not an asset).\n * Tested on every segment of the resolved path, so trailing slashes and dot segments can't hide a name.\n * Names ending in a dot or a space are refused too, since Windows strips those when it opens the file.\n */\nconst HIDDEN_SEGMENT = /^\\.|\\.(ts|tsx|mts|cts)$|[. ]$/i\n\n/**\n * Laravel's server.php for `artisan serve`: a GET or HEAD for a file that exists under public/ is answered\n * with that file, so the built Vite assets (public/build) and other public files work without a web server.\n * Anything else (directories, missing files, other methods) returns undefined and goes to the application.\n */\nexport async function servePublicFile(publicPath: string, request: Request): Promise<Response | undefined> {\n if (request.method !== 'GET' && request.method !== 'HEAD') return undefined\n let pathname: string\n try {\n pathname = decodeURIComponent(new URL(request.url).pathname)\n } catch {\n return undefined\n }\n if (pathname === '/' || pathname.includes('\\0')) return undefined\n const root = resolve(publicPath)\n const file = resolve(root, `.${pathname}`)\n if (!file.startsWith(root + sep)) return undefined\n if (relative(root, file).split(/[\\\\/]/).some((segment) => HIDDEN_SEGMENT.test(segment))) return undefined\n const info = await stat(file).catch(() => undefined)\n if (info === undefined || !info.isFile()) return undefined\n\n const type = mimeFromExtension(file)\n const headers = new Headers({\n 'content-type': type.startsWith('text/') || type === 'application/json' ? `${type}; charset=utf-8` : type,\n 'content-length': String(info.size),\n 'last-modified': info.mtime.toUTCString(),\n })\n // Vite's hashed build output never changes under the same name.\n if (pathname.startsWith('/build/assets/')) headers.set('cache-control', 'public, max-age=31536000, immutable')\n if (request.method === 'HEAD') return new Response(null, { status: 200, headers })\n const body = Readable.toWeb(createReadStream(file)) as unknown as ReadableStream<Uint8Array>\n return new Response(body, { status: 200, headers })\n}\n","import type { Application } from '@orieljs/contracts'\nimport { setClientAddress } from '../clientAddress'\nimport { HttpServerError } from '../errors'\nimport { plainServerError } from '../Kernel'\nimport {\n displayHost,\n exitOnSignals,\n handleSafely,\n terminateRequest,\n type ResolvedServeOptions,\n type RunningServer,\n} from './types'\n\n/** The slice of Bun's API used here (typed locally: there is no Bun lib in the build). */\ninterface BunServer {\n readonly port: number\n stop(closeActiveConnections?: boolean): Promise<void> | void\n requestIP(request: Request): { address: string } | null\n}\ninterface BunRuntime {\n serve(options: {\n port: number\n hostname: string\n fetch(request: Request, server: BunServer): Promise<Response>\n error(error: Error): Response\n }): BunServer\n}\n\nexport function bunRuntime(): BunRuntime | undefined {\n return (globalThis as { Bun?: BunRuntime }).Bun\n}\n\nexport async function serveBun(app: Application, options: ResolvedServeOptions): Promise<RunningServer> {\n const bun = bunRuntime()\n if (bun === undefined) throw new HttpServerError('Bun.serve is not available: the process is not running on Bun.')\n let markClosed: () => void = () => undefined\n const closed = new Promise<void>((resolve) => (markClosed = resolve))\n\n const server = bun.serve({\n port: options.port,\n hostname: options.hostname,\n async fetch(request, current) {\n setClientAddress(request, current.requestIP(request)?.address)\n const response = await handleSafely(app, request, options.publicPath)\n // Bun has no \"response sent\" hook: terminate on the next tick.\n setTimeout(() => void terminateRequest(app, request, response), 0)\n return response\n },\n error(error) {\n console.error(error)\n return plainServerError()\n },\n })\n\n let closing: Promise<void> | undefined\n const close = () =>\n (closing ??= (async () => {\n let timer: ReturnType<typeof setTimeout> | undefined\n const forced = new Promise<void>((resolve) => {\n timer = setTimeout(() => void Promise.resolve(server.stop(true)).then(resolve), options.shutdownTimeout)\n })\n await Promise.race([Promise.resolve(server.stop(false)), forced])\n clearTimeout(timer)\n markClosed()\n })())\n if (options.signals) exitOnSignals(close, closed)\n\n return {\n runtime: 'bun',\n hostname: options.hostname,\n port: server.port,\n url: `http://${displayHost(options.hostname)}:${server.port}`,\n close,\n closed,\n }\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from 'node:http'\nimport type { AddressInfo } from 'node:net'\nimport { Readable } from 'node:stream'\nimport { pipeline } from 'node:stream/promises'\nimport type { ReadableStream as NodeReadableStream } from 'node:stream/web'\nimport type { Application } from '@orieljs/contracts'\nimport { setClientAddress } from '../clientAddress'\nimport {\n displayHost,\n exitOnSignals,\n handleSafely,\n terminateRequest,\n type ResolvedServeOptions,\n type RunningServer,\n} from './types'\n\n/**\n * The request's body as a web stream that pulls from `req`. Readable.toWeb(req) is not used: cancelling it (readBody\n * does that for a declared length over the limit) closes its controller while the socket still emits data, which\n * throws out of the adapter and kills the process. Cancelling this one just stops listening; node drops the unread\n * remainder once the response finishes.\n */\nfunction requestBody(req: IncomingMessage): ReadableStream<Uint8Array> {\n let finished = false\n const detach = () => {\n finished = true\n req.off('data', onData)\n req.off('end', onEnd)\n req.off('error', onError)\n req.off('close', onClose)\n }\n let controller!: ReadableStreamDefaultController<Uint8Array>\n const onData = (chunk: Buffer) => {\n if (finished) return\n controller.enqueue(new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength))\n if ((controller.desiredSize ?? 0) <= 0) req.pause()\n }\n const onEnd = () => {\n if (finished) return\n detach()\n controller.close()\n }\n const onError = (error: Error) => {\n if (finished) return\n detach()\n controller.error(error)\n }\n const onClose = () => {\n if (!finished && !req.complete) onError(new Error('The request was aborted.'))\n }\n return new ReadableStream<Uint8Array>(\n {\n start(c) {\n controller = c\n req.on('data', onData)\n req.on('end', onEnd)\n req.on('error', onError)\n req.on('close', onClose)\n req.pause()\n },\n pull() {\n req.resume()\n },\n cancel() {\n detach()\n },\n },\n { highWaterMark: 0 },\n )\n}\n\n/** node:http IncomingMessage → web Request (the body streams; the signal aborts when the client goes away). */\nexport function toWebRequest(req: IncomingMessage, res: ServerResponse, fallbackHost: string): Request {\n // Concatenate rather than resolve: a target such as '//evil.com/x' must stay on this host, not become evil.com.\n const target = req.url ?? '/'\n const url = new URL(`http://${req.headers.host ?? fallbackHost}${target.startsWith('/') ? target : `/${target}`}`)\n const headers = new Headers()\n for (let i = 0; i < req.rawHeaders.length; i += 2) {\n const name = req.rawHeaders[i]!\n if (!name.startsWith(':')) headers.append(name, req.rawHeaders[i + 1]!)\n }\n const method = (req.method ?? 'GET').toUpperCase()\n const controller = new AbortController()\n res.once('close', () => {\n if (!res.writableFinished) controller.abort()\n })\n const init: RequestInit & { duplex?: 'half' } = { method, headers, signal: controller.signal }\n if (method !== 'GET' && method !== 'HEAD') {\n init.body = requestBody(req)\n init.duplex = 'half'\n }\n return new Request(url, init)\n}\n\n/** Web Response → ServerResponse, streaming the body with backpressure. Several Set-Cookie headers stay separate. */\nexport async function writeResponse(res: ServerResponse, response: Response): Promise<void> {\n res.statusCode = response.status\n if (response.statusText !== '') res.statusMessage = response.statusText\n response.headers.forEach((value, name) => {\n if (name !== 'set-cookie') res.setHeader(name, value)\n })\n const cookies = response.headers.getSetCookie()\n if (cookies.length > 0) res.setHeader('set-cookie', cookies)\n if (response.body === null) {\n res.end()\n return\n }\n await pipeline(Readable.fromWeb(response.body as unknown as NodeReadableStream<Uint8Array>), res)\n}\n\nexport async function serveNode(app: Application, options: ResolvedServeOptions): Promise<RunningServer> {\n const fallbackHost = `${displayHost(options.hostname)}:${options.port}`\n const server = createServer((req, res) => {\n void (async () => {\n let request: Request\n try {\n request = toWebRequest(req, res, fallbackHost)\n } catch {\n res.statusCode = 400\n res.end('Bad Request')\n return\n }\n setClientAddress(request, req.socket.remoteAddress)\n const response = await handleSafely(app, request, options.publicPath)\n try {\n await writeResponse(res, response)\n } catch {\n // The client went away mid-response.\n res.destroy()\n }\n await terminateRequest(app, request, response)\n })()\n })\n\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject)\n server.listen(options.port, options.hostname, () => {\n server.off('error', reject)\n resolve()\n })\n })\n\n const address = server.address() as AddressInfo\n const closed = new Promise<void>((resolve) => server.once('close', () => resolve()))\n let closing: Promise<void> | undefined\n const close = () =>\n (closing ??= (async () => {\n const done = new Promise<void>((resolve) => server.close(() => resolve()))\n // Keep-alive connections become idle once their request finishes; close them as that happens.\n server.closeIdleConnections()\n const idle = setInterval(() => server.closeIdleConnections(), 50)\n const force = setTimeout(() => server.closeAllConnections(), options.shutdownTimeout)\n await done\n clearInterval(idle)\n clearTimeout(force)\n })())\n if (options.signals) exitOnSignals(close, closed)\n\n return {\n runtime: 'node',\n hostname: options.hostname,\n port: address.port,\n url: `http://${displayHost(options.hostname)}:${address.port}`,\n close,\n closed,\n }\n}\n","import type { Application } from '@orieljs/contracts'\nimport { bunRuntime, serveBun } from './bun'\nimport { serveNode } from './node'\nimport type { ResolvedServeOptions, Runtime, RunningServer, ServeOptions } from './types'\n\nexport function detectRuntime(): Runtime {\n return bunRuntime() !== undefined ? 'bun' : 'node'\n}\n\n/** Boots the app and serves it with node:http or Bun.serve (public/index.ts: `await serve(app)`). */\nexport async function serve(app: Application, options: ServeOptions = {}): Promise<RunningServer> {\n const resolved: ResolvedServeOptions = {\n port: options.port ?? Number(process.env.PORT ?? process.env.SERVER_PORT ?? 8000),\n hostname: options.hostname ?? '127.0.0.1',\n signals: options.signals ?? true,\n shutdownTimeout: options.shutdownTimeout ?? 10_000,\n ...(options.publicPath !== false && { publicPath: options.publicPath ?? app.publicPath() }),\n }\n await app.boot()\n const runtime = options.runtime ?? detectRuntime()\n const server = runtime === 'bun' ? await serveBun(app, resolved) : await serveNode(app, resolved)\n const onListen = options.onListen ?? ((running: RunningServer) => console.log(`Server running on [${running.url}].`))\n onListen(server)\n return server\n}\n","import { existsSync } from 'node:fs'\nimport { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { dirname } from 'node:path'\nimport {\n Router,\n type Application,\n type CommandContext,\n type ConsoleKernel,\n type MiddlewareReference,\n type Route,\n} from '@orieljs/contracts'\nimport { serve } from './server/serve'\nimport type { RunningServer, ServeOptions } from './server/types'\n\ninterface Io {\n option(name: string): string | undefined\n flag(name: string): boolean\n info(message: string): void\n line(message: string): void\n warn(message: string): void\n error(message: string): void\n}\n\n/**\n * The closure command's `this` (the contract's CommandContext), with the options normalised: a value option that\n * is absent (undefined, null, false or '') reads as undefined, and a flag is true only when set.\n */\nfunction io(command: CommandContext): Io {\n return {\n option: (name) => {\n const value: unknown = command.option(name)\n return value === undefined || value === null || value === false || value === '' ? undefined : String(value)\n },\n flag: (name) => {\n const value: unknown = command.option(name)\n return value === true || value === 'true' || value === '1'\n },\n info: (message) => command.info(message),\n line: (message) => command.line(message),\n warn: (message) => command.warn(message),\n error: (message) => command.error(message),\n }\n}\n\nexport interface RouteListRow {\n /** 'GET|HEAD' */\n readonly method: string\n readonly uri: string\n readonly name: string | null\n /** 'PostController@show' or 'Closure' */\n readonly action: string\n readonly middleware: string[]\n}\n\ninterface ListableRoute extends Route {\n getActionName?(): string\n gatherMiddleware?(): MiddlewareReference[]\n}\n\nconst middlewareName = (reference: MiddlewareReference): string => (typeof reference === 'string' ? reference : reference.name)\n\n/** One row per route, sorted by URI (Laravel's default --sort=uri; ties keep registration order). */\nexport function routeListRows(routes: readonly Route[]): RouteListRow[] {\n const rows = routes.map((route) => {\n const listable = route as ListableRoute\n return {\n method: route.methods.join('|'),\n uri: route.uri,\n name: route.getName() ?? null,\n action: typeof listable.getActionName === 'function' ? listable.getActionName() : 'Closure',\n middleware: typeof listable.gatherMiddleware === 'function' ? listable.gatherMiddleware().map(middlewareName) : [],\n }\n })\n return rows.sort((a, b) => (a.uri < b.uri ? -1 : a.uri > b.uri ? 1 : 0))\n}\n\nexport interface RouteListFilters {\n method?: string\n name?: string\n path?: string\n /** Comma-separated. */\n exceptPath?: string\n}\n\n/** Laravel's RouteListCommand::filterRoute: substring matches, method compared uppercased. */\nexport function filterRouteList(rows: readonly RouteListRow[], filters: RouteListFilters): RouteListRow[] {\n const excluded = (filters.exceptPath ?? '').split(',').filter((path) => path !== '')\n return rows.filter((row) => {\n if (filters.name !== undefined && !(row.name ?? '').includes(filters.name)) return false\n if (filters.path !== undefined && !row.uri.includes(filters.path)) return false\n if (filters.method !== undefined && !row.method.includes(filters.method.toUpperCase())) return false\n return !excluded.some((path) => row.uri.includes(path))\n })\n}\n\n/**\n * Laravel's route:list layout: the method column padded, the URI, a dotted leader, then `name › action`\n * (closures show only the name), and a right-aligned \"Showing [n] routes\" footer.\n */\nexport function formatRouteList(rows: readonly RouteListRow[], width: number): string[] {\n const methodWidth = Math.max(...rows.map((row) => row.method.length))\n const lines = rows.map((row) => {\n const spaces = ' '.repeat(Math.max(methodWidth + 6 - row.method.length, 0))\n const action = row.action === 'Closure' ? (row.name ?? '') : row.name === null ? row.action : `${row.name} › ${row.action}`\n const used = row.method.length + spaces.length + row.uri.length + action.length + 6 + (action === '' ? 0 : 1)\n const dots = '.'.repeat(Math.max(width - used, 0))\n return ` ${row.method} ${spaces}${row.uri}${dots === '' ? '' : ` ${dots}`}${action === '' ? '' : ` ${action}`}`\n })\n const count = `Showing [${rows.length}] ${rows.length === 1 ? 'route' : 'routes'}`\n return [...lines, '', `${' '.repeat(Math.max(width - count.length - 2, 0))}${count}`]\n}\n\n/** The routes/api.ts that install:api writes (Laravel's api.stub, with the token guard). */\nexport const API_ROUTES_STUB = `import { request, Route } from '@orieljs/framework'\n\nRoute.get('/user', () => request().user()).middleware('auth:token')\n`\n\n/**\n * Adds `api: 'routes/api.ts'` to withRouting() in bootstrap/app.ts: uncomments a commented `// api:` entry,\n * else inserts it after the `web:` entry, else at the start of withRouting({, else adds a withRouting() call\n * before create(). Returns the source unchanged when api is already there, and undefined when it can't tell where.\n * (Function replacers, so a `$` in the file is never read as a replacement pattern.)\n */\nexport function addApiRouting(source: string): string | undefined {\n const code = source.replace(/^[ \\t]*\\/\\/.*$/gm, '')\n if (/withRouting\\(\\s*\\{[^}]*\\bapi\\s*:/.test(code)) return source\n const commented = /^([ \\t]*)\\/\\/\\s*(api:\\s*['\"`][^'\"`\\n]*['\"`],?)[ \\t]*$/m.exec(source)\n if (commented !== null) return source.replace(commented[0], () => `${commented[1]}${commented[2]}`)\n const web = /^([ \\t]*)web:\\s*(['\"`])[^'\"`\\n]*\\2[ \\t]*,?[ \\t]*$/m.exec(source)\n if (web !== null) {\n const line = web[0].trimEnd()\n return source.replace(web[0], () => `${line.endsWith(',') ? line : `${line},`}\\n${web[1]}api: 'routes/api.ts',`)\n }\n const inline = /withRouting\\(\\s*\\{/.exec(source)\n if (inline !== null) return source.replace(inline[0], () => `${inline[0]} api: 'routes/api.ts',`)\n const create = /^([ \\t]*)\\.create\\(\\)/m.exec(source)\n if (create !== null) return source.replace(create[0], () => `${create[1]}.withRouting({ api: 'routes/api.ts' })\\n${create[0]}`)\n return undefined\n}\n\nexport interface HttpCommandOptions {\n /** Replaces serve() (tests). */\n serve?: (app: Application, options: ServeOptions) => Promise<RunningServer>\n /** The terminal width for route:list. Default: process.stdout.columns, else 120. */\n terminalWidth?: () => number\n}\n\n/** Registers `serve`, `route:list` and `install:api` as closure commands (PC1). */\nexport function registerHttpCommands(kernel: ConsoleKernel, app: Application, options: HttpCommandOptions = {}): void {\n const serveApp = options.serve ?? serve\n const terminalWidth = options.terminalWidth ?? (() => process.stdout.columns ?? 120)\n\n kernel\n .command(\n 'serve {--host=127.0.0.1 : The host address to serve the application on} {--port= : The port to serve the application on}',\n async function (this: CommandContext) {\n const out = io(this)\n const port = out.option('port')\n if (port !== undefined && !/^\\d+$/.test(port)) {\n out.error('The --port option must be a number.')\n return 1\n }\n const server = await serveApp(app, {\n hostname: out.option('host') ?? '127.0.0.1',\n ...(port !== undefined && { port: Number(port) }),\n onListen: (running) => {\n out.info(`Server running on [${running.url}].`)\n out.line('Press Ctrl+C to stop the server')\n },\n })\n await server.closed\n return 0\n },\n )\n .purpose('Serve the application on the Oriel development server')\n\n kernel\n .command(\n 'route:list {--method= : Filter the routes by method} {--name= : Filter the routes by name} ' +\n '{--path= : Only show routes matching the given path pattern} ' +\n '{--except-path= : Do not display the routes matching the given path pattern} ' +\n '{--reverse : Reverse the ordering of the routes} {--json : Output the route list as JSON}',\n function (this: CommandContext) {\n const out = io(this)\n if (!app.bound(Router)) {\n out.error('The router is not available. Is the Routing service provider registered?')\n return 1\n }\n const all = routeListRows(app.make(Router).getRoutes())\n if (all.length === 0) {\n out.error(\"Your application doesn't have any routes.\")\n return 0\n }\n const rows = filterRouteList(all, {\n ...(out.option('method') !== undefined && { method: out.option('method') }),\n ...(out.option('name') !== undefined && { name: out.option('name') }),\n ...(out.option('path') !== undefined && { path: out.option('path') }),\n ...(out.option('except-path') !== undefined && { exceptPath: out.option('except-path') }),\n })\n if (rows.length === 0) {\n out.error(\"Your application doesn't have any routes matching the given criteria.\")\n return 0\n }\n if (out.flag('reverse')) rows.reverse()\n if (out.flag('json')) {\n out.line(JSON.stringify(rows))\n return 0\n }\n for (const line of formatRouteList(rows, terminalWidth())) out.line(line)\n return 0\n },\n )\n .purpose('List all registered routes')\n\n kernel\n .command('install:api {--force : Overwrite any existing API routes file}', async function (this: CommandContext) {\n const out = io(this)\n const routesFile = app.basePath('routes/api.ts')\n if (existsSync(routesFile) && !out.flag('force')) {\n out.error('API routes file already exists.')\n } else {\n await mkdir(dirname(routesFile), { recursive: true })\n await writeFile(routesFile, API_ROUTES_STUB)\n out.info('Published API routes file.')\n }\n\n const bootstrapFile = app.bootstrapPath('app.ts')\n const source = existsSync(bootstrapFile) ? await readFile(bootstrapFile, 'utf8') : undefined\n const updated = source === undefined ? undefined : addApiRouting(source)\n if (updated === undefined) {\n out.warn(\n 'Unable to automatically add API route definition to bootstrap file. ' +\n \"Add api: 'routes/api.ts' to withRouting() in bootstrap/app.ts.\",\n )\n } else if (updated !== source) {\n await writeFile(bootstrapFile, updated)\n }\n\n out.info('API scaffolding installed. Run [oriel migrate] to create the personal access tokens table.')\n return 0\n })\n .purpose('Create an API routes file and prepare the application for API authentication')\n}\n","import { ConsoleKernel, ExceptionHandler, HttpKernel, Redirector, ResponseFactory, Router } from '@orieljs/contracts'\nimport { ServiceProvider } from '@orieljs/support'\nimport { registerHttpCommands } from './commands'\nimport { ErrorHandler } from './ErrorHandler'\nimport { applyExceptionCallbacks } from './ExceptionsConfiguration'\nimport { HttpRedirector } from './HttpRedirector'\nimport { HttpResponseFactory } from './HttpResponseFactory'\nimport { Kernel } from './Kernel'\nimport { applyMiddlewareCallbacks } from './MiddlewareConfiguration'\n\n/**\n * Binds the HTTP kernel (replacing any kernel bound before, such as Foundation's ClosureKernel), the exception\n * handler, the response factory and the redirector, and merges the `http` config defaults.\n *\n * The HttpRequest is deliberately NOT bound on the application: the kernel creates one per request and puts it in\n * the request scope with scope.instance(). A root `scoped()` binding would make bound(HttpRequest) true everywhere,\n * and that check is how the URL generator, the redirects and the helpers know they are inside a request.\n */\nexport class HttpServiceProvider extends ServiceProvider {\n override register(): void {\n this.mergeConfigFrom(\n {\n trusted_proxies: [],\n max_body_size: 8 * 1024 * 1024,\n csrf_except: [],\n redirect_guests_to: undefined,\n redirect_users_to: undefined,\n },\n 'http',\n )\n this.app.singleton(HttpKernel, () => new Kernel(this.app))\n this.app.singleton(ExceptionHandler, () => {\n const handler = new ErrorHandler(this.app)\n applyExceptionCallbacks(this.app, handler)\n return handler\n })\n this.app.singleton(ResponseFactory, () => new HttpResponseFactory())\n this.app.singleton(Redirector, () => new HttpRedirector())\n }\n\n override boot(): void {\n // After every provider's boot(), so web({ remove }) and alias() overrides see the components' defaults.\n this.app.booted(() => {\n const kernel = this.app.make(HttpKernel)\n if (kernel instanceof Kernel && this.app.bound(Router)) applyMiddlewareCallbacks(this.app, kernel)\n })\n if (this.app.bound(ConsoleKernel)) registerHttpCommands(this.app.make(ConsoleKernel), this.app)\n }\n}\n"],"mappings":"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","names":["response","url","request","request","inject","inject","Session","currentContainer","inject","Str","Str","inject","Session","currentContainer","HttpRequest","UrlGenerator","inject","inject","HttpRequest","UrlGenerator","inject","inject","CurrentRoute","HttpRequest","currentContainer","request","request","currentContainer","request","response","HttpRequest","route","CurrentRoute","ConfigRepository","Router","url","ConfigRepository","Redirector","UrlGenerator","ViewFactory","currentContainer","url","request","response","Redirector","redirect","UrlGenerator","url","ViewFactory","ConfigRepository","currentContainer","createReadStream","stat","Readable","request","stat","Readable","createReadStream","request","response","resolve","request","response","Readable","url","response","Readable","request","resolve","readFile","Router","route","Router","readFile","ExceptionHandler","HttpKernel","Redirector","ResponseFactory","Router","HttpKernel","ExceptionHandler","ResponseFactory","Redirector","Router"]}
1
+ {"version":3,"sources":["../errors.ts","../body.ts","../context.ts","../HttpRedirectResponse.ts","../HttpRedirector.ts","../clientAddress.ts","../FormUploadedFile.ts","../mime.ts","../IncomingRequest.ts","../input.ts","../helpers.ts","../HttpResponseFactory.ts","../Kernel.ts","../middleware/ConvertEmptyStringsToNull.ts","../middleware/TrimStrings.ts","../MiddlewareConfiguration.ts","../ErrorHandler.ts","../errorPages.ts","../ExceptionsConfiguration.ts","../server/types.ts","../server/static.ts","../server/bun.ts","../server/node.ts","../server/serve.ts","../commands.ts","../HttpServiceProvider.ts"],"sourcesContent":["import type { OrielError } from '@orieljs/contracts'\n\n/** Symfony's HttpException: abort(404), abort(403, 'Nope'). An empty message renders as the status text. */\nexport class HttpException extends Error implements OrielError {\n readonly kind = 'Http' as const\n override readonly name = 'HttpException'\n constructor(\n readonly status: number,\n message = '',\n readonly headers: Record<string, string> = {},\n ) {\n super(message)\n }\n}\n\n/** Carries a ready Response out of deep code: abort(response). The handler returns it as is. */\nexport class HttpResponseException extends Error implements OrielError {\n readonly kind = 'Http' as const\n override readonly name = 'HttpResponseException'\n readonly status: number\n constructor(readonly response: Response) {\n super(`HTTP response exception (${response.status}).`)\n this.status = response.status\n }\n}\n\n/** Http's internal failures (not thrown by this package itself; used by the kernel and error rendering). */\nexport class HttpServerError extends Error implements OrielError {\n readonly kind = 'Server' as const\n readonly status = 500\n override readonly name = 'HttpServerError'\n}\n","import { HttpException } from './errors'\n\n/**\n * Whether a JSON text nests objects and arrays deeper than `maxDepth`, found by scanning (no parsing, no recursion):\n * brackets inside strings don't count. The kernel answers 400 for such bodies (http.max_json_depth) before the\n * recursive input handling (sanitizing, TrimStrings, validation) could overflow the stack.\n */\nexport function exceedsJsonDepth(text: string, maxDepth: number): boolean {\n let depth = 0\n let inString = false\n for (let i = 0; i < text.length; i++) {\n const code = text.charCodeAt(i)\n if (inString) {\n if (code === 92) i++ // a backslash escapes the next character\n else if (code === 34) inString = false\n } else if (code === 34) inString = true\n else if (code === 123 || code === 91) {\n if (++depth > maxDepth) return true\n } else if (code === 125 || code === 93) depth--\n }\n return false\n}\n\n/** Reads a request body into memory, refusing more than `limit` bytes (413), like PHP's post_max_size. */\nexport async function readBody(raw: Request, limit: number | null): Promise<Uint8Array> {\n if (raw.body === null) return new Uint8Array(0)\n const declared = Number(raw.headers.get('content-length') ?? NaN)\n if (limit !== null && Number.isFinite(declared) && declared > limit) {\n await raw.body.cancel()\n throw new HttpException(413, 'Content Too Large')\n }\n const reader = raw.body.getReader()\n const chunks: Uint8Array[] = []\n let size = 0\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n size += value.byteLength\n if (limit !== null && size > limit) {\n await reader.cancel()\n throw new HttpException(413, 'Content Too Large')\n }\n chunks.push(value)\n }\n const out = new Uint8Array(size)\n let offset = 0\n for (const chunk of chunks) {\n out.set(chunk, offset)\n offset += chunk.byteLength\n }\n return out\n}\n","import { CookieJar, HttpRequest, Session, type Container } from '@orieljs/contracts'\nimport { currentContainer } from '@orieljs/container'\n\n/** The current container, only when it is a request scope (the kernel binds HttpRequest there). */\nexport function requestScope(): Container | undefined {\n const container = currentContainer()\n return container !== undefined && container.bound(HttpRequest) ? container : undefined\n}\n\nexport function currentRequest(): HttpRequest | undefined {\n return requestScope()?.make(HttpRequest)\n}\n\n/** The request's session, or undefined outside a request or when no Session provider is registered. */\nexport function optionalSession(): Session | undefined {\n const scope = requestScope()\n return scope?.bound(Session) ? scope.make(Session) : undefined\n}\n\nexport function optionalCookieJar(): CookieJar | undefined {\n const scope = requestScope()\n return scope?.bound(CookieJar) ? scope.make(CookieJar) : undefined\n}\n","import type { Cookie, HeadersInit, RedirectResponse } from '@orieljs/contracts'\nimport { currentRequest, optionalCookieJar, optionalSession } from './context'\n\ntype ErrorsInput = Record<string, string | string[]> | { toObject(): Record<string, string[]> }\n\n/** A Set-Cookie value. `minutes` 0 is a session cookie; a negative value deletes the cookie. */\nfunction serializeCookie(cookie: Cookie): string {\n const parts = [`${encodeURIComponent(cookie.name)}=${encodeURIComponent(cookie.value)}`, `Path=${cookie.path}`]\n if (cookie.domain !== undefined) parts.push(`Domain=${cookie.domain}`)\n if (cookie.secure) parts.push('Secure')\n if (cookie.httpOnly) parts.push('HttpOnly')\n parts.push(`SameSite=${cookie.sameSite.charAt(0).toUpperCase()}${cookie.sameSite.slice(1)}`)\n if (cookie.minutes < 0) parts.push('Max-Age=0', 'Expires=Thu, 01 Jan 1970 00:00:00 GMT')\n else if (cookie.minutes > 0) parts.push(`Max-Age=${Math.round(cookie.minutes * 60)}`)\n return parts.join('; ')\n}\n\n/**\n * Laravel's RedirectResponse. with()/withErrors()/withInput() flash to the request's Session immediately, like\n * Laravel; without a bound Session (an API-only app) they are skipped silently.\n */\nexport class HttpRedirectResponse implements RedirectResponse {\n readonly #headers: Headers\n\n constructor(\n readonly targetUrl: string,\n readonly status = 302,\n headers?: HeadersInit,\n ) {\n this.#headers = new Headers(headers)\n }\n\n with(key: string | Record<string, unknown>, value?: unknown): this {\n const session = optionalSession()\n if (session === undefined) return this\n if (typeof key === 'string') session.flash(key, value)\n else for (const [name, item] of Object.entries(key)) session.flash(name, item)\n return this\n }\n\n /** Flashes `errors` as { [bag]: { field: string[] } }, keeping the other bags already flashed. */\n withErrors(errors: ErrorsInput, bag = 'default'): this {\n const session = optionalSession()\n if (session === undefined) return this\n const source =\n typeof (errors as { toObject?: unknown }).toObject === 'function'\n ? (errors as { toObject(): Record<string, string[]> }).toObject()\n : (errors as Record<string, string | string[]>)\n const normalized = Object.fromEntries(\n Object.entries(source).map(([field, messages]) => [field, Array.isArray(messages) ? [...messages] : [messages]]),\n )\n const existing = session.get<Record<string, Record<string, string[]>>>('errors', {})\n session.flash('errors', { ...existing, [bag]: normalized })\n return this\n }\n\n /** Flashes `input`, or the current request's input (files are never part of input()). */\n withInput(input?: Record<string, unknown>): this {\n const session = optionalSession()\n if (session === undefined) return this\n session.flashInput(input ?? currentRequest()?.input<Record<string, unknown>>() ?? {})\n return this\n }\n\n /**\n * Always a Set-Cookie header on this response (Laravel's RedirectResponse::withCookie). A bound CookieJar only\n * supplies the defaults (path, domain, secure, same-site); queueing would lose the cookie outside the web group.\n */\n withCookie(name: string, value: string, minutes = 0): this {\n const jar = optionalCookieJar()\n const cookie: Cookie =\n jar !== undefined\n ? jar.make(name, value, minutes)\n : { name, value, minutes, path: '/', secure: false, httpOnly: true, sameSite: 'lax' }\n this.#headers.append('Set-Cookie', serializeCookie(cookie))\n return this\n }\n\n header(name: string, value: string): this {\n this.#headers.set(name, value)\n return this\n }\n\n toResponse(): Response {\n const headers = new Headers(this.#headers)\n headers.set('Location', this.targetUrl)\n return new Response(null, { status: this.status, headers })\n }\n}\n","import { UrlGenerator, type HeadersInit, type Redirector } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport { currentRequest, optionalSession } from './context'\nimport { HttpRedirectResponse } from './HttpRedirectResponse'\n\n/**\n * A URL's path, query and fragment: '/dashboard?tab=1' (the intended URL is stored like this). Leading slashes\n * collapse to one, so '//evil.com/x' can never be read back as a protocol-relative URL.\n */\nfunction pathOf(url: string): string {\n let parsed: URL\n try {\n parsed = new URL(url, 'http://localhost')\n } catch {\n return '/'\n }\n return `${parsed.pathname.replace(/^\\/+/, '/')}${parsed.search}${parsed.hash}`\n}\n\n/** Laravel's Redirector. Stateless: the URL generator and session come from the current container. */\nexport class HttpRedirector implements Redirector {\n to(path: string, status = 302, headers?: HeadersInit): HttpRedirectResponse {\n return new HttpRedirectResponse(inject(UrlGenerator).to(path), status, headers)\n }\n\n route(name: string, parameters?: unknown, status = 302): HttpRedirectResponse {\n return new HttpRedirectResponse(inject(UrlGenerator).route(name, parameters), status)\n }\n\n back(fallback?: string, status = 302): HttpRedirectResponse {\n return new HttpRedirectResponse(inject(UrlGenerator).previous(fallback), status)\n }\n\n /** Pulls url.intended from the session (put there by guest()), else goes to `fallback`. */\n intended(fallback = '/', status = 302): HttpRedirectResponse {\n const path = optionalSession()?.pull<string | undefined>('url.intended') ?? fallback\n return this.to(path, status)\n }\n\n away(url: string, status = 302): HttpRedirectResponse {\n return new HttpRedirectResponse(url, status)\n }\n\n /**\n * Remembers where a guest was going (a GET page, else the previous URL), then redirects to `path`. Only the path\n * is stored, so intended() goes back on whichever host serves the app, and never to another site's Referer.\n */\n guest(path: string, status = 302): HttpRedirectResponse {\n const session = optionalSession()\n const request = currentRequest()\n if (session !== undefined) {\n const intended =\n request !== undefined && request.method() === 'GET' && !request.expectsJson()\n ? request.fullUrl()\n : inject(UrlGenerator).previous()\n session.put('url.intended', pathOf(intended))\n }\n return this.to(path, status)\n }\n\n setIntendedUrl(url: string): void {\n optionalSession()?.put('url.intended', url)\n }\n\n refresh(status = 302): HttpRedirectResponse {\n return this.to(currentRequest()?.fullUrl() ?? inject(UrlGenerator).current(), status)\n }\n}\n","/**\n * The socket address of each incoming Request, filled by the server adapters (and by test clients).\n * Kept on globalThis under a Symbol.for key, so a package that can't import @orieljs/http (Testing) can set it.\n */\nconst KEY = Symbol.for('oriel:http.client-address')\nconst store = ((globalThis as unknown as Record<symbol, WeakMap<Request, string> | undefined>)[KEY] ??= new WeakMap<Request, string>())\n\nexport function setClientAddress(request: Request, address: string | undefined): void {\n if (address !== undefined && address !== '') store.set(request, address)\n}\n\nexport function clientAddress(request: Request): string | undefined {\n return store.get(request)\n}\n","import { FilesystemManager, type UploadedFile } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport { FileType, Str } from '@orieljs/support'\nimport { extensionFromMime } from './mime'\n\n/** Extensions a stored file never takes from the client's claim alone: the formats the bytes are read for, and what a browser renders or runs. */\nconst NEVER_CLAIMED: ReadonlySet<string> = new Set([\n ...FileType.BINARY_AND_MARKUP_TYPES.flatMap(({ extensions }) => extensions),\n 'jpe', 'svgz', 'xhtml', 'xht', 'shtml', 'xsl', 'xslt', 'mht', 'mhtml', 'js', 'mjs',\n 'rss', 'atom', 'rdf', 'mathml', 'mml', 'xul',\n])\n\n/** A claim is kept only as a plain extension, the same test putFile() applies to the name it writes. */\nconst PLAIN_EXTENSION = /^[a-z0-9]+$/\n\n/** An uploaded file from a multipart body. store()/storeAs() go through the FilesystemManager. */\nexport class FormUploadedFile implements UploadedFile {\n readonly clientName: string\n readonly mimeType: string\n readonly size: number\n\n /**\n * Reads the leading bytes first, so extension(), hashName() and store() name the file by its content. The request\n * builds its uploads this way.\n */\n static async fromFile(file: Blob & { readonly name?: string }): Promise<FormUploadedFile> {\n return new FormUploadedFile(file, FileType.detectFileType(new Uint8Array(await file.slice(0, FileType.SNIFF_BYTES).arrayBuffer())))\n }\n\n constructor(\n private readonly file: Blob & { readonly name?: string },\n private readonly detected?: FileType.DetectedType,\n ) {\n this.clientName = file.name ?? ''\n this.mimeType = file.type === '' ? 'application/octet-stream' : file.type\n this.size = file.size\n }\n\n /**\n * Laravel's extension(): the type the bytes show (guessExtension()), when they were read and match a known format.\n * Text and bytes no format matches keep the client's claim (its MIME type, else its file name) when it is a plain\n * extension, unless it names a format the bytes would have shown or one a browser renders or runs: otherwise 'txt'\n * for text, '' for the rest. Unread (built directly), the client's claim when it is a plain extension, else ''.\n */\n extension(): string {\n const claimed = extensionFromMime(this.mimeType) ?? this.clientExtension()\n const detected = this.detected\n if (detected === undefined) return PLAIN_EXTENSION.test(claimed) ? claimed : ''\n if (detected !== FileType.TEXT && detected.extensions.length > 0) return detected.extensions[0]!\n if (PLAIN_EXTENSION.test(claimed) && !NEVER_CLAIMED.has(claimed)) return claimed\n return detected === FileType.TEXT ? 'txt' : ''\n }\n\n clientExtension(): string {\n const dot = this.clientName.lastIndexOf('.')\n return dot === -1 ? '' : this.clientName.slice(dot + 1).toLowerCase()\n }\n\n /** A random 40-character name with the guessed extension. */\n hashName(): string {\n const extension = this.extension()\n return extension === '' ? Str.random(40) : `${Str.random(40)}.${extension}`\n }\n\n arrayBuffer(): Promise<ArrayBuffer> {\n return this.file.arrayBuffer()\n }\n\n text(): Promise<string> {\n return this.file.text()\n }\n\n stream(): ReadableStream<Uint8Array> {\n return this.file.stream() as ReadableStream<Uint8Array>\n }\n\n store(directory: string, disk?: string): Promise<string> {\n return inject(FilesystemManager).disk(disk).putFile(directory, this)\n }\n\n storeAs(directory: string, name: string, disk?: string): Promise<string> {\n return inject(FilesystemManager).disk(disk).putFileAs(directory, this, name)\n }\n}\n","/** A small extension ↔ MIME map for uploads and downloads (not exhaustive on purpose). */\nconst TYPES: Record<string, string> = {\n avif: 'image/avif',\n css: 'text/css',\n csv: 'text/csv',\n doc: 'application/msword',\n docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n gif: 'image/gif',\n gz: 'application/gzip',\n html: 'text/html',\n ico: 'image/vnd.microsoft.icon',\n jpg: 'image/jpeg',\n js: 'text/javascript',\n map: 'application/json',\n json: 'application/json',\n md: 'text/markdown',\n mp3: 'audio/mpeg',\n mp4: 'video/mp4',\n otf: 'font/otf',\n pdf: 'application/pdf',\n png: 'image/png',\n svg: 'image/svg+xml',\n ttf: 'font/ttf',\n txt: 'text/plain',\n wasm: 'application/wasm',\n webm: 'video/webm',\n webp: 'image/webp',\n woff: 'font/woff',\n woff2: 'font/woff2',\n xls: 'application/vnd.ms-excel',\n xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n xml: 'application/xml',\n zip: 'application/zip',\n}\nconst ALIASES: Record<string, string> = { jpeg: 'jpg', htm: 'html', mjs: 'js', text: 'txt' }\nconst EXTENSIONS = Object.fromEntries(Object.entries(TYPES).map(([extension, type]) => [type, extension]))\n\n/** 'report.PDF' or 'pdf' → 'application/pdf'; unknown → 'application/octet-stream'. */\nexport function mimeFromExtension(pathOrExtension: string): string {\n const extension = pathOrExtension.slice(pathOrExtension.lastIndexOf('.') + 1).toLowerCase()\n return TYPES[ALIASES[extension] ?? extension] ?? 'application/octet-stream'\n}\n\n/** 'image/jpeg; charset=…' → 'jpg'; unknown → undefined. */\nexport function extensionFromMime(type: string): string | undefined {\n return EXTENSIONS[type.split(';')[0]!.trim().toLowerCase()]\n}\n","import {\n CurrentRoute,\n Session,\n ValidationFactory,\n type HttpRequest,\n type Rules,\n type UploadedFile,\n} from '@orieljs/contracts'\nimport { currentContainer, inject } from '@orieljs/container'\nimport { Arr, Str } from '@orieljs/support'\nimport { exceedsJsonDepth, readBody } from './body'\nimport { HttpException } from './errors'\nimport { clientAddress } from './clientAddress'\nimport { FormUploadedFile } from './FormUploadedFile'\nimport { fromEntries, isBlank, isPlainObject, mergeRecursive, sanitize, transformLeaves } from './input'\n\ntype Tree = Record<string, unknown>\n\nexport interface IncomingRequestOptions {\n /** Proxy addresses whose X-Forwarded-* headers are believed: exact IPs, IPv4 CIDRs, or '*'. */\n trustedProxies?: readonly string[]\n /** Largest request body in bytes before a 413 (config http.max_body_size); null is unlimited. Default 8 MB. */\n maxBodySize?: number | null\n /** Deepest nesting of objects and arrays in a JSON body before a 400 (config http.max_json_depth); null is unlimited. Default 512. */\n maxJsonDepth?: number | null\n}\n\nconst TRUE_VALUES = new Set(['1', 'true', 'on', 'yes'])\n\nconst normalizeIp = (ip: string): string => ip.trim().replace(/^::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/i, '$1')\n\nfunction ipv4ToNumber(ip: string): number | undefined {\n const parts = ip.split('.')\n if (parts.length !== 4 || parts.some((part) => !/^\\d{1,3}$/.test(part) || Number(part) > 255)) return undefined\n return parts.reduce((total, part) => total * 256 + Number(part), 0)\n}\n\n/** Exact match, IPv4 CIDR ('10.0.0.0/8') or '*'. */\nexport function ipMatches(ip: string, patterns: readonly string[]): boolean {\n const address = normalizeIp(ip)\n return patterns.some((pattern) => {\n if (pattern === '*') return true\n if (!pattern.includes('/')) return normalizeIp(pattern) === address\n const [range, bits] = pattern.split('/') as [string, string]\n const base = ipv4ToNumber(range)\n const value = ipv4ToNumber(address)\n const size = Number(bits)\n if (base === undefined || value === undefined || !(size >= 0 && size <= 32)) return false\n const mask = size === 0 ? 0 : (~0 << (32 - size)) >>> 0\n return ((base & mask) >>> 0) === ((value & mask) >>> 0)\n })\n}\n\n/**\n * The HttpRequest implementation (Laravel's Illuminate\\Http\\Request). The kernel calls load() once, before any\n * middleware, so every accessor below is synchronous.\n *\n * `http.max_body_size` applies to the bodies this class parses (JSON, urlencoded and multipart). A handler that reads\n * `request.raw` directly bypasses it and must enforce its own limit.\n */\nexport class IncomingRequest implements HttpRequest {\n readonly #url: URL\n readonly #trustedProxies: readonly string[]\n readonly #maxBodySize: number | null\n readonly #maxJsonDepth: number | null\n #query: Tree\n #body: Tree = {}\n #files: Tree = {}\n #content = ''\n #method: string\n #cookies: Record<string, string> | undefined\n #loading: Promise<this> | undefined\n #userResolver: ((guard?: string) => unknown) | undefined\n\n constructor(\n readonly raw: Request,\n options: IncomingRequestOptions = {},\n ) {\n this.#url = new URL(raw.url)\n this.#trustedProxies = options.trustedProxies ?? []\n this.#maxBodySize = options.maxBodySize === undefined ? 8 * 1024 * 1024 : options.maxBodySize\n this.#maxJsonDepth = options.maxJsonDepth === undefined ? 512 : options.maxJsonDepth\n this.#query = fromEntries(this.#url.searchParams.entries())\n this.#method = raw.method.toUpperCase()\n }\n\n /** Reads and parses the body (JSON, urlencoded or multipart) once, then applies method spoofing. */\n load(): Promise<this> {\n return (this.#loading ??= this.#load())\n }\n\n async #load(): Promise<this> {\n const method = this.raw.method.toUpperCase()\n if (method !== 'GET' && method !== 'HEAD' && this.raw.body !== null) {\n const type = (this.raw.headers.get('content-type') ?? '').toLowerCase()\n const isJson = type.includes('/json') || type.includes('+json')\n const isUrlencoded = type.startsWith('application/x-www-form-urlencoded')\n const isMultipart = type.startsWith('multipart/form-data')\n if (isJson || isUrlencoded || isMultipart) {\n // Size (413) and depth (400) errors must reach the caller; only a malformed body reads as empty input, as in Laravel.\n const bytes = await readBody(this.raw, this.#maxBodySize)\n if (isJson && this.#maxJsonDepth !== null && exceedsJsonDepth(new TextDecoder().decode(bytes), this.#maxJsonDepth)) {\n throw new HttpException(400, 'The request body is nested too deeply.')\n }\n try {\n if (isJson) {\n this.#content = new TextDecoder().decode(bytes)\n this.#body = this.#parseJson(this.#content)\n } else if (isUrlencoded) {\n this.#content = new TextDecoder().decode(bytes)\n this.#body = fromEntries(new URLSearchParams(this.#content).entries())\n } else {\n await this.#parseForm(await new Response(bytes as Uint8Array<ArrayBuffer>, { headers: { 'content-type': this.raw.headers.get('content-type') ?? '' } }).formData())\n }\n } catch {\n // A malformed body reads as empty input, as in Laravel.\n }\n }\n }\n if (method === 'POST') {\n const override =\n this.raw.headers.get('x-http-method-override') ?? this.#string(this.#body._method) ?? this.#string(this.#query._method)\n const spoofed = override?.toUpperCase()\n if (spoofed !== undefined && /^[A-Z]+$/.test(spoofed) && !['GET', 'HEAD', 'CONNECT', 'TRACE'].includes(spoofed)) {\n this.#method = spoofed\n }\n }\n return this\n }\n\n #parseJson(text: string): Tree {\n let parsed: unknown\n try {\n parsed = JSON.parse(text)\n } catch {\n return {}\n }\n if (Array.isArray(parsed)) return sanitize({ ...parsed }) as Tree\n return isPlainObject(parsed) ? (sanitize(parsed) as Tree) : {}\n }\n\n async #parseForm(form: FormData): Promise<void> {\n const fields: Array<[string, unknown]> = []\n const files: Array<[string, unknown]> = []\n for (const [name, value] of form.entries()) {\n if (typeof value === 'string') fields.push([name, value])\n // A file input left empty arrives as filename=\"\" with no bytes (PHP's UPLOAD_ERR_NO_FILE).\n else if (!((value.name ?? '') === '' && value.size === 0)) files.push([name, await FormUploadedFile.fromFile(value)])\n }\n this.#body = fromEntries(fields)\n this.#files = fromEntries(files)\n }\n\n #string(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined\n }\n\n method(): string {\n return this.#method\n }\n\n isMethod(method: string): boolean {\n return this.#method === method.toUpperCase()\n }\n\n /** The scheme and host, honouring X-Forwarded-Proto/Host from trusted proxies. */\n root(): string {\n const trusted = this.#fromTrustedProxy()\n const proto = trusted ? this.raw.headers.get('x-forwarded-proto')?.split(',')[0]?.trim() : undefined\n const host = trusted ? this.raw.headers.get('x-forwarded-host')?.split(',')[0]?.trim() : undefined\n const scheme = proto === 'https' || proto === 'http' ? proto : this.#url.protocol.slice(0, -1)\n return `${scheme}://${host !== undefined && host !== '' ? host : this.#url.host}`\n }\n\n /** The URL without the query string or a trailing slash. */\n url(): string {\n return `${this.root()}${this.#url.pathname}`.replace(/\\/+$/, '')\n }\n\n fullUrl(): string {\n return this.#url.search === '' ? this.url() : `${this.url()}${this.#url.search}`\n }\n\n /** 'posts/1', or '/' for the root. */\n path(): string {\n const trimmed = this.#url.pathname.replace(/^\\/+|\\/+$/g, '')\n return trimmed === '' ? '/' : trimmed\n }\n\n decodedPath(): string {\n try {\n return decodeURIComponent(this.path())\n } catch {\n return this.path()\n }\n }\n\n secure(): boolean {\n return this.root().startsWith('https:')\n }\n\n /** request.is('admin/*'): wildcard match against the decoded path. */\n is(...patterns: string[]): boolean {\n const path = this.decodedPath()\n return patterns.some((pattern) => {\n const trimmed = pattern.replace(/^\\/+|\\/+$/g, '')\n return Str.is(trimmed === '' ? '/' : trimmed, path)\n })\n }\n\n routeIs(...names: string[]): boolean {\n const name = this.#currentRoute()?.route.getName()\n return name !== undefined && names.some((pattern) => Str.is(pattern, name))\n }\n\n header(name: string): string | undefined\n header(name: string, defaultValue: string): string\n header(name: string, defaultValue?: string): string | undefined {\n return this.raw.headers.get(name) ?? defaultValue\n }\n\n bearerToken(): string | undefined {\n const header = this.header('authorization', '')\n const position = header.toLowerCase().lastIndexOf('bearer ')\n if (position === -1) return undefined\n const token = header.slice(position + 7).split(',')[0]!.trim()\n return token === '' ? undefined : token\n }\n\n userAgent(): string | undefined {\n return this.header('user-agent')\n }\n\n /** The socket address, or the right-most untrusted X-Forwarded-For entry when the socket is a trusted proxy. */\n ip(): string | undefined {\n const socket = clientAddress(this.raw)\n if (socket === undefined) return undefined\n const address = normalizeIp(socket)\n if (!this.#fromTrustedProxy()) return address\n const chain = (this.raw.headers.get('x-forwarded-for') ?? '')\n .split(',')\n .map((entry) => normalizeIp(entry))\n .filter((entry) => entry !== '')\n for (let i = chain.length - 1; i >= 0; i--) if (!ipMatches(chain[i]!, this.#trustedProxies)) return chain[i]\n return chain[0] ?? address\n }\n\n #fromTrustedProxy(): boolean {\n const socket = clientAddress(this.raw)\n return socket !== undefined && this.#trustedProxies.length > 0 && ipMatches(socket, this.#trustedProxies)\n }\n\n ajax(): boolean {\n return this.header('x-requested-with') === 'XMLHttpRequest'\n }\n\n pjax(): boolean {\n return this.header('x-pjax') === 'true'\n }\n\n /** The first Accept type is JSON. */\n wantsJson(): boolean {\n const first = this.header('accept', '').split(',')[0]!.trim()\n return first.includes('/json') || first.includes('+json')\n }\n\n /** Laravel: (ajax and not pjax and accepts anything) or wantsJson. */\n expectsJson(): boolean {\n const first = this.header('accept', '').split(',')[0]!.split(';')[0]!.trim()\n const acceptsAny = first === '' || first === '*/*' || first === '*'\n return (this.ajax() && !this.pjax() && acceptsAny) || this.wantsJson()\n }\n\n /** The raw body text for JSON and urlencoded requests ('' otherwise; the raw stream stays unread for other types). */\n content(): string {\n return this.#content\n }\n\n query<T = unknown>(key?: string, defaultValue?: T): T {\n return Arr.get<T>(this.#query, key, defaultValue)\n }\n\n /** Body wins over the query string (PHP's $body + $query). Files are not input. */\n input<T = unknown>(key?: string, defaultValue?: T): T {\n return Arr.get<T>({ ...this.#query, ...this.#body }, key, defaultValue)\n }\n\n /** Input plus files (array_replace_recursive). */\n all(): Record<string, unknown> {\n return mergeRecursive({ ...this.#query, ...this.#body }, this.#files)\n }\n\n only(...keys: Array<string | string[]>): Record<string, unknown> {\n const all = this.all()\n const out: Tree = {}\n for (const key of keys.flat()) if (Arr.has(all, key)) Arr.set(out, key, Arr.get(all, key))\n return out\n }\n\n except(...keys: Array<string | string[]>): Record<string, unknown> {\n const all = structuredCloneInput(this.all())\n for (const key of keys.flat()) Arr.forget(all, key)\n return all\n }\n\n has(...keys: Array<string | string[]>): boolean {\n const all = this.all()\n return keys.flat().every((key) => Arr.has(all, key))\n }\n\n hasAny(...keys: Array<string | string[]>): boolean {\n const all = this.all()\n return keys.flat().some((key) => Arr.has(all, key))\n }\n\n missing(...keys: Array<string | string[]>): boolean {\n return !this.has(...keys)\n }\n\n filled(key: string): boolean {\n return !isBlank(Arr.get(this.all(), key))\n }\n\n string(key: string, defaultValue = ''): string {\n const value = this.input<unknown>(key)\n return value === undefined || value === null ? defaultValue : String(value)\n }\n\n /** PHP's FILTER_VALIDATE_BOOLEAN: '1', 'true', 'on', 'yes' (any case) and true are true. */\n boolean(key: string, defaultValue = false): boolean {\n const value = this.input<unknown>(key)\n if (value === undefined) return defaultValue\n if (typeof value === 'boolean') return value\n if (typeof value === 'number') return value === 1\n return typeof value === 'string' && TRUE_VALUES.has(value.trim().toLowerCase())\n }\n\n /** PHP's intval: leading digits, else 0. */\n integer(key: string, defaultValue = 0): number {\n const value = this.input<unknown>(key)\n if (value === undefined) return defaultValue\n if (typeof value === 'number') return Number.isFinite(value) ? Math.trunc(value) : 0\n if (typeof value === 'boolean') return value ? 1 : 0\n const parsed = Number.parseInt(String(value).trim(), 10)\n return Number.isNaN(parsed) ? 0 : parsed\n }\n\n /** Adds or replaces top-level body values. */\n merge(values: Record<string, unknown>): this {\n this.#body = { ...this.#body, ...(sanitize(values) as Tree) }\n return this\n }\n\n /** Rewrites every scalar in the query and the body (TrimStrings and ConvertEmptyStringsToNull use this). */\n transformInput(transform: (key: string, value: unknown) => unknown): this {\n this.#query = transformLeaves(this.#query, transform)\n this.#body = transformLeaves(this.#body, transform)\n return this\n }\n\n file(key: string): UploadedFile | undefined {\n const value = Arr.get<unknown>(this.#files, key)\n return value instanceof FormUploadedFile ? value : undefined\n }\n\n hasFile(key: string): boolean {\n const value = Arr.get<unknown>(this.#files, key)\n return value instanceof FormUploadedFile || (Array.isArray(value) && value.some((item) => item instanceof FormUploadedFile))\n }\n\n allFiles(): Record<string, unknown> {\n return { ...this.#files }\n }\n\n cookie(name: string): string | undefined {\n return this.cookies()[name]\n }\n\n cookies(): Record<string, string> {\n if (this.#cookies === undefined) {\n const cookies: Record<string, string> = {}\n for (const part of (this.raw.headers.get('cookie') ?? '').split(';')) {\n const index = part.indexOf('=')\n if (index === -1) continue\n const name = part.slice(0, index).trim()\n if (name === '' || Object.hasOwn(cookies, name)) continue\n let value = part.slice(index + 1).trim()\n if (value.startsWith('\"') && value.endsWith('\"')) value = value.slice(1, -1)\n try {\n cookies[name] = decodeURIComponent(value)\n } catch {\n cookies[name] = value\n }\n }\n this.#cookies = cookies\n }\n return { ...this.#cookies }\n }\n\n /** Replaces the parsed cookies (EncryptCookies calls this after decrypting). */\n setCookies(cookies: Record<string, string>): void {\n this.#cookies = { ...cookies }\n }\n\n /** One route parameter (after model binding), or all of them. */\n route<T = unknown>(key?: string): T {\n const parameters = this.#currentRoute()?.parameters ?? {}\n return (key === undefined ? { ...parameters } : parameters[key]) as T\n }\n\n session(): Session {\n return inject(Session)\n }\n\n user<T = unknown>(guard?: string): T | undefined {\n return this.#userResolver?.(guard) as T | undefined\n }\n\n setUserResolver(resolver: (guard?: string) => unknown): void {\n this.#userResolver = resolver\n }\n\n /** Validates all() through the ValidationFactory; throws its Validation error on failure. */\n validate<T = Record<string, unknown>>(\n rules: Rules,\n messages?: Record<string, string>,\n attributes?: Record<string, string>,\n ): Promise<T> {\n return inject(ValidationFactory).make(this.all(), rules, messages, attributes).validated<T>()\n }\n\n #currentRoute() {\n const container = currentContainer()\n return container?.bound(CurrentRoute) ? container.make(CurrentRoute) : undefined\n }\n}\n\n/** A copy deep enough for except() to forget nested keys without touching the request. */\nfunction structuredCloneInput(tree: Tree): Tree {\n const out: Tree = {}\n for (const [key, value] of Object.entries(tree)) {\n out[key] = isPlainObject(value) ? structuredCloneInput(value) : Array.isArray(value) ? [...value] : value\n }\n return out\n}\n","/** Helpers for request input: PHP-style bracket keys, safe cloning (no prototype pollution) and blank checks. */\n\ntype Tree = Record<string, unknown>\n\nconst FORBIDDEN = new Set(['__proto__', 'prototype', 'constructor'])\n\n/** Keys PHP treats as integers: '0', '7', '42' (not '07' or '-1'). */\nconst INTEGER_KEY = /^(?:0|[1-9]\\d*)$/\n\n// Duplicated in Routing's BaseUrlGenerator.ts on purpose: Http, Routing and Pipeline may not import each other.\nexport const isPlainObject = (value: unknown): value is Tree => {\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/** 'user[name]' → ['user', 'name']; 'tags[]' → ['tags', '']; a malformed key stays whole. */\nexport function parseBracketKey(name: string): string[] {\n const open = name.indexOf('[')\n if (open <= 0 || !name.endsWith(']')) return [name]\n const segments = [name.slice(0, open)]\n const rest = name.slice(open)\n const matches = rest.match(/\\[[^[\\]]*\\]/g)\n if (matches === null || matches.join('') !== rest) return [name]\n for (const match of matches) segments.push(match.slice(1, -1))\n return segments\n}\n\n/** Objects whose keys are exactly 0..n-1 become arrays, recursively (PHP arrays → JS lists). */\nexport function normalizeLists(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(normalizeLists)\n if (!isPlainObject(value)) return value\n const keys = Object.keys(value)\n const out: Tree = {}\n for (const key of keys) out[key] = normalizeLists(value[key])\n if (keys.length > 0 && keys.every((key, index) => key === String(index))) return keys.map((key) => out[key])\n return out\n}\n\n/**\n * Builds nested input from flat form entries, PHP style: 'user[name]', 'tags[]', 'a[b][]'.\n * Keys containing __proto__/prototype/constructor are dropped.\n */\nexport function fromEntries(entries: Iterable<readonly [string, unknown]>): Tree {\n const root: Tree = {}\n // The next '[]' index per node, kept as PHP does (one past the highest integer key) so appending stays O(1).\n const nextIndex = new WeakMap<Tree, number>()\n for (const [name, value] of entries) {\n const segments = parseBracketKey(name)\n if (segments.some((segment) => FORBIDDEN.has(segment))) continue\n let node = root\n for (let i = 0; i < segments.length; i++) {\n let segment = segments[i]!\n const next = nextIndex.get(node) ?? 0\n if (segment === '') {\n segment = String(next)\n nextIndex.set(node, next + 1)\n } else if (INTEGER_KEY.test(segment) && Number(segment) >= next) {\n nextIndex.set(node, Number(segment) + 1)\n }\n if (i === segments.length - 1) {\n node[segment] = value\n break\n }\n if (!isPlainObject(node[segment])) node[segment] = {}\n node = node[segment] as Tree\n }\n }\n return normalizeLists(root) as Tree\n}\n\n/** Deep copy of parsed JSON without dangerous keys (JSON.parse creates an own \"__proto__\" property). */\nexport function sanitize(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sanitize)\n if (!isPlainObject(value)) return value\n const out: Tree = {}\n for (const [key, item] of Object.entries(value)) if (!FORBIDDEN.has(key)) out[key] = sanitize(item)\n return out\n}\n\n/** array_replace_recursive: `override` wins, nested plain objects merge. */\nexport function mergeRecursive(base: Tree, override: Tree): Tree {\n const out: Tree = { ...base }\n for (const [key, value] of Object.entries(override)) {\n if (FORBIDDEN.has(key)) continue\n const current = out[key]\n out[key] =\n (isPlainObject(current) || Array.isArray(current)) && (isPlainObject(value) || Array.isArray(value))\n ? normalizeLists(mergeRecursive({ ...current } as Tree, { ...value } as Tree))\n : value\n }\n return out\n}\n\n/** Laravel's blank(): null, undefined, whitespace-only strings, and empty arrays/objects. */\nexport function isBlank(value: unknown): boolean {\n if (value === null || value === undefined) return true\n if (typeof value === 'string') return value.trim() === ''\n if (Array.isArray(value)) return value.length === 0\n if (isPlainObject(value)) return Object.keys(value).length === 0\n return false\n}\n\n/** Applies `transform(dottedKey, value)` to every scalar leaf, inside nested objects and lists; the result replaces the leaf. */\nexport function transformLeaves(tree: Tree, transform: (key: string, value: unknown) => unknown, prefix = ''): Tree {\n const out: Tree = {}\n for (const [key, value] of Object.entries(tree)) out[key] = transformValue(`${prefix}${key}`, value, transform)\n return out\n}\n\nfunction transformValue(path: string, value: unknown, transform: (key: string, value: unknown) => unknown): unknown {\n if (Array.isArray(value)) return value.map((item, index) => transformValue(`${path}.${index}`, item, transform))\n if (isPlainObject(value)) return transformLeaves(value, transform, `${path}.`)\n return transform(path, value)\n}\n","import {\n HttpRequest,\n Redirector,\n ResponseFactory,\n UrlGenerator,\n type BodyInit,\n type HeadersInit,\n type RedirectResponse,\n type RouteName,\n} from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport { HttpException, HttpResponseException } from './errors'\n\n/** request() → the current HttpRequest; request('key', default) → its input. */\nexport function request(): HttpRequest\nexport function request<T = unknown>(key: string, defaultValue?: T): T\nexport function request(key?: string, defaultValue?: unknown): unknown {\n const current = inject(HttpRequest)\n return key === undefined ? current : current.input(key, defaultValue)\n}\n\n/** response() → the ResponseFactory; response(content, status, headers) → a Response. */\nexport function response(): ResponseFactory\nexport function response(content: BodyInit | null, status?: number, headers?: HeadersInit): Response\nexport function response(content?: BodyInit | null, status?: number, headers?: HeadersInit): ResponseFactory | Response {\n const factory = inject(ResponseFactory)\n return content === undefined ? factory : factory.make(content, status, headers)\n}\n\n/** The Redirector with its route() typed by the generated route names. */\nexport type TypedRedirector = Omit<Redirector, 'route'> & {\n route(name: RouteName, parameters?: unknown, status?: number): RedirectResponse\n}\n\n/** redirect() → the Redirector; redirect('/path', status) → a RedirectResponse. */\nexport function redirect(): TypedRedirector\nexport function redirect(to: string, status?: number): RedirectResponse\nexport function redirect(to?: string, status?: number): TypedRedirector | RedirectResponse {\n const redirector = inject(Redirector)\n return to === undefined ? redirector : redirector.to(to, status)\n}\n\n/** Redirect to the previous URL (same argument order as Redirector.back()). */\nexport function back(fallback?: string, status?: number): RedirectResponse {\n return inject(Redirector).back(fallback, status)\n}\n\n/** url() → the UrlGenerator; url('/path', query, absolute) → a URL. */\nexport function url(): UrlGenerator\nexport function url(path: string, query?: Record<string, unknown>, absolute?: boolean): string\nexport function url(path?: string, query?: Record<string, unknown>, absolute?: boolean): UrlGenerator | string {\n const generator = inject(UrlGenerator)\n return path === undefined ? generator : generator.to(path, query, absolute)\n}\n\n/** The URL of a named route. */\nexport function route(name: RouteName, parameters?: unknown, absolute?: boolean): string {\n return inject(UrlGenerator).route(name, parameters, absolute)\n}\n\n/** abort(404), abort(403, 'Nope', headers), or abort(response) to send a ready response. */\nexport function abort(status: number | Response, message = '', headers: Record<string, string> = {}): never {\n if (status instanceof Response) throw new HttpResponseException(status)\n throw new HttpException(status, message, headers)\n}\n\nexport function abortIf(condition: unknown, status: number | Response, message = '', headers: Record<string, string> = {}): void {\n if (condition) abort(status, message, headers)\n}\n\nexport function abortUnless(condition: unknown, status: number | Response, message = '', headers: Record<string, string> = {}): void {\n if (!condition) abort(status, message, headers)\n}\n","import { createReadStream } from 'node:fs'\nimport { stat } from 'node:fs/promises'\nimport { basename } from 'node:path'\nimport { Readable } from 'node:stream'\nimport { ViewFactory, type BodyInit, type HeadersInit, type ResponseFactory } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport { HttpException } from './errors'\nimport { mimeFromExtension } from './mime'\n\n/** 'attachment; filename=\"report.pdf\"' plus filename* for non-ASCII names (RFC 6266). */\nexport function contentDisposition(type: 'attachment' | 'inline', name: string): string {\n const fallback = name.replace(/[^\\x20-\\x7e]/g, '_').replace(/[\"\\\\]/g, '\\\\$&')\n const header = `${type}; filename=\"${fallback}\"`\n return /^[\\x20-\\x7e]*$/.test(name) ? header : `${header}; filename*=UTF-8''${encodeURIComponent(name)}`\n}\n\n/** Laravel's ResponseFactory (the response() helper). */\nexport class HttpResponseFactory implements ResponseFactory {\n /** Strings default to text/html; charset=utf-8, as in Laravel. */\n make(content: BodyInit | null = null, status = 200, headers?: HeadersInit): Response {\n const merged = new Headers(headers)\n if (typeof content === 'string' && !merged.has('content-type')) merged.set('content-type', 'text/html; charset=utf-8')\n return new Response(content, { status, headers: merged })\n }\n\n json(data: unknown, status = 200, headers?: HeadersInit): Response {\n const merged = new Headers(headers)\n if (!merged.has('content-type')) merged.set('content-type', 'application/json')\n return new Response(JSON.stringify(data === undefined ? null : data), { status, headers: merged })\n }\n\n noContent(status = 204): Response {\n return new Response(null, { status })\n }\n\n /** Renders a view (through the ViewFactory) into an HTML response. */\n async view(name: string, data: Record<string, unknown> = {}, status = 200, headers?: HeadersInit): Promise<Response> {\n const html = await inject(ViewFactory).make(name, data).render()\n return this.make(html, status, headers)\n }\n\n /** Streams a file as an attachment. A missing file is a 404. */\n download(path: string, name = basename(path), headers?: HeadersInit): Promise<Response> {\n return this.#file(path, 'attachment', name, headers)\n }\n\n /** Streams a file for the browser to display (Laravel's response()->file()). */\n file(path: string, headers?: HeadersInit): Promise<Response> {\n return this.#file(path, 'inline', basename(path), headers)\n }\n\n stream(body: ReadableStream, status = 200, headers?: HeadersInit): Response {\n return new Response(body, { status, headers })\n }\n\n async #file(path: string, disposition: 'attachment' | 'inline', name: string, headers?: HeadersInit): Promise<Response> {\n const info = await stat(path).catch(() => undefined)\n // No file path in the message: HTTP error messages are shown to clients.\n if (info === undefined || !info.isFile()) throw new HttpException(404)\n const merged = new Headers(headers)\n if (!merged.has('content-type')) merged.set('content-type', mimeFromExtension(name))\n merged.set('content-length', String(info.size))\n merged.set('content-disposition', contentDisposition(disposition, name))\n const body = Readable.toWeb(createReadStream(path)) as ReadableStream<Uint8Array>\n return new Response(body, { status: 200, headers: merged })\n }\n}\n","import {\n ConfigRepository,\n CurrentRoute,\n ExceptionHandler,\n HttpRequest,\n PipelineFactory,\n Router,\n type Application,\n type Container,\n type HttpKernel,\n type Middleware,\n type MiddlewareClass,\n} from '@orieljs/contracts'\nimport { currentContainer } from '@orieljs/container'\nimport { HttpServerError } from './errors'\nimport { IncomingRequest } from './IncomingRequest'\nimport { ConvertEmptyStringsToNull } from './middleware/ConvertEmptyStringsToNull'\nimport { TrimStrings } from './middleware/TrimStrings'\n\ninterface RequestState {\n readonly scope: Container\n readonly request: IncomingRequest\n readonly middleware: Middleware[]\n}\n\n/** The plain-text 500 the kernel falls back to. Exported so the server adapters can reuse it. */\nexport const plainServerError = (): Response =>\n new Response('Server Error', { status: 500, headers: { 'content-type': 'text/plain; charset=utf-8' } })\n\n/**\n * Laravel's Http Kernel: wraps the raw Request, binds it in the request scope, loads the body, then sends it through\n * the global middleware to the router. Every stage renders its own errors through the ExceptionHandler.\n */\nexport class Kernel implements HttpKernel {\n #middleware: MiddlewareClass[] = [TrimStrings, ConvertEmptyStringsToNull]\n readonly #requests = new WeakMap<Request, RequestState>()\n\n constructor(protected readonly app: Application) {}\n\n getGlobalMiddleware(): MiddlewareClass[] {\n return [...this.#middleware]\n }\n\n setGlobalMiddleware(middleware: MiddlewareClass[]): this {\n this.#middleware = [...middleware]\n return this\n }\n\n appendMiddleware(...middleware: MiddlewareClass[]): this {\n for (const cls of middleware) if (!this.#middleware.includes(cls)) this.#middleware.push(cls)\n return this\n }\n\n prependMiddleware(...middleware: MiddlewareClass[]): this {\n for (const cls of [...middleware].reverse()) if (!this.#middleware.includes(cls)) this.#middleware.unshift(cls)\n return this\n }\n\n hasMiddleware(middleware: MiddlewareClass): boolean {\n return this.#middleware.includes(middleware)\n }\n\n /** Runs in the current request scope (Application.handle() opens one); called directly, it opens its own. */\n handle(raw: Request): Promise<Response> {\n const current = currentContainer()\n const scope = current !== undefined && current !== this.app ? current : this.app.createScope()\n return scope.run(() => this.#handle(raw, scope))\n }\n\n async #handle(raw: Request, scope: Container): Promise<Response> {\n let request: IncomingRequest | undefined\n let response: Response\n try {\n request = new IncomingRequest(raw, {\n trustedProxies: this.#trustedProxies(),\n maxBodySize: this.#maxBodySize(),\n maxJsonDepth: this.#maxJsonDepth(),\n })\n scope.instance(HttpRequest, request)\n const state: RequestState = { scope, request, middleware: [] }\n this.#requests.set(raw, state)\n await request.load()\n response = await this.#sendThroughGlobal(state)\n } catch (error) {\n request ??= this.#bareRequest(scope, raw)\n if (request !== undefined) {\n response = await this.#renderLast(scope, request, error)\n } else {\n await this.#report(scope, error)\n response = plainServerError()\n }\n }\n // HEAD: same status and headers as GET, no body. Cancel the dropped body so an open file stream is released.\n if (raw.method.toUpperCase() === 'HEAD' && response.body !== null) {\n await response.body.cancel().catch(() => undefined)\n response = new Response(null, { status: response.status, statusText: response.statusText, headers: response.headers })\n }\n return response\n }\n\n /** The request without options, for rendering an error raised while the real one was being built. */\n #bareRequest(scope: Container, raw: Request): IncomingRequest | undefined {\n try {\n const request = new IncomingRequest(raw)\n scope.instance(HttpRequest, request)\n return request\n } catch {\n return undefined\n }\n }\n\n /** Runs terminate() on the global and route middleware (inside the request's scope), then Application.terminate(), inside the same scope, so terminating callbacks see the request's bindings. */\n async terminate(raw: Request, response: Response): Promise<void> {\n const state = this.#requests.get(raw)\n if (state !== undefined) {\n this.#requests.delete(raw)\n await state.scope.run(async () => {\n const route = state.scope.bound(CurrentRoute) ? state.scope.make(CurrentRoute).middleware : []\n for (const middleware of [...state.middleware, ...route]) {\n if (typeof middleware.terminate !== 'function') continue\n try {\n await middleware.terminate(state.request, response)\n } catch (error) {\n await this.#report(state.scope, error)\n }\n }\n await this.app.terminate()\n })\n return\n }\n await this.app.terminate()\n }\n\n #sendThroughGlobal(state: RequestState): Promise<Response> {\n const { scope, request } = state\n const pipes = this.#middleware.map((cls) => {\n const instance = scope.make(cls)\n state.middleware.push(instance)\n return (passable: HttpRequest, next: (passable: HttpRequest) => Promise<unknown>) =>\n this.#guard(scope, passable, () => instance.handle(passable, next as (r: HttpRequest) => Promise<Response>))\n })\n return scope\n .make(PipelineFactory)\n .make<HttpRequest>()\n .send(request)\n .through(pipes)\n .then((passable) => this.#guard(scope, passable, () => this.#dispatch(scope, passable)))\n }\n\n #dispatch(scope: Container, request: HttpRequest): Promise<Response> {\n return scope.make(Router).dispatch(request)\n }\n\n /** Converts a Responsable result, and renders a thrown error at this stage (Laravel's Routing\\Pipeline). */\n async #guard(scope: Container, request: HttpRequest, run: () => Promise<unknown>): Promise<Response> {\n try {\n const result = await run()\n if (result instanceof Response) return result\n const responsable = result as { toResponse?: (request: unknown) => Response | Promise<Response> } | null\n if (typeof responsable?.toResponse === 'function') return await responsable.toResponse(request)\n throw new HttpServerError('Middleware must return a Response.')\n } catch (error) {\n if (!scope.bound(ExceptionHandler)) throw error\n const handler = scope.make(ExceptionHandler)\n await handler.report(error)\n return handler.render(request, error)\n }\n }\n\n /** Last resort: the handler failed or isn't bound. Never throws. */\n async #renderLast(scope: Container, request: HttpRequest, error: unknown): Promise<Response> {\n if (scope.bound(ExceptionHandler)) {\n try {\n const handler = scope.make(ExceptionHandler)\n await handler.report(error)\n return await handler.render(request, error)\n } catch (renderError) {\n console.error(renderError)\n }\n } else {\n console.error(error)\n }\n return plainServerError()\n }\n\n async #report(scope: Container, error: unknown): Promise<void> {\n try {\n if (scope.bound(ExceptionHandler)) await scope.make(ExceptionHandler).report(error)\n else console.error(error)\n } catch (reportError) {\n console.error(reportError)\n }\n }\n\n /** config('http.max_body_size'): bytes, or null for no limit. Anything else is a configuration error. */\n #maxBodySize(): number | null {\n if (!this.app.bound(ConfigRepository)) return 8 * 1024 * 1024\n const value = this.app.make(ConfigRepository).get<unknown>('http.max_body_size', 8 * 1024 * 1024)\n if (value === null) return null\n if (typeof value === 'number' && Number.isFinite(value) && value >= 0) return value\n throw new HttpServerError(\n `Invalid http.max_body_size ${JSON.stringify(value) ?? String(value)}: use a number of bytes (0 or more), or null for no limit.`,\n )\n }\n\n /** config('http.max_json_depth'): how deep a JSON body may nest, or null for no limit. */\n #maxJsonDepth(): number | null {\n if (!this.app.bound(ConfigRepository)) return 512\n const value = this.app.make(ConfigRepository).get<unknown>('http.max_json_depth', 512)\n if (value === null) return null\n if (typeof value === 'number' && Number.isInteger(value) && value >= 1) return value\n throw new HttpServerError(\n `Invalid http.max_json_depth ${JSON.stringify(value) ?? String(value)}: use a whole number (1 or more), or null for no limit.`,\n )\n }\n\n /** config('http.trusted_proxies'): an array, or a comma-separated string such as '*' or '10.0.0.0/8,::1'. */\n #trustedProxies(): string[] {\n if (!this.app.bound(ConfigRepository)) return []\n const value = this.app.make(ConfigRepository).get<unknown>('http.trusted_proxies', [])\n if (typeof value === 'string') return value.split(',').map((entry) => entry.trim()).filter((entry) => entry !== '')\n return Array.isArray(value) ? value.map(String) : []\n }\n}\n","import type { HttpRequest, Middleware, Next } from '@orieljs/contracts'\nimport { IncomingRequest } from '../IncomingRequest'\n\n/** '' becomes null in the query and body, so `nullable` validation behaves as in Laravel. */\nexport class ConvertEmptyStringsToNull implements Middleware {\n async handle(request: HttpRequest, next: Next): Promise<Response> {\n if (request instanceof IncomingRequest) request.transformInput((_key, value) => (value === '' ? null : value))\n return next(request)\n }\n}\n","import type { HttpRequest, Middleware, Next } from '@orieljs/contracts'\nimport { IncomingRequest } from '../IncomingRequest'\n\n/** Laravel's trim: whitespace plus BOM, zero-width space and left-to-right mark. */\nconst TRIM = /^[\\s\\uFEFF\\u200B\\u200E]+|[\\s\\uFEFF\\u200B\\u200E]+$/g\n\n/** Trims every string in the query and body, except password fields (Laravel's TrimStrings). */\nexport class TrimStrings implements Middleware {\n /** Dotted input keys left untouched. Override in a subclass to change. */\n protected except: string[] = ['current_password', 'password', 'password_confirmation']\n\n async handle(request: HttpRequest, next: Next): Promise<Response> {\n if (request instanceof IncomingRequest) {\n request.transformInput((key, value) =>\n typeof value === 'string' && !this.except.includes(key) ? value.replace(TRIM, '') : value,\n )\n }\n return next(request)\n }\n}\n","import {\n ConfigRepository,\n MiddlewareCallbacks,\n Router,\n type Application,\n type HttpRequest,\n type MiddlewareClass,\n type MiddlewareConfigurator,\n type MiddlewareReference,\n} from '@orieljs/contracts'\nimport type { Kernel } from './Kernel'\n\ninterface GroupOptions {\n append?: MiddlewareClass[]\n prepend?: MiddlewareClass[]\n remove?: MiddlewareClass[]\n}\n\n/** The `m` in withMiddleware((m) => …): edits the kernel's global middleware and the router's groups and aliases. */\nexport class MiddlewareConfiguration implements MiddlewareConfigurator {\n constructor(\n private readonly kernel: Kernel,\n private readonly router: Router,\n private readonly config?: ConfigRepository,\n ) {}\n\n append(...middleware: MiddlewareClass[]): this {\n this.kernel.appendMiddleware(...middleware)\n return this\n }\n\n prepend(...middleware: MiddlewareClass[]): this {\n this.kernel.prependMiddleware(...middleware)\n return this\n }\n\n web(options: GroupOptions): this {\n return this.#modifyGroup('web', options)\n }\n\n api(options: GroupOptions): this {\n return this.#modifyGroup('api', options)\n }\n\n alias(aliases: Record<string, MiddlewareClass>): this {\n for (const [name, middleware] of Object.entries(aliases)) this.router.aliasMiddleware(name, middleware)\n return this\n }\n\n group(name: string, middleware: Array<MiddlewareClass | string>): this {\n this.router.middlewareGroup(name, middleware)\n return this\n }\n\n /** Stored in config('http.csrf_except'), which the Session component's VerifyCsrfToken reads. */\n validateCsrfTokens(options: { except: string[] }): this {\n const current = this.config?.get<string[]>('http.csrf_except', []) ?? []\n this.config?.set('http.csrf_except', [...current, ...options.except])\n return this\n }\n\n /** Stored in config('http.redirect_guests_to'), which the Auth middleware and the exception handler read. */\n redirectGuestsTo(url: string | ((request: HttpRequest) => string)): this {\n this.config?.set('http.redirect_guests_to', url)\n return this\n }\n\n /** Laravel 11's redirectUsersTo(): stored in config('http.redirect_users_to') for Auth's RedirectIfAuthenticated. */\n redirectUsersTo(url: string | ((request: HttpRequest) => string)): this {\n this.config?.set('http.redirect_users_to', url)\n return this\n }\n\n /** Laravel's order: prepends, then the group minus removals, then appends. */\n #modifyGroup(name: string, { append = [], prepend = [], remove = [] }: GroupOptions): this {\n const current: MiddlewareReference[] = this.router.getMiddlewareGroups()[name] ?? []\n const moved = new Set<MiddlewareReference>([...append, ...prepend, ...remove])\n this.router.middlewareGroup(name, [...prepend, ...current.filter((entry) => !moved.has(entry)), ...append])\n return this\n }\n}\n\n/** Runs the withMiddleware() callbacks collected by the ApplicationBuilder (HttpServiceProvider calls this once booted). */\nexport function applyMiddlewareCallbacks(app: Application, kernel: Kernel): void {\n if (!app.bound(MiddlewareCallbacks)) return\n const callbacks = app.make(MiddlewareCallbacks) as Array<(configurator: MiddlewareConfigurator) => void>\n if (callbacks.length === 0) return\n const config = app.bound(ConfigRepository) ? app.make(ConfigRepository) : undefined\n const configurator = new MiddlewareConfiguration(kernel, app.make(Router), config)\n for (const callback of callbacks) callback(configurator)\n}\n","import {\n ConfigRepository,\n LogManager,\n Redirector,\n UrlGenerator,\n ViewFactory,\n type Application,\n type AuthenticationError,\n type Container,\n type ErrorKind,\n type ExceptionHandler,\n type HttpRequest,\n type OrielError,\n type ValidationError,\n} from '@orieljs/contracts'\nimport { currentContainer } from '@orieljs/container'\nimport { debugPage, minimalPage, stackFrames, statusText } from './errorPages'\nimport { HttpResponseException } from './errors'\nimport { IncomingRequest } from './IncomingRequest'\n\nexport type ReportCallback = (error: unknown) => void | boolean | Promise<void | boolean>\nexport type RenderCallback = (error: unknown, request: unknown) => Response | undefined | Promise<Response | undefined>\nexport type ErrorClass = abstract new (...args: never[]) => Error\nexport type JsonWhenCallback = (request: HttpRequest, error: unknown) => boolean\n\n/** Laravel's $internalDontReport: expected errors that are rendered, never logged ('Server' is not here). */\nconst NOT_REPORTED = new Set<ErrorKind>(['Http', 'ModelNotFound', 'Validation', 'Authentication', 'Authorization', 'TokenMismatch'])\n/** Kinds whose message is safe to show to users, at any status (Laravel's HttpException rendering). */\nconst HTTP_KINDS = new Set<ErrorKind>(['Http', 'ModelNotFound', 'Authorization', 'TokenMismatch'])\n\nconst kindOf = (error: unknown): ErrorKind | undefined =>\n typeof error === 'object' && error !== null && typeof (error as OrielError).kind === 'string' ? (error as OrielError).kind : undefined\n\n/** HTTP status for an error (spec §7). */\nexport function statusFor(error: unknown): number {\n const status = (error as Partial<OrielError> | null)?.status\n switch (kindOf(error)) {\n case 'Http':\n return status ?? 500\n case 'ModelNotFound':\n return 404\n case 'Authorization':\n return status ?? 403\n case 'TokenMismatch':\n return 419\n case 'Authentication':\n return 401\n case 'Validation':\n return status ?? 422\n case 'Server':\n return status ?? 500\n default:\n return 500\n }\n}\n\n/** \"The title field is required. (and 2 more errors)\" (Laravel's ValidationException::summarize). */\nexport function summarizeValidation(errors: Record<string, string[]>): string {\n const messages = Object.values(errors).flat()\n if (messages.length === 0) return 'The given data was invalid.'\n const more = messages.length - 1\n return more === 0 ? messages[0]! : `${messages[0]!} (and ${more} more ${more === 1 ? 'error' : 'errors'})`\n}\n\n/** An HTTP-like error: its message may be shown and it doesn't get the debug page. */\nconst isHttpLike = (error: unknown): boolean => {\n const kind = kindOf(error)\n return kind !== undefined && HTTP_KINDS.has(kind)\n}\n\n/** The exception handler (spec §7): report through the LogManager, render by error kind. */\nexport class ErrorHandler implements ExceptionHandler {\n /** Input keys never flashed back on a validation redirect. */\n protected dontFlash = ['current_password', 'password', 'password_confirmation']\n readonly #reportCallbacks: ReportCallback[] = []\n readonly #renderCallbacks: RenderCallback[] = []\n readonly #dontReport: ErrorClass[] = []\n readonly #reported = new WeakSet<object>()\n #jsonWhen: JsonWhenCallback | undefined\n\n constructor(protected readonly app: Application) {}\n\n reportUsing(callback: ReportCallback): void {\n this.#reportCallbacks.push(callback)\n }\n\n renderUsing(callback: RenderCallback): void {\n this.#renderCallbacks.push(callback)\n }\n\n ignore(...classes: ErrorClass[]): void {\n this.#dontReport.push(...classes)\n }\n\n /** Laravel's shouldRenderJsonWhen(): the callback decides JSON or HTML instead of the Accept header. */\n shouldRenderJsonWhen(callback: JsonWhenCallback): void {\n this.#jsonWhen = callback\n }\n\n /** Laravel's shouldReturnJson(): the shouldRenderJsonWhen() callback when set, else request.expectsJson(). */\n protected shouldReturnJson(request: HttpRequest, error: unknown): boolean {\n return this.#jsonWhen !== undefined ? this.#jsonWhen(request, error) : request.expectsJson()\n }\n\n shouldReport(error: unknown): boolean {\n const kind = kindOf(error)\n if (kind !== undefined && NOT_REPORTED.has(kind)) return false\n return !this.#dontReport.some((cls) => error instanceof cls)\n }\n\n /** Report callbacks first (returning false stops the default log), then LogManager.error(), else console.error. Once per error. */\n async report(error: unknown): Promise<void> {\n if (!this.shouldReport(error)) return\n if (typeof error === 'object' && error !== null) {\n if (this.#reported.has(error)) return\n this.#reported.add(error)\n }\n try {\n for (const callback of this.#reportCallbacks) if ((await callback(error)) === false) return\n const container = this.#container()\n if (container.bound(LogManager)) {\n const message = error instanceof Error ? error.message : String(error)\n container.make(LogManager).error(message, { exception: error })\n } else {\n console.error(error)\n }\n } catch (reportError) {\n console.error(reportError)\n }\n }\n\n async render(request: unknown, error: unknown): Promise<Response> {\n for (const callback of this.#renderCallbacks) {\n const response = await callback(error, request)\n if (response instanceof Response) return response\n }\n if (error instanceof HttpResponseException) return error.response\n const custom = await this.#renderCustom(request, error)\n if (custom !== undefined) return custom\n\n const http = this.#httpRequest(request)\n const kind = kindOf(error)\n let response: Response\n if (kind === 'Validation') response = await this.#renderValidation(http, error as ValidationError)\n else if (kind === 'Authentication') response = await this.#renderAuthentication(http, error as AuthenticationError)\n else if (this.shouldReturnJson(http, error)) response = this.#renderJson(error)\n else response = await this.#renderHtml(http, error)\n\n const headers = (error as Partial<OrielError> | null)?.headers\n if (headers !== undefined) for (const [name, value] of Object.entries(headers)) response.headers.set(name, value)\n return response\n }\n\n /** An error with its own render(request) or toResponse(request) (Laravel's renderable exceptions / Responsable). */\n async #renderCustom(request: unknown, error: unknown): Promise<Response | undefined> {\n if (typeof error !== 'object' || error === null) return undefined\n const candidate = error as { render?: (request: unknown) => unknown; toResponse?: (request: unknown) => unknown }\n for (const method of [candidate.render, candidate.toResponse]) {\n if (typeof method !== 'function') continue\n const response = await method.call(error, request)\n if (response instanceof Response) return response\n }\n return undefined\n }\n\n async #renderValidation(request: HttpRequest, error: ValidationError): Promise<Response> {\n if (this.shouldReturnJson(request, error)) {\n return this.#json({ message: summarizeValidation(error.errors), errors: error.errors }, statusFor(error))\n }\n const input = { ...request.input<Record<string, unknown>>() }\n for (const key of this.dontFlash) delete input[key]\n const container = this.#container()\n if (!container.bound(Redirector)) {\n return this.#redirect(error.redirectTo ?? request.header('referer') ?? '/')\n }\n const redirector = container.make(Redirector)\n const redirect = error.redirectTo !== undefined ? redirector.to(error.redirectTo) : redirector.back()\n // toResponse(request) may return a Promise per the Responsable contract; await it.\n const response = await redirect.withInput(input).withErrors(error.errors, error.errorBag).toResponse(request)\n return response\n }\n\n async #renderAuthentication(request: HttpRequest, error: AuthenticationError): Promise<Response> {\n if (this.shouldReturnJson(request, error)) return this.#json({ message: error.message || 'Unauthenticated.' }, 401)\n const target = error.redirectTo ?? this.#guestRedirect(request)\n const container = this.#container()\n if (!container.bound(Redirector)) return this.#redirect(target)\n const redirector = container.make(Redirector) as Redirector & { guest?: (path: string) => { toResponse(r: unknown): unknown } }\n const redirect = typeof redirector.guest === 'function' ? redirector.guest(target) : redirector.to(target)\n // toResponse(request) may return a Promise per the Responsable contract; await it.\n return (await redirect.toResponse(request)) as Response\n }\n\n /** config('http.redirect_guests_to'), then route('login'), then '/login'. */\n #guestRedirect(request: HttpRequest): string {\n const configured = this.#config<unknown>('http.redirect_guests_to', undefined)\n if (typeof configured === 'function') return String((configured as (request: HttpRequest) => string)(request))\n if (typeof configured === 'string' && configured !== '') return configured\n const container = this.#container()\n if (container.bound(UrlGenerator)) {\n const url = container.make(UrlGenerator)\n if (url.hasRoute('login')) return url.route('login')\n }\n return '/login'\n }\n\n #renderJson(error: unknown): Response {\n const status = statusFor(error)\n if (isHttpLike(error)) {\n const message = error instanceof Error && error.message !== '' ? error.message : statusText(status)\n return this.#json({ message }, status)\n }\n if (!this.#debug()) return this.#json({ message: 'Server Error' }, status)\n const err = error instanceof Error ? error : new Error(String(error))\n const [frame] = stackFrames(err)\n return this.#json(\n {\n message: err.message,\n exception: err.name,\n file: frame?.file,\n line: frame?.line,\n trace: stackFrames(err).map((entry) => entry.text),\n },\n status,\n )\n }\n\n async #renderHtml(request: HttpRequest, error: unknown): Promise<Response> {\n const status = statusFor(error)\n if (!isHttpLike(error) && this.#debug()) {\n return this.#html(await debugPage(error, request.method(), request.fullUrl()), status)\n }\n const message = status === 403 && error instanceof Error && error.message !== '' ? error.message : statusText(status)\n const view = await this.#errorView(status, error, message)\n return this.#html(view ?? minimalPage(status, message), status)\n }\n\n /** resources/views/errors/{status}.tsx, then errors/4xx or errors/5xx, through the ViewFactory. */\n async #errorView(status: number, error: unknown, message: string): Promise<string | undefined> {\n const container = this.#container()\n if (!container.bound(ViewFactory)) return undefined\n const views = container.make(ViewFactory)\n for (const name of [`errors.${status}`, `errors.${Math.floor(status / 100)}xx`]) {\n if (!views.exists(name)) continue\n try {\n return await views.make(name, { exception: error, status, message }).render()\n } catch (viewError) {\n await this.report(viewError)\n return undefined\n }\n }\n return undefined\n }\n\n #httpRequest(request: unknown): HttpRequest {\n if (typeof request === 'object' && request !== null && typeof (request as HttpRequest).expectsJson === 'function') {\n return request as HttpRequest\n }\n return new IncomingRequest(request instanceof Request ? request : new Request('http://localhost/'))\n }\n\n #json(body: unknown, status: number): Response {\n return new Response(JSON.stringify(body), { status, headers: { 'content-type': 'application/json' } })\n }\n\n #html(body: string, status: number): Response {\n return new Response(body, { status, headers: { 'content-type': 'text/html; charset=utf-8' } })\n }\n\n #redirect(location: string): Response {\n return new Response(null, { status: 302, headers: { Location: location } })\n }\n\n #debug(): boolean {\n return this.#config<unknown>('app.debug', false) === true\n }\n\n #config<T>(key: string, fallback: T): T {\n return this.app.bound(ConfigRepository) ? this.app.make(ConfigRepository).get<T>(key, fallback) : fallback\n }\n\n /** The request scope while handling a request (so scoped services resolve), else the application. */\n #container(): Container {\n return currentContainer() ?? this.app\n }\n}\n","import { readFile } from 'node:fs/promises'\nimport { fileURLToPath } from 'node:url'\n\nconst STATUS_TEXTS: Record<number, string> = {\n 400: 'Bad Request',\n 401: 'Unauthorized',\n 402: 'Payment Required',\n 403: 'Forbidden',\n 404: 'Not Found',\n 405: 'Method Not Allowed',\n 408: 'Request Timeout',\n 409: 'Conflict',\n 410: 'Gone',\n 413: 'Content Too Large',\n 415: 'Unsupported Media Type',\n 419: 'Page Expired',\n 422: 'Unprocessable Content',\n 429: 'Too Many Requests',\n 500: 'Server Error',\n 502: 'Bad Gateway',\n 503: 'Service Unavailable',\n 504: 'Gateway Timeout',\n}\n\n/** Laravel's wording for the status (its error pages say \"Server Error\" and \"Page Expired\"). */\nexport function statusText(status: number): string {\n return STATUS_TEXTS[status] ?? (status >= 500 ? 'Server Error' : 'Error')\n}\n\nexport function escapeHtml(value: string): string {\n return value.replace(/[&<>\"']/g, (char) => `&#${char.charCodeAt(0)};`)\n}\n\n/** Laravel's minimal error page: \"404 | Not Found\". */\nexport function minimalPage(status: number, message: string): string {\n const title = escapeHtml(message)\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>${title}</title>\n<style>body{margin:0;font-family:ui-sans-serif,system-ui,sans-serif;background:#f7fafc;color:#1a202c;display:flex;align-items:center;justify-content:center;min-height:100vh}.code{padding:0 1rem;border-right:1px solid #a0aec0;font-size:1.125rem}.message{padding:0 1rem;font-size:1.125rem;text-transform:uppercase;letter-spacing:.05em}</style>\n</head>\n<body><div class=\"code\">${status}</div><div class=\"message\">${title}</div></body>\n</html>`\n}\n\nexport interface StackFrame {\n readonly file: string\n readonly line: number\n readonly column: number\n readonly text: string\n}\n\n/** Parses V8/JavaScriptCore stack lines into frames that point at files. */\nexport function stackFrames(error: Error): StackFrame[] {\n const frames: StackFrame[] = []\n for (const raw of (error.stack ?? '').split('\\n').slice(1)) {\n const text = raw.trim()\n const match = /(?:\\(|@|at )((?:file:\\/\\/)?(?:\\/|[A-Za-z]:\\\\)[^()]*?):(\\d+):(\\d+)\\)?$/.exec(text)\n if (match === null) continue\n const location = match[1]!\n const file = location.startsWith('file://') ? fileURLToPath(location) : location\n frames.push({ file, line: Number(match[2]), column: Number(match[3]), text })\n }\n return frames\n}\n\n/** Up to `radius` lines either side of the frame's line, or undefined when the file can't be read. */\nasync function excerpt(frame: StackFrame, radius = 5): Promise<string | undefined> {\n const source = await readFile(frame.file, 'utf8').catch(() => undefined)\n if (source === undefined) return undefined\n const lines = source.split('\\n')\n const start = Math.max(1, frame.line - radius)\n const end = Math.min(lines.length, frame.line + radius)\n const rows: string[] = []\n for (let number = start; number <= end; number++) {\n const current = number === frame.line ? ' class=\"current\"' : ''\n rows.push(`<tr${current}><td class=\"n\">${number}</td><td><code>${escapeHtml(lines[number - 1] ?? '')}</code></td></tr>`)\n }\n return `<table class=\"source\">${rows.join('')}</table>`\n}\n\n/** The APP_DEBUG page: class, message, request, a source excerpt of the first app frame, the stack and causes. */\nexport async function debugPage(error: unknown, method: string, url: string): Promise<string> {\n const err = error instanceof Error ? error : new Error(String(error))\n const frames = stackFrames(err)\n const appFrame = frames.find((frame) => !frame.file.includes('node_modules') && !frame.file.startsWith('node:')) ?? frames[0]\n const source = appFrame === undefined ? undefined : await excerpt(appFrame)\n const causes: string[] = []\n for (let cause = err.cause, depth = 0; cause !== undefined && depth < 5; cause = (cause as Error).cause, depth++) {\n causes.push(`<li>${escapeHtml(cause instanceof Error ? `${cause.name}: ${cause.message}` : String(cause))}</li>`)\n }\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>${escapeHtml(err.message || err.name)}</title>\n<style>body{margin:0;font-family:ui-sans-serif,system-ui,sans-serif;background:#f3f4f6;color:#111827}main{max-width:1100px;margin:2rem auto;padding:0 1rem}header{background:#fff;border-radius:.5rem;padding:1.5rem;box-shadow:0 1px 3px #0001}.class{color:#dc2626;font-weight:600}.message{font-size:1.5rem;margin:.5rem 0}.request{color:#6b7280}section{background:#fff;border-radius:.5rem;padding:1rem;margin-top:1rem;box-shadow:0 1px 3px #0001;overflow:auto}.source td{padding:0 .5rem;white-space:pre;font-size:.85rem}.source .n{color:#9ca3af;text-align:right}.source .current{background:#fee2e2}ol{font-family:ui-monospace,monospace;font-size:.85rem}</style>\n</head>\n<body><main>\n<header><div class=\"class\">${escapeHtml(err.name)}</div><div class=\"message\">${escapeHtml(err.message)}</div><div class=\"request\">${escapeHtml(method)} ${escapeHtml(url)}</div></header>\n${appFrame === undefined ? '' : `<section><div>${escapeHtml(appFrame.file)}:${appFrame.line}</div>${source ?? ''}</section>`}\n<section><ol>${frames.map((frame) => `<li>${escapeHtml(frame.text)}</li>`).join('')}</ol></section>\n${causes.length === 0 ? '' : `<section><div>Caused by</div><ul>${causes.join('')}</ul></section>`}\n</main></body>\n</html>`\n}\n","import { ExceptionCallbacks, type Application, type ExceptionsConfigurator, type HttpRequest } from '@orieljs/contracts'\nimport type { ErrorClass, ErrorHandler, RenderCallback, ReportCallback } from './ErrorHandler'\n\n/** The `e` in withExceptions((e) => …). */\nexport class ExceptionsConfiguration implements ExceptionsConfigurator {\n constructor(private readonly handler: ErrorHandler) {}\n\n report(callback: ReportCallback): this {\n this.handler.reportUsing(callback)\n return this\n }\n\n render(callback: RenderCallback): this {\n this.handler.renderUsing(callback)\n return this\n }\n\n dontReport(...classes: ErrorClass[]): this {\n this.handler.ignore(...classes)\n return this\n }\n\n /** shouldRenderJsonWhen((request) => request.is('api/*')): JSON errors for those requests, whatever they accept. */\n shouldRenderJsonWhen(callback: (request: HttpRequest, error: unknown) => boolean): this {\n this.handler.shouldRenderJsonWhen(callback)\n return this\n }\n}\n\n/** Runs the withExceptions() callbacks against a handler (the provider does this when the handler is built). */\nexport function applyExceptionCallbacks(app: Application, handler: ErrorHandler): void {\n if (!app.bound(ExceptionCallbacks)) return\n const configurator = new ExceptionsConfiguration(handler)\n for (const callback of app.make(ExceptionCallbacks)) callback(configurator)\n}\n","import { HttpKernel, type Application } from '@orieljs/contracts'\nimport { plainServerError } from '../Kernel'\nimport { servePublicFile } from './static'\n\nexport type Runtime = 'node' | 'bun'\n\nexport interface ServeOptions {\n /** Default: PORT, then SERVER_PORT, then 8000 (Laravel's serve). 0 picks a free port. */\n port?: number\n /** Default: 127.0.0.1. */\n hostname?: string\n /** Close gracefully on SIGINT/SIGTERM, then exit. Default: true. */\n signals?: boolean\n /** How long close() waits for in-flight requests before cutting connections (ms). Default: 10000. */\n shutdownTimeout?: number\n /** Default: detected (Bun when globalThis.Bun exists). */\n runtime?: Runtime\n /** Called once listening. Default: prints \"Server running on [url].\" */\n onListen?: (server: RunningServer) => void\n /** Serve existing files from this directory before the app (Laravel's server.php). Default: app.publicPath(); false turns it off. */\n publicPath?: string | false\n}\n\nexport interface ResolvedServeOptions {\n readonly port: number\n readonly hostname: string\n readonly signals: boolean\n readonly shutdownTimeout: number\n /** Where public files are served from, or undefined when turned off. */\n readonly publicPath?: string\n}\n\nexport interface RunningServer {\n readonly runtime: Runtime\n readonly hostname: string\n readonly port: number\n /** 'http://127.0.0.1:8000' */\n readonly url: string\n /** Stops accepting connections, waits for in-flight requests (up to shutdownTimeout), then resolves. */\n close(): Promise<void>\n /** Resolves once the server has closed. */\n readonly closed: Promise<void>\n}\n\n/** HttpKernel.terminate() after the response went out (Laravel's terminable middleware). Never throws. */\nexport async function terminateRequest(app: Application, request: Request, response: Response): Promise<void> {\n try {\n if (app.bound(HttpKernel)) await app.make(HttpKernel).terminate?.(request, response)\n } catch (error) {\n console.error(error)\n }\n}\n\n/** A public file when one matches, else app.handle(), turning a crash outside the kernel into a plain 500. */\nexport async function handleSafely(app: Application, request: Request, publicPath?: string): Promise<Response> {\n try {\n if (publicPath !== undefined) {\n const file = await servePublicFile(publicPath, request)\n if (file !== undefined) return file\n }\n return await app.handle(request)\n } catch (error) {\n console.error(error)\n return plainServerError()\n }\n}\n\n/** SIGINT/SIGTERM → close() → process.exit(0). The listeners go away when the server closes. */\nexport function exitOnSignals(close: () => Promise<void>, closed: Promise<void>): void {\n const onSignal = () => {\n void close().then(() => process.exit(0))\n }\n process.once('SIGINT', onSignal)\n process.once('SIGTERM', onSignal)\n void closed.then(() => {\n process.off('SIGINT', onSignal)\n process.off('SIGTERM', onSignal)\n })\n}\n\nexport const displayHost = (hostname: string): string => (hostname.includes(':') ? `[${hostname}]` : hostname)\n","import { createReadStream } from 'node:fs'\nimport { stat } from 'node:fs/promises'\nimport { Readable } from 'node:stream'\nimport { relative, resolve, sep } from 'node:path'\nimport { mimeFromExtension } from '../mime'\n\n/**\n * Source files and dotfiles in public/ are never served (public/index.ts is the entry point, not an asset).\n * Tested on every segment of the resolved path, so trailing slashes and dot segments can't hide a name.\n * Names ending in a dot or a space are refused too, since Windows strips those when it opens the file.\n */\nconst HIDDEN_SEGMENT = /^\\.|\\.(ts|tsx|mts|cts)$|[. ]$/i\n\n/**\n * Laravel's server.php for `artisan serve`: a GET or HEAD for a file that exists under public/ is answered\n * with that file, so the built Vite assets (public/build) and other public files work without a web server.\n * Anything else (directories, missing files, other methods) returns undefined and goes to the application.\n */\nexport async function servePublicFile(publicPath: string, request: Request): Promise<Response | undefined> {\n if (request.method !== 'GET' && request.method !== 'HEAD') return undefined\n let pathname: string\n try {\n pathname = decodeURIComponent(new URL(request.url).pathname)\n } catch {\n return undefined\n }\n if (pathname === '/' || pathname.includes('\\0')) return undefined\n const root = resolve(publicPath)\n const file = resolve(root, `.${pathname}`)\n if (!file.startsWith(root + sep)) return undefined\n if (relative(root, file).split(/[\\\\/]/).some((segment) => HIDDEN_SEGMENT.test(segment))) return undefined\n const info = await stat(file).catch(() => undefined)\n if (info === undefined || !info.isFile()) return undefined\n\n const type = mimeFromExtension(file)\n const headers = new Headers({\n 'content-type': type.startsWith('text/') || type === 'application/json' ? `${type}; charset=utf-8` : type,\n 'content-length': String(info.size),\n 'last-modified': info.mtime.toUTCString(),\n })\n // Vite's hashed build output never changes under the same name.\n if (pathname.startsWith('/build/assets/')) headers.set('cache-control', 'public, max-age=31536000, immutable')\n if (request.method === 'HEAD') return new Response(null, { status: 200, headers })\n const body = Readable.toWeb(createReadStream(file)) as unknown as ReadableStream<Uint8Array>\n return new Response(body, { status: 200, headers })\n}\n","import type { Application } from '@orieljs/contracts'\nimport { setClientAddress } from '../clientAddress'\nimport { HttpServerError } from '../errors'\nimport { plainServerError } from '../Kernel'\nimport {\n displayHost,\n exitOnSignals,\n handleSafely,\n terminateRequest,\n type ResolvedServeOptions,\n type RunningServer,\n} from './types'\n\n/** The slice of Bun's API used here (typed locally: there is no Bun lib in the build). */\ninterface BunServer {\n readonly port: number\n stop(closeActiveConnections?: boolean): Promise<void> | void\n requestIP(request: Request): { address: string } | null\n}\ninterface BunRuntime {\n serve(options: {\n port: number\n hostname: string\n fetch(request: Request, server: BunServer): Promise<Response>\n error(error: Error): Response\n }): BunServer\n}\n\nexport function bunRuntime(): BunRuntime | undefined {\n return (globalThis as { Bun?: BunRuntime }).Bun\n}\n\nexport async function serveBun(app: Application, options: ResolvedServeOptions): Promise<RunningServer> {\n const bun = bunRuntime()\n if (bun === undefined) throw new HttpServerError('Bun.serve is not available: the process is not running on Bun.')\n let markClosed: () => void = () => undefined\n const closed = new Promise<void>((resolve) => (markClosed = resolve))\n\n const server = bun.serve({\n port: options.port,\n hostname: options.hostname,\n async fetch(request, current) {\n setClientAddress(request, current.requestIP(request)?.address)\n const response = await handleSafely(app, request, options.publicPath)\n // Bun has no \"response sent\" hook: terminate on the next tick.\n setTimeout(() => void terminateRequest(app, request, response), 0)\n return response\n },\n error(error) {\n console.error(error)\n return plainServerError()\n },\n })\n\n let closing: Promise<void> | undefined\n const close = () =>\n (closing ??= (async () => {\n let timer: ReturnType<typeof setTimeout> | undefined\n const forced = new Promise<void>((resolve) => {\n timer = setTimeout(() => void Promise.resolve(server.stop(true)).then(resolve), options.shutdownTimeout)\n })\n await Promise.race([Promise.resolve(server.stop(false)), forced])\n clearTimeout(timer)\n markClosed()\n })())\n if (options.signals) exitOnSignals(close, closed)\n\n return {\n runtime: 'bun',\n hostname: options.hostname,\n port: server.port,\n url: `http://${displayHost(options.hostname)}:${server.port}`,\n close,\n closed,\n }\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from 'node:http'\nimport type { AddressInfo } from 'node:net'\nimport { Readable } from 'node:stream'\nimport { pipeline } from 'node:stream/promises'\nimport type { ReadableStream as NodeReadableStream } from 'node:stream/web'\nimport type { Application } from '@orieljs/contracts'\nimport { setClientAddress } from '../clientAddress'\nimport {\n displayHost,\n exitOnSignals,\n handleSafely,\n terminateRequest,\n type ResolvedServeOptions,\n type RunningServer,\n} from './types'\n\n/**\n * The request's body as a web stream that pulls from `req`. Readable.toWeb(req) is not used: cancelling it (readBody\n * does that for a declared length over the limit) closes its controller while the socket still emits data, which\n * throws out of the adapter and kills the process. Cancelling this one just stops listening; node drops the unread\n * remainder once the response finishes.\n */\nfunction requestBody(req: IncomingMessage): ReadableStream<Uint8Array> {\n let finished = false\n const detach = () => {\n finished = true\n req.off('data', onData)\n req.off('end', onEnd)\n req.off('error', onError)\n req.off('close', onClose)\n }\n let controller!: ReadableStreamDefaultController<Uint8Array>\n const onData = (chunk: Buffer) => {\n if (finished) return\n controller.enqueue(new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength))\n if ((controller.desiredSize ?? 0) <= 0) req.pause()\n }\n const onEnd = () => {\n if (finished) return\n detach()\n controller.close()\n }\n const onError = (error: Error) => {\n if (finished) return\n detach()\n controller.error(error)\n }\n const onClose = () => {\n if (!finished && !req.complete) onError(new Error('The request was aborted.'))\n }\n return new ReadableStream<Uint8Array>(\n {\n start(c) {\n controller = c\n req.on('data', onData)\n req.on('end', onEnd)\n req.on('error', onError)\n req.on('close', onClose)\n req.pause()\n },\n pull() {\n req.resume()\n },\n cancel() {\n detach()\n },\n },\n { highWaterMark: 0 },\n )\n}\n\n/** node:http IncomingMessage → web Request (the body streams; the signal aborts when the client goes away). */\nexport function toWebRequest(req: IncomingMessage, res: ServerResponse, fallbackHost: string): Request {\n // Concatenate rather than resolve: a target such as '//evil.com/x' must stay on this host, not become evil.com.\n const target = req.url ?? '/'\n const url = new URL(`http://${req.headers.host ?? fallbackHost}${target.startsWith('/') ? target : `/${target}`}`)\n const headers = new Headers()\n for (let i = 0; i < req.rawHeaders.length; i += 2) {\n const name = req.rawHeaders[i]!\n if (!name.startsWith(':')) headers.append(name, req.rawHeaders[i + 1]!)\n }\n const method = (req.method ?? 'GET').toUpperCase()\n const controller = new AbortController()\n res.once('close', () => {\n if (!res.writableFinished) controller.abort()\n })\n const init: RequestInit & { duplex?: 'half' } = { method, headers, signal: controller.signal }\n if (method !== 'GET' && method !== 'HEAD') {\n init.body = requestBody(req)\n init.duplex = 'half'\n }\n return new Request(url, init)\n}\n\n/** Web Response → ServerResponse, streaming the body with backpressure. Several Set-Cookie headers stay separate. */\nexport async function writeResponse(res: ServerResponse, response: Response): Promise<void> {\n res.statusCode = response.status\n if (response.statusText !== '') res.statusMessage = response.statusText\n response.headers.forEach((value, name) => {\n if (name !== 'set-cookie') res.setHeader(name, value)\n })\n const cookies = response.headers.getSetCookie()\n if (cookies.length > 0) res.setHeader('set-cookie', cookies)\n if (response.body === null) {\n res.end()\n return\n }\n await pipeline(Readable.fromWeb(response.body as unknown as NodeReadableStream<Uint8Array>), res)\n}\n\nexport async function serveNode(app: Application, options: ResolvedServeOptions): Promise<RunningServer> {\n const fallbackHost = `${displayHost(options.hostname)}:${options.port}`\n const server = createServer((req, res) => {\n void (async () => {\n let request: Request\n try {\n request = toWebRequest(req, res, fallbackHost)\n } catch {\n res.statusCode = 400\n res.end('Bad Request')\n return\n }\n setClientAddress(request, req.socket.remoteAddress)\n const response = await handleSafely(app, request, options.publicPath)\n try {\n await writeResponse(res, response)\n } catch {\n // The client went away mid-response.\n res.destroy()\n }\n await terminateRequest(app, request, response)\n })()\n })\n\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject)\n server.listen(options.port, options.hostname, () => {\n server.off('error', reject)\n resolve()\n })\n })\n\n const address = server.address() as AddressInfo\n const closed = new Promise<void>((resolve) => server.once('close', () => resolve()))\n let closing: Promise<void> | undefined\n const close = () =>\n (closing ??= (async () => {\n const done = new Promise<void>((resolve) => server.close(() => resolve()))\n // Keep-alive connections become idle once their request finishes; close them as that happens.\n server.closeIdleConnections()\n const idle = setInterval(() => server.closeIdleConnections(), 50)\n const force = setTimeout(() => server.closeAllConnections(), options.shutdownTimeout)\n await done\n clearInterval(idle)\n clearTimeout(force)\n })())\n if (options.signals) exitOnSignals(close, closed)\n\n return {\n runtime: 'node',\n hostname: options.hostname,\n port: address.port,\n url: `http://${displayHost(options.hostname)}:${address.port}`,\n close,\n closed,\n }\n}\n","import type { Application } from '@orieljs/contracts'\nimport { bunRuntime, serveBun } from './bun'\nimport { serveNode } from './node'\nimport type { ResolvedServeOptions, Runtime, RunningServer, ServeOptions } from './types'\n\nexport function detectRuntime(): Runtime {\n return bunRuntime() !== undefined ? 'bun' : 'node'\n}\n\n/** Boots the app and serves it with node:http or Bun.serve (public/index.ts: `await serve(app)`). */\nexport async function serve(app: Application, options: ServeOptions = {}): Promise<RunningServer> {\n const resolved: ResolvedServeOptions = {\n port: options.port ?? Number(process.env.PORT ?? process.env.SERVER_PORT ?? 8000),\n hostname: options.hostname ?? '127.0.0.1',\n signals: options.signals ?? true,\n shutdownTimeout: options.shutdownTimeout ?? 10_000,\n ...(options.publicPath !== false && { publicPath: options.publicPath ?? app.publicPath() }),\n }\n await app.boot()\n const runtime = options.runtime ?? detectRuntime()\n const server = runtime === 'bun' ? await serveBun(app, resolved) : await serveNode(app, resolved)\n const onListen = options.onListen ?? ((running: RunningServer) => console.log(`Server running on [${running.url}].`))\n onListen(server)\n return server\n}\n","import { existsSync } from 'node:fs'\nimport { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { dirname } from 'node:path'\nimport {\n Router,\n type Application,\n type CommandContext,\n type ConsoleKernel,\n type MiddlewareReference,\n type Route,\n} from '@orieljs/contracts'\nimport { serve } from './server/serve'\nimport type { RunningServer, ServeOptions } from './server/types'\n\ninterface Io {\n option(name: string): string | undefined\n flag(name: string): boolean\n info(message: string): void\n line(message: string): void\n warn(message: string): void\n error(message: string): void\n}\n\n/**\n * The closure command's `this` (the contract's CommandContext), with the options normalised: a value option that\n * is absent (undefined, null, false or '') reads as undefined, and a flag is true only when set.\n */\nfunction io(command: CommandContext): Io {\n return {\n option: (name) => {\n const value: unknown = command.option(name)\n return value === undefined || value === null || value === false || value === '' ? undefined : String(value)\n },\n flag: (name) => {\n const value: unknown = command.option(name)\n return value === true || value === 'true' || value === '1'\n },\n info: (message) => command.info(message),\n line: (message) => command.line(message),\n warn: (message) => command.warn(message),\n error: (message) => command.error(message),\n }\n}\n\nexport interface RouteListRow {\n /** 'GET|HEAD' */\n readonly method: string\n readonly uri: string\n readonly name: string | null\n /** 'PostController@show' or 'Closure' */\n readonly action: string\n readonly middleware: string[]\n}\n\ninterface ListableRoute extends Route {\n getActionName?(): string\n gatherMiddleware?(): MiddlewareReference[]\n}\n\nconst middlewareName = (reference: MiddlewareReference): string => (typeof reference === 'string' ? reference : reference.name)\n\n/** One row per route, sorted by URI (Laravel's default --sort=uri; ties keep registration order). */\nexport function routeListRows(routes: readonly Route[]): RouteListRow[] {\n const rows = routes.map((route) => {\n const listable = route as ListableRoute\n return {\n method: route.methods.join('|'),\n uri: route.uri,\n name: route.getName() ?? null,\n action: typeof listable.getActionName === 'function' ? listable.getActionName() : 'Closure',\n middleware: typeof listable.gatherMiddleware === 'function' ? listable.gatherMiddleware().map(middlewareName) : [],\n }\n })\n return rows.sort((a, b) => (a.uri < b.uri ? -1 : a.uri > b.uri ? 1 : 0))\n}\n\nexport interface RouteListFilters {\n method?: string\n name?: string\n path?: string\n /** Comma-separated. */\n exceptPath?: string\n}\n\n/** Laravel's RouteListCommand::filterRoute: substring matches, method compared uppercased. */\nexport function filterRouteList(rows: readonly RouteListRow[], filters: RouteListFilters): RouteListRow[] {\n const excluded = (filters.exceptPath ?? '').split(',').filter((path) => path !== '')\n return rows.filter((row) => {\n if (filters.name !== undefined && !(row.name ?? '').includes(filters.name)) return false\n if (filters.path !== undefined && !row.uri.includes(filters.path)) return false\n if (filters.method !== undefined && !row.method.includes(filters.method.toUpperCase())) return false\n return !excluded.some((path) => row.uri.includes(path))\n })\n}\n\n/**\n * Laravel's route:list layout: the method column padded, the URI, a dotted leader, then `name › action`\n * (closures show only the name), and a right-aligned \"Showing [n] routes\" footer.\n */\nexport function formatRouteList(rows: readonly RouteListRow[], width: number): string[] {\n const methodWidth = Math.max(...rows.map((row) => row.method.length))\n const lines = rows.map((row) => {\n const spaces = ' '.repeat(Math.max(methodWidth + 6 - row.method.length, 0))\n const action = row.action === 'Closure' ? (row.name ?? '') : row.name === null ? row.action : `${row.name} › ${row.action}`\n const used = row.method.length + spaces.length + row.uri.length + action.length + 6 + (action === '' ? 0 : 1)\n const dots = '.'.repeat(Math.max(width - used, 0))\n return ` ${row.method} ${spaces}${row.uri}${dots === '' ? '' : ` ${dots}`}${action === '' ? '' : ` ${action}`}`\n })\n const count = `Showing [${rows.length}] ${rows.length === 1 ? 'route' : 'routes'}`\n return [...lines, '', `${' '.repeat(Math.max(width - count.length - 2, 0))}${count}`]\n}\n\n/** The routes/api.ts that install:api writes (Laravel's api.stub, with the token guard). */\nexport const API_ROUTES_STUB = `import { request, Route } from '@orieljs/framework'\n\nRoute.get('/user', () => request().user()).middleware('auth:token')\n`\n\n/**\n * Adds `api: 'routes/api.ts'` to withRouting() in bootstrap/app.ts: uncomments a commented `// api:` entry,\n * else inserts it after the `web:` entry, else at the start of withRouting({, else adds a withRouting() call\n * before create(). Returns the source unchanged when api is already there, and undefined when it can't tell where.\n * (Function replacers, so a `$` in the file is never read as a replacement pattern.)\n */\nexport function addApiRouting(source: string): string | undefined {\n const code = source.replace(/^[ \\t]*\\/\\/.*$/gm, '')\n if (/withRouting\\(\\s*\\{[^}]*\\bapi\\s*:/.test(code)) return source\n const commented = /^([ \\t]*)\\/\\/\\s*(api:\\s*['\"`][^'\"`\\n]*['\"`],?)[ \\t]*$/m.exec(source)\n if (commented !== null) return source.replace(commented[0], () => `${commented[1]}${commented[2]}`)\n const web = /^([ \\t]*)web:\\s*(['\"`])[^'\"`\\n]*\\2[ \\t]*,?[ \\t]*$/m.exec(source)\n if (web !== null) {\n const line = web[0].trimEnd()\n return source.replace(web[0], () => `${line.endsWith(',') ? line : `${line},`}\\n${web[1]}api: 'routes/api.ts',`)\n }\n const inline = /withRouting\\(\\s*\\{/.exec(source)\n if (inline !== null) return source.replace(inline[0], () => `${inline[0]} api: 'routes/api.ts',`)\n const create = /^([ \\t]*)\\.create\\(\\)/m.exec(source)\n if (create !== null) return source.replace(create[0], () => `${create[1]}.withRouting({ api: 'routes/api.ts' })\\n${create[0]}`)\n return undefined\n}\n\nexport interface HttpCommandOptions {\n /** Replaces serve() (tests). */\n serve?: (app: Application, options: ServeOptions) => Promise<RunningServer>\n /** The terminal width for route:list. Default: process.stdout.columns, else 120. */\n terminalWidth?: () => number\n}\n\n/** Registers `serve`, `route:list` and `install:api` as closure commands (PC1). */\nexport function registerHttpCommands(kernel: ConsoleKernel, app: Application, options: HttpCommandOptions = {}): void {\n const serveApp = options.serve ?? serve\n const terminalWidth = options.terminalWidth ?? (() => process.stdout.columns ?? 120)\n\n kernel\n .command(\n 'serve {--host=127.0.0.1 : The host address to serve the application on} {--port= : The port to serve the application on}',\n async function (this: CommandContext) {\n const out = io(this)\n const port = out.option('port')\n if (port !== undefined && !/^\\d+$/.test(port)) {\n out.error('The --port option must be a number.')\n return 1\n }\n const server = await serveApp(app, {\n hostname: out.option('host') ?? '127.0.0.1',\n ...(port !== undefined && { port: Number(port) }),\n onListen: (running) => {\n out.info(`Server running on [${running.url}].`)\n out.line('Press Ctrl+C to stop the server')\n },\n })\n await server.closed\n return 0\n },\n )\n .purpose('Serve the application on the Oriel development server')\n\n kernel\n .command(\n 'route:list {--method= : Filter the routes by method} {--name= : Filter the routes by name} ' +\n '{--path= : Only show routes matching the given path pattern} ' +\n '{--except-path= : Do not display the routes matching the given path pattern} ' +\n '{--reverse : Reverse the ordering of the routes} {--json : Output the route list as JSON}',\n function (this: CommandContext) {\n const out = io(this)\n if (!app.bound(Router)) {\n out.error('The router is not available. Is the Routing service provider registered?')\n return 1\n }\n const all = routeListRows(app.make(Router).getRoutes())\n if (all.length === 0) {\n out.error(\"Your application doesn't have any routes.\")\n return 0\n }\n const rows = filterRouteList(all, {\n ...(out.option('method') !== undefined && { method: out.option('method') }),\n ...(out.option('name') !== undefined && { name: out.option('name') }),\n ...(out.option('path') !== undefined && { path: out.option('path') }),\n ...(out.option('except-path') !== undefined && { exceptPath: out.option('except-path') }),\n })\n if (rows.length === 0) {\n out.error(\"Your application doesn't have any routes matching the given criteria.\")\n return 0\n }\n if (out.flag('reverse')) rows.reverse()\n if (out.flag('json')) {\n out.line(JSON.stringify(rows))\n return 0\n }\n for (const line of formatRouteList(rows, terminalWidth())) out.line(line)\n return 0\n },\n )\n .purpose('List all registered routes')\n\n kernel\n .command('install:api {--force : Overwrite any existing API routes file}', async function (this: CommandContext) {\n const out = io(this)\n const routesFile = app.basePath('routes/api.ts')\n if (existsSync(routesFile) && !out.flag('force')) {\n out.error('API routes file already exists.')\n } else {\n await mkdir(dirname(routesFile), { recursive: true })\n await writeFile(routesFile, API_ROUTES_STUB)\n out.info('Published API routes file.')\n }\n\n const bootstrapFile = app.bootstrapPath('app.ts')\n const source = existsSync(bootstrapFile) ? await readFile(bootstrapFile, 'utf8') : undefined\n const updated = source === undefined ? undefined : addApiRouting(source)\n if (updated === undefined) {\n out.warn(\n 'Unable to automatically add API route definition to bootstrap file. ' +\n \"Add api: 'routes/api.ts' to withRouting() in bootstrap/app.ts.\",\n )\n } else if (updated !== source) {\n await writeFile(bootstrapFile, updated)\n }\n\n out.info('API scaffolding installed. Run [oriel migrate] to create the personal access tokens table.')\n return 0\n })\n .purpose('Create an API routes file and prepare the application for API authentication')\n}\n","import { ConsoleKernel, ExceptionHandler, HttpKernel, Redirector, ResponseFactory, Router } from '@orieljs/contracts'\nimport { ServiceProvider } from '@orieljs/support'\nimport { registerHttpCommands } from './commands'\nimport { ErrorHandler } from './ErrorHandler'\nimport { applyExceptionCallbacks } from './ExceptionsConfiguration'\nimport { HttpRedirector } from './HttpRedirector'\nimport { HttpResponseFactory } from './HttpResponseFactory'\nimport { Kernel } from './Kernel'\nimport { applyMiddlewareCallbacks } from './MiddlewareConfiguration'\n\n/**\n * Binds the HTTP kernel (replacing any kernel bound before, such as Foundation's ClosureKernel), the exception\n * handler, the response factory and the redirector, and merges the `http` config defaults.\n *\n * The HttpRequest is deliberately NOT bound on the application: the kernel creates one per request and puts it in\n * the request scope with scope.instance(). A root `scoped()` binding would make bound(HttpRequest) true everywhere,\n * and that check is how the URL generator, the redirects and the helpers know they are inside a request.\n */\nexport class HttpServiceProvider extends ServiceProvider {\n override register(): void {\n this.mergeConfigFrom(\n {\n trusted_proxies: [],\n max_body_size: 8 * 1024 * 1024,\n max_json_depth: 512,\n csrf_except: [],\n redirect_guests_to: undefined,\n redirect_users_to: undefined,\n },\n 'http',\n )\n this.app.singleton(HttpKernel, () => new Kernel(this.app))\n this.app.singleton(ExceptionHandler, () => {\n const handler = new ErrorHandler(this.app)\n applyExceptionCallbacks(this.app, handler)\n return handler\n })\n this.app.singleton(ResponseFactory, () => new HttpResponseFactory())\n this.app.singleton(Redirector, () => new HttpRedirector())\n }\n\n override boot(): void {\n // After every provider's boot(), so web({ remove }) and alias() overrides see the components' defaults.\n this.app.booted(() => {\n const kernel = this.app.make(HttpKernel)\n if (kernel instanceof Kernel && this.app.bound(Router)) applyMiddlewareCallbacks(this.app, kernel)\n })\n if (this.app.bound(ConsoleKernel)) registerHttpCommands(this.app.make(ConsoleKernel), this.app)\n }\n}\n"],"mappings":"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","names":["response","url","request","request","inject","inject","Session","currentContainer","inject","Str","Str","inject","Session","currentContainer","HttpRequest","UrlGenerator","inject","inject","HttpRequest","UrlGenerator","inject","inject","CurrentRoute","HttpRequest","currentContainer","request","request","currentContainer","request","response","HttpRequest","route","CurrentRoute","ConfigRepository","Router","url","ConfigRepository","Redirector","UrlGenerator","ViewFactory","currentContainer","url","request","response","Redirector","redirect","UrlGenerator","url","ViewFactory","ConfigRepository","currentContainer","createReadStream","stat","Readable","request","stat","Readable","createReadStream","request","response","resolve","request","response","Readable","url","response","Readable","request","resolve","readFile","Router","route","Router","readFile","ExceptionHandler","HttpKernel","Redirector","ResponseFactory","Router","HttpKernel","ExceptionHandler","ResponseFactory","Redirector","Router"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orieljs/http",
3
- "version": "0.1.0-alpha.3",
3
+ "version": "0.1.0-alpha.5",
4
4
  "description": "The Oriel Http 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"