@opengis/fastify-table
Version:
core-plugins
122 lines (106 loc) • 4.73 kB
JavaScript
import { createHash } from 'node:crypto';
import getTemplate from '../../../table/funcs/getTemplate.js';
import metaFormat from '../../../table/funcs/metaFormat/index.js';
const defaultTitles = {
editor_date: 'Дата оновлення',
editor_id: 'Редактор',
сdate: 'Дата створення',
uid: 'Автор',
body: 'Зміст',
entity_id: 'ID Сутності',
entity_type: 'Таблиця сутності',
file_path: 'Шлях до файлу',
uploaded_name: 'Назва файлу',
size: 'Розмір файлу',
ext: 'Розширення файлу',
};
function getValue(val, tableName) {
if (!val) return null;
if (['crm.files'].includes(tableName)) {
return typeof val === 'object'
? JSON.stringify(val)
: val;
}
return typeof val === 'object'
? JSON.stringify(val)?.substring?.(0, 30)
: val?.toString?.()?.substring?.(0, 30);
}
// extract titles and cls from form schema
// alt: extract table template from referer -> form
export default async function logChanges({
pg, table: table1, tokenData, referer, id, data, uid = 1, type,
}) {
const table = table1.replace(/"/g, '');
if (!id) {
console.error('param id is required');
return null;
}
if (!table || !pg.pk?.[table]) {
console.error('table not found');
return null;
}
if (!pg.pk?.['log.table_changes'] || !pg.pk?.['log.table_changes_data']) {
console.error('log table not found');
return null;
}
if (!type) {
console.error('invalid type');
return null;
}
try {
const { change_id: changeId } = await pg.query(`insert into log.table_changes(change_date,change_type,change_user_id,entity_type,entity_id)
values(CURRENT_DATE, $1, $2, $3, $4) returning change_id`, [type, uid, table, id]).then((res) => res.rows?.[0] || {});
const q = `select json_object_agg(entity_key, value_hash) from (
select
entity_key,
value_hash,
( rank() over (partition by entity_key order by cdate desc) = 1 ) as is_latest
from log.table_changes_data
where change_id in (
select
change_id
from log.table_changes
where entity_id=$1
and entity_type=$2
)
)q where is_latest`;
// console.log(q, type, id);
const old = type !== 'INSERT' ? await pg.query(q, [id, table]).then(el => el.rows?.[0]?.json_object_agg || {}) : {};
const body = await getTemplate('form', tokenData?.form);
const schema = body?.schema || body || {};
const titles = Object.keys(schema)
.reduce((acc, curr) => Object.assign(acc, { [curr]: schema[curr].title || schema[curr].ua }), {});
const cls = Object.keys(schema)
.filter(el => schema[el]?.data)
.reduce((acc, curr) => Object.assign(acc, { [curr]: schema[curr].data }), {});
const data1 = data ? await metaFormat({
rows: [data], cls, sufix: false, reassign: false,
}, pg) : null;
const newObj = Object.fromEntries(Object.entries(data1?.[0] || {}).map(el => ([[titles[el[0]] || defaultTitles[el[0]] || el[0]], el[1]])));
const changesData = Object.keys(newObj || {}).map(el => ({
change_id: changeId,
entity_key: el,
value_old: getValue(old?.[el], table),
value_new: type === 'DELETE' ? null : getValue(newObj?.[el], table),
value_hash: newObj?.[el] ? createHash('md5').update(JSON.stringify(newObj?.[el])).digest('hex') : null,
uid,
})).filter(el => (old?.[el.entity_key] !== el.value_hash));
const res = await Promise.all(changesData.map(async (el) => {
const insertQuery = `insert into log.table_changes_data (${Object.entries(el)?.map((key) => `"${key[0]}"`).join(',')})
values (${Object.entries(el)?.map((key, i) => `$${i + 1}`).join(',')}) returning *`;
const { rows = [] } = await pg.query(insertQuery, [...Object.entries(el).map((el1) => (el1[1] && typeof el1[1] === 'object' && (!Array.isArray(el1[1]) || typeof el1[1]?.[0] === 'object') ? JSON.stringify(el1[1]) : el1[1]))]) || {};
return rows[0];
}));
const newData = type === 'DELETE' ? {} : (Array.isArray(res) ? res : [res]).reduce((acc, curr) => Object.assign(acc, { [curr.entity_key]: curr.value_new }), {});
// console.log('logChanges OK', type);
return {
change_id: changeId, entity_type: table, entity_id: id, uid, change_type: type, old, new: newData,
};
}
catch (err) {
console.error('logChanges error', type, table, id, data, err.toString());
return {
error: err.toString(), entity_type: table, entity_id: id, uid, change_type: type,
};
}
}