@opengis/fastify-table 1.4.82 → 1.4.84
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/index.js +30 -9
- package/package.json +2 -2
- package/server/helpers/core/token.js +18 -18
- package/server/plugins/cron/funcs/addCron.js +52 -52
- package/server/plugins/crud/funcs/dataDelete.js +2 -2
- package/server/plugins/crud/funcs/getOpt.js +14 -14
- package/server/plugins/crud/funcs/utils/getFolder.js +11 -11
- package/server/plugins/logger/errorStatus.js +19 -19
- package/server/plugins/pg/funcs/init.js +2 -2
- package/server/plugins/redis/client.js +8 -8
- package/server/plugins/redis/funcs/redisClients.js +3 -3
- package/server/plugins/sqlite/funcs/getSqlite.js +8 -3
- package/server/plugins/sqlite/funcs/init.js +1 -1
- package/server/plugins/sqlite/sqliteClients.js +8 -3
- package/server/plugins/table/funcs/getFilterSQL/util/getCustomQuery.js +13 -13
- package/server/plugins/table/funcs/getFilterSQL/util/getTableSql.js +34 -34
- package/server/plugins/table/funcs/getTemplates.js +19 -19
- package/server/plugins/table/funcs/gisIRColumn.js +82 -82
- package/server/plugins/table/funcs/loadTemplate.js +1 -1
- package/server/plugins/table/funcs/loadTemplatePath.js +1 -1
- package/server/plugins/table/funcs/userTemplateDir.js +1 -1
- package/server/plugins/util/funcs/unflattenObject.js +4 -1
- package/server/routes/crud/controllers/deleteCrud.js +35 -9
- package/server/routes/table/controllers/search.js +74 -74
- package/server/routes/table/controllers/tableData.js +2 -2
- package/server/routes/table/functions/getData.js +6 -6
- package/server/routes/widget/controllers/widget.del.js +89 -89
- package/server/routes/widget/hook/onWidgetSet.js +13 -13
- package/server/routes/widget/index.mjs +38 -38
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
import getSelect from './getSelect.js';
|
|
2
|
-
|
|
3
|
-
import getFilterSQL from './getFilterSQL/index.js';
|
|
4
|
-
import getTemplate from './getTemplate.js';
|
|
5
|
-
import pgClients from '../../pg/pgClients.js';
|
|
6
|
-
import config from '../../../../config.js';
|
|
7
|
-
import getSelectVal from './metaFormat/getSelectVal.js';
|
|
8
|
-
|
|
9
|
-
export default async function gisIRColumn({
|
|
10
|
-
pg = pgClients.client, layer, column, sql, query = '1=1', filter, state, search, custom,
|
|
11
|
-
}) {
|
|
12
|
-
const time = Date.now();
|
|
13
|
-
|
|
14
|
-
const sel = await getSelect(query.cls || column, pg);
|
|
15
|
-
|
|
16
|
-
const body = await getTemplate('table', layer);
|
|
17
|
-
const fData = await getFilterSQL({
|
|
18
|
-
table: layer,
|
|
19
|
-
filter,
|
|
20
|
-
state,
|
|
21
|
-
search,
|
|
22
|
-
custom,
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
const { tlist } = await pg.one(`select array_agg((select nspname from pg_namespace where oid=relnamespace)||'.'||relname) tlist from pg_class
|
|
26
|
-
where relkind in ('r','v','m')`);
|
|
27
|
-
|
|
28
|
-
const tableName = body?.table || layer;
|
|
29
|
-
if (!tlist.includes(tableName)) return { error: `table not found: ${tableName}`, status: 400 };
|
|
30
|
-
|
|
31
|
-
// eslint-disable-next-line max-len
|
|
32
|
-
const { fields } = await pg.query(`select * from (${fData?.optimizedSQL || `select * from ${tableName}`})q limit 0`);
|
|
33
|
-
|
|
34
|
-
const col = fields.find((el) => el.name === column);
|
|
35
|
-
|
|
36
|
-
if (!col) return { status: 404, message: 'not found' };
|
|
37
|
-
const colField = pg.pgType[col.dataTypeID]?.includes('[]') ? `unnest(${column})` : column;
|
|
38
|
-
|
|
39
|
-
const q = `select ${colField} as id, count(*)::int from (
|
|
40
|
-
${fData?.optimizedSQL || `select * from ${tableName} where ${body?.query || 'true'}`}
|
|
41
|
-
)t group by ${colField} order by count desc limit 15`;
|
|
42
|
-
|
|
43
|
-
if (sql) return q;
|
|
44
|
-
|
|
45
|
-
if (!body?.columns?.length) {
|
|
46
|
-
const { rows } = await pg.query(q);
|
|
47
|
-
if (sel?.arr?.length) {
|
|
48
|
-
rows.forEach((el) => {
|
|
49
|
-
const data = sel?.find((item) => item.id?.toString() === el.id?.toString());
|
|
50
|
-
Object.assign(el, data || {});
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
return {
|
|
54
|
-
count: rows?.reduce((acc, el) => acc + el.count, 0),
|
|
55
|
-
sql: config.local ? q : undefined,
|
|
56
|
-
rows,
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const { rows } = await pg.query(q);
|
|
61
|
-
const cls = query.cls || body?.columns?.find((el) => el.name === column)?.data || col.data || col.option;
|
|
62
|
-
const select = await getSelectVal({
|
|
63
|
-
pg, name: cls, values: rows.map((el) => el.id), ar: 1,
|
|
64
|
-
});
|
|
65
|
-
rows.forEach((el) => {
|
|
66
|
-
if (Array.isArray(select)) {
|
|
67
|
-
Object.assign(el, select.find((item) => item.id?.toString() === el.id?.toString()) || {});
|
|
68
|
-
}
|
|
69
|
-
else if (typeof select?.[el.id] === 'string') {
|
|
70
|
-
Object.assign(el, { text: select?.[el.id] });
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
Object.assign(el, select?.[el.id] || {});
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
return {
|
|
77
|
-
time: Date.now() - time,
|
|
78
|
-
count: rows.reduce((acc, el) => acc + el.count, 0),
|
|
79
|
-
sql: config.local ? q : undefined,
|
|
80
|
-
rows,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
1
|
+
import getSelect from './getSelect.js';
|
|
2
|
+
|
|
3
|
+
import getFilterSQL from './getFilterSQL/index.js';
|
|
4
|
+
import getTemplate from './getTemplate.js';
|
|
5
|
+
import pgClients from '../../pg/pgClients.js';
|
|
6
|
+
import config from '../../../../config.js';
|
|
7
|
+
import getSelectVal from './metaFormat/getSelectVal.js';
|
|
8
|
+
|
|
9
|
+
export default async function gisIRColumn({
|
|
10
|
+
pg = pgClients.client, layer, column, sql, query = '1=1', filter, state, search, custom,
|
|
11
|
+
}) {
|
|
12
|
+
const time = Date.now();
|
|
13
|
+
|
|
14
|
+
const sel = await getSelect(query.cls || column, pg);
|
|
15
|
+
|
|
16
|
+
const body = await getTemplate('table', layer);
|
|
17
|
+
const fData = await getFilterSQL({
|
|
18
|
+
table: layer,
|
|
19
|
+
filter,
|
|
20
|
+
state,
|
|
21
|
+
search,
|
|
22
|
+
custom,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const { tlist } = await pg.one(`select array_agg((select nspname from pg_namespace where oid=relnamespace)||'.'||relname) tlist from pg_class
|
|
26
|
+
where relkind in ('r','v','m')`);
|
|
27
|
+
|
|
28
|
+
const tableName = body?.table || layer;
|
|
29
|
+
if (!tlist.includes(tableName)) return { error: `table not found: ${tableName}`, status: 400 };
|
|
30
|
+
|
|
31
|
+
// eslint-disable-next-line max-len
|
|
32
|
+
const { fields } = await pg.query(`select * from (${fData?.optimizedSQL || `select * from ${tableName}`})q limit 0`);
|
|
33
|
+
|
|
34
|
+
const col = fields.find((el) => el.name === column);
|
|
35
|
+
|
|
36
|
+
if (!col) return { status: 404, message: 'not found' };
|
|
37
|
+
const colField = pg.pgType[col.dataTypeID]?.includes('[]') ? `unnest(${column})` : column;
|
|
38
|
+
|
|
39
|
+
const q = `select ${colField} as id, count(*)::int from (
|
|
40
|
+
${fData?.optimizedSQL || `select * from ${tableName} where ${body?.query || 'true'}`}
|
|
41
|
+
)t group by ${colField} order by count desc limit 15`;
|
|
42
|
+
|
|
43
|
+
if (sql) return q;
|
|
44
|
+
|
|
45
|
+
if (!body?.columns?.length) {
|
|
46
|
+
const { rows } = await pg.query(q);
|
|
47
|
+
if (sel?.arr?.length) {
|
|
48
|
+
rows.forEach((el) => {
|
|
49
|
+
const data = sel?.find((item) => item.id?.toString() === el.id?.toString());
|
|
50
|
+
Object.assign(el, data || {});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
count: rows?.reduce((acc, el) => acc + el.count, 0),
|
|
55
|
+
sql: config.local ? q : undefined,
|
|
56
|
+
rows,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const { rows } = await pg.query(q);
|
|
61
|
+
const cls = query.cls || body?.columns?.find((el) => el.name === column)?.data || col.data || col.option;
|
|
62
|
+
const select = await getSelectVal({
|
|
63
|
+
pg, name: cls, values: rows.map((el) => el.id), ar: 1,
|
|
64
|
+
});
|
|
65
|
+
rows.forEach((el) => {
|
|
66
|
+
if (Array.isArray(select)) {
|
|
67
|
+
Object.assign(el, select.find((item) => item.id?.toString() === el.id?.toString()) || {});
|
|
68
|
+
}
|
|
69
|
+
else if (typeof select?.[el.id] === 'string') {
|
|
70
|
+
Object.assign(el, { text: select?.[el.id] });
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
Object.assign(el, select?.[el.id] || {});
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return {
|
|
77
|
+
time: Date.now() - time,
|
|
78
|
+
count: rows.reduce((acc, el) => acc + el.count, 0),
|
|
79
|
+
sql: config.local ? q : undefined,
|
|
80
|
+
rows,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export default {};
|
|
1
|
+
export default {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export default {};
|
|
1
|
+
export default {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export default [];
|
|
1
|
+
export default [];
|
|
@@ -10,6 +10,7 @@ export default function unflattenObject(flatObj) {
|
|
|
10
10
|
if (index === keys.length - 1) {
|
|
11
11
|
// json array
|
|
12
12
|
if (typeof flatObj[key] === 'string' && flatObj[key].startsWith('[') && flatObj[key] !== ('[object Object]')) {
|
|
13
|
+
// console.log('unflatten aray', key);
|
|
13
14
|
try {
|
|
14
15
|
nestedObj[part] = JSON.parse(flatObj[key] || '{}');
|
|
15
16
|
}
|
|
@@ -18,7 +19,8 @@ export default function unflattenObject(flatObj) {
|
|
|
18
19
|
nestedObj[part] = flatObj[key]; // fallback to original value if parsing fails
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
|
-
else if (['true', 'false'].includes(flatObj[key]) || (!isNaN(flatObj[key]) &&
|
|
22
|
+
else if (['true', 'false'].includes(flatObj[key]) || (!isNaN(flatObj[key])) && false) {
|
|
23
|
+
// console.log('unflatten number', key);
|
|
22
24
|
try {
|
|
23
25
|
nestedObj[part] = JSON.parse(flatObj[key] || '{}');
|
|
24
26
|
}
|
|
@@ -28,6 +30,7 @@ export default function unflattenObject(flatObj) {
|
|
|
28
30
|
}
|
|
29
31
|
}
|
|
30
32
|
else {
|
|
33
|
+
// console.log('unflatten else', key);
|
|
31
34
|
nestedObj[part] = flatObj[key];
|
|
32
35
|
}
|
|
33
36
|
}
|
|
@@ -18,17 +18,31 @@ export default async function deleteCrud(req, reply) {
|
|
|
18
18
|
const { referer } = headers;
|
|
19
19
|
const tokenData = await getToken({
|
|
20
20
|
uid: user.uid, token: params.id || params.table, json: 1,
|
|
21
|
-
}) || await getOpt(params.id || params.table, user.uid);
|
|
21
|
+
}) || await getOpt(params.id || params.table, user.uid) || await getOpt(params.table, user.uid);
|
|
22
22
|
|
|
23
|
-
const {
|
|
23
|
+
const {
|
|
24
|
+
table: del, id = params.id, query, actions: actionsToken,
|
|
25
|
+
} = hookData || tokenData || (config.security?.disableToken || config.local || config.auth?.disable ? req.params : {});
|
|
26
|
+
if (actionsToken && !actionsToken?.include('del')) {
|
|
27
|
+
return reply.status(403).send({
|
|
28
|
+
error: 'del is not allowed ',
|
|
29
|
+
code: 403,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
24
32
|
const { actions = [] } = await getAccess({ table: del, id, user }, pg) || {};
|
|
25
33
|
|
|
26
34
|
if (!tokenData && !config?.local && !config.security?.disableToken && !config.auth?.disable) {
|
|
27
|
-
return reply.status(
|
|
35
|
+
return reply.status(403).send({
|
|
36
|
+
error: 'invalid token',
|
|
37
|
+
code: 403,
|
|
38
|
+
});
|
|
28
39
|
}
|
|
29
40
|
|
|
30
41
|
if (!actions.includes('del') && !config?.local && !tokenData) {
|
|
31
|
-
return reply.status(403).send(
|
|
42
|
+
return reply.status(403).send({
|
|
43
|
+
error: 'access restricted: actions',
|
|
44
|
+
code: 403,
|
|
45
|
+
});
|
|
32
46
|
}
|
|
33
47
|
|
|
34
48
|
const loadTemplate = await getTemplate('table', del);
|
|
@@ -36,22 +50,34 @@ export default async function deleteCrud(req, reply) {
|
|
|
36
50
|
const { table } = loadTemplate || hookData || tokenData || req.params || {};
|
|
37
51
|
|
|
38
52
|
if (!table) {
|
|
39
|
-
return reply.status(404).send(
|
|
53
|
+
return reply.status(404).send({
|
|
54
|
+
error: 'table is required',
|
|
55
|
+
code: 404,
|
|
56
|
+
});
|
|
40
57
|
}
|
|
41
58
|
|
|
42
59
|
if (!id) {
|
|
43
|
-
return reply.status(404).send(
|
|
60
|
+
return reply.status(404).send({
|
|
61
|
+
error: 'id is required',
|
|
62
|
+
code: 404,
|
|
63
|
+
});
|
|
44
64
|
}
|
|
45
65
|
|
|
46
66
|
const data = await dataDelete({
|
|
47
|
-
pg, table, id, uid: user?.uid, tokenData, referer,
|
|
67
|
+
pg, table, id, uid: user?.uid, tokenData, referer, query,
|
|
48
68
|
}).catch(err => {
|
|
49
69
|
if (err.message?.includes?.('foreign key' || 'unique')) {
|
|
50
70
|
const constraint = err.message.match(/constraint "([^"]+)"/g);
|
|
51
|
-
return reply.status(400).send(
|
|
71
|
+
return reply.status(400).send({
|
|
72
|
+
error: `Видалення заборонено для збереження цілісності БД: ${constraint}`,
|
|
73
|
+
code: 400,
|
|
74
|
+
});
|
|
52
75
|
}
|
|
53
76
|
if (config.trace) console.error(err.toString());
|
|
54
|
-
return
|
|
77
|
+
return {
|
|
78
|
+
error: err.toString(),
|
|
79
|
+
code: 400,
|
|
80
|
+
};
|
|
55
81
|
});
|
|
56
82
|
|
|
57
83
|
return reply.status(200).send({ rowCount: data?.rowCount || 0, msg: !data?.rowCount ? data : null });
|
|
@@ -1,74 +1,74 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getMeta, metaFormat, getTemplates, getTemplate, handlebars,
|
|
3
|
-
} from '../../../../utils.js';
|
|
4
|
-
|
|
5
|
-
function sequence(tables, data, fn) {
|
|
6
|
-
return tables.reduce((promise, table) => promise.then(() => fn({
|
|
7
|
-
...data, tableName: table.replace('.json', ''),
|
|
8
|
-
})), Promise.resolve());
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async function getData({
|
|
12
|
-
pg, tableName, query = {}, maxLimit, res,
|
|
13
|
-
}) {
|
|
14
|
-
const loadTable = await getTemplate('table', tableName);
|
|
15
|
-
|
|
16
|
-
if (!loadTable) { return { message: 'not found', status: 404 }; }
|
|
17
|
-
|
|
18
|
-
const {
|
|
19
|
-
table, columns, meta,
|
|
20
|
-
} = loadTable;
|
|
21
|
-
|
|
22
|
-
const { pk } = await getMeta(table);
|
|
23
|
-
|
|
24
|
-
const cols = columns.map((el) => el.name || el).join(',');
|
|
25
|
-
const [orderColumn, orderDir] = (query.order || loadTable.order || '').split('-');
|
|
26
|
-
const order = cols.includes(orderColumn) && orderColumn?.length ? `order by ${orderColumn} ${query.desc || orderDir === 'desc' ? 'desc' : ''}` : '';
|
|
27
|
-
|
|
28
|
-
const limit = Math.max(maxLimit - res.rows.length, 0);
|
|
29
|
-
// Math.max(query.offset - res.rows.length,0)
|
|
30
|
-
const offset = query.page && query.page > 0 ? ` offset ${(query.page - 1) * limit}` : '';
|
|
31
|
-
|
|
32
|
-
const search1 = meta?.search && query.key ? `(${meta?.search.concat(meta?.title ? `,${meta?.title}` : '').split(',').map(el => `${el} ilike '%${query.key}%'`).join(' or ')})` : 'false';
|
|
33
|
-
|
|
34
|
-
const where = [!pk ? 'false' : 'true', loadTable.query, search1].filter((el) => el);
|
|
35
|
-
const q = `select ${[`"${pk}" as id`, meta?.title ? `${meta.title} as title` : ''].filter((el) => el).join(',')} from ${table} t where ${where.join(' and ') || 'true'} ${order} ${offset} limit ${limit}`;
|
|
36
|
-
if (query.sql) {
|
|
37
|
-
res.sql.push(q);
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const { rows } = await pg.query(q);
|
|
42
|
-
|
|
43
|
-
const total = await pg.queryCache(`select count(*) from ${table} t where ${where.join(' and ') || 'true'}`).then((el) => el?.rows[0]?.count) || 0;
|
|
44
|
-
|
|
45
|
-
await metaFormat({ rows, table: tableName });
|
|
46
|
-
res.total += +total;
|
|
47
|
-
rows.forEach((row) => {
|
|
48
|
-
const href = meta?.href ? handlebars.compile(meta.href)({ ...row, [pk]: row.id }) : undefined;
|
|
49
|
-
res.rows.push({
|
|
50
|
-
...row, register: tableName, register_title: loadTable.ua, href,
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export default async function search({
|
|
57
|
-
pg, funcs, query = {},
|
|
58
|
-
}) {
|
|
59
|
-
const time = Date.now();
|
|
60
|
-
|
|
61
|
-
const tables = query.table ? [query.table] : await getTemplates('table');
|
|
62
|
-
const res = { rows: [], sql: [], total: 0 };
|
|
63
|
-
|
|
64
|
-
const maxLimit = Math.min(100, query.limit || '16');
|
|
65
|
-
await sequence(tables, {
|
|
66
|
-
pg, funcs, query, maxLimit, res,
|
|
67
|
-
}, getData);
|
|
68
|
-
|
|
69
|
-
if (query.sql) return res.sql.join(';\n');
|
|
70
|
-
|
|
71
|
-
return {
|
|
72
|
-
time: Date.now() - time, total: res.total, count: res.rows.length, rows: res.rows,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
getMeta, metaFormat, getTemplates, getTemplate, handlebars,
|
|
3
|
+
} from '../../../../utils.js';
|
|
4
|
+
|
|
5
|
+
function sequence(tables, data, fn) {
|
|
6
|
+
return tables.reduce((promise, table) => promise.then(() => fn({
|
|
7
|
+
...data, tableName: table.replace('.json', ''),
|
|
8
|
+
})), Promise.resolve());
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async function getData({
|
|
12
|
+
pg, tableName, query = {}, maxLimit, res,
|
|
13
|
+
}) {
|
|
14
|
+
const loadTable = await getTemplate('table', tableName);
|
|
15
|
+
|
|
16
|
+
if (!loadTable) { return { message: 'not found', status: 404 }; }
|
|
17
|
+
|
|
18
|
+
const {
|
|
19
|
+
table, columns, meta,
|
|
20
|
+
} = loadTable;
|
|
21
|
+
|
|
22
|
+
const { pk } = await getMeta(table);
|
|
23
|
+
|
|
24
|
+
const cols = columns.map((el) => el.name || el).join(',');
|
|
25
|
+
const [orderColumn, orderDir] = (query.order || loadTable.order || '').split('-');
|
|
26
|
+
const order = cols.includes(orderColumn) && orderColumn?.length ? `order by ${orderColumn} ${query.desc || orderDir === 'desc' ? 'desc' : ''}` : '';
|
|
27
|
+
|
|
28
|
+
const limit = Math.max(maxLimit - res.rows.length, 0);
|
|
29
|
+
// Math.max(query.offset - res.rows.length,0)
|
|
30
|
+
const offset = query.page && query.page > 0 ? ` offset ${(query.page - 1) * limit}` : '';
|
|
31
|
+
|
|
32
|
+
const search1 = meta?.search && query.key ? `(${meta?.search.concat(meta?.title ? `,${meta?.title}` : '').split(',').map(el => `${el} ilike '%${query.key}%'`).join(' or ')})` : 'false';
|
|
33
|
+
|
|
34
|
+
const where = [!pk ? 'false' : 'true', loadTable.query, search1].filter((el) => el);
|
|
35
|
+
const q = `select ${[`"${pk}" as id`, meta?.title ? `${meta.title} as title` : ''].filter((el) => el).join(',')} from ${table} t where ${where.join(' and ') || 'true'} ${order} ${offset} limit ${limit}`;
|
|
36
|
+
if (query.sql) {
|
|
37
|
+
res.sql.push(q);
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const { rows } = await pg.query(q);
|
|
42
|
+
|
|
43
|
+
const total = await pg.queryCache(`select count(*) from ${table} t where ${where.join(' and ') || 'true'}`).then((el) => el?.rows[0]?.count) || 0;
|
|
44
|
+
|
|
45
|
+
await metaFormat({ rows, table: tableName });
|
|
46
|
+
res.total += +total;
|
|
47
|
+
rows.forEach((row) => {
|
|
48
|
+
const href = meta?.href ? handlebars.compile(meta.href)({ ...row, [pk]: row.id }) : undefined;
|
|
49
|
+
res.rows.push({
|
|
50
|
+
...row, register: tableName, register_title: loadTable.ua, href,
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export default async function search({
|
|
57
|
+
pg, funcs, query = {},
|
|
58
|
+
}) {
|
|
59
|
+
const time = Date.now();
|
|
60
|
+
|
|
61
|
+
const tables = query.table ? [query.table] : await getTemplates('table');
|
|
62
|
+
const res = { rows: [], sql: [], total: 0 };
|
|
63
|
+
|
|
64
|
+
const maxLimit = Math.min(100, query.limit || '16');
|
|
65
|
+
await sequence(tables, {
|
|
66
|
+
pg, funcs, query, maxLimit, res,
|
|
67
|
+
}, getData);
|
|
68
|
+
|
|
69
|
+
if (query.sql) return res.sql.join(';\n');
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
time: Date.now() - time, total: res.total, count: res.rows.length, rows: res.rows,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
@@ -30,7 +30,7 @@ export default async function getTableData(req, reply, called) {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
const resp = await getData({
|
|
33
|
-
pg, params: { id, table: tokenData.table }, headers, query, user, contextQuery: [contextQuery1, tokenData.query].filter(Boolean).join(' and '), sufix, filterList,
|
|
33
|
+
pg, params: { id, table: tokenData.table }, headers, query, user, contextQuery: [contextQuery1, tokenData.query].filter(Boolean).join(' and '), sufix, filterList, actions: tokenData1?.actions,
|
|
34
34
|
}, reply, called);
|
|
35
35
|
if (resp?.addToken && tokenData.obj) { Object.assign(resp, { addToken: params.table }); }
|
|
36
36
|
return resp;
|
|
@@ -52,7 +52,7 @@ export default async function getTableData(req, reply, called) {
|
|
|
52
52
|
const contextQuery = [contextQuery1, interfaceQuery, context].filter(Boolean).join(' and ') || ' 2=2 ';
|
|
53
53
|
|
|
54
54
|
const res = await getData({
|
|
55
|
-
pg, params, query, headers, user, contextQuery, sufix, filterList,
|
|
55
|
+
pg, params, query, headers, user, contextQuery, sufix, filterList, actions: tokenData1?.actions,
|
|
56
56
|
}, reply, called);
|
|
57
57
|
const route = pg.tlist?.includes('admin.routes') ? await pg.query('select route_id as path, title from admin.routes where enabled and alias=$1 limit 1', [params.table])
|
|
58
58
|
.then(el => el.rows?.[0] || {}) : {};
|
|
@@ -34,7 +34,7 @@ const defaultLimit = 20;
|
|
|
34
34
|
|
|
35
35
|
export default async function dataAPI(req, reply, called) {
|
|
36
36
|
const {
|
|
37
|
-
pg = pgClients.client, params, headers = {}, query = {}, user = {}, contextQuery, sufix = true, filterList,
|
|
37
|
+
pg = pgClients.client, params, headers = {}, query = {}, user = {}, contextQuery, sufix = true, filterList, actions: actionsParam,
|
|
38
38
|
} = req;
|
|
39
39
|
|
|
40
40
|
const time = Date.now();
|
|
@@ -52,8 +52,8 @@ export default async function dataAPI(req, reply, called) {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
const tokenData = await getOpt(params.table, user?.uid);
|
|
55
|
-
|
|
56
|
-
const loadTable = await getTemplate('table',
|
|
55
|
+
const templateName = tokenData?.table || hookData?.table || params.table;
|
|
56
|
+
const loadTable = await getTemplate('table', templateName);
|
|
57
57
|
|
|
58
58
|
// check sql inline fields count
|
|
59
59
|
if (!checkInline[params?.table] && loadTable?.sql?.length && loadTable.table) {
|
|
@@ -227,7 +227,7 @@ export default async function dataAPI(req, reply, called) {
|
|
|
227
227
|
|
|
228
228
|
timeArr.push(Date.now());
|
|
229
229
|
|
|
230
|
-
if (uid && rows.length && !config.security?.disableToken && (editable || actions.includes('edit') || actions.includes('del'))) {
|
|
230
|
+
if (uid && rows.length && !config.security?.disableToken && (editable || actionsParam?.includes('edit') || actions.includes('edit') || actions.includes('del'))) {
|
|
231
231
|
rows.forEach(row => {
|
|
232
232
|
Object.assign(row, {
|
|
233
233
|
token: setToken({
|
|
@@ -381,8 +381,8 @@ export default async function dataAPI(req, reply, called) {
|
|
|
381
381
|
|
|
382
382
|
public: ispublic,
|
|
383
383
|
tokens,
|
|
384
|
-
card: loadTable?.card,
|
|
385
|
-
actions,
|
|
384
|
+
card: !!(loadTable?.card ?? await getTemplate('card', templateName)),
|
|
385
|
+
actions: actionsParam || actions || ['view'],
|
|
386
386
|
total,
|
|
387
387
|
filtered,
|
|
388
388
|
count: rows.length,
|