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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  renderToString,
23
23
  styleString,
24
24
  view
25
- } from "./chunk-3DETYZMZ.js";
25
+ } from "./chunk-A5XRLEWM.js";
26
26
  import {
27
27
  API_ROUTES_STUB,
28
28
  Application as Application2,
@@ -60,6 +60,7 @@ import {
60
60
  NotificationFake,
61
61
  On,
62
62
  PERSISTENT_MIDDLEWARE,
63
+ Pagination,
63
64
  PendingEvent,
64
65
  PropertyNotUpdatableError,
65
66
  ProviderBootError,
@@ -74,6 +75,7 @@ import {
74
75
  Vite,
75
76
  ViteError,
76
77
  ViteHtml,
78
+ WithPagination,
77
79
  abort,
78
80
  abortIf,
79
81
  abortUnless,
@@ -129,7 +131,7 @@ import {
129
131
  vite,
130
132
  viteReactRefresh,
131
133
  writeResponse
132
- } from "./chunk-SBZQ6L3Z.js";
134
+ } from "./chunk-WNJP46B7.js";
133
135
  import {
134
136
  Arr,
135
137
  BindingResolutionError,
@@ -147,12 +149,13 @@ import {
147
149
  config,
148
150
  currentContainer,
149
151
  facade,
152
+ fileType_exports,
150
153
  inject,
151
154
  now,
152
155
  retry,
153
156
  tap,
154
157
  value
155
- } from "./chunk-DCI2T7WJ.js";
158
+ } from "./chunk-PM5YTG57.js";
156
159
  import {
157
160
  Application,
158
161
  AuthFactory,
@@ -179,6 +182,7 @@ import {
179
182
  LogManager,
180
183
  MailManager,
181
184
  NotificationDispatcher,
185
+ PaginationState,
182
186
  PasswordBroker,
183
187
  PipelineFactory,
184
188
  QueueManager,
@@ -193,7 +197,7 @@ import {
193
197
  ValidationFactory,
194
198
  ViewFactory,
195
199
  token
196
- } from "./chunk-WSGWYXAO.js";
200
+ } from "./chunk-BSQKOLSK.js";
197
201
 
198
202
  // ../Auth/dist/index.js
199
203
  import { createHash } from "crypto";
@@ -1377,6 +1381,39 @@ var AccessGate = class _AccessGate {
1377
1381
  return registered === void 0 ? [cls.name] : [baseName(registered), cls.name];
1378
1382
  }
1379
1383
  };
1384
+ var list = (abilities) => typeof abilities === "string" ? [abilities] : [...abilities];
1385
+ function Authorizable(Base) {
1386
+ return class AuthorizableUser extends Base {
1387
+ /** Whether the user has the ability (every one, for a list); the arguments go to the policy or ability callback. */
1388
+ async can(abilities, ...args) {
1389
+ const gate = inject(Gate).forUser(this);
1390
+ for (const ability of list(abilities)) if (!await gate.allows(ability, ...args)) return false;
1391
+ return true;
1392
+ }
1393
+ /** Whether the user has any of the abilities. */
1394
+ async canAny(abilities, ...args) {
1395
+ return inject(Gate).forUser(this).any(list(abilities), ...args);
1396
+ }
1397
+ /** Whether the user lacks the ability (any one, for a list). */
1398
+ async cant(abilities, ...args) {
1399
+ return !await this.can(abilities, ...args);
1400
+ }
1401
+ /** The same as cant(). */
1402
+ cannot(abilities, ...args) {
1403
+ return this.cant(abilities, ...args);
1404
+ }
1405
+ };
1406
+ }
1407
+ var Controller = class {
1408
+ /** Authorizes the ability for the signed-in user (the Gate's authorize()). */
1409
+ async authorize(ability, ...args) {
1410
+ return inject(Gate).authorize(ability, ...args);
1411
+ }
1412
+ /** Authorizes the ability for the given user (Gate.forUser(user).authorize()). */
1413
+ async authorizeForUser(user, ability, ...args) {
1414
+ return inject(Gate).forUser(user).authorize(ability, ...args);
1415
+ }
1416
+ };
1380
1417
  var Authorize = class {
1381
1418
  #gate = inject(Gate);
1382
1419
  async handle(request2, next, ability, ...models) {
@@ -1618,7 +1655,7 @@ async function discoverPolicies(directory, gate) {
1618
1655
  return found;
1619
1656
  }
1620
1657
  var Auth = facade(AuthFactory);
1621
- var Gate2 = facade(Gate);
1658
+ var Gate4 = facade(Gate);
1622
1659
  var Password = facade(PasswordBroker, {
1623
1660
  broker: (name) => inject(PasswordBrokerManager).broker(name)
1624
1661
  });
@@ -1689,7 +1726,7 @@ var QUEUE_OPTIONS = ["connection", "queue", "delay", "tries", "backoff", "timeou
1689
1726
  function isQueueable(job) {
1690
1727
  if (typeof job !== "object" || job === null) return false;
1691
1728
  const members = job;
1692
- if (members[SHOULD_QUEUE] === true) return true;
1729
+ if (members.shouldQueue === true || members[SHOULD_QUEUE] === true) return true;
1693
1730
  if (QUEUE_OPTIONS.some((option) => members[option] !== void 0)) return true;
1694
1731
  return typeof members.uniqueId === "function" || typeof members.retryUntil === "function";
1695
1732
  }
@@ -1900,9 +1937,9 @@ var Dispatcher = class {
1900
1937
  }
1901
1938
  #afterResponseList() {
1902
1939
  const owner = currentContainer() ?? this.container;
1903
- let list3 = this.#afterResponse.get(owner);
1904
- if (list3 === void 0) this.#afterResponse.set(owner, list3 = []);
1905
- return list3;
1940
+ let list4 = this.#afterResponse.get(owner);
1941
+ if (list4 === void 0) this.#afterResponse.set(owner, list4 = []);
1942
+ return list4;
1906
1943
  }
1907
1944
  /** Runs the job (like dispatchSync) after the response is sent, or after the current queued job. */
1908
1945
  dispatchAfterResponse(job) {
@@ -2051,6 +2088,10 @@ var Dispatchable = class {
2051
2088
  }
2052
2089
  };
2053
2090
  var Queueable = class extends Dispatchable {
2091
+ /** ShouldQueue's marker, so subclasses may write `implements ShouldQueue` without the field. */
2092
+ get shouldQueue() {
2093
+ return true;
2094
+ }
2054
2095
  };
2055
2096
  Object.defineProperty(Queueable.prototype, SHOULD_QUEUE, { value: true });
2056
2097
  function dispatch(job) {
@@ -2921,8 +2962,8 @@ var RedisRepository = class extends Repository2 {
2921
2962
  redisStore;
2922
2963
  redis;
2923
2964
  tags(names) {
2924
- const list3 = Array.isArray(names) ? names : [names];
2925
- const taggedStore = this.redisStore.tags(list3);
2965
+ const list4 = Array.isArray(names) ? names : [names];
2966
+ const taggedStore = this.redisStore.tags(list4);
2926
2967
  const prefix = this.redisStore.getPrefix();
2927
2968
  return new Repository2(taggedStore, (_store, name, seconds, owner) => new RedisLock(this.redis, prefix + name, seconds, owner));
2928
2969
  }
@@ -3765,9 +3806,12 @@ export class {{ class }} extends Dispatchable {
3765
3806
  }
3766
3807
  `;
3767
3808
  var MAIL_STUB = `import { Mailable } from '@orieljs/framework'
3768
- import type { Content, Envelope } from '@orieljs/framework/contracts'
3809
+ import type { Content, Envelope, ShouldQueue } from '@orieljs/framework/contracts'
3810
+
3811
+ export class {{ class }} extends Mailable implements ShouldQueue {
3812
+ /** Sent by the queue worker (node oriel queue:work): remove this line and \`implements ShouldQueue\` to send it right away. */
3813
+ readonly shouldQueue = true
3769
3814
 
3770
- export class {{ class }} extends Mailable {
3771
3815
  override async envelope(): Promise<Envelope> {
3772
3816
  return { subject: '{{ subject }}' }
3773
3817
  }
@@ -3778,9 +3822,12 @@ export class {{ class }} extends Mailable {
3778
3822
  }
3779
3823
  `;
3780
3824
  var NOTIFICATION_STUB = `import { MailMessage, Notification } from '@orieljs/framework'
3781
- import type { Notifiable } from '@orieljs/framework/contracts'
3825
+ import type { Notifiable, ShouldQueue } from '@orieljs/framework/contracts'
3826
+
3827
+ export class {{ class }} extends Notification implements ShouldQueue {
3828
+ /** Sent by the queue worker (node oriel queue:work): remove this line and \`implements ShouldQueue\` to send it right away. */
3829
+ readonly shouldQueue = true
3782
3830
 
3783
- export class {{ class }} extends Notification {
3784
3831
  via(_notifiable: Notifiable): string[] {
3785
3832
  return ['mail']
3786
3833
  }
@@ -4527,7 +4574,7 @@ var SHOULD_QUEUE2 = /* @__PURE__ */ Symbol.for("oriel:bus.shouldQueue");
4527
4574
  var QUEUE_OPTIONS2 = ["connection", "queue", "delay", "tries", "backoff", "timeout"];
4528
4575
  function isQueueable2(job) {
4529
4576
  const members = job;
4530
- if (members[SHOULD_QUEUE2] === true) return true;
4577
+ if (members.shouldQueue === true || members[SHOULD_QUEUE2] === true) return true;
4531
4578
  if (QUEUE_OPTIONS2.some((option) => members[option] !== void 0)) return true;
4532
4579
  return typeof members.uniqueId === "function" || typeof members.retryUntil === "function";
4533
4580
  }
@@ -5623,14 +5670,17 @@ var LengthAwarePaginator = class extends AbstractPaginator {
5623
5670
  nextPageUrl() {
5624
5671
  return this.hasMorePages() ? this.url(this.currentPageValue + 1) : null;
5625
5672
  }
5626
- /** The page links Laravel renders: previous, the page window with '...' gaps, next. */
5673
+ /**
5674
+ * The page links Laravel renders: previous, the page window with '...' gaps, next. The labels are plain text
5675
+ * ("« Previous", "Next »"), not Laravel's `&laquo;` entities, so a page can print them as text.
5676
+ */
5627
5677
  linkCollection() {
5628
- const links = [{ url: this.previousPageUrl(), label: "&laquo; Previous", active: false }];
5678
+ const links = [{ url: this.previousPageUrl(), label: "\xAB Previous", active: false }];
5629
5679
  for (const element of this.elements()) {
5630
5680
  if (element === "...") links.push({ url: null, label: "...", active: false });
5631
5681
  else for (const [page, url2] of element) links.push({ url: url2, label: String(page), active: page === this.currentPageValue });
5632
5682
  }
5633
- links.push({ url: this.nextPageUrl(), label: "Next &raquo;", active: false });
5683
+ links.push({ url: this.nextPageUrl(), label: "Next \xBB", active: false });
5634
5684
  return links;
5635
5685
  }
5636
5686
  /** Laravel's UrlWindow: the first pages, the slider around the current page and the last pages, with '...' between. */
@@ -5752,6 +5802,9 @@ var EMPTY = sql2.raw("");
5752
5802
  var isSqlFragment = (value2) => typeof value2 === "object" && value2 !== null && typeof value2.toOperationNode === "function";
5753
5803
  var join8 = (parts, separator = ", ") => sql2.join(parts, sql2.raw(separator));
5754
5804
  var clauses = (parts) => join8(parts.filter((part) => part !== void 0), " ");
5805
+ function likeToGlob(pattern) {
5806
+ return pattern.replaceAll("*", "[*]").replaceAll("?", "[?]").replaceAll("%", "*").replaceAll("_", "?");
5807
+ }
5755
5808
  var Grammar = class {
5756
5809
  constructor(driver) {
5757
5810
  this.driver = driver;
@@ -5832,6 +5885,8 @@ var Grammar = class {
5832
5885
  }
5833
5886
  case "null":
5834
5887
  return sql2`${this.wrap(where.column)} ${sql2.raw(where.not ? "is not null" : "is null")}`;
5888
+ case "like":
5889
+ return this.compileWhereLike(where);
5835
5890
  case "between":
5836
5891
  return sql2`${this.wrap(where.column)} ${sql2.raw(where.not ? "not between" : "between")} ${this.parameter(where.values[0])} and ${this.parameter(where.values[1])}`;
5837
5892
  case "column":
@@ -5844,6 +5899,18 @@ var Grammar = class {
5844
5899
  return rawWithBindings(where.sql, where.bindings.map((value2) => this.prepare(value2)));
5845
5900
  }
5846
5901
  }
5902
+ /**
5903
+ * whereLike() per driver, as Laravel 12's grammars: Postgres compares the column as text with ilike (like when
5904
+ * case-sensitive); MySQL uses like (like binary); SQLite uses like, or glob with the pattern translated.
5905
+ */
5906
+ compileWhereLike(where) {
5907
+ const not = where.not ? "not " : "";
5908
+ const column = this.wrap(where.column);
5909
+ if (this.driver === "pgsql") return sql2`${column}::text ${sql2.raw(`${not}${where.caseSensitive ? "like" : "ilike"}`)} ${this.parameter(where.value)}`;
5910
+ if (this.driver === "mysql") return sql2`${column} ${sql2.raw(`${not}${where.caseSensitive ? "like binary" : "like"}`)} ${this.parameter(where.value)}`;
5911
+ if (where.caseSensitive) return sql2`${column} ${sql2.raw(`${not}glob`)} ${this.parameter(likeToGlob(where.value))}`;
5912
+ return sql2`${column} ${sql2.raw(`${not}like`)} ${this.parameter(where.value)}`;
5913
+ }
5847
5914
  compileJoin(joinClause) {
5848
5915
  if (joinClause.joinType === "cross") return sql2`cross join ${this.wrapTable(joinClause.table)}`;
5849
5916
  return sql2`${sql2.raw(joinClause.joinType)} join ${this.wrapTable(joinClause.table)} ${this.compileWheres(joinClause.wheres, "on") ?? EMPTY}`;
@@ -6096,6 +6163,25 @@ var Builder = class _Builder {
6096
6163
  this.wheres.push({ type: "between", column, values, not: true, boolean: "and" });
6097
6164
  return this;
6098
6165
  }
6166
+ /**
6167
+ * Laravel's whereLike(): the value is the pattern, `%` and `_` included (`whereLike('title', `%${term}%`)`).
6168
+ * Case-insensitive unless caseSensitive: ilike on Postgres, like on MySQL and SQLite (their like already ignores
6169
+ * case: MySQL through the column's collation, SQLite for ASCII letters). Case-sensitive is like on Postgres,
6170
+ * like binary on MySQL and glob on SQLite.
6171
+ */
6172
+ whereLike(column, value2, caseSensitive = false, boolean = "and", not = false) {
6173
+ this.wheres.push({ type: "like", column, value: value2, caseSensitive, not, boolean });
6174
+ return this;
6175
+ }
6176
+ orWhereLike(column, value2, caseSensitive = false) {
6177
+ return this.whereLike(column, value2, caseSensitive, "or");
6178
+ }
6179
+ whereNotLike(column, value2, caseSensitive = false, boolean = "and") {
6180
+ return this.whereLike(column, value2, caseSensitive, boolean, true);
6181
+ }
6182
+ orWhereNotLike(column, value2, caseSensitive = false) {
6183
+ return this.whereNotLike(column, value2, caseSensitive, "or");
6184
+ }
6099
6185
  /** Compares two columns: whereColumn('updated_at', '>', 'created_at'). */
6100
6186
  whereColumn(first, operatorOrSecond, second, boolean = "and") {
6101
6187
  const [operator, other] = second === void 0 ? ["=", operatorOrSecond] : [operatorOrSecond, second];
@@ -6219,10 +6305,16 @@ var Builder = class _Builder {
6219
6305
  this.lockMode = "share";
6220
6306
  return this;
6221
6307
  }
6222
- /** Calls callback(this, value) when value is truthy (or the default callback otherwise). */
6223
6308
  when(value2, callback, otherwise) {
6224
- if (value2) callback(this, value2);
6225
- else otherwise?.(this, value2);
6309
+ const resolved = typeof value2 === "function" ? value2(this) : value2;
6310
+ if (resolved) callback(this, resolved);
6311
+ else otherwise?.(this, resolved);
6312
+ return this;
6313
+ }
6314
+ unless(value2, callback, otherwise) {
6315
+ const resolved = typeof value2 === "function" ? value2(this) : value2;
6316
+ if (!resolved) callback(this, resolved);
6317
+ else otherwise?.(this, resolved);
6226
6318
  return this;
6227
6319
  }
6228
6320
  tap(callback) {
@@ -7909,6 +8001,18 @@ var Builder2 = class extends Builder {
7909
8001
  whereBetween(column, values) {
7910
8002
  return super.whereBetween(column, values);
7911
8003
  }
8004
+ whereLike(column, value2, caseSensitive = false, boolean = "and", not = false) {
8005
+ return super.whereLike(column, value2, caseSensitive, boolean, not);
8006
+ }
8007
+ orWhereLike(column, value2, caseSensitive = false) {
8008
+ return super.orWhereLike(column, value2, caseSensitive);
8009
+ }
8010
+ whereNotLike(column, value2, caseSensitive = false, boolean = "and") {
8011
+ return super.whereNotLike(column, value2, caseSensitive, boolean);
8012
+ }
8013
+ orWhereNotLike(column, value2, caseSensitive = false) {
8014
+ return super.orWhereNotLike(column, value2, caseSensitive);
8015
+ }
7912
8016
  orderBy(column, direction = "asc") {
7913
8017
  return super.orderBy(column, direction);
7914
8018
  }
@@ -9472,6 +9576,14 @@ var Model = class _Model {
9472
9576
  const query = this.query();
9473
9577
  return Reflect.apply(query.where, query, args);
9474
9578
  }
9579
+ static when(...args) {
9580
+ const query = this.query();
9581
+ return Reflect.apply(query.when, query, args);
9582
+ }
9583
+ static unless(...args) {
9584
+ const query = this.query();
9585
+ return Reflect.apply(query.unless, query, args);
9586
+ }
9475
9587
  static whereKey(id) {
9476
9588
  return this.query().whereKey(id);
9477
9589
  }
@@ -9490,6 +9602,13 @@ var Model = class _Model {
9490
9602
  static whereBetween(column, values) {
9491
9603
  return this.query().whereBetween(column, values);
9492
9604
  }
9605
+ /** Post.whereLike('title', `%${term}%`): case-insensitive unless caseSensitive (see the query builder's whereLike()). */
9606
+ static whereLike(column, value2, caseSensitive = false) {
9607
+ return this.query().whereLike(column, value2, caseSensitive);
9608
+ }
9609
+ static whereNotLike(column, value2, caseSensitive = false) {
9610
+ return this.query().whereNotLike(column, value2, caseSensitive);
9611
+ }
9493
9612
  static whereColumn(first, operatorOrSecond, second) {
9494
9613
  return this.query().whereColumn(first, operatorOrSecond, second);
9495
9614
  }
@@ -9675,8 +9794,8 @@ var Model = class _Model {
9675
9794
  /** Guarded names match case-insensitively: SQLite and MySQL column names are case-insensitive. */
9676
9795
  isGuarded(key) {
9677
9796
  if (this.guarded.length === 0) return false;
9678
- const lower = key.toLowerCase();
9679
- return this.guarded.some((guarded) => guarded === "*" || guarded.toLowerCase() === lower);
9797
+ const lower2 = key.toLowerCase();
9798
+ return this.guarded.some((guarded) => guarded === "*" || guarded.toLowerCase() === lower2);
9680
9799
  }
9681
9800
  totallyGuarded() {
9682
9801
  return !_Model.isUnguarded() && this.fillable.length === 0 && this.guarded.length === 1 && this.guarded[0] === "*";
@@ -10448,6 +10567,90 @@ var Pivot = class extends Model {
10448
10567
  incrementing = false;
10449
10568
  timestamps = false;
10450
10569
  };
10570
+ var DatabaseNotification = class extends Model {
10571
+ table = "notifications";
10572
+ keyType = "string";
10573
+ incrementing = false;
10574
+ guarded = [];
10575
+ casts = { data: "array", read_at: "datetime" };
10576
+ /** The model the notification was sent to. */
10577
+ notifiable() {
10578
+ return this.morphTo("notifiable");
10579
+ }
10580
+ /** Sets read_at to now and saves, unless it is already read. */
10581
+ async markAsRead() {
10582
+ if (this.unread()) await this.forceFill({ read_at: this.freshTimestamp() }).save();
10583
+ }
10584
+ /** Clears read_at and saves, unless it is already unread. */
10585
+ async markAsUnread() {
10586
+ if (this.read()) await this.forceFill({ read_at: null }).save();
10587
+ }
10588
+ read() {
10589
+ return this.read_at !== null && this.read_at !== void 0;
10590
+ }
10591
+ unread() {
10592
+ return !this.read();
10593
+ }
10594
+ /** `query.read()`: only read notifications. */
10595
+ static scopeRead(query) {
10596
+ return query.whereNotNull("read_at");
10597
+ }
10598
+ /** `query.unread()`: only unread notifications. */
10599
+ static scopeUnread(query) {
10600
+ return query.whereNull("read_at");
10601
+ }
10602
+ };
10603
+ var DatabaseNotificationCollection = class extends Collection {
10604
+ /** Marks every notification as read (one save each, as in Laravel). */
10605
+ async markAsRead() {
10606
+ for (const notification of this.all()) await notification.markAsRead();
10607
+ }
10608
+ /** Marks every notification as unread. */
10609
+ async markAsUnread() {
10610
+ for (const notification of this.all()) await notification.markAsUnread();
10611
+ }
10612
+ };
10613
+ var DatabaseNotificationsRelation = class extends MorphMany {
10614
+ async get() {
10615
+ return new DatabaseNotificationCollection(await this.runSelect());
10616
+ }
10617
+ async getResults() {
10618
+ const key = this.getParentKey();
10619
+ return key === null || key === void 0 ? new DatabaseNotificationCollection() : this.get();
10620
+ }
10621
+ initRelation(models, relation) {
10622
+ for (const model of models) model.setRelation(relation, new DatabaseNotificationCollection());
10623
+ return models;
10624
+ }
10625
+ match(models, results, relation) {
10626
+ const dictionary = this.buildDictionary(results);
10627
+ for (const model of models) {
10628
+ model.setRelation(relation, new DatabaseNotificationCollection(dictionary.get(String(model.getAttribute(this.localKey))) ?? []));
10629
+ }
10630
+ return models;
10631
+ }
10632
+ };
10633
+ function HasDatabaseNotifications(Base) {
10634
+ class WithDatabaseNotifications extends Base {
10635
+ notifications() {
10636
+ const related = this.newRelatedInstance(DatabaseNotification);
10637
+ return new DatabaseNotificationsRelation(
10638
+ related,
10639
+ this,
10640
+ related.qualifyColumn("notifiable_type"),
10641
+ related.qualifyColumn("notifiable_id"),
10642
+ this.getKeyName()
10643
+ ).latest();
10644
+ }
10645
+ readNotifications() {
10646
+ return this.notifications().whereNotNull("read_at");
10647
+ }
10648
+ unreadNotifications() {
10649
+ return this.notifications().whereNull("read_at");
10650
+ }
10651
+ }
10652
+ return WithDatabaseNotifications;
10653
+ }
10451
10654
  var Migration = class {
10452
10655
  /** The connection to run on (default: the default connection). */
10453
10656
  connection = void 0;
@@ -10858,7 +11061,7 @@ var TypeGenerator = class {
10858
11061
  }
10859
11062
  };
10860
11063
  var text = (value2) => typeof value2 === "string" && value2 !== "" ? value2 : void 0;
10861
- var list = (value2) => Array.isArray(value2) ? value2.map(String) : text(value2) ? [String(value2)] : [];
11064
+ var list2 = (value2) => Array.isArray(value2) ? value2.map(String) : text(value2) ? [String(value2)] : [];
10862
11065
  var integer = (value2) => {
10863
11066
  const number3 = Number(value2 ?? 0);
10864
11067
  return Number.isInteger(number3) && number3 > 0 ? number3 : 0;
@@ -10874,7 +11077,7 @@ function confirmToProceed(context, command) {
10874
11077
  return false;
10875
11078
  }
10876
11079
  function migrationPaths(context, command) {
10877
- const paths = list(command.option("path"));
11080
+ const paths = list2(command.option("path"));
10878
11081
  if (!paths.length) return [context.app.databasePath("migrations")];
10879
11082
  return paths.map((path) => isAbsolute(path) ? path : context.app.basePath(path));
10880
11083
  }
@@ -11462,9 +11665,21 @@ function currentRequest2() {
11462
11665
  return void 0;
11463
11666
  }
11464
11667
  }
11668
+ function paginationState() {
11669
+ const container = currentContainer();
11670
+ if (!container?.bound(PaginationState)) return void 0;
11671
+ try {
11672
+ return container.make(PaginationState);
11673
+ } catch (error) {
11674
+ if (error instanceof BindingResolutionError) return void 0;
11675
+ throw error;
11676
+ }
11677
+ }
11465
11678
  function usePaginationResolvers() {
11466
- AbstractPaginator.currentPathResolver = () => currentRequest2()?.url() ?? "/";
11679
+ AbstractPaginator.currentPathResolver = () => paginationState()?.currentPath() ?? currentRequest2()?.url() ?? "/";
11467
11680
  AbstractPaginator.currentPageResolver = (pageName) => {
11681
+ const state = paginationState()?.currentPage(pageName);
11682
+ if (state !== void 0) return state;
11468
11683
  const page = Number(currentRequest2()?.input(pageName));
11469
11684
  return Number.isInteger(page) && page >= 1 ? page : 1;
11470
11685
  };
@@ -11713,8 +11928,8 @@ function decrypt(payload, unserialize = true) {
11713
11928
  return inject(Encrypter).decrypt(payload, unserialize);
11714
11929
  }
11715
11930
  function previousKeys(value2) {
11716
- const list3 = Array.isArray(value2) ? value2 : typeof value2 === "string" ? value2.split(",") : [];
11717
- return list3.map((key) => String(key).trim()).filter((key) => key !== "");
11931
+ const list4 = Array.isArray(value2) ? value2 : typeof value2 === "string" ? value2.split(",") : [];
11932
+ return list4.map((key) => String(key).trim()).filter((key) => key !== "");
11718
11933
  }
11719
11934
  var EncryptionServiceProvider = class extends ServiceProvider {
11720
11935
  register() {
@@ -11846,8 +12061,8 @@ var SHOULD_QUEUE22 = /* @__PURE__ */ Symbol.for("oriel:bus.shouldQueue");
11846
12061
  var QUEUE_OPTION_KEYS = ["connection", "queue", "delay", "tries", "backoff", "timeout"];
11847
12062
  function isQueueableListener(cls, instance) {
11848
12063
  const members = instance;
11849
- if (members[SHOULD_QUEUE22] === true) return true;
11850
12064
  const statics = cls;
12065
+ if (members.shouldQueue === true || statics.shouldQueue === true || members[SHOULD_QUEUE22] === true) return true;
11851
12066
  if (QUEUE_OPTION_KEYS.some((key) => members[key] !== void 0 || statics[key] !== void 0)) return true;
11852
12067
  return typeof members.uniqueId === "function" || typeof members.retryUntil === "function" || typeof statics.uniqueId === "function" || typeof statics.retryUntil === "function";
11853
12068
  }
@@ -11892,9 +12107,9 @@ var Dispatcher2 = class {
11892
12107
  throw new InvalidListenerError(label);
11893
12108
  }
11894
12109
  for (const event2 of Array.isArray(events) ? events : [events]) {
11895
- const list3 = this.listeners.get(event2) ?? [];
11896
- list3.push(listener);
11897
- this.listeners.set(event2, list3);
12110
+ const list4 = this.listeners.get(event2) ?? [];
12111
+ list4.push(listener);
12112
+ this.listeners.set(event2, list4);
11898
12113
  }
11899
12114
  }
11900
12115
  hasListeners(event2) {
@@ -11907,7 +12122,7 @@ var Dispatcher2 = class {
11907
12122
  /** Introspection for the event:list command. Not part of the EventDispatcher contract. */
11908
12123
  registeredEvents() {
11909
12124
  const rows = [];
11910
- for (const [key, list3] of this.listeners) rows.push({ event: nameOf(key), listeners: list3.length });
12125
+ for (const [key, list4] of this.listeners) rows.push({ event: nameOf(key), listeners: list4.length });
11911
12126
  return rows.sort((a, b) => a.event.localeCompare(b.event));
11912
12127
  }
11913
12128
  subscribe(subscriber) {
@@ -11951,8 +12166,8 @@ var Dispatcher2 = class {
11951
12166
  const exact = [...this.listeners.get(key) ?? []];
11952
12167
  const wildcardLists = typeof key === "string" ? this.wildcardPatternsFor(key).map((pattern) => [...this.listeners.get(pattern) ?? []]) : [];
11953
12168
  for (const listener of exact) yield { listener, wildcard: false };
11954
- for (const list3 of wildcardLists) {
11955
- for (const listener of list3) yield { listener, wildcard: true };
12169
+ for (const list4 of wildcardLists) {
12170
+ for (const listener of list4) yield { listener, wildcard: true };
11956
12171
  }
11957
12172
  }
11958
12173
  wildcardPatternsFor(event2) {
@@ -12039,6 +12254,7 @@ import { dirname as dirname4, extname as extname2, resolve as resolve2 } from "p
12039
12254
  import { Readable } from "stream";
12040
12255
  import { pipeline } from "stream/promises";
12041
12256
  import { resolve, sep as sep3 } from "path";
12257
+ import { posix } from "path";
12042
12258
  import {
12043
12259
  CopyObjectCommand,
12044
12260
  DeleteObjectCommand,
@@ -12109,24 +12325,54 @@ var MIME_TYPES = {
12109
12325
  zip: "application/zip",
12110
12326
  gz: "application/gzip",
12111
12327
  tar: "application/x-tar",
12328
+ "7z": "application/x-7z-compressed",
12329
+ rar: "application/vnd.rar",
12330
+ epub: "application/epub+zip",
12331
+ rtf: "application/rtf",
12332
+ doc: "application/msword",
12333
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
12334
+ xls: "application/vnd.ms-excel",
12335
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
12336
+ ppt: "application/vnd.ms-powerpoint",
12337
+ pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
12338
+ odt: "application/vnd.oasis.opendocument.text",
12339
+ ods: "application/vnd.oasis.opendocument.spreadsheet",
12340
+ odp: "application/vnd.oasis.opendocument.presentation",
12112
12341
  png: "image/png",
12113
12342
  jpg: "image/jpeg",
12114
12343
  jpeg: "image/jpeg",
12115
12344
  gif: "image/gif",
12116
12345
  webp: "image/webp",
12346
+ avif: "image/avif",
12117
12347
  svg: "image/svg+xml",
12118
12348
  ico: "image/x-icon",
12119
12349
  bmp: "image/bmp",
12350
+ tif: "image/tiff",
12351
+ tiff: "image/tiff",
12352
+ heic: "image/heic",
12353
+ heif: "image/heif",
12120
12354
  mp3: "audio/mpeg",
12355
+ m4a: "audio/mp4",
12121
12356
  wav: "audio/wav",
12357
+ ogg: "audio/ogg",
12358
+ oga: "audio/ogg",
12359
+ opus: "audio/ogg",
12360
+ flac: "audio/flac",
12361
+ aac: "audio/aac",
12122
12362
  mp4: "video/mp4",
12363
+ mov: "video/quicktime",
12123
12364
  webm: "video/webm",
12365
+ ogv: "video/ogg",
12366
+ avi: "video/x-msvideo",
12124
12367
  woff: "font/woff",
12125
12368
  woff2: "font/woff2",
12126
- ttf: "font/ttf"
12369
+ ttf: "font/ttf",
12370
+ otf: "font/otf",
12371
+ wasm: "application/wasm"
12127
12372
  };
12128
12373
  function mimeFromExtension(extension) {
12129
- return MIME_TYPES[extension.replace(/^\./, "").toLowerCase()];
12374
+ const key = extension.replace(/^\./, "").toLowerCase();
12375
+ return Object.hasOwn(MIME_TYPES, key) ? MIME_TYPES[key] : void 0;
12130
12376
  }
12131
12377
  function resolveDiskPath(root, path) {
12132
12378
  const resolvedRoot = resolve(root);
@@ -12206,7 +12452,7 @@ var LocalFilesystem = class {
12206
12452
  async putFileAs(directory, file, name, options) {
12207
12453
  const path = joinDiskPath(directory, name);
12208
12454
  const bytes = new Uint8Array(await file.arrayBuffer());
12209
- await this.put(path, bytes, { mimeType: file.mimeType, ...options });
12455
+ await this.put(path, bytes, options);
12210
12456
  return path;
12211
12457
  }
12212
12458
  async delete(paths) {
@@ -12371,27 +12617,37 @@ var S3Filesystem = class {
12371
12617
  const response2 = await this.getObject(path);
12372
12618
  return response2.Body.transformToWebStream();
12373
12619
  }
12620
+ /** Sends the type of the path when the options name none (Laravel's S3 adapter detects one too). */
12374
12621
  async put(path, contents, options) {
12375
12622
  const body = contents instanceof ReadableStream ? await collectStream(contents) : contents;
12376
- await this.client.send(
12377
- new PutObjectCommand({
12378
- Bucket: this.config.bucket,
12379
- Key: path,
12380
- Body: body,
12381
- ContentType: options?.mimeType,
12382
- ACL: options?.visibility === "public" ? "public-read" : void 0
12383
- })
12384
- );
12623
+ await this.putObject(path, body, options?.mimeType ?? mimeFromExtension(posix.extname(path)), options);
12385
12624
  return true;
12386
12625
  }
12387
12626
  async putFile(directory, file, options) {
12388
12627
  return this.putFileAs(directory, file, uniqueFileName(file.extension()), options);
12389
12628
  }
12629
+ /**
12630
+ * Sends the upload's own type: its extension(), which follows what a request upload's bytes show (the client's claim
12631
+ * counts only where extension() keeps it). Never the MIME type the client sent as such, nor the name it is stored
12632
+ * under (an app may name it after the client's file name): S3, or a CDN in front of it, serves the object with this
12633
+ * type. An upload of no known type is sent with none (served as binary).
12634
+ */
12390
12635
  async putFileAs(directory, file, name, options) {
12391
12636
  const path = joinDiskPath(directory, name);
12392
- await this.put(path, new Uint8Array(await file.arrayBuffer()), { mimeType: file.mimeType, ...options });
12637
+ await this.putObject(path, new Uint8Array(await file.arrayBuffer()), options?.mimeType ?? mimeFromExtension(file.extension()), options);
12393
12638
  return path;
12394
12639
  }
12640
+ async putObject(path, body, contentType, options) {
12641
+ await this.client.send(
12642
+ new PutObjectCommand({
12643
+ Bucket: this.config.bucket,
12644
+ Key: path,
12645
+ Body: body,
12646
+ ContentType: contentType,
12647
+ ACL: options?.visibility === "public" ? "public-read" : void 0
12648
+ })
12649
+ );
12650
+ }
12395
12651
  async delete(paths) {
12396
12652
  for (const path of Array.isArray(paths) ? paths : [paths]) {
12397
12653
  await this.client.send(new DeleteObjectCommand({ Bucket: this.config.bucket, Key: path }));
@@ -13814,8 +14070,8 @@ var InertiaMiddleware = class {
13814
14070
  bag,
13815
14071
  Object.fromEntries(
13816
14072
  Object.entries(fields ?? {}).map(([field, messages]) => {
13817
- const list3 = Array.isArray(messages) ? messages.map(String) : [String(messages)];
13818
- return [field, this.withAllErrors ? list3 : list3[0] ?? ""];
14073
+ const list4 = Array.isArray(messages) ? messages.map(String) : [String(messages)];
14074
+ return [field, this.withAllErrors ? list4 : list4[0] ?? ""];
13819
14075
  })
13820
14076
  )
13821
14077
  ])
@@ -14667,8 +14923,8 @@ function normalizeAddress(recipient) {
14667
14923
  }
14668
14924
  function normalizeAddresses(recipients) {
14669
14925
  if (recipients === void 0) return [];
14670
- const list3 = Array.isArray(recipients) ? recipients : [recipients];
14671
- return list3.map(normalizeAddress);
14926
+ const list4 = Array.isArray(recipients) ? recipients : [recipients];
14927
+ return list4.map(normalizeAddress);
14672
14928
  }
14673
14929
  function formatAddress(address) {
14674
14930
  return address.name ? `${address.name} <${address.address}>` : address.address;
@@ -14837,7 +15093,7 @@ var Mailable = class {
14837
15093
  var SHOULD_QUEUE4 = /* @__PURE__ */ Symbol.for("oriel:bus.shouldQueue");
14838
15094
  function isQueueableMailable(mailable) {
14839
15095
  const record = mailable;
14840
- if (record[SHOULD_QUEUE4] === true) return true;
15096
+ if (record.shouldQueue === true || record[SHOULD_QUEUE4] === true) return true;
14841
15097
  return record.connection !== void 0 || record.queue !== void 0 || record.delay !== void 0 || record.tries !== void 0 || record.backoff !== void 0 || record.timeout !== void 0 || typeof record.uniqueId === "function" || typeof record.retryUntil === "function";
14842
15098
  }
14843
15099
  var MailerImpl = class {
@@ -15285,47 +15541,10 @@ var MailNotificationChannel = class {
15285
15541
  }
15286
15542
  };
15287
15543
  var NOTIFICATIONS_TABLE = "notifications";
15288
- var ZONELESS_TIMESTAMP = /^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}(:\d{2}(\.\d+)?)?$/;
15289
- function parseStoredDate2(value2) {
15290
- if (value2 instanceof Date) return value2;
15291
- if (typeof value2 === "number") return new Date(value2);
15292
- const text3 = String(value2);
15293
- return ZONELESS_TIMESTAMP.test(text3) ? /* @__PURE__ */ new Date(`${text3.replace(" ", "T")}Z`) : new Date(text3);
15294
- }
15295
- function wrapRow(row, db) {
15296
- const record = {
15297
- id: String(row.id),
15298
- type: String(row.type),
15299
- data: JSON.parse(String(row.data)),
15300
- createdAt: parseStoredDate2(row.created_at),
15301
- updatedAt: parseStoredDate2(row.updated_at),
15302
- readAt: row.read_at ? parseStoredDate2(row.read_at) : void 0,
15303
- async markAsRead() {
15304
- if (record.readAt) return;
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;
15308
- },
15309
- async markAsUnread() {
15310
- if (!record.readAt) return;
15311
- await db.table(NOTIFICATIONS_TABLE).where("id", record.id).update({ read_at: null, updated_at: /* @__PURE__ */ new Date() });
15312
- record.readAt = void 0;
15313
- }
15314
- };
15315
- return record;
15316
- }
15317
- function requireDatabase() {
15544
+ function requireDatabase(connection) {
15318
15545
  const container = currentContainer();
15319
15546
  if (!container?.bound(DatabaseManager)) throw new DatabaseUnavailableError();
15320
- return container.make(DatabaseManager).connection();
15321
- }
15322
- async function fetchNotifications(notifiableType, notifiableId, filter = "all") {
15323
- const db = requireDatabase();
15324
- let query = db.table(NOTIFICATIONS_TABLE).where("notifiable_type", notifiableType).where("notifiable_id", notifiableId).orderBy("created_at", "desc");
15325
- if (filter === "unread") query = query.whereNull("read_at");
15326
- if (filter === "read") query = query.whereNotNull("read_at");
15327
- const rows = await query.get();
15328
- return rows.all().map((row) => wrapRow(row, db));
15547
+ return container.make(DatabaseManager).connection(connection);
15329
15548
  }
15330
15549
  var DatabaseNotificationChannel = class {
15331
15550
  async send(notifiable, notification) {
@@ -15335,12 +15554,12 @@ var DatabaseNotificationChannel = class {
15335
15554
  const data = notification.toDatabase ? notification.toDatabase(notifiable) : notification.toArray(notifiable);
15336
15555
  const model = notifiable;
15337
15556
  if (typeof model.getKey !== "function") throw new NotDatabaseNotifiableError(notifiable.constructor.name);
15338
- const db = requireDatabase();
15557
+ const db = requireDatabase(typeof model.getConnectionName === "function" ? model.getConnectionName() : void 0);
15339
15558
  const now5 = /* @__PURE__ */ new Date();
15340
15559
  await db.table(NOTIFICATIONS_TABLE).insert({
15341
15560
  id: notification.id ?? randomUUID4(),
15342
15561
  type: notification.constructor.name,
15343
- notifiable_type: notifiable.constructor.name,
15562
+ notifiable_type: typeof model.getMorphClass === "function" ? model.getMorphClass() : notifiable.constructor.name,
15344
15563
  notifiable_id: model.getKey(),
15345
15564
  data: JSON.stringify(data),
15346
15565
  read_at: null,
@@ -15374,13 +15593,8 @@ function resolveDispatcher() {
15374
15593
  if (!container?.bound(NotificationDispatcher)) throw new NotificationDispatcherUnavailableError();
15375
15594
  return container.make(NotificationDispatcher);
15376
15595
  }
15377
- function requireKey(instance) {
15378
- const model = instance;
15379
- if (typeof model.getKey !== "function") throw new NotDatabaseNotifiableError(instance.constructor.name);
15380
- return model.getKey();
15381
- }
15382
- function Notifiable(Base) {
15383
- return class NotifiableMixin extends Base {
15596
+ function RoutesNotifications(Base) {
15597
+ return class RoutesNotificationsMixin extends Base {
15384
15598
  routeNotificationFor(channel, notification) {
15385
15599
  const custom = this[`routeNotificationFor${Str.studly(channel)}`];
15386
15600
  if (typeof custom === "function") return custom.call(this, notification);
@@ -15397,15 +15611,6 @@ function Notifiable(Base) {
15397
15611
  async notifyNow(notification, channels) {
15398
15612
  await resolveDispatcher().sendNow(this, notification, channels);
15399
15613
  }
15400
- notifications() {
15401
- return fetchNotifications(this.constructor.name, requireKey(this));
15402
- }
15403
- unreadNotifications() {
15404
- return fetchNotifications(this.constructor.name, requireKey(this), "unread");
15405
- }
15406
- readNotifications() {
15407
- return fetchNotifications(this.constructor.name, requireKey(this), "read");
15408
- }
15409
15614
  };
15410
15615
  }
15411
15616
  var AnonymousNotifiable = class {
@@ -15475,7 +15680,7 @@ var SendQueuedNotifications = class {
15475
15680
  SendQueuedNotifications.prototype[SHOULD_QUEUE5] = true;
15476
15681
  function isQueueableNotification(notification) {
15477
15682
  const record = notification;
15478
- if (record[SHOULD_QUEUE5] === true) return true;
15683
+ if (record.shouldQueue === true || record[SHOULD_QUEUE5] === true) return true;
15479
15684
  return record.connection !== void 0 || record.queue !== void 0 || record.delay !== void 0 || record.tries !== void 0 || record.backoff !== void 0 || record.timeout !== void 0 || typeof record.uniqueId === "function" || typeof record.retryUntil === "function";
15480
15685
  }
15481
15686
  function forNotifiable(notification) {
@@ -15513,12 +15718,12 @@ var Dispatcher3 = class {
15513
15718
  return channel;
15514
15719
  }
15515
15720
  async send(notifiables, notification) {
15516
- const list3 = toNotifiableList(notifiables);
15517
- if (list3.length === 0) return;
15721
+ const list4 = toNotifiableList(notifiables);
15722
+ if (list4.length === 0) return;
15518
15723
  if (isQueueableNotification(notification)) {
15519
15724
  if (!this.container.bound(BusDispatcher)) throw new NotificationQueueUnavailableError();
15520
15725
  const bus = this.container.make(BusDispatcher);
15521
- for (const notifiable of list3) {
15726
+ for (const notifiable of list4) {
15522
15727
  const own = forNotifiable(notification);
15523
15728
  for (const channel of notification.via(notifiable)) {
15524
15729
  await bus.dispatch(new SendQueuedNotifications([notifiable], own, [channel]));
@@ -15526,11 +15731,11 @@ var Dispatcher3 = class {
15526
15731
  }
15527
15732
  return;
15528
15733
  }
15529
- await this.sendNow(list3, notification);
15734
+ await this.sendNow(list4, notification);
15530
15735
  }
15531
15736
  async sendNow(notifiables, notification, channels) {
15532
- const list3 = toNotifiableList(notifiables);
15533
- for (const notifiable of list3) {
15737
+ const list4 = toNotifiableList(notifiables);
15738
+ for (const notifiable of list4) {
15534
15739
  const own = forNotifiable(notification);
15535
15740
  const names = channels ?? notification.via(notifiable);
15536
15741
  for (const name of names) {
@@ -17305,7 +17510,7 @@ function discoverJobs(directory, registry2) {
17305
17510
  return discoverClasses(directory, registry2, isJobClass);
17306
17511
  }
17307
17512
  var text2 = (value2) => optionalString2(value2) || void 0;
17308
- var list2 = (value2) => Array.isArray(value2) ? value2.map(String) : text2(value2) ? [String(value2)] : [];
17513
+ var list3 = (value2) => Array.isArray(value2) ? value2.map(String) : text2(value2) ? [String(value2)] : [];
17309
17514
  var number2 = (value2, fallback) => {
17310
17515
  const parsed = Number(value2);
17311
17516
  return value2 === void 0 || value2 === null || value2 === "" || Number.isNaN(parsed) ? fallback : parsed;
@@ -17393,7 +17598,7 @@ function registerQueueCommands(kernel, context) {
17393
17598
  'queue:retry {id?* : The ID of the failed job or "all" to retry all jobs} {--queue= : Retry all of the failed jobs for the specified queue}',
17394
17599
  "Retry a failed queue job",
17395
17600
  async (out) => {
17396
- const ids = await retryableIds(list2(out.argument("id")), text2(out.option("queue")));
17601
+ const ids = await retryableIds(list3(out.argument("id")), text2(out.option("queue")));
17397
17602
  if (ids.length === 0) {
17398
17603
  out.info("No retryable jobs found.");
17399
17604
  return 0;
@@ -18215,6 +18420,14 @@ var BaseRouter = class {
18215
18420
  getModel(parameter) {
18216
18421
  return this.#models.get(parameter);
18217
18422
  }
18423
+ /**
18424
+ * Binds a matched route's raw parameter values as a request to it would: Route.bind() callbacks, Route.model(),
18425
+ * then implicit binding through the RouteModelResolver of `container`. A missing model throws
18426
+ * RouteModelNotFoundError (404). Live uses it to check a page route's `can:` middleware again on each update.
18427
+ */
18428
+ substituteBindings(route2, values, container) {
18429
+ return substituteBindings(this, route2, values, container);
18430
+ }
18218
18431
  aliasMiddleware(name, middleware) {
18219
18432
  this.#aliases[name] = middleware;
18220
18433
  return this;
@@ -18228,20 +18441,20 @@ var BaseRouter = class {
18228
18441
  return this;
18229
18442
  }
18230
18443
  pushMiddlewareToGroup(group, middleware) {
18231
- const list3 = this.#groups[group] ??= [];
18232
- if (!list3.includes(middleware)) list3.push(middleware);
18444
+ const list4 = this.#groups[group] ??= [];
18445
+ if (!list4.includes(middleware)) list4.push(middleware);
18233
18446
  return this;
18234
18447
  }
18235
18448
  prependMiddlewareToGroup(group, middleware) {
18236
- const list3 = this.#groups[group] ??= [];
18237
- if (!list3.includes(middleware)) list3.unshift(middleware);
18449
+ const list4 = this.#groups[group] ??= [];
18450
+ if (!list4.includes(middleware)) list4.unshift(middleware);
18238
18451
  return this;
18239
18452
  }
18240
18453
  hasMiddlewareGroup(name) {
18241
18454
  return Object.hasOwn(this.#groups, name);
18242
18455
  }
18243
18456
  getMiddlewareGroups() {
18244
- return Object.fromEntries(Object.entries(this.#groups).map(([name, list3]) => [name, [...list3]]));
18457
+ return Object.fromEntries(Object.entries(this.#groups).map(([name, list4]) => [name, [...list4]]));
18245
18458
  }
18246
18459
  /** Every route, in registration order. */
18247
18460
  getRoutes() {
@@ -18483,6 +18696,48 @@ var BaseUrlGenerator = class {
18483
18696
  }
18484
18697
  };
18485
18698
  var Route = facade(Router);
18699
+ var DiagnosingHealth = class {
18700
+ };
18701
+ var escapeHtml3 = (value2) => value2.replace(/[&<>"']/g, (char) => `&#${char.charCodeAt(0)};`);
18702
+ var STYLE = ':root{color-scheme:dark}*{box-sizing:border-box;margin:0}html{background:#05050b}body{min-height:100vh;display:grid;place-items:center;padding:20px;background:#1a1a1a;color:#fff;font:400 16px/1.7 system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif}main{display:flex;align-items:center;gap:20px;width:100%;max-width:640px;padding:20px 32px;border-radius:18px;background:#212121}.dot{flex:none;width:12px;height:12px;border-radius:50%;background:#74ec5a}.dot.down{background:#ff3543}h1{font-size:21px;line-height:1.4;font-weight:600}p{color:#a3a3a3}.time{color:#ba94ff}';
18703
+ function healthResponse(page = {}) {
18704
+ const healthy = page.healthy ?? true;
18705
+ const time = page.milliseconds === void 0 ? "" : ` Response rendered in <span class="time">${Math.round(page.milliseconds)} ms</span>.`;
18706
+ const html2 = `<!DOCTYPE html>
18707
+ <html lang="en">
18708
+ <head>
18709
+ <meta charset="utf-8">
18710
+ <meta name="viewport" content="width=device-width, initial-scale=1">
18711
+ <title>${escapeHtml3(page.appName ?? "Oriel")}</title>
18712
+ <style>${STYLE}</style>
18713
+ </head>
18714
+ <body>
18715
+ <main>
18716
+ <span class="${healthy ? "dot" : "dot down"}" aria-hidden="true"></span>
18717
+ <div>
18718
+ <h1>Application ${healthy ? "up" : "experiencing problems"}</h1>
18719
+ <p>HTTP request received.${time}</p>
18720
+ </div>
18721
+ </main>
18722
+ </body>
18723
+ </html>
18724
+ `;
18725
+ return new Response(html2, { status: healthy ? 200 : 500, headers: { "content-type": "text/html; charset=utf-8" } });
18726
+ }
18727
+ async function diagnoseHealth(app2) {
18728
+ const started = performance.now();
18729
+ const config2 = app2.bound(ConfigRepository) ? app2.make(ConfigRepository) : void 0;
18730
+ let healthy = true;
18731
+ try {
18732
+ if (app2.bound(EventDispatcher)) await app2.make(EventDispatcher).dispatch(new DiagnosingHealth());
18733
+ } catch (error) {
18734
+ if (config2?.get("app.debug", false) === true) throw error;
18735
+ if (app2.bound(ExceptionHandler)) await app2.make(ExceptionHandler).report(error);
18736
+ healthy = false;
18737
+ }
18738
+ const appName2 = String(config2?.get("app.name", "Oriel") ?? "Oriel");
18739
+ return healthResponse({ healthy, appName: appName2, milliseconds: performance.now() - started });
18740
+ }
18486
18741
  var generation2 = 0;
18487
18742
  async function loadRoutesFrom(app2, router, file) {
18488
18743
  const url2 = `${pathToFileURL7(file).href}?oriel-routes=${++generation2}`;
@@ -18492,10 +18747,6 @@ async function loadRoutesFrom(app2, router, file) {
18492
18747
  ));
18493
18748
  if (typeof module.default === "function") await app2.run(() => module.default(router));
18494
18749
  }
18495
- function healthResponse() {
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>';
18497
- return new Response(html2, { status: 200, headers: { "content-type": "text/html; charset=utf-8" } });
18498
- }
18499
18750
  var sha12 = (value2) => createHash8("sha1").update(value2).digest("hex");
18500
18751
  function withHeaders2(response2, headers) {
18501
18752
  try {
@@ -18572,7 +18823,7 @@ var RoutingServiceProvider = class extends ServiceProvider {
18572
18823
  if (!this.app.bound(RoutingPaths)) return;
18573
18824
  const { web, api, health, apiPrefix } = this.app.make(RoutingPaths);
18574
18825
  const router = this.app.make(Router);
18575
- if (health !== void 0) router.get(health, () => healthResponse());
18826
+ if (health !== void 0) router.get(health, () => diagnoseHealth(this.app));
18576
18827
  if (web !== void 0) await router.middleware("web").group(() => this.#load(router, web));
18577
18828
  if (api !== void 0) await router.prefix(apiPrefix).middleware("api").group(() => this.#load(router, api));
18578
18829
  });
@@ -18656,8 +18907,8 @@ var Store = class {
18656
18907
  for (const [name, item] of Object.entries(values)) Arr.set(this.#attributes, name, item);
18657
18908
  }
18658
18909
  push(key, value2) {
18659
- const list3 = this.get(key, []);
18660
- this.put(key, [...Array.isArray(list3) ? list3 : [list3], value2]);
18910
+ const list4 = this.get(key, []);
18911
+ this.put(key, [...Array.isArray(list4) ? list4 : [list4], value2]);
18661
18912
  }
18662
18913
  increment(key, amount = 1) {
18663
18914
  const value2 = Number(this.get(key, 0)) + amount;
@@ -19323,7 +19574,7 @@ var ValidationErrorImpl = class extends Error {
19323
19574
  var ValidationException = class _ValidationException extends ValidationErrorImpl {
19324
19575
  /** Messages per field, each a string or a list. */
19325
19576
  static withMessages(messages) {
19326
- const errors2 = Object.fromEntries(Object.entries(messages).map(([field, list3]) => [field, typeof list3 === "string" ? [list3] : [...list3]]));
19577
+ const errors2 = Object.fromEntries(Object.entries(messages).map(([field, list4]) => [field, typeof list4 === "string" ? [list4] : [...list4]]));
19327
19578
  return new _ValidationException(errors2);
19328
19579
  }
19329
19580
  constructor(errors2, errorBag = "default", redirectTo2) {
@@ -19434,6 +19685,9 @@ var DEFAULT_MESSAGES = {
19434
19685
  file: "The :attribute field must be a file.",
19435
19686
  image: "The :attribute field must be an image.",
19436
19687
  mimes: "The :attribute field must be a file of type: :values.",
19688
+ mimetypes: "The :attribute field must be a file of type: :values.",
19689
+ extensions: "The :attribute field must have one of the following extensions: :values.",
19690
+ dimensions: "The :attribute field has invalid image dimensions.",
19437
19691
  "max.string": "The :attribute field must not be greater than :max characters.",
19438
19692
  "max.numeric": "The :attribute field must not be greater than :max.",
19439
19693
  "max.array": "The :attribute field must not have more than :max items.",
@@ -19524,6 +19778,90 @@ var databaseRules = {
19524
19778
  messageKey: () => "exists"
19525
19779
  }
19526
19780
  };
19781
+ var FRAME_MARKERS = /* @__PURE__ */ new Set([192, 193, 194, 195, 197, 198, 199, 201, 202, 203, 205, 206, 207]);
19782
+ var MAX_JPEG_STEPS = 1024;
19783
+ var MAX_BOXES = 1024;
19784
+ var fourcc = (view2, offset) => String.fromCharCode(view2.getUint8(offset), view2.getUint8(offset + 1), view2.getUint8(offset + 2), view2.getUint8(offset + 3));
19785
+ var u24le = (view2, offset) => view2.getUint8(offset) | view2.getUint8(offset + 1) << 8 | view2.getUint8(offset + 2) << 16;
19786
+ var READERS = {
19787
+ "image/png": (view2) => fourcc(view2, 12) === "IHDR" ? { width: view2.getUint32(16), height: view2.getUint32(20) } : void 0,
19788
+ "image/gif": (view2) => ({ width: view2.getUint16(6, true), height: view2.getUint16(8, true) }),
19789
+ "image/bmp": (view2) => view2.getUint32(14, true) === 12 ? { width: view2.getUint16(18, true), height: view2.getUint16(20, true) } : { width: Math.abs(view2.getInt32(18, true)), height: Math.abs(view2.getInt32(22, true)) },
19790
+ "image/jpeg": jpeg,
19791
+ "image/webp": webp,
19792
+ "image/avif": avif
19793
+ };
19794
+ function imageDimensions(bytes, mime) {
19795
+ const reader = READERS[mime];
19796
+ if (!reader) return void 0;
19797
+ try {
19798
+ const size = reader(new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength));
19799
+ return size && size.width > 0 && size.height > 0 ? size : void 0;
19800
+ } catch (error) {
19801
+ if (error instanceof RangeError) return void 0;
19802
+ throw error;
19803
+ }
19804
+ }
19805
+ function jpeg(view2) {
19806
+ let offset = 2;
19807
+ for (let step = 0; step < MAX_JPEG_STEPS && offset + 4 <= view2.byteLength; step++) {
19808
+ if (view2.getUint8(offset) !== 255) return void 0;
19809
+ const marker = view2.getUint8(offset + 1);
19810
+ if (marker === 255) offset += 1;
19811
+ else if (marker === 216 || marker === 1 || marker >= 208 && marker <= 215) offset += 2;
19812
+ else if (marker === 217 || marker === 218) return void 0;
19813
+ else if (FRAME_MARKERS.has(marker)) return { height: view2.getUint16(offset + 5), width: view2.getUint16(offset + 7) };
19814
+ else offset += 2 + view2.getUint16(offset + 2);
19815
+ }
19816
+ return void 0;
19817
+ }
19818
+ function webp(view2) {
19819
+ const chunk = fourcc(view2, 12);
19820
+ if (chunk === "VP8 ") {
19821
+ if (view2.getUint8(23) !== 157 || view2.getUint8(24) !== 1 || view2.getUint8(25) !== 42) return void 0;
19822
+ return { width: view2.getUint16(26, true) & 16383, height: view2.getUint16(28, true) & 16383 };
19823
+ }
19824
+ if (chunk === "VP8L") {
19825
+ if (view2.getUint8(20) !== 47) return void 0;
19826
+ const bits = view2.getUint32(21, true);
19827
+ return { width: (bits & 16383) + 1, height: (bits >>> 14 & 16383) + 1 };
19828
+ }
19829
+ if (chunk === "VP8X") return { width: u24le(view2, 24) + 1, height: u24le(view2, 27) + 1 };
19830
+ return void 0;
19831
+ }
19832
+ function* boxes(view2, start2, end) {
19833
+ let offset = start2;
19834
+ for (let count = 0; count < MAX_BOXES && offset + 8 <= end; count++) {
19835
+ let size = view2.getUint32(offset);
19836
+ let header = 8;
19837
+ if (size === 1) {
19838
+ size = Number(view2.getBigUint64(offset + 8));
19839
+ header = 16;
19840
+ } else if (size === 0) {
19841
+ size = end - offset;
19842
+ }
19843
+ if (size < header || offset + size > end) return;
19844
+ yield { type: fourcc(view2, offset + 4), start: offset + header, end: offset + size };
19845
+ offset += size;
19846
+ }
19847
+ }
19848
+ var findBox = (view2, start2, end, type) => {
19849
+ for (const box of boxes(view2, start2, end)) if (box.type === type) return box;
19850
+ return void 0;
19851
+ };
19852
+ function avif(view2) {
19853
+ const meta = findBox(view2, 0, view2.byteLength, "meta");
19854
+ const iprp = meta && findBox(view2, meta.start + 4, meta.end, "iprp");
19855
+ const ipco = iprp && findBox(view2, iprp.start, iprp.end, "ipco");
19856
+ if (!ipco) return void 0;
19857
+ let largest;
19858
+ for (const box of boxes(view2, ipco.start, ipco.end)) {
19859
+ if (box.type !== "ispe") continue;
19860
+ const size = { width: view2.getUint32(box.start + 4), height: view2.getUint32(box.start + 8) };
19861
+ if (!largest || size.width * size.height > largest.width * largest.height) largest = size;
19862
+ }
19863
+ return largest;
19864
+ }
19527
19865
  function splitParameters(name, raw3) {
19528
19866
  return name === "regex" || name === "not_regex" ? [raw3] : raw3.split(",");
19529
19867
  }
@@ -19571,25 +19909,139 @@ function expandWildcardKeys(pattern, data) {
19571
19909
  }
19572
19910
  return paths;
19573
19911
  }
19574
- var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set(["jpg", "jpeg", "png", "bmp", "gif", "svg", "webp"]);
19912
+ var { BINARY_AND_MARKUP_TYPES, detectFileType, EMPTY: EMPTY2, RASTER_IMAGES, SVG, TEXT } = fileType_exports;
19913
+ var inspections = /* @__PURE__ */ new WeakMap();
19914
+ function inspect(file) {
19915
+ let inspection = inspections.get(file);
19916
+ if (!inspection) {
19917
+ inspection = file.arrayBuffer().then((buffer) => {
19918
+ const bytes = new Uint8Array(buffer);
19919
+ const type = detectFileType(bytes);
19920
+ return { type, dimensions: RASTER_IMAGES.has(type.mime) ? imageDimensions(bytes, type.mime) : void 0 };
19921
+ });
19922
+ inspections.set(file, inspection);
19923
+ }
19924
+ return inspection;
19925
+ }
19926
+ function clientExtension(file) {
19927
+ const name = file.clientName.slice(Math.max(file.clientName.lastIndexOf("/"), file.clientName.lastIndexOf("\\")) + 1);
19928
+ const dot = name.lastIndexOf(".");
19929
+ return dot === -1 ? "" : name.slice(dot + 1).trim().toLowerCase();
19930
+ }
19931
+ var PHP_EXTENSIONS = /* @__PURE__ */ new Set(["php", "php3", "php4", "php5", "php7", "php8", "phtml", "phar"]);
19932
+ var blocksPhp = (file, allowed) => !allowed.includes("php") && PHP_EXTENSIONS.has(clientExtension(file));
19933
+ var TEXT_FORMATS = /* @__PURE__ */ new Set(["txt", "text", "csv", "tsv", "json", "md"]);
19934
+ var RECOGNISED_EXTENSIONS = new Set(BINARY_AND_MARKUP_TYPES.flatMap(({ extensions }) => extensions));
19935
+ var lower = (values) => values.map((value2) => value2.trim().toLowerCase());
19936
+ function meetsMimes(type, extension, allowed) {
19937
+ if (type === EMPTY2) return false;
19938
+ if (type === TEXT && allowed.has("txt")) return true;
19939
+ if (type !== TEXT && type.extensions.length > 0) return type.extensions.some((name) => allowed.has(name));
19940
+ if (!allowed.has(extension) || RECOGNISED_EXTENSIONS.has(extension)) return false;
19941
+ return type === TEXT || !TEXT_FORMATS.has(extension);
19942
+ }
19943
+ function allowedExtensions(ctx) {
19944
+ const allowed = new Set(lower(ctx.parameters));
19945
+ if (allowed.has("jpg") || allowed.has("jpeg")) allowed.add("jpg").add("jpeg");
19946
+ return allowed;
19947
+ }
19948
+ var listed = (ctx) => ({ values: ctx.parameters.join(", ") });
19949
+ var DIMENSION_KEYS = ["width", "height", "min_width", "min_height", "max_width", "max_height", "ratio"];
19950
+ function namedParameter(parameter) {
19951
+ const at = parameter.indexOf("=");
19952
+ return at === -1 ? [parameter, ""] : [parameter.slice(0, at), parameter.slice(at + 1)];
19953
+ }
19954
+ function parseRatio(value2) {
19955
+ const match = /^(\d+(?:\.\d+)?|\.\d+)(?:\/(\d+))?$/.exec(value2.trim());
19956
+ if (!match) return void 0;
19957
+ const ratio = Number(match[1]) / Number(match[2] ?? 1);
19958
+ return Number.isFinite(ratio) && ratio > 0 ? ratio : void 0;
19959
+ }
19960
+ function dimensionConstraints(parameters) {
19961
+ if (parameters.length === 0) throw new InvalidRuleParameterError("dimensions", "", `expected one or more of ${DIMENSION_KEYS.join(", ")}`);
19962
+ const constraints = {};
19963
+ for (const parameter of parameters) {
19964
+ const [key, value2] = namedParameter(parameter);
19965
+ if (!DIMENSION_KEYS.includes(key)) {
19966
+ throw new InvalidRuleParameterError("dimensions", parameter, `expected one of ${DIMENSION_KEYS.join(", ")}`);
19967
+ }
19968
+ const number3 = key === "ratio" ? parseRatio(value2) : /^\d+$/.test(value2) ? Number(value2) : void 0;
19969
+ if (number3 === void 0) {
19970
+ throw new InvalidRuleParameterError("dimensions", parameter, key === "ratio" ? "expected a ratio such as 3/2 or 1.5" : "expected a whole number of pixels");
19971
+ }
19972
+ constraints[key] = number3;
19973
+ }
19974
+ return constraints;
19975
+ }
19976
+ function meetsDimensions(constraints, { width, height }) {
19977
+ const { width: exactWidth, height: exactHeight, min_width, max_width, min_height, max_height, ratio } = constraints;
19978
+ if (exactWidth !== void 0 && width !== exactWidth) return false;
19979
+ if (exactHeight !== void 0 && height !== exactHeight) return false;
19980
+ if (min_width !== void 0 && width < min_width) return false;
19981
+ if (max_width !== void 0 && width > max_width) return false;
19982
+ if (min_height !== void 0 && height < min_height) return false;
19983
+ if (max_height !== void 0 && height > max_height) return false;
19984
+ return ratio === void 0 || Math.abs(ratio - width / height) <= 1 / (Math.max((width + height) / 2, height) + 1);
19985
+ }
19575
19986
  var fileRules = {
19576
19987
  file: { validate: (ctx) => isUploadedFileLike(ctx.value), messageKey: () => "file" },
19988
+ /** A JPEG, PNG, GIF, WebP, AVIF or BMP by its bytes; SVG only as `image:allow_svg` (Laravel 12). */
19577
19989
  image: {
19578
- validate: (ctx) => {
19579
- if (!isUploadedFileLike(ctx.value)) return false;
19580
- if (ctx.value.mimeType.startsWith("image/")) return true;
19581
- return IMAGE_EXTENSIONS.has(ctx.value.extension().toLowerCase());
19990
+ validate: async (ctx) => {
19991
+ if (!isUploadedFileLike(ctx.value) || blocksPhp(ctx.value, [])) return false;
19992
+ const { type } = await inspect(ctx.value);
19993
+ return RASTER_IMAGES.has(type.mime) || type === SVG && ctx.parameters.includes("allow_svg");
19582
19994
  },
19583
19995
  messageKey: () => "image"
19584
19996
  },
19585
19997
  mimes: {
19586
- validate: (ctx) => {
19998
+ validate: async (ctx) => {
19587
19999
  if (!isUploadedFileLike(ctx.value)) return false;
19588
- const allowed = ctx.parameters.map((p) => p.toLowerCase());
19589
- return allowed.includes(ctx.value.extension().toLowerCase());
20000
+ const allowed = allowedExtensions(ctx);
20001
+ if (blocksPhp(ctx.value, [...allowed])) return false;
20002
+ return meetsMimes((await inspect(ctx.value)).type, clientExtension(ctx.value), allowed);
19590
20003
  },
19591
20004
  messageKey: () => "mimes",
19592
- replacements: (ctx) => ({ values: ctx.parameters.join(", ") })
20005
+ replacements: listed
20006
+ },
20007
+ /**
20008
+ * The detected MIME type is listed, or its `type/*` wildcard is. `image/*` includes SVG (`image/svg+xml`), as in
20009
+ * Laravel: the rule for photos is `image`.
20010
+ */
20011
+ mimetypes: {
20012
+ validate: async (ctx) => {
20013
+ if (!isUploadedFileLike(ctx.value)) return false;
20014
+ const allowed = lower(ctx.parameters);
20015
+ if (blocksPhp(ctx.value, allowed)) return false;
20016
+ const { mime } = (await inspect(ctx.value)).type;
20017
+ return allowed.includes(mime) || allowed.includes(`${mime.split("/")[0]}/*`);
20018
+ },
20019
+ messageKey: () => "mimetypes",
20020
+ replacements: listed
20021
+ },
20022
+ /**
20023
+ * The pixel size read from the image's header meets every constraint: width, height, min_width, max_width,
20024
+ * min_height, max_height, ratio. SVG and images whose header can't be read fail.
20025
+ */
20026
+ dimensions: {
20027
+ validate: async (ctx) => {
20028
+ const constraints = dimensionConstraints(ctx.parameters);
20029
+ if (!isUploadedFileLike(ctx.value)) return false;
20030
+ const { dimensions } = await inspect(ctx.value);
20031
+ return dimensions !== void 0 && meetsDimensions(constraints, dimensions);
20032
+ },
20033
+ messageKey: () => "dimensions",
20034
+ replacements: (ctx) => Object.fromEntries(ctx.parameters.map(namedParameter))
20035
+ },
20036
+ /** The client file name's extension is listed (Laravel 11). It checks the name only: pair it with mimes or image. */
20037
+ extensions: {
20038
+ validate: (ctx) => {
20039
+ if (!isUploadedFileLike(ctx.value)) return false;
20040
+ const allowed = lower(ctx.parameters);
20041
+ return !blocksPhp(ctx.value, allowed) && allowed.includes(clientExtension(ctx.value));
20042
+ },
20043
+ messageKey: () => "extensions",
20044
+ replacements: listed
19593
20045
  }
19594
20046
  };
19595
20047
  var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
@@ -20276,6 +20728,11 @@ var Notification2 = class extends Notification {
20276
20728
  return NotificationFake.fake(...args);
20277
20729
  }
20278
20730
  };
20731
+
20732
+ // notifiable.ts
20733
+ function Notifiable(Base) {
20734
+ return RoutesNotifications(HasDatabaseNotifications(Base));
20735
+ }
20279
20736
  export {
20280
20737
  API_ROUTES_STUB,
20281
20738
  AboutCommand,
@@ -20299,6 +20756,7 @@ export {
20299
20756
  AuthenticatableModel,
20300
20757
  Authenticate,
20301
20758
  AuthenticationError,
20759
+ Authorizable,
20302
20760
  AuthorizationError,
20303
20761
  AuthorizationErrorImpl,
20304
20762
  Authorize,
@@ -20347,6 +20805,7 @@ export {
20347
20805
  ConsoleServiceProvider,
20348
20806
  Container2 as Container,
20349
20807
  ContainerNotAvailableError,
20808
+ Controller,
20350
20809
  ControllerMethodNotFoundError,
20351
20810
  ConvertEmptyStringsToNull,
20352
20811
  Cookie,
@@ -20368,7 +20827,10 @@ export {
20368
20827
  DatabaseJob,
20369
20828
  DatabaseLock,
20370
20829
  DatabaseManagerImpl,
20830
+ DatabaseNotification,
20371
20831
  DatabaseNotificationChannel,
20832
+ DatabaseNotificationCollection,
20833
+ DatabaseNotificationsRelation,
20372
20834
  DatabaseQueue,
20373
20835
  DatabaseServiceProvider,
20374
20836
  DatabaseSessionHandler,
@@ -20377,6 +20839,7 @@ export {
20377
20839
  DatabaseUnavailableError,
20378
20840
  DecryptError,
20379
20841
  DeferProp,
20842
+ DiagnosingHealth,
20380
20843
  Dispatchable,
20381
20844
  ELEMENT,
20382
20845
  EloquentUserProvider,
@@ -20412,13 +20875,14 @@ export {
20412
20875
  FormRequest,
20413
20876
  FormUploadedFile,
20414
20877
  Fragment,
20415
- Gate2 as Gate,
20878
+ Gate4 as Gate,
20416
20879
  GateResponse,
20417
20880
  GeneratorCommand,
20418
20881
  GenericLock,
20419
20882
  Grammar,
20420
20883
  GroupRegistrar,
20421
20884
  HasApiTokens,
20885
+ HasDatabaseNotifications,
20422
20886
  HasMany,
20423
20887
  HasManyThrough,
20424
20888
  HasOne,
@@ -20559,6 +21023,7 @@ export {
20559
21023
  OptionalProp,
20560
21024
  PERSISTENT_MIDDLEWARE,
20561
21025
  PERSONAL_ACCESS_TOKENS_MIGRATION,
21026
+ Pagination,
20562
21027
  Paginator,
20563
21028
  Password,
20564
21029
  PasswordBroker2 as PasswordBroker,
@@ -20613,6 +21078,7 @@ export {
20613
21078
  RouteModelNotFoundError,
20614
21079
  RouteModelResolverImpl,
20615
21080
  RouteNotDefinedError,
21081
+ RoutesNotifications,
20616
21082
  RoutingError,
20617
21083
  RoutingServiceProvider,
20618
21084
  Rule,
@@ -20710,6 +21176,7 @@ export {
20710
21176
  ViteError,
20711
21177
  ViteHtml,
20712
21178
  WORKER_DISCOVERY_DIRECTORIES,
21179
+ WithPagination,
20713
21180
  WithoutOverlapping,
20714
21181
  Worker,
20715
21182
  __,
@@ -20787,7 +21254,6 @@ export {
20787
21254
  extensionFromMime,
20788
21255
  facade,
20789
21256
  fake,
20790
- fetchNotifications,
20791
21257
  filterRouteList,
20792
21258
  formatAddress,
20793
21259
  formatDate,