@beignet/cli 0.0.3 → 0.0.4

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 (98) hide show
  1. package/CHANGELOG.md +205 -0
  2. package/README.md +379 -61
  3. package/dist/ansi.d.ts +10 -0
  4. package/dist/ansi.d.ts.map +1 -0
  5. package/dist/ansi.js +20 -0
  6. package/dist/ansi.js.map +1 -0
  7. package/dist/choices.d.ts +72 -0
  8. package/dist/choices.d.ts.map +1 -0
  9. package/dist/choices.js +88 -0
  10. package/dist/choices.js.map +1 -0
  11. package/dist/completion.d.ts +47 -0
  12. package/dist/completion.d.ts.map +1 -0
  13. package/dist/completion.js +123 -0
  14. package/dist/completion.js.map +1 -0
  15. package/dist/config.d.ts +8 -0
  16. package/dist/config.d.ts.map +1 -1
  17. package/dist/config.js +8 -0
  18. package/dist/config.js.map +1 -1
  19. package/dist/create-prompts.d.ts +42 -0
  20. package/dist/create-prompts.d.ts.map +1 -0
  21. package/dist/create-prompts.js +136 -0
  22. package/dist/create-prompts.js.map +1 -0
  23. package/dist/create.d.ts +4 -1
  24. package/dist/create.d.ts.map +1 -1
  25. package/dist/create.js +16 -26
  26. package/dist/create.js.map +1 -1
  27. package/dist/db.d.ts +1 -0
  28. package/dist/db.d.ts.map +1 -1
  29. package/dist/db.js +37 -2
  30. package/dist/db.js.map +1 -1
  31. package/dist/github-annotations.d.ts +18 -0
  32. package/dist/github-annotations.d.ts.map +1 -0
  33. package/dist/github-annotations.js +22 -0
  34. package/dist/github-annotations.js.map +1 -0
  35. package/dist/index.d.ts +1 -9
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +657 -588
  38. package/dist/index.js.map +1 -1
  39. package/dist/inspect.d.ts +21 -2
  40. package/dist/inspect.d.ts.map +1 -1
  41. package/dist/inspect.js +1938 -131
  42. package/dist/inspect.js.map +1 -1
  43. package/dist/lib.d.ts +20 -0
  44. package/dist/lib.d.ts.map +1 -0
  45. package/dist/lib.js +17 -0
  46. package/dist/lib.js.map +1 -0
  47. package/dist/lint.d.ts +10 -1
  48. package/dist/lint.d.ts.map +1 -1
  49. package/dist/lint.js +340 -33
  50. package/dist/lint.js.map +1 -1
  51. package/dist/make.d.ts +20 -3
  52. package/dist/make.d.ts.map +1 -1
  53. package/dist/make.js +1756 -394
  54. package/dist/make.js.map +1 -1
  55. package/dist/outbox.d.ts +24 -0
  56. package/dist/outbox.d.ts.map +1 -0
  57. package/dist/outbox.js +138 -0
  58. package/dist/outbox.js.map +1 -0
  59. package/dist/schedule.d.ts +36 -0
  60. package/dist/schedule.d.ts.map +1 -0
  61. package/dist/schedule.js +155 -0
  62. package/dist/schedule.js.map +1 -0
  63. package/dist/task.d.ts +26 -0
  64. package/dist/task.d.ts.map +1 -0
  65. package/dist/task.js +106 -0
  66. package/dist/task.js.map +1 -0
  67. package/dist/templates.d.ts +3 -32
  68. package/dist/templates.d.ts.map +1 -1
  69. package/dist/templates.js +1002 -527
  70. package/dist/templates.js.map +1 -1
  71. package/dist/version.d.ts +8 -0
  72. package/dist/version.d.ts.map +1 -0
  73. package/dist/version.js +18 -0
  74. package/dist/version.js.map +1 -0
  75. package/package.json +9 -8
  76. package/src/ansi.ts +30 -0
  77. package/src/choices.ts +137 -0
  78. package/src/completion.ts +169 -0
  79. package/src/config.ts +16 -0
  80. package/src/create-prompts.ts +182 -0
  81. package/src/create.ts +24 -31
  82. package/src/db.ts +60 -4
  83. package/src/github-annotations.ts +37 -0
  84. package/src/index.ts +1067 -803
  85. package/src/inspect.ts +2859 -115
  86. package/src/lib.ts +45 -0
  87. package/src/lint.ts +493 -39
  88. package/src/make.ts +2181 -405
  89. package/src/outbox.ts +249 -0
  90. package/src/schedule.ts +272 -0
  91. package/src/task.ts +169 -0
  92. package/src/templates.ts +1073 -567
  93. package/src/version.ts +20 -0
  94. package/dist/create-bin.d.ts +0 -3
  95. package/dist/create-bin.d.ts.map +0 -1
  96. package/dist/create-bin.js +0 -9
  97. package/dist/create-bin.js.map +0 -1
  98. package/src/create-bin.ts +0 -11
package/README.md CHANGED
@@ -1,25 +1,57 @@
1
1
  # @beignet/cli
2
2
 
3
+ > [!CAUTION]
4
+ > Beignet is experimental alpha software. The `0.0.x` package line is for early
5
+ > evaluation, and APIs may change between releases while the framework settles.
6
+
3
7
  Command-line tools for creating and maintaining Beignet apps.
