UNPKG

@clickup/pg-mig

Version:

PostgreSQL schema migration tool with microsharding and clustering support

92 lines (78 loc) 2.56 kB
import { writeFileSync } from "fs"; import { join } from "path"; import compact from "lodash/compact"; import max from "lodash/max"; import moment from "moment"; import type { MigrateOptions } from "../cli"; import { Registry } from "../internal/Registry"; import { printError, printText } from "../internal/render"; import { actionChain } from "./actionChain"; /** * Makes new migration files. */ export async function actionMake( options: Exclude<MigrateOptions, "action">, registry: Registry, name: string, ): Promise<boolean> { const [migrationName, schemaPrefix] = name.split("@"); const usage = "Format: --make=migration_name@schema_prefix"; if (!migrationName?.match(/^[-a-z0-9_]+$/)) { printError( "migration_name is missing or includes incorrect characters (snake_case required)", ); printText(usage); return false; } if (!schemaPrefix) { printError("schema_prefix is missing"); printText(usage); return false; } if (!registry.getPrefixes().includes(schemaPrefix)) { printText( `WARNING: schema prefix "${schemaPrefix}" wasn't found. Valid prefixes:`, ); for (const prefix of registry.getPrefixes()) { printText(`- ${prefix}`); } } printText("Making migration files..."); const createdFiles = await makeMigration( options.migDir, migrationName, schemaPrefix, max(compact(registry.getVersions().map((v) => v.match(/^(\d+)\./)?.[1]))) ?? null, ); registry = new Registry(registry.dir); await actionChain(options, registry); printText("Created files:"); for (const file of createdFiles) { printText(file); } return true; } async function makeMigration( migrationDir: string, migrationName: string, schemaPrefix: string, maxUtcTimestamp: string | null, ): Promise<string[]> { let utcTimestamp = moment(Date.now()).utc().format("YYYYMMDDHHmmss"); // In case we have skewed timestamp in the existing versions (like 20251424: // there is no month 14), we just add one minute to the last version timestamp // instead of using the current time. if (maxUtcTimestamp && utcTimestamp <= maxUtcTimestamp) { utcTimestamp = String(Number(maxUtcTimestamp) + 60); } const migrationFilenameBase = `${utcTimestamp}.${migrationName}.${schemaPrefix}`; const migrationFiles = [ `${migrationFilenameBase}.up.sql`, `${migrationFilenameBase}.dn.sql`, ].map((f) => join(migrationDir, f)); for (const f of migrationFiles) { writeFileSync(f, "", { mode: 0o644 }); } return migrationFiles; }