@beignet/cli 0.0.8 → 0.0.9

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/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @beignet/cli
2
2
 
3
+ ## 0.0.9
4
+
5
+ ### Patch Changes
6
+
7
+ - 6ebec8c: Provider packages can now declare `variants` in their `beignet.provider` manifest — one entry per selectable backend with its own env requirements and registration tokens. `beignet doctor` checks required env vars only for the variants an app actually registers, and reports a single registration hint listing all variants when none is wired. The Drizzle database provider uses this to describe its sqlite, postgres, and mysql backends.
8
+ - 1bb42a3: Rename `@beignet/provider-drizzle-turso` to `@beignet/provider-db-drizzle`, with databases as subpath exports. Import from `@beignet/provider-db-drizzle/sqlite`; `DrizzleTurso*` symbols are now `DrizzleSqlite*`, the provider registers as `drizzle-sqlite`, and the connection env vars are `SQLITE_DB_URL` and `SQLITE_DB_AUTH_TOKEN` (the auth token applies to hosted libSQL such as Turso). Provider packages now follow `provider-<capability>-<implementation>` naming, and multi-backend implementations add backends as subpaths — `/postgres` and `/mysql` are planned next.
9
+ - Updated dependencies [6ebec8c]
10
+ - Updated dependencies [6ebec8c]
11
+ - Updated dependencies [1bb42a3]
12
+ - @beignet/core@0.0.9
13
+
3
14
  ## 0.0.8
4
15
 
5
16
  ### Patch Changes
package/README.md CHANGED
@@ -39,18 +39,18 @@ Both delegate to `beignet create`, so `bunx @beignet/cli create my-app` is
39
39
  equivalent.
40
40
 
41
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.
42
+ prompt-based setup that asks for the project directory, whether to scaffold
43
+ an API-only app, and which provider integrations to add. Passing any
44
+ selection flag (`--api`, `--integrations`, or `--package-manager`) skips the
45
+ prompts, and `--yes` forces the non-interactive defaults (the full-stack
46
+ starter with `bun`) even on a terminal. Non-interactive runs in scripts and
47
+ CI behave exactly as before.
48
48
 
49
49
  By default the CLI creates a Next.js app with:
50
50
 
51
51
  - Contract-first todos API routes
52
52
  - Better Auth routes and Beignet auth provider wiring
53
- - Drizzle/libSQL persistence with a local SQLite default and Turso-ready config
53
+ - Drizzle SQLite (libSQL) persistence with a local SQLite default and support for hosted libSQL (Turso)
54
54
  - UOW, audit logging, durable idempotency, and a durable outbox drain route
55
55
  - Jobs, events, listeners, schedules, mail-backed notifications, and uploads
56
56
  - App-owned ports with provider-backed infra adapters
@@ -62,6 +62,45 @@ By default the CLI creates a Next.js app with:
62
62
  - React Hook Form
63
63
  - OpenAPI output
64
64
 
65
+ Pass `--api` to scaffold an API-only app. It keeps the same contracts, auth,
66
+ persistence, and devtools, and swaps the UI shell for a minimal API landing
67
+ page and a reduced typed client.
68
+
69
+ The starter ships local production-shaped defaults: Better Auth, Drizzle
70
+ SQLite (libSQL) persistence, pino logging, UOW, durable idempotency, a
71
+ durable outbox, audit logging, and devtools. Add external service
72
+ integrations only when you want those providers:
73
+
74
+ ```bash
75
+ bunx @beignet/cli create my-app --integrations inngest,resend
76
+ ```
77
+
78
+ Available integrations:
79
+
80
+ - `inngest` - Inngest-backed background jobs via `@beignet/provider-inngest`
81
+ - `resend` - Resend-backed mail via `@beignet/provider-mail-resend`
82
+ - `upstash-rate-limit` - Upstash-backed rate limiting via
83
+ `@beignet/provider-rate-limit-upstash`
84
+
85
+ Each selected integration adds its provider package dependencies, wires the
86
+ provider in `server/providers.ts`, extends `.env.example`, and writes setup
87
+ notes to `docs/integrations.md`.
88
+
89
+ Drizzle SQLite (libSQL) ships in every starter. The scaffold includes
90
+ `infra/db/schema/`, `infra/db/repositories.ts`, `infra/db/test-database.ts`,
91
+ SQL-backed idempotency and outbox tables, a Drizzle todo repository adapter,
92
+ `drizzle.config.ts`, checked-in starter migrations, database scripts, and
93
+ `SQLITE_*` env examples, so the generated todo resource uses durable
94
+ persistence instead of an in-memory repository. Later `make feature` or
95
+ `make resource` calls in that app generate both a Drizzle table/repository
96
+ and an in-memory test fake.
97
+
98
+ Better Auth also ships in every starter. The scaffold adds the Better Auth
99
+ Next.js route, Beignet auth provider wiring, typed `UNAUTHORIZED` and
100
+ `FORBIDDEN` errors, a request-bound authorization gate, and
101
+ `requireUser(ctx)`. Use hooks for HTTP boundary authentication and use cases
102
+ or policies for business authorization.
103
+
65
104
  Preview the planned files without writing anything:
66
105
 
67
106
  ```bash
@@ -75,7 +114,6 @@ The CLI writes files only. After creation:
75
114
  cd my-app
76
115
  bun install
77
116
  cp .env.example .env.local
78
- bun beignet db generate
79
117
  bun beignet db migrate
80
118
  bun run dev
81
119
  ```
@@ -116,6 +154,7 @@ beignet make job <feature>/<name> [options]
116
154
  beignet make notification <feature>/<name> [options]
117
155
  beignet make listener <feature>/<name> --event <feature>/<event> [options]
118
156
  beignet make schedule <feature>/<name> [options]
157
+ beignet make upload <feature>/<name> [options]
119
158
  beignet make port <name> [options]
120
159
  beignet make policy <name> [options]
121
160
  beignet make adapter <name> [options]
@@ -136,10 +175,9 @@ beignet --version
136
175
 
137
176
  Options:
138
177
  --template next Template to use. Currently only `next`.
139
- --preset standard `minimal` or `standard`. Defaults to `standard`.
178
+ --api Scaffold an API-only app without the UI shell.
140
179
  --package-manager bun Package manager shown in next steps.
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.
180
+ --integrations inngest,resend Add integrations: inngest, resend, upstash-rate-limit. Accepts one value or a comma-separated list.
143
181
  --yes Skip interactive create prompts and use the defaults.
144
182
  --force Write into a non-empty directory.
145
183
  --dry-run Preview create/make writes without changing files.
@@ -220,7 +258,7 @@ shell or source the rc file to activate completions. Zsh completions require
220
258
  `compinit` to be loaded, which most zsh setups already do.
221
259
 
222
260
  Completions cover commands, subcommands, flags, and enum flag values such as
223
- `--preset` and `--features`. The shell scripts call the
261
+ `--template` and `--integrations`. The shell scripts call the
224
262
  `beignet completion propose` helper, which prints one proposal per line for a
225
263
  partial command line; it exists for the shell integration and is safe to
226
264
  ignore otherwise. Completions complete whatever `beignet` resolves to on your
@@ -795,59 +833,6 @@ artifacts are already registered individually, the fix bails out and the
795
833
  diagnostic stays. Listener registration is report-only because apps own their
796
834
  event-bus wiring.
797
835
 
798
- Available presets:
799
-
800
- - `minimal` - choose this when you want the small contract/core/server/use-case loop without the full app conventions.
801
- - `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/`.
802
-
803
- The standard preset includes the local production-shaped defaults: Better Auth,
804
- Drizzle/libSQL, Pino logging, local storage, devtools, UOW, durable idempotency, outbox, audit
805
- logging, and feature-owned background workflow examples. Add external service
806
- integrations only when you want those providers:
807
-
808
- ```bash
809
- bun create beignet my-app --preset standard --integrations drizzle-turso,inngest,resend
810
- ```
811
-
812
- Available features:
813
-
814
- - `client`
815
- - `react-query`
816
- - `forms`
817
- - `openapi`
818
-
819
- Available integrations:
820
-
821
- - `better-auth`
822
- - `drizzle-turso`
823
- - `inngest`
824
- - `pino`
825
- - `resend`
826
- - `upstash-rate-limit`
827
-
828
- 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.
829
-
830
- With `--preset minimal --integrations drizzle-turso`, the starter keeps the
831
- small app shape and scaffolds the smallest durable wiring: `drizzle.config.ts`,
832
- a todos-only schema in `infra/db/schema/`, a Drizzle todo repository in
833
- `infra/todos/`, and an app-owned database provider in `infra/db/provider.ts`
834
- that contributes the deferred `todos` port and creates and seeds the starter
835
- table at startup. The generated `db:generate` and `db:migrate` scripts work
836
- with `beignet db ...`; the `db:seed` and `db:reset` scripts are
837
- standard-preset-only because their entrypoints are not scaffolded.
838
-
839
- With `--preset standard`, Better Auth is included by default. The starter adds
840
- the Better Auth Next.js route, Beignet auth provider wiring, typed
841
- `UNAUTHORIZED` and `FORBIDDEN` errors, a request-bound authorization gate, and
842
- `requireUser(ctx)`. Use hooks for HTTP boundary authentication and use cases or
843
- policies for business authorization.
844
-
845
- With `--preset minimal --integrations better-auth`, the starter wires an
846
- app-owned `lib/better-auth.ts` backed by Better Auth's in-memory adapter, the
847
- `app/api/auth/[...all]` route, `createAuthBetterAuthProvider(...)` behind a
848
- deferred `auth` port, and an `auth` session on the request context. Users and
849
- sessions reset on restart; switch to a database adapter before production.
850
-
851
836
  ## License