4
8
 
5
- ## Create an app
9
+ The package ships a single `beignet` bin. Generated apps install
10
+ `@beignet/cli` as a dev dependency and add a `beignet` package script, so the
11
+ day-to-day form inside an app is:
6
12
 
7
13
  ```bash
8
- bunx -p @beignet/cli beignet create my-app
14
+ bun beignet doctor --strict
9
15
  ```
10
16
 
11
- Or use the package binary directly:
17
+ With npm use `npm run beignet -- doctor --strict`, with pnpm
18
+ `pnpm beignet doctor --strict`, and with yarn `yarn beignet doctor --strict`.
19
+ For one-off runs outside an app, invoke the scoped package directly:
20
+
21
+ ```bash
22
+ bunx @beignet/cli routes
23
+ ```
24
+
25
+ Never run the unscoped `beignet` name through bunx or npx; that npm name
26
+ belongs to an unrelated package.
27
+
28
+ ## Create an app
29
+
30
+ App scaffolding lives in the `create-beignet` package:
12
31
 
13
32
  ```bash
14
- bunx -p @beignet/cli create-beignet my-app
33
+ npm create beignet@latest my-app
34
+ # or
35
+ bun create beignet my-app
15
36
  ```
16
37
 
38
+ Both delegate to `beignet create`, so `bunx @beignet/cli create my-app` is
39
+ equivalent.
40
+
41
+ Running create in an interactive terminal without selection flags opens a
42
+ prompt-based setup that asks for the project directory, preset, features,
43
+ integrations, and package manager. Passing any selection flag
44
+ (`--preset`, `--features`, `--integrations`, or `--package-manager`) skips the
45
+ prompts, and `--yes` forces the non-interactive defaults (the `standard`
46
+ preset with `bun`) even on a terminal. Non-interactive runs in scripts and CI
47
+ behave exactly as before.
48
+
17
49
  By default the CLI creates a Next.js app with:
18
50
 
19
51
  - Contract-first todos API routes
20
52
  - Better Auth routes and Beignet auth provider wiring
21
53
  - Drizzle/libSQL persistence with a local SQLite default and Turso-ready config
22
- - UOW, audit logging, and a durable outbox drain route
54
+ - UOW, audit logging, durable idempotency, and a durable outbox drain route
23
55
  - Jobs, events, listeners, schedules, mail-backed notifications, and uploads
24
56
  - App-owned ports with provider-backed infra adapters
25
57
  - Validated application use cases
@@ -30,31 +62,52 @@ By default the CLI creates a Next.js app with:
30
62
  - React Hook Form
31
63
  - OpenAPI output
32
64
 
65
+ Preview the planned files without writing anything:
66
+
67
+ ```bash
68
+ bunx @beignet/cli create my-app --dry-run
69
+ bunx @beignet/cli create my-app --dry-run --json
70
+ ```
71
+
33
72
  The CLI writes files only. After creation:
34
73
 
35
74
  ```bash
36
75
  cd my-app
37
76
  bun install
38
77
  cp .env.example .env.local
78
+ bun beignet db generate
79
+ bun beignet db migrate
39
80
  bun run dev
40
81
  ```
41
82
 
42
- Common follow-up commands:
83
+ Open `http://localhost:3000` for the starter UI. The generated homepage links
84
+ to the todo feature, health check, OpenAPI document, devtools, and Beignet
85
+ docs.
86
+
87
+ Inspect the app, then generate the next feature:
43
88
 
44
89
  ```bash
45
90
  # in another terminal, from my-app
46
- bunx -p @beignet/cli beignet make feature projects
47
- bunx -p @beignet/cli beignet db generate
48
- bunx -p @beignet/cli beignet db migrate
49
- bunx -p @beignet/cli beignet routes
50
- bunx -p @beignet/cli beignet lint
51
- bunx -p @beignet/cli beignet doctor
91
+ bun beignet routes
92
+ bun beignet lint
93
+ bun beignet doctor
94
+ bun beignet make feature projects
95
+ bun beignet db generate
96
+ bun beignet db migrate
97
+ bun run test
98
+ bun run typecheck
99
+ bun beignet lint
100
+ bun beignet doctor
52
101
  ```
53
102
 
54
103
  ## Options
55
104
 
