@opengis/fastify-table 1.4.9 → 1.4.10
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/package.json +9 -10
- package/server/plugins/file/providers/index.js +0 -1
- package/server/routes/table/controllers/filter.js +19 -18
- package/server/routes/table/functions/getData.js +12 -3
- package/server/routes/table/index.js +2 -3
- package/server/routes/table/schema.js +30 -39
- package/server/routes/table/controllers/tableFilter.js +0 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengis/fastify-table",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "core-plugins",
|
|
6
6
|
"keywords": [
|
|
@@ -26,14 +26,20 @@
|
|
|
26
26
|
"test:routes": "node --test .\\test\\routes",
|
|
27
27
|
"test:functions": "node --test .\\test\\functions",
|
|
28
28
|
"compress": "node compress.js",
|
|
29
|
-
"dev": "
|
|
29
|
+
"dev": "set NODE_ENV=development&& node server.js"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
+
"@aws-sdk/client-s3": "3.554.0",
|
|
32
33
|
"@fastify/http-proxy": "11.1.2",
|
|
34
|
+
"@fastify/multipart": "9.0.3",
|
|
35
|
+
"@grpc/grpc-js": "1.10.6",
|
|
36
|
+
"@grpc/proto-loader": "0.7.12",
|
|
33
37
|
"dotenv": "16.5.0",
|
|
34
38
|
"fastify": "5.3.3",
|
|
35
39
|
"fastify-plugin": "5.0.1",
|
|
40
|
+
"formidable": "3.5.1",
|
|
36
41
|
"handlebars": "4.7.8",
|
|
42
|
+
"image-size": "1.2.0",
|
|
37
43
|
"ioredis": "5.3.2",
|
|
38
44
|
"js-yaml": "4.1.0",
|
|
39
45
|
"markdown-it": "14.1.0",
|
|
@@ -42,16 +48,9 @@
|
|
|
42
48
|
"pino-abstract-transport": "2.0.0",
|
|
43
49
|
"promised-handlebars": "2.0.1",
|
|
44
50
|
"qrcode": "1.5.4",
|
|
45
|
-
"uglify-js": "3.19.3"
|
|
46
|
-
"@aws-sdk/client-s3": "3.554.0",
|
|
47
|
-
"@fastify/multipart": "9.0.3",
|
|
48
|
-
"@grpc/grpc-js": "1.10.6",
|
|
49
|
-
"@grpc/proto-loader": "0.7.12",
|
|
50
|
-
"formidable": "3.5.1",
|
|
51
|
-
"image-size": "1.2.0"
|
|
51
|
+
"uglify-js": "3.19.3"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"cross-env": "7.0.3",
|
|
55
54
|
"eslint": "8.49.0",
|
|
56
55
|
"eslint-config-airbnb": "19.0.4"
|
|
57
56
|
},
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
logger, autoIndex, getSelect, getTemplate, getSelectVal, pgClients,
|
|
3
|
+
} from '../../../../utils.js';
|
|
2
4
|
|
|
3
5
|
export default async function filterAPI(req) {
|
|
4
6
|
const time = Date.now();
|
|
@@ -21,8 +23,10 @@ export default async function filterAPI(req) {
|
|
|
21
23
|
const filters = (loadTable?.filter_list || loadTable?.filters || loadTable?.filterList || []).concat(loadTable?.filterSql || []);
|
|
22
24
|
|
|
23
25
|
// admin.custom_column - user filter NA-165
|
|
24
|
-
const { rows: properties = [] } = await pg.query(
|
|
25
|
-
properties.forEach((row) => filters.push({
|
|
26
|
+
const { rows: properties = [] } = await pg.query('select column_id, name, title, format, data from admin.custom_column where entity=$1 and uid=$2 and filter', [params.table, user?.uid]);
|
|
27
|
+
properties.forEach((row) => filters.push({
|
|
28
|
+
id: row.name, name: row.name, ua: row.title, type: row.format, data: row.data,
|
|
29
|
+
}));
|
|
26
30
|
|
|
27
31
|
// KRYVYIRIH-231
|
|
28
32
|
autoIndex({ table: loadTable.table, columns: filters.filter((el) => columns?.find?.((item) => item?.name === el.name)) })
|
|
@@ -43,7 +47,7 @@ export default async function filterAPI(req) {
|
|
|
43
47
|
const { dataTypeID } = columns.find((item) => item.name === el.id) || {};
|
|
44
48
|
|
|
45
49
|
if (el.extra && Array.isArray(cls?.arr || cls)) {
|
|
46
|
-
const countArr = await pg.query(
|
|
50
|
+
const countArr = await pg.query('select value_text as id, count(*) from crm.extra_data where property_key=$1 and property_entity=$2 group by value_text', [el.id, loadTable.table]);
|
|
47
51
|
const options = countArr.rows.map(cel => {
|
|
48
52
|
const data = (cls?.arr || cls).find(c => c.id === cel.id);
|
|
49
53
|
return { ...cel, ...data };
|
|
@@ -73,12 +77,10 @@ export default async function filterAPI(req) {
|
|
|
73
77
|
return { ...cel, ...data };
|
|
74
78
|
});
|
|
75
79
|
Object.assign(el, { options });
|
|
76
|
-
|
|
77
80
|
}));
|
|
78
81
|
|
|
79
82
|
const q = ((loadTable?.filterState || []).concat(loadTable?.filterCustom || [])).filter((el) => el.name && el.sql).map((el) => `select count(*), '${el.name}' as name from (${optimizedSQL})q where ${el.sql}`).join(' union all ');
|
|
80
83
|
|
|
81
|
-
|
|
82
84
|
const { rows = [], timeout: timeout1 } = q ? await pg.queryCache(q) : {};
|
|
83
85
|
if (timeout1) logger.file('timeout/filter', { table: params.table, type: 'state/custom' });
|
|
84
86
|
|
|
@@ -89,7 +91,6 @@ export default async function filterAPI(req) {
|
|
|
89
91
|
});
|
|
90
92
|
}
|
|
91
93
|
|
|
92
|
-
|
|
93
94
|
const sqlList = loadTable?.sql
|
|
94
95
|
?.filter((el) => !el.disabled && el?.sql?.replace)
|
|
95
96
|
?.map((el, i) => ` left join lateral (${el.filter ? el.sql.replace(/limit 1/ig, '') : el.sql}) as ${el.name || `t${i + 1}`} on 1=1 `)
|
|
@@ -97,23 +98,23 @@ export default async function filterAPI(req) {
|
|
|
97
98
|
|
|
98
99
|
// percentile_cont - alternative
|
|
99
100
|
await Promise.all(filters.filter((el) => el.name && el.type === 'Range' && fields?.find?.((item) => item?.name === el.name)).map(async (el) => {
|
|
100
|
-
|
|
101
|
-
|
|
101
|
+
const data = await pg.queryCache(
|
|
102
|
+
`select array[
|
|
102
103
|
min(${el.name}),
|
|
103
104
|
percentile_disc(0.25) within group (order by ${el.name}),
|
|
104
105
|
percentile_disc(0.5) within group (order by ${el.name}),
|
|
105
106
|
percentile_disc(0.75) within group (order by ${el.name}),
|
|
106
107
|
max(${el.name})
|
|
107
108
|
] as range from ${loadTable.table} ${sqlList && false ? ` t ${sqlList}` : ''} where ${loadTable.query || '1=1'}`,
|
|
108
|
-
{ table: loadTable.table }
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
109
|
+
{ table: loadTable.table },
|
|
110
|
+
).then(el => {
|
|
111
|
+
if (el.timeout) {
|
|
112
|
+
logger.file('timeout/filter', { table: params.table, type: 'Range', filter: el.name });
|
|
113
|
+
return el;
|
|
114
|
+
}
|
|
115
|
+
return el.rows?.[0]?.range;
|
|
116
|
+
});
|
|
115
117
|
Object.assign(el, { data });
|
|
116
|
-
|
|
117
118
|
}));
|
|
118
119
|
|
|
119
120
|
const sqlFilters = (loadTable?.filterCustom || []).filter((el) => el.name && el.sql);
|
|
@@ -136,4 +137,4 @@ export default async function filterAPI(req) {
|
|
|
136
137
|
inline: loadTable?.filterInline,
|
|
137
138
|
state: loadTable?.filterState,
|
|
138
139
|
};
|
|
139
|
-
}
|
|
140
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
config, getTemplate, getFilterSQL, getMeta, metaFormat, getAccess, setToken, gisIRColumn, applyHook, handlebars, handlebarsSync, getSelect, setOpt, getOpt, pgClients,
|
|
2
|
+
config, getTemplate, getFilterSQL, getMeta, metaFormat, getAccess, setToken, gisIRColumn, applyHook, handlebars, handlebarsSync, getSelect, setOpt, getOpt, pgClients, logger, getFilter,
|
|
3
3
|
} from '../../../../utils.js';
|
|
4
4
|
|
|
5
5
|
import extraDataGet from '../../../plugins/extra/extraDataGet.js';
|
|
@@ -78,13 +78,22 @@ export default async function dataAPI(req, reply, called) {
|
|
|
78
78
|
table, columns = [], sql, cardSql, form, meta, sqlColumns, public: ispublic, editable = false,
|
|
79
79
|
} = loadTable || hookData || tokenData || params;
|
|
80
80
|
|
|
81
|
-
const filters = ((body?.filter_list || [])
|
|
81
|
+
/* const filters = ((body?.filter_list || [])
|
|
82
82
|
.concat(body?.filterInline || [])
|
|
83
83
|
.concat(body?.filterCustom || [])
|
|
84
84
|
.concat(body?.filterState || [])
|
|
85
85
|
.concat(body?.filterList || [])
|
|
86
86
|
.concat(body?.filters || [])
|
|
87
|
-
).filter(el => el.id || el.name);
|
|
87
|
+
).filter(el => el.id || el.name); */
|
|
88
|
+
|
|
89
|
+
if (body?.filter_list || body?.filterList) {
|
|
90
|
+
console.warn('invalid filters in template: filter_list / filterList');
|
|
91
|
+
logger.file('crud/warning', { msg: 'invalid filters', template: tokenData?.table || hookData?.table || params.table });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const { list: filters = [] } = await getFilter({
|
|
95
|
+
pg, table: tokenData?.table || hookData?.table || params.table, user,
|
|
96
|
+
}) || {};
|
|
88
97
|
|
|
89
98
|
const tableMeta = await getMeta({ pg, table });
|
|
90
99
|
timeArr.push(Date.now());
|
|
@@ -5,7 +5,6 @@ import cardData from './controllers/cardData.js';
|
|
|
5
5
|
import dataInfo from './controllers/dataInfo.js';
|
|
6
6
|
import tableInfo from './controllers/tableInfo.js';
|
|
7
7
|
import tokenInfo from './controllers/tokenInfo.js';
|
|
8
|
-
import tableFilter from './controllers/tableFilter.js';
|
|
9
8
|
|
|
10
9
|
import card from './controllers/card.js';
|
|
11
10
|
import search from './controllers/search.js';
|
|
@@ -15,7 +14,7 @@ import form from './controllers/form.js';
|
|
|
15
14
|
import loadTemplatePath from '../../plugins/table/funcs/loadTemplatePath.js';
|
|
16
15
|
|
|
17
16
|
import {
|
|
18
|
-
tableDataSchema, tableSchema, searchSchema, suggestSchema, formSchema, filterSchema, cardTabDataSchema, tableDataIdSchema,
|
|
17
|
+
tableDataSchema, tableSchema, searchSchema, suggestSchema, formSchema, filterSchema, cardTabDataSchema, tableDataIdSchema,
|
|
19
18
|
} from './schema.js';
|
|
20
19
|
|
|
21
20
|
const policy = ['public'];
|
|
@@ -25,7 +24,7 @@ async function plugin(app, config = {}) {
|
|
|
25
24
|
|
|
26
25
|
app.get(`${prefix}/token-info/:token`, { config: { policy: ['admin'] } }, tokenInfo);
|
|
27
26
|
|
|
28
|
-
app.get(`${prefix}/table-filter/:table`, { config: { policy }, schema:
|
|
27
|
+
app.get(`${prefix}/table-filter/:table`, { config: { policy }, schema: filterSchema }, filter);
|
|
29
28
|
|
|
30
29
|
app.get(`${prefix}/table-info/:table/:id?`, { config: { policy }, schema: tableDataSchema }, tableInfo);
|
|
31
30
|
app.get(`${prefix}/suggest/:data`, { config: { policy }, schema: suggestSchema }, suggest);
|
|
@@ -1,33 +1,24 @@
|
|
|
1
1
|
const tableDataSchema = {
|
|
2
2
|
type: 'object',
|
|
3
3
|
properties: {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const tableFilterSchema = {
|
|
26
|
-
type: 'object',
|
|
27
|
-
properties: {
|
|
28
|
-
params: {
|
|
29
|
-
name: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
|
|
30
|
-
},
|
|
4
|
+
querystring: {
|
|
5
|
+
limit: { type: 'string', pattern: '^(\\d+)$' },
|
|
6
|
+
page: { type: 'string', pattern: '^(\\d+)$' },
|
|
7
|
+
// filter: { type: 'string', pattern: '^([\\w\\d_-]+)=([А-Яа-яҐґЄєІіЇї\\d\\w\\s\\/\\[\\]\\(\\)\\{\\}\\|,.!?;:—_=-@%#$&^*+=`~]+)$' },
|
|
8
|
+
// search: { type: 'string', pattern: '^([А-Яа-яҐґЄєІіЇї\\d\\w\\s\\/\\[\\]\\(\\)\\{\\}\\|,.!?;:—_=-@%#$&^*+=`~]+)$' },
|
|
9
|
+
order: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
|
|
10
|
+
desc: { type: 'string', pattern: '^(\\d+)$' },
|
|
11
|
+
state: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
|
|
12
|
+
custom: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
|
|
13
|
+
bbox: { type: 'string', pattern: '^([\\d\\s,.-]+)$' },
|
|
14
|
+
polyline: { type: 'string', pattern: '^([\\d\\w|@{}~_`]+)$' },
|
|
15
|
+
// key: { type: 'string', pattern: '^([\\d\\w_]+)$' },
|
|
16
|
+
sql: { type: 'string', pattern: '^(\\d)$' },
|
|
17
|
+
},
|
|
18
|
+
params: {
|
|
19
|
+
id: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
|
|
20
|
+
table: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
|
|
21
|
+
},
|
|
31
22
|
},
|
|
32
23
|
};
|
|
33
24
|
|
|
@@ -85,7 +76,7 @@ const suggestSchema = {
|
|
|
85
76
|
count: { type: 'string', pattern: '^(\\d)$' },
|
|
86
77
|
},
|
|
87
78
|
params: {
|
|
88
|
-
|
|
79
|
+
// data: { type: 'string', pattern: '^([\\d\\w]+)$' },
|
|
89
80
|
},
|
|
90
81
|
},
|
|
91
82
|
};
|
|
@@ -111,25 +102,25 @@ const filterSchema = {
|
|
|
111
102
|
const cardTabDataSchema = {
|
|
112
103
|
type: 'object',
|
|
113
104
|
properties: {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
105
|
+
querystring: {
|
|
106
|
+
sql: { type: 'string', pattern: '^(\\d)$' },
|
|
107
|
+
},
|
|
108
|
+
params: {
|
|
109
|
+
token: { type: 'string', pattern: '^([\\d\\w]+)$' },
|
|
110
|
+
},
|
|
120
111
|
},
|
|
121
112
|
};
|
|
122
113
|
|
|
123
114
|
const tableDataIdSchema = {
|
|
124
115
|
type: 'object',
|
|
125
116
|
properties: {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
117
|
+
params: {
|
|
118
|
+
id: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
|
|
119
|
+
name: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
|
|
120
|
+
},
|
|
130
121
|
},
|
|
131
122
|
};
|
|
132
123
|
|
|
133
124
|
export {
|
|
134
|
-
tableDataSchema, tableDataIdSchema, tableSchema, searchSchema, suggestSchema, formSchema, filterSchema, cardTabDataSchema,
|
|
125
|
+
tableDataSchema, tableDataIdSchema, tableSchema, searchSchema, suggestSchema, formSchema, filterSchema, cardTabDataSchema,
|
|
135
126
|
};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { getFilter, pgClients } from '../../../../utils.js';
|
|
2
|
-
|
|
3
|
-
export default async function tableFilter(req) {
|
|
4
|
-
const {
|
|
5
|
-
pg = pgClients.client, params = {}, query = {}, user = {},
|
|
6
|
-
} = req;
|
|
7
|
-
|
|
8
|
-
const {
|
|
9
|
-
filter, custom, state, search,
|
|
10
|
-
} = query;
|
|
11
|
-
|
|
12
|
-
const result = await getFilter({
|
|
13
|
-
table: params.table, pg, filter, custom, state, search, user,
|
|
14
|
-
});
|
|
15
|
-
return result;
|
|
16
|
-
}
|