@orieljs/framework 0.1.0-alpha.1 → 0.1.0-alpha.11

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.
Files changed (88) hide show
  1. package/NOTICE +7 -0
  2. package/README.md +10 -1
  3. package/TRADEMARKS.md +33 -0
  4. package/dist/{chunk-WI7E7Q46.js → chunk-24673JQF.js} +8 -4
  5. package/dist/chunk-24673JQF.js.map +1 -0
  6. package/dist/{chunk-K6MAA3RM.js → chunk-HTJKT2R2.js} +9 -1
  7. package/dist/chunk-HTJKT2R2.js.map +1 -0
  8. package/dist/chunk-KDE5BLI3.js +8776 -0
  9. package/dist/chunk-KDE5BLI3.js.map +1 -0
  10. package/dist/chunk-MURTCTRH.js +3253 -0
  11. package/dist/chunk-MURTCTRH.js.map +1 -0
  12. package/dist/contracts.d.ts +852 -168
  13. package/dist/contracts.js +9 -1
  14. package/dist/index.d-WQpfdIbG.d.ts +630 -0
  15. package/dist/index.d.ts +3015 -5160
  16. package/dist/index.js +7628 -2640
  17. package/dist/index.js.map +1 -1
  18. package/dist/{jsx-runtime-B8J6xq-7.d.ts → jsx-runtime-6um4Mwfb.d.ts} +99 -149
  19. package/dist/jsx-runtime.d.ts +3 -1
  20. package/dist/jsx-runtime.js +3 -3
  21. package/dist/testing-CKwfWJGn.d.ts +1586 -0
  22. package/dist/testing.d.ts +3 -1408
  23. package/dist/testing.js +29 -5
  24. package/docs/authentication.md +487 -0
  25. package/docs/authorization.md +435 -0
  26. package/docs/cache.md +647 -0
  27. package/docs/collections.md +2270 -0
  28. package/docs/configuration.md +334 -0
  29. package/docs/console.md +654 -0
  30. package/docs/container.md +430 -0
  31. package/docs/controllers.md +406 -0
  32. package/docs/csrf.md +126 -0
  33. package/docs/database-testing.md +144 -0
  34. package/docs/database.md +236 -0
  35. package/docs/deployment.md +371 -0
  36. package/docs/eloquent-collections.md +218 -0
  37. package/docs/eloquent-factories.md +255 -0
  38. package/docs/eloquent-mutators.md +254 -0
  39. package/docs/eloquent-observers.md +145 -0
  40. package/docs/eloquent-relationships.md +557 -0
  41. package/docs/eloquent.md +494 -0
  42. package/docs/encryption.md +104 -0
  43. package/docs/errors.md +318 -0
  44. package/docs/events.md +336 -0
  45. package/docs/export.md +93 -0
  46. package/docs/facades.md +278 -0
  47. package/docs/hashing.md +118 -0
  48. package/docs/helpers.md +1281 -0
  49. package/docs/http-tests.md +386 -0
  50. package/docs/inertia.md +485 -0
  51. package/docs/installation.md +219 -0
  52. package/docs/lifecycle.md +234 -0
  53. package/docs/live-tests.md +226 -0
  54. package/docs/live.md +910 -0
  55. package/docs/logging.md +255 -0
  56. package/docs/mail.md +619 -0
  57. package/docs/middleware.md +385 -0
  58. package/docs/migrations.md +416 -0
  59. package/docs/mocking.md +264 -0
  60. package/docs/navigation.json +277 -0
  61. package/docs/notifications.md +225 -0
  62. package/docs/pagination.md +247 -0
  63. package/docs/passwords.md +207 -0
  64. package/docs/providers.md +187 -0
  65. package/docs/queries.md +600 -0
  66. package/docs/queues.md +330 -0
  67. package/docs/requests.md +533 -0
  68. package/docs/responses.md +444 -0
  69. package/docs/routing.md +738 -0
  70. package/docs/scheduling.md +277 -0
  71. package/docs/seeding.md +122 -0
  72. package/docs/session.md +409 -0
  73. package/docs/starter-kits.md +399 -0
  74. package/docs/storage.md +192 -0
  75. package/docs/structure.md +264 -0
  76. package/docs/testing.md +165 -0
  77. package/docs/time-travel.md +138 -0
  78. package/docs/validation.md +1792 -0
  79. package/docs/verification.md +152 -0
  80. package/docs/views.md +566 -0
  81. package/docs/vite.md +400 -0
  82. package/package.json +37 -30
  83. package/dist/chunk-AI2RFMBT.js +0 -745
  84. package/dist/chunk-AI2RFMBT.js.map +0 -1
  85. package/dist/chunk-BZPCRKFQ.js +0 -2941
  86. package/dist/chunk-BZPCRKFQ.js.map +0 -1
  87. package/dist/chunk-K6MAA3RM.js.map +0 -1
  88. package/dist/chunk-WI7E7Q46.js.map +0 -1
@@ -35,148 +35,32 @@ interface Container {
35
35
  }
36
36
  declare const Container: Token<Container>;
37
37
 
38
- interface ServiceProvider {
39
- /** Bind things into the container. Synchronous. Don't resolve other services here. */
40
- register?(): void;
41
- /** Runs after every provider is registered. May be async (e.g. importing route files). */
42
- boot?(): void | Promise<void>;
43
- }
44
- type ServiceProviderClass = new (app: Application) => ServiceProvider;
45
- interface Application extends Container {
46
- readonly version: string;
47
- basePath(path?: string): string;
48
- appPath(path?: string): string;
49
- bootstrapPath(path?: string): string;
50
- configPath(path?: string): string;
51
- databasePath(path?: string): string;
52
- publicPath(path?: string): string;
53
- resourcePath(path?: string): string;
54
- storagePath(path?: string): string;
55
- /** With no args returns the environment name. With args returns whether it matches any of them. */
56
- environment(): string;
57
- environment(...environments: string[]): boolean;
58
- isProduction(): boolean;
59
- isLocal(): boolean;
60
- runningInConsole(): boolean;
61
- /** Mark the app as running in the console (the CLI entry point calls this). Defaults to true. */
62
- setRunningInConsole(value?: boolean): void;
63
- runningUnitTests(): boolean;
64
- /** Registers the provider. If the app is already booted, the provider is booted immediately. */
65
- register(provider: ServiceProvider | ServiceProviderClass): Promise<ServiceProvider>;
66
- getProviders(): ServiceProvider[];
67
- boot(): Promise<void>;
68
- isBooted(): boolean;
69
- booting(callback: (app: Application) => void | Promise<void>): void;
70
- booted(callback: (app: Application) => void | Promise<void>): void;
71
- /** Handle one HTTP request in a fresh request scope via the bound HttpKernel. */
72
- handle(request: Request): Promise<Response>;
73
- /** Register a callback that terminate() runs, in registration order. */
74
- terminating(callback: () => void | Promise<void>): void;
75
- terminate(): Promise<void>;
76
- }
77
- declare const Application: Token<Application>;
78
- interface ExceptionHandler {
79
- report(error: unknown): Promise<void>;
80
- shouldReport(error: unknown): boolean;
81
- /** `request` is the scoped HttpRequest (Contracts/Http) when available, else the raw Request. */
82
- render(request: unknown, error: unknown): Promise<Response>;
83
- }
84
- declare const ExceptionHandler: Token<ExceptionHandler>;
85
- /** Paths passed to Application.configure().withRouting(). Routing (Wave 1) loads them. */
86
- interface RoutingPaths {
87
- web?: string;
88
- api?: string;
89
- console?: string;
90
- health?: string;
91
- apiPrefix: string;
92
- }
93
- declare const RoutingPaths: Token<RoutingPaths>;
94
- /** The object passed to Application.configure().withExceptions(e => …), like Laravel's Exceptions class. */
95
- interface ExceptionsConfigurator {
96
- /** Custom reporting. Return false to stop the default logging. */
97
- report(callback: (error: unknown) => void | boolean | Promise<void | boolean>): this;
98
- /** Custom rendering. Return undefined to fall through to the default rendering. */
99
- render(callback: (error: unknown, request: unknown) => Response | undefined | Promise<Response | undefined>): this;
100
- /** Never report errors of these classes. */
101
- dontReport(...classes: Array<abstract new (...args: never[]) => Error>): this;
102
- }
103
- /** Callbacks collected by withMiddleware()/withExceptions(); invoked by Http / the exception handler (Wave 1). */
104
- type ConfigCallbacks<T> = Array<(configurator: T) => void>;
105
- /** Typed as unknown here because MiddlewareConfigurator lives in Contracts/Http; Http casts on use. */
106
- declare const MiddlewareCallbacks: Token<ConfigCallbacks<unknown>>;
107
- declare const ExceptionCallbacks: Token<ConfigCallbacks<ExceptionsConfigurator>>;
108
-
109
- interface ConfigRepository {
110
- has(key: string): boolean;
111
- /** Dot notation: get('database.connections.sqlite.database'). */
112
- get<T = unknown>(key: string, defaultValue?: T): T;
113
- set(key: string, value: unknown): void;
114
- set(values: Record<string, unknown>): void;
115
- push(key: string, value: unknown): void;
116
- all(): Record<string, unknown>;
117
- }
118
- declare const ConfigRepository: Token<ConfigRepository>;
119
-
120
- interface Arrayable<T = unknown> {
121
- toArray(): T;
122
- }
123
- interface Jsonable {
124
- toJson(): string;
125
- }
126
- interface Htmlable {
127
- toHtml(): string;
128
- }
129
- /** Anything a controller can return that knows how to become a Response. */
130
- interface Responsable {
131
- toResponse(request: unknown): Response | Promise<Response>;
132
- }
133
- /** The minimal collection surface contracts rely on (implemented by @orieljs/collections). */
134
- interface Enumerable<T> extends Iterable<T>, Arrayable<unknown[]> {
135
- all(): T[];
136
- count(): number;
137
- isEmpty(): boolean;
138
- }
139
- interface ClassRegistry {
140
- /** Registers under `name` (default: cls.name). Throws if the name is already taken by a different class. */
141
- register(cls: Class<unknown>, name?: string): string;
142
- nameOf(cls: Class<unknown>): string | undefined;
143
- resolve<T = unknown>(name: string): Class<T>;
144
- has(name: string): boolean;
145
- }
146
- declare const ClassRegistry: Token<ClassRegistry>;
147
-
148
- type PipeNext<T> = (passable: T) => Promise<unknown>;
149
- type PipeClosure<T> = (passable: T, next: PipeNext<T>) => Promise<unknown> | unknown;
150
- /** A class resolved from the container whose `via` method (default 'handle') is called; or a string alias 'name:param1,param2'. */
151
- type Pipe<T> = PipeClosure<T> | Class<object> | string;
152
- interface Pipeline<T = unknown> {
153
- send(passable: T): this;
154
- through(pipes: ReadonlyArray<Pipe<T>>): this;
155
- pipe(...pipes: Array<Pipe<T>>): this;
156
- /** Method called on class pipes. Default 'handle'. */
157
- via(method: string): this;
158
- then<R>(destination: (passable: T) => R | Promise<R>): Promise<R>;
159
- thenReturn(): Promise<T>;
160
- }
161
- interface PipelineFactory {
162
- make<T>(): Pipeline<T>;
163
- }
164
- declare const PipelineFactory: Token<PipelineFactory>;
165
-
166
38
  /** The session of the current request (scoped). Loaded and saved by the StartSession middleware. */
