@orieljs/framework 0.1.0-alpha.6 → 0.1.0-alpha.7

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 (86) hide show
  1. package/NOTICE +4 -0
  2. package/README.md +10 -1
  3. package/TRADEMARKS.md +33 -0
  4. package/dist/{chunk-ZOEPKBVF.js → chunk-4MWG3B7G.js} +1347 -428
  5. package/dist/chunk-4MWG3B7G.js.map +1 -0
  6. package/dist/{chunk-POEP4B2M.js → chunk-7ZQZYDOC.js} +745 -105
  7. package/dist/chunk-7ZQZYDOC.js.map +1 -0
  8. package/dist/{chunk-I63ZFMX6.js → chunk-GVNLZZTN.js} +1 -1
  9. package/dist/chunk-GVNLZZTN.js.map +1 -0
  10. package/dist/{chunk-MFTZQMZM.js → chunk-VOYW3R5J.js} +4 -4
  11. package/dist/chunk-VOYW3R5J.js.map +1 -0
  12. package/dist/contracts.d.ts +515 -17
  13. package/dist/contracts.js +1 -1
  14. package/dist/index.d-WQpfdIbG.d.ts +630 -0
  15. package/dist/index.d.ts +964 -152
  16. package/dist/index.js +4279 -866
  17. package/dist/index.js.map +1 -1
  18. package/dist/{jsx-runtime-CBZQYYDS.d.ts → jsx-runtime-6um4Mwfb.d.ts} +96 -5
  19. package/dist/jsx-runtime.d.ts +2 -2
  20. package/dist/jsx-runtime.js +3 -3
  21. package/dist/{testing-BM481Hdz.d.ts → testing-CKwfWJGn.d.ts} +180 -15
  22. package/dist/testing.d.ts +2 -2
  23. package/dist/testing.js +3 -3
  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 +651 -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 +276 -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/facades.md +278 -0
  46. package/docs/hashing.md +118 -0
  47. package/docs/helpers.md +1281 -0
  48. package/docs/http-tests.md +386 -0
  49. package/docs/inertia.md +485 -0
  50. package/docs/installation.md +209 -0
  51. package/docs/lifecycle.md +234 -0
  52. package/docs/live-tests.md +226 -0
  53. package/docs/live.md +910 -0
  54. package/docs/logging.md +255 -0
  55. package/docs/mail.md +619 -0
  56. package/docs/middleware.md +384 -0
  57. package/docs/migrations.md +416 -0
  58. package/docs/mocking.md +264 -0
  59. package/docs/navigation.json +273 -0
  60. package/docs/notifications.md +225 -0
  61. package/docs/pagination.md +247 -0
  62. package/docs/passwords.md +207 -0
  63. package/docs/providers.md +187 -0
  64. package/docs/queries.md +600 -0
  65. package/docs/queues.md +330 -0
  66. package/docs/requests.md +533 -0
  67. package/docs/responses.md +444 -0
  68. package/docs/routing.md +738 -0
  69. package/docs/scheduling.md +277 -0
  70. package/docs/seeding.md +122 -0
  71. package/docs/session.md +409 -0
  72. package/docs/starter-kits.md +396 -0
  73. package/docs/storage.md +192 -0
  74. package/docs/structure.md +264 -0
  75. package/docs/testing.md +165 -0
  76. package/docs/time-travel.md +138 -0
  77. package/docs/validation.md +1792 -0
  78. package/docs/verification.md +152 -0
  79. package/docs/views.md +566 -0
  80. package/docs/vite.md +322 -0
  81. package/package.json +34 -32
  82. package/dist/chunk-I63ZFMX6.js.map +0 -1
  83. package/dist/chunk-MFTZQMZM.js.map +0 -1
  84. package/dist/chunk-POEP4B2M.js.map +0 -1
  85. package/dist/chunk-ZOEPKBVF.js.map +0 -1
  86. package/dist/index.d-BJyJx6U1.d.ts +0 -319
