@opengis/fastify-table 2.0.149 → 2.0.151
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -3,7 +3,7 @@ import getRedis from "../../redis/funcs/getRedis.js";
|
|
|
3
3
|
import pgClients from "../../pg/pgClients.js";
|
|
4
4
|
import getTemplate from "../../table/funcs/getTemplate.js";
|
|
5
5
|
import config from "../../../../config.js";
|
|
6
|
-
|
|
6
|
+
import logChanges from "./utils/logChanges.js";
|
|
7
7
|
import getInsertQuery from "./utils/getInsertQuery.js";
|
|
8
8
|
import logger from "../../logger/getLogger.js";
|
|
9
9
|
import extraData from "../../extra/extraData.js";
|
|
@@ -95,16 +95,16 @@ export default async function dataInsert({ id, table: table1, referer, data, pg:
|
|
|
95
95
|
Object.assign(res.rows[0], { [key]: parentRows.filter(Boolean) });
|
|
96
96
|
}));
|
|
97
97
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
98
|
+
await logChanges({
|
|
99
|
+
pg: client,
|
|
100
|
+
table,
|
|
101
|
+
tokenData,
|
|
102
|
+
referer,
|
|
103
|
+
data,
|
|
104
|
+
id: id1,
|
|
105
|
+
uid,
|
|
106
|
+
type: "INSERT",
|
|
107
|
+
});
|
|
108
108
|
if (config.redis && rclient?.status !== "end") {
|
|
109
109
|
rclient.incr(`pg:${client.options?.database}:${table}:crud`);
|
|
110
110
|
}
|
|
@@ -16,6 +16,7 @@ export default function logChanges({ pg, table: table1, tokenData, referer, id,
|
|
|
16
16
|
change_type: string;
|
|
17
17
|
old: any;
|
|
18
18
|
new: any;
|
|
19
|
+
titles: Record<string, string>;
|
|
19
20
|
error?: undefined;
|
|
20
21
|
} | {
|
|
21
22
|
error: any;
|
|
@@ -26,5 +27,6 @@ export default function logChanges({ pg, table: table1, tokenData, referer, id,
|
|
|
26
27
|
change_id?: undefined;
|
|
27
28
|
old?: undefined;
|
|
28
29
|
new?: undefined;
|
|
30
|
+
titles?: undefined;
|
|
29
31
|
} | null>;
|
|
30
32
|
//# sourceMappingURL=logChanges.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logChanges.d.ts","sourceRoot":"","sources":["../../../../../../server/plugins/crud/funcs/utils/logChanges.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"logChanges.d.ts","sourceRoot":"","sources":["../../../../../../server/plugins/crud/funcs/utils/logChanges.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAC;AA8C5D,wBAA8B,UAAU,CAAC,EACvC,EAAE,EACF,KAAK,EAAE,MAAM,EACb,SAAS,EACT,OAAO,EACP,EAAE,EACF,IAAI,EACJ,GAAO,EACP,IAAI,GACL,EAAE;IACD,EAAE,EAAE,UAAU,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;CACd;;;;;;;;;;;;;;;;;;;;UAiNA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import getTemplate from "../../../table/funcs/getTemplate.js";
|
|
3
3
|
import metaFormat from "../../../table/funcs/metaFormat/index.js";
|
|
4
|
+
import getMeta from "../../../pg/funcs/getMeta.js";
|
|
4
5
|
const defaultTitles = {
|
|
5
6
|
editor_date: "Дата оновлення",
|
|
6
7
|
editor_id: "Редактор",
|
|
@@ -14,15 +15,26 @@ const defaultTitles = {
|
|
|
14
15
|
size: "Розмір файлу",
|
|
15
16
|
ext: "Розширення файлу",
|
|
16
17
|
};
|
|
17
|
-
|
|
18
|
+
// skip log of system columns changes made by CRUD functions - log only changes of data
|
|
19
|
+
const systemColumns = [
|
|
20
|
+
"cdate",
|
|
21
|
+
"editor_date",
|
|
22
|
+
"created_at",
|
|
23
|
+
"updated_at",
|
|
24
|
+
"editor_id",
|
|
25
|
+
"uid",
|
|
26
|
+
"updated_by",
|
|
27
|
+
"created_by",
|
|
28
|
+
];
|
|
29
|
+
function getValue(val, tableName, columnTypes) {
|
|
30
|
+
if (typeof val === "boolean")
|
|
31
|
+
return val;
|
|
18
32
|
if (!val)
|
|
19
33
|
return null;
|
|
20
34
|
if (["crm.files"].includes(tableName)) {
|
|
21
35
|
return typeof val === "object" ? JSON.stringify(val) : val;
|
|
22
36
|
}
|
|
23
|
-
return typeof val === "object"
|
|
24
|
-
? JSON.stringify(val)?.substring?.(0, 30)
|
|
25
|
-
: val?.toString?.()?.substring?.(0, 30);
|
|
37
|
+
return typeof val === "object" ? null : val?.toString?.()?.substring?.(0, 30);
|
|
26
38
|
}
|
|
27
39
|
// extract titles and cls from form schema
|
|
28
40
|
// alt: extract table template from referer -> form
|
|
@@ -75,35 +87,74 @@ export default async function logChanges({ pg, table: table1, tokenData, referer
|
|
|
75
87
|
const body = await getTemplate("form", tokenData?.form);
|
|
76
88
|
const schema = body?.schema || body || {};
|
|
77
89
|
const titles = Object.keys(schema).reduce((acc, curr) => Object.assign(acc, { [curr]: schema[curr].title || schema[curr].ua }), {});
|
|
90
|
+
Object.assign(titles, defaultTitles);
|
|
78
91
|
const cls = Object.keys(schema)
|
|
79
92
|
.filter((el) => schema[el]?.data)
|
|
80
93
|
.reduce((acc, curr) => Object.assign(acc, { [curr]: schema[curr].data }), {});
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
// const original = JSON.parse(JSON.stringify(data));
|
|
95
|
+
const row = await metaFormat({
|
|
96
|
+
rows: [data].filter(Boolean),
|
|
97
|
+
cls,
|
|
98
|
+
sufix: false,
|
|
99
|
+
reassign: false,
|
|
100
|
+
}, pg).then((el) => el[0]);
|
|
101
|
+
const newObj1 = {};
|
|
102
|
+
const meta = await getMeta({ pg, table });
|
|
103
|
+
const columnTypes = (meta?.columns || []).reduce((acc, curr) => ({
|
|
104
|
+
...acc,
|
|
105
|
+
[curr.name]: pg?.pgType?.[curr.dataTypeID],
|
|
106
|
+
}), {});
|
|
107
|
+
if (type !== "DELETE") {
|
|
108
|
+
Object.keys(row || {})
|
|
109
|
+
.filter((key) => !systemColumns.includes(key))
|
|
110
|
+
.reduce((acc, curr) => {
|
|
111
|
+
Object.assign(newObj1, {
|
|
112
|
+
[titles[curr] || curr]: columnTypes[curr] === "geometry"
|
|
113
|
+
? {}
|
|
114
|
+
: {
|
|
115
|
+
value: getValue(row[curr], table, columnTypes),
|
|
116
|
+
hash: typeof row[curr] === "boolean" || row[curr]
|
|
117
|
+
? createHash("md5")
|
|
118
|
+
.update(JSON.stringify(row[curr]))
|
|
119
|
+
.digest("hex")
|
|
120
|
+
: null,
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
return acc;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
await Promise.all(Object.keys(row)
|
|
127
|
+
.filter((key) => row[key] && columnTypes[key] === "geometry")
|
|
128
|
+
.map(async (key) => pg
|
|
129
|
+
.query(typeof row[key] === "string" // binary geometry as string via update?
|
|
130
|
+
? "select st_asgeojson(st_pointonsurface($1))::json"
|
|
131
|
+
: "select st_asgeojson(st_pointonsurface(st_geomfromgeojson($1)))::json", [row[key]])
|
|
132
|
+
.then((el) => ({ key, geometry: el.rows[0].st_asgeojson })))).then((r) => r.forEach((curr) => {
|
|
133
|
+
const value = curr.geometry.coordinates.join(",");
|
|
134
|
+
const hash = createHash("md5")
|
|
135
|
+
.update(JSON.stringify(value))
|
|
136
|
+
.digest("hex");
|
|
137
|
+
if (titles[curr.key]) {
|
|
138
|
+
newObj1[titles[curr.key]] = { value, hash };
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
newObj1[curr.key] = { value, hash };
|
|
142
|
+
}
|
|
143
|
+
}));
|
|
144
|
+
const changesData = Object.keys(newObj1 || {})
|
|
145
|
+
.filter((key) => typeof newObj1?.[key] === "boolean" || newObj1?.[key])
|
|
146
|
+
.filter((key) => old[key] ? old[key].hash !== newObj1[key]?.hash : newObj1[key]?.hash)
|
|
147
|
+
.map((key) => ({
|
|
95
148
|
change_id: changeId,
|
|
96
|
-
entity_key:
|
|
97
|
-
value_old:
|
|
98
|
-
value_new:
|
|
99
|
-
value_hash:
|
|
100
|
-
? createHash("md5").update(JSON.stringify(newObj?.[el])).digest("hex")
|
|
101
|
-
: null,
|
|
149
|
+
entity_key: key,
|
|
150
|
+
value_old: old?.[key]?.value,
|
|
151
|
+
value_new: newObj1?.[key]?.value,
|
|
152
|
+
value_hash: newObj1?.[key]?.hash,
|
|
102
153
|
uid,
|
|
103
|
-
}))
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
154
|
+
}));
|
|
155
|
+
if (process.env.NODE_ENV === "test") {
|
|
156
|
+
console.log("changesData", changesData);
|
|
157
|
+
}
|
|
107
158
|
const res = await Promise.all(changesData.map(async (el) => {
|
|
108
159
|
const insertQuery = `insert into log.table_changes_data (${Object.entries(el)
|
|
109
160
|
?.map((key) => `"${key[0]}"`)
|
|
@@ -111,18 +162,18 @@ export default async function logChanges({ pg, table: table1, tokenData, referer
|
|
|
111
162
|
values (${Object.entries(el)
|
|
112
163
|
?.map((key, i) => `$${i + 1}`)
|
|
113
164
|
.join(",")}) returning *`;
|
|
114
|
-
const
|
|
165
|
+
const row1 = await pg
|
|
166
|
+
.query(insertQuery, [
|
|
115
167
|
...Object.entries(el).map((el1) => el1[1] &&
|
|
116
168
|
typeof el1[1] === "object" &&
|
|
117
169
|
(!Array.isArray(el1[1]) || typeof el1[1]?.[0] === "object")
|
|
118
170
|
? JSON.stringify(el1[1])
|
|
119
171
|
: el1[1]),
|
|
120
|
-
])
|
|
121
|
-
|
|
172
|
+
])
|
|
173
|
+
.then((el) => el.rows?.[0] || {});
|
|
174
|
+
return row1;
|
|
122
175
|
}));
|
|
123
|
-
const newData =
|
|
124
|
-
? {}
|
|
125
|
-
: (Array.isArray(res) ? res : [res]).reduce((acc, curr) => Object.assign(acc, { [curr.entity_key]: curr.value_new }), {});
|
|
176
|
+
const newData = (Array.isArray(res) ? res : [res]).reduce((acc, curr) => Object.assign(acc, { [curr.entity_key]: curr.value_new }), {});
|
|
126
177
|
// console.log('logChanges OK', type);
|
|
127
178
|
return {
|
|
128
179
|
change_id: changeId,
|
|
@@ -132,6 +183,7 @@ export default async function logChanges({ pg, table: table1, tokenData, referer
|
|
|
132
183
|
change_type: type,
|
|
133
184
|
old,
|
|
134
185
|
new: newData,
|
|
186
|
+
titles,
|
|
135
187
|
};
|
|
136
188
|
}
|
|
137
189
|
catch (err) {
|