@beignet/cli 0.0.35 → 0.0.37
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 +17 -0
- package/README.md +18 -0
- package/dist/config.d.ts +14 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +29 -0
- package/dist/config.js.map +1 -1
- package/dist/inspect.js +6 -2
- package/dist/inspect.js.map +1 -1
- package/dist/provider-audit.d.ts.map +1 -1
- package/dist/provider-audit.js +8 -3
- package/dist/provider-audit.js.map +1 -1
- package/dist/templates/base.d.ts.map +1 -1
- package/dist/templates/base.js +6 -1
- package/dist/templates/base.js.map +1 -1
- package/dist/templates/db/index.d.ts +1 -0
- package/dist/templates/db/index.d.ts.map +1 -1
- package/dist/templates/db/index.js.map +1 -1
- package/dist/templates/db/mysql.d.ts.map +1 -1
- package/dist/templates/db/mysql.js +16 -0
- package/dist/templates/db/mysql.js.map +1 -1
- package/dist/templates/db/postgres.d.ts.map +1 -1
- package/dist/templates/db/postgres.js +16 -0
- package/dist/templates/db/postgres.js.map +1 -1
- package/dist/templates/db/sqlite.d.ts.map +1 -1
- package/dist/templates/db/sqlite.js +16 -0
- package/dist/templates/db/sqlite.js.map +1 -1
- package/dist/templates/index.d.ts.map +1 -1
- package/dist/templates/index.js +2 -1
- package/dist/templates/index.js.map +1 -1
- package/dist/templates/server.d.ts +1 -1
- package/dist/templates/server.d.ts.map +1 -1
- package/dist/templates/server.js +51 -35
- package/dist/templates/server.js.map +1 -1
- package/dist/templates/shared.js +3 -3
- package/dist/templates/shared.js.map +1 -1
- package/package.json +2 -2
- package/src/config.ts +64 -0
- package/src/inspect.ts +16 -2
- package/src/provider-audit.ts +25 -8
- package/src/templates/base.ts +6 -1
- package/src/templates/db/index.ts +1 -0
- package/src/templates/db/mysql.ts +16 -0
- package/src/templates/db/postgres.ts +16 -0
- package/src/templates/db/sqlite.ts +16 -0
- package/src/templates/index.ts +2 -1
- package/src/templates/server.ts +51 -37
- package/src/templates/shared.ts +3 -3
package/dist/templates/server.js
CHANGED
|
@@ -18,6 +18,7 @@ export function serverProviders(ctx) {
|
|
|
18
18
|
? 'import { createUpstashRateLimitProvider } from "@beignet/provider-rate-limit-upstash";'
|
|
19
19
|
: undefined,
|
|
20
20
|
'import * as schema from "@/infra/db/schema";',
|
|
21
|
+
'import { databaseClient } from "@/infra/db/client";',
|
|
21
22
|
'import { starterDatabaseProvider } from "@/infra/db/provider";',
|
|
22
23
|
'import { auth } from "@/lib/better-auth";',
|
|
23
24
|
'import type { AuthSessionMetadata, AuthUser } from "@/ports/auth";',
|
|
@@ -38,7 +39,10 @@ export function serverProviders(ctx) {
|
|
|
38
39
|
].filter((entry) => Boolean(entry));
|
|
39
40
|
return `${imports.join("\n")}
|
|
40
41
|
|
|
41
|
-
const ${db.providerInstance} = ${db.providerFactory}({
|
|
42
|
+
const ${db.providerInstance} = ${db.providerFactory}({
|
|
43
|
+
schema,
|
|
44
|
+
client: databaseClient,
|
|
45
|
+
});
|
|
42
46
|
|
|
43
47
|
export const providers = [
|
|
44
48
|
${entries.join("\n")}
|
|
@@ -138,7 +142,8 @@ export function env(ctx) {
|
|
|
138
142
|
\t\tSQLITE_DB_AUTH_TOKEN: z.string().optional(),`
|
|
139
143
|
: `\t\t${databaseDescriptor(ctx).urlEnvVar}: z
|
|
140
144
|
\t\t\t.string()
|
|
141
|
-
\t\t\t.default("${databaseLocalUrl(ctx.database, ctx.name)}")
|
|
145
|
+
\t\t\t.default("${databaseLocalUrl(ctx.database, ctx.name)}"),
|
|
146
|
+
\t\t${ctx.database === "postgres" ? "POSTGRES" : "MYSQL"}_DB_POOL_MAX: z.coerce.number().int().positive().default(5),`;
|
|
142
147
|
return `import { createEnv } from "@beignet/core/config";
|
|
143
148
|
import { z } from "zod";
|
|
144
149
|
|
|
@@ -187,54 +192,45 @@ export const isDevtoolsEnabled =
|
|
|
187
192
|
}
|
|
188
193
|
export function betterAuth(ctx) {
|
|
189
194
|
const connectionByDatabase = {
|
|
190
|
-
sqlite: `import {
|
|
191
|
-
import { betterAuth } from "better-auth";
|
|
195
|
+
sqlite: `import { betterAuth } from "better-auth";
|
|
192
196
|
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
193
197
|
import { drizzle } from "drizzle-orm/libsql";
|
|
198
|
+
import { databaseClient } from "@/infra/db/client";
|
|
194
199
|
import { ensureDatabaseReady } from "@/infra/db/database-ready";
|
|
195
200
|
import * as schema from "@/infra/db/schema";
|
|
196
201
|
import { env } from "@/lib/env";
|
|
197
202
|
|
|
198
|
-
const client = createClient({
|
|
199
|
-
url: env.SQLITE_DB_URL,
|
|
200
|
-
authToken: env.SQLITE_DB_AUTH_TOKEN,
|
|
201
|
-
});
|
|
202
|
-
|
|
203
203
|
// Auth routes can be the first thing to touch the database, before any
|
|
204
204
|
// Beignet provider boots, so readiness is enforced here too.
|
|
205
|
-
await ensureDatabaseReady(
|
|
205
|
+
await ensureDatabaseReady(databaseClient);
|
|
206
206
|
|
|
207
|
-
const db = drizzle(
|
|
207
|
+
const db = drizzle(databaseClient, { schema });`,
|
|
208
208
|
postgres: `import { betterAuth } from "better-auth";
|
|
209
209
|
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
210
210
|
import { drizzle } from "drizzle-orm/node-postgres";
|
|
211
|
-
import
|
|
211
|
+
import { databaseClient } from "@/infra/db/client";
|
|
212
212
|
import { ensureDatabaseReady } from "@/infra/db/database-ready";
|
|
213
213
|
import * as schema from "@/infra/db/schema";
|
|
214
214
|
import { env } from "@/lib/env";
|
|
215
215
|
|
|
216
|
-
const pool = new pg.Pool({ connectionString: env.POSTGRES_DB_URL });
|
|
217
|
-
|
|
218
216
|
// Auth routes can be the first thing to touch the database, before any
|
|
219
217
|
// Beignet provider boots, so readiness is enforced here too.
|
|
220
|
-
await ensureDatabaseReady(
|
|
218
|
+
await ensureDatabaseReady(databaseClient);
|
|
221
219
|
|
|
222
|
-
const db = drizzle(
|
|
220
|
+
const db = drizzle(databaseClient, { schema });`,
|
|
223
221
|
mysql: `import { betterAuth } from "better-auth";
|
|
224
222
|
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
225
223
|
import { drizzle } from "drizzle-orm/mysql2";
|
|
226
|
-
import
|
|
224
|
+
import { databaseClient } from "@/infra/db/client";
|
|
227
225
|
import { ensureDatabaseReady } from "@/infra/db/database-ready";
|
|
228
226
|
import * as schema from "@/infra/db/schema";
|
|
229
227
|
import { env } from "@/lib/env";
|
|
230
228
|
|
|
231
|
-
const pool = mysql.createPool({ uri: env.MYSQL_DB_URL });
|
|
232
|
-
|
|
233
229
|
// Auth routes can be the first thing to touch the database, before any
|
|
234
230
|
// Beignet provider boots, so readiness is enforced here too.
|
|
235
|
-
await ensureDatabaseReady(
|
|
231
|
+
await ensureDatabaseReady(databaseClient);
|
|
236
232
|
|
|
237
|
-
const db = drizzle(
|
|
233
|
+
const db = drizzle(databaseClient, { schema, mode: "default" });`,
|
|
238
234
|
};
|
|
239
235
|
return `${connectionByDatabase[ctx.database]}
|
|
240
236
|
|
|
@@ -268,16 +264,7 @@ export const auth = betterAuth({
|
|
|
268
264
|
});
|
|
269
265
|
`;
|
|
270
266
|
}
|
|
271
|
-
export function server(
|
|
272
|
-
const db = databaseDescriptor(ctx);
|
|
273
|
-
const providerConfigEntries = ctx.database === "sqlite"
|
|
274
|
-
? `\t\t"drizzle-sqlite": {
|
|
275
|
-
\t\t\tDB_URL: env.SQLITE_DB_URL,
|
|
276
|
-
\t\t\tDB_AUTH_TOKEN: env.SQLITE_DB_AUTH_TOKEN,
|
|
277
|
-
\t\t},`
|
|
278
|
-
: `\t\t"${db.providerName}": {
|
|
279
|
-
\t\t\tDB_URL: env.${db.urlEnvVar},
|
|
280
|
-
\t\t},`;
|
|
267
|
+
export function server() {
|
|
281
268
|
return `import "@beignet/core/server-only";
|
|
282
269
|
import { createNextServer, createNextServerLoader } from "@beignet/next";
|
|
283
270
|
import {
|
|
@@ -287,6 +274,7 @@ import {
|
|
|
287
274
|
} from "@beignet/core/server";
|
|
288
275
|
import type { AppContext } from "@/app-context";
|
|
289
276
|
import { appPorts } from "@/infra/app-ports";
|
|
277
|
+
import { closeDatabaseClient } from "@/infra/db/client";
|
|
290
278
|
import { env } from "@/lib/env";
|
|
291
279
|
import { appContext } from "./context";
|
|
292
280
|
import { routes } from "./routes";
|
|
@@ -294,12 +282,9 @@ import { routes } from "./routes";
|
|
|
294
282
|
export const getServer = createNextServerLoader(async () => {
|
|
295
283
|
const { providers } = await import("./providers");
|
|
296
284
|
|
|
297
|
-
|
|
285
|
+
const server = await createNextServer({
|
|
298
286
|
ports: appPorts,
|
|
299
287
|
providers,
|
|
300
|
-
providerConfig: {
|
|
301
|
-
${providerConfigEntries}
|
|
302
|
-
},
|
|
303
288
|
hooks: [
|
|
304
289
|
createSecurityHeadersHooks<AppContext>(),
|
|
305
290
|
createErrorReportingHooks<AppContext>(),
|
|
@@ -324,7 +309,38 @@ ${providerConfigEntries}
|
|
|
324
309
|
};
|
|
325
310
|
},
|
|
326
311
|
});
|
|
312
|
+
let stopPromise: Promise<void> | undefined;
|
|
313
|
+
|
|
314
|
+
return {
|
|
315
|
+
...server,
|
|
316
|
+
stop() {
|
|
317
|
+
stopPromise ??= stopServerAndDatabase(server);
|
|
318
|
+
return stopPromise;
|
|
319
|
+
},
|
|
320
|
+
};
|
|
327
321
|
});
|
|
322
|
+
|
|
323
|
+
async function stopServerAndDatabase(server: {
|
|
324
|
+
stop(): Promise<void>;
|
|
325
|
+
}): Promise<void> {
|
|
326
|
+
const errors: unknown[] = [];
|
|
327
|
+
try {
|
|
328
|
+
await server.stop();
|
|
329
|
+
} catch (error) {
|
|
330
|
+
errors.push(error);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
try {
|
|
334
|
+
await closeDatabaseClient();
|
|
335
|
+
} catch (error) {
|
|
336
|
+
errors.push(error);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if (errors.length === 1) throw errors[0];
|
|
340
|
+
if (errors.length > 1) {
|
|
341
|
+
throw new AggregateError(errors, "Server and database shutdown failed");
|
|
342
|
+
}
|
|
343
|
+
}
|
|
328
344
|
`;
|
|
329
345
|
}
|
|
330
346
|
const files = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/templates/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EACL,kBAAkB,EAClB,cAAc,GAEf,MAAM,aAAa,CAAC;AAErB,MAAM,UAAU,eAAe,CAAC,GAAoB;IAClD,MAAM,EAAE,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG;QACd,qCAAqC;QACrC,6DAA6D;QAC7D,gFAAgF;QAChF,YAAY,EAAE,CAAC,eAAe,yCAAyC,EAAE,CAAC,OAAO,IAAI;QACrF,cAAc,CAAC,GAAG,EAAE,SAAS,CAAC;YAC5B,CAAC,CAAC,6EAA6E;YAC/E,CAAC,CAAC,SAAS;QACb,2EAA2E;QAC3E,cAAc,CAAC,GAAG,EAAE,QAAQ,CAAC;YAC3B,CAAC,CAAC,2EAA2E;YAC7E,CAAC,CAAC,SAAS;QACb,cAAc,CAAC,GAAG,EAAE,oBAAoB,CAAC;YACvC,CAAC,CAAC,wFAAwF;YAC1F,CAAC,CAAC,SAAS;QACb,8CAA8C;QAC9C,gEAAgE;QAChE,2CAA2C;QAC3C,oEAAoE;KACrE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAElD,MAAM,OAAO,GAAG;QACd,6BAA6B;QAC7B,kEAAkE;QAClE,+BAA+B;QAC/B,KAAK,EAAE,CAAC,gBAAgB,GAAG;QAC3B,4BAA4B;QAC5B,cAAc,CAAC,GAAG,EAAE,SAAS,CAAC;YAC5B,CAAC,CAAC,gCAAgC;YAClC,CAAC,CAAC,SAAS;QACb,cAAc,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,SAAS;QAC3E,cAAc,CAAC,GAAG,EAAE,oBAAoB,CAAC;YACvC,CAAC,CAAC,qCAAqC;YACvC,CAAC,CAAC,SAAS;KACd,CAAC,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAErD,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;;QAEtB,EAAE,CAAC,gBAAgB,MAAM,EAAE,CAAC,eAAe
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/templates/server.ts"],"names":[],"mappings":"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"}
|
package/dist/templates/shared.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const externalVersions = {
|
|
2
2
|
biome: "^2.4.14",
|
|
3
|
-
next: "^16.2.
|
|
3
|
+
next: "^16.2.10",
|
|
4
4
|
react: "^19.2.5",
|
|
5
5
|
reactDom: "^19.2.5",
|
|
6
6
|
tsx: "^4.22.4",
|
|
@@ -16,7 +16,7 @@ export const externalVersions = {
|
|
|
16
16
|
bullmq: "^5.0.0",
|
|
17
17
|
drizzleKit: "^0.31.10",
|
|
18
18
|
drizzleOrm: "^0.45.2",
|
|
19
|
-
inngest: "^3.
|
|
19
|
+
inngest: "^3.54.0",
|
|
20
20
|
libsqlClient: "^0.14.0",
|
|
21
21
|
vercelBlob: "^2.5.0",
|
|
22
22
|
mysql2: "^3.12.0",
|
|
@@ -26,7 +26,7 @@ export const externalVersions = {
|
|
|
26
26
|
resend: "^6.14.0",
|
|
27
27
|
sentryNode: "^10.58.0",
|
|
28
28
|
stripe: "^22.2.1",
|
|
29
|
-
nodemailer: "^
|
|
29
|
+
nodemailer: "^9.0.1",
|
|
30
30
|
openFeatureServerSdk: "^1.22.0",
|
|
31
31
|
typesPg: "^8.11.0",
|
|
32
32
|
ioredis: "^5.0.0",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/templates/shared.ts"],"names":[],"mappings":"AAgCA,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,KAAK,EAAE,SAAS;IAChB,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/templates/shared.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@beignet/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.37",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI for creating and maintaining Beignet apps.",
|
|
6
6
|
"main": "./dist/lib.js",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"typescript": "^5.3.0"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@beignet/core": "^0.0.
|
|
73
|
+
"@beignet/core": "^0.0.37",
|
|
74
74
|
"@clack/prompts": "^1.5.1",
|
|
75
75
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
76
76
|
"@stricli/core": "^1.2.7",
|
package/src/config.ts
CHANGED
|
@@ -56,6 +56,17 @@ export type BeignetDatabaseConfig = {
|
|
|
56
56
|
schemaSources?: string[];
|
|
57
57
|
};
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Explicit exceptions for static provider package requirements.
|
|
61
|
+
*/
|
|
62
|
+
export type BeignetProviderAuditConfig = {
|
|
63
|
+
/**
|
|
64
|
+
* Environment variables supplied through another mechanism, such as an
|
|
65
|
+
* injected platform client, and therefore not required in app env files.
|
|
66
|
+
*/
|
|
67
|
+
ignoreRequiredEnv?: string[];
|
|
68
|
+
};
|
|
69
|
+
|
|
59
70
|
/**
|
|
60
71
|
* User-authored Beignet CLI config.
|
|
61
72
|
*/
|
|
@@ -63,6 +74,7 @@ export type BeignetConfig = {
|
|
|
63
74
|
framework?: BeignetFramework;
|
|
64
75
|
paths?: Partial<BeignetPaths>;
|
|
65
76
|
database?: BeignetDatabaseConfig;
|
|
77
|
+
providerAudit?: BeignetProviderAuditConfig;
|
|
66
78
|
};
|
|
67
79
|
|
|
68
80
|
/**
|
|
@@ -75,6 +87,9 @@ export type ResolvedBeignetConfig = {
|
|
|
75
87
|
tables: BeignetDatabaseTables;
|
|
76
88
|
schemaSources: string[];
|
|
77
89
|
};
|
|
90
|
+
providerAudit: {
|
|
91
|
+
ignoreRequiredEnv: string[];
|
|
92
|
+
};
|
|
78
93
|
configFile?: string;
|
|
79
94
|
};
|
|
80
95
|
|
|
@@ -116,6 +131,9 @@ export const defaultBeignetConfig: ResolvedBeignetConfig = {
|
|
|
116
131
|
},
|
|
117
132
|
schemaSources: [],
|
|
118
133
|
},
|
|
134
|
+
providerAudit: {
|
|
135
|
+
ignoreRequiredEnv: [],
|
|
136
|
+
},
|
|
119
137
|
};
|
|
120
138
|
|
|
121
139
|
/**
|
|
@@ -145,11 +163,17 @@ export function resolveConfig(
|
|
|
145
163
|
config.database?.schemaSources ??
|
|
146
164
|
defaultBeignetConfig.database.schemaSources,
|
|
147
165
|
};
|
|
166
|
+
const providerAudit = {
|
|
167
|
+
ignoreRequiredEnv:
|
|
168
|
+
config.providerAudit?.ignoreRequiredEnv ??
|
|
169
|
+
defaultBeignetConfig.providerAudit.ignoreRequiredEnv,
|
|
170
|
+
};
|
|
148
171
|
|
|
149
172
|
return {
|
|
150
173
|
framework: config.framework ?? defaultBeignetConfig.framework,
|
|
151
174
|
paths: normalizeConfigPaths(paths),
|
|
152
175
|
database: normalizeDatabaseConfig(database),
|
|
176
|
+
providerAudit: normalizeProviderAuditConfig(providerAudit),
|
|
153
177
|
configFile,
|
|
154
178
|
};
|
|
155
179
|
}
|
|
@@ -298,6 +322,20 @@ function assertConfigObject(
|
|
|
298
322
|
throw new Error(`${configFile} database must be an object.`);
|
|
299
323
|
}
|
|
300
324
|
|
|
325
|
+
if (config.providerAudit !== undefined && !isRecord(config.providerAudit)) {
|
|
326
|
+
throw new Error(`${configFile} providerAudit must be an object.`);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
if (
|
|
330
|
+
config.providerAudit !== undefined &&
|
|
331
|
+
config.providerAudit.ignoreRequiredEnv !== undefined &&
|
|
332
|
+
!Array.isArray(config.providerAudit.ignoreRequiredEnv)
|
|
333
|
+
) {
|
|
334
|
+
throw new Error(
|
|
335
|
+
`${configFile} providerAudit.ignoreRequiredEnv must be an array.`,
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
|
|
301
339
|
if (
|
|
302
340
|
config.database !== undefined &&
|
|
303
341
|
config.database.tables !== undefined &&
|
|
@@ -385,6 +423,32 @@ function normalizeDatabaseSchemaSource(index: number, value: string): string {
|
|
|
385
423
|
return value.trim();
|
|
386
424
|
}
|
|
387
425
|
|
|
426
|
+
function normalizeProviderAuditConfig(config: {
|
|
427
|
+
ignoreRequiredEnv: string[];
|
|
428
|
+
}): {
|
|
429
|
+
ignoreRequiredEnv: string[];
|
|
430
|
+
} {
|
|
431
|
+
return {
|
|
432
|
+
ignoreRequiredEnv: [
|
|
433
|
+
...new Set(
|
|
434
|
+
config.ignoreRequiredEnv.map((value, index) =>
|
|
435
|
+
normalizeIgnoredRequiredEnv(index, value),
|
|
436
|
+
),
|
|
437
|
+
),
|
|
438
|
+
],
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
function normalizeIgnoredRequiredEnv(index: number, value: string): string {
|
|
443
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
444
|
+
throw new Error(
|
|
445
|
+
`Beignet config providerAudit.ignoreRequiredEnv[${index}] must be a string.`,
|
|
446
|
+
);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
return value.trim();
|
|
450
|
+
}
|
|
451
|
+
|
|
388
452
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
389
453
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
390
454
|
}
|
package/src/inspect.ts
CHANGED
|
@@ -2228,7 +2228,10 @@ async function inspectProductionReadiness(
|
|
|
2228
2228
|
provider.variants,
|
|
2229
2229
|
providerEntries,
|
|
2230
2230
|
)) {
|
|
2231
|
-
for (const envVar of
|
|
2231
|
+
for (const envVar of configuredProviderRequiredEnv(
|
|
2232
|
+
variant.requiredEnv,
|
|
2233
|
+
config,
|
|
2234
|
+
)) {
|
|
2232
2235
|
if (
|
|
2233
2236
|
await providerRequiredEnvExists(
|
|
2234
2237
|
targetDir,
|
|
@@ -2275,7 +2278,10 @@ async function inspectProductionReadiness(
|
|
|
2275
2278
|
continue;
|
|
2276
2279
|
}
|
|
2277
2280
|
|
|
2278
|
-
for (const envVar of
|
|
2281
|
+
for (const envVar of configuredProviderRequiredEnv(
|
|
2282
|
+
provider.requiredEnv ?? [],
|
|
2283
|
+
config,
|
|
2284
|
+
)) {
|
|
2279
2285
|
if (
|
|
2280
2286
|
await providerRequiredEnvExists(
|
|
2281
2287
|
targetDir,
|
|
@@ -5539,6 +5545,14 @@ function configuredProviderRequiredTables(
|
|
|
5539
5545
|
);
|
|
5540
5546
|
}
|
|
5541
5547
|
|
|
5548
|
+
function configuredProviderRequiredEnv(
|
|
5549
|
+
envVars: readonly string[],
|
|
5550
|
+
config: ResolvedBeignetConfig,
|
|
5551
|
+
): string[] {
|
|
5552
|
+
const ignored = new Set(config.providerAudit.ignoreRequiredEnv);
|
|
5553
|
+
return envVars.filter((envVar) => !ignored.has(envVar));
|
|
5554
|
+
}
|
|
5555
|
+
|
|
5542
5556
|
function configuredProviderRequiredTable(
|
|
5543
5557
|
tableName: string,
|
|
5544
5558
|
config: ResolvedBeignetConfig,
|
package/src/provider-audit.ts
CHANGED
|
@@ -1015,6 +1015,14 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
|
|
1015
1015
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1016
1016
|
}
|
|
1017
1017
|
|
|
1018
|
+
function configuredProviderRequiredEnv(
|
|
1019
|
+
envVars: readonly string[],
|
|
1020
|
+
config: ResolvedBeignetConfig,
|
|
1021
|
+
): string[] {
|
|
1022
|
+
const ignored = new Set(config.providerAudit.ignoreRequiredEnv);
|
|
1023
|
+
return envVars.filter((envVar) => !ignored.has(envVar));
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1018
1026
|
function configuredProviderRequiredTables(
|
|
1019
1027
|
tableNames: readonly string[],
|
|
1020
1028
|
config: ResolvedBeignetConfig,
|
|
@@ -1140,13 +1148,18 @@ async function providerAuditEntryForRule(options: {
|
|
|
1140
1148
|
const requiredEnv =
|
|
1141
1149
|
options.rule.variants !== undefined
|
|
1142
1150
|
? aggregateVariantRequirement(variants, "requiredEnv")
|
|
1143
|
-
: await requirementAudit(
|
|
1144
|
-
|
|
1145
|
-
options.
|
|
1146
|
-
options.
|
|
1147
|
-
envVar,
|
|
1148
|
-
options.sourceCache,
|
|
1151
|
+
: await requirementAudit(
|
|
1152
|
+
configuredProviderRequiredEnv(
|
|
1153
|
+
options.rule.requiredEnv ?? [],
|
|
1154
|
+
options.config,
|
|
1149
1155
|
),
|
|
1156
|
+
(envVar) =>
|
|
1157
|
+
providerRequiredEnvExists(
|
|
1158
|
+
options.targetDir,
|
|
1159
|
+
options.configFiles,
|
|
1160
|
+
envVar,
|
|
1161
|
+
options.sourceCache,
|
|
1162
|
+
),
|
|
1150
1163
|
);
|
|
1151
1164
|
|
|
1152
1165
|
const requiredTables =
|
|
@@ -1222,12 +1235,16 @@ async function providerVariantAudit(options: {
|
|
|
1222
1235
|
variant: ProviderDoctorVariantRule;
|
|
1223
1236
|
registered: boolean;
|
|
1224
1237
|
}): Promise<ProviderVariantAudit> {
|
|
1238
|
+
const requiredEnv = configuredProviderRequiredEnv(
|
|
1239
|
+
options.variant.requiredEnv,
|
|
1240
|
+
options.config,
|
|
1241
|
+
);
|
|
1225
1242
|
if (!options.registered) {
|
|
1226
1243
|
return {
|
|
1227
1244
|
name: options.variant.name,
|
|
1228
1245
|
displayName: options.variant.displayName,
|
|
1229
1246
|
registration: "inactive",
|
|
1230
|
-
requiredEnv: inactiveRequirement(
|
|
1247
|
+
requiredEnv: inactiveRequirement(requiredEnv),
|
|
1231
1248
|
requiredTables: inactiveRequirement(options.variant.requiredTables),
|
|
1232
1249
|
};
|
|
1233
1250
|
}
|
|
@@ -1240,7 +1257,7 @@ async function providerVariantAudit(options: {
|
|
|
1240
1257
|
options.variant.registrationSeverity,
|
|
1241
1258
|
options.providerEntries,
|
|
1242
1259
|
),
|
|
1243
|
-
requiredEnv: await requirementAudit(
|
|
1260
|
+
requiredEnv: await requirementAudit(requiredEnv, (envVar) =>
|
|
1244
1261
|
providerRequiredEnvExists(
|
|
1245
1262
|
options.targetDir,
|
|
1246
1263
|
options.configFiles,
|
package/src/templates/base.ts
CHANGED
|
@@ -314,7 +314,7 @@ Use \`${cli} make feature projects --recipe full-slice\` when you want a richer
|
|
|
314
314
|
- \`features/shared/errors.ts\` keeps application errors and route-owned error schemas together.
|
|
315
315
|
- \`ports/\` defines app-owned dependencies.
|
|
316
316
|
- \`infra/\` implements ports for the selected runtime.
|
|
317
|
-
- \`infra/db/schema/\` contains the Drizzle schema, \`drizzle/\` contains the checked-in migrations, and \`infra/todos/\` contains the durable todo repository adapter.
|
|
317
|
+
- \`infra/db/client.ts\` owns the process-wide database client shared by Better Auth and the Beignet provider; the public server \`stop()\` closes it after provider shutdown. \`infra/db/schema/\` contains the Drizzle schema, \`drizzle/\` contains the checked-in migrations, and \`infra/todos/\` contains the durable todo repository adapter.
|
|
318
318
|
- \`server/routes.ts\` keeps the central route registry and OpenAPI contract list.
|
|
319
319
|
- \`server/context.ts\` declares the context blueprint shared by the server and route tests.
|
|
320
320
|
- \`server/providers.ts\` wires devtools, Better Auth, pino, ${
|
|
@@ -342,6 +342,7 @@ ${optionalAuthRedirects}
|
|
|
342
342
|
cli +
|
|
343
343
|
" db migrate` against it before starting the app."
|
|
344
344
|
}
|
|
345
|
+
- Size the process-wide database client for the deployment. Postgres and MySQL use the generated pool-limit environment variable; count web, worker, preview, and task processes against the database connection limit, and keep writable SQLite files on one host.
|
|
345
346
|
- Run \`${cli} db generate\` and \`${cli} db migrate\` after changing the Drizzle schema.
|
|
346
347
|
- Run \`${cli} db reset\` to rebuild a local ${
|
|
347
348
|
ctx.database === "sqlite"
|
|
@@ -438,11 +439,15 @@ export function envExample(ctx: TemplateContext): string {
|
|
|
438
439
|
"# Local Postgres matching the docker one-liner below; point at your own server in production.",
|
|
439
440
|
`# ${databaseStartCommand("postgres", ctx.name)}`,
|
|
440
441
|
`POSTGRES_DB_URL=${databaseLocalUrl("postgres", ctx.name)}`,
|
|
442
|
+
"# Maximum connections opened by each running app process.",
|
|
443
|
+
"POSTGRES_DB_POOL_MAX=5",
|
|
441
444
|
]
|
|
442
445
|
: [
|
|
443
446
|
"# Local MySQL matching the docker one-liner below; point at your own server in production.",
|
|
444
447
|
`# ${databaseStartCommand("mysql", ctx.name)}`,
|
|
445
448
|
`MYSQL_DB_URL=${databaseLocalUrl("mysql", ctx.name)}`,
|
|
449
|
+
"# Maximum connections opened by each running app process.",
|
|
450
|
+
"MYSQL_DB_POOL_MAX=5",
|
|
446
451
|
];
|
|
447
452
|
|
|
448
453
|
const lines = [
|
|
@@ -36,6 +36,22 @@ export function mysqlDbFiles(ctx: TemplateContext): DbTemplateFiles {
|
|
|
36
36
|
url: process.env.MYSQL_DB_URL ?? "${databaseLocalUrl("mysql", ctx.name)}",
|
|
37
37
|
},
|
|
38
38
|
};
|
|
39
|
+
`,
|
|
40
|
+
dbClient: `import "@beignet/core/server-only";
|
|
41
|
+
import mysql from "mysql2/promise";
|
|
42
|
+
import { env } from "@/lib/env";
|
|
43
|
+
|
|
44
|
+
export const databaseClient = mysql.createPool({
|
|
45
|
+
uri: env.MYSQL_DB_URL,
|
|
46
|
+
connectionLimit: env.MYSQL_DB_POOL_MAX,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
let closePromise: Promise<void> | undefined;
|
|
50
|
+
|
|
51
|
+
export function closeDatabaseClient(): Promise<void> {
|
|
52
|
+
closePromise ??= Promise.resolve().then(() => databaseClient.end());
|
|
53
|
+
return closePromise;
|
|
54
|
+
}
|
|
39
55
|
`,
|
|
40
56
|
dbSchema: `import {
|
|
41
57
|
boolean,
|
|
@@ -33,6 +33,22 @@ export function postgresDbFiles(ctx: TemplateContext): DbTemplateFiles {
|
|
|
33
33
|
url: process.env.POSTGRES_DB_URL ?? "${databaseLocalUrl("postgres", ctx.name)}",
|
|
34
34
|
},
|
|
35
35
|
};
|
|
36
|
+
`,
|
|
37
|
+
dbClient: `import "@beignet/core/server-only";
|
|
38
|
+
import pg from "pg";
|
|
39
|
+
import { env } from "@/lib/env";
|
|
40
|
+
|
|
41
|
+
export const databaseClient = new pg.Pool({
|
|
42
|
+
connectionString: env.POSTGRES_DB_URL,
|
|
43
|
+
max: env.POSTGRES_DB_POOL_MAX,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
let closePromise: Promise<void> | undefined;
|
|
47
|
+
|
|
48
|
+
export function closeDatabaseClient(): Promise<void> {
|
|
49
|
+
closePromise ??= Promise.resolve().then(() => databaseClient.end());
|
|
50
|
+
return closePromise;
|
|
51
|
+
}
|
|
36
52
|
`,
|
|
37
53
|
dbSchema: `import { boolean, index, pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
|
38
54
|
|
|
@@ -24,6 +24,22 @@ const files = {
|
|
|
24
24
|
authToken: process.env.SQLITE_DB_AUTH_TOKEN,
|
|
25
25
|
},
|
|
26
26
|
};
|
|
27
|
+
`,
|
|
28
|
+
dbClient: `import "@beignet/core/server-only";
|
|
29
|
+
import { createClient } from "@libsql/client";
|
|
30
|
+
import { env } from "@/lib/env";
|
|
31
|
+
|
|
32
|
+
export const databaseClient = createClient({
|
|
33
|
+
url: env.SQLITE_DB_URL,
|
|
34
|
+
authToken: env.SQLITE_DB_AUTH_TOKEN,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
let closePromise: Promise<void> | undefined;
|
|
38
|
+
|
|
39
|
+
export function closeDatabaseClient(): Promise<void> {
|
|
40
|
+
closePromise ??= Promise.resolve().then(() => databaseClient.close());
|
|
41
|
+
return closePromise;
|
|
42
|
+
}
|
|
27
43
|
`,
|
|
28
44
|
dbSchema: `import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
29
45
|
|
package/src/templates/index.ts
CHANGED
|
@@ -110,6 +110,7 @@ export function getTemplateFiles(ctx: TemplateContext): TemplateFile[] {
|
|
|
110
110
|
{ path: "ports/index.ts", content: ports(ctx) },
|
|
111
111
|
{ path: "ports/auth.ts", content: serverFiles.authPort },
|
|
112
112
|
{ path: "infra/app-ports.ts", content: infrastructurePorts(ctx) },
|
|
113
|
+
{ path: "infra/db/client.ts", content: db.dbClient },
|
|
113
114
|
{ path: "infra/db/database-ready.ts", content: db.databaseReady },
|
|
114
115
|
{ path: "infra/db/provider.ts", content: db.dbProvider },
|
|
115
116
|
{ path: "infra/db/repositories.ts", content: db.dbRepositories },
|
|
@@ -137,7 +138,7 @@ export function getTemplateFiles(ctx: TemplateContext): TemplateFile[] {
|
|
|
137
138
|
...testSupportTemplateFiles,
|
|
138
139
|
{ path: "lib/use-case.ts", content: serverFiles.useCaseBuilder },
|
|
139
140
|
{ path: "lib/routes.ts", content: serverFiles.routesBuilder },
|
|
140
|
-
{ path: "server/index.ts", content: server(
|
|
141
|
+
{ path: "server/index.ts", content: server() },
|
|
141
142
|
{ path: "server/context.ts", content: serverFiles.serverContext },
|
|
142
143
|
{ path: "server/routes.ts", content: serverFiles.serverRoutes },
|
|
143
144
|
{ path: "server/providers.ts", content: serverProviders(ctx) },
|