package/docs/vite.md ADDED
@@ -0,0 +1,322 @@
1
+ # Asset bundling (Vite)
2
+
3
+ Vite bundles your pages' scripts and styles. While you work, it serves them and updates them in the browser as you
4
+ edit them; for production, it builds them into `public/build`.
5
+
6
+ ## Introduction
7
+
8
+ Oriel's Vite plugin, `oriel()` from `@orieljs/vite`, connects Vite and your app, as Laravel's `laravel-vite-plugin`
9
+ does: your views load the right files with `vite()`, from the dev server while it runs and from the build otherwise.
10
+
11
+ Every starter kit except the API kit has Vite set up. The API kit has no pages, so it has no `vite.config.ts` and no
12
+ `dev` or `build` script.
13
+
14
+ ## Installation and setup
15
+
16
+ ### Installing Node
17
+
18
+ Vite runs on Node 22 or later, or Bun, as your app does.
19
+
20
+ ### Installing Vite and the Oriel plugin
21
+
22
+ Every new app lists `vite` and `@orieljs/vite` in `package.json`, the API kit's too: its tests use them. To give an API
23
+ app pages, add a `vite.config.ts` as below, and `"dev": "vite"` and `"build": "vite build"` to its scripts.
24
+
25
+ ### Configuring Vite
26
+
27
+ `vite.config.ts`, in your app's root, lists your entry points, the files your pages load:
28
+
29
+ ```ts title="vite.config.ts"
30
+ import { oriel } from '@orieljs/vite'
31
+ import { defineConfig } from 'vite'
32
+
33
+ export default defineConfig({
34
+ plugins: [oriel({ input: ['resources/css/app.css', 'resources/js/app.ts'] })],
35
+ })
36
+ ```
37
+
38
+ An Inertia app names its framework, which loads that framework's Vite plugin (`@vitejs/plugin-react` for React), and
39
+ its server entry for SSR. The React kit's:
40
+
41
+ ```ts title="vite.config.ts"
42
+ import { oriel } from '@orieljs/vite'
43
+ import tailwindcss from '@tailwindcss/vite'
44
+ import { defineConfig } from 'vite'
45
+
46
+ export default defineConfig({
47
+ plugins: [
48
+ tailwindcss(),
49
+ oriel({ framework: 'react', input: ['resources/css/app.css', 'resources/js/app.tsx'], ssr: 'resources/js/ssr.tsx' }),
50
+ ],
51
+ })
52
+ ```
53
+
54
+ `framework` is `'react'`, `'vue'`, `'svelte'`, `'solid'` or `'angular'`. The Live kit names none: its components render
55
+ on the server.
56
+
57
+ | Option | What it is |
58
+ | --- | --- |
59
+ | `input` | The entry points |
60
+ | `framework` | The Inertia framework, whose Vite plugin it loads |
61
+ | `frameworkOptions` | Options for that plugin |
62
+ | `ssr` | The SSR entry, found by itself (`resources/js/ssr.tsx`) unless you name it; `false` turns SSR off |
63
+ | `inertia` | Options for `@inertiajs/vite`, or `false` to leave it out |
64
+ | `refresh` | The server files that reload the page when they change: `true` for the defaults, `false`, or your own globs |
65
+ | `types` | The generated page and route types: `true`, `false`, or `{ pages, routes, command }` |
66
+ | `publicDirectory`, `buildDirectory` | Where the build goes: `public` and `build` |
67
+ | `hotFile` | The file that tells your app the dev server is running: `public/hot` |
68
+ | `ssrOutputDirectory` | Where the SSR build goes: `bootstrap/ssr` |
69
+
70
+ ### Loading your scripts and styles
71
+
72
+ `vite()` in a view writes the tags for your entry points:
73
+
74
+ ```tsx title="resources/views/app.tsx"
75
+ import { vite } from '@orieljs/framework'
76
+
77
+ export default function App() {
78
+ return (
79
+ <html lang="en">
80
+ <head>
81
+ <meta charset="utf-8" />
82
+ {vite(['resources/css/app.css', 'resources/js/app.ts'])}
83
+ </head>
84
+ <body>...</body>
85
+ </html>
86
+ )
87
+ }
88
+ ```
89
+
90
+ While the dev server runs, the tags point at it. Otherwise they point at the built files, with the scripts and styles
91
+ they import preloaded. Each script and stylesheet tag carries `data-navigate-track`, so Live's `o:navigate` loads a
92
+ page in full when it names a new build's files; `useScriptTagAttributes({ 'data-navigate-track': false })` leaves it
93
+ out. A file that isn't in the build throws a `ViteError`: "Unable to locate file in Vite manifest:
94
+ resources/js/app.ts.".
95
+
96
+ A React app also needs `viteReactRefresh()` before `vite()`, so that React's fast refresh works while you work:
97
+
98
+ ```tsx
99
+ const head = (
100
+ <head>
101
+ {viteReactRefresh()}
102
+ {vite(['resources/css/app.css', 'resources/js/app.tsx'])}
103
+ </head>
104
+ )
105
+ ```
106
+
107
+ ## Running Vite
108
+
109
+ `npm run dev` starts the dev server, and `npm run build` builds your assets for production:
110
+
111
+ ```sh
112
+ npm run dev
113
+
114
+ npm run build
115
+ ```
116
+
117
+ Run your app's server next to the dev server, in a second terminal: `node oriel serve --watch`.
118
+ [Running your application](installation.md#running-your-application) explains how the two work together.
119
+
120
+ The kits with SSR build twice, `vite build && vite build --ssr`: the browser's bundle into `public/build`, and the
121
+ server's into `bootstrap/ssr`.
122
+
123
+ While the dev server runs, it writes its URL to `public/hot`, and deletes the file when it stops. Don't deploy that
124
+ file: while it exists, your pages load their assets from a dev server that isn't there.
125
+
126
+ ## Working with JavaScript
127
+
128
+ ### Aliases
129
+
130
+ `@` is `resources/js`, so you can import `@/components/Button` from anywhere in your scripts.
131
+
132
+ ### Inertia
133
+
134
+ The plugin loads `@inertiajs/vite`, which finds your pages in `resources/js/pages` and builds the SSR bundle. The
135
+ [Inertia](inertia.md) page covers the rest.
136
+
137
+ ### Generated types
138
+
139
+ In an Inertia app, the plugin writes your pages' prop types to `resources/js/oriel/pages.d.ts` and runs
140
+ `oriel route:types`, which writes the route table behind `route()` in your pages. It runs both when Vite starts, and
141
+ again while `npm run dev` runs: the page types when a file in `app` or `routes` changes, the route types when one in
142
+ `routes` or `app/Http/Controllers` does. `types: false` turns it off, and `types: { routes: false }` keeps the page
143
+ types only.
144
+
145
+ ### Environment variables
146
+
147
+ Vite gives your scripts the variables in `.env` that start with `VITE_`, and only those:
148
+
149
+ ```sh
150
+ VITE_SENTRY_DSN_PUBLIC=https://example.com
151
+ ```
152
+
153
+ ```ts nocheck
154
+ const dsn = import.meta.env.VITE_SENTRY_DSN_PUBLIC
155
+ ```
156
+
157
+ > [!WARNING]
158
+ > Every `VITE_` variable ends up in the scripts anyone can download. Keep your secrets in other variables.
159
+
160
+ ## Working with stylesheets
161
+
162
+ Give your CSS file to `input`, or import it from a script, and Vite processes it: the kits' `resources/css/app.css` is
163
+ built with Tailwind CSS, through `@tailwindcss/vite`. Vite's own CSS features, such as PostCSS and CSS modules, work as
164
+ its documentation describes.
165
+
166
+ ## Working with views and routes
167
+
168
+ ### Processing static assets with Vite
169
+
170
+ An image your script imports is in the build, with a hashed name. `vite().asset()` gives its URL in a view; to have
171
+ images that no script imports built too, import them as a glob in your entry point:
172
+
173
+ ```ts title="resources/js/app.ts"
174
+ import.meta.glob(['../images/**'])
175
+ ```
176
+
177
+ ```tsx
178
+ const logo = <img src={vite().asset('resources/images/logo.png')} alt="Logo" />
179
+ ```
180
+
181
+ `vite().content('resources/css/mail.css')` gives a built file's contents, such as styles to put in a mail.
182
+
183
+ ### Refreshing on save
184
+
185
+ When a view, a route file, a translation or a Live component changes, Vite reloads the page in the browser:
186
+
187
+ | Folder | Reloads |
188
+ | --- | --- |
189
+ | `resources/views/**` | Views |
190
+ | `routes/**` | Route files |
191
+ | `app/Live/**` | Live components |
192
+ | `lang/**`, `resources/lang/**` | Translations |
193
+
194
+ `refresh` takes your own list instead: `refresh: ['resources/views/**', 'app/Http/Controllers/**']`.
195
+
196
+ > [!NOTE]
197
+ > Vite reloads the page as soon as the file changes, often before `serve --watch` has restarted the server, and it
198
+ > doesn't reload again once the new server is up. After "Restarting server...", reload the page once more.
199
+
200
+ ## Custom base URLs
201
+
202
+ To serve your built assets from another host, such as a CDN, set `ASSET_URL` in `.env`. The build reads it, so the
203
+ URLs inside your scripts and styles start with it:
204
+
205
+ ```sh
206
+ ASSET_URL=https://cdn.example.com
207
+ ```
208
+
209
+ The tags `vite()` writes, and `asset()`, use `app.asset_url`. A new app's `config/app.ts` doesn't have it, so add it:
210
+
211
+ ```ts title="config/app.ts"
212
+ import { env } from '@orieljs/framework'
213
+
214
+ export default {
215
+ // ...
216
+ asset_url: env('ASSET_URL'),
217
+ }
218
+ ```
219
+
220
+ ## Disabling Vite in tests
221
+
222
+ A test that renders a page needs the build's manifest, unless Vite is off. `withoutVite()` makes `vite()` and
223
+ `viteReactRefresh()` write nothing for the rest of the test. The `TestCase` of the starter kits with pages calls it
224
+ for every test:
225
+
226
+ ```ts title="tests/TestCase.ts"
227
+ import { TestCase as BaseTestCase } from '@orieljs/framework/testing'
228
+ import type { Application } from '@orieljs/framework'
229
+ import { afterEach, beforeEach } from 'vitest'
230
+ import { createApplication } from '../bootstrap/app'
231
+
232
+ export class TestCase extends BaseTestCase {
233
+ static override hooks = { beforeEach, afterEach }
234
+
235
+ override createApplication(): Promise<Application> {
236
+ return createApplication()
237
+ }
238
+
239
+ override async setUp(): Promise<void> {
240
+ await super.setUp()
241
+ this.withoutVite()
242
+ }
243
+ }
244
+ ```
245
+
246
+ ### Decorators in tests
247
+
248
+ Vitest transforms your TypeScript with Oxc, which leaves TC39 decorators, such as Live's `@On`, in place, and Node
249
+ can't run them yet. The `decorators()` plugin lowers them; a new app's `vitest.config.ts` has it:
250
+
251
+ ```ts title="vitest.config.ts"
252
+ import { decorators } from '@orieljs/vite'
253
+ import { defineConfig } from 'vitest/config'
254
+
255
+ export default defineConfig({
256
+ plugins: [decorators()],
257
+ })
258
+ ```
259
+
260
+ ## Server-side rendering (SSR)
261
+
262
+ `ssr` names the server entry of an Inertia app, and `vite build --ssr` builds it into `bootstrap/ssr`. While the dev
263
+ server runs, it renders the pages on the server itself. The Angular kit has no SSR. [Inertia
264
+ SSR](starter-kits.md#inertia-ssr) covers running the SSR server.
265
+
266
+ ## Script and style tag attributes
267
+
268
+ ### Content Security Policy (CSP) nonce
269
+
270
+ `vite().useCspNonce()` makes a nonce for the request, and the tags `vite()` writes carry it. Call it in a middleware,
271
+ and send the same nonce in your policy:
272
+
273
+ ```ts title="app/Http/Middleware/AddContentSecurityPolicyHeaders.ts"
274
+ import { vite } from '@orieljs/framework'
275
+ import type { HttpRequest, Middleware, Next } from '@orieljs/framework/contracts'
276
+
277
+ export class AddContentSecurityPolicyHeaders implements Middleware {
278
+ async handle(request: HttpRequest, next: Next): Promise<Response> {
279
+ const nonce = vite().useCspNonce()
280
+
281
+ const response = await next(request)
282
+
283
+ response.headers.set('Content-Security-Policy', `script-src 'nonce-${nonce}'`)
284
+
285
+ return response
286
+ }
287
+ }
288
+ ```
289
+
290
+ `vite().cspNonce()` gives the nonce, for your own inline scripts: `<script nonce={vite().cspNonce()}>`. The starter
291
+ kits' appearance script and welcome page use it. Each request has its own `vite()`, so the nonce stays in its request.
292
+
293
+ ### Subresource Integrity (SRI)
294
+
295
+ When the manifest gives each file an `integrity` hash, such as one a plugin like `vite-plugin-manifest-sri` adds, the
296
+ tags carry it. `vite().useIntegrityKey('hash')` reads another key, and `useIntegrityKey(false)` leaves it out.
297
+
298
+ ### Arbitrary attributes
299
+
300
+ `useScriptTagAttributes()` and `useStyleTagAttributes()` add attributes to the tags, as an object or a function of the
301
+ file:
302
+
303
+ ```ts
304
+ vite().useScriptTagAttributes({ 'data-turbo-track': 'reload', async: true })
305
+
306
+ vite().useStyleTagAttributes((src) => (src === 'resources/css/app.css' ? { 'data-theme': 'main' } : {}))
307
+ ```
308
+
309
+ A value of `true` writes a bare attribute, and `false` leaves the attribute out. `usePreloadTagAttributes(false)` drops
310
+ the preload tags.
311
+
312
+ ## Advanced customization
313
+
314
+ `vite()` also has `useHotFile()`, `useBuildDirectory()`, `useManifestFilename()` and `createAssetPathsUsing()`, for a
315
+ build that isn't in the usual place. Set them in a middleware, as the nonce is, or pass the build folder to `vite()`:
316
+ `vite(['resources/js/admin.ts'], 'admin-build')`.
317
+
318
+ ### Dev server CORS
319
+
320
+ Your pages, on your app's URL, load scripts from the dev server, on another port. The dev server lets your `APP_URL`,
321
+ `localhost` and any `.test` host load them. For another origin, set `server.cors` in `vite.config.ts`, as Vite's
322
+ documentation describes.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orieljs/framework",
3
- "version": "0.1.0-alpha.6",
3
+ "version": "0.1.0-alpha.7",
4
4
  "description": "Oriel: a Laravel-style, full-stack TypeScript framework for Node.js and Bun.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -38,8 +38,10 @@
38
38
  },
39
39
  "files": [
40
40
  "dist",
41
+ "docs",
41
42
  "LICENSE",
42
- "NOTICE"
43
+ "NOTICE",
44
+ "TRADEMARKS.md"
43
45
  ],
44
46
  "dependencies": {
45
47
  "@aws-sdk/client-s3": "3.1139.0",
@@ -56,35 +58,35 @@
56
58
  "pluralize": "8.0.0"
57
59
  },
58
60
  "devDependencies": {
59
- "@orieljs/auth": "0.1.0-alpha.6",
60
- "@orieljs/collections": "0.1.0-alpha.6",
61
- "@orieljs/bus": "0.1.0-alpha.6",
62
- "@orieljs/cache": "0.1.0-alpha.6",
63
- "@orieljs/config": "0.1.0-alpha.6",
64
- "@orieljs/console": "0.1.0-alpha.6",
65
- "@orieljs/contracts": "0.1.0-alpha.6",
66
- "@orieljs/container": "0.1.0-alpha.6",
67
- "@orieljs/cookie": "0.1.0-alpha.6",
68
- "@orieljs/encryption": "0.1.0-alpha.6",
69
- "@orieljs/database": "0.1.0-alpha.6",
70
- "@orieljs/events": "0.1.0-alpha.6",
71
- "@orieljs/foundation": "0.1.0-alpha.6",
72
- "@orieljs/filesystem": "0.1.0-alpha.6",
73
- "@orieljs/hashing": "0.1.0-alpha.6",
74
- "@orieljs/http": "0.1.0-alpha.6",
75
- "@orieljs/inertia": "0.1.0-alpha.6",
76
- "@orieljs/live": "0.1.0-alpha.6",
77
- "@orieljs/log": "0.1.0-alpha.6",
78
- "@orieljs/notifications": "0.1.0-alpha.6",
79
- "@orieljs/pipeline": "0.1.0-alpha.6",
80
- "@orieljs/mail": "0.1.0-alpha.6",
81
- "@orieljs/queue": "0.1.0-alpha.6",
82
- "@orieljs/session": "0.1.0-alpha.6",
83
- "@orieljs/routing": "0.1.0-alpha.6",
84
- "@orieljs/support": "0.1.0-alpha.6",
85
- "@orieljs/testing": "0.1.0-alpha.6",
86
- "@orieljs/validation": "0.1.0-alpha.6",
87
- "@orieljs/view": "0.1.0-alpha.6"
61
+ "@orieljs/auth": "0.1.0-alpha.7",
62
+ "@orieljs/bus": "0.1.0-alpha.7",
63
+ "@orieljs/collections": "0.1.0-alpha.7",
64
+ "@orieljs/console": "0.1.0-alpha.7",
65
+ "@orieljs/config": "0.1.0-alpha.7",
66
+ "@orieljs/cache": "0.1.0-alpha.7",
67
+ "@orieljs/container": "0.1.0-alpha.7",
68
+ "@orieljs/contracts": "0.1.0-alpha.7",
69
+ "@orieljs/cookie": "0.1.0-alpha.7",
70
+ "@orieljs/database": "0.1.0-alpha.7",
71
+ "@orieljs/events": "0.1.0-alpha.7",
72
+ "@orieljs/encryption": "0.1.0-alpha.7",
73
+ "@orieljs/filesystem": "0.1.0-alpha.7",
74
+ "@orieljs/http": "0.1.0-alpha.7",
75
+ "@orieljs/inertia": "0.1.0-alpha.7",
76
+ "@orieljs/live": "0.1.0-alpha.7",
77
+ "@orieljs/hashing": "0.1.0-alpha.7",
78
+ "@orieljs/mail": "0.1.0-alpha.7",
79
+ "@orieljs/foundation": "0.1.0-alpha.7",
80
+ "@orieljs/notifications": "0.1.0-alpha.7",
81
+ "@orieljs/log": "0.1.0-alpha.7",
82
+ "@orieljs/pipeline": "0.1.0-alpha.7",
83
+ "@orieljs/routing": "0.1.0-alpha.7",
84
+ "@orieljs/queue": "0.1.0-alpha.7",
85
+ "@orieljs/session": "0.1.0-alpha.7",
86
+ "@orieljs/testing": "0.1.0-alpha.7",
87
+ "@orieljs/support": "0.1.0-alpha.7",
88
+ "@orieljs/validation": "0.1.0-alpha.7",
89
+ "@orieljs/view": "0.1.0-alpha.7"
88
90
  },
89
91
  "peerDependencies": {
90
92
  "pg": "^8.23.0",
@@ -99,6 +101,6 @@
99
101
  }
100
102
  },
