SPB Git forge

spb/websensor

Public
33commits 1branches 0releases
3.4 MBsize
maindefault branch
11 days agolast push
TypeScript 55.4% Python 43.2% SQL 1.2%
1.8 KB · 51 lines typescript
Raw Blame History
1import { readdirSync, readFileSync } from "node:fs";2import { dirname, join } from "node:path";3import { fileURLToPath } from "node:url";4import pg from "pg";56/** Plain-SQL forward migrations tracked in `schema_migrations`. Idempotent. */7export async function migrate(databaseUrl = process.env.DATABASE_URL ?? "postgres://localhost:5432/websensor"): Promise<string[]> {8  const here = dirname(fileURLToPath(import.meta.url));9  const dir = join(here, "..", "migrations");10  const files = readdirSync(dir)11    .filter((f) => f.endsWith(".sql"))12    .sort();13  const client = new pg.Client({ connectionString: databaseUrl });14  await client.connect();15  const applied: string[] = [];16  try {17    await client.query("create table if not exists schema_migrations (name text primary key, applied_at timestamptz not null default now())");18    await client.query("select pg_advisory_lock(7245)");19    const done = new Set((await client.query<{ name: string }>("select name from schema_migrations")).rows.map((r) => r.name));20    for (const f of files) {21      if (done.has(f)) continue;22      const sql = readFileSync(join(dir, f), "utf8");23      await client.query("begin");24      try {25        await client.query(sql);26        await client.query("insert into schema_migrations (name) values ($1)", [f]);27        await client.query("commit");28        applied.push(f);29      } catch (e) {30        await client.query("rollback");31        throw e;32      }33    }34    await client.query("select pg_advisory_unlock(7245)");35  } finally {36    await client.end();37  }38  return applied;39}4041if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {42  migrate()43    .then((a) => {44      console.log(a.length ? `applied: ${a.join(", ")}` : "schema up to date");45    })46    .catch((e) => {47      console.error(e);48      process.exit(1);49    });50}51