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