@opengis/fastify-table 1.0.9 → 1.0.11
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/.eslintrc.cjs +42 -42
- package/Changelog.md +47 -47
- package/README.md +26 -26
- package/config.js +11 -11
- package/crud/controllers/deleteCrud.js +10 -10
- package/crud/controllers/insert.js +28 -28
- package/crud/controllers/update.js +29 -29
- package/crud/controllers/utils/checkXSS.js +45 -45
- package/crud/controllers/utils/xssInjection.js +72 -72
- package/crud/funcs/dataDelete.js +15 -15
- package/crud/funcs/dataInsert.js +24 -24
- package/crud/funcs/dataUpdate.js +3 -3
- package/crud/funcs/{getIdByToken.js → getToken.js} +27 -29
- package/crud/funcs/isFileExists.js +13 -13
- package/crud/funcs/{setTokenById.js → setToken.js} +53 -55
- package/helper.js +28 -28
- package/index.js +32 -32
- package/package.json +22 -22
- package/pg/funcs/autoIndex.js +89 -89
- package/pg/funcs/getMeta.js +27 -27
- package/pg/funcs/getPG.js +3 -0
- package/pg/funcs/init.js +42 -42
- package/pg/funcs/pgClients.js +2 -2
- package/pg/index.js +35 -35
- package/pg/pgClients.js +20 -17
- package/policy/funcs/checkPolicy.js +74 -74
- package/policy/funcs/sqlInjection.js +33 -33
- package/policy/index.js +14 -14
- package/redis/client.js +8 -8
- package/redis/funcs/getRedis.js +1 -2
- package/redis/funcs/redisClients.js +2 -2
- package/redis/index.js +19 -19
- package/server/templates/form/test.dataset.form.json +411 -411
- package/server.js +14 -14
- package/table/controllers/data.js +57 -55
- package/table/controllers/filter.js +32 -24
- package/table/controllers/form.js +10 -10
- package/table/controllers/suggest.js +60 -60
- package/table/controllers/utils/getSelect.js +20 -20
- package/table/controllers/utils/getSelectMeta.js +66 -66
- package/table/funcs/getFilterSQL/index.js +75 -75
- package/table/funcs/getFilterSQL/util/formatValue.js +142 -142
- package/table/funcs/getFilterSQL/util/getCustomQuery.js +13 -13
- package/table/funcs/getFilterSQL/util/getFilterQuery.js +73 -73
- package/table/funcs/getFilterSQL/util/getOptimizedQuery.js +12 -12
- package/table/funcs/getFilterSQL/util/getTableSql.js +34 -34
- package/table/funcs/metaFormat/getSelectVal.js +20 -0
- package/table/funcs/metaFormat/index.js +24 -0
- package/table/index.js +25 -14
- package/test/api/crud.test.js +50 -50
- package/test/api/crud.xss.test.js +68 -70
- package/test/api/table.test.js +49 -49
- package/test/config.example +18 -18
- package/test/funcs/crud.test.js +76 -77
- package/test/funcs/pg.test.js +34 -32
- package/test/funcs/redis.test.js +19 -19
- package/test/templates/cls/itree.recommend.json +26 -0
- package/test/templates/cls/itree.type_plant.json +65 -0
- package/test/templates/cls/test.json +9 -9
- package/test/templates/form/cp_building.form.json +32 -32
- package/test/templates/select/account_id.json +3 -3
- package/test/templates/select/contact_id.sql +1 -0
- package/test/templates/select/storage.data.json +2 -2
- package/test/templates/table/gis.dataset.table.json +20 -20
- package/test/templates/table/green_space.table.json +3 -3
- package/test/funcs/table.test.js +0 -48
package/server.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
// This file contains code that we reuse
|
|
2
|
-
// between our tests.
|
|
3
|
-
import Fastify from 'fastify';
|
|
4
|
-
import config from './test/config.js';
|
|
5
|
-
import appService from './index.js';
|
|
6
|
-
|
|
7
|
-
const app = Fastify({ logger: false });
|
|
8
|
-
app.register(appService, config);
|
|
9
|
-
app.listen({ host: '0.0.0.0', port: process.env.PORT || 3000 }, (err) => {
|
|
10
|
-
if (err) {
|
|
11
|
-
app.log.error(err);
|
|
12
|
-
process.exit(1);
|
|
13
|
-
}
|
|
14
|
-
});
|
|
1
|
+
// This file contains code that we reuse
|
|
2
|
+
// between our tests.
|
|
3
|
+
import Fastify from 'fastify';
|
|
4
|
+
import config from './test/config.js';
|
|
5
|
+
import appService from './index.js';
|
|
6
|
+
|
|
7
|
+
const app = Fastify({ logger: false });
|
|
8
|
+
app.register(appService, config);
|
|
9
|
+
app.listen({ host: '0.0.0.0', port: process.env.PORT || 3000 }, (err) => {
|
|
10
|
+
if (err) {
|
|
11
|
+
app.log.error(err);
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
@@ -1,55 +1,57 @@
|
|
|
1
|
-
import getTemplate from './utils/getTemplate.js';
|
|
2
|
-
import getFilterSQL from '../funcs/getFilterSQL/index.js';
|
|
3
|
-
import getMeta from '../../pg/funcs/getMeta.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
1
|
+
import getTemplate from './utils/getTemplate.js';
|
|
2
|
+
import getFilterSQL from '../funcs/getFilterSQL/index.js';
|
|
3
|
+
import getMeta from '../../pg/funcs/getMeta.js';
|
|
4
|
+
import metaFormat from '../funcs/metaFormat/index.js';
|
|
5
|
+
|
|
6
|
+
const maxLimit = 100;
|
|
7
|
+
export default async function data(req) {
|
|
8
|
+
const time = Date.now();
|
|
9
|
+
const {
|
|
10
|
+
pg, params, query = {},
|
|
11
|
+
} = req;
|
|
12
|
+
|
|
13
|
+
const loadTable = await getTemplate('table', params.table);
|
|
14
|
+
|
|
15
|
+
if (!loadTable) { return { status: 404, message: 'not found' }; }
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
table, columns, sql, filters, form, meta,
|
|
19
|
+
} = loadTable;
|
|
20
|
+
const { pk } = await getMeta(table);
|
|
21
|
+
|
|
22
|
+
const cols = columns.map((el) => el.name || el).join(',');
|
|
23
|
+
const sqlTable = sql?.filter?.((el) => !el?.disabled && el?.sql?.replace).map((el, i) => ` left join lateral (${el.sql}) ${el.name || `t${i}`} on 1=1 `)?.join('') || '';
|
|
24
|
+
|
|
25
|
+
const fData = query.filter ? await getFilterSQL({
|
|
26
|
+
filter: query.filter,
|
|
27
|
+
table,
|
|
28
|
+
json: 1,
|
|
29
|
+
}) : {};
|
|
30
|
+
|
|
31
|
+
const keyQuery = query.key && loadTable.key && !params.id ? `${loadTable.key}=$1` : null;
|
|
32
|
+
|
|
33
|
+
const limit = Math.min(maxLimit, +(query.limit || 10));
|
|
34
|
+
|
|
35
|
+
const offset = query.page && query.page > 0 ? ` offset ${(query.page - 1) * limit}` : '';
|
|
36
|
+
// id, query, filter
|
|
37
|
+
const [orderColumn, orderDir] = (query.order || loadTable.order || '').split('-');
|
|
38
|
+
|
|
39
|
+
const order = cols.includes(orderColumn) && orderColumn?.length ? `order by ${orderColumn} ${query.desc || orderDir === 'desc' ? 'desc' : ''}` : '';
|
|
40
|
+
const state = loadTable.filterState && query.state ? loadTable.filterState[query.state]?.sql : null;
|
|
41
|
+
const custom = loadTable.filterCustom && query.custom ? loadTable.filterCustom[query.custom]?.sql : null;
|
|
42
|
+
const search = loadTable.meta?.search && query.search ? `(${loadTable.meta?.search.split(',').map(el => `${el} ilike '%${query.search}%'`).join(' or ')})` : null;
|
|
43
|
+
|
|
44
|
+
const where = [(params.id ? ` "${pk}" = $1` : null), keyQuery, loadTable.query, fData.q, state, custom, search].filter((el) => el);
|
|
45
|
+
const q = `select ${pk ? `"${pk}" as id,` : ''} ${query.id || query.key ? '*' : cols || '*'} from ${table} t ${sqlTable} where ${where.join(' and ') || 'true'} ${order} ${offset} limit ${limit}`;
|
|
46
|
+
|
|
47
|
+
if (query.sql === '1') { return q; }
|
|
48
|
+
|
|
49
|
+
const { rows } = await pg.query(q, (params.id ? [params.id] : null) || (query.key && loadTable.key ? [query.key] : []));
|
|
50
|
+
|
|
51
|
+
const total = keyQuery || params.id ? rows.length : await pg.queryCache(`select count(*) from ${table} t where ${where.join(' and ') || 'true'}`).then((el) => el?.rows[0]?.count);
|
|
52
|
+
|
|
53
|
+
await metaFormat({ rows, table: params.table });
|
|
54
|
+
return {
|
|
55
|
+
time: Date.now() - time, total, count: rows.length, pk, form, rows, meta, columns, filters,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -1,24 +1,32 @@
|
|
|
1
|
-
import getTemplate from './utils/getTemplate.js';
|
|
2
|
-
import getSelect from './utils/getSelect.js';
|
|
3
|
-
|
|
4
|
-
export default async function filter(req) {
|
|
5
|
-
const time = Date.now();
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
1
|
+
import getTemplate from './utils/getTemplate.js';
|
|
2
|
+
import getSelect from './utils/getSelect.js';
|
|
3
|
+
|
|
4
|
+
export default async function filter(req) {
|
|
5
|
+
const time = Date.now();
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
params,
|
|
9
|
+
} = req;
|
|
10
|
+
const loadTable = await getTemplate('table', params.table);
|
|
11
|
+
if (!loadTable) { return { status: 404, message: 'not found' }; }
|
|
12
|
+
|
|
13
|
+
const filters = loadTable?.filters || loadTable?.filterList || [];
|
|
14
|
+
await Promise.all(filters.filter((el) => el.data).map(async (el) => {
|
|
15
|
+
const cls = await getSelect(el.data);
|
|
16
|
+
if (!cls?.arr || !loadTable.table) return;
|
|
17
|
+
const countArr = await req.pg.queryCache(`select ${el.id}::text as id,count(*) from ${loadTable.table} group by ${el.id}`);
|
|
18
|
+
|
|
19
|
+
const options = countArr.rows.map(cel => {
|
|
20
|
+
const data = cls?.arr.find(c => c.id === cel.id);
|
|
21
|
+
return { ...cel, ...data };
|
|
22
|
+
});
|
|
23
|
+
Object.assign(el, { options });
|
|
24
|
+
}));
|
|
25
|
+
return {
|
|
26
|
+
time: Date.now() - time,
|
|
27
|
+
list: filters,
|
|
28
|
+
custom: loadTable?.filterCustom?.map(el => ({ label: el.label })),
|
|
29
|
+
inline: loadTable?.filterInline,
|
|
30
|
+
state: loadTable?.filterState?.map(el => ({ label: el.label })),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import getTemplate from './utils/getTemplate.js';
|
|
2
|
-
|
|
3
|
-
export default async function formFunction(req) {
|
|
4
|
-
const time = Date.now();
|
|
5
|
-
const { params } = req;
|
|
6
|
-
const form = await getTemplate('form', params.form);
|
|
7
|
-
if (!form) { return { status: 404, message: 'not found' }; }
|
|
8
|
-
|
|
9
|
-
return { time: Date.now() - time, form };
|
|
10
|
-
}
|
|
1
|
+
import getTemplate from './utils/getTemplate.js';
|
|
2
|
+
|
|
3
|
+
export default async function formFunction(req) {
|
|
4
|
+
const time = Date.now();
|
|
5
|
+
const { params } = req;
|
|
6
|
+
const form = await getTemplate('form', params.form);
|
|
7
|
+
if (!form) { return { status: 404, message: 'not found' }; }
|
|
8
|
+
|
|
9
|
+
return { time: Date.now() - time, form };
|
|
10
|
+
}
|
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
import getSelectMeta from './utils/getSelectMeta.js';
|
|
2
|
-
import getPG from '../../pg/funcs/getPG.js';
|
|
3
|
-
|
|
4
|
-
const limit = 50;
|
|
5
|
-
const headers = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET', 'Cache-Control': 'no-cache' };
|
|
6
|
-
|
|
7
|
-
export default async function suggest(req) {
|
|
8
|
-
const { params, query, pg: pg1 } = req;
|
|
9
|
-
|
|
10
|
-
const lang = query.lang || 'ua';
|
|
11
|
-
const time = Date.now();
|
|
12
|
-
const parent = query.parent || '';
|
|
13
|
-
|
|
14
|
-
const selectName = query.sel || query.name || params.data;
|
|
15
|
-
if (!selectName) return { headers, status: 400, message: 'name is required' };
|
|
16
|
-
|
|
17
|
-
const meta = await getSelectMeta({ name: selectName });
|
|
18
|
-
const pg = meta.db ? getPG({ db: meta.db }) : pg1;
|
|
19
|
-
if (!meta) return { headers, status: 404, message: 'Not found query select ' };
|
|
20
|
-
|
|
21
|
-
const { arr, searchQuery } = meta;
|
|
22
|
-
|
|
23
|
-
if (arr) {
|
|
24
|
-
const lower = query.key?.toLowerCase();
|
|
25
|
-
const data = query.key || query.val
|
|
26
|
-
? arr?.filter((el) => !lower || (el[lang] || el.text)?.toLowerCase()?.indexOf(lower) !== -1)?.filter((el) => !query.val || el.id === query.val)
|
|
27
|
-
: arr;
|
|
28
|
-
return {
|
|
29
|
-
limit, count: data.length, mode: 'array', time: Date.now() - time, data,
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// search
|
|
34
|
-
const search = query.key ? searchQuery : null;
|
|
35
|
-
|
|
36
|
-
// val
|
|
37
|
-
const pk = meta.originalCols.split(',')[0];
|
|
38
|
-
const val = query.val ? ` ${pk}=any('{${query.val.replace(/'/g, "''")}}')` : '';
|
|
39
|
-
|
|
40
|
-
const sqlSuggest = `with rows(id,text) as (${meta.original.replace(/{{parent}}/gi, parent)} where ${[search, val].filter((el) => el).join(' and ') || 'true'}) select * from rows limit ${limit}`;
|
|
41
|
-
if (query.sql) return sqlSuggest;
|
|
42
|
-
|
|
43
|
-
// query
|
|
44
|
-
const { rows: dataNew } = meta.searchColumn ? { rows: [] } : await pg.query(sqlSuggest, query.key ? [`${query.key}%`] : []);
|
|
45
|
-
const { rows: dataNew1 } = dataNew.length < limit ? await pg.query(sqlSuggest, query.key ? [`%${query.key}%`] : []) : {};
|
|
46
|
-
const ids = dataNew.map((el) => el.id);
|
|
47
|
-
const data = dataNew.concat((dataNew1 || []).filter((el) => !ids?.includes(el.id)));
|
|
48
|
-
|
|
49
|
-
const message = {
|
|
50
|
-
time: Date.now() - time,
|
|
51
|
-
count: data.length,
|
|
52
|
-
total: meta.count - 0,
|
|
53
|
-
mode: 'sql',
|
|
54
|
-
db: meta.db,
|
|
55
|
-
sql: sqlSuggest,
|
|
56
|
-
data,
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
return message;
|
|
60
|
-
}
|
|
1
|
+
import getSelectMeta from './utils/getSelectMeta.js';
|
|
2
|
+
import getPG from '../../pg/funcs/getPG.js';
|
|
3
|
+
|
|
4
|
+
const limit = 50;
|
|
5
|
+
const headers = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET', 'Cache-Control': 'no-cache' };
|
|
6
|
+
|
|
7
|
+
export default async function suggest(req) {
|
|
8
|
+
const { params, query, pg: pg1 } = req;
|
|
9
|
+
|
|
10
|
+
const lang = query.lang || 'ua';
|
|
11
|
+
const time = Date.now();
|
|
12
|
+
const parent = query.parent || '';
|
|
13
|
+
|
|
14
|
+
const selectName = query.sel || query.name || params.data;
|
|
15
|
+
if (!selectName) return { headers, status: 400, message: 'name is required' };
|
|
16
|
+
|
|
17
|
+
const meta = await getSelectMeta({ name: selectName });
|
|
18
|
+
const pg = meta.db ? getPG({ db: meta.db }) : pg1;
|
|
19
|
+
if (!meta) return { headers, status: 404, message: 'Not found query select ' };
|
|
20
|
+
|
|
21
|
+
const { arr, searchQuery } = meta;
|
|
22
|
+
|
|
23
|
+
if (arr) {
|
|
24
|
+
const lower = query.key?.toLowerCase();
|
|
25
|
+
const data = query.key || query.val
|
|
26
|
+
? arr?.filter((el) => !lower || (el[lang] || el.text)?.toLowerCase()?.indexOf(lower) !== -1)?.filter((el) => !query.val || el.id === query.val)
|
|
27
|
+
: arr;
|
|
28
|
+
return {
|
|
29
|
+
limit, count: data.length, mode: 'array', time: Date.now() - time, data,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// search
|
|
34
|
+
const search = query.key ? searchQuery : null;
|
|
35
|
+
|
|
36
|
+
// val
|
|
37
|
+
const pk = meta.originalCols.split(',')[0];
|
|
38
|
+
const val = query.val ? ` ${pk}=any('{${query.val.replace(/'/g, "''")}}')` : '';
|
|
39
|
+
|
|
40
|
+
const sqlSuggest = `with rows(id,text) as (${meta.original.replace(/{{parent}}/gi, parent)} where ${[search, val].filter((el) => el).join(' and ') || 'true'}) select * from rows limit ${limit}`;
|
|
41
|
+
if (query.sql) return sqlSuggest;
|
|
42
|
+
|
|
43
|
+
// query
|
|
44
|
+
const { rows: dataNew } = meta.searchColumn ? { rows: [] } : await pg.query(sqlSuggest, query.key ? [`${query.key}%`] : []);
|
|
45
|
+
const { rows: dataNew1 } = dataNew.length < limit ? await pg.query(sqlSuggest, query.key ? [`%${query.key}%`] : []) : {};
|
|
46
|
+
const ids = dataNew.map((el) => el.id);
|
|
47
|
+
const data = dataNew.concat((dataNew1 || []).filter((el) => !ids?.includes(el.id)));
|
|
48
|
+
|
|
49
|
+
const message = {
|
|
50
|
+
time: Date.now() - time,
|
|
51
|
+
count: data.length,
|
|
52
|
+
total: meta.count - 0,
|
|
53
|
+
mode: 'sql',
|
|
54
|
+
db: meta.db,
|
|
55
|
+
sql: sqlSuggest,
|
|
56
|
+
data,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return message;
|
|
60
|
+
}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import getTemplate from './getTemplate.js';
|
|
2
|
-
|
|
3
|
-
const loadCls = {};
|
|
4
|
-
|
|
5
|
-
export default async function getTable(name) {
|
|
6
|
-
if (loadCls[name]) return loadCls[name];
|
|
7
|
-
|
|
8
|
-
const clsData = await getTemplate('cls', name);
|
|
9
|
-
|
|
10
|
-
if (clsData) {
|
|
11
|
-
loadCls[name] = { arr: clsData };
|
|
12
|
-
return loadCls[name];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const selectData = await getTemplate('select', name);
|
|
16
|
-
if (!selectData) { return null; }
|
|
17
|
-
|
|
18
|
-
loadCls[name] = selectData;
|
|
19
|
-
return loadCls[name];
|
|
20
|
-
}
|
|
1
|
+
import getTemplate from './getTemplate.js';
|
|
2
|
+
|
|
3
|
+
const loadCls = {};
|
|
4
|
+
|
|
5
|
+
export default async function getTable(name) {
|
|
6
|
+
if (loadCls[name]) return loadCls[name];
|
|
7
|
+
|
|
8
|
+
const clsData = await getTemplate('cls', name);
|
|
9
|
+
|
|
10
|
+
if (clsData) {
|
|
11
|
+
loadCls[name] = { arr: clsData };
|
|
12
|
+
return loadCls[name];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const selectData = await getTemplate('select', name);
|
|
16
|
+
if (!selectData) { return null; }
|
|
17
|
+
|
|
18
|
+
loadCls[name] = selectData;
|
|
19
|
+
return loadCls[name];
|
|
20
|
+
}
|
|
@@ -1,66 +1,66 @@
|
|
|
1
|
-
// import pgClients from '../../../pg/pgClients.js';
|
|
2
|
-
import getPG from '../../../pg/funcs/getPG.js';
|
|
3
|
-
|
|
4
|
-
import getSelect from './getSelect.js';
|
|
5
|
-
|
|
6
|
-
/*
|
|
7
|
-
function getTable(table) {
|
|
8
|
-
// eslint-disable-next-line class-methods-use-this
|
|
9
|
-
const result = table.toLowerCase().replace(/[\n\r]+/g, ' ').split(' from ').filter((el) => /^[a-z0-9_]+\.[a-z0-9_]+/.test(el))
|
|
10
|
-
.map((el) => el.split(/[ )]/)[0]);
|
|
11
|
-
return result?.pop();
|
|
12
|
-
} */
|
|
13
|
-
|
|
14
|
-
const selectMeta = {};
|
|
15
|
-
|
|
16
|
-
export default async function getSelectMeta({ name, pg: pg1 }) {
|
|
17
|
-
if (selectMeta[name]) return selectMeta[name];
|
|
18
|
-
|
|
19
|
-
const cls = await getSelect(name);
|
|
20
|
-
|
|
21
|
-
if (!cls) return null;
|
|
22
|
-
if (cls.arr) return cls;
|
|
23
|
-
if (!cls.sql) return null;
|
|
24
|
-
|
|
25
|
-
const pg = pg1 || getPG({ db: cls.db || 'client' });
|
|
26
|
-
const { sql: original } = cls;
|
|
27
|
-
const sql = `with c(id,text) as (${original} ) select * from c where id is not null `;
|
|
28
|
-
|
|
29
|
-
/*= == meta table === */
|
|
30
|
-
const tableNew = original.toLowerCase().replace(/\n/g, ' ').split(' from ').filter((el) => /^[a-z0-9_]+\.[a-z0-9_]+/.test(el))
|
|
31
|
-
.map((el) => el.split(/[ )]/)[0].replace(/[\r\n]+/g, ''));
|
|
32
|
-
|
|
33
|
-
const dataOrigin = await pg.query(`${sql} limit 0`);
|
|
34
|
-
|
|
35
|
-
const dataOrigin1 = await pg.query(`${original} limit 0`);
|
|
36
|
-
|
|
37
|
-
// const table = getTable(original);
|
|
38
|
-
const count = cls?.count ?? await pg.query(`select count(*) from (${original})q`).then((el) => el?.rows?.[0].count);
|
|
39
|
-
|
|
40
|
-
// column name
|
|
41
|
-
const cols = dataOrigin.fields.map((el) => el.name);
|
|
42
|
-
const type = dataOrigin.fields.map((el) => pg.pgType?.[el.dataTypeID] || 'text');
|
|
43
|
-
|
|
44
|
-
const searchColumn = cls?.searchColumn || (
|
|
45
|
-
dataOrigin.fields.find((el) => el.name === 'search') ? 'search' : dataOrigin1.fields[1].name);
|
|
46
|
-
|
|
47
|
-
const searchQuery = `(${searchColumn.split(',').map((el) => `"${el}" ilike $1 `).join(' or ')})`;
|
|
48
|
-
|
|
49
|
-
const data = {
|
|
50
|
-
|
|
51
|
-
type: type.join(','),
|
|
52
|
-
cols: cols.join(','),
|
|
53
|
-
originalCols: dataOrigin1.fields.map((el) => el.name).join(','),
|
|
54
|
-
db: cls.db,
|
|
55
|
-
original: original?.includes('where') ? `select * from (${original})q` : original,
|
|
56
|
-
sql,
|
|
57
|
-
count,
|
|
58
|
-
searchQuery,
|
|
59
|
-
table: tableNew.join(','),
|
|
60
|
-
time: new Date().toISOString(),
|
|
61
|
-
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
selectMeta[name] = data;
|
|
65
|
-
return data;
|
|
66
|
-
}
|
|
1
|
+
// import pgClients from '../../../pg/pgClients.js';
|
|
2
|
+
import getPG from '../../../pg/funcs/getPG.js';
|
|
3
|
+
|
|
4
|
+
import getSelect from './getSelect.js';
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
function getTable(table) {
|
|
8
|
+
// eslint-disable-next-line class-methods-use-this
|
|
9
|
+
const result = table.toLowerCase().replace(/[\n\r]+/g, ' ').split(' from ').filter((el) => /^[a-z0-9_]+\.[a-z0-9_]+/.test(el))
|
|
10
|
+
.map((el) => el.split(/[ )]/)[0]);
|
|
11
|
+
return result?.pop();
|
|
12
|
+
} */
|
|
13
|
+
|
|
14
|
+
const selectMeta = {};
|
|
15
|
+
|
|
16
|
+
export default async function getSelectMeta({ name, pg: pg1 }) {
|
|
17
|
+
if (selectMeta[name]) return selectMeta[name];
|
|
18
|
+
|
|
19
|
+
const cls = await getSelect(name);
|
|
20
|
+
|
|
21
|
+
if (!cls) return null;
|
|
22
|
+
if (cls.arr) return cls;
|
|
23
|
+
if (!cls.sql) return null;
|
|
24
|
+
|
|
25
|
+
const pg = pg1 || getPG({ db: cls.db || 'client' });
|
|
26
|
+
const { sql: original } = cls;
|
|
27
|
+
const sql = `with c(id,text) as (${original} ) select * from c where id is not null `;
|
|
28
|
+
|
|
29
|
+
/*= == meta table === */
|
|
30
|
+
const tableNew = original.toLowerCase().replace(/\n/g, ' ').split(' from ').filter((el) => /^[a-z0-9_]+\.[a-z0-9_]+/.test(el))
|
|
31
|
+
.map((el) => el.split(/[ )]/)[0].replace(/[\r\n]+/g, ''));
|
|
32
|
+
|
|
33
|
+
const dataOrigin = await pg.query(`${sql} limit 0`);
|
|
34
|
+
|
|
35
|
+
const dataOrigin1 = await pg.query(`${original} limit 0`);
|
|
36
|
+
|
|
37
|
+
// const table = getTable(original);
|
|
38
|
+
const count = cls?.count ?? await pg.query(`select count(*) from (${original})q`).then((el) => el?.rows?.[0].count);
|
|
39
|
+
|
|
40
|
+
// column name
|
|
41
|
+
const cols = dataOrigin.fields.map((el) => el.name);
|
|
42
|
+
const type = dataOrigin.fields.map((el) => pg.pgType?.[el.dataTypeID] || 'text');
|
|
43
|
+
|
|
44
|
+
const searchColumn = cls?.searchColumn || (
|
|
45
|
+
dataOrigin.fields.find((el) => el.name === 'search') ? 'search' : dataOrigin1.fields[1].name);
|
|
46
|
+
|
|
47
|
+
const searchQuery = `(${searchColumn.split(',').map((el) => `"${el}" ilike $1 `).join(' or ')})`;
|
|
48
|
+
|
|
49
|
+
const data = {
|
|
50
|
+
|
|
51
|
+
type: type.join(','),
|
|
52
|
+
cols: cols.join(','),
|
|
53
|
+
originalCols: dataOrigin1.fields.map((el) => el.name).join(','),
|
|
54
|
+
db: cls.db,
|
|
55
|
+
original: original?.includes('where') ? `select * from (${original})q` : original,
|
|
56
|
+
sql,
|
|
57
|
+
count,
|
|
58
|
+
searchQuery,
|
|
59
|
+
table: tableNew.join(','),
|
|
60
|
+
time: new Date().toISOString(),
|
|
61
|
+
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
selectMeta[name] = data;
|
|
65
|
+
return data;
|
|
66
|
+
}
|