zet-lib 1.3.38 → 1.3.40
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/LICENSE +21 -21
- package/README.md +15 -15
- package/lib/ErrorWithCode.js +6 -6
- package/lib/Form.js +1019 -1019
- package/lib/Mail.js +68 -68
- package/lib/Modal.js +95 -95
- package/lib/Pool.js +437 -437
- package/lib/UI.js +7 -7
- package/lib/Util.js +1384 -1367
- package/lib/access.js +6 -6
- package/lib/cache.js +3 -3
- package/lib/connection.js +409 -409
- package/lib/debug.js +22 -22
- package/lib/index.js +36 -36
- package/lib/io.js +44 -44
- package/lib/languages/lang_en.js +125 -125
- package/lib/languages/lang_fr.js +125 -125
- package/lib/languages/lang_id.js +126 -126
- package/lib/languages/lang_jp.js +125 -125
- package/lib/moduleLib.js +661 -661
- package/lib/tableForm.js +10 -10
- package/lib/views/generator.ejs +598 -598
- package/lib/views/generator_layout.ejs +224 -224
- package/lib/views/generatorjs.ejs +927 -927
- package/lib/zAppRouter.js +1637 -1637
- package/lib/zCache.js +301 -301
- package/lib/zComponent.js +27 -27
- package/lib/zFn.js +58 -58
- package/lib/zFunction.js +20 -20
- package/lib/zGeneratorRouter.js +1641 -1641
- package/lib/zMenuRouter.js +556 -556
- package/lib/zPage.js +188 -188
- package/lib/zReport.js +982 -982
- package/lib/zRole.js +256 -256
- package/lib/zRoleRouter.js +609 -609
- package/lib/zRoute.js +5025 -5019
- package/lib/zTester.js +93 -93
- package/lib/zapp.js +65 -65
- package/lib/zdataTable.js +330 -330
- package/package.json +56 -56
package/lib/connection.js
CHANGED
|
@@ -1,409 +1,409 @@
|
|
|
1
|
-
const { Pool } = require('./Pool')
|
|
2
|
-
const config = require('dotenv').config()
|
|
3
|
-
const Util = require('./Util')
|
|
4
|
-
|
|
5
|
-
const configPG = {
|
|
6
|
-
user: process.env.PGUSER,
|
|
7
|
-
host: process.env.PGHOST,
|
|
8
|
-
database: process.env.PGDATABASE,
|
|
9
|
-
password: process.env.PGPASSWORD,
|
|
10
|
-
port: process.env.PGPORT,
|
|
11
|
-
max: 20, // set pool max size to 20
|
|
12
|
-
idleTimeoutMillis: 1000, // close idle clients after 1 second
|
|
13
|
-
connectionTimeoutMillis: 10000, // return an error after 10 second if connection could not be established
|
|
14
|
-
maxUses: 7500, // close (and replace) a connection after it has been used 7500 times (see below for discussion)
|
|
15
|
-
poolSize: 50, // Default is 10 connections
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const pool = new Pool(configPG)
|
|
19
|
-
|
|
20
|
-
pool.on('error', (err) => {
|
|
21
|
-
console.error('Unexpected error on idle client', err)
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
const connection = {}
|
|
25
|
-
|
|
26
|
-
connection.query = async (string, arr) => {
|
|
27
|
-
try {
|
|
28
|
-
/*console.log(string);
|
|
29
|
-
console.log(JSON.stringify(arr))*/
|
|
30
|
-
const result = await pool.query(string, arr)
|
|
31
|
-
return result.rows
|
|
32
|
-
} catch (e) {
|
|
33
|
-
console.log(string)
|
|
34
|
-
console.log(e)
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const orderByFn = (obj) => {
|
|
39
|
-
const objOrderby = !obj.orderBy ? [] : obj.orderBy
|
|
40
|
-
let orderBy = ''
|
|
41
|
-
if (objOrderby.length) {
|
|
42
|
-
orderBy = ` ORDER BY `
|
|
43
|
-
for (var i = 0; i < objOrderby.length; i++) {
|
|
44
|
-
if (i % 2 == 0) {
|
|
45
|
-
orderBy += ` "${obj.orderBy[i]}" `
|
|
46
|
-
} else {
|
|
47
|
-
orderBy += ` ${obj.orderBy[i]} `
|
|
48
|
-
if (i == objOrderby.length - 1) {
|
|
49
|
-
orderBy += ` `
|
|
50
|
-
} else {
|
|
51
|
-
orderBy += `, `
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
if (obj.hasOwnProperty('order_by')) {
|
|
57
|
-
orderBy = ` ORDER BY `
|
|
58
|
-
orderBy += obj.order_by.join(',')
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return orderBy
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const whereFn = (obj) => {
|
|
65
|
-
const where = obj.where || {}
|
|
66
|
-
//[{field:"your_field",option:"=>",value:"12",operator:"AND",type:"text,json,date, inline"}]
|
|
67
|
-
const whereArray = obj.whereArray || []
|
|
68
|
-
let increment = 1
|
|
69
|
-
let arr = [],
|
|
70
|
-
wherequery = []
|
|
71
|
-
for (const key in where) {
|
|
72
|
-
wherequery.push(key.indexOf('.') > -1 ? ` ${key} = $${increment} ` : ` "${key}" = $${increment}`)
|
|
73
|
-
arr.push(where[key])
|
|
74
|
-
increment++
|
|
75
|
-
}
|
|
76
|
-
//console.log(whereArray);
|
|
77
|
-
let hasWhere = false
|
|
78
|
-
wherequery = arr.length ? wherequery.join(' AND ') : ''
|
|
79
|
-
if (whereArray.length) {
|
|
80
|
-
let andOr = wherequery ? ' AND ' : ''
|
|
81
|
-
whereArray.map((item, index) => {
|
|
82
|
-
let type = !item.type ? 'text' : item.type
|
|
83
|
-
if (index > 0) {
|
|
84
|
-
andOr = ''
|
|
85
|
-
}
|
|
86
|
-
let operator = !item.operator ? ' AND ' : item.operator
|
|
87
|
-
if (index == whereArray.length - 1) {
|
|
88
|
-
operator = ''
|
|
89
|
-
}
|
|
90
|
-
let fields = ''
|
|
91
|
-
if (type == 'date') {
|
|
92
|
-
field = item.field.indexOf('.') > -1 ? item.field + '::text ' : ` ${item.field}::text `
|
|
93
|
-
} else {
|
|
94
|
-
field = item.field.indexOf('.') > -1 ? item.field : item.field ? ` "${item.field}" ` : ''
|
|
95
|
-
}
|
|
96
|
-
//is JSON is field is JSON
|
|
97
|
-
//JSON_CONTAINS(color, '"Red"' ,'$')
|
|
98
|
-
if (item.isJSON) {
|
|
99
|
-
wherequery += andOr + ` JSON_CONTAINS(${field}, '"${item.value}"' ,'$') ${operator}`
|
|
100
|
-
hasWhere = true
|
|
101
|
-
} else {
|
|
102
|
-
if (type == 'json') {
|
|
103
|
-
wherequery += andOr + ` JSON_CONTAINS(${field}, '"${item.value}"' ,'$') ${operator}`
|
|
104
|
-
hasWhere = true
|
|
105
|
-
} else if (type == 'inline') {
|
|
106
|
-
//select * from attendance where employee_id = 4803 and date IN ('2023-12-21','2023-12-22')
|
|
107
|
-
if (field) {
|
|
108
|
-
wherequery += andOr + ` ${field} ${item.value} ${operator}`
|
|
109
|
-
} else {
|
|
110
|
-
wherequery += andOr + ` ${item.value} ${operator}`
|
|
111
|
-
}
|
|
112
|
-
hasWhere = true
|
|
113
|
-
} else {
|
|
114
|
-
if (item.option.includes('{{value}}')) {
|
|
115
|
-
item.option = item.option.replace('{{value}}', `$${increment}`)
|
|
116
|
-
wherequery += `${andOr} ${field} ${item.option} ${operator}`
|
|
117
|
-
increment++
|
|
118
|
-
} else if (item.option.includes('$')) {
|
|
119
|
-
wherequery += `${andOr} ${field} ${item.option} ${operator}`
|
|
120
|
-
increment++
|
|
121
|
-
} else {
|
|
122
|
-
wherequery += `${andOr} ${field} ${item.option} $${increment} ${operator}`
|
|
123
|
-
increment++
|
|
124
|
-
}
|
|
125
|
-
let itemValue = item.value
|
|
126
|
-
if (item.option == '=') {
|
|
127
|
-
itemValue = Util.replaceAll(itemValue + '', '%', '')
|
|
128
|
-
}
|
|
129
|
-
arr.push(itemValue)
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
})
|
|
133
|
-
//console.log(arr)
|
|
134
|
-
}
|
|
135
|
-
if (arr.length > 0) {
|
|
136
|
-
hasWhere = true
|
|
137
|
-
}
|
|
138
|
-
let wheres = ''
|
|
139
|
-
if (hasWhere) {
|
|
140
|
-
wheres = `WHERE ${wherequery}`
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
let objAll = {
|
|
144
|
-
where: wheres,
|
|
145
|
-
arr: arr,
|
|
146
|
-
increment: increment,
|
|
147
|
-
}
|
|
148
|
-
//console.log(obj)
|
|
149
|
-
return objAll
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
connection.results = async (obj) => {
|
|
153
|
-
const select = obj.select || '*'
|
|
154
|
-
const table = obj.table || ''
|
|
155
|
-
//[{field:"your_field",option:"=>",value:"12",operator:"AND",type:"text,json,date"}]
|
|
156
|
-
const statement = obj.statement || ''
|
|
157
|
-
const limit = obj.limit ? ` LIMIT ${obj.limit} ` : ''
|
|
158
|
-
const offset = obj.hasOwnProperty('offset') ? ` OFFSET ${obj.offset} ` : obj.limit ? 'OFFSET 0' : ''
|
|
159
|
-
const orderBy = orderByFn(obj)
|
|
160
|
-
const values = obj.values || []
|
|
161
|
-
const objJoin = obj.joins || []
|
|
162
|
-
let join = ''
|
|
163
|
-
if (objJoin.length) {
|
|
164
|
-
join = objJoin.join(' ')
|
|
165
|
-
}
|
|
166
|
-
const whereObj = whereFn(obj)
|
|
167
|
-
const wheres = whereObj.where
|
|
168
|
-
const arr = whereObj.arr
|
|
169
|
-
const sql = `SELECT ${select} FROM "${table}" ${join} ${wheres} ${statement} ${orderBy} ${limit} ${offset}`
|
|
170
|
-
/*console.log(sql)
|
|
171
|
-
console.log(arr);*/
|
|
172
|
-
try {
|
|
173
|
-
const result = await pool.query(sql, arr.length ? arr : values.length ? values : null)
|
|
174
|
-
return !result.rows ? [] : result.rows
|
|
175
|
-
} catch (e) {
|
|
176
|
-
console.log(sql)
|
|
177
|
-
console.log(arr)
|
|
178
|
-
console.log(e.toString())
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
connection.sql = async (obj) => {
|
|
183
|
-
const select = obj.select || '*'
|
|
184
|
-
const table = obj.table || ''
|
|
185
|
-
//[{field:"your_field",option:"=>",value:"12",operator:"AND",type:"text,json,date"}]
|
|
186
|
-
const statement = obj.statement || ''
|
|
187
|
-
const limit = obj.limit ? ` LIMIT ${obj.limit} ` : ''
|
|
188
|
-
const offset = obj.hasOwnProperty('offset') ? ` OFFSET ${obj.offset} ` : obj.limit ? 'OFFSET 0' : ''
|
|
189
|
-
const orderBy = orderByFn(obj)
|
|
190
|
-
const values = obj.values || []
|
|
191
|
-
const objJoin = obj.joins || []
|
|
192
|
-
let join = ''
|
|
193
|
-
if (objJoin.length) {
|
|
194
|
-
join = objJoin.join(' ')
|
|
195
|
-
}
|
|
196
|
-
const whereObj = whereFn(obj)
|
|
197
|
-
const wheres = whereObj.where
|
|
198
|
-
const arr = whereObj.arr
|
|
199
|
-
const sql = `SELECT ${select} FROM "${table}" ${join} ${wheres} ${statement} ${orderBy} ${limit} ${offset}`
|
|
200
|
-
return { sql: sql, arr: arr }
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
connection.result = async (obj) => {
|
|
204
|
-
const results = await connection.results(obj)
|
|
205
|
-
if (results.length) {
|
|
206
|
-
return results[0]
|
|
207
|
-
} else {
|
|
208
|
-
return []
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
connection.insert = async (obj) => {
|
|
213
|
-
let result
|
|
214
|
-
const table = obj.table
|
|
215
|
-
const data = obj.data
|
|
216
|
-
let increment = 1
|
|
217
|
-
const datas = []
|
|
218
|
-
const values = []
|
|
219
|
-
const arr = []
|
|
220
|
-
const returning = data.returning || 'RETURNING *'
|
|
221
|
-
delete data.returning
|
|
222
|
-
for (const key in data) {
|
|
223
|
-
datas.push(key)
|
|
224
|
-
values.push(`$${increment}`)
|
|
225
|
-
arr.push(data[key])
|
|
226
|
-
increment++
|
|
227
|
-
}
|
|
228
|
-
const sql = `INSERT INTO "${table}" ("${datas.join('","')}") VALUES (${values.join(',')}) ${returning}`
|
|
229
|
-
/* console.log("ON INSERT " + sql)
|
|
230
|
-
console.log(arr)
|
|
231
|
-
*/
|
|
232
|
-
|
|
233
|
-
try {
|
|
234
|
-
const results = await pool.query(sql, arr)
|
|
235
|
-
return results.rows[0]
|
|
236
|
-
} catch (e) {
|
|
237
|
-
console.log(sql)
|
|
238
|
-
console.log(arr)
|
|
239
|
-
console.log(e.toString())
|
|
240
|
-
throw e
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
connection.update = async (obj) => {
|
|
245
|
-
const table = obj.table
|
|
246
|
-
const data = obj.data
|
|
247
|
-
const returning = data.returning || 'RETURNING *'
|
|
248
|
-
delete data.returning
|
|
249
|
-
|
|
250
|
-
const where = obj.where || {}
|
|
251
|
-
//[{field:"your_field",option:"=>",value:"12",operator:"AND"}]
|
|
252
|
-
let whereArray = obj.whereArray || []
|
|
253
|
-
const arr = [],
|
|
254
|
-
dataArr = []
|
|
255
|
-
let wherequery = []
|
|
256
|
-
let increment = 1
|
|
257
|
-
for (let key in data) {
|
|
258
|
-
dataArr.push(` "${key}" = $${increment}`)
|
|
259
|
-
arr.push(data[key])
|
|
260
|
-
increment++
|
|
261
|
-
}
|
|
262
|
-
for (var key in where) {
|
|
263
|
-
wherequery.push(` "${key}" = $${increment}`)
|
|
264
|
-
arr.push(where[key])
|
|
265
|
-
increment++
|
|
266
|
-
}
|
|
267
|
-
wherequery = arr.length ? wherequery.join(' AND ') : ''
|
|
268
|
-
if (whereArray.length) {
|
|
269
|
-
let andOr = wherequery ? ' AND ' : ''
|
|
270
|
-
whereArray.forEach((item, index) => {
|
|
271
|
-
if (index > 0) andOr = ''
|
|
272
|
-
const operator = !item.operator ? ' AND ' : item.operator
|
|
273
|
-
const field = item.field.indexOf('.') > -1 ? item.field : `"${item.field}"`
|
|
274
|
-
wherequery += `${andOr} ${field} ${item.option} $${increment} ${operator}`
|
|
275
|
-
arr.push(item.value)
|
|
276
|
-
increment++
|
|
277
|
-
})
|
|
278
|
-
wherequery = wherequery.slice(0, -5)
|
|
279
|
-
}
|
|
280
|
-
const wheres = arr.length ? ' WHERE ' + wherequery : ''
|
|
281
|
-
const sql = `UPDATE "${table}" SET ${dataArr.join(', ')} ${wheres} ${returning}`
|
|
282
|
-
/* console.log(sql);
|
|
283
|
-
console.log(arr);*/
|
|
284
|
-
try {
|
|
285
|
-
const result = await pool.query(sql, arr)
|
|
286
|
-
return result.rows[0]
|
|
287
|
-
} catch (e) {
|
|
288
|
-
console.log(sql)
|
|
289
|
-
console.log(arr)
|
|
290
|
-
console.log(e.toString())
|
|
291
|
-
throw e
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
connection.delete = async (obj) => {
|
|
296
|
-
const table = obj.table
|
|
297
|
-
const where = obj.where || {}
|
|
298
|
-
let arr = [],
|
|
299
|
-
wherequery = []
|
|
300
|
-
let increment = 1
|
|
301
|
-
for (const key in where) {
|
|
302
|
-
wherequery.push(` "${key}" = $${increment}`)
|
|
303
|
-
arr.push(where[key])
|
|
304
|
-
increment++
|
|
305
|
-
}
|
|
306
|
-
wherequery = arr.length ? wherequery.join(' AND ') : ''
|
|
307
|
-
const wheres = arr.length ? ' WHERE ' + wherequery : ''
|
|
308
|
-
const sql = `DELETE FROM "${table}" ${wheres}`
|
|
309
|
-
/*console.log(sql);
|
|
310
|
-
console.log(arr)*/
|
|
311
|
-
try {
|
|
312
|
-
return await pool.query(sql, arr)
|
|
313
|
-
} catch (e) {
|
|
314
|
-
console.log(sql)
|
|
315
|
-
console.log(arr)
|
|
316
|
-
console.log(e.toString())
|
|
317
|
-
throw e
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
connection.driver = config.driver
|
|
322
|
-
connection.showTables = "SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname != 'pg_catalog' AND schemaname != 'information_schema'"
|
|
323
|
-
connection.showFullFields = (tableRelations) => {
|
|
324
|
-
return `SELECT
|
|
325
|
-
column_name AS "Field", concat(data_type,'(',character_maximum_length,')') AS "Type" , is_nullable AS "Null"
|
|
326
|
-
FROM
|
|
327
|
-
information_schema.COLUMNS
|
|
328
|
-
WHERE
|
|
329
|
-
TABLE_NAME = '${tableRelations}';`
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
connection.describeTable = (table) => {
|
|
333
|
-
return connection.showFullFields(table)
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
connection.showComments = (table) => {
|
|
337
|
-
return ` SELECT c.table_schema,c.table_name,c.column_name as "COLUMN_NAME",pgd.description as "COLUMN_COMMENT"
|
|
338
|
-
FROM pg_catalog.pg_statio_all_tables as st
|
|
339
|
-
inner join pg_catalog.pg_description pgd on (pgd.objoid=st.relid)
|
|
340
|
-
inner join information_schema.columns c on (pgd.objsubid=c.ordinal_position
|
|
341
|
-
and c.table_schema=st.schemaname and c.table_name=st.relname)
|
|
342
|
-
WHERE c.table_name = '${table}' ORDER BY c.column_name`
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
connection.showFields = (table) => {
|
|
346
|
-
return `
|
|
347
|
-
SELECT
|
|
348
|
-
tc.table_name AS "TABLE_NAME",
|
|
349
|
-
kcu.column_name AS "COLUMN_NAME",
|
|
350
|
-
tc.constraint_name AS "CONSTRAINT_NAME",
|
|
351
|
-
ccu.table_name AS "REFERENCED_TABLE_NAME",
|
|
352
|
-
ccu.column_name AS "REFERENCED_COLUMN_NAME",
|
|
353
|
-
tc.table_schema
|
|
354
|
-
FROM
|
|
355
|
-
information_schema.table_constraints AS tc
|
|
356
|
-
JOIN information_schema.key_column_usage AS kcu
|
|
357
|
-
ON tc.constraint_name = kcu.constraint_name
|
|
358
|
-
AND tc.table_schema = kcu.table_schema
|
|
359
|
-
JOIN information_schema.constraint_column_usage AS ccu
|
|
360
|
-
ON ccu.constraint_name = tc.constraint_name
|
|
361
|
-
AND ccu.table_schema = tc.table_schema
|
|
362
|
-
WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name='${table}';`
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
//list constraint list
|
|
366
|
-
connection.constraintList = (table, schema = 'public') => {
|
|
367
|
-
return `
|
|
368
|
-
SELECT con.*
|
|
369
|
-
FROM pg_catalog.pg_constraint con
|
|
370
|
-
INNER JOIN pg_catalog.pg_class rel
|
|
371
|
-
ON rel.oid = con.conrelid
|
|
372
|
-
INNER JOIN pg_catalog.pg_namespace nsp
|
|
373
|
-
ON nsp.oid = connamespace
|
|
374
|
-
WHERE nsp.nspname = '${schema}' AND rel.relname = '${table}'; `
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
//find foreign key
|
|
378
|
-
connection.foreignKeyList = (table) => {
|
|
379
|
-
return `SELECT
|
|
380
|
-
tc.table_schema,
|
|
381
|
-
tc.constraint_name,
|
|
382
|
-
tc.table_name,
|
|
383
|
-
kcu.column_name,
|
|
384
|
-
ccu.table_schema AS foreign_table_schema,
|
|
385
|
-
ccu.table_name AS foreign_table_name,
|
|
386
|
-
ccu.column_name AS foreign_column_name
|
|
387
|
-
FROM information_schema.table_constraints AS tc
|
|
388
|
-
JOIN information_schema.key_column_usage AS kcu
|
|
389
|
-
ON tc.constraint_name = kcu.constraint_name
|
|
390
|
-
AND tc.table_schema = kcu.table_schema
|
|
391
|
-
JOIN information_schema.constraint_column_usage AS ccu
|
|
392
|
-
ON ccu.constraint_name = tc.constraint_name
|
|
393
|
-
WHERE tc.constraint_type = 'FOREIGN KEY'
|
|
394
|
-
AND tc.table_name='${table}';`
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
var toNumber = function (num) {
|
|
398
|
-
num = num + ''
|
|
399
|
-
var t = replaceAll(num, '.', '')
|
|
400
|
-
if (t) {
|
|
401
|
-
return parseFloat(t)
|
|
402
|
-
} else return 0
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
function replaceAll(str, find, replace) {
|
|
406
|
-
return str.replace(new RegExp(find, 'g'), replace)
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
module.exports = connection
|
|
1
|
+
const { Pool } = require('./Pool')
|
|
2
|
+
const config = require('dotenv').config()
|
|
3
|
+
const Util = require('./Util')
|
|
4
|
+
|
|
5
|
+
const configPG = {
|
|
6
|
+
user: process.env.PGUSER,
|
|
7
|
+
host: process.env.PGHOST,
|
|
8
|
+
database: process.env.PGDATABASE,
|
|
9
|
+
password: process.env.PGPASSWORD,
|
|
10
|
+
port: process.env.PGPORT,
|
|
11
|
+
max: 20, // set pool max size to 20
|
|
12
|
+
idleTimeoutMillis: 1000, // close idle clients after 1 second
|
|
13
|
+
connectionTimeoutMillis: 10000, // return an error after 10 second if connection could not be established
|
|
14
|
+
maxUses: 7500, // close (and replace) a connection after it has been used 7500 times (see below for discussion)
|
|
15
|
+
poolSize: 50, // Default is 10 connections
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const pool = new Pool(configPG)
|
|
19
|
+
|
|
20
|
+
pool.on('error', (err) => {
|
|
21
|
+
console.error('Unexpected error on idle client', err)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const connection = {}
|
|
25
|
+
|
|
26
|
+
connection.query = async (string, arr) => {
|
|
27
|
+
try {
|
|
28
|
+
/*console.log(string);
|
|
29
|
+
console.log(JSON.stringify(arr))*/
|
|
30
|
+
const result = await pool.query(string, arr)
|
|
31
|
+
return result.rows
|
|
32
|
+
} catch (e) {
|
|
33
|
+
console.log(string)
|
|
34
|
+
console.log(e)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const orderByFn = (obj) => {
|
|
39
|
+
const objOrderby = !obj.orderBy ? [] : obj.orderBy
|
|
40
|
+
let orderBy = ''
|
|
41
|
+
if (objOrderby.length) {
|
|
42
|
+
orderBy = ` ORDER BY `
|
|
43
|
+
for (var i = 0; i < objOrderby.length; i++) {
|
|
44
|
+
if (i % 2 == 0) {
|
|
45
|
+
orderBy += ` "${obj.orderBy[i]}" `
|
|
46
|
+
} else {
|
|
47
|
+
orderBy += ` ${obj.orderBy[i]} `
|
|
48
|
+
if (i == objOrderby.length - 1) {
|
|
49
|
+
orderBy += ` `
|
|
50
|
+
} else {
|
|
51
|
+
orderBy += `, `
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (obj.hasOwnProperty('order_by')) {
|
|
57
|
+
orderBy = ` ORDER BY `
|
|
58
|
+
orderBy += obj.order_by.join(',')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return orderBy
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const whereFn = (obj) => {
|
|
65
|
+
const where = obj.where || {}
|
|
66
|
+
//[{field:"your_field",option:"=>",value:"12",operator:"AND",type:"text,json,date, inline"}]
|
|
67
|
+
const whereArray = obj.whereArray || []
|
|
68
|
+
let increment = 1
|
|
69
|
+
let arr = [],
|
|
70
|
+
wherequery = []
|
|
71
|
+
for (const key in where) {
|
|
72
|
+
wherequery.push(key.indexOf('.') > -1 ? ` ${key} = $${increment} ` : ` "${key}" = $${increment}`)
|
|
73
|
+
arr.push(where[key])
|
|
74
|
+
increment++
|
|
75
|
+
}
|
|
76
|
+
//console.log(whereArray);
|
|
77
|
+
let hasWhere = false
|
|
78
|
+
wherequery = arr.length ? wherequery.join(' AND ') : ''
|
|
79
|
+
if (whereArray.length) {
|
|
80
|
+
let andOr = wherequery ? ' AND ' : ''
|
|
81
|
+
whereArray.map((item, index) => {
|
|
82
|
+
let type = !item.type ? 'text' : item.type
|
|
83
|
+
if (index > 0) {
|
|
84
|
+
andOr = ''
|
|
85
|
+
}
|
|
86
|
+
let operator = !item.operator ? ' AND ' : item.operator
|
|
87
|
+
if (index == whereArray.length - 1) {
|
|
88
|
+
operator = ''
|
|
89
|
+
}
|
|
90
|
+
let fields = ''
|
|
91
|
+
if (type == 'date') {
|
|
92
|
+
field = item.field.indexOf('.') > -1 ? item.field + '::text ' : ` ${item.field}::text `
|
|
93
|
+
} else {
|
|
94
|
+
field = item.field.indexOf('.') > -1 ? item.field : item.field ? ` "${item.field}" ` : ''
|
|
95
|
+
}
|
|
96
|
+
//is JSON is field is JSON
|
|
97
|
+
//JSON_CONTAINS(color, '"Red"' ,'$')
|
|
98
|
+
if (item.isJSON) {
|
|
99
|
+
wherequery += andOr + ` JSON_CONTAINS(${field}, '"${item.value}"' ,'$') ${operator}`
|
|
100
|
+
hasWhere = true
|
|
101
|
+
} else {
|
|
102
|
+
if (type == 'json') {
|
|
103
|
+
wherequery += andOr + ` JSON_CONTAINS(${field}, '"${item.value}"' ,'$') ${operator}`
|
|
104
|
+
hasWhere = true
|
|
105
|
+
} else if (type == 'inline') {
|
|
106
|
+
//select * from attendance where employee_id = 4803 and date IN ('2023-12-21','2023-12-22')
|
|
107
|
+
if (field) {
|
|
108
|
+
wherequery += andOr + ` ${field} ${item.value} ${operator}`
|
|
109
|
+
} else {
|
|
110
|
+
wherequery += andOr + ` ${item.value} ${operator}`
|
|
111
|
+
}
|
|
112
|
+
hasWhere = true
|
|
113
|
+
} else {
|
|
114
|
+
if (item.option.includes('{{value}}')) {
|
|
115
|
+
item.option = item.option.replace('{{value}}', `$${increment}`)
|
|
116
|
+
wherequery += `${andOr} ${field} ${item.option} ${operator}`
|
|
117
|
+
increment++
|
|
118
|
+
} else if (item.option.includes('$')) {
|
|
119
|
+
wherequery += `${andOr} ${field} ${item.option} ${operator}`
|
|
120
|
+
increment++
|
|
121
|
+
} else {
|
|
122
|
+
wherequery += `${andOr} ${field} ${item.option} $${increment} ${operator}`
|
|
123
|
+
increment++
|
|
124
|
+
}
|
|
125
|
+
let itemValue = item.value
|
|
126
|
+
if (item.option == '=') {
|
|
127
|
+
itemValue = Util.replaceAll(itemValue + '', '%', '')
|
|
128
|
+
}
|
|
129
|
+
arr.push(itemValue)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
//console.log(arr)
|
|
134
|
+
}
|
|
135
|
+
if (arr.length > 0) {
|
|
136
|
+
hasWhere = true
|
|
137
|
+
}
|
|
138
|
+
let wheres = ''
|
|
139
|
+
if (hasWhere) {
|
|
140
|
+
wheres = `WHERE ${wherequery}`
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
let objAll = {
|
|
144
|
+
where: wheres,
|
|
145
|
+
arr: arr,
|
|
146
|
+
increment: increment,
|
|
147
|
+
}
|
|
148
|
+
//console.log(obj)
|
|
149
|
+
return objAll
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
connection.results = async (obj) => {
|
|
153
|
+
const select = obj.select || '*'
|
|
154
|
+
const table = obj.table || ''
|
|
155
|
+
//[{field:"your_field",option:"=>",value:"12",operator:"AND",type:"text,json,date"}]
|
|
156
|
+
const statement = obj.statement || ''
|
|
157
|
+
const limit = obj.limit ? ` LIMIT ${obj.limit} ` : ''
|
|
158
|
+
const offset = obj.hasOwnProperty('offset') ? ` OFFSET ${obj.offset} ` : obj.limit ? 'OFFSET 0' : ''
|
|
159
|
+
const orderBy = orderByFn(obj)
|
|
160
|
+
const values = obj.values || []
|
|
161
|
+
const objJoin = obj.joins || []
|
|
162
|
+
let join = ''
|
|
163
|
+
if (objJoin.length) {
|
|
164
|
+
join = objJoin.join(' ')
|
|
165
|
+
}
|
|
166
|
+
const whereObj = whereFn(obj)
|
|
167
|
+
const wheres = whereObj.where
|
|
168
|
+
const arr = whereObj.arr
|
|
169
|
+
const sql = `SELECT ${select} FROM "${table}" ${join} ${wheres} ${statement} ${orderBy} ${limit} ${offset}`
|
|
170
|
+
/*console.log(sql)
|
|
171
|
+
console.log(arr);*/
|
|
172
|
+
try {
|
|
173
|
+
const result = await pool.query(sql, arr.length ? arr : values.length ? values : null)
|
|
174
|
+
return !result.rows ? [] : result.rows
|
|
175
|
+
} catch (e) {
|
|
176
|
+
console.log(sql)
|
|
177
|
+
console.log(arr)
|
|
178
|
+
console.log(e.toString())
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
connection.sql = async (obj) => {
|
|
183
|
+
const select = obj.select || '*'
|
|
184
|
+
const table = obj.table || ''
|
|
185
|
+
//[{field:"your_field",option:"=>",value:"12",operator:"AND",type:"text,json,date"}]
|
|
186
|
+
const statement = obj.statement || ''
|
|
187
|
+
const limit = obj.limit ? ` LIMIT ${obj.limit} ` : ''
|
|
188
|
+
const offset = obj.hasOwnProperty('offset') ? ` OFFSET ${obj.offset} ` : obj.limit ? 'OFFSET 0' : ''
|
|
189
|
+
const orderBy = orderByFn(obj)
|
|
190
|
+
const values = obj.values || []
|
|
191
|
+
const objJoin = obj.joins || []
|
|
192
|
+
let join = ''
|
|
193
|
+
if (objJoin.length) {
|
|
194
|
+
join = objJoin.join(' ')
|
|
195
|
+
}
|
|
196
|
+
const whereObj = whereFn(obj)
|
|
197
|
+
const wheres = whereObj.where
|
|
198
|
+
const arr = whereObj.arr
|
|
199
|
+
const sql = `SELECT ${select} FROM "${table}" ${join} ${wheres} ${statement} ${orderBy} ${limit} ${offset}`
|
|
200
|
+
return { sql: sql, arr: arr }
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
connection.result = async (obj) => {
|
|
204
|
+
const results = await connection.results(obj)
|
|
205
|
+
if (results.length) {
|
|
206
|
+
return results[0]
|
|
207
|
+
} else {
|
|
208
|
+
return []
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
connection.insert = async (obj) => {
|
|
213
|
+
let result
|
|
214
|
+
const table = obj.table
|
|
215
|
+
const data = obj.data
|
|
216
|
+
let increment = 1
|
|
217
|
+
const datas = []
|
|
218
|
+
const values = []
|
|
219
|
+
const arr = []
|
|
220
|
+
const returning = data.returning || 'RETURNING *'
|
|
221
|
+
delete data.returning
|
|
222
|
+
for (const key in data) {
|
|
223
|
+
datas.push(key)
|
|
224
|
+
values.push(`$${increment}`)
|
|
225
|
+
arr.push(data[key])
|
|
226
|
+
increment++
|
|
227
|
+
}
|
|
228
|
+
const sql = `INSERT INTO "${table}" ("${datas.join('","')}") VALUES (${values.join(',')}) ${returning}`
|
|
229
|
+
/* console.log("ON INSERT " + sql)
|
|
230
|
+
console.log(arr)
|
|
231
|
+
*/
|
|
232
|
+
|
|
233
|
+
try {
|
|
234
|
+
const results = await pool.query(sql, arr)
|
|
235
|
+
return results.rows[0]
|
|
236
|
+
} catch (e) {
|
|
237
|
+
console.log(sql)
|
|
238
|
+
console.log(arr)
|
|
239
|
+
console.log(e.toString())
|
|
240
|
+
throw e
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
connection.update = async (obj) => {
|
|
245
|
+
const table = obj.table
|
|
246
|
+
const data = obj.data
|
|
247
|
+
const returning = data.returning || 'RETURNING *'
|
|
248
|
+
delete data.returning
|
|
249
|
+
|
|
250
|
+
const where = obj.where || {}
|
|
251
|
+
//[{field:"your_field",option:"=>",value:"12",operator:"AND"}]
|
|
252
|
+
let whereArray = obj.whereArray || []
|
|
253
|
+
const arr = [],
|
|
254
|
+
dataArr = []
|
|
255
|
+
let wherequery = []
|
|
256
|
+
let increment = 1
|
|
257
|
+
for (let key in data) {
|
|
258
|
+
dataArr.push(` "${key}" = $${increment}`)
|
|
259
|
+
arr.push(data[key])
|
|
260
|
+
increment++
|
|
261
|
+
}
|
|
262
|
+
for (var key in where) {
|
|
263
|
+
wherequery.push(` "${key}" = $${increment}`)
|
|
264
|
+
arr.push(where[key])
|
|
265
|
+
increment++
|
|
266
|
+
}
|
|
267
|
+
wherequery = arr.length ? wherequery.join(' AND ') : ''
|
|
268
|
+
if (whereArray.length) {
|
|
269
|
+
let andOr = wherequery ? ' AND ' : ''
|
|
270
|
+
whereArray.forEach((item, index) => {
|
|
271
|
+
if (index > 0) andOr = ''
|
|
272
|
+
const operator = !item.operator ? ' AND ' : item.operator
|
|
273
|
+
const field = item.field.indexOf('.') > -1 ? item.field : `"${item.field}"`
|
|
274
|
+
wherequery += `${andOr} ${field} ${item.option} $${increment} ${operator}`
|
|
275
|
+
arr.push(item.value)
|
|
276
|
+
increment++
|
|
277
|
+
})
|
|
278
|
+
wherequery = wherequery.slice(0, -5)
|
|
279
|
+
}
|
|
280
|
+
const wheres = arr.length ? ' WHERE ' + wherequery : ''
|
|
281
|
+
const sql = `UPDATE "${table}" SET ${dataArr.join(', ')} ${wheres} ${returning}`
|
|
282
|
+
/* console.log(sql);
|
|
283
|
+
console.log(arr);*/
|
|
284
|
+
try {
|
|
285
|
+
const result = await pool.query(sql, arr)
|
|
286
|
+
return result.rows[0]
|
|
287
|
+
} catch (e) {
|
|
288
|
+
console.log(sql)
|
|
289
|
+
console.log(arr)
|
|
290
|
+
console.log(e.toString())
|
|
291
|
+
throw e
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
connection.delete = async (obj) => {
|
|
296
|
+
const table = obj.table
|
|
297
|
+
const where = obj.where || {}
|
|
298
|
+
let arr = [],
|
|
299
|
+
wherequery = []
|
|
300
|
+
let increment = 1
|
|
301
|
+
for (const key in where) {
|
|
302
|
+
wherequery.push(` "${key}" = $${increment}`)
|
|
303
|
+
arr.push(where[key])
|
|
304
|
+
increment++
|
|
305
|
+
}
|
|
306
|
+
wherequery = arr.length ? wherequery.join(' AND ') : ''
|
|
307
|
+
const wheres = arr.length ? ' WHERE ' + wherequery : ''
|
|
308
|
+
const sql = `DELETE FROM "${table}" ${wheres}`
|
|
309
|
+
/*console.log(sql);
|
|
310
|
+
console.log(arr)*/
|
|
311
|
+
try {
|
|
312
|
+
return await pool.query(sql, arr)
|
|
313
|
+
} catch (e) {
|
|
314
|
+
console.log(sql)
|
|
315
|
+
console.log(arr)
|
|
316
|
+
console.log(e.toString())
|
|
317
|
+
throw e
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
connection.driver = config.driver
|
|
322
|
+
connection.showTables = "SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname != 'pg_catalog' AND schemaname != 'information_schema'"
|
|
323
|
+
connection.showFullFields = (tableRelations) => {
|
|
324
|
+
return `SELECT
|
|
325
|
+
column_name AS "Field", concat(data_type,'(',character_maximum_length,')') AS "Type" , is_nullable AS "Null"
|
|
326
|
+
FROM
|
|
327
|
+
information_schema.COLUMNS
|
|
328
|
+
WHERE
|
|
329
|
+
TABLE_NAME = '${tableRelations}';`
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
connection.describeTable = (table) => {
|
|
333
|
+
return connection.showFullFields(table)
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
connection.showComments = (table) => {
|
|
337
|
+
return ` SELECT c.table_schema,c.table_name,c.column_name as "COLUMN_NAME",pgd.description as "COLUMN_COMMENT"
|
|
338
|
+
FROM pg_catalog.pg_statio_all_tables as st
|
|
339
|
+
inner join pg_catalog.pg_description pgd on (pgd.objoid=st.relid)
|
|
340
|
+
inner join information_schema.columns c on (pgd.objsubid=c.ordinal_position
|
|
341
|
+
and c.table_schema=st.schemaname and c.table_name=st.relname)
|
|
342
|
+
WHERE c.table_name = '${table}' ORDER BY c.column_name`
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
connection.showFields = (table) => {
|
|
346
|
+
return `
|
|
347
|
+
SELECT
|
|
348
|
+
tc.table_name AS "TABLE_NAME",
|
|
349
|
+
kcu.column_name AS "COLUMN_NAME",
|
|
350
|
+
tc.constraint_name AS "CONSTRAINT_NAME",
|
|
351
|
+
ccu.table_name AS "REFERENCED_TABLE_NAME",
|
|
352
|
+
ccu.column_name AS "REFERENCED_COLUMN_NAME",
|
|
353
|
+
tc.table_schema
|
|
354
|
+
FROM
|
|
355
|
+
information_schema.table_constraints AS tc
|
|
356
|
+
JOIN information_schema.key_column_usage AS kcu
|
|
357
|
+
ON tc.constraint_name = kcu.constraint_name
|
|
358
|
+
AND tc.table_schema = kcu.table_schema
|
|
359
|
+
JOIN information_schema.constraint_column_usage AS ccu
|
|
360
|
+
ON ccu.constraint_name = tc.constraint_name
|
|
361
|
+
AND ccu.table_schema = tc.table_schema
|
|
362
|
+
WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name='${table}';`
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
//list constraint list
|
|
366
|
+
connection.constraintList = (table, schema = 'public') => {
|
|
367
|
+
return `
|
|
368
|
+
SELECT con.*
|
|
369
|
+
FROM pg_catalog.pg_constraint con
|
|
370
|
+
INNER JOIN pg_catalog.pg_class rel
|
|
371
|
+
ON rel.oid = con.conrelid
|
|
372
|
+
INNER JOIN pg_catalog.pg_namespace nsp
|
|
373
|
+
ON nsp.oid = connamespace
|
|
374
|
+
WHERE nsp.nspname = '${schema}' AND rel.relname = '${table}'; `
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
//find foreign key
|
|
378
|
+
connection.foreignKeyList = (table) => {
|
|
379
|
+
return `SELECT
|
|
380
|
+
tc.table_schema,
|
|
381
|
+
tc.constraint_name,
|
|
382
|
+
tc.table_name,
|
|
383
|
+
kcu.column_name,
|
|
384
|
+
ccu.table_schema AS foreign_table_schema,
|
|
385
|
+
ccu.table_name AS foreign_table_name,
|
|
386
|
+
ccu.column_name AS foreign_column_name
|
|
387
|
+
FROM information_schema.table_constraints AS tc
|
|
388
|
+
JOIN information_schema.key_column_usage AS kcu
|
|
389
|
+
ON tc.constraint_name = kcu.constraint_name
|
|
390
|
+
AND tc.table_schema = kcu.table_schema
|
|
391
|
+
JOIN information_schema.constraint_column_usage AS ccu
|
|
392
|
+
ON ccu.constraint_name = tc.constraint_name
|
|
393
|
+
WHERE tc.constraint_type = 'FOREIGN KEY'
|
|
394
|
+
AND tc.table_name='${table}';`
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
var toNumber = function (num) {
|
|
398
|
+
num = num + ''
|
|
399
|
+
var t = replaceAll(num, '.', '')
|
|
400
|
+
if (t) {
|
|
401
|
+
return parseFloat(t)
|
|
402
|
+
} else return 0
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
function replaceAll(str, find, replace) {
|
|
406
|
+
return str.replace(new RegExp(find, 'g'), replace)
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
module.exports = connection
|