@opengis/fastify-table 1.0.97 → 1.1.1

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.
Files changed (59) hide show
  1. package/.eslintrc.cjs +42 -42
  2. package/README.md +26 -26
  3. package/config.js +10 -10
  4. package/cron/controllers/cronApi.js +22 -22
  5. package/cron/controllers/utils/cronList.js +1 -1
  6. package/cron/funcs/addCron.js +131 -131
  7. package/cron/index.js +10 -10
  8. package/crud/controllers/utils/checkXSS.js +45 -45
  9. package/crud/controllers/utils/xssInjection.js +72 -72
  10. package/crud/funcs/dataUpdate.js +30 -30
  11. package/crud/funcs/getToken.js +27 -27
  12. package/crud/funcs/isFileExists.js +13 -13
  13. package/crud/funcs/setToken.js +53 -53
  14. package/crud/funcs/utils/logChanges.js +7 -4
  15. package/notification/controllers/testEmail.js +49 -49
  16. package/notification/funcs/utils/sendEmail.js +39 -39
  17. package/notification/index.js +38 -38
  18. package/package.json +1 -1
  19. package/pg/funcs/getPG.js +30 -30
  20. package/redis/funcs/getRedis.js +23 -23
  21. package/server/migrations/crm.sql +150 -150
  22. package/server/migrations/log.sql +80 -80
  23. package/server/templates/select/test.storage.data.json +3 -3
  24. package/server/templates/select/test.suggest.ato_new.json +2 -2
  25. package/server/templates/select/test.suggest.ato_new.sql +25 -25
  26. package/server/templates/select/test.suggest.data.json +4 -4
  27. package/server/templates/select/test.suggest.parent.sql +2 -2
  28. package/server.js +14 -14
  29. package/table/controllers/card.js +44 -44
  30. package/table/controllers/filter.js +37 -37
  31. package/table/controllers/form.js +28 -28
  32. package/table/controllers/search.js +80 -72
  33. package/table/controllers/utils/getSelect.js +20 -20
  34. package/table/controllers/utils/getTemplate.js +69 -28
  35. package/table/controllers/utils/getTemplatePath.js +40 -0
  36. package/table/controllers/utils/getTemplate_old.js +28 -0
  37. package/table/controllers/utils/getTemplates.js +18 -18
  38. package/table/controllers/utils/loadTemplate.js +1 -0
  39. package/table/controllers/utils/loadTemplatePath.js +1 -0
  40. package/table/index.js +84 -80
  41. package/test/api/crud.xss.test.js +72 -72
  42. package/test/api/notification.test.js +37 -37
  43. package/test/api/suggest.test.js +65 -65
  44. package/test/config.example +18 -18
  45. package/test/funcs/notification.test.js +31 -31
  46. package/test/funcs/pg.test.js +34 -34
  47. package/test/funcs/redis.test.js +19 -19
  48. package/test/templates/cls/test.json +9 -9
  49. package/test/templates/form/cp_building.form.json +32 -32
  50. package/test/templates/select/account_id.json +3 -3
  51. package/test/templates/select/storage.data.json +2 -2
  52. package/test/templates/table/gis.dataset.table.json +20 -20
  53. package/util/controllers/logger.file.js +90 -90
  54. package/util/controllers/next.id.js +4 -4
  55. package/util/controllers/properties.get.js +19 -19
  56. package/util/controllers/utils/checkUserAccess.js +19 -19
  57. package/util/controllers/utils/getRootDir.js +20 -20
  58. package/util/index.js +23 -23
  59. package/utils.js +8 -0
