Release: weekly deploy
This commit is contained in:
@@ -32,6 +32,11 @@ function sqlLiteral(value) {
|
|||||||
if (typeof value === 'boolean') return value ? 'TRUE' : 'FALSE';
|
if (typeof value === 'boolean') return value ? 'TRUE' : 'FALSE';
|
||||||
if (value instanceof Date) return `'${value.toISOString()}'`;
|
if (value instanceof Date) return `'${value.toISOString()}'`;
|
||||||
if (typeof value === 'number' || typeof value === 'bigint') return String(value);
|
if (typeof value === 'number' || typeof value === 'bigint') return String(value);
|
||||||
|
// node-pg returns JS arrays for Postgres array columns (e.g. users.permissions TEXT[])
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
if (value.length === 0) return `ARRAY[]::text[]`;
|
||||||
|
return `ARRAY[${value.map((item) => sqlLiteral(item)).join(', ')}]`;
|
||||||
|
}
|
||||||
if (typeof value === 'object') {
|
if (typeof value === 'object') {
|
||||||
return `'${JSON.stringify(value).replace(/'/g, "''")}'`;
|
return `'${JSON.stringify(value).replace(/'/g, "''")}'`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,28 @@ function getInsertTableName(statement) {
|
|||||||
return match ? match[1] : null;
|
return match ? match[1] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Older backups serialized TEXT[] (e.g. users.permissions) via JSON.stringify,
|
||||||
|
* producing '["a","b"]' which Postgres rejects as an array literal. Rewrite
|
||||||
|
* JSON string-array literals to ARRAY['a','b']::text[].
|
||||||
|
*/
|
||||||
|
function coerceJsonStringArrayLiterals(statement) {
|
||||||
|
return statement.replace(/'(\[(?:"(?:\\.|[^"\\])*"(?:\s*,\s*"(?:\\.|[^"\\])*")*)?\])'/g, (full, jsonBody) => {
|
||||||
|
let arr;
|
||||||
|
try {
|
||||||
|
arr = JSON.parse(jsonBody);
|
||||||
|
} catch {
|
||||||
|
return full;
|
||||||
|
}
|
||||||
|
if (!Array.isArray(arr) || !arr.every((item) => typeof item === 'string')) {
|
||||||
|
return full;
|
||||||
|
}
|
||||||
|
if (arr.length === 0) return `ARRAY[]::text[]`;
|
||||||
|
const items = arr.map((s) => `'${String(s).replace(/'/g, "''")}'`).join(', ');
|
||||||
|
return `ARRAY[${items}]::text[]`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function filterInsertsForRestore(inserts, prod) {
|
function filterInsertsForRestore(inserts, prod) {
|
||||||
if (!prod) return inserts;
|
if (!prod) return inserts;
|
||||||
return inserts.filter((statement) => {
|
return inserts.filter((statement) => {
|
||||||
@@ -113,7 +135,9 @@ async function main() {
|
|||||||
|
|
||||||
const config = prod ? loadProdPgConfig() : loadDevPgConfig();
|
const config = prod ? loadProdPgConfig() : loadDevPgConfig();
|
||||||
const dbName = config.database;
|
const dbName = config.database;
|
||||||
const allInserts = extractInsertStatements(fs.readFileSync(filePath, 'utf8'));
|
const allInserts = extractInsertStatements(fs.readFileSync(filePath, 'utf8')).map(
|
||||||
|
coerceJsonStringArrayLiterals
|
||||||
|
);
|
||||||
const inserts = filterInsertsForRestore(allInserts, prod);
|
const inserts = filterInsertsForRestore(allInserts, prod);
|
||||||
const skippedInserts = prod ? allInserts.length - inserts.length : 0;
|
const skippedInserts = prod ? allInserts.length - inserts.length : 0;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user