@opengis/fastify-table 1.2.39 → 1.2.41
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 +1 -1
- package/server/plugins/crud/funcs/dataUpdate.js +1 -1
- package/server/plugins/crud/funcs/getAccess.js +7 -7
- package/server/plugins/policy/funcs/checkPolicy.js +9 -4
- package/server/routes/crud/controllers/deleteCrud.js +5 -5
- package/server/routes/crud/controllers/insert.js +8 -7
- package/server/routes/crud/controllers/table.js +8 -11
- package/server/routes/crud/controllers/update.js +6 -5
- package/server/routes/table/controllers/data.js +16 -13
- package/server/routes/table/controllers/suggest.js +1 -1
package/package.json
CHANGED
|
@@ -41,7 +41,7 @@ export default async function dataUpdate({
|
|
|
41
41
|
}).map((el) => (typeof el[1] === 'object' && el[1] && (!Array.isArray(el[1]) || typeof el[1]?.[0] === 'object') ? JSON.stringify(el[1]) : el[1]));
|
|
42
42
|
|
|
43
43
|
// update geometry with srid
|
|
44
|
-
if (!srids[table]) {
|
|
44
|
+
if (!srids[table] && pg.tlist?.includes('public.geometry_columns')) {
|
|
45
45
|
const { srids1 } = await pg.query(`select json_object_agg(_table,rel) as srids1 from (
|
|
46
46
|
select f_table_schema||'.'||f_table_name as _table,
|
|
47
47
|
json_object_agg(f_geometry_column, case when srid = 0 then 4326 else srid end) as rel
|
|
@@ -29,10 +29,10 @@ left join admin.user_roles d on
|
|
|
29
29
|
end )
|
|
30
30
|
where $1 in (a.route_id, a.alias, a.table_name) and $2 in (b.user_uid, d.user_uid)`;
|
|
31
31
|
|
|
32
|
-
export default async function getAccess({ table, user = {} }) {
|
|
32
|
+
export default async function getAccess({ table, user = {} }, pg = pgClients.client) {
|
|
33
33
|
if (!table) return null;
|
|
34
34
|
|
|
35
|
-
const hookData = await applyHook('getAccess', { table, user });
|
|
35
|
+
const hookData = await applyHook('getAccess', { table, user, pg });
|
|
36
36
|
if (hookData) return hookData;
|
|
37
37
|
|
|
38
38
|
const { uid, user_type: userType = 'regular' } = user;
|
|
@@ -60,11 +60,11 @@ export default async function getAccess({ table, user = {} }) {
|
|
|
60
60
|
return { actions: [], query: '1=1' };
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
const userAccess =
|
|
64
|
-
&&
|
|
65
|
-
&&
|
|
66
|
-
&&
|
|
67
|
-
? await
|
|
63
|
+
const userAccess = pg?.pk?.['admin.routes']
|
|
64
|
+
&& pg.pk?.['admin.role_access']
|
|
65
|
+
&& pg.pk?.['admin.roles']
|
|
66
|
+
&& pg.pk?.['admin.user_roles']
|
|
67
|
+
? await pg.query(q, [table, uid])
|
|
68
68
|
.then(el => ({
|
|
69
69
|
...el.rows[0] || {},
|
|
70
70
|
roles: el.rows?.map?.(row => row.role_id) || [],
|
|
@@ -64,16 +64,21 @@ export default function checkPolicy(req, reply) {
|
|
|
64
64
|
return null;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
const validToken = (req.ip === '193.239.152.181' || req.ip === '127.0.0.1' || req.ip.startsWith('192.168.') || config.debug)
|
|
68
|
+
&& req.headers?.uid
|
|
69
|
+
&& req.headers?.token
|
|
70
|
+
&& config.auth?.tokens?.includes?.(headers.token);
|
|
71
|
+
|
|
72
|
+
if (validToken && !req?.user?.uid) {
|
|
73
|
+
req.user = { uid: req.headers?.uid };
|
|
74
|
+
}
|
|
75
|
+
|
|
67
76
|
/* === policy: public === */
|
|
68
77
|
if (policy.includes('public')) {
|
|
69
78
|
return null;
|
|
70
79
|
}
|
|
71
80
|
|
|
72
81
|
/* === 0. policy: unauthorized access from admin URL === */
|
|
73
|
-
const validToken = (req.ip === '193.239.152.181' || req.ip === '127.0.0.1' || req.ip.startsWith('192.168.') || config.debug) && req.headers?.uid && req.headers?.token && config.auth?.tokens?.includes?.(headers.token);
|
|
74
|
-
if (validToken && !req?.user?.uid) {
|
|
75
|
-
req.user = { uid: req.headers?.uid };
|
|
76
|
-
}
|
|
77
82
|
if (!validToken && !user?.uid && !config.auth?.disable && isAdmin && !policy.includes('public') && !skipCheckPolicyRoutes.filter((el) => el).find(el => req.url.includes(el))) {
|
|
78
83
|
logger.file('policy/unauthorized', {
|
|
79
84
|
path, method, params, query, body, token: headers?.token, userId: headers?.uid, ip: req.ip, headers, message: 'unauthorized',
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
-
dataDelete, getTemplate, getAccess, applyHook, getToken, config,
|
|
2
|
+
dataDelete, getTemplate, getAccess, applyHook, getToken, config, pgClients,
|
|
3
3
|
} from '../../../../utils.js';
|
|
4
4
|
|
|
5
5
|
export default async function deleteCrud(req) {
|
|
6
|
-
const { user, params = {}, headers = {} } = req || {};
|
|
6
|
+
const { pg = pgClients.client, user, params = {}, headers = {} } = req || {};
|
|
7
7
|
|
|
8
8
|
const hookData = await applyHook('preDelete', {
|
|
9
|
-
table: params?.table, id: params?.id, user,
|
|
9
|
+
pg, table: params?.table, id: params?.id, user,
|
|
10
10
|
});
|
|
11
11
|
|
|
12
12
|
if (hookData?.message && hookData?.status) {
|
|
@@ -19,7 +19,7 @@ export default async function deleteCrud(req) {
|
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
const { table: del, id } = hookData || tokenData || (config.auth?.disable ? req.params : {});
|
|
22
|
-
const { actions = [] } = await getAccess({ table: del, id, user }) || {};
|
|
22
|
+
const { actions = [] } = await getAccess({ table: del, id, user }, pg) || {};
|
|
23
23
|
|
|
24
24
|
if (!actions.includes('del') && !config?.local && !tokenData) {
|
|
25
25
|
return { message: 'access restricted', status: 403 };
|
|
@@ -32,7 +32,7 @@ export default async function deleteCrud(req) {
|
|
|
32
32
|
if (!id) return { status: 404, message: 'id is required' };
|
|
33
33
|
|
|
34
34
|
const data = await dataDelete({
|
|
35
|
-
table, id, uid: user?.uid, tokenData, referer,
|
|
35
|
+
pg, table, id, uid: user?.uid, tokenData, referer,
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
return { rowCount: data.rowCount, msg: !data.rowCount ? data : null };
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
|
|
5
5
|
export default async function insert(req) {
|
|
6
6
|
const {
|
|
7
|
-
user = {}, params = {}, body = {}, headers = {},
|
|
7
|
+
pg = pgClients.client, user = {}, params = {}, body = {}, headers = {},
|
|
8
8
|
} = req || {};
|
|
9
9
|
if (!user) return { message: 'access restricted', status: 403 };
|
|
10
10
|
|
|
11
|
-
const hookData = await applyHook('preInsert', { table: params?.table, user });
|
|
11
|
+
const hookData = await applyHook('preInsert', { pg, table: params?.table, user });
|
|
12
12
|
|
|
13
13
|
if (hookData?.message && hookData?.status) {
|
|
14
14
|
return { message: hookData?.message, status: hookData?.status };
|
|
@@ -21,7 +21,7 @@ export default async function insert(req) {
|
|
|
21
21
|
|
|
22
22
|
const { form, table: add } = hookData || tokenData || (config.auth?.disable ? req.params : {});
|
|
23
23
|
|
|
24
|
-
const { actions = [] } = await getAccess({ table: add, user }) || {};
|
|
24
|
+
const { actions = [] } = await getAccess({ table: add, user }, pg) || {};
|
|
25
25
|
|
|
26
26
|
if (!actions.includes('add') && !config?.local && !tokenData) {
|
|
27
27
|
return { message: 'access restricted', status: 403 };
|
|
@@ -68,6 +68,7 @@ export default async function insert(req) {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
const res = await dataInsert({
|
|
71
|
+
pg,
|
|
71
72
|
id: params?.id,
|
|
72
73
|
table: loadTemplate?.table || table,
|
|
73
74
|
data: body,
|
|
@@ -79,19 +80,19 @@ export default async function insert(req) {
|
|
|
79
80
|
|
|
80
81
|
// admin.custom_column
|
|
81
82
|
await applyHook('afterInsert', {
|
|
82
|
-
table, token: params?.table, body, payload: res, user,
|
|
83
|
+
pg, table, token: params?.table, body, payload: res, user,
|
|
83
84
|
});
|
|
84
85
|
// form DataTable
|
|
85
86
|
// to do: rewrite as single transaction
|
|
86
87
|
const extraKeys = Object.keys(schema || {})?.filter((key) => schema?.[key]?.type === 'DataTable' && schema?.[key]?.table && schema?.[key]?.parent_id && body[key]?.length);
|
|
87
|
-
const pkey = res?.rows?.[0]?.[loadTemplate?.key ||
|
|
88
|
+
const pkey = res?.rows?.[0]?.[loadTemplate?.key || pg.pk?.[loadTemplate?.table || table]];
|
|
88
89
|
if (extraKeys?.length) {
|
|
89
90
|
res.extra = {};
|
|
90
91
|
await Promise.all(extraKeys?.map(async (key) => {
|
|
91
92
|
const objId = body[schema[key].parent_id] || req.body?.id || res?.rows?.[0]?.[schema[key].parent_id] || pkey;
|
|
92
93
|
const extraRows = await Promise.all(body[key].map(async (row) => {
|
|
93
94
|
const extraRes = await dataInsert({
|
|
94
|
-
table: schema[key].table, data: { ...row, [schema[key].parent_id]: objId }, uid: user?.uid, tokenData, referer,
|
|
95
|
+
pg, table: schema[key].table, data: { ...row, [schema[key].parent_id]: objId }, uid: user?.uid, tokenData, referer,
|
|
95
96
|
});
|
|
96
97
|
return extraRes?.rows?.[0];
|
|
97
98
|
}));
|
|
@@ -99,6 +100,6 @@ export default async function insert(req) {
|
|
|
99
100
|
}));
|
|
100
101
|
}
|
|
101
102
|
|
|
102
|
-
const pk =
|
|
103
|
+
const pk = pg.pk?.[loadTemplate?.table || table];
|
|
103
104
|
return { id: res?.rows?.[0]?.[pk], rows: res.rows, extra: res.extra };
|
|
104
105
|
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
|
-
config, getAccess, getTemplate, getMeta, setToken, applyHook, getToken,
|
|
2
|
+
config, getAccess, getTemplate, getMeta, setToken, applyHook, getToken, pgClients,
|
|
3
3
|
} from '../../../../utils.js';
|
|
4
4
|
|
|
5
5
|
export default async function tableAPI(req) {
|
|
6
6
|
const {
|
|
7
|
-
pg, params, user = {}, query = {},
|
|
7
|
+
pg = pgClients.client, params, user = {}, query = {},
|
|
8
8
|
} = req;
|
|
9
9
|
const tokenData = await getToken({ token: params?.table, uid: user.uid, json: 1 }) || {};
|
|
10
10
|
|
|
11
11
|
const hookData = await applyHook('preTable', {
|
|
12
|
-
table: params?.table, id: params?.id, ...tokenData || {}, user,
|
|
12
|
+
pg, table: params?.table, id: params?.id, ...tokenData || {}, user,
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
if (hookData?.message && hookData?.status) {
|
|
@@ -24,7 +24,8 @@ export default async function tableAPI(req) {
|
|
|
24
24
|
|
|
25
25
|
const { table, /* columns, */ form } = loadTable;
|
|
26
26
|
|
|
27
|
-
const
|
|
27
|
+
const templateName = hookData?.table || tokenData.table || params.table;
|
|
28
|
+
const tableName = table || templateName;
|
|
28
29
|
|
|
29
30
|
const id = hookData?.id || tokenData.id || params.id;
|
|
30
31
|
|
|
@@ -33,17 +34,13 @@ export default async function tableAPI(req) {
|
|
|
33
34
|
return { message: 'not enough params', status: 400 };
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
const { actions = [], query: accessQuery } = await getAccess({
|
|
37
|
-
table: hookData?.table || tokenData.table || params.table,
|
|
38
|
-
id,
|
|
39
|
-
user,
|
|
40
|
-
}) || {};
|
|
37
|
+
const { actions = [], query: accessQuery } = await getAccess({ table: templateName, id, user }, pg) || {};
|
|
41
38
|
|
|
42
39
|
if (!actions.includes('edit') && !config?.local && !tokenData) {
|
|
43
40
|
return { message: 'access restricted', status: 403 };
|
|
44
41
|
}
|
|
45
42
|
|
|
46
|
-
const { pk, columns: dbColumns = [] } = await getMeta(tableName);
|
|
43
|
+
const { pk, columns: dbColumns = [] } = await getMeta({ pg, table: tableName });
|
|
47
44
|
if (!pk) return { message: `table not found: ${table}`, status: 404 };
|
|
48
45
|
|
|
49
46
|
// const cols = columns.map((el) => el.name || el).join(',');
|
|
@@ -85,7 +82,7 @@ export default async function tableAPI(req) {
|
|
|
85
82
|
})[0];
|
|
86
83
|
}
|
|
87
84
|
const res = await applyHook('afterTable', {
|
|
88
|
-
table: tableName, payload: [data], user,
|
|
85
|
+
pg, table: tableName, payload: [data], user,
|
|
89
86
|
});
|
|
90
87
|
return res || data || {};
|
|
91
88
|
}
|
|
@@ -11,7 +11,7 @@ export default async function update(req) {
|
|
|
11
11
|
|
|
12
12
|
if (!user) return { message: 'access restricted', status: 403 };
|
|
13
13
|
const hookData = await applyHook('preUpdate', {
|
|
14
|
-
table: params?.table, id: params?.id, user,
|
|
14
|
+
pg, table: params?.table, id: params?.id, user,
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
if (hookData?.message && hookData?.status) {
|
|
@@ -25,7 +25,7 @@ export default async function update(req) {
|
|
|
25
25
|
|
|
26
26
|
const { form, table: edit, id } = hookData || tokenData || (config.auth?.disable ? params : {});
|
|
27
27
|
|
|
28
|
-
const { actions = [] } = await getAccess({ table: edit, id, user }) || {};
|
|
28
|
+
const { actions = [] } = await getAccess({ table: edit, id, user }, pg) || {};
|
|
29
29
|
|
|
30
30
|
if (!actions.includes('edit') && !config?.local && !tokenData) {
|
|
31
31
|
return { message: 'access restricted', status: 403 };
|
|
@@ -75,6 +75,7 @@ export default async function update(req) {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
const res = await dataUpdate({
|
|
78
|
+
pg,
|
|
78
79
|
table: loadTemplate?.table || table,
|
|
79
80
|
id,
|
|
80
81
|
data: body,
|
|
@@ -85,7 +86,7 @@ export default async function update(req) {
|
|
|
85
86
|
|
|
86
87
|
// admin.custom_column
|
|
87
88
|
await applyHook('afterUpdate', {
|
|
88
|
-
table: params?.table, body, payload: res, user,
|
|
89
|
+
pg, table: params?.table, body, payload: res, user,
|
|
89
90
|
});
|
|
90
91
|
|
|
91
92
|
// form DataTable
|
|
@@ -95,11 +96,11 @@ export default async function update(req) {
|
|
|
95
96
|
await Promise.all(extraKeys?.map(async (key) => {
|
|
96
97
|
const objId = body[schema[key].parent_id] || body?.id || res?.[schema[key]?.parent_id] || res?.[pg.pk?.[loadTemplate?.table || table] || ''];
|
|
97
98
|
// delete old extra data
|
|
98
|
-
await
|
|
99
|
+
await pg.query(`delete from ${schema[key].table} where ${schema[key].parent_id}=$1`, [objId]); // rewrite?
|
|
99
100
|
// insert new extra data
|
|
100
101
|
if (Array.isArray(body[key]) && body[key]?.length) {
|
|
101
102
|
const extraRows = await Promise.all(body[key]?.map?.(async (row) => {
|
|
102
|
-
const extraRes = await dataInsert({ table: schema[key].table, data: { ...row, [schema[key].parent_id]: objId }, uid, tokenData, referer });
|
|
103
|
+
const extraRes = await dataInsert({ pg, table: schema[key].table, data: { ...row, [schema[key].parent_id]: objId }, uid, tokenData, referer });
|
|
103
104
|
return extraRes?.rows?.[0];
|
|
104
105
|
}));
|
|
105
106
|
Object.assign(res.extra, { [key]: extraRows.filter((el) => el) });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
config, getTemplate, getFilterSQL, getMeta, metaFormat, getAccess, setToken, gisIRColumn, applyHook, handlebars, handlebarsSync, getSelect, setOpt, getOpt,
|
|
2
|
+
config, getTemplate, getFilterSQL, getMeta, metaFormat, getAccess, setToken, gisIRColumn, applyHook, handlebars, handlebarsSync, getSelect, setOpt, getOpt, pgClients,
|
|
3
3
|
} from '../../../../utils.js';
|
|
4
4
|
|
|
5
5
|
import conditions from './utils/conditions.js';
|
|
@@ -12,7 +12,7 @@ const components = {
|
|
|
12
12
|
const maxLimit = 100;
|
|
13
13
|
export default async function dataAPI(req, reply, called) {
|
|
14
14
|
const {
|
|
15
|
-
pg, params, query = {}, user = {},
|
|
15
|
+
pg = pgClients.client, params, query = {}, user = {},
|
|
16
16
|
} = req;
|
|
17
17
|
|
|
18
18
|
const time = Date.now();
|
|
@@ -20,7 +20,7 @@ export default async function dataAPI(req, reply, called) {
|
|
|
20
20
|
const { uid } = user;
|
|
21
21
|
|
|
22
22
|
const hookData = await applyHook('preData', {
|
|
23
|
-
table: params?.table, id: params?.id, user,
|
|
23
|
+
pg, table: params?.table, id: params?.id, user,
|
|
24
24
|
});
|
|
25
25
|
if (hookData?.message && hookData?.status) {
|
|
26
26
|
return { message: hookData?.message, status: hookData?.status };
|
|
@@ -32,7 +32,7 @@ export default async function dataAPI(req, reply, called) {
|
|
|
32
32
|
if (!loadTable && !(tokenData?.table && pg.pk?.[tokenData?.table])) { return { message: 'template not found', status: 404 }; }
|
|
33
33
|
|
|
34
34
|
const id = tokenData?.id || hookData?.id || params?.id;
|
|
35
|
-
const { actions = [], query: accessQuery } = await getAccess({ table: tokenData?.table || hookData?.table || params.table, id, user }) || {};
|
|
35
|
+
const { actions = [], query: accessQuery } = await getAccess({ table: tokenData?.table || hookData?.table || params.table, id, user }, pg) || {};
|
|
36
36
|
|
|
37
37
|
if (!actions.includes('view') && !config?.local && !called) {
|
|
38
38
|
return { message: 'access restricted', status: 403 };
|
|
@@ -42,11 +42,13 @@ export default async function dataAPI(req, reply, called) {
|
|
|
42
42
|
table, columns = [], sql, cardSql, filters, form, meta, sqlColumns, public: ispublic,
|
|
43
43
|
} = loadTable || tokenData;
|
|
44
44
|
|
|
45
|
-
const tableMeta = await getMeta(table);
|
|
45
|
+
const tableMeta = await getMeta({ pg, table });
|
|
46
|
+
|
|
46
47
|
if (tableMeta?.view) {
|
|
47
48
|
if (!loadTable?.key && !tokenData?.key) return { message: `key not found: ${table}`, status: 404 };
|
|
48
49
|
Object.assign(tableMeta, { pk: loadTable?.key || tokenData?.key });
|
|
49
50
|
}
|
|
51
|
+
|
|
50
52
|
const { pk, columns: dbColumns = [] } = tableMeta || {};
|
|
51
53
|
|
|
52
54
|
if (!pk) return { message: `table not found: ${table}`, status: 404 };
|
|
@@ -56,7 +58,7 @@ export default async function dataAPI(req, reply, called) {
|
|
|
56
58
|
const cardSqlFiltered = hookData?.id || params.id ? (cardSql?.filter?.((el) => !el?.disabled && el?.name && el?.sql?.replace) || []) : [];
|
|
57
59
|
const cardSqlTable = cardSqlFiltered.length ? cardSqlFiltered.map((el, i) => ` left join lateral (${el.sql.replace('{{uid}}', uid)}) ct${i} on 1=1 `).join('\n') || '' : '';
|
|
58
60
|
|
|
59
|
-
const { fields } = await pg.queryCache(`select * from ${table} t ${sqlTable} ${cardSqlTable} limit 0`);
|
|
61
|
+
const { fields = [] } = pg.queryCache ? await pg.queryCache(`select * from ${table} t ${sqlTable} ${cardSqlTable} limit 0`) : {};
|
|
60
62
|
const dbColumnsTable = fields.map(el => el.name);
|
|
61
63
|
const cols = columns.filter((el) => el.name !== 'geom' && dbColumnsTable.includes(el.name)).map((el) => el.name || el).join(',');
|
|
62
64
|
const metaCols = Object.keys(loadTable?.meta?.cls || {}).filter((el) => !cols.includes(el)).length
|
|
@@ -78,6 +80,7 @@ export default async function dataAPI(req, reply, called) {
|
|
|
78
80
|
|
|
79
81
|
const checkFilter = [query.filter, query.search, query.state, query.custom].filter((el) => el).length;
|
|
80
82
|
const fData = checkFilter ? await getFilterSQL({
|
|
83
|
+
pg,
|
|
81
84
|
table: params.table,
|
|
82
85
|
filter: query.filter,
|
|
83
86
|
search: query.search,
|
|
@@ -112,7 +115,7 @@ export default async function dataAPI(req, reply, called) {
|
|
|
112
115
|
${params.id || query.key ? '*' : sqlColumns || cols || '*'}
|
|
113
116
|
${metaCols}
|
|
114
117
|
|
|
115
|
-
${dbColumns.find((el) => el.name === 'geom' && pg.pgType[el.dataTypeID] === 'geometry') ? ',st_asgeojson(geom)::json as geom' : ''}
|
|
118
|
+
${dbColumns.find((el) => el.name === 'geom' && pg.pgType?.[el.dataTypeID] === 'geometry') ? ',st_asgeojson(geom)::json as geom' : ''}
|
|
116
119
|
from (select * from ${table} where ${sqlTable ? 'true' : (where.join(' and ') || 'true')} ${order}) t
|
|
117
120
|
${sqlTable}
|
|
118
121
|
${params.id ? cardSqlTable : ''}
|
|
@@ -129,7 +132,7 @@ export default async function dataAPI(req, reply, called) {
|
|
|
129
132
|
const filterWhere = [fData.q, search, bbox, queryPolyline, interfaceQuery, loadTable?.query, tokenData?.query].filter((el) => el);
|
|
130
133
|
|
|
131
134
|
const aggColumns = columns.filter((el) => el.agg).reduce((acc, curr) => Object.assign(acc, { [curr.name]: curr.agg }), {});
|
|
132
|
-
const aggregates = dbColumns.map((el) => ({ name: el.name, type: pg.pgType[el.dataTypeID] })).filter((el) => ['numeric', 'double precision'].includes(el.type) && aggColumns[el.name]);
|
|
135
|
+
const aggregates = dbColumns.map((el) => ({ name: el.name, type: pg.pgType?.[el.dataTypeID] })).filter((el) => ['numeric', 'double precision'].includes(el.type) && aggColumns[el.name]);
|
|
133
136
|
const qCount = `select
|
|
134
137
|
count(*)::int as total,
|
|
135
138
|
count(*) FILTER(WHERE ${filterWhere.join(' and ') || 'true'})::int as filtered
|
|
@@ -142,9 +145,9 @@ export default async function dataAPI(req, reply, called) {
|
|
|
142
145
|
|
|
143
146
|
const counts = keyQuery || tokenData?.id || hookData?.id || params.id
|
|
144
147
|
? { total: rows.length, filtered: rows.length }
|
|
145
|
-
: await pg.queryCache(qCount, { table: loadTable?.table || tokenData?.table, time: 5 }).then(el => el?.rows[0] || {});
|
|
148
|
+
: await pg.queryCache?.(qCount, { table: loadTable?.table || tokenData?.table, time: 5 }).then(el => el?.rows[0] || {});
|
|
146
149
|
|
|
147
|
-
const { total, filtered } = counts;
|
|
150
|
+
const { total, filtered } = counts || {};
|
|
148
151
|
const agg = Object.keys(counts).filter(el => !['total', 'filtered'].includes(el)).reduce((acc, el) => ({ ...acc, [el]: counts[el] }), {});
|
|
149
152
|
|
|
150
153
|
await metaFormat({ rows, table: tokenData?.table || hookData?.table || params.table });
|
|
@@ -215,8 +218,8 @@ export default async function dataAPI(req, reply, called) {
|
|
|
215
218
|
|
|
216
219
|
// data result
|
|
217
220
|
const data = {};
|
|
218
|
-
const route = await pg.query(`select route_id as path, title from admin.routes where enabled and alias=$1 limit 1`, [table])
|
|
219
|
-
.then(el => el.rows?.[0] || {});
|
|
221
|
+
const route = pg.pk?.['admin.routes'] ? await pg.query(`select route_id as path, title from admin.routes where enabled and alias=$1 limit 1`, [table])
|
|
222
|
+
.then(el => el.rows?.[0] || {}) : {};
|
|
220
223
|
Object.assign(route, { tableTitle: loadTable?.title });
|
|
221
224
|
if (index?.data && index?.data?.[0]?.name) {
|
|
222
225
|
await Promise.all(index.data.filter((el) => el?.name && el?.sql).map(async (el) => {
|
|
@@ -266,7 +269,7 @@ export default async function dataAPI(req, reply, called) {
|
|
|
266
269
|
}
|
|
267
270
|
|
|
268
271
|
const result = await applyHook('afterData', {
|
|
269
|
-
table: loadTable?.table || tokenData?.table, payload: res, user,
|
|
272
|
+
pg, table: loadTable?.table || tokenData?.table, payload: res, user,
|
|
270
273
|
});
|
|
271
274
|
|
|
272
275
|
return result || res;
|
|
@@ -47,7 +47,7 @@ export default async function suggest(req) {
|
|
|
47
47
|
original: `with c(id,text) as (select ${column || 'row_number() over()'}, ${column}, count(*) from ${tableName} group by ${column} limit ${limit}) select * from c`,
|
|
48
48
|
searchQuery: '(lower("text") ~ $1 )',
|
|
49
49
|
}
|
|
50
|
-
: await getSelectMeta({ name: selectName, nocache: query?.nocache });
|
|
50
|
+
: await getSelectMeta({ pg: pg1, name: selectName, nocache: query?.nocache });
|
|
51
51
|
|
|
52
52
|
if (meta?.minLength && query.key && query.key.length < meta?.minLength) {
|
|
53
53
|
return { message: `min length: ${meta.minLength}` };
|