@@ -1,26 +1,26 @@
1
- select
2
- codifier,
3
- case
4
- when object_type = 'A' then name_ua
5
- else case
6
- when object_type in ('P', 'H', 'O', 'B') then name_ua || ' ' || prefix_ua
7
- else prefix_ua || ' ' || name_ua
8
- end
9
- end as title
10
- from
11
- ato_new.ato_new_all
12
- left join ato_new.ato_settings_city_and_terrytory on ato_type = object_type
13
- where
14
- codifier is not null
15
- union
16
- all
17
- select
18
- country_id,
19
- name_ua as title
20
- from
21
- ato_new.country
22
- where
23
- country_id = '2845832997045798794'
24
- union
25
- all
1
+ select
2
+ codifier,
3
+ case
4
+ when object_type = 'A' then name_ua
5
+ else case
6
+ when object_type in ('P', 'H', 'O', 'B') then name_ua || ' ' || prefix_ua
7
+ else prefix_ua || ' ' || name_ua
8
+ end
9
+ end as title
10
+ from
11
+ ato_new.ato_new_all
12
+ left join ato_new.ato_settings_city_and_terrytory on ato_type = object_type
13
+ where
14
+ codifier is not null
15
+ union
16
+ all
17
+ select
18
+ country_id,
19
+ name_ua as title
20
+ from
21
+ ato_new.country
22
+ where
23
+ country_id = '2845832997045798794'
24
+ union
25
+ all
26
26
  select 'UA00000000000000000', 'Україна'
