@beignet/cli 0.0.36 → 0.0.38
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 +27 -0
- package/README.md +36 -5
- package/dist/config.d.ts +15 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +30 -1
- package/dist/config.js.map +1 -1
- package/dist/inspect.js +21 -17
- package/dist/inspect.js.map +1 -1
- package/dist/lint.d.ts.map +1 -1
- package/dist/lint.js +27 -6
- package/dist/lint.js.map +1 -1
- package/dist/make/inbox.js +7 -7
- package/dist/make/inbox.js.map +1 -1
- package/dist/make/payments.d.ts +2 -1
- package/dist/make/payments.d.ts.map +1 -1
- package/dist/make/payments.js +15 -11
- package/dist/make/payments.js.map +1 -1
- package/dist/make/shared.d.ts +1 -1
- package/dist/make/shared.d.ts.map +1 -1
- package/dist/make/shared.js +49 -37
- package/dist/make/shared.js.map +1 -1
- package/dist/make/tenancy.js +8 -8
- package/dist/make/tenancy.js.map +1 -1
- package/dist/make.d.ts.map +1 -1
- package/dist/make.js +27 -16
- package/dist/make.js.map +1 -1
- package/dist/operational-error-reporting.d.ts +15 -0
- package/dist/operational-error-reporting.d.ts.map +1 -0
- package/dist/operational-error-reporting.js +42 -0
- package/dist/operational-error-reporting.js.map +1 -0
- package/dist/outbox.d.ts.map +1 -1
- package/dist/outbox.js +73 -0
- package/dist/outbox.js.map +1 -1
- package/dist/provider-add.js +17 -17
- package/dist/provider-add.js.map +1 -1
- package/dist/provider-audit.d.ts.map +1 -1
- package/dist/provider-audit.js +11 -6
- package/dist/provider-audit.js.map +1 -1
- package/dist/schedule.d.ts.map +1 -1
- package/dist/schedule.js +28 -1
- package/dist/schedule.js.map +1 -1
- package/dist/task.d.ts.map +1 -1
- package/dist/task.js +37 -4
- package/dist/task.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 +4 -3
- package/dist/templates/index.js.map +1 -1
- package/dist/templates/server.d.ts +2 -2
- package/dist/templates/server.d.ts.map +1 -1
- package/dist/templates/server.js +56 -40
- package/dist/templates/server.js.map +1 -1
- package/dist/templates/shared.js +3 -3
- package/dist/templates/shared.js.map +1 -1
- package/dist/templates/testing.js +1 -1
- package/dist/templates/todos.js +6 -6
- package/package.json +4 -4
- package/src/config.ts +66 -2
- package/src/inspect.ts +31 -19
- package/src/lint.ts +35 -4
- package/src/make/inbox.ts +7 -7
- package/src/make/payments.ts +23 -15
- package/src/make/shared.ts +56 -40
- package/src/make/tenancy.ts +8 -8
- package/src/make.ts +30 -16
- package/src/operational-error-reporting.ts +60 -0
- package/src/outbox.ts +77 -0
- package/src/provider-add.ts +21 -17
- package/src/provider-audit.ts +28 -11
- package/src/schedule.ts +32 -1
- package/src/task.ts +41 -4
- 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 +4 -3
- package/src/templates/server.ts +56 -42
- package/src/templates/shared.ts +3 -3
- package/src/templates/testing.ts +1 -1
- package/src/templates/todos.ts +6 -6
package/src/templates/server.ts
CHANGED
|
@@ -23,6 +23,7 @@ export function serverProviders(ctx: TemplateContext): string {
|
|
|
23
23
|
? 'import { createUpstashRateLimitProvider } from "@beignet/provider-rate-limit-upstash";'
|
|
24
24
|
: undefined,
|
|
25
25
|
'import * as schema from "@/infra/db/schema";',
|
|
26
|
+
'import { databaseClient } from "@/infra/db/client";',
|
|
26
27
|
'import { starterDatabaseProvider } from "@/infra/db/provider";',
|
|
27
28
|
'import { auth } from "@/lib/better-auth";',
|
|
28
29
|
'import type { AuthSessionMetadata, AuthUser } from "@/ports/auth";',
|
|
@@ -45,7 +46,10 @@ export function serverProviders(ctx: TemplateContext): string {
|
|
|
45
46
|
|
|
46
47
|
return `${imports.join("\n")}
|
|
47
48
|
|
|
48
|
-
const ${db.providerInstance} = ${db.providerFactory}({
|
|
49
|
+
const ${db.providerInstance} = ${db.providerFactory}({
|
|
50
|
+
schema,
|
|
51
|
+
client: databaseClient,
|
|
52
|
+
});
|
|
49
53
|
|
|
50
54
|
export const providers = [
|
|
51
55
|
${entries.join("\n")}
|
|
@@ -97,7 +101,7 @@ ${usesResend ? "\tmailer: MailerPort;\n" : ""}${usesUpstash ? "\trateLimit: Rate
|
|
|
97
101
|
`;
|
|
98
102
|
}
|
|
99
103
|
|
|
100
|
-
export function
|
|
104
|
+
export function portWiring(ctx: TemplateContext): string {
|
|
101
105
|
const deferred = [
|
|
102
106
|
'\t\t"auth",',
|
|
103
107
|
'\t\t"idempotency",',
|
|
@@ -126,13 +130,13 @@ const gate = createGate({
|
|
|
126
130
|
});
|
|
127
131
|
|
|
128
132
|
/**
|
|
129
|
-
*
|
|
133
|
+
* Initial port values the server boots with.
|
|
130
134
|
*
|
|
131
135
|
* Bound ports are app-owned. Every deferred key is contributed by a provider
|
|
132
136
|
* in server/providers.ts during startup; createNextServer(...) fails boot if
|
|
133
137
|
* any of them is still unbound after providers have started.
|
|
134
138
|
*/
|
|
135
|
-
export const
|
|
139
|
+
export const initialPorts = definePorts<AppPorts>()({
|
|
136
140
|
bound: {
|
|
137
141
|
errorReporter: createNoopErrorReporter(),
|
|
138
142
|
gate,
|
|
@@ -151,7 +155,8 @@ export function env(ctx: TemplateContext): string {
|
|
|
151
155
|
\t\tSQLITE_DB_AUTH_TOKEN: z.string().optional(),`
|
|
152
156
|
: `\t\t${databaseDescriptor(ctx).urlEnvVar}: z
|
|
153
157
|
\t\t\t.string()
|
|
154
|
-
\t\t\t.default("${databaseLocalUrl(ctx.database, ctx.name)}")
|
|
158
|
+
\t\t\t.default("${databaseLocalUrl(ctx.database, ctx.name)}"),
|
|
159
|
+
\t\t${ctx.database === "postgres" ? "POSTGRES" : "MYSQL"}_DB_POOL_MAX: z.coerce.number().int().positive().default(5),`;
|
|
155
160
|
|
|
156
161
|
return `import { createEnv } from "@beignet/core/config";
|
|
157
162
|
import { z } from "zod";
|
|
@@ -202,54 +207,45 @@ export const isDevtoolsEnabled =
|
|
|
202
207
|
|
|
203
208
|
export function betterAuth(ctx: TemplateContext): string {
|
|
204
209
|
const connectionByDatabase = {
|
|
205
|
-
sqlite: `import {
|
|
206
|
-
import { betterAuth } from "better-auth";
|
|
210
|
+
sqlite: `import { betterAuth } from "better-auth";
|
|
207
211
|
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
208
212
|
import { drizzle } from "drizzle-orm/libsql";
|
|
213
|
+
import { databaseClient } from "@/infra/db/client";
|
|
209
214
|
import { ensureDatabaseReady } from "@/infra/db/database-ready";
|
|
210
215
|
import * as schema from "@/infra/db/schema";
|
|
211
216
|
import { env } from "@/lib/env";
|
|
212
217
|
|
|
213
|
-
const client = createClient({
|
|
214
|
-
url: env.SQLITE_DB_URL,
|
|
215
|
-
authToken: env.SQLITE_DB_AUTH_TOKEN,
|
|
216
|
-
});
|
|
217
|
-
|
|
218
218
|
// Auth routes can be the first thing to touch the database, before any
|
|
219
219
|
// Beignet provider boots, so readiness is enforced here too.
|
|
220
|
-
await ensureDatabaseReady(
|
|
220
|
+
await ensureDatabaseReady(databaseClient);
|
|
221
221
|
|
|
222
|
-
const db = drizzle(
|
|
222
|
+
const db = drizzle(databaseClient, { schema });`,
|
|
223
223
|
postgres: `import { betterAuth } from "better-auth";
|
|
224
224
|
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
225
225
|
import { drizzle } from "drizzle-orm/node-postgres";
|
|
226
|
-
import
|
|
226
|
+
import { databaseClient } from "@/infra/db/client";
|
|
227
227
|
import { ensureDatabaseReady } from "@/infra/db/database-ready";
|
|
228
228
|
import * as schema from "@/infra/db/schema";
|
|
229
229
|
import { env } from "@/lib/env";
|
|
230
230
|
|
|
231
|
-
const pool = new pg.Pool({ connectionString: env.POSTGRES_DB_URL });
|
|
232
|
-
|
|
233
231
|
// Auth routes can be the first thing to touch the database, before any
|
|
234
232
|
// Beignet provider boots, so readiness is enforced here too.
|
|
235
|
-
await ensureDatabaseReady(
|
|
233
|
+
await ensureDatabaseReady(databaseClient);
|
|
236
234
|
|
|
237
|
-
const db = drizzle(
|
|
235
|
+
const db = drizzle(databaseClient, { schema });`,
|
|
238
236
|
mysql: `import { betterAuth } from "better-auth";
|
|
239
237
|
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
240
238
|
import { drizzle } from "drizzle-orm/mysql2";
|
|
241
|
-
import
|
|
239
|
+
import { databaseClient } from "@/infra/db/client";
|
|
242
240
|
import { ensureDatabaseReady } from "@/infra/db/database-ready";
|
|
243
241
|
import * as schema from "@/infra/db/schema";
|
|
244
242
|
import { env } from "@/lib/env";
|
|
245
243
|
|
|
246
|
-
const pool = mysql.createPool({ uri: env.MYSQL_DB_URL });
|
|
247
|
-
|
|
248
244
|
// Auth routes can be the first thing to touch the database, before any
|
|
249
245
|
// Beignet provider boots, so readiness is enforced here too.
|
|
250
|
-
await ensureDatabaseReady(
|
|
246
|
+
await ensureDatabaseReady(databaseClient);
|
|
251
247
|
|
|
252
|
-
const db = drizzle(
|
|
248
|
+
const db = drizzle(databaseClient, { schema, mode: "default" });`,
|
|
253
249
|
} as const;
|
|
254
250
|
|
|
255
251
|
return `${connectionByDatabase[ctx.database]}
|
|
@@ -285,18 +281,7 @@ export const auth = betterAuth({
|
|
|
285
281
|
`;
|
|
286
282
|
}
|
|
287
283
|
|
|
288
|
-
export function server(
|
|
289
|
-
const db = databaseDescriptor(ctx);
|
|
290
|
-
const providerConfigEntries =
|
|
291
|
-
ctx.database === "sqlite"
|
|
292
|
-
? `\t\t"drizzle-sqlite": {
|
|
293
|
-
\t\t\tDB_URL: env.SQLITE_DB_URL,
|
|
294
|
-
\t\t\tDB_AUTH_TOKEN: env.SQLITE_DB_AUTH_TOKEN,
|
|
295
|
-
\t\t},`
|
|
296
|
-
: `\t\t"${db.providerName}": {
|
|
297
|
-
\t\t\tDB_URL: env.${db.urlEnvVar},
|
|
298
|
-
\t\t},`;
|
|
299
|
-
|
|
284
|
+
export function server(): string {
|
|
300
285
|
return `import "@beignet/core/server-only";
|
|
301
286
|
import { createNextServer, createNextServerLoader } from "@beignet/next";
|
|
302
287
|
import {
|
|
@@ -305,7 +290,8 @@ import {
|
|
|
305
290
|
createSecurityHeadersHooks,
|
|
306
291
|
} from "@beignet/core/server";
|
|
307
292
|
import type { AppContext } from "@/app-context";
|
|
308
|
-
import {
|
|
293
|
+
import { initialPorts } from "@/infra/port-wiring";
|
|
294
|
+
import { closeDatabaseClient } from "@/infra/db/client";
|
|
309
295
|
import { env } from "@/lib/env";
|
|
310
296
|
import { appContext } from "./context";
|
|
311
297
|
import { routes } from "./routes";
|
|
@@ -313,12 +299,9 @@ import { routes } from "./routes";
|
|
|
313
299
|
export const getServer = createNextServerLoader(async () => {
|
|
314
300
|
const { providers } = await import("./providers");
|
|
315
301
|
|
|
316
|
-
|
|
317
|
-
ports:
|
|
302
|
+
const server = await createNextServer({
|
|
303
|
+
ports: initialPorts,
|
|
318
304
|
providers,
|
|
319
|
-
providerConfig: {
|
|
320
|
-
${providerConfigEntries}
|
|
321
|
-
},
|
|
322
305
|
hooks: [
|
|
323
306
|
createSecurityHeadersHooks<AppContext>(),
|
|
324
307
|
createErrorReportingHooks<AppContext>(),
|
|
@@ -343,7 +326,38 @@ ${providerConfigEntries}
|
|
|
343
326
|
};
|
|
344
327
|
},
|
|
345
328
|
});
|
|
329
|
+
let stopPromise: Promise<void> | undefined;
|
|
330
|
+
|
|
331
|
+
return {
|
|
332
|
+
...server,
|
|
333
|
+
stop() {
|
|
334
|
+
stopPromise ??= stopServerAndDatabase(server);
|
|
335
|
+
return stopPromise;
|
|
336
|
+
},
|
|
337
|
+
};
|
|
346
338
|
});
|
|
339
|
+
|
|
340
|
+
async function stopServerAndDatabase(server: {
|
|
341
|
+
stop(): Promise<void>;
|
|
342
|
+
}): Promise<void> {
|
|
343
|
+
const errors: unknown[] = [];
|
|
344
|
+
try {
|
|
345
|
+
await server.stop();
|
|
346
|
+
} catch (error) {
|
|
347
|
+
errors.push(error);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
try {
|
|
351
|
+
await closeDatabaseClient();
|
|
352
|
+
} catch (error) {
|
|
353
|
+
errors.push(error);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (errors.length === 1) throw errors[0];
|
|
357
|
+
if (errors.length > 1) {
|
|
358
|
+
throw new AggregateError(errors, "Server and database shutdown failed");
|
|
359
|
+
}
|
|
360
|
+
}
|
|
347
361
|
`;
|
|
348
362
|
}
|
|
349
363
|
|
package/src/templates/shared.ts
CHANGED
|
@@ -32,7 +32,7 @@ export type TemplateContext = {
|
|
|
32
32
|
|
|
33
33
|
export const externalVersions = {
|
|
34
34
|
biome: "^2.4.14",
|
|
35
|
-
next: "^16.2.
|
|
35
|
+
next: "^16.2.10",
|
|
36
36
|
react: "^19.2.5",
|
|
37
37
|
reactDom: "^19.2.5",
|
|
38
38
|
tsx: "^4.22.4",
|
|
@@ -48,7 +48,7 @@ export const externalVersions = {
|
|
|
48
48
|
bullmq: "^5.0.0",
|
|
49
49
|
drizzleKit: "^0.31.10",
|
|
50
50
|
drizzleOrm: "^0.45.2",
|
|
51
|
-
inngest: "^3.
|
|
51
|
+
inngest: "^3.54.0",
|
|
52
52
|
libsqlClient: "^0.14.0",
|
|
53
53
|
vercelBlob: "^2.5.0",
|
|
54
54
|
mysql2: "^3.12.0",
|
|
@@ -58,7 +58,7 @@ export const externalVersions = {
|
|
|
58
58
|
resend: "^6.14.0",
|
|
59
59
|
sentryNode: "^10.58.0",
|
|
60
60
|
stripe: "^22.2.1",
|
|
61
|
-
nodemailer: "^
|
|
61
|
+
nodemailer: "^9.0.1",
|
|
62
62
|
openFeatureServerSdk: "^1.22.0",
|
|
63
63
|
typesPg: "^8.11.0",
|
|
64
64
|
ioredis: "^5.0.0",
|
package/src/templates/testing.ts
CHANGED
|
@@ -536,7 +536,7 @@ async function configuredRoots(cwd: string): Promise<string[]> {
|
|
|
536
536
|
paths.features,
|
|
537
537
|
parentPath(paths.routes),
|
|
538
538
|
parentPath(paths.server),
|
|
539
|
-
parentPath(paths.
|
|
539
|
+
parentPath(paths.portWiring),
|
|
540
540
|
parentPath(paths.ports),
|
|
541
541
|
parentPath(paths.useCaseBuilder),
|
|
542
542
|
parentPath(paths.routesBuilder),
|
package/src/templates/todos.ts
CHANGED
|
@@ -368,7 +368,7 @@ import {
|
|
|
368
368
|
import { createInMemoryDevtools } from "@beignet/devtools";
|
|
369
369
|
import type { AppContext } from "@/app-context";
|
|
370
370
|
import type { TodoRepository } from "@/features/todos/ports";
|
|
371
|
-
import {
|
|
371
|
+
import { initialPorts } from "@/infra/port-wiring";
|
|
372
372
|
import type { AppTransactionPorts } from "@/ports";
|
|
373
373
|
import {
|
|
374
374
|
createTodoUseCase,
|
|
@@ -388,9 +388,9 @@ function createTester(userId: string, todos: TodoRepository) {
|
|
|
388
388
|
session: { id: \`session_\${userId}\` },
|
|
389
389
|
};
|
|
390
390
|
const testFixture = createTestPorts<AppContext["ports"], AppTransactionPorts>({
|
|
391
|
-
base:
|
|
391
|
+
base: initialPorts,
|
|
392
392
|
overrides: {
|
|
393
|
-
gate:
|
|
393
|
+
gate: initialPorts.gate,
|
|
394
394
|
todos,
|
|
395
395
|
devtools: createInMemoryDevtools(),
|
|
396
396
|
},
|
|
@@ -483,7 +483,7 @@ import { createInMemoryDevtools } from "@beignet/devtools";
|
|
|
483
483
|
import { createTestApp, createTestRequester } from "@beignet/web/testing";
|
|
484
484
|
import type { AppContext } from "@/app-context";
|
|
485
485
|
import type { TodoRepository } from "@/features/todos/ports";
|
|
486
|
-
import {
|
|
486
|
+
import { initialPorts } from "@/infra/port-wiring";
|
|
487
487
|
import type { AppPorts, AppTransactionPorts } from "@/ports";
|
|
488
488
|
import type { AuthRequest, AuthSessionMetadata, AuthUser } from "@/ports/auth";
|
|
489
489
|
import { type AppServiceContextInput, appContext } from "@/server/context";
|
|
@@ -507,9 +507,9 @@ async function createTodosTestApp(
|
|
|
507
507
|
) {
|
|
508
508
|
const todos = options.todos ?? createTestTodoRepository();
|
|
509
509
|
const fixture = createTestPorts<AppContext["ports"], AppTransactionPorts>({
|
|
510
|
-
base:
|
|
510
|
+
base: initialPorts,
|
|
511
511
|
overrides: {
|
|
512
|
-
gate:
|
|
512
|
+
gate: initialPorts.gate,
|
|
513
513
|
todos,
|
|
514
514
|
devtools: createInMemoryDevtools(),
|
|
515
515
|
auth: options.auth ?? createSignedOutAuth(),
|