@orieljs/framework 0.1.0-alpha.10 → 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.
@@ -2,9 +2,9 @@ import {
2
2
  Fragment,
3
3
  jsx,
4
4
  jsxs
5
- } from "./chunk-VOYW3R5J.js";
6
- import "./chunk-7ZQZYDOC.js";
7
- import "./chunk-GVNLZZTN.js";
5
+ } from "./chunk-24673JQF.js";
6
+ import "./chunk-MURTCTRH.js";
7
+ import "./chunk-HTJKT2R2.js";
8
8
  export {
9
9
  Fragment,
10
10
  jsx,
package/dist/testing.js CHANGED
@@ -52,9 +52,9 @@ import {
52
52
  travelBack,
53
53
  travelTo,
54
54
  usingInMemoryDatabase
55
- } from "./chunk-OXAATQA6.js";
56
- import "./chunk-7ZQZYDOC.js";
57
- import "./chunk-GVNLZZTN.js";
55
+ } from "./chunk-KDE5BLI3.js";
56
+ import "./chunk-MURTCTRH.js";
57
+ import "./chunk-HTJKT2R2.js";
58
58
  export {
59
59
  AnonymousNotifiable,
60
60
  AssertableInertia,
package/docs/console.md CHANGED
@@ -55,6 +55,7 @@ These are the commands every app has. A new app adds one of its own, `inspire`,
55
55
  | Command | What it does |
56
56
  | --- | --- |
57
57
  | `about` | Shows your app's name, the Oriel and Node versions, the environment, debug mode and URL |
58
+ | `export` | Saves your app's pages as files any static host serves ([Static export](export.md)) |
58
59
  | `help` | Shows a command's help screen |
59
60
  | `list` | Lists the commands, all of them or one group's |
60
61
  | `serve` | Serves your app on Oriel's server; `--watch` restarts it when your code changes |
@@ -115,6 +116,7 @@ These are the commands every app has. A new app adds one of its own, `inspire`,
115
116
  | `schedule:run` | Runs the scheduled tasks that are due |
116
117
  | `schedule:work` | Runs the tasks that are due, every minute, until you stop it |
117
118
  | `storage:link` | Links `public/storage` to `storage/app/public` |
119
+ | `vercel:build` | Writes your app's build for Vercel into `.vercel/output` ([Deploying to Vercel](deployment.md#deploying-to-vercel)) |
118
120
 
119
121
  `node oriel help <command>` lists a command's options. A few that are worth knowing up front:
120
122
 
@@ -10,6 +10,10 @@ So deploying it means starting that process, keeping it running, and restarting
10
10
  the processes beside it: the queue workers, the scheduler and, for the Inertia kits with server-side rendering, the
11
11
  SSR server.
12
12
 
13
+ An app whose pages are the same for every visitor can skip the server altogether: [Static export](export.md) saves its
14
+ pages as files any static host serves. On Vercel, your app runs without a server of its own, in a function that starts
15
+ when requests come: see [Deploying to Vercel](#deploying-to-vercel).
16
+
13
17
  ## Server requirements
14
18
 
15
19
  Your server needs **Node 22** or later, or **Bun 1.2** or later. On Node, your app's TypeScript runs through `tsx`,
@@ -238,6 +242,97 @@ node oriel inertia:stop-ssr
238
242
 
239
243
  Laravel's `reload` command, which does both, isn't in Oriel.
240
244
 
245
+ ## Deploying to Vercel
246
+
247
+ On Vercel there is no server to keep running: Vercel's CDN sends the files in `public`, and every other request goes
248
+ to a function that runs your app. `node oriel vercel:build` writes both into `.vercel/output`, the folder Vercel
249
+ deploys (its [Build Output API](https://vercel.com/docs/build-output-api)): `static` holds `public`, whose built
250
+ assets are cached for a year as `serve()` sends them, and the function holds your app's code,
251
+ `public/build/manifest.json` and your production dependencies. Your `.env` files and your
252
+ SQLite databases are left out: the secrets come from Vercel's environment variables, and the database from a server.
253
+
254
+ ### Setting up the project
255
+
256
+ Add a `vercel.json` to your app, so that Vercel's build runs the command:
257
+
258
+ ```json title="vercel.json"
259
+ {
260
+ "framework": null,
261
+ "buildCommand": "npm run build && node oriel migrate --force && node oriel vercel:build"
262
+ }
263
+ ```
264
+
265
+ The API kit has no `build` script: leave `npm run build &&` out. Then import your repository in Vercel, or deploy from
266
+ your machine with `npx vercel deploy`: either way, the build runs on Vercel's machines, which run Linux, as its
267
+ functions do. The function holds native packages built for the machine that ran the build, such as esbuild, which
268
+ `tsx` needs, so a function built on macOS or Windows fails on Vercel. `vercel:build` warns when it runs elsewhere than
269
+ Linux: don't deploy that build with `vercel deploy --prebuilt`.
270
+
271
+ `migrate --force` runs on every deploy, the previews' too. Give the Preview environment a database of its own, such as
272
+ a branch of your production database, so that a preview never migrates your live data.
273
+
274
+ ### Environment variables
275
+
276
+ Set your app's values in the project's settings, under Environment Variables:
277
+
278
+ ```dotenv
279
+ APP_ENV=production
280
+ APP_DEBUG=false
281
+ APP_KEY=base64:...
282
+ APP_URL=https://example.vercel.app
283
+ DB_CONNECTION=pgsql
284
+ DB_URL=postgres://...
285
+ SESSION_DRIVER=database
286
+ CACHE_STORE=database
287
+ QUEUE_CONNECTION=sync
288
+ INERTIA_SSR_ENABLED=false
289
+ ```
290
+
291
+ Vercel gives them to the build, which runs the migrations, and to the function. PostgreSQL needs `pg` in your
292
+ dependencies (`npm install pg`); Vercel's Marketplace has PostgreSQL databases with a free plan, which set `DB_URL`'s
293
+ value for you under a name of their own, such as `DATABASE_URL`: copy it into `DB_URL`. When the address says
294
+ `sslmode=require`, as Neon's do, `pg` warns on every cold start: write `sslmode=verify-full`, which also checks the
295
+ server's certificate.
296
+
297
+ ### What changes on Vercel
298
+
299
+ Vercel starts an instance of the function when requests come, and stops it when they stop. The first request to a new
300
+ instance boots your app; the next ones reuse it. Nothing your app keeps in memory or on disk outlasts the instance,
301
+ and each instance has its own, so:
302
+
303
+ - **Your database is a server**, PostgreSQL or MySQL. The function's files are read-only, so SQLite can't write.
304
+ - **Sessions and the cache** need a store every instance shares: `database` (the kits have the `sessions` and `cache`
305
+ tables' migrations) or `redis`. Sessions can also use `cookie`. `file` and `array` don't outlast the instance.
306
+ - **Logs** go to stderr, which Vercel's logs show: the function sets `LOG_CHANNEL=stderr` when you don't set it.
307
+ - **Vercel's proxy is trusted.** Every request reaches the function through it, and it sets the `X-Forwarded-*`
308
+ headers itself, so the function trusts them when `trusted_proxies`, in `config/http.ts`, is empty: your URLs keep
309
+ the browser's `https`, and `request().ip()` is the visitor's (see
310
+ [Configuring trusted proxies](requests.md#configuring-trusted-proxies)).
311
+ - **Files your app stores** go on an `s3` disk (see [File storage](storage.md)): the `local` and `public` disks write
312
+ into `storage`, which the function can't.
313
+ - **No queue worker or scheduler runs.** With `QUEUE_CONNECTION=sync`, a job runs during the request that dispatches
314
+ it.
315
+ - **Inertia pages render in the browser**, as they do when no SSR server answers: the SSR server doesn't run on
316
+ Vercel. `INERTIA_SSR_ENABLED=false` skips asking it.
317
+
318
+ ### Caching pages on the CDN
319
+
320
+ Pages that are the same for every visitor can be kept by Vercel's CDN, so that most requests for them never reach the
321
+ function. The `cache.headers` middleware sets their `Cache-Control`: `s_maxage` is how many seconds the CDN keeps a
322
+ page, and `stale_while_revalidate` how long it may still send the old copy while it fetches a new one:
323
+
324
+ ```ts title="routes/web.ts"
325
+ import { Route, StartSession, VerifyCsrfToken, view } from '@orieljs/framework'
326
+
327
+ Route.get('/pricing', () => view('pricing'))
328
+ .middleware('cache.headers:public;s_maxage=3600;stale_while_revalidate=60')
329
+ .withoutMiddleware(StartSession, VerifyCsrfToken)
330
+ ```
331
+
332
+ `cache.headers` leaves a response that sets a cookie alone, so that the CDN never hands one visitor's cookies to the
333
+ next. The `web` group's `StartSession` and `VerifyCsrfToken` set cookies on every page: take them off the pages you
334
+ cache, as above. Those pages have no session, so they can't show who is signed in.
335
+
241
336
  ## Debug mode
242
337
 
243
338
  `debug` in `config/app.ts` reads `APP_DEBUG`, and decides how much an error response shows (see
package/docs/export.md ADDED
@@ -0,0 +1,93 @@
1
+ # Static export
2
+
3
+ When every visitor sees the same pages, `oriel export` saves your app's pages as plain files that any static host can
4
+ serve, with no Oriel server running.
5
+
6
+ ## Introduction
7
+
8
+ A documentation site, a blog without comments, a product page: some apps answer every visitor the same way. For them,
9
+ running a server is optional. `oriel export` starts your app, asks it for each page the way a browser would, and writes
10
+ the answers to a folder. Upload the folder to any static host, such as Vercel, Netlify, GitHub Pages or an S3 bucket,
11
+ and the site works without a server.
12
+
13
+ The pages are still made by your app: its routes, controllers, views and middleware all run, once per page, while you
14
+ export. What an export can't keep is anything that happens per request: forms that post, sessions, logins, Live
15
+ components and anything else that needs the server to answer.
16
+
17
+ ## Exporting your app
18
+
19
+ Build the assets first, then export:
20
+
21
+ ```sh
22
+ npm run build
23
+ node oriel export
24
+ ```
25
+
26
+ The site is written to `dist/`. The command lists the redirects it met and how many pages it wrote:
27
+
28
+ ```text
29
+ Redirect /old → /about, not written.
30
+ Exported 24 pages to [dist] in 840 ms.
31
+ ```
32
+
33
+ `--output` writes somewhere else:
34
+
35
+ ```sh
36
+ node oriel export --output=site
37
+ ```
38
+
39
+ The export only replaces a folder it made itself (or an empty one), so pointing `--output` at a folder that holds
40
+ other files stops it without deleting anything. It also stops while the Vite dev server runs (`public/hot` exists),
41
+ since the pages would point at the dev server: stop `npm run dev`, build, then export.
42
+
43
+ ## Which pages are exported
44
+
45
+ The export starts at `/` and follows every link to the same site, using the origin of `app.url`. A link to another
46
+ site, a `mailto:` or `tel:` link, or a link to a file in `public/` is left alone. Query strings and `#anchors` are
47
+ ignored, so `/docs/routing?tab=1#named` exports `/docs/routing`.
48
+
49
+ Pages nothing links to, such as a feed, are listed in `paths`. Pages to leave out are listed in `exclude`, where `*`
50
+ matches anything. A redirect is listed in the command's output and not written; its target is exported when something
51
+ links to it.
52
+
53
+ A page that answers with an error (4xx or 5xx) stops the export and names the page. The site is written into a
54
+ temporary folder first, so the last export stays as it was.
55
+
56
+ ## Configuration
57
+
58
+ Add a `config/export.ts` file to change the defaults:
59
+
60
+ ```ts
61
+ export default {
62
+ output: 'dist',
63
+ crawl: true,
64
+ paths: ['/feed.xml'],
65
+ exclude: ['/drafts/*'],
66
+ file_names: 'html',
67
+ }
68
+ ```
69
+
70
+ | Key | Default | |
71
+ | --- | --- | --- |
72
+ | `output` | `'dist'` | The folder the site is written to, relative to the app |
73
+ | `crawl` | `true` | Follow links from `/` and from `paths`; `false` exports only those |
74
+ | `paths` | `[]` | Pages to export besides `/` |
75
+ | `exclude` | `[]` | Pages to leave out; `*` matches anything |
76
+ | `file_names` | `'html'` | `'html'` writes `/docs/routing` as `docs/routing.html`; `'directory'` writes `docs/routing/index.html` |
77
+
78
+ A path with an extension, such as `/feed.xml`, keeps its name in either style. The files in `public/`, your built
79
+ assets among them, are copied into the folder first.
80
+
81
+ ## The 404 page
82
+
83
+ When your app has a 404 page (`resources/views/errors/404.tsx`), the export writes it as `404.html`. Vercel, Netlify
84
+ and GitHub Pages show that file for an address that doesn't exist.
85
+
86
+ ## Hosting the files
87
+
88
+ - **Vercel and Netlify** serve `docs/routing.html` at `/docs/routing` when clean URLs are on (Vercel's `cleanUrls`,
89
+ Netlify's pretty URLs).
90
+ - **GitHub Pages** and most other hosts serve `docs/routing.html` at `/docs/routing.html`, and
91
+ `docs/routing/index.html` at `/docs/routing/`: export with `file_names: 'directory'` for addresses without `.html`.
92
+
93
+ To run your app live instead, with forms, sessions and Live components, see [Deployment](deployment.md).
@@ -197,6 +197,16 @@ node oriel migrate
197
197
 
198
198
  For MySQL, `DB_CONNECTION` is `mysql` and the port is usually 3306.
199
199
 
200
+ ## Editor support
201
+
202
+ The OrielJS extension for VS Code covers the strings Oriel reads at run time, where TypeScript can't help: it completes
203
+ validation rules, `config()` keys, `env()` names, view names, and the actions and properties in Live's `o:` attributes,
204
+ shows their docs when you hover, and warns about one your app doesn't have. It also runs `route:types` and
205
+ `inertia:types` again when your routes, controllers or pages change, and puts the `oriel` commands in the command
206
+ palette. Install it from the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=orieljs.orieljs),
207
+ or search for OrielJS in the editor's Extensions view. It needs Oriel 0.1.0-alpha.9 or later, and reads your app only
208
+ in a trusted workspace.
209
+
200
210
  ## Next steps
201
211
 
202
212
  Read how an app is laid out in [Directory structure](structure.md), and how it reads its settings in
@@ -231,6 +231,7 @@ they own.
231
231
  | Alias | Middleware | What it does |
232
232
  | --- | --- | --- |
233
233
  | `auth` | `Authenticate` | Lets signed-in users through. A guest gets a 401 for JSON, or a redirect to the login page. `auth:token` names the guard; with several, the first that has a user wins |
234
+ | `cache.headers` | `SetCacheHeaders` | Sets `Cache-Control` on GET and HEAD responses, as `cache.headers:public;max_age=3600;s_maxage=86400;etag` (`etag` adds an ETag and answers 304 when it matches); a response that sets a cookie is left alone, so a CDN never stores one visitor's page |
234
235
  | `can` | `Authorize` | Checks an ability with the gate, as `can:update,post`; a parameter that names a route parameter passes the bound model. A denial is a 403 |
235
236
  | `guest` | `RedirectIfAuthenticated` | Lets guests through, and redirects signed-in users |
236
237
  | `inertia.encrypt` | `EncryptHistory` | Encrypts the browser history state of the Inertia pages behind it |
@@ -22,6 +22,10 @@
22
22
  {
23
23
  "slug": "deployment",
24
24
  "title": "Deployment"
25
+ },
26
+ {
27
+ "slug": "export",
28
+ "title": "Static export"
25
29
  }
26
30
  ]
27
31
  },
@@ -194,6 +194,9 @@ And the component classes the pages are built from:
194
194
 
195
195
  Utilities still override them: `<button class="btn btn-sm w-full">`.
196
196
 
197
+ In a production build, these names and Tailwind's are scrambled into short ones: every kit's `vite.config.ts` sets
198
+ `obfuscate: true` (see [Class name scrambling](vite.md#class-name-scrambling)).
199
+
197
200
  ### Accessibility
198
201
 
199
202
  The kits are built to be read by everyone:
package/docs/vite.md CHANGED
@@ -163,6 +163,84 @@ Give your CSS file to `input`, or import it from a script, and Vite processes it
163
163
  built with Tailwind CSS, through `@tailwindcss/vite`. Vite's own CSS features, such as PostCSS and CSS modules, work as
164
164
  its documentation describes.
165
165
 
166
+ ## Class name scrambling
167
+
168
+ A production build can give your classes short, meaningless names: `items-center` becomes something like `k3vq` in the
169
+ built CSS, in your scripts, and in the HTML Oriel sends, so your pages give nothing away about how they are styled.
170
+ Every starter kit turns it on; `npm run dev` and your tests keep the names you wrote.
171
+
172
+ ```ts title="vite.config.ts"
173
+ import { oriel } from '@orieljs/vite'
174
+ import { defineConfig } from 'vite'
175
+
176
+ export default defineConfig({
177
+ plugins: [oriel({ input: ['resources/css/app.css', 'resources/js/app.ts'], obfuscate: true })],
178
+ })
179
+ ```
180
+
181
+ `npm run build` writes the names it chose to `bootstrap/cache/classes.json`, out of `public/`, where anyone could
182
+ download them and read your class names back. The SSR build reads them, so it runs after the client build, as the
183
+ kits' `build` script does. Oriel reads them too, and renames the classes in every HTML page it sends: your views,
184
+ Inertia's server-rendered pages, and Live's components and their updates, with Live's `o:loading-class` and
185
+ `o:offline-class`. Deploy `bootstrap/cache/classes.json` with your built assets. While `npm run dev` runs
186
+ (`public/hot` exists), and while your tests run, Oriel renames nothing.
187
+
188
+ A class keeps the same short name from one build to the next, so a script that didn't change keeps its contents and
189
+ its file name, and the browser's cached copy stays right.
190
+
191
+ ### What gets renamed
192
+
193
+ In your scripts, the names in class positions: `class` and `className` props, properties named like `activeClass`,
194
+ `swatchClass` or `iconClasses`, `classList.add()` and its kin, `clsx()`, `cn()` and `classNames()`,
195
+ `el.className = …`, `setAttribute('class', …)`, the selectors you give `querySelector()`, `querySelectorAll()`,
196
+ `closest()` and `matches()`, and each framework's own forms: Vue's `:class`, Svelte's `class:` directives, Solid's
197
+ `classList`, Angular's `[class.name]`. A string anywhere else keeps its words, so `type: 'hidden'` is still a hidden
198
+ input, and a name your CSS doesn't define keeps its name.
199
+
200
+ Your dependencies keep their class names, and so do the classes their style sheets define, so a library's markup
201
+ always matches its CSS, whether you import it or the library injects it. CSS modules' names are hashed already, and
202
+ stay as Vite wrote them. `dark` is never renamed: the kits' appearance script sets it before the page draws.
203
+
204
+ ### Names built from pieces
205
+
206
+ A class built from pieces at run time can't be renamed: `` `btn-${variant}` `` asks for `btn-primary`, which the
207
+ built CSS calls something else. The build lists each one it finds, with its file and line:
208
+
209
+ ```text
210
+ These class names are built from pieces, so they aren't scrambled:
211
+ resources/js/components/Button.tsx:12: `btn-${variant}` builds a class name from pieces, so it keeps its name; …
212
+ ```
213
+
214
+ Write the whole name in a class position instead:
215
+
216
+ ```ts
217
+ declare const button: { className: string }
218
+ declare const variant: 'primary' | 'danger'
219
+ // ---cut---
220
+ button.className = variant === 'danger' ? 'btn btn-danger' : 'btn btn-primary'
221
+
222
+ const variants = {
223
+ primary: { label: 'Save', buttonClass: 'btn btn-primary' },
224
+ danger: { label: 'Delete', buttonClass: 'btn btn-danger' },
225
+ }
226
+ ```
227
+
228
+ Or keep those names as they are, with `keep`:
229
+
230
+ ```ts
231
+ import { oriel } from '@orieljs/vite'
232
+ // ---cut---
233
+ oriel({ input: ['resources/css/app.css', 'resources/js/app.ts'], obfuscate: { keep: ['btn-primary', 'btn-danger'] } })
234
+ ```
235
+
236
+ `keep` is also for a class something outside the build looks for, such as a script on another site or a test that
237
+ reads a production page.
238
+
239
+ ### Turning it off
240
+
241
+ `obfuscate: false`, or no `obfuscate` at all, which is the default: the build keeps your class names, removes an
242
+ earlier build's `classes.json`, and Oriel sends your HTML as it is.
243
+
166
244
  ## Working with views and routes
167
245
 
168
246
  ### Processing static assets with Vite
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orieljs/framework",
3
- "version": "0.1.0-alpha.10",
3
+ "version": "0.1.0-alpha.11",
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",
@@ -58,35 +58,37 @@
58
58
  "pluralize": "8.0.0"
59
59
  },
60
60
  "devDependencies": {
61
- "@orieljs/collections": "0.1.0-alpha.10",
62
- "@orieljs/config": "0.1.0-alpha.10",
63
- "@orieljs/console": "0.1.0-alpha.10",
64
- "@orieljs/cache": "0.1.0-alpha.10",
65
- "@orieljs/auth": "0.1.0-alpha.10",
66
- "@orieljs/bus": "0.1.0-alpha.10",
67
- "@orieljs/database": "0.1.0-alpha.10",
68
- "@orieljs/container": "0.1.0-alpha.10",
69
- "@orieljs/contracts": "0.1.0-alpha.10",
70
- "@orieljs/encryption": "0.1.0-alpha.10",
71
- "@orieljs/cookie": "0.1.0-alpha.10",
72
- "@orieljs/foundation": "0.1.0-alpha.10",
73
- "@orieljs/hashing": "0.1.0-alpha.10",
74
- "@orieljs/filesystem": "0.1.0-alpha.10",
75
- "@orieljs/events": "0.1.0-alpha.10",
76
- "@orieljs/http": "0.1.0-alpha.10",
77
- "@orieljs/inertia": "0.1.0-alpha.10",
78
- "@orieljs/log": "0.1.0-alpha.10",
79
- "@orieljs/mail": "0.1.0-alpha.10",
80
- "@orieljs/notifications": "0.1.0-alpha.10",
81
- "@orieljs/pipeline": "0.1.0-alpha.10",
82
- "@orieljs/queue": "0.1.0-alpha.10",
83
- "@orieljs/support": "0.1.0-alpha.10",
84
- "@orieljs/live": "0.1.0-alpha.10",
85
- "@orieljs/session": "0.1.0-alpha.10",
86
- "@orieljs/validation": "0.1.0-alpha.10",
87
- "@orieljs/testing": "0.1.0-alpha.10",
88
- "@orieljs/view": "0.1.0-alpha.10",
89
- "@orieljs/routing": "0.1.0-alpha.10"
61
+ "@orieljs/auth": "0.1.0-alpha.11",
62
+ "@orieljs/collections": "0.1.0-alpha.11",
63
+ "@orieljs/console": "0.1.0-alpha.11",
64
+ "@orieljs/config": "0.1.0-alpha.11",
65
+ "@orieljs/contracts": "0.1.0-alpha.11",
66
+ "@orieljs/container": "0.1.0-alpha.11",
67
+ "@orieljs/cache": "0.1.0-alpha.11",
68
+ "@orieljs/bus": "0.1.0-alpha.11",
69
+ "@orieljs/database": "0.1.0-alpha.11",
70
+ "@orieljs/cookie": "0.1.0-alpha.11",
71
+ "@orieljs/encryption": "0.1.0-alpha.11",
72
+ "@orieljs/events": "0.1.0-alpha.11",
73
+ "@orieljs/filesystem": "0.1.0-alpha.11",
74
+ "@orieljs/hashing": "0.1.0-alpha.11",
75
+ "@orieljs/http": "0.1.0-alpha.11",
76
+ "@orieljs/inertia": "0.1.0-alpha.11",
77
+ "@orieljs/live": "0.1.0-alpha.11",
78
+ "@orieljs/log": "0.1.0-alpha.11",
79
+ "@orieljs/mail": "0.1.0-alpha.11",
80
+ "@orieljs/notifications": "0.1.0-alpha.11",
81
+ "@orieljs/obfuscate": "0.1.0-alpha.11",
82
+ "@orieljs/pipeline": "0.1.0-alpha.11",
83
+ "@orieljs/queue": "0.1.0-alpha.11",
84
+ "@orieljs/support": "0.1.0-alpha.11",
85
+ "@orieljs/testing": "0.1.0-alpha.11",
86
+ "@orieljs/foundation": "0.1.0-alpha.11",
87
+ "@orieljs/validation": "0.1.0-alpha.11",
88
+ "@orieljs/view": "0.1.0-alpha.11",
89
+ "@orieljs/routing": "0.1.0-alpha.11",
90
+ "@orieljs/session": "0.1.0-alpha.11",
91
+ "@orieljs/vercel": "0.1.0-alpha.11"
90
92
  },
91
93
  "peerDependencies": {
92
94
  "pg": "^8.23.0",