UNPKG

@opengis/fastify-table

Version:

core-plugins

149 lines (148 loc) 5.38 kB
import getPG from "../../pg/funcs/getPG.js"; import getRedis from "../../redis/funcs/getRedis.js"; import pgClients from "../../pg/pgClients.js"; import getTemplate from "../../table/funcs/getTemplate.js"; import config from "../../../../config.js"; import logChanges from "./utils/logChanges.js"; import getInsertQuery from "./utils/getInsertQuery.js"; import logger from "../../logger/getLogger.js"; import extraData from "../../extra/extraData.js"; const rclient = getRedis(); export default async function dataUpsert({ id, table: table1, referer, data, pg: pg1, uid, tokenData = {}, update = true, constraint, }) { const pg = pg1 || getPG({ name: "client" }); if (!pg) return null; // pg client single transaction support if (!pg?.pk && config.pg) { pg.options = pgClients.client?.options; pg.tlist = pgClients.client?.tlist; pg.pgType = pgClients.client?.pgType; pg.relkinds = pgClients.client?.relkinds; pg.pk = pgClients.client?.pk; } if (config.trace) console.log("form", tokenData?.form); const table = pg.pk?.[table1] ? table1 : table1.replace(/"/g, ""); const { insertQuery, args = [], keys = [], systemColumns = [], } = (await getInsertQuery({ pg, table, data, id, uid, })) || {}; const updatedAtColumn = systemColumns .map((el) => el[0]) .find((colname) => ["editor_date", "updated_at"].includes(colname)); const upsert = () => { if (!update || !keys.length) { const p1 = `on conflict(${constraint || pg.pk?.[table]}) do `; const p2 = updatedAtColumn ? `update set ${updatedAtColumn}=now()` : "nothing"; return p1 + p2 + "returning *"; } return `on conflict(${constraint || pg.pk?.[table]}) do update set ${typeof update === "string" ? update : keys.map((colname) => `${colname} = EXCLUDED."${colname}"`).join(", ")} ${keys.includes(updatedAtColumn) || !updatedAtColumn ? "" : `,${updatedAtColumn}=now()`} returning *`; }; if (!insertQuery || !args.length) return null; const q = [insertQuery.replace("returning *", ""), upsert()] .filter(Boolean) .join(" "); // for transactions const isClient = typeof pg.query === "function" && typeof pg.release === "function"; const client = (isClient ? pg : await pg.connect()); if (isClient || !client.pk) { client.options = pg.options; client.tlist = pg.tlist; client.pgType = pg.pgType; client.relkinds = pg.relkinds; client.pk = pg.pk; } try { if (!isClient) { await client.query("begin;"); } const row = await client.query(q, args).then((el) => el.rows?.[0]); const id1 = row?.[pg.pk?.[table] || ""]; if (!id1) return null; await extraData({ table, form: tokenData?.form, id: id1, data, uid, row, }, client); // foreign key dataTable (table + parent_id) const formData = tokenData?.form ? (await getTemplate("form", tokenData.form)) || {} : {}; const schema = formData?.schema || formData; const parentKeys = Object.keys(schema || {})?.filter((key) => data[key]?.length && Array.isArray(data[key]) && schema?.[key]?.table && schema?.[key]?.parent_id); if (parentKeys?.length) { await Promise.all(parentKeys?.map(async (key) => { const parentKey = schema[key].parent_id; const objId = data[parentKey] || data?.id || row?.[parentKey] || id1; const parentRows = await Promise.all(data[key].map(async (row) => { Object.assign(row, { [parentKey]: objId }); const parentRes = await getInsertQuery({ pg: client, table: schema[key].table, data: row, uid, }); if (!parentRes?.insertQuery || !parentRes?.args?.length) return null; const { rows = [] } = await client.query(parentRes.insertQuery, parentRes.args); return rows[0]; })); Object.assign(row, { [key]: parentRows.filter(Boolean) }); })); } await logChanges({ pg: client, table, tokenData, referer, data, id: id1, uid, type: "UPSERT", }); if (config.redis) { rclient.incr(`pg:${table}:crud`); } if (!isClient) { await client.query("commit;"); } return row; } catch (err) { logger.file("crud/upsert", { error: err.toString(), stack: err.stack, table, id, referer, uid, form: tokenData?.form, }); if (!isClient) { await client.query("rollback;"); } throw err; } finally { if (!isClient) { client?.release?.(); } } }