@opengis/fastify-table 2.5.21 → 2.5.23
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.
- package/dist/server/plugins/file/uploadMultiPart.d.ts.map +1 -1
- package/dist/server/plugins/file/uploadMultiPart.js +7 -4
- package/dist/server/plugins/file/utils/inspectContent.d.ts +6 -0
- package/dist/server/plugins/file/utils/inspectContent.d.ts.map +1 -0
- package/dist/server/plugins/file/utils/inspectContent.js +58 -0
- package/dist/server/plugins/pg/funcs/autoIndex.d.ts.map +1 -1
- package/dist/server/plugins/pg/funcs/autoIndex.js +8 -3
- package/dist/server/plugins/pg/funcs/pool.d.ts.map +1 -1
- package/dist/server/plugins/pg/funcs/pool.js +3 -0
- package/dist/server/plugins/table/funcs/getFilterSQL/index.js +1 -1
- package/dist/server/plugins/table/funcs/getFilterSQLParametrized/formatValue.d.ts +2 -0
- package/dist/server/plugins/table/funcs/getFilterSQLParametrized/formatValue.d.ts.map +1 -0
- package/dist/server/plugins/table/funcs/getFilterSQLParametrized/formatValue.js +211 -0
- package/dist/server/plugins/table/funcs/getFilterSQLParametrized/getFilterList.d.ts +8 -0
- package/dist/server/plugins/table/funcs/getFilterSQLParametrized/getFilterList.d.ts.map +1 -0
- package/dist/server/plugins/table/funcs/getFilterSQLParametrized/getFilterList.js +90 -0
- package/dist/server/plugins/table/funcs/getFilterSQLParametrized/getFilterQuery.d.ts +17 -0
- package/dist/server/plugins/table/funcs/getFilterSQLParametrized/getFilterQuery.d.ts.map +1 -0
- package/dist/server/plugins/table/funcs/getFilterSQLParametrized/getFilterQuery.js +90 -0
- package/dist/server/plugins/table/funcs/getFilterSQLParametrized/getRangeQuery.d.ts +17 -0
- package/dist/server/plugins/table/funcs/getFilterSQLParametrized/getRangeQuery.d.ts.map +1 -0
- package/dist/server/plugins/table/funcs/getFilterSQLParametrized/getRangeQuery.js +340 -0
- package/dist/server/plugins/table/funcs/getFilterSQLParametrized/getTableSql.d.ts +9 -0
- package/dist/server/plugins/table/funcs/getFilterSQLParametrized/getTableSql.d.ts.map +1 -0
- package/dist/server/plugins/table/funcs/getFilterSQLParametrized/getTableSql.js +40 -0
- package/dist/server/plugins/table/funcs/getFilterSQLParametrized/index.d.ts +19 -0
- package/dist/server/plugins/table/funcs/getFilterSQLParametrized/index.d.ts.map +1 -0
- package/dist/server/plugins/table/funcs/getFilterSQLParametrized/index.js +156 -0
- package/dist/server/routes/table/functions/getData.d.ts.map +1 -1
- package/dist/server/routes/table/functions/getData.js +35 -29
- package/dist/server/routes/table/functions/prettify.d.ts +2 -0
- package/dist/server/routes/table/functions/prettify.d.ts.map +1 -0
- package/dist/server/routes/table/functions/prettify.js +11 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +2 -0
- package/package.json +1 -1
- package/dist/server/plugins/policy/funcs/checkSQL.d.ts +0 -8
- package/dist/server/plugins/policy/funcs/checkSQL.d.ts.map +0 -1
- package/dist/server/plugins/policy/funcs/checkSQL.js +0 -19
- package/dist/server/plugins/policy/sqlInjection.d.ts +0 -3
- package/dist/server/plugins/policy/sqlInjection.d.ts.map +0 -1
- package/dist/server/plugins/policy/sqlInjection.js +0 -33
- package/dist/server/plugins/table/funcs/getData.d.ts +0 -2
- package/dist/server/plugins/table/funcs/getData.d.ts.map +0 -1
- package/dist/server/plugins/table/funcs/getData.js +0 -25
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
/* eslint-disable no-restricted-globals */
|
|
2
|
+
const dateTypeList = [
|
|
3
|
+
"date",
|
|
4
|
+
"timestamp",
|
|
5
|
+
"timestamp without time zone",
|
|
6
|
+
"timestamp with time zone",
|
|
7
|
+
];
|
|
8
|
+
const numberTypeList = [
|
|
9
|
+
"float8",
|
|
10
|
+
"int4",
|
|
11
|
+
"int8",
|
|
12
|
+
"numeric",
|
|
13
|
+
"double precision",
|
|
14
|
+
"integer",
|
|
15
|
+
"bigint",
|
|
16
|
+
];
|
|
17
|
+
const isValidDate = (dateStr) => {
|
|
18
|
+
if (!dateStr) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
if (["min", "max", "cd", "cw", "cm", "cq", "cy"].includes(dateStr)) {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
// iso date: 2024-01-01
|
|
25
|
+
if (dateStr.includes("-")) {
|
|
26
|
+
return new Date(dateStr).toString() !== "Invalid Date";
|
|
27
|
+
}
|
|
28
|
+
// locale date: 01.01.2024
|
|
29
|
+
const [dd, mm, yyyy] = dateStr.split(".");
|
|
30
|
+
return new Date(`${yyyy}-${mm}-${dd}`).toString() !== "Invalid Date";
|
|
31
|
+
};
|
|
32
|
+
const isValidNumber = (numStr) => ["min", "max"].includes(numStr) ? true : !isNaN(numStr);
|
|
33
|
+
function dt(y, m, d) {
|
|
34
|
+
return new Date(Date.UTC(y, m, d)).toISOString().slice(0, 10);
|
|
35
|
+
}
|
|
36
|
+
const dp = {
|
|
37
|
+
d: new Date().getDate(),
|
|
38
|
+
w: new Date().getDate() - (new Date().getDay() || 7) + 1,
|
|
39
|
+
m: new Date().getMonth(),
|
|
40
|
+
q: parseFloat((new Date().getMonth() / 4).toFixed()) * 3,
|
|
41
|
+
y: new Date().getFullYear(),
|
|
42
|
+
};
|
|
43
|
+
function formatDateISOString(date) {
|
|
44
|
+
if (!date?.includes("."))
|
|
45
|
+
return date;
|
|
46
|
+
const [day, month, year] = date.split(".");
|
|
47
|
+
return `${year}-${month}-${day}`;
|
|
48
|
+
}
|
|
49
|
+
function checkValid(value, fieldType, filterType, sql, extra) {
|
|
50
|
+
const sep = (value.includes(",") ? "," : null) ||
|
|
51
|
+
(value.includes("_") ? "_" : null) ||
|
|
52
|
+
(value.includes("-") ? "-" : null);
|
|
53
|
+
// number range w/o valid separator => skip invalid filter
|
|
54
|
+
if (filterType === "range" && !sep) {
|
|
55
|
+
return { isvalid: false };
|
|
56
|
+
}
|
|
57
|
+
// date range, specific options: current day, week, month, year etc.
|
|
58
|
+
if (["date", "datepicker"].includes(filterType) && value === "cd") {
|
|
59
|
+
return {
|
|
60
|
+
min: dt(dp.y, dp.m, dp.d),
|
|
61
|
+
max: dt(dp.y, dp.m, dp.d),
|
|
62
|
+
isvalid: true,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (["date", "datepicker"].includes(filterType) && value === "cw") {
|
|
66
|
+
return {
|
|
67
|
+
min: dt(dp.y, dp.m, dp.w),
|
|
68
|
+
max: dt(dp.y, dp.m, dp.w + 6),
|
|
69
|
+
isvalid: true,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (["date", "datepicker"].includes(filterType) && value === "cm") {
|
|
73
|
+
return {
|
|
74
|
+
min: dt(dp.y, dp.m, 1),
|
|
75
|
+
max: dt(dp.y, dp.m + 1, 0),
|
|
76
|
+
isvalid: true,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
if (["date", "datepicker"].includes(filterType) && value === "cq") {
|
|
80
|
+
return {
|
|
81
|
+
min: dt(dp.y, dp.q, 1),
|
|
82
|
+
max: dt(dp.y, dp.q + 3, 0),
|
|
83
|
+
isvalid: true,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (["date", "datepicker"].includes(filterType) && value === "cy") {
|
|
87
|
+
return {
|
|
88
|
+
min: dt(dp.y, 0, 1),
|
|
89
|
+
max: dt(dp.y, 11, 31),
|
|
90
|
+
isvalid: true,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
// specific period from now - days, months, years
|
|
94
|
+
if (["date", "datepicker"].includes(filterType) &&
|
|
95
|
+
value.match(/^(?<val>[1-9]\d*)(?<unit>d|m|y)$/)?.groups?.unit) {
|
|
96
|
+
const { val, unit } = value.match(/^(?<val>[1-9]\d*)(?<unit>d|m|y)$/)?.groups || {};
|
|
97
|
+
const min = (unit === "d" ? dt(dp.y, dp.m, dp.d - +val) : null) ||
|
|
98
|
+
(unit === "m" ? dt(dp.y, dp.m - +val, dp.d) : null) ||
|
|
99
|
+
(unit === "y" ? dt(dp.y - +val, dp.m, dp.d) : null);
|
|
100
|
+
return {
|
|
101
|
+
min,
|
|
102
|
+
max: dt(dp.y, dp.m, dp.d),
|
|
103
|
+
isvalid: isValidDate(min),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
// specific quarter - before skip date value validation
|
|
107
|
+
if (["date", "datepicker"].includes(filterType) &&
|
|
108
|
+
value.match(/^(?<year>\d{4})-q(?<quarter>[1-4])$/)?.groups?.quarter) {
|
|
109
|
+
const { year, quarter } = value.match(/^(?<year>\d{4})-q(?<quarter>[1-4])$/)?.groups || {};
|
|
110
|
+
const startMonth = +quarter * 3;
|
|
111
|
+
return {
|
|
112
|
+
min: dt(year, startMonth - 3, 1),
|
|
113
|
+
max: dt(year, startMonth, 0),
|
|
114
|
+
isvalid: true,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
// date value validation
|
|
118
|
+
if (["date", "datepicker"].includes(filterType) &&
|
|
119
|
+
!sep &&
|
|
120
|
+
!isValidDate(value)) {
|
|
121
|
+
return { isvalid: false };
|
|
122
|
+
}
|
|
123
|
+
// specific date / day
|
|
124
|
+
if (["date", "datepicker"].includes(filterType) &&
|
|
125
|
+
value.match(/^\d{4}-\d{2}-\d{2}$/)?.[0]) {
|
|
126
|
+
return {
|
|
127
|
+
min: new Date(value).toISOString().split("T")[0],
|
|
128
|
+
max: new Date(value).toISOString().split("T")[0],
|
|
129
|
+
isvalid: true,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
// specific month
|
|
133
|
+
if (["date", "datepicker"].includes(filterType) &&
|
|
134
|
+
value.match(/^\d{4}-\d{2}$/)?.[0]) {
|
|
135
|
+
return {
|
|
136
|
+
min: new Date(value).toISOString().split("T")[0],
|
|
137
|
+
max: dt(new Date(value).getFullYear(), new Date(value).getMonth() + 1, 0),
|
|
138
|
+
isvalid: true,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
// specific year
|
|
142
|
+
if (["date", "datepicker"].includes(filterType) &&
|
|
143
|
+
value.match(/^\d{4}$/)?.[0]) {
|
|
144
|
+
return {
|
|
145
|
+
min: dt(value, 0, 1),
|
|
146
|
+
max: dt(value, 11, 31),
|
|
147
|
+
isvalid: true,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
if (sep) {
|
|
151
|
+
const [minValue = "min", maxValue = "max"] = value.split(sep);
|
|
152
|
+
// range for numbers
|
|
153
|
+
if (filterType === "range" && fieldType) {
|
|
154
|
+
const isvalid = (numberTypeList.includes(fieldType) || sql || extra) &&
|
|
155
|
+
isValidNumber(minValue) &&
|
|
156
|
+
isValidNumber(maxValue);
|
|
157
|
+
return { min: minValue, max: maxValue, isvalid };
|
|
158
|
+
}
|
|
159
|
+
// date range, example: 01.01.2024-31.12.2024
|
|
160
|
+
if (["date", "datepicker"].includes(filterType)) {
|
|
161
|
+
const min = minValue === "min" ? minValue : formatDateISOString(minValue);
|
|
162
|
+
const max = maxValue === "max" ? maxValue : formatDateISOString(maxValue);
|
|
163
|
+
const isvalid = fieldType &&
|
|
164
|
+
(dateTypeList.includes(fieldType) || sql || extra) &&
|
|
165
|
+
isValidDate(min) &&
|
|
166
|
+
isValidDate(max);
|
|
167
|
+
return { min, max, isvalid };
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return { isvalid: false };
|
|
171
|
+
}
|
|
172
|
+
export default function getRangeQuery({ value, name, fieldType, filterType, sql, extra, pk, args: argsParams, }) {
|
|
173
|
+
const { min, max, isvalid } = checkValid(value, fieldType, filterType, sql, extra);
|
|
174
|
+
if (!isvalid) {
|
|
175
|
+
return { query: "false" };
|
|
176
|
+
}
|
|
177
|
+
const args = Array.from(argsParams || []);
|
|
178
|
+
const checkBoth = sql && typeof sql === "string" && sql.includes("$1") && sql.includes("$2");
|
|
179
|
+
// with sql subquery
|
|
180
|
+
if (filterType &&
|
|
181
|
+
["date", "datepicker"].includes(filterType) &&
|
|
182
|
+
typeof sql === "string") {
|
|
183
|
+
if (checkBoth) {
|
|
184
|
+
args.push(min);
|
|
185
|
+
args.push(max);
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
args.push(min || max);
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
query: sql
|
|
192
|
+
.replace(/\$1/g, `$${checkBoth ? args.length - 1 : args.length}::date`)
|
|
193
|
+
.replace(/\$2/g, `$${args.length}::date`),
|
|
194
|
+
values: checkBoth ? [min, max] : [min || max],
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
// with sql subquery
|
|
198
|
+
if (filterType && ["range"].includes(filterType) && sql) {
|
|
199
|
+
if (checkBoth) {
|
|
200
|
+
args.push(min);
|
|
201
|
+
args.push(max);
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
args.push(min || max);
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
query: sql
|
|
208
|
+
.replace(/\$1/g, `${checkBoth ? args.length - 1 : args.length}`)
|
|
209
|
+
.replace(/\$2/g, `${args.length}`),
|
|
210
|
+
values: checkBoth ? [min, max] : [min || max],
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
// preset date values
|
|
214
|
+
if (filterType &&
|
|
215
|
+
["date", "datepicker"].includes(filterType) &&
|
|
216
|
+
["cd", "cw", "cm", "cq", "cy"].includes(value)) {
|
|
217
|
+
if (value === "cd") {
|
|
218
|
+
args.push(min);
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
args.push(min);
|
|
222
|
+
args.push(max);
|
|
223
|
+
}
|
|
224
|
+
const query = value === "cd"
|
|
225
|
+
? `${name}::date = $${args.length}::date`
|
|
226
|
+
: `${name}::date between $${args.length - 1}::date and $${args.length}::date`;
|
|
227
|
+
return { query, values: value === "cd" ? [min] : [min, max] };
|
|
228
|
+
}
|
|
229
|
+
// extra columns, example: crm.extra_data
|
|
230
|
+
if (filterType &&
|
|
231
|
+
["date", "datepicker"].includes(filterType) &&
|
|
232
|
+
extra?.table &&
|
|
233
|
+
pk) {
|
|
234
|
+
const where = [];
|
|
235
|
+
const values = [];
|
|
236
|
+
args.push(name);
|
|
237
|
+
const nameIdx = args.length;
|
|
238
|
+
if (max && min && min === max) {
|
|
239
|
+
args.push(value);
|
|
240
|
+
values.push(value);
|
|
241
|
+
where.push(`value_date::date > $${args.length}::date`);
|
|
242
|
+
}
|
|
243
|
+
else if (max === "max") {
|
|
244
|
+
args.push(min);
|
|
245
|
+
values.push(min);
|
|
246
|
+
where.push(`value_date::date > $${args.length}::date`);
|
|
247
|
+
}
|
|
248
|
+
else if (min === "min") {
|
|
249
|
+
args.push(max);
|
|
250
|
+
values.push(max);
|
|
251
|
+
where.push(`value_date::date < $${args.length}::date`);
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
args.push(min);
|
|
255
|
+
values.push(min);
|
|
256
|
+
args.push(max);
|
|
257
|
+
values.push(max);
|
|
258
|
+
where.push(`value_date::date between $${args.length - 1}::date and $${args.length}::date`);
|
|
259
|
+
}
|
|
260
|
+
const query = `${pk} in (select object_id from ${extra.table} where property_key=$${nameIdx} and ${where.join(" AND ") || "true"})`;
|
|
261
|
+
return { query, values };
|
|
262
|
+
}
|
|
263
|
+
// extra columns, example: crm.extra_data
|
|
264
|
+
if (filterType && ["range"].includes(filterType) && extra?.table && pk) {
|
|
265
|
+
const where = [];
|
|
266
|
+
const values = [];
|
|
267
|
+
args.push(name);
|
|
268
|
+
const nameIdx = args.length;
|
|
269
|
+
if (max && min && min === max) {
|
|
270
|
+
args.push(value);
|
|
271
|
+
values.push(value);
|
|
272
|
+
where.push(`value_text::numeric > $${args.length}`);
|
|
273
|
+
}
|
|
274
|
+
else if (max === "max") {
|
|
275
|
+
args.push(min);
|
|
276
|
+
values.push(min);
|
|
277
|
+
where.push(`value_text::numeric > $${args.length}`);
|
|
278
|
+
}
|
|
279
|
+
else if (min === "min") {
|
|
280
|
+
args.push(max);
|
|
281
|
+
values.push(max);
|
|
282
|
+
where.push(`value_text::numeric < $${args.length}`);
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
args.push(min);
|
|
286
|
+
values.push(min);
|
|
287
|
+
args.push(max);
|
|
288
|
+
values.push(max);
|
|
289
|
+
where.push(`value_text::numeric between $${args.length - 1} and $${args.length}`);
|
|
290
|
+
}
|
|
291
|
+
const query = `${pk} in (select object_id from ${extra.table} where property_key=$${nameIdx} and ${where.join(" AND ") || "true"} )`;
|
|
292
|
+
return { query, values };
|
|
293
|
+
}
|
|
294
|
+
// same date
|
|
295
|
+
if (filterType &&
|
|
296
|
+
["date", "datepicker"].includes(filterType) &&
|
|
297
|
+
max &&
|
|
298
|
+
min &&
|
|
299
|
+
min === max) {
|
|
300
|
+
args.push(min);
|
|
301
|
+
return { query: `${name}::date = $${args.length}::date`, values: [min] };
|
|
302
|
+
}
|
|
303
|
+
// skip, same as 1=1
|
|
304
|
+
if (filterType &&
|
|
305
|
+
["range"].includes(filterType) &&
|
|
306
|
+
min === "min" &&
|
|
307
|
+
max === "max") {
|
|
308
|
+
return { query: "true" };
|
|
309
|
+
}
|
|
310
|
+
// default
|
|
311
|
+
if (filterType && max === "max") {
|
|
312
|
+
args.push(min);
|
|
313
|
+
const query = ["date", "datepicker"].includes(filterType)
|
|
314
|
+
? `${name} >= $${args.length}::date`
|
|
315
|
+
: `${name} >= $${args.length}`;
|
|
316
|
+
return {
|
|
317
|
+
query,
|
|
318
|
+
values: [min],
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
if (filterType && min === "min") {
|
|
322
|
+
args.push(max);
|
|
323
|
+
const query = ["date", "datepicker"].includes(filterType)
|
|
324
|
+
? `${name} <= $${args.length}::date`
|
|
325
|
+
: `${name} <= $${args.length}`;
|
|
326
|
+
return { query, values: [max] };
|
|
327
|
+
}
|
|
328
|
+
if (filterType && ["date", "datepicker"].includes(filterType)) {
|
|
329
|
+
args.push(min);
|
|
330
|
+
args.push(max);
|
|
331
|
+
return {
|
|
332
|
+
query: `${name}::date between $${args.length - 1}::date and $${args.length}::date`,
|
|
333
|
+
values: [min, max],
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
return {
|
|
337
|
+
query: `${name} between $${args.length - 1} and $${args.length}`,
|
|
338
|
+
values: [min, max],
|
|
339
|
+
};
|
|
340
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ExtendedPG } from "../../../../types/core.js";
|
|
2
|
+
declare function getTableSql({ pg, body, table, fields, }: {
|
|
3
|
+
pg: ExtendedPG;
|
|
4
|
+
body: Record<string, any>;
|
|
5
|
+
table: string;
|
|
6
|
+
fields: any[];
|
|
7
|
+
}): Promise<any>;
|
|
8
|
+
export default getTableSql;
|
|
9
|
+
//# sourceMappingURL=getTableSql.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getTableSql.d.ts","sourceRoot":"","sources":["../../../../../../server/plugins/table/funcs/getFilterSQLParametrized/getTableSql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAqB5D,iBAAe,WAAW,CAAC,EACzB,EAAqB,EACrB,IAAI,EACJ,KAAK,EACL,MAAM,GACP,EAAE;IACD,EAAE,EAAE,UAAU,CAAC;IACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,GAAG,EAAE,CAAC;CACf,gBA8BA;AAED,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import pgClients from "../../../pg/pgClients.js";
|
|
2
|
+
function getTable(table) {
|
|
3
|
+
const result = table
|
|
4
|
+
?.toLowerCase()
|
|
5
|
+
?.replace(/[\n\r]+/g, " ")
|
|
6
|
+
?.split(" from ")
|
|
7
|
+
?.filter((el) => /^[a-z0-9_]+\.[a-z0-9_]+/.test(el))
|
|
8
|
+
?.map((el) => el.split(/[ )]/)[0]);
|
|
9
|
+
return result;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* @param {Number} opt.json - (1|0) 1 - Результат - Object, 0 - String
|
|
13
|
+
* @param {String} opt.query - запит до таблиці
|
|
14
|
+
* @param {String} opt.hash - інформація з хешу по запиту
|
|
15
|
+
*/
|
|
16
|
+
const tableSql = {};
|
|
17
|
+
async function getTableSql({ pg = pgClients.client, body, table, fields, }) {
|
|
18
|
+
if (tableSql[table])
|
|
19
|
+
return tableSql[table];
|
|
20
|
+
const fieldList = fields.map((el) => el.name);
|
|
21
|
+
const tableList = body?.sql
|
|
22
|
+
?.map((el) => getTable(el.sql))
|
|
23
|
+
.reduce((acc, el) => acc.concat(el), [])
|
|
24
|
+
.filter((el) => fieldList.includes(pg.pk?.[el]));
|
|
25
|
+
if (!tableList) {
|
|
26
|
+
tableSql[table] = [];
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
const data = await Promise.all(tableList?.map(async (tableEl) => {
|
|
30
|
+
const { fields: fieldsEl } = await pg.query(`select * from ${tableEl} limit 0`);
|
|
31
|
+
return fieldsEl.map((el) => ({
|
|
32
|
+
name: el.name,
|
|
33
|
+
table: tableEl,
|
|
34
|
+
pk: pg.pk?.[tableEl],
|
|
35
|
+
}));
|
|
36
|
+
}));
|
|
37
|
+
tableSql[table] = data.reduce((acc, el) => acc.concat(el), []);
|
|
38
|
+
return tableSql[table];
|
|
39
|
+
}
|
|
40
|
+
export default getTableSql;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ExtendedPG } from "../../../../types/core.js";
|
|
2
|
+
export default function getFilterSQLParametrized({ table, filter, pg, search, searchColumn: searchColumn1, filterList, query, custom, state, uid, objectId, }: {
|
|
3
|
+
table: string | undefined;
|
|
4
|
+
filter?: string;
|
|
5
|
+
pg: ExtendedPG;
|
|
6
|
+
search?: string;
|
|
7
|
+
searchColumn?: string;
|
|
8
|
+
filterList?: any[];
|
|
9
|
+
query?: string;
|
|
10
|
+
custom?: string;
|
|
11
|
+
state?: string;
|
|
12
|
+
uid?: string;
|
|
13
|
+
objectId?: string;
|
|
14
|
+
order?: string;
|
|
15
|
+
}): Promise<{
|
|
16
|
+
q: string;
|
|
17
|
+
args: any[];
|
|
18
|
+
}>;
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../server/plugins/table/funcs/getFilterSQLParametrized/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAgD5D,wBAA8B,wBAAwB,CAAC,EACrD,KAAK,EACL,MAAM,EACN,EAAqB,EACrB,MAAM,EACN,YAAY,EAAE,aAAa,EAC3B,UAAU,EACV,KAAK,EACL,MAAM,EACN,KAAK,EACL,GAAG,EACH,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,UAAU,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;;;GAoMA"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { BadRequestError } from "../../../../../errors.js";
|
|
2
|
+
import getTemplate from "../getTemplate.js";
|
|
3
|
+
import pgClients from "../../../pg/pgClients.js";
|
|
4
|
+
import config from "../../../../../config.js";
|
|
5
|
+
// filter util
|
|
6
|
+
import getTableSql from "./getTableSql.js";
|
|
7
|
+
import getFilterQuery from "./getFilterQuery.js";
|
|
8
|
+
import getFilterList from "./getFilterList.js";
|
|
9
|
+
const checkInline = {};
|
|
10
|
+
const defaultTable = "crm.extra_data";
|
|
11
|
+
function getExtraQuery({ columns, schema, table, pk, args, }) {
|
|
12
|
+
const extraColumns = Object.keys(schema || {})
|
|
13
|
+
.filter((key) => !columns.map((el) => el?.name).includes(key))
|
|
14
|
+
.map((key) => ({ name: key, type: schema[key]?.type }));
|
|
15
|
+
extraColumns.forEach((col) => args.push(col.name));
|
|
16
|
+
const q = extraColumns.reduce((acc, curr) => {
|
|
17
|
+
args.push(curr.name);
|
|
18
|
+
return acc.push(`,(select value_text as "${curr.name}" from ${table} where property_key=$${args.length} and object_id=t.${pk} limit 1)`);
|
|
19
|
+
}, []);
|
|
20
|
+
return {
|
|
21
|
+
q,
|
|
22
|
+
args,
|
|
23
|
+
extraColumns,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export default async function getFilterSQLParametrized({ table, filter, pg = pgClients.client, search, searchColumn: searchColumn1, filterList, query, custom, state, uid, objectId, }) {
|
|
27
|
+
if (!table) {
|
|
28
|
+
throw BadRequestError("param table is required");
|
|
29
|
+
}
|
|
30
|
+
const args = [];
|
|
31
|
+
const body = await getTemplate("table", table);
|
|
32
|
+
const loadTemplate = body?.form
|
|
33
|
+
? await getTemplate("form", body?.form)
|
|
34
|
+
: null;
|
|
35
|
+
const { extra } = loadTemplate || {};
|
|
36
|
+
const extraDataTable = extra
|
|
37
|
+
? config.extraData?.[body.table] ||
|
|
38
|
+
config.extraData?.[body.table.split(".").shift()] ||
|
|
39
|
+
config.extraData?.default ||
|
|
40
|
+
config.extraData ||
|
|
41
|
+
defaultTable
|
|
42
|
+
: undefined;
|
|
43
|
+
const fieldsModel = body?.table && pg.pk?.[body.table]
|
|
44
|
+
? await pg
|
|
45
|
+
.query(`select * from ${body.table} limit 0`)
|
|
46
|
+
.then((r) => r.fields || [])
|
|
47
|
+
: [];
|
|
48
|
+
const { q: extraSqlColumns, extraColumns = [] } = extraDataTable && pg.pk?.[extraDataTable] && pg.pk?.[body.table || table]
|
|
49
|
+
? getExtraQuery({
|
|
50
|
+
columns: fieldsModel,
|
|
51
|
+
schema: loadTemplate?.schema,
|
|
52
|
+
table: extraDataTable,
|
|
53
|
+
pk: pg.pk[body.table || table],
|
|
54
|
+
args,
|
|
55
|
+
})
|
|
56
|
+
: { q: null };
|
|
57
|
+
// check sql inline fields count
|
|
58
|
+
if (body?.table && !checkInline[body?.table] && body?.sql?.length) {
|
|
59
|
+
const filterSql = body.sql.filter((el) => !el?.disabled && (el.inline ?? true));
|
|
60
|
+
const sqlTable = filterSql
|
|
61
|
+
.map((el, i) => ` left join lateral (${el.sql}) ${el.name || `t${i}`} on 1=1 `)
|
|
62
|
+
?.join("") || "";
|
|
63
|
+
const d = await Promise.all(filterSql.map((el, i) => pg
|
|
64
|
+
.query(`select ${el.name || `t${i}`}.* from(select * from ${body.table})t ${sqlTable} limit 0`)
|
|
65
|
+
.then((item) => item.fields)));
|
|
66
|
+
d.forEach((el, i) => {
|
|
67
|
+
filterSql[i].inline = el.length === 1;
|
|
68
|
+
filterSql[i].fields = el.map((f) => f.name);
|
|
69
|
+
});
|
|
70
|
+
checkInline[body?.table] = body.sql;
|
|
71
|
+
}
|
|
72
|
+
else if (checkInline[body?.table]) {
|
|
73
|
+
body.sql = checkInline[body?.table];
|
|
74
|
+
}
|
|
75
|
+
const sqlTable = body?.sql?.length
|
|
76
|
+
? body.sql
|
|
77
|
+
.filter((el) => !el?.disabled &&
|
|
78
|
+
!el.inline &&
|
|
79
|
+
el?.sql?.replace &&
|
|
80
|
+
(!el.sql.includes("{{uid}}") || uid))
|
|
81
|
+
.map((el, i) => ` left join lateral (${el.sql.replace("{{uid}}", uid)}) ${el.name || `t${i}`} on 1=1 `)
|
|
82
|
+
.join("")
|
|
83
|
+
: null;
|
|
84
|
+
const sqlInline = body?.sql
|
|
85
|
+
?.filter?.((el) => el.inline)
|
|
86
|
+
.map((el) => `,(${el.sql})`)
|
|
87
|
+
.join("");
|
|
88
|
+
const fieldQuery = `select * ${extraSqlColumns || ""} ${sqlInline || ""} from ${body?.table || table} t ${sqlTable || ""} limit 0`;
|
|
89
|
+
const fields = await pg.query(fieldQuery).then((r) => r.fields || []);
|
|
90
|
+
const autoSearchColumn = fields
|
|
91
|
+
?.filter((el) => pg.pgType?.[el.dataTypeID] === "text")
|
|
92
|
+
?.map((el) => `"${el.name}"`)
|
|
93
|
+
.join(",");
|
|
94
|
+
const searchColumn = searchColumn1 ||
|
|
95
|
+
body?.search_column ||
|
|
96
|
+
body?.meta?.search ||
|
|
97
|
+
autoSearchColumn;
|
|
98
|
+
const fieldsList = (fieldsModel || fields)?.map((el) => el.name);
|
|
99
|
+
const where = [];
|
|
100
|
+
try {
|
|
101
|
+
const tableSQL = await getTableSql({
|
|
102
|
+
pg,
|
|
103
|
+
body,
|
|
104
|
+
table,
|
|
105
|
+
fields,
|
|
106
|
+
});
|
|
107
|
+
if (search && searchColumn && typeof search === "string") {
|
|
108
|
+
args.push(`%${decodeURIComponent(search.replace(/%/g, "%25")).replace(/%/g, "\\%")}%`);
|
|
109
|
+
where.push(`(${searchColumn
|
|
110
|
+
.split(",")
|
|
111
|
+
?.map((name) => {
|
|
112
|
+
const { pk } = tableSQL.find((el) => el.name === name) || {};
|
|
113
|
+
return pk && !fieldsList.includes(name)
|
|
114
|
+
? `${pk} in (select ${pk} from (${fieldQuery.replace(/limit 0/g, "")} where ${name} ilike $${args.length} )q where 1=1)`
|
|
115
|
+
: `${name}::text ilike $${args.length}`;
|
|
116
|
+
})
|
|
117
|
+
.join(" or ")})`);
|
|
118
|
+
}
|
|
119
|
+
const filterList1 = await getFilterList({
|
|
120
|
+
table,
|
|
121
|
+
uid,
|
|
122
|
+
filterList,
|
|
123
|
+
extraColumns,
|
|
124
|
+
extraDataTable,
|
|
125
|
+
}, pg);
|
|
126
|
+
const modelQuery = body?.model || body?.table || table;
|
|
127
|
+
const filters = getFilterQuery({
|
|
128
|
+
filter,
|
|
129
|
+
table: modelQuery,
|
|
130
|
+
tableSQL,
|
|
131
|
+
fields,
|
|
132
|
+
filterList: filterList1,
|
|
133
|
+
uid,
|
|
134
|
+
objectId,
|
|
135
|
+
args,
|
|
136
|
+
}, pg);
|
|
137
|
+
if (body?.filterCustom?.length && custom) {
|
|
138
|
+
where.push(body.filterCustom?.find((el) => el.name === custom)?.sql);
|
|
139
|
+
}
|
|
140
|
+
if (body?.filterState?.length && state) {
|
|
141
|
+
where.push(body.filterState?.find((el) => el.name === state)?.sql);
|
|
142
|
+
}
|
|
143
|
+
const filterQuery = filters
|
|
144
|
+
.filter((el) => el.query)
|
|
145
|
+
.map((el) => `${el.query}`)
|
|
146
|
+
.join(" and ");
|
|
147
|
+
const q = where
|
|
148
|
+
.concat([body?.query, query, filterQuery])
|
|
149
|
+
.filter(Boolean)
|
|
150
|
+
.join(" and ");
|
|
151
|
+
return { q, args };
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
throw err;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getData.d.ts","sourceRoot":"","sources":["../../../../../server/routes/table/functions/getData.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"getData.d.ts","sourceRoot":"","sources":["../../../../../server/routes/table/functions/getData.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AA0FzD,wBAA8B,OAAO,CACnC,EACE,EAAqB,EACrB,MAAM,EACN,KAAK,EACL,EAAE,EACF,OAAY,EACZ,KAAU,EACV,IAAS,EACT,YAAY,EACZ,YAAY,EACZ,KAAY,EACZ,UAAU,EACV,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,gBAAgB,EAC7B,OAAO,EAAE,YAAY,EACrB,QAAgB,GACjB,EAAE;IACD,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,MAAM,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,EACD,KAAK,CAAC,EAAE,YAAY,EACpB,MAAM,CAAC,EAAE,GAAG,gBA64Bb"}
|