Initial commit
This commit is contained in:
23
packages/db/src/index.ts
Normal file
23
packages/db/src/index.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import postgres, { type Sql } from "postgres";
|
||||
import { z } from "zod";
|
||||
|
||||
const envSchema = z.object({
|
||||
DATABASE_URL: z.string().min(1)
|
||||
});
|
||||
|
||||
let cachedDb: Sql | undefined;
|
||||
|
||||
export function getDb() {
|
||||
if (cachedDb) return cachedDb;
|
||||
|
||||
const env = envSchema.parse(process.env);
|
||||
cachedDb = postgres(env.DATABASE_URL);
|
||||
return cachedDb;
|
||||
}
|
||||
|
||||
export async function closeDb() {
|
||||
if (!cachedDb) return;
|
||||
const db = cachedDb;
|
||||
cachedDb = undefined;
|
||||
await db.end({ timeout: 5 });
|
||||
}
|
||||
43
packages/db/src/migrate.ts
Normal file
43
packages/db/src/migrate.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { readdir } from "node:fs/promises";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import postgres from "postgres";
|
||||
import { z } from "zod";
|
||||
|
||||
const envSchema = z.object({
|
||||
DATABASE_URL: z.string().min(1)
|
||||
});
|
||||
|
||||
async function main() {
|
||||
const env = envSchema.parse(process.env);
|
||||
const sql = postgres(env.DATABASE_URL, { max: 1 });
|
||||
|
||||
try {
|
||||
await sql`CREATE TABLE IF NOT EXISTS schema_migrations (id text primary key, applied_at timestamptz not null default now())`;
|
||||
|
||||
const migrationsDir = path.join(import.meta.dir, "..", "migrations");
|
||||
const files = (await readdir(migrationsDir)).filter((f) => f.endsWith(".sql")).sort();
|
||||
|
||||
for (const file of files) {
|
||||
const already = await sql<{ id: string }[]>`SELECT id FROM schema_migrations WHERE id = ${file}`;
|
||||
if (already.length > 0) continue;
|
||||
|
||||
const contents = await readFile(path.join(migrationsDir, file), "utf8");
|
||||
await sql.begin(async (tx) => {
|
||||
await tx.unsafe(contents);
|
||||
await tx`INSERT INTO schema_migrations (id) VALUES (${file})`;
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Applied migration ${file}`);
|
||||
}
|
||||
} finally {
|
||||
await sql.end({ timeout: 5 });
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
Reference in New Issue
Block a user