toiljs 0.0.116 → 0.0.118
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +16 -7
- package/build/backend/.tsbuildinfo +1 -1
- package/build/cli/.tsbuildinfo +1 -1
- package/build/cli/index.js +2375 -258
- package/build/client/.tsbuildinfo +1 -1
- package/build/client/auth.d.ts +3 -0
- package/build/client/auth.js +19 -10
- package/build/client/dev/devtools.js +1 -1
- package/build/client/dev/error-overlay.js +1 -1
- package/build/client/index.d.ts +1 -1
- package/build/client/index.js +1 -1
- package/build/client/navigation/navigation.js +28 -3
- package/build/client/routing/Router.js +5 -2
- package/build/client/routing/mount.js +1 -1
- package/build/compiler/.tsbuildinfo +1 -1
- package/build/compiler/auth-emails.js +7 -3
- package/build/compiler/emails.js +1 -1
- package/build/compiler/index.d.ts +1 -0
- package/build/compiler/index.js +26 -5
- package/build/compiler/pages.js +2 -3
- package/build/compiler/prerender.d.ts +3 -8
- package/build/compiler/prerender.js +88 -127
- package/build/compiler/ssg.js +3 -4
- package/build/compiler/template-build.js +3 -4
- package/build/compiler/toil-docs.generated.js +8 -7
- package/build/compiler/vite.js +4 -6
- package/build/devserver/.tsbuildinfo +1 -1
- package/build/devserver/db/database.js +7 -3
- package/build/devserver/db/types.js +1 -1
- package/build/devserver/production.js +4 -3
- package/build/devserver/runtime/crypto.d.ts +1 -1
- package/build/io/.tsbuildinfo +1 -1
- package/build/logger/.tsbuildinfo +1 -1
- package/build/shared/.tsbuildinfo +1 -1
- package/examples/basic/client/routes/analytics.tsx +7 -5
- package/examples/basic/client/routes/pq.tsx +2 -1
- package/examples/basic/server/tsconfig.json +1 -3
- package/package.json +45 -44
- package/presets/no-uint8array-tostring.js +120 -153
- package/presets/oxlint.d.ts +5 -0
- package/presets/oxlint.js +224 -0
- package/server/auth/AuthController.ts +53 -14
- package/server/auth/FactorSettings.ts +41 -0
- package/server/auth/SessionEpochs.ts +58 -0
- package/server/auth/SessionRevocations.ts +13 -0
- package/server/globals/auth.ts +27 -2
- package/server/runtime/tsconfig.json +1 -3
- package/tsconfig.json +2 -11
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
- package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -90
- package/.github/ISSUE_TEMPLATE/config.yml +0 -8
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -43
- package/.github/changelog-config.json +0 -45
- package/.github/dependabot.yml +0 -27
- package/.github/workflows/ci.yml +0 -222
- package/.vscode/settings.json +0 -10
- package/docs/README.md +0 -107
- package/docs/auth/README.md +0 -104
- package/docs/auth/configuration.md +0 -105
- package/docs/auth/emails.md +0 -92
- package/docs/auth/extending.md +0 -202
- package/docs/auth/how-it-works.md +0 -138
- package/docs/auth/usage.md +0 -188
- package/docs/backend/README.md +0 -143
- package/docs/backend/data.md +0 -351
- package/docs/backend/rest.md +0 -402
- package/docs/backend/rpc.md +0 -226
- package/docs/background/README.md +0 -114
- package/docs/background/daemons.md +0 -276
- package/docs/background/derive.md +0 -179
- package/docs/cli/README.md +0 -379
- package/docs/concepts/ai-guide.md +0 -132
- package/docs/concepts/config.md +0 -416
- package/docs/concepts/decorators.md +0 -127
- package/docs/concepts/security.md +0 -108
- package/docs/concepts/tiers.md +0 -166
- package/docs/concepts/types.md +0 -216
- package/docs/database/README.md +0 -143
- package/docs/database/capacity.md +0 -350
- package/docs/database/counters.md +0 -174
- package/docs/database/documents.md +0 -277
- package/docs/database/events.md +0 -307
- package/docs/database/membership.md +0 -246
- package/docs/database/setup.md +0 -155
- package/docs/database/unique.md +0 -216
- package/docs/database/views.md +0 -246
- package/docs/frontend/README.md +0 -104
- package/docs/frontend/components.md +0 -286
- package/docs/frontend/data-fetching.md +0 -260
- package/docs/frontend/images.md +0 -148
- package/docs/frontend/metadata.md +0 -344
- package/docs/frontend/navigation.md +0 -296
- package/docs/frontend/rendering.md +0 -236
- package/docs/frontend/routing.md +0 -346
- package/docs/frontend/scripts.md +0 -118
- package/docs/frontend/search.md +0 -191
- package/docs/frontend/styling.md +0 -147
- package/docs/frontend/toil-global.md +0 -216
- package/docs/getting-started/README.md +0 -81
- package/docs/getting-started/create-project.md +0 -131
- package/docs/getting-started/deploy.md +0 -101
- package/docs/getting-started/first-app.md +0 -215
- package/docs/getting-started/installation.md +0 -124
- package/docs/getting-started/migrating.md +0 -125
- package/docs/getting-started/project-structure.md +0 -163
- package/docs/introduction/README.md +0 -66
- package/docs/introduction/design-principles.md +0 -81
- package/docs/introduction/distributed.md +0 -91
- package/docs/introduction/how-it-works.md +0 -121
- package/docs/introduction/hyperscale.md +0 -70
- package/docs/introduction/modern-stack.md +0 -85
- package/docs/introduction/vs-other-frameworks.md +0 -64
- package/docs/introduction/why-toil.md +0 -99
- package/docs/llms.txt +0 -95
- package/docs/realtime/README.md +0 -102
- package/docs/realtime/channels.md +0 -211
- package/docs/realtime/streams.md +0 -369
- package/docs/services/README.md +0 -60
- package/docs/services/analytics.md +0 -279
- package/docs/services/caching.md +0 -175
- package/docs/services/cookies.md +0 -235
- package/docs/services/crypto.md +0 -209
- package/docs/services/email.md +0 -289
- package/docs/services/environment.md +0 -141
- package/docs/services/ratelimit.md +0 -174
- package/docs/services/time.md +0 -85
- package/eslint.config.js +0 -57
- package/examples/basic/client/routes/docs/[...slug].tsx +0 -12
- package/presets/eslint.js +0 -88
- package/src/backend/index.ts +0 -204
- package/src/cli/configure.ts +0 -363
- package/src/cli/create.ts +0 -924
- package/src/cli/db.ts +0 -158
- package/src/cli/diagnostics.ts +0 -665
- package/src/cli/doctor.ts +0 -982
- package/src/cli/features.ts +0 -170
- package/src/cli/index.ts +0 -326
- package/src/cli/notify.ts +0 -120
- package/src/cli/proc.ts +0 -56
- package/src/cli/ui.ts +0 -169
- package/src/cli/update.ts +0 -248
- package/src/cli/updates.ts +0 -92
- package/src/cli/validate.ts +0 -31
- package/src/cli/version-check.ts +0 -125
- package/src/client/auth.ts +0 -869
- package/src/client/channel/channel.ts +0 -146
- package/src/client/components/Form.tsx +0 -65
- package/src/client/components/Image.tsx +0 -160
- package/src/client/components/Script.tsx +0 -113
- package/src/client/components/Slot.tsx +0 -21
- package/src/client/dev/devtools.tsx +0 -1089
- package/src/client/dev/error-overlay.tsx +0 -225
- package/src/client/errors.ts +0 -11
- package/src/client/head/head.ts +0 -182
- package/src/client/head/metadata.ts +0 -110
- package/src/client/index.ts +0 -130
- package/src/client/navigation/Link.tsx +0 -108
- package/src/client/navigation/NavLink.tsx +0 -86
- package/src/client/navigation/navigation.ts +0 -235
- package/src/client/navigation/prefetch.ts +0 -169
- package/src/client/navigation/scroll.ts +0 -53
- package/src/client/routing/Router.tsx +0 -216
- package/src/client/routing/action.ts +0 -122
- package/src/client/routing/error-boundary.tsx +0 -43
- package/src/client/routing/hooks.ts +0 -140
- package/src/client/routing/lazy.ts +0 -77
- package/src/client/routing/loader.ts +0 -381
- package/src/client/routing/match.ts +0 -47
- package/src/client/routing/mount.tsx +0 -90
- package/src/client/routing/params-context.ts +0 -10
- package/src/client/routing/slot-context.ts +0 -7
- package/src/client/rpc.ts +0 -97
- package/src/client/search/search.ts +0 -189
- package/src/client/search/use-page-search.ts +0 -73
- package/src/client/ssr/markers.tsx +0 -172
- package/src/client/stream/client.ts +0 -237
- package/src/client/types.ts +0 -73
- package/src/compiler/auth-emails.ts +0 -312
- package/src/compiler/config.ts +0 -369
- package/src/compiler/docs.ts +0 -127
- package/src/compiler/email-preview.ts +0 -314
- package/src/compiler/emails.ts +0 -404
- package/src/compiler/fonts.ts +0 -89
- package/src/compiler/generate.ts +0 -471
- package/src/compiler/image-blur.ts +0 -42
- package/src/compiler/image-report.ts +0 -88
- package/src/compiler/index.ts +0 -1362
- package/src/compiler/pages.ts +0 -49
- package/src/compiler/plugin.ts +0 -391
- package/src/compiler/prerender.ts +0 -263
- package/src/compiler/routes.ts +0 -170
- package/src/compiler/seo.ts +0 -415
- package/src/compiler/sri.ts +0 -144
- package/src/compiler/ssg.ts +0 -177
- package/src/compiler/ssr-codegen.ts +0 -85
- package/src/compiler/template-build.ts +0 -676
- package/src/compiler/template.ts +0 -262
- package/src/compiler/toil-docs.generated.ts +0 -77
- package/src/compiler/vite.ts +0 -245
- package/src/devserver/analytics/index.ts +0 -317
- package/src/devserver/config/dotenv.ts +0 -102
- package/src/devserver/config/env.ts +0 -30
- package/src/devserver/config/ratelimit.ts +0 -123
- package/src/devserver/daemon/catalog.ts +0 -120
- package/src/devserver/daemon/cron.ts +0 -87
- package/src/devserver/daemon/host.ts +0 -134
- package/src/devserver/daemon/index.ts +0 -369
- package/src/devserver/daemon/runtime.ts +0 -48
- package/src/devserver/db/catalog.ts +0 -109
- package/src/devserver/db/database.ts +0 -1834
- package/src/devserver/db/derives.ts +0 -121
- package/src/devserver/db/index.ts +0 -20
- package/src/devserver/db/routeKinds.ts +0 -191
- package/src/devserver/db/types.ts +0 -168
- package/src/devserver/email/caps.ts +0 -0
- package/src/devserver/email/config.ts +0 -141
- package/src/devserver/email/console.ts +0 -348
- package/src/devserver/email/index.ts +0 -155
- package/src/devserver/email/providers.ts +0 -131
- package/src/devserver/email/status.ts +0 -23
- package/src/devserver/email/validate.ts +0 -37
- package/src/devserver/email/wire.ts +0 -55
- package/src/devserver/http/cache.ts +0 -0
- package/src/devserver/http/envelope.ts +0 -157
- package/src/devserver/http/proxy.ts +0 -172
- package/src/devserver/http/runtime.ts +0 -387
- package/src/devserver/index.ts +0 -43
- package/src/devserver/production-ipc.ts +0 -63
- package/src/devserver/production-worker.ts +0 -83
- package/src/devserver/production.ts +0 -718
- package/src/devserver/runtime/crypto.ts +0 -587
- package/src/devserver/runtime/host.ts +0 -427
- package/src/devserver/runtime/module.ts +0 -442
- package/src/devserver/server.ts +0 -251
- package/src/devserver/ssr.ts +0 -208
- package/src/devserver/stream/catalog.ts +0 -106
- package/src/devserver/stream/host.ts +0 -42
- package/src/devserver/stream/index.ts +0 -301
- package/src/devserver/stream/manager.ts +0 -167
- package/src/devserver/stream/router.ts +0 -101
- package/src/devserver/stream/wire.ts +0 -58
- package/src/devserver/stream/ws.ts +0 -78
- package/src/devserver/wasm/sections.ts +0 -59
- package/src/devserver/wasm/surface.ts +0 -115
- package/src/io/FastMap.ts +0 -151
- package/src/io/FastSet.ts +0 -113
- package/src/io/codec.ts +0 -362
- package/src/io/index.ts +0 -10
- package/src/io/lengths.ts +0 -14
- package/src/io/types.ts +0 -19
- package/src/logger/index.ts +0 -22
- package/src/shared/index.ts +0 -46
- package/test/analytics-dev.test.ts +0 -113
- package/test/assembly/aspect-shim.ts +0 -33
- package/test/assembly/cookie.spec.ts +0 -303
- package/test/assembly/example.spec.ts +0 -22
- package/test/assembly/ssr.spec.ts +0 -95
- package/test/assembly.test.ts +0 -59
- package/test/auth-emails.test.ts +0 -118
- package/test/built-ssr.test.ts +0 -148
- package/test/channel.test.ts +0 -21
- package/test/config-host-port.test.ts +0 -59
- package/test/configure.test.ts +0 -94
- package/test/daemon-build.test.ts +0 -278
- package/test/daemon-catalog.test.ts +0 -349
- package/test/daemon-emulation.test.ts +0 -256
- package/test/db.test.ts +0 -0
- package/test/devserver-database.test.ts +0 -1102
- package/test/devserver-email.test.ts +0 -306
- package/test/devserver-pqauth.test.ts +0 -93
- package/test/devserver-secrets.test.ts +0 -63
- package/test/devserver.test.ts +0 -259
- package/test/doctor.test.ts +0 -298
- package/test/dom/Image.test.tsx +0 -144
- package/test/dom/Link.test.tsx +0 -67
- package/test/dom/NavLink.test.tsx +0 -37
- package/test/dom/Script.test.tsx +0 -48
- package/test/dom/action.test.tsx +0 -146
- package/test/dom/error-overlay.test.tsx +0 -44
- package/test/dom/loader.test.tsx +0 -121
- package/test/dom/navigation.test.ts +0 -59
- package/test/dom/revalidate.test.tsx +0 -38
- package/test/dom/route-head.test.tsx +0 -56
- package/test/dom/router-loading.test.tsx +0 -44
- package/test/dom/scroll.test.ts +0 -56
- package/test/dom/slot.test.tsx +0 -131
- package/test/dom/use-metadata.test.tsx +0 -58
- package/test/dom/view-transitions.test.tsx +0 -53
- package/test/dynamic-routing.test.ts +0 -132
- package/test/email-console.test.ts +0 -86
- package/test/email-preview.test.ts +0 -73
- package/test/emails.test.ts +0 -58
- package/test/errors.test.ts +0 -21
- package/test/example-guestbook.test.ts +0 -123
- package/test/features.test.ts +0 -149
- package/test/fixtures/bignum-wire/spec.ts +0 -25
- package/test/fixtures/daemon-app.ts +0 -65
- package/test/fixtures/stream-echo.ts +0 -26
- package/test/fixtures/stream-gate.ts +0 -28
- package/test/fixtures/stream-trap.ts +0 -18
- package/test/fixtures/stream-typed.ts +0 -41
- package/test/fonts.test.ts +0 -28
- package/test/global-setup.ts +0 -17
- package/test/head.test.ts +0 -42
- package/test/image-blur.test.ts +0 -50
- package/test/io.test.ts +0 -117
- package/test/metadata.test.ts +0 -40
- package/test/navlink.test.ts +0 -28
- package/test/pages.test.ts +0 -105
- package/test/placeholder.test.ts +0 -9
- package/test/pqauth-e2e.test.ts +0 -216
- package/test/pqauth-email.test.ts +0 -801
- package/test/prerender.test.ts +0 -116
- package/test/prettier-plugin.test.ts +0 -46
- package/test/routes.test.ts +0 -76
- package/test/rpc-bignum-wire.test.ts +0 -164
- package/test/rpc-dispatch.test.ts +0 -132
- package/test/rpc-kinds.test.ts +0 -18
- package/test/rpc.test.ts +0 -66
- package/test/search.test.ts +0 -114
- package/test/seo.test.ts +0 -175
- package/test/slot-layouts.test.ts +0 -69
- package/test/sri.test.ts +0 -129
- package/test/ssg.test.ts +0 -36
- package/test/ssr-hydration.test.tsx +0 -122
- package/test/ssr-render.test.ts +0 -197
- package/test/ssr-template.test.tsx +0 -482
- package/test/stream-emulation.test.ts +0 -479
- package/test/ui.test.ts +0 -40
- package/test/update.test.ts +0 -58
- package/test/validate.test.ts +0 -42
- package/test/version-check.test.ts +0 -130
- package/tests/data-parity/generated-parity.ts +0 -99
- package/tests/data-parity/parity.ts +0 -80
- package/tests/data-parity/spec.ts +0 -46
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
# The Toil global (reference)
|
|
2
|
-
|
|
3
|
-
Almost the entire toiljs client API hangs off one global object, `Toil`, so your route files need no imports for the everyday things. This page is the full index: every `Toil.*` member, its TypeScript signature, and a one-line description, grouped by area. Reach for it when you know roughly what you want and just need the exact name or shape; the deeper guides (linked per section) explain the concepts.
|
|
4
|
-
|
|
5
|
-
`Toil` is not a hand-written object. It is the module namespace of the `toiljs/client` package, exposed as a global. The compiler writes a `toil-env.d.ts` at your project root containing `declare const Toil: typeof import('toiljs/client')`, so `Toil` is typed as the whole package and every member autocompletes with no import. Put another way: anything you could `import { X } from 'toiljs/client'` is reachable as `Toil.X`.
|
|
6
|
-
|
|
7
|
-
A few members are also bare globals, handed to you the same way. `Server` (the typed backend client) and `parseError` are global on their own and additionally live under `Toil` (so `Server` and `Toil.Server` are the same value, likewise `parseError`). `FastMap`, `FastSet`, `DataWriter`, and `DataReader` (the fast collections and compact binary codec from `toiljs/io`, see [Data types](../backend/data.md)) are bare globals only: they are not under `Toil`, so write `new DataWriter()`, never `new Toil.DataWriter()`.
|
|
8
|
-
|
|
9
|
-
## Components (JSX)
|
|
10
|
-
|
|
11
|
-
Drop-in components you render in JSX. See [Images](./images.md), [Scripts](./scripts.md), [Fetching data](./data-fetching.md), and [Metadata and SEO](./metadata.md) for the detail.
|
|
12
|
-
|
|
13
|
-
| Member | Signature | Description |
|
|
14
|
-
| --- | --- | --- |
|
|
15
|
-
| `Toil.Image` | `Image(props: ImageProps): ReactNode` | A drop-in `<img>` that reserves space (no layout shift), lazy-loads, and can fade in from a blur placeholder. See [Images](./images.md). |
|
|
16
|
-
| `Toil.Script` | `Script(props: ScriptProps): ReactNode` | Loads an external or inline `<script>` with a load `strategy`, deduplicated so it runs at most once. Renders nothing. See [Scripts](./scripts.md). |
|
|
17
|
-
| `Toil.Form` | `Form(props: FormProps): ReactNode` | A `<form>` that runs an action on submit (no reload) and revalidates loader data on success. See [Fetching data](./data-fetching.md). |
|
|
18
|
-
| `Toil.Slot` | `Slot(props: SlotProps): ReactNode` | Renders the parallel-route slot named `props.name` (`{ name: string; fallback?: ReactNode }`) for the current URL. See [Routing](./routing.md). |
|
|
19
|
-
| `Toil.Head` | `Head(props: HeadSpec): null` | Declarative form of `useHead`: `<Toil.Head title="..." meta={[...]} />`. Renders nothing. See [Metadata and SEO](./metadata.md). |
|
|
20
|
-
| `Toil.Metadata` | `Metadata(props: Metadata): null` | Declarative form of `useMetadata`: `<Toil.Metadata title="..." openGraph={...} />`. Renders nothing. See [Metadata and SEO](./metadata.md). |
|
|
21
|
-
| `Toil.Router` | `Router(props: { routes; layout?; notFound?; globalError?; slots? }): ReactNode` | The app router element. `Toil.mount` renders this for you, so you rarely use it directly. |
|
|
22
|
-
|
|
23
|
-
## SSR marker primitives
|
|
24
|
-
|
|
25
|
-
These mark a route's dynamic bits so the edge can server-render it (the compiler's template extractor finds them deterministically). They are transparent at runtime: in the browser they render exactly the normal tree. See [Components](./components.md) and [Rendering and SSR](./rendering.md).
|
|
26
|
-
|
|
27
|
-
| Member | Signature | Description |
|
|
28
|
-
| --- | --- | --- |
|
|
29
|
-
| `Toil.Hole` | `Hole(props: HoleProps): ReactNode` | A scalar text hole (`{ id: string; children?: ReactNode }`); renders `children` in the browser, a text insertion point under the SSR extractor. |
|
|
30
|
-
| `Toil.Repeat` | `Repeat<T>(props: RepeatProps<T>): ReactNode` | A repeat region (`{ id; each: readonly T[]; children: (item: T, index: number) => ReactNode }`); `each.map(children)` in the browser. |
|
|
31
|
-
| `Toil.RawHtml` | `RawHtml(props: RawHtmlProps): ReactNode` | A raw-HTML block hole (`{ id; html; as? }`); wraps `dangerouslySetInnerHTML` in a host element (default `div`). |
|
|
32
|
-
| `Toil.attr` | `attr(id: string, value: string): string` | An attribute-value hole, used in attribute position (`href={Toil.attr('u', d.url)}`); returns `value` unchanged in the browser. |
|
|
33
|
-
| `Toil.Island` | `Island(props: IslandProps): ReactNode` | A client-only escape hatch (`{ children? }`); renders nothing on the server and first paint, then reveals `children` after mount (so no SSR / SEO, by design). |
|
|
34
|
-
|
|
35
|
-
## Navigation
|
|
36
|
-
|
|
37
|
-
Client-side links and imperative navigation. Detailed guide: [Navigation](./navigation.md).
|
|
38
|
-
|
|
39
|
-
| Member | Signature | Description |
|
|
40
|
-
| --- | --- | --- |
|
|
41
|
-
| `Toil.Link` | `Link(props: LinkProps): ReactNode` | A client-side navigation `<a>`: no full reload, prefetches on hover/focus, falls through to the browser for external / `target` / `download` / `#hash` links. |
|
|
42
|
-
| `Toil.NavLink` | `NavLink(props: NavLinkProps): ReactNode` | A `Link` that adds an active class (default `"active"`) and `aria-current="page"` when it points at the current page. |
|
|
43
|
-
| `Toil.matchActive` | `matchActive(linkPath: string, currentPath: string, end: boolean): boolean` | Whether a link to `linkPath` is active for `currentPath` (the pure rule behind `NavLink`). |
|
|
44
|
-
| `Toil.navigate` | `navigate(href: Href, options?: NavigateOptions): void` | Navigate in code (no hook needed), pushing history or replacing with `{ replace: true }`. |
|
|
45
|
-
| `Toil.back` | `back(): void` | Go back one history entry. |
|
|
46
|
-
| `Toil.forward` | `forward(): void` | Go forward one history entry. |
|
|
47
|
-
| `Toil.refresh` | `refresh(): void` | Re-render the current route and re-run its loader (its `loading.tsx` shows while it re-fetches). |
|
|
48
|
-
| `Toil.href` | `href(path: string): Href` | Assert a runtime-built string is a valid `Href`. Escape hatch for a path assembled from data. |
|
|
49
|
-
| `Toil.prefetch` | `prefetch(href: string): void` | Warm a route's chunk ahead of navigation; a no-op for external, unknown, or already-warmed targets. |
|
|
50
|
-
| `Toil.setViewTransitions` | `setViewTransitions(enabled: boolean): void` | Enable animated View Transitions for navigation (normally set once from `client.viewTransitions`). |
|
|
51
|
-
| `Toil.setTransitions` | `setTransitions(enabled: boolean): void` | Keep the current page visible until the next route is ready (normally set once from `client.transitions`). |
|
|
52
|
-
|
|
53
|
-
## Routing and location hooks
|
|
54
|
-
|
|
55
|
-
Hooks a component uses to read where it is and to get a router handle.
|
|
56
|
-
|
|
57
|
-
| Member | Signature | Description |
|
|
58
|
-
| --- | --- | --- |
|
|
59
|
-
| `Toil.useParams` | `useParams<T extends RouteParams = RouteParams>(): T` | Read the dynamic route params, e.g. `{ id }` for `/blog/[id]`. Values are always strings. |
|
|
60
|
-
| `Toil.useNavigate` | `useNavigate(): (href: Href, options?: NavigateOptions) => void` | Returns the bare `navigate` function. |
|
|
61
|
-
| `Toil.useRouter` | `useRouter(): RouterInstance` | Returns the router handle (`push` / `replace` / `back` / `forward` / `refresh` / `revalidate` / `prefetch`). |
|
|
62
|
-
| `Toil.useLocation` | `useLocation(): string` | The current pathname, re-read on each navigation (an alias of `usePathname`). |
|
|
63
|
-
| `Toil.usePathname` | `usePathname(): string` | The current pathname, e.g. `"/blog/42"`. |
|
|
64
|
-
| `Toil.useSearchParams` | `useSearchParams(): URLSearchParams` | The query string as a `URLSearchParams`, re-read on each navigation. |
|
|
65
|
-
| `Toil.useNavigationPending` | `useNavigationPending(): boolean` | `true` while a navigation is in flight (drives a top loading bar). |
|
|
66
|
-
| `Toil.matchRoute` | `matchRoute(pattern: string, pathname: string): RouteParams \| null` | Pure route matcher: extract params, or `null` if the pattern does not match. |
|
|
67
|
-
|
|
68
|
-
## Route data and mutations
|
|
69
|
-
|
|
70
|
-
Loaders read data on navigation, actions write it. See [Fetching data](./data-fetching.md).
|
|
71
|
-
|
|
72
|
-
| Member | Signature | Description |
|
|
73
|
-
| --- | --- | --- |
|
|
74
|
-
| `Toil.useLoaderData` | `useLoaderData<L extends LoaderFunction>(loader: L): Awaited<ReturnType<L>>` | Read the data the current route's `loader` returned. Passing `loader` infers the type; the no-arg `useLoaderData<T>()` returns `unknown` unless you supply `T`. |
|
|
75
|
-
| `Toil.revalidate` | `revalidate(href?: string): void` | Invalidate loader data and re-render so the active route (or a given href) re-fetches. Call after a mutation; usable outside React. |
|
|
76
|
-
| `Toil.invalidateLoaderData` | `invalidateLoaderData(href?: string): void` | Drop cached loader data (all routes, or one href) without re-rendering. |
|
|
77
|
-
| `Toil.useAction` | `useAction<TInput = void, TData = unknown>(fn: (input: TInput) => TData \| Promise<TData>, options?: UseActionOptions<TData>): ActionHandle<TInput, TData>` | Run a mutation with pending / error / result tracking; revalidates loader data on success. |
|
|
78
|
-
|
|
79
|
-
## Head and metadata
|
|
80
|
-
|
|
81
|
-
Set the document `<head>` from a component or resolve a route's metadata. See [Metadata and SEO](./metadata.md).
|
|
82
|
-
|
|
83
|
-
| Member | Signature | Description |
|
|
84
|
-
| --- | --- | --- |
|
|
85
|
-
| `Toil.useHead` | `useHead(spec: HeadSpec): void` | Apply a title / `<meta>` / `<link>` contribution for the component's lifetime (reverts on unmount, composes across the tree). |
|
|
86
|
-
| `Toil.useTitle` | `useTitle(title: string): void` | Set `document.title` for the component's lifetime. |
|
|
87
|
-
| `Toil.mergeHead` | `mergeHead(specs: readonly HeadSpec[]): ResolvedHead` | Merge head specs in order: the last `title` wins, `meta` dedupes by name/property, `link` by rel+href. |
|
|
88
|
-
| `Toil.useMetadata` | `useMetadata(metadata: Metadata): void` | Apply a route-style `Metadata` object from inside any component (the runtime counterpart of a route's `metadata` export). |
|
|
89
|
-
| `Toil.resolveMetadata` | `resolveMetadata(metadata: Metadata): HeadSpec` | Expand a `Metadata` object into a title plus concrete `<meta>` / `<link>` tags. |
|
|
90
|
-
|
|
91
|
-
## Page search
|
|
92
|
-
|
|
93
|
-
Query the statically-baked index of your pages' metadata. See [Search](./search.md).
|
|
94
|
-
|
|
95
|
-
| Member | Signature | Description |
|
|
96
|
-
| --- | --- | --- |
|
|
97
|
-
| `Toil.searchPages` | `searchPages(query: string, options?: PageSearchOptions): PageSearchResult[]` | Rank the registered page index against a query (pure, framework-agnostic; AND semantics across terms). |
|
|
98
|
-
| `Toil.usePageSearch` | `usePageSearch(query: string, options?: PageSearchOptions): PageSearch` | React binding for `searchPages`, memoized, with a `goTo` helper that navigates to a match. |
|
|
99
|
-
| `Toil.registerPages` | `registerPages(pages: readonly PageMeta[]): void` | Replace the live page index. Called once at startup by the generated bundle; rarely called by user code. |
|
|
100
|
-
| `Toil.getPages` | `getPages(): readonly PageMeta[]` | The registered page index (every page, including dynamic ones). Empty before registration. |
|
|
101
|
-
| `Toil.pagePath` | `pagePath(target: string \| PageMeta \| PageSearchResult): string` | Normalize a result / page / raw path to its route path string. |
|
|
102
|
-
|
|
103
|
-
## Realtime
|
|
104
|
-
|
|
105
|
-
Open a channel or a typed stream to the backend. See [Channels](../realtime/channels.md) and [Streams](../realtime/streams.md).
|
|
106
|
-
|
|
107
|
-
| Member | Signature | Description |
|
|
108
|
-
| --- | --- | --- |
|
|
109
|
-
| `Toil.connectChannel` | `connectChannel(onMessage: (data: ChannelData) => void, options?: ChannelOptions): Channel` | Open a WebSocket channel to the backend, invoking `onMessage` per frame; returns `send` / `close`. |
|
|
110
|
-
| `Toil.useChannel` | `useChannel(options?: ChannelOptions): ChannelHook` | React hook over `connectChannel`: connects on mount, tracks `connected` + `messages`, exposes `send`. |
|
|
111
|
-
| `Toil.resolveChannelUrl` | `resolveChannelUrl(path?: string, location?: { protocol: string; host: string }): string` | Derive the channel's `ws(s)://` URL from the current page location. |
|
|
112
|
-
| `Toil.makeStreamClient` | `makeStreamClient(routes: Record<string, string>, origin?: string, encoders?: Record<string, (msg: never) => Uint8Array>): StreamClient` | Build the `Server.Stream` client from the generated route map. Used by generated code; rarely called directly. |
|
|
113
|
-
|
|
114
|
-
## Backend client, errors, bootstrap
|
|
115
|
-
|
|
116
|
-
| Member | Signature | Description |
|
|
117
|
-
| --- | --- | --- |
|
|
118
|
-
| `Toil.Server` | `Server.REST.<controller>.<route>(args)` / `Server.Stream.<class>.connect(path?)` / `Server.<service>.<method>(args)` | The typed backend surface. Its shape is generated into `shared/server.ts`; this global is the runtime behind it. See [Fetching data](./data-fetching.md). |
|
|
119
|
-
| `Toil.parseError` | `parseError(err: unknown): string` | Extract a human-readable message from an unknown thrown value: `Error.message`, else `String(err)`. |
|
|
120
|
-
| `Toil.mount` | `mount(routes: RouteDef[], layout?: LayoutLoader, notFound?: NotFoundLoader, globalError?: ErrorComponentLoader, slots?: Record<string, RouteDef[]>): void` | Boot the app into `#root` and start idle link prefetching. Called by the generated entry file; you rarely call it yourself. |
|
|
121
|
-
|
|
122
|
-
## Auth
|
|
123
|
-
|
|
124
|
-
The whole password-auth client lives under `Toil.Auth`, and its error family is exposed on `Toil.*` (and mirrored under `Toil.Auth.*`) so you can branch on it. The password never leaves the browser. See [Auth](../auth/README.md).
|
|
125
|
-
|
|
126
|
-
| Member | Signature | Description |
|
|
127
|
-
| --- | --- | --- |
|
|
128
|
-
| `Toil.Auth.register` | `register(username: string, password: string, email: string, opts?: AuthOptions): Promise<void>` | Create an account (only a derived public key is ever sent). Throws `UsernameTakenError` / `EmailInUseError` on conflict. |
|
|
129
|
-
| `Toil.Auth.login` | `login(username: string, password: string, opts?: AuthOptions): Promise<Uint8Array>` | Log in with mutual authentication; resolves to the opaque session token. |
|
|
130
|
-
| `Toil.Auth.confirmEmail` | `confirmEmail(token: string, opts?: AuthOptions): Promise<void>` | Confirm an account from the one-time token in the emailed link. |
|
|
131
|
-
| `Toil.Auth.resendConfirmation` | `resendConfirmation(email: string, opts?: AuthOptions): Promise<void>` | Ask the server to re-send the confirmation email (never reveals whether the address exists). |
|
|
132
|
-
| `Toil.Auth.requestPasswordReset` | `requestPasswordReset(email: string, opts?: AuthOptions): Promise<void>` | Begin a password reset by emailing a link (anti-enumeration: always resolves). |
|
|
133
|
-
| `Toil.Auth.resetPassword` | `resetPassword(token: string, newPassword: string, opts?: AuthOptions): Promise<void>` | Complete a reset from the token plus a new password. |
|
|
134
|
-
| `Toil.Auth.verifyTwoFactor` | `verifyTwoFactor(twoFaId: string, code: string, opts?: AuthOptions): Promise<Uint8Array>` | Finish a 2FA login by submitting the code for `twoFaId`; resolves to the session token. |
|
|
135
|
-
| `Toil.Auth.setupTwoFactor` | `setupTwoFactor(method: number, opts?: AuthOptions): Promise<void>` | Begin enabling or disabling 2FA for the current session user (pass a `TwoFactorMethod` value). |
|
|
136
|
-
| `Toil.Auth.confirmTwoFactorSetup` | `confirmTwoFactorSetup(code: string, opts?: AuthOptions): Promise<void>` | Confirm a pending `setupTwoFactor` with the delivered code. |
|
|
137
|
-
| `Toil.Auth.twoFactorStatus` | `twoFactorStatus(opts?: AuthOptions): Promise<number>` | The current user's 2FA method (a `TwoFactorMethod` value; `0` means off). |
|
|
138
|
-
| `Toil.Auth.TwoFactorMethod` | `{ None: 0, Email: 1 }` | The 2FA method values, mirroring the server enum. |
|
|
139
|
-
|
|
140
|
-
The typed error surface (each error carries a stable `code`, and every subclass maps 1:1 to an `AuthErrorCode`):
|
|
141
|
-
|
|
142
|
-
| Member | Signature | Description |
|
|
143
|
-
| --- | --- | --- |
|
|
144
|
-
| `Toil.AuthError` | `class AuthError extends Error { readonly code: AuthErrorCode }` | Base class for every auth error. `err instanceof Toil.AuthError` narrows the whole family; `err.code` discriminates within it. |
|
|
145
|
-
| `Toil.AuthErrorCode` | `enum AuthErrorCode` (string values) | The stable, machine-readable discriminant carried as `err.code`. Branch on this, never on `err.message` or `err.name`. |
|
|
146
|
-
| `Toil.UsernameTakenError` | `class UsernameTakenError extends AuthError` | register: the username is already registered (`AuthErrorCode.UsernameTaken`). |
|
|
147
|
-
| `Toil.EmailInUseError` | `class EmailInUseError extends AuthError` | register: the email is already in use (`AuthErrorCode.EmailInUse`). |
|
|
148
|
-
| `Toil.InvalidCredentialsError` | `class InvalidCredentialsError extends AuthError` | login: wrong username or password (`AuthErrorCode.InvalidCredentials`). |
|
|
149
|
-
| `Toil.EmailNotConfirmedError` | `class EmailNotConfirmedError extends AuthError` | login: valid credential, but the email is not confirmed (`AuthErrorCode.EmailNotConfirmed`). |
|
|
150
|
-
| `Toil.TwoFactorRequiredError` | `class TwoFactorRequiredError extends AuthError { readonly twoFaId: string }` | login: a second factor is required; echo `err.twoFaId` to `verifyTwoFactor` (`AuthErrorCode.TwoFactorRequired`). |
|
|
151
|
-
| `Toil.ServerAuthFailedError` | `class ServerAuthFailedError extends AuthError` | login/2fa: the server failed to prove its identity, possible MITM (`AuthErrorCode.ServerAuthFailed`). |
|
|
152
|
-
| `Toil.TwoFactorCodeError` | `class TwoFactorCodeError extends AuthError` | 2fa: the code was wrong, expired, or already used (`AuthErrorCode.TwoFactorCodeInvalid`). |
|
|
153
|
-
| `Toil.ConfirmationInvalidError` | `class ConfirmationInvalidError extends AuthError` | confirm: the confirmation link was invalid or expired (`AuthErrorCode.ConfirmationInvalid`). |
|
|
154
|
-
| `Toil.PasswordResetInvalidError` | `class PasswordResetInvalidError extends AuthError` | reset: the reset link was invalid or expired (`AuthErrorCode.PasswordResetInvalid`). |
|
|
155
|
-
|
|
156
|
-
The `AuthErrorCode` string values:
|
|
157
|
-
|
|
158
|
-
```ts
|
|
159
|
-
enum AuthErrorCode {
|
|
160
|
-
RequestFailed = 'request_failed',
|
|
161
|
-
ProtocolError = 'protocol_error',
|
|
162
|
-
UsernameTaken = 'username_taken',
|
|
163
|
-
EmailInUse = 'email_in_use',
|
|
164
|
-
RegistrationRejected = 'registration_rejected',
|
|
165
|
-
InvalidCredentials = 'invalid_credentials',
|
|
166
|
-
EmailNotConfirmed = 'email_not_confirmed',
|
|
167
|
-
TwoFactorRequired = 'two_factor_required',
|
|
168
|
-
ServerAuthFailed = 'server_auth_failed',
|
|
169
|
-
TwoFactorCodeInvalid = 'two_factor_code_invalid',
|
|
170
|
-
TwoFactorSetupFailed = 'two_factor_setup_failed',
|
|
171
|
-
ConfirmationInvalid = 'confirmation_invalid',
|
|
172
|
-
PasswordResetInvalid = 'password_reset_invalid',
|
|
173
|
-
}
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
Catch by class for the common branches, or on `err.code` for a precise check:
|
|
177
|
-
|
|
178
|
-
```tsx
|
|
179
|
-
try {
|
|
180
|
-
const token = await Toil.Auth.login(username, password);
|
|
181
|
-
// ... persist the session token and redirect
|
|
182
|
-
} catch (err) {
|
|
183
|
-
if (err instanceof Toil.EmailNotConfirmedError) return promptEmailConfirmation();
|
|
184
|
-
if (err instanceof Toil.TwoFactorRequiredError) return promptTwoFactorCode(err.twoFaId);
|
|
185
|
-
if (err instanceof Toil.AuthError && err.code === Toil.AuthErrorCode.InvalidCredentials) {
|
|
186
|
-
return setError('Incorrect username or password.');
|
|
187
|
-
}
|
|
188
|
-
throw err;
|
|
189
|
-
}
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
## A note on types
|
|
193
|
-
|
|
194
|
-
Every member above is a value, and values on `Toil.*` need no import: `Toil.Link`, `Toil.useParams`, `Toil.Auth.login`. Types are different. In type position, only a small set are namespaced as `Toil.<Type>`, because the generated `toil-env.d.ts` aliases exactly these under a `declare namespace Toil` block:
|
|
195
|
-
|
|
196
|
-
`LoaderArgs`, `LoaderFunction`, `Revalidate`, `Metadata`, `GenerateMetadata`, `GenerateStaticParams`, `StaticParams`, `RouteErrorProps`, `Href`, `RoutePath`, `PageMeta`, `SearchHints`.
|
|
197
|
-
|
|
198
|
-
So a loader can annotate its argument with no import:
|
|
199
|
-
|
|
200
|
-
```tsx
|
|
201
|
-
export const loader = async ({ params }: Toil.LoaderArgs) => { /* ... */ };
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
Every other exported type (for example `LinkProps`, `NavLinkState`, `NavigateOptions`, `RouterInstance`, `ImageProps`, `ScriptProps`, `FormProps`, `ActionState`) is not in that namespace, so it must be imported from the package:
|
|
205
|
-
|
|
206
|
-
```tsx
|
|
207
|
-
import type { ImageProps } from 'toiljs/client';
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
## Related
|
|
211
|
-
|
|
212
|
-
- [Navigation](./navigation.md): links, active state, and navigating in code.
|
|
213
|
-
- [Components](./components.md): the built-in components and the SSR marker primitives.
|
|
214
|
-
- [Fetching data](./data-fetching.md): the `Server` client, loaders, actions, and forms.
|
|
215
|
-
- [Metadata and SEO](./metadata.md): titles, descriptions, and social-share tags per route.
|
|
216
|
-
- [Auth](../auth/README.md): the full password-auth client and its error handling.
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
# Getting started
|
|
2
|
-
|
|
3
|
-
toiljs is a full-stack web framework: you write a React frontend and a TypeScript backend in one project, and toiljs ships both together. This section takes you from "nothing installed" to "a small feature running end to end."
|
|
4
|
-
|
|
5
|
-
## What toiljs is
|
|
6
|
-
|
|
7
|
-
Think of a normal web app as two programs that have to agree with each other:
|
|
8
|
-
|
|
9
|
-
- A **frontend**: the React code that runs in your user's browser.
|
|
10
|
-
- A **backend**: the code that runs on a server, answers requests, and talks to a database.
|
|
11
|
-
|
|
12
|
-
Normally these live in separate projects, speak to each other over hand-written HTTP calls, and drift apart until something breaks at runtime. toiljs puts both in one repository and wires them together with types, so a change on one side shows up as a compile error on the other side instead of a bug in production.
|
|
13
|
-
|
|
14
|
-
The twist is what your backend becomes. You write it in TypeScript, but toiljs does not run it in Node.js. Instead, a compiler called **toilscript** turns your backend into **WebAssembly** (often shortened to "Wasm"): a small, fast, sandboxed program that runs at the **edge**. "Edge" just means servers spread all over the world, close to your users, so requests do not have to travel to one far-away data center. A worldwide database called **ToilDB** is built in, so you can store and read data without setting up or connecting to a database yourself.
|
|
15
|
-
|
|
16
|
-
New terms, defined once:
|
|
17
|
-
|
|
18
|
-
- **WebAssembly / Wasm**: a compact binary format that runs code in a locked-down sandbox at near-native speed. Your backend compiles to a single `.wasm` file.
|
|
19
|
-
- **toilscript**: the compiler that turns your TypeScript backend into that `.wasm` file. It accepts a strict subset of TypeScript (more on that below).
|
|
20
|
-
- **Dacely edge**: the global network of servers that runs your `.wasm` backend.
|
|
21
|
-
- **ToilDB**: the built-in database that lives on the edge next to your code.
|
|
22
|
-
|
|
23
|
-
## The client / server / shared mental model
|
|
24
|
-
|
|
25
|
-
Every toiljs project is organized into three folders. The most important thing to learn first is **where each piece of code actually runs**.
|
|
26
|
-
|
|
27
|
-
```mermaid
|
|
28
|
-
flowchart LR
|
|
29
|
-
A["Your project<br/>(one repo)"] -->|toiljs build| B["client bundle<br/>React + JS"]
|
|
30
|
-
A -->|toilscript compiles| C["server.wasm<br/>your backend"]
|
|
31
|
-
B --> U["User's browser"]
|
|
32
|
-
C --> E["Dacely edge<br/>(worldwide servers)"]
|
|
33
|
-
E --> D[("ToilDB<br/>global database")]
|
|
34
|
-
U <-->|"HTTP / realtime"| E
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
- **`client/`** is your React app: pages, components, and styles. It is bundled by [Vite](https://vitejs.dev) and runs **in the browser**.
|
|
38
|
-
- **`server/`** is your backend: HTTP routes, database access, auth. It is compiled by toilscript to `build/server/release.wasm` and runs **on the edge** (and locally when you run the dev server).
|
|
39
|
-
- **`shared/`** holds a file that toiljs **generates for you** (`shared/server.ts`). It is a fully typed client: the browser calls your backend through a `Server` object, and TypeScript checks every call. You do not write this file by hand.
|
|
40
|
-
|
|
41
|
-
Here is the loop in one picture:
|
|
42
|
-
|
|
43
|
-
```mermaid
|
|
44
|
-
flowchart TD
|
|
45
|
-
W["client/routes/page.tsx<br/>(browser)"] -->|"Server.REST.likes.like()"| G["shared/server.ts<br/>(generated typed client)"]
|
|
46
|
-
G -->|"HTTP request"| S["server/routes/Likes.ts<br/>(your @rest route, in wasm)"]
|
|
47
|
-
S -->|"read / write"| DB[("ToilDB")]
|
|
48
|
-
S -->|"typed response"| W
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
You write both ends in TypeScript, and the generated `shared/server.ts` in the middle keeps them in sync.
|
|
52
|
-
|
|
53
|
-
## Two rules to keep in mind
|
|
54
|
-
|
|
55
|
-
These two facts explain most of how toiljs backends behave. They are covered in depth later, but it helps to meet them now.
|
|
56
|
-
|
|
57
|
-
1. **The server runs one fresh instance per request.** Every request gets a brand-new copy of your `.wasm`, and its memory is wiped when the request ends. So a normal variable you set in one request is gone by the next request. Anything that must survive (accounts, counters, posts) has to go into **ToilDB** or another store. Nothing in a plain module-level variable persists.
|
|
58
|
-
|
|
59
|
-
2. **The server is not Node.js.** toilscript compiles a strict subset of TypeScript, so you cannot `import` an arbitrary npm package into `server/` or use Node APIs like `fs`. Instead, toiljs gives you built-in globals for the common needs: `crypto`, cookies, email, the database, and more. See [Types](../concepts/types.md) and [Decorators](../concepts/decorators.md) for the details.
|
|
60
|
-
|
|
61
|
-
The client side, by contrast, is normal React. You can use React libraries and browser APIs there as usual.
|
|
62
|
-
|
|
63
|
-
## The getting-started path
|
|
64
|
-
|
|
65
|
-
Work through these pages in order:
|
|
66
|
-
|
|
67
|
-
1. **[Installation](./installation.md)**: check your Node.js version and install the toiljs command-line tool.
|
|
68
|
-
2. **[Create a project](./create-project.md)**: scaffold a new app and see what you get.
|
|
69
|
-
3. **[Project structure](./project-structure.md)**: a tour of every folder and file, and where each one runs.
|
|
70
|
-
4. **[Your first app](./first-app.md)**: build a tiny feature end to end, a page that calls a backend route and reads and writes one piece of ToilDB data.
|
|
71
|
-
5. **[Migrating an existing app](./migrating.md)**: bring a React app you already have into toiljs.
|
|
72
|
-
6. **[Deploy](./deploy.md)**: build for production and self-host it, and how the managed edge fits in.
|
|
73
|
-
|
|
74
|
-
## Related
|
|
75
|
-
|
|
76
|
-
- [Documentation home](../README.md)
|
|
77
|
-
- [The CLI reference](../cli/README.md)
|
|
78
|
-
- [Frontend overview](../frontend/README.md)
|
|
79
|
-
- [Backend overview](../backend/README.md)
|
|
80
|
-
- [Database overview](../database/README.md)
|
|
81
|
-
- [Compute tiers (where code runs)](../concepts/tiers.md)
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
# Create a project
|
|
2
|
-
|
|
3
|
-
Scaffold a brand-new toiljs app with one command. The CLI asks a few questions, writes the files, and (optionally) installs dependencies for you.
|
|
4
|
-
|
|
5
|
-
## Why and when
|
|
6
|
-
|
|
7
|
-
`toiljs create` is how every project starts. It wires up the enforced toiljs presets (TypeScript, ESLint, and Prettier config), the file-based routing, and a working client and server, so you get a project that builds and runs on the first try. Use it for a new app. To bring an **existing** React app into toiljs instead, see [Migrating](./migrating.md).
|
|
8
|
-
|
|
9
|
-
## The command
|
|
10
|
-
|
|
11
|
-
```sh
|
|
12
|
-
toiljs create my-app
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Replace `my-app` with your project name (it becomes the folder name). If you leave the name off, the wizard asks for one.
|
|
16
|
-
|
|
17
|
-
By default this runs an interactive wizard. To skip every question and accept the defaults (handy for scripts and CI), add `--yes`:
|
|
18
|
-
|
|
19
|
-
```sh
|
|
20
|
-
toiljs create my-app --yes
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## What the wizard asks
|
|
24
|
-
|
|
25
|
-
Running `toiljs create` walks you through these prompts. Each one has a flag you can pass instead, so you can answer some or all of them up front.
|
|
26
|
-
|
|
27
|
-
| Prompt | What it decides | Flag | Default |
|
|
28
|
-
| --- | --- | --- | --- |
|
|
29
|
-
| Project name | The folder and package name | (the first argument) | `my-toil-app` |
|
|
30
|
-
| Which template? | How much starter code you get | `-t, --template <app\|minimal>` | `app` |
|
|
31
|
-
| Styling | The CSS flavor for `client/` | `--style <css\|sass\|less\|stylus>` | `css` |
|
|
32
|
-
| Add Tailwind CSS? | Adds Tailwind on top of the styling | `--tailwind` / `--no-tailwind` | off |
|
|
33
|
-
| AI assistant files | Editor hint files for Claude, Cursor, Codex, Copilot | `--no-ai` (to skip) | all |
|
|
34
|
-
| Optimize images at build time? | Resize and compress imported images | `--images` / `--no-images` | on |
|
|
35
|
-
| Initialize a git repository? | Runs `git init` and stages the files | `--git` / `--no-git` | on |
|
|
36
|
-
| Install dependencies now? | Runs your package manager's install | `--install` / `--no-install` | on |
|
|
37
|
-
|
|
38
|
-
Two more flags do not have a prompt:
|
|
39
|
-
|
|
40
|
-
- `--pm <npm\|pnpm\|yarn\|bun>` picks the package manager to install with (default `npm`).
|
|
41
|
-
- `-y, --yes` accepts every default and runs without any prompts.
|
|
42
|
-
|
|
43
|
-
### The two templates
|
|
44
|
-
|
|
45
|
-
- **`app`** (default) is the full starter: a landing page, a shared layout, styles, and a set of demo routes that show off HTTP routes, typed RPC, cookies, auth, and a ToilDB-backed guestbook. Great for learning by reading real, working code.
|
|
46
|
-
- **`minimal`** is the bare minimum: a layout, a single home page, and a tiny server handler with one example endpoint. Great when you want a clean slate.
|
|
47
|
-
|
|
48
|
-
A fully non-interactive example:
|
|
49
|
-
|
|
50
|
-
```sh
|
|
51
|
-
toiljs create my-app --yes --template minimal --style css --no-tailwind --pm pnpm
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
## What gets scaffolded
|
|
55
|
-
|
|
56
|
-
Here is the shape of a new **`app`** project. The exact set of demo routes may grow over time, so this is trimmed for readability.
|
|
57
|
-
|
|
58
|
-
```text
|
|
59
|
-
my-app/
|
|
60
|
-
package.json scripts + dependencies (toiljs, react, toilscript, ...)
|
|
61
|
-
toil.config.ts client/build config (SEO, images, page transitions)
|
|
62
|
-
toilconfig.json server (wasm) build config for toilscript
|
|
63
|
-
tsconfig.json TypeScript config for the client
|
|
64
|
-
eslint.config.js linting preset
|
|
65
|
-
.prettierrc formatting preset
|
|
66
|
-
.gitignore ignores build output, generated files, and .env files
|
|
67
|
-
toil-env.d.ts generated editor types for client globals (Toil.*)
|
|
68
|
-
toil-routes.d.ts generated typed-route names (filled in on first build)
|
|
69
|
-
README.md
|
|
70
|
-
CLAUDE.md / AGENTS.md AI assistant hint files (if you kept them)
|
|
71
|
-
|
|
72
|
-
client/ your React app (runs in the browser)
|
|
73
|
-
toil.tsx the client entry: mounts routes + layout
|
|
74
|
-
layout.tsx the root layout that wraps every page
|
|
75
|
-
404.tsx the not-found page
|
|
76
|
-
global-error.tsx the top-level error page
|
|
77
|
-
routes/ file-based pages (index.tsx = "/", about.tsx = "/about", ...)
|
|
78
|
-
components/ shared React components
|
|
79
|
-
styles/main.css global styles
|
|
80
|
-
public/ static files served as-is (favicon, robots.txt, images)
|
|
81
|
-
|
|
82
|
-
server/ your backend (compiled to wasm, runs on the edge)
|
|
83
|
-
main.ts the entry: wires the handler + imports your surface modules
|
|
84
|
-
tsconfig.json server-only TS config (loads the toilscript editor plugin)
|
|
85
|
-
toil-server-env.d.ts generated editor types for server globals (Cookie, crypto, ...)
|
|
86
|
-
core/ your top-level request handler and shared logic
|
|
87
|
-
models/ @data classes (the typed wire types)
|
|
88
|
-
routes/ @rest controllers (HTTP endpoints)
|
|
89
|
-
services/ @service classes and @remote functions (typed RPC)
|
|
90
|
-
migrations/ ToilDB schema migrations (README explains the convention)
|
|
91
|
-
scheduled/ reserved for scheduled tasks
|
|
92
|
-
|
|
93
|
-
shared/ (created by the build)
|
|
94
|
-
server.ts GENERATED typed client: the Server proxy + @data codecs
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
The **`minimal`** template is the same layout with far fewer files: `client/` has just `layout.tsx`, `routes/index.tsx`, and `styles/main.css`; `server/` has `main.ts` and `core/AppHandler.ts` with a single example endpoint.
|
|
98
|
-
|
|
99
|
-
A few files are worth calling out now, and the next page ([Project structure](./project-structure.md)) walks through all of them:
|
|
100
|
-
|
|
101
|
-
- **`shared/server.ts` does not exist yet** in a fresh project. It is generated the first time you run `toiljs dev` or `toiljs build`. That is normal and expected.
|
|
102
|
-
- **`toil-routes.d.ts`** starts as a stub and gets filled in with your real route names on the first build, which is what makes `Toil.Link` route names type-check.
|
|
103
|
-
- **`.env` and `.env.secrets` are not created** for you. You add them yourself when you need local environment variables or secrets. They are already listed in `.gitignore` so you never commit them. See [Environment and secrets](../services/environment.md).
|
|
104
|
-
|
|
105
|
-
## Run it
|
|
106
|
-
|
|
107
|
-
Once scaffolding (and install) finishes, the CLI prints your next steps:
|
|
108
|
-
|
|
109
|
-
```sh
|
|
110
|
-
cd my-app
|
|
111
|
-
npm run dev
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
`npm run dev` runs `toiljs dev`, which builds your server to wasm, generates `shared/server.ts`, and starts the dev server with hot reload. Open the printed URL (by default `http://localhost:3000`) and you have a live app.
|
|
115
|
-
|
|
116
|
-
If you told the wizard **not** to install dependencies, run `npm install` first.
|
|
117
|
-
|
|
118
|
-
## Gotchas and notes
|
|
119
|
-
|
|
120
|
-
- **Scaffolding into a non-empty folder** asks for confirmation in interactive mode, and fails in `--yes` mode. Create into a fresh, empty directory.
|
|
121
|
-
- **The project name must be a valid package name** and must stay inside the current directory (no `..`, no absolute paths).
|
|
122
|
-
- **Git init is best-effort.** If `git` is not installed, the CLI skips that step and keeps going.
|
|
123
|
-
- **You do not run `toilscript` yourself.** It is added as a dependency and driven by `toiljs dev` / `toiljs build`.
|
|
124
|
-
|
|
125
|
-
## Related
|
|
126
|
-
|
|
127
|
-
- [Project structure](./project-structure.md)
|
|
128
|
-
- [Your first app](./first-app.md)
|
|
129
|
-
- [The CLI reference](../cli/README.md)
|
|
130
|
-
- [Configuration](../concepts/config.md)
|
|
131
|
-
- [Styling](../frontend/styling.md)
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
# Deploying a toiljs app
|
|
2
|
-
|
|
3
|
-
This page is an honest look at how you get a toiljs app in front of real users. There are two paths, and it helps to be clear about which one exists today.
|
|
4
|
-
|
|
5
|
-
- **Self-host it yourself.** You build the app and run it on a machine you control, with `toiljs build` then `toiljs start`. This works right now, on your laptop, a VPS, or any server that can run Node.js.
|
|
6
|
-
- **Run it on the managed Dacely edge.** This is the platform toiljs is built for: a worldwide fleet of servers that runs your compiled backend close to every user. It is the target the whole framework is designed around.
|
|
7
|
-
|
|
8
|
-
One thing up front, so you do not go looking for it: **there is no `toiljs deploy` command.** The CLI can build and self-host; pushing a build onto the managed edge is a platform step, not a CLI subcommand. The rest of this page covers what you can do today (self-hosting) and what the managed edge gives you.
|
|
9
|
-
|
|
10
|
-
## The one build powers both
|
|
11
|
-
|
|
12
|
-
Both paths serve the exact same artifacts. `toiljs build` produces them once:
|
|
13
|
-
|
|
14
|
-
```mermaid
|
|
15
|
-
flowchart LR
|
|
16
|
-
A["Your project"] -->|toiljs build| B["build/client/<br/>(HTML, JS, CSS, assets)"]
|
|
17
|
-
A -->|toiljs build| C["build/server/release.wasm<br/>(your backend)"]
|
|
18
|
-
B --> H["toiljs start<br/>(self-host)"]
|
|
19
|
-
C --> H
|
|
20
|
-
B --> E["managed Dacely edge<br/>(worldwide)"]
|
|
21
|
-
C --> E
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
So you never build differently for the two targets. You build once, then either run it yourself or hand the same output to the edge.
|
|
25
|
-
|
|
26
|
-
## Self-hosting with `toiljs start`
|
|
27
|
-
|
|
28
|
-
`toiljs start` runs your built app on a fast production HTTP server. It serves your static client, dispatches dynamic requests into your `release.wasm`, does server-side rendering, runs daemons, and exposes a `/_toil` websocket channel. Use it to put your app on your own machine or server instead of the managed edge.
|
|
29
|
-
|
|
30
|
-
### Step 1: build
|
|
31
|
-
|
|
32
|
-
`start` serves whatever is in `build/`, so you must build first. If there is no build, `start` exits with an error (it looks for `build/client/index.html`).
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
npm run build
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
### Step 2: start
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
# Serve on http://127.0.0.1:3000 (loopback only, one worker per CPU).
|
|
42
|
-
npx toiljs start
|
|
43
|
-
|
|
44
|
-
# Accept outside connections, on port 8080, with 4 worker processes.
|
|
45
|
-
npx toiljs start --host 0.0.0.0 --port 8080 --threads 4
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### start flags
|
|
49
|
-
|
|
50
|
-
| Flag | Meaning |
|
|
51
|
-
| --- | --- |
|
|
52
|
-
| `--port <n>` | Port to listen on. Default `3000` (or `client.port` from your config). |
|
|
53
|
-
| `--host <host>` | Address to bind. Default `127.0.0.1`, which is **loopback only** (reachable just from the same machine). Pass `0.0.0.0` to accept connections from other machines. |
|
|
54
|
-
| `--threads <n>` | Number of HTTP worker processes. Default is automatic (one per available CPU). Pass `1` to disable the worker pool. `--workers` is an accepted alias, and you can also set `server.threads` in your config or the `TOILJS_THREADS` environment variable. |
|
|
55
|
-
| `--root <dir>` | Run against a project in another directory instead of the current one. |
|
|
56
|
-
|
|
57
|
-
These flags are verified against the CLI. Note that `--host` and `--threads` are `start`-only: `toiljs dev` always binds locally and does not take them. For the full command reference, see [the CLI](../cli/README.md#toiljs-start).
|
|
58
|
-
|
|
59
|
-
### A realistic self-host
|
|
60
|
-
|
|
61
|
-
On a small server (say a VPS), a minimal run looks like this:
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
# Install and build.
|
|
65
|
-
npm ci
|
|
66
|
-
npm run build
|
|
67
|
-
|
|
68
|
-
# Bind on all interfaces so a reverse proxy or the public can reach it.
|
|
69
|
-
npx toiljs start --host 0.0.0.0 --port 8080 --threads 4
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
Then put a reverse proxy (nginx, Caddy) in front for TLS and a real hostname, pointing it at `http://127.0.0.1:8080`. Keep the process alive with your usual tool (systemd, pm2, a container restart policy).
|
|
73
|
-
|
|
74
|
-
### Self-host gotchas
|
|
75
|
-
|
|
76
|
-
- **`start` needs a fresh build.** It serves `build/`, not your source. After any code change, run `toiljs build` again before restarting.
|
|
77
|
-
- **The default bind is loopback.** With no `--host`, only the same machine can reach it. Set `--host 0.0.0.0` (usually behind a reverse proxy) to serve real traffic.
|
|
78
|
-
- **Self-host is one place, not the whole world.** You get one server (or however many you run yourself). The latency and worldwide reach of the managed edge is exactly the thing self-hosting does not give you.
|
|
79
|
-
- **The database is different.** Self-hosting runs the built server, but ToilDB's worldwide data layer is an edge feature. Treat self-host as a way to run and test your build, not as a substitute for the managed edge's global database.
|
|
80
|
-
|
|
81
|
-
## The managed Dacely edge
|
|
82
|
-
|
|
83
|
-
The managed **Dacely edge** is the platform toiljs targets: a fleet of servers in many cities that runs your compiled backend as close to each user as possible, backed by the worldwide **ToilDB** database. You write one project, and the build already decides which part of your code belongs to which layer of the edge.
|
|
84
|
-
|
|
85
|
-
Your backend runs across four **compute tiers**, from a per-request handler at the very edge up to a single worldwide coordinator:
|
|
86
|
-
|
|
87
|
-
| Tier | Name | Where it runs | Typical code |
|
|
88
|
-
| --- | --- | --- | --- |
|
|
89
|
-
| **L1** | Hot / edge | The node nearest the user, fresh per request | `@rest`, `@service` / `@remote` |
|
|
90
|
-
| **L2** | Regional | One box per connection, per region | `@stream` (Regional) |
|
|
91
|
-
| **L3** | Continental | One box per connection, per continent | `@stream` (Continental) |
|
|
92
|
-
| **L4** | Global / daemon | Exactly one leader worldwide | `@daemon`, `@scheduled` |
|
|
93
|
-
|
|
94
|
-
Because the same `toiljs build` output feeds the edge, everything you built and tested with `toiljs dev` and `toiljs start` is what runs there. The edge decides each server's role for you; you do not configure tiers by hand. For the full picture of what each tier means and how to write for it, see [Compute tiers (L1 to L4)](../concepts/tiers.md).
|
|
95
|
-
|
|
96
|
-
## Related
|
|
97
|
-
|
|
98
|
-
- [The CLI](../cli/README.md): the full reference for `build` and `start` and every flag.
|
|
99
|
-
- [Configuration (`toil.config.ts`)](../concepts/config.md): `server.threads` and the other self-host knobs.
|
|
100
|
-
- [Compute tiers (L1 to L4)](../concepts/tiers.md): how your code maps onto the managed edge.
|
|
101
|
-
- [Getting started](./README.md): the path from install to a running feature.
|