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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/template.ts +45 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-bakery",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "Scaffold a Bakery app: bun create bakery <directory>",
5
5
  "keywords": [
6
6
  "bakery",
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. It states
159
- // the contract — it does not validate it. The body is still client input.
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: 1,
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 — it
195
- // does not validate it. The body is still client input.
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[] = [