* Exports database data to a backup file.
(options?: {
env?: string;
schema?: string;
args?: string[];
})
| 316 | * Exports database data to a backup file. |
| 317 | */ |
| 318 | async function backup(options?: { |
| 319 | env?: string; |
| 320 | schema?: string; |
| 321 | args?: string[]; |
| 322 | }) { |
| 323 | const schema = options?.schema ?? "public"; |
| 324 | const db = getDatabase(options); |
| 325 | |
| 326 | const tables = await db |
| 327 | .from("information_schema.tables") |
| 328 | .where({ |
| 329 | table_schema: options?.schema ?? "public", |
| 330 | table_type: "BASE TABLE", |
| 331 | }) |
| 332 | .andWhereNot({ table_name: "migration" }) |
| 333 | .andWhereNot({ table_name: "migration_lock" }) |
| 334 | .select("table_name") |
| 335 | .then((rows) => rows.map((row) => `"${row.table_name}"`).join(", ")) |
| 336 | .finally(() => db.destroy()); |
| 337 | |
| 338 | const cmd = execa( |
| 339 | "pg_dump", |
| 340 | [ |
| 341 | "--verbose", |
| 342 | "--data-only", |
| 343 | `--schema=${schema}`, |
| 344 | "--no-owner", |
| 345 | "--no-privileges", |
| 346 | // '--column-inserts', |
| 347 | "--disable-triggers", |
| 348 | "--exclude-table=migration", |
| 349 | "--exclude-table=migration_lock", |
| 350 | "--exclude-table=migration_id_seq", |
| 351 | "--exclude-table=migration_lock_index_seq", |
| 352 | ...(options?.args ?? []), |
| 353 | ], |
| 354 | { stdio: ["pipe", "pipe", "inherit"] }, |
| 355 | ).on("exit", (code) => { |
| 356 | if (code && code !== 0) process.exit(code); |
| 357 | }); |
| 358 | |
| 359 | const timestamp = new Date().toISOString().replace(/(-|:|\.\d{3})/g, ""); |
| 360 | const suffix = options?.env ? `_${options.env}` : ""; |
| 361 | const file = resolve(backupsDir, `${timestamp}${suffix}.sql`); |
| 362 | const out = createWriteStream(file, { encoding: "utf8" }); |
| 363 | const rl = createInterface({ input: cmd.stdout!, terminal: false }); |
| 364 | |
| 365 | rl.on("line", (line) => { |
| 366 | // Some (system) triggers cannot be disabled in a cloud environment |
| 367 | // "DISABLE TRIGGER ALL" => "DISABLE TRIGGER USER" |
| 368 | if (line.endsWith(" TRIGGER ALL;")) { |
| 369 | out.write(`${line.substring(0, line.length - 5)} USER;${EOL}`, "utf8"); |
| 370 | } |
| 371 | // Add a command that truncates all the database tables |
| 372 | else if (line.startsWith("SET row_security")) { |
| 373 | out.write(`${line}${EOL}${EOL}TRUNCATE TABLE ${tables} CASCADE;${EOL}`); |
| 374 | } else { |
| 375 | out.write(`${line}${EOL}`, "utf8"); |
no test coverage detected