@@ -1,5 +1,5 @@
1
- {
2
- "db": "mbk_poltava",
3
- "key": "dataset_id",
4
- "searchColumn": "table_name"
1
+ {
2
+ "db": "mbk_poltava",
3
+ "key": "dataset_id",
4
+ "searchColumn": "table_name"
5
5
  }
@@ -1,3 +1,3 @@
1
- select dataset_id, dataset_name, table_name from gis.dataset
2
- where
1
+ select dataset_id, dataset_name, table_name from gis.dataset
2
+ where
3
3
  dataset_id = '{{parent}}'
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,44 +1,44 @@
1
- import getTemplate from './utils/getTemplate.js';
2
- import getMeta from '../../pg/funcs/getMeta.js';
3
- import metaFormat from '../funcs/metaFormat/index.js';
4
-
5
- export default async function card(req) {
6
- const time = Date.now();
7
- const {
8
- pg, params = {}, query = {}, opt = {},
9
- } = req;
10
-
11
- const loadTable = await getTemplate('table', params.table);
12
-
13
- if (!loadTable) { return { message: 'template not found', status: 404 }; }
14
-
15
- const {
16
- table, columns, meta, sql, cardSql,
17
- } = loadTable;
18
-
19
- const { pk, columns: dbColumns = [] } = await getMeta(table);
20
-
21
- if (!pk) return { message: `table not found: ${table}`, status: 404 };
22
-
23
- const cols = columns.map((el) => el.name || el).join(',');
24
- const columnList = dbColumns.map((el) => el.name || el).join(',');
25
- 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('') || '';
26
- const cardSqlFiltered = opt.id || params.id ? cardSql?.filter?.((el) => !el?.disabled && el?.name && el?.sql?.replace) : [];
27
- const cardSqlTable = cardSqlFiltered?.length ? cardSqlFiltered.map((el, i) => ` left join lateral (select json_agg(row_to_json(q)) as ${el.name} from (${el.sql})q) ct${i} on 1=1 `).join('') || '' : '';
28
-
29
- const where = [`"${pk}" = $1`, loadTable.query].filter((el) => el);
30
- const cardColumns = cardSqlFiltered?.length ? `,${cardSqlFiltered.map((el) => el.name)}` : '';
31
- const q = `select ${pk ? `"${pk}" as id,` : ''} ${columnList.includes('geom') ? 'st_asgeojson(geom)::json as geom,' : ''} ${cols || '*'} ${cardColumns} from ${table} t ${sqlTable} ${cardSqlTable}
32
- where ${where.join(' and ') || 'true'} limit 1`;
33
-
34
- if (query.sql === '1') { return q; }
35
-
36
- const { rows } = await pg.query(q, [opt.id || params.id]);
37
-
38
- await metaFormat({ rows, table: params.table });
39
-
40
- const data = meta.card?.length ? meta.card.reduce((acc, curr) => Object.assign(acc, { [columns.find((col) => col.name === curr)?.ua || '']: rows[0][curr] }), {}) : {};
41
- return {
42
- time: Date.now() - time, data,
43
- };
44
- }
1
+ import getTemplate from './utils/getTemplate.js';
2
+ import getMeta from '../../pg/funcs/getMeta.js';
3
+ import metaFormat from '../funcs/metaFormat/index.js';
4
+
5
+ export default async function card(req) {
6
+ const time = Date.now();
7
+ const {
8
+ pg, params = {}, query = {}, opt = {},
9
+ } = req;
10
+
11
+ const loadTable = await getTemplate('table', params.table);
12
+
13
+ if (!loadTable) { return { message: 'template not found', status: 404 }; }
14
+
15
+ const {
16
+ table, columns, meta, sql, cardSql,
17
+ } = loadTable;
18
+
19
+ const { pk, columns: dbColumns = [] } = await getMeta(table);
20
+
21
+ if (!pk) return { message: `table not found: ${table}`, status: 404 };
22
+
23
+ const cols = columns.map((el) => el.name || el).join(',');
24
+ const columnList = dbColumns.map((el) => el.name || el).join(',');
25
+ 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('') || '';
26
+ const cardSqlFiltered = opt.id || params.id ? cardSql?.filter?.((el) => !el?.disabled && el?.name && el?.sql?.replace) : [];
27
+ const cardSqlTable = cardSqlFiltered?.length ? cardSqlFiltered.map((el, i) => ` left join lateral (select json_agg(row_to_json(q)) as ${el.name} from (${el.sql})q) ct${i} on 1=1 `).join('') || '' : '';
28
+
29
+ const where = [`"${pk}" = $1`, loadTable.query].filter((el) => el);
30
+ const cardColumns = cardSqlFiltered?.length ? `,${cardSqlFiltered.map((el) => el.name)}` : '';
31
+ const q = `select ${pk ? `"${pk}" as id,` : ''} ${columnList.includes('geom') ? 'st_asgeojson(geom)::json as geom,' : ''} ${cols || '*'} ${cardColumns} from ${table} t ${sqlTable} ${cardSqlTable}
32
+ where ${where.join(' and ') || 'true'} limit 1`;
33
+
34
+ if (query.sql === '1') { return q; }
35
+
36
+ const { rows } = await pg.query(q, [opt.id || params.id]);
37
+
38
+ await metaFormat({ rows, table: params.table });
39
+
40
+ const data = meta.card?.length ? meta.card.reduce((acc, curr) => Object.assign(acc, { [columns.find((col) => col.name === curr)?.ua || '']: rows[0][curr] }), {}) : {};
41
+ return {
42
+ time: Date.now() - time, data,
43
+ };
44
+ }
@@ -1,37 +1,37 @@
1
- import getTemplate from './utils/getTemplate.js';
2
- import getSelect from './utils/getSelect.js';
3
- import getMeta from '../../pg/funcs/getMeta.js';
4
-
5
- export default async function filter(req) {
6
- const time = Date.now();
7
-
8
- const {
9
- params,
10
- } = req;
11
- const loadTable = await getTemplate('table', params.table);
12
- if (!loadTable) { return { status: 404, message: 'not found' }; }
13
- const { columns } = await getMeta({ table: loadTable.table });
14
-
15
- const filters = loadTable?.filters || loadTable?.filterList || [];
16
- await Promise.all(filters.filter((el) => el.data).map(async (el) => {
17
- const cls = await getSelect(el.data);
18
- if (!cls?.arr || !loadTable.table) return;
19
- const { dataTypeID } = columns.find((item) => item.name === el.id) || {};
20
- const countArr = req.pg.pgType[dataTypeID]?.includes('[]')
21
- ? await req.pg.queryCache(`select unnest(${el.id})::text as id,count(*) from ${loadTable.table} group by unnest(${el.id})`)
22
- : await req.pg.queryCache(`select ${el.id}::text as id,count(*) from ${loadTable.table} group by ${el.id}`);
23
-
24
- const options = countArr.rows.map(cel => {
25
- const data = cls?.arr.find(c => c.id === cel.id);
26
- return { ...cel, ...data };
27
- });
28
- Object.assign(el, { options });
29
- }));
30
- return {
31
- time: Date.now() - time,
32
- list: filters,
33
- custom: loadTable?.filterCustom?.map(el => ({ label: el.label })),
34
- inline: loadTable?.filterInline,
35
- state: loadTable?.filterState?.map(el => ({ label: el.label })),
36
- };
37
- }
1
+ import getTemplate from './utils/getTemplate.js';
2
+ import getSelect from './utils/getSelect.js';
3
+ import getMeta from '../../pg/funcs/getMeta.js';
4
+
5
+ export default async function filter(req) {
6
+ const time = Date.now();
7
+
8
+ const {
9
+ params,
10
+ } = req;
11
+ const loadTable = await getTemplate('table', params.table);
12
+ if (!loadTable) { return { status: 404, message: 'not found' }; }
13
+ const { columns } = await getMeta({ table: loadTable.table });
14
+
15
+ const filters = loadTable?.filters || loadTable?.filterList || [];
16
+ await Promise.all(filters.filter((el) => el.data).map(async (el) => {
17
+ const cls = await getSelect(el.data);
18
+ if (!cls?.arr || !loadTable.table) return;
19
+ const { dataTypeID } = columns.find((item) => item.name === el.id) || {};
20
+ const countArr = req.pg.pgType[dataTypeID]?.includes('[]')
21
+ ? await req.pg.queryCache(`select unnest(${el.id})::text as id,count(*) from ${loadTable.table} group by unnest(${el.id})`)
22
+ : await req.pg.queryCache(`select ${el.id}::text as id,count(*) from ${loadTable.table} group by ${el.id}`);
23
+
24
+ const options = countArr.rows.map(cel => {
25
+ const data = cls?.arr.find(c => c.id === cel.id);
26
+ return { ...cel, ...data };
27
+ });
28
+ Object.assign(el, { options });
29
+ }));
30
+ return {
31
+ time: Date.now() - time,
32
+ list: filters,
33
+ custom: loadTable?.filterCustom?.map(el => ({ label: el.label })),
34
+ inline: loadTable?.filterInline,
35
+ state: loadTable?.filterState?.map(el => ({ label: el.label })),
36
+ };
37
+ }
@@ -1,28 +1,28 @@
1
- import getTemplate from './utils/getTemplate.js';
2
-
3
- const sql = `select property_key as key, property_json as json, property_int as int,
4
- property_text as text from admin.properties where 1=1`;
5
-
6
- async function getSettings({ pg }) {
7
- const { rows = [] } = await pg.query(sql);
8
- const data = rows.reduce((acc, curr) => Object.assign(acc, { [curr.key]: curr.json || curr.int || curr.text }), {});
9
- return data;
10
- }
11
-
12
- export default async function formFunction(req) {
13
- const time = Date.now();
14
- const { pg, params } = req;
15
- const form = await getTemplate('form', params.form);
16
- if (!form) { return { status: 404, message: 'not found' }; }
17
-
18
- // replace settings
19
- const arr = JSON.stringify(form).match(/{{settings.([^}]*)}}/g);
20
- if (arr?.length) {
21
- const string = JSON.stringify(form);
22
- const settings = await getSettings({ pg });
23
- const match = arr.reduce((acc, curr) => Object.assign(acc, { [curr]: settings[curr.replace(/^{{settings./g, '').replace(/}}$/, '')] }), {});
24
- const res = Object.keys(match).reduce((s, m) => s.replace(m, match[m]), string);
25
- return { time: Date.now() - time, form: JSON.parse(res) };
26
- }
27
- return { time: Date.now() - time, form };
28
- }
1
+ import getTemplate from './utils/getTemplate.js';
2
+
3
+ const sql = `select property_key as key, property_json as json, property_int as int,
4
+ property_text as text from admin.properties where 1=1`;
5
+
6
+ async function getSettings({ pg }) {
7
+ const { rows = [] } = await pg.query(sql);
8
+ const data = rows.reduce((acc, curr) => Object.assign(acc, { [curr.key]: curr.json || curr.int || curr.text }), {});
9
+ return data;
10
+ }
11
+
12
+ export default async function formFunction(req) {
13
+ const time = Date.now();
14
+ const { pg, params } = req;
15
+ const form = await getTemplate('form', params.form);
16
+ if (!form) { return { status: 404, message: 'not found' }; }
17
+
18
+ // replace settings
19
+ const arr = JSON.stringify(form).match(/{{settings.([^}]*)}}/g);
20
+ if (arr?.length) {
21
+ const string = JSON.stringify(form);
22
+ const settings = await getSettings({ pg });
23
+ const match = arr.reduce((acc, curr) => Object.assign(acc, { [curr]: settings[curr.replace(/^{{settings./g, '').replace(/}}$/, '')] }), {});
24
+ const res = Object.keys(match).reduce((s, m) => s.replace(m, match[m]), string);
25
+ return { time: Date.now() - time, form: JSON.parse(res) };
26
+ }
27
+ return { time: Date.now() - time, form };
28
+ }
@@ -1,72 +1,80 @@
1
- import getTemplate from './utils/getTemplate.js';
2
- import getMeta from '../../pg/funcs/getMeta.js';
3
- import metaFormat from '../funcs/metaFormat/index.js';
4
- import getTemplates from './utils/getTemplates.js';
5
-
6
- function sequence(tables, data, fn) {
7
- return tables.reduce((promise, table) => promise.then(() => fn({
8
- ...data, tableName: table.replace('.json', ''),
9
- })), Promise.resolve());
10
- }
11
-
12
- async function getData({
13
- pg, funcs, tableName, query = {}, maxLimit, res,
14
- }) {
15
- const loadTable = await getTemplate('table', tableName);
16
-
17
- if (!loadTable) { return { message: 'not found', status: 404 }; }
18
-
19
- const { table, columns, meta, ua } = loadTable;
20
-
21
- const { pk } = await getMeta(table);
22
-
23
- const cols = columns.map((el) => el.name || el).join(',');
24
- const [orderColumn, orderDir] = (query.order || loadTable.order || '').split('-');
25
- const order = cols.includes(orderColumn) && orderColumn?.length ? `order by ${orderColumn} ${query.desc || orderDir === 'desc' ? 'desc' : ''}` : '';
26
-
27
- const limit = Math.max(maxLimit - res.rows.length, 0);
28
- // Math.max(query.offset - res.rows.length,0)
29
- const offset = query.page && query.page > 0 ? ` offset ${(query.page - 1) * limit}` : '';
30
-
31
- const search = meta?.search && query.key ? `(${meta?.search.concat(meta?.title ? `,${meta?.title}` : '').split(',').map(el => `${el} ilike '%${query.key}%'`).join(' or ')})` : 'false';
32
-
33
- const where = [!pk ? 'false' : 'true', loadTable.query, search].filter((el) => el);
34
- 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}`;
35
- if (query.sql) {
36
- res.sql.push(q);
37
- return;
38
- }
39
-
40
- const { rows } = await pg.query(q);
41
-
42
- const total = await pg.queryCache(`select count(*) from ${table} t where ${where.join(' and ') || 'true'}`).then((el) => el?.rows[0]?.count) || 0;
43
-
44
- await metaFormat({ rows, table: tableName });
45
- res.total += +total;
46
- rows.forEach((row) => {
47
- const href = meta?.href ? funcs.handlebars.compile(meta.href)({ ...row, [pk]: row.id }) : undefined;
48
- res.rows.push({ ...row, register: tableName, register_title: loadTable.ua, href });
49
- });
50
- }
51
-
52
- export default async function search({
53
- pg, funcs, query = {},
54
- }) {
55
- const time = Date.now();
56
-
57
- try {
58
- const tables = query.table ? [query.table] : await getTemplates('table');
59
- const res = { rows: [], sql: [], total: 0 };
60
-
61
- const maxLimit = Math.min(100, query.limit || '16');
62
- await sequence(tables, { pg, funcs, query, maxLimit, res }, getData);
63
-
64
- if (query.sql) return res.sql.join(';\n');
65
-
66
- return {
67
- time: Date.now() - time, total: res.total, count: res.rows.length, rows: res.rows,
68
- };
69
- } catch (err) {
70
- return { error: err.toString(), status: 500 };
71
- }
72
- }
1
+ import getTemplate from './utils/getTemplate.js';
2
+ import getMeta from '../../pg/funcs/getMeta.js';
3
+ import metaFormat from '../funcs/metaFormat/index.js';
4
+ import getTemplates from './utils/getTemplates.js';
5
+
6
+ function sequence(tables, data, fn) {
7
+ return tables.reduce((promise, table) => promise.then(() => fn({
8
+ ...data, tableName: table.replace('.json', ''),
9
+ })), Promise.resolve());
10
+ }
11
+
12
+ async function getData({
13
+ pg, funcs, tableName, query = {}, maxLimit, res,
14
+ }) {
15
+ const loadTable = await getTemplate('table', tableName);
16
+
17
+ if (!loadTable) { return { message: 'not found', status: 404 }; }
18
+
19
+ const {
20
+ table, columns, meta,
21
+ } = loadTable;
22
+
23
+ const { pk } = await getMeta(table);
24
+
25
+ const cols = columns.map((el) => el.name || el).join(',');
26
+ const [orderColumn, orderDir] = (query.order || loadTable.order || '').split('-');
27
+ const order = cols.includes(orderColumn) && orderColumn?.length ? `order by ${orderColumn} ${query.desc || orderDir === 'desc' ? 'desc' : ''}` : '';
28
+
29
+ const limit = Math.max(maxLimit - res.rows.length, 0);
30
+ // Math.max(query.offset - res.rows.length,0)
31
+ const offset = query.page && query.page > 0 ? ` offset ${(query.page - 1) * limit}` : '';
32
+
33
+ const search1 = meta?.search && query.key ? `(${meta?.search.concat(meta?.title ? `,${meta?.title}` : '').split(',').map(el => `${el} ilike '%${query.key}%'`).join(' or ')})` : 'false';
34
+
35
+ const where = [!pk ? 'false' : 'true', loadTable.query, search1].filter((el) => el);
36
+ 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}`;
37
+ if (query.sql) {
38
+ res.sql.push(q);
39
+ return null;
40
+ }
41
+
42
+ const { rows } = await pg.query(q);
43
+
44
+ const total = await pg.queryCache(`select count(*) from ${table} t where ${where.join(' and ') || 'true'}`).then((el) => el?.rows[0]?.count) || 0;
45
+
46
+ await metaFormat({ rows, table: tableName });
47
+ res.total += +total;
48
+ rows.forEach((row) => {
49
+ const href = meta?.href ? funcs.handlebars.compile(meta.href)({ ...row, [pk]: row.id }) : undefined;
50
+ res.rows.push({
51
+ ...row, register: tableName, register_title: loadTable.ua, href,
52
+ });
53
+ });
54
+ return null;
55
+ }
56
+
57
+ export default async function search({
58
+ pg, funcs, query = {},
59
+ }) {
60
+ const time = Date.now();
61
+
62
+ try {
63
+ const tables = query.table ? [query.table] : await getTemplates('table');
64
+ const res = { rows: [], sql: [], total: 0 };
65
+
66
+ const maxLimit = Math.min(100, query.limit || '16');
67
+ await sequence(tables, {
68
+ pg, funcs, query, maxLimit, res,
69
+ }, getData);
70
+
71
+ if (query.sql) return res.sql.join(';\n');
72
+
73
+ return {
74
+ time: Date.now() - time, total: res.total, count: res.rows.length, rows: res.rows,
75
+ };
76
+ }
77
+ catch (err) {
78
+ return { error: err.toString(), status: 500 };
79
+ }
80
+ }
@@ -1,20 +1,20 @@
1
- import getTemplate from './getTemplate.js';
2
-
3
- const loadCls = {};
4
-
5
- export default async function getSelect(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 getSelect(name) {
6
+ if (loadCls[name]) return loadCls[name];
7
+
8
+ const clsData = await getTemplate('cls', name);
9
+ console.log(clsData);
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,28 +1,69 @@
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 { sql };
27
- return data;
28
- }
1
+ import { readdir, readFile } from 'fs/promises';
2
+ import path from 'path';
3
+ import yaml from 'js-yaml';
4
+
5
+ import getTemplatePath from './getTemplatePath.js';
6
+ import loadTemplate from './loadTemplate.js';
7
+
8
+ async function readFileData(file) {
9
+ const data = await readFile(file, 'utf-8');
10
+ const ext = file.substring(file.lastIndexOf('.') + 1);
11
+
12
+ if (ext === 'yml') {
13
+ return yaml.load(data);
14
+ }
15
+ if (ext === 'json') {
16
+ return JSON.parse(data);
17
+ }
18
+ return data;
19
+ }
20
+
21
+ const isProduction = process.env.NODE_ENV === 'production';
22
+
23
+ async function getTemplateData(template) {
24
+ // dir template: dashboard, card
25
+ if (template[0][3]) {
26
+ const files = await readdir(template[0][1]);
27
+ const data = await Promise.all(files.map(async el => readFileData(path.join(template[0][1], el))));
28
+ return files.map((el, i) => [el, data[i]]);
29
+ }
30
+
31
+ // one file template: table, form
32
+ if (template.length === 1) {
33
+ const data = await readFileData(template[0][1]);
34
+ return data;
35
+ }
36
+
37
+ // multi file template: select, etc
38
+ if (template.length > 1) {
39
+ const data = await Promise.all(template.map(async el => readFileData(el[1])));
40
+ const result = {};
41
+ template.forEach((el, i) => {
42
+ Object.assign(result, typeof data[i] === 'object' ? data[i] : { [el[2]]: data[i] });
43
+ });
44
+ return result;
45
+ }
46
+ return null;
47
+ }
48
+ export default async function getTemplate(type, name) {
49
+ if (!type) return null;
50
+ if (!name) return null;
51
+
52
+ const key = `${type}:${name}`;
53
+ if (name === 'cache' && !isProduction) return loadTemplate; // all cache debug
54
+ if (loadTemplate[key] && isProduction) return loadTemplate[key]; // from cache
55
+
56
+ // type one or multi
57
+ const templateList = Array.isArray(type)
58
+ ? type.map(el => getTemplatePath(el)).filter(list => list?.filter(el => el[0] === name).length)[0] || []
59
+ : getTemplatePath(type);
60
+
61
+ // find template
62
+ const template = templateList?.filter(el => el[0] === name);
63
+ if (name === 'list' && !isProduction) return templateList; // all template debug
64
+
65
+ if (!template.length) return null; // not found
66
+
67
+ loadTemplate[key] = await getTemplateData(template);
68
+ return loadTemplate[key];
69
+ }