zet-lib 3.2.4 → 3.3.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.
package/lib/Form.js CHANGED
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  const Util = require("./Util");
7
+ const path = require('path');
7
8
 
8
9
  const Form = {};
9
10
  // Menghitung jumlah tanda "[" dalam str
@@ -550,7 +551,12 @@ Form.field = (obj) => {
550
551
  break;
551
552
 
552
553
  case "html":
553
- displayForm = obj.code;
554
+ let obj_code = typeof obj.code === 'string' ? obj.code : '';
555
+ if (!obj_code && obj.code) {
556
+ const dir = path.join(dirRoot,'public','runtime','html',obj.routeName,obj.id+'.txt')
557
+ obj_code = Util.readFile(dir);
558
+ }
559
+ displayForm = obj_code;
554
560
  break;
555
561
 
556
562
  case "location":
@@ -1038,7 +1044,7 @@ Form.build = (obj) => {
1038
1044
  }
1039
1045
 
1040
1046
  if(obj.type == "html") {
1041
- html = obj.code;
1047
+ html = Form.field(obj)
1042
1048
  }
1043
1049
  return html;
1044
1050
  };
package/lib/Mail.js CHANGED
@@ -1,4 +1,5 @@
1
1
  require("dotenv").config();
2
+ const path = require('path');
2
3
  const nodemailer = require('nodemailer')
3
4
  const ejs = require('ejs')
4
5
  const Util = require('./Util')
@@ -47,7 +48,7 @@ MAIL.send = function (options = {}, transporter = null) {
47
48
  }
48
49
 
