create-bakery 1.1.1 → 1.2.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.
- package/package.json +1 -1
- package/src/template.ts +45 -5
package/package.json
CHANGED
package/src/template.ts
CHANGED
|
@@ -155,14 +155,37 @@ const API_ROUTE = `import { defineRoute, response } from '@bakery-framework/core
|
|
|
155
155
|
import DB from '@bakery-framework/orm'
|
|
156
156
|
|
|
157
157
|
// The type parameter declares the body's shape: body.title / body.slug /
|
|
158
|
-
// body.body are strings below, while undeclared keys stay reachable.
|
|
159
|
-
//
|
|
158
|
+
// body.body are strings below, while undeclared keys stay reachable.
|
|
159
|
+
//
|
|
160
|
+
// It states the contract; it does not enforce it. To enforce it, pass a
|
|
161
|
+
// validator and the handler only runs on a body that satisfies it:
|
|
162
|
+
//
|
|
163
|
+
// export default defineRoute({ body: mySchema }, async (req, body) => …)
|
|
164
|
+
//
|
|
165
|
+
// The body option takes a Standard Schema (zod, valibot, arktype — Bakery
|
|
166
|
+
// bundles none of them), or a plain function returning the parsed value or
|
|
167
|
+
// throwing. A rejection answers 400 through the same JSON envelope as
|
|
168
|
+
// everything else.
|
|
169
|
+
// posts.authorId is a foreign key into users, so a post cannot be inserted
|
|
170
|
+
// before its author exists — the database refuses a dangling id, which is the
|
|
171
|
+
// entire point of the constraint. A real app takes the author from the session;
|
|
172
|
+
// this creates one on demand so the route works on a freshly synced database.
|
|
173
|
+
async function authorId(): Promise<number> {
|
|
174
|
+
const [existing] = await DB.from('users').selectAll('users').limit(1).array()
|
|
175
|
+
if (existing) return Number(existing.id)
|
|
176
|
+
|
|
177
|
+
const created = await DB.Insert.into('users')
|
|
178
|
+
.values({ username: 'demo', email: 'demo@example.com' })
|
|
179
|
+
.run()
|
|
180
|
+
return Number(created.lastInsertRowid)
|
|
181
|
+
}
|
|
182
|
+
|
|
160
183
|
export default defineRoute<{ title: string; slug: string; body: string }>(
|
|
161
184
|
async (req, body) => {
|
|
162
185
|
if (req.method === 'POST') {
|
|
163
186
|
await DB.Insert.into('posts')
|
|
164
187
|
.values({
|
|
165
|
-
authorId:
|
|
188
|
+
authorId: await authorId(),
|
|
166
189
|
title: body.title,
|
|
167
190
|
slug: body.slug,
|
|
168
191
|
body: body.body,
|
|
@@ -191,8 +214,8 @@ const API_ROUTE_NO_ORM = `import { defineRoute, response } from '@bakery-framewo
|
|
|
191
214
|
// with it, or add @bakery-framework/orm later.
|
|
192
215
|
const posts: { title: string }[] = []
|
|
193
216
|
|
|
194
|
-
// The type parameter declares the body's shape. It states the contract
|
|
195
|
-
//
|
|
217
|
+
// The type parameter declares the body's shape. It states the contract; to
|
|
218
|
+
// enforce it, pass a validator: defineRoute({ body: schema }, handler).
|
|
196
219
|
export default defineRoute<{ title: string }>(async (req, body) => {
|
|
197
220
|
if (req.method === 'POST') {
|
|
198
221
|
posts.push({ title: body.title })
|
|
@@ -436,6 +459,7 @@ export function templateFiles(
|
|
|
436
459
|
scripts: {
|
|
437
460
|
dev: 'bakery --dev',
|
|
438
461
|
start: 'bakery',
|
|
462
|
+
typecheck: 'tsc --noEmit',
|
|
439
463
|
...(orm ? { 'db:sync': 'bun run scripts/db-sync.ts' } : {}),
|
|
440
464
|
},
|
|
441
465
|
// Sorted, because the key order here is otherwise "whichever plugin was
|
|
@@ -444,6 +468,22 @@ export function templateFiles(
|
|
|
444
468
|
dependencies: Object.fromEntries(
|
|
445
469
|
Object.entries(dependencies).sort(([a], [b]) => a.localeCompare(b)),
|
|
446
470
|
),
|
|
471
|
+
// `bun-types` is not optional, and its absence is invisible until you run
|
|
472
|
+
// tsc. `@bakery-framework/core/tsconfig.server.json` sets
|
|
473
|
+
// `"types": ["bun-types"]` — it has to, that is what makes `Bun.*` a type
|
|
474
|
+
// error in browser code — but core declares no dependencies at all, so
|
|
475
|
+
// nothing installs the package the setting names. In this repo it resolves
|
|
476
|
+
// from a *root* devDependency, which is why the gap was invisible from
|
|
477
|
+
// inside the workspace: a generated app typechecked here and died with
|
|
478
|
+
// `TS2688: Cannot find type definition file for 'bun-types'` anywhere else.
|
|
479
|
+
//
|
|
480
|
+
// An app owning its own toolchain is the right shape regardless — the
|
|
481
|
+
// alternative is core taking a dependency, and having none is a property
|
|
482
|
+
// worth more than this convenience.
|
|
483
|
+
devDependencies: {
|
|
484
|
+
'bun-types': '^1.3.14',
|
|
485
|
+
typescript: '^7.0.0',
|
|
486
|
+
},
|
|
447
487
|
}
|
|
448
488
|
|
|
449
489
|
const files: TemplateFile[] = [
|