UNPKG

@opengis/fastify-table

Version:

core-plugins

217 lines (183 loc) 7.29 kB
// Вигрузка схеми бд // Usage examples: // bun .\script\dump.js --table=bpmn.tasks // bun .\script\dump.js --schema=bpmn import { type ExtendedPG } from "../server/types/core.js"; import path from "node:path"; import { existsSync } from "node:fs"; import { mkdir, writeFile, rm } from "node:fs/promises"; import { config, handlebars, pgClients, getTemplate } from "../utils.js"; import { build, teardown } from "../helper.js"; if (import.meta.main) { dumpMigrateSQL(); } const debug = false; export default async function dumpMigrateSQL() { const app = await build(); // app.addHook("onClose", async () => teardown()); try { // const { database, host, port, user, password } = config.pg; if (!config.pg) { console.error("empty config.pg, skip..."); return null; } if (!Bun.argv[2]) { console.error("missing schema / table name, skip..."); } const [key, value] = Bun.argv[2]?.substring?.(2)?.split?.("=") || []; const tableName = key === "table" ? value : null; const schemaName = key === "schema" ? value : value?.split?.(".")?.shift?.(); const pg = pgClients.client; // const pg = await getPGAsync({ database, host, port, user, password }); await pg.query(`select 1`); const schemaExists = await pg .query( `SELECT 1 FROM information_schema.schemata WHERE schema_name = $1`, [schemaName] ) .then((el: any) => el.rowCount); if (!schemaExists) { console.error("Вказаної схеми не існує", config.pg?.database); return null; } // if (tableName && !pg.pk?.[tableName]) { // console.error('Вказаної таблиці не існує', config.pg?.database); // return null; // } const dump = await schemaItem({ pg, table: tableName, schema: schemaName, debug, }); if (debug) { console.log(dump); return null; } const filepath = await saveFile(dump, tableName || schemaName || ""); console.log("success", filepath); // app.close(); } catch (err) { console.error(err); // app.close(); } finally { await app.close(); process.exit(0); } } async function saveFile(data: any, filename: string) { if (!data) throw new Error(`no data - ${filename}`); const filepath = path.join("log/dump", `${filename}.sql`); const fileExists = existsSync(filepath); // overwrite old file if (fileExists) { await rm(filepath, { force: true, recursive: true }); } await mkdir(path.dirname(filepath), { recursive: true }); await writeFile(filepath, Buffer.from(data, "utf-8")); return filepath; } async function schemaItem({ pg, table, schema, debug, }: { pg: ExtendedPG; table?: string | null; schema?: string; debug?: boolean; }) { if (!schema && !table) return new Error("param schema is required"); const { rows: schemaInfo } = await pg.query(`select c.oid,relname,nspname,obj_description(c.oid) as description, ( select json_agg(row_to_json(q)) from ( select column_name, case when data_type='USER-DEFINED' AND udt_name='geometry' THEN 'geometry' when data_type='ARRAY' AND udt_name='_text' THEN 'text[]' when data_type='ARRAY' AND udt_name='_int4' THEN 'integer[]' else data_type end as data_type, ordinal_position, column_default, is_nullable, case when column_name='uid' then 'ідентифікатор автора запису в БД' when column_name='cdate' then 'Дата створення запису в БД' when column_name='editor_id' then 'Ідентифікатор автора, який останій вніс зміни в запис' when column_name='editor_date' then 'Час останії зміни в записі' when column_name='files' then 'Системна колонка' when column_name='doc_status' then 'Статус документа' when column_name='reg_status' then 'Статус реєстрації' when column_name='obj_version' then 'Версія запису' else col_description(a.attrelid,ordinal_position) end as description from information_schema.columns col LEFT JOIN pg_attribute a ON col.column_name=a.attname and c.oid = a.attrelid where col.table_schema=nspname and col.table_name=relname )q ) as columns from pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace where ${ table ? `nspname||'.'||relname='${table}'` : `'${schema}'=nspname` } and relam=2 order by nspname,relname`); if (!schemaInfo?.length) throw new Error("invalid params"); const { rows: constraints } = await pg.query(`select con.conrelid::regclass as constraint_table, a.column_name, con.conname as constraint_name,contype as constraint_type, con.confrelid::regclass as foreign_table, con.confupdtype, con.confdeltype, con.confmatchtype, u.column_name as foreign_column, case when contype='c' then pg_get_constraintdef(con.oid, true) else null end AS check_definition from pg_constraint con left join pg_class c ON c.oid = con.conrelid left join pg_namespace n ON n.oid = c.relnamespace left join lateral ( select string_agg(a.attname,',') as column_name from pg_attribute a where con.conrelid = a.attrelid and a.attnum = any(con.conkey) limit 1 )a on 1=1 left join lateral ( select column_name from information_schema.constraint_column_usage u where conname=u.constraint_name limit 1 )u on 1=1 where ${ table ? `conrelid::regclass::text = '${table}'` : `nspname = '${schema}'` }`); // add table constraints, mermaid schemaInfo?.forEach((row: any) => { // constraint type to column row?.columns?.forEach((col: any) => { const { constraint_type } = constraints?.find( (con: any) => con?.column_name === col?.column_name && con.constraint_table === `${row.nspname}.${row.relname}` ) || {}; Object.assign(col, { constraint_type }); }); // table relations const tableConstraints = constraints ?.filter( (el: any) => el?.constraint_table === `${row.nspname}.${row.relname}` ) ?.map((el: any) => ({ ...el, check_definition: el.check_definition ? new handlebars.SafeString(el.check_definition) : null, })); Object.assign(row, { constraints: tableConstraints }); }); if (debug) return schemaInfo; const body = await getTemplate("pt", "schemaItem.pt"); const schemaContent = await handlebars.compile( typeof body === "string" ? body : body?.hbs || "template not found schemaItem.pt" )({ nspname: schema, rows: schemaInfo, constraints }); return schemaContent.replace(/'/g, "'"); }