@beignet/cli 0.0.9 → 0.0.10

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 (66) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +35 -19
  3. package/dist/choices.d.ts +32 -3
  4. package/dist/choices.d.ts.map +1 -1
  5. package/dist/choices.js +54 -3
  6. package/dist/choices.js.map +1 -1
  7. package/dist/create-prompts.d.ts +5 -4
  8. package/dist/create-prompts.d.ts.map +1 -1
  9. package/dist/create-prompts.js +22 -4
  10. package/dist/create-prompts.js.map +1 -1
  11. package/dist/create.d.ts +7 -1
  12. package/dist/create.d.ts.map +1 -1
  13. package/dist/create.js +13 -3
  14. package/dist/create.js.map +1 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +25 -6
  17. package/dist/index.js.map +1 -1
  18. package/dist/make.d.ts +21 -1
  19. package/dist/make.d.ts.map +1 -1
  20. package/dist/make.js +210 -37
  21. package/dist/make.js.map +1 -1
  22. package/dist/templates/base.d.ts.map +1 -1
  23. package/dist/templates/base.js +79 -9
  24. package/dist/templates/base.js.map +1 -1
  25. package/dist/templates/db/index.d.ts +21 -0
  26. package/dist/templates/db/index.d.ts.map +1 -0
  27. package/dist/templates/db/index.js +14 -0
  28. package/dist/templates/db/index.js.map +1 -0
  29. package/dist/templates/db/mysql.d.ts +4 -0
  30. package/dist/templates/db/mysql.d.ts.map +1 -0
  31. package/dist/templates/db/mysql.js +972 -0
  32. package/dist/templates/db/mysql.js.map +1 -0
  33. package/dist/templates/db/postgres.d.ts +4 -0
  34. package/dist/templates/db/postgres.d.ts.map +1 -0
  35. package/dist/templates/db/postgres.js +863 -0
  36. package/dist/templates/db/postgres.js.map +1 -0
  37. package/dist/templates/db/sqlite.d.ts +3 -0
  38. package/dist/templates/db/sqlite.d.ts.map +1 -0
  39. package/dist/templates/db/sqlite.js +878 -0
  40. package/dist/templates/db/sqlite.js.map +1 -0
  41. package/dist/templates/index.d.ts +5 -5
  42. package/dist/templates/index.d.ts.map +1 -1
  43. package/dist/templates/index.js +21 -20
  44. package/dist/templates/index.js.map +1 -1
  45. package/dist/templates/server.d.ts +3 -3
  46. package/dist/templates/server.d.ts.map +1 -1
  47. package/dist/templates/server.js +149 -97
  48. package/dist/templates/server.js.map +1 -1
  49. package/dist/templates/shared.d.ts +34 -1
  50. package/dist/templates/shared.d.ts.map +1 -1
  51. package/dist/templates/shared.js +45 -0
  52. package/dist/templates/shared.js.map +1 -1
  53. package/package.json +2 -2
  54. package/src/choices.ts +70 -3
  55. package/src/create-prompts.ts +25 -3
  56. package/src/create.ts +24 -2
  57. package/src/index.ts +29 -5
  58. package/src/make.ts +265 -34
  59. package/src/templates/base.ts +95 -9
  60. package/src/templates/db/index.ts +34 -0
  61. package/src/templates/db/mysql.ts +976 -0
  62. package/src/templates/db/postgres.ts +867 -0
  63. package/src/templates/{db.ts → db/sqlite.ts} +31 -152
  64. package/src/templates/index.ts +24 -19
  65. package/src/templates/server.ts +161 -97
  66. package/src/templates/shared.ts +90 -1