167
39
  interface Session {
168
40
  getId(): string;
169
41
  start(): Promise<void>;
170
42
  save(): Promise<void>;
171
43
  all(): Record<string, unknown>;
44
+ only(keys: string[]): Record<string, unknown>;
45
+ except(keys: string[]): Record<string, unknown>;
46
+ /** Whether every key is present, even with a null value. */
47
+ exists(...keys: string[]): boolean;
48
+ missing(...keys: string[]): boolean;
49
+ /** Whether the key is present and not null. */
172
50
  has(key: string): boolean;
173
51
  get<T = unknown>(key: string, defaultValue?: T): T;
174
52
  put(key: string | Record<string, unknown>, value?: unknown): void;
175
53
  push(key: string, value: unknown): void;
54
+ /** Adds `amount` (default 1) to the number under the key and returns the new value. */
55
+ increment(key: string, amount?: number): number;
56
+ decrement(key: string, amount?: number): number;
176
57
  pull<T = unknown>(key: string, defaultValue?: T): T;
58
+ /** Forgets the key and returns its value. */
59
+ remove<T = unknown>(key: string): T;
177
60
  forget(...keys: string[]): void;
178
61
  flush(): void;
179
- flash(key: string, value: unknown): void;
62
+ /** Puts the value (true when omitted) for the next request only. */
63
+ flash(key: string, value?: unknown): void;
180
64
  now(key: string, value: unknown): void;
181
65
  reflash(): void;
182
66
  keep(...keys: string[]): void;
@@ -198,6 +82,370 @@ interface SessionHandler {
198
82
  gc(maxLifetimeSeconds: number): Promise<void>;
199
83
  }
200
84
 
85
+ /**
86
+ * What one rule tells the validated data's type about a value that passed it. Every member is optional:
87
+ * - `value`: the type of a passing value. A field's type is the intersection of its rules' values
88
+ * (`'string|in:a,b'` is `'a' | 'b'`); a field whose rules set none is `unknown`.
89
+ * - `presence`: `'required'` puts the key in the data and rules out null (`required`, `accepted`); `'present'` puts
90
+ * the key in the data; `'filled'` rules out null without putting the key in; `'excluded'` leaves the key out;
91
+ * `'optional'` may leave the key out whatever else would put it in (`sometimes` skips a missing key, and a rule that
92
+ * excludes the field under a condition drops it with its children), so the key is optional and doesn't put its
93
+ * parent in. A key nothing puts in is optional, as the validated data has only the keys the input had.
94
+ * - `each`: on a field that also has `array`, the type of each item instead of `value` (`in` checks every item of an
95
+ * array: `'array|in:a,b'` is `Array<'a' | 'b'>`).
96
+ * - `nullable`: null passes, unless a `'required'` or `'filled'` rule says otherwise.
97
+ */
98
+ interface RuleTyping {
99
+ value?: unknown;
100
+ each?: unknown;
101
+ presence?: 'required' | 'present' | 'filled' | 'excluded' | 'optional';
102
+ nullable?: true;
103
+ }
104
+ /** A number, or the text of one: a form sends every field as text, and `integer` and `numeric` accept both. */
105
+ type NumericValue = number | `${number}`;
106
+ /** `a,b,c` → `'a' | 'b' | 'c'`: a rule's comma-separated parameters, as Validator splits them. */
107
+ type RuleParameterList<P extends string> = P extends `${infer Head},${infer Tail}` ? Head | RuleParameterList<Tail> : P;
108
+ /**
109
+ * What `in` (and `Rule.in()`) lets through: it compares the value's text with each listed value, so `'1'` lets the
110
+ * number 1 through too, and `'true'` the boolean. A list known only as `string` (`` `in:${list.join(',')}` ``) says
111
+ * nothing, as any value whose text is listed passes.
112
+ */
113
+ type InValue<V> = string extends V ? unknown : V extends string ? V | (V extends `${infer N extends number}` ? N : never) | (V extends 'true' ? true : V extends 'false' ? false : never) : V extends number | boolean ? V | `${V}` : V;
114
+ /**
115
+ * The string rules that tell the validated data's type something, by name, each a RuleTyping. `Parameters` is the
116
+ * rule's text after the colon (`'a,b'` for `in:a,b`). A rule that only checks a value it doesn't change the type of
117
+ * (`max`, `confirmed`, `unique`) has no entry. Add a member for a new type-setting rule; an app adds its own
118
+ * `Validator.extend()` rules by declaration merging, with the same type parameter.
119
+ */
120
+ interface ValidationRuleTypes<Parameters extends string = string> {
121
+ required: {
122
+ presence: 'required';
123
+ };
124
+ /** Skips the field when the key is missing, so the key may be left out even with `required`. */
125
+ sometimes: {
126
+ presence: 'optional';
127
+ };
128
+ nullable: {
129
+ nullable: true;
130
+ };
131
+ accepted: {
132
+ presence: 'required';
133
+ value: true | 1 | 'yes' | 'on' | '1' | 'true';
134
+ };
135
+ declined: {
136
+ presence: 'required';
137
+ value: false | 0 | 'no' | 'off' | '0' | 'false';
138
+ };
139
+ present: {
140
+ presence: 'present';
141
+ };
142
+ filled: {
143
+ presence: 'filled';
144
+ };
145
+ missing: {
146
+ presence: 'excluded';
147
+ };
148
+ exclude: {
149
+ presence: 'excluded';
150
+ };
151
+ /** Drop the field, children and all, under a condition, so the key may be left out even with `required`. */
152
+ exclude_if: {
153
+ presence: 'optional';
154
+ };
155
+ exclude_unless: {
156
+ presence: 'optional';
157
+ };
158
+ exclude_with: {
159
+ presence: 'optional';
160
+ };
161
+ exclude_without: {
162
+ presence: 'optional';
163
+ };
164
+ /**
165
+ * Passes only when the field is missing or empty, so a value that is there is null, blank or whitespace-only text,
166
+ * [] or {}.
167
+ */
168
+ prohibited: {
169
+ value: null | string | [] | Record<string, never>;
170
+ };
171
+ string: {
172
+ value: string;
173
+ };
174
+ /** `integer:strict` and `numeric:strict` refuse the text of a number. */
175
+ integer: {
176
+ value: Parameters extends 'strict' ? number : NumericValue;
177
+ };
178
+ numeric: {
179
+ value: Parameters extends 'strict' ? number : NumericValue;
180
+ };
181
+ /** `boolean:strict` lets only true and false through. */
182
+ boolean: {
183
+ value: Parameters extends 'strict' ? boolean : boolean | 0 | 1 | '0' | '1';
184
+ };
185
+ /** `array` is a list; `array:a,b` an object whose keys are among those named. */
186
+ array: {
187
+ value: Parameters extends '' ? unknown[] : {
188
+ [K in RuleParameterList<Parameters>]?: unknown;
189
+ };
190
+ };
191
+ list: {
192
+ value: unknown[];
193
+ };
194
+ contains: {
195
+ value: unknown[];
196
+ };
197
+ doesnt_contain: {
198
+ value: unknown[];
199
+ };
200
+ required_array_keys: {
201
+ value: {
202
+ [K in RuleParameterList<Parameters>]: unknown;
203
+ };
204
+ };
205
+ in_array_keys: {
206
+ value: Record<string, unknown>;
207
+ };
208
+ email: {
209
+ value: string;
210
+ };
211
+ url: {
212
+ value: string;
213
+ };
214
+ uuid: {
215
+ value: string;
216
+ };
217
+ alpha: {
218
+ value: string;
219
+ };
220
+ alpha_num: {
221
+ value: string;
222
+ };
223
+ alpha_dash: {
224
+ value: string;
225
+ };
226
+ regex: {
227
+ value: string;
228
+ };
229
+ lowercase: {
230
+ value: string | number;
231
+ };
232
+ uppercase: {
233
+ value: string | number;
234
+ };
235
+ ascii: {
236
+ value: string | number;
237
+ };
238
+ hex_color: {
239
+ value: string;
240
+ };
241
+ json: {
242
+ value: string;
243
+ };
244
+ ip: {
245
+ value: string;
246
+ };
247
+ ipv4: {
248
+ value: string;
249
+ };
250
+ ipv6: {
251
+ value: string;
252
+ };
253
+ mac_address: {
254
+ value: string;
255
+ };
256
+ ulid: {
257
+ value: string;
258
+ };
259
+ timezone: {
260
+ value: string;
261
+ };
262
+ active_url: {
263
+ value: string;
264
+ };
265
+ digits: {
266
+ value: NumericValue;
267
+ };
268
+ digits_between: {
269
+ value: NumericValue;
270
+ };
271
+ max_digits: {
272
+ value: NumericValue;
273
+ };
274
+ min_digits: {
275
+ value: NumericValue;
276
+ };
277
+ decimal: {
278
+ value: NumericValue;
279
+ };
280
+ multiple_of: {
281
+ value: NumericValue;
282
+ };
283
+ date: {
284
+ value: string;
285
+ };
286
+ /** A number passes a format made of digits (`Y`, `U`), as in Laravel. */
287
+ date_format: {
288
+ value: string | number;
289
+ };
290
+ /** A number passes the comparisons as a timestamp, as in Laravel; with `date` in the set, the value is text. */
291
+ before: {
292
+ value: string | number;
293
+ };
294
+ before_or_equal: {
295
+ value: string | number;
296
+ };
297
+ after: {
298
+ value: string | number;
299
+ };
300
+ after_or_equal: {
301
+ value: string | number;
302
+ };
303
+ date_equals: {
304
+ value: string | number;
305
+ };
306
+ current_password: {
307
+ value: string;
308
+ };
309
+ in: {
310
+ value: InValue<RuleParameterList<Parameters>>;
311
+ each: InValue<RuleParameterList<Parameters>>;
312
+ };
313
+ file: {
314
+ value: UploadedFile;
315
+ };
316
+ image: {
317
+ value: UploadedFile;
318
+ };
319
+ mimes: {
320
+ value: UploadedFile;
321
+ };
322
+ mimetypes: {
323
+ value: UploadedFile;
324
+ };
325
+ extensions: {
326
+ value: UploadedFile;
327
+ };
328
+ dimensions: {
329
+ value: UploadedFile;
330
+ };
331
+ }
332
+ /**
333
+ * A rule object that tells the validated data's type what it lets through, as a string rule's entry in
334
+ * ValidationRuleTypes does. `__typing` is never set or read at run time: declare it (`declare readonly __typing?:
335
+ * { value: string }`). A rule object without it changes nothing, so its field takes the type of the string rules
336
+ * beside it (`['required', 'string', new Uppercase()]` is a string).
337
+ */
338
+ interface TypedValidationRule<T extends RuleTyping = RuleTyping> extends ValidationRule {
339
+ readonly __typing?: T;
340
+ }
341
+ type RuleName<R extends string> = R extends `${infer Name}:${string}` ? Name : R;
342
+ type RuleParameters<R extends string> = R extends `${string}:${infer Parameters}` ? Parameters : '';
343
+ type PipeRules<S extends string> = S extends `${infer Head}|${infer Tail}` ? Head | PipeRules<Tail> : S;
344
+ /** What a rule without an entry, or a rule object without `__typing`, says: nothing. */
345
+ type NoTyping = Record<never, never>;
346
+ type StringRuleTyping<R extends string> = R extends unknown ? RuleName<R> extends keyof ValidationRuleTypes ? ValidationRuleTypes<RuleParameters<R>>[RuleName<R>] : NoTyping : never;
347
+ type ObjectRuleTyping<O> = '__typing' extends keyof O ? Exclude<O['__typing' & keyof O], undefined> : NoTyping;
348
+ type ItemTyping<I> = I extends string ? StringRuleTyping<I> : ObjectRuleTyping<I>;
349
+ /** The typings of one field's rules, as a union: `'required|string'` or `['required', 'string', rule]`. */
350
+ type SpecTypings<Spec> = Spec extends string ? StringRuleTyping<PipeRules<Spec>> : Spec extends ReadonlyArray<infer Item> ? ItemTyping<Item> : NoTyping;
351
+ /** A rule string the compiler only knows as `string` (rules written without `as const`) says nothing. */
352
+ type IsWide<Spec> = Spec extends string ? (string extends Spec ? true : false) : Spec extends ReadonlyArray<infer Item> ? (string extends Extract<Item, string> ? true : false) : false;
353
+ type Intersect<U> = (U extends unknown ? (value: U) => void : never) extends (value: infer I) => void ? I : never;
354
+ type Boxed<T> = T extends {
355
+ value: infer V;
356
+ } ? {
357
+ v: V;
358
+ } : never;
359
+ type BoxedEach<T> = T extends {
360
+ each: infer E;
361
+ } ? {
362
+ v: E;
363
+ } : never;
364
+ type Unbox<B> = [B] extends [never] ? unknown : Intersect<B> extends {
365
+ v: infer V;
366
+ } ? V : never;
367
+ type WithoutEach<T> = T extends {
368
+ each: unknown;
369
+ } ? never : T;
370
+ /** The intersection of the rules' values; on an array, the rules with `each` type its items instead. */
371
+ type ValueOf<T> = [BoxedEach<T>] extends [never] ? Unbox<Boxed<T>> : Unbox<Boxed<WithoutEach<T>>> extends readonly unknown[] ? Array<Unbox<BoxedEach<T>>> : Unbox<Boxed<T>>;
372
+ type PresenceOf<T> = T extends {
373
+ presence: infer P;
374
+ } ? P : never;
375
+ type NullableOf<T> = T extends {
376
+ nullable: true;
377
+ } ? true : never;
378
+ interface FieldInfo {
379
+ value: unknown;
380
+ required: boolean;
381
+ optional: boolean;
382
+ nullable: boolean;
383
+ excluded: boolean;
384
+ }
385
+ type FieldFrom<T, Optional = [Extract<PresenceOf<T>, 'optional'>] extends [never] ? false : true> = {
386
+ value: ValueOf<T>;
387
+ required: Optional extends true ? false : [Extract<PresenceOf<T>, 'required' | 'present'>] extends [never] ? false : true;
388
+ optional: Optional;
389
+ nullable: [NullableOf<T>] extends [never] ? false : [Extract<PresenceOf<T>, 'required' | 'filled'>] extends [never] ? true : false;
390
+ excluded: [Extract<PresenceOf<T>, 'excluded'>] extends [never] ? false : true;
391
+ };
392
+ /** Rules the compiler only knows as `string` say nothing, not even that the key is there. */
393
+ type FieldOf<Spec> = IsWide<Spec> extends true ? NoRules : FieldFrom<SpecTypings<Spec>>;
394
+ type NoRules = {
395
+ value: unknown;
396
+ required: false;
397
+ optional: false;
398
+ nullable: false;
399
+ excluded: false;
400
+ };
401
+ type Keys<R> = Extract<keyof R, string>;
402
+ type Head<K extends string> = K extends `${infer H}.${string}` ? H : K;
403
+ type Heads<R> = Head<Keys<R>>;
404
+ type Children<R, H extends string> = {
405
+ [K in Keys<R> as K extends `${H}.${infer Rest}` ? Rest : never]: R[K];
406
+ };
407
+ type HasChildren<R, H extends string> = [Keys<Children<R, H>>] extends [never] ? false : true;
408
+ type Own<R, H extends string> = H extends keyof R ? FieldOf<R[H]> : NoRules;
409
+ type OrNull<T, Nullable> = Nullable extends true ? T | null : T;
410
+ /**
411
+ * A wildcard's rules (`items.*.name`) make an array of what they describe; dotted keys (`author.name`) an object.
412
+ * Without a rule that makes the parent a list (`array`, `list`), validated() may give an object instead: an object
413
+ * sent under `items.*` stays one, and a sparse match (`{ items: [{}, { qty: 1 }] }`) keeps its index keys.
414
+ */
415
+ type Structure<C, Parent> = '*' extends Heads<C> ? Items<ValueAt<C, '*'>, Parent> : Shape<C>;
416
+ type Items<V, Parent> = [Parent] extends [readonly unknown[]] ? V[] : V[] | Record<string, V>;
417
+ type ValueAt<R, H extends string, F extends FieldInfo = Own<R, H>> = OrNull<HasChildren<R, H> extends true ? Structure<Children<R, H>, F['value']> : F['value'], F['nullable']>;
418
+ /**
419
+ * A key is in the data when a rule puts it there, or when a child key without a wildcard is required, unless a rule
420
+ * may leave it out.
421
+ */
422
+ type IsRequired<R, H extends string> = Own<R, H>['optional'] extends true ? false : Own<R, H>['required'] extends true ? true : HasChildren<R, H> extends true ? '*' extends Heads<Children<R, H>> ? false : [RequiredHeads<Children<R, H>>] extends [never] ? false : true : false;
423
+ type RequiredHeads<R> = {
424
+ [H in Heads<R>]: Own<R, H>['excluded'] extends true ? never : IsRequired<R, H> extends true ? H : never;
425
+ }[Heads<R>];
426
+ type Simplify<T> = {
427
+ [K in keyof T]: T[K];
428
+ } & {};
429
+ type Shape<R> = string extends Keys<R> ? Record<string, unknown> : Simplify<{
430
+ [H in Heads<R> as Own<R, H>['excluded'] extends true ? never : IsRequired<R, H> extends true ? H : never]: ValueAt<R, H>;
431
+ } & {
432
+ [H in Heads<R> as Own<R, H>['excluded'] extends true ? never : IsRequired<R, H> extends true ? never : H]?: ValueAt<R, H>;
433
+ }>;
434
+ /**
435
+ * The type of one field's passing value, from its rule string: `'nullable|integer'` → `number | \`${number}\` | null`.
436
+ * A rule string the compiler only knows as `string` gives unknown.
437
+ */
438
+ type InferRuleType<S extends string> = string extends S ? unknown : OrNull<FieldOf<S>['value'], FieldOf<S>['nullable']>;
439
+ /**
440
+ * The validated data a Rules object gives: nested as Validator's validated() nests it (`author.name` → `{ author: {
441
+ * name } }`, `tags.*` → an array, or an object too unless `tags` has `array` or `list`), each key optional unless a
442
+ * rule puts it in, each value typed by its rules. Rules known only as `Rules` (or any `Record<string, …>`) give
443
+ * `Record<string, unknown>`, and rule strings known only as `string` give optional keys of unknown. Write a
444
+ * FormRequest's `rules()` with `as const` so its rule strings keep their text; `request().validate({ … })` needs
445
+ * nothing.
446
+ */
447
+ type InferValidatedType<R> = R extends unknown ? Shape<R> : never;
448
+
201
449
  /** A rule object (Laravel's ValidationRule). Call fail() to reject the value. */
202
450
  interface ValidationRule {
203
451
  validate(attribute: string, value: unknown, fail: (message: string) => void, data: Record<string, unknown>): void | Promise<void>;
@@ -205,6 +453,7 @@ interface ValidationRule {
205
453
  /** 'required|string|max:255', or an array mixing strings and rule objects. Keys support dot + `*` wildcards. */
206
454
  type Rules = Record<string, string | ReadonlyArray<string | ValidationRule>>;
207
455
  interface MessageBag {
456
+ add(key: string, message: string): void;
208
457
  has(key: string): boolean;
209
458
  first(key?: string): string | undefined;
210
459
  get(key: string): string[];
@@ -213,18 +462,21 @@ interface MessageBag {
213
462
  count(): number;
214
463
  toObject(): Record<string, string[]>;
215
464
  }
216
- interface Validator {
465
+ /** `R` is the rules' type: `validated()` is typed from them, as `request().validate()` is. */
466
+ interface Validator<R extends Rules = Rules> {
217
467
  passes(): Promise<boolean>;
218
468
  fails(): Promise<boolean>;
219
469
  /** Only the keys that have rules. Throws ValidationError (Exceptions.ts) on failure. */
220
- validated<T = Record<string, unknown>>(): Promise<T>;
470
+ validated<T = InferValidatedType<R>>(): Promise<T>;
221
471
  /** Valid only after passes()/fails()/validated() has run. */
222
472
  errors(): MessageBag;
223
473
  after(callback: (validator: Validator) => void | Promise<void>): this;
474
+ /** Adds a failure message for `field` (from an after() hook). */
475
+ fail(field: string, message: string): void;
224
476
  }
225
477
  type RuleCallback = (attribute: string, value: unknown, parameters: string[], data: Record<string, unknown>) => boolean | Promise<boolean>;
226
478
  interface ValidationFactory {
227
- make(data: Record<string, unknown>, rules: Rules, messages?: Record<string, string>, attributes?: Record<string, string>): Validator;
479
+ make<const R extends Rules>(data: Record<string, unknown>, rules: R, messages?: Record<string, string>, attributes?: Record<string, string>): Validator<R>;
228
480
  /** Registers a string rule, e.g. extend('uppercase', fn, ':attribute must be uppercase'). */
229
481
  extend(name: string, callback: RuleCallback, message?: string): void;
230
482
  }
@@ -238,7 +490,13 @@ interface UploadedFile {
238
490
  readonly mimeType: string;
239
491
  readonly size: number;
240
492
  extension(): string;
493
+ /** The extension of the name the browser gave the file, lower-cased ('' without one). */
494
+ clientExtension(): string;
495
+ /** A random 40-character name with extension(): the name store() gives the file. */
496
+ hashName(): string;
241
497
  arrayBuffer(): Promise<ArrayBuffer>;
498
+ text(): Promise<string>;
499
+ stream(): ReadableStream<Uint8Array>;
242
500
  /** Stores on a Filesystem disk. Returns the stored path. */
243
501
  store(directory: string, disk?: string): Promise<string>;
244
502
  storeAs(directory: string, name: string, disk?: string): Promise<string>;
@@ -261,6 +519,8 @@ interface HttpRequest {
261
519
  header(name: string, defaultValue: string): string;
262
520
  bearerToken(): string | undefined;
263
521
  ip(): string | undefined;
522
+ /** The raw body as text (Laravel's getContent()); '' when there is none. */
523
+ content(): string;
264
524
  expectsJson(): boolean;
265
525
  ajax(): boolean;
266
526
  query<T = unknown>(key?: string, defaultValue?: T): T;
@@ -280,11 +540,18 @@ interface HttpRequest {
280
540
  /** Route parameter (after model binding), or every parameter when called with no key. */
281
541
  route<T = unknown>(key?: string): T;
282
542
  session(): Session;
283
- /** The user resolved earlier by auth middleware. Undefined for guests. Use `await Auth.user()` to resolve lazily. */
284
- user<T = unknown>(guard?: string): T | undefined;
543
+ /**
544
+ * The signed-in user, found through the request's guard (the default one, or the one named) the first time it is
545
+ * asked for, then the same instance for the rest of the request. Undefined for a guest.
546
+ */
547
+ user<T = unknown>(guard?: string): Promise<T | undefined>;
548
+ /** How user() finds the user (Auth sets it). The resolver may return a promise. */
285
549
  setUserResolver(resolver: (guard?: string) => unknown): void;
286
- /** Validates this request's input via the ValidationFactory; throws a Validation OrielError (422) on failure. */
287
- validate<T = Record<string, unknown>>(rules: Rules, messages?: Record<string, string>, attributes?: Record<string, string>): Promise<T>;
550
+ /**
551
+ * Validates this request's input via the ValidationFactory; throws a Validation OrielError (422) on failure. The
552
+ * validated data is typed from the rules: `validate({ title: 'required|string' })` is `{ title: string }`.
553
+ */
554
+ validate<const R extends Rules>(rules: R, messages?: Record<string, string>, attributes?: Record<string, string>): Promise<InferValidatedType<R>>;
288
555
  }
289
556
  declare const HttpRequest: Token<HttpRequest>;
290
557
  type Next = (request: HttpRequest) => Promise<Response>;
@@ -313,6 +580,8 @@ interface MiddlewareConfigurator {
313
580
  except: string[];
314
581
  }): this;
315
582
  redirectGuestsTo(url: string | ((request: HttpRequest) => string)): this;
583
+ /** Where the `guest` middleware sends a signed-in user. */
584
+ redirectUsersTo(url: string | ((request: HttpRequest) => string)): this;
316
585
  }
317
586
  interface HttpKernel {
318
587
  handle(request: Request): Promise<Response>;
@@ -323,25 +592,182 @@ interface ResponseFactory {
323
592
  make(content?: BodyInit | null, status?: number, headers?: HeadersInit): Response;
324
593
  json(data: unknown, status?: number, headers?: HeadersInit): Response;
325
594
  noContent(status?: number): Response;
595
+ /** Renders the view into an HTML response. */
596
+ view(name: string, data?: Record<string, unknown>, status?: number, headers?: HeadersInit): Promise<Response>;
326
597
  download(path: string, name?: string, headers?: HeadersInit): Promise<Response>;
598
+ /** Sends the file inline, for the browser to show (download() sends it as an attachment). */
599
+ file(path: string, headers?: HeadersInit): Promise<Response>;
327
600
  stream(body: ReadableStream, status?: number, headers?: HeadersInit): Response;
328
601
  }
329
602
  declare const ResponseFactory: Token<ResponseFactory>;
330
603
 
604
+ interface ServiceProvider {
605
+ /** Bind things into the container. Synchronous. Don't resolve other services here. */
606
+ register?(): void;
607
+ /** Runs after every provider is registered. May be async (e.g. importing route files). */
608
+ boot?(): void | Promise<void>;
609
+ }
610
+ type ServiceProviderClass = new (app: Application) => ServiceProvider;
611
+ interface Application extends Container {
612
+ readonly version: string;
613
+ basePath(path?: string): string;
614
+ appPath(path?: string): string;
615
+ bootstrapPath(path?: string): string;
616
+ configPath(path?: string): string;
617
+ databasePath(path?: string): string;
618
+ publicPath(path?: string): string;
619
+ resourcePath(path?: string): string;
620
+ storagePath(path?: string): string;
621
+ /** With no args returns the environment name. With args returns whether it matches any of them. */
622
+ environment(): string;
623
+ environment(...environments: string[]): boolean;
624
+ isProduction(): boolean;
625
+ isLocal(): boolean;
626
+ runningInConsole(): boolean;
627
+ /** Mark the app as running in the console (the CLI entry point calls this). Defaults to true. */
628
+ setRunningInConsole(value?: boolean): void;
629
+ runningUnitTests(): boolean;
630
+ /** Registers the provider. If the app is already booted, the provider is booted immediately. */
631
+ register(provider: ServiceProvider | ServiceProviderClass): Promise<ServiceProvider>;
632
+ getProviders(): ServiceProvider[];
633
+ boot(): Promise<void>;
634
+ isBooted(): boolean;
635
+ booting(callback: (app: Application) => void | Promise<void>): void;
636
+ booted(callback: (app: Application) => void | Promise<void>): void;
637
+ /** Handle one HTTP request in a fresh request scope via the bound HttpKernel. */
638
+ handle(request: Request): Promise<Response>;
639
+ /** Register a callback that terminate() runs, in registration order. */
640
+ terminating(callback: () => void | Promise<void>): void;
641
+ terminate(): Promise<void>;
642
+ /**
643
+ * Register a callback that shutdown() runs once, before the process exits: close pools and clients, write out
644
+ * files. terminating() callbacks run after every request; these run once, at the end.
645
+ */
646
+ onShutdown(callback: () => void | Promise<void>): void;
647
+ /** Runs the shutdown callbacks once, newest first; a failing one is printed and the rest still run. Never rejects. */
648
+ shutdown(): Promise<void>;
649
+ }
650
+ declare const Application: Token<Application>;
651
+ interface ExceptionHandler {
652
+ report(error: unknown): Promise<void>;
653
+ shouldReport(error: unknown): boolean;
654
+ /** `request` is the scoped HttpRequest (Contracts/Http) when available, else the raw Request. */
655
+ render(request: unknown, error: unknown): Promise<Response>;
656
+ }
657
+ declare const ExceptionHandler: Token<ExceptionHandler>;
658
+ /** Paths passed to Application.configure().withRouting(). Routing (Wave 1) loads them. */
659
+ interface RoutingPaths {
660
+ /** One route file or several, loaded in order (Laravel's `withRouting(web: [...])`). */
661
+ web?: string | string[];
662
+ api?: string | string[];
663
+ console?: string;
664
+ health?: string;
665
+ apiPrefix: string;
666
+ }
667
+ declare const RoutingPaths: Token<RoutingPaths>;
668
+ /** The object passed to Application.configure().withExceptions(e => …), like Laravel's Exceptions class. */
669
+ interface ExceptionsConfigurator {
670
+ /** Custom reporting. Return false to stop the default logging. */
671
+ report(callback: (error: unknown) => void | boolean | Promise<void | boolean>): this;
672
+ /** Custom rendering. Return undefined to fall through to the default rendering. */
673
+ render(callback: (error: unknown, request: unknown) => Response | undefined | Promise<Response | undefined>): this;
674
+ /** Never report errors of these classes. */
675
+ dontReport(...classes: Array<abstract new (...args: never[]) => Error>): this;
676
+ /** Render errors as JSON when the callback returns true, whatever the Accept header. */
677
+ shouldRenderJsonWhen(callback: (request: HttpRequest, error: unknown) => boolean): this;
678
+ }
679
+ /** Callbacks collected by withMiddleware()/withExceptions(); invoked by Http / the exception handler (Wave 1). */
680
+ type ConfigCallbacks<T> = Array<(configurator: T) => void>;
681
+ /** Typed as unknown here because MiddlewareConfigurator lives in Contracts/Http; Http casts on use. */
682
+ declare const MiddlewareCallbacks: Token<ConfigCallbacks<unknown>>;
683
+ declare const ExceptionCallbacks: Token<ConfigCallbacks<ExceptionsConfigurator>>;
684
+ /**
685
+ * The class names of a scrambled production build (`bootstrap/cache/classes.json`, written by `@orieljs/vite`'s
686
+ * `obfuscate` option): `html()` renames the classes in HTML as the build renamed them in its CSS, and returns the
687
+ * HTML as it was when there is no such build, while the Vite dev server runs, or while the app runs its tests.
688
+ */
689
+ interface ClassNames {
690
+ /** Whether there's a map to apply now: a scrambled build, and no dev server. */
691
+ readonly active: boolean;
692
+ html(html: string): string;
693
+ }
694
+ declare const ClassNames: Token<ClassNames>;
695
+
696
+ interface ConfigRepository {
697
+ has(key: string): boolean;
698
+ /** Dot notation: get('database.connections.sqlite.database'). */
699
+ get<T = unknown>(key: string, defaultValue?: T): T;
700
+ set(key: string, value: unknown): void;
701
+ set(values: Record<string, unknown>): void;
702
+ push(key: string, value: unknown): void;
703
+ all(): Record<string, unknown>;
704
+ }
705
+ declare const ConfigRepository: Token<ConfigRepository>;
706
+
707
+ interface Arrayable<T = unknown> {
708
+ toArray(): T;
709
+ }
710
+ interface Jsonable {
711
+ toJson(): string;
712
+ }
713
+ interface Htmlable {
714
+ toHtml(): string;
715
+ }
716
+ /** Anything a controller can return that knows how to become a Response. */
717
+ interface Responsable {
718
+ toResponse(request: unknown): Response | Promise<Response>;
719
+ }
720
+ /** The minimal collection surface contracts rely on (implemented by @orieljs/collections). */
721
+ interface Enumerable<T> extends Iterable<T>, Arrayable<unknown[]> {
722
+ all(): T[];
723
+ count(): number;
724
+ isEmpty(): boolean;
725
+ }
726
+ interface ClassRegistry {
727
+ /** Registers under `name` (default: cls.name). Throws if the name is already taken by a different class. */
728
+ register(cls: Class<unknown>, name?: string): string;
729
+ nameOf(cls: Class<unknown>): string | undefined;
730
+ resolve<T = unknown>(name: string): Class<T>;
731
+ has(name: string): boolean;
732
+ }
733
+ declare const ClassRegistry: Token<ClassRegistry>;
734
+
735
+ type PipeNext<T> = (passable: T) => Promise<unknown>;
736
+ type PipeClosure<T> = (passable: T, next: PipeNext<T>) => Promise<unknown> | unknown;
737
+ /** A class resolved from the container whose `via` method (default 'handle') is called; or a string alias 'name:param1,param2'. */
738
+ type Pipe<T> = PipeClosure<T> | Class<object> | string;
739
+ interface Pipeline<T = unknown> {
740
+ send(passable: T): this;
741
+ through(pipes: ReadonlyArray<Pipe<T>>): this;
742
+ pipe(...pipes: Array<Pipe<T>>): this;
743
+ /** Method called on class pipes. Default 'handle'. */
744
+ via(method: string): this;
745
+ then<R>(destination: (passable: T) => R | Promise<R>): Promise<R>;
746
+ thenReturn(): Promise<T>;
747
+ }
748
+ interface PipelineFactory {
749
+ make<T>(): Pipeline<T>;
750
+ }
751
+ declare const PipelineFactory: Token<PipelineFactory>;
752
+
331
753
  /** Public method names of a controller (excludes non-function members). */
332
754
  type ActionMethods<C> = {
333
755
  [K in keyof C]: C[K] extends (...args: any[]) => unknown ? K : never;
334
756
  }[keyof C] & string;
335
757
  type ControllerAction<C> = readonly [Class<C>, ActionMethods<C>];
336
758
  type RouteClosure = (...args: any[]) => unknown;
337
- type RouteAction = RouteClosure | ControllerAction<any>;
759
+ /** A class with __invoke(): Route.get('/counter', Counter) (single-action controllers, full-page Live components). */
760
+ type InvokableClass = Class<{
761
+ __invoke(...args: any[]): unknown;
762
+ }>;
763
+ type RouteAction = RouteClosure | ControllerAction<any> | InvokableClass;
338
764
  type MiddlewareReference = string | MiddlewareClass;
339
765
  interface Route {
340
766
  readonly methods: readonly string[];
341
767
  readonly uri: string;
342
768
  getName(): string | undefined;
343
769
  name(name: string): this;
344
- middleware(...middleware: MiddlewareReference[]): this;
770
+ middleware(...middleware: Array<MiddlewareReference | readonly MiddlewareReference[]>): this;
345
771
  withoutMiddleware(...middleware: MiddlewareReference[]): this;
346
772
  where(parameter: string, pattern: string): this;
347
773
  where(patterns: Record<string, string>): this;
@@ -349,7 +775,7 @@ interface Route {
349
775
  interface RouteRegistrar {
350
776
  prefix(prefix: string): RouteRegistrar;
351
777
  name(prefix: string): RouteRegistrar;
352
- middleware(...middleware: MiddlewareReference[]): RouteRegistrar;
778
+ middleware(...middleware: Array<MiddlewareReference | readonly MiddlewareReference[]>): RouteRegistrar;
353
779
  controller(controller: Class<unknown>): RouteRegistrar;
354
780
  group(routes: () => void | Promise<void>): Promise<void>;
355
781
  }
@@ -369,22 +795,24 @@ interface CurrentRoute {
369
795
  }
370
796
  declare const CurrentRoute: Token<CurrentRoute>;
371
797
  interface Router {
372
- get<C>(uri: string, action: ControllerAction<C> | RouteClosure | string): Route;
373
- post<C>(uri: string, action: ControllerAction<C> | RouteClosure | string): Route;
374
- put<C>(uri: string, action: ControllerAction<C> | RouteClosure | string): Route;
375
- patch<C>(uri: string, action: ControllerAction<C> | RouteClosure | string): Route;
376
- delete<C>(uri: string, action: ControllerAction<C> | RouteClosure | string): Route;
377
- options<C>(uri: string, action: ControllerAction<C> | RouteClosure | string): Route;
378
- any<C>(uri: string, action: ControllerAction<C> | RouteClosure | string): Route;
379
- match<C>(methods: string[], uri: string, action: ControllerAction<C> | RouteClosure | string): Route;
798
+ get<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): Route;
799
+ post<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): Route;
800
+ put<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): Route;
801
+ patch<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): Route;
802
+ delete<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): Route;
803
+ options<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): Route;
804
+ any<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): Route;
805
+ match<C>(methods: string[], uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): Route;
380
806
  redirect(from: string, to: string, status?: number): Route;
381
807
  view(uri: string, view: string, data?: Record<string, unknown>): Route;
808
+ /** Route.inertia('/about', 'About', props): a GET route that renders an Inertia page (Laravel's Route::inertia). */
809
+ inertia(uri: string, component: string, props?: Record<string, unknown>): Route;
382
810
  resource(name: string, controller: Class<unknown>, options?: ResourceOptions): void;
383
811
  apiResource(name: string, controller: Class<unknown>, options?: ResourceOptions): void;
384
812
  fallback(action: RouteAction): Route;
385
813
  prefix(prefix: string): RouteRegistrar;
386
814
  name(prefix: string): RouteRegistrar;
387
- middleware(...middleware: MiddlewareReference[]): RouteRegistrar;
815
+ middleware(...middleware: Array<MiddlewareReference | readonly MiddlewareReference[]>): RouteRegistrar;
388
816
  controller(controller: Class<unknown>): RouteRegistrar;
389
817
  /** Explicit model binding: Route.model('author', User). */
390
818
  model(parameter: string, model: Class<unknown>): void;
@@ -414,6 +842,36 @@ interface RouteModelResolver {
414
842
  resolveExplicit(model: Class<unknown>, value: string, field?: string): Promise<unknown>;
415
843
  }
416
844
  declare const RouteModelResolver: Token<RouteModelResolver>;
845
+ /**
846
+ * Route name → parameters, for the typed route() and redirect().route() helpers. Empty until `oriel route:types`
847
+ * augments it (types/routes.d.ts); while it is empty any string is accepted. The contracts themselves keep taking
848
+ * strings: the framework builds route names at run time.
849
+ */
850
+ interface RouteList {
851
+ }
852
+ /** A route name: the generated ones, or any string before `oriel route:types` has run. */
853
+ type RouteName = [keyof RouteList] extends [never] ? string : Extract<keyof RouteList, string>;
854
+ /** A route parameter's value: a scalar, or a model (its route key, or the `{post:slug}` column, goes in the URL). */
855
+ type RouteParameter = string | number | bigint | boolean | {
856
+ getRouteKey(): unknown;
857
+ };
858
+ type GeneratedParameters<N extends keyof RouteList> = {
859
+ [K in keyof RouteList[N]]: RouteParameter;
860
+ };
861
+ type RequiredParameters<P> = {
862
+ [K in keyof P]-?: Record<never, never> extends Pick<P, K> ? never : K;
863
+ }[keyof P];
864
+ /**
865
+ * A named route's parameters: named (`{ post }`, extra keys become the query string), one value (it fills the first
866
+ * parameter), or values in URI order (`[post, comment]`).
867
+ */
868
+ type RouteParameters<N extends string> = N extends keyof RouteList ? (GeneratedParameters<N> & Record<string, unknown>) | RouteParameter | readonly RouteParameter[] : unknown;
869
+ /**
870
+ * The arguments after a route name in route() and redirect().route(): the parameters, required when the route has a
871
+ * required one, then `Rest` (route()'s `absolute`, redirect().route()'s `status`). Before `oriel route:types` has
872
+ * named the route, anything is accepted.
873
+ */
874
+ type RouteArguments<N extends string, Rest extends unknown[] = [absolute?: boolean]> = N extends keyof RouteList ? [RequiredParameters<RouteList[N]>] extends [never] ? [parameters?: RouteParameters<N>, ...rest: Rest] : [parameters: RouteParameters<N>, ...rest: Rest] : [parameters?: unknown, ...rest: Rest];
417
875
  interface UrlGenerator {
418
876
  to(path: string, query?: Record<string, unknown>, absolute?: boolean): string;
419
877
  route(name: string, parameters?: unknown, absolute?: boolean): string;
@@ -421,21 +879,34 @@ interface UrlGenerator {
421
879
  current(): string;
422
880
  previous(fallback?: string): string;
423
881
  hasRoute(name: string): boolean;
882
+ /** A URL to a named route with a `signature` query (HMAC-SHA256 keyed by APP_KEY); `expiration` adds `expires`. */
883
+ signedRoute(name: string, parameters?: unknown, expiration?: Date | number, absolute?: boolean): string;
884
+ /** signedRoute() that expires: a Date, or seconds from now. */
885
+ temporarySignedRoute(name: string, expiration: Date | number, parameters?: unknown, absolute?: boolean): string;
886
+ /** Whether the request URL carries a valid, unexpired signature (`absolute: false` signs the path only). */
887
+ hasValidSignature(request: HttpRequest, absolute?: boolean): boolean;
424
888
  }
425
889
  declare const UrlGenerator: Token<UrlGenerator>;
426
890
  interface RedirectResponse extends Responsable {
427
891
  readonly targetUrl: string;
428
892
  with(key: string | Record<string, unknown>, value?: unknown): this;
429
- withErrors(errors: Record<string, string | string[]>, bag?: string): this;
893
+ /** Flashes the errors (a record, or a validator's `errors()`) into the bag, `default` unless named. */
894
+ withErrors(errors: Record<string, string | string[]> | MessageBag, bag?: string): this;
430
895
  withInput(input?: Record<string, unknown>): this;
431
896
  withCookie(name: string, value: string, minutes?: number): this;
897
+ header(name: string, value: string): this;
432
898
  }
433
899
  interface Redirector {
434
900
  to(path: string, status?: number): RedirectResponse;
435
901
  route(name: string, parameters?: unknown, status?: number): RedirectResponse;
436
902
  back(fallback?: string, status?: number): RedirectResponse;
437
- intended(fallback?: string): RedirectResponse;
903
+ intended(fallback?: string, status?: number): RedirectResponse;
438
904
  away(url: string, status?: number): RedirectResponse;
905
+ /** Remembers the URL a guest was going to (for intended()), then redirects to `path`. */
906
+ guest(path: string, status?: number): RedirectResponse;
907
+ /** Redirects to the current URL. */
908
+ refresh(status?: number): RedirectResponse;
909
+ setIntendedUrl(url: string): void;
439
910
  }
440
911
  declare const Redirector: Token<Redirector>;
441
912
 
@@ -492,6 +963,8 @@ interface ViewFactory {
492
963
  exists(name: string): boolean;
493
964
  share(key: string | Record<string, unknown>, value?: unknown): void;
494
965
  composer(views: string | string[], composer: (view: View) => void | Promise<void>): void;
966
+ /** Renders TSX (an element, a string, an Htmlable, a View, promises of them) to HTML, like Blade::render(). */
967
+ renderToString(node: unknown): Promise<string>;
495
968
  }
496
969
  declare const ViewFactory: Token<ViewFactory>;
497
970
 
@@ -512,6 +985,8 @@ interface Logger {
512
985
  interface LogManager extends Logger {
513
986
  channel(name?: string): Logger;
514
987
  stack(channels: string[]): Logger;
988
+ /** Writes out and closes the channels opened so far (log files are written asynchronously); a script awaits it last. */
989
+ flush(): Promise<void>;
515
990
  }
516
991
  declare const LogManager: Token<LogManager>;
517
992
 
@@ -602,6 +1077,8 @@ interface DatabaseConnection {
602
1077
  interface DatabaseManager extends DatabaseConnection {
603
1078
  connection(name?: string): DatabaseConnection;
604
1079
  disconnect(name?: string): Promise<void>;
1080
+ /** Closes every open connection and forgets them (the application's shutdown, the end of a test). */
1081
+ disconnectAll(): Promise<void>;
605
1082
  }
606
1083
  declare const DatabaseManager: Token<DatabaseManager>;
607
1084
  /** What non-Database components may rely on from a model instance. */
@@ -612,6 +1089,8 @@ interface ModelInstance {
612
1089
  getTable(): string;
613
1090
  getRouteKey(): unknown;
614
1091
  getRouteKeyName(): string;
1092
+ /** The value stored in a polymorphic `*_type` column for this model: its morph map alias, else its class name. */
1093
+ getMorphClass(): string;
615
1094
  getAttribute<T = unknown>(key: string): T;
616
1095
  setAttribute(key: string, value: unknown): this;
617
1096
  fill(attributes: Row): this;
@@ -627,6 +1106,19 @@ interface ModelStatic<M extends ModelInstance = ModelInstance> {
627
1106
  find(id: unknown): Promise<M | undefined>;
628
1107
  findOrFail(id: unknown): Promise<M>;
629
1108
  }
1109
+ /**
1110
+ * What decides a paginator's page and the path of its links when the request doesn't (Laravel's
1111
+ * Paginator::currentPageResolver and currentPathResolver, which Livewire's WithPagination replaces). Live binds one for
1112
+ * the application, which answers while a WithPagination component mounts, runs an update's hooks and actions, or
1113
+ * renders. Unbound, or `undefined` from a method, the paginators read the request (`?page=` and its URL).
1114
+ */
1115
+ interface PaginationState {
1116
+ /** The page to show for `pageName` ('page' by default). */
1117
+ currentPage(pageName: string): number | undefined;
1118
+ /** The base path of the page links. */
1119
+ currentPath(): string | undefined;
1120
+ }
1121
+ declare const PaginationState: Token<PaginationState>;
630
1122
 
631
1123
  interface Authenticatable {
632
1124
  getAuthIdentifierName(): string;
@@ -695,6 +1187,11 @@ interface MustVerifyEmail {
695
1187
 
696
1188
  /** Options a job class may declare as public fields. Their presence (or implementing ShouldQueue) makes things queueable. */
697
1189
  interface ShouldQueue {
1190
+ /**
1191
+ * Marks the class as queued at run time: `implements ShouldQueue` leaves no trace once compiled, so the interface
1192
+ * asks for `readonly shouldQueue = true`. Jobs, listeners, mailables and notifications carrying it are queued.
1193
+ */
1194
+ readonly shouldQueue: true;
698
1195
  connection?: string;
699
1196
  queue?: string;
700
1197
  /** Seconds. */
@@ -704,7 +1201,11 @@ interface ShouldQueue {
704
1201
  backoff?: number | number[];
705
1202
  /** Seconds. */
706
1203
  timeout?: number;
707
- uniqueId?(): string;
1204
+ /**
1205
+ * Laravel's ShouldBeUnique: while a job with this id is pending, another one is dropped. A queued listener's
1206
+ * receives the event (Laravel 13); a number is used as its string.
1207
+ */
1208
+ uniqueId?(...args: never[]): string | number;
708
1209
  }
709
1210
  /** A job: public fields are its serialized data; handle() runs on the worker (inject() works inside it). */
710
1211
  interface Job extends Partial<ShouldQueue> {
@@ -879,27 +1380,83 @@ interface ConsoleKernel {
879
1380
  command(signature: string, handler: (this: CommandContext, ...args: unknown[]) => number | void | Promise<number | void>): ClosureCommand;
880
1381
  }
881
1382
  declare const ConsoleKernel: Token<ConsoleKernel>;
1383
+ /** A callback a scheduled event runs before or after itself (before(), after(), onSuccess(), onFailure()). */
1384
+ type ScheduleHook = () => unknown;
882
1385
  interface ScheduledEvent {
883
1386
  readonly expression: string;
1387
+ /**
1388
+ * What a Schedule.command() event runs: the command and its parameters ('posts:announce --force'), without the
1389
+ * runtime and `oriel` in front. Undefined for call() and job() events. Laravel's `$event->command`.
1390
+ */
1391
+ readonly command: string | undefined;
1392
+ /** Whether withoutOverlapping() was called. Laravel's `$event->withoutOverlapping`, a method's name here. */
1393
+ readonly preventsOverlapping: boolean;
1394
+ /** Minutes the withoutOverlapping() lock is kept at most (1440 unless withoutOverlapping() says). Laravel's `$event->expiresAt`. */
1395
+ readonly expiresAt: number;
884
1396
  cron(expression: string): this;
1397
+ /**
1398
+ * Runs every N seconds: the event is due every minute, and schedule:run (or schedule:work) keeps running it until
1399
+ * the minute ends. N divides 60.
1400
+ */
1401
+ everySecond(): this;
1402
+ everyTwoSeconds(): this;
1403
+ everyFiveSeconds(): this;
1404
+ everyTenSeconds(): this;
1405
+ everyFifteenSeconds(): this;
1406
+ everyTwentySeconds(): this;
1407
+ everyThirtySeconds(): this;
885
1408
  everyMinute(): this;
1409
+ everyTwoMinutes(): this;
1410
+ everyThreeMinutes(): this;
1411
+ everyFourMinutes(): this;
886
1412
  everyFiveMinutes(): this;
1413
+ everyTenMinutes(): this;
887
1414
  everyFifteenMinutes(): this;
888
1415
  everyThirtyMinutes(): this;
889
1416
  hourly(): this;
890
- hourlyAt(minute: number): this;
1417
+ /** At these minutes past every hour. */
1418
+ hourlyAt(minute: number | readonly number[]): this;
1419
+ /** Every odd hour (1, 3, … 23), at `minute` past (0 by default). */
1420
+ everyOddHour(minute?: number | readonly number[]): this;
1421
+ everyTwoHours(minute?: number | readonly number[]): this;
1422
+ everyThreeHours(minute?: number | readonly number[]): this;
1423
+ everyFourHours(minute?: number | readonly number[]): this;
1424
+ everySixHours(minute?: number | readonly number[]): this;
891
1425
  daily(): this;
1426
+ /** The same as dailyAt(). */
1427
+ at(time: string): this;
892
1428
  dailyAt(time: string): this;
893
1429
  twiceDaily(first?: number, second?: number): this;
1430
+ /** At hours `first` and `second`, `minute` past. */
1431
+ twiceDailyAt(first?: number, second?: number, minute?: number): this;
1432
+ weekdays(): this;
1433
+ weekends(): this;
1434
+ mondays(): this;
1435
+ tuesdays(): this;
1436
+ wednesdays(): this;
1437
+ thursdays(): this;
1438
+ fridays(): this;
1439
+ saturdays(): this;
1440
+ sundays(): this;
894
1441
  weekly(): this;
895
- weeklyOn(day: number, time?: string): this;
1442
+ /** On these days of the week (0 = Sunday … 6 = Saturday), at `time` ('0:0' by default). */
1443
+ weeklyOn(day: number | readonly number[], time?: string): this;
896
1444
  monthly(): this;
897
- monthlyOn(day: number, time?: string): this;
1445
+ monthlyOn(day?: number, time?: string): this;
1446
+ twiceMonthly(first?: number, second?: number, time?: string): this;
1447
+ /** On the last day of every month, at `time`. */
1448
+ lastDayOfMonth(time?: string): this;
1449
+ quarterly(): this;
1450
+ /** On day `day` of the first month of each quarter, at `time`. */
1451
+ quarterlyOn(day?: number, time?: string): this;
898
1452
  yearly(): this;
899
- weekdays(): this;
900
- weekends(): this;
1453
+ yearlyOn(month?: number, day?: number, time?: string): this;
1454
+ /** On these days of the week (0 = Sunday … 6 = Saturday): `days([1, 3])` or `days(1, 3)`. */
1455
+ days(days: number | readonly number[], ...more: number[]): this;
901
1456
  timezone(timezone: string): this;
902
1457
  between(start: string, end: string): this;
1458
+ /** Skips the event between these times (a window may cross midnight: '23:00', '4:00'). */
1459
+ unlessBetween(start: string, end: string): this;
903
1460
  when(callback: () => boolean | Promise<boolean>): this;
904
1461
  skip(callback: () => boolean | Promise<boolean>): this;
905
1462
  /** Uses a cache lock (default 1440 minutes). */
@@ -909,6 +1466,22 @@ interface ScheduledEvent {
909
1466
  runInBackground(): this;
910
1467
  name(name: string): this;
911
1468
  description(description: string): this;
1469
+ /** Runs before the event, once its filters and locks let it run. */
1470
+ before(callback: ScheduleHook): this;
1471
+ /** Runs after the event, whether it succeeded or failed (also then()). */
1472
+ after(callback: ScheduleHook): this;
1473
+ then(callback: ScheduleHook): this;
1474
+ /** Runs after the event when it succeeded: a command exited 0, a closure neither threw nor returned false. */
1475
+ onSuccess(callback: ScheduleHook): this;
1476
+ /** Runs after the event when it failed: a command exited non-zero, a closure threw or returned false. */
1477
+ onFailure(callback: ScheduleHook): this;
1478
+ /** The name, else the description: the command, the job's class, or 'Closure'. schedule:list shows it. */
1479
+ getSummaryForDisplay(): string;
1480
+ /**
1481
+ * The cache lock withoutOverlapping() holds: `framework/schedule-` and the sha1 of the expression and the command,
1482
+ * or of the name for call() and job() events (Laravel's mutexName()). schedule:clear-cache deletes it.
1483
+ */
1484
+ mutexName(): string;
912
1485
  isDue(now: Date): boolean;
913
1486
  run(): Promise<void>;
914
1487
  }
@@ -987,6 +1560,8 @@ interface PendingMail {
987
1560
  cc(recipients: MailRecipient | MailRecipient[]): this;
988
1561
  bcc(recipients: MailRecipient | MailRecipient[]): this;
989
1562
  send(mailable: Mailable): Promise<SentMessage | undefined>;
1563
+ /** Sends at once, even when the mailable is queueable (Laravel's sendNow()). A fake resolves undefined. */
1564
+ sendNow(mailable: Mailable): Promise<SentMessage | undefined>;
990
1565
  queue(mailable: Mailable): Promise<void>;
991
1566
  later(delaySeconds: number, mailable: Mailable): Promise<void>;
992
1567
  }
@@ -994,6 +1569,8 @@ interface Mailer {
994
1569
  to(recipients: MailRecipient | MailRecipient[]): PendingMail;
995
1570
  /** Sends to the recipients given in the mailable's envelope. Queues it if the mailable is queueable. */
996
1571
  send(mailable: Mailable): Promise<SentMessage | undefined>;
1572
+ /** Sends to the envelope's recipients at once, even when the mailable is queueable (Laravel's sendNow()). */
1573
+ sendNow(mailable: Mailable): Promise<SentMessage | undefined>;
997
1574
  queue(mailable: Mailable): Promise<void>;
998
1575
  }
999
1576
  interface MailManager extends Mailer {
@@ -1029,6 +1606,28 @@ interface NotificationDispatcher {
1029
1606
  extend(channel: string, factory: () => NotificationChannel): void;
1030
1607
  }
1031
1608
  declare const NotificationDispatcher: Token<NotificationDispatcher>;
1609
+ /**
1610
+ * A stored database notification (Laravel's DatabaseNotification model): one row of the `notifications` table, with
1611
+ * its snake_case columns. `user.notifications()`, `unreadNotifications()` and `readNotifications()` query these,
1612
+ * newest first.
1613
+ */
1614
+ interface DatabaseNotification extends ModelInstance {
1615
+ /** A UUID. */
1616
+ readonly id: string;
1617
+ /** The notification's class name. */
1618
+ readonly type: string;
1619
+ /** What the notification's toDatabase() (or toArray()) returned. */
1620
+ readonly data: Record<string, unknown>;
1621
+ read_at: Date | null;
1622
+ readonly created_at: Date | null;
1623
+ readonly updated_at: Date | null;
1624
+ /** Sets read_at to now and saves, unless it is already read. */
1625
+ markAsRead(): Promise<void>;
1626
+ /** Clears read_at and saves, unless it is already unread. */
1627
+ markAsUnread(): Promise<void>;
1628
+ read(): boolean;
1629
+ unread(): boolean;
1630
+ }
1032
1631
 
1033
1632
  interface Lock {
1034
1633
  /** Tries once. Returns whether it was acquired. */
@@ -1068,6 +1667,18 @@ interface CacheManager extends CacheRepository {
1068
1667
  extend(driver: string, factory: (config: Record<string, unknown>) => CacheRepository): void;
1069
1668
  }
1070
1669
  declare const CacheManager: Token<CacheManager>;
1670
+ /** Laravel's RateLimiter: hits per key, kept in the default cache store. */
1671
+ interface RateLimiter {
1672
+ tooManyAttempts(key: string, maxAttempts: number): Promise<boolean>;
1673
+ /** Adds a hit; the window starts at the first hit and lasts `decaySeconds` (default 60). Returns the hit count. */
1674
+ hit(key: string, decaySeconds?: number): Promise<number>;
1675
+ attempts(key: string): Promise<number>;
1676
+ remaining(key: string, maxAttempts: number): Promise<number>;
1677
+ /** Seconds until the key's window resets. */
1678
+ availableIn(key: string): Promise<number>;
1679
+ clear(key: string): Promise<void>;
1680
+ }
1681
+ declare const RateLimiter: Token<RateLimiter>;
1071
1682
 
1072
1683
  type ListenerClass<E> = Class<{
1073
1684
  handle(event: E): unknown;
@@ -1124,38 +1735,99 @@ interface FilesystemManager extends Filesystem {
1124
1735
  }
1125
1736
  declare const FilesystemManager: Token<FilesystemManager>;
1126
1737
 
1127
- /** The Inertia page object (protocol v2). */
1738
+ /** Infinite-scroll metadata for one prop (page.scrollProps[path]). */
1739
+ interface InertiaScrollProp {
1740
+ pageName: string;
1741
+ previousPage: string | number | null;
1742
+ nextPage: string | number | null;
1743
+ currentPage: string | number | null;
1744
+ reset: boolean;
1745
+ }
1746
+ /** A once prop the client keeps between visits (page.onceProps[key]). `expiresAt` is epoch milliseconds. */
1747
+ interface InertiaOnceProp {
1748
+ prop: string;
1749
+ expiresAt: number | null;
1750
+ }
1751
+ /**
1752
+ * The Inertia page object (protocol v3, @inertiajs/core 3.x). Only component, props, url and version are always
1753
+ * present; the other fields are left out when empty or false.
1754
+ */
1128
1755
  interface InertiaPage {
1129
1756
  component: string;
1130
1757
  props: Record<string, unknown>;
1758
+ /** Path and query, never absolute: '/posts?page=2'. */
1131
1759
  url: string;
1132
- version: string | null;
1133
- encryptHistory?: boolean;
1134
- clearHistory?: boolean;
1760
+ /** '' when the app has no asset version. */
1761
+ version: string;
1762
+ sharedProps?: string[];
1135
1763
  mergeProps?: string[];
1764
+ prependProps?: string[];
1765
+ deepMergeProps?: string[];
1766
+ /** '<prop path>.<key field>', e.g. 'posts.data.id'. */
1767
+ matchPropsOn?: string[];
1768
+ /** Group name → prop paths loaded after the first render. */
1136
1769
  deferredProps?: Record<string, string[]>;
1770
+ rescuedProps?: string[];
1771
+ scrollProps?: Record<string, InertiaScrollProp>;
1772
+ onceProps?: Record<string, InertiaOnceProp>;
1773
+ clearHistory?: true;
1774
+ encryptHistory?: true;
1775
+ flash?: Record<string, unknown>;
1776
+ preserveFragment?: true;
1137
1777
  }
1138
1778
  interface InertiaResponse extends Responsable {
1139
1779
  with(key: string | Record<string, unknown>, value?: unknown): this;
1140
1780
  withViewData(key: string | Record<string, unknown>, value?: unknown): this;
1781
+ rootView(view: string): this;
1782
+ /** Flash data for the next page (page.flash), stored in the session. */
1783
+ flash(key: string | Record<string, unknown>, value?: unknown): this;
1141
1784
  }
1142
1785
  type PropCallback<T = unknown> = () => T | Promise<T>;
1786
+ /** The SSR result spliced into the root view: the `head` tags and the rendered `body`. */
1787
+ interface InertiaSsrResponse {
1788
+ head: string;
1789
+ body: string;
1790
+ }
1791
+ /** Sends a page to the SSR server. Resolves to undefined when SSR is off, unreachable or failing. */
1792
+ interface InertiaSsrGateway {
1793
+ dispatch(page: InertiaPage): Promise<InertiaSsrResponse | undefined>;
1794
+ }
1795
+ declare const InertiaSsrGateway: Token<InertiaSsrGateway>;
1143
1796
  interface InertiaFactory {
1144
1797
  render(component: string, props?: Record<string, unknown>): InertiaResponse;
1145
1798
  share(key: string | Record<string, unknown>, value?: unknown): void;
1799
+ /** A shared once prop: sent on the first visit, then kept by the client. */
1800
+ shareOnce(key: string, callback: PropCallback): void;
1146
1801
  getShared(key?: string): unknown;
1147
- version(version: string | (() => string | Promise<string>)): void;
1802
+ flushShared(): void;
1803
+ version(version: string | null | (() => string | null | Promise<string | null>)): void;
1804
+ getVersion(): Promise<string>;
1805
+ setRootView(view: string): void;
1148
1806
  /** Only evaluated on partial reloads that ask for it. */
1149
1807
  optional<T>(callback: PropCallback<T>): unknown;
1150
1808
  /** Loaded in a follow-up request after the first render. */
1151
1809
  defer<T>(callback: PropCallback<T>, group?: string): unknown;
1152
1810
  /** Always included, even in partial reloads. */
1153
1811
  always<T>(value: T | PropCallback<T>): unknown;
1154
- /** Merged with the existing client-side value instead of replacing it. */
1812
+ /** Appended to the existing client-side value instead of replacing it. */
1155
1813
  merge<T>(value: T | PropCallback<T>): unknown;
1156
- /** 409 + X-Inertia-Location for external redirects. */
1814
+ /** Deep-merged with the existing client-side value. */
1815
+ deepMerge<T>(value: T | PropCallback<T>): unknown;
1816
+ /** Resolved once, then remembered by the client. */
1817
+ once<T>(callback: PropCallback<T>): unknown;
1818
+ /** Infinite scroll over a paginator: merged page by page, with scroll metadata. */
1819
+ scroll<T>(value: T | PropCallback<T>, wrapper?: string): unknown;
1820
+ /** Flash data for the next page (page.flash), stored in the session. */
1821
+ flash(key: string | Record<string, unknown>, value?: unknown): this;
1822
+ encryptHistory(encrypt?: boolean): void;
1823
+ /** The next page tells the client to clear its encrypted history. */
1824
+ clearHistory(): void;
1825
+ /** The next page keeps the URL fragment of the request that redirected to it. */
1826
+ preserveFragment(): void;
1827
+ /** 409 + X-Inertia-Location for Inertia requests, a plain 302 otherwise. */
1157
1828
  location(url: string): Response;
1158
- setRootView(view: string): void;
1829
+ /** Redirect back (Inertia.flash('saved', true).back()). */
1830
+ back(fallback?: string, status?: number): RedirectResponse;
1159
1831
  }
1160
1832
  declare const InertiaFactory: Token<InertiaFactory>;
1161
1833
 
@@ -1175,11 +1847,18 @@ interface LiveSnapshot {
1175
1847
  }
1176
1848
  interface LiveEffects {
1177
1849
  html?: string;
1850
+ /** Browser events from this.dispatch(); `self` keeps one on this component, `to` sends it to one component name. */
1178
1851
  dispatches?: Array<{
1179
1852
  name: string;
1180
- params: unknown[];
1853
+ params: Record<string, unknown>;
1854
+ self?: true;
1855
+ to?: string;
1181
1856
  }>;
1857
+ /** Events this component listens to (@On, static listeners); sent with the first render. */
1858
+ listeners?: string[];
1182
1859
  redirect?: string;
1860
+ /** Follow `redirect` with o:navigate instead of a full page load. */
1861
+ redirectUsingNavigate?: true;
1183
1862
  returns?: unknown[];
1184
1863
  }
1185
1864
  interface LiveUpdateRequest {
@@ -1201,12 +1880,17 @@ interface LiveUpdateResponse {
1201
1880
  }
1202
1881
  interface LiveManager {
1203
1882
  register(component: Class<unknown>, name?: string): void;
1204
- /** Server-renders the first HTML (snapshot embedded). */
1205
- mount(component: string | Class<unknown>, params?: Record<string, unknown>): Promise<string>;
1883
+ /** Server-renders the first HTML (snapshot embedded). `key` identifies a child inside its parent (o:key). */
1884
+ mount(component: string | Class<unknown>, params?: Record<string, unknown>, key?: string): Promise<string>;
1206
1885
  /** Checks checksums and CSRF, then applies updates and calls, re-renders and returns new snapshots. */
1207
1886
  update(request: LiveUpdateRequest): Promise<LiveUpdateResponse>;
1887
+ /**
1888
+ * A full-page component (Route.get('/counter', Counter)): mounts `component` (a component instance) with the current route's parameters and
1889
+ * returns the response, its layout view or a redirect.
1890
+ */
1891
+ page(component: object): Promise<unknown>;
1208
1892
  isLiveRequest(request: HttpRequest): boolean;
1209
1893
  }
1210
1894
  declare const LiveManager: Token<LiveManager>;
1211
1895
 
1212
- export { type AbilityCallback, type Abstract, type ActionMethods, type Address, Application, type Arrayable, type Attachment, AuthFactory, type Authenticatable, type AuthenticationError, type Batch, BatchRepository, type BodyInit, BusDispatcher, CacheManager, type CacheRepository, type Class, ClassRegistry, type ClosureCommand, type Command, type CommandContext, type Concrete, type ConfigCallbacks, ConfigRepository, ConsoleKernel, Container, type Content, type ControllerAction, type Cookie, CookieJar, type Credentials, CurrentRoute, type DatabaseConnection, DatabaseManager, type DriverName, Encrypter, type Enumerable, type Envelope, type ErrorKind, EventDispatcher, ExceptionCallbacks, ExceptionHandler, type ExceptionsConfigurator, type Factory, type FailedJob, FailedJobProvider, type Filesystem, FilesystemManager, Gate, type Guard, Hasher, type HeadersInit, type Htmlable, HttpKernel, HttpRequest, InertiaFactory, type InertiaPage, type InertiaResponse, type Job, type Jsonable, type Listener, type ListenerClass, type LiveEffects, LiveManager, type LiveSnapshot, type LiveUpdateRequest, type LiveUpdateResponse, type Lock, type LogLevel, LogManager, type Logger, MailManager, type MailRecipient, type MailTransport, type Mailable, type Mailer, type MessageBag, type Middleware, MiddlewareCallbacks, type MiddlewareClass, type MiddlewareConfigurator, type MiddlewareReference, type ModelInstance, type ModelNotFoundError, type ModelStatic, type MustVerifyEmail, type Next, type Notifiable, type Notification, type NotificationChannel, NotificationDispatcher, type Operator, type OptionValue, type OrielError, type OutgoingMessage, PasswordBroker, type PasswordStatus, type PendingBatch, type PendingBatchOptions, type PendingChain, type PendingMail, type Pipe, type PipeClosure, type PipeNext, type Pipeline, PipelineFactory, type PropCallback, type PutOptions, type QueryBuilder, type Queue, type QueueJob, QueueManager, type QueuePayload, type RedirectResponse, Redirector, type ResourceOptions, type Responsable, ResponseFactory, type Route, type RouteAction, type RouteClosure, RouteModelResolver, type RouteRegistrar, Router, RoutingPaths, type Row, type RuleCallback, type Rules, Schedule, type ScheduledEvent, type SentMessage, type ServiceProvider, type ServiceProviderClass, Session, type SessionHandler, type ShouldQueue, type StatefulGuard, type Token, type UploadedFile, UrlGenerator, type UserProvider, type ValidationError, ValidationFactory, type ValidationRule, type Validator, type View, ViewFactory, token };
1896
+ export { type AbilityCallback, type Abstract, type ActionMethods, type Address, Application, type Arrayable, type Attachment, AuthFactory, type Authenticatable, type AuthenticationError, type Batch, BatchRepository, type BodyInit, BusDispatcher, CacheManager, type CacheRepository, type Class, ClassNames, ClassRegistry, type ClosureCommand, type Command, type CommandContext, type Concrete, type ConfigCallbacks, ConfigRepository, ConsoleKernel, Container, type Content, type ControllerAction, type Cookie, CookieJar, type Credentials, CurrentRoute, type DatabaseConnection, DatabaseManager, type DatabaseNotification, type DriverName, Encrypter, type Enumerable, type Envelope, type ErrorKind, EventDispatcher, ExceptionCallbacks, ExceptionHandler, type ExceptionsConfigurator, type Factory, type FailedJob, FailedJobProvider, type Filesystem, FilesystemManager, Gate, type Guard, Hasher, type HeadersInit, type Htmlable, HttpKernel, HttpRequest, type InValue, InertiaFactory, type InertiaOnceProp, type InertiaPage, type InertiaResponse, type InertiaScrollProp, InertiaSsrGateway, type InertiaSsrResponse, type InferRuleType, type InferValidatedType, type InvokableClass, type Job, type Jsonable, type Listener, type ListenerClass, type LiveEffects, LiveManager, type LiveSnapshot, type LiveUpdateRequest, type LiveUpdateResponse, type Lock, type LogLevel, LogManager, type Logger, MailManager, type MailRecipient, type MailTransport, type Mailable, type Mailer, type MessageBag, type Middleware, MiddlewareCallbacks, type MiddlewareClass, type MiddlewareConfigurator, type MiddlewareReference, type ModelInstance, type ModelNotFoundError, type ModelStatic, type MustVerifyEmail, type Next, type Notifiable, type Notification, type NotificationChannel, NotificationDispatcher, type NumericValue, type Operator, type OptionValue, type OrielError, type OutgoingMessage, PaginationState, PasswordBroker, type PasswordStatus, type PendingBatch, type PendingBatchOptions, type PendingChain, type PendingMail, type Pipe, type PipeClosure, type PipeNext, type Pipeline, PipelineFactory, type PropCallback, type PutOptions, type QueryBuilder, type Queue, type QueueJob, QueueManager, type QueuePayload, RateLimiter, type RedirectResponse, Redirector, type ResourceOptions, type Responsable, ResponseFactory, type Route, type RouteAction, type RouteArguments, type RouteClosure, type RouteList, RouteModelResolver, type RouteName, type RouteParameter, type RouteParameters, type RouteRegistrar, Router, RoutingPaths, type Row, type RuleCallback, type RuleParameterList, type RuleTyping, type Rules, Schedule, type ScheduleHook, type ScheduledEvent, type SentMessage, type ServiceProvider, type ServiceProviderClass, Session, type SessionHandler, type ShouldQueue, type StatefulGuard, type Token, type TypedValidationRule, type UploadedFile, UrlGenerator, type UserProvider, type ValidationError, ValidationFactory, type ValidationRule, type ValidationRuleTypes, type Validator, type View, ViewFactory, token };