56
105
  ```bash
57
- beignet create <directory> [options]
106
+ beignet create [directory] [options]
107
+ beignet task run <name> [options]
108
+ beignet outbox drain [options]
109
+ beignet schedule run <name> [options]
110
+ beignet make task <feature>/<name> [options]
58
111
  beignet make contract <name> [options]
59
112
  beignet make event <feature>/<name> [options]
60
113
  beignet make factory <feature>/<name> [options]
@@ -74,32 +127,104 @@ beignet db generate [--dry-run] [--json]
74
127
  beignet db migrate [--dry-run] [--json]
75
128
  beignet db seed [--dry-run] [--json]
76
129
  beignet db reset [--dry-run] [--json]
77
- beignet routes [--json]
78
- beignet lint [--json]
79
- beignet doctor [--json] [--strict] [--fix]
130
+ beignet routes [--json] [--cwd <dir>]
131
+ beignet lint [--json] [--cwd <dir>] [--format human|json|github]
132
+ beignet doctor [--json] [--strict] [--fix] [--cwd <dir>] [--format human|json|github]
133
+ beignet completion install [--shell bash|zsh]
134
+ beignet completion uninstall [--shell bash|zsh]
135
+ beignet --version
80
136
 
81
137
  Options:
82
138
  --template next Template to use. Currently only `next`.
83
- --preset standard `minimal` or `standard`.
139
+ --preset standard `minimal` or `standard`. Defaults to `standard`.
84
140
  --package-manager bun Package manager shown in next steps.
85
- --feature react-query Add a starter feature. Repeatable.
86
- --features client,openapi Add features from a comma-separated list.
87
- --integration inngest Add an integration. Repeatable.
88
- --integrations inngest,pino Add integrations from a comma-separated list.
141
+ --features client,openapi Add starter features. Accepts one value or a comma-separated list.
142
+ --integrations inngest,pino Add integrations. Accepts one value or a comma-separated list.
143
+ --yes Skip interactive create prompts and use the defaults.
89
144
  --force Write into a non-empty directory.
90
- --dry-run Preview make writes without changing files.
145
+ --dry-run Preview create/make writes without changing files.
91
146
  --json Print machine-readable output.
92
- --with policy,events Add optional artifacts to `make feature`; also supports jobs, notifications, uploads.
147
+ --cwd path/to/app Run routes, lint, or doctor against another app directory.
148
+ --format github Output format for lint and doctor: human, json, or github.
149
+ --input '{"dryRun":true}' JSON input for `beignet task run`.
150
+ --payload '{"date":"..."}' JSON payload for `beignet schedule run`.
151
+ --module server/tasks.ts Override the task, outbox, or schedule registry path.
152
+ --batch-size 100 Maximum outbox messages to claim in one drain pass.
153
+ --scheduled-at 2026-01-01 Provider scheduled timestamp for schedule runs.
154
+ --triggered-at 2026-01-01 Trigger timestamp for schedule runs.
155
+ --attempt 1 One-based provider attempt number for schedule runs.
156
+ --source manual Provider or app source label for schedule runs.
157
+ --with policy,events Add optional artifacts to `make feature`; also supports tasks, jobs, notifications, ui, uploads.
158
+ --auth Add authorization metadata, policy wiring, policy tests, and use-case gate checks to `make resource`.
159
+ --tenant Add tenant-scoped schemas, repository filters, and use-case tenant checks to `make resource`.
160
+ --events Add created, updated, and deleted domain events to `make resource`.
161
+ --soft-delete Archive resource rows with deletedAt instead of hard-deleting them.
93
162
  --event posts/published Event for `make listener`.
94
163
  --cron "0 9 * * *" Cron expression for `make schedule`.
95
164
  --timezone America/Chicago Timezone for `make schedule`.
96
165
  --route Add a Next.js cron route for `make schedule`.
97
166
  --strict Include CI-oriented doctor warnings and fail on warnings.
98
167
  --fix Apply low-risk doctor fixes before reporting.
168
+ --shell zsh Shell for `completion install`/`uninstall`. Defaults to $SHELL.
99
169
  -h, --help Show help.
170
+ -v, --version Print the CLI version.
171
+ ```
172
+
173
+ ## Exit codes
174
+
175
+ Every command uses the same exit-code matrix:
176
+
177
+ | Code | Meaning |
178
+ | ---- | ------------------------------------------------------------------------ |
179
+ | 0 | Success. |
180
+ | 1 | Findings: lint diagnostics, doctor errors, or strict-mode doctor warnings. |
181
+ | 2 | Usage or internal errors: unknown commands, bad flags, missing arguments, runtime failures, or running `beignet` with no arguments. |
182
+
183
+ `--format` never changes the exit code; `lint --format github` still exits 1
184
+ when it finds diagnostics.
185
+
186
+ ## Output formats
187
+
188
+ `lint` and `doctor` support three output formats. `--json` stays the
189
+ canonical machine-readable flag; `--format` adds GitHub Actions annotations:
190
+
191
+ ```bash
192
+ beignet lint --format github
193
+ beignet doctor --strict --format github
194
+ ```
195
+
196
+ The github format emits one `::error`, `::warning`, or `::notice` workflow
197
+ command per diagnostic, with `file`, `line`, and `col` properties when known.
198
+ When `GITHUB_ACTIONS=true` is set and no format is passed, lint and doctor
199
+ default to the github format; otherwise they default to human output.
200
+ Combining `--json` with a conflicting `--format` is an error. Human output
201
+ groups doctor diagnostics by severity, colors severity labels on TTYs, and
202
+ respects `NO_COLOR`.
203
+
204
+ All `--json` results begin with `schemaVersion: 1` so other tools can detect
205
+ output-shape changes.
206
+
207
+ ## Shell completions
208
+
209
+ Install tab completions for the `beignet` bin into your shell rc file:
210
+
211
+ ```bash
212
+ beignet completion install
213
+ beignet completion install --shell zsh
214
+ beignet completion uninstall
100
215
  ```
101
216
 
