@clickup/pg-mig
Version:
PostgreSQL schema migration tool with microsharding and clustering support
119 lines • 4.23 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Psql = exports.MIGRATION_VERSION_APPLIED = void 0;
const child_process_1 = require("child_process");
const shell_quote_1 = require("shell-quote");
/**
* A tag which is expected to be echoed right after the migration file is
* applied. This is for better output (an optional thing).
*/
exports.MIGRATION_VERSION_APPLIED = "MIGRATION_VERSION_APPLIED";
/**
* A wrapper for running psql.
*
* Keeps track on stdout/stderr (and both), also allows to trigger
* and event if something is changed there, plus to read the last
* line of the output.
*/
class Psql {
constructor(dest, cwd, args, stdin) {
this.dest = dest;
this.cwd = cwd;
this.stdin = stdin;
this._code = null;
this._stdout = "";
this._stderr = "";
this._out = ""; // a mix of stdin and stdout
this._args = [
"-X", // do not read psqlrc
"-vON_ERROR_STOP=1", // if it fails, then exit code will be nonzero
...args,
];
this._cmdline = "psql " + (0, shell_quote_1.quote)(this._args);
}
get code() {
return this._code;
}
get stdout() {
return this._stdout;
}
get stderr() {
return this._stderr;
}
get warning() {
return this._stderr.match(/\bWARNING: {2}/m)
? this._stderr.trimEnd()
: null;
}
get out() {
return this._out;
}
get cmdline() {
return this._cmdline;
}
get lastOutLine() {
const end = this._out.lastIndexOf(`\n${exports.MIGRATION_VERSION_APPLIED}\n`);
const out = end >= 0 ? this._out.substring(0, end + 1) : this._out;
let posNewline1 = out.lastIndexOf("\n");
let posNewline2 = out.length;
// Find the 1st non-empty line scanning backward.
while (posNewline1 >= 0 && posNewline1 + 1 === posNewline2) {
posNewline2 = posNewline1;
posNewline1 = out.lastIndexOf("\n", posNewline2 - 1);
}
return out.substring(posNewline1 + 1, posNewline2).trimEnd();
}
async run(onOut = () => { }) {
return new Promise((resolve) => {
var _a;
const proc = (0, child_process_1.spawn)("psql", this._args, {
cwd: this.cwd,
env: {
...process.env,
PGHOST: this.dest.host,
PGPORT: this.dest.port.toString(),
PGUSER: this.dest.user,
PGPASSWORD: this.dest.pass,
PGDATABASE: this.dest.db,
// Remove node_modules from PATH to force pg-mig use the "vanilla"
// psql tool, even if the package manager overrides it. This is for
// performance, and also, we are not meant to use a non-vanilla psql.
PATH: ((_a = process.env["PATH"]) !== null && _a !== void 0 ? _a : "")
.split(":")
.filter((p) => !p.includes("/node_modules/"))
.join(":"),
},
});
let clearSetInResponse = false;
if (this.stdin) {
clearSetInResponse = true;
proc.stdin.write(this.stdin);
proc.stdin.end();
}
proc.stdout.on("data", (data) => {
let str = data.toString();
if (clearSetInResponse) {
str = str.replace(/^SET\r?\n/s, "");
clearSetInResponse = false;
}
this._stdout += str;
this._out += str;
if (this._stdout !== "") {
onOut(this);
}
});
proc.stderr.on("data", (data) => {
const str = data.toString();
this._stderr += str;
this._out += str;
onOut(this);
});
proc.on("close", (code) => {
this._code = code;
resolve(this);
});
});
}
}
exports.Psql = Psql;
//# sourceMappingURL=Psql.js.map