@@ -0,0 +1,972 @@
1
+ // The starter ships its initial Drizzle migration inside the template so the
2
+ // first run is `db migrate` with no generate step. `dbSchema` and the
3
+ // `starterMigration*` files below pair together — regenerate together.
4
+ //
5
+ // To regenerate: scaffold a scratch app with `dbSchema` as
6
+ // infra/db/schema/index.ts plus `drizzleConfig` as drizzle.config.ts, run
7
+ // `drizzle-kit generate --name starter` with the drizzle-kit version pinned in
8
+ // externalVersions (no MySQL server needed; generate diffs the schema against
9
+ // an empty snapshot), paste drizzle/0000_starter.sql,
10
+ // drizzle/meta/_journal.json, and drizzle/meta/0000_snapshot.json back here
11
+ // verbatim, then append the output of
12
+ // createDrizzleMysqlIdempotencySetupStatements() from
13
+ // @beignet/provider-db-drizzle/mysql to the migration SQL, separated by
14
+ // `--> statement-breakpoint`. The idempotency table is provider-owned and
15
+ // lives outside the app schema, so `db generate` never diffs against it.
16
+ //
17
+ // The Better Auth tables were generated with
18
+ // `bunx @better-auth/cli generate` against a scratch app configured with
19
+ // drizzleAdapter(db, { provider: "mysql" }), then normalized to the starter's
20
+ // conventions (tabs, no relations, no extra indexes, no column defaults).
21
+ // MySQL cannot put UNIQUE constraints on bare text columns, so identity
22
+ // columns are varchar: 36-char ids and foreign keys, 255-char unique email
23
+ // and token.
24
+ import { databaseLocalUrl, databaseStartCommand } from "../../choices.js";
25
+ export function mysqlDbFiles(ctx) {
26
+ return {
27
+ drizzleConfig: `export default {
28
+ schema: "./infra/db/schema/index.ts",
29
+ out: "./drizzle",
30
+ dialect: "mysql",
31
+ dbCredentials: {
32
+ url: process.env.MYSQL_DB_URL ?? "${databaseLocalUrl("mysql", ctx.name)}",
33
+ },
34
+ };
35
+ `,
36
+ dbSchema: `import {
37
+ boolean,
38
+ index,
39
+ mysqlTable,
40
+ text,
41
+ timestamp,
42
+ varchar,
43
+ } from "drizzle-orm/mysql-core";
44
+
45
+ export const user = mysqlTable("user", {
46
+ id: varchar("id", { length: 36 }).primaryKey(),
47
+ name: varchar("name", { length: 255 }).notNull(),
48
+ email: varchar("email", { length: 255 }).notNull().unique(),
49
+ emailVerified: boolean("email_verified").notNull().default(false),
50
+ image: text("image"),
51
+ createdAt: timestamp("created_at", { fsp: 3 }).notNull(),
52
+ updatedAt: timestamp("updated_at", { fsp: 3 }).notNull(),
53
+ });
54
+
55
+ export const session = mysqlTable("session", {
56
+ id: varchar("id", { length: 36 }).primaryKey(),
57
+ expiresAt: timestamp("expires_at", { fsp: 3 }).notNull(),
58
+ token: varchar("token", { length: 255 }).notNull().unique(),
59
+ createdAt: timestamp("created_at", { fsp: 3 }).notNull(),
60
+ updatedAt: timestamp("updated_at", { fsp: 3 }).notNull(),
61
+ ipAddress: text("ip_address"),
62
+ userAgent: text("user_agent"),
63
+ userId: varchar("user_id", { length: 36 })
64
+ .notNull()
65
+ .references(() => user.id, { onDelete: "cascade" }),
66
+ });
67
+
68
+ export const account = mysqlTable("account", {
69
+ id: varchar("id", { length: 36 }).primaryKey(),
70
+ accountId: text("account_id").notNull(),
71
+ providerId: text("provider_id").notNull(),
72
+ userId: varchar("user_id", { length: 36 })
73
+ .notNull()
74
+ .references(() => user.id, { onDelete: "cascade" }),
75
+ accessToken: text("access_token"),
76
+ refreshToken: text("refresh_token"),
77
+ idToken: text("id_token"),
78
+ accessTokenExpiresAt: timestamp("access_token_expires_at", { fsp: 3 }),
79
+ refreshTokenExpiresAt: timestamp("refresh_token_expires_at", { fsp: 3 }),
80
+ scope: text("scope"),
81
+ password: text("password"),
82
+ createdAt: timestamp("created_at", { fsp: 3 }).notNull(),
83
+ updatedAt: timestamp("updated_at", { fsp: 3 }).notNull(),
84
+ });
85
+
86
+ export const verification = mysqlTable("verification", {
87
+ id: varchar("id", { length: 36 }).primaryKey(),
88
+ identifier: varchar("identifier", { length: 255 }).notNull(),
89
+ value: text("value").notNull(),
90
+ expiresAt: timestamp("expires_at", { fsp: 3 }).notNull(),
91
+ createdAt: timestamp("created_at", { fsp: 3 }),
92
+ updatedAt: timestamp("updated_at", { fsp: 3 }),
93
+ });
94
+
95
+ export const todos = mysqlTable(
96
+ "todos",
97
+ {
98
+ id: varchar("id", { length: 36 }).primaryKey(),
99
+ userId: varchar("user_id", { length: 36 })
100
+ .notNull()
101
+ .references(() => user.id, { onDelete: "cascade" }),
102
+ title: text("title").notNull(),
103
+ completed: boolean("completed").notNull().default(false),
104
+ // Kept as an ISO-8601 varchar column on purpose: TodoSchema validates
105
+ // createdAt with z.string().datetime(), repositories pass rows through
106
+ // unmapped, and list ordering compares the strings lexicographically.
107
+ createdAt: varchar("created_at", { length: 32 }).notNull(),
108
+ },
109
+ (table) => ({
110
+ userIdx: index("todos_user_idx").on(table.userId, table.createdAt),
111
+ }),
112
+ );
113
+ `,
114
+ drizzleTodoRepository: `import type { beignetServerOnly } from "@beignet/core/server-only";
115
+ import { offsetPageResult } from "@beignet/core/pagination";
116
+ import type { DrizzleMysqlDatabase } from "@beignet/provider-db-drizzle/mysql";
117
+ import { count, desc, eq } from "drizzle-orm";
118
+ import type {
119
+ NewTodo,
120
+ TodoRepository,
121
+ UpdateTodoData,
122
+ } from "@/features/todos/ports";
123
+ import type { Todo } from "@/features/todos/schemas";
124
+ import * as schema from "@/infra/db/schema";
125
+
126
+ type TodoRow = typeof schema.todos.$inferSelect;
127
+
128
+ function toTodo(row: TodoRow): Todo {
129
+ return {
130
+ id: row.id,
131
+ userId: row.userId,
132
+ title: row.title,
133
+ completed: row.completed,
134
+ createdAt: row.createdAt,
135
+ };
136
+ }
137
+
138
+ export function createDrizzleTodoRepository(
139
+ db: DrizzleMysqlDatabase<typeof schema>,
140
+ ): TodoRepository {
141
+ return {
142
+ async list(userId, page) {
143
+ const rows = await db
144
+ .select()
145
+ .from(schema.todos)
146
+ .where(eq(schema.todos.userId, userId))
147
+ .orderBy(desc(schema.todos.createdAt))
148
+ .limit(page.limit)
149
+ .offset(page.offset);
150
+ const [{ total }] = await db
151
+ .select({ total: count() })
152
+ .from(schema.todos)
153
+ .where(eq(schema.todos.userId, userId));
154
+
155
+ return offsetPageResult(rows.map(toTodo), page, total);
156
+ },
157
+ async findById(id: string) {
158
+ const [row] = await db
159
+ .select()
160
+ .from(schema.todos)
161
+ .where(eq(schema.todos.id, id))
162
+ .limit(1);
163
+
164
+ return row ? toTodo(row) : null;
165
+ },
166
+ async create(input: NewTodo) {
167
+ // MySQL has no INSERT ... RETURNING; the full row is known up front.
168
+ const todo = {
169
+ id: crypto.randomUUID(),
170
+ userId: input.userId,
171
+ title: input.title,
172
+ completed: false,
173
+ createdAt: new Date().toISOString(),
174
+ };
175
+ await db.insert(schema.todos).values(todo);
176
+
177
+ return todo;
178
+ },
179
+ async update(id: string, input: UpdateTodoData) {
180
+ // MySQL has no UPDATE ... RETURNING; re-read the row after writing.
181
+ await db
182
+ .update(schema.todos)
183
+ .set({ completed: input.completed })
184
+ .where(eq(schema.todos.id, id));
185
+ const [row] = await db
186
+ .select()
187
+ .from(schema.todos)
188
+ .where(eq(schema.todos.id, id))
189
+ .limit(1);
190
+
191
+ if (!row) {
192
+ throw new Error(\`Failed to update todo \${id}\`);
193
+ }
194
+
195
+ return toTodo(row);
196
+ },
197
+ async delete(id: string) {
198
+ await db.delete(schema.todos).where(eq(schema.todos.id, id));
199
+ },
200
+ };
201
+ }
202
+ `,
203
+ dbRepositories: `import type { DrizzleMysqlDatabase } from "@beignet/provider-db-drizzle/mysql";
204
+ import { createDrizzleTodoRepository } from "@/infra/todos/drizzle-todo-repository";
205
+ import type { AppTransactionPorts } from "@/ports";
206
+ import * as schema from "./schema";
207
+
208
+ export function createRepositories(
209
+ db: DrizzleMysqlDatabase<typeof schema>,
210
+ ): Omit<AppTransactionPorts, "idempotency"> {
211
+ return {
212
+ todos: createDrizzleTodoRepository(db),
213
+ };
214
+ }
215
+ `,
216
+ databaseReady: `import { drizzle } from "drizzle-orm/mysql2";
217
+ import { migrate } from "drizzle-orm/mysql2/migrator";
218
+ import type { Pool, RowDataPacket } from "mysql2/promise";
219
+
220
+ let ready: Promise<void> | undefined;
221
+
222
+ /**
223
+ * Make sure the database is usable before the first query runs.
224
+ *
225
+ * In development, pending migrations from \`drizzle/\` are applied
226
+ * automatically so a fresh clone works without remembering
227
+ * \`beignet db migrate\`. In production the schema is never mutated;
228
+ * an unmigrated database fails loudly with the command to run.
229
+ *
230
+ * Memoized per process so Next.js page-data workers that reach this in
231
+ * parallel share one preparation pass.
232
+ */
233
+ export function ensureDatabaseReady(pool: Pool): Promise<void> {
234
+ ready ??= prepare(pool);
235
+ return ready;
236
+ }
237
+
238
+ async function prepare(pool: Pool): Promise<void> {
239
+ if (process.env.NODE_ENV === "production") {
240
+ const [tables] = await pool.query<RowDataPacket[]>(
241
+ "SELECT table_name FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'user' LIMIT 1",
242
+ );
243
+ if (tables.length === 0) {
244
+ throw new Error(
245
+ "Database has no tables yet. Run \`beignet db migrate\` against this database before starting the app.",
246
+ );
247
+ }
248
+ return;
249
+ }
250
+
251
+ await migrate(drizzle(pool), { migrationsFolder: "drizzle" });
252
+ }
253
+ `,
254
+ dbProvider: `import type { beignetServerOnly } from "@beignet/core/server-only";
255
+ import { createProvider } from "@beignet/core/providers";
256
+ import {
257
+ createDrizzleMysqlIdempotencyPort,
258
+ createDrizzleMysqlUnitOfWork,
259
+ type DbPort,
260
+ } from "@beignet/provider-db-drizzle/mysql";
261
+ import type { AppPorts } from "@/ports";
262
+ import { ensureDatabaseReady } from "./database-ready";
263
+ import { createRepositories } from "./repositories";
264
+ import type * as schema from "./schema";
265
+
266
+ export const starterDatabaseProvider = createProvider<{
267
+ db: DbPort<typeof schema>;
268
+ }>()({
269
+ name: "starter-database",
270
+
271
+ async setup({ ports }) {
272
+ const dbPort = ports.db;
273
+ if (!dbPort) {
274
+ throw new Error(
275
+ "starterDatabaseProvider requires a db port. Register createDrizzleMysqlProvider({ schema }) before it.",
276
+ );
277
+ }
278
+
279
+ const repositories = createRepositories(dbPort.db);
280
+ const idempotency = createDrizzleMysqlIdempotencyPort(dbPort.db);
281
+
282
+ const providedPorts: Pick<AppPorts, "idempotency" | "todos" | "uow"> = {
283
+ ...repositories,
284
+ idempotency,
285
+ uow: createDrizzleMysqlUnitOfWork({
286
+ db: dbPort.db,
287
+ createTransactionPorts: (tx) => ({
288
+ ...createRepositories(tx),
289
+ idempotency: createDrizzleMysqlIdempotencyPort(tx),
290
+ }),
291
+ }),
292
+ };
293
+
294
+ return {
295
+ ports: providedPorts,
296
+ async start() {
297
+ await ensureDatabaseReady(dbPort.pool);
298
+ },
299
+ };
300
+ },
301
+ });
302
+ `,
303
+ dbReset: `import { drizzle } from "drizzle-orm/mysql2";
304
+ import { migrate } from "drizzle-orm/mysql2/migrator";
305
+ import mysql from "mysql2/promise";
306
+ import { env } from "@/lib/env";
307
+
308
+ const host = new URL(env.MYSQL_DB_URL).hostname;
309
+ if (
310
+ host !== "localhost" &&
311
+ host !== "127.0.0.1" &&
312
+ process.env.BEIGNET_ALLOW_DATABASE_RESET !== "true"
313
+ ) {
314
+ throw new Error(
315
+ "Refusing to reset a non-local database. Set BEIGNET_ALLOW_DATABASE_RESET=true if this is intentional.",
316
+ );
317
+ }
318
+
319
+ const tables = [
320
+ "verification",
321
+ "account",
322
+ "session",
323
+ "todos",
324
+ "user",
325
+ "idempotency_records",
326
+ "__drizzle_migrations",
327
+ ] as const;
328
+
329
+ const pool = mysql.createPool({ uri: env.MYSQL_DB_URL });
330
+
331
+ try {
332
+ await pool.query("SET FOREIGN_KEY_CHECKS = 0");
333
+ try {
334
+ for (const table of tables) {
335
+ await pool.query(\`DROP TABLE IF EXISTS \\\`\${table}\\\`\`);
336
+ }
337
+ } finally {
338
+ await pool.query("SET FOREIGN_KEY_CHECKS = 1");
339
+ }
340
+
341
+ await migrate(drizzle(pool), { migrationsFolder: "drizzle" });
342
+ console.log("Database reset.");
343
+ } finally {
344
+ await pool.end();
345
+ }
346
+ `,
347
+ dbTestDatabase: `import { drizzle, type MySql2Database } from "drizzle-orm/mysql2";
348
+ import { migrate } from "drizzle-orm/mysql2/migrator";
349
+ import mysql, { type Pool } from "mysql2/promise";
350
+ import { createRepositories } from "./repositories";
351
+ import * as schema from "./schema";
352
+
353
+ // Set MYSQL_TEST_URL to run database-backed tests against a real MySQL 8.0+
354
+ // server. The starter's shipped tests use in-memory ports and do not need it.
355
+ const MYSQL_TEST_URL = process.env.MYSQL_TEST_URL;
356
+
357
+ /**
358
+ * Whether database-backed tests can run. Pair with \`test.skipIf\`:
359
+ *
360
+ * \`\`\`ts
361
+ * test.skipIf(!isMysqlTestDatabaseAvailable())("...", async () => { ... });
362
+ * \`\`\`
363
+ */
364
+ export function isMysqlTestDatabaseAvailable(): boolean {
365
+ return Boolean(MYSQL_TEST_URL);
366
+ }
367
+
368
+ export type TestDatabase = {
369
+ pool: Pool;
370
+ db: MySql2Database<typeof schema>;
371
+ repositories: ReturnType<typeof createRepositories>;
372
+ databaseName: string;
373
+ close(): Promise<void>;
374
+ };
375
+
376
+ /**
377
+ * Create an isolated test database on the MYSQL_TEST_URL server.
378
+ *
379
+ * Each call creates a uniquely named database, applies the checked-in
380
+ * migrations into it, and drops it again on close, so parallel tests never
381
+ * share state.
382
+ */
383
+ export async function createTestDatabase(): Promise<TestDatabase> {
384
+ if (!MYSQL_TEST_URL) {
385
+ throw new Error(
386
+ "MYSQL_TEST_URL is not set. Start MySQL with: " +
387
+ "${databaseStartCommand("mysql", ctx.name)} " +
388
+ "then run tests with MYSQL_TEST_URL=${databaseLocalUrl("mysql", ctx.name)}.",
389
+ );
390
+ }
391
+
392
+ const databaseName = \`beignet_test_\${crypto
393
+ .randomUUID()
394
+ .replaceAll("-", "")
395
+ .slice(0, 12)}\`;
396
+
397
+ const bootstrap = await mysql.createConnection({ uri: MYSQL_TEST_URL });
398
+ try {
399
+ await bootstrap.query(\`CREATE DATABASE \\\`\${databaseName}\\\`\`);
400
+ } finally {
401
+ await bootstrap.end();
402
+ }
403
+
404
+ const url = new URL(MYSQL_TEST_URL);
405
+ url.pathname = \`/\${databaseName}\`;
406
+ const pool = mysql.createPool({ uri: url.toString() });
407
+ const db = drizzle(pool, { schema, mode: "default" });
408
+ await migrate(db, { migrationsFolder: "drizzle" });
409
+
410
+ return {
411
+ pool,
412
+ db,
413
+ repositories: createRepositories(db),
414
+ databaseName,
415
+ close: async () => {
416
+ await pool.end();
417
+ const cleanup = await mysql.createConnection({ uri: MYSQL_TEST_URL });
418
+ try {
419
+ await cleanup.query(\`DROP DATABASE IF EXISTS \\\`\${databaseName}\\\`\`);
420
+ } finally {
421
+ await cleanup.end();
422
+ }
423
+ },
424
+ };
425
+ }
426
+ `,
427
+ ...mysqlStarterMigration,
428
+ };
429
+ }
430
+ const mysqlStarterMigration = {
431
+ // Generated by drizzle-kit generate --name starter against dbSchema
432
+ // above, with the provider idempotency setup statements appended.
433
+ starterMigrationSql: `CREATE TABLE \`account\` (
434
+ \`id\` varchar(36) NOT NULL,
435
+ \`account_id\` text NOT NULL,
436
+ \`provider_id\` text NOT NULL,
437
+ \`user_id\` varchar(36) NOT NULL,
438
+ \`access_token\` text,
439
+ \`refresh_token\` text,
440
+ \`id_token\` text,
441
+ \`access_token_expires_at\` timestamp(3),
442
+ \`refresh_token_expires_at\` timestamp(3),
443
+ \`scope\` text,
444
+ \`password\` text,
445
+ \`created_at\` timestamp(3) NOT NULL,
446
+ \`updated_at\` timestamp(3) NOT NULL,
447
+ CONSTRAINT \`account_id\` PRIMARY KEY(\`id\`)
448
+ );
449
+ --> statement-breakpoint
450
+ CREATE TABLE \`session\` (
451
+ \`id\` varchar(36) NOT NULL,
452
+ \`expires_at\` timestamp(3) NOT NULL,
453
+ \`token\` varchar(255) NOT NULL,
454
+ \`created_at\` timestamp(3) NOT NULL,
455
+ \`updated_at\` timestamp(3) NOT NULL,
456
+ \`ip_address\` text,
457
+ \`user_agent\` text,
458
+ \`user_id\` varchar(36) NOT NULL,
459
+ CONSTRAINT \`session_id\` PRIMARY KEY(\`id\`),
460
+ CONSTRAINT \`session_token_unique\` UNIQUE(\`token\`)
461
+ );
462
+ --> statement-breakpoint
463
+ CREATE TABLE \`todos\` (
464
+ \`id\` varchar(36) NOT NULL,
465
+ \`user_id\` varchar(36) NOT NULL,
466
+ \`title\` text NOT NULL,
467
+ \`completed\` boolean NOT NULL DEFAULT false,
468
+ \`created_at\` varchar(32) NOT NULL,
469
+ CONSTRAINT \`todos_id\` PRIMARY KEY(\`id\`)
470
+ );
471
+ --> statement-breakpoint
472
+ CREATE TABLE \`user\` (
473
+ \`id\` varchar(36) NOT NULL,
474
+ \`name\` varchar(255) NOT NULL,
475
+ \`email\` varchar(255) NOT NULL,
476
+ \`email_verified\` boolean NOT NULL DEFAULT false,
477
+ \`image\` text,
478
+ \`created_at\` timestamp(3) NOT NULL,
479
+ \`updated_at\` timestamp(3) NOT NULL,
480
+ CONSTRAINT \`user_id\` PRIMARY KEY(\`id\`),
481
+ CONSTRAINT \`user_email_unique\` UNIQUE(\`email\`)
482
+ );
483
+ --> statement-breakpoint
484
+ CREATE TABLE \`verification\` (
485
+ \`id\` varchar(36) NOT NULL,
486
+ \`identifier\` varchar(255) NOT NULL,
487
+ \`value\` text NOT NULL,
488
+ \`expires_at\` timestamp(3) NOT NULL,
489
+ \`created_at\` timestamp(3),
490
+ \`updated_at\` timestamp(3),
491
+ CONSTRAINT \`verification_id\` PRIMARY KEY(\`id\`)
492
+ );
493
+ --> statement-breakpoint
494
+ ALTER TABLE \`account\` ADD CONSTRAINT \`account_user_id_user_id_fk\` FOREIGN KEY (\`user_id\`) REFERENCES \`user\`(\`id\`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
495
+ ALTER TABLE \`session\` ADD CONSTRAINT \`session_user_id_user_id_fk\` FOREIGN KEY (\`user_id\`) REFERENCES \`user\`(\`id\`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
496
+ ALTER TABLE \`todos\` ADD CONSTRAINT \`todos_user_id_user_id_fk\` FOREIGN KEY (\`user_id\`) REFERENCES \`user\`(\`id\`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
497
+ CREATE INDEX \`todos_user_idx\` ON \`todos\` (\`user_id\`,\`created_at\`);
498
+ --> statement-breakpoint
499
+ CREATE TABLE IF NOT EXISTS \`idempotency_records\` (
500
+ storage_key varchar(512) NOT NULL PRIMARY KEY,
501
+ namespace varchar(255) NOT NULL,
502
+ idempotency_key varchar(255) NOT NULL,
503
+ scope_key varchar(255) NOT NULL,
504
+ fingerprint varchar(255) NOT NULL,
505
+ status varchar(16) NOT NULL,
506
+ result_json longtext,
507
+ reserved_at varchar(32) NOT NULL,
508
+ completed_at varchar(32),
509
+ expires_at varchar(32),
510
+ updated_at varchar(32) NOT NULL,
511
+ INDEX \`idempotency_records_lookup_idx\` (namespace, scope_key, idempotency_key),
512
+ INDEX \`idempotency_records_expires_idx\` (expires_at)
513
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;
514
+ `,
515
+ starterMigrationJournal: `{
516
+ "version": "7",
517
+ "dialect": "mysql",
518
+ "entries": [
519
+ {
520
+ "idx": 0,
521
+ "version": "5",
522
+ "when": 1781285557496,
523
+ "tag": "0000_starter",
524
+ "breakpoints": true
525
+ }
526
+ ]
527
+ }`,
528
+ starterMigrationSnapshot: `{
529
+ "version": "5",
530
+ "dialect": "mysql",
531
+ "id": "597ed4cf-be53-41d9-9c60-d53032e7ca3f",
532
+ "prevId": "00000000-0000-0000-0000-000000000000",
533
+ "tables": {
534
+ "account": {
535
+ "name": "account",
536
+ "columns": {
537
+ "id": {
538
+ "name": "id",
539
+ "type": "varchar(36)",
540
+ "primaryKey": false,
541
+ "notNull": true,
542
+ "autoincrement": false
543
+ },
544
+ "account_id": {
545
+ "name": "account_id",
546
+ "type": "text",
547
+ "primaryKey": false,
548
+ "notNull": true,
549
+ "autoincrement": false
550
+ },
551
+ "provider_id": {
552
+ "name": "provider_id",
553
+ "type": "text",
554
+ "primaryKey": false,
555
+ "notNull": true,
556
+ "autoincrement": false
557
+ },
558
+ "user_id": {
559
+ "name": "user_id",
560
+ "type": "varchar(36)",
561
+ "primaryKey": false,
562
+ "notNull": true,
563
+ "autoincrement": false
564
+ },
565
+ "access_token": {
566
+ "name": "access_token",
567
+ "type": "text",
568
+ "primaryKey": false,
569
+ "notNull": false,
570
+ "autoincrement": false
571
+ },
572
+ "refresh_token": {
573
+ "name": "refresh_token",
574
+ "type": "text",
575
+ "primaryKey": false,
576
+ "notNull": false,
577
+ "autoincrement": false
578
+ },
579
+ "id_token": {
580
+ "name": "id_token",
581
+ "type": "text",
582
+ "primaryKey": false,
583
+ "notNull": false,
584
+ "autoincrement": false
585
+ },
586
+ "access_token_expires_at": {
587
+ "name": "access_token_expires_at",
588
+ "type": "timestamp(3)",
589
+ "primaryKey": false,
590
+ "notNull": false,
591
+ "autoincrement": false
592
+ },
593
+ "refresh_token_expires_at": {
594
+ "name": "refresh_token_expires_at",
595
+ "type": "timestamp(3)",
596
+ "primaryKey": false,
597
+ "notNull": false,
598
+ "autoincrement": false
599
+ },
600
+ "scope": {
601
+ "name": "scope",
602
+ "type": "text",
603
+ "primaryKey": false,
604
+ "notNull": false,
605
+ "autoincrement": false
606
+ },
607
+ "password": {
608
+ "name": "password",
609
+ "type": "text",
610
+ "primaryKey": false,
611
+ "notNull": false,
612
+ "autoincrement": false
613
+ },
614
+ "created_at": {
615
+ "name": "created_at",
616
+ "type": "timestamp(3)",
617
+ "primaryKey": false,
618
+ "notNull": true,
619
+ "autoincrement": false
620
+ },
621
+ "updated_at": {
622
+ "name": "updated_at",
623
+ "type": "timestamp(3)",
624
+ "primaryKey": false,
625
+ "notNull": true,
626
+ "autoincrement": false
627
+ }
628
+ },
629
+ "indexes": {},
630
+ "foreignKeys": {
631
+ "account_user_id_user_id_fk": {
632
+ "name": "account_user_id_user_id_fk",
633
+ "tableFrom": "account",
634
+ "tableTo": "user",
635
+ "columnsFrom": [
636
+ "user_id"
637
+ ],
638
+ "columnsTo": [
639
+ "id"
640
+ ],
641
+ "onDelete": "cascade",
642
+ "onUpdate": "no action"
643
+ }
644
+ },
645
+ "compositePrimaryKeys": {
646
+ "account_id": {
647
+ "name": "account_id",
648
+ "columns": [
649
+ "id"
650
+ ]
651
+ }
652
+ },
653
+ "uniqueConstraints": {},
654
+ "checkConstraint": {}
655
+ },
656
+ "session": {
657
+ "name": "session",
658
+ "columns": {
659
+ "id": {
660
+ "name": "id",
661
+ "type": "varchar(36)",
662
+ "primaryKey": false,
663
+ "notNull": true,
664
+ "autoincrement": false
665
+ },
666
+ "expires_at": {
667
+ "name": "expires_at",
668
+ "type": "timestamp(3)",
669
+ "primaryKey": false,
670
+ "notNull": true,
671
+ "autoincrement": false
672
+ },
673
+ "token": {
674
+ "name": "token",
675
+ "type": "varchar(255)",
676
+ "primaryKey": false,
677
+ "notNull": true,
678
+ "autoincrement": false
679
+ },
680
+ "created_at": {
681
+ "name": "created_at",
682
+ "type": "timestamp(3)",
683
+ "primaryKey": false,
684
+ "notNull": true,
685
+ "autoincrement": false
686
+ },
687
+ "updated_at": {
688
+ "name": "updated_at",
689
+ "type": "timestamp(3)",
690
+ "primaryKey": false,
691
+ "notNull": true,
692
+ "autoincrement": false
693
+ },
694
+ "ip_address": {
695
+ "name": "ip_address",
696
+ "type": "text",
697
+ "primaryKey": false,
698
+ "notNull": false,
699
+ "autoincrement": false
700
+ },
701
+ "user_agent": {
702
+ "name": "user_agent",
703
+ "type": "text",
704
+ "primaryKey": false,
705
+ "notNull": false,
706
+ "autoincrement": false
707
+ },
708
+ "user_id": {
709
+ "name": "user_id",
710
+ "type": "varchar(36)",
711
+ "primaryKey": false,
712
+ "notNull": true,
713
+ "autoincrement": false
714
+ }
715
+ },
716
+ "indexes": {},
717
+ "foreignKeys": {
718
+ "session_user_id_user_id_fk": {
719
+ "name": "session_user_id_user_id_fk",
720
+ "tableFrom": "session",
721
+ "tableTo": "user",
722
+ "columnsFrom": [
723
+ "user_id"
724
+ ],
725
+ "columnsTo": [
726
+ "id"
727
+ ],
728
+ "onDelete": "cascade",
729
+ "onUpdate": "no action"
730
+ }
731
+ },
732
+ "compositePrimaryKeys": {
733
+ "session_id": {
734
+ "name": "session_id",
735
+ "columns": [
736
+ "id"
737
+ ]
738
+ }
739
+ },
740
+ "uniqueConstraints": {
741
+ "session_token_unique": {
742
+ "name": "session_token_unique",
743
+ "columns": [
744
+ "token"
745
+ ]
746
+ }
747
+ },
748
+ "checkConstraint": {}
749
+ },
750
+ "todos": {
751
+ "name": "todos",
752
+ "columns": {
753
+ "id": {
754
+ "name": "id",
755
+ "type": "varchar(36)",
756
+ "primaryKey": false,
757
+ "notNull": true,
758
+ "autoincrement": false
759
+ },
760
+ "user_id": {
761
+ "name": "user_id",
762
+ "type": "varchar(36)",
763
+ "primaryKey": false,
764
+ "notNull": true,
765
+ "autoincrement": false
766
+ },
767
+ "title": {
768
+ "name": "title",
769
+ "type": "text",
770
+ "primaryKey": false,
771
+ "notNull": true,
772
+ "autoincrement": false
773
+ },
774
+ "completed": {
775
+ "name": "completed",
776
+ "type": "boolean",
777
+ "primaryKey": false,
778
+ "notNull": true,
779
+ "autoincrement": false,
780
+ "default": false
781
+ },
782
+ "created_at": {
783
+ "name": "created_at",
784
+ "type": "varchar(32)",
785
+ "primaryKey": false,
786
+ "notNull": true,
787
+ "autoincrement": false
788
+ }
789
+ },
790
+ "indexes": {
791
+ "todos_user_idx": {
792
+ "name": "todos_user_idx",
793
+ "columns": [
794
+ "user_id",
795
+ "created_at"
796
+ ],
797
+ "isUnique": false
798
+ }
799
+ },
800
+ "foreignKeys": {
801
+ "todos_user_id_user_id_fk": {
802
+ "name": "todos_user_id_user_id_fk",
803
+ "tableFrom": "todos",
804
+ "tableTo": "user",
805
+ "columnsFrom": [
806
+ "user_id"
807
+ ],
808
+ "columnsTo": [
809
+ "id"
810
+ ],
811
+ "onDelete": "cascade",
812
+ "onUpdate": "no action"
813
+ }
814
+ },
815
+ "compositePrimaryKeys": {
816
+ "todos_id": {
817
+ "name": "todos_id",
818
+ "columns": [
819
+ "id"
820
+ ]
821
+ }
822
+ },
823
+ "uniqueConstraints": {},
824
+ "checkConstraint": {}
825
+ },
826
+ "user": {
827
+ "name": "user",
828
+ "columns": {
829
+ "id": {
830
+ "name": "id",
831
+ "type": "varchar(36)",
832
+ "primaryKey": false,
833
+ "notNull": true,
834
+ "autoincrement": false
835
+ },
836
+ "name": {
837
+ "name": "name",
838
+ "type": "varchar(255)",
839
+ "primaryKey": false,
840
+ "notNull": true,
841
+ "autoincrement": false
842
+ },
843
+ "email": {
844
+ "name": "email",
845
+ "type": "varchar(255)",
846
+ "primaryKey": false,
847
+ "notNull": true,
848
+ "autoincrement": false
849
+ },
850
+ "email_verified": {
851
+ "name": "email_verified",
852
+ "type": "boolean",
853
+ "primaryKey": false,
854
+ "notNull": true,
855
+ "autoincrement": false,
856
+ "default": false
857
+ },
858
+ "image": {
859
+ "name": "image",
860
+ "type": "text",
861
+ "primaryKey": false,
862
+ "notNull": false,
863
+ "autoincrement": false
864
+ },
865
+ "created_at": {
866
+ "name": "created_at",
867
+ "type": "timestamp(3)",
868
+ "primaryKey": false,
869
+ "notNull": true,
870
+ "autoincrement": false
871
+ },
872
+ "updated_at": {
873
+ "name": "updated_at",
874
+ "type": "timestamp(3)",
875
+ "primaryKey": false,
876
+ "notNull": true,
877
+ "autoincrement": false
878
+ }
879
+ },
880
+ "indexes": {},
881
+ "foreignKeys": {},
882
+ "compositePrimaryKeys": {
883
+ "user_id": {
884
+ "name": "user_id",
885
+ "columns": [
886
+ "id"
887
+ ]
888
+ }
889
+ },
890
+ "uniqueConstraints": {
891
+ "user_email_unique": {
892
+ "name": "user_email_unique",
893
+ "columns": [
894
+ "email"
895
+ ]
896
+ }
897
+ },
898
+ "checkConstraint": {}
899
+ },
900
+ "verification": {
901
+ "name": "verification",
902
+ "columns": {
903
+ "id": {
904
+ "name": "id",
905
+ "type": "varchar(36)",
906
+ "primaryKey": false,
907
+ "notNull": true,
908
+ "autoincrement": false
909
+ },
910
+ "identifier": {
911
+ "name": "identifier",
912
+ "type": "varchar(255)",
913
+ "primaryKey": false,
914
+ "notNull": true,
915
+ "autoincrement": false
916
+ },
917
+ "value": {
918
+ "name": "value",
919
+ "type": "text",
920
+ "primaryKey": false,
921
+ "notNull": true,
922
+ "autoincrement": false
923
+ },
924
+ "expires_at": {
925
+ "name": "expires_at",
926
+ "type": "timestamp(3)",
927
+ "primaryKey": false,
928
+ "notNull": true,
929
+ "autoincrement": false
930
+ },
931
+ "created_at": {
932
+ "name": "created_at",
933
+ "type": "timestamp(3)",
934
+ "primaryKey": false,
935
+ "notNull": false,
936
+ "autoincrement": false
937
+ },
938
+ "updated_at": {
939
+ "name": "updated_at",
940
+ "type": "timestamp(3)",
941
+ "primaryKey": false,
942
+ "notNull": false,
943
+ "autoincrement": false
944
+ }
945
+ },
946
+ "indexes": {},
947
+ "foreignKeys": {},
948
+ "compositePrimaryKeys": {
949
+ "verification_id": {
950
+ "name": "verification_id",
951
+ "columns": [
952
+ "id"
953
+ ]
954
+ }
955
+ },
956
+ "uniqueConstraints": {},
957
+ "checkConstraint": {}
958
+ }
959
+ },
960
+ "views": {},
961
+ "_meta": {
962
+ "schemas": {},
963
+ "tables": {},
964
+ "columns": {}
965
+ },
966
+ "internal": {
967
+ "tables": {},
968
+ "indexes": {}
969
+ }
970
+ }`,
971
+ };
972
+ //# sourceMappingURL=mysql.js.map