102
- ## App conventions
217
+ `install` writes a managed block to `~/.bashrc` or `~/.zshrc` (detected from
218
+ `$SHELL` when `--shell` is omitted) and `uninstall` removes it. Restart your
219
+ shell or source the rc file to activate completions. Zsh completions require
220
+ `compinit` to be loaded, which most zsh setups already do.
221
+
222
+ Completions cover commands, subcommands, flags, and enum flag values such as
223
+ `--preset` and `--features`. The shell scripts call the
224
+ `beignet completion propose` helper, which prints one proposal per line for a
225
+ partial command line; it exists for the shell integration and is safe to
226
+ ignore otherwise. Completions complete whatever `beignet` resolves to on your
227
+ `PATH`, such as the app-local bin installed by generated apps.
103
228
 
104
229
  Beignet CLI commands are convention-aware. `routes`, `lint`, `doctor`, and
105
230
  generators work best in the Next.js layout created by `beignet create`:
@@ -107,12 +232,17 @@ generators work best in the Next.js layout created by `beignet create`:
107
232
  ```txt
108
233
  features/
109
234
  app/api/
235
+ server/context.ts
110
236
  server/index.ts
111
237
  server/routes.ts
112
238
  ```
113
239
 
240
+ `server/context.ts` declares the app's context blueprint with
241
+ `defineServerContext(...)`; `server/index.ts` passes it to the server and
242
+ generated route tests pass the same value to `createTestApp(...)`.
243
+
114
244
  Route inspection supports contract-group definitions and direct
115
- `createContract({ method, path })` exports.
245
+ `defineContract({ method, path })` exports.
116
246
 
117
247
  The standard app layout includes the files feature generators expect:
118
248
 
@@ -123,6 +253,11 @@ ports/index.ts
123
253
  lib/use-case.ts
124
254
  ```
125
255
 
256
+ Standard apps also include context-bound capability builders in `lib/`
257
+ (`lib/listeners.ts`, `lib/jobs.ts`, `lib/schedules.ts`, and
258
+ `lib/notifications.ts`); generators create missing builder files on demand,
259
+ including `lib/tasks.ts`.
260
+
126
261
  Generated apps include these files by default. The CLI uses this shape to
127
262
  inspect routes, wire generated features, and report drift safely. `beignet
128
263
  doctor` reports when a directory does not match the app layout.
@@ -141,6 +276,9 @@ export default defineConfig({
141
276
  features: "src/features",
142
277
  routes: "src/app/api",
143
278
  server: "src/core/server/index.ts",
279
+ tasks: "src/core/server/tasks.ts",
280
+ outbox: "src/core/server/outbox.ts",
281
+ schedules: "src/core/server/schedules.ts",
144
282
  },
145
283
  });
146
284
  ```
@@ -168,7 +306,8 @@ divergent files unless you pass `--force`.
168
306
 
169
307
  ## Generate a feature
170
308
 
171
- Inside a Beignet app, scaffold the standard contract-first vertical slice with:
309
+ Inside a Beignet app, scaffold the standard contract-first vertical slice for a
310
+ product capability or workflow with:
172
311
 
173
312
  ```bash
174
313
  beignet make feature projects
@@ -193,7 +332,7 @@ around the feature's real workflow.
193
332
  Add common feature-owned artifacts with `--with`:
194
333
 
195
334
  ```bash
196
- beignet make feature projects --with policy,events,jobs,uploads
335
+ beignet make feature projects --with policy,events,jobs,notifications,ui,uploads
197
336
  ```
198
337
 
199
338
  The optional artifacts use predictable starter names:
@@ -201,10 +340,20 @@ The optional artifacts use predictable starter names:
201
340
  - `features/projects/policy.ts`
202
341
  - `features/projects/domain/events/created.ts`
203
342
  - `features/projects/jobs/process.ts`
343
+ - `features/projects/notifications/created.ts`
344
+ - `features/projects/components/projects-panel.tsx`
204
345
  - `features/projects/uploads/attachment.ts`
205
346
 
206
- Event, job, and upload registries are created or updated in the matching
207
- folder `index.ts` files.
347
+ Event, job, notification, and upload registries are created or updated in the
348
+ matching folder `index.ts` files. The UI addon is opt-in:
349
+
350
+ ```bash
351
+ beignet make feature projects --with ui
352
+ ```
353
+
354
+ It writes a feature-colocated React component that uses the generated
355
+ contracts through `client/index.ts` and TanStack Query, with error messages
356
+ from `contractErrorMessage` in `@beignet/core/client`.
208
357
 
209
358
  ## Generate a use case
210
359
 
@@ -223,7 +372,10 @@ The name uses `feature/action` format. The command writes
223
372
 
224
373
  ## Generate a test
225
374
 
226
- Use `make test` after generating a use case:
375
+ Use `make test` after generating a focused use case. Generated features and
376
+ resources already include their baseline contract, use-case, route, policy, and
377
+ repository-oriented tests; `make test` is for adding coverage around an
378
+ additional workflow that does not need a whole new resource slice.
227
379
 
228
380
  ```bash
229
381
  beignet make use-case projects/archive-project
