@clickup/pg-mig
Version:
PostgreSQL schema migration tool with microsharding and clustering support
171 lines • 7.83 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.renderGrid = renderGrid;
exports.renderPatchSummary = renderPatchSummary;
exports.renderLatestVersions = renderLatestVersions;
exports.printText = printText;
exports.printSuccess = printSuccess;
exports.printError = printError;
const path_1 = require("path");
const chalk_1 = __importDefault(require("chalk"));
const compact_1 = __importDefault(require("lodash/compact"));
const sortBy_1 = __importDefault(require("lodash/sortBy"));
const sum_1 = __importDefault(require("lodash/sum"));
const collapse_1 = require("./helpers/collapse");
const DefaultMap_1 = require("./helpers/DefaultMap");
const promiseAllMap_1 = require("./helpers/promiseAllMap");
const Table = require("table-layout");
const lengthsByGrid = new WeakMap();
function renderGrid(grid, skipEmptyLines) {
var _a, _b;
let lengths = lengthsByGrid.get(grid);
if (!lengths) {
const chains = [...grid.chains, ...grid.beforeChains, ...grid.afterChains];
const versionLengths = (0, sortBy_1.default)(chains.flatMap((chain) => chain.migrations.map((migration) => migration.version.length)));
lengths = {
succeededMigrations: 4,
errorMigrations: 3,
destName: Math.max(...chains.map((chain) => chain.dest.name("short").length)),
destSchema: Math.max(...chains.map((chain) => chain.dest.schema.length)),
migrationVersion: versionLengths[Math.floor(versionLengths.length * 0.8)] || 1,
prefix: 0,
};
lengths.prefix =
(0, sum_1.default)(Object.values(lengths)) + Object.values(lengths).length;
lengthsByGrid.set(grid, lengths);
}
const activeRows = [];
const errors = [];
const warnings = [];
for (const worker of (0, sortBy_1.default)(grid.workers, (worker) => { var _a; return (_a = worker.curDest) === null || _a === void 0 ? void 0 : _a.name(); }, (worker) => { var _a; return (_a = worker.curDest) === null || _a === void 0 ? void 0 : _a.schema; })) {
if (worker.curDest && (!skipEmptyLines || ((_a = worker.curLine) === null || _a === void 0 ? void 0 : _a.trim()))) {
activeRows.push([
chalk_1.default.green(worker.succeededMigrations
.toString()
.padStart(lengths.succeededMigrations)),
worker.errorMigrations.length
? chalk_1.default.red(worker.errorMigrations.length
.toString()
.padStart(lengths.errorMigrations))
: chalk_1.default.gray("0".padStart(lengths.errorMigrations)),
worker.curDest.name("short").padEnd(lengths.destName),
worker.curDest.schema.padEnd(lengths.destSchema),
worker
.curMigration.version.substring(0, lengths.migrationVersion)
.padEnd(lengths.migrationVersion),
((_b = worker.curLine) === null || _b === void 0 ? void 0 : _b.trimEnd()) || "",
]);
}
for (const { dest, migration, payload } of worker.errorMigrations) {
errors.push(chalk_1.default.red("#") +
" " +
chalk_1.default.red(dest.toString() + " <- " + migration.version) +
"\n" +
("" + payload).replace(/^/gm, " ").trimEnd());
}
for (const { dest, migration, payload } of worker.warningMigrations) {
warnings.push(chalk_1.default.yellow("#") +
" " +
chalk_1.default.yellow(dest.toString() + " <- " + migration.version) +
"\n" +
("" + payload).replace(/^/gm, " ").trimEnd());
}
}
const { processedMigrations, totalMigrations, elapsedSeconds } = grid;
const leftMigrations = Math.max(totalMigrations - processedMigrations, 0);
const percentDone = totalMigrations > 0 && processedMigrations <= totalMigrations
? Math.round((processedMigrations / totalMigrations) * 100)
: "100";
const leftSeconds = processedMigrations > 0
? Math.round((elapsedSeconds / processedMigrations) * leftMigrations) +
"s left"
: "";
const qps = elapsedSeconds > 0
? Math.round((processedMigrations / elapsedSeconds) * 100) / 100 +
" migrations/s"
: "";
const tableOptions = {
maxWidth: process.stdout.columns
? Math.max(process.stdout.columns - 2, lengths.prefix + 30)
: 1000000,
padding: { right: " ", left: "" },
};
const lines = (0, compact_1.default)([
activeRows.length > 0 &&
"Migrating: " +
[
percentDone + "%",
Math.round(elapsedSeconds) + "s elapsed",
leftSeconds,
qps,
]
.filter((v) => v.length > 0)
.join(", "),
// Render each row as an independent table, in sake of just wrapping the
// long worker.curLine strings.
...activeRows.map((row) => new Table([row], tableOptions).toString().trimRight()),
...errors,
...warnings,
]);
return { lines, errors, warnings };
}
function renderPatchSummary(chains, beforeAfterFiles) {
const destsGrouped = new DefaultMap_1.DefaultMap();
for (const chain of chains) {
const key = (chain.type === "dn" ? "(undo) " : "") +
chain.migrations.map((ver) => ver.version).join(", ");
destsGrouped
.getOrAdd(key, [])
.push(chain.dest.name("short") + ":" + chain.dest.schema);
}
const rows = [];
for (const [key, dests] of destsGrouped) {
rows.push((0, collapse_1.collapse)(dests) + ": " + key);
}
return chalk_1.default.yellow("Migration versions to apply:\n" +
(0, compact_1.default)([
...(rows.length ? rows : ["<no new migration versions>"]),
beforeAfterFiles.map((fileName) => (0, path_1.basename)(fileName)).join(", "),
])
.map((s) => " * " + s)
.join("\n"));
}
async function renderLatestVersions(dests, registry) {
const destsGrouped = new DefaultMap_1.DefaultMap();
await (0, promiseAllMap_1.promiseAllMap)(dests, async (dest) => {
const allSchemas = await dest.loadSchemas();
const reEntries = registry.groupBySchema(allSchemas);
const schemas = Array.from(reEntries.keys());
const versionsBySchema = await dest.loadVersionsBySchema(schemas);
for (const [schema, versions] of versionsBySchema) {
destsGrouped
.getOrAdd(versions[versions.length - 1] || "", [])
.push(dest.name("short") + ":" + schema);
}
});
const rows = [];
for (const [key, dests] of (0, sortBy_1.default)(Array.from(destsGrouped), ([key]) => key).reverse()) {
rows.push((0, collapse_1.collapse)(dests) + ": " + (key || "<no versions>"));
}
return ("Existing latest versions in the DB:\n" +
(rows.length ? rows : ["<empty>"]).map((s) => " * " + s).join("\n"));
}
function printText(text) {
// eslint-disable-next-line no-console
return console.log(text);
}
function printSuccess(text) {
return printText(chalk_1.default.green(text));
}
function printError(e) {
var _a;
return printText(chalk_1.default.red(e instanceof Error
? ((_a = e.stack) !== null && _a !== void 0 ? _a : e.message).trim()
: typeof e === "string" && !e.includes("\n")
? `Error: ${e}`
: "" + e));
}
//# sourceMappingURL=render.js.map