@launchql/core
Version:
LaunchQL Package and Migration Tools
103 lines (102 loc) • 4.44 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.writePackage = exports.packageModule = exports.cleanTree = void 0;
const logger_1 = require("@launchql/logger");
const fs_1 = require("fs");
const path_1 = require("path");
const pgsql_deparser_1 = require("pgsql-deparser");
const pgsql_parser_1 = require("pgsql-parser");
const files_1 = require("../files");
const resolve_1 = require("../resolution/resolve");
const transform_1 = require("./transform");
const log = new logger_1.Logger('package');
const noop = () => undefined;
const cleanTree = (tree) => {
return (0, transform_1.transformProps)(tree, {
stmt_len: noop,
stmt_location: noop,
location: noop,
});
};
exports.cleanTree = cleanTree;
const filterStatements = (stmts, extension) => {
if (!extension)
return stmts;
return stmts.filter(node => {
const stmt = node.stmt;
return !stmt.hasOwnProperty('TransactionStmt') &&
!stmt.hasOwnProperty('CreateExtensionStmt');
});
};
const packageModule = async (packageDir, { usePlan = true, extension = true, pretty = true, functionDelimiter = '$EOFCODE$' } = {}) => {
const resolveFn = usePlan ? resolve_1.resolveWithPlan : resolve_1.resolve;
const sql = resolveFn(packageDir);
if (!sql?.trim()) {
log.warn(`⚠️ No SQL generated for module at ${packageDir}. Skipping.`);
return { sql: '' };
}
const extname = (0, files_1.getExtensionName)(packageDir);
try {
const parsed = await (0, pgsql_parser_1.parse)(sql);
parsed.stmts = filterStatements(parsed.stmts, extension);
const topLine = extension
? `\\echo Use "CREATE EXTENSION ${extname}" to load this file. \\quit\n`
: '';
const finalSql = await (0, pgsql_deparser_1.deparse)(parsed, {
pretty,
functionDelimiter
});
const tree1 = parsed.stmts;
const tree2 = await (0, pgsql_parser_1.parse)(finalSql);
const results = {
sql: `${topLine}${finalSql}`,
};
const diff = JSON.stringify((0, exports.cleanTree)(tree1)) !== JSON.stringify((0, exports.cleanTree)(tree2));
if (diff) {
results.diff = true;
results.tree1 = JSON.stringify((0, exports.cleanTree)(tree1), null, 2);
results.tree2 = JSON.stringify((0, exports.cleanTree)(tree2), null, 2);
}
return results;
}
catch (e) {
log.error(`❌ Failed to parse SQL for ${packageDir}`);
console.error(e);
throw e;
}
};
exports.packageModule = packageModule;
const writePackage = async ({ version, extension = true, usePlan = true, packageDir, }) => {
const pkgPath = `${packageDir}/package.json`;
const pkg = require(pkgPath);
const extname = await (0, files_1.getExtensionName)(packageDir);
const makePath = `${packageDir}/Makefile`;
const controlPath = `${packageDir}/${extname}.control`;
const sqlFileName = `${extname}--${version}.sql`;
const Makefile = (0, fs_1.readFileSync)(makePath, 'utf-8');
const control = (0, fs_1.readFileSync)(controlPath, 'utf-8');
const { sql, diff, tree1, tree2 } = await (0, exports.packageModule)(packageDir, {
extension,
usePlan,
});
const outPath = extension ? `${packageDir}/sql` : `${packageDir}/out`;
(0, fs_1.rmSync)(outPath, { recursive: true, force: true });
(0, fs_1.mkdirSync)(outPath, { recursive: true });
if (extension) {
(0, fs_1.writeFileSync)(controlPath, control.replace(/default_version = '[0-9\.]+'/, `default_version = '${version}'`));
pkg.version = version;
(0, fs_1.writeFileSync)(pkgPath, JSON.stringify(pkg, null, 2));
const regex = new RegExp(`${extname}--[0-9.]+.sql`);
(0, fs_1.writeFileSync)(makePath, Makefile.replace(regex, sqlFileName));
}
if (diff) {
log.warn(`⚠️ SQL diff exists! Review the ${(0, path_1.relative)(packageDir, outPath)}/ folder.`);
// Uncomment if needed:
// writeFileSync(`${outPath}/orig.${sqlFileName}.tree.json`, tree1);
// writeFileSync(`${outPath}/parsed.${sqlFileName}.tree.json`, tree2);
}
const writePath = `${outPath}/${sqlFileName}`;
(0, fs_1.writeFileSync)(writePath, sql);
log.success(`${(0, path_1.relative)(packageDir, writePath)} written`);
};
exports.writePackage = writePackage;