@@ -231,7 +383,8 @@ beignet make test projects/archive-project
231
383
  ```
232
384
 
233
385
  The command writes `features/projects/tests/archive-project.test.ts`, builds the
234
- app context through `createUseCaseTester`, and asserts the starter
386
+ app context through `createTestPorts(...)`, `createTestContextFactory(...)`, and
387
+ `createUseCaseTester(...)`, and asserts the starter
235
388
  `{ ok: true }` response. It also adds a `test` script when the app does not
236
389
  already define one. Treat the output as a compiling starting point: replace the
237
390
  input, context setup, and assertion with behavior-specific coverage as the use
@@ -284,27 +437,52 @@ was already customized, the command stops instead of guessing.
284
437
 
285
438
  ## Generate a resource
286
439
 
287
- Use `make resource` when the feature you are building is CRUD-shaped and you
288
- prefer resource language:
440
+ Use `make resource` when the feature you are building is CRUD-shaped and the
441
+ main concept is an entity with repository-backed persistence:
289
442
 
290
443
  ```bash
291
444
  beignet make resource projects
445
+ beignet make resource projects --auth --tenant --events --soft-delete
292
446
  ```
293
447
 
294
- Today `make resource` and `make feature` generate the same contract-to-test
295
- slice. The feature command is the recommended default because not every Beignet
296
- feature maps cleanly to a REST resource.
448
+ `make resource` generates a CRUD-shaped slice with list, create, get, update,
449
+ and delete contracts, use cases, route handlers, repository methods, a policy
450
+ starter, tests, and feature-specific not-found and conflict catalog errors. Use
451
+ `make feature` for workflows and capabilities that do not map cleanly to a REST
452
+ resource.
453
+
454
+ Generated list routes use cursor pagination with `limit`, `cursor`, `name`,
455
+ `sortBy`, and `sortDirection` query parameters. The generated use case
456
+ normalizes cursor pages, validates opaque base64url cursors against the selected
457
+ sort, and passes one repository query object into memory and Drizzle adapters.
458
+ Adapters filter `name` with case-insensitive contains matching, sort only by
459
+ `createdAt` or `name` plus `id`, and fetch `limit + 1` records to derive
460
+ `nextCursor` without a count query.
461
+
462
+ Generated resources also include optimistic concurrency by default. Responses
463
+ include a numeric `version`; update request bodies must send that version back;
464
+ memory and Drizzle repositories include the version in the update check and
465
+ increment it on success. Stale updates become the generated
466
+ `<Resource>Conflict` catalog error.
467
+
468
+ Use `--auth` to generate authorization metadata, policy wiring, and use-case
469
+ `ctx.gate.authorize(...)` calls. Use `--tenant` to scope repository reads and
470
+ writes by `ctx.tenant`. Use `--events` to generate created, updated, and
471
+ deleted domain events and publish them through `ctx.ports.eventBus`. Use
472
+ `--soft-delete` when delete routes should archive rows with `deletedAt` while
473
+ list, get, and update operations continue to read only active records.
297
474
 
298
475
  In standard apps, the command also creates
299
476
  `infra/db/schema/projects.ts`,
300
477
  `infra/projects/drizzle-project-repository.ts`, and registers the repository in
301
478
  `infra/db/repositories.ts`.
302
479
 
303
- ## Generate events, jobs, notifications, listeners, schedules, and uploads
480
+ ## Generate tasks, events, jobs, notifications, listeners, schedules, and uploads
304
481
 
305
482
  Use feature artifact generators when a workflow grows beyond a single use case:
306
483
 
307
484
  ```bash
485
+ beignet make task posts/backfill-search
308
486
  beignet make event posts/published
309
487
  beignet make job posts/send-published-email
310
488
  beignet make notification posts/published
@@ -315,6 +493,7 @@ beignet make upload posts/attachment
315
493
 
316
494
  These commands use `feature/name` format and write colocated feature files:
317
495
 
496
+ - `features/posts/tasks/backfill-search.ts`
318
497
  - `features/posts/domain/events/published.ts`
319
498
  - `features/posts/jobs/send-published-email.ts`
320
499
  - `features/posts/notifications/published.ts`
@@ -323,17 +502,73 @@ These commands use `feature/name` format and write colocated feature files:
323
502
  - `features/posts/uploads/attachment.ts`
324
503
 
325
504
  Each command creates or updates the folder's `index.ts` with an exported
326
- registry such as `postJobs`, `postNotifications`, `postListeners`,
327
- `postSchedules`, or `postUploads`. Event and listener generators add
328
- `@beignet/core/events`, job generators use `@beignet/core/jobs`, notification
329
- generators use `@beignet/core/notifications`, schedule generators use
330
- `@beignet/core/schedules`, and upload generators use `@beignet/core/uploads`.
505
+ registry such as `postTasks`, `postJobs`, `postNotifications`,
506
+ `postListeners`, `postSchedules`, or `postUploads`. Task generators also
507
+ create or update `server/tasks.ts`, which is the registry and lifecycle
508
+ boundary used by `beignet task run <name> --input '{"dryRun":true}'`.
509
+ New task registries include `createTaskContext(...)` and
510
+ `stopTaskContext(...)` placeholders so provider startup and teardown stay
511
+ out of task definitions.
512
+
513
+ Task, job, listener, schedule, and notification generators define artifacts
514
+ through app-owned context-bound builders in `lib/`. Each generator creates the
515
+ builder file when it is missing:
516
+
517
+ - `lib/tasks.ts` exports `defineTask` from `createTasks<AppContext>()`
518
+ (`@beignet/core/tasks`)
519
+ - `lib/jobs.ts` exports `defineJob` from `createJobs<AppContext>()`
520
+ (`@beignet/core/jobs`)
521
+ - `lib/listeners.ts` exports `defineListener` from
522
+ `createListeners<AppContext>()` (`@beignet/core/events`)
523
+ - `lib/schedules.ts` exports `defineSchedule` from
524
+ `createSchedules<AppContext>()` (`@beignet/core/schedules`)
525
+ - `lib/notifications.ts` exports `defineNotification` from
526
+ `createNotifications<AppContext>()` (`@beignet/core/notifications`)
527
+
528
+ Event generators use `@beignet/core/events` directly and upload generators use
529
+ `@beignet/core/uploads`.
331
530
  `--route` also writes a Next.js cron
