@opengis/fastify-table 1.2.50 → 1.2.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengis/fastify-table",
3
- "version": "1.2.50",
3
+ "version": "1.2.51",
4
4
  "type": "module",
5
5
  "description": "core-plugins",
6
6
  "keywords": [
@@ -1,131 +1,133 @@
1
- import getTemplate from '../getTemplate.js';
2
- import pgClients from '../../../pg/pgClients.js';
3
- import config from '../../../../../config.js';
4
-
5
- // filter util
6
- import getTableSql from './util/getTableSql.js';
7
- import getFilterQuery from './util/getFilterQuery.js';
8
- import getOptimizedQuery from './util/getOptimizedQuery.js';
9
-
10
- const defaultTable = 'crm.extra_data';
11
-
12
- function getExtraQuery(mainColumns, extraColumns, schema, table, pk, mode = 'property') {
13
- const extraKeys = mode === 'column'
14
- ? Object.keys(schema || {}).filter(key => !mainColumns.map(el => el?.name).includes(key) && extraColumns.map(el => el?.name).includes(key))
15
- : Object.keys(schema || {}).filter(key => !mainColumns.map(el => el?.name).includes(key));
16
-
17
- if (mode === 'column') {
18
- return { q: `left join lateral (select ${extraKeys.map(key => `"${key}"`).join(',')} from ${table} where ${pk}=t.${pk} limit 1) extra on 1=1`, extraKeys };
19
- }
20
- return {
21
- q: extraKeys.map((el, idx) => `left join lateral (select value_text as "${el.replace(/'/g, "''")}" from ${table} where property_key='${el.replace(/'/g, "''")}' and object_id=t.${pk} limit 1) extra${idx} on 1=1`).join(' '),
22
- extraKeys,
23
- };
24
- }
25
-
26
- export default async function getFilterSQL({
27
- table, filter, pg = pgClients.client, search, filterList, query, custom, state,
28
- }) {
29
- if (!table) return { error: 'param table is required', status: 400 };
30
-
31
- const body = await getTemplate('table', table);
32
- const loadTemplate = body?.form ? await getTemplate('form', body?.form) : null;
33
- const { extra } = loadTemplate || {};
34
-
35
- const extraDataTable = extra
36
- ? config.extraData?.[body.table]
37
- || config.extraData?.[body.table.split('.').shift()]
38
- || config.extraData?.['default']
39
- || config.extraData
40
- || defaultTable
41
- : undefined;
42
-
43
- const { fields: fieldsExtra = [] } = pg.pk?.[extraDataTable] ? await pg.query(`select * from ${extraDataTable} limit 0`) : {};
44
- const mode = fieldsExtra.find((col) => col?.name === pg.pk?.[body?.table || table]) ? 'column' : 'property';
45
-
46
- const { fields: fieldsModel = [] } = body?.table && pg.pk[body?.table] ? await pg.query(`select * from ${body.table} limit 0`) : {};
47
- const { q: extraSqlList, extraKeys } = pg.pk?.[extraDataTable] && pg.pk?.[body?.table]
48
- ? getExtraQuery(fieldsModel, fieldsExtra, loadTemplate?.schema, extraDataTable, pg.pk[body?.table || table], mode)
49
- : {};
50
-
51
- // console.log('extra getFilterSQL', extraDataTable, pg.pk?.[extraDataTable]);
52
-
53
- const sqlList = body?.sql?.length
54
- ? body?.sql?.filter((el) => !el.disabled && el?.sql?.replace)
55
- .map((el, i) => {
56
- Object.assign(el, { name: el.name || `t${i + 1}` });
57
- return ` left join lateral (${el.filter ? el.sql.replace(/limit 1/ig, '') : el.sql}) as ${el.name} on 1=1 `;
58
- }).join(' ')
59
- : '';
60
- const fieldQuery = `select * from ${body?.table || table} t ${sqlList || ''} ${extraSqlList || ''} limit 0`;
61
- const { fields = [] } = !extra || mode === 'column' ? await pg.query(fieldQuery) : { fields: extraKeys.map(el => ({ name: el.name, dataTypeID: 25 })) };
62
- const autoSearchColumn = fields?.filter((el) => pg.pgType?.[el.dataTypeID] === 'text')?.map((el) => el.name).join(',');
63
- const searchColumn = body?.search_column || body?.meta?.search || autoSearchColumn;
64
- const fieldsList = (fieldsModel || fields)?.map((el) => el.name);
65
- try {
66
- const tableSQL = await getTableSql({
67
- pg, body, table, fields,
68
- });
69
- const sval = `ilike '%${decodeURIComponent(search?.replace(/%/g, '%25')).replace(/'/g, "''").replace(/%/g, '\\%')}%'`;
70
- const searchQuery = search && searchColumn
71
- ? ` (${searchColumn.split(',')?.map((name) => {
72
- const { pk } = tableSQL.find((el) => el.name === name) || {};
73
- return pk && !fieldsList.includes(name) ? `${pk} in (select ${pk} from (${fieldQuery.replace(/limit 0/g, '')} where ${name} ${sval} )q where 1=1)` : `${name} ${sval}`;
74
- }).join(' or ')} )` : '';
75
-
76
- const filterList1 = await Promise.all((filterList || (body?.filter_list || []).concat(body?.filterInline || []).concat(body?.filterCustom || []).concat(body?.filterState || []).concat(body?.filterList || [])
77
- .concat(body?.filters || [])).concat(body?.filterSql || []) /* .concat(extraFilters || []).concat(customFilters || []) */
78
-
79
- ?.map(async (el) => {
80
- if (el.name && extraKeys?.includes?.(el.name)) {
81
- Object.assign(el, { extra: { table: extraDataTable, mode } });
82
- }
83
- if (!el?.data) return el;
84
- const cls = await getTemplate(['cls', 'select'], el.data);
85
- if (Array.isArray(cls) && cls?.length) {
86
- Object.assign(el, { options: cls });
87
- }
88
- else if (typeof (cls?.sql || cls) === 'string') {
89
- Object.assign(el, { sql: cls?.sql || cls });
90
- }
91
- return el;
92
- }));
93
-
94
- const filters = getFilterQuery({
95
- pg,
96
- filter,
97
- table: body?.table || table,
98
- tableSQL,
99
- fields,
100
- filterList: filterList1,
101
- });
102
-
103
- // filter
104
- const customQuery = body?.filterCustom?.length && custom ? body.filterCustom?.find((el) => el.name === custom)?.sql : null;
105
- const stateQuery = body?.filterState?.length && state ? body.filterState?.find((el) => el.name === state)?.sql : null;
106
-
107
- const filterQuery = filters?.filter((el) => el.query)?.map((el) => `${el.query} `).join(' and ');
108
- const q = [body?.query, query, searchQuery, filterQuery, stateQuery, customQuery].filter((el) => el).join(' and ');
109
-
110
- // table
111
- const modelQuery = body?.model || body?.table || table;
112
- const optimizedSQL = `select * from ${getOptimizedQuery({ body, extraSqlList, table, q })} `;
113
- const tableCount = getOptimizedQuery({ body, extraSqlList, table, q }, true);
114
- // console.log(optimizedSQL);
115
- return {
116
- filterList,
117
-
118
- q,
119
- optimizedSQL,
120
- extraSqlList,
121
- extraKeys,
122
- tableCount,
123
- table: modelQuery,
124
- // filter parts
125
- searchQuery,
126
- };
127
- }
128
- catch (err) {
129
- throw new Error(err.toString());
130
- }
131
- }
1
+ import getTemplate from '../getTemplate.js';
2
+ import pgClients from '../../../pg/pgClients.js';
3
+ import config from '../../../../../config.js';
4
+
5
+ // filter util
6
+ import getTableSql from './util/getTableSql.js';
7
+ import getFilterQuery from './util/getFilterQuery.js';
8
+ import getOptimizedQuery from './util/getOptimizedQuery.js';
9
+
10
+ const defaultTable = 'crm.extra_data';
11
+
12
+ function getExtraQuery(mainColumns, extraColumns, schema, table, pk, mode = 'property') {
13
+ const extraKeys = mode === 'column'
14
+ ? Object.keys(schema || {}).filter(key => !mainColumns.map(el => el?.name).includes(key) && extraColumns.map(el => el?.name).includes(key))
15
+ : Object.keys(schema || {}).filter(key => !mainColumns.map(el => el?.name).includes(key));
16
+
17
+ if (mode === 'column') {
18
+ return { q: `left join lateral (select ${extraKeys.map(key => `"${key}"`).join(',')} from ${table} where ${pk}=t.${pk} limit 1) extra on 1=1`, extraKeys };
19
+ }
20
+ return {
21
+ q: extraKeys.map((el, idx) => `left join lateral (select value_text as "${el.replace(/'/g, "''")}" from ${table} where property_key='${el.replace(/'/g, "''")}' and object_id=t.${pk} limit 1) extra${idx} on 1=1`).join(' '),
22
+ extraKeys,
23
+ };
24
+ }
25
+
26
+ export default async function getFilterSQL({
27
+ table, filter, pg = pgClients.client, search, filterList, query, custom, state,
28
+ }) {
29
+ if (!table) return { error: 'param table is required', status: 400 };
30
+
31
+ const body = await getTemplate('table', table);
32
+ const loadTemplate = body?.form ? await getTemplate('form', body?.form) : null;
33
+ const { extra } = loadTemplate || {};
34
+
35
+ const extraDataTable = extra
36
+ ? config.extraData?.[body.table]
37
+ || config.extraData?.[body.table.split('.').shift()]
38
+ || config.extraData?.['default']
39
+ || config.extraData
40
+ || defaultTable
41
+ : undefined;
42
+
43
+ const { fields: fieldsExtra = [] } = pg.pk?.[extraDataTable] ? await pg.query(`select * from ${extraDataTable} limit 0`) : {};
44
+ const mode = fieldsExtra.find((col) => col?.name === pg.pk?.[body?.table || table]) ? 'column' : 'property';
45
+
46
+ const { fields: fieldsModel = [] } = body?.table && pg.pk[body?.table] ? await pg.query(`select * from ${body.table} limit 0`) : {};
47
+ const { q: extraSqlList, extraKeys } = pg.pk?.[extraDataTable] && pg.pk?.[body?.table]
48
+ ? getExtraQuery(fieldsModel, fieldsExtra, loadTemplate?.schema, extraDataTable, pg.pk[body?.table || table], mode)
49
+ : {};
50
+
51
+ // console.log('extra getFilterSQL', extraDataTable, pg.pk?.[extraDataTable]);
52
+
53
+ const sqlList = body?.sql?.length
54
+ ? body?.sql?.filter((el) => !el.disabled && el?.sql?.replace)
55
+ .map((el, i) => {
56
+ Object.assign(el, { name: el.name || `t${i + 1}` });
57
+ return ` left join lateral (${el.filter ? el.sql.replace(/limit 1/ig, '') : el.sql}) as ${el.name} on 1=1 `;
58
+ }).join(' ')
59
+ : '';
60
+ const fieldQuery = `select * from ${body?.table || table} t ${sqlList || ''} ${extraSqlList || ''} limit 0`;
61
+ const { fields = [] } = !extra || mode === 'column' ? await pg.query(fieldQuery) : { fields: extraKeys.map(el => ({ name: el.name, dataTypeID: 25 })) };
62
+ const autoSearchColumn = fields?.filter((el) => pg.pgType?.[el.dataTypeID] === 'text')?.map((el) => el.name).join(',');
63
+ const searchColumn = body?.search_column || body?.meta?.search || autoSearchColumn;
64
+ const fieldsList = (fieldsModel || fields)?.map((el) => el.name);
65
+ try {
66
+ const tableSQL = await getTableSql({
67
+ pg, body, table, fields,
68
+ });
69
+ const sval = `ilike '%${decodeURIComponent(search?.replace(/%/g, '%25')).replace(/'/g, "''").replace(/%/g, '\\%')}%'`;
70
+ const searchQuery = search && searchColumn
71
+ ? ` (${searchColumn.split(',')?.map((name) => {
72
+ const { pk } = tableSQL.find((el) => el.name === name) || {};
73
+ return pk && !fieldsList.includes(name) ? `${pk} in (select ${pk} from (${fieldQuery.replace(/limit 0/g, '')} where ${name} ${sval} )q where 1=1)` : `${name} ${sval}`;
74
+ }).join(' or ')} )` : '';
75
+
76
+ body?.filterSql?.forEach?.((el) => Object.assign(el, { filtersql: 1 }));
77
+
78
+ const filterList1 = await Promise.all((filterList || (body?.filter_list || []).concat(body?.filterInline || []).concat(body?.filterCustom || []).concat(body?.filterState || []).concat(body?.filterList || [])
79
+ .concat(body?.filters || [])).concat(body?.filterSql || []) /* .concat(extraFilters || []).concat(customFilters || []) */
80
+
81
+ ?.map(async (el) => {
82
+ if (el.name && extraKeys?.includes?.(el.name)) {
83
+ Object.assign(el, { extra: { table: extraDataTable, mode } });
84
+ }
85
+ if (!el?.data) return el;
86
+ const cls = await getTemplate(['cls', 'select'], el.data);
87
+ if (Array.isArray(cls) && cls?.length) {
88
+ Object.assign(el, { options: cls });
89
+ }
90
+ else if (typeof (cls?.sql || cls) === 'string') {
91
+ Object.assign(el, { sql: cls?.sql || cls });
92
+ }
93
+ return el;
94
+ }));
95
+
96
+ const filters = getFilterQuery({
97
+ pg,
98
+ filter,
99
+ table: body?.table || table,
100
+ tableSQL,
101
+ fields,
102
+ filterList: filterList1,
103
+ });
104
+
105
+ // filter
106
+ const customQuery = body?.filterCustom?.length && custom ? body.filterCustom?.find((el) => el.name === custom)?.sql : null;
107
+ const stateQuery = body?.filterState?.length && state ? body.filterState?.find((el) => el.name === state)?.sql : null;
108
+
109
+ const filterQuery = filters?.filter((el) => el.query)?.map((el) => `${el.query} `).join(' and ');
110
+ const q = [body?.query, query, searchQuery, filterQuery, stateQuery, customQuery].filter((el) => el).join(' and ');
111
+
112
+ // table
113
+ const modelQuery = body?.model || body?.table || table;
114
+ const optimizedSQL = `select * from ${getOptimizedQuery({ body, extraSqlList, table, q })} `;
115
+ const tableCount = getOptimizedQuery({ body, extraSqlList, table, q }, true);
116
+ // console.log(optimizedSQL);
117
+ return {
118
+ filterList,
119
+
120
+ q,
121
+ optimizedSQL,
122
+ extraSqlList,
123
+ extraKeys,
124
+ tableCount,
125
+ table: modelQuery,
126
+ // filter parts
127
+ searchQuery,
128
+ };
129
+ }
130
+ catch (err) {
131
+ throw new Error(err.toString());
132
+ }
133
+ }
@@ -25,7 +25,7 @@ function formatDateISOString(date) {
25
25
  function formatValue({
26
26
  pg, table, filter = {}, name, value, operator = '=', dataTypeID, uid = 1, optimize,
27
27
  }) {
28
- const { data, sql, extra } = filter;
28
+ const { data, sql, extra, filtersql } = filter;
29
29
  const pk = pg?.pk && table ? pg.pk[table] : undefined;
30
30
 
31
31
  if (!dataTypeID && !extra) return {};
@@ -36,7 +36,7 @@ function formatValue({
36
36
  const filterType = filter.type?.toLowerCase();
37
37
 
38
38
  // body.filterSql
39
- if (sql && !data) {
39
+ if (sql && filtersql) {
40
40
  // date range
41
41
  if (filterType === 'date') {
42
42
  const [startDate, endDate] = value.split('-');