toiljs 0.0.115 → 0.0.117

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 (326) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +16 -7
  3. package/TYPESCRIPT_LAW.md +1946 -2073
  4. package/build/backend/.tsbuildinfo +1 -1
  5. package/build/cli/.tsbuildinfo +1 -1
  6. package/build/cli/index.js +2375 -258
  7. package/build/client/.tsbuildinfo +1 -1
  8. package/build/client/dev/devtools.js +1 -1
  9. package/build/client/dev/error-overlay.js +1 -1
  10. package/build/client/routing/mount.js +1 -1
  11. package/build/compiler/.tsbuildinfo +1 -1
  12. package/build/compiler/auth-emails.js +7 -3
  13. package/build/compiler/emails.js +1 -1
  14. package/build/compiler/index.d.ts +1 -0
  15. package/build/compiler/index.js +25 -4
  16. package/build/compiler/pages.js +2 -3
  17. package/build/compiler/prerender.d.ts +3 -8
  18. package/build/compiler/prerender.js +88 -127
  19. package/build/compiler/ssg.js +3 -4
  20. package/build/compiler/template-build.js +3 -4
  21. package/build/compiler/toil-docs.generated.js +6 -5
  22. package/build/compiler/vite.js +3 -6
  23. package/build/devserver/.tsbuildinfo +1 -1
  24. package/build/devserver/db/database.js +7 -3
  25. package/build/devserver/db/types.js +1 -1
  26. package/build/devserver/production.js +4 -3
  27. package/build/devserver/runtime/crypto.d.ts +1 -1
  28. package/build/io/.tsbuildinfo +1 -1
  29. package/build/logger/.tsbuildinfo +1 -1
  30. package/build/shared/.tsbuildinfo +1 -1
  31. package/examples/basic/client/routes/analytics.tsx +7 -5
  32. package/examples/basic/server/tsconfig.json +1 -3
  33. package/package.json +45 -44
  34. package/presets/no-uint8array-tostring.js +120 -153
  35. package/presets/oxlint.d.ts +5 -0
  36. package/presets/oxlint.js +224 -0
  37. package/server/runtime/tsconfig.json +1 -3
  38. package/tsconfig.json +2 -11
  39. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
  40. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -90
  41. package/.github/ISSUE_TEMPLATE/config.yml +0 -8
  42. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  43. package/.github/PULL_REQUEST_TEMPLATE.md +0 -43
  44. package/.github/changelog-config.json +0 -45
  45. package/.github/dependabot.yml +0 -27
  46. package/.github/workflows/ci.yml +0 -222
  47. package/.vscode/settings.json +0 -10
  48. package/docs/README.md +0 -107
  49. package/docs/auth/README.md +0 -104
  50. package/docs/auth/configuration.md +0 -105
  51. package/docs/auth/emails.md +0 -92
  52. package/docs/auth/extending.md +0 -202
  53. package/docs/auth/how-it-works.md +0 -138
  54. package/docs/auth/usage.md +0 -188
  55. package/docs/backend/README.md +0 -143
  56. package/docs/backend/data.md +0 -351
  57. package/docs/backend/rest.md +0 -402
  58. package/docs/backend/rpc.md +0 -226
  59. package/docs/background/README.md +0 -114
  60. package/docs/background/daemons.md +0 -276
  61. package/docs/background/derive.md +0 -179
  62. package/docs/cli/README.md +0 -379
  63. package/docs/concepts/ai-guide.md +0 -132
  64. package/docs/concepts/config.md +0 -416
  65. package/docs/concepts/decorators.md +0 -127
  66. package/docs/concepts/security.md +0 -108
  67. package/docs/concepts/tiers.md +0 -166
  68. package/docs/concepts/types.md +0 -216
  69. package/docs/database/README.md +0 -143
  70. package/docs/database/capacity.md +0 -350
  71. package/docs/database/counters.md +0 -174
  72. package/docs/database/documents.md +0 -277
  73. package/docs/database/events.md +0 -307
  74. package/docs/database/membership.md +0 -246
  75. package/docs/database/setup.md +0 -155
  76. package/docs/database/unique.md +0 -216
  77. package/docs/database/views.md +0 -246
  78. package/docs/frontend/README.md +0 -104
  79. package/docs/frontend/components.md +0 -286
  80. package/docs/frontend/data-fetching.md +0 -260
  81. package/docs/frontend/images.md +0 -148
  82. package/docs/frontend/metadata.md +0 -344
  83. package/docs/frontend/navigation.md +0 -296
  84. package/docs/frontend/rendering.md +0 -236
  85. package/docs/frontend/routing.md +0 -346
  86. package/docs/frontend/scripts.md +0 -118
  87. package/docs/frontend/search.md +0 -191
  88. package/docs/frontend/styling.md +0 -147
  89. package/docs/frontend/toil-global.md +0 -216
  90. package/docs/getting-started/README.md +0 -81
  91. package/docs/getting-started/create-project.md +0 -131
  92. package/docs/getting-started/deploy.md +0 -101
  93. package/docs/getting-started/first-app.md +0 -215
  94. package/docs/getting-started/installation.md +0 -124
  95. package/docs/getting-started/migrating.md +0 -125
  96. package/docs/getting-started/project-structure.md +0 -163
  97. package/docs/introduction/README.md +0 -66
  98. package/docs/introduction/design-principles.md +0 -81
  99. package/docs/introduction/distributed.md +0 -91
  100. package/docs/introduction/how-it-works.md +0 -121
  101. package/docs/introduction/hyperscale.md +0 -70
  102. package/docs/introduction/modern-stack.md +0 -85
  103. package/docs/introduction/vs-other-frameworks.md +0 -64
  104. package/docs/introduction/why-toil.md +0 -99
  105. package/docs/llms.txt +0 -95
  106. package/docs/realtime/README.md +0 -102
  107. package/docs/realtime/channels.md +0 -211
  108. package/docs/realtime/streams.md +0 -369
  109. package/docs/services/README.md +0 -60
  110. package/docs/services/analytics.md +0 -279
  111. package/docs/services/caching.md +0 -175
  112. package/docs/services/cookies.md +0 -235
  113. package/docs/services/crypto.md +0 -209
  114. package/docs/services/email.md +0 -289
  115. package/docs/services/environment.md +0 -141
  116. package/docs/services/ratelimit.md +0 -174
  117. package/docs/services/time.md +0 -85
  118. package/eslint.config.js +0 -57
  119. package/examples/basic/client/routes/docs/[...slug].tsx +0 -12
  120. package/presets/eslint.js +0 -88
  121. package/src/backend/index.ts +0 -204
  122. package/src/cli/configure.ts +0 -363
  123. package/src/cli/create.ts +0 -924
  124. package/src/cli/db.ts +0 -158
  125. package/src/cli/diagnostics.ts +0 -665
  126. package/src/cli/doctor.ts +0 -982
  127. package/src/cli/features.ts +0 -170
  128. package/src/cli/index.ts +0 -326
  129. package/src/cli/notify.ts +0 -120
  130. package/src/cli/proc.ts +0 -56
  131. package/src/cli/ui.ts +0 -169
  132. package/src/cli/update.ts +0 -248
  133. package/src/cli/updates.ts +0 -92
  134. package/src/cli/validate.ts +0 -31
  135. package/src/cli/version-check.ts +0 -125
  136. package/src/client/auth.ts +0 -869
  137. package/src/client/channel/channel.ts +0 -146
  138. package/src/client/components/Form.tsx +0 -65
  139. package/src/client/components/Image.tsx +0 -160
  140. package/src/client/components/Script.tsx +0 -113
  141. package/src/client/components/Slot.tsx +0 -21
  142. package/src/client/dev/devtools.tsx +0 -1089
  143. package/src/client/dev/error-overlay.tsx +0 -225
  144. package/src/client/errors.ts +0 -11
  145. package/src/client/head/head.ts +0 -182
  146. package/src/client/head/metadata.ts +0 -110
  147. package/src/client/index.ts +0 -130
  148. package/src/client/navigation/Link.tsx +0 -108
  149. package/src/client/navigation/NavLink.tsx +0 -86
  150. package/src/client/navigation/navigation.ts +0 -235
  151. package/src/client/navigation/prefetch.ts +0 -169
  152. package/src/client/navigation/scroll.ts +0 -53
  153. package/src/client/routing/Router.tsx +0 -216
  154. package/src/client/routing/action.ts +0 -122
  155. package/src/client/routing/error-boundary.tsx +0 -43
  156. package/src/client/routing/hooks.ts +0 -140
  157. package/src/client/routing/lazy.ts +0 -77
  158. package/src/client/routing/loader.ts +0 -381
  159. package/src/client/routing/match.ts +0 -47
  160. package/src/client/routing/mount.tsx +0 -90
  161. package/src/client/routing/params-context.ts +0 -10
  162. package/src/client/routing/slot-context.ts +0 -7
  163. package/src/client/rpc.ts +0 -97
  164. package/src/client/search/search.ts +0 -189
  165. package/src/client/search/use-page-search.ts +0 -73
  166. package/src/client/ssr/markers.tsx +0 -172
  167. package/src/client/stream/client.ts +0 -237
  168. package/src/client/types.ts +0 -73
  169. package/src/compiler/auth-emails.ts +0 -312
  170. package/src/compiler/config.ts +0 -369
  171. package/src/compiler/docs.ts +0 -127
  172. package/src/compiler/email-preview.ts +0 -314
  173. package/src/compiler/emails.ts +0 -404
  174. package/src/compiler/fonts.ts +0 -89
  175. package/src/compiler/generate.ts +0 -471
  176. package/src/compiler/image-blur.ts +0 -42
  177. package/src/compiler/image-report.ts +0 -88
  178. package/src/compiler/index.ts +0 -1362
  179. package/src/compiler/pages.ts +0 -49
  180. package/src/compiler/plugin.ts +0 -391
  181. package/src/compiler/prerender.ts +0 -263
  182. package/src/compiler/routes.ts +0 -170
  183. package/src/compiler/seo.ts +0 -415
  184. package/src/compiler/sri.ts +0 -144
  185. package/src/compiler/ssg.ts +0 -177
  186. package/src/compiler/ssr-codegen.ts +0 -85
  187. package/src/compiler/template-build.ts +0 -676
  188. package/src/compiler/template.ts +0 -262
  189. package/src/compiler/toil-docs.generated.ts +0 -77
  190. package/src/compiler/vite.ts +0 -245
  191. package/src/devserver/analytics/index.ts +0 -317
  192. package/src/devserver/config/dotenv.ts +0 -102
  193. package/src/devserver/config/env.ts +0 -30
  194. package/src/devserver/config/ratelimit.ts +0 -123
  195. package/src/devserver/daemon/catalog.ts +0 -120
  196. package/src/devserver/daemon/cron.ts +0 -87
  197. package/src/devserver/daemon/host.ts +0 -134
  198. package/src/devserver/daemon/index.ts +0 -369
  199. package/src/devserver/daemon/runtime.ts +0 -48
  200. package/src/devserver/db/catalog.ts +0 -109
  201. package/src/devserver/db/database.ts +0 -1834
  202. package/src/devserver/db/derives.ts +0 -121
  203. package/src/devserver/db/index.ts +0 -20
  204. package/src/devserver/db/routeKinds.ts +0 -191
  205. package/src/devserver/db/types.ts +0 -168
  206. package/src/devserver/email/caps.ts +0 -0
  207. package/src/devserver/email/config.ts +0 -141
  208. package/src/devserver/email/console.ts +0 -348
  209. package/src/devserver/email/index.ts +0 -155
  210. package/src/devserver/email/providers.ts +0 -131
  211. package/src/devserver/email/status.ts +0 -23
  212. package/src/devserver/email/validate.ts +0 -37
  213. package/src/devserver/email/wire.ts +0 -55
  214. package/src/devserver/http/cache.ts +0 -0
  215. package/src/devserver/http/envelope.ts +0 -157
  216. package/src/devserver/http/proxy.ts +0 -172
  217. package/src/devserver/http/runtime.ts +0 -387
  218. package/src/devserver/index.ts +0 -43
  219. package/src/devserver/production-ipc.ts +0 -63
  220. package/src/devserver/production-worker.ts +0 -83
  221. package/src/devserver/production.ts +0 -718
  222. package/src/devserver/runtime/crypto.ts +0 -587
  223. package/src/devserver/runtime/host.ts +0 -427
  224. package/src/devserver/runtime/module.ts +0 -442
  225. package/src/devserver/server.ts +0 -251
  226. package/src/devserver/ssr.ts +0 -208
  227. package/src/devserver/stream/catalog.ts +0 -106
  228. package/src/devserver/stream/host.ts +0 -42
  229. package/src/devserver/stream/index.ts +0 -301
  230. package/src/devserver/stream/manager.ts +0 -167
  231. package/src/devserver/stream/router.ts +0 -101
  232. package/src/devserver/stream/wire.ts +0 -58
  233. package/src/devserver/stream/ws.ts +0 -78
  234. package/src/devserver/wasm/sections.ts +0 -59
  235. package/src/devserver/wasm/surface.ts +0 -115
  236. package/src/io/FastMap.ts +0 -151
  237. package/src/io/FastSet.ts +0 -113
  238. package/src/io/codec.ts +0 -362
  239. package/src/io/index.ts +0 -10
  240. package/src/io/lengths.ts +0 -14
  241. package/src/io/types.ts +0 -19
  242. package/src/logger/index.ts +0 -22
  243. package/src/shared/index.ts +0 -46
  244. package/test/analytics-dev.test.ts +0 -113
  245. package/test/assembly/aspect-shim.ts +0 -33
  246. package/test/assembly/cookie.spec.ts +0 -303
  247. package/test/assembly/example.spec.ts +0 -22
  248. package/test/assembly/ssr.spec.ts +0 -95
  249. package/test/assembly.test.ts +0 -59
  250. package/test/auth-emails.test.ts +0 -118
  251. package/test/built-ssr.test.ts +0 -148
  252. package/test/channel.test.ts +0 -21
  253. package/test/config-host-port.test.ts +0 -59
  254. package/test/configure.test.ts +0 -94
  255. package/test/daemon-build.test.ts +0 -278
  256. package/test/daemon-catalog.test.ts +0 -349
  257. package/test/daemon-emulation.test.ts +0 -256
  258. package/test/db.test.ts +0 -0
  259. package/test/devserver-database.test.ts +0 -1102
  260. package/test/devserver-email.test.ts +0 -306
  261. package/test/devserver-pqauth.test.ts +0 -93
  262. package/test/devserver-secrets.test.ts +0 -63
  263. package/test/devserver.test.ts +0 -259
  264. package/test/doctor.test.ts +0 -298
  265. package/test/dom/Image.test.tsx +0 -144
  266. package/test/dom/Link.test.tsx +0 -67
  267. package/test/dom/NavLink.test.tsx +0 -37
  268. package/test/dom/Script.test.tsx +0 -48
  269. package/test/dom/action.test.tsx +0 -146
  270. package/test/dom/error-overlay.test.tsx +0 -44
  271. package/test/dom/loader.test.tsx +0 -121
  272. package/test/dom/navigation.test.ts +0 -59
  273. package/test/dom/revalidate.test.tsx +0 -38
  274. package/test/dom/route-head.test.tsx +0 -56
  275. package/test/dom/router-loading.test.tsx +0 -44
  276. package/test/dom/scroll.test.ts +0 -56
  277. package/test/dom/slot.test.tsx +0 -131
  278. package/test/dom/use-metadata.test.tsx +0 -58
  279. package/test/dom/view-transitions.test.tsx +0 -53
  280. package/test/dynamic-routing.test.ts +0 -132
  281. package/test/email-console.test.ts +0 -86
  282. package/test/email-preview.test.ts +0 -73
  283. package/test/emails.test.ts +0 -58
  284. package/test/errors.test.ts +0 -21
  285. package/test/example-guestbook.test.ts +0 -123
  286. package/test/features.test.ts +0 -149
  287. package/test/fixtures/bignum-wire/spec.ts +0 -25
  288. package/test/fixtures/daemon-app.ts +0 -65
  289. package/test/fixtures/stream-echo.ts +0 -26
  290. package/test/fixtures/stream-gate.ts +0 -28
  291. package/test/fixtures/stream-trap.ts +0 -18
  292. package/test/fixtures/stream-typed.ts +0 -41
  293. package/test/fonts.test.ts +0 -28
  294. package/test/global-setup.ts +0 -17
  295. package/test/head.test.ts +0 -42
  296. package/test/image-blur.test.ts +0 -50
  297. package/test/io.test.ts +0 -117
  298. package/test/metadata.test.ts +0 -40
  299. package/test/navlink.test.ts +0 -28
  300. package/test/pages.test.ts +0 -105
  301. package/test/placeholder.test.ts +0 -9
  302. package/test/pqauth-e2e.test.ts +0 -216
  303. package/test/pqauth-email.test.ts +0 -801
  304. package/test/prerender.test.ts +0 -116
  305. package/test/prettier-plugin.test.ts +0 -46
  306. package/test/routes.test.ts +0 -76
  307. package/test/rpc-bignum-wire.test.ts +0 -164
  308. package/test/rpc-dispatch.test.ts +0 -132
  309. package/test/rpc-kinds.test.ts +0 -18
  310. package/test/rpc.test.ts +0 -66
  311. package/test/search.test.ts +0 -114
  312. package/test/seo.test.ts +0 -175
  313. package/test/slot-layouts.test.ts +0 -69
  314. package/test/sri.test.ts +0 -129
  315. package/test/ssg.test.ts +0 -36
  316. package/test/ssr-hydration.test.tsx +0 -122
  317. package/test/ssr-render.test.ts +0 -197
  318. package/test/ssr-template.test.tsx +0 -482
  319. package/test/stream-emulation.test.ts +0 -479
  320. package/test/ui.test.ts +0 -40
  321. package/test/update.test.ts +0 -58
  322. package/test/validate.test.ts +0 -42
  323. package/test/version-check.test.ts +0 -130
  324. package/tests/data-parity/generated-parity.ts +0 -99
  325. package/tests/data-parity/parity.ts +0 -80
  326. package/tests/data-parity/spec.ts +0 -46