332
531
  route under `app/api/cron/<feature>/<name>/route.ts`. Generated cron routes
333
532
  require `CRON_SECRET` and record schedule start, completion, and failure events
334
533
  in devtools. Generated uploads include starter metadata, constraints,
335
534
  authorization, storage key, storage metadata, and completion hooks.
336
535
 
536
+ Use `beignet outbox drain` when you need to drain durable events and jobs from
537
+ an app-owned CLI, CI, or worker entrypoint:
538
+
539
+ ```bash
540
+ beignet outbox drain --batch-size 100
541
+ ```
542
+
543
+ The runner loads `server/outbox.ts` or `paths.outbox`. That module should export
544
+ `outboxRegistry`, `createOutboxDrainContext(...)`, and optionally
545
+ `stopOutboxDrainContext(...)`. The context owns app ports and provider
546
+ lifecycle, so the CLI drain uses the same outbox, event bus, jobs,
547
+ instrumentation, actor, and tenant decisions as the scheduled drain route.
548
+
549
+ There is intentionally no separate `beignet jobs drain` command. Outbox-backed
550
+ jobs drain through the outbox beside durable events. Direct provider jobs should
551
+ use provider-owned worker entrypoints, such as an Inngest route built with
552
+ `createInngestJobFunction(...)`.
553
+
554
+ Use `beignet schedule run` when you need to run a schedule explicitly from a
555
+ local shell, CI job, or worker entrypoint:
556
+
557
+ ```bash
558
+ beignet schedule run posts.log-daily-summary --scheduled-at 2026-01-01T09:00:00.000Z
559
+ ```
560
+
561
+ The runner loads `server/schedules.ts` or `paths.schedules`. That module should
562
+ export a `schedules` array, `createScheduleContext(...)`, and optionally
563
+ `stopScheduleContext(...)`. Omit `--payload` when the schedule should build its
564
+ own payload from `createPayload(...)`; pass `--payload` when a provider or manual
565
+ run supplies the payload.
566
+
567
+ Operational CLI commands are bounded entrypoints. Use them from a local shell,
568
+ CI job, release job, scheduler, or worker host. Do not start outbox drains,
569
+ queue consumers, or interval polling from provider lifecycle hooks in serverless
570
+ apps.
571
+
337
572
  `make listener` expects the event file to exist at the canonical generated path.
338
573
  Run `make event <feature>/<event>` first, then generate listeners for that event.
339
574
 
@@ -359,9 +594,16 @@ run Drizzle Kit and the generated `infra/db/seed.ts` / `infra/db/reset.ts`
359
594
  entrypoints. This keeps schema generation and migration behavior Drizzle-native
360
595
  while making the lifecycle discoverable through Beignet.
361
596
 
597
+ `beignet db` checks standard prerequisites before running those scripts. If the
598
+ script is missing, Drizzle Kit has no `drizzle.config.*`, or the standard
599
+ seed/reset entrypoint was removed, the error points to the exact file or
600
+ package script to restore.
601
+
362
602
  `db reset` is intentionally app-owned because destructive behavior depends on
363
603
  the environment. The standard starter refuses to reset non-local database URLs
364
- unless `BEIGNET_ALLOW_DATABASE_RESET=true` is set.
604
+ unless `BEIGNET_ALLOW_DATABASE_RESET=true` is set. Drizzle starters also include
605
+ `infra/db/test-database.ts`, which creates an isolated local libSQL database for
606
+ repository and persistence tests.
365
607
 
366
608
  Generate feature-owned test factories and local/demo seeds with:
367
609
 
@@ -375,6 +617,12 @@ through app-owned repository ports. Seeds are written under
375
617
  `features/posts/seeds/`; import them from the app-owned database seed entrypoint
376
618
  and run them with `runSeeds(...)`.
377
619
 
620
+ Generated feature and use-case tests use Beignet's test context helpers so
621
+ request IDs, actors, tenants, and ports follow the same pattern as the testing
622
+ docs. Generated route tests boot `createTestApp(...)` with the app's
623
+ `server/context.ts` blueprint, so HTTP coverage exercises the same identity
624
+ resolution as production.
625
+
378
626
  Preview writes without changing files:
379
627
 
380
628
  ```bash
@@ -409,22 +657,30 @@ Run `lint` when you want the CLI to enforce Beignet dependency direction:
409
657
  beignet lint
410
658
  ```
411
659
 
