@opengis/fastify-table 1.0.36 → 1.0.37
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/Changelog.md +4 -0
- package/crud/controllers/insert.js +29 -29
- package/crud/controllers/update.js +31 -31
- package/crud/funcs/getOpt.js +10 -10
- package/crud/funcs/setOpt.js +16 -16
- package/crud/index.js +29 -29
- package/helper.js +28 -28
- package/notification/controllers/userNotifications.js +19 -19
- package/notification/funcs/addNotification.js +8 -8
- package/notification/index.js +19 -19
- package/package.json +1 -1
- package/pg/pgClients.js +20 -20
- 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/redisClients.js +2 -2
- package/redis/index.js +19 -19
- package/server/templates/form/test.dataset.form.json +411 -411
- package/server/templates/select/test.storage.data.json +2 -2
- package/server/templates/table/test.dataset.table.json +24 -24
- package/table/controllers/data.js +57 -57
- 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/controllers/utils/getTemplate.js +28 -28
- 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/metaFormat/getSelectVal.js +20 -20
- package/table/funcs/metaFormat/index.js +26 -26
- package/table/index.js +42 -42
- package/test/api/crud.test.js +56 -56
- package/test/api/crud.xss.test.js +71 -71
- package/test/api/notification.test.js +37 -37
- package/test/api/table.test.js +57 -57
- package/test/funcs/notification.test.js +31 -31
- package/widget/controllers/utils/historyFormat.js +76 -76
- package/widget/controllers/utils/obj2db.js +13 -13
- package/widget/controllers/widget.del.js +44 -41
- package/widget/controllers/widget.get.js +86 -77
- package/widget/controllers/widget.set.js +70 -64
- package/widget/index.js +29 -29
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
{
|
|
2
|
-
"key": "dataset_id"
|
|
1
|
+
{
|
|
2
|
+
"key": "dataset_id"
|
|
3
3
|
}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
{
|
|
2
|
-
"columns": [
|
|
3
|
-
{
|
|
4
|
-
"name": "dataset_id",
|
|
5
|
-
"title": "22"
|
|
6
|
-
},
|
|
7
|
-
{
|
|
8
|
-
"name": "dataset_name",
|
|
9
|
-
"title": "dataset_name"
|
|
10
|
-
}
|
|
11
|
-
],
|
|
12
|
-
"table": "gis.dataset",
|
|
13
|
-
"order": "dataset_name",
|
|
14
|
-
"meta": {
|
|
15
|
-
"title": "dataset_name",
|
|
16
|
-
"search": "dataset_name,dataset_id"
|
|
17
|
-
},
|
|
18
|
-
"filters": [
|
|
19
|
-
{
|
|
20
|
-
"ua": "Назва набору",
|
|
21
|
-
"name": "dataset_name",
|
|
22
|
-
"type": "text"
|
|
23
|
-
}
|
|
24
|
-
]
|
|
1
|
+
{
|
|
2
|
+
"columns": [
|
|
3
|
+
{
|
|
4
|
+
"name": "dataset_id",
|
|
5
|
+
"title": "22"
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"name": "dataset_name",
|
|
9
|
+
"title": "dataset_name"
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"table": "gis.dataset",
|
|
13
|
+
"order": "dataset_name",
|
|
14
|
+
"meta": {
|
|
15
|
+
"title": "dataset_name",
|
|
16
|
+
"search": "dataset_name,dataset_id"
|
|
17
|
+
},
|
|
18
|
+
"filters": [
|
|
19
|
+
{
|
|
20
|
+
"ua": "Назва набору",
|
|
21
|
+
"name": "dataset_name",
|
|
22
|
+
"type": "text"
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
25
|
}
|
|
@@ -1,57 +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
|
-
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: params.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
|
+
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: params.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,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
|
+
}
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
import { readFile } from 'fs/promises';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import config from '../../../config.js';
|
|
5
|
-
|
|
6
|
-
const loadTemplate = {};
|
|
7
|
-
|
|
8
|
-
export default async function getTemplateDir(type, name) {
|
|
9
|
-
if (!type) return null;
|
|
10
|
-
if (!name) return null;
|
|
11
|
-
|
|
12
|
-
const cwd = process.cwd();
|
|
13
|
-
const typeDir = path.join(cwd, (config.templateDir || 'server/templates'), type);
|
|
14
|
-
|
|
15
|
-
if (!loadTemplate[type]) {
|
|
16
|
-
const typeList = fs.existsSync(typeDir) ? fs.readdirSync(typeDir) : [];
|
|
17
|
-
loadTemplate[type] = typeList;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const fullname = loadTemplate[type].find((el) => path.parse(el).name === name);
|
|
21
|
-
const ext = fullname ? path.extname(fullname)?.slice(1) : null;
|
|
22
|
-
if (!ext) return null;
|
|
23
|
-
|
|
24
|
-
const sql = loadTemplate[type].includes(`${name}.sql`) ? await readFile(path.join(typeDir, `${name}.sql`), 'utf-8') : null;
|
|
25
|
-
const data = loadTemplate[type].includes(`${name}.json`) ? JSON.parse(await readFile(path.join(typeDir, `${name}.json`), 'utf-8')) : await readFile(path.join(typeDir, `${name}.${ext}`), 'utf-8');
|
|
26
|
-
if (sql) return { ...data || {}, sql };
|
|
27
|
-
return data;
|
|
28
|
-
}
|
|
1
|
+
import { readFile } from 'fs/promises';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import config from '../../../config.js';
|
|
5
|
+
|
|
6
|
+
const loadTemplate = {};
|
|
7
|
+
|
|
8
|
+
export default async function getTemplateDir(type, name) {
|
|
9
|
+
if (!type) return null;
|
|
10
|
+
if (!name) return null;
|
|
11
|
+
|
|
12
|
+
const cwd = process.cwd();
|
|
13
|
+
const typeDir = path.join(cwd, (config.templateDir || 'server/templates'), type);
|
|
14
|
+
|
|
15
|
+
if (!loadTemplate[type]) {
|
|
16
|
+
const typeList = fs.existsSync(typeDir) ? fs.readdirSync(typeDir) : [];
|
|
17
|
+
loadTemplate[type] = typeList;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const fullname = loadTemplate[type].find((el) => path.parse(el).name === name);
|
|
21
|
+
const ext = fullname ? path.extname(fullname)?.slice(1) : null;
|
|
22
|
+
if (!ext) return null;
|
|
23
|
+
|
|
24
|
+
const sql = loadTemplate[type].includes(`${name}.sql`) ? await readFile(path.join(typeDir, `${name}.sql`), 'utf-8') : null;
|
|
25
|
+
const data = loadTemplate[type].includes(`${name}.json`) ? JSON.parse(await readFile(path.join(typeDir, `${name}.json`), 'utf-8')) : await readFile(path.join(typeDir, `${name}.${ext}`), 'utf-8');
|
|
26
|
+
if (sql) return { ...data || {}, sql };
|
|
27
|
+
return data;
|
|
28
|
+
}
|