852
837
 
853
838
  MIT
package/dist/create.js CHANGED
@@ -46,7 +46,7 @@ export async function createProject(options) {
46
46
  * Providers that ship in every starter. They used to be `--integrations`
47
47
  * choices, so passing them gets a pointed error instead of a generic one.
48
48
  */
49
- const baseProviderNames = new Set(["better-auth", "drizzle-turso", "pino"]);
49
+ const baseProviderNames = new Set(["better-auth", "drizzle-sqlite", "pino"]);
50
50
  function resolveIntegrations(explicitIntegrations) {
51
51
  for (const integration of explicitIntegrations) {
52
52
  if (baseProviderNames.has(integration)) {
@@ -1 +1 @@
1
- {"version":3,"file":"create.js","sourceRoot":"","sources":["../src/create.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../src/create.ts"],"names":[],"mappings":"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"}
package/dist/inspect.js CHANGED
@@ -1214,9 +1214,28 @@ async function inspectProductionReadiness(targetDir, files, config, convention)
1214
1214
  });
1215
1215
  }
1216
1216
  }
1217
+ const providerEntries = await readProviderListEntries(targetDir, files, config, sourceCache);
1217
1218
  for (const provider of providerDoctorRules) {
1218
1219
  if (!installedPackages.has(provider.packageName))
1219
1220
  continue;
1221
+ if (provider.variants !== undefined) {
1222
+ // Multi-variant packages only require the env vars of the variants the
1223
+ // app actually registers; an unused variant must not warn.
1224
+ for (const variant of detectedProviderVariants(provider.variants, providerEntries)) {
1225
+ for (const envVar of variant.requiredEnv) {
1226
+ if (await anyFileContains(targetDir, configFiles, envVar, sourceCache)) {
1227
+ continue;
1228
+ }
1229
+ diagnostics.push({
1230
+ severity: "warning",
1231
+ code: "BEIGNET_PROVIDER_ENV_MISSING",
1232
+ file: "package.json",
1233
+ message: `${provider.packageName} is installed and ${variant.displayName} is registered, but ${envVar} is not mentioned in app env/config files. ${variant.displayName} requires ${envVar}; add the environment variable or remove the provider registration.`,
1234
+ });
1235
+ }
1236
+ }
1237
+ continue;
1238
+ }
1220
1239
  for (const envVar of provider.requiredEnv ?? []) {
1221
1240
  if (await anyFileContains(targetDir, configFiles, envVar, sourceCache)) {
1222
1241
  continue;
@@ -1360,17 +1379,31 @@ async function inspectProviderRegistrationDrift(targetDir, files, config, conven
1360
1379
  const providerDoctorRules = await providerDoctorRulesForInstalledPackages(targetDir, packageJson);
1361
1380
  const providerFiles = serverProviderFiles(files, config);
1362
1381
  const sourceCache = new Map();
1363
- const providerSource = (await Promise.all(providerFiles.map((file) => readCachedSource(targetDir, file, sourceCache)))).join("\n");
1364
- const providerListSource = extractProviderListSource(providerSource);
1365
- const providerEntries = providerListSource === undefined
1366
- ? []
1367
- : providerListEntries(providerListSource);
1382
+ const providerEntries = await readProviderListEntries(targetDir, files, config, sourceCache);
1368
1383
  for (const provider of providerDoctorRules) {
1384
+ if (!installedPackages.has(provider.packageName))
1385
+ continue;
1386
+ if (provider.variants !== undefined) {
1387
+ if (detectedProviderVariants(provider.variants, providerEntries).length > 0) {
1388
+ continue;
1389
+ }
1390
+ const severity = providerVariantRegistrationSeverity(provider.variants);
1391
+ if (severity === undefined)
1392
+ continue;
1393
+ const hints = provider.variants
1394
+ .filter((variant) => variant.tokens.length > 0)
1395
+ .map((variant) => registrationTokenHint(variant.tokens));
1396
+ diagnostics.push({
1397
+ severity,
1398
+ code: "BEIGNET_PROVIDER_REGISTRATION_MISSING",
1399
+ file: providerFiles[0] ?? config.paths.server,
1400
+ message: `${provider.packageName} is installed, but no ${provider.displayName} variant is registered in server/providers.ts. Register one of the available providers (${hints.join(", ")}) in the exported providers array or remove the unused package.`,
1401
+ });
1402
+ continue;
1403
+ }
1369
1404
  const severity = provider.registrationSeverity;
1370
1405
  if (severity === undefined)
1371
1406
  continue;
1372
- if (!installedPackages.has(provider.packageName))
1373
- continue;
1374
1407
  if (provider.tokens.some((token) => providerEntries.some((entry) => entry.includes(token)))) {
1375
1408
  continue;
1376
1409
  }
@@ -1384,8 +1417,12 @@ async function inspectProviderRegistrationDrift(targetDir, files, config, conven
1384
1417
  });
1385
1418
  }
1386
1419
  const drizzleIndex = findProviderEntryIndex(providerEntries, [
1387
- "drizzleTursoProvider",
1388
- "createDrizzleTursoProvider",
1420
+ "drizzleSqliteProvider",
1421
+ "createDrizzleSqliteProvider",
1422
+ "drizzlePostgresProvider",
1423
+ "createDrizzlePostgresProvider",
1424
+ "drizzleMysqlProvider",
1425
+ "createDrizzleMysqlProvider",
1389
1426
  ]);
1390
1427
  const appDatabaseProviderIndex = findProviderEntryIndex(providerEntries, [
1391
1428
  "starterDatabaseProvider",
@@ -1400,7 +1437,7 @@ async function inspectProviderRegistrationDrift(targetDir, files, config, conven
1400
1437
  severity: "warning",
1401
1438
  code: "BEIGNET_PROVIDER_ORDER",
1402
1439
  file: providerFiles[0] ?? config.paths.server,
1403
- message: "An app database provider is registered before createDrizzleTursoProvider(...). Register the Drizzle/Turso provider first so app-owned database wiring can read ctx.ports.db during setup.",
1440
+ message: "An app database provider is registered before the Drizzle database provider. Register the Drizzle database provider first so app-owned database wiring can read ctx.ports.db during setup.",
1404
1441
  });
1405
1442
  }
1406
1443
  return diagnostics;
@@ -1483,10 +1520,39 @@ function providerDoctorRuleFromMetadata(packageName, metadata) {
1483
1520
  tokens: registration?.tokens ?? [],
1484
1521
  appPorts: metadata.appPorts ?? [],
1485
1522
  requiredEnv: metadata.requiredEnv ?? [],
1486
- registrationSeverity: registration?.severity ??
1487
- (registration?.required === true ? "warning" : undefined),
1523
+ registrationSeverity: registrationSeverityFromMetadata(registration),
1524
+ variants: metadata.variants?.map((variant) => ({
1525
+ name: variant.name,
1526
+ displayName: variant.displayName ?? variant.name,
1527
+ tokens: variant.registration?.tokens ?? [],
1528
+ requiredEnv: variant.requiredEnv ?? [],
1529
+ registrationSeverity: registrationSeverityFromMetadata(variant.registration),
1530
+ })),
1488
1531
  };
1489
1532
  }
1533
+ function registrationSeverityFromMetadata(registration) {
1534
+ return (registration?.severity ??
1535
+ (registration?.required === true ? "warning" : undefined));
1536
+ }
1537
+ function detectedProviderVariants(variants, providerEntries) {
1538
+ return variants.filter((variant) => variant.tokens.some((token) => providerEntries.some((entry) => entry.includes(token))));
1539
+ }
1540
+ function providerVariantRegistrationSeverity(variants) {
1541
+ const severities = variants.map((variant) => variant.registrationSeverity);
1542
+ if (severities.includes("warning"))
1543
+ return "warning";
1544
+ if (severities.includes("hint"))
1545
+ return "hint";
1546
+ return undefined;
1547
+ }
1548
+ async function readProviderListEntries(targetDir, files, config, sourceCache) {
1549
+ const providerFiles = serverProviderFiles(files, config);
1550
+ const providerSource = (await Promise.all(providerFiles.map((file) => readCachedSource(targetDir, file, sourceCache)))).join("\n");
1551
+ const providerListSource = extractProviderListSource(providerSource);
1552
+ return providerListSource === undefined
1553
+ ? []
1554
+ : providerListEntries(providerListSource);
1555
+ }
1490
1556
  function registrationTokenHint(tokens) {
1491
1557
  const token = tokens[0];
1492
1558
  if (!token)