@agung_dhewe/webapps 1.1.2

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 (130) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +2 -0
  3. package/jsconfig.json +10 -0
  4. package/libs/fgta5js-dist/fgta5js-v1.8.3.min.css +2 -0
  5. package/libs/fgta5js-dist/fgta5js-v1.8.3.min.js +11 -0
  6. package/libs/fgta5js-dist/fgta5js-v1.8.3.min.js.map +1 -0
  7. package/libs/fgta5js-dist/fonts/karla-italic-latin-ext.woff2 +0 -0
  8. package/libs/fgta5js-dist/fonts/karla-italic-latin.woff2 +0 -0
  9. package/libs/fgta5js-dist/fonts/karla-normal-latin-ext.woff2 +0 -0
  10. package/libs/fgta5js-dist/fonts/karla-normal-latin.woff2 +0 -0
  11. package/libs/fgta5js-dist/fonts/karla.css +142 -0
  12. package/libs/webmodule/module-edit.css +163 -0
  13. package/libs/webmodule/module-footer.css +22 -0
  14. package/libs/webmodule/module-list.css +25 -0
  15. package/libs/webmodule/module.css +52 -0
  16. package/libs/webmodule/module.js +195 -0
  17. package/libs/webmodule/pagehelper.mjs +45 -0
  18. package/modules/generator/appgen-components.mjs +142 -0
  19. package/modules/generator/appgen-icons.mjs +6 -0
  20. package/modules/generator/appgen-io.mjs +784 -0
  21. package/modules/generator/appgen-ui-search.mjs +173 -0
  22. package/modules/generator/appgen-ui-unique.mjs +153 -0
  23. package/modules/generator/appgen-ui.mjs +1181 -0
  24. package/modules/generator/generator-context.mjs +18 -0
  25. package/modules/generator/generator-designtemplate.html +1508 -0
  26. package/modules/generator/generator-ext.html +0 -0
  27. package/modules/generator/generator-ext.mjs +3 -0
  28. package/modules/generator/generator.css +642 -0
  29. package/modules/generator/generator.mjs +195 -0
  30. package/modules/generator/generator.png +0 -0
  31. package/modules/generator/generatorEdit.html +185 -0
  32. package/modules/generator/generatorEdit.mjs +238 -0
  33. package/modules/generator/generatorList.html +32 -0
  34. package/modules/generator/generatorList.mjs +243 -0
  35. package/modules/login/login.css +11 -0
  36. package/modules/login/login.html +12 -0
  37. package/modules/login/login.mjs +111 -0
  38. package/package.json +46 -0
  39. package/percobaan/simmpan-ke-minio.js +24 -0
  40. package/src/api.js +80 -0
  41. package/src/apis/generator.api.js +226 -0
  42. package/src/apis/login.api.js +109 -0
  43. package/src/bucket.js +24 -0
  44. package/src/context.js +26 -0
  45. package/src/datalog.sql +22 -0
  46. package/src/datarecords.js +0 -0
  47. package/src/db.js +61 -0
  48. package/src/generator/createApiExtenderModule.js +54 -0
  49. package/src/generator/createApiModule.js +218 -0
  50. package/src/generator/createIcon.js +62 -0
  51. package/src/generator/createInfoAboutExtender.js +42 -0
  52. package/src/generator/createInfoLogs.js +41 -0
  53. package/src/generator/createInfoRecordExtender.js +41 -0
  54. package/src/generator/createModuleContext.js +48 -0
  55. package/src/generator/createModuleDetilEditHtml.js +110 -0
  56. package/src/generator/createModuleDetilEditMjs.js +172 -0
  57. package/src/generator/createModuleDetilListHtml.js +146 -0
  58. package/src/generator/createModuleDetilListMjs.js +73 -0
  59. package/src/generator/createModuleEjs.js +51 -0
  60. package/src/generator/createModuleExtenderHtml.js +43 -0
  61. package/src/generator/createModuleExtenderMjs.js +43 -0
  62. package/src/generator/createModuleHeaderEditHtml.js +148 -0
  63. package/src/generator/createModuleHeaderEditMjs.js +197 -0
  64. package/src/generator/createModuleHeaderListHtml.js +144 -0
  65. package/src/generator/createModuleHeaderListMjs.js +67 -0
  66. package/src/generator/createModuleMjs.js +67 -0
  67. package/src/generator/createModuleRollup.js +42 -0
  68. package/src/generator/createProgramData.js +96 -0
  69. package/src/generator/createTable.js +156 -0
  70. package/src/generator/ddl.js +475 -0
  71. package/src/generator/helper.js +149 -0
  72. package/src/generator/templates/__rollup-module.ejs +90 -0
  73. package/src/generator/templates/api-extender-module.js.ejs +0 -0
  74. package/src/generator/templates/api-module.js.ejs +818 -0
  75. package/src/generator/templates/module-context.ejs +16 -0
  76. package/src/generator/templates/module-ext-about.ejs +1 -0
  77. package/src/generator/templates/module-ext-record.ejs +1 -0
  78. package/src/generator/templates/module-ext.html.ejs +3 -0
  79. package/src/generator/templates/module-ext.mjs.ejs +21 -0
  80. package/src/generator/templates/module-logs.ejs +14 -0
  81. package/src/generator/templates/module.ejs.ejs +48 -0
  82. package/src/generator/templates/module.mjs.ejs +256 -0
  83. package/src/generator/templates/moduleDetilEdit.html.ejs +34 -0
  84. package/src/generator/templates/moduleDetilEdit.mjs.ejs +792 -0
  85. package/src/generator/templates/moduleDetilList.html.ejs +26 -0
  86. package/src/generator/templates/moduleDetilList.mjs.ejs +319 -0
  87. package/src/generator/templates/moduleHeaderEdit.html.ejs +53 -0
  88. package/src/generator/templates/moduleHeaderEdit.mjs.ejs +807 -0
  89. package/src/generator/templates/moduleHeaderList.html.ejs +24 -0
  90. package/src/generator/templates/moduleHeaderList.mjs.ejs +308 -0
  91. package/src/generator/templates/sqlAddField.ejs +3 -0
  92. package/src/generator/templates/sqlAddForeignKey.ejs +12 -0
  93. package/src/generator/templates/sqlAddUniqueIndex.ejs +4 -0
  94. package/src/generator/templates/sqlCreateTable.ejs +9 -0
  95. package/src/generator/templates/sqlDropForeignKey.ejs +3 -0
  96. package/src/generator/templates/sqlDropUniqueIndex.ejs +4 -0
  97. package/src/generator/templates/sqlModifyField.ejs +6 -0
  98. package/src/generator/trygenerate.js +83 -0
  99. package/src/generator/worker.js +389 -0
  100. package/src/helper.js +82 -0
  101. package/src/logger.js +39 -0
  102. package/src/router.js +84 -0
  103. package/src/routers/defaultLoginApi.js +29 -0
  104. package/src/routers/defaultLoginAsset.js +18 -0
  105. package/src/routers/defaultLoginPage.js +36 -0
  106. package/src/routers/defaultRootIndex.js +16 -0
  107. package/src/routers/downloadHandler.js +51 -0
  108. package/src/routers/fileUploadApi.js +15 -0
  109. package/src/routers/generatorApi.js +30 -0
  110. package/src/routers/generatorAsset.js +18 -0
  111. package/src/routers/generatorPage.js +37 -0
  112. package/src/routers/handleError.js +43 -0
  113. package/src/routers/handleModuleNotfound.js +12 -0
  114. package/src/routers/moduleApi.js +34 -0
  115. package/src/routers/modulePage.js +102 -0
  116. package/src/sequencerdoc.js +311 -0
  117. package/src/sequencerline.js +214 -0
  118. package/src/session.js +57 -0
  119. package/src/startup.js +59 -0
  120. package/src/webapps.js +239 -0
  121. package/src/workermanager.js +83 -0
  122. package/templates/_lib_debug.ejs +11 -0
  123. package/templates/_lib_production.ejs +5 -0
  124. package/templates/application.page.ejs +143 -0
  125. package/templates/generator.page.ejs +131 -0
  126. package/templates/index.page.ejs +24 -0
  127. package/templates/login.page.ejs +102 -0
  128. package/templates/moduleError.ejs +16 -0
  129. package/templates/moduleNotfound.ejs +14 -0
  130. package/webapps.code-workspace +11 -0