101
103
  "scripts": {
102
- "build": "tsup && node ../../../scripts/copy-license.mjs"
104
+ "build": "tsup && node ../../../scripts/copy-license.mjs && node ../../../scripts/copy-docs.mjs"
103
105
  }
104
106
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../Contracts/Container.ts","../../Contracts/Foundation.ts","../../Contracts/Config.ts","../../Contracts/Support.ts","../../Contracts/Pipeline.ts","../../Contracts/Http.ts","../../Contracts/Routing.ts","../../Contracts/Session.ts","../../Contracts/Cookie.ts","../../Contracts/Encryption.ts","../../Contracts/Hashing.ts","../../Contracts/View.ts","../../Contracts/Log.ts","../../Contracts/Database.ts","../../Contracts/Validation.ts","../../Contracts/Auth.ts","../../Contracts/Queue.ts","../../Contracts/Bus.ts","../../Contracts/Console.ts","../../Contracts/Mail.ts","../../Contracts/Notifications.ts","../../Contracts/Cache.ts","../../Contracts/Events.ts","../../Contracts/Filesystem.ts","../../Contracts/Inertia.ts","../../Contracts/Live.ts"],"sourcesContent":["/** A typed, runtime-unique key for container bindings. */\nexport interface Token<T> {\n readonly id: symbol\n readonly description: string\n /** Phantom field: only carries T at the type level. Never set at runtime. */\n readonly __type?: T\n}\n\nexport function token<T>(description: string): Token<T> {\n return Object.freeze({ id: Symbol.for(`oriel:${description}`), description })\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type Class<T> = abstract new (...args: any[]) => T\nexport type Abstract<T> = Token<T> | Class<T>\nexport type Factory<T> = (container: Container) => T\nexport type Concrete<T> = Factory<T> | (new () => T)\n\nexport interface Container {\n /** New instance on every make(). A class with no concrete binds to itself (constructed with no args). Root only; throws on a scope. */\n bind<T>(abstract: Abstract<T>, concrete?: Concrete<T>): void\n /** One instance for the life of this container and its scopes. Root only; throws on a scope. */\n singleton<T>(abstract: Abstract<T>, concrete?: Concrete<T>): void\n /** One instance per scope (e.g. per HTTP request or queue job). Root only; throws on a scope. */\n scoped<T>(abstract: Abstract<T>, concrete?: Concrete<T>): void\n /** Register an existing object as a shared instance. Returns it. On a scope it stays local to that scope. */\n instance<T>(abstract: Abstract<T>, instance: T): T\n /** Resolve. Unbound classes are constructed with `new Class()`. Unbound tokens throw BindingResolutionError. */\n make<T>(abstract: Abstract<T>): T\n bound(abstract: Abstract<unknown>): boolean\n resolved(abstract: Abstract<unknown>): boolean\n /** Decorate or replace an instance each time it's resolved (applied before resolving callbacks). Root only; throws on a scope. */\n extend<T>(abstract: Abstract<T>, extender: (instance: T, container: Container) => T): void\n /** Called after each resolution of the abstract. Root only; throws on a scope. */\n resolving<T>(abstract: Abstract<T>, callback: (instance: T, container: Container) => void): void\n forgetInstance(abstract: Abstract<unknown>): void\n /** A child container: shares bindings and singletons with its parent, and has its own scoped instances. Bindings can't be registered on it. */\n createScope(): Container\n /** Run fn with this container as the \"current\" one for inject(), helpers and facades (AsyncLocalStorage). */\n run<R>(fn: () => R): R\n}\nexport const Container = token<Container>('Container.Container')\n","import { token, type Container } from './Container'\nimport type { HttpRequest } from './Http'\n\nexport interface ServiceProvider {\n /** Bind things into the container. Synchronous. Don't resolve other services here. */\n register?(): void\n /** Runs after every provider is registered. May be async (e.g. importing route files). */\n boot?(): void | Promise<void>\n}\nexport type ServiceProviderClass = new (app: Application) => ServiceProvider\n\nexport interface Application extends Container {\n readonly version: string\n basePath(path?: string): string\n appPath(path?: string): string\n bootstrapPath(path?: string): string\n configPath(path?: string): string\n databasePath(path?: string): string\n publicPath(path?: string): string\n resourcePath(path?: string): string\n storagePath(path?: string): string\n /** With no args returns the environment name. With args returns whether it matches any of them. */\n environment(): string\n environment(...environments: string[]): boolean\n isProduction(): boolean\n isLocal(): boolean\n runningInConsole(): boolean\n /** Mark the app as running in the console (the CLI entry point calls this). Defaults to true. */\n setRunningInConsole(value?: boolean): void\n runningUnitTests(): boolean\n /** Registers the provider. If the app is already booted, the provider is booted immediately. */\n register(provider: ServiceProvider | ServiceProviderClass): Promise<ServiceProvider>\n getProviders(): ServiceProvider[]\n boot(): Promise<void>\n isBooted(): boolean\n booting(callback: (app: Application) => void | Promise<void>): void\n booted(callback: (app: Application) => void | Promise<void>): void\n /** Handle one HTTP request in a fresh request scope via the bound HttpKernel. */\n handle(request: Request): Promise<Response>\n /** Register a callback that terminate() runs, in registration order. */\n terminating(callback: () => void | Promise<void>): void\n terminate(): Promise<void>\n}\nexport const Application = token<Application>('Foundation.Application')\n\nexport interface ExceptionHandler {\n report(error: unknown): Promise<void>\n shouldReport(error: unknown): boolean\n /** `request` is the scoped HttpRequest (Contracts/Http) when available, else the raw Request. */\n render(request: unknown, error: unknown): Promise<Response>\n}\nexport const ExceptionHandler = token<ExceptionHandler>('Foundation.ExceptionHandler')\n\n/** Paths passed to Application.configure().withRouting(). Routing (Wave 1) loads them. */\nexport interface RoutingPaths {\n /** One route file or several, loaded in order (Laravel's `withRouting(web: [...])`). */\n web?: string | string[]\n api?: string | string[]\n console?: string\n health?: string\n apiPrefix: string\n}\nexport const RoutingPaths = token<RoutingPaths>('Foundation.RoutingPaths')\n\n/** The object passed to Application.configure().withExceptions(e => …), like Laravel's Exceptions class. */\nexport interface ExceptionsConfigurator {\n /** Custom reporting. Return false to stop the default logging. */\n report(callback: (error: unknown) => void | boolean | Promise<void | boolean>): this\n /** Custom rendering. Return undefined to fall through to the default rendering. */\n render(callback: (error: unknown, request: unknown) => Response | undefined | Promise<Response | undefined>): this\n /** Never report errors of these classes. */\n dontReport(...classes: Array<abstract new (...args: never[]) => Error>): this\n /** Render errors as JSON when the callback returns true, whatever the Accept header. */\n shouldRenderJsonWhen(callback: (request: HttpRequest, error: unknown) => boolean): this\n}\n\n/** Callbacks collected by withMiddleware()/withExceptions(); invoked by Http / the exception handler (Wave 1). */\nexport type ConfigCallbacks<T> = Array<(configurator: T) => void>\n/** Typed as unknown here because MiddlewareConfigurator lives in Contracts/Http; Http casts on use. */\nexport const MiddlewareCallbacks = token<ConfigCallbacks<unknown>>('Foundation.MiddlewareCallbacks')\nexport const ExceptionCallbacks = token<ConfigCallbacks<ExceptionsConfigurator>>('Foundation.ExceptionCallbacks')\n","import { token } from './Container'\n\nexport interface ConfigRepository {\n has(key: string): boolean\n /** Dot notation: get('database.connections.sqlite.database'). */\n get<T = unknown>(key: string, defaultValue?: T): T\n set(key: string, value: unknown): void\n set(values: Record<string, unknown>): void\n push(key: string, value: unknown): void\n all(): Record<string, unknown>\n}\nexport const ConfigRepository = token<ConfigRepository>('Config.Repository')\n","import { token, type Class } from './Container'\n\nexport interface Arrayable<T = unknown> {\n toArray(): T\n}\nexport interface Jsonable {\n toJson(): string\n}\nexport interface Htmlable {\n toHtml(): string\n}\n/** Anything a controller can return that knows how to become a Response. */\nexport interface Responsable {\n toResponse(request: unknown): Response | Promise<Response>\n}\n/** The minimal collection surface contracts rely on (implemented by @orieljs/collections). */\nexport interface Enumerable<T> extends Iterable<T>, Arrayable<unknown[]> {\n all(): T[]\n count(): number\n isEmpty(): boolean\n}\n\nexport interface ClassRegistry {\n /** Registers under `name` (default: cls.name). Throws if the name is already taken by a different class. */\n register(cls: Class<unknown>, name?: string): string\n nameOf(cls: Class<unknown>): string | undefined\n resolve<T = unknown>(name: string): Class<T>\n has(name: string): boolean\n}\nexport const ClassRegistry = token<ClassRegistry>('Support.ClassRegistry')\n","import { token, type Class } from './Container'\n\nexport type PipeNext<T> = (passable: T) => Promise<unknown>\nexport type PipeClosure<T> = (passable: T, next: PipeNext<T>) => Promise<unknown> | unknown\n/** A class resolved from the container whose `via` method (default 'handle') is called; or a string alias 'name:param1,param2'. */\nexport type Pipe<T> = PipeClosure<T> | Class<object> | string\n\nexport interface Pipeline<T = unknown> {\n send(passable: T): this\n through(pipes: ReadonlyArray<Pipe<T>>): this\n pipe(...pipes: Array<Pipe<T>>): this\n /** Method called on class pipes. Default 'handle'. */\n via(method: string): this\n then<R>(destination: (passable: T) => R | Promise<R>): Promise<R>\n thenReturn(): Promise<T>\n}\n\nexport interface PipelineFactory {\n make<T>(): Pipeline<T>\n}\nexport const PipelineFactory = token<PipelineFactory>('Pipeline.Factory')\n","import { token } from './Container'\nimport type { Session } from './Session'\nimport type { Rules } from './Validation'\n\n/** Web-standard body/headers init types, derived from the runtime's global Response/Headers (no DOM lib needed). */\nexport type BodyInit = ConstructorParameters<typeof Response>[0]\nexport type HeadersInit = ConstructorParameters<typeof Headers>[0]\n\nexport interface UploadedFile {\n readonly clientName: string\n readonly mimeType: string\n readonly size: number\n extension(): string\n arrayBuffer(): Promise<ArrayBuffer>\n /** Stores on a Filesystem disk. Returns the stored path. */\n store(directory: string, disk?: string): Promise<string>\n storeAs(directory: string, name: string, disk?: string): Promise<string>\n}\n\n/**\n * Oriel's request wrapper (one per request, scoped).\n * The Http kernel awaits `load()` before any middleware runs, so every input accessor below is synchronous.\n */\nexport interface HttpRequest {\n readonly raw: Request\n load(): Promise<this>\n method(): string\n isMethod(method: string): boolean\n url(): string\n fullUrl(): string\n path(): string\n is(...patterns: string[]): boolean\n routeIs(...names: string[]): boolean\n header(name: string): string | undefined\n header(name: string, defaultValue: string): string\n bearerToken(): string | undefined\n ip(): string | undefined\n /** The raw body as text (Laravel's getContent()); '' when there is none. */\n content(): string\n expectsJson(): boolean\n ajax(): boolean\n query<T = unknown>(key?: string, defaultValue?: T): T\n input<T = unknown>(key?: string, defaultValue?: T): T\n all(): Record<string, unknown>\n only(...keys: string[]): Record<string, unknown>\n except(...keys: string[]): Record<string, unknown>\n has(...keys: string[]): boolean\n filled(key: string): boolean\n boolean(key: string, defaultValue?: boolean): boolean\n integer(key: string, defaultValue?: number): number\n merge(values: Record<string, unknown>): this\n file(key: string): UploadedFile | undefined\n cookie(name: string): string | undefined\n /** Replace the parsed request cookies (EncryptCookies calls this after decrypting). */\n setCookies(cookies: Record<string, string>): void\n /** Route parameter (after model binding), or every parameter when called with no key. */\n route<T = unknown>(key?: string): T\n session(): Session\n /** The user resolved earlier by auth middleware. Undefined for guests. Use `await Auth.user()` to resolve lazily. */\n user<T = unknown>(guard?: string): T | undefined\n setUserResolver(resolver: (guard?: string) => unknown): void\n /** Validates this request's input via the ValidationFactory; throws a Validation OrielError (422) on failure. */\n validate<T = Record<string, unknown>>(\n rules: Rules,\n messages?: Record<string, string>,\n attributes?: Record<string, string>,\n ): Promise<T>\n}\nexport const HttpRequest = token<HttpRequest>('Http.Request')\n\nexport type Next = (request: HttpRequest) => Promise<Response>\nexport interface Middleware {\n handle(request: HttpRequest, next: Next, ...parameters: string[]): Promise<Response>\n terminate?(request: HttpRequest, response: Response): Promise<void>\n}\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type MiddlewareClass = new (...args: any[]) => Middleware\n\n/** The object passed to Application.configure().withMiddleware(m => …), like Laravel's Middleware class. */\nexport interface MiddlewareConfigurator {\n append(...middleware: MiddlewareClass[]): this\n prepend(...middleware: MiddlewareClass[]): this\n web(options: { append?: MiddlewareClass[]; prepend?: MiddlewareClass[]; remove?: MiddlewareClass[] }): this\n api(options: { append?: MiddlewareClass[]; prepend?: MiddlewareClass[]; remove?: MiddlewareClass[] }): this\n alias(aliases: Record<string, MiddlewareClass>): this\n group(name: string, middleware: Array<MiddlewareClass | string>): this\n validateCsrfTokens(options: { except: string[] }): this\n redirectGuestsTo(url: string | ((request: HttpRequest) => string)): this\n}\n\nexport interface HttpKernel {\n handle(request: Request): Promise<Response>\n terminate?(request: Request, response: Response): Promise<void>\n}\nexport const HttpKernel = token<HttpKernel>('Http.Kernel')\n\nexport interface ResponseFactory {\n make(content?: BodyInit | null, status?: number, headers?: HeadersInit): Response\n json(data: unknown, status?: number, headers?: HeadersInit): Response\n noContent(status?: number): Response\n download(path: string, name?: string, headers?: HeadersInit): Promise<Response>\n stream(body: ReadableStream, status?: number, headers?: HeadersInit): Response\n}\nexport const ResponseFactory = token<ResponseFactory>('Http.ResponseFactory')\n","import { token, type Class } from './Container'\nimport type { Responsable } from './Support'\nimport type { HttpRequest, Middleware, MiddlewareClass } from './Http'\n\n/** Public method names of a controller (excludes non-function members). */\nexport type ActionMethods<C> = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in keyof C]: C[K] extends (...args: any[]) => unknown ? K : never\n}[keyof C] &\n string\n\nexport type ControllerAction<C> = readonly [Class<C>, ActionMethods<C>]\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type RouteClosure = (...args: any[]) => unknown\n/** A class with __invoke(): Route.get('/counter', Counter) (single-action controllers, full-page Live components). */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type InvokableClass = Class<{ __invoke(...args: any[]): unknown }>\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type RouteAction = RouteClosure | ControllerAction<any> | InvokableClass\nexport type MiddlewareReference = string | MiddlewareClass\n\nexport interface Route {\n readonly methods: readonly string[]\n readonly uri: string\n getName(): string | undefined\n name(name: string): this\n middleware(...middleware: Array<MiddlewareReference | readonly MiddlewareReference[]>): this\n withoutMiddleware(...middleware: MiddlewareReference[]): this\n where(parameter: string, pattern: string): this\n where(patterns: Record<string, string>): this\n}\n\nexport interface RouteRegistrar {\n prefix(prefix: string): RouteRegistrar\n name(prefix: string): RouteRegistrar\n middleware(...middleware: Array<MiddlewareReference | readonly MiddlewareReference[]>): RouteRegistrar\n controller(controller: Class<unknown>): RouteRegistrar\n group(routes: () => void | Promise<void>): Promise<void>\n}\n\nexport interface ResourceOptions {\n only?: string[]\n except?: string[]\n parameters?: Record<string, string>\n names?: Record<string, string>\n}\n\nexport interface Router {\n get<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): Route\n post<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): Route\n put<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): Route\n patch<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): Route\n delete<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): Route\n options<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): Route\n any<C>(uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): Route\n match<C>(methods: string[], uri: string, action: ControllerAction<C> | RouteClosure | InvokableClass | string): Route\n redirect(from: string, to: string, status?: number): Route\n view(uri: string, view: string, data?: Record<string, unknown>): Route\n /** Route.inertia('/about', 'About', props): a GET route that renders an Inertia page (Laravel's Route::inertia). */\n inertia(uri: string, component: string, props?: Record<string, unknown>): Route\n resource(name: string, controller: Class<unknown>, options?: ResourceOptions): void\n apiResource(name: string, controller: Class<unknown>, options?: ResourceOptions): void\n fallback(action: RouteAction): Route\n prefix(prefix: string): RouteRegistrar\n name(prefix: string): RouteRegistrar\n middleware(...middleware: Array<MiddlewareReference | readonly MiddlewareReference[]>): RouteRegistrar\n controller(controller: Class<unknown>): RouteRegistrar\n /** Explicit model binding: Route.model('author', User). */\n model(parameter: string, model: Class<unknown>): void\n /** Custom binding resolver. */\n bind(parameter: string, resolver: (value: string) => unknown | Promise<unknown>): void\n pattern(parameter: string, pattern: string): void\n /** Name a middleware class, e.g. aliasMiddleware('auth', Authenticate). */\n aliasMiddleware(name: string, middleware: MiddlewareClass): this\n /** Define (or replace) a middleware group such as 'web' or 'api'. */\n middlewareGroup(name: string, middleware: MiddlewareReference[]): this\n /** Append to a group unless it is already present. */\n pushMiddlewareToGroup(group: string, middleware: MiddlewareReference): this\n getMiddlewareGroups(): Record<string, MiddlewareReference[]>\n getRoutes(): readonly Route[]\n current(): Route | undefined\n /** Match the request, bind parameters, run the route middleware and the action. Called by the Http kernel. */\n dispatch(request: HttpRequest): Promise<Response>\n}\n\n/** The route matched for the current request (scope-local; set by the router before route middleware runs). */\nexport interface CurrentRoute {\n readonly route: Route\n /** Route parameters after model binding, in URI order. */\n readonly parameters: Record<string, unknown>\n /** Resolved route middleware instances, for HttpKernel.terminate(). */\n readonly middleware: Middleware[]\n}\nexport const CurrentRoute = token<CurrentRoute>('Routing.CurrentRoute')\nexport const Router = token<Router>('Routing.Router')\n\n/**\n * Resolves implicit route-model bindings by naming convention ({post} → Post).\n * Bound by Database (Wave 1) so that Routing never imports Database.\n * Returns undefined when no model matches the parameter name. Throws ModelNotFound when the model exists but the row doesn't.\n */\nexport interface RouteModelResolver {\n resolve(parameter: string, value: string, field?: string): Promise<unknown | undefined>\n resolveExplicit(model: Class<unknown>, value: string, field?: string): Promise<unknown>\n}\nexport const RouteModelResolver = token<RouteModelResolver>('Routing.ModelResolver')\n\n/**\n * Route name → parameters, for the typed route() and redirect().route() helpers. Empty until `oriel route:types`\n * augments it (types/routes.d.ts); while it is empty any string is accepted. The contracts themselves keep taking\n * strings: the framework builds route names at run time.\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface RouteList {}\n\n/** A route name: the generated ones, or any string before `oriel route:types` has run. */\nexport type RouteName = [keyof RouteList] extends [never] ? string : Extract<keyof RouteList, string>\n\nexport interface UrlGenerator {\n to(path: string, query?: Record<string, unknown>, absolute?: boolean): string\n route(name: string, parameters?: unknown, absolute?: boolean): string\n asset(path: string): string\n current(): string\n previous(fallback?: string): string\n hasRoute(name: string): boolean\n /** A URL to a named route with a `signature` query (HMAC-SHA256 keyed by APP_KEY); `expiration` adds `expires`. */\n signedRoute(name: string, parameters?: unknown, expiration?: Date | number, absolute?: boolean): string\n /** signedRoute() that expires: a Date, or seconds from now. */\n temporarySignedRoute(name: string, expiration: Date | number, parameters?: unknown, absolute?: boolean): string\n /** Whether the request URL carries a valid, unexpired signature (`absolute: false` signs the path only). */\n hasValidSignature(request: HttpRequest, absolute?: boolean): boolean\n}\nexport const UrlGenerator = token<UrlGenerator>('Routing.UrlGenerator')\n\nexport interface RedirectResponse extends Responsable {\n readonly targetUrl: string\n with(key: string | Record<string, unknown>, value?: unknown): this\n withErrors(errors: Record<string, string | string[]>, bag?: string): this\n withInput(input?: Record<string, unknown>): this\n withCookie(name: string, value: string, minutes?: number): this\n}\n\nexport interface Redirector {\n to(path: string, status?: number): RedirectResponse\n route(name: string, parameters?: unknown, status?: number): RedirectResponse\n back(fallback?: string, status?: number): RedirectResponse\n intended(fallback?: string): RedirectResponse\n away(url: string, status?: number): RedirectResponse\n}\nexport const Redirector = token<Redirector>('Routing.Redirector')\n","import { token } from './Container'\n\n/** The session of the current request (scoped). Loaded and saved by the StartSession middleware. */\nexport interface Session {\n getId(): string\n start(): Promise<void>\n save(): Promise<void>\n all(): Record<string, unknown>\n has(key: string): boolean\n get<T = unknown>(key: string, defaultValue?: T): T\n put(key: string | Record<string, unknown>, value?: unknown): void\n push(key: string, value: unknown): void\n pull<T = unknown>(key: string, defaultValue?: T): T\n forget(...keys: string[]): void\n flush(): void\n flash(key: string, value: unknown): void\n now(key: string, value: unknown): void\n reflash(): void\n keep(...keys: string[]): void\n getOldInput<T = unknown>(key?: string, defaultValue?: T): T\n flashInput(input: Record<string, unknown>): void\n token(): string\n regenerateToken(): void\n regenerate(destroy?: boolean): Promise<void>\n invalidate(): Promise<void>\n previousUrl(): string | undefined\n setPreviousUrl(url: string): void\n}\nexport const Session = token<Session>('Session.Store')\n\n/** Storage driver (file, cookie, database, redis). */\nexport interface SessionHandler {\n read(id: string): Promise<string>\n write(id: string, data: string): Promise<void>\n destroy(id: string): Promise<void>\n gc(maxLifetimeSeconds: number): Promise<void>\n}\n","import { token } from './Container'\n\nexport interface Cookie {\n name: string\n value: string\n /** Minutes until expiry. 0 = session cookie, negative = delete. */\n minutes: number\n path: string\n domain?: string\n secure: boolean\n httpOnly: boolean\n sameSite: 'lax' | 'strict' | 'none'\n}\n\nexport interface CookieJar {\n make(name: string, value: string, minutes?: number, options?: Partial<Omit<Cookie, 'name' | 'value' | 'minutes'>>): Cookie\n forever(name: string, value: string): Cookie\n forget(name: string): Cookie\n /** Queue a cookie to attach to the outgoing response (scoped per request). */\n queue(cookie: Cookie): void\n queued(): Cookie[]\n}\nexport const CookieJar = token<CookieJar>('Cookie.Jar')\n","import { token } from './Container'\n\nexport interface Encrypter {\n /** JSON-serializes unless serialize=false (then value must be a string). AES-256-GCM, keyed by APP_KEY. */\n encrypt(value: unknown, serialize?: boolean): string\n decrypt<T = unknown>(payload: string, unserialize?: boolean): T\n encryptString(value: string): string\n decryptString(payload: string): string\n getKey(): Uint8Array\n}\nexport const Encrypter = token<Encrypter>('Encryption.Encrypter')\n","import { token } from './Container'\n\nexport interface Hasher {\n make(value: string): Promise<string>\n check(value: string, hashed: string): Promise<boolean>\n needsRehash(hashed: string): boolean\n info(hashed: string): { algorithm: string; options: Record<string, unknown> }\n}\nexport const Hasher = token<Hasher>('Hashing.Hasher')\n","import { token } from './Container'\nimport type { Htmlable } from './Support'\n\nexport interface View extends Htmlable {\n readonly name: string\n with(key: string | Record<string, unknown>, value?: unknown): this\n render(): Promise<string>\n}\n\n/** Resolves 'posts.index' → resources/views/posts/index.tsx and renders it to HTML on the server. */\nexport interface ViewFactory {\n make(name: string, data?: Record<string, unknown>): View\n exists(name: string): boolean\n share(key: string | Record<string, unknown>, value?: unknown): void\n composer(views: string | string[], composer: (view: View) => void | Promise<void>): void\n /** Renders TSX (an element, a string, an Htmlable, a View, promises of them) to HTML, like Blade::render(). */\n renderToString(node: unknown): Promise<string>\n}\nexport const ViewFactory = token<ViewFactory>('View.Factory')\n","import { token } from './Container'\n\nexport type LogLevel = 'emergency' | 'alert' | 'critical' | 'error' | 'warning' | 'notice' | 'info' | 'debug'\n\nexport interface Logger {\n log(level: LogLevel, message: string, context?: Record<string, unknown>): void\n emergency(message: string, context?: Record<string, unknown>): void\n alert(message: string, context?: Record<string, unknown>): void\n critical(message: string, context?: Record<string, unknown>): void\n error(message: string, context?: Record<string, unknown>): void\n warning(message: string, context?: Record<string, unknown>): void\n notice(message: string, context?: Record<string, unknown>): void\n info(message: string, context?: Record<string, unknown>): void\n debug(message: string, context?: Record<string, unknown>): void\n /** Adds context to every later log entry in the current scope (request or job). */\n withContext(context: Record<string, unknown>): this\n}\n\nexport interface LogManager extends Logger {\n channel(name?: string): Logger\n stack(channels: string[]): Logger\n}\nexport const LogManager = token<LogManager>('Log.Manager')\n","import { token } from './Container'\nimport type { Enumerable } from './Support'\n\nexport type Operator = '=' | '!=' | '<>' | '<' | '<=' | '>' | '>=' | 'like' | 'not like' | 'ilike' | 'in' | 'not in'\nexport type Row = Record<string, unknown>\n\n/** The minimal query surface other components rely on (Queue, Cache, Session, Validation, Notifications). */\nexport interface QueryBuilder<T = Row> {\n select(...columns: string[]): this\n where(column: string, value: unknown): this\n where(column: string, operator: Operator, value: unknown): this\n where(conditions: Row): this\n orWhere(column: string, value: unknown): this\n orWhere(column: string, operator: Operator, value: unknown): this\n whereIn(column: string, values: readonly unknown[]): this\n whereNotIn(column: string, values: readonly unknown[]): this\n whereNull(column: string): this\n whereNotNull(column: string): this\n orderBy(column: string, direction?: 'asc' | 'desc'): this\n limit(count: number): this\n offset(count: number): this\n lockForUpdate(): this\n get(): Promise<Enumerable<T>>\n first(): Promise<T | undefined>\n find(id: unknown): Promise<T | undefined>\n value<V = unknown>(column: string): Promise<V | undefined>\n pluck<V = unknown>(column: string): Promise<Enumerable<V>>\n count(): Promise<number>\n exists(): Promise<boolean>\n insert(values: Row | Row[]): Promise<void>\n /**\n * Inserts rows, skipping any that violate a unique key instead of failing (Laravel's insertOrIgnore). Returns the\n * number of rows inserted. Nothing is thrown for a duplicate, so a caller's transaction stays usable on Postgres.\n */\n insertOrIgnore(values: Row | Row[]): Promise<number>\n insertGetId(values: Row, keyName?: string): Promise<number | string>\n update(values: Row): Promise<number>\n upsert(values: Row | Row[], uniqueBy: string[], update?: string[]): Promise<number>\n increment(column: string, amount?: number, extra?: Row): Promise<number>\n decrement(column: string, amount?: number, extra?: Row): Promise<number>\n delete(): Promise<number>\n}\n\nexport type DriverName = 'pgsql' | 'mysql' | 'sqlite'\n\nexport interface DatabaseConnection {\n getName(): string\n getDriverName(): DriverName\n table<T = Row>(table: string): QueryBuilder<T>\n select<T = Row>(sql: string, bindings?: readonly unknown[]): Promise<T[]>\n statement(sql: string, bindings?: readonly unknown[]): Promise<void>\n /** Nested calls use savepoints. Rolls back if fn throws. */\n transaction<R>(fn: (connection: DatabaseConnection) => Promise<R>): Promise<R>\n /**\n * Start a transaction that stays open, for every caller of this connection, until commit()/rollBack().\n * Nested calls use savepoints. Meant for test isolation (RefreshDatabase); app code uses transaction(fn).\n */\n beginTransaction(): Promise<void>\n commit(): Promise<void>\n /** Rolls back the innermost level opened by beginTransaction(). Does nothing when none is open. */\n rollBack(): Promise<void>\n /** 0 outside a transaction. */\n transactionLevel(): number\n}\n\nexport interface DatabaseManager extends DatabaseConnection {\n connection(name?: string): DatabaseConnection\n disconnect(name?: string): Promise<void>\n}\nexport const DatabaseManager = token<DatabaseManager>('Database.Manager')\n\n/** What non-Database components may rely on from a model instance. */\nexport interface ModelInstance {\n exists: boolean\n getKey(): unknown\n getKeyName(): string\n getTable(): string\n getRouteKey(): unknown\n getRouteKeyName(): string\n /** The value stored in a polymorphic `*_type` column for this model: its morph map alias, else its class name. */\n getMorphClass(): string\n getAttribute<T = unknown>(key: string): T\n setAttribute(key: string, value: unknown): this\n fill(attributes: Row): this\n save(): Promise<boolean>\n delete(): Promise<boolean>\n refresh(): Promise<this>\n toArray(): Row\n toJSON(): Row\n}\n\nexport interface ModelStatic<M extends ModelInstance = ModelInstance> {\n new (): M\n query(): QueryBuilder<M>\n find(id: unknown): Promise<M | undefined>\n findOrFail(id: unknown): Promise<M>\n}\n\n/**\n * What decides a paginator's page and the path of its links when the request doesn't (Laravel's\n * Paginator::currentPageResolver and currentPathResolver, which Livewire's WithPagination replaces). Live binds one for\n * the application, which answers while a WithPagination component mounts, runs an update's hooks and actions, or\n * renders. Unbound, or `undefined` from a method, the paginators read the request (`?page=` and its URL).\n */\nexport interface PaginationState {\n /** The page to show for `pageName` ('page' by default). */\n currentPage(pageName: string): number | undefined\n /** The base path of the page links. */\n currentPath(): string | undefined\n}\nexport const PaginationState = token<PaginationState>('Database.PaginationState')\n","import { token } from './Container'\n\n/** A rule object (Laravel's ValidationRule). Call fail() to reject the value. */\nexport interface ValidationRule {\n validate(\n attribute: string,\n value: unknown,\n fail: (message: string) => void,\n data: Record<string, unknown>,\n ): void | Promise<void>\n}\n\n/** 'required|string|max:255', or an array mixing strings and rule objects. Keys support dot + `*` wildcards. */\nexport type Rules = Record<string, string | ReadonlyArray<string | ValidationRule>>\n\nexport interface MessageBag {\n has(key: string): boolean\n first(key?: string): string | undefined\n get(key: string): string[]\n all(): string[]\n isEmpty(): boolean\n count(): number\n toObject(): Record<string, string[]>\n}\n\nexport interface Validator {\n passes(): Promise<boolean>\n fails(): Promise<boolean>\n /** Only the keys that have rules. Throws ValidationError (Exceptions.ts) on failure. */\n validated<T = Record<string, unknown>>(): Promise<T>\n /** Valid only after passes()/fails()/validated() has run. */\n errors(): MessageBag\n after(callback: (validator: Validator) => void | Promise<void>): this\n}\n\nexport type RuleCallback = (\n attribute: string,\n value: unknown,\n parameters: string[],\n data: Record<string, unknown>,\n) => boolean | Promise<boolean>\n\nexport interface ValidationFactory {\n make(\n data: Record<string, unknown>,\n rules: Rules,\n messages?: Record<string, string>,\n attributes?: Record<string, string>,\n ): Validator\n /** Registers a string rule, e.g. extend('uppercase', fn, ':attribute must be uppercase'). */\n extend(name: string, callback: RuleCallback, message?: string): void\n}\nexport const ValidationFactory = token<ValidationFactory>('Validation.Factory')\n","import { token, type Class } from './Container'\n\nexport interface Authenticatable {\n getAuthIdentifierName(): string\n getAuthIdentifier(): unknown\n getAuthPassword(): string\n getRememberToken(): string | undefined\n setRememberToken(value: string): void\n getRememberTokenName(): string\n}\n\nexport type Credentials = Record<string, unknown>\n\nexport interface UserProvider {\n retrieveById(id: unknown): Promise<Authenticatable | undefined>\n retrieveByToken(id: unknown, token: string): Promise<Authenticatable | undefined>\n updateRememberToken(user: Authenticatable, token: string): Promise<void>\n retrieveByCredentials(credentials: Credentials): Promise<Authenticatable | undefined>\n validateCredentials(user: Authenticatable, credentials: Credentials): Promise<boolean>\n}\n\nexport interface Guard {\n check(): Promise<boolean>\n guest(): Promise<boolean>\n user<T extends Authenticatable = Authenticatable>(): Promise<T | undefined>\n id(): Promise<unknown>\n validate(credentials: Credentials): Promise<boolean>\n hasUser(): boolean\n setUser(user: Authenticatable): void\n}\n\nexport interface StatefulGuard extends Guard {\n attempt(credentials: Credentials, remember?: boolean): Promise<boolean>\n once(credentials: Credentials): Promise<boolean>\n login(user: Authenticatable, remember?: boolean): Promise<void>\n loginUsingId(id: unknown, remember?: boolean): Promise<Authenticatable | false>\n logout(): Promise<void>\n}\n\nexport interface AuthFactory {\n guard(name?: string): StatefulGuard | Guard\n shouldUse(name: string): void\n extend(driver: string, factory: (name: string, config: Record<string, unknown>) => Guard): void\n provider(driver: string, factory: (config: Record<string, unknown>) => UserProvider): void\n}\nexport const AuthFactory = token<AuthFactory>('Auth.Factory')\n\nexport type AbilityCallback = (user: Authenticatable | undefined, ...args: unknown[]) => boolean | Promise<boolean>\n\nexport interface Gate {\n define(ability: string, callback: AbilityCallback): this\n policy(model: Class<unknown>, policy: Class<unknown>): this\n before(callback: (user: Authenticatable | undefined, ability: string) => boolean | undefined | Promise<boolean | undefined>): this\n allows(ability: string, ...args: unknown[]): Promise<boolean>\n denies(ability: string, ...args: unknown[]): Promise<boolean>\n /** Throws an Authorization OrielError (403) when denied. */\n authorize(ability: string, ...args: unknown[]): Promise<void>\n any(abilities: string[], ...args: unknown[]): Promise<boolean>\n forUser(user: Authenticatable | undefined): Gate\n}\nexport const Gate = token<Gate>('Auth.Gate')\n\nexport type PasswordStatus = 'passwords.sent' | 'passwords.reset' | 'passwords.user' | 'passwords.token' | 'passwords.throttled'\n\nexport interface PasswordBroker {\n sendResetLink(credentials: Credentials): Promise<PasswordStatus>\n reset(credentials: Credentials, callback: (user: Authenticatable, password: string) => Promise<void>): Promise<PasswordStatus>\n}\nexport const PasswordBroker = token<PasswordBroker>('Auth.PasswordBroker')\n\nexport interface MustVerifyEmail {\n hasVerifiedEmail(): boolean\n markEmailAsVerified(): Promise<boolean>\n sendEmailVerificationNotification(): Promise<void>\n getEmailForVerification(): string\n}\n","import { token } from './Container'\n\n/** Options a job class may declare as public fields. Their presence (or implementing ShouldQueue) makes things queueable. */\nexport interface ShouldQueue {\n /**\n * Marks the class as queued at run time: `implements ShouldQueue` leaves no trace once compiled, so the interface\n * asks for `readonly shouldQueue = true`. Jobs, listeners, mailables and notifications carrying it are queued.\n */\n readonly shouldQueue: true\n connection?: string\n queue?: string\n /** Seconds. */\n delay?: number\n tries?: number\n /** Seconds, or a per-attempt list. */\n backoff?: number | number[]\n /** Seconds. */\n timeout?: number\n uniqueId?(): string\n}\n\n/** A job: public fields are its serialized data; handle() runs on the worker (inject() works inside it). */\nexport interface Job extends Partial<ShouldQueue> {\n handle(): unknown | Promise<unknown>\n failed?(error: unknown): void | Promise<void>\n}\n\nexport interface QueuePayload {\n uuid: string\n /** ClassRegistry name. */\n job: string\n displayName: string\n data: Record<string, unknown>\n attempts: number\n maxTries?: number\n backoff?: number[]\n timeout?: number\n /** Unix ms. */\n pushedAt: number\n batchId?: string\n chain?: QueuePayload[]\n /** Unix ms after which the job fails instead of retrying. */\n retryUntil?: number\n /** Mark the job failed (instead of releasing it) when it times out. */\n failOnTimeout?: boolean\n}\n\nexport interface QueueJob {\n getJobId(): string\n getQueue(): string\n payload(): QueuePayload\n attempts(): number\n delete(): Promise<void>\n release(delaySeconds?: number): Promise<void>\n /** Marks as failed: stores it via FailedJobProvider and calls job.failed(). */\n fail(error: unknown): Promise<void>\n isDeleted(): boolean\n isReleased(): boolean\n}\n\nexport interface Queue {\n push(job: Job, queue?: string): Promise<string>\n later(delaySeconds: number, job: Job, queue?: string): Promise<string>\n pushRaw(payload: QueuePayload, queue?: string, delaySeconds?: number): Promise<string>\n pop(queue?: string): Promise<QueueJob | undefined>\n size(queue?: string): Promise<number>\n clear(queue?: string): Promise<number>\n}\n\nexport interface QueueManager extends Queue {\n connection(name?: string): Queue\n extend(driver: string, factory: (config: Record<string, unknown>) => Queue): void\n}\nexport const QueueManager = token<QueueManager>('Queue.Manager')\n\nexport interface FailedJob {\n id: string\n connection: string\n queue: string\n payload: QueuePayload\n exception: string\n failedAt: Date\n}\n\nexport interface FailedJobProvider {\n log(connection: string, queue: string, payload: QueuePayload, error: unknown): Promise<string>\n all(): Promise<FailedJob[]>\n find(id: string): Promise<FailedJob | undefined>\n forget(id: string): Promise<boolean>\n flush(): Promise<void>\n}\nexport const FailedJobProvider = token<FailedJobProvider>('Queue.FailedJobProvider')\n","import { token } from './Container'\nimport type { Job } from './Queue'\n\nexport interface Batch {\n readonly id: string\n readonly name: string\n readonly totalJobs: number\n readonly pendingJobs: number\n readonly failedJobs: number\n progress(): number\n finished(): boolean\n cancelled(): boolean\n cancel(): Promise<void>\n}\n\nexport interface PendingChain {\n onConnection(connection: string): this\n onQueue(queue: string): this\n /** Runs as a job if any job in the chain fails. Callbacks are jobs, because closures can't be serialized. */\n catch(job: Job): this\n dispatch(): Promise<void>\n}\n\nexport interface PendingBatch {\n name(name: string): this\n onConnection(connection: string): this\n onQueue(queue: string): this\n allowFailures(allow?: boolean): this\n then(job: Job): this\n catch(job: Job): this\n finally(job: Job): this\n dispatch(): Promise<Batch>\n}\n\nexport interface BusDispatcher {\n /** Queues it when the job is queueable (implements ShouldQueue / declares queue options), otherwise runs it now. */\n dispatch(job: Job): Promise<unknown>\n dispatchSync(job: Job): Promise<unknown>\n /** Runs after the current response is sent (or the current job finishes). */\n dispatchAfterResponse(job: Job): void\n chain(jobs: Job[]): PendingChain\n batch(jobs: Job[]): PendingBatch\n findBatch(id: string): Promise<Batch | undefined>\n}\nexport const BusDispatcher = token<BusDispatcher>('Bus.Dispatcher')\n\n/** What PendingBatch hands to the repository. Callbacks are jobs, because closures can't be serialized. */\nexport interface PendingBatchOptions {\n name: string\n then: Job[]\n catch: Job[]\n finally: Job[]\n allowFailures: boolean\n connection?: string\n queue?: string\n}\n\n/** Stores batches and runs their bookkeeping (Laravel's BatchRepository). Bound by the Queue component. */\nexport interface BatchRepository {\n store(options: PendingBatchOptions): Promise<Batch>\n find(id: string): Promise<Batch | undefined>\n /** Adds `amount` to both total and pending jobs, before the jobs are pushed. */\n incrementTotalJobs(id: string, amount: number): Promise<void>\n /** A batched job succeeded: decrement pending, then run then/finally callbacks when due. */\n recordSuccessfulJob(id: string, jobUuid: string): Promise<void>\n /** A batched job failed for good: count it, cancel unless failures are allowed, run catch/finally when due. */\n recordFailedJob(id: string, jobUuid: string, error: unknown): Promise<void>\n markAsFinished(id: string): Promise<void>\n cancel(id: string): Promise<void>\n delete(id: string): Promise<void>\n}\nexport const BatchRepository = token<BatchRepository>('Queue.BatchRepository')\n","import { token } from './Container'\nimport type { Job } from './Queue'\n\n/** A CLI command. Signature uses Laravel syntax: 'mail:send {user} {--queue=default}'. */\nexport interface Command {\n readonly signature: string\n readonly description: string\n handle(): number | void | Promise<number | void>\n}\n\nexport type OptionValue = string | boolean | string[] | undefined\n\n/** `this` inside a closure command (Laravel's Command API). */\nexport interface CommandContext extends Command {\n argument(name: string): string | string[] | undefined\n arguments(): Record<string, string | string[]>\n option(name: string): OptionValue\n options(): Record<string, OptionValue>\n info(message: string): void\n line(message?: string): void\n comment(message: string): void\n warn(message: string): void\n error(message: string): void\n newLine(count?: number): void\n table(headers: string[], rows: string[][]): void\n ask(question: string, defaultValue?: string): Promise<string>\n secret(question: string): Promise<string>\n confirm(question: string, defaultValue?: boolean): Promise<boolean>\n choice(question: string, choices: string[], defaultIndex?: number): Promise<string>\n}\n\n/** What ConsoleKernel.command() returns. */\nexport interface ClosureCommand extends CommandContext {\n purpose(description: string): this\n}\n\nexport interface ConsoleKernel {\n /** Returns the exit code. */\n handle(argv: string[]): Promise<number>\n call(command: string, parameters?: Record<string, unknown>): Promise<number>\n /** Output buffered from the last call(). */\n output(): string\n all(): Record<string, Command>\n /** Register command classes or instances (components call this from their provider's boot()). */\n register(...commands: Array<Command | (new () => Command)>): void\n /** Closure command, like Artisan::command() in routes/console.ts. `this` is the command (argument(), info(), …). */\n command(signature: string, handler: (this: CommandContext, ...args: unknown[]) => number | void | Promise<number | void>): ClosureCommand\n}\nexport const ConsoleKernel = token<ConsoleKernel>('Console.Kernel')\n\nexport interface ScheduledEvent {\n readonly expression: string\n /**\n * What a Schedule.command() event runs: the command and its parameters ('posts:announce --force'), without the\n * runtime and `oriel` in front. Undefined for call() and job() events. Laravel's `$event->command`.\n */\n readonly command: string | undefined\n /** Whether withoutOverlapping() was called. Laravel's `$event->withoutOverlapping`, a method's name here. */\n readonly preventsOverlapping: boolean\n /** Minutes the withoutOverlapping() lock is kept at most (1440 unless withoutOverlapping() says). Laravel's `$event->expiresAt`. */\n readonly expiresAt: number\n cron(expression: string): this\n everyMinute(): this\n everyFiveMinutes(): this\n everyFifteenMinutes(): this\n everyThirtyMinutes(): this\n hourly(): this\n hourlyAt(minute: number): this\n daily(): this\n dailyAt(time: string): this\n twiceDaily(first?: number, second?: number): this\n weekly(): this\n weeklyOn(day: number, time?: string): this\n monthly(): this\n monthlyOn(day: number, time?: string): this\n yearly(): this\n weekdays(): this\n weekends(): this\n timezone(timezone: string): this\n between(start: string, end: string): this\n when(callback: () => boolean | Promise<boolean>): this\n skip(callback: () => boolean | Promise<boolean>): this\n /** Uses a cache lock (default 1440 minutes). */\n withoutOverlapping(expiresAtMinutes?: number): this\n /** Uses a cache lock so only one server runs it. */\n onOneServer(): this\n runInBackground(): this\n name(name: string): this\n description(description: string): this\n /** The name, else the description: the command, the job's class, or 'Closure'. schedule:list shows it. */\n getSummaryForDisplay(): string\n /**\n * The cache lock withoutOverlapping() holds: `framework/schedule-` and the sha1 of the expression and the command,\n * or of the name for call() and job() events (Laravel's mutexName()). schedule:clear-cache deletes it.\n */\n mutexName(): string\n isDue(now: Date): boolean\n run(): Promise<void>\n}\n\nexport interface Schedule {\n command(command: string, parameters?: string[]): ScheduledEvent\n job(job: Job, queue?: string, connection?: string): ScheduledEvent\n call(callback: () => unknown | Promise<unknown>): ScheduledEvent\n events(): ScheduledEvent[]\n dueEvents(now: Date): ScheduledEvent[]\n}\nexport const Schedule = token<Schedule>('Console.Schedule')\n","import { token } from './Container'\n\nexport interface Address {\n address: string\n name?: string\n}\n/** A plain email string, an Address, or anything with email (+ optional name), such as a User model. */\nexport type MailRecipient = string | Address | { email: string; name?: string }\n\nexport interface Envelope {\n from?: MailRecipient\n to?: MailRecipient[]\n cc?: MailRecipient[]\n bcc?: MailRecipient[]\n replyTo?: MailRecipient[]\n subject?: string\n tags?: string[]\n metadata?: Record<string, string>\n}\n\nexport interface Content {\n /** A View name, rendered by ViewFactory (TSX). */\n view?: string\n /** A plain-text view name. */\n text?: string\n /** Raw HTML (used when no view is given). */\n htmlString?: string\n /** Raw plain-text body (used when no text view is given). */\n textString?: string\n with?: Record<string, unknown>\n}\n\nexport interface Attachment {\n name: string\n path?: string\n data?: Uint8Array | string\n mime?: string\n}\n\n/** Laravel 10+ style mailable: envelope() + content() + attachments(). */\nexport interface Mailable {\n envelope(): Envelope | Promise<Envelope>\n content(): Content | Promise<Content>\n attachments?(): Attachment[] | Promise<Attachment[]>\n}\n\n/** Fully rendered message handed to a transport. */\nexport interface OutgoingMessage {\n from: Address\n to: Address[]\n cc: Address[]\n bcc: Address[]\n replyTo: Address[]\n subject: string\n html?: string\n text?: string\n attachments: Attachment[]\n headers: Record<string, string>\n}\n\nexport interface SentMessage {\n messageId: string\n message: OutgoingMessage\n}\n\nexport interface MailTransport {\n send(message: OutgoingMessage): Promise<SentMessage>\n}\n\nexport interface PendingMail {\n cc(recipients: MailRecipient | MailRecipient[]): this\n bcc(recipients: MailRecipient | MailRecipient[]): this\n send(mailable: Mailable): Promise<SentMessage | undefined>\n /** Sends at once, even when the mailable is queueable (Laravel's sendNow()). A fake resolves undefined. */\n sendNow(mailable: Mailable): Promise<SentMessage | undefined>\n queue(mailable: Mailable): Promise<void>\n later(delaySeconds: number, mailable: Mailable): Promise<void>\n}\n\nexport interface Mailer {\n to(recipients: MailRecipient | MailRecipient[]): PendingMail\n /** Sends to the recipients given in the mailable's envelope. Queues it if the mailable is queueable. */\n send(mailable: Mailable): Promise<SentMessage | undefined>\n /** Sends to the envelope's recipients at once, even when the mailable is queueable (Laravel's sendNow()). */\n sendNow(mailable: Mailable): Promise<SentMessage | undefined>\n queue(mailable: Mailable): Promise<void>\n}\n\nexport interface MailManager extends Mailer {\n mailer(name?: string): Mailer\n extend(transport: string, factory: (config: Record<string, unknown>) => MailTransport): void\n}\nexport const MailManager = token<MailManager>('Mail.Manager')\n","import { token } from './Container'\nimport type { ModelInstance } from './Database'\n\nexport interface Notifiable {\n /** e.g. 'mail' → email address, 'database' → the model itself. */\n routeNotificationFor(channel: string, notification: Notification): unknown\n}\n\nexport interface Notification {\n /** Optional id; set by the dispatcher when missing. */\n id?: string\n via(notifiable: Notifiable): string[]\n /** Returns a Mailable (Contracts/Mail) or the Notifications MailMessage builder. */\n toMail?(notifiable: Notifiable): unknown\n toDatabase?(notifiable: Notifiable): Record<string, unknown>\n toArray?(notifiable: Notifiable): Record<string, unknown>\n}\n\nexport interface NotificationChannel {\n send(notifiable: Notifiable, notification: Notification): Promise<void>\n}\n\nexport interface NotificationDispatcher {\n /** Queues it when the notification is queueable, otherwise sends immediately. */\n send(notifiables: Notifiable | Notifiable[], notification: Notification): Promise<void>\n sendNow(notifiables: Notifiable | Notifiable[], notification: Notification, channels?: string[]): Promise<void>\n /** On-demand: Notification.route('mail', 'a@b.c').notify(n). */\n route(channel: string, route: unknown): Notifiable & { notify(notification: Notification): Promise<void> }\n extend(channel: string, factory: () => NotificationChannel): void\n}\nexport const NotificationDispatcher = token<NotificationDispatcher>('Notifications.Dispatcher')\n\n/**\n * A stored database notification (Laravel's DatabaseNotification model): one row of the `notifications` table, with\n * its snake_case columns. `user.notifications()`, `unreadNotifications()` and `readNotifications()` query these,\n * newest first.\n */\nexport interface DatabaseNotification extends ModelInstance {\n /** A UUID. */\n readonly id: string\n /** The notification's class name. */\n readonly type: string\n /** What the notification's toDatabase() (or toArray()) returned. */\n readonly data: Record<string, unknown>\n read_at: Date | null\n readonly created_at: Date | null\n readonly updated_at: Date | null\n /** Sets read_at to now and saves, unless it is already read. */\n markAsRead(): Promise<void>\n /** Clears read_at and saves, unless it is already unread. */\n markAsUnread(): Promise<void>\n read(): boolean\n unread(): boolean\n}\n","import { token } from './Container'\n\nexport interface Lock {\n /** Tries once. Returns whether it was acquired. */\n get(): Promise<boolean>\n /** Tries once. Runs the callback and releases if acquired, else returns false. */\n get<T>(callback: () => T | Promise<T>): Promise<T | false>\n /** Waits up to `seconds` to acquire. Throws LockTimeoutError (an OrielError, kind 'Server', status 500) on timeout. */\n block<T>(seconds: number, callback?: () => T | Promise<T>): Promise<T | true>\n release(): Promise<boolean>\n forceRelease(): Promise<void>\n owner(): string\n}\n\nexport interface CacheRepository {\n get<T = unknown>(key: string): Promise<T | undefined>\n get<T>(key: string, defaultValue: T | (() => T)): Promise<T>\n many<T = unknown>(keys: string[]): Promise<Record<string, T | undefined>>\n has(key: string): Promise<boolean>\n missing(key: string): Promise<boolean>\n /** ttl in seconds; undefined = forever. */\n put(key: string, value: unknown, ttlSeconds?: number): Promise<boolean>\n /** Only stores if the key is missing. Atomic in every driver. */\n add(key: string, value: unknown, ttlSeconds?: number): Promise<boolean>\n increment(key: string, by?: number): Promise<number>\n decrement(key: string, by?: number): Promise<number>\n forever(key: string, value: unknown): Promise<boolean>\n pull<T = unknown>(key: string, defaultValue?: T): Promise<T | undefined>\n forget(key: string): Promise<boolean>\n flush(): Promise<boolean>\n remember<T>(key: string, ttlSeconds: number, callback: () => T | Promise<T>): Promise<T>\n rememberForever<T>(key: string, callback: () => T | Promise<T>): Promise<T>\n lock(name: string, seconds?: number, owner?: string): Lock\n /** Only supported by the redis store. Others throw. */\n tags(names: string | string[]): CacheRepository\n}\n\nexport interface CacheManager extends CacheRepository {\n store(name?: string): CacheRepository\n extend(driver: string, factory: (config: Record<string, unknown>) => CacheRepository): void\n}\nexport const CacheManager = token<CacheManager>('Cache.Manager')\n\n/** Laravel's RateLimiter: hits per key, kept in the default cache store. */\nexport interface RateLimiter {\n tooManyAttempts(key: string, maxAttempts: number): Promise<boolean>\n /** Adds a hit; the window starts at the first hit and lasts `decaySeconds` (default 60). Returns the hit count. */\n hit(key: string, decaySeconds?: number): Promise<number>\n attempts(key: string): Promise<number>\n remaining(key: string, maxAttempts: number): Promise<number>\n /** Seconds until the key's window resets. */\n availableIn(key: string): Promise<number>\n clear(key: string): Promise<void>\n}\nexport const RateLimiter = token<RateLimiter>('Cache.RateLimiter')\n","import { token, type Class } from './Container'\n\nexport type ListenerClass<E> = Class<{ handle(event: E): unknown }>\nexport type Listener<E> = ((event: E) => unknown) | ListenerClass<E>\n\nexport interface EventDispatcher {\n /** Class events (recommended) or string events like 'eloquent.created: Post'. */\n listen<E>(events: Class<E> | string | Array<Class<E> | string>, listener: Listener<E>): void\n hasListeners(event: Class<unknown> | string): boolean\n /** Runs listeners in registration order. Listener classes that are queueable are queued. Returns results. */\n dispatch(event: object | string, payload?: unknown[]): Promise<unknown[]>\n /** Stops at the first listener that returns something other than undefined. Returns that value. */\n until(event: object | string, payload?: unknown[]): Promise<unknown>\n subscribe(subscriber: Class<{ subscribe(events: EventDispatcher): void }>): void\n forget(event: Class<unknown> | string): void\n}\nexport const EventDispatcher = token<EventDispatcher>('Events.Dispatcher')\n","import { token } from './Container'\nimport type { UploadedFile } from './Http'\n\nexport interface PutOptions {\n visibility?: 'public' | 'private'\n mimeType?: string\n}\n\n/** Paths are relative to the disk root. Throws on paths that escape it ('../'). */\nexport interface Filesystem {\n exists(path: string): Promise<boolean>\n missing(path: string): Promise<boolean>\n get(path: string): Promise<string>\n getBytes(path: string): Promise<Uint8Array>\n readStream(path: string): Promise<ReadableStream<Uint8Array>>\n put(path: string, contents: string | Uint8Array | ReadableStream<Uint8Array>, options?: PutOptions): Promise<boolean>\n /** Stores under a generated unique name. Returns the stored path. */\n putFile(directory: string, file: UploadedFile, options?: PutOptions): Promise<string>\n putFileAs(directory: string, file: UploadedFile, name: string, options?: PutOptions): Promise<string>\n delete(paths: string | string[]): Promise<boolean>\n copy(from: string, to: string): Promise<boolean>\n move(from: string, to: string): Promise<boolean>\n size(path: string): Promise<number>\n lastModified(path: string): Promise<Date>\n mimeType(path: string): Promise<string | undefined>\n url(path: string): string\n temporaryUrl(path: string, expiresAt: Date): Promise<string>\n files(directory?: string, recursive?: boolean): Promise<string[]>\n directories(directory?: string, recursive?: boolean): Promise<string[]>\n makeDirectory(path: string): Promise<boolean>\n deleteDirectory(path: string): Promise<boolean>\n /** Absolute local path (local disks only). */\n path(path: string): string\n}\n\nexport interface FilesystemManager extends Filesystem {\n disk(name?: string): Filesystem\n extend(driver: string, factory: (config: Record<string, unknown>) => Filesystem): void\n}\nexport const FilesystemManager = token<FilesystemManager>('Filesystem.Manager')\n","import { token } from './Container'\nimport type { RedirectResponse } from './Routing'\nimport type { Responsable } from './Support'\n\n/** Infinite-scroll metadata for one prop (page.scrollProps[path]). */\nexport interface InertiaScrollProp {\n pageName: string\n previousPage: string | number | null\n nextPage: string | number | null\n currentPage: string | number | null\n reset: boolean\n}\n\n/** A once prop the client keeps between visits (page.onceProps[key]). `expiresAt` is epoch milliseconds. */\nexport interface InertiaOnceProp {\n prop: string\n expiresAt: number | null\n}\n\n/**\n * The Inertia page object (protocol v3, @inertiajs/core 3.x). Only component, props, url and version are always\n * present; the other fields are left out when empty or false.\n */\nexport interface InertiaPage {\n component: string\n props: Record<string, unknown>\n /** Path and query, never absolute: '/posts?page=2'. */\n url: string\n /** '' when the app has no asset version. */\n version: string\n sharedProps?: string[]\n mergeProps?: string[]\n prependProps?: string[]\n deepMergeProps?: string[]\n /** '<prop path>.<key field>', e.g. 'posts.data.id'. */\n matchPropsOn?: string[]\n /** Group name → prop paths loaded after the first render. */\n deferredProps?: Record<string, string[]>\n rescuedProps?: string[]\n scrollProps?: Record<string, InertiaScrollProp>\n onceProps?: Record<string, InertiaOnceProp>\n clearHistory?: true\n encryptHistory?: true\n flash?: Record<string, unknown>\n preserveFragment?: true\n}\n\nexport interface InertiaResponse extends Responsable {\n with(key: string | Record<string, unknown>, value?: unknown): this\n withViewData(key: string | Record<string, unknown>, value?: unknown): this\n rootView(view: string): this\n /** Flash data for the next page (page.flash), stored in the session. */\n flash(key: string | Record<string, unknown>, value?: unknown): this\n}\n\nexport type PropCallback<T = unknown> = () => T | Promise<T>\n\n/** The SSR result spliced into the root view: the `head` tags and the rendered `body`. */\nexport interface InertiaSsrResponse {\n head: string\n body: string\n}\n\n/** Sends a page to the SSR server. Resolves to undefined when SSR is off, unreachable or failing. */\nexport interface InertiaSsrGateway {\n dispatch(page: InertiaPage): Promise<InertiaSsrResponse | undefined>\n}\nexport const InertiaSsrGateway = token<InertiaSsrGateway>('Inertia.SsrGateway')\n\nexport interface InertiaFactory {\n render(component: string, props?: Record<string, unknown>): InertiaResponse\n share(key: string | Record<string, unknown>, value?: unknown): void\n /** A shared once prop: sent on the first visit, then kept by the client. */\n shareOnce(key: string, callback: PropCallback): void\n getShared(key?: string): unknown\n flushShared(): void\n version(version: string | null | (() => string | null | Promise<string | null>)): void\n getVersion(): Promise<string>\n setRootView(view: string): void\n /** Only evaluated on partial reloads that ask for it. */\n optional<T>(callback: PropCallback<T>): unknown\n /** Loaded in a follow-up request after the first render. */\n defer<T>(callback: PropCallback<T>, group?: string): unknown\n /** Always included, even in partial reloads. */\n always<T>(value: T | PropCallback<T>): unknown\n /** Appended to the existing client-side value instead of replacing it. */\n merge<T>(value: T | PropCallback<T>): unknown\n /** Deep-merged with the existing client-side value. */\n deepMerge<T>(value: T | PropCallback<T>): unknown\n /** Resolved once, then remembered by the client. */\n once<T>(callback: PropCallback<T>): unknown\n /** Infinite scroll over a paginator: merged page by page, with scroll metadata. */\n scroll<T>(value: T | PropCallback<T>, wrapper?: string): unknown\n /** Flash data for the next page (page.flash), stored in the session. */\n flash(key: string | Record<string, unknown>, value?: unknown): this\n encryptHistory(encrypt?: boolean): void\n /** The next page tells the client to clear its encrypted history. */\n clearHistory(): void\n /** The next page keeps the URL fragment of the request that redirected to it. */\n preserveFragment(): void\n /** 409 + X-Inertia-Location for Inertia requests, a plain 302 otherwise. */\n location(url: string): Response\n /** Redirect back (Inertia.flash('saved', true).back()). */\n back(fallback?: string, status?: number): RedirectResponse\n}\nexport const InertiaFactory = token<InertiaFactory>('Inertia.Factory')\n","import { token, type Class } from './Container'\nimport type { HttpRequest } from './Http'\n\nexport interface LiveSnapshot {\n data: Record<string, unknown>\n memo: {\n id: string\n /** ClassRegistry name of the component. */\n name: string\n path: string\n method: string\n children: Record<string, [tag: string, id: string]>\n errors: Record<string, string[]>\n }\n /** HMAC-SHA256 of JSON(data + memo), keyed by APP_KEY. */\n checksum: string\n}\n\nexport interface LiveEffects {\n html?: string\n /** Browser events from this.dispatch(); `self` keeps one on this component, `to` sends it to one component name. */\n dispatches?: Array<{ name: string; params: Record<string, unknown>; self?: true; to?: string }>\n /** Events this component listens to (@On, static listeners); sent with the first render. */\n listeners?: string[]\n redirect?: string\n /** Follow `redirect` with o:navigate instead of a full page load. */\n redirectUsingNavigate?: true\n returns?: unknown[]\n}\n\nexport interface LiveUpdateRequest {\n components: Array<{\n /** JSON-encoded LiveSnapshot. */\n snapshot: string\n updates: Record<string, unknown>\n calls: Array<{ method: string; params: unknown[] }>\n }>\n}\n\nexport interface LiveUpdateResponse {\n components: Array<{ snapshot: string; effects: LiveEffects }>\n}\n\nexport interface LiveManager {\n register(component: Class<unknown>, name?: string): void\n /** Server-renders the first HTML (snapshot embedded). `key` identifies a child inside its parent (o:key). */\n mount(component: string | Class<unknown>, params?: Record<string, unknown>, key?: string): Promise<string>\n /** Checks checksums and CSRF, then applies updates and calls, re-renders and returns new snapshots. */\n update(request: LiveUpdateRequest): Promise<LiveUpdateResponse>\n /**\n * A full-page component (Route.get('/counter', Counter)): mounts `component` (a component instance) with the current route's parameters and\n * returns the response, its layout view or a redirect.\n */\n page(component: object): Promise<unknown>\n isLiveRequest(request: HttpRequest): boolean\n}\nexport const LiveManager = token<LiveManager>('Live.Manager')\n"],"mappings":";AAQO,SAAS,MAAS,aAA+B;AACtD,SAAO,OAAO,OAAO,EAAE,IAAI,uBAAO,IAAI,SAAS,WAAW,EAAE,GAAG,YAAY,CAAC;AAC9E;AA+BO,IAAM,YAAY,MAAiB,qBAAqB;ACExD,IAAM,cAAc,MAAmB,wBAAwB;AAQ/D,IAAM,mBAAmB,MAAwB,6BAA6B;AAW9E,IAAM,eAAe,MAAoB,yBAAyB;AAiBlE,IAAM,sBAAsB,MAAgC,gCAAgC;AAC5F,IAAM,qBAAqB,MAA+C,+BAA+B;ACrEzG,IAAM,mBAAmB,MAAwB,mBAAmB;ACkBpE,IAAM,gBAAgB,MAAqB,uBAAuB;ACTlE,IAAM,kBAAkB,MAAuB,kBAAkB;ACgDjE,IAAM,cAAc,MAAmB,cAAc;AA0BrD,IAAM,aAAa,MAAkB,aAAa;AASlD,IAAM,kBAAkB,MAAuB,sBAAsB;ACVrE,IAAM,eAAe,MAAoB,sBAAsB;AAC/D,IAAM,SAAS,MAAc,gBAAgB;AAW7C,IAAM,qBAAqB,MAA0B,uBAAuB;AA2B5E,IAAM,eAAe,MAAoB,sBAAsB;AAiB/D,IAAM,aAAa,MAAkB,oBAAoB;ACzHzD,IAAM,UAAU,MAAe,eAAe;ACN9C,IAAM,YAAY,MAAiB,YAAY;ACZ/C,IAAM,YAAY,MAAiB,sBAAsB;ACFzD,IAAM,SAAS,MAAc,gBAAgB;ACU7C,IAAM,cAAc,MAAmB,cAAc;ACIrD,IAAM,aAAa,MAAkB,aAAa;AC+ClD,IAAM,kBAAkB,MAAuB,kBAAkB;AAyCjE,IAAM,kBAAkB,MAAuB,0BAA0B;AC1DzE,IAAM,oBAAoB,MAAyB,oBAAoB;ACPvE,IAAM,cAAc,MAAmB,cAAc;AAerD,IAAM,OAAO,MAAY,WAAW;AAQpC,IAAM,iBAAiB,MAAsB,qBAAqB;ACKlE,IAAM,eAAe,MAAoB,eAAe;AAkBxD,IAAM,oBAAoB,MAAyB,yBAAyB;AC/C5E,IAAM,gBAAgB,MAAqB,gBAAgB;AA2B3D,IAAM,kBAAkB,MAAuB,uBAAuB;ACvBtE,IAAM,gBAAgB,MAAqB,gBAAgB;AA2D3D,IAAM,WAAW,MAAgB,kBAAkB;ACfnD,IAAM,cAAc,MAAmB,cAAc;AC9DrD,IAAM,yBAAyB,MAA8B,0BAA0B;ACWvF,IAAM,eAAe,MAAoB,eAAe;AAaxD,IAAM,cAAc,MAAmB,mBAAmB;ACtC1D,IAAM,kBAAkB,MAAuB,mBAAmB;ACuBlE,IAAM,oBAAoB,MAAyB,oBAAoB;AC4BvE,IAAM,oBAAoB,MAAyB,oBAAoB;AAsCvE,IAAM,iBAAiB,MAAsB,iBAAiB;ACjD9D,IAAM,cAAc,MAAmB,cAAc;","names":[]}