412
- The command scans static imports and fails when core feature layers reach into
413
- runtime or framework layers. It catches domain, use case, workflow, policy,
414
- port, contract, and route files importing things like `infra/`, UI components,
415
- client modules, provider packages, Next.js, React, or database vendors in the
416
- wrong direction. Workflow folders include feature-owned jobs, listeners,
417
- notifications, schedules, and uploads.
660
+ The command scans static imports and fails when app layers reach into runtime
661
+ or framework layers. It catches domain, use case, workflow, policy, port,
662
+ contract, route, infra, and component files importing things like `infra/`, UI
663
+ components, route handlers, server modules, client modules, provider packages,
664
+ Next.js, React, or database vendors in the wrong direction. It also catches
665
+ feature-specific domain files importing another feature's domain unless the
666
+ target is `features/shared/domain`. Workflow folders include feature-owned
667
+ jobs, listeners, notifications, schedules, and uploads.
418
668
 
419
- Use JSON output in CI or custom scripts:
669
+ Import diagnostics include 1-based `line` and `column` positions. Human
670
+ output prints clickable `file.ts:12:3` locations; runtime-boundary
671
+ diagnostics report the chain root file and the full import chain in the
672
+ message instead.
673
+
674
+ Use JSON output in CI or custom scripts, or GitHub annotations in workflows:
420
675
 
421
676
  ```bash
422
677
  beignet lint --json
678
+ beignet lint --format github
423
679
  ```
424
680
 
425
681
  ## Check for drift
426
682
 
427
- Run `doctor` when you want quick feedback on contract wiring drift:
683
+ Run `doctor` when you want a framework integrity report:
428
684
 