@@ -1,215 +0,0 @@
1
- # Your first app
2
-
3
- Build a tiny feature end to end: a page with a "Like" button that reads and writes a real number in ToilDB, so the count survives page reloads and restarts. Along the way you meet the typed client, an HTTP route, and the database, the three pieces you use in almost every toiljs app.
4
-
5
- ## What you will build
6
-
7
- A `/likes` page that shows a running like count and a button to add one. The count lives in ToilDB, so it is shared by everyone and it persists.
8
-
9
- ```mermaid
10
- sequenceDiagram
11
- participant B as Browser (/likes page)
12
- participant SH as shared/server.ts (typed client)
13
- participant W as server.wasm (@rest route)
14
- participant DB as ToilDB (counter)
15
- B->>SH: Server.REST.likes.add()
16
- SH->>W: POST /likes
17
- W->>DB: counter.add(key, 1)
18
- W-->>SH: { count: 43 }
19
- SH-->>B: typed LikeCount
20
- B->>B: show "43 likes"
21
- ```
22
-
23
- ## Before you start
24
-
25
- You need a project. If you do not have one yet, create one and start the dev server:
26
-
27
- ```sh
28
- toiljs create my-app
29
- cd my-app
30
- npm run dev
31
- ```
32
-
33
- Leave `npm run dev` running in a terminal. It rebuilds your server, regenerates the typed client, and hot-reloads the browser every time you save. The app is at `http://localhost:3000`.
34
-
35
- ## Why the database (and not a variable)
36
-
37
- Your first instinct might be to keep the count in a normal variable on the server. That will not work, and it is worth understanding why now.
38
-
39
- **The server runs a fresh copy of your `.wasm` for every request, and wipes its memory when the request ends.** So a variable you set while handling one request is gone by the next request. Anything that must outlive a single request, a counter, a user, a post, has to go into a store. toiljs ships one: **ToilDB**, a database built into the edge.
40
-
41
- ToilDB offers a few specialized shapes called **families**. For a running total, the right one is a **counter**: a value you can atomically add to and read back. (Others include documents, events, and views. See [Database overview](../database/README.md).)
42
-
43
- ## Step 1: add a data type for the response
44
-
45
- Your server and client talk in typed messages called `@data` classes. A `@data` class can cross the wire and be parsed into a real typed object on the other side. Create one to hold the count.
46
-
47
- Create `server/models/LikeCount.ts`:
48
-
49
- ```ts
50
- // The response our route returns: just the current like count.
51
- @data
52
- export class LikeCount {
53
- count: i64 = 0;
54
- constructor(count: i64 = 0) {
55
- this.count = count;
56
- }
57
- }
58
- ```
59
-
60
- Two things to notice:
61
-
62
- - `@data` is a decorator that marks this class as a wire type. You use it with no import (it is a compiler built-in). See [Data types](../backend/data.md).
63
- - The field type is `i64`, a 64-bit integer. The server uses precise integer types like `i64` and `u64`. On the client side these arrive as JavaScript `bigint`. More on this in [Types](../concepts/types.md).
64
-
65
- ## Step 2: add the HTTP route
66
-
67
- Now the backend endpoint. Create `server/routes/Likes.ts`:
68
-
69
- ```ts
70
- import { RouteContext } from 'toiljs/server/runtime';
71
-
72
- import { LikeCount } from '../models/LikeCount';
73
-
74
- // The KEY that names one counter. A counter is a map from a key to a number,
75
- // so a single fixed key ("home") gives us one global tally.
76
- @data
77
- class LikeKey {
78
- page: string = 'home';
79
- constructor(page: string = 'home') {
80
- this.page = page;
81
- }
82
- }
83
-
84
- // A @database declares your ToilDB collections. Each @collection is one named
85
- // store. Here we declare a single counter keyed by LikeKey.
86
- @database
87
- class LikesDb {
88
- @collection static likes: Counter<LikeKey>;
89
- }
90
-
91
- // A @rest controller exposes HTTP endpoints. 'likes' is the URL prefix, so the
92
- // routes below live under /likes.
93
- @rest('likes')
94
- class Likes {
95
- // GET /likes -> read the current count.
96
- // A @get handler is a "query": it may read but not write. Reading one
97
- // counter by its key is a point read, which queries are allowed to do.
98
- @get('/')
99
- public show(): LikeCount {
100
- const key = new LikeKey('home');
101
- return new LikeCount(LikesDb.likes.get(key));
102
- }
103
-
104
- // POST /likes -> add one, then return the new count.
105
- // A @post handler is an "action": it may write. `add` bumps the counter.
106
- // (A body-less POST takes the RouteContext; we do not need it here.)
107
- @post('/')
108
- public add(_ctx: RouteContext): LikeCount {
109
- const key = new LikeKey('home');
110
- LikesDb.likes.add(key, 1);
111
- return new LikeCount(LikesDb.likes.get(key));
112
- }
113
- }
114
- ```
115
-
116
- What each decorator does:
117
-
118
- - **`@rest('likes')`** turns the class into an HTTP controller mounted at `/likes`.
119
- - **`@get('/')`** and **`@post('/')`** map a method to a verb and path. A `@get` is a read-only **query**; a `@post` is a write-capable **action**. This split is how toiljs keeps expensive or unsafe operations out of read paths.
120
- - **`@database`** and **`@collection`** declare your ToilDB stores. `Counter<LikeKey>` is a counter you look up by a `LikeKey`.
121
-
122
- The counter gives you two operations: `add(key, delta)` to change it and `get(key)` to read it. See [Counters](../database/counters.md) and [HTTP routes](../backend/rest.md) for the full API.
123
-
124
- ## Step 3: register the route
125
-
126
- Open `server/main.ts` and add an import for your new route, next to the others:
127
-
128
- ```ts
129
- import './routes/Likes';
130
- ```
131
-
132
- The build actually discovers decorated files under `server/` on its own, but importing them from `main.ts` is the convention: it keeps a direct `toilscript` build finding the same code. (Every `app` project already imports its demo routes this way.)
133
-
134
- Save. Watch the terminal: `toiljs dev` recompiles the server to wasm and regenerates `shared/server.ts`. A moment later your new endpoint exists, fully typed.
135
-
136
- ## Step 4: add the client page
137
-
138
- Now the frontend. Create `client/routes/likes.tsx`. The file name is the URL, so this page is at `/likes`.
139
-
140
- ```tsx
141
- import { useEffect, useState } from 'react';
142
-
143
- export default function LikesPage() {
144
- // The count is a bigint because the server field is i64.
145
- const [count, setCount] = useState(0n);
146
-
147
- // Read the current count once, when the page first loads.
148
- useEffect(() => {
149
- Server.REST.likes.show().then((res) => setCount(res.count));
150
- }, []);
151
-
152
- // Add a like, then update the UI with the fresh count the server returns.
153
- const like = async () => {
154
- const res = await Server.REST.likes.add();
155
- setCount(res.count);
156
- };
157
-
158
- return (
159
- <main>
160
- <h1>{String(count)} likes</h1>
161
- <button onClick={like}>Like</button>
162
- </main>
163
- );
164
- }
165
- ```
166
-
167
- The magic here is `Server.REST.likes`. You never wrote it. toiljs generated it into `shared/server.ts` from your `@rest` controller, so:
168
-
169
- - `Server.REST.likes.show()` returns a `Promise<LikeCount>`, and `res.count` is typed for you.
170
- - `Server.REST.likes.add()` sends the POST and returns the updated `LikeCount`.
171
- - `Server` is a global in client code, so you do not import it. Its types come from the generated file.
172
-
173
- If you rename the route or change its return type on the server, this client code stops type-checking until you fix it. That is the whole point: the browser and the backend cannot silently disagree.
174
-
175
- ## Step 5: try it
176
-
177
- Open `http://localhost:3000/likes`. You should see "0 likes" and a button. Click **Like** a few times and the number climbs.
178
-
179
- Now the important test: **reload the page.** The count is still there. Stop the dev server, start it again, reload: still there. That is ToilDB persisting your counter, exactly as it would on the real edge. The same code that ran against the local dev database runs against the worldwide database in production, with no connection string to configure.
180
-
181
- ## What just happened
182
-
183
- ```mermaid
184
- flowchart LR
185
- M["server/models/LikeCount.ts<br/>@data"] --> GEN
186
- R["server/routes/Likes.ts<br/>@rest + @database"] --> GEN
187
- GEN["toiljs dev<br/>compiles + generates"] --> WASM["release.wasm"]
188
- GEN --> SS["shared/server.ts<br/>(typed Server.REST.likes)"]
189
- SS --> P["client/routes/likes.tsx<br/>calls Server.REST.likes"]
190
- ```
191
-
192
- You wrote three small files. toiljs compiled the server to WebAssembly, generated a typed client from your route, and your React page called it with full type safety. The like count lives in ToilDB, so it persists.
193
-
194
- ## Gotchas and notes
195
-
196
- - **`res.count` is a `bigint`, not a `number`.** That is why the page uses `useState(0n)` and `String(count)`. Server integer types map to `bigint` on the client. See [Types](../concepts/types.md).
197
- - **A `@get` cannot write, and a `@post` can.** If you try to call `.add(...)` from a `@get`, the compiler rejects it. Reads that scan many rows are also blocked in handlers; a single-key `get` is fine.
198
- - **You do not edit `shared/server.ts`.** It is regenerated on every server build. Change the route, and the client updates itself.
199
- - **If the editor does not know `Server.REST.likes` yet**, it is because the server has not rebuilt since you added the route. Save a server file (or restart `toiljs dev`) to regenerate `shared/server.ts`.
200
- - **The counter is global.** Everyone hitting `/likes` shares the same "home" tally, because we used one fixed key. Use a different key per page or per user to split the count.
201
-
202
- ## Where to go next
203
-
204
- - Return richer objects and lists: [Data types](../backend/data.md) and [HTTP routes](../backend/rest.md).
205
- - Call the server without URLs, as plain function calls: [Typed RPC](../backend/rpc.md).
206
- - Store more than a number: [Documents](../database/documents.md), [Events](../database/events.md), and [Views](../database/views.md).
207
- - Add login and sessions: [Auth](../auth/README.md).
208
- - Style your pages: [Styling](../frontend/styling.md) and [Routing](../frontend/routing.md).
209
-
210
- ## Related
211
-
212
- - [Project structure](./project-structure.md)
213
- - [Database overview](../database/README.md)
214
- - [Counters](../database/counters.md)
215
- - [Backend overview](../backend/README.md)
@@ -1,124 +0,0 @@
1
- # Installation
2
-
3
- Install the toiljs command-line tool (CLI) so you can create and run projects. This takes a couple of minutes.
4
-
5
- ## Why and when
6
-
7
- You need the toiljs CLI once, before you create your first project. The CLI is the single tool you use to scaffold, run, build, and check toiljs apps. After a project exists, the same CLI is also installed inside that project, so day-to-day you can run it through your package scripts (`npm run dev`) without a global install.
8
-
9
- ## Prerequisites
10
-
11
- You need **Node.js version 24.0.0 or newer**. Node.js is the JavaScript runtime that powers the toiljs CLI, the dev server, and the build. (Your backend does not run on Node.js, but the tools that build it do.)
12
-
13
- Check your version:
14
-
15
- ```sh
16
- node --version
17
- ```
18
-
19
- If it prints `v24.0.0` or higher, you are set. If it is older or the command is not found, install a current Node.js from [nodejs.org](https://nodejs.org), or use a version manager like [nvm](https://github.com/nvm-sh/nvm) or [fnm](https://github.com/Schniz/fnm):
20
-
21
- ```sh
22
- # with nvm
23
- nvm install 24
24
- nvm use 24
25
- ```
26
-
27
- You also need a package manager. **npm** comes with Node.js, so you already have it. toiljs also supports **pnpm**, **yarn**, and **bun** if you prefer one of those.
28
-
29
- ### TypeScript 6, not 7
30
-
31
- toiljs requires **TypeScript 6** (`>=6.0.0 <7.0.0`). TypeScript 7 is not supported yet.
32
-
33
- TypeScript 7 is the native (Go) port of the compiler. It ships a much faster `tsc`, but its package no longer exports the JavaScript compiler API, whose main entry is now just `{ version, versionMajorMinor }`. toiljs reads each route's static `metadata` export through that API to bake your SEO tags into the built HTML, and the `toiljs/eslint` preset loads it too. On TypeScript 7 the metadata baking silently stops (your built pages lose their tags) and typescript-eslint fails to load at all.
34
-
35
- Pin TypeScript in your `package.json`:
36
-
37
- ```json
38
- {
39
- "devDependencies": {
40
- "typescript": "^6.0.3"
41
- }
42
- }
43
- ```
44
-
45
- `toiljs doctor` flags an unsupported TypeScript, and `toiljs doctor --fix` pins it back for you. `toiljs update` will not upgrade you into TypeScript 7. Support will land once the tools toiljs builds on can read the new `typescript/unstable/*` API.
46
-
47
- ## Install the CLI
48
-
49
- The package is called `toiljs`, and it provides a command named `toiljs`. You have two ways to use it.
50
-
51
- ### Option A: run it on demand with npx (no install)
52
-
53
- `npx` comes with npm and runs a package without installing it globally. This is the quickest way to create your first project:
54
-
55
- ```sh
56
- npx toiljs create my-app
57
- ```
58
-
59
- ### Option B: install it globally
60
-
61
- If you plan to create projects often, install it once so `toiljs` is always on your path:
62
-
63
- ```sh
64
- npm install -g toiljs
65
- ```
66
-
67
- Then you can run `toiljs` directly:
68
-
69
- ```sh
70
- toiljs create my-app
71
- ```
72
-
73
- Both options end up at the same place. The rest of these docs write `toiljs <command>`; if you did not install globally, just put `npx` in front (`npx toiljs <command>`).
74
-
75
- ## Verify it works
76
-
77
- Check the version:
78
-
79
- ```sh
80
- toiljs --version
81
- ```
82
-
83
- You should see a version number printed (for example, `0.0.86`).
84
-
85
- To see every command and flag, run help:
86
-
87
- ```sh
88
- toiljs --help
89
- ```
90
-
91
- Inside a project, there is a deeper health check called **doctor**. It inspects your setup and dependencies and tells you exactly what to fix. You will use it after you create a project, but it is good to know it exists:
92
-
93
- ```sh
94
- toiljs doctor
95
- ```
96
-
97
- `toiljs doctor` reads your project (its `package.json`, config, routes, and build output), runs a series of checks, and prints a grouped report. One of the first checks is your Node.js version against the required `>=24.0.0`, so if your Node is too old, doctor will say so. Add `--fix` to let it repair the things it can (such as the typed-RPC wiring), or `--json` for machine-readable output in a CI pipeline.
98
-
99
- ## How the tooling fits together
100
-
101
- The `toiljs` CLI is a friendly front end over two underlying tools. You rarely call them directly, but it helps to know they exist.
102
-
103
- ```mermaid
104
- flowchart LR
105
- CLI["toiljs CLI"] --> TS["toilscript<br/>(compiles server/ to wasm)"]
106
- CLI --> VITE["Vite<br/>(bundles client/ React)"]
107
- TS --> W["build/server/release.wasm"]
108
- VITE --> B["build/client/"]
109
- ```
110
-
111
- When you create a project, both `toiljs` and `toilscript` are added to it as dependencies, so everything is pinned to versions that work together. You do not install `toilscript` separately.
112
-
113
- ## Gotchas and notes
114
-
115
- - **"command not found: toiljs"** after a global install usually means npm's global bin folder is not on your `PATH`. Either fix your `PATH` or just use `npx toiljs ...` instead.
116
- - **Node too old** is the most common first-time failure. WebAssembly tooling and the build depend on features in Node 24 and up. Upgrade before creating a project.
117
- - **Every command checks for updates.** On each run, the CLI quietly checks npm for a newer toiljs and prints a note if you are behind. It never blocks the command. To turn it off, set the environment variable `TOILJS_NO_UPDATE_CHECK=1`.
118
- - You do **not** need to install a database, a Docker container, or any cloud account to develop locally. The dev server includes a local ToilDB so your data-backed features run out of the box.
119
-
120
- ## Related
121
-
122
- - [Create a project](./create-project.md)
123
- - [The CLI reference](../cli/README.md)
124
- - [Getting started overview](./README.md)
@@ -1,125 +0,0 @@
1
- # Migrating an existing React app
2
-
3
- How to bring a React app you already have into toiljs. The frontend usually moves over with small changes. The backend is the real work, because a toiljs server is not Node.js, and this page is honest about what that means.
4
-
5
- ## Why and when
6
-
7
- Move to toiljs when you want your frontend and backend in one typed repo, deployed to the edge, with a built-in global database, and you are willing to rewrite your server logic against toiljs's rules. If you only want a React bundler, toiljs is more than you need. If you want the full-stack, typed, edge model, this is the payoff.
8
-
9
- The safest approach is **not** to convert your old project in place. Instead, scaffold a fresh toiljs project and move code into it piece by piece. A fresh project comes with the required presets, config, and routing already wired, so you spend your time on your code, not on plumbing.
10
-
11
- ```sh
12
- toiljs create my-app
13
- cd my-app
14
- ```
15
-
16
- ## The big picture: what moves where
17
-
18
- ```mermaid
19
- flowchart LR
20
- subgraph OLD["Your current app"]
21
- FE["React components,<br/>pages, styles, assets"]
22
- BE["Node/Express backend,<br/>DB access, npm libs"]
23
- end
24
- FE -->|"mostly copy"| C["toiljs client/"]
25
- BE -->|"rewrite"| S["toiljs server/"]
26
- C -.->|"generated typed client"| S
27
- S --> DB[("ToilDB")]
28
- ```
29
-
30
- - Your **React frontend** copies into `client/` with modest changes (routing and asset paths).
31
- - Your **backend** is **rewritten** into `server/` as toilscript, because it compiles to WebAssembly, not Node.
32
-
33
- ## The frontend: what changes
34
-
35
- `client/` is a normal Vite + React app, so most of your frontend works as is. The common adjustments:
36
-
37
- - **Routing becomes file-based.** toiljs has no `<Routes>`/`<Route>` config. A file at `client/routes/about.tsx` is the `/about` page; `client/routes/blog/[slug].tsx` is `/blog/:slug`. Move each page component to the matching file and delete your router setup. Use `Toil.Link` for navigation instead of your router's `Link`. See [Routing](../frontend/routing.md).
38
- - **Static assets move to `client/public/`.** Files there are served as is (images at `/images/...`, plus `favicon` and `robots.txt`).
39
- - **Global styles move to `client/styles/`**, and are imported from `client/toil.tsx`. See [Styling](../frontend/styling.md).
40
- - **Your React npm packages are fine.** The client is regular JavaScript, so component libraries, state managers, and browser APIs all work.
41
- - **Data fetching changes** if you want the typed client: replace hand-written `fetch('/api/...')` calls with the generated `Server.REST.*` methods. You can keep raw `fetch` too, but you lose the type safety. See [Fetching data](../frontend/data-fetching.md).
42
-
43
- Metadata and SEO that you used a helmet library for is built in: set a `metadata` export per route, or use `Toil.Head`. See [Metadata and SEO](../frontend/metadata.md).
44
-
45
- ## The backend: the honest part
46
-
47
- This is where migration takes real effort. Read this section carefully before you plan the work.
48
-
49
- Your toiljs server is compiled by **toilscript** into WebAssembly. toilscript accepts a **strict subset of TypeScript**. It looks like TypeScript, but treat it as a small, separate language that happens to share the syntax. The practical consequences:
50
-
51
- ### What is NOT available on the server
52
-
53
- - **No arbitrary npm packages.** You cannot `import` a library from `node_modules` into `server/`. There is no `express`, no `pg`, no `stripe` SDK, no `lodash`. If your route logic leans on npm libraries, that logic has to be reworked.
54
- - **No Node.js APIs.** No `fs`, `http`, `process`, `Buffer`, `path`, or other Node built-ins. The server runs in a sandbox, not in Node.
55
- - **No DOM or browser APIs**, because it is not a browser either.
56
- - **No connecting to your existing database.** There is no connection string and no driver. Your data moves to **ToilDB**, the built-in database.
57
-
58
- ### What you use instead
59
-
60
- toiljs replaces the common needs with built-in globals and decorators, so you rarely miss the missing libraries:
61
-
62
- | You used to reach for | On the toiljs server you use |
63
- | --- | --- |
64
- | `express` routes / a router | `@rest` controllers with `@get` / `@post` ([HTTP routes](../backend/rest.md)) |
65
- | A REST client between services | `@service` / `@remote` typed RPC ([RPC](../backend/rpc.md)) |
66
- | Postgres / Mongo / Redis | [ToilDB](../database/README.md) families (documents, counters, events, views) |
67
- | `jsonwebtoken`, session middleware | Built-in [auth](../auth/README.md) and cookies |
68
- | `crypto` from Node | the `crypto` global (synchronous Web Crypto) ([Crypto](../services/crypto.md)) |
69
- | `nodemailer` / an email SDK | the built-in email service ([Email](../services/email.md)) |
70
- | `process.env` | `Environment.get()` / `Environment.getSecure()` ([Environment](../services/environment.md)) |
71
- | `Date.now()`, timers | the `Time` global ([Time](../services/time.md)) |
72
-
73
- ### Type system differences
74
-
75
- toilscript uses precise, explicit numeric types instead of JavaScript's single `number`. You will write `i32`, `u64`, `f64`, and even `u256`, and be explicit about integer sizes. Values that must cross the wire are `@data` classes with concrete fields, not free-form objects. There is no `any`-style duck typing to lean on. The full rules, and how server types map to `bigint` and friends on the client, are in [Types](../concepts/types.md).
76
-
77
- ### Two behaviors to design around
78
-
79
- - **Memory resets every request.** Each request gets a fresh `.wasm` instance and its memory is wiped afterward. A module-level variable does not persist. Anything durable goes in ToilDB. (This is the same rule you met in [Your first app](./first-app.md).)
80
- - **Reads and writes are split.** A `@get` is a read-only query; a `@post` is a write action. Operations that scan unbounded data are not allowed in a request handler; they move to a [`@derive`](../background/derive.md) or a background [daemon](../background/daemons.md).
81
-
82
- ## Configuration
83
-
84
- Two config files replace the various configs you may have had:
85
-
86
- - **`toil.config.ts`** is your client and build config: SEO defaults, image optimization, page transitions, and dev-server options. It uses `defineConfig`. See [Configuration](../concepts/config.md).
87
- - **`toilconfig.json`** is the low-level server (wasm) build config. The scaffold sets sensible defaults, and you usually leave it alone.
88
-
89
- Environment variables move from a `.env` you read with `process.env` to `.env` / `.env.secrets` files you read with `Environment.get()` / `Environment.getSecure()`. Secrets and plain vars are kept in separate buckets. See [Environment and secrets](../services/environment.md).
90
-
91
- ## Step by step
92
-
93
- 1. **Scaffold a fresh project** with `toiljs create` and get it running with `npm run dev`. Start from something that works.
94
- 2. **Move the frontend.** Copy components into `client/components/`, turn each page into a file under `client/routes/`, move styles into `client/styles/`, and static assets into `client/public/`. Swap your router's `Link` for `Toil.Link`. Install your client-side npm dependencies.
95
- 3. **Get the client rendering** against the routes, even if the data is still stubbed or points at your old backend. Fix routing and asset paths first.
96
- 4. **Rebuild the backend, one route at a time.** For each old endpoint, add a `@data` model in `server/models/`, a `@rest` controller in `server/routes/`, and move its data into a ToilDB family. Import each new route in `server/main.ts`. This is the bulk of the effort; go endpoint by endpoint.
97
- 5. **Move persistence to ToilDB.** Map each table or collection to a ToilDB family (a document store, a counter, an event log, or a view). See [Database overview](../database/README.md) for choosing a family.
98
- 6. **Switch the client to the typed client.** Replace `fetch('/api/...')` calls with `Server.REST.*` (or `Server.<service>.*` for RPC). Now a backend change that breaks the contract shows up as a client type error.
99
- 7. **Run the doctor.** `toiljs doctor` checks your wiring (routes, RPC generation, config, dependencies) and points at anything still off. Add `--fix` to let it repair what it can.
100
-
101
- ## When toiljs is not the right move
102
-
103
- Be honest with yourself about the backend rewrite. Migration is a poor fit if:
104
-
105
- - Your server depends heavily on npm libraries or Node-only APIs that have no toiljs equivalent, and rewriting them is not worth it.
106
- - You must keep talking to an existing external database or service that toiljs cannot reach. (Daemons can make outbound HTTP calls in some cases, but general server-side networking is limited by design.)
107
- - You need long-lived in-process server state that does not fit the per-request, database-backed model.
108
-
109
- In those cases, you can still adopt toiljs for the frontend and keep your existing backend, calling it with plain `fetch`. You just give up the single-repo, end-to-end-typed benefits for that part.
110
-
111
- ## Gotchas and notes
112
-
113
- - **Do not try to `import` server code into the client or vice versa.** They compile with different rules. The only bridge is the generated `shared/server.ts`.
114
- - **One `@data` type per file** under `models/` matches the tooling's expectations.
115
- - **`shared/server.ts` is generated**, so it will not exist until your first build, and you never edit it.
116
- - **Plan the backend as a rewrite, not a port.** The frontend moves; the backend is re-expressed in toiljs's model. Budget for that.
117
-
118
- ## Related
119
-
120
- - [Getting started overview](./README.md)
121
- - [Backend overview](../backend/README.md)
122
- - [Types](../concepts/types.md)
123
- - [Database overview](../database/README.md)
124
- - [The CLI reference](../cli/README.md)
125
- - [Configuration](../concepts/config.md)
@@ -1,163 +0,0 @@
1
- # Project structure
2
-
3
- A tour of every folder and file in a toiljs project, what each one is for, and the single most important question: **where does this code run, the browser or the edge?**
4
-
5
- ## Why this matters
6
-
7
- toiljs blends frontend and backend into one repo, so the same `.ts` file extension can mean two very different things. A file in `client/` becomes JavaScript that runs in your user's browser. A file in `server/` becomes WebAssembly that runs on the edge, with different rules and different available APIs. Knowing which folder you are in tells you what you are allowed to do. Keep this mental split and everything else falls into place.
8
-
9
- ```mermaid
10
- flowchart TD
11
- subgraph Browser["Runs in the browser"]
12
- C["client/*"]
13
- end
14
- subgraph Edge["Runs on the edge (WebAssembly)"]
15
- S["server/* -> release.wasm"]
16
- end
17
- subgraph Generated["Generated glue (types + config)"]
18
- SH["shared/server.ts"]
19
- CFG["toil.config.ts / toilconfig.json"]
20
- end
21
- C -. "typed calls" .-> SH
22
- SH -. "HTTP / realtime" .-> S
23
- S --> DB[("ToilDB")]
24
- ```
25
-
26
- ## The top level
27
-
28
- These files sit in your project root.
29
-
30
- | File | What it is | Runs where |
31
- | --- | --- | --- |
32
- | `package.json` | Scripts (`dev`, `build`, `lint`, `typecheck`, `format`) and dependencies (`toiljs`, `react`, `toilscript`, ...) | tooling only |
33
- | `toil.config.ts` | **Client and build config.** Uses `defineConfig` to set SEO, images, page transitions, and dev options. | tooling only |
34
- | `toilconfig.json` | **Server (wasm) build config** for toilscript: the entry file, the output `.wasm` path, and low-level compile options. You rarely edit this. | tooling only |
35
- | `tsconfig.json` | TypeScript config for the client (`client/`, `shared/`, `emails/`). Extends `toiljs/tsconfig`. | tooling only |
36
- | `eslint.config.js` | Linting preset (`toiljs/eslint`). | tooling only |
37
- | `.prettierrc` | Formatting preset (`toiljs/prettier`). | tooling only |
38
- | `.prettierignore` | Files Prettier should skip (generated files). | tooling only |
39
- | `.gitignore` | Ignores `build/`, `.toil/`, generated files, and your `.env` files. | tooling only |
40
- | `.vscode/settings.json` | Tells VS Code to use the project's TypeScript so the toilscript editor plugin loads. | editor only |
41
- | `toil-env.d.ts` | **Generated** editor types for client globals like `Toil.Link` and `Toil.Image`. Do not edit. | editor only |
42
- | `toil-routes.d.ts` | **Generated** list of your real route names, so `Toil.Link href="..."` type-checks. Filled in on the first build. | editor only |
43
- | `README.md` | Your project's readme. | docs |
44
- | `CLAUDE.md`, `AGENTS.md`, etc. | Optional AI-assistant hint files that point tools at the toiljs docs. | docs |
45
-
46
- Two folders you may also see at the root:
47
-
48
- - **`.toil/`** is a working directory toiljs manages (a build cache and a copy of the docs). It is gitignored. You never edit it.
49
- - **`.env` and `.env.secrets`** are files **you** create when you need local environment variables or secrets during `toiljs dev`. They are gitignored so you never commit them, and the edge loads their real values out of band in production. Your server reads them with `Environment.get("KEY")` and `Environment.getSecure("KEY")`. See [Environment and secrets](../services/environment.md).
50
-
51
- ## `client/` (runs in the browser)
52
-
53
- This is a normal React app. You can use React libraries and browser APIs here freely.
54
-
55
- ```text
56
- client/
57
- toil.tsx the entry point; mounts your app
58
- layout.tsx the root layout wrapping every page
59
- 404.tsx the not-found page
60
- global-error.tsx the top-level error page
61
- routes/ file-based pages
62
- components/ shared React components
63
- styles/ global stylesheets
64
- public/ static files served as-is
65
- ```
66
-
67
- - **`toil.tsx`** is the entry file. It imports your global styles and calls `Toil.mount(...)` to start the app. You rarely change it beyond the style imports.
68
- - **`layout.tsx`** is your root layout: the header, footer, and page shell that wrap every route. Its `children` prop is the current page.
69
- - **`404.tsx`** renders when no route matches. **`global-error.tsx`** renders when a route throws.
70
- - **`routes/`** is where pages live, and the file name **is** the URL. `routes/index.tsx` is `/`, `routes/about.tsx` is `/about`, `routes/blog/[slug].tsx` is `/blog/:slug`. This is called **file-based routing**. See [Routing](../frontend/routing.md).
71
- - **`components/`** holds React components you reuse across pages. Nothing here is a route.
72
- - **`styles/`** holds your global CSS (or Sass, Less, or Stylus, if you chose one). See [Styling](../frontend/styling.md).
73
- - **`public/`** holds static files served exactly as they are: `favicon`, `robots.txt`, and an `images/` folder (reachable at `/images/...`). The `public/index.html` is the base HTML shell your app mounts into.
74
-
75
- A single global, `Toil`, is available in client code without an import (for `Toil.Link`, `Toil.Image`, and `Toil.Head`). It is typed by the generated `toil-env.d.ts`.
76
-
77
- ## `server/` (runs on the edge, as WebAssembly)
78
-
79
- This is your backend. It is compiled by toilscript into one `.wasm` file. Remember the two rules: **memory resets every request**, and **this is not Node.js** (a strict TypeScript subset, no arbitrary npm packages). See [Backend overview](../backend/README.md) and [Types](../concepts/types.md).
80
-
81
- ```text
82
- server/
83
- main.ts the entry: wires the handler + imports your 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
86
- core/ your request handler and shared logic
87
- models/ @data classes
88
- routes/ @rest controllers (HTTP)
89
- services/ @service / @remote (typed RPC)
90
- migrations/ ToilDB schema migrations
91
- scheduled/ reserved for scheduled tasks
92
- ```
93
-
94
- - **`main.ts`** is the entry the build compiles. It does three required things: it sets `Server.handler` (a factory that returns one fresh handler per request), it re-exports the wasm entry points (`export * from 'toiljs/server/runtime/exports'`), and it defines the `abort` hook. It also `import`s your other server modules so a direct toilscript run builds the same code.
95
- - **`core/`** holds your top-level `ToilHandler` (often `AppHandler.ts`): the first code that sees each request. It can dispatch to your `@rest` controllers and then fall through to any hand-written logic.
96
- - **`models/`** holds your `@data` classes, one type per file. A `@data` class is a typed message that can cross the wire between client and server (and into ToilDB). See [Data types](../backend/data.md).
97
- - **`routes/`** holds your `@rest` controllers: classes decorated with `@rest`, `@get`, and `@post` that expose HTTP endpoints. See [HTTP routes](../backend/rest.md).
98
- - **`services/`** holds `@service` classes and free `@remote` functions: typed remote calls the client makes as plain function calls (no URLs). See [Typed RPC](../backend/rpc.md).
99
- - **`migrations/`** holds ToilDB schema migrations. When you change the shape of a stored `@data` type, you add a `<Type>.migration.ts` here that carries old records forward. The compiler enforces this convention. See [Documents](../database/documents.md).
100
- - **`scheduled/`** is reserved for scheduled tasks. New decorated files anywhere under `server/` are picked up automatically by the build.
101
- - **`tsconfig.json`** and **`toil-server-env.d.ts`** are editor-support files. They teach your editor about the server globals (`crypto`, `Cookie`, `Environment`, and friends) so it stops flagging them. They do not affect the build.
102
-
103
- ### How the build discovers your server code
104
-
105
- You do not register routes in a config file. The compiler scans every `.ts` file under `server/` and picks up anything that declares a decorated surface (`@rest`, `@service`, `@remote`, `@data`, `@user`, `@database`, and so on). Importing those files from `main.ts` is still good practice: it keeps a direct `toilscript` run building the exact same server.
106
-
107
- ## `shared/` (generated glue)
108
-
109
- ```text
110
- shared/
111
- server.ts GENERATED typed client (do not edit)
112
- ```
113
-
114
- **`shared/server.ts` is written for you** by the server build. It contains:
115
-
116
- - A typed `Server` object the browser uses to call your backend: `Server.REST.*` for HTTP routes and `Server.<service>.*` for RPC.
117
- - The client-side codecs for every `@data` class, so responses come back as real typed objects.
118
- - A `getUser()` helper for reading the signed-in user on the client.
119
-
120
- Because it is generated, it does not exist in a fresh project and it is gitignored. It appears the first time you run `toiljs dev` or `toiljs build`. Never hand-edit it; change your server code and it regenerates.
121
-
122
- ## `build/` (compiled output)
123
-
124
- ```text
125
- build/
126
- server/release.wasm your compiled backend (+ release.wat, a readable text form)
127
- client/ the bundled React app (from Vite)
128
- ```
129
-
130
- This is what actually ships. It is gitignored and recreated by `toiljs build`. You do not edit anything here.
131
-
132
- ## Putting it together: one request
133
-
134
- ```mermaid
135
- sequenceDiagram
136
- participant B as Browser (client/)
137
- participant SH as shared/server.ts
138
- participant W as server.wasm (server/)
139
- participant DB as ToilDB
140
- B->>SH: Server.REST.likes.like()
141
- SH->>W: HTTP POST /likes
142
- W->>DB: counter.add(key, 1)
143
- W-->>SH: typed LikeCount response
144
- SH-->>B: { count }
145
- ```
146
-
147
- The browser calls a typed method, the generated client turns it into an HTTP request, your `.wasm` handles it and touches ToilDB, and a typed result comes back. You wrote both ends; the middle is generated.
148
-
149
- ## Gotchas and notes
150
-
151
- - **A `.ts` file's folder decides its rules.** The same code that works in `client/` may not compile in `server/`, because the server is a strict subset without Node APIs.
152
- - **Do not edit generated files.** `shared/server.ts`, `toil-env.d.ts`, `toil-routes.d.ts`, and `toil-server-env.d.ts` are all regenerated by the build and will overwrite your changes.
153
- - **One `@data` type per file** under `models/` keeps things tidy and matches the convention the tooling expects.
154
- - **`build/` and `.toil/` are disposable.** Delete them and the next build recreates them.
155
-
156
- ## Related
157
-
158
- - [Your first app](./first-app.md)
159
- - [Frontend overview](../frontend/README.md) and [Routing](../frontend/routing.md)
160
- - [Backend overview](../backend/README.md)
161
- - [Database overview](../database/README.md)
162
- - [Configuration](../concepts/config.md)
163
- - [Decorators reference](../concepts/decorators.md)