@shaferllc/keel 0.59.0 → 0.68.0

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 (166) hide show
  1. package/AGENTS.md +167 -0
  2. package/README.md +30 -1
  3. package/bin/keel-mcp.mjs +9 -0
  4. package/dist/core/application.d.ts +5 -5
  5. package/dist/core/application.js +14 -2
  6. package/dist/core/auth.d.ts +47 -0
  7. package/dist/core/auth.js +77 -0
  8. package/dist/core/authorization.d.ts +9 -1
  9. package/dist/core/authorization.js +22 -2
  10. package/dist/core/cache.d.ts +82 -5
  11. package/dist/core/cache.js +181 -23
  12. package/dist/core/cli/stubs.d.ts +12 -0
  13. package/dist/core/cli/stubs.js +120 -0
  14. package/dist/core/container.d.ts +20 -0
  15. package/dist/core/container.js +52 -0
  16. package/dist/core/cors.d.ts +29 -0
  17. package/dist/core/cors.js +72 -0
  18. package/dist/core/crypto.d.ts +40 -4
  19. package/dist/core/crypto.js +66 -6
  20. package/dist/core/csrf.d.ts +25 -0
  21. package/dist/core/csrf.js +78 -0
  22. package/dist/core/database.d.ts +49 -4
  23. package/dist/core/database.js +89 -21
  24. package/dist/core/events.d.ts +129 -5
  25. package/dist/core/events.js +165 -7
  26. package/dist/core/health.d.ts +141 -0
  27. package/dist/core/health.js +226 -0
  28. package/dist/core/helpers.d.ts +15 -3
  29. package/dist/core/helpers.js +23 -3
  30. package/dist/core/index.d.ts +33 -18
  31. package/dist/core/index.js +16 -8
  32. package/dist/core/lock.d.ts +139 -0
  33. package/dist/core/lock.js +215 -0
  34. package/dist/core/logger.d.ts +82 -4
  35. package/dist/core/logger.js +141 -23
  36. package/dist/core/mail.d.ts +128 -7
  37. package/dist/core/mail.js +264 -16
  38. package/dist/core/model.d.ts +2 -0
  39. package/dist/core/model.js +16 -14
  40. package/dist/core/provider.d.ts +7 -0
  41. package/dist/core/provider.js +7 -0
  42. package/dist/core/queue.d.ts +134 -9
  43. package/dist/core/queue.js +304 -14
  44. package/dist/core/rate-limit.js +3 -0
  45. package/dist/core/relations.js +13 -13
  46. package/dist/core/request.d.ts +26 -0
  47. package/dist/core/request.js +77 -0
  48. package/dist/core/shield.d.ts +39 -0
  49. package/dist/core/shield.js +60 -0
  50. package/dist/core/social.d.ts +173 -0
  51. package/dist/core/social.js +337 -0
  52. package/dist/core/storage.d.ts +159 -6
  53. package/dist/core/storage.js +287 -7
  54. package/dist/core/tokens.d.ts +74 -0
  55. package/dist/core/tokens.js +155 -0
  56. package/dist/db/d1.d.ts +32 -0
  57. package/dist/db/d1.js +26 -0
  58. package/dist/db/libsql.d.ts +29 -0
  59. package/dist/db/libsql.js +32 -0
  60. package/dist/db/pg.d.ts +29 -0
  61. package/dist/db/pg.js +33 -0
  62. package/dist/mcp/server.d.ts +19 -0
  63. package/dist/mcp/server.js +355 -0
  64. package/docs/ai-manifest.json +2472 -0
  65. package/docs/ai.md +128 -0
  66. package/docs/architecture.md +331 -0
  67. package/docs/authentication.md +453 -0
  68. package/docs/authorization.md +167 -0
  69. package/docs/broadcasting.md +137 -0
  70. package/docs/broker.md +500 -0
  71. package/docs/cache.md +558 -0
  72. package/docs/configuration.md +311 -0
  73. package/docs/console.md +356 -0
  74. package/docs/container.md +467 -0
  75. package/docs/controllers.md +265 -0
  76. package/docs/cors.md +51 -0
  77. package/docs/database.md +530 -0
  78. package/docs/debugging.md +129 -0
  79. package/docs/decorators.md +127 -0
  80. package/docs/errors.md +395 -0
  81. package/docs/events.md +496 -0
  82. package/docs/examples/architecture-app.ts +27 -0
  83. package/docs/examples/authentication.ts +61 -0
  84. package/docs/examples/authorization.ts +79 -0
  85. package/docs/examples/broadcasting.ts +60 -0
  86. package/docs/examples/broker-cache-validate.ts +34 -0
  87. package/docs/examples/broker-fault-tolerance.ts +29 -0
  88. package/docs/examples/broker-middleware.ts +27 -0
  89. package/docs/examples/broker.ts +203 -0
  90. package/docs/examples/cache.ts +222 -0
  91. package/docs/examples/configuration.ts +81 -0
  92. package/docs/examples/container.ts +134 -0
  93. package/docs/examples/controllers.ts +86 -0
  94. package/docs/examples/database.ts +118 -0
  95. package/docs/examples/debugging.ts +41 -0
  96. package/docs/examples/decorators.ts +40 -0
  97. package/docs/examples/errors.ts +121 -0
  98. package/docs/examples/events.ts +204 -0
  99. package/docs/examples/factories.ts +84 -0
  100. package/docs/examples/hashing.ts +71 -0
  101. package/docs/examples/health.ts +94 -0
  102. package/docs/examples/helpers.ts +171 -0
  103. package/docs/examples/hooks.ts +54 -0
  104. package/docs/examples/inertia.ts +81 -0
  105. package/docs/examples/locks.ts +120 -0
  106. package/docs/examples/logger.ts +92 -0
  107. package/docs/examples/mail.ts +160 -0
  108. package/docs/examples/middleware.ts +119 -0
  109. package/docs/examples/migrations.ts +126 -0
  110. package/docs/examples/models.ts +239 -0
  111. package/docs/examples/notification.ts +124 -0
  112. package/docs/examples/providers.ts +123 -0
  113. package/docs/examples/queues.ts +254 -0
  114. package/docs/examples/rate-limiting.ts +42 -0
  115. package/docs/examples/redis.ts +99 -0
  116. package/docs/examples/request-response.ts +197 -0
  117. package/docs/examples/routing.ts +186 -0
  118. package/docs/examples/scheduling.ts +62 -0
  119. package/docs/examples/sessions.ts +102 -0
  120. package/docs/examples/static-files.ts +63 -0
  121. package/docs/examples/storage.ts +132 -0
  122. package/docs/examples/templates.ts +58 -0
  123. package/docs/examples/testing.ts +66 -0
  124. package/docs/examples/transformer.ts +141 -0
  125. package/docs/examples/transformers.ts +49 -0
  126. package/docs/examples/url-builder.ts +86 -0
  127. package/docs/examples/validation.ts +102 -0
  128. package/docs/examples/views.tsx +62 -0
  129. package/docs/examples/vite.ts +106 -0
  130. package/docs/factories.md +166 -0
  131. package/docs/getting-started.md +290 -0
  132. package/docs/hashing.md +259 -0
  133. package/docs/health.md +225 -0
  134. package/docs/helpers.md +347 -0
  135. package/docs/hono.md +186 -0
  136. package/docs/hooks.md +118 -0
  137. package/docs/inertia.md +241 -0
  138. package/docs/locks.md +323 -0
  139. package/docs/logger.md +290 -0
  140. package/docs/mail.md +678 -0
  141. package/docs/middleware.md +425 -0
  142. package/docs/migrations.md +476 -0
  143. package/docs/models.md +810 -0
  144. package/docs/notifications.md +474 -0
  145. package/docs/providers.md +363 -0
  146. package/docs/queues.md +679 -0
  147. package/docs/rate-limiting.md +155 -0
  148. package/docs/redis.md +178 -0
  149. package/docs/request-response.md +953 -0
  150. package/docs/routing.md +804 -0
  151. package/docs/scheduling.md +110 -0
  152. package/docs/security.md +85 -0
  153. package/docs/sessions.md +354 -0
  154. package/docs/social-auth.md +174 -0
  155. package/docs/static-files.md +211 -0
  156. package/docs/storage.md +450 -0
  157. package/docs/templates.md +315 -0
  158. package/docs/testing.md +125 -0
  159. package/docs/transformers.md +381 -0
  160. package/docs/url-builder.md +295 -0
  161. package/docs/validation.md +288 -0
  162. package/docs/views.md +267 -0
  163. package/docs/vite.md +434 -0
  164. package/llms-full.txt +17694 -0
  165. package/llms.txt +116 -0
  166. package/package.json +38 -7
