@orieljs/framework 0.1.0-alpha.2 → 0.1.0-alpha.4

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.js CHANGED
@@ -22,28 +22,114 @@ import {
22
22
  renderToString,
23
23
  styleString,
24
24
  view
25
- } from "./chunk-TIE5OAMF.js";
25
+ } from "./chunk-3DETYZMZ.js";
26
26
  import {
27
+ API_ROUTES_STUB,
27
28
  Application as Application2,
28
29
  ApplicationBuilder,
29
30
  BusFake,
30
31
  ClosureKernel,
32
+ Component,
33
+ Computed,
34
+ ConvertEmptyStringsToNull,
35
+ CorruptComponentPayloadError,
36
+ ErrorBag,
37
+ ErrorHandler,
31
38
  EventFake,
39
+ ExceptionsConfiguration,
40
+ FormUploadedFile,
41
+ HttpException,
42
+ HttpRedirectResponse,
43
+ HttpRedirector,
44
+ HttpResponseException,
45
+ HttpResponseFactory,
46
+ HttpServerError,
47
+ HttpServiceProvider,
48
+ IncomingRequest,
49
+ InvalidLiveRequestError,
50
+ Kernel,
51
+ Live,
52
+ LiveComponentManager,
53
+ LiveComponentNotFoundError,
54
+ LiveError,
55
+ LiveServiceProvider,
56
+ Locked,
32
57
  MailFake,
58
+ MethodNotCallableError,
59
+ MiddlewareConfiguration,
33
60
  NotificationFake,
61
+ On,
62
+ PERSISTENT_MIDDLEWARE,
63
+ PendingEvent,
64
+ PropertyNotUpdatableError,
34
65
  ProviderBootError,
35
66
  ProviderRegisterError,
36
67
  QueueFake,
37
68
  Repository,
38
69
  StorageFake,
70
+ TestRequestScope,
71
+ Testable,
72
+ TrimStrings,
73
+ UPDATE_URI,
39
74
  Vite,
40
75
  ViteError,
41
76
  ViteHtml,
77
+ abort,
78
+ abortIf,
79
+ abortUnless,
80
+ addApiRouting,
81
+ applyExceptionCallbacks,
82
+ applyMiddlewareCallbacks,
83
+ back,
84
+ bunRuntime,
85
+ clientAddress,
86
+ componentName,
87
+ contentDisposition,
88
+ currentRequest,
42
89
  currentVite,
90
+ debugPage,
91
+ detectRuntime,
43
92
  env,
93
+ escapeHtml,
94
+ exceedsJsonDepth,
95
+ extensionFromMime,
96
+ filterRouteList,
97
+ formatRouteList,
98
+ fromEntries,
99
+ ipMatches,
100
+ isBlank,
101
+ live,
102
+ mergeRecursive,
103
+ minimalPage,
104
+ normalizeLists,
105
+ optionalCookieJar,
106
+ optionalSession,
107
+ parseBracketKey,
108
+ persistentMiddleware,
109
+ redirect,
110
+ registerHttpCommands,
111
+ request,
112
+ requestScope,
113
+ response,
114
+ route,
115
+ routeListRows,
116
+ sanitize,
117
+ serve,
118
+ serveBun,
119
+ serveNode,
120
+ servePublicFile,
121
+ setClientAddress,
122
+ stackFrames,
123
+ statusFor,
124
+ statusText,
125
+ summarizeValidation,
126
+ toWebRequest,
127
+ transformLeaves,
128
+ url,
44
129
  vite,
45
- viteReactRefresh
46
- } from "./chunk-UPZAML2Q.js";
130
+ viteReactRefresh,
131
+ writeResponse
132
+ } from "./chunk-SBZQ6L3Z.js";
47
133
  import {
48
134
  Arr,
49
135
  BindingResolutionError,
@@ -55,6 +141,7 @@ import {
55
141
  LazyCollection,
56
142
  ServiceProvider,
57
143
  Str,
144
+ __,
58
145
  app,
59
146
  collect,
60
147
  config,
@@ -65,7 +152,7 @@ import {
65
152
  retry,
66
153
  tap,
67
154
  value
68
- } from "./chunk-IRHK7GH7.js";
155
+ } from "./chunk-DCI2T7WJ.js";
69
156
  import {
70
157
  Application,
71
158
  AuthFactory,
@@ -81,25 +168,22 @@ import {
81
168
  DatabaseManager,
82
169
  Encrypter,
83
170
  EventDispatcher,
84
- ExceptionCallbacks,
85
171
  ExceptionHandler,
86
172
  FailedJobProvider,
87
173
  FilesystemManager,
88
174
  Gate,
89
175
  Hasher,
90
- HttpKernel,
91
176
  HttpRequest,
92
177
  InertiaFactory,
93
178
  InertiaSsrGateway,
94
179
  LogManager,
95
180
  MailManager,
96
- MiddlewareCallbacks,
97
181
  NotificationDispatcher,
98
182
  PasswordBroker,
99
183
  PipelineFactory,
100
184
  QueueManager,
185
+ RateLimiter,
101
186
  Redirector,
102
- ResponseFactory,
103
187
  RouteModelResolver,
104
188
  Router,
105
189
  RoutingPaths,
@@ -109,12 +193,14 @@ import {
109
193
  ValidationFactory,
110
194
  ViewFactory,
111
195
  token
112
- } from "./chunk-3ZRPBRAE.js";
196
+ } from "./chunk-WSGWYXAO.js";
113
197
 
114
198
  // ../Auth/dist/index.js
115
- import { timingSafeEqual } from "crypto";
116
199
  import { createHash } from "crypto";
117
200
  import { createHash as createHash2 } from "crypto";
201
+ import { timingSafeEqual } from "crypto";
202
+ import { createHash as createHash3 } from "crypto";
203
+ import { createHash as createHash4 } from "crypto";
118
204
  import { createHmac } from "crypto";
119
205
  import { readdir } from "fs/promises";
120
206
  import { join } from "path";
@@ -194,6 +280,24 @@ var PasswordReset = class {
194
280
  }
195
281
  user;
196
282
  };
283
+ var Registered = class {
284
+ constructor(user) {
285
+ this.user = user;
286
+ }
287
+ user;
288
+ };
289
+ var Verified = class {
290
+ constructor(user) {
291
+ this.user = user;
292
+ }
293
+ user;
294
+ };
295
+ var Lockout = class {
296
+ constructor(request2) {
297
+ this.request = request2;
298
+ }
299
+ request;
300
+ };
197
301
  var createUrlCallback;
198
302
  var toMailCallback;
199
303
  var ResetPassword = class {
@@ -242,6 +346,83 @@ var ResetPassword = class {
242
346
  return `/reset-password/${encodeURIComponent(this.token)}?email=${encodeURIComponent(email)}`;
243
347
  }
244
348
  };
349
+ var createUrlCallback2;
350
+ var toMailCallback2;
351
+ var VerifyEmail = class {
352
+ /** Build the verification URL yourself (e.g. for a SPA front end). */
353
+ static createUrlUsing(callback) {
354
+ createUrlCallback2 = callback;
355
+ }
356
+ /** Build the mail yourself (e.g. a MailMessage from the Notifications component). */
357
+ static toMailUsing(callback) {
358
+ toMailCallback2 = callback;
359
+ }
360
+ via() {
361
+ return ["mail"];
362
+ }
363
+ toMail(notifiable) {
364
+ const user = notifiable;
365
+ const url2 = this.verificationUrl(user);
366
+ if (toMailCallback2 !== void 0) return toMailCallback2(user, url2);
367
+ const mail = {
368
+ subject: "Verify Email Address",
369
+ lines: ["Please click the button below to verify your email address."],
370
+ actionText: "Verify Email Address",
371
+ actionUrl: url2,
372
+ outroLines: ["If you did not create an account, no further action is required."]
373
+ };
374
+ return mail;
375
+ }
376
+ verificationUrl(notifiable) {
377
+ if (createUrlCallback2 !== void 0) return createUrlCallback2(notifiable);
378
+ const container = currentContainer();
379
+ if (container === void 0 || !container.bound(UrlGenerator)) {
380
+ throw new Error("VerifyEmail needs the UrlGenerator (Routing) to sign the verification link.");
381
+ }
382
+ const config2 = container.bound(ConfigRepository) ? container.make(ConfigRepository) : void 0;
383
+ const minutes = Number(config2?.get("auth.verification.expire", 60) ?? 60);
384
+ const id = typeof notifiable.getKey === "function" ? notifiable.getKey() : notifiable.getAuthIdentifier?.();
385
+ const hash2 = createHash("sha1").update(notifiable.getEmailForVerification()).digest("hex");
386
+ return container.make(UrlGenerator).temporarySignedRoute("verification.verify", minutes * 60, { id, hash: hash2 });
387
+ }
388
+ };
389
+ var SendEmailVerificationNotification = class {
390
+ async handle(event2) {
391
+ const user = event2.user;
392
+ if (typeof user.hasVerifiedEmail !== "function" || typeof user.sendEmailVerificationNotification !== "function") return;
393
+ if (!user.hasVerifiedEmail()) await user.sendEmailVerificationNotification();
394
+ }
395
+ };
396
+ function equals(known, user) {
397
+ const a = Buffer.from(known);
398
+ const b = Buffer.from(user);
399
+ return a.length === b.length && timingSafeEqual(a, b);
400
+ }
401
+ var EmailVerificationRequest = class {
402
+ static async validate() {
403
+ if (!await new this().authorize()) throw new AuthorizationError();
404
+ return {};
405
+ }
406
+ authorize() {
407
+ const request2 = inject(HttpRequest);
408
+ const user = request2.user();
409
+ if (user === void 0 || user === null) return false;
410
+ const key = typeof user.getKey === "function" ? user.getKey() : user.getAuthIdentifier();
411
+ const hash2 = createHash2("sha1").update(user.getEmailForVerification()).digest("hex");
412
+ return equals(String(key), String(request2.route("id") ?? "")) && equals(hash2, String(request2.route("hash") ?? ""));
413
+ }
414
+ rules() {
415
+ return {};
416
+ }
417
+ /** Marks the signed-in user's email as verified and fires Verified, unless it already was. */
418
+ async fulfill() {
419
+ const user = inject(HttpRequest).user();
420
+ if (user === void 0 || user === null || user.hasVerifiedEmail()) return;
421
+ await user.markEmailAsVerified();
422
+ const container = currentContainer();
423
+ if (container?.bound(EventDispatcher)) await container.make(EventDispatcher).dispatch(new Verified(user));
424
+ }
425
+ };
245
426
  var verificationSender;
246
427
  function sendEmailVerificationUsing(callback) {
247
428
  verificationSender = callback;
@@ -297,19 +478,13 @@ function AuthenticatableModel(Base) {
297
478
  getEmailForVerification() {
298
479
  return String(this.getAttribute("email") ?? "");
299
480
  }
481
+ /** Sends the VerifyEmail notification (a signed link), or what sendEmailVerificationUsing() configured. */
300
482
  async sendEmailVerificationNotification() {
301
- if (verificationSender === void 0) {
302
- throw new Error("No email verification sender is configured. Call sendEmailVerificationUsing() in a service provider.");
303
- }
304
- await verificationSender(this);
483
+ if (verificationSender !== void 0) return verificationSender(this);
484
+ return sendNotification(this, new VerifyEmail());
305
485
  }
306
486
  };
307
487
  }
308
- function equals(known, user) {
309
- const a = Buffer.from(known);
310
- const b = Buffer.from(user);
311
- return a.length === b.length && timingSafeEqual(a, b);
312
- }
313
488
  var EloquentUserProvider = class {
314
489
  constructor(hasher, model) {
315
490
  this.hasher = hasher;
@@ -365,7 +540,7 @@ var EloquentUserProvider = class {
365
540
  return this.model;
366
541
  }
367
542
  };
368
- var GUARD_HASH = createHash("sha1").update("Oriel\\Auth\\SessionGuard").digest("hex");
543
+ var GUARD_HASH = createHash3("sha1").update("Oriel\\Auth\\SessionGuard").digest("hex");
369
544
  var SessionGuard = class {
370
545
  constructor(name, provider, container, options = {}) {
371
546
  this.name = name;
@@ -512,8 +687,8 @@ var SessionGuard = class {
512
687
  const session2 = this.#session();
513
688
  if (session2 === void 0) return;
514
689
  session2.put(this.getName(), id);
515
- const store2 = session2;
516
- if (typeof store2.migrate === "function") await store2.migrate(true);
690
+ const store = session2;
691
+ if (typeof store.migrate === "function") await store.migrate(true);
517
692
  else await session2.regenerate(true);
518
693
  }
519
694
  async #cycleRememberToken(user) {
@@ -560,7 +735,7 @@ function parseStoredDate(value2) {
560
735
  }
561
736
  return Number.isNaN(date.getTime()) ? void 0 : date;
562
737
  }
563
- var sha256 = (value2) => createHash2("sha256").update(value2).digest("hex");
738
+ var sha256 = (value2) => createHash4("sha256").update(value2).digest("hex");
564
739
  function tokenableType(user) {
565
740
  const container = currentContainer();
566
741
  const cls = user.constructor;
@@ -628,7 +803,7 @@ var TokenRepository = class {
628
803
  clock;
629
804
  async create(user, name, abilities = ["*"], expiresAt) {
630
805
  const secret = Str.random(40);
631
- const now4 = this.clock();
806
+ const now5 = this.clock();
632
807
  const attributes = {
633
808
  tokenable_type: tokenableType(user),
634
809
  tokenable_id: user.getAuthIdentifier(),
@@ -637,8 +812,8 @@ var TokenRepository = class {
637
812
  abilities: JSON.stringify(abilities),
638
813
  last_used_at: null,
639
814
  expires_at: expiresAt ?? null,
640
- created_at: now4,
641
- updated_at: now4
815
+ created_at: now5,
816
+ updated_at: now5
642
817
  };
643
818
  const id = await this.#query().insertGetId(attributes);
644
819
  return { accessToken: new PersonalAccessToken({ id, ...attributes }, this), plainTextToken: `${id}|${secret}` };
@@ -659,9 +834,9 @@ var TokenRepository = class {
659
834
  }
660
835
  /** Records the token's use (last_used_at). */
661
836
  async touch(token2) {
662
- const now4 = this.clock();
663
- token2.attributes.last_used_at = now4;
664
- await this.#query().where("id", token2.id).update({ last_used_at: now4 });
837
+ const now5 = this.clock();
838
+ token2.attributes.last_used_at = now5;
839
+ await this.#query().where("id", token2.id).update({ last_used_at: now5 });
665
840
  }
666
841
  async tokensFor(user) {
667
842
  const rows = await this.#query().where("tokenable_type", tokenableType(user)).where("tokenable_id", user.getAuthIdentifier()).get();
@@ -771,15 +946,15 @@ var TokenGuard = class {
771
946
  return { user, token: token2 };
772
947
  }
773
948
  #isValid(token2) {
774
- const now4 = (this.options.clock ?? (() => /* @__PURE__ */ new Date()))().getTime();
949
+ const now5 = (this.options.clock ?? (() => /* @__PURE__ */ new Date()))().getTime();
775
950
  const expiresAt = token2.expiresAt;
776
951
  const rawExpiresAt = token2.attributes.expires_at;
777
952
  if (rawExpiresAt !== null && rawExpiresAt !== void 0 && expiresAt === void 0) return false;
778
- if (expiresAt !== void 0 && expiresAt.getTime() <= now4) return false;
953
+ if (expiresAt !== void 0 && expiresAt.getTime() <= now5) return false;
779
954
  const expiration = this.options.expiration;
780
955
  if (typeof expiration === "number") {
781
956
  const createdAt = token2.createdAt;
782
- if (createdAt === void 0 || createdAt.getTime() + expiration * 6e4 <= now4) return false;
957
+ if (createdAt === void 0 || createdAt.getTime() + expiration * 6e4 <= now5) return false;
783
958
  }
784
959
  return true;
785
960
  }
@@ -1477,6 +1652,7 @@ var AuthServiceProvider = class extends ServiceProvider {
1477
1652
  if (this.app.bound(Router)) {
1478
1653
  this.app.make(Router).aliasMiddleware("auth", Authenticate).aliasMiddleware("guest", RedirectIfAuthenticated).aliasMiddleware("can", Authorize).aliasMiddleware("verified", EnsureEmailIsVerified);
1479
1654
  }
1655
+ if (this.app.bound(EventDispatcher)) this.app.make(EventDispatcher).listen(Registered, SendEmailVerificationNotification);
1480
1656
  await discoverPolicies(this.app.appPath("Policies"), this.app.make(Gate));
1481
1657
  }
1482
1658
  };
@@ -1549,11 +1725,11 @@ var UniqueLock = class _UniqueLock {
1549
1725
  async acquire(job) {
1550
1726
  const members = job;
1551
1727
  const uniqueFor = typeof members.uniqueFor === "function" ? members.uniqueFor.call(job) : members.uniqueFor ?? 0;
1552
- const store2 = members.uniqueVia?.call(job);
1728
+ const store = members.uniqueVia?.call(job);
1553
1729
  const key = _UniqueLock.key(job);
1554
- if (!await this.store(store2).lock(key, uniqueFor > 0 ? uniqueFor : void 0).get()) return void 0;
1730
+ if (!await this.store(store).lock(key, uniqueFor > 0 ? uniqueFor : void 0).get()) return void 0;
1555
1731
  const spec = { key, untilProcessing: members.uniqueUntilProcessing === true };
1556
- if (store2 !== void 0) spec.store = store2;
1732
+ if (store !== void 0) spec.store = store;
1557
1733
  return spec;
1558
1734
  }
1559
1735
  async release(spec) {
@@ -1899,7 +2075,7 @@ var BusServiceProvider = class extends ServiceProvider {
1899
2075
 
1900
2076
  // ../Cache/dist/index.js
1901
2077
  import { setTimeout as sleep } from "timers/promises";
1902
- import { createHash as createHash3 } from "crypto";
2078
+ import { createHash as createHash5 } from "crypto";
1903
2079
  import { link, mkdir, readFile, rename, rm, stat, writeFile } from "fs/promises";
1904
2080
  import { dirname, join as join2 } from "path";
1905
2081
  import { setTimeout as sleep2 } from "timers/promises";
@@ -1920,8 +2096,8 @@ var TagsNotSupportedError = class extends Error {
1920
2096
  kind = "Server";
1921
2097
  status = 500;
1922
2098
  name = "TagsNotSupportedError";
1923
- constructor(store2) {
1924
- super(`The [${store2}] cache store does not support tags. Only the redis store does.`);
2099
+ constructor(store) {
2100
+ super(`The [${store}] cache store does not support tags. Only the redis store does.`);
1925
2101
  }
1926
2102
  };
1927
2103
  var UnknownCacheStoreError = class extends Error {
@@ -1955,8 +2131,8 @@ function roundTrip(value2) {
1955
2131
  return JSON.parse(serialize(value2));
1956
2132
  }
1957
2133
  var GenericLock = class {
1958
- constructor(store2, name, seconds, owner, pollMs = 50) {
1959
- this.store = store2;
2134
+ constructor(store, name, seconds, owner, pollMs = 50) {
2135
+ this.store = store;
1960
2136
  this.name = name;
1961
2137
  this.seconds = seconds;
1962
2138
  this.pollMs = pollMs;
@@ -2003,10 +2179,10 @@ var GenericLock = class {
2003
2179
  await this.store.forget(this.name);
2004
2180
  }
2005
2181
  };
2006
- var defaultLockFactory = (store2, name, seconds, owner) => new GenericLock(store2, name, seconds, owner);
2182
+ var defaultLockFactory = (store, name, seconds, owner) => new GenericLock(store, name, seconds, owner);
2007
2183
  var Repository2 = class {
2008
- constructor(store2, lockFactory = defaultLockFactory) {
2009
- this.store = store2;
2184
+ constructor(store, lockFactory = defaultLockFactory) {
2185
+ this.store = store;
2010
2186
  this.lockFactory = lockFactory;
2011
2187
  }
2012
2188
  store;
@@ -2176,7 +2352,7 @@ var FileStore = class {
2176
2352
  directory;
2177
2353
  keyPrefix;
2178
2354
  path(key) {
2179
- const hash2 = createHash3("sha1").update(this.keyPrefix + key).digest("hex");
2355
+ const hash2 = createHash5("sha1").update(this.keyPrefix + key).digest("hex");
2180
2356
  return join2(this.directory, hash2.slice(0, 2), hash2.slice(2, 4), hash2);
2181
2357
  }
2182
2358
  tempPath(path) {
@@ -2347,8 +2523,8 @@ var FileStore = class {
2347
2523
  };
2348
2524
  async function insertOrTakeOver(connection, table, row) {
2349
2525
  if (await connection.table(table).insertOrIgnore(row) === 1) return true;
2350
- const now4 = Math.floor(Date.now() / 1e3);
2351
- return await connection.table(table).where("key", row.key).where("expiration", "<=", now4).update(row) > 0;
2526
+ const now5 = Math.floor(Date.now() / 1e3);
2527
+ return await connection.table(table).where("key", row.key).where("expiration", "<=", now5).update(row) > 0;
2352
2528
  }
2353
2529
  var FOREVER_SECONDS = 31536e4;
2354
2530
  var now22 = () => Math.floor(Date.now() / 1e3);
@@ -2780,8 +2956,8 @@ var CacheManager2 = class {
2780
2956
  const table = cfg.table ?? "cache";
2781
2957
  const lockTable = cfg.lockTable ?? "cache_locks";
2782
2958
  const prefix = this.str(cfg.prefix);
2783
- const store2 = new DatabaseStore(connection, table, prefix);
2784
- return new Repository2(store2, (_store, name, seconds, owner) => new DatabaseLock(connection, lockTable, prefix + name, seconds, owner));
2959
+ const store = new DatabaseStore(connection, table, prefix);
2960
+ return new Repository2(store, (_store, name, seconds, owner) => new DatabaseLock(connection, lockTable, prefix + name, seconds, owner));
2785
2961
  }
2786
2962
  buildRedisStore(cfg) {
2787
2963
  const resolved = resolveRedisConfig(
@@ -2789,8 +2965,8 @@ var CacheManager2 = class {
2789
2965
  (connectionName) => this.container.make(ConfigRepository).get(`database.redis.${connectionName}`, {})
2790
2966
  );
2791
2967
  const redis = makeRedisClient(resolved);
2792
- const store2 = new RedisStore(redis, this.str(cfg.prefix));
2793
- return new RedisRepository(store2, redis);
2968
+ const store = new RedisStore(redis, this.str(cfg.prefix));
2969
+ return new RedisRepository(store, redis);
2794
2970
  }
2795
2971
  store(name) {
2796
2972
  const cacheConfig = this.cacheConfig();
@@ -2859,7 +3035,54 @@ var CacheManager2 = class {
2859
3035
  return this.store().tags(names);
2860
3036
  }
2861
3037
  };
3038
+ var now4 = () => Math.floor(Date.now() / 1e3);
3039
+ var CacheRateLimiter = class {
3040
+ constructor(store) {
3041
+ this.store = store;
3042
+ }
3043
+ store;
3044
+ async tooManyAttempts(key, maxAttempts) {
3045
+ const clean = this.cleanKey(key);
3046
+ if (await this.#attempts(clean) >= maxAttempts) {
3047
+ if (await this.store().has(`${clean}:timer`)) return true;
3048
+ await this.store().forget(clean);
3049
+ }
3050
+ return false;
3051
+ }
3052
+ async hit(key, decaySeconds = 60) {
3053
+ const clean = this.cleanKey(key);
3054
+ const cache2 = this.store();
3055
+ await cache2.add(`${clean}:timer`, now4() + decaySeconds, decaySeconds);
3056
+ const added = await cache2.add(clean, 0, decaySeconds);
3057
+ const hits = await cache2.increment(clean);
3058
+ if (!added && hits === 1) await cache2.put(clean, 1, decaySeconds);
3059
+ return hits;
3060
+ }
3061
+ attempts(key) {
3062
+ return this.#attempts(this.cleanKey(key));
3063
+ }
3064
+ async remaining(key, maxAttempts) {
3065
+ return Math.max(0, maxAttempts - await this.#attempts(this.cleanKey(key)));
3066
+ }
3067
+ async availableIn(key) {
3068
+ const timer = await this.store().get(`${this.cleanKey(key)}:timer`);
3069
+ return timer === void 0 ? 0 : Math.max(0, Number(timer) - now4());
3070
+ }
3071
+ async clear(key) {
3072
+ const clean = this.cleanKey(key);
3073
+ await this.store().forget(clean);
3074
+ await this.store().forget(`${clean}:timer`);
3075
+ }
3076
+ /** Laravel's cleanRateLimiterKey(): accented letters become their plain letter ('zoë' and 'zoe' share a key). */
3077
+ cleanKey(key) {
3078
+ return key.normalize("NFKD").replace(/[̀-ͯ]/g, "");
3079
+ }
3080
+ async #attempts(clean) {
3081
+ return Number(await this.store().get(clean) ?? 0);
3082
+ }
3083
+ };
2862
3084
  var Cache = facade(CacheManager);
3085
+ var RateLimiter2 = facade(RateLimiter);
2863
3086
  function cache(arg, ttlSeconds) {
2864
3087
  const manager2 = inject(CacheManager);
2865
3088
  if (arg === void 0) return manager2;
@@ -2887,6 +3110,12 @@ var CacheServiceProvider = class extends ServiceProvider {
2887
3110
  "cache"
2888
3111
  );
2889
3112
  this.app.singleton(CacheManager, (container) => new CacheManager2(container));
3113
+ this.app.singleton(RateLimiter, (container) => {
3114
+ return new CacheRateLimiter(() => {
3115
+ const name = container.make(ConfigRepository).get("cache.limiter", void 0);
3116
+ return container.make(CacheManager).store(name === void 0 || name === "" ? void 0 : name);
3117
+ });
3118
+ });
2890
3119
  }
2891
3120
  };
2892
3121
 
@@ -2901,7 +3130,7 @@ import { start } from "repl";
2901
3130
  import { existsSync as existsSync2, readdirSync } from "fs";
2902
3131
  import { join as join4 } from "path";
2903
3132
  import { pathToFileURL as pathToFileURL2 } from "url";
2904
- import { createHash as createHash4 } from "crypto";
3133
+ import { createHash as createHash6 } from "crypto";
2905
3134
  import { CronExpressionParser } from "cron-parser";
2906
3135
  var InvalidSignatureError = class extends Error {
2907
3136
  name = "InvalidSignatureError";
@@ -2971,7 +3200,7 @@ var NodeConsoleInput = class {
2971
3200
  const line = this.lines.shift();
2972
3201
  if (line !== void 0) return line;
2973
3202
  if (this.ended) throw new Error("Aborted.");
2974
- return new Promise((resolve4, reject) => this.waiting.push({ resolve: resolve4, reject }));
3203
+ return new Promise((resolve3, reject) => this.waiting.push({ resolve: resolve3, reject }));
2975
3204
  }
2976
3205
  close() {
2977
3206
  const rl = this.rl;
@@ -3016,11 +3245,11 @@ var Command = class {
3016
3245
  consoleOutput = new NodeConsoleOutput();
3017
3246
  consoleInput = new NodeConsoleInput();
3018
3247
  /** @internal Set by the kernel before handle() runs. */
3019
- bind(args, options, io2) {
3248
+ bind(args, options, io) {
3020
3249
  this.boundArguments = args;
3021
3250
  this.boundOptions = options;
3022
- this.consoleInput = io2.input;
3023
- this.consoleOutput = io2.output;
3251
+ this.consoleInput = io.input;
3252
+ this.consoleOutput = io.output;
3024
3253
  }
3025
3254
  argument(name) {
3026
3255
  return this.boundArguments[name];
@@ -3990,15 +4219,15 @@ var ScheduleListCommand = class extends Command {
3990
4219
  function summaryOf(event2) {
3991
4220
  return event2.getSummary();
3992
4221
  }
3993
- async function runDueEvents(events, io2, now4) {
4222
+ async function runDueEvents(events, io, now5) {
3994
4223
  const backgroundRuns = [];
3995
4224
  for (const event2 of events) {
3996
- io2.info(`Running scheduled task: ${summaryOf(event2)}`);
4225
+ io.info(`Running scheduled task: ${summaryOf(event2)}`);
3997
4226
  const attempt = async () => {
3998
4227
  try {
3999
- await event2.run(now4);
4228
+ await event2.run(now5);
4000
4229
  } catch (error) {
4001
- io2.error(` Failed: ${error instanceof Error ? error.message : String(error)}`);
4230
+ io.error(` Failed: ${error instanceof Error ? error.message : String(error)}`);
4002
4231
  }
4003
4232
  };
4004
4233
  if (event2.isBackground()) {
@@ -4013,13 +4242,13 @@ var ScheduleRunCommand = class extends Command {
4013
4242
  signature = "schedule:run";
4014
4243
  description = "Run the scheduled commands";
4015
4244
  async handle() {
4016
- const now4 = /* @__PURE__ */ new Date();
4017
- const due = inject(Schedule).dueEvents(now4);
4245
+ const now5 = /* @__PURE__ */ new Date();
4246
+ const due = inject(Schedule).dueEvents(now5);
4018
4247
  if (due.length === 0) {
4019
4248
  this.info("No scheduled commands are ready to run.");
4020
4249
  return 0;
4021
4250
  }
4022
- await runDueEvents(due, this, now4);
4251
+ await runDueEvents(due, this, now5);
4023
4252
  return 0;
4024
4253
  }
4025
4254
  };
@@ -4033,7 +4262,7 @@ var ScheduleWorkCommand = class extends Command {
4033
4262
  description = "Start the schedule worker";
4034
4263
  async handle() {
4035
4264
  const schedule = inject(Schedule);
4036
- const sleep5 = this.workOptions.sleep ?? ((ms) => new Promise((resolve4) => setTimeout(resolve4, ms)));
4265
+ const sleep5 = this.workOptions.sleep ?? ((ms) => new Promise((resolve3) => setTimeout(resolve3, ms)));
4037
4266
  const clock = this.workOptions.now ?? Date.now;
4038
4267
  this.info("Running scheduled tasks every minute.");
4039
4268
  let lastMinute;
@@ -4042,8 +4271,8 @@ var ScheduleWorkCommand = class extends Command {
4042
4271
  const minute = Math.floor(time / 6e4);
4043
4272
  if (minute !== lastMinute) {
4044
4273
  lastMinute = minute;
4045
- const now4 = new Date(time);
4046
- await runDueEvents(schedule.dueEvents(now4), this, now4);
4274
+ const now5 = new Date(time);
4275
+ await runDueEvents(schedule.dueEvents(now5), this, now5);
4047
4276
  }
4048
4277
  await sleep5(Math.max(0, (minute + 1) * 6e4 - clock()) + 10);
4049
4278
  }
@@ -4066,13 +4295,13 @@ var TestCommand = class extends Command {
4066
4295
  if (typeof filter === "string") args.push("--testNamePattern", filter);
4067
4296
  const extra = this.argument("args");
4068
4297
  if (Array.isArray(extra)) args.push(...extra);
4069
- return new Promise((resolve4) => {
4298
+ return new Promise((resolve3) => {
4070
4299
  const child = this.spawner("npx", args);
4071
4300
  child.on("error", (error) => {
4072
4301
  this.error(error.message);
4073
- resolve4(1);
4302
+ resolve3(1);
4074
4303
  });
4075
- child.on("exit", (code) => resolve4(code ?? 1));
4304
+ child.on("exit", (code) => resolve3(code ?? 1));
4076
4305
  });
4077
4306
  }
4078
4307
  };
@@ -4087,10 +4316,10 @@ var TinkerCommand = class extends Command {
4087
4316
  handle() {
4088
4317
  const app2 = inject(Application);
4089
4318
  const startRepl = this.tinkerOptions.start ?? ((options) => start(options));
4090
- return new Promise((resolve4) => {
4319
+ return new Promise((resolve3) => {
4091
4320
  const repl = startRepl({ prompt: "oriel> " });
4092
4321
  repl.context.app = app2;
4093
- repl.on("exit", () => resolve4(0));
4322
+ repl.on("exit", () => resolve3(0));
4094
4323
  });
4095
4324
  }
4096
4325
  };
@@ -4182,11 +4411,11 @@ function parametersToInput(parameters, signature) {
4182
4411
  }
4183
4412
  return { arguments: args, options };
4184
4413
  }
4185
- var Kernel = class {
4186
- constructor(app2, io2 = {}) {
4414
+ var Kernel2 = class {
4415
+ constructor(app2, io = {}) {
4187
4416
  this.app = app2;
4188
- this.defaultInput = io2.input ?? new NodeConsoleInput();
4189
- this.defaultOutput = io2.output ?? new NodeConsoleOutput();
4417
+ this.defaultInput = io.input ?? new NodeConsoleInput();
4418
+ this.defaultOutput = io.output ?? new NodeConsoleOutput();
4190
4419
  }
4191
4420
  app;
4192
4421
  commands = /* @__PURE__ */ new Map();
@@ -4219,22 +4448,22 @@ var Kernel = class {
4219
4448
  return code;
4220
4449
  }
4221
4450
  /** @internal Runs a command with the given I/O. Command.call() passes its own, so nested output isn't swallowed. */
4222
- async callWithIo(command, parameters, io2) {
4451
+ async callWithIo(command, parameters, io) {
4223
4452
  const instance = this.findOrThrow(command);
4224
4453
  const signature = parseSignature(instance.signature);
4225
- return this.execute(instance, signature, parametersToInput(parameters, signature), io2);
4454
+ return this.execute(instance, signature, parametersToInput(parameters, signature), io);
4226
4455
  }
4227
4456
  async handle(argv) {
4228
- const io2 = { input: this.defaultInput, output: this.defaultOutput };
4457
+ const io = { input: this.defaultInput, output: this.defaultOutput };
4229
4458
  this.running++;
4230
4459
  try {
4231
4460
  const [name, ...rest] = this.normalizeTopLevel(argv);
4232
4461
  const instance = this.findOrThrow(name);
4233
4462
  const signature = parseSignature(instance.signature);
4234
4463
  const input = parseArgv(rest, signature);
4235
- return await this.execute(instance, signature, input, io2);
4464
+ return await this.execute(instance, signature, input, io);
4236
4465
  } catch (error) {
4237
- return this.reportTopLevelError(error, io2.output);
4466
+ return this.reportTopLevelError(error, io.output);
4238
4467
  } finally {
4239
4468
  if (--this.running === 0) this.defaultInput.close?.();
4240
4469
  }
@@ -4276,10 +4505,10 @@ var Kernel = class {
4276
4505
  throw new CommandNotFoundError(`Command "${name}" is not defined.`, suggest(name, [...this.commands.keys()]));
4277
4506
  return instance;
4278
4507
  }
4279
- async execute(instance, signature, input, io2) {
4508
+ async execute(instance, signature, input, io) {
4280
4509
  validateRequiredArguments(signature, input);
4281
4510
  const run = Object.create(instance);
4282
- run.bind?.(resolveArguments(signature, input), resolveOptions(signature, input), io2);
4511
+ run.bind?.(resolveArguments(signature, input), resolveOptions(signature, input), io);
4283
4512
  const scope = this.app.createScope();
4284
4513
  scope.instance(ConsoleKernel, this);
4285
4514
  return scope.run(async () => {
@@ -4312,7 +4541,7 @@ function parseTime(time) {
4312
4541
  return [minute, hour];
4313
4542
  }
4314
4543
  function sha1(value2) {
4315
- return createHash4("sha1").update(value2).digest("hex");
4544
+ return createHash6("sha1").update(value2).digest("hex");
4316
4545
  }
4317
4546
  var ScheduledEventImpl = class {
4318
4547
  /**
@@ -4451,21 +4680,21 @@ var ScheduledEventImpl = class {
4451
4680
  * Minute precision: `now` is truncated to the start of its minute, since cron-parser's includesDate() also
4452
4681
  * compares seconds. Without timezone(), expressions are read in app.timezone (UTC by default), as in Laravel.
4453
4682
  */
4454
- isDue(now4) {
4455
- const minute = new Date(Math.floor(now4.getTime() / 6e4) * 6e4);
4683
+ isDue(now5) {
4684
+ const minute = new Date(Math.floor(now5.getTime() / 6e4) * 6e4);
4456
4685
  const parsed = CronExpressionParser.parse(this.cronExpression, { tz: this.zone() });
4457
4686
  if (!parsed.includesDate(minute)) return false;
4458
- return !this.betweenWindow || this.isWithinWindow(now4);
4687
+ return !this.betweenWindow || this.isWithinWindow(now5);
4459
4688
  }
4460
4689
  zone() {
4461
4690
  if (this.tz !== void 0) return this.tz;
4462
4691
  const container = currentContainer();
4463
4692
  return container?.bound(ConfigRepository) ? container.make(ConfigRepository).get("app.timezone", "UTC") : "UTC";
4464
4693
  }
4465
- isWithinWindow(now4) {
4694
+ isWithinWindow(now5) {
4466
4695
  const { start: start2, end } = this.betweenWindow;
4467
4696
  const format = (d) => d.toLocaleTimeString("en-GB", { hour: "2-digit", minute: "2-digit", hour12: false, timeZone: this.zone() });
4468
- const current = format(now4);
4697
+ const current = format(now5);
4469
4698
  return start2 <= end ? current >= start2 && current <= end : current >= start2 || current <= end;
4470
4699
  }
4471
4700
  /**
@@ -4555,8 +4784,8 @@ var ScheduleImpl = class {
4555
4784
  events() {
4556
4785
  return [...this.scheduledEvents];
4557
4786
  }
4558
- dueEvents(now4) {
4559
- return this.scheduledEvents.filter((event2) => event2.isDue(now4));
4787
+ dueEvents(now5) {
4788
+ return this.scheduledEvents.filter((event2) => event2.isDue(now5));
4560
4789
  }
4561
4790
  push(event2) {
4562
4791
  this.scheduledEvents.push(event2);
@@ -4566,7 +4795,7 @@ var ScheduleImpl = class {
4566
4795
  var ConsoleServiceProvider = class extends ServiceProvider {
4567
4796
  register() {
4568
4797
  this.mergeConfigFrom({ stubs: {} }, "console");
4569
- this.app.singleton(ConsoleKernel, () => new Kernel(this.app));
4798
+ this.app.singleton(ConsoleKernel, () => new Kernel2(this.app));
4570
4799
  this.app.singleton(Schedule, () => new ScheduleImpl());
4571
4800
  }
4572
4801
  boot() {
@@ -4625,14 +4854,14 @@ async function runConsoleAndExit(app2, argv = process.argv.slice(2), exit = (cod
4625
4854
  // ../Cookie/dist/index.js
4626
4855
  import { createHmac as createHmac2, timingSafeEqual as timingSafeEqual2 } from "crypto";
4627
4856
  var SAME_SITE = { lax: "Lax", strict: "Strict", none: "None" };
4628
- function serializeCookie(cookie2, now4 = Date.now()) {
4857
+ function serializeCookie(cookie2, now5 = Date.now()) {
4629
4858
  const parts = [];
4630
4859
  if (cookie2.minutes < 0) {
4631
4860
  parts.push(`${cookie2.name}=`, "Expires=Thu, 01 Jan 1970 00:00:00 GMT", "Max-Age=0");
4632
4861
  } else {
4633
4862
  parts.push(`${cookie2.name}=${encodeURIComponent(cookie2.value)}`);
4634
4863
  if (cookie2.minutes > 0) {
4635
- parts.push(`Expires=${new Date(now4 + cookie2.minutes * 6e4).toUTCString()}`, `Max-Age=${cookie2.minutes * 60}`);
4864
+ parts.push(`Expires=${new Date(now5 + cookie2.minutes * 6e4).toUTCString()}`, `Max-Age=${cookie2.minutes * 60}`);
4636
4865
  }
4637
4866
  }
4638
4867
  parts.push(`Path=${cookie2.path}`);
@@ -4755,14 +4984,14 @@ var AddQueuedCookiesToResponse = class {
4755
4984
  }
4756
4985
  };
4757
4986
  var neverEncrypt = /* @__PURE__ */ new Set();
4758
- function isDeletion(attributes, now4 = Date.now()) {
4987
+ function isDeletion(attributes, now5 = Date.now()) {
4759
4988
  for (const part of attributes.split(";")) {
4760
4989
  const equals4 = part.indexOf("=");
4761
4990
  if (equals4 === -1) continue;
4762
4991
  const key = part.slice(0, equals4).trim().toLowerCase();
4763
4992
  const value2 = part.slice(equals4 + 1).trim();
4764
4993
  if (key === "max-age" && Number(value2) <= 0) return true;
4765
- if (key === "expires" && Date.parse(value2) <= now4) return true;
4994
+ if (key === "expires" && Date.parse(value2) <= now5) return true;
4766
4995
  }
4767
4996
  return false;
4768
4997
  }
@@ -8465,9 +8694,9 @@ var BelongsToMany = class extends Relation {
8465
8694
  pivotRow(id, attributes, creating) {
8466
8695
  const row = { ...attributes, [this.foreignPivotKey]: this.getParentKey(), [this.relatedPivotKey]: this.idOf(id) };
8467
8696
  if (this.pivotTimestamps && creating) {
8468
- const now4 = formatDateTime(this.parent.freshTimestamp());
8469
- row[this.pivotTimestamps[0]] ??= now4;
8470
- row[this.pivotTimestamps[1]] ??= now4;
8697
+ const now5 = formatDateTime(this.parent.freshTimestamp());
8698
+ row[this.pivotTimestamps[0]] ??= now5;
8699
+ row[this.pivotTimestamps[1]] ??= now5;
8471
8700
  }
8472
8701
  return row;
8473
8702
  }
@@ -9857,9 +10086,9 @@ var Model = class _Model {
9857
10086
  }
9858
10087
  /** The current time, to the second (the storage precision). */
9859
10088
  freshTimestamp() {
9860
- const now4 = /* @__PURE__ */ new Date();
9861
- now4.setMilliseconds(0);
9862
- return now4;
10089
+ const now5 = /* @__PURE__ */ new Date();
10090
+ now5.setMilliseconds(0);
10091
+ return now5;
9863
10092
  }
9864
10093
  updateTimestamps() {
9865
10094
  const time = this.freshTimestamp();
@@ -11224,7 +11453,7 @@ function databaseConfigDefaults(app2) {
11224
11453
  }
11225
11454
  };
11226
11455
  }
11227
- function currentRequest() {
11456
+ function currentRequest2() {
11228
11457
  const container = currentContainer();
11229
11458
  if (!container?.bound(HttpRequest)) return void 0;
11230
11459
  try {
@@ -11234,13 +11463,13 @@ function currentRequest() {
11234
11463
  }
11235
11464
  }
11236
11465
  function usePaginationResolvers() {
11237
- AbstractPaginator.currentPathResolver = () => currentRequest()?.url() ?? "/";
11466
+ AbstractPaginator.currentPathResolver = () => currentRequest2()?.url() ?? "/";
11238
11467
  AbstractPaginator.currentPageResolver = (pageName) => {
11239
- const page = Number(currentRequest()?.input(pageName));
11468
+ const page = Number(currentRequest2()?.input(pageName));
11240
11469
  return Number.isInteger(page) && page >= 1 ? page : 1;
11241
11470
  };
11242
- AbstractPaginator.queryStringResolver = () => currentRequest()?.query() ?? {};
11243
- AbstractPaginator.currentCursorResolver = (cursorName) => currentRequest()?.input(cursorName);
11471
+ AbstractPaginator.queryStringResolver = () => currentRequest2()?.query() ?? {};
11472
+ AbstractPaginator.currentCursorResolver = (cursorName) => currentRequest2()?.input(cursorName);
11244
11473
  }
11245
11474
  var DatabaseServiceProvider = class extends ServiceProvider {
11246
11475
  register() {
@@ -12660,1866 +12889,93 @@ var HashingServiceProvider = class extends ServiceProvider {
12660
12889
  }
12661
12890
  };
12662
12891
 
12663
- // ../Http/dist/index.js
12664
- import { createReadStream as createReadStream2 } from "fs";
12665
- import { stat as stat3 } from "fs/promises";
12666
- import { basename as basename2 } from "path";
12667
- import { Readable as Readable2 } from "stream";
12668
- import { readFile as readFile4 } from "fs/promises";
12669
- import { fileURLToPath } from "url";
12670
- import { createReadStream as createReadStream22 } from "fs";
12671
- import { stat as stat22 } from "fs/promises";
12672
- import { Readable as Readable22 } from "stream";
12673
- import { relative as relative5, resolve as resolve3, sep as sep4 } from "path";
12674
- import { createServer } from "http";
12675
- import { Readable as Readable3 } from "stream";
12676
- import { pipeline as pipeline2 } from "stream/promises";
12892
+ // ../Inertia/dist/index.js
12677
12893
  import { existsSync as existsSync7 } from "fs";
12678
- import { mkdir as mkdir5, readFile as readFile22, writeFile as writeFile6 } from "fs/promises";
12679
- import { dirname as dirname5 } from "path";
12680
- var HttpException = class extends Error {
12681
- constructor(status, message = "", headers = {}) {
12682
- super(message);
12683
- this.status = status;
12684
- this.headers = headers;
12685
- }
12686
- status;
12687
- headers;
12688
- kind = "Http";
12689
- name = "HttpException";
12894
+ import { join as join10 } from "path";
12895
+ import { createHash as createHash7 } from "crypto";
12896
+ import { existsSync as existsSync23, readFileSync } from "fs";
12897
+ import { spawn as spawn2 } from "child_process";
12898
+ import { existsSync as existsSync33 } from "fs";
12899
+ import { mkdir as mkdir5, writeFile as writeFile6 } from "fs/promises";
12900
+ import { dirname as dirname5, isAbsolute as isAbsolute2, join as join24, relative as relative5 } from "path";
12901
+ import { existsSync as existsSync42, readFileSync as readFileSync2 } from "fs";
12902
+ var Header = {
12903
+ INERTIA: "X-Inertia",
12904
+ ERROR_BAG: "X-Inertia-Error-Bag",
12905
+ LOCATION: "X-Inertia-Location",
12906
+ REDIRECT: "X-Inertia-Redirect",
12907
+ VERSION: "X-Inertia-Version",
12908
+ PARTIAL_COMPONENT: "X-Inertia-Partial-Component",
12909
+ PARTIAL_ONLY: "X-Inertia-Partial-Data",
12910
+ PARTIAL_EXCEPT: "X-Inertia-Partial-Except",
12911
+ RESET: "X-Inertia-Reset",
12912
+ INFINITE_SCROLL_MERGE_INTENT: "X-Inertia-Infinite-Scroll-Merge-Intent",
12913
+ EXCEPT_ONCE_PROPS: "X-Inertia-Except-Once-Props"
12690
12914
  };
12691
- var HttpResponseException = class extends Error {
12692
- constructor(response2) {
12693
- super(`HTTP response exception (${response2.status}).`);
12694
- this.response = response2;
12695
- this.status = response2.status;
12915
+ function parseList(value2) {
12916
+ const items = (value2 ?? "").split(",").filter((item) => item !== "");
12917
+ return items.length === 0 ? void 0 : items;
12918
+ }
12919
+ var Prop = class {
12920
+ constructor(value2) {
12921
+ this.value = value2;
12696
12922
  }
12697
- response;
12698
- kind = "Http";
12699
- name = "HttpResponseException";
12700
- status;
12701
- };
12702
- var HttpServerError = class extends Error {
12703
- kind = "Server";
12704
- status = 500;
12705
- name = "HttpServerError";
12706
- };
12707
- async function readBody2(raw3, limit) {
12708
- if (raw3.body === null) return new Uint8Array(0);
12709
- const declared = Number(raw3.headers.get("content-length") ?? NaN);
12710
- if (limit !== null && Number.isFinite(declared) && declared > limit) {
12711
- await raw3.body.cancel();
12712
- throw new HttpException(413, "Content Too Large");
12923
+ value;
12924
+ mergeState = { merge: false, deep: false, append: true, appendPaths: [], prependPaths: [], matchOn: [] };
12925
+ onceState = { once: false, fresh: false, key: void 0, ttlSeconds: void 0 };
12926
+ deferred = false;
12927
+ deferGroup;
12928
+ /** Calls the callback, if the value is one. */
12929
+ async resolve() {
12930
+ return typeof this.value === "function" ? await this.value() : this.value;
12713
12931
  }
12714
- const reader = raw3.body.getReader();
12715
- const chunks = [];
12716
- let size = 0;
12717
- for (; ; ) {
12718
- const { done, value: value2 } = await reader.read();
12719
- if (done) break;
12720
- size += value2.byteLength;
12721
- if (limit !== null && size > limit) {
12722
- await reader.cancel();
12723
- throw new HttpException(413, "Content Too Large");
12724
- }
12725
- chunks.push(value2);
12932
+ /** Never sent on the first load (OptionalProp, DeferProp). */
12933
+ ignoresFirstLoad() {
12934
+ return false;
12726
12935
  }
12727
- const out = new Uint8Array(size);
12728
- let offset = 0;
12729
- for (const chunk of chunks) {
12730
- out.set(chunk, offset);
12731
- offset += chunk.byteLength;
12936
+ /** Sent even when a partial reload didn't ask for it (AlwaysProp). */
12937
+ isAlways() {
12938
+ return false;
12732
12939
  }
12733
- return out;
12734
- }
12735
- function requestScope() {
12736
- const container = currentContainer();
12737
- return container !== void 0 && container.bound(HttpRequest) ? container : void 0;
12738
- }
12739
- function currentRequest2() {
12740
- return requestScope()?.make(HttpRequest);
12741
- }
12742
- function optionalSession() {
12743
- const scope = requestScope();
12744
- return scope?.bound(Session) ? scope.make(Session) : void 0;
12745
- }
12746
- function optionalCookieJar() {
12747
- const scope = requestScope();
12748
- return scope?.bound(CookieJar) ? scope.make(CookieJar) : void 0;
12749
- }
12750
- function serializeCookie2(cookie2) {
12751
- const parts = [`${encodeURIComponent(cookie2.name)}=${encodeURIComponent(cookie2.value)}`, `Path=${cookie2.path}`];
12752
- if (cookie2.domain !== void 0) parts.push(`Domain=${cookie2.domain}`);
12753
- if (cookie2.secure) parts.push("Secure");
12754
- if (cookie2.httpOnly) parts.push("HttpOnly");
12755
- parts.push(`SameSite=${cookie2.sameSite.charAt(0).toUpperCase()}${cookie2.sameSite.slice(1)}`);
12756
- if (cookie2.minutes < 0) parts.push("Max-Age=0", "Expires=Thu, 01 Jan 1970 00:00:00 GMT");
12757
- else if (cookie2.minutes > 0) parts.push(`Max-Age=${Math.round(cookie2.minutes * 60)}`);
12758
- return parts.join("; ");
12759
- }
12760
- var HttpRedirectResponse = class {
12761
- constructor(targetUrl, status = 302, headers) {
12762
- this.targetUrl = targetUrl;
12763
- this.status = status;
12764
- this.#headers = new Headers(headers);
12940
+ /** Errors are reported and the prop is left out, instead of failing the page (defer(..., { rescue: true })). */
12941
+ shouldRescue() {
12942
+ return false;
12765
12943
  }
12766
- targetUrl;
12767
- status;
12768
- #headers;
12769
- with(key, value2) {
12770
- const session2 = optionalSession();
12771
- if (session2 === void 0) return this;
12772
- if (typeof key === "string") session2.flash(key, value2);
12773
- else for (const [name, item] of Object.entries(key)) session2.flash(name, item);
12944
+ // Once (honoured by OptionalProp, DeferProp, MergeProp and OnceProp) ------------------------------------
12945
+ /** once(), once(false), once(true, { as: 'key', until: 3600 }). */
12946
+ once(value2 = true, options = {}) {
12947
+ this.onceState.once = value2;
12948
+ if (options.as !== void 0) this.onceState.key = options.as;
12949
+ if (options.until !== void 0) this.onceState.ttlSeconds = secondsUntil(options.until);
12774
12950
  return this;
12775
12951
  }
12776
- /** Flashes `errors` as { [bag]: { field: string[] } }, keeping the other bags already flashed. */
12777
- withErrors(errors2, bag = "default") {
12778
- const session2 = optionalSession();
12779
- if (session2 === void 0) return this;
12780
- const source = typeof errors2.toObject === "function" ? errors2.toObject() : errors2;
12781
- const normalized = Object.fromEntries(
12782
- Object.entries(source).map(([field, messages]) => [field, Array.isArray(messages) ? [...messages] : [messages]])
12783
- );
12784
- const existing = session2.get("errors", {});
12785
- session2.flash("errors", { ...existing, [bag]: normalized });
12952
+ /** A custom once key, so pages can share the prop under different names. */
12953
+ as(key) {
12954
+ this.onceState.key = key;
12786
12955
  return this;
12787
12956
  }
12788
- /** Flashes `input`, or the current request's input (files are never part of input()). */
12789
- withInput(input) {
12790
- const session2 = optionalSession();
12791
- if (session2 === void 0) return this;
12792
- session2.flashInput(input ?? currentRequest2()?.input() ?? {});
12957
+ /** Send the prop again even though the client already has it. */
12958
+ fresh(value2 = true) {
12959
+ this.onceState.fresh = value2;
12793
12960
  return this;
12794
12961
  }
12795
- /**
12796
- * Always a Set-Cookie header on this response (Laravel's RedirectResponse::withCookie). A bound CookieJar only
12797
- * supplies the defaults (path, domain, secure, same-site); queueing would lose the cookie outside the web group.
12798
- */
12799
- withCookie(name, value2, minutes = 0) {
12800
- const jar = optionalCookieJar();
12801
- const cookie2 = jar !== void 0 ? jar.make(name, value2, minutes) : { name, value: value2, minutes, path: "/", secure: false, httpOnly: true, sameSite: "lax" };
12802
- this.#headers.append("Set-Cookie", serializeCookie2(cookie2));
12962
+ /** Expire after a number of seconds, or at a Date. */
12963
+ until(delay) {
12964
+ this.onceState.ttlSeconds = secondsUntil(delay);
12803
12965
  return this;
12804
12966
  }
12805
- header(name, value2) {
12806
- this.#headers.set(name, value2);
12807
- return this;
12967
+ // Merging -------------------------------------------------------------------------------------------------
12968
+ isMergeable() {
12969
+ return false;
12808
12970
  }
12809
- toResponse() {
12810
- const headers = new Headers(this.#headers);
12811
- headers.set("Location", this.targetUrl);
12812
- return new Response(null, { status: this.status, headers });
12971
+ shouldMerge() {
12972
+ return this.isMergeable() && this.mergeState.merge;
12813
12973
  }
12814
- };
12815
- var HttpRedirector = class {
12816
- to(path, status = 302, headers) {
12817
- return new HttpRedirectResponse(inject(UrlGenerator).to(path), status, headers);
12974
+ shouldDeepMerge() {
12975
+ return this.mergeState.deep;
12818
12976
  }
12819
- route(name, parameters, status = 302) {
12820
- return new HttpRedirectResponse(inject(UrlGenerator).route(name, parameters), status);
12821
- }
12822
- back(fallback, status = 302) {
12823
- return new HttpRedirectResponse(inject(UrlGenerator).previous(fallback), status);
12824
- }
12825
- /** Pulls url.intended from the session (put there by guest()), else goes to `fallback`. */
12826
- intended(fallback = "/", status = 302) {
12827
- const path = optionalSession()?.pull("url.intended") ?? fallback;
12828
- return this.to(path, status);
12829
- }
12830
- away(url2, status = 302) {
12831
- return new HttpRedirectResponse(url2, status);
12832
- }
12833
- /** Remembers where a guest was going (a GET page, else the previous URL), then redirects to `path`. */
12834
- guest(path, status = 302) {
12835
- const session2 = optionalSession();
12836
- const request2 = currentRequest2();
12837
- if (session2 !== void 0) {
12838
- const intended = request2 !== void 0 && request2.method() === "GET" && !request2.expectsJson() ? request2.fullUrl() : inject(UrlGenerator).previous();
12839
- session2.put("url.intended", intended);
12840
- }
12841
- return this.to(path, status);
12842
- }
12843
- setIntendedUrl(url2) {
12844
- optionalSession()?.put("url.intended", url2);
12845
- }
12846
- refresh(status = 302) {
12847
- return this.to(currentRequest2()?.fullUrl() ?? inject(UrlGenerator).current(), status);
12848
- }
12849
- };
12850
- var KEY = /* @__PURE__ */ Symbol.for("oriel:http.client-address");
12851
- var store = globalThis[KEY] ??= /* @__PURE__ */ new WeakMap();
12852
- function setClientAddress(request2, address) {
12853
- if (address !== void 0 && address !== "") store.set(request2, address);
12854
- }
12855
- function clientAddress(request2) {
12856
- return store.get(request2);
12857
- }
12858
- var TYPES = {
12859
- avif: "image/avif",
12860
- css: "text/css",
12861
- csv: "text/csv",
12862
- doc: "application/msword",
12863
- docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
12864
- gif: "image/gif",
12865
- gz: "application/gzip",
12866
- html: "text/html",
12867
- ico: "image/vnd.microsoft.icon",
12868
- jpg: "image/jpeg",
12869
- js: "text/javascript",
12870
- map: "application/json",
12871
- json: "application/json",
12872
- md: "text/markdown",
12873
- mp3: "audio/mpeg",
12874
- mp4: "video/mp4",
12875
- otf: "font/otf",
12876
- pdf: "application/pdf",
12877
- png: "image/png",
12878
- svg: "image/svg+xml",
12879
- ttf: "font/ttf",
12880
- txt: "text/plain",
12881
- wasm: "application/wasm",
12882
- webm: "video/webm",
12883
- webp: "image/webp",
12884
- woff: "font/woff",
12885
- woff2: "font/woff2",
12886
- xls: "application/vnd.ms-excel",
12887
- xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
12888
- xml: "application/xml",
12889
- zip: "application/zip"
12890
- };
12891
- var ALIASES = { jpeg: "jpg", htm: "html", mjs: "js", text: "txt" };
12892
- var EXTENSIONS2 = Object.fromEntries(Object.entries(TYPES).map(([extension, type]) => [type, extension]));
12893
- function mimeFromExtension2(pathOrExtension) {
12894
- const extension = pathOrExtension.slice(pathOrExtension.lastIndexOf(".") + 1).toLowerCase();
12895
- return TYPES[ALIASES[extension] ?? extension] ?? "application/octet-stream";
12896
- }
12897
- function extensionFromMime(type) {
12898
- return EXTENSIONS2[type.split(";")[0].trim().toLowerCase()];
12899
- }
12900
- var FormUploadedFile = class {
12901
- constructor(file) {
12902
- this.file = file;
12903
- this.clientName = file.name ?? "";
12904
- this.mimeType = file.type === "" ? "application/octet-stream" : file.type;
12905
- this.size = file.size;
12906
- }
12907
- file;
12908
- clientName;
12909
- mimeType;
12910
- size;
12911
- /** Guessed from the MIME type, falling back to the client's extension (Laravel's extension()). */
12912
- extension() {
12913
- return extensionFromMime(this.mimeType) ?? this.clientExtension();
12914
- }
12915
- clientExtension() {
12916
- const dot = this.clientName.lastIndexOf(".");
12917
- return dot === -1 ? "" : this.clientName.slice(dot + 1).toLowerCase();
12918
- }
12919
- /** A random 40-character name with the guessed extension. */
12920
- hashName() {
12921
- const extension = this.extension();
12922
- return extension === "" ? Str.random(40) : `${Str.random(40)}.${extension}`;
12923
- }
12924
- arrayBuffer() {
12925
- return this.file.arrayBuffer();
12926
- }
12927
- text() {
12928
- return this.file.text();
12929
- }
12930
- stream() {
12931
- return this.file.stream();
12932
- }
12933
- store(directory, disk) {
12934
- return inject(FilesystemManager).disk(disk).putFile(directory, this);
12935
- }
12936
- storeAs(directory, name, disk) {
12937
- return inject(FilesystemManager).disk(disk).putFileAs(directory, this, name);
12938
- }
12939
- };
12940
- var FORBIDDEN = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
12941
- var INTEGER_KEY = /^(?:0|[1-9]\d*)$/;
12942
- var isPlainObject2 = (value2) => {
12943
- if (typeof value2 !== "object" || value2 === null || Array.isArray(value2)) return false;
12944
- const prototype = Object.getPrototypeOf(value2);
12945
- return prototype === Object.prototype || prototype === null;
12946
- };
12947
- function parseBracketKey(name) {
12948
- const open = name.indexOf("[");
12949
- if (open <= 0 || !name.endsWith("]")) return [name];
12950
- const segments = [name.slice(0, open)];
12951
- const rest = name.slice(open);
12952
- const matches = rest.match(/\[[^[\]]*\]/g);
12953
- if (matches === null || matches.join("") !== rest) return [name];
12954
- for (const match of matches) segments.push(match.slice(1, -1));
12955
- return segments;
12956
- }
12957
- function normalizeLists(value2) {
12958
- if (Array.isArray(value2)) return value2.map(normalizeLists);
12959
- if (!isPlainObject2(value2)) return value2;
12960
- const keys = Object.keys(value2);
12961
- const out = {};
12962
- for (const key of keys) out[key] = normalizeLists(value2[key]);
12963
- if (keys.length > 0 && keys.every((key, index) => key === String(index))) return keys.map((key) => out[key]);
12964
- return out;
12965
- }
12966
- function fromEntries(entries) {
12967
- const root = {};
12968
- const nextIndex = /* @__PURE__ */ new WeakMap();
12969
- for (const [name, value2] of entries) {
12970
- const segments = parseBracketKey(name);
12971
- if (segments.some((segment) => FORBIDDEN.has(segment))) continue;
12972
- let node = root;
12973
- for (let i = 0; i < segments.length; i++) {
12974
- let segment = segments[i];
12975
- const next = nextIndex.get(node) ?? 0;
12976
- if (segment === "") {
12977
- segment = String(next);
12978
- nextIndex.set(node, next + 1);
12979
- } else if (INTEGER_KEY.test(segment) && Number(segment) >= next) {
12980
- nextIndex.set(node, Number(segment) + 1);
12981
- }
12982
- if (i === segments.length - 1) {
12983
- node[segment] = value2;
12984
- break;
12985
- }
12986
- if (!isPlainObject2(node[segment])) node[segment] = {};
12987
- node = node[segment];
12988
- }
12989
- }
12990
- return normalizeLists(root);
12991
- }
12992
- function sanitize(value2) {
12993
- if (Array.isArray(value2)) return value2.map(sanitize);
12994
- if (!isPlainObject2(value2)) return value2;
12995
- const out = {};
12996
- for (const [key, item] of Object.entries(value2)) if (!FORBIDDEN.has(key)) out[key] = sanitize(item);
12997
- return out;
12998
- }
12999
- function mergeRecursive(base, override) {
13000
- const out = { ...base };
13001
- for (const [key, value2] of Object.entries(override)) {
13002
- if (FORBIDDEN.has(key)) continue;
13003
- const current = out[key];
13004
- out[key] = (isPlainObject2(current) || Array.isArray(current)) && (isPlainObject2(value2) || Array.isArray(value2)) ? normalizeLists(mergeRecursive({ ...current }, { ...value2 })) : value2;
13005
- }
13006
- return out;
13007
- }
13008
- function isBlank(value2) {
13009
- if (value2 === null || value2 === void 0) return true;
13010
- if (typeof value2 === "string") return value2.trim() === "";
13011
- if (Array.isArray(value2)) return value2.length === 0;
13012
- if (isPlainObject2(value2)) return Object.keys(value2).length === 0;
13013
- return false;
13014
- }
13015
- function transformLeaves(tree, transform, prefix = "") {
13016
- const out = {};
13017
- for (const [key, value2] of Object.entries(tree)) out[key] = transformValue(`${prefix}${key}`, value2, transform);
13018
- return out;
13019
- }
13020
- function transformValue(path, value2, transform) {
13021
- if (Array.isArray(value2)) return value2.map((item, index) => transformValue(`${path}.${index}`, item, transform));
13022
- if (isPlainObject2(value2)) return transformLeaves(value2, transform, `${path}.`);
13023
- return transform(path, value2);
13024
- }
13025
- var TRUE_VALUES = /* @__PURE__ */ new Set(["1", "true", "on", "yes"]);
13026
- var normalizeIp = (ip) => ip.trim().replace(/^::ffff:(\d+\.\d+\.\d+\.\d+)$/i, "$1");
13027
- function ipv4ToNumber(ip) {
13028
- const parts = ip.split(".");
13029
- if (parts.length !== 4 || parts.some((part) => !/^\d{1,3}$/.test(part) || Number(part) > 255)) return void 0;
13030
- return parts.reduce((total, part) => total * 256 + Number(part), 0);
13031
- }
13032
- function ipMatches(ip, patterns) {
13033
- const address = normalizeIp(ip);
13034
- return patterns.some((pattern) => {
13035
- if (pattern === "*") return true;
13036
- if (!pattern.includes("/")) return normalizeIp(pattern) === address;
13037
- const [range, bits] = pattern.split("/");
13038
- const base = ipv4ToNumber(range);
13039
- const value2 = ipv4ToNumber(address);
13040
- const size = Number(bits);
13041
- if (base === void 0 || value2 === void 0 || !(size >= 0 && size <= 32)) return false;
13042
- const mask = size === 0 ? 0 : ~0 << 32 - size >>> 0;
13043
- return (base & mask) >>> 0 === (value2 & mask) >>> 0;
13044
- });
13045
- }
13046
- var IncomingRequest = class {
13047
- constructor(raw3, options = {}) {
13048
- this.raw = raw3;
13049
- this.#url = new URL(raw3.url);
13050
- this.#trustedProxies = options.trustedProxies ?? [];
13051
- this.#maxBodySize = options.maxBodySize === void 0 ? 8 * 1024 * 1024 : options.maxBodySize;
13052
- this.#query = fromEntries(this.#url.searchParams.entries());
13053
- this.#method = raw3.method.toUpperCase();
13054
- }
13055
- raw;
13056
- #url;
13057
- #trustedProxies;
13058
- #maxBodySize;
13059
- #query;
13060
- #body = {};
13061
- #files = {};
13062
- #content = "";
13063
- #method;
13064
- #cookies;
13065
- #loading;
13066
- #userResolver;
13067
- /** Reads and parses the body (JSON, urlencoded or multipart) once, then applies method spoofing. */
13068
- load() {
13069
- return this.#loading ??= this.#load();
13070
- }
13071
- async #load() {
13072
- const method = this.raw.method.toUpperCase();
13073
- if (method !== "GET" && method !== "HEAD" && this.raw.body !== null) {
13074
- const type = (this.raw.headers.get("content-type") ?? "").toLowerCase();
13075
- const isJson = type.includes("/json") || type.includes("+json");
13076
- const isUrlencoded = type.startsWith("application/x-www-form-urlencoded");
13077
- const isMultipart = type.startsWith("multipart/form-data");
13078
- if (isJson || isUrlencoded || isMultipart) {
13079
- const bytes = await readBody2(this.raw, this.#maxBodySize);
13080
- try {
13081
- if (isJson) {
13082
- this.#content = new TextDecoder().decode(bytes);
13083
- this.#body = this.#parseJson(this.#content);
13084
- } else if (isUrlencoded) {
13085
- this.#content = new TextDecoder().decode(bytes);
13086
- this.#body = fromEntries(new URLSearchParams(this.#content).entries());
13087
- } else {
13088
- this.#parseForm(await new Response(bytes, { headers: { "content-type": this.raw.headers.get("content-type") ?? "" } }).formData());
13089
- }
13090
- } catch {
13091
- }
13092
- }
13093
- }
13094
- if (method === "POST") {
13095
- const override = this.raw.headers.get("x-http-method-override") ?? this.#string(this.#body._method) ?? this.#string(this.#query._method);
13096
- const spoofed = override?.toUpperCase();
13097
- if (spoofed !== void 0 && /^[A-Z]+$/.test(spoofed) && !["GET", "HEAD", "CONNECT", "TRACE"].includes(spoofed)) {
13098
- this.#method = spoofed;
13099
- }
13100
- }
13101
- return this;
13102
- }
13103
- #parseJson(text3) {
13104
- let parsed;
13105
- try {
13106
- parsed = JSON.parse(text3);
13107
- } catch {
13108
- return {};
13109
- }
13110
- if (Array.isArray(parsed)) return sanitize({ ...parsed });
13111
- return isPlainObject2(parsed) ? sanitize(parsed) : {};
13112
- }
13113
- #parseForm(form) {
13114
- const fields = [];
13115
- const files3 = [];
13116
- for (const [name, value2] of form.entries()) {
13117
- if (typeof value2 === "string") fields.push([name, value2]);
13118
- else if (!((value2.name ?? "") === "" && value2.size === 0)) files3.push([name, new FormUploadedFile(value2)]);
13119
- }
13120
- this.#body = fromEntries(fields);
13121
- this.#files = fromEntries(files3);
13122
- }
13123
- #string(value2) {
13124
- return typeof value2 === "string" && value2 !== "" ? value2 : void 0;
13125
- }
13126
- method() {
13127
- return this.#method;
13128
- }
13129
- isMethod(method) {
13130
- return this.#method === method.toUpperCase();
13131
- }
13132
- /** The scheme and host, honouring X-Forwarded-Proto/Host from trusted proxies. */
13133
- root() {
13134
- const trusted = this.#fromTrustedProxy();
13135
- const proto = trusted ? this.raw.headers.get("x-forwarded-proto")?.split(",")[0]?.trim() : void 0;
13136
- const host = trusted ? this.raw.headers.get("x-forwarded-host")?.split(",")[0]?.trim() : void 0;
13137
- const scheme = proto === "https" || proto === "http" ? proto : this.#url.protocol.slice(0, -1);
13138
- return `${scheme}://${host !== void 0 && host !== "" ? host : this.#url.host}`;
13139
- }
13140
- /** The URL without the query string or a trailing slash. */
13141
- url() {
13142
- return `${this.root()}${this.#url.pathname}`.replace(/\/+$/, "");
13143
- }
13144
- fullUrl() {
13145
- return this.#url.search === "" ? this.url() : `${this.url()}${this.#url.search}`;
13146
- }
13147
- /** 'posts/1', or '/' for the root. */
13148
- path() {
13149
- const trimmed = this.#url.pathname.replace(/^\/+|\/+$/g, "");
13150
- return trimmed === "" ? "/" : trimmed;
13151
- }
13152
- decodedPath() {
13153
- try {
13154
- return decodeURIComponent(this.path());
13155
- } catch {
13156
- return this.path();
13157
- }
13158
- }
13159
- secure() {
13160
- return this.root().startsWith("https:");
13161
- }
13162
- /** request.is('admin/*'): wildcard match against the decoded path. */
13163
- is(...patterns) {
13164
- const path = this.decodedPath();
13165
- return patterns.some((pattern) => {
13166
- const trimmed = pattern.replace(/^\/+|\/+$/g, "");
13167
- return Str.is(trimmed === "" ? "/" : trimmed, path);
13168
- });
13169
- }
13170
- routeIs(...names) {
13171
- const name = this.#currentRoute()?.route.getName();
13172
- return name !== void 0 && names.some((pattern) => Str.is(pattern, name));
13173
- }
13174
- header(name, defaultValue) {
13175
- return this.raw.headers.get(name) ?? defaultValue;
13176
- }
13177
- bearerToken() {
13178
- const header = this.header("authorization", "");
13179
- const position = header.toLowerCase().lastIndexOf("bearer ");
13180
- if (position === -1) return void 0;
13181
- const token2 = header.slice(position + 7).split(",")[0].trim();
13182
- return token2 === "" ? void 0 : token2;
13183
- }
13184
- userAgent() {
13185
- return this.header("user-agent");
13186
- }
13187
- /** The socket address, or the right-most untrusted X-Forwarded-For entry when the socket is a trusted proxy. */
13188
- ip() {
13189
- const socket = clientAddress(this.raw);
13190
- if (socket === void 0) return void 0;
13191
- const address = normalizeIp(socket);
13192
- if (!this.#fromTrustedProxy()) return address;
13193
- const chain = (this.raw.headers.get("x-forwarded-for") ?? "").split(",").map((entry) => normalizeIp(entry)).filter((entry) => entry !== "");
13194
- for (let i = chain.length - 1; i >= 0; i--) if (!ipMatches(chain[i], this.#trustedProxies)) return chain[i];
13195
- return chain[0] ?? address;
13196
- }
13197
- #fromTrustedProxy() {
13198
- const socket = clientAddress(this.raw);
13199
- return socket !== void 0 && this.#trustedProxies.length > 0 && ipMatches(socket, this.#trustedProxies);
13200
- }
13201
- ajax() {
13202
- return this.header("x-requested-with") === "XMLHttpRequest";
13203
- }
13204
- pjax() {
13205
- return this.header("x-pjax") === "true";
13206
- }
13207
- /** The first Accept type is JSON. */
13208
- wantsJson() {
13209
- const first = this.header("accept", "").split(",")[0].trim();
13210
- return first.includes("/json") || first.includes("+json");
13211
- }
13212
- /** Laravel: (ajax and not pjax and accepts anything) or wantsJson. */
13213
- expectsJson() {
13214
- const first = this.header("accept", "").split(",")[0].split(";")[0].trim();
13215
- const acceptsAny = first === "" || first === "*/*" || first === "*";
13216
- return this.ajax() && !this.pjax() && acceptsAny || this.wantsJson();
13217
- }
13218
- /** The raw body text for JSON and urlencoded requests ('' otherwise; the raw stream stays unread for other types). */
13219
- content() {
13220
- return this.#content;
13221
- }
13222
- query(key, defaultValue) {
13223
- return Arr.get(this.#query, key, defaultValue);
13224
- }
13225
- /** Body wins over the query string (PHP's $body + $query). Files are not input. */
13226
- input(key, defaultValue) {
13227
- return Arr.get({ ...this.#query, ...this.#body }, key, defaultValue);
13228
- }
13229
- /** Input plus files (array_replace_recursive). */
13230
- all() {
13231
- return mergeRecursive({ ...this.#query, ...this.#body }, this.#files);
13232
- }
13233
- only(...keys) {
13234
- const all = this.all();
13235
- const out = {};
13236
- for (const key of keys.flat()) if (Arr.has(all, key)) Arr.set(out, key, Arr.get(all, key));
13237
- return out;
13238
- }
13239
- except(...keys) {
13240
- const all = structuredCloneInput(this.all());
13241
- for (const key of keys.flat()) Arr.forget(all, key);
13242
- return all;
13243
- }
13244
- has(...keys) {
13245
- const all = this.all();
13246
- return keys.flat().every((key) => Arr.has(all, key));
13247
- }
13248
- hasAny(...keys) {
13249
- const all = this.all();
13250
- return keys.flat().some((key) => Arr.has(all, key));
13251
- }
13252
- missing(...keys) {
13253
- return !this.has(...keys);
13254
- }
13255
- filled(key) {
13256
- return !isBlank(Arr.get(this.all(), key));
13257
- }
13258
- string(key, defaultValue = "") {
13259
- const value2 = this.input(key);
13260
- return value2 === void 0 || value2 === null ? defaultValue : String(value2);
13261
- }
13262
- /** PHP's FILTER_VALIDATE_BOOLEAN: '1', 'true', 'on', 'yes' (any case) and true are true. */
13263
- boolean(key, defaultValue = false) {
13264
- const value2 = this.input(key);
13265
- if (value2 === void 0) return defaultValue;
13266
- if (typeof value2 === "boolean") return value2;
13267
- if (typeof value2 === "number") return value2 === 1;
13268
- return typeof value2 === "string" && TRUE_VALUES.has(value2.trim().toLowerCase());
13269
- }
13270
- /** PHP's intval: leading digits, else 0. */
13271
- integer(key, defaultValue = 0) {
13272
- const value2 = this.input(key);
13273
- if (value2 === void 0) return defaultValue;
13274
- if (typeof value2 === "number") return Number.isFinite(value2) ? Math.trunc(value2) : 0;
13275
- if (typeof value2 === "boolean") return value2 ? 1 : 0;
13276
- const parsed = Number.parseInt(String(value2).trim(), 10);
13277
- return Number.isNaN(parsed) ? 0 : parsed;
13278
- }
13279
- /** Adds or replaces top-level body values. */
13280
- merge(values) {
13281
- this.#body = { ...this.#body, ...sanitize(values) };
13282
- return this;
13283
- }
13284
- /** Rewrites every scalar in the query and the body (TrimStrings and ConvertEmptyStringsToNull use this). */
13285
- transformInput(transform) {
13286
- this.#query = transformLeaves(this.#query, transform);
13287
- this.#body = transformLeaves(this.#body, transform);
13288
- return this;
13289
- }
13290
- file(key) {
13291
- const value2 = Arr.get(this.#files, key);
13292
- return value2 instanceof FormUploadedFile ? value2 : void 0;
13293
- }
13294
- hasFile(key) {
13295
- const value2 = Arr.get(this.#files, key);
13296
- return value2 instanceof FormUploadedFile || Array.isArray(value2) && value2.some((item) => item instanceof FormUploadedFile);
13297
- }
13298
- allFiles() {
13299
- return { ...this.#files };
13300
- }
13301
- cookie(name) {
13302
- return this.cookies()[name];
13303
- }
13304
- cookies() {
13305
- if (this.#cookies === void 0) {
13306
- const cookies = {};
13307
- for (const part of (this.raw.headers.get("cookie") ?? "").split(";")) {
13308
- const index = part.indexOf("=");
13309
- if (index === -1) continue;
13310
- const name = part.slice(0, index).trim();
13311
- if (name === "" || Object.hasOwn(cookies, name)) continue;
13312
- let value2 = part.slice(index + 1).trim();
13313
- if (value2.startsWith('"') && value2.endsWith('"')) value2 = value2.slice(1, -1);
13314
- try {
13315
- cookies[name] = decodeURIComponent(value2);
13316
- } catch {
13317
- cookies[name] = value2;
13318
- }
13319
- }
13320
- this.#cookies = cookies;
13321
- }
13322
- return { ...this.#cookies };
13323
- }
13324
- /** Replaces the parsed cookies (EncryptCookies calls this after decrypting). */
13325
- setCookies(cookies) {
13326
- this.#cookies = { ...cookies };
13327
- }
13328
- /** One route parameter (after model binding), or all of them. */
13329
- route(key) {
13330
- const parameters = this.#currentRoute()?.parameters ?? {};
13331
- return key === void 0 ? { ...parameters } : parameters[key];
13332
- }
13333
- session() {
13334
- return inject(Session);
13335
- }
13336
- user(guard2) {
13337
- return this.#userResolver?.(guard2);
13338
- }
13339
- setUserResolver(resolver) {
13340
- this.#userResolver = resolver;
13341
- }
13342
- /** Validates all() through the ValidationFactory; throws its Validation error on failure. */
13343
- validate(rules, messages, attributes) {
13344
- return inject(ValidationFactory).make(this.all(), rules, messages, attributes).validated();
13345
- }
13346
- #currentRoute() {
13347
- const container = currentContainer();
13348
- return container?.bound(CurrentRoute) ? container.make(CurrentRoute) : void 0;
13349
- }
13350
- };
13351
- function structuredCloneInput(tree) {
13352
- const out = {};
13353
- for (const [key, value2] of Object.entries(tree)) {
13354
- out[key] = isPlainObject2(value2) ? structuredCloneInput(value2) : Array.isArray(value2) ? [...value2] : value2;
13355
- }
13356
- return out;
13357
- }
13358
- function request(key, defaultValue) {
13359
- const current = inject(HttpRequest);
13360
- return key === void 0 ? current : current.input(key, defaultValue);
13361
- }
13362
- function response(content, status, headers) {
13363
- const factory = inject(ResponseFactory);
13364
- return content === void 0 ? factory : factory.make(content, status, headers);
13365
- }
13366
- function redirect(to, status) {
13367
- const redirector = inject(Redirector);
13368
- return to === void 0 ? redirector : redirector.to(to, status);
13369
- }
13370
- function back(fallback, status) {
13371
- return inject(Redirector).back(fallback, status);
13372
- }
13373
- function url(path, query, absolute) {
13374
- const generator = inject(UrlGenerator);
13375
- return path === void 0 ? generator : generator.to(path, query, absolute);
13376
- }
13377
- function route(name, parameters, absolute) {
13378
- return inject(UrlGenerator).route(name, parameters, absolute);
13379
- }
13380
- function abort(status, message = "", headers = {}) {
13381
- if (status instanceof Response) throw new HttpResponseException(status);
13382
- throw new HttpException(status, message, headers);
13383
- }
13384
- function abortIf(condition, status, message = "", headers = {}) {
13385
- if (condition) abort(status, message, headers);
13386
- }
13387
- function abortUnless(condition, status, message = "", headers = {}) {
13388
- if (!condition) abort(status, message, headers);
13389
- }
13390
- function contentDisposition(type, name) {
13391
- const fallback = name.replace(/[^\x20-\x7e]/g, "_").replace(/["\\]/g, "\\$&");
13392
- const header = `${type}; filename="${fallback}"`;
13393
- return /^[\x20-\x7e]*$/.test(name) ? header : `${header}; filename*=UTF-8''${encodeURIComponent(name)}`;
13394
- }
13395
- var HttpResponseFactory = class {
13396
- /** Strings default to text/html; charset=utf-8, as in Laravel. */
13397
- make(content = null, status = 200, headers) {
13398
- const merged = new Headers(headers);
13399
- if (typeof content === "string" && !merged.has("content-type")) merged.set("content-type", "text/html; charset=utf-8");
13400
- return new Response(content, { status, headers: merged });
13401
- }
13402
- json(data, status = 200, headers) {
13403
- const merged = new Headers(headers);
13404
- if (!merged.has("content-type")) merged.set("content-type", "application/json");
13405
- return new Response(JSON.stringify(data === void 0 ? null : data), { status, headers: merged });
13406
- }
13407
- noContent(status = 204) {
13408
- return new Response(null, { status });
13409
- }
13410
- /** Renders a view (through the ViewFactory) into an HTML response. */
13411
- async view(name, data = {}, status = 200, headers) {
13412
- const html2 = await inject(ViewFactory).make(name, data).render();
13413
- return this.make(html2, status, headers);
13414
- }
13415
- /** Streams a file as an attachment. A missing file is a 404. */
13416
- download(path, name = basename2(path), headers) {
13417
- return this.#file(path, "attachment", name, headers);
13418
- }
13419
- /** Streams a file for the browser to display (Laravel's response()->file()). */
13420
- file(path, headers) {
13421
- return this.#file(path, "inline", basename2(path), headers);
13422
- }
13423
- stream(body, status = 200, headers) {
13424
- return new Response(body, { status, headers });
13425
- }
13426
- async #file(path, disposition, name, headers) {
13427
- const info = await stat3(path).catch(() => void 0);
13428
- if (info === void 0 || !info.isFile()) throw new HttpException(404);
13429
- const merged = new Headers(headers);
13430
- if (!merged.has("content-type")) merged.set("content-type", mimeFromExtension2(name));
13431
- merged.set("content-length", String(info.size));
13432
- merged.set("content-disposition", contentDisposition(disposition, name));
13433
- const body = Readable2.toWeb(createReadStream2(path));
13434
- return new Response(body, { status: 200, headers: merged });
13435
- }
13436
- };
13437
- var ConvertEmptyStringsToNull = class {
13438
- async handle(request2, next) {
13439
- if (request2 instanceof IncomingRequest) request2.transformInput((_key, value2) => value2 === "" ? null : value2);
13440
- return next(request2);
13441
- }
13442
- };
13443
- var TRIM = /^[\s\uFEFF\u200B\u200E]+|[\s\uFEFF\u200B\u200E]+$/g;
13444
- var TrimStrings = class {
13445
- /** Dotted input keys left untouched. Override in a subclass to change. */
13446
- except = ["current_password", "password", "password_confirmation"];
13447
- async handle(request2, next) {
13448
- if (request2 instanceof IncomingRequest) {
13449
- request2.transformInput(
13450
- (key, value2) => typeof value2 === "string" && !this.except.includes(key) ? value2.replace(TRIM, "") : value2
13451
- );
13452
- }
13453
- return next(request2);
13454
- }
13455
- };
13456
- var plainServerError = () => new Response("Server Error", { status: 500, headers: { "content-type": "text/plain; charset=utf-8" } });
13457
- var Kernel2 = class {
13458
- constructor(app2) {
13459
- this.app = app2;
13460
- }
13461
- app;
13462
- #middleware = [TrimStrings, ConvertEmptyStringsToNull];
13463
- #requests = /* @__PURE__ */ new WeakMap();
13464
- getGlobalMiddleware() {
13465
- return [...this.#middleware];
13466
- }
13467
- setGlobalMiddleware(middleware) {
13468
- this.#middleware = [...middleware];
13469
- return this;
13470
- }
13471
- appendMiddleware(...middleware) {
13472
- for (const cls of middleware) if (!this.#middleware.includes(cls)) this.#middleware.push(cls);
13473
- return this;
13474
- }
13475
- prependMiddleware(...middleware) {
13476
- for (const cls of [...middleware].reverse()) if (!this.#middleware.includes(cls)) this.#middleware.unshift(cls);
13477
- return this;
13478
- }
13479
- hasMiddleware(middleware) {
13480
- return this.#middleware.includes(middleware);
13481
- }
13482
- /** Runs in the current request scope (Application.handle() opens one); called directly, it opens its own. */
13483
- handle(raw3) {
13484
- const current = currentContainer();
13485
- const scope = current !== void 0 && current !== this.app ? current : this.app.createScope();
13486
- return scope.run(() => this.#handle(raw3, scope));
13487
- }
13488
- async #handle(raw3, scope) {
13489
- let request2;
13490
- let response2;
13491
- try {
13492
- request2 = new IncomingRequest(raw3, { trustedProxies: this.#trustedProxies(), maxBodySize: this.#maxBodySize() });
13493
- scope.instance(HttpRequest, request2);
13494
- const state = { scope, request: request2, middleware: [] };
13495
- this.#requests.set(raw3, state);
13496
- await request2.load();
13497
- response2 = await this.#sendThroughGlobal(state);
13498
- } catch (error) {
13499
- request2 ??= this.#bareRequest(scope, raw3);
13500
- if (request2 !== void 0) {
13501
- response2 = await this.#renderLast(scope, request2, error);
13502
- } else {
13503
- await this.#report(scope, error);
13504
- response2 = plainServerError();
13505
- }
13506
- }
13507
- if (raw3.method.toUpperCase() === "HEAD" && response2.body !== null) {
13508
- await response2.body.cancel().catch(() => void 0);
13509
- response2 = new Response(null, { status: response2.status, statusText: response2.statusText, headers: response2.headers });
13510
- }
13511
- return response2;
13512
- }
13513
- /** The request without options, for rendering an error raised while the real one was being built. */
13514
- #bareRequest(scope, raw3) {
13515
- try {
13516
- const request2 = new IncomingRequest(raw3);
13517
- scope.instance(HttpRequest, request2);
13518
- return request2;
13519
- } catch {
13520
- return void 0;
13521
- }
13522
- }
13523
- /** 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. */
13524
- async terminate(raw3, response2) {
13525
- const state = this.#requests.get(raw3);
13526
- if (state !== void 0) {
13527
- this.#requests.delete(raw3);
13528
- await state.scope.run(async () => {
13529
- const route2 = state.scope.bound(CurrentRoute) ? state.scope.make(CurrentRoute).middleware : [];
13530
- for (const middleware of [...state.middleware, ...route2]) {
13531
- if (typeof middleware.terminate !== "function") continue;
13532
- try {
13533
- await middleware.terminate(state.request, response2);
13534
- } catch (error) {
13535
- await this.#report(state.scope, error);
13536
- }
13537
- }
13538
- await this.app.terminate();
13539
- });
13540
- return;
13541
- }
13542
- await this.app.terminate();
13543
- }
13544
- #sendThroughGlobal(state) {
13545
- const { scope, request: request2 } = state;
13546
- const pipes = this.#middleware.map((cls) => {
13547
- const instance = scope.make(cls);
13548
- state.middleware.push(instance);
13549
- return (passable, next) => this.#guard(scope, passable, () => instance.handle(passable, next));
13550
- });
13551
- return scope.make(PipelineFactory).make().send(request2).through(pipes).then((passable) => this.#guard(scope, passable, () => this.#dispatch(scope, passable)));
13552
- }
13553
- #dispatch(scope, request2) {
13554
- return scope.make(Router).dispatch(request2);
13555
- }
13556
- /** Converts a Responsable result, and renders a thrown error at this stage (Laravel's Routing\Pipeline). */
13557
- async #guard(scope, request2, run) {
13558
- try {
13559
- const result = await run();
13560
- if (result instanceof Response) return result;
13561
- const responsable = result;
13562
- if (typeof responsable?.toResponse === "function") return await responsable.toResponse(request2);
13563
- throw new HttpServerError("Middleware must return a Response.");
13564
- } catch (error) {
13565
- if (!scope.bound(ExceptionHandler)) throw error;
13566
- const handler3 = scope.make(ExceptionHandler);
13567
- await handler3.report(error);
13568
- return handler3.render(request2, error);
13569
- }
13570
- }
13571
- /** Last resort: the handler failed or isn't bound. Never throws. */
13572
- async #renderLast(scope, request2, error) {
13573
- if (scope.bound(ExceptionHandler)) {
13574
- try {
13575
- const handler3 = scope.make(ExceptionHandler);
13576
- await handler3.report(error);
13577
- return await handler3.render(request2, error);
13578
- } catch (renderError2) {
13579
- console.error(renderError2);
13580
- }
13581
- } else {
13582
- console.error(error);
13583
- }
13584
- return plainServerError();
13585
- }
13586
- async #report(scope, error) {
13587
- try {
13588
- if (scope.bound(ExceptionHandler)) await scope.make(ExceptionHandler).report(error);
13589
- else console.error(error);
13590
- } catch (reportError) {
13591
- console.error(reportError);
13592
- }
13593
- }
13594
- /** config('http.max_body_size'): bytes, or null for no limit. Anything else is a configuration error. */
13595
- #maxBodySize() {
13596
- if (!this.app.bound(ConfigRepository)) return 8 * 1024 * 1024;
13597
- const value2 = this.app.make(ConfigRepository).get("http.max_body_size", 8 * 1024 * 1024);
13598
- if (value2 === null) return null;
13599
- if (typeof value2 === "number" && Number.isFinite(value2) && value2 >= 0) return value2;
13600
- throw new HttpServerError(
13601
- `Invalid http.max_body_size ${JSON.stringify(value2) ?? String(value2)}: use a number of bytes (0 or more), or null for no limit.`
13602
- );
13603
- }
13604
- /** config('http.trusted_proxies'): an array, or a comma-separated string such as '*' or '10.0.0.0/8,::1'. */
13605
- #trustedProxies() {
13606
- if (!this.app.bound(ConfigRepository)) return [];
13607
- const value2 = this.app.make(ConfigRepository).get("http.trusted_proxies", []);
13608
- if (typeof value2 === "string") return value2.split(",").map((entry) => entry.trim()).filter((entry) => entry !== "");
13609
- return Array.isArray(value2) ? value2.map(String) : [];
13610
- }
13611
- };
13612
- var MiddlewareConfiguration = class {
13613
- constructor(kernel, router, config2) {
13614
- this.kernel = kernel;
13615
- this.router = router;
13616
- this.config = config2;
13617
- }
13618
- kernel;
13619
- router;
13620
- config;
13621
- append(...middleware) {
13622
- this.kernel.appendMiddleware(...middleware);
13623
- return this;
13624
- }
13625
- prepend(...middleware) {
13626
- this.kernel.prependMiddleware(...middleware);
13627
- return this;
13628
- }
13629
- web(options) {
13630
- return this.#modifyGroup("web", options);
13631
- }
13632
- api(options) {
13633
- return this.#modifyGroup("api", options);
13634
- }
13635
- alias(aliases2) {
13636
- for (const [name, middleware] of Object.entries(aliases2)) this.router.aliasMiddleware(name, middleware);
13637
- return this;
13638
- }
13639
- group(name, middleware) {
13640
- this.router.middlewareGroup(name, middleware);
13641
- return this;
13642
- }
13643
- /** Stored in config('http.csrf_except'), which the Session component's VerifyCsrfToken reads. */
13644
- validateCsrfTokens(options) {
13645
- const current = this.config?.get("http.csrf_except", []) ?? [];
13646
- this.config?.set("http.csrf_except", [...current, ...options.except]);
13647
- return this;
13648
- }
13649
- /** Stored in config('http.redirect_guests_to'), which the Auth middleware and the exception handler read. */
13650
- redirectGuestsTo(url2) {
13651
- this.config?.set("http.redirect_guests_to", url2);
13652
- return this;
13653
- }
13654
- /** Laravel 11's redirectUsersTo(): stored in config('http.redirect_users_to') for Auth's RedirectIfAuthenticated. */
13655
- redirectUsersTo(url2) {
13656
- this.config?.set("http.redirect_users_to", url2);
13657
- return this;
13658
- }
13659
- /** Laravel's order: prepends, then the group minus removals, then appends. */
13660
- #modifyGroup(name, { append = [], prepend = [], remove = [] }) {
13661
- const current = this.router.getMiddlewareGroups()[name] ?? [];
13662
- const moved = /* @__PURE__ */ new Set([...append, ...prepend, ...remove]);
13663
- this.router.middlewareGroup(name, [...prepend, ...current.filter((entry) => !moved.has(entry)), ...append]);
13664
- return this;
13665
- }
13666
- };
13667
- function applyMiddlewareCallbacks(app2, kernel) {
13668
- if (!app2.bound(MiddlewareCallbacks)) return;
13669
- const callbacks = app2.make(MiddlewareCallbacks);
13670
- if (callbacks.length === 0) return;
13671
- const config2 = app2.bound(ConfigRepository) ? app2.make(ConfigRepository) : void 0;
13672
- const configurator = new MiddlewareConfiguration(kernel, app2.make(Router), config2);
13673
- for (const callback of callbacks) callback(configurator);
13674
- }
13675
- var STATUS_TEXTS = {
13676
- 400: "Bad Request",
13677
- 401: "Unauthorized",
13678
- 402: "Payment Required",
13679
- 403: "Forbidden",
13680
- 404: "Not Found",
13681
- 405: "Method Not Allowed",
13682
- 408: "Request Timeout",
13683
- 409: "Conflict",
13684
- 410: "Gone",
13685
- 413: "Content Too Large",
13686
- 415: "Unsupported Media Type",
13687
- 419: "Page Expired",
13688
- 422: "Unprocessable Content",
13689
- 429: "Too Many Requests",
13690
- 500: "Server Error",
13691
- 502: "Bad Gateway",
13692
- 503: "Service Unavailable",
13693
- 504: "Gateway Timeout"
13694
- };
13695
- function statusText(status) {
13696
- return STATUS_TEXTS[status] ?? (status >= 500 ? "Server Error" : "Error");
13697
- }
13698
- function escapeHtml(value2) {
13699
- return value2.replace(/[&<>"']/g, (char) => `&#${char.charCodeAt(0)};`);
13700
- }
13701
- function minimalPage(status, message) {
13702
- const title = escapeHtml(message);
13703
- return `<!DOCTYPE html>
13704
- <html lang="en">
13705
- <head>
13706
- <meta charset="utf-8">
13707
- <meta name="viewport" content="width=device-width, initial-scale=1">
13708
- <title>${title}</title>
13709
- <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>
13710
- </head>
13711
- <body><div class="code">${status}</div><div class="message">${title}</div></body>
13712
- </html>`;
13713
- }
13714
- function stackFrames(error) {
13715
- const frames = [];
13716
- for (const raw3 of (error.stack ?? "").split("\n").slice(1)) {
13717
- const text3 = raw3.trim();
13718
- const match = /(?:\(|@|at )((?:file:\/\/)?(?:\/|[A-Za-z]:\\)[^()]*?):(\d+):(\d+)\)?$/.exec(text3);
13719
- if (match === null) continue;
13720
- const location = match[1];
13721
- const file = location.startsWith("file://") ? fileURLToPath(location) : location;
13722
- frames.push({ file, line: Number(match[2]), column: Number(match[3]), text: text3 });
13723
- }
13724
- return frames;
13725
- }
13726
- async function excerpt(frame, radius = 5) {
13727
- const source = await readFile4(frame.file, "utf8").catch(() => void 0);
13728
- if (source === void 0) return void 0;
13729
- const lines = source.split("\n");
13730
- const start2 = Math.max(1, frame.line - radius);
13731
- const end = Math.min(lines.length, frame.line + radius);
13732
- const rows = [];
13733
- for (let number3 = start2; number3 <= end; number3++) {
13734
- const current = number3 === frame.line ? ' class="current"' : "";
13735
- rows.push(`<tr${current}><td class="n">${number3}</td><td><code>${escapeHtml(lines[number3 - 1] ?? "")}</code></td></tr>`);
13736
- }
13737
- return `<table class="source">${rows.join("")}</table>`;
13738
- }
13739
- async function debugPage(error, method, url2) {
13740
- const err = error instanceof Error ? error : new Error(String(error));
13741
- const frames = stackFrames(err);
13742
- const appFrame = frames.find((frame) => !frame.file.includes("node_modules") && !frame.file.startsWith("node:")) ?? frames[0];
13743
- const source = appFrame === void 0 ? void 0 : await excerpt(appFrame);
13744
- const causes = [];
13745
- for (let cause = err.cause, depth = 0; cause !== void 0 && depth < 5; cause = cause.cause, depth++) {
13746
- causes.push(`<li>${escapeHtml(cause instanceof Error ? `${cause.name}: ${cause.message}` : String(cause))}</li>`);
13747
- }
13748
- return `<!DOCTYPE html>
13749
- <html lang="en">
13750
- <head>
13751
- <meta charset="utf-8">
13752
- <title>${escapeHtml(err.message || err.name)}</title>
13753
- <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>
13754
- </head>
13755
- <body><main>
13756
- <header><div class="class">${escapeHtml(err.name)}</div><div class="message">${escapeHtml(err.message)}</div><div class="request">${escapeHtml(method)} ${escapeHtml(url2)}</div></header>
13757
- ${appFrame === void 0 ? "" : `<section><div>${escapeHtml(appFrame.file)}:${appFrame.line}</div>${source ?? ""}</section>`}
13758
- <section><ol>${frames.map((frame) => `<li>${escapeHtml(frame.text)}</li>`).join("")}</ol></section>
13759
- ${causes.length === 0 ? "" : `<section><div>Caused by</div><ul>${causes.join("")}</ul></section>`}
13760
- </main></body>
13761
- </html>`;
13762
- }
13763
- var NOT_REPORTED = /* @__PURE__ */ new Set(["Http", "ModelNotFound", "Validation", "Authentication", "Authorization", "TokenMismatch"]);
13764
- var HTTP_KINDS = /* @__PURE__ */ new Set(["Http", "ModelNotFound", "Authorization", "TokenMismatch"]);
13765
- var kindOf = (error) => typeof error === "object" && error !== null && typeof error.kind === "string" ? error.kind : void 0;
13766
- function statusFor(error) {
13767
- const status = error?.status;
13768
- switch (kindOf(error)) {
13769
- case "Http":
13770
- return status ?? 500;
13771
- case "ModelNotFound":
13772
- return 404;
13773
- case "Authorization":
13774
- return status ?? 403;
13775
- case "TokenMismatch":
13776
- return 419;
13777
- case "Authentication":
13778
- return 401;
13779
- case "Validation":
13780
- return status ?? 422;
13781
- case "Server":
13782
- return status ?? 500;
13783
- default:
13784
- return 500;
13785
- }
13786
- }
13787
- function summarizeValidation(errors2) {
13788
- const messages = Object.values(errors2).flat();
13789
- if (messages.length === 0) return "The given data was invalid.";
13790
- const more = messages.length - 1;
13791
- return more === 0 ? messages[0] : `${messages[0]} (and ${more} more ${more === 1 ? "error" : "errors"})`;
13792
- }
13793
- var isHttpLike = (error) => {
13794
- const kind = kindOf(error);
13795
- return kind !== void 0 && HTTP_KINDS.has(kind);
13796
- };
13797
- var ErrorHandler = class {
13798
- constructor(app2) {
13799
- this.app = app2;
13800
- }
13801
- app;
13802
- /** Input keys never flashed back on a validation redirect. */
13803
- dontFlash = ["current_password", "password", "password_confirmation"];
13804
- #reportCallbacks = [];
13805
- #renderCallbacks = [];
13806
- #dontReport = [];
13807
- #reported = /* @__PURE__ */ new WeakSet();
13808
- reportUsing(callback) {
13809
- this.#reportCallbacks.push(callback);
13810
- }
13811
- renderUsing(callback) {
13812
- this.#renderCallbacks.push(callback);
13813
- }
13814
- ignore(...classes) {
13815
- this.#dontReport.push(...classes);
13816
- }
13817
- shouldReport(error) {
13818
- const kind = kindOf(error);
13819
- if (kind !== void 0 && NOT_REPORTED.has(kind)) return false;
13820
- return !this.#dontReport.some((cls) => error instanceof cls);
13821
- }
13822
- /** Report callbacks first (returning false stops the default log), then LogManager.error(), else console.error. Once per error. */
13823
- async report(error) {
13824
- if (!this.shouldReport(error)) return;
13825
- if (typeof error === "object" && error !== null) {
13826
- if (this.#reported.has(error)) return;
13827
- this.#reported.add(error);
13828
- }
13829
- try {
13830
- for (const callback of this.#reportCallbacks) if (await callback(error) === false) return;
13831
- const container = this.#container();
13832
- if (container.bound(LogManager)) {
13833
- const message = error instanceof Error ? error.message : String(error);
13834
- container.make(LogManager).error(message, { exception: error });
13835
- } else {
13836
- console.error(error);
13837
- }
13838
- } catch (reportError) {
13839
- console.error(reportError);
13840
- }
13841
- }
13842
- async render(request2, error) {
13843
- for (const callback of this.#renderCallbacks) {
13844
- const response3 = await callback(error, request2);
13845
- if (response3 instanceof Response) return response3;
13846
- }
13847
- if (error instanceof HttpResponseException) return error.response;
13848
- const custom = await this.#renderCustom(request2, error);
13849
- if (custom !== void 0) return custom;
13850
- const http = this.#httpRequest(request2);
13851
- const kind = kindOf(error);
13852
- let response2;
13853
- if (kind === "Validation") response2 = await this.#renderValidation(http, error);
13854
- else if (kind === "Authentication") response2 = await this.#renderAuthentication(http, error);
13855
- else if (http.expectsJson()) response2 = this.#renderJson(error);
13856
- else response2 = await this.#renderHtml(http, error);
13857
- const headers = error?.headers;
13858
- if (headers !== void 0) for (const [name, value2] of Object.entries(headers)) response2.headers.set(name, value2);
13859
- return response2;
13860
- }
13861
- /** An error with its own render(request) or toResponse(request) (Laravel's renderable exceptions / Responsable). */
13862
- async #renderCustom(request2, error) {
13863
- if (typeof error !== "object" || error === null) return void 0;
13864
- const candidate = error;
13865
- for (const method of [candidate.render, candidate.toResponse]) {
13866
- if (typeof method !== "function") continue;
13867
- const response2 = await method.call(error, request2);
13868
- if (response2 instanceof Response) return response2;
13869
- }
13870
- return void 0;
13871
- }
13872
- async #renderValidation(request2, error) {
13873
- if (request2.expectsJson()) {
13874
- return this.#json({ message: summarizeValidation(error.errors), errors: error.errors }, statusFor(error));
13875
- }
13876
- const input = { ...request2.input() };
13877
- for (const key of this.dontFlash) delete input[key];
13878
- const container = this.#container();
13879
- if (!container.bound(Redirector)) {
13880
- return this.#redirect(error.redirectTo ?? request2.header("referer") ?? "/");
13881
- }
13882
- const redirector = container.make(Redirector);
13883
- const redirect2 = error.redirectTo !== void 0 ? redirector.to(error.redirectTo) : redirector.back();
13884
- const response2 = await redirect2.withInput(input).withErrors(error.errors, error.errorBag).toResponse(request2);
13885
- return response2;
13886
- }
13887
- async #renderAuthentication(request2, error) {
13888
- if (request2.expectsJson()) return this.#json({ message: error.message || "Unauthenticated." }, 401);
13889
- const target = error.redirectTo ?? this.#guestRedirect(request2);
13890
- const container = this.#container();
13891
- if (!container.bound(Redirector)) return this.#redirect(target);
13892
- const redirector = container.make(Redirector);
13893
- const redirect2 = typeof redirector.guest === "function" ? redirector.guest(target) : redirector.to(target);
13894
- return await redirect2.toResponse(request2);
13895
- }
13896
- /** config('http.redirect_guests_to'), then route('login'), then '/login'. */
13897
- #guestRedirect(request2) {
13898
- const configured = this.#config("http.redirect_guests_to", void 0);
13899
- if (typeof configured === "function") return String(configured(request2));
13900
- if (typeof configured === "string" && configured !== "") return configured;
13901
- const container = this.#container();
13902
- if (container.bound(UrlGenerator)) {
13903
- const url2 = container.make(UrlGenerator);
13904
- if (url2.hasRoute("login")) return url2.route("login");
13905
- }
13906
- return "/login";
13907
- }
13908
- #renderJson(error) {
13909
- const status = statusFor(error);
13910
- if (isHttpLike(error)) {
13911
- const message = error instanceof Error && error.message !== "" ? error.message : statusText(status);
13912
- return this.#json({ message }, status);
13913
- }
13914
- if (!this.#debug()) return this.#json({ message: "Server Error" }, status);
13915
- const err = error instanceof Error ? error : new Error(String(error));
13916
- const [frame] = stackFrames(err);
13917
- return this.#json(
13918
- {
13919
- message: err.message,
13920
- exception: err.name,
13921
- file: frame?.file,
13922
- line: frame?.line,
13923
- trace: stackFrames(err).map((entry) => entry.text)
13924
- },
13925
- status
13926
- );
13927
- }
13928
- async #renderHtml(request2, error) {
13929
- const status = statusFor(error);
13930
- if (!isHttpLike(error) && this.#debug()) {
13931
- return this.#html(await debugPage(error, request2.method(), request2.fullUrl()), status);
13932
- }
13933
- const message = status === 403 && error instanceof Error && error.message !== "" ? error.message : statusText(status);
13934
- const view2 = await this.#errorView(status, error, message);
13935
- return this.#html(view2 ?? minimalPage(status, message), status);
13936
- }
13937
- /** resources/views/errors/{status}.tsx, then errors/4xx or errors/5xx, through the ViewFactory. */
13938
- async #errorView(status, error, message) {
13939
- const container = this.#container();
13940
- if (!container.bound(ViewFactory)) return void 0;
13941
- const views = container.make(ViewFactory);
13942
- for (const name of [`errors.${status}`, `errors.${Math.floor(status / 100)}xx`]) {
13943
- if (!views.exists(name)) continue;
13944
- try {
13945
- return await views.make(name, { exception: error, status, message }).render();
13946
- } catch (viewError) {
13947
- await this.report(viewError);
13948
- return void 0;
13949
- }
13950
- }
13951
- return void 0;
13952
- }
13953
- #httpRequest(request2) {
13954
- if (typeof request2 === "object" && request2 !== null && typeof request2.expectsJson === "function") {
13955
- return request2;
13956
- }
13957
- return new IncomingRequest(request2 instanceof Request ? request2 : new Request("http://localhost/"));
13958
- }
13959
- #json(body, status) {
13960
- return new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json" } });
13961
- }
13962
- #html(body, status) {
13963
- return new Response(body, { status, headers: { "content-type": "text/html; charset=utf-8" } });
13964
- }
13965
- #redirect(location) {
13966
- return new Response(null, { status: 302, headers: { Location: location } });
13967
- }
13968
- #debug() {
13969
- return this.#config("app.debug", false) === true;
13970
- }
13971
- #config(key, fallback) {
13972
- return this.app.bound(ConfigRepository) ? this.app.make(ConfigRepository).get(key, fallback) : fallback;
13973
- }
13974
- /** The request scope while handling a request (so scoped services resolve), else the application. */
13975
- #container() {
13976
- return currentContainer() ?? this.app;
13977
- }
13978
- };
13979
- var ExceptionsConfiguration = class {
13980
- constructor(handler3) {
13981
- this.handler = handler3;
13982
- }
13983
- handler;
13984
- report(callback) {
13985
- this.handler.reportUsing(callback);
13986
- return this;
13987
- }
13988
- render(callback) {
13989
- this.handler.renderUsing(callback);
13990
- return this;
13991
- }
13992
- dontReport(...classes) {
13993
- this.handler.ignore(...classes);
13994
- return this;
13995
- }
13996
- };
13997
- function applyExceptionCallbacks(app2, handler3) {
13998
- if (!app2.bound(ExceptionCallbacks)) return;
13999
- const configurator = new ExceptionsConfiguration(handler3);
14000
- for (const callback of app2.make(ExceptionCallbacks)) callback(configurator);
14001
- }
14002
- var HIDDEN_SEGMENT = /^\.|\.(ts|tsx|mts|cts)$|[. ]$/i;
14003
- async function servePublicFile(publicPath, request2) {
14004
- if (request2.method !== "GET" && request2.method !== "HEAD") return void 0;
14005
- let pathname;
14006
- try {
14007
- pathname = decodeURIComponent(new URL(request2.url).pathname);
14008
- } catch {
14009
- return void 0;
14010
- }
14011
- if (pathname === "/" || pathname.includes("\0")) return void 0;
14012
- const root = resolve3(publicPath);
14013
- const file = resolve3(root, `.${pathname}`);
14014
- if (!file.startsWith(root + sep4)) return void 0;
14015
- if (relative5(root, file).split(/[\\/]/).some((segment) => HIDDEN_SEGMENT.test(segment))) return void 0;
14016
- const info = await stat22(file).catch(() => void 0);
14017
- if (info === void 0 || !info.isFile()) return void 0;
14018
- const type = mimeFromExtension2(file);
14019
- const headers = new Headers({
14020
- "content-type": type.startsWith("text/") || type === "application/json" ? `${type}; charset=utf-8` : type,
14021
- "content-length": String(info.size),
14022
- "last-modified": info.mtime.toUTCString()
14023
- });
14024
- if (pathname.startsWith("/build/assets/")) headers.set("cache-control", "public, max-age=31536000, immutable");
14025
- if (request2.method === "HEAD") return new Response(null, { status: 200, headers });
14026
- const body = Readable22.toWeb(createReadStream22(file));
14027
- return new Response(body, { status: 200, headers });
14028
- }
14029
- async function terminateRequest(app2, request2, response2) {
14030
- try {
14031
- if (app2.bound(HttpKernel)) await app2.make(HttpKernel).terminate?.(request2, response2);
14032
- } catch (error) {
14033
- console.error(error);
14034
- }
14035
- }
14036
- async function handleSafely(app2, request2, publicPath) {
14037
- try {
14038
- if (publicPath !== void 0) {
14039
- const file = await servePublicFile(publicPath, request2);
14040
- if (file !== void 0) return file;
14041
- }
14042
- return await app2.handle(request2);
14043
- } catch (error) {
14044
- console.error(error);
14045
- return plainServerError();
14046
- }
14047
- }
14048
- function exitOnSignals(close, closed) {
14049
- const onSignal = () => {
14050
- void close().then(() => process.exit(0));
14051
- };
14052
- process.once("SIGINT", onSignal);
14053
- process.once("SIGTERM", onSignal);
14054
- void closed.then(() => {
14055
- process.off("SIGINT", onSignal);
14056
- process.off("SIGTERM", onSignal);
14057
- });
14058
- }
14059
- var displayHost = (hostname) => hostname.includes(":") ? `[${hostname}]` : hostname;
14060
- function bunRuntime() {
14061
- return globalThis.Bun;
14062
- }
14063
- async function serveBun(app2, options) {
14064
- const bun = bunRuntime();
14065
- if (bun === void 0) throw new HttpServerError("Bun.serve is not available: the process is not running on Bun.");
14066
- let markClosed = () => void 0;
14067
- const closed = new Promise((resolve22) => markClosed = resolve22);
14068
- const server = bun.serve({
14069
- port: options.port,
14070
- hostname: options.hostname,
14071
- async fetch(request2, current) {
14072
- setClientAddress(request2, current.requestIP(request2)?.address);
14073
- const response2 = await handleSafely(app2, request2, options.publicPath);
14074
- setTimeout(() => void terminateRequest(app2, request2, response2), 0);
14075
- return response2;
14076
- },
14077
- error(error) {
14078
- console.error(error);
14079
- return plainServerError();
14080
- }
14081
- });
14082
- let closing;
14083
- const close = () => closing ??= (async () => {
14084
- let timer;
14085
- const forced = new Promise((resolve22) => {
14086
- timer = setTimeout(() => void Promise.resolve(server.stop(true)).then(resolve22), options.shutdownTimeout);
14087
- });
14088
- await Promise.race([Promise.resolve(server.stop(false)), forced]);
14089
- clearTimeout(timer);
14090
- markClosed();
14091
- })();
14092
- if (options.signals) exitOnSignals(close, closed);
14093
- return {
14094
- runtime: "bun",
14095
- hostname: options.hostname,
14096
- port: server.port,
14097
- url: `http://${displayHost(options.hostname)}:${server.port}`,
14098
- close,
14099
- closed
14100
- };
14101
- }
14102
- function requestBody(req) {
14103
- let finished = false;
14104
- const detach = () => {
14105
- finished = true;
14106
- req.off("data", onData);
14107
- req.off("end", onEnd);
14108
- req.off("error", onError);
14109
- req.off("close", onClose);
14110
- };
14111
- let controller;
14112
- const onData = (chunk) => {
14113
- if (finished) return;
14114
- controller.enqueue(new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength));
14115
- if ((controller.desiredSize ?? 0) <= 0) req.pause();
14116
- };
14117
- const onEnd = () => {
14118
- if (finished) return;
14119
- detach();
14120
- controller.close();
14121
- };
14122
- const onError = (error) => {
14123
- if (finished) return;
14124
- detach();
14125
- controller.error(error);
14126
- };
14127
- const onClose = () => {
14128
- if (!finished && !req.complete) onError(new Error("The request was aborted."));
14129
- };
14130
- return new ReadableStream(
14131
- {
14132
- start(c) {
14133
- controller = c;
14134
- req.on("data", onData);
14135
- req.on("end", onEnd);
14136
- req.on("error", onError);
14137
- req.on("close", onClose);
14138
- req.pause();
14139
- },
14140
- pull() {
14141
- req.resume();
14142
- },
14143
- cancel() {
14144
- detach();
14145
- }
14146
- },
14147
- { highWaterMark: 0 }
14148
- );
14149
- }
14150
- function toWebRequest(req, res, fallbackHost) {
14151
- const target = req.url ?? "/";
14152
- const url2 = new URL(`http://${req.headers.host ?? fallbackHost}${target.startsWith("/") ? target : `/${target}`}`);
14153
- const headers = new Headers();
14154
- for (let i = 0; i < req.rawHeaders.length; i += 2) {
14155
- const name = req.rawHeaders[i];
14156
- if (!name.startsWith(":")) headers.append(name, req.rawHeaders[i + 1]);
14157
- }
14158
- const method = (req.method ?? "GET").toUpperCase();
14159
- const controller = new AbortController();
14160
- res.once("close", () => {
14161
- if (!res.writableFinished) controller.abort();
14162
- });
14163
- const init = { method, headers, signal: controller.signal };
14164
- if (method !== "GET" && method !== "HEAD") {
14165
- init.body = requestBody(req);
14166
- init.duplex = "half";
14167
- }
14168
- return new Request(url2, init);
14169
- }
14170
- async function writeResponse(res, response2) {
14171
- res.statusCode = response2.status;
14172
- if (response2.statusText !== "") res.statusMessage = response2.statusText;
14173
- response2.headers.forEach((value2, name) => {
14174
- if (name !== "set-cookie") res.setHeader(name, value2);
14175
- });
14176
- const cookies = response2.headers.getSetCookie();
14177
- if (cookies.length > 0) res.setHeader("set-cookie", cookies);
14178
- if (response2.body === null) {
14179
- res.end();
14180
- return;
14181
- }
14182
- await pipeline2(Readable3.fromWeb(response2.body), res);
14183
- }
14184
- async function serveNode(app2, options) {
14185
- const fallbackHost = `${displayHost(options.hostname)}:${options.port}`;
14186
- const server = createServer((req, res) => {
14187
- void (async () => {
14188
- let request2;
14189
- try {
14190
- request2 = toWebRequest(req, res, fallbackHost);
14191
- } catch {
14192
- res.statusCode = 400;
14193
- res.end("Bad Request");
14194
- return;
14195
- }
14196
- setClientAddress(request2, req.socket.remoteAddress);
14197
- const response2 = await handleSafely(app2, request2, options.publicPath);
14198
- try {
14199
- await writeResponse(res, response2);
14200
- } catch {
14201
- res.destroy();
14202
- }
14203
- await terminateRequest(app2, request2, response2);
14204
- })();
14205
- });
14206
- await new Promise((resolve22, reject) => {
14207
- server.once("error", reject);
14208
- server.listen(options.port, options.hostname, () => {
14209
- server.off("error", reject);
14210
- resolve22();
14211
- });
14212
- });
14213
- const address = server.address();
14214
- const closed = new Promise((resolve22) => server.once("close", () => resolve22()));
14215
- let closing;
14216
- const close = () => closing ??= (async () => {
14217
- const done = new Promise((resolve22) => server.close(() => resolve22()));
14218
- server.closeIdleConnections();
14219
- const idle = setInterval(() => server.closeIdleConnections(), 50);
14220
- const force = setTimeout(() => server.closeAllConnections(), options.shutdownTimeout);
14221
- await done;
14222
- clearInterval(idle);
14223
- clearTimeout(force);
14224
- })();
14225
- if (options.signals) exitOnSignals(close, closed);
14226
- return {
14227
- runtime: "node",
14228
- hostname: options.hostname,
14229
- port: address.port,
14230
- url: `http://${displayHost(options.hostname)}:${address.port}`,
14231
- close,
14232
- closed
14233
- };
14234
- }
14235
- function detectRuntime() {
14236
- return bunRuntime() !== void 0 ? "bun" : "node";
14237
- }
14238
- async function serve(app2, options = {}) {
14239
- const resolved = {
14240
- port: options.port ?? Number(process.env.PORT ?? process.env.SERVER_PORT ?? 8e3),
14241
- hostname: options.hostname ?? "127.0.0.1",
14242
- signals: options.signals ?? true,
14243
- shutdownTimeout: options.shutdownTimeout ?? 1e4,
14244
- ...options.publicPath !== false && { publicPath: options.publicPath ?? app2.publicPath() }
14245
- };
14246
- await app2.boot();
14247
- const runtime = options.runtime ?? detectRuntime();
14248
- const server = runtime === "bun" ? await serveBun(app2, resolved) : await serveNode(app2, resolved);
14249
- const onListen = options.onListen ?? ((running) => console.log(`Server running on [${running.url}].`));
14250
- onListen(server);
14251
- return server;
14252
- }
14253
- function io(command) {
14254
- return {
14255
- option: (name) => {
14256
- const value2 = command.option(name);
14257
- return value2 === void 0 || value2 === null || value2 === false || value2 === "" ? void 0 : String(value2);
14258
- },
14259
- flag: (name) => {
14260
- const value2 = command.option(name);
14261
- return value2 === true || value2 === "true" || value2 === "1";
14262
- },
14263
- info: (message) => command.info(message),
14264
- line: (message) => command.line(message),
14265
- warn: (message) => command.warn(message),
14266
- error: (message) => command.error(message)
14267
- };
14268
- }
14269
- var middlewareName = (reference) => typeof reference === "string" ? reference : reference.name;
14270
- function routeListRows(routes) {
14271
- const rows = routes.map((route2) => {
14272
- const listable = route2;
14273
- return {
14274
- method: route2.methods.join("|"),
14275
- uri: route2.uri,
14276
- name: route2.getName() ?? null,
14277
- action: typeof listable.getActionName === "function" ? listable.getActionName() : "Closure",
14278
- middleware: typeof listable.gatherMiddleware === "function" ? listable.gatherMiddleware().map(middlewareName) : []
14279
- };
14280
- });
14281
- return rows.sort((a, b) => a.uri < b.uri ? -1 : a.uri > b.uri ? 1 : 0);
14282
- }
14283
- function filterRouteList(rows, filters) {
14284
- const excluded2 = (filters.exceptPath ?? "").split(",").filter((path) => path !== "");
14285
- return rows.filter((row) => {
14286
- if (filters.name !== void 0 && !(row.name ?? "").includes(filters.name)) return false;
14287
- if (filters.path !== void 0 && !row.uri.includes(filters.path)) return false;
14288
- if (filters.method !== void 0 && !row.method.includes(filters.method.toUpperCase())) return false;
14289
- return !excluded2.some((path) => row.uri.includes(path));
14290
- });
14291
- }
14292
- function formatRouteList(rows, width) {
14293
- const methodWidth = Math.max(...rows.map((row) => row.method.length));
14294
- const lines = rows.map((row) => {
14295
- const spaces = " ".repeat(Math.max(methodWidth + 6 - row.method.length, 0));
14296
- const action = row.action === "Closure" ? row.name ?? "" : row.name === null ? row.action : `${row.name} \u203A ${row.action}`;
14297
- const used = row.method.length + spaces.length + row.uri.length + action.length + 6 + (action === "" ? 0 : 1);
14298
- const dots = ".".repeat(Math.max(width - used, 0));
14299
- return ` ${row.method} ${spaces}${row.uri}${dots === "" ? "" : ` ${dots}`}${action === "" ? "" : ` ${action}`}`;
14300
- });
14301
- const count = `Showing [${rows.length}] ${rows.length === 1 ? "route" : "routes"}`;
14302
- return [...lines, "", `${" ".repeat(Math.max(width - count.length - 2, 0))}${count}`];
14303
- }
14304
- var API_ROUTES_STUB = `import { request, Route } from '@orieljs/framework'
14305
-
14306
- Route.get('/user', () => request().user()).middleware('auth:token')
14307
- `;
14308
- function addApiRouting(source) {
14309
- const code = source.replace(/^[ \t]*\/\/.*$/gm, "");
14310
- if (/withRouting\(\s*\{[^}]*\bapi\s*:/.test(code)) return source;
14311
- const commented = /^([ \t]*)\/\/\s*(api:\s*['"`][^'"`\n]*['"`],?)[ \t]*$/m.exec(source);
14312
- if (commented !== null) return source.replace(commented[0], () => `${commented[1]}${commented[2]}`);
14313
- const web = /^([ \t]*)web:\s*(['"`])[^'"`\n]*\2[ \t]*,?[ \t]*$/m.exec(source);
14314
- if (web !== null) {
14315
- const line = web[0].trimEnd();
14316
- return source.replace(web[0], () => `${line.endsWith(",") ? line : `${line},`}
14317
- ${web[1]}api: 'routes/api.ts',`);
14318
- }
14319
- const inline = /withRouting\(\s*\{/.exec(source);
14320
- if (inline !== null) return source.replace(inline[0], () => `${inline[0]} api: 'routes/api.ts',`);
14321
- const create = /^([ \t]*)\.create\(\)/m.exec(source);
14322
- if (create !== null) return source.replace(create[0], () => `${create[1]}.withRouting({ api: 'routes/api.ts' })
14323
- ${create[0]}`);
14324
- return void 0;
14325
- }
14326
- function registerHttpCommands(kernel, app2, options = {}) {
14327
- const serveApp = options.serve ?? serve;
14328
- const terminalWidth = options.terminalWidth ?? (() => process.stdout.columns ?? 120);
14329
- kernel.command(
14330
- "serve {--host=127.0.0.1 : The host address to serve the application on} {--port= : The port to serve the application on}",
14331
- async function() {
14332
- const out = io(this);
14333
- const port = out.option("port");
14334
- if (port !== void 0 && !/^\d+$/.test(port)) {
14335
- out.error("The --port option must be a number.");
14336
- return 1;
14337
- }
14338
- const server = await serveApp(app2, {
14339
- hostname: out.option("host") ?? "127.0.0.1",
14340
- ...port !== void 0 && { port: Number(port) },
14341
- onListen: (running) => {
14342
- out.info(`Server running on [${running.url}].`);
14343
- out.line("Press Ctrl+C to stop the server");
14344
- }
14345
- });
14346
- await server.closed;
14347
- return 0;
14348
- }
14349
- ).purpose("Serve the application on the Oriel development server");
14350
- kernel.command(
14351
- "route:list {--method= : Filter the routes by method} {--name= : Filter the routes by name} {--path= : Only show routes matching the given path pattern} {--except-path= : Do not display the routes matching the given path pattern} {--reverse : Reverse the ordering of the routes} {--json : Output the route list as JSON}",
14352
- function() {
14353
- const out = io(this);
14354
- if (!app2.bound(Router)) {
14355
- out.error("The router is not available. Is the Routing service provider registered?");
14356
- return 1;
14357
- }
14358
- const all = routeListRows(app2.make(Router).getRoutes());
14359
- if (all.length === 0) {
14360
- out.error("Your application doesn't have any routes.");
14361
- return 0;
14362
- }
14363
- const rows = filterRouteList(all, {
14364
- ...out.option("method") !== void 0 && { method: out.option("method") },
14365
- ...out.option("name") !== void 0 && { name: out.option("name") },
14366
- ...out.option("path") !== void 0 && { path: out.option("path") },
14367
- ...out.option("except-path") !== void 0 && { exceptPath: out.option("except-path") }
14368
- });
14369
- if (rows.length === 0) {
14370
- out.error("Your application doesn't have any routes matching the given criteria.");
14371
- return 0;
14372
- }
14373
- if (out.flag("reverse")) rows.reverse();
14374
- if (out.flag("json")) {
14375
- out.line(JSON.stringify(rows));
14376
- return 0;
14377
- }
14378
- for (const line of formatRouteList(rows, terminalWidth())) out.line(line);
14379
- return 0;
14380
- }
14381
- ).purpose("List all registered routes");
14382
- kernel.command("install:api {--force : Overwrite any existing API routes file}", async function() {
14383
- const out = io(this);
14384
- const routesFile = app2.basePath("routes/api.ts");
14385
- if (existsSync7(routesFile) && !out.flag("force")) {
14386
- out.error("API routes file already exists.");
14387
- } else {
14388
- await mkdir5(dirname5(routesFile), { recursive: true });
14389
- await writeFile6(routesFile, API_ROUTES_STUB);
14390
- out.info("Published API routes file.");
14391
- }
14392
- const bootstrapFile = app2.bootstrapPath("app.ts");
14393
- const source = existsSync7(bootstrapFile) ? await readFile22(bootstrapFile, "utf8") : void 0;
14394
- const updated = source === void 0 ? void 0 : addApiRouting(source);
14395
- if (updated === void 0) {
14396
- out.warn(
14397
- "Unable to automatically add API route definition to bootstrap file. Add api: 'routes/api.ts' to withRouting() in bootstrap/app.ts."
14398
- );
14399
- } else if (updated !== source) {
14400
- await writeFile6(bootstrapFile, updated);
14401
- }
14402
- out.info("API scaffolding installed. Run [oriel migrate] to create the personal access tokens table.");
14403
- return 0;
14404
- }).purpose("Create an API routes file and prepare the application for API authentication");
14405
- }
14406
- var HttpServiceProvider = class extends ServiceProvider {
14407
- register() {
14408
- this.mergeConfigFrom(
14409
- {
14410
- trusted_proxies: [],
14411
- max_body_size: 8 * 1024 * 1024,
14412
- csrf_except: [],
14413
- redirect_guests_to: void 0,
14414
- redirect_users_to: void 0
14415
- },
14416
- "http"
14417
- );
14418
- this.app.singleton(HttpKernel, () => new Kernel2(this.app));
14419
- this.app.singleton(ExceptionHandler, () => {
14420
- const handler3 = new ErrorHandler(this.app);
14421
- applyExceptionCallbacks(this.app, handler3);
14422
- return handler3;
14423
- });
14424
- this.app.singleton(ResponseFactory, () => new HttpResponseFactory());
14425
- this.app.singleton(Redirector, () => new HttpRedirector());
14426
- }
14427
- boot() {
14428
- this.app.booted(() => {
14429
- const kernel = this.app.make(HttpKernel);
14430
- if (kernel instanceof Kernel2 && this.app.bound(Router)) applyMiddlewareCallbacks(this.app, kernel);
14431
- });
14432
- if (this.app.bound(ConsoleKernel)) registerHttpCommands(this.app.make(ConsoleKernel), this.app);
14433
- }
14434
- };
14435
-
14436
- // ../Inertia/dist/index.js
14437
- import { existsSync as existsSync8 } from "fs";
14438
- import { join as join10 } from "path";
14439
- import { createHash as createHash5 } from "crypto";
14440
- import { existsSync as existsSync23, readFileSync } from "fs";
14441
- import { spawn as spawn2 } from "child_process";
14442
- import { existsSync as existsSync33 } from "fs";
14443
- import { mkdir as mkdir6, writeFile as writeFile7 } from "fs/promises";
14444
- import { dirname as dirname6, isAbsolute as isAbsolute2, join as join24, relative as relative6 } from "path";
14445
- import { existsSync as existsSync42, readFileSync as readFileSync2 } from "fs";
14446
- var Header = {
14447
- INERTIA: "X-Inertia",
14448
- ERROR_BAG: "X-Inertia-Error-Bag",
14449
- LOCATION: "X-Inertia-Location",
14450
- REDIRECT: "X-Inertia-Redirect",
14451
- VERSION: "X-Inertia-Version",
14452
- PARTIAL_COMPONENT: "X-Inertia-Partial-Component",
14453
- PARTIAL_ONLY: "X-Inertia-Partial-Data",
14454
- PARTIAL_EXCEPT: "X-Inertia-Partial-Except",
14455
- RESET: "X-Inertia-Reset",
14456
- INFINITE_SCROLL_MERGE_INTENT: "X-Inertia-Infinite-Scroll-Merge-Intent",
14457
- EXCEPT_ONCE_PROPS: "X-Inertia-Except-Once-Props"
14458
- };
14459
- function parseList(value2) {
14460
- const items = (value2 ?? "").split(",").filter((item) => item !== "");
14461
- return items.length === 0 ? void 0 : items;
14462
- }
14463
- var Prop = class {
14464
- constructor(value2) {
14465
- this.value = value2;
14466
- }
14467
- value;
14468
- mergeState = { merge: false, deep: false, append: true, appendPaths: [], prependPaths: [], matchOn: [] };
14469
- onceState = { once: false, fresh: false, key: void 0, ttlSeconds: void 0 };
14470
- deferred = false;
14471
- deferGroup;
14472
- /** Calls the callback, if the value is one. */
14473
- async resolve() {
14474
- return typeof this.value === "function" ? await this.value() : this.value;
14475
- }
14476
- /** Never sent on the first load (OptionalProp, DeferProp). */
14477
- ignoresFirstLoad() {
14478
- return false;
14479
- }
14480
- /** Sent even when a partial reload didn't ask for it (AlwaysProp). */
14481
- isAlways() {
14482
- return false;
14483
- }
14484
- /** Errors are reported and the prop is left out, instead of failing the page (defer(..., { rescue: true })). */
14485
- shouldRescue() {
14486
- return false;
14487
- }
14488
- // Once (honoured by OptionalProp, DeferProp, MergeProp and OnceProp) ------------------------------------
14489
- /** once(), once(false), once(true, { as: 'key', until: 3600 }). */
14490
- once(value2 = true, options = {}) {
14491
- this.onceState.once = value2;
14492
- if (options.as !== void 0) this.onceState.key = options.as;
14493
- if (options.until !== void 0) this.onceState.ttlSeconds = secondsUntil(options.until);
14494
- return this;
14495
- }
14496
- /** A custom once key, so pages can share the prop under different names. */
14497
- as(key) {
14498
- this.onceState.key = key;
14499
- return this;
14500
- }
14501
- /** Send the prop again even though the client already has it. */
14502
- fresh(value2 = true) {
14503
- this.onceState.fresh = value2;
14504
- return this;
14505
- }
14506
- /** Expire after a number of seconds, or at a Date. */
14507
- until(delay) {
14508
- this.onceState.ttlSeconds = secondsUntil(delay);
14509
- return this;
14510
- }
14511
- // Merging -------------------------------------------------------------------------------------------------
14512
- isMergeable() {
14513
- return false;
14514
- }
14515
- shouldMerge() {
14516
- return this.isMergeable() && this.mergeState.merge;
14517
- }
14518
- shouldDeepMerge() {
14519
- return this.mergeState.deep;
14520
- }
14521
- matchesOn() {
14522
- return [...this.mergeState.matchOn];
12977
+ matchesOn() {
12978
+ return [...this.mergeState.matchOn];
14523
12979
  }
14524
12980
  appendsAtRoot() {
14525
12981
  return this.mergeState.append && this.mergesAtRoot();
@@ -15097,9 +13553,9 @@ var Response2 = class {
15097
13553
  }
15098
13554
  };
15099
13555
  function pageExists(component, paths, extensions) {
15100
- return paths.some((path) => extensions.some((extension) => existsSync8(join10(path, `${component}.${extension}`))));
13556
+ return paths.some((path) => extensions.some((extension) => existsSync7(join10(path, `${component}.${extension}`))));
15101
13557
  }
15102
- var ResponseFactory2 = class _ResponseFactory {
13558
+ var ResponseFactory = class _ResponseFactory {
15103
13559
  constructor(app2, parent) {
15104
13560
  this.app = app2;
15105
13561
  this.parent = parent;
@@ -15224,7 +13680,7 @@ function inertiaFactory() {
15224
13680
  const container = currentContainer();
15225
13681
  if (container === void 0) throw new ContainerNotAvailableError("Inertia");
15226
13682
  if (container.bound(HttpRequest)) return container.make(InertiaFactory);
15227
- return container.make(Application).make(ResponseFactory2);
13683
+ return container.make(Application).make(ResponseFactory);
15228
13684
  }
15229
13685
  function inertia(component, props = {}) {
15230
13686
  const factory = inertiaFactory();
@@ -15400,7 +13856,7 @@ function isEmpty(response2) {
15400
13856
  return response2.status === 200 && (response2.body === null || response2.headers.get("content-length") === "0");
15401
13857
  }
15402
13858
  function md5(value2) {
15403
- return createHash5("md5").update(value2).digest("hex");
13859
+ return createHash7("md5").update(value2).digest("hex");
15404
13860
  }
15405
13861
  var EncryptHistory = class {
15406
13862
  #container = inject(Container);
@@ -15479,6 +13935,7 @@ export class {{ class }} extends InertiaMiddleware {
15479
13935
  }
15480
13936
  }
15481
13937
  `;
13938
+ var DEFAULT_EXCEPT_ROUTES = ["live.*"];
15482
13939
  async function loadPageTypes() {
15483
13940
  const specifier = "@orieljs/vite/types";
15484
13941
  try {
@@ -15502,12 +13959,12 @@ function registerInertiaCommands(kernel, app2, gateway, options = {}) {
15502
13959
  }
15503
13960
  const output = absolute(optionText(this.option("output")) ?? config2("inertia.types.routes", "resources/js/oriel/routes.ts"));
15504
13961
  const server = absolute(optionText(this.option("server")) ?? config2("inertia.types.server_routes", "types/routes.d.ts"));
15505
- const table = routeTable(app2.make(Router).getRoutes(), config2("inertia.types.except_routes", []));
15506
- await mkdir6(dirname6(output), { recursive: true });
15507
- await writeFile7(output, renderRoutesModule(table));
15508
- await mkdir6(dirname6(server), { recursive: true });
15509
- await writeFile7(server, renderServerRouteTypes(routeTable(app2.make(Router).getRoutes())));
15510
- this.info(`Route types for ${Object.keys(table).length} named routes written to ${relative6(app2.basePath(), output)}.`);
13962
+ const table = routeTable(app2.make(Router).getRoutes(), config2("inertia.types.except_routes", DEFAULT_EXCEPT_ROUTES));
13963
+ await mkdir5(dirname5(output), { recursive: true });
13964
+ await writeFile6(output, renderRoutesModule(table));
13965
+ await mkdir5(dirname5(server), { recursive: true });
13966
+ await writeFile6(server, renderServerRouteTypes(routeTable(app2.make(Router).getRoutes())));
13967
+ this.info(`Route types for ${Object.keys(table).length} named routes written to ${relative5(app2.basePath(), output)}.`);
15511
13968
  return 0;
15512
13969
  }
15513
13970
  ).purpose("Generate the route table and route name types for the frontend");
@@ -15520,7 +13977,7 @@ function registerInertiaCommands(kernel, app2, gateway, options = {}) {
15520
13977
  const output = absolute(optionText(this.option("output")) ?? config2("inertia.types.pages", "resources/js/oriel/pages.d.ts"));
15521
13978
  const result = await module.generatePageTypes({ root: app2.basePath(), output });
15522
13979
  for (const warning of result.warnings) this.warn(warning);
15523
- this.info(`Page types for ${result.pages} pages written to ${relative6(app2.basePath(), result.output)}.`);
13980
+ this.info(`Page types for ${result.pages} pages written to ${relative5(app2.basePath(), result.output)}.`);
15524
13981
  return 0;
15525
13982
  }).purpose("Generate TypeScript types for the Inertia page props");
15526
13983
  kernel.command("inertia:middleware {name=HandleInertiaRequests : The middleware class name} {--force : Overwrite an existing file}", async function() {
@@ -15531,12 +13988,12 @@ function registerInertiaCommands(kernel, app2, gateway, options = {}) {
15531
13988
  }
15532
13989
  const file = app2.appPath(join24("Http", "Middleware", `${name}.ts`));
15533
13990
  if (existsSync33(file) && this.option("force") !== true) {
15534
- this.error(`Middleware [${relative6(app2.basePath(), file)}] already exists.`);
13991
+ this.error(`Middleware [${relative5(app2.basePath(), file)}] already exists.`);
15535
13992
  return 1;
15536
13993
  }
15537
- await mkdir6(dirname6(file), { recursive: true });
15538
- await writeFile7(file, MIDDLEWARE_STUB2.replace("{{ class }}", () => name));
15539
- this.info(`Middleware [${relative6(app2.basePath(), file)}] created successfully.`);
13994
+ await mkdir5(dirname5(file), { recursive: true });
13995
+ await writeFile6(file, MIDDLEWARE_STUB2.replace("{{ class }}", () => name));
13996
+ this.info(`Middleware [${relative5(app2.basePath(), file)}] created successfully.`);
15540
13997
  return 0;
15541
13998
  }).purpose("Create a new Inertia middleware");
15542
13999
  kernel.command("inertia:start-ssr {--runtime= : The runtime that runs the SSR bundle (node or bun)}", async function() {
@@ -15549,13 +14006,18 @@ function registerInertiaCommands(kernel, app2, gateway, options = {}) {
15549
14006
  this.error("Inertia SSR bundle not found. Build it with `vite build --ssr`, or set `inertia.ssr.bundle`.");
15550
14007
  return 1;
15551
14008
  }
14009
+ const port = urlPort(gateway.productionUrl());
14010
+ if (port === void 0) {
14011
+ this.error(`inertia.ssr.url [${gateway.productionUrl()}] is not a URL.`);
14012
+ return 1;
14013
+ }
15552
14014
  const runtime = optionText(this.option("runtime")) ?? config2("inertia.ssr.runtime", "node");
15553
- const child = (options.spawn ?? spawn2)(runtime, [bundle], { stdio: "inherit" });
15554
- return await new Promise((resolve4) => {
15555
- child.on("exit", (code) => resolve4(code ?? 0));
14015
+ const child = (options.spawn ?? spawn2)(runtime, [bundle], { stdio: "inherit", env: { ...process.env, INERTIA_SSR_PORT: port } });
14016
+ return await new Promise((resolve3) => {
14017
+ child.on("exit", (code) => resolve3(code ?? 0));
15556
14018
  child.on("error", (error) => {
15557
14019
  this.error(`Could not start the SSR server: ${error.message}`);
15558
- resolve4(1);
14020
+ resolve3(1);
15559
14021
  });
15560
14022
  });
15561
14023
  }).purpose("Start the Inertia SSR server");
@@ -15576,6 +14038,15 @@ function registerInertiaCommands(kernel, app2, gateway, options = {}) {
15576
14038
  return 1;
15577
14039
  }).purpose("Check the Inertia SSR server health status");
15578
14040
  }
14041
+ function urlPort(url2) {
14042
+ try {
14043
+ const parsed = new URL(url2);
14044
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return void 0;
14045
+ return parsed.port !== "" ? parsed.port : parsed.protocol === "https:" ? "443" : "80";
14046
+ } catch {
14047
+ return void 0;
14048
+ }
14049
+ }
15579
14050
  function optionText(value2) {
15580
14051
  return value2 === void 0 || value2 === null || value2 === false || value2 === "" ? void 0 : String(value2);
15581
14052
  }
@@ -15703,12 +14174,13 @@ var InertiaServiceProvider = class extends ServiceProvider {
15703
14174
  expose_shared_prop_keys: true,
15704
14175
  store_previous_url: false,
15705
14176
  history: { encrypt: false },
15706
- types: { pages: "resources/js/oriel/pages.d.ts", routes: "resources/js/oriel/routes.ts", server_routes: "types/routes.d.ts", except_routes: [] }
14177
+ // live.* (Live's update endpoint) stays out of the browser's route table; the server's route names keep it.
14178
+ types: { pages: "resources/js/oriel/pages.d.ts", routes: "resources/js/oriel/routes.ts", server_routes: "types/routes.d.ts", except_routes: [...DEFAULT_EXCEPT_ROUTES] }
15707
14179
  },
15708
14180
  "inertia"
15709
14181
  );
15710
- this.app.singleton(ResponseFactory2, () => new ResponseFactory2(this.app));
15711
- this.app.scoped(InertiaFactory, (container) => container.make(ResponseFactory2).forRequest());
14182
+ this.app.singleton(ResponseFactory, () => new ResponseFactory(this.app));
14183
+ this.app.scoped(InertiaFactory, (container) => container.make(ResponseFactory).forRequest());
15712
14184
  this.app.singleton(HttpGateway, () => new HttpGateway(this.app));
15713
14185
  this.app.singleton(InertiaSsrGateway, (container) => container.make(HttpGateway));
15714
14186
  }
@@ -15721,7 +14193,7 @@ var InertiaServiceProvider = class extends ServiceProvider {
15721
14193
  // ../Log/dist/index.js
15722
14194
  import pino2 from "pino";
15723
14195
  import { createWriteStream as createWriteStream2, mkdirSync as mkdirSync2, readdirSync as readdirSync5, rmSync } from "fs";
15724
- import { basename as basename3, dirname as dirname7, extname as extname3, join as join11 } from "path";
14196
+ import { basename as basename2, dirname as dirname6, extname as extname3, join as join11 } from "path";
15725
14197
  import { Writable } from "stream";
15726
14198
  import "pino";
15727
14199
  var rootKey = {};
@@ -15843,12 +14315,12 @@ function localDay(date) {
15843
14315
  }
15844
14316
  var DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
15845
14317
  var DailyRotatingStream = class extends Writable {
15846
- constructor(basePath, days, now4 = () => /* @__PURE__ */ new Date()) {
14318
+ constructor(basePath, days, now5 = () => /* @__PURE__ */ new Date()) {
15847
14319
  super();
15848
14320
  this.days = days;
15849
- this.now = now4;
15850
- this.dir = dirname7(basePath);
15851
- this.stem = basename3(basePath, extname3(basePath) || void 0);
14321
+ this.now = now5;
14322
+ this.dir = dirname6(basePath);
14323
+ this.stem = basename2(basePath, extname3(basePath) || void 0);
15852
14324
  mkdirSync2(this.dir, { recursive: true });
15853
14325
  }
15854
14326
  days;
@@ -15913,8 +14385,8 @@ var DailyRotatingStream = class extends Writable {
15913
14385
  prune() {
15914
14386
  if (this.days <= 0) return;
15915
14387
  const prefix = `${this.stem}-`;
15916
- const now4 = this.now();
15917
- const cutoff = new Date(now4.getFullYear(), now4.getMonth(), now4.getDate() - (this.days - 1)).getTime();
14388
+ const now5 = this.now();
14389
+ const cutoff = new Date(now5.getFullYear(), now5.getMonth(), now5.getDate() - (this.days - 1)).getTime();
15918
14390
  for (const file of readdirSync5(this.dir)) {
15919
14391
  if (!file.startsWith(prefix) || !file.endsWith(".log")) continue;
15920
14392
  const match = DATE_PATTERN.exec(file.slice(prefix.length, -".log".length));
@@ -15977,9 +14449,9 @@ function createSingleChannel(path, minimumLevel = "debug") {
15977
14449
  destination.on("error", (error) => reportLogWriteFailure(path, error));
15978
14450
  return new PinoLogger(pino2(PINO_OPTIONS, destination), minimumLevel);
15979
14451
  }
15980
- function createDailyChannel(path, days = 14, minimumLevel = "debug", now4) {
14452
+ function createDailyChannel(path, days = 14, minimumLevel = "debug", now5) {
15981
14453
  assertLogLevel(minimumLevel);
15982
- const stream = new DailyRotatingStream(path, days, now4);
14454
+ const stream = new DailyRotatingStream(path, days, now5);
15983
14455
  return new PinoLogger(pino2(PINO_OPTIONS, stream), minimumLevel);
15984
14456
  }
15985
14457
  function createStderrChannel(minimumLevel = "debug") {
@@ -16682,7 +15154,8 @@ var MailMessage = class {
16682
15154
  introLines = [];
16683
15155
  actionData;
16684
15156
  outroLines = [];
16685
- salutationLine = "Regards,\nApplication";
15157
+ /** Unset: "Regards," and config('app.name'), as Laravel's template. */
15158
+ salutationLine;
16686
15159
  toAddresses = [];
16687
15160
  ccAddresses = [];
16688
15161
  bccAddresses = [];
@@ -16747,11 +15220,18 @@ var MailMessage = class {
16747
15220
  html2.push(`<p>${escapeHtml2(line)}</p>`);
16748
15221
  text3.push(line);
16749
15222
  }
16750
- html2.push(`<p>${escapeHtml2(this.salutationLine).replace(/\n/g, "<br>")}</p>`);
16751
- text3.push(this.salutationLine);
15223
+ const salutation = this.salutationLine ?? `Regards,
15224
+ ${appName()}`;
15225
+ html2.push(`<p>${escapeHtml2(salutation).replace(/\n/g, "<br>")}</p>`);
15226
+ text3.push(salutation);
16752
15227
  return { html: `<!doctype html><html><body>${html2.join("\n")}</body></html>`, text: text3.join("\n\n") };
16753
15228
  }
16754
15229
  };
15230
+ function appName() {
15231
+ const container = currentContainer();
15232
+ const name = container?.bound(ConfigRepository) ? container.make(ConfigRepository).get("app.name") : void 0;
15233
+ return typeof name === "string" && name !== "" ? name : "Oriel";
15234
+ }
16755
15235
  function escapeHtml2(value2) {
16756
15236
  return value2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
16757
15237
  }
@@ -16822,9 +15302,9 @@ function wrapRow(row, db) {
16822
15302
  readAt: row.read_at ? parseStoredDate2(row.read_at) : void 0,
16823
15303
  async markAsRead() {
16824
15304
  if (record.readAt) return;
16825
- const now4 = /* @__PURE__ */ new Date();
16826
- await db.table(NOTIFICATIONS_TABLE).where("id", record.id).update({ read_at: now4, updated_at: now4 });
16827
- record.readAt = now4;
15305
+ const now5 = /* @__PURE__ */ new Date();
15306
+ await db.table(NOTIFICATIONS_TABLE).where("id", record.id).update({ read_at: now5, updated_at: now5 });
15307
+ record.readAt = now5;
16828
15308
  },
16829
15309
  async markAsUnread() {
16830
15310
  if (!record.readAt) return;
@@ -16856,7 +15336,7 @@ var DatabaseNotificationChannel = class {
16856
15336
  const model = notifiable;
16857
15337
  if (typeof model.getKey !== "function") throw new NotDatabaseNotifiableError(notifiable.constructor.name);
16858
15338
  const db = requireDatabase();
16859
- const now4 = /* @__PURE__ */ new Date();
15339
+ const now5 = /* @__PURE__ */ new Date();
16860
15340
  await db.table(NOTIFICATIONS_TABLE).insert({
16861
15341
  id: notification.id ?? randomUUID4(),
16862
15342
  type: notification.constructor.name,
@@ -16864,8 +15344,8 @@ var DatabaseNotificationChannel = class {
16864
15344
  notifiable_id: model.getKey(),
16865
15345
  data: JSON.stringify(data),
16866
15346
  read_at: null,
16867
- created_at: now4,
16868
- updated_at: now4
15347
+ created_at: now5,
15348
+ updated_at: now5
16869
15349
  });
16870
15350
  }
16871
15351
  };
@@ -17207,7 +15687,7 @@ import { randomUUID as randomUUID24 } from "crypto";
17207
15687
  import { Redis as Redis2 } from "ioredis";
17208
15688
  import { randomUUID as randomUUID32 } from "crypto";
17209
15689
  import { setTimeout as sleep4 } from "timers/promises";
17210
- import { existsSync as existsSync9, readdirSync as readdirSync6, statSync as statSync3 } from "fs";
15690
+ import { existsSync as existsSync8, readdirSync as readdirSync6, statSync as statSync3 } from "fs";
17211
15691
  import { join as join12 } from "path";
17212
15692
  import { pathToFileURL as pathToFileURL6 } from "url";
17213
15693
  var QueueError = class extends Error {
@@ -17312,7 +15792,7 @@ function resolveClass(registry2, name) {
17312
15792
  if (!registry2.has(name)) throw new JobClassNotFoundError(name);
17313
15793
  return registry2.resolve(name);
17314
15794
  }
17315
- function isPlainObject3(value2) {
15795
+ function isPlainObject2(value2) {
17316
15796
  const proto = Object.getPrototypeOf(value2);
17317
15797
  return proto === Object.prototype || proto === null;
17318
15798
  }
@@ -17366,7 +15846,7 @@ function serializeValue(value2, registry2, path = "data", seen = /* @__PURE__ */
17366
15846
  }
17367
15847
  return { [TAG]: "model", class: name2, key: serializeValue(object.getKey(), registry2, `${path}.key`, seen) ?? null };
17368
15848
  }
17369
- if (isPlainObject3(object)) {
15849
+ if (isPlainObject2(object)) {
17370
15850
  const fields = serializeFields(object, registry2, path, seen);
17371
15851
  return Object.hasOwn(fields, TAG) ? { [TAG]: "object", value: fields } : fields;
17372
15852
  }
@@ -17700,8 +16180,8 @@ var CallQueuedHandler = class {
17700
16180
  const lock = payload.uniqueLock;
17701
16181
  if (!lock || !this.container.bound(CacheManager)) return;
17702
16182
  const cache2 = this.container.make(CacheManager);
17703
- const store2 = lock.store !== void 0 ? cache2.store(lock.store) : cache2;
17704
- await store2.lock(lock.key).forceRelease();
16183
+ const store = lock.store !== void 0 ? cache2.store(lock.store) : cache2;
16184
+ await store.lock(lock.key).forceRelease();
17705
16185
  }
17706
16186
  };
17707
16187
  var WithoutOverlapping = class {
@@ -17938,34 +16418,34 @@ var DatabaseQueue = class extends QueueBase {
17938
16418
  });
17939
16419
  }
17940
16420
  async pushToDatabase(queue, payload, delaySeconds2, attempts, db = this.database()) {
17941
- const now4 = this.currentTime();
16421
+ const now5 = this.currentTime();
17942
16422
  const id = await db.table(this.table).insertGetId({
17943
16423
  queue,
17944
16424
  payload: encodePayload({ ...payload, attempts: 0 }),
17945
16425
  attempts,
17946
16426
  reserved_at: null,
17947
- available_at: now4 + Math.max(0, Math.round(delaySeconds2)),
17948
- created_at: now4
16427
+ available_at: now5 + Math.max(0, Math.round(delaySeconds2)),
16428
+ created_at: now5
17949
16429
  });
17950
16430
  return String(id);
17951
16431
  }
17952
16432
  /** The oldest available row, or the oldest reservation older than retry_after, whichever has the lower id. */
17953
16433
  async getNextAvailableJob(db, queue) {
17954
- const now4 = this.currentTime();
17955
- const available = await db.table(this.table).where("queue", queue).whereNull("reserved_at").where("available_at", "<=", now4).orderBy("id", "asc").lockForUpdate().first();
17956
- const expired = await db.table(this.table).where("queue", queue).whereNotNull("reserved_at").where("reserved_at", "<=", now4 - this.retryAfter).orderBy("id", "asc").lockForUpdate().first();
16434
+ const now5 = this.currentTime();
16435
+ const available = await db.table(this.table).where("queue", queue).whereNull("reserved_at").where("available_at", "<=", now5).orderBy("id", "asc").lockForUpdate().first();
16436
+ const expired = await db.table(this.table).where("queue", queue).whereNotNull("reserved_at").where("reserved_at", "<=", now5 - this.retryAfter).orderBy("id", "asc").lockForUpdate().first();
17957
16437
  if (!available || !expired) return available ?? expired;
17958
16438
  return Number(available.id) <= Number(expired.id) ? available : expired;
17959
16439
  }
17960
16440
  /** Reserves the row only if nobody else changed it since we read it. */
17961
16441
  async markJobAsReserved(db, record) {
17962
- const now4 = this.currentTime();
16442
+ const now5 = this.currentTime();
17963
16443
  const query = db.table(this.table).where("id", record.id).where("attempts", record.attempts);
17964
16444
  if (record.reserved_at === null) query.whereNull("reserved_at");
17965
16445
  else query.where("reserved_at", record.reserved_at);
17966
- const affected = await query.update({ reserved_at: now4, attempts: Number(record.attempts) + 1 });
16446
+ const affected = await query.update({ reserved_at: now5, attempts: Number(record.attempts) + 1 });
17967
16447
  if (affected === 0) return false;
17968
- record.reserved_at = now4;
16448
+ record.reserved_at = now5;
17969
16449
  record.attempts = Number(record.attempts) + 1;
17970
16450
  return true;
17971
16451
  }
@@ -18093,11 +16573,11 @@ var RedisQueue = class extends QueueBase {
18093
16573
  }
18094
16574
  async pop(queue) {
18095
16575
  const key = this.key(queue);
18096
- const now4 = this.now();
18097
- await this.redis().eval(MIGRATE_EXPIRED_JOBS, 3, `${key}:delayed`, key, `${key}:notify`, now4);
18098
- await this.redis().eval(MIGRATE_EXPIRED_JOBS, 3, `${key}:reserved`, key, `${key}:notify`, now4);
16576
+ const now5 = this.now();
16577
+ await this.redis().eval(MIGRATE_EXPIRED_JOBS, 3, `${key}:delayed`, key, `${key}:notify`, now5);
16578
+ await this.redis().eval(MIGRATE_EXPIRED_JOBS, 3, `${key}:reserved`, key, `${key}:notify`, now5);
18099
16579
  for (; ; ) {
18100
- const [job, reserved] = await this.redis().eval(POP, 3, key, `${key}:reserved`, `${key}:notify`, now4 + this.retryAfter);
16580
+ const [job, reserved] = await this.redis().eval(POP, 3, key, `${key}:reserved`, `${key}:notify`, now5 + this.retryAfter);
18101
16581
  if (!job || !reserved) return void 0;
18102
16582
  try {
18103
16583
  return new RedisJob(this.jobContext(), this, job, reserved, this.getQueue(queue));
@@ -18491,8 +16971,8 @@ var DatabaseBatchRepository = class {
18491
16971
  await this.database().table(this.table).where("id", id).update({ finished_at: this.now() });
18492
16972
  }
18493
16973
  async cancel(id) {
18494
- const now4 = this.now();
18495
- await this.database().table(this.table).where("id", id).update({ cancelled_at: now4, finished_at: now4 });
16974
+ const now5 = this.now();
16975
+ await this.database().table(this.table).where("id", id).update({ cancelled_at: now5, finished_at: now5 });
18496
16976
  }
18497
16977
  async delete(id) {
18498
16978
  await this.database().table(this.table).where("id", id).delete();
@@ -18797,13 +17277,13 @@ var Worker = class _Worker {
18797
17277
  }
18798
17278
  }
18799
17279
  };
18800
- var EXTENSIONS3 = [".ts", ".js", ".mts", ".mjs"];
17280
+ var EXTENSIONS2 = [".ts", ".js", ".mts", ".mjs"];
18801
17281
  function files2(directory) {
18802
17282
  const found = [];
18803
17283
  for (const entry of readdirSync6(directory).sort()) {
18804
17284
  const path = join12(directory, entry);
18805
17285
  if (statSync3(path).isDirectory()) found.push(...files2(path));
18806
- else if (EXTENSIONS3.some((extension) => entry.endsWith(extension)) && !entry.endsWith(".d.ts")) found.push(path);
17286
+ else if (EXTENSIONS2.some((extension) => entry.endsWith(extension)) && !entry.endsWith(".d.ts")) found.push(path);
18807
17287
  }
18808
17288
  return found;
18809
17289
  }
@@ -18811,7 +17291,7 @@ var WORKER_DISCOVERY_DIRECTORIES = ["Events", "Listeners", "Mail", "Notification
18811
17291
  var isClass2 = (value2) => typeof value2 === "function" && /^class[\s{]/.test(Function.prototype.toString.call(value2));
18812
17292
  var isJobClass = (value2) => typeof value2.prototype.handle === "function";
18813
17293
  async function discoverClasses(directory, registry2, filter = () => true) {
18814
- if (!existsSync9(directory)) return [];
17294
+ if (!existsSync8(directory)) return [];
18815
17295
  const names = [];
18816
17296
  for (const file of files2(directory)) {
18817
17297
  const module = await import(pathToFileURL6(file).href);
@@ -19022,7 +17502,9 @@ var QueueServiceProvider = class extends ServiceProvider {
19022
17502
  };
19023
17503
 
19024
17504
  // ../Routing/dist/index.js
17505
+ import { createHmac as createHmac4, timingSafeEqual as timingSafeEqual4 } from "crypto";
19025
17506
  import { pathToFileURL as pathToFileURL7 } from "url";
17507
+ import { createHash as createHash8 } from "crypto";
19026
17508
  var NotFoundHttpError = class extends Error {
19027
17509
  kind = "Http";
19028
17510
  status = 404;
@@ -19076,6 +17558,24 @@ var RoutingError = class extends Error {
19076
17558
  status = 500;
19077
17559
  name = "RoutingError";
19078
17560
  };
17561
+ var InvalidUrlSignatureError = class extends Error {
17562
+ kind = "Http";
17563
+ status = 403;
17564
+ name = "InvalidUrlSignatureError";
17565
+ constructor() {
17566
+ super("Invalid signature.");
17567
+ }
17568
+ };
17569
+ var ThrottleRequestsError = class extends Error {
17570
+ constructor(headers = {}) {
17571
+ super("Too Many Attempts.");
17572
+ this.headers = headers;
17573
+ }
17574
+ headers;
17575
+ kind = "Http";
17576
+ status = 429;
17577
+ name = "ThrottleRequestsError";
17578
+ };
19079
17579
  async function toResponse(request2, value2) {
19080
17580
  if (value2 instanceof Response) return value2;
19081
17581
  if (value2 === null || value2 === void 0) return new Response(null, { status: 204 });
@@ -19320,6 +17820,7 @@ var RouteDefinition = class {
19320
17820
  this.#name = (this.#name ?? "") + name;
19321
17821
  return this;
19322
17822
  }
17823
+ /** middleware('auth', 'verified') or middleware(['auth', 'verified']). */
19323
17824
  middleware(...middleware) {
19324
17825
  this.#middleware.push(...middleware.flat());
19325
17826
  return this;
@@ -19777,7 +18278,7 @@ var BaseRouter = class {
19777
18278
  }
19778
18279
  };
19779
18280
  var VALID_URL = /^(#|\/\/|https?:\/\/|(mailto|tel|sms):)/i;
19780
- var isPlainObject4 = (value2) => {
18281
+ var isPlainObject3 = (value2) => {
19781
18282
  if (typeof value2 !== "object" || value2 === null || Array.isArray(value2)) return false;
19782
18283
  const prototype = Object.getPrototypeOf(value2);
19783
18284
  return prototype === Object.prototype || prototype === null;
@@ -19786,7 +18287,7 @@ function buildQuery2(values) {
19786
18287
  const pairs = [];
19787
18288
  const add = (key, value2) => {
19788
18289
  if (value2 === null || value2 === void 0) return;
19789
- if (typeof value2 === "object" && (Array.isArray(value2) || isPlainObject4(value2))) {
18290
+ if (typeof value2 === "object" && (Array.isArray(value2) || isPlainObject3(value2))) {
19790
18291
  for (const [child, nested] of Object.entries(value2)) add(`${key}[${child}]`, nested);
19791
18292
  return;
19792
18293
  }
@@ -19802,6 +18303,17 @@ function routeKey(value2, field) {
19802
18303
  if (field !== void 0) return typeof model.getAttribute === "function" ? model.getAttribute(field) : model[field];
19803
18304
  return typeof model.getRouteKey === "function" ? model.getRouteKey() : value2;
19804
18305
  }
18306
+ function sign(url2, key) {
18307
+ return createHmac4("sha256", key).update(url2).digest("hex");
18308
+ }
18309
+ function safeEquals(expected, given) {
18310
+ const a = Buffer.from(expected);
18311
+ const b = Buffer.from(given);
18312
+ return a.length === b.length && timingSafeEqual4(a, b);
18313
+ }
18314
+ function availableAt(expiration) {
18315
+ return expiration instanceof Date ? Math.floor(expiration.getTime() / 1e3) : Math.floor(Date.now() / 1e3) + expiration;
18316
+ }
19805
18317
  var BaseUrlGenerator = class {
19806
18318
  constructor(router, container) {
19807
18319
  this.router = router;
@@ -19830,8 +18342,8 @@ var BaseUrlGenerator = class {
19830
18342
  route(name, parameters, absolute = true) {
19831
18343
  const route2 = this.router.getByName(name);
19832
18344
  if (route2 === void 0) throw new RouteNotDefinedError(name);
19833
- const named = isPlainObject4(parameters) ? { ...parameters } : {};
19834
- const positional = Array.isArray(parameters) ? [...parameters] : parameters === void 0 || parameters === null || isPlainObject4(parameters) ? [] : [parameters];
18345
+ const named = isPlainObject3(parameters) ? { ...parameters } : {};
18346
+ const positional = Array.isArray(parameters) ? [...parameters] : parameters === void 0 || parameters === null || isPlainObject3(parameters) ? [] : [parameters];
19835
18347
  const values = /* @__PURE__ */ new Map();
19836
18348
  const missing = [];
19837
18349
  for (const parameter of route2.parameters) {
@@ -19889,6 +18401,69 @@ var BaseUrlGenerator = class {
19889
18401
  hasRoute(name) {
19890
18402
  return this.router.getByName(name) !== void 0;
19891
18403
  }
18404
+ /**
18405
+ * Laravel's URL::signedRoute(): the route URL with its parameters sorted by name, then a `signature` query (the
18406
+ * HMAC-SHA256 of that URL, keyed by APP_KEY). `expiration` (a Date, or seconds from now) adds `expires`.
18407
+ * `absolute: false` signs the path only (checked by `signed:relative`).
18408
+ */
18409
+ signedRoute(name, parameters, expiration, absolute = true) {
18410
+ const named = this.#namedParameters(name, parameters);
18411
+ for (const reserved of ["signature", "expires"]) {
18412
+ if (Object.hasOwn(named, reserved)) {
18413
+ throw new RoutingError(`"${reserved}" is a reserved parameter when generating signed routes. Please rename your route parameter.`);
18414
+ }
18415
+ }
18416
+ if (expiration !== void 0) named.expires = availableAt(expiration);
18417
+ const sorted = Object.fromEntries(Object.keys(named).sort().map((key) => [key, named[key]]));
18418
+ const signature = sign(this.route(name, sorted, absolute), this.#signingKeys()[0]);
18419
+ return this.route(name, { ...sorted, signature }, absolute);
18420
+ }
18421
+ /** Laravel's URL::temporarySignedRoute(): a signed URL that expires at `expiration` (a Date, or seconds from now). */
18422
+ temporarySignedRoute(name, expiration, parameters, absolute = true) {
18423
+ return this.signedRoute(name, parameters, expiration, absolute);
18424
+ }
18425
+ /** The request URL carries a correct signature (current or previous APP_KEY) that hasn't expired. */
18426
+ hasValidSignature(request2, absolute = true) {
18427
+ return this.hasCorrectSignature(request2, absolute) && this.signatureHasNotExpired(request2);
18428
+ }
18429
+ /** The signature matches the URL without its `signature` query, in a constant-time comparison. */
18430
+ hasCorrectSignature(request2, absolute = true) {
18431
+ const full = new URL(request2.fullUrl());
18432
+ const path = request2.path();
18433
+ const url2 = absolute ? request2.url() : path === "/" ? "/" : `/${path}`;
18434
+ const query = full.search.slice(1).split("&").filter((pair) => pair !== "" && pair.split("=")[0] !== "signature").join("&");
18435
+ const original = query === "" ? url2 : `${url2}?${query}`;
18436
+ const given = full.searchParams.get("signature") ?? "";
18437
+ return this.#signingKeys().some((key) => safeEquals(sign(original, key), given));
18438
+ }
18439
+ /** No `expires` query, or one that is still in the future. */
18440
+ signatureHasNotExpired(request2) {
18441
+ const expires = new URL(request2.fullUrl()).searchParams.get("expires");
18442
+ if (expires === null || expires === "") return true;
18443
+ const at = Number(expires);
18444
+ return Number.isFinite(at) && Math.floor(Date.now() / 1e3) <= at;
18445
+ }
18446
+ /** Named parameters: an object as is, positional values (a list or one value) by the route's parameter names. */
18447
+ #namedParameters(name, parameters) {
18448
+ if (isPlainObject3(parameters)) return { ...parameters };
18449
+ const route2 = this.router.getByName(name);
18450
+ if (route2 === void 0) throw new RouteNotDefinedError(name);
18451
+ const values = parameters === void 0 || parameters === null ? [] : Array.isArray(parameters) ? parameters : [parameters];
18452
+ const named = {};
18453
+ route2.parameters.forEach((parameter, index) => {
18454
+ if (index < values.length) named[parameter.name] = values[index];
18455
+ });
18456
+ return named;
18457
+ }
18458
+ /** The Encrypter's key, then its previous keys (config app.previous_keys), so rotated keys still verify. */
18459
+ #signingKeys() {
18460
+ const scope = this.#scope();
18461
+ if (scope === void 0 || !scope.bound(Encrypter)) {
18462
+ throw new RoutingError("Signed URLs need the Encrypter: set APP_KEY (oriel key:generate).");
18463
+ }
18464
+ const encrypter = scope.make(Encrypter);
18465
+ return typeof encrypter.getAllKeys === "function" ? encrypter.getAllKeys() : [encrypter.getKey()];
18466
+ }
19892
18467
  #join(path, absolute) {
19893
18468
  const trimmed = path.replace(/^\/+|\/+$/g, "");
19894
18469
  if (!absolute) return `/${trimmed}`;
@@ -19921,6 +18496,60 @@ function healthResponse() {
19921
18496
  const html2 = '<!DOCTYPE html>\n<html lang="en">\n<head>\n<meta charset="utf-8">\n<title>Application up</title>\n</head>\n<body><h1>Application up</h1></body>\n</html>';
19922
18497
  return new Response(html2, { status: 200, headers: { "content-type": "text/html; charset=utf-8" } });
19923
18498
  }
18499
+ var sha12 = (value2) => createHash8("sha1").update(value2).digest("hex");
18500
+ function withHeaders2(response2, headers) {
18501
+ try {
18502
+ for (const [name, value2] of Object.entries(headers)) response2.headers.set(name, value2);
18503
+ return response2;
18504
+ } catch {
18505
+ const copy = new Headers(response2.headers);
18506
+ for (const [name, value2] of Object.entries(headers)) copy.set(name, value2);
18507
+ return new Response(response2.body, { status: response2.status, statusText: response2.statusText, headers: copy });
18508
+ }
18509
+ }
18510
+ var ThrottleRequests = class {
18511
+ async handle(request2, next, maxAttempts = "60", decayMinutes = "1", prefix = "") {
18512
+ const max = Number(maxAttempts);
18513
+ const decay = Number(decayMinutes);
18514
+ if (maxAttempts.trim() === "" || !Number.isInteger(max) || max < 0 || decayMinutes.trim() === "" || !Number.isFinite(decay) || decay <= 0) {
18515
+ throw new RoutingError(
18516
+ `Invalid throttle parameters "${maxAttempts},${decayMinutes}": use throttle:<maxAttempts>,<decayMinutes>[,<prefix>] (named rate limiters are not supported).`
18517
+ );
18518
+ }
18519
+ const limiter = inject(RateLimiter);
18520
+ const key = prefix + this.resolveRequestSignature(request2);
18521
+ if (await limiter.tooManyAttempts(key, max)) {
18522
+ const retryAfter = await limiter.availableIn(key);
18523
+ throw new ThrottleRequestsError({
18524
+ "X-RateLimit-Limit": String(max),
18525
+ "X-RateLimit-Remaining": "0",
18526
+ "Retry-After": String(retryAfter),
18527
+ "X-RateLimit-Reset": String(Math.floor(Date.now() / 1e3) + retryAfter)
18528
+ });
18529
+ }
18530
+ await limiter.hit(key, Math.round(decay * 60));
18531
+ const response2 = await next(request2);
18532
+ return withHeaders2(response2, {
18533
+ "X-RateLimit-Limit": String(max),
18534
+ "X-RateLimit-Remaining": String(await limiter.remaining(key, max))
18535
+ });
18536
+ }
18537
+ /** The signed-in user's identifier, else the client IP, hashed (Laravel's resolveRequestSignature()). */
18538
+ resolveRequestSignature(request2) {
18539
+ const user = request2.user();
18540
+ if (user !== void 0 && user !== null && typeof user.getAuthIdentifier === "function") {
18541
+ return sha12(String(user.getAuthIdentifier()));
18542
+ }
18543
+ return sha12(`|${request2.ip() ?? ""}`);
18544
+ }
18545
+ };
18546
+ var ValidateSignature = class {
18547
+ async handle(request2, next, ...parameters) {
18548
+ const absolute = parameters[0] !== "relative";
18549
+ if (inject(UrlGenerator).hasValidSignature(request2, absolute)) return next(request2);
18550
+ throw new InvalidUrlSignatureError();
18551
+ }
18552
+ };
19924
18553
  var RoutingServiceProvider = class extends ServiceProvider {
19925
18554
  register() {
19926
18555
  this.app.singleton(Router, () => new BaseRouter(this.app));
@@ -19938,23 +18567,28 @@ var RoutingServiceProvider = class extends ServiceProvider {
19938
18567
  * when the route files run.
19939
18568
  */
19940
18569
  boot() {
18570
+ this.app.make(Router).aliasMiddleware("signed", ValidateSignature).aliasMiddleware("throttle", ThrottleRequests);
19941
18571
  this.app.booted(async () => {
19942
18572
  if (!this.app.bound(RoutingPaths)) return;
19943
18573
  const { web, api, health, apiPrefix } = this.app.make(RoutingPaths);
19944
18574
  const router = this.app.make(Router);
19945
18575
  if (health !== void 0) router.get(health, () => healthResponse());
19946
- if (web !== void 0) await router.middleware("web").group(() => loadRoutesFrom(this.app, router, web));
19947
- if (api !== void 0) await router.prefix(apiPrefix).middleware("api").group(() => loadRoutesFrom(this.app, router, api));
18576
+ if (web !== void 0) await router.middleware("web").group(() => this.#load(router, web));
18577
+ if (api !== void 0) await router.prefix(apiPrefix).middleware("api").group(() => this.#load(router, api));
19948
18578
  });
19949
18579
  }
18580
+ /** One file or several, in order: each is imported afresh for this application (a nested import is not). */
18581
+ async #load(router, files3) {
18582
+ for (const file of [files3].flat()) await loadRoutesFrom(this.app, router, file);
18583
+ }
19950
18584
  };
19951
18585
 
19952
18586
  // ../Session/dist/index.js
19953
- import { mkdir as mkdir7, readdir as readdir3, readFile as readFile5, rename as rename3, rm as rm3, stat as stat4, writeFile as writeFile8 } from "fs/promises";
18587
+ import { mkdir as mkdir6, readdir as readdir3, readFile as readFile4, rename as rename3, rm as rm3, stat as stat3, writeFile as writeFile7 } from "fs/promises";
19954
18588
  import { join as join13 } from "path";
19955
18589
  import { Redis as Redis3 } from "ioredis";
19956
18590
  import { randomInt } from "crypto";
19957
- import { timingSafeEqual as timingSafeEqual4 } from "crypto";
18591
+ import { timingSafeEqual as timingSafeEqual5 } from "crypto";
19958
18592
  var unique = (values) => [...new Set(values)];
19959
18593
  var Store = class {
19960
18594
  #id = "";
@@ -20193,18 +18827,18 @@ var FileSessionHandler = class {
20193
18827
  if (!VALID_ID.test(id)) return "";
20194
18828
  const file = join13(this.path, id);
20195
18829
  try {
20196
- const { mtimeMs } = await stat4(file);
18830
+ const { mtimeMs } = await stat3(file);
20197
18831
  if (mtimeMs < this.clock() - this.minutes * 6e4) return "";
20198
- return await readFile5(file, "utf8");
18832
+ return await readFile4(file, "utf8");
20199
18833
  } catch {
20200
18834
  return "";
20201
18835
  }
20202
18836
  }
20203
18837
  async write(id, data) {
20204
18838
  if (!VALID_ID.test(id)) return;
20205
- await mkdir7(this.path, { recursive: true });
18839
+ await mkdir6(this.path, { recursive: true });
20206
18840
  const temporary = join13(this.path, `.${id}.${Str.random(8)}.tmp`);
20207
- await writeFile8(temporary, data, "utf8");
18841
+ await writeFile7(temporary, data, "utf8");
20208
18842
  await rename3(temporary, join13(this.path, id));
20209
18843
  }
20210
18844
  async destroy(id) {
@@ -20215,7 +18849,7 @@ var FileSessionHandler = class {
20215
18849
  const files3 = await readdir3(this.path).catch(() => []);
20216
18850
  for (const file of files3) {
20217
18851
  if (!VALID_ID.test(file)) continue;
20218
- const { mtimeMs } = await stat4(join13(this.path, file)).catch(() => ({ mtimeMs: Number.POSITIVE_INFINITY }));
18852
+ const { mtimeMs } = await stat3(join13(this.path, file)).catch(() => ({ mtimeMs: Number.POSITIVE_INFINITY }));
20219
18853
  if (mtimeMs <= expiration) await rm3(join13(this.path, file), { force: true });
20220
18854
  }
20221
18855
  }
@@ -20523,7 +19157,7 @@ var StartSession = class {
20523
19157
  function equals3(known, user) {
20524
19158
  const a = Buffer.from(known);
20525
19159
  const b = Buffer.from(user);
20526
- return a.length === b.length && timingSafeEqual4(a, b);
19160
+ return a.length === b.length && timingSafeEqual5(a, b);
20527
19161
  }
20528
19162
  var VerifyCsrfToken = class {
20529
19163
  /** URIs (wildcards allowed) excluded from the check, in addition to config('http.csrf_except'). */
@@ -20625,15 +19259,15 @@ var SessionFacade = facade(Session, {
20625
19259
  extend: (driver, factory) => inject(SessionManager).extend(driver, factory)
20626
19260
  });
20627
19261
  function session(key, defaultValue) {
20628
- const store2 = inject(Session);
20629
- if (key === void 0) return store2;
20630
- if (typeof key === "string") return store2.get(key, defaultValue);
20631
- store2.put(key);
19262
+ const store = inject(Session);
19263
+ if (key === void 0) return store;
19264
+ if (typeof key === "string") return store.get(key, defaultValue);
19265
+ store.put(key);
20632
19266
  return void 0;
20633
19267
  }
20634
19268
  function old(key, defaultValue) {
20635
- const store2 = scopeSession();
20636
- return store2 === void 0 ? defaultValue : store2.getOldInput(key, defaultValue);
19269
+ const store = scopeSession();
19270
+ return store === void 0 ? defaultValue : store.getOldInput(key, defaultValue);
20637
19271
  }
20638
19272
  function csrfToken() {
20639
19273
  return inject(Session).token();
@@ -20686,6 +19320,23 @@ var ValidationErrorImpl = class extends Error {
20686
19320
  status = 422;
20687
19321
  name = "ValidationError";
20688
19322
  };
19323
+ var ValidationException = class _ValidationException extends ValidationErrorImpl {
19324
+ /** Messages per field, each a string or a list. */
19325
+ static withMessages(messages) {
19326
+ const errors2 = Object.fromEntries(Object.entries(messages).map(([field, list3]) => [field, typeof list3 === "string" ? [list3] : [...list3]]));
19327
+ return new _ValidationException(errors2);
19328
+ }
19329
+ constructor(errors2, errorBag = "default", redirectTo2) {
19330
+ super(errors2, errorBag, redirectTo2);
19331
+ this.message = summarize(errors2);
19332
+ }
19333
+ };
19334
+ function summarize(errors2) {
19335
+ const messages = Object.values(errors2).flat();
19336
+ if (messages.length === 0) return "The given data was invalid.";
19337
+ const more = messages.length - 1;
19338
+ return more === 0 ? messages[0] : `${messages[0]} (and ${more} more ${more === 1 ? "error" : "errors"})`;
19339
+ }
20689
19340
  var AuthorizationErrorImpl = class extends Error {
20690
19341
  kind = "Authorization";
20691
19342
  status = 403;
@@ -20761,6 +19412,13 @@ var DEFAULT_MESSAGES = {
20761
19412
  alpha_num: "The :attribute field must only contain letters and numbers.",
20762
19413
  alpha_dash: "The :attribute field must only contain letters, numbers, dashes and underscores.",
20763
19414
  regex: "The :attribute field format is invalid.",
19415
+ lowercase: "The :attribute field must be lowercase.",
19416
+ uppercase: "The :attribute field must be uppercase.",
19417
+ current_password: "The password is incorrect.",
19418
+ "password.letters": "The :attribute field must contain at least one letter.",
19419
+ "password.mixed": "The :attribute field must contain at least one uppercase and one lowercase letter.",
19420
+ "password.numbers": "The :attribute field must contain at least one number.",
19421
+ "password.symbols": "The :attribute field must contain at least one symbol.",
20764
19422
  confirmed: "The :attribute field confirmation does not match.",
20765
19423
  same: "The :attribute field must match :other.",
20766
19424
  different: "The :attribute field must be different from :other.",
@@ -20826,6 +19484,17 @@ var MessageBagImpl = class {
20826
19484
  return structuredClone(this.items);
20827
19485
  }
20828
19486
  };
19487
+ var authRules = {
19488
+ current_password: {
19489
+ validate: async (ctx) => {
19490
+ const guard2 = inject(AuthFactory).guard(ctx.parameters[0]);
19491
+ if (await guard2.guest()) return false;
19492
+ const user = await guard2.user();
19493
+ return user !== void 0 && typeof ctx.value === "string" && inject(Hasher).check(ctx.value, user.getAuthPassword());
19494
+ },
19495
+ messageKey: () => "current_password"
19496
+ }
19497
+ };
20829
19498
  function guessColumn(attribute, expandedFromWildcard = false) {
20830
19499
  if (!expandedFromWildcard) return attribute;
20831
19500
  return attribute.split(".").filter((segment) => !/^\d+$/.test(segment)).at(-1) ?? attribute;
@@ -21008,8 +19677,8 @@ function resolveDateParam(rule, param, data) {
21008
19677
  const parsed = parseDate(fieldValue);
21009
19678
  if (!Number.isNaN(parsed)) return parsed;
21010
19679
  }
21011
- const relative7 = relativeDate(param);
21012
- if (relative7 !== void 0) return relative7;
19680
+ const relative6 = relativeDate(param);
19681
+ if (relative6 !== void 0) return relative6;
21013
19682
  const literal = parseDate(param);
21014
19683
  if (!Number.isNaN(literal)) return literal;
21015
19684
  if (FIELD_REFERENCE_RE.test(param)) return Number.NaN;
@@ -21046,6 +19715,14 @@ var formatRules = {
21046
19715
  validate: (ctx) => typeof ctx.value === "string" && ALPHA_DASH_RE.test(ctx.value),
21047
19716
  messageKey: () => "alpha_dash"
21048
19717
  },
19718
+ lowercase: {
19719
+ validate: (ctx) => (typeof ctx.value === "string" || typeof ctx.value === "number") && String(ctx.value).toLowerCase() === String(ctx.value),
19720
+ messageKey: () => "lowercase"
19721
+ },
19722
+ uppercase: {
19723
+ validate: (ctx) => (typeof ctx.value === "string" || typeof ctx.value === "number") && String(ctx.value).toUpperCase() === String(ctx.value),
19724
+ messageKey: () => "uppercase"
19725
+ },
21049
19726
  regex: {
21050
19727
  validate: (ctx) => typeof ctx.value === "string" && compileRegex(ctx.parameters[0] ?? "").test(ctx.value),
21051
19728
  messageKey: () => "regex"
@@ -21167,7 +19844,7 @@ var typeRules = {
21167
19844
  function hasAny(ctx, names) {
21168
19845
  return names.some((name) => ctx.ruleNames.includes(name));
21169
19846
  }
21170
- function isPlainObject5(value2) {
19847
+ function isPlainObject4(value2) {
21171
19848
  if (typeof value2 !== "object" || value2 === null) return false;
21172
19849
  const proto = Object.getPrototypeOf(value2);
21173
19850
  return proto === Object.prototype || proto === null;
@@ -21180,7 +19857,7 @@ function measure(ctx) {
21180
19857
  if (Array.isArray(value2)) return { type: "array", size: value2.length };
21181
19858
  if (isUploadedFileLike(value2)) return { type: "file", size: value2.size / 1024 };
21182
19859
  if (hasAny(ctx, ["file", "image"])) return { type: "file", size: Number.NaN };
21183
- if (isPlainObject5(value2)) return { type: "array", size: Object.keys(value2).length };
19860
+ if (isPlainObject4(value2)) return { type: "array", size: Object.keys(value2).length };
21184
19861
  if (hasAny(ctx, ["array"])) return { type: "array", size: stringLength(value2) };
21185
19862
  return { type: "string", size: stringLength(value2) };
21186
19863
  }
@@ -21227,7 +19904,81 @@ var builtinRules = {
21227
19904
  ...formatRules,
21228
19905
  ...sizeRules,
21229
19906
  ...fileRules,
21230
- ...databaseRules
19907
+ ...databaseRules,
19908
+ ...authRules
19909
+ };
19910
+ var defaultRule;
19911
+ var PasswordRule = class _PasswordRule {
19912
+ #min;
19913
+ #max;
19914
+ #letters = false;
19915
+ #mixedCase = false;
19916
+ #numbers = false;
19917
+ #symbols = false;
19918
+ constructor(min = 8) {
19919
+ this.#min = Math.max(1, min);
19920
+ }
19921
+ /** A password rule of at least `size` characters: PasswordRule.min(12).mixedCase(). */
19922
+ static min(size) {
19923
+ return new _PasswordRule(size);
19924
+ }
19925
+ static defaults(rule) {
19926
+ if (rule !== void 0) {
19927
+ defaultRule = rule ?? void 0;
19928
+ return;
19929
+ }
19930
+ const resolved = typeof defaultRule === "function" ? defaultRule() : defaultRule;
19931
+ return resolved === void 0 ? new _PasswordRule(8) : resolved.#copy();
19932
+ }
19933
+ min(size) {
19934
+ this.#min = Math.max(1, size);
19935
+ return this;
19936
+ }
19937
+ max(size) {
19938
+ this.#max = size;
19939
+ return this;
19940
+ }
19941
+ /** At least one letter. */
19942
+ letters() {
19943
+ this.#letters = true;
19944
+ return this;
19945
+ }
19946
+ /** At least one uppercase and one lowercase letter. */
19947
+ mixedCase() {
19948
+ this.#mixedCase = true;
19949
+ return this;
19950
+ }
19951
+ /** At least one number. */
19952
+ numbers() {
19953
+ this.#numbers = true;
19954
+ return this;
19955
+ }
19956
+ /** At least one symbol (punctuation, a symbol or a space). */
19957
+ symbols() {
19958
+ this.#symbols = true;
19959
+ return this;
19960
+ }
19961
+ validate(attribute, value2, fail) {
19962
+ const name = defaultAttributeName(attribute);
19963
+ const say = (key, replacements = {}) => fail(applyReplacements(DEFAULT_MESSAGES[key], { attribute: name, ...replacements }));
19964
+ if (typeof value2 !== "string") return say("string");
19965
+ const length = [...value2].length;
19966
+ if (length < this.#min) say("min.string", { min: String(this.#min) });
19967
+ if (this.#max !== void 0 && length > this.#max) say("max.string", { max: String(this.#max) });
19968
+ if (this.#mixedCase && !/(\p{Ll}+.*\p{Lu})|(\p{Lu}+.*\p{Ll})/u.test(value2)) say("password.mixed");
19969
+ if (this.#letters && !/\p{L}/u.test(value2)) say("password.letters");
19970
+ if (this.#symbols && !/\p{Z}|\p{S}|\p{P}/u.test(value2)) say("password.symbols");
19971
+ if (this.#numbers && !/\p{N}/u.test(value2)) say("password.numbers");
19972
+ }
19973
+ #copy() {
19974
+ const copy = new _PasswordRule(this.#min);
19975
+ copy.#max = this.#max;
19976
+ copy.#letters = this.#letters;
19977
+ copy.#mixedCase = this.#mixedCase;
19978
+ copy.#numbers = this.#numbers;
19979
+ copy.#symbols = this.#symbols;
19980
+ return copy;
19981
+ }
21231
19982
  };
21232
19983
  var BuiltinRuleObject = class {
21233
19984
  // Declares all 4 contract parameters so a subclass's inferred type (from `Rule.in(...)` etc.) still accepts a
@@ -21300,7 +20051,9 @@ var ExistsRule = class extends BuiltinRuleObject {
21300
20051
  var Rule = {
21301
20052
  in: (values) => new InRule(values),
21302
20053
  unique: (table, column) => new UniqueRule(table, column),
21303
- exists: (table, column) => new ExistsRule(table, column)
20054
+ exists: (table, column) => new ExistsRule(table, column),
20055
+ /** Laravel's Password::defaults(): the application's password rule (at least 8 characters unless PasswordRule.defaults() changed it). */
20056
+ password: () => PasswordRule.defaults()
21304
20057
  };
21305
20058
  var SKIPPED_MODIFIERS = /* @__PURE__ */ new Set(["bail", "nullable", "sometimes"]);
21306
20059
  function buildNested(flat) {
@@ -21415,9 +20168,9 @@ var ValidatorImpl = class {
21415
20168
  const implicit = rule.kind === "named" && (this.registry[rule.name]?.implicit ?? false);
21416
20169
  if (!implicit && (!present2 || isBlank2)) continue;
21417
20170
  if (!implicit && nullable && isNull) continue;
21418
- const message = await this.runRule(rule, field, pattern, value2, names);
21419
- if (message !== void 0) {
21420
- this.bag.add(field, message);
20171
+ const messages = await this.runRule(rule, field, pattern, value2, names);
20172
+ if (messages.length > 0) {
20173
+ for (const message of messages) this.bag.add(field, message);
21421
20174
  if (bail || implicit) break;
21422
20175
  }
21423
20176
  }
@@ -21430,26 +20183,24 @@ var ValidatorImpl = class {
21430
20183
  const expanded = pattern.includes("*");
21431
20184
  if (rule.kind === "object") {
21432
20185
  if (rule.rule instanceof BuiltinRuleObject) {
21433
- if (await rule.rule.passes(field, value2, this.data, expanded)) return void 0;
20186
+ if (await rule.rule.passes(field, value2, this.data, expanded)) return [];
21434
20187
  const ctx2 = { attribute: field, expandedFromWildcard: expanded, value: value2, parameters: [], data: this.data, ruleNames };
21435
- return this.failureMessage(rule.rule.ruleName, this.registry[rule.rule.ruleName], ctx2, pattern);
20188
+ return [this.failureMessage(rule.rule.ruleName, this.registry[rule.rule.ruleName], ctx2, pattern)];
21436
20189
  }
21437
- let failure;
21438
- await rule.rule.validate(field, value2, (message) => {
21439
- failure = message;
21440
- }, this.data);
21441
- return failure;
20190
+ const failures = [];
20191
+ await rule.rule.validate(field, value2, (message) => void failures.push(message), this.data);
20192
+ return failures;
21442
20193
  }
21443
20194
  const builtin = this.registry[rule.name];
21444
20195
  if (!builtin) throw new UnknownValidationRuleError(rule.name);
21445
20196
  const ctx = { attribute: field, expandedFromWildcard: expanded, value: value2, parameters: rule.parameters, data: this.data, ruleNames };
21446
- if (await builtin.validate(ctx)) return void 0;
21447
- return this.failureMessage(rule.name, builtin, ctx, pattern);
20197
+ if (await builtin.validate(ctx)) return [];
20198
+ return [this.failureMessage(rule.name, builtin, ctx, pattern)];
21448
20199
  }
21449
20200
  /** Custom message (concrete field, then wildcard pattern, then rule name) or the default, with :attribute filled. */
21450
20201
  failureMessage(name, builtin, ctx, pattern) {
21451
20202
  const field = ctx.attribute;
21452
- const template = this.customMessages[`${field}.${name}`] ?? this.customMessages[`${pattern}.${name}`] ?? this.customMessages[name] ?? DEFAULT_MESSAGES[builtin?.messageKey(ctx) ?? name] ?? builtin?.defaultMessage ?? "The :attribute field is invalid.";
20203
+ const template = this.customMessages[`${field}.${name}`] ?? this.customMessages[`${pattern}.${name}`] ?? this.customMessages[name] ?? builtin?.message ?? DEFAULT_MESSAGES[builtin?.messageKey(ctx) ?? name] ?? builtin?.defaultMessage ?? "The :attribute field is invalid.";
21453
20204
  const display = this.customAttributes[field] ?? this.customAttributes[pattern] ?? defaultAttributeName(field);
21454
20205
  return applyReplacements(template, { attribute: display, ...builtin?.replacements?.(ctx) ?? {} });
21455
20206
  }
@@ -21463,6 +20214,7 @@ var ValidationFactoryImpl = class {
21463
20214
  this.extended[name] = {
21464
20215
  validate: (ctx) => callback(ctx.attribute, ctx.value, ctx.parameters, ctx.data),
21465
20216
  messageKey: () => name,
20217
+ ...message === void 0 ? {} : { message },
21466
20218
  defaultMessage: message ?? "The :attribute field is invalid."
21467
20219
  };
21468
20220
  }
@@ -21495,6 +20247,7 @@ function defaultProviders() {
21495
20247
  AuthServiceProvider,
21496
20248
  ViewServiceProvider,
21497
20249
  InertiaServiceProvider,
20250
+ LiveServiceProvider,
21498
20251
  RoutingServiceProvider,
21499
20252
  HttpServiceProvider,
21500
20253
  ConsoleServiceProvider
@@ -21573,6 +20326,7 @@ export {
21573
20326
  CHAIN,
21574
20327
  Cache,
21575
20328
  CacheManager2 as CacheManager,
20329
+ CacheRateLimiter,
21576
20330
  Repository2 as CacheRepositoryImpl,
21577
20331
  CacheServiceProvider,
21578
20332
  CallQueuedHandler,
@@ -21585,9 +20339,11 @@ export {
21585
20339
  ColumnDefinition,
21586
20340
  Command,
21587
20341
  CommandNotFoundError,
20342
+ Component,
21588
20343
  ComponentNotFoundError,
20344
+ Computed,
21589
20345
  Connection,
21590
- Kernel as ConsoleKernelImpl,
20346
+ Kernel2 as ConsoleKernelImpl,
21591
20347
  ConsoleServiceProvider,
21592
20348
  Container2 as Container,
21593
20349
  ContainerNotAvailableError,
@@ -21598,6 +20354,7 @@ export {
21598
20354
  CookieServiceProvider,
21599
20355
  CookieSessionHandler,
21600
20356
  CookieValuePrefix,
20357
+ CorruptComponentPayloadError,
21601
20358
  Crypt,
21602
20359
  Cursor,
21603
20360
  CursorPaginator,
@@ -21623,12 +20380,14 @@ export {
21623
20380
  Dispatchable,
21624
20381
  ELEMENT,
21625
20382
  EloquentUserProvider,
20383
+ EmailVerificationRequest,
21626
20384
  EncryptCookies,
21627
20385
  EncryptError,
21628
20386
  EncryptHistory,
21629
20387
  Encrypter2 as Encrypter,
21630
20388
  EncryptionServiceProvider,
21631
20389
  EnsureEmailIsVerified,
20390
+ ErrorBag,
21632
20391
  ErrorHandler,
21633
20392
  Event2 as Event,
21634
20393
  Dispatcher2 as EventDispatcherImpl,
@@ -21671,7 +20430,7 @@ export {
21671
20430
  HelpCommand,
21672
20431
  HtmlString,
21673
20432
  HttpException,
21674
- Kernel2 as HttpKernelImpl,
20433
+ Kernel as HttpKernelImpl,
21675
20434
  HttpRedirectResponse,
21676
20435
  HttpRedirector,
21677
20436
  HttpResponseException,
@@ -21685,14 +20444,16 @@ export {
21685
20444
  InertiaHtml,
21686
20445
  InertiaMiddleware,
21687
20446
  Response2 as InertiaPageResponse,
21688
- ResponseFactory2 as InertiaResponseFactory,
20447
+ ResponseFactory as InertiaResponseFactory,
21689
20448
  InertiaServiceProvider,
21690
20449
  InvalidCacheConfigError,
21691
20450
  InvalidCastError,
21692
20451
  InvalidListenerError,
20452
+ InvalidLiveRequestError,
21693
20453
  InvalidLogLevelError,
21694
20454
  InvalidRuleParameterError,
21695
20455
  InvalidSignatureError,
20456
+ InvalidUrlSignatureError,
21696
20457
  InvalidViewError,
21697
20458
  JOBS_TABLE_MIGRATION,
21698
20459
  JobClassNotFoundError,
@@ -21703,8 +20464,15 @@ export {
21703
20464
  LazyCollection,
21704
20465
  LengthAwarePaginator,
21705
20466
  ListCommand,
20467
+ Live,
20468
+ LiveComponentManager,
20469
+ LiveComponentNotFoundError,
20470
+ LiveError,
20471
+ LiveServiceProvider,
21706
20472
  LocalFilesystem,
21707
20473
  LockTimeoutError,
20474
+ Locked,
20475
+ Lockout,
21708
20476
  Log,
21709
20477
  LogChannelCycleError,
21710
20478
  LogManager2 as LogManager,
@@ -21752,6 +20520,7 @@ export {
21752
20520
  MergeProp,
21753
20521
  MessageBagImpl,
21754
20522
  MethodNotAllowedHttpError,
20523
+ MethodNotCallableError,
21755
20524
  MiddlewareConfiguration,
21756
20525
  MiddlewareNotFoundError,
21757
20526
  Migration,
@@ -21785,24 +20554,29 @@ export {
21785
20554
  NullLogger,
21786
20555
  NullQueue,
21787
20556
  OPERATORS,
20557
+ On,
21788
20558
  OnceProp,
21789
20559
  OptionalProp,
20560
+ PERSISTENT_MIDDLEWARE,
21790
20561
  PERSONAL_ACCESS_TOKENS_MIGRATION,
21791
20562
  Paginator,
21792
20563
  Password,
21793
20564
  PasswordBroker2 as PasswordBroker,
21794
20565
  PasswordBrokerManager,
21795
20566
  PasswordReset,
20567
+ PasswordRule,
21796
20568
  PathTraversalError,
21797
20569
  PendingBatch,
21798
20570
  PendingChain,
21799
20571
  PendingDispatch,
20572
+ PendingEvent,
21800
20573
  PersonalAccessToken,
21801
20574
  PinoLogger,
21802
20575
  PipelineError,
21803
20576
  PipelineServiceProvider,
21804
20577
  Pivot,
21805
20578
  PostgresSchemaGrammar,
20579
+ PropertyNotUpdatableError,
21806
20580
  PropsResolver,
21807
20581
  ProviderBootError,
21808
20582
  ProviderRegisterError,
@@ -21819,6 +20593,7 @@ export {
21819
20593
  QueuedConsoleInput,
21820
20594
  QueuedMailSender,
21821
20595
  RESTART_CACHE_KEY,
20596
+ RateLimiter2 as RateLimiter,
21822
20597
  RedirectIfAuthenticated,
21823
20598
  RedisJob,
21824
20599
  RedisLock,
@@ -21827,6 +20602,7 @@ export {
21827
20602
  RedisSessionHandler,
21828
20603
  RedisStore,
21829
20604
  RedisTaggedStore,
20605
+ Registered,
21830
20606
  Relation,
21831
20607
  RelationNotFoundError,
21832
20608
  RelationNotLoadedError,
@@ -21856,6 +20632,7 @@ export {
21856
20632
  SchemaGrammar,
21857
20633
  ScrollProp,
21858
20634
  Seeder,
20635
+ SendEmailVerificationNotification,
21859
20636
  SendQueuedMailable,
21860
20637
  SendQueuedNotifications,
21861
20638
  ServiceProvider,
@@ -21878,6 +20655,10 @@ export {
21878
20655
  SyncQueue,
21879
20656
  TagsNotSupportedError,
21880
20657
  TestCommand,
20658
+ TestRequestScope,
20659
+ Testable,
20660
+ ThrottleRequests,
20661
+ ThrottleRequestsError,
21881
20662
  TimeoutExceededError,
21882
20663
  TinkerCommand,
21883
20664
  TokenGuard,
@@ -21887,6 +20668,7 @@ export {
21887
20668
  TsxView,
21888
20669
  TypeGenerator,
21889
20670
  UNIQUE_LOCK,
20671
+ UPDATE_URI,
21890
20672
  USERS_TABLE_MIGRATION,
21891
20673
  UniqueJobsNeedCacheError,
21892
20674
  UniqueLock,
@@ -21907,13 +20689,17 @@ export {
21907
20689
  UnsupportedCipherError,
21908
20690
  UnsupportedOperationError,
21909
20691
  UrlGenerationError,
20692
+ ValidateSignature,
21910
20693
  Validated,
21911
20694
  ValidationErrorImpl,
20695
+ ValidationException,
21912
20696
  ValidationFactoryImpl,
21913
20697
  ValidationServiceProvider,
21914
20698
  Validator,
21915
20699
  ValidatorImpl,
20700
+ Verified,
21916
20701
  VerifyCsrfToken,
20702
+ VerifyEmail,
21917
20703
  View,
21918
20704
  Factory as ViewFactoryImpl,
21919
20705
  ViewFactoryUnavailableError,
@@ -21926,6 +20712,7 @@ export {
21926
20712
  WORKER_DISCOVERY_DIRECTORIES,
21927
20713
  WithoutOverlapping,
21928
20714
  Worker,
20715
+ __,
21929
20716
  abort,
21930
20717
  abortIf,
21931
20718
  abortUnless,
@@ -21949,6 +20736,7 @@ export {
21949
20736
  collect,
21950
20737
  columnKey,
21951
20738
  compareRoutes,
20739
+ componentName,
21952
20740
  config,
21953
20741
  contentDisposition,
21954
20742
  cookie,
@@ -21963,7 +20751,7 @@ export {
21963
20751
  csrfToken,
21964
20752
  currentContainer,
21965
20753
  currentLogContext,
21966
- currentRequest2 as currentRequest,
20754
+ currentRequest,
21967
20755
  currentVite,
21968
20756
  databaseConfigDefaults,
21969
20757
  debugPage,
@@ -21994,6 +20782,7 @@ export {
21994
20782
  errors,
21995
20783
  escapeHtml,
21996
20784
  event,
20785
+ exceedsJsonDepth,
21997
20786
  expandWildcardKeys,
21998
20787
  extensionFromMime,
21999
20788
  facade,
@@ -22035,6 +20824,7 @@ export {
22035
20824
  isUploadedFileLike,
22036
20825
  joinDiskPath,
22037
20826
  keyGenerateHandler,
20827
+ live,
22038
20828
  loadRelations,
22039
20829
  loadRoutesFrom,
22040
20830
  logger,
@@ -22069,6 +20859,7 @@ export {
22069
20859
  parseRuleSpec,
22070
20860
  parseSignature,
22071
20861
  passwordVerify,
20862
+ persistentMiddleware,
22072
20863
  prepareValue,
22073
20864
  queueConfigDefaults,
22074
20865
  queueOptionsOf,