@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 +11 -0
- package/README.md +50 -65
- package/dist/create.js +1 -1
- package/dist/create.js.map +1 -1
- package/dist/inspect.js +78 -12
- package/dist/inspect.js.map +1 -1
- package/dist/make.js +2 -2
- package/dist/templates/base.js +4 -4
- package/dist/templates/base.js.map +1 -1
- package/dist/templates/db.js +16 -16
- package/dist/templates/server.js +10 -10
- package/dist/templates/server.js.map +1 -1
- package/package.json +2 -2
- package/src/create.ts +1 -1
- package/src/inspect.ts +137 -19
- package/src/make.ts +2 -2
- package/src/templates/base.ts +4 -4
- package/src/templates/db.ts +16 -16
- package/src/templates/server.ts +10 -10
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,
|
|
43
|
-
|
|
44
|
-
(`--
|
|
45
|
-
prompts, and `--yes` forces the non-interactive defaults (the
|
|
46
|
-
|
|
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
|
|
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
|
-
--
|
|
178
|
+
--api Scaffold an API-only app without the UI shell.
|
|
140
179
|
--package-manager bun Package manager shown in next steps.
|
|
141
|
-
--
|
|
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
|
-
`--
|
|
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-
|
|
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)) {
|
package/dist/create.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","sourceRoot":"","sources":["../src/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,gBAAgB,EAEhB,kBAAkB,GAGnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAgC7C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAsB;IAEtB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,oBAAoB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,KAAK,CAAC;IACvD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,MAAM,CAAC;IAC5C,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,YAAY,GAAG,mBAAmB,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;IAErE,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,qBAAqB,QAAQ,8BAA8B,CAC5D,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAEvC,MAAM,cAAc,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAExD,MAAM,KAAK,GAAG,gBAAgB,CAAC;QAC7B,IAAI;QACJ,cAAc;QACd,cAAc,EAAE,OAAO,CAAC,cAAc,IAAI,wBAAwB,EAAE;QACpE,GAAG;QACH,YAAY;KACb,CAAC,CAAC;IAEH,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE5C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YACpD,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5D,MAAM,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,OAAO;QACL,aAAa,EAAE,CAAC;QAChB,IAAI;QACJ,SAAS;QACT,MAAM;QACN,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;QACrC,cAAc;KACf,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,aAAa,EAAE,
|
|
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
|
|
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
|
-
"
|
|
1388
|
-
"
|
|
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
|
|
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
|
|
1487
|
-
|
|
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)
|