@@ -0,0 +1,166 @@
1
+ # Factories & Seeders
2
+
3
+ Populate the database with realistic fixtures for tests and demos. A **factory**
4
+ describes how to build a model's attributes; a **seeder** orchestrates factories
5
+ (and raw writes) into a repeatable dataset. Both are edge-safe and dependency-free
6
+ — the built-in `Faker` needs no external library.
7
+
8
+ ## Factories
9
+
10
+ Define a factory with the model and a definition function. The function receives
11
+ a `Faker` and the instance index, and returns the attributes:
12
+
13
+ ```ts
14
+ import { factory } from "@shaferllc/keel/core";
15
+
16
+ const users = factory(User, (f, i) => ({
17
+ name: f.name(),
18
+ email: f.email(),
19
+ }));
20
+ ```
21
+
22
+ Generate one with `keel make:factory User` (→ `database/factories/UserFactory.ts`).
23
+
24
+ ### Building vs. persisting
25
+
26
+ ```ts
27
+ users.make(); // a User instance, not saved
28
+ users.make({ name: "Ada" }); // with an override
29
+ await users.create(); // saved via Model.create, id back-filled
30
+ await users.create({ role: "admin" });
31
+ ```
32
+
33
+ ### Batches
34
+
35
+ `count(n)` sets how many the next call produces (an array):
36
+
37
+ ```ts
38
+ const ten = await users.count(10).create(); // User[]
39
+ const drafts = users.count(3).make(); // User[] (unsaved)
40
+
41
+ // the index lets each row differ
42
+ factory(User, (f, i) => ({ email: `user${i}@x.com` })).count(5);
43
+ ```
44
+
45
+ ## Faker
46
+
47
+ A small, seedable generator — enough for believable data without a dependency.
48
+
49
+ ```ts
50
+ const f = new Faker(); // random
51
+ const f = new Faker(42); // seeded — reproducible runs
52
+
53
+ f.name(); // "Grace Hopper"
54
+ f.firstName(); f.lastName();
55
+ f.email(); // "grace.hopper.1234@example.com"
56
+ f.word(); f.words(3); f.sentence(); f.paragraph();
57
+ f.number(1, 100); f.boolean();
58
+ f.pick(["a", "b", "c"]);
59
+ f.slug(); f.uuid();
60
+ ```
61
+
62
+ Seed a factory's faker for deterministic fixtures:
63
+
64
+ ```ts
65
+ import { Faker } from "@shaferllc/keel/core";
66
+ users.usingFaker(new Faker(42));
67
+ ```
68
+
69
+ `Faker` uses an xorshift32 PRNG — fast, edge-safe, and seedable. (Its `uuid()` is
70
+ for fixtures, not security; use `crypto` for real identifiers.)
71
+
72
+ ## Seeders
73
+
74
+ A seeder is a class with a `run()` method. Generate one with
75
+ `keel make:seeder Database`:
76
+
77
+ ```ts
78
+ import { Seeder } from "@shaferllc/keel/core";
79
+
80
+ class UserSeeder extends Seeder {
81
+ async run() {
82
+ await factory(User, (f) => ({ name: f.name(), email: f.email() }))
83
+ .count(10)
84
+ .create();
85
+ }
86
+ }
87
+
88
+ class DatabaseSeeder extends Seeder {
89
+ async run() {
90
+ await this.call([UserSeeder]); // compose seeders in order
91
+ }
92
+ }
93
+ ```
94
+
95
+ Run one with the `seed` helper (after your connection is registered):
96
+
97
+ ```ts
98
+ import { seed } from "@shaferllc/keel/core";
99
+ import { setConnection } from "@shaferllc/keel/core";
100
+
101
+ setConnection(myConnection, "postgres");
102
+ await seed(DatabaseSeeder);
103
+ ```
104
+
105
+ ## In tests
106
+
107
+ Factories shine in tests — register a connection (or a mock), then build fixtures
108
+ inline:
109
+
110
+ ```ts
111
+ setConnection(testConnection, "sqlite");
112
+
113
+ const [author] = await factory(User, (f) => ({ name: f.name() })).count(1).create();
114
+ const post = await factory(Post, (f) => ({ title: f.sentence() })).create({
115
+ user_id: author.id,
116
+ });
117
+ ```
118
+
119
+ ## API reference
120
+
121
+ ### `factory(model, definition)`
122
+
123
+ `factory<T extends Model>(model, definition: (f: Faker, i: number) => Row): ModelFactory<T>`
124
+
125
+ Start a factory for `model`. The definition receives a `Faker` and the instance
126
+ index, and returns the attributes.
127
+
128
+ ### `ModelFactory`
129
+
130
+ Returned by `factory()` (the `Factory` class, exported as `ModelFactory`).
131
+
132
+ | Method | Signature | Notes |
133
+ |--------|-----------|-------|
134
+ | `make` | `(overrides?) => T \| T[]` | build instance(s), unsaved |
135
+ | `create` | `(overrides?) => Promise<T \| T[]>` | persist via `Model.create` |
136
+ | `count` | `(n) => this` | how many the next `make`/`create` yields |
137
+ | `usingFaker` | `(faker) => this` | use a seeded `Faker` for reproducible data |
138
+
139
+ `count(1)` still returns an array; `count()` unset returns a single model.
140
+
141
+ ### `Faker`
142
+
143
+ `new Faker(seed?)` — seedable (deterministic) xorshift32 generator.
144
+
145
+ | Method | Returns |
146
+ |--------|---------|
147
+ | `name` / `firstName` / `lastName` | string |
148
+ | `email` / `slug` / `uuid` | string |
149
+ | `word` / `words(n?)` / `sentence(n?)` / `paragraph(n?)` | string |
150
+ | `number(min?, max?)` | number |
151
+ | `boolean` | boolean |
152
+ | `pick(items)` | one element of `items` |
153
+
154
+ `uuid()` is for fixtures, not security — use `crypto` for real ids.
155
+
156
+ ### `Seeder` / `seed(SeederClass)`
157
+
158
+ Abstract `Seeder` with an `async run()`; `protected call([...Seeders])` composes
159
+ others in order. `seed(DatabaseSeeder)` instantiates and runs one.
160
+
161
+ ### Interfaces & types
162
+
163
+ #### `Definition`
164
+
165
+ `type Definition<T> = (faker: Faker, index: number) => Row` — the factory
166
+ definition function.
@@ -0,0 +1,290 @@
1
+ # Getting Started
2
+
3
+ Keel is a house framework for Node.js — a small, legible MVC layer over
4
+ [Hono](./hono.md). This guide is a guided first hour: install it, stand up a
5
+ route, a controller, and a view, read some config, drive the console, and know
6
+ where to go next.
7
+
8
+ ## Requirements
9
+
10
+ - Node.js **≥ 22**
11
+ - npm (ships with Node)
12
+
13
+ Keel targets modern Node and web-standard APIs, so a current runtime matters —
14
+ `22` is the floor.
15
+
16
+ ## Install
17
+
18
+ Keel ships as two repos: the **framework** (`@shaferllc/keel`, published to
19
+ npm) and a **starter app** (`shaferllc/keel-app`) you build on. Which path you
20
+ take depends on whether you're starting fresh or bolting Keel onto something
21
+ that already exists. See [Architecture](./architecture.md#two-repos-library-and-starter)
22
+ for why it's split this way.
23
+
24
+ ### From the starter (recommended)
25
+
26
+ The fastest route to a running app is the starter — a working skeleton with the
27
+ folders, config, and scripts already wired:
28
+
29
+ ```bash
30
+ git clone https://github.com/shaferllc/keel-app.git my-app
31
+ cd my-app
32
+ npm install
33
+ ```
34
+
35
+ The starter depends on `@shaferllc/keel`, so you pick up framework updates with
36
+ an ordinary `npm update @shaferllc/keel` — your app code in `app/` stays put.
37
+
38
+ A fresh checkout ships with a working `.env`. To start from the template
39
+ instead:
40
+
41
+ ```bash
42
+ cp .env.example .env
43
+ ```
44
+
45
+ ### Into an existing app
46
+
47
+ Already have a Node project? Add the package:
48
+
49
+ ```bash
50
+ npm install @shaferllc/keel
51
+ ```
52
+
53
+ Everything Keel exposes comes from one entry point:
54
+
55
+ ```ts
56
+ import { Application, Router, config } from "@shaferllc/keel/core";
57
+ ```
58
+
59
+ You supply the four convention folders yourself — `app/`, `config/`, `routes/`,
60
+ `bootstrap/` — plus an entry that calls `createApplication()`. The starter's
61
+ `bootstrap/app.ts` is the reference; copy it and trim to taste.
62
+
63
+ ### Hacking on the framework itself
64
+
65
+ To work on Keel proper, clone the framework repo — it carries an example app you
66
+ can run directly:
67
+
68
+ ```bash
69
+ git clone https://github.com/shaferllc/keel.git
70
+ cd keel
71
+ npm install
72
+ npm run dev # example app on http://localhost:3000
73
+ npm run build # compile the package to dist/
74
+ ```
75
+
76
+ ## Run the server
77
+
78
+ ```bash
79
+ npm run dev # tsx watch — restarts on change
80
+ # or
81
+ npm run serve # one-shot
82
+ ```
83
+
84
+ You should see:
85
+
86
+ ```
87
+ ⚓ Keel listening on http://localhost:3000
88
+ ```
89
+
90
+ Hit the sample routes the starter ships with:
91
+
92
+ ```bash
93
+ curl localhost:3000/ # {"framework":"Keel", ...}
94
+ curl localhost:3000/ping # {"pong":true}
95
+ curl localhost:3000/hello/Tom # Hello, Tom!
96
+ ```
97
+
98
+ ## Your first route
99
+
100
+ Routes live in `routes/web.ts`. The simplest is a **closure** — a function that
101
+ takes the request context `c` and returns a response:
102
+
103
+ ```ts
104
+ router.get("/status", (c) => c.json({ ok: true, time: Date.now() }));
105
+ ```
106
+
107
+ Save — `tsx watch` reloads — and visit `http://localhost:3000/status`.
108
+
109
+ A route handler can be a closure, a `[Controller, method]` tuple, or even a
110
+ ready-made `Response`. Closures are perfect for one-liners; reach for a
111
+ controller once there's real logic to house. Parameters come off the path with a
112
+ leading colon:
113
+
114
+ ```ts
115
+ router.get("/greet/:name", (c) => c.text(`Ahoy, ${c.req.param("name")}!`));
116
+ ```
117
+
118
+ You don't have to thread `c` everywhere, either — Keel's [request
119
+ helpers](./request-response.md) reach the active request from anywhere, so the
120
+ same route reads:
121
+
122
+ ```ts
123
+ import { text, param } from "@shaferllc/keel/core";
124
+
125
+ router.get("/greet/:name", () => text(`Ahoy, ${param("name")}!`));
126
+ ```
127
+
128
+ See [Routing](./routing.md) for names, groups, resource routes, param
129
+ constraints, and URL generation.
130
+
131
+ ## Your first controller
132
+
133
+ Once a handler grows past a line or two, move it into a controller. Generate one
134
+ with the console:
135
+
136
+ ```bash
137
+ npm run keel make:controller Task
138
+ ```
139
+
140
+ That writes `app/Controllers/TaskController.ts`:
141
+
142
+ ```ts
143
+ import type { Ctx } from "@shaferllc/keel/core";
144
+
145
+ export class TaskController {
146
+ index(c: Ctx) {
147
+ return c.json({ controller: "TaskController", action: "index" });
148
+ }
149
+ }
150
+ ```
151
+
152
+ Wire it up in `routes/web.ts` with a `[Controller, method]` tuple. Keel resolves
153
+ the controller **out of the container**, so its constructor gets dependency
154
+ injection for free:
155
+
156
+ ```ts
157
+ import { TaskController } from "../app/Controllers/TaskController.js";
158
+
159
+ router.get("/tasks", [TaskController, "index"]);
160
+ ```
161
+
162
+ Confirm it's registered:
163
+
164
+ ```bash
165
+ npm run keel routes
166
+ ```
167
+
168
+ ```
169
+ GET /tasks TaskController@index
170
+ ```
171
+
172
+ Add more actions as plain methods, and give related routes their REST shape in
173
+ one call with `router.resource("tasks", TaskController)`. [Controllers](./controllers.md)
174
+ covers single-action controllers, lazy-loaded controllers, and how DI reaches
175
+ the constructor.
176
+
177
+ ## Your first view
178
+
179
+ Keel views are [Hono JSX](./hono.md) components — plain functions that return
180
+ markup. They live by convention in `resources/views/`. Create
181
+ `resources/views/tasks.tsx`:
182
+
183
+ ```tsx
184
+ // @jsxImportSource hono/jsx
185
+ import type { FC } from "hono/jsx";
186
+
187
+ export const TasksPage: FC<{ count: number }> = ({ count }) => (
188
+ <main>
189
+ <h1>⚓ Tasks</h1>
190
+ <p>You have {count} task(s) aboard.</p>
191
+ </main>
192
+ );
193
+ ```
194
+
195
+ Render it from the controller with the `view()` helper — it renders the
196
+ component to a full HTML document and type-checks the props against the
197
+ component:
198
+
199
+ ```ts
200
+ import type { Ctx } from "@shaferllc/keel/core";
201
+ import { view } from "@shaferllc/keel/core";
202
+ import { TasksPage } from "../../resources/views/tasks.js";
203
+
204
+ export class TaskController {
205
+ index(c: Ctx) {
206
+ return view(TasksPage, { count: 3 });
207
+ }
208
+ }
209
+ ```
210
+
211
+ Note the `.js` import specifier for a `.tsx` file — that's the Node ESM
212
+ convention, and it's correct even though the file on disk is TypeScript. See
213
+ [Views](./views.md) for layouts, async components, and streaming.
214
+
215
+ ## Configuration
216
+
217
+ Config files live in `config/` and each exports a default object. They're loaded
218
+ at boot under their filename, so `config/app.ts` is reachable as `config('app.*')`:
219
+
220
+ ```ts
221
+ // config/app.ts
222
+ import { env } from "@shaferllc/keel/core";
223
+
224
+ export default {
225
+ name: env("APP_NAME", "Keel"),
226
+ env: env("APP_ENV", "local"),
227
+ debug: env("APP_DEBUG", true),
228
+ url: env("APP_URL", "http://localhost:3000"),
229
+ port: env("APP_PORT", 3000),
230
+ };
231
+ ```
232
+
233
+ `env()` reads a variable from `.env` (loaded at boot) with a typed fallback — it
234
+ coerces `"true"`/`"false"` to booleans and numeric strings to numbers when the
235
+ fallback is a number. Read config anywhere with the `config()` helper, using dot
236
+ notation and an optional fallback:
237
+
238
+ ```ts
239
+ import { config } from "@shaferllc/keel/core";
240
+
241
+ config("app.name"); // "Keel"
242
+ config("app.port", 3000); // number, with a fallback
243
+ ```
244
+
245
+ Add a new config file by dropping it in `config/` — `config/mail.ts` becomes
246
+ `config('mail.*')` with no wiring. [Configuration](./configuration.md) has the
247
+ full story.
248
+
249
+ ## The console
250
+
251
+ The `keel` console drives the app from the command line. In the starter, run it
252
+ through npm:
253
+
254
+ ```bash
255
+ npm run keel routes # list every registered route
256
+ npm run keel serve --port 8080 # start the server on a chosen port
257
+ npm run keel make:controller Post # -> app/Controllers/PostController.ts
258
+ npm run keel make:provider Billing # -> app/Providers/BillingServiceProvider.ts
259
+ npm run keel make:middleware Auth # -> app/Http/Middleware/authMiddleware.ts
260
+ ```
261
+
262
+ The `make:*` generators scaffold from the same stubs the framework uses, so
263
+ generated files are wired to the right folders and import from
264
+ `@shaferllc/keel/core`. `keel routes` is your map — run it whenever you're
265
+ unsure what's mounted. [The Console](./console.md) lists every command.
266
+
267
+ ## Where to go next
268
+
269
+ You now have the shape of a Keel app: routes point at controllers, controllers
270
+ render views and read config, and the console scaffolds the pieces. The deep
271
+ guides pick up from here:
272
+
273
+ - [Architecture](./architecture.md) — how boot, the container, and the request
274
+ lifecycle fit together
275
+ - [The Service Container](./container.md) — how dependency injection works
276
+ - [Service Providers](./providers.md) — where you register your own services
277
+ - [Routing](./routing.md) — parameters, names, groups, resources, URLs
278
+ - [Controllers](./controllers.md) — actions, DI, single-action controllers
279
+ - [Views](./views.md) — JSX components, layouts, streaming
280
+ - [Middleware](./middleware.md) — global and per-route request filters
281
+ - [Request & Response](./request-response.md) — the helpers that reach the
282
+ active request
283
+ - [Database](./database.md) and [Models](./models.md) — the query builder and
284
+ the active-record layer on top of it
285
+ - [Configuration](./configuration.md) and [The Console](./console.md) — settings
286
+ and commands
287
+
288
+ When something isn't documented, open the source — the whole framework is a few
289
+ hundred readable lines in `src/core/`, and [Built on Hono](./hono.md) explains
290
+ what you inherit from the layer underneath.