@@ -0,0 +1,156 @@
1
+ import { kebabToCamel, isFileExist, getSectionData } from './helper.js'
2
+ import { fileURLToPath } from 'url';
3
+ import * as ddl from './ddl.js'
4
+ import path from 'path'
5
+ import fs from 'fs/promises'
6
+ import pgp from 'pg-promise'
7
+ import db from '../db.js'
8
+
9
+
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = path.dirname(__filename);
12
+
13
+ export async function createTable(context, options) {
14
+ const skipGenerate = options.skipGenerate===true
15
+ const moduleName = context.moduleName
16
+ const title = context.title
17
+
18
+
19
+
20
+ try {
21
+ if (skipGenerate) {
22
+ context.postMessage({message: `skip generate table(s)`})
23
+ return
24
+ }
25
+
26
+
27
+ // start geneate program code
28
+ let sections = []
29
+ for (var entityName in context.entities) {
30
+
31
+ // prepare target file
32
+ const targetFile = path.join(context.moduleDir, `${moduleName}-${entityName}.sql`)
33
+
34
+
35
+ // reporting progress to parent process
36
+ context.postMessage({message: `generating file: '${targetFile}`})
37
+
38
+
39
+ // start generate table for tis entity
40
+ const entity = context.entities[entityName]
41
+ const {table, descr, pk, identifierMethod} = entity
42
+ const pkData = entity.Items[pk]
43
+ const {schema, tablename} = ddl.parseTableName(table)
44
+ const {data_fieldname, data_type, data_length, description} = pkData
45
+
46
+
47
+
48
+ const scriptContent = []
49
+
50
+ scriptContent.push(`-- ${moduleName}.sql`)
51
+ scriptContent.push("\n")
52
+
53
+ // Buat Table dengan field hanya untuk primary key
54
+ {
55
+ const sql = await ddl.createTable(schema, tablename, descr, {
56
+ fieldname: data_fieldname,
57
+ datatype: data_type,
58
+ length: data_length,
59
+ identifierMethod: identifierMethod
60
+ })
61
+ scriptContent.push(sql)
62
+ }
63
+
64
+ const recordColumns = createRecordColumns()
65
+ const entityItems = structuredClone({...entity.Items, ...recordColumns})
66
+
67
+ // Buat Fields
68
+ {
69
+
70
+ for (var fieldname in entityItems) {
71
+ if (fieldname==pk) {
72
+ continue
73
+ }
74
+
75
+ const field = entityItems[fieldname]
76
+ const {data_fieldname, data_type, data_length, data_precision, data_allownull, data_defaultvalue, description} = field
77
+
78
+ const sql = await ddl.createField(schema, tablename, {
79
+ fieldname: data_fieldname,
80
+ datatype: data_type,
81
+ length: data_length,
82
+ precision: data_precision,
83
+ allownull: data_allownull,
84
+ defaultvalue: data_defaultvalue,
85
+ description: description
86
+ })
87
+ scriptContent.push(sql)
88
+ }
89
+
90
+ }
91
+
92
+ // buat foreign key
93
+ scriptContent.push("\n")
94
+ {
95
+ const foreignKeys = Object.entries(entityItems)
96
+ .filter(([_, value]) => value.Reference.table !== null && value.Reference.table !== '')
97
+ .reduce((acc, [key, value]) => {
98
+ acc[key] = value;
99
+ return acc;
100
+ }, {})
101
+
102
+
103
+ const sql = await ddl.createFereignKey(schema, tablename, foreignKeys)
104
+ scriptContent.push(sql)
105
+
106
+ }
107
+
108
+
109
+
110
+ // buat unique index
111
+ scriptContent.push("\n")
112
+ {
113
+ const sql = await ddl.createUniqueIndex(schema, tablename, entity.Uniques)
114
+ scriptContent.push(sql)
115
+ }
116
+
117
+
118
+ let content = scriptContent.join("\n")
119
+ await fs.writeFile(targetFile, content, 'utf8');
120
+
121
+
122
+ }
123
+ } catch (err) {
124
+ throw err
125
+ }
126
+
127
+ }
128
+
129
+
130
+ function createRecordColumns() {
131
+ const records = {
132
+ _createby: {
133
+ data_fieldname: '_createby', data_type: 'bigint', data_allownull: false, description: 'user yang pertama kali membuat record ini',
134
+ Reference: {table: '',pk: ''}
135
+ },
136
+
137
+ _createdate: {
138
+ data_fieldname: '_createdate', data_type: 'timestamp', data_allownull: false, description: 'waktu record dibuat pertama kali',
139
+ Reference: {table: '',pk: ''}
140
+ },
141
+
142
+ _modifyby: {
143
+ data_fieldname: '_modifyby', data_type: 'bigint', data_allownull: true, description: 'user yang terakhir modifikasi record ini',
144
+ Reference: {table: '',pk: ''}
145
+ },
146
+
147
+ _modifydate: {
148
+ data_fieldname: '_modifydate', data_type: 'timestamp', data_allownull: true, description: 'waktu terakhir record dimodifikasi',
149
+ Reference: {table: '',pk: ''}
150
+ }
151
+ }
152
+
153
+ return records
154
+ }
155
+
156
+
@@ -0,0 +1,475 @@
1
+ import pgp from 'pg-promise'
2
+ import db from '../db.js'
3
+ import path from 'path'
4
+ import fs from 'fs/promises'
5
+ import ejs from 'ejs'
6
+ import { fileURLToPath } from 'url';
7
+ import { console } from 'inspector'
8
+
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = path.dirname(__filename);
11
+
12
+
13
+ export function parseTableName(str) {
14
+ if (typeof str !== 'string' || !str.trim()) {
15
+ throw new Error("Input harus berupa string non-kosong");
16
+ }
17
+
18
+ const parts = str.split('.');
19
+ if (parts.length === 2) {
20
+ const [schema, tablename] = parts;
21
+ return { schema, tablename };
22
+ } else if (parts.length === 1) {
23
+ return { schema: 'public', tablename: parts[0] };
24
+ } else {
25
+ throw new Error("Format tidak valid. Gunakan 'schema.tablename' atau hanya 'tablename'");
26
+ }
27
+ }
28
+
29
+ export async function tableExist(schema, tablename) {
30
+ const sqlCekTableExists = `
31
+ SELECT EXISTS (
32
+ SELECT 1
33
+ FROM information_schema.tables
34
+ WHERE table_schema = \${schema}
35
+ AND table_name = \${tablename}
36
+ ) AS "exists"
37
+ `
38
+
39
+ try {
40
+ const res = await db.one(sqlCekTableExists, {schema, tablename});
41
+ return res.exists
42
+ } catch (err) {
43
+ throw err
44
+ }
45
+ }
46
+
47
+ export async function fieldExists(schema, tablename, fieldname) {
48
+ const sqlCekFieldExists = `
49
+ SELECT EXISTS (
50
+ SELECT 1
51
+ FROM information_schema.columns
52
+ WHERE table_schema = \${schema}
53
+ AND table_name = \${tablename}
54
+ AND column_name = \${fieldname}
55
+ ) AS "exists"
56
+ `
57
+
58
+ try {
59
+ const res = await db.one(sqlCekFieldExists, {schema, tablename, fieldname});
60
+ return res.exists
61
+ } catch (err) {
62
+ throw err
63
+ }
64
+ }
65
+
66
+ export async function createTable(schema, tablename, tabledescr, pk) {
67
+ const {fieldname, datatype, length, precision, allownull, defaultvalue, description, identifierMethod} = pk
68
+
69
+ try {
70
+
71
+ // manual, auto-by-default, auto-always, auto-yearly, auto-monthly, custom
72
+
73
+ let type
74
+
75
+
76
+ if (['int', 'bigint'].includes(datatype)) {
77
+ if (datatype=='int') {
78
+ // auto-monthly dan auto-yearly hanya berlaku untuk bigint
79
+ if (['auto-yearly', 'auto-monthly'].includes(identifierMethod)) {
80
+ throw new Error(`identifier '${identifierMethod}' tidak bisa diterapkan untuk tipe data '${datatype}'`)
81
+ }
82
+ }
83
+
84
+ // if (['auto-yearly', 'auto-monthly'].includes(identifierMethod)) {
85
+ // throw new Error(`identifier '${identifierMethod}' tidak bisa diterapkan untuk tipe data '${datatype}'`)
86
+ // } else
87
+
88
+ if (identifierMethod=='auto-by-default') {
89
+ // auto increment by default apabila tidak diisi
90
+ type = `${datatype} generated by default as identity`
91
+
92
+ } else if (identifierMethod=='auto-always') {
93
+ // auto increment otomatis, tidak bisa diisi sendiri kecuali di ovveride counternya
94
+ type = `${datatype} generated always as identity`
95
+
96
+ } else {
97
+ // manual or custome
98
+ type = `${datatype} not null`
99
+ }
100
+
101
+ } else if (['char', 'varchar', 'text'].includes(datatype)) {
102
+ // manual, auto-by-default, auto-always, auto-yearly, auto-monthly, custom
103
+ if (['auto-by-default', 'auto-always'].includes(identifierMethod)) {
104
+ throw new Error(`identifier '${identifierMethod}' tidak bisa diterapkan untuk tipe data '${datatype}'`)
105
+ }
106
+
107
+ if (type=='text') {
108
+ type = `text not null`
109
+ } else {
110
+ type = `${datatype}(${length}) not null`
111
+ }
112
+ } else if(datatype=='smallint') {
113
+ if (identifierMethod=='auto-by-default') {
114
+ type = `${datatype} generated by default as identity`
115
+ } else if (identifierMethod=='auto-always') {
116
+ throw new Error(`datatype '${datatype}' tidak diperbolehkan untuk menggunakan auto-always`)
117
+ } else {
118
+ type = `${datatype} not null`
119
+ }
120
+ } else {
121
+ throw new Error(`datatype '${datatype}' currently is not supported by generator`)
122
+ }
123
+
124
+ const variables = {
125
+ schema,
126
+ tablename,
127
+ fieldname,
128
+ type,
129
+ tabledescr
130
+ }
131
+
132
+ const tplFilePath = path.join(__dirname, 'templates', 'sqlCreateTable.ejs')
133
+ const template = await fs.readFile(tplFilePath, 'utf-8');
134
+ const sql = ejs.render(template, variables)
135
+
136
+ // eksekusi create table
137
+ if (!await tableExist(schema, tablename)) {
138
+ await db.none(sql)
139
+ }
140
+
141
+
142
+ return sql
143
+ } catch (err) {
144
+ throw err
145
+ }
146
+ }
147
+
148
+
149
+
150
+ export async function createField(schema, tablename, field) {
151
+ const {fieldname, datatype, length, precision, allownull, defaultvalue, description} = field
152
+
153
+ const script = []
154
+
155
+ try {
156
+
157
+ const type = getSqlDataType(datatype, length, precision)
158
+ const sqlAdd = await sqlAddField(schema, tablename, field)
159
+ const sqlModify = await sqlModifyField(schema, tablename, field)
160
+
161
+ script.push('-- =============================================')
162
+ script.push(`-- FIELD: ${fieldname} ${type}`)
163
+ script.push('-- =============================================')
164
+ script.push(sqlAdd)
165
+ script.push(sqlModify)
166
+ script.push('')
167
+
168
+
169
+ if (await fieldExists(schema, tablename, fieldname)) {
170
+ await db.none(sqlModify)
171
+ } else {
172
+ await db.none(sqlAdd)
173
+ }
174
+
175
+ return script.join("\n")
176
+ } catch (err) {
177
+ throw err
178
+ }
179
+ }
180
+
181
+ function getSqlDataType(datatype, length, precision) {
182
+ if (['char', 'varchar'].includes(datatype)) {
183
+ return `${datatype}(${length})`
184
+ } else if (datatype=='decimal') {
185
+ return `${datatype}(${length}, ${precision})`
186
+ } else if (datatype=='timestamp') {
187
+ return 'timestamp with time zone'
188
+ } else {
189
+ return datatype
190
+ }
191
+ }
192
+
193
+ function defaultValueOf(datatype, defaultvalue, allownull) {
194
+ if (['char', 'varchar', 'text'].includes(datatype)) {
195
+ if (defaultvalue=='') {
196
+ if (allownull) {
197
+ return null
198
+ } else {
199
+ return `''`
200
+ }
201
+ } else {
202
+ return `'${defaultvalue}'`
203
+ }
204
+ } else if (['int', 'smallint', 'bigint', 'decimal'].includes(datatype)) {
205
+ if (defaultvalue=='') {
206
+ if (allownull) {
207
+ return null
208
+ } else {
209
+ return '0'
210
+ }
211
+ } else {
212
+ return defaultvalue
213
+ }
214
+ } else if (['date', 'time', 'timestamp'].includes(datatype)) {
215
+ if (defaultvalue=='') {
216
+ if (allownull) {
217
+ return null
218
+ } else {
219
+ return '(now())'
220
+ }
221
+ } else {
222
+ return defaultvalue
223
+ }
224
+ } else if (datatype=='boolean') {
225
+ if (allownull) {
226
+ return null
227
+ } else {
228
+ if (defaultvalue=='1' || defaultvalue =='true') {
229
+ return true
230
+ } else {
231
+ return false
232
+ }
233
+ }
234
+ } else {
235
+ return defaultvalue
236
+ }
237
+
238
+ }
239
+
240
+ async function sqlAddField(schema, tablename, f) {
241
+ const {fieldname, datatype, length, precision, allownull, defaultvalue, description} = f
242
+
243
+ try {
244
+
245
+ const type = getSqlDataType(datatype, length, precision)
246
+ const setnull = !allownull ? 'not null' : ''
247
+ const value = defaultValueOf(datatype, defaultvalue, allownull)
248
+ const setdefault = value!=null ? `default ${value}` : ''
249
+ const variables = {
250
+ schema,
251
+ tablename,
252
+ fieldname,
253
+ type,
254
+ setnull,
255
+ setdefault,
256
+ description
257
+ }
258
+
259
+ const tplFilePath = path.join(__dirname, 'templates', 'sqlAddField.ejs')
260
+ const template = await fs.readFile(tplFilePath, 'utf-8');
261
+ const sql = ejs.render(template, variables)
262
+ return sql
263
+ } catch (err) {
264
+ throw err
265
+ }
266
+ }
267
+
268
+ async function sqlModifyField(schema, tablename, f) {
269
+ const {fieldname, datatype, length, precision, allownull, defaultvalue, description} = f
270
+
271
+ try {
272
+ const type = getSqlDataType(datatype, length, precision)
273
+ const alternull = allownull ? `ALTER COLUMN ${fieldname} DROP NOT NULL` : `ALTER COLUMN ${fieldname} SET NOT NULL`
274
+ const value = defaultValueOf(datatype, defaultvalue, allownull)
275
+ const alterdefault = value==null ? `ALTER COLUMN ${fieldname} DROP DEFAULT` : `ALTER COLUMN ${fieldname} SET DEFAULT ${value}`
276
+ const variables = {
277
+ schema,
278
+ tablename,
279
+ fieldname,
280
+ type,
281
+ alterdefault,
282
+ alternull,
283
+ description
284
+ }
285
+
286
+ const tplFilePath = path.join(__dirname, 'templates', 'sqlModifyField.ejs')
287
+ const template = await fs.readFile(tplFilePath, 'utf-8');
288
+ const sql = ejs.render(template, variables)
289
+ return sql
290
+ } catch (err) {
291
+ throw err
292
+ }
293
+ }
294
+
295
+ export async function createUniqueIndex(schema, tablename, uniques) {
296
+ const script = []
297
+
298
+ script.push('-- =============================================')
299
+ script.push(`-- UNIQUE INDEX`)
300
+ script.push('-- =============================================')
301
+
302
+
303
+ try {
304
+
305
+ // Hapus semua existing unique index
306
+ const sqlGetIniques = `
307
+ SELECT constraint_name
308
+ FROM information_schema.table_constraints
309
+ WHERE constraint_type = 'UNIQUE'
310
+ AND table_schema = \${schema}
311
+ AND table_name = \${tablename};
312
+ `
313
+ const existingUniques = await db.any(sqlGetIniques, {schema:schema, tablename:tablename});
314
+ if (existingUniques.length>0) {
315
+ const variables = {
316
+ schema,
317
+ tablename,
318
+ existingUniques
319
+ }
320
+ const tplFilePath = path.join(__dirname, 'templates', 'sqlDropUniqueIndex.ejs')
321
+ const template = await fs.readFile(tplFilePath, 'utf-8');
322
+ const sqlDropUnique = ejs.render(template, variables)
323
+
324
+ await db.none(sqlDropUnique)
325
+
326
+ script.push(sqlDropUnique)
327
+ }
328
+
329
+
330
+
331
+ // Tambahkan Unique Index
332
+ const data = []
333
+ for (let uniqName in uniques) {
334
+ let uniq = uniques[uniqName]
335
+ data.push({
336
+ uniquename: `uq$${schema}$${tablename}$${uniq.name}`,
337
+ uniquefields:uniq.fields})
338
+ }
339
+
340
+ if (data.length>0) {
341
+ const variables = {
342
+ schema,
343
+ tablename,
344
+ data
345
+ }
346
+ const tplFilePath = path.join(__dirname, 'templates', 'sqlAddUniqueIndex.ejs')
347
+ const template = await fs.readFile(tplFilePath, 'utf-8');
348
+ const sqlAddUnique = ejs.render(template, variables)
349
+
350
+ await db.none(sqlAddUnique)
351
+
352
+ script.push(sqlAddUnique)
353
+ }
354
+
355
+
356
+ return script.join("\n")
357
+ } catch (err) {
358
+ throw err
359
+ }
360
+ }
361
+
362
+
363
+ export async function createFereignKey(schema, tablename, foreignKeys) {
364
+ // const {fk_name, fk_table, fk_field} = reference
365
+
366
+ const script = []
367
+
368
+ script.push('-- =============================================')
369
+ script.push(`-- FOREIGN KEY CONSTRAINT`)
370
+ script.push('-- =============================================')
371
+
372
+
373
+ try {
374
+ // Drop dulu referensi yang ada
375
+ {
376
+ const sqlGetFk = `
377
+ SELECT constraint_name
378
+ FROM information_schema.table_constraints
379
+ WHERE constraint_type = 'FOREIGN KEY'
380
+ AND table_schema = \${schema}
381
+ AND table_name = \${tablename}
382
+ `
383
+ const existingFk = await db.any(sqlGetFk, {schema, tablename});
384
+ if (existingFk.length>0) {
385
+ const variables = {
386
+ schema,
387
+ tablename,
388
+ existingFk
389
+ }
390
+ const tplFilePath = path.join(__dirname, 'templates', 'sqlDropForeignKey.ejs')
391
+ const template = await fs.readFile(tplFilePath, 'utf-8');
392
+ const sqlDropForeignKey = ejs.render(template, variables)
393
+
394
+ await db.none(sqlDropForeignKey)
395
+ script.push(sqlDropForeignKey)
396
+ }
397
+ }
398
+
399
+
400
+ // Tambahkan kembali foreign key
401
+ {
402
+ const fkList = []
403
+ for (var fieldname in foreignKeys) {
404
+ const field = foreignKeys[fieldname]
405
+ const {data_fieldname, Reference} = field
406
+ const ref_name = `fk$${schema}$${tablename}$${data_fieldname}`
407
+
408
+
409
+ {
410
+ const {schema, tablename} = parseTableName(Reference.table)
411
+ Reference.ref_schema = schema
412
+ Reference.ref_tablename = tablename
413
+ }
414
+
415
+ fkList.push({
416
+ fieldname: data_fieldname,
417
+ ref_name: ref_name,
418
+ ref_schema: Reference.ref_schema,
419
+ ref_tablename: Reference.ref_tablename,
420
+ ref_fieldname: Reference.bindingValue
421
+ })
422
+
423
+ }
424
+
425
+ const variables = {
426
+ schema,
427
+ tablename,
428
+ fkList
429
+ }
430
+
431
+ const tplFilePath = path.join(__dirname, 'templates', 'sqlAddForeignKey.ejs')
432
+ const template = await fs.readFile(tplFilePath, 'utf-8');
433
+ const sqlAddForeignKey = ejs.render(template, variables)
434
+
435
+ await db.none(sqlAddForeignKey)
436
+ script.push(sqlAddForeignKey)
437
+ }
438
+
439
+ return script.join("\n")
440
+ } catch (err) {
441
+ throw err
442
+ }
443
+ }
444
+
445
+
446
+
447
+ /*
448
+
449
+ 2509010000000000001
450
+ 9223372036854775807
451
+
452
+ company code: 01: TFI, 02: Metro
453
+ --
454
+ JV01.2501.000000
455
+ JV02.2501.000000
456
+
457
+
458
+ header sequencer
459
+ 2501 00 000 00 00000000
460
+ ---- -- --- -- --------
461
+ monthly
462
+ doc
463
+ block
464
+ cluster
465
+ runnning number
466
+
467
+
468
+ detil sequencer
469
+ 2501 000,000,000,000,000
470
+ montyly
471
+ running number
472
+
473
+ */
474
+
475
+