429
685
  ```bash
430
686
  beignet doctor
@@ -435,38 +691,85 @@ Today it detects:
435
691
  - Contracts without a matching Next.js route handler
436
692
  - Feature route groups that are not registered in the central route list
437
693
  - Next.js route handlers that do not map to known contracts
438
- - OpenAPI drift in direct arrays and common exported contract lists
694
+ - OpenAPI drift in direct arrays, exported contract lists, and
695
+ `contractsFromRoutes(routes)` route registries
696
+ - OpenAPI entries for contracts outside the registered route surface
697
+ - Strict-mode canonical app conformance drift, including missing app context,
698
+ server route/provider registries, app ports, client helpers, typed route
699
+ groups, and local `AppContext` redeclarations
439
700
  - Partially wired generated feature slices
701
+ - CRUD resource slices missing generated contracts, use cases, repository
702
+ methods, route entries, not-found catalog errors, or strict-mode test coverage
703
+ - Route-owned catalog errors declared on contracts but missing from
704
+ `features/shared/errors.ts`
705
+ - Feature runtime `appError(...)` calls that are not declared on the feature's
706
+ contracts
707
+ - Authorization metadata whose ability is missing from feature policy coverage
708
+ - Audit-required metadata without feature audit writes or test assertions
709
+ - Mixed `@beignet/*` version ranges in package.json, and mixed installed
710
+ `@beignet/*` versions in node_modules; the packages release together, so one
711
+ app should use one version
712
+ - CLI versions that differ from the app's installed `@beignet/core`, reported
713
+ as an informational hint that suggests the app-local `bun beignet`
714
+ - Malformed installed provider package metadata
440
715
  - Provider packages without matching canonical app ports
716
+ - Installed lifecycle provider packages that are not registered in
717
+ `server/providers.ts`, reported as an informational hint when the provider
718
+ declares registration as optional, such as `@beignet/devtools`
719
+ - App database providers registered before the provider that installs `db`
441
720
  - Generated ports without test fakes
442
721
  - Drizzle repository adapters that are not wired through `infra/db/repositories.ts`
443
722
  - Repository ports whose infra folder has no repository adapter
723
+ - Missing Drizzle config, schema index exports, database scripts, or standard seed/reset entrypoints
724
+ - Single-file `infra/db/schema.ts` schemas that should move to the
725
+ `infra/db/schema/` directory form
726
+ - Feature tests placed directly under `features/<feature>/` instead of
727
+ `features/<feature>/tests/`
728
+ - Standard database reset entrypoints that no longer guard non-local resets
444
729
  - Feature seeds without a matching feature factory
445
730
  - Feature seeds without a `db:seed` package script
446
731
  - Upload definitions without an upload route
732
+ - Upload definitions without explicit size limits
733
+ - Devtools routes that are explicitly enabled without authorization
734
+ - Cron routes that do not use `CRON_SECRET`
735
+ - Installed provider packages without expected environment configuration
736
+ - Better Auth providers without an auth route or trusted-origin configuration
737
+ - Credentialed wildcard CORS configuration
447
738
  - Notification dispatchers that bypass `ctx.ports.notifications`
448
739
  - Feature artifacts in non-canonical folders
449
740
 
450
- Use `beignet doctor --strict` for CI-oriented checks that may be noisy
451
- locally, such as missing generated feature tests. Use
452
- `beignet doctor --json` in CI or custom scripts.
741
+ Provider package diagnostics come from package-owned `beignet.provider`
742
+ metadata in installed package manifests. The CLI does not import provider
743
+ implementation modules to discover those facts, and it reports malformed
744
+ metadata before using provider-derived doctor rules.
745
+
746
+ Use `beignet doctor --strict` for CI-oriented checks that may be noisy locally,
747
+ such as missing generated feature tests, canonical app conformance drift, and
748
+ feature-owned route errors that appear unused. Strict mode fails on warnings as
749
+ well as errors; informational hints never affect the exit code, so an
750
+ installed-but-unregistered optional provider such as `@beignet/devtools` still
751
+ passes `doctor --strict`. Use
752
+ `beignet doctor --json` in CI or custom scripts. Doctor JSON includes
753
+ `schemaVersion: 1` plus `targetDir`, `config`, `strict`, `convention`,
754
+ `contracts`, `routes`, `diagnostics`, and `fixes`.
453
755
 
454
756
  Use `beignet doctor --fix` for low-risk maintenance fixes. Today it can add
455
- a missing `test` script and repair direct `createOpenAPIHandler([...])` arrays
456
- when the missing contracts are already imported in the OpenAPI route.
757
+ a missing `test` script, register existing feature route groups in the central
758
+ route list, and repair direct `createOpenAPIHandler([...])` arrays when the
759
+ missing contracts are already imported in the OpenAPI route.
457
760
 
458
761
  Available presets:
459
762
 
460
763
  - `minimal` - choose this when you want the small contract/core/server/use-case loop without the full app conventions.
461
- - `standard` - choose this when you want the full app layout with Better Auth, Drizzle/libSQL, UOW, outbox, audit logging, devtools, provider wiring, health checks, typed clients, feature-owned jobs/events/schedules/uploads/notifications, and separated `ports/` + `infra/`.
764
+ - `standard` - choose this when you want the full app layout with Better Auth, Drizzle/libSQL, UOW, durable idempotency, outbox, audit logging, devtools, provider wiring, health checks, typed clients, feature-owned jobs/events/schedules/uploads/notifications, and separated `ports/` + `infra/`.
462
765
 
463
766
  The standard preset includes the local production-shaped defaults: Better Auth,
464
- Drizzle/libSQL, Pino logging, local storage, devtools, UOW, outbox, audit
767
+ Drizzle/libSQL, Pino logging, local storage, devtools, UOW, durable idempotency, outbox, audit
465
768
  logging, and feature-owned background workflow examples. Add external service
466
769
  integrations only when you want those providers:
467
770
 
468
771
  ```bash
469
- bunx -p @beignet/cli beignet create my-app --preset standard --integrations drizzle-turso,inngest,resend
772
+ bun create beignet my-app --preset standard --integrations drizzle-turso,inngest,resend
470
773
  ```
471
774
 
472
775
  Available features:
@@ -485,7 +788,16 @@ Available integrations:
485
788
  - `resend`
486
789
  - `upstash-rate-limit`
487
790
 
488
- With `--preset standard`, Drizzle/libSQL is included by default. The starter scaffolds `infra/db/schema/`, `infra/db/repositories.ts`, a Drizzle todo repository adapter, `drizzle.config.ts`, database scripts, and `TURSO_*` env examples so the generated todo resource uses durable persistence instead of the in-memory repository. Later `make feature` or `make resource` calls in that app generate both a Drizzle table/repository and an in-memory test fake.
791
+ With `--preset standard`, Drizzle/libSQL is included by default. The starter scaffolds `infra/db/schema/`, `infra/db/repositories.ts`, `infra/db/test-database.ts`, SQL-backed idempotency and outbox tables, a Drizzle todo repository adapter, `drizzle.config.ts`, database scripts, and `TURSO_*` env examples so the generated todo resource uses durable persistence instead of the in-memory repository. Later `make feature` or `make resource` calls in that app generate both a Drizzle table/repository and an in-memory test fake.
792
+
793
+ With `--preset minimal --integrations drizzle-turso`, the starter keeps the
794
+ small app shape and scaffolds the smallest durable wiring: `drizzle.config.ts`,
795
+ a todos-only schema in `infra/db/schema/`, a Drizzle todo repository in
796
+ `infra/todos/`, and an app-owned database provider in `infra/db/provider.ts`
797
+ that contributes the deferred `todos` port and creates and seeds the starter
798
+ table at startup. The generated `db:generate` and `db:migrate` scripts work
799
+ with `beignet db ...`; the `db:seed` and `db:reset` scripts are
800
+ standard-preset-only because their entrypoints are not scaffolded.
489
801
 
490
802
  With `--preset standard`, Better Auth is included by default. The starter adds
491
803
  the Better Auth Next.js route, Beignet auth provider wiring, typed
@@ -493,6 +805,12 @@ the Better Auth Next.js route, Beignet auth provider wiring, typed
493
805
  `requireUser(ctx)`. Use hooks for HTTP boundary authentication and use cases or
494
806
  policies for business authorization.
495
807
 
808
+ With `--preset minimal --integrations better-auth`, the starter wires an
809
+ app-owned `lib/better-auth.ts` backed by Better Auth's in-memory adapter, the
810
+ `app/api/auth/[...all]` route, `createAuthBetterAuthProvider(...)` behind a
811
+ deferred `auth` port, and an `auth` session on the request context. Users and
812
+ sessions reset on restart; switch to a database adapter before production.
813
+
496
814
  ## License
497
815
 
498
816
  MIT