49
50
  MAIL.forgotPassword = (datas = {}, options = {}) => {
50
- ejs.renderFile(`${dirRoot}/views/layouts/email/forgot_password.ejs`, { data: datas, Util: Util }, function (err, data) {
51
+ ejs.renderFile(path.join(dirRoot, 'views', 'layouts', 'email', 'forgot_password.ejs'), { data: datas, Util: Util }, function (err, data) {
51
52
  let option = Object.assign(mailOptions, options)
52
53
  option.html = data
53
54
  if (err) {
@@ -59,7 +60,7 @@ MAIL.forgotPassword = (datas = {}, options = {}) => {
59
60
  }
60
61
 
61
62
  MAIL.register = (datas = {}, options = {}) => {
62
- ejs.renderFile(`${dirRoot}/views/layouts/email/register.ejs`, { data: datas, Util: Util }, function (err, data) {
63
+ ejs.renderFile(path.join(dirRoot, 'views', 'layouts', 'email', 'register.ejs'), { data: datas, Util: Util }, function (err, data) {
63
64
  let option = Object.assign(mailOptions, options)
64
65
  option.html = data
65
66
  if (err) {
@@ -88,7 +89,7 @@ MAIL.approval = (req, res, data, email) => {
88
89
  });
89
90
 
90
91
  ejs.renderFile(
91
- dirRoot + "/views/layouts/email/approval.ejs",
92
+ path.join(dirRoot, 'views', 'layouts', 'email', 'approval.ejs'),
92
93
  { data: data, Util: Util },
93
94
  function (err, html) {
94
95
  if (err) {
package/lib/Model.js CHANGED
@@ -2394,7 +2394,8 @@ Model.relation = {
2394
2394
  "isSearch",
2395
2395
  "order_by",
2396
2396
  "import_field",
2397
- "relation_info"
2397
+ "relation_info",
2398
+ "isAttributes",
2398
2399
  ],
2399
2400
  labels: {
2400
2401
  required: "Required",
@@ -2413,7 +2414,8 @@ Model.relation = {
2413
2414
  isSearch:"Auto complete Search",
2414
2415
  order_by : "Order By",
2415
2416
  import_field :"Default Import Field (id)",
2416
- relation_info : "Relation Data"
2417
+ relation_info : "Relation Data",
2418
+ isAttributes:"Show all attributes data",
2417
2419
  },
2418
2420
  defaultValues: {
2419
2421
  required: false,
@@ -2423,6 +2425,7 @@ Model.relation = {
2423
2425
  name: "username",
2424
2426
  concat: "CONCAT(fullname, ' ',email)",
2425
2427
  where:"",
2428
+ isAttributes:false,
2426
2429
  isChain: false,
2427
2430
  onChange: "",
2428
2431
  information: "",
@@ -2463,6 +2466,10 @@ Model.relation = {
2463
2466
  tag: "input",
2464
2467
  type: "text",
2465
2468
  },
2469
+ isAttributes: {
2470
+ tag: "input",
2471
+ type: "checkbox",
2472
+ },
2466
2473
  isChain: {
2467
2474
  tag: "input",
2468
2475
  type: "checkbox",
package/lib/connection.js CHANGED
@@ -21,6 +21,77 @@ pool.on('error', (err) => {
21
21
  console.error('Unexpected error on idle client', err)
22
22
  })
23
23
 
24
+ // Validasi identifier (nama tabel) untuk mencegah SQL injection
25
+ const SAFE_IDENTIFIER = /^[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)?$/
26
+ const sanitizeTableName = (table) => {
27
+ if (typeof table !== 'string' || !table.trim()) return ''
28
+ const t = table.trim()
29
+ if (!SAFE_IDENTIFIER.test(t)) {
30
+ throw new Error(`Invalid table name: ${t}`)
31
+ }
32
+ return t
33
+ }
34
+
35
+ // Validasi limit/offset sebagai integer non-negatif
36
+ const toSafeNonNegativeInt = (val, fallback) => {
37
+ if (val === undefined || val === null) return fallback
38
+ const n = parseInt(val, 10)
39
+ if (!Number.isInteger(n) || n < 0) return fallback
40
+ return n
41
+ }
42
+
43
+ // Validasi satu segmen ORDER BY (identifier + optional ASC/DESC) untuk mencegah SQL injection
44
+ const SAFE_IDENTIFIER_PART = /^[a-zA-Z_][a-zA-Z0-9_]*$/
45
+ const sanitizeOrderBySegment = (segment) => {
46
+ if (typeof segment !== 'string' || !segment.trim()) return ''
47
+ const parts = segment.trim().split(/\s+/)
48
+ const ident = parts[0]
49
+ const dir = parts[1] ? parts[1].toUpperCase() : ''
50
+ if (dir && dir !== 'ASC' && dir !== 'DESC') return ''
51
+ const identParts = ident.split('.')
52
+ const valid = identParts.length > 0 && identParts.every(p => SAFE_IDENTIFIER_PART.test(p))
53
+ if (!valid) return ''
54
+ const quotedIdent = identParts.map(p => `"${p}"`).join('.')
55
+ return dir ? `${quotedIdent} ${dir}` : quotedIdent
56
+ }
57
+
58
+ // Validasi nama kolom (identifier tunggal) untuk INSERT/UPDATE
59
+ const sanitizeColumnName = (key) => SAFE_IDENTIFIER_PART.test(String(key).trim()) ? String(key).trim() : null
60
+
61
+ // Validasi klausa RETURNING: hanya RETURNING * atau RETURNING col1, col2, ...
62
+ const SAFE_RETURNING = /^RETURNING \*$/i
63
+ const SAFE_RETURNING_COLS = /^RETURNING ([a-zA-Z_][a-zA-Z0-9_]*)(,\s*[a-zA-Z_][a-zA-Z0-9_]*)*$/i
64
+ const sanitizeReturning = (clause) => {
65
+ if (typeof clause !== 'string' || !clause.trim()) return 'RETURNING *'
66
+ const s = clause.trim()
67
+ if (SAFE_RETURNING.test(s)) return s
68
+ if (SAFE_RETURNING_COLS.test(s)) return s
69
+ return 'RETURNING *'
70
+ }
71
+
72
+ // Validasi field di WHERE (identifier atau schema.table)
73
+ const sanitizeWhereField = (field) => {
74
+ if (field == null || typeof field !== 'string' || !field.trim()) return ''
75
+ const identParts = String(field).trim().split('.')
76
+ const valid = identParts.length > 0 && identParts.every(p => SAFE_IDENTIFIER_PART.test(p))
77
+ if (!valid) return ''
78
+ return identParts.map(p => `"${p}"`).join('.')
79
+ }
80
+
81
+ // Whitelist operator perbandingan untuk WHERE
82
+ const SAFE_WHERE_OPERATORS = new Set(['=', '!=', '<>', '<', '>', '<=', '>=', 'LIKE', 'ILIKE', 'IS NOT', 'IS'])
83
+ const sanitizeWhereOption = (option) => {
84
+ if (option == null || typeof option !== 'string') return ''
85
+ const s = String(option).trim().toUpperCase()
86
+ return SAFE_WHERE_OPERATORS.has(s) ? s : ''
87
+ }
88
+
89
+ const sanitizeWhereConnector = (op) => {
90
+ if (op == null || typeof op !== 'string') return ' AND '
91
+ const s = String(op).trim().toUpperCase()
92
+ return (s === 'OR' ? ' OR ' : ' AND ')
93
+ }
94
+
24
95
  const connection = {}
25
96
 
26
97
  connection.query = async (string, arr) => {
@@ -53,9 +124,11 @@ const orderByFn = (obj) => {
53
124
  }
54
125
  }
55
126
  }
56
- if (obj.hasOwnProperty('order_by')) {
57
- orderBy = ` ORDER BY `
58
- orderBy += obj.order_by.join(',')
127
+ if (obj.hasOwnProperty('order_by') && Array.isArray(obj.order_by) && obj.order_by.length) {
128
+ const segments = obj.order_by.map(sanitizeOrderBySegment).filter(Boolean)
129
+ if (segments.length) {
130
+ orderBy = ` ORDER BY ${segments.join(', ')} `
131
+ }
59
132
  }
60
133
 
61
134
  return orderBy
@@ -67,7 +140,7 @@ const whereFn = (obj) => {
67
140
  const whereArray = obj.whereArray || []
68
141
  let increment = 1
69
142
  let arr = [],
70
- wherequery = []
143
+ wherequery = []
71
144
  for (const key in where) {
72
145
  wherequery.push(key.indexOf('.') > -1 ? ` ${key} = $${increment} ` : ` "${key}" = $${increment}`)
73
146
  arr.push(where[key])
@@ -93,14 +166,17 @@ const whereFn = (obj) => {
93
166
  } else {
94
167
  field = item.field.indexOf('.') > -1 ? item.field : item.field ? ` "${item.field}" ` : ''
95
168
  }
96
- //is JSON is field is JSON
97
- //JSON_CONTAINS(color, '"Red"' ,'$')
169
+ // PostgreSQL: jsonb containment (@>) dengan parameter untuk keamanan
98
170
  if (item.isJSON) {
99
- wherequery += andOr + ` JSON_CONTAINS(${field}, '"${item.value}"' ,'$') ${operator}`
171
+ wherequery += andOr + ` (${String(field).trim()})::jsonb @> $${increment}::jsonb ${operator}`
172
+ arr.push(JSON.stringify(item.value))
173
+ increment++
100
174
  hasWhere = true
101
175
  } else {
102
176
  if (type == 'json') {
103
- wherequery += andOr + ` JSON_CONTAINS(${field}, '"${item.value}"' ,'$') ${operator}`
177
+ wherequery += andOr + ` (${String(field).trim()})::jsonb @> $${increment}::jsonb ${operator}`
178
+ arr.push(JSON.stringify(item.value))
179
+ increment++
104
180
  hasWhere = true
105
181
  } else if (type == 'inline') {
106
182
  //select * from attendance where employee_id = 4803 and date IN ('2023-12-21','2023-12-22')
@@ -150,11 +226,13 @@ const whereFn = (obj) => {
150
226
  }
151
227
 
152
228
  connection.results = async (obj) => {
229
+ const table = sanitizeTableName(obj.table || '')
153
230
  const select = obj.select || '*'
154
- const table = obj.table || ''
155
231
  const statement = obj.statement || ''
156
- const limit = obj.limit ? ` LIMIT ${obj.limit} ` : ''
157
- const offset = obj.hasOwnProperty('offset') ? ` OFFSET ${obj.offset} ` : obj.limit ? 'OFFSET 0' : ''
232
+ const limitVal = toSafeNonNegativeInt(obj.limit, null)
233
+ const offsetVal = obj.hasOwnProperty('offset') ? toSafeNonNegativeInt(obj.offset, 0) : (obj.limit ? 0 : null)
234
+ const limit = limitVal !== null ? ` LIMIT ${limitVal} ` : ''
235
+ const offset = offsetVal !== null ? ` OFFSET ${offsetVal} ` : ''
158
236
  const orderBy = orderByFn(obj)
159
237
  const values = obj.values || []
160
238
  const objJoin = obj.joins || []
@@ -166,35 +244,16 @@ connection.results = async (obj) => {
166
244
  const wheres = whereObj.where
167
245
  const arr = whereObj.arr
168
246
 
169
- // --- OPTIMIZATION: Fast count for count(id) as count ---
170
- if (select.trim().toLowerCase() === 'count(id) as count' && !wheres) {
171
- // No filter, use fast count from pg_class
172
- const sql = `SELECT reltuples::bigint AS count FROM pg_class WHERE relname = '${table}'`;
173
- try {
174
- const start = Date.now();
175
- const result = await pool.query(sql);
176
- const elapsed = Date.now() - start;
177
- console.log(`[zet-lib] Fast count for ${table}: ${elapsed}ms`);
178
- return result.rows;
179
- } catch (e) {
180
- console.log(sql)
181
- console.log(e.toString())
182
- }
183
- }
184
-
185
- const sql = `SELECT ${select} FROM "${table}" ${join} ${wheres} ${statement} ${orderBy} ${limit} ${offset}`
247
+ const sql = `SELECT ${select} FROM "${table}" ${join} ${wheres} ${statement} ${orderBy} ${limit} ${offset}`.replace(/\s+/g, ' ').trim()
186
248
  try {
187
- const start = Date.now();
249
+ const start = Date.now()
188
250
  const result = await pool.query(sql, arr.length ? arr : values.length ? values : null)
189
- const elapsed = Date.now() - start;
190
- /*if (select.trim().toLowerCase() === 'count(id) as count') {
191
- console.log(`[zet-lib] Count query for ${table}: ${elapsed}ms`);
192
- }*/
193
251
  return !result.rows ? [] : result.rows
194
252
  } catch (e) {
195
253
  console.log(sql)
196
254
  console.log(arr)
197
255
  console.log(e.toString())
256
+ throw e
198
257
  }
199
258
  }
200
259
 
@@ -229,25 +288,26 @@ connection.result = async (obj) => {
229
288
  }
230
289
 
231
290
  connection.insert = async (obj) => {
232
- let result
233
- const table = obj.table
234
- const data = obj.data
291
+ const table = sanitizeTableName(obj.table || '')
292
+ if (!table) throw new Error('Table name is required for insert')
293
+ const data = { ...obj.data }
294
+ const returning = sanitizeReturning(data.returning || 'RETURNING *')
295
+ delete data.returning
235
296
  let increment = 1
236
297
  const datas = []
237
298
  const values = []
238
299
  const arr = []
239
- const returning = data.returning || 'RETURNING *'
240
- delete data.returning
241
300
  for (const key in data) {
242
- datas.push(key)
243
- values.push(`$${increment}`)
244
- arr.push(data[key])
245
- increment++
301
+ const col = sanitizeColumnName(key)
302
+ if (col) {
303
+ datas.push(col)
304
+ values.push(`$${increment}`)
305
+ arr.push(data[key])
306
+ increment++
307
+ }
246
308
  }
247
- const sql = `INSERT INTO "${table}" ("${datas.join('","')}") VALUES (${values.join(',')}) ${returning}`
248
- /* console.log("ON INSERT " + sql)
249
- console.log(arr)
250
- */
309
+ if (datas.length === 0) throw new Error('At least one valid column is required for insert')
310
+ const sql = `INSERT INTO "${table}" ("${datas.join('","')}") VALUES (${values.join(',')}) ${returning}`
251
311
 
252
312
  try {
253
313
  const results = await pool.query(sql, arr)
@@ -261,45 +321,59 @@ connection.insert = async (obj) => {
261
321
  }
262
322
 
263
323
  connection.update = async (obj) => {
264
- const table = obj.table
265
- const data = obj.data
266
- const returning = data.returning || 'RETURNING *'
324
+ const table = sanitizeTableName(obj.table || '')
325
+ if (!table) throw new Error('Table name is required for update')
326
+ const data = { ...obj.data }
327
+ const returning = sanitizeReturning(data.returning || 'RETURNING *')
267
328
  delete data.returning
268
329
 
269
330
  const where = obj.where || {}
270
- //[{field:"your_field",option:"=>",value:"12",operator:"AND"}]
271
- let whereArray = obj.whereArray || []
272
- const arr = [],
273
- dataArr = []
331
+ const whereArray = obj.whereArray || []
332
+ const arr = []
333
+ const dataArr = []
274
334
  let wherequery = []
275
335
  let increment = 1
276
- for (let key in data) {
277
- dataArr.push(` "${key}" = $${increment}`)
278
- arr.push(data[key])
279
- increment++
336
+
337
+ for (const key in data) {
338
+ const col = sanitizeColumnName(key)
339
+ if (col) {
340
+ dataArr.push(`"${col}" = $${increment}`)
341
+ arr.push(data[key])
342
+ increment++
343
+ }
280
344
  }
281
- for (var key in where) {
282
- wherequery.push(` "${key}" = $${increment}`)
283
- arr.push(where[key])
284
- increment++
345
+ if (dataArr.length === 0) throw new Error('At least one valid column is required for update')
346
+
347
+ for (const key in where) {
348
+ const col = sanitizeColumnName(key)
349
+ if (col) {
350
+ wherequery.push(`"${col}" = $${increment}`)
351
+ arr.push(where[key])
352
+ increment++
353
+ }
285
354
  }
286
- wherequery = arr.length ? wherequery.join(' AND ') : ''
355
+ wherequery = wherequery.length ? wherequery.join(' AND ') : ''
356
+
287
357
  if (whereArray.length) {
288
358
  let andOr = wherequery ? ' AND ' : ''
289
359
  whereArray.forEach((item, index) => {
290
360
  if (index > 0) andOr = ''
291
- const operator = !item.operator ? ' AND ' : item.operator
292
- const field = item.field.indexOf('.') > -1 ? item.field : `"${item.field}"`
293
- wherequery += `${andOr} ${field} ${item.option} $${increment} ${operator}`
294
- arr.push(item.value)
295
- increment++
361
+ const field = sanitizeWhereField(item.field)
362
+ const option = sanitizeWhereOption(item.option)
363
+ const connector = sanitizeWhereConnector(item.operator)
364
+ if (field && option) {
365
+ wherequery += `${andOr} ${field} ${option} $${increment} ${connector}`
366
+ arr.push(item.value)
367
+ increment++
368
+ }
296
369
  })
297
- wherequery = wherequery.slice(0, -5)
370
+ if (wherequery.endsWith(' AND ')) wherequery = wherequery.slice(0, -5)
371
+ else if (wherequery.endsWith(' OR ')) wherequery = wherequery.slice(0, -4)
298
372
  }
299
- const wheres = arr.length ? ' WHERE ' + wherequery : ''
300
- const sql = `UPDATE "${table}" SET ${dataArr.join(', ')} ${wheres} ${returning}`
301
- /* console.log(sql);
302
- console.log(arr);*/
373
+
374
+ const wheres = wherequery ? ' WHERE ' + wherequery : ''
375
+ const sql = `UPDATE "${table}" SET ${dataArr.join(', ')}${wheres} ${returning}`
376
+
303
377
  try {
304
378
  const result = await pool.query(sql, arr)
305
379
  return result.rows[0]
@@ -312,21 +386,23 @@ connection.update = async (obj) => {
312
386
  }
313
387
 
314
388
  connection.delete = async (obj) => {
315
- const table = obj.table
389
+ const table = sanitizeTableName(obj.table || '')
390
+ if (!table) throw new Error('Table name is required for delete')
316
391
  const where = obj.where || {}
317
- let arr = [],
318
- wherequery = []
392
+ const arr = []
393
+ const wherequery = []
319
394
  let increment = 1
320
395
  for (const key in where) {
321
- wherequery.push(` "${key}" = $${increment}`)
322
- arr.push(where[key])
323
- increment++
396
+ const col = sanitizeColumnName(key)
397
+ if (col) {
398
+ wherequery.push(`"${col}" = $${increment}`)
399
+ arr.push(where[key])
400
+ increment++
401
+ }
324
402
  }
325
- wherequery = arr.length ? wherequery.join(' AND ') : ''
326
- const wheres = arr.length ? ' WHERE ' + wherequery : ''
327
- const sql = `DELETE FROM "${table}" ${wheres} RETURNING *`
328
- /*console.log(sql);
329
- console.log(arr)*/
403
+ const whereClause = wherequery.length ? wherequery.join(' AND ') : ''
404
+ const wheres = whereClause ? ' WHERE ' + whereClause : ''
405
+ const sql = `DELETE FROM "${table}"${wheres} RETURNING *`
330
406
  try {
331
407
  return await pool.query(sql, arr)
332
408
  } catch (e) {
@@ -346,7 +422,7 @@ connection.insertData = async(tableName, data) => {
346
422
  }
347
423
 
348
424
  pgPool = new Pool(configPG);
349
-
425
+
350
426
  const columns = Object.keys(data);
351
427
  if (columns.length === 0) {
352
428
  throw new Error('No columns found in the data object');
@@ -381,7 +457,7 @@ connection.deleteData = async(tableName, where) => {
381
457
  }
382
458
 
383
459
  pgPool = new Pool(configPG);
384
-
460
+
385
461
  const whereColumns = Object.keys(where);
386
462
  if (whereColumns.length === 0) {
387
463
  throw new Error('No where conditions provided for delete');
@@ -417,13 +493,13 @@ connection.insertMultipleRecords = async(tableName,records) => {
417
493
  }
418
494
 
419
495
  pgPool = new Pool(configPG);
420
-
496
+
421
497
  // Validasi bahwa semua records memiliki struktur yang sama
422
498
  const firstRecord = records[0];
423
499
  if (!firstRecord || typeof firstRecord !== 'object') {
424
500
  throw new Error('First record is invalid or empty');
425
501
  }
426
-
502
+
427
503
  const columns = Object.keys(firstRecord);
428
504
  if (columns.length === 0) {
429
505
  throw new Error('No columns found in the first record');
@@ -444,7 +520,7 @@ connection.insertMultipleRecords = async(tableName,records) => {
444
520
  const placeholders = records.map((_, rowIndex) =>
445
521
  `(${columns.map((_, colIndex) => `$${rowIndex * columns.length + colIndex + 1}`).join(',')})`
446
522
  ).join(',');
447
-
523
+
448
524
  // Create the INSERT query
449
525
  const insertQuery = `
450
526
  INSERT INTO "${tableName}" (${columns.map(col => `"${col}"`).join(',')})
@@ -34,7 +34,7 @@ generatorApp.CREATE_MODEL_API = async (columns, constraintList, MYMODEL) => {
34
34
  generatorApp.CREATE_ROUTER = async (MYMODEL, zFields) => {
35
35
  let CONTENT =
36
36
  zFields.router ||
37
- fs.readFileSync(generatorApp.DIRECTORY + "/routerApp.ejs", "utf-8");
37
+ fs.readFileSync(path.join(generatorApp.DIRECTORY, "routerApp.ejs"), "utf-8");
38
38
  const zfields = await connection.result({
39
39
  table: "zfields",
40
40
  where: { table: MYMODEL.table },
@@ -58,7 +58,7 @@ generatorApp.CREATE_ROUTER = async (MYMODEL, zFields) => {
58
58
  }
59
59
 
60
60
  fs.writeFileSync(
61
- generatorApp.DIRECTORY_ROUTES + "/" + MYMODEL.table + ".js",
61
+ path.join(generatorApp.DIRECTORY_ROUTES, MYMODEL.table + ".js"),
62
62
  CONTENT,
63
63
  "utf-8"
64
64
  );
@@ -67,7 +67,7 @@ generatorApp.CREATE_ROUTER = async (MYMODEL, zFields) => {
67
67
  generatorApp.CREATE_ROUTER_API = (MYMODEL, zfields) => {
68
68
  let CONTENT =
69
69
  zfields.router ||
70
- fs.readFileSync(generatorApp.DIRECTORY + "/routerApp.ejs", "utf-8");
70
+ fs.readFileSync(path.join(generatorApp.DIRECTORY, "routerApp.ejs"), "utf-8");
71
71
  //var zfields = await connection.result({table: "zfields", where: {table: MYMODEL.table}});
72
72
  const ADDITIONAL_FIELDS = generatorApp.ADDITIONAL_FIELDS(MYMODEL);
73
73
  const OBJ = {
@@ -86,7 +86,7 @@ generatorApp.CREATE_ROUTER_API = (MYMODEL, zfields) => {
86
86
  for (let KEY in OBJ) {
87
87
  CONTENT = Util.replaceAll(CONTENT, "[[[" + KEY + "]]]", OBJ[KEY]);
88
88
  }
89
- //fs.writeFileSync(generatorApp.DIRECTORY_ROUTES + "/" + MYMODEL.table + ".js", CONTENT, 'utf-8');
89
+ //fs.writeFileSync(path.join(generatorApp.DIRECTORY_ROUTES, MYMODEL.table + ".js"), CONTENT, 'utf-8');
90
90
  return {
91
91
  filename: MYMODEL.table + ".js",
92
92
  content: CONTENT,
@@ -123,7 +123,7 @@ generatorApp.CREATE_VIEWS = async (MYMODEL, zFields) => {
123
123
  "[[[GENERATE_VIEW]]]": GENERATE_VIEW,
124
124
  };
125
125
 
126
- const DIR_VIEW = generatorApp.DIRECTORY_VIEWS + "/" + MYMODEL.table;
126
+ const DIR_VIEW = path.join(generatorApp.DIRECTORY_VIEWS, MYMODEL.table);
127
127
  if (!fs.existsSync(DIR_VIEW)) {
128
128
  fs.mkdirSync(DIR_VIEW);
129
129
  }
@@ -133,16 +133,16 @@ generatorApp.CREATE_VIEWS = async (MYMODEL, zFields) => {
133
133
  name = name.replace(".", "_");
134
134
  let source = zFields[name];
135
135
  if (source) {
136
- fs.writeFileSync(DIR_VIEW + "/" + item, source);
136
+ fs.writeFileSync(path.join(DIR_VIEW, item), source);
137
137
  } else {
138
- source = generatorApp.DIRECTORY_GENERATOR_VIEWS + "/" + item;
139
- fs.copySync(source, DIR_VIEW + "/" + item);
138
+ source = path.join(generatorApp.DIRECTORY_GENERATOR_VIEWS, item);
139
+ fs.copySync(source, path.join(DIR_VIEW, item));
140
140
  }
141
- console.log(DIR_VIEW + "/" + item);
141
+ console.log(path.join(DIR_VIEW, item));
142
142
  for (let KEY in OBJ) {
143
143
  generatorApp.MODIFIY(
144
- DIR_VIEW + "/" + item,
145
- DIR_VIEW + "/" + item,
144
+ path.join(DIR_VIEW, item),
145
+ path.join(DIR_VIEW, item),
146
146
  KEY,
147
147
  OBJ[KEY]
148
148
  );
@@ -183,7 +183,7 @@ generatorApp.CREATE_VIEWS_API = (MYMODEL, zFields) => {
183
183
  "[[[GENERATE_VIEW]]]": GENERATE_VIEW,
184
184
  };
185
185
 
186
- const DIR_VIEW = `${dirRoot}/public/temp/${token}`;
186
+ const DIR_VIEW = path.join(dirRoot, "public", "temp", token);
187
187
  if (!fs.existsSync(DIR_VIEW)) {
188
188
  fs.mkdirSync(DIR_VIEW);
189
189
  }
@@ -194,23 +194,23 @@ generatorApp.CREATE_VIEWS_API = (MYMODEL, zFields) => {
194
194
  name = name.replace(".", "_");
195
195
  let source = zFields.hasOwnProperty(name)
196
196
  ? zFields[name]
197
- : fs.readFileSync(generatorApp.DIRECTORY_GENERATOR_VIEWS + "/" + item, {
197
+ : fs.readFileSync(path.join(generatorApp.DIRECTORY_GENERATOR_VIEWS, item), {
198
198
  encoding: "utf8",
199
199
  flag: "r",
200
200
  });
201
201
  if (source) {
202
- fs.writeFileSync(DIR_VIEW + "/" + item, source);
202
+ fs.writeFileSync(path.join(DIR_VIEW, item), source);
203
203
  } else {
204
204
  source = fs.readFileSync(
205
- generatorApp.DIRECTORY_GENERATOR_VIEWS + "/" + item,
205
+ path.join(generatorApp.DIRECTORY_GENERATOR_VIEWS, item),
206
206
  { encoding: "utf8", flag: "r" }
207
207
  );
208
- fs.copySync(source, DIR_VIEW + "/" + item);
208
+ fs.copySync(source, path.join(DIR_VIEW, item));
209
209
  }
210
210
  for (let KEY in OBJ) {
211
211
  generatorApp.MODIFIY(
212
- DIR_VIEW + "/" + item,
213
- DIR_VIEW + "/" + item,
212
+ path.join(DIR_VIEW, item),
213
+ path.join(DIR_VIEW, item),
214
214
  KEY,
215
215
  OBJ[KEY]
216
216
  );
@@ -218,7 +218,7 @@ generatorApp.CREATE_VIEWS_API = (MYMODEL, zFields) => {
218
218
  }
219
219
  for (let i = 0; i < views.length; i++) {
220
220
  const item = views[i];
221
- datas[item] = fs.readFileSync(`${DIR_VIEW}/${item}`, {
221
+ datas[item] = fs.readFileSync(path.join(DIR_VIEW, item), {
222
222
  encoding: "utf8",
223
223
  flag: "r",
224
224
  });