@agung_dhewe/webapps 1.1.2 → 1.2.4
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/fgta5js-dist/fgta5js-v1.8.5.min.js +11 -0
- package/lib/fgta5js-dist/fgta5js-v1.8.5.min.js.map +1 -0
- package/{libs → lib}/webmodule/module-edit.css +73 -18
- package/{libs → lib}/webmodule/module-list.css +13 -0
- package/lib/webmodule/module-print.css +28 -0
- package/{libs → lib}/webmodule/module.css +13 -6
- package/{libs → lib}/webmodule/module.js +14 -4
- package/lib/webmodule/pagehelper.mjs +129 -0
- package/modules/generator/appgen-io.mjs +153 -76
- package/modules/generator/appgen-ui.mjs +234 -167
- package/modules/generator/generator-designtemplate-def.html +38 -0
- package/modules/generator/generator-designtemplate.html +11 -1492
- package/modules/generator/generator.css +103 -65
- package/modules/generator/generator.mjs +1 -1
- package/modules/generator/generator.svg +98 -0
- package/modules/generator/generatorEdit.mjs +43 -35
- package/modules/generator/generatorList.mjs +27 -0
- package/modules/generator/tpl-designerinfo.html +100 -0
- package/modules/generator/tpl-field-checkbox.html +200 -0
- package/modules/generator/tpl-field-combobox.html +228 -0
- package/modules/generator/tpl-field-datepicker.html +192 -0
- package/modules/generator/tpl-field-filebox.html +189 -0
- package/modules/generator/tpl-field-numberbox.html +218 -0
- package/modules/generator/tpl-field-textbox.html +255 -0
- package/modules/generator/tpl-field-timepicker.html +192 -0
- package/modules/generator/tpl-searchdesign.html +32 -0
- package/modules/generator/tpl-uniquedesign.html +25 -0
- package/modules/login/login.css +10 -2
- package/package.json +5 -3
- package/percobaan/coba-sequencer.js +16 -0
- package/src/api.js +12 -9
- package/src/apis/generator.api.js +35 -23
- package/src/apis/login.api.js +1 -0
- package/src/context.js +12 -2
- package/src/db.js +58 -32
- package/src/generator/createApiModule.js +4 -1
- package/src/generator/createIcon.js +24 -2
- package/src/generator/createLayoutCss.js +107 -0
- package/src/generator/createModuleDetilEditHtml.js +12 -1
- package/src/generator/createModuleDetilEditMjs.js +32 -28
- package/src/generator/createModuleDetilListHtml.js +14 -7
- package/src/generator/createModuleDetilListMjs.js +13 -1
- package/src/generator/createModuleHeaderEditHtml.js +13 -1
- package/src/generator/createModuleHeaderEditMjs.js +23 -2
- package/src/generator/createProgramData.js +3 -2
- package/src/generator/createTable.js +42 -38
- package/src/generator/helper.js +45 -27
- package/src/generator/templates/__rollup-module copy.ejs +90 -0
- package/src/generator/templates/__rollup-module.ejs +102 -31
- package/src/generator/templates/api-module.js.ejs +171 -32
- package/src/generator/templates/layout.css.ejs +24 -0
- package/src/generator/templates/module-ext.html.ejs +1 -1
- package/src/generator/templates/module-ext.mjs.ejs +19 -1
- package/src/generator/templates/module.ejs.ejs +8 -0
- package/src/generator/templates/module.mjs.ejs +42 -5
- package/src/generator/templates/moduleDetilEdit.html.ejs +11 -0
- package/src/generator/templates/moduleDetilEdit.mjs.ejs +135 -30
- package/src/generator/templates/moduleDetilList.html.ejs +2 -1
- package/src/generator/templates/moduleDetilList.mjs.ejs +86 -11
- package/src/generator/templates/moduleHeaderEdit.html.ejs +8 -1
- package/src/generator/templates/moduleHeaderEdit.mjs.ejs +123 -36
- package/src/generator/templates/moduleHeaderList.html.ejs +5 -1
- package/src/generator/templates/moduleHeaderList.mjs.ejs +47 -15
- package/src/generator/trygenerate.js +18 -2
- package/src/generator/worker.js +83 -72
- package/src/helper.js +12 -13
- package/src/logger.js +12 -12
- package/src/notifier.js +29 -0
- package/src/routers/generatorApi.js +9 -3
- package/src/routers/generatorPage.js +3 -1
- package/src/routers/moduleApi.js +1 -1
- package/src/routers/modulePage.js +42 -7
- package/src/sequencerdoc.js +22 -46
- package/src/sequencerline.js +16 -4
- package/src/session.js +69 -33
- package/src/startup.js +47 -10
- package/src/webapps.js +62 -18
- package/templates/_lib_debug.ejs +8 -8
- package/templates/_lib_production.ejs +2 -2
- package/templates/application.page.ejs +43 -8
- package/templates/generator.page.ejs +4 -3
- package/templates/index.page.ejs +2 -2
- package/templates/login.page.ejs +3 -3
- package/libs/fgta5js-dist/fgta5js-v1.8.3.min.js +0 -11
- package/libs/fgta5js-dist/fgta5js-v1.8.3.min.js.map +0 -1
- package/libs/webmodule/pagehelper.mjs +0 -45
- package/modules/generator/generator.png +0 -0
- /package/{libs/fgta5js-dist/fgta5js-v1.8.3.min.css → lib/fgta5js-dist/fgta5js-v1.8.5.min.css} +0 -0
- /package/{libs → lib}/fgta5js-dist/fonts/karla-italic-latin-ext.woff2 +0 -0
- /package/{libs → lib}/fgta5js-dist/fonts/karla-italic-latin.woff2 +0 -0
- /package/{libs → lib}/fgta5js-dist/fonts/karla-normal-latin-ext.woff2 +0 -0
- /package/{libs → lib}/fgta5js-dist/fonts/karla-normal-latin.woff2 +0 -0
- /package/{libs → lib}/fgta5js-dist/fonts/karla.css +0 -0
- /package/{libs → lib}/webmodule/module-footer.css +0 -0
package/src/generator/worker.js
CHANGED
|
@@ -29,19 +29,22 @@ import { createInfoLogs } from './createInfoLogs.js';
|
|
|
29
29
|
import { createInfoRecordExtender } from './createInfoRecordExtender.js';
|
|
30
30
|
import { createIcon } from './createIcon.js'
|
|
31
31
|
import { createProgramData } from './createProgramData.js'
|
|
32
|
+
import { createLayoutCss } from './createLayoutCss.js';
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
|
|
35
|
-
const { generator_id, user_id, user_name, ipaddress, jeda } = workerData;
|
|
36
|
+
const { generator_id, user_id, user_name, ipaddress, ModuleDbContract, jeda } = workerData;
|
|
36
37
|
|
|
37
38
|
|
|
38
39
|
main(generator_id)
|
|
39
40
|
|
|
40
41
|
|
|
41
42
|
async function main(id) {
|
|
43
|
+
const tablename = ModuleDbContract.generator.table
|
|
44
|
+
|
|
42
45
|
try {
|
|
43
|
-
const queryParams = {generator_id: id}
|
|
44
|
-
const sql =
|
|
46
|
+
const queryParams = { generator_id: id }
|
|
47
|
+
const sql = `select generator_data from ${tablename} where generator_id = \${generator_id}`
|
|
45
48
|
const data = await db.one(sql, queryParams);
|
|
46
49
|
|
|
47
50
|
|
|
@@ -50,8 +53,8 @@ async function main(id) {
|
|
|
50
53
|
|
|
51
54
|
|
|
52
55
|
await generate(id, data.generator_data)
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
|
|
57
|
+
|
|
55
58
|
} catch (err) {
|
|
56
59
|
err.message = `Generator Worker: ${err.message}`
|
|
57
60
|
throw err
|
|
@@ -59,14 +62,14 @@ async function main(id) {
|
|
|
59
62
|
}
|
|
60
63
|
|
|
61
64
|
async function sleep(s) {
|
|
62
|
-
if (s==0) {
|
|
65
|
+
if (s == 0) {
|
|
63
66
|
return
|
|
64
67
|
}
|
|
65
68
|
|
|
66
|
-
return new Promise(lanjut=>{
|
|
67
|
-
setTimeout(()=>{
|
|
69
|
+
return new Promise(lanjut => {
|
|
70
|
+
setTimeout(() => {
|
|
68
71
|
lanjut()
|
|
69
|
-
}, s*1000)
|
|
72
|
+
}, s * 1000)
|
|
70
73
|
})
|
|
71
74
|
}
|
|
72
75
|
|
|
@@ -87,9 +90,9 @@ async function generate(id, data) {
|
|
|
87
90
|
|
|
88
91
|
|
|
89
92
|
const context = {
|
|
90
|
-
id:id,
|
|
93
|
+
id: id,
|
|
91
94
|
user_id: user_id,
|
|
92
|
-
user_name: user_name,
|
|
95
|
+
user_name: user_name,
|
|
93
96
|
ipaddress: ipaddress,
|
|
94
97
|
title: data.title,
|
|
95
98
|
descr: data.description,
|
|
@@ -97,6 +100,7 @@ async function generate(id, data) {
|
|
|
97
100
|
appname: data.appname,
|
|
98
101
|
moduleName: data.name,
|
|
99
102
|
entities: data.entities,
|
|
103
|
+
actions: data.actions,
|
|
100
104
|
icon: data.icon,
|
|
101
105
|
timeGenerated: formattedTime,
|
|
102
106
|
postMessage: (info) => {
|
|
@@ -115,7 +119,7 @@ async function generate(id, data) {
|
|
|
115
119
|
const headerItems = entityHeader.Items
|
|
116
120
|
for (var entityName in context.entities) {
|
|
117
121
|
// tambahkan jika bukan header
|
|
118
|
-
if (entityName!='header') {
|
|
122
|
+
if (entityName != 'header') {
|
|
119
123
|
const headerPK = structuredClone(headerItems[headerPkFieldName])
|
|
120
124
|
headerPK.Reference.pk = entityHeader.pk
|
|
121
125
|
headerPK.Reference.table = entityHeader.table
|
|
@@ -132,98 +136,103 @@ async function generate(id, data) {
|
|
|
132
136
|
// process.exit(0)
|
|
133
137
|
|
|
134
138
|
|
|
135
|
-
await prepareDirectory(context, {overwrite:true})
|
|
139
|
+
await prepareDirectory(context, { overwrite: true })
|
|
136
140
|
await sleep(jedaWaktu)
|
|
137
141
|
|
|
138
142
|
|
|
139
|
-
|
|
140
|
-
const iconFileName = await createIcon(context, {overwrite:true})
|
|
141
143
|
|
|
142
|
-
await
|
|
143
|
-
|
|
144
|
-
await
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
await createApiModule(context, {overwrite:true})
|
|
144
|
+
const iconFileName = await createIcon(context, { overwrite: true })
|
|
145
|
+
|
|
146
|
+
await createProgramData(context, { iconFileName })
|
|
147
|
+
|
|
148
|
+
await createTable(context, { overwrite: true })
|
|
148
149
|
await sleep(jedaWaktu)
|
|
149
150
|
|
|
150
151
|
|
|
151
|
-
|
|
152
|
-
await createModuleRollup(context, {overwrite:true})
|
|
152
|
+
|
|
153
|
+
await createModuleRollup(context, { overwrite: true })
|
|
153
154
|
await sleep(jedaWaktu)
|
|
154
155
|
|
|
155
|
-
await createModuleContext(context, {overwrite:true})
|
|
156
|
+
await createModuleContext(context, { overwrite: true })
|
|
156
157
|
await sleep(jedaWaktu)
|
|
157
158
|
|
|
158
|
-
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
|
|
161
|
+
await createModuleEjs(context, { overwrite: true })
|
|
161
162
|
await sleep(jedaWaktu)
|
|
162
163
|
|
|
163
|
-
|
|
164
|
-
await createModuleMjs(context, {overwrite:true, iconFileName})
|
|
164
|
+
|
|
165
|
+
await createModuleMjs(context, { overwrite: true, iconFileName })
|
|
165
166
|
await sleep(jedaWaktu)
|
|
166
167
|
|
|
167
168
|
|
|
168
169
|
|
|
169
170
|
// Header
|
|
170
|
-
await createModuleHeaderListHtml(context, {overwrite:true})
|
|
171
|
+
await createModuleHeaderListHtml(context, { overwrite: true })
|
|
171
172
|
await sleep(jedaWaktu)
|
|
172
|
-
|
|
173
173
|
|
|
174
|
-
|
|
174
|
+
|
|
175
|
+
await createModuleHeaderListMjs(context, { overwrite: true })
|
|
175
176
|
await sleep(jedaWaktu)
|
|
176
177
|
|
|
177
|
-
|
|
178
|
-
await createModuleHeaderEditHtml(context,
|
|
178
|
+
|
|
179
|
+
await createModuleHeaderEditHtml(context, { overwrite: true })
|
|
179
180
|
await sleep(jedaWaktu)
|
|
180
181
|
|
|
181
|
-
|
|
182
|
-
await createModuleHeaderEditMjs(context, {overwrite:true})
|
|
182
|
+
|
|
183
|
+
await createModuleHeaderEditMjs(context, { overwrite: true })
|
|
183
184
|
await sleep(jedaWaktu)
|
|
184
|
-
|
|
185
185
|
|
|
186
|
-
|
|
186
|
+
|
|
187
|
+
|
|
187
188
|
// Detils
|
|
188
|
-
await createModuleDetilListHtml(context, {overwrite:true})
|
|
189
|
+
await createModuleDetilListHtml(context, { overwrite: true })
|
|
189
190
|
await sleep(jedaWaktu)
|
|
190
191
|
|
|
191
|
-
await createModuleDetilListMjs(context, {overwrite:true})
|
|
192
|
+
await createModuleDetilListMjs(context, { overwrite: true })
|
|
192
193
|
await sleep(jedaWaktu)
|
|
193
194
|
|
|
194
195
|
|
|
195
|
-
await createModuleDetilEditHtml(context, {overwrite:true})
|
|
196
|
+
await createModuleDetilEditHtml(context, { overwrite: true })
|
|
196
197
|
await sleep(jedaWaktu)
|
|
197
|
-
|
|
198
|
-
await createModuleDetilEditMjs(context, {overwrite:true})
|
|
198
|
+
|
|
199
|
+
await createModuleDetilEditMjs(context, { overwrite: true })
|
|
199
200
|
await sleep(jedaWaktu)
|
|
200
|
-
|
|
201
201
|
|
|
202
|
-
|
|
202
|
+
|
|
203
|
+
await createInfoLogs(context, { overwrite: true })
|
|
203
204
|
await sleep(jedaWaktu)
|
|
204
205
|
|
|
205
206
|
|
|
206
207
|
// Extender
|
|
207
|
-
await
|
|
208
|
+
await createModuleExtenderHtml(context, { overwrite: false })
|
|
208
209
|
await sleep(jedaWaktu)
|
|
209
210
|
|
|
210
|
-
await
|
|
211
|
+
await createModuleExtenderMjs(context, { overwrite: false })
|
|
211
212
|
await sleep(jedaWaktu)
|
|
212
213
|
|
|
213
|
-
await
|
|
214
|
+
await createInfoAboutExtender(context, { overwrite: false })
|
|
214
215
|
await sleep(jedaWaktu)
|
|
215
216
|
|
|
216
|
-
await
|
|
217
|
+
await createInfoRecordExtender(context, { overwrite: false })
|
|
217
218
|
await sleep(jedaWaktu)
|
|
218
219
|
|
|
219
|
-
|
|
220
|
+
|
|
221
|
+
// Layout CSS
|
|
222
|
+
await createLayoutCss(context, { overwrite: true })
|
|
220
223
|
await sleep(jedaWaktu)
|
|
221
|
-
|
|
222
|
-
|
|
223
224
|
|
|
224
225
|
|
|
226
|
+
// Api
|
|
227
|
+
|
|
228
|
+
await createApiExtenderModule(context, { overwrite: false })
|
|
229
|
+
await createApiModule(context, { overwrite: true })
|
|
230
|
+
|
|
231
|
+
context.postMessage({ message: `restarting service` })
|
|
232
|
+
await sleep(1)
|
|
233
|
+
|
|
225
234
|
// Selesai
|
|
226
|
-
context.postMessage({message: `finish`, done:true})
|
|
235
|
+
context.postMessage({ message: `finish`, done: true })
|
|
227
236
|
} catch (err) {
|
|
228
237
|
throw err
|
|
229
238
|
}
|
|
@@ -237,7 +246,7 @@ async function prepareDirectory(context) {
|
|
|
237
246
|
|
|
238
247
|
try {
|
|
239
248
|
|
|
240
|
-
context.postMessage({message: `preparing directory`})
|
|
249
|
+
context.postMessage({ message: `preparing directory` })
|
|
241
250
|
// await sleep(1)
|
|
242
251
|
|
|
243
252
|
// cek jika directory project exists
|
|
@@ -250,20 +259,20 @@ async function prepareDirectory(context) {
|
|
|
250
259
|
const apiDir = path.join(directory, 'src', 'apis')
|
|
251
260
|
const apiExtenderDir = path.join(apiDir, 'extenders')
|
|
252
261
|
|
|
253
|
-
const moduleDirExists =
|
|
262
|
+
const moduleDirExists = await directoryExists(moduleDir)
|
|
254
263
|
if (!moduleDirExists) {
|
|
255
264
|
// direktori modul tidak ditemukan, buat dulu
|
|
256
|
-
context.postMessage({message: `creating new directory: '${moduleDir}`})
|
|
265
|
+
context.postMessage({ message: `creating new directory: '${moduleDir}` })
|
|
257
266
|
await mkdir(moduleDir, {});
|
|
258
267
|
// await sleep(1)
|
|
259
268
|
}
|
|
260
269
|
|
|
261
|
-
const apiDirExists =
|
|
270
|
+
const apiDirExists = await directoryExists(apiDir)
|
|
262
271
|
if (!apiDirExists) {
|
|
263
272
|
throw new Error(`directory tujuan '${apiDir}' tidak ditemukan`)
|
|
264
273
|
}
|
|
265
274
|
|
|
266
|
-
const apiExtenderDirExists =
|
|
275
|
+
const apiExtenderDirExists = await directoryExists(apiExtenderDir)
|
|
267
276
|
if (!apiExtenderDirExists) {
|
|
268
277
|
throw new Error(`directory tujuan '${apiExtenderDir}' tidak ditemukan`)
|
|
269
278
|
}
|
|
@@ -276,7 +285,7 @@ async function prepareDirectory(context) {
|
|
|
276
285
|
console.log("\n\n\x1b[1m\x1b[31mERROR\x1b[0m")
|
|
277
286
|
console.log('Module sudah di lock, tidak bisa digenerate ulang')
|
|
278
287
|
process.exit(1)
|
|
279
|
-
}
|
|
288
|
+
}
|
|
280
289
|
|
|
281
290
|
|
|
282
291
|
context.moduleDir = moduleDir
|
|
@@ -312,7 +321,7 @@ async function checkEntitiy(context) {
|
|
|
312
321
|
|
|
313
322
|
|
|
314
323
|
// cek appname
|
|
315
|
-
if (apps[context.appname]==null) {
|
|
324
|
+
if (apps[context.appname] == null) {
|
|
316
325
|
throw new Error(`App Name: '${context.appname}' tidak valid. Cek di data apps`)
|
|
317
326
|
}
|
|
318
327
|
|
|
@@ -324,15 +333,15 @@ async function checkEntitiy(context) {
|
|
|
324
333
|
const entity_table = entity.table
|
|
325
334
|
const entity_pk = entity.pk
|
|
326
335
|
const Items = entity.Items
|
|
327
|
-
|
|
328
|
-
let pkExists = false
|
|
336
|
+
|
|
337
|
+
let pkExists = false
|
|
329
338
|
|
|
330
339
|
for (let fieldName in Items) {
|
|
331
340
|
const item = Items[fieldName]
|
|
332
341
|
const component = item.component
|
|
333
342
|
|
|
334
343
|
// Cek Primary Key
|
|
335
|
-
if (fieldName==entity_pk) {
|
|
344
|
+
if (fieldName == entity_pk) {
|
|
336
345
|
pkExists = true
|
|
337
346
|
if (!item.showInForm) {
|
|
338
347
|
throw new Error(`Primary key '${fieldName}' pada entity '${entityName}' harus di embed di form. Apabila ingin menyembunyakannya, gunakan 'hidden' di Container CSS `)
|
|
@@ -340,7 +349,7 @@ async function checkEntitiy(context) {
|
|
|
340
349
|
}
|
|
341
350
|
|
|
342
351
|
// Cek combobox
|
|
343
|
-
if (component=='Combobox') {
|
|
352
|
+
if (component == 'Combobox') {
|
|
344
353
|
// cek apakah konfig udah bener
|
|
345
354
|
const reference = item.Reference
|
|
346
355
|
const table = reference.table.trim()
|
|
@@ -350,31 +359,33 @@ async function checkEntitiy(context) {
|
|
|
350
359
|
const loaderApiModule = reference.loaderApiModule.trim()
|
|
351
360
|
const loaderApiPath = reference.loaderApiPath.trim()
|
|
352
361
|
|
|
353
|
-
if(table=='') {
|
|
362
|
+
if (table == '') {
|
|
354
363
|
throw new Error(`table reference Combobox '${fieldName}' di entity '${entityName}' tidak boleh kosong`)
|
|
355
364
|
}
|
|
356
365
|
|
|
357
|
-
if(pk=='') {
|
|
366
|
+
if (pk == '') {
|
|
358
367
|
throw new Error(`PK untuk table reference Combobox '${fieldName}' di entity '${entityName}' tidak boleh kosong`)
|
|
359
368
|
}
|
|
360
|
-
|
|
361
|
-
if(bindingValue=='') {
|
|
369
|
+
|
|
370
|
+
if (bindingValue == '') {
|
|
362
371
|
throw new Error(`binding value untuk table reference Combobox '${fieldName}' di entity '${entityName}' tidak boleh kosong`)
|
|
363
372
|
}
|
|
364
373
|
|
|
365
|
-
if(bindingText=='') {
|
|
374
|
+
if (bindingText == '') {
|
|
366
375
|
throw new Error(`binding value untuk table reference Combobox '${fieldName}' di entity '${entityName}' tidak boleh kosong`)
|
|
367
376
|
}
|
|
368
377
|
|
|
369
|
-
if(loaderApiModule=='') {
|
|
378
|
+
if (loaderApiModule == '') {
|
|
370
379
|
throw new Error(`loader API Name untuk table reference Combobox '${fieldName}' di entity '${entityName}' tidak boleh kosong`)
|
|
371
380
|
}
|
|
372
381
|
|
|
373
|
-
if (apps[loaderApiModule]==null) {
|
|
374
|
-
|
|
382
|
+
if (apps[loaderApiModule] == null) {
|
|
383
|
+
if (loaderApiModule != '/') {
|
|
384
|
+
throw new Error(`loader API Name: '${loaderApiModule}' untuk table reference Combobox '${fieldName}' di entity '${entityName}' tidak valid. Cek di data apps`)
|
|
385
|
+
}
|
|
375
386
|
}
|
|
376
387
|
|
|
377
|
-
if(loaderApiPath=='') {
|
|
388
|
+
if (loaderApiPath == '') {
|
|
378
389
|
throw new Error(`loader API path untuk table reference Combobox '${fieldName}' di entity '${entityName}' tidak boleh kosong`)
|
|
379
390
|
}
|
|
380
391
|
}
|
package/src/helper.js
CHANGED
|
@@ -6,21 +6,20 @@ import context from './context.js'
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
export function kebabToCamel(str) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
return str
|
|
10
|
+
.split('-')
|
|
11
|
+
.map((part, index) =>
|
|
12
|
+
index === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1)
|
|
13
|
+
)
|
|
14
|
+
.join('');
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
export async function importApiModule(modulename, options={}) {
|
|
18
|
+
export async function importApiModule(modulename, options = {}) {
|
|
19
19
|
// jika mode debug,
|
|
20
20
|
// load api akan selalu dilakukan saat request (tanpa caching)
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
const cached = options.cached===true ? true : false
|
|
22
|
+
const cached = context.isApiCached()
|
|
24
23
|
const apiDir = options.apiDir || path.join('.', 'apis')
|
|
25
24
|
const apiPath = path.join(apiDir, `${modulename}.api.js`)
|
|
26
25
|
|
|
@@ -32,11 +31,11 @@ export async function importApiModule(modulename, options={}) {
|
|
|
32
31
|
const freshUrl = `${fullPath}?v=${mtime}`;
|
|
33
32
|
const module = await import(freshUrl);
|
|
34
33
|
|
|
35
|
-
if (module.default===undefined) {
|
|
34
|
+
if (module.default === undefined) {
|
|
36
35
|
throw new Error(`modul api '${modulename}' tidak mempunyai default class untuk import`)
|
|
37
36
|
}
|
|
38
37
|
|
|
39
|
-
return module.default;
|
|
38
|
+
return module.default;
|
|
40
39
|
}
|
|
41
40
|
}
|
|
42
41
|
|
|
@@ -52,8 +51,8 @@ export async function isFileExists(filepath) {
|
|
|
52
51
|
}
|
|
53
52
|
}
|
|
54
53
|
|
|
55
|
-
export async function parseTemplate(tplFilePath, variables={}) {
|
|
56
|
-
const template =
|
|
54
|
+
export async function parseTemplate(tplFilePath, variables = {}) {
|
|
55
|
+
const template = await fs.readFile(tplFilePath, 'utf-8');
|
|
57
56
|
const content = ejs.render(template, variables)
|
|
58
57
|
return content
|
|
59
58
|
}
|
package/src/logger.js
CHANGED
|
@@ -6,25 +6,25 @@ export default new (class {
|
|
|
6
6
|
console.log('logger access', modulename, url, errormessage)
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
async log(logdata) {
|
|
11
|
-
const { id, user_id, user_name, moduleName, action, tablename, executionTimeMs, remark, metadata, ipaddress=''} = logdata
|
|
12
|
-
const sql = `insert into datalog
|
|
11
|
+
const { id, user_id, user_name, moduleName, action, tablename, executionTimeMs, remark, metadata, ipaddress = '' } = logdata
|
|
12
|
+
const sql = `insert into log."datalog"
|
|
13
13
|
(log_time, log_user_id, log_user_name, log_action, log_ipaddress, log_module, log_table, log_doc_id, log_remark, log_executiontime, log_metadata)
|
|
14
14
|
values
|
|
15
15
|
(now(), \${log_user_id}, \${log_user_name}, \${log_action}, \${log_ipaddress}, \${log_module}, \${log_table}, \${log_doc_id}, \${log_remark}, \${log_executiontime}, \${log_metadata})
|
|
16
16
|
RETURNING log_time
|
|
17
17
|
`
|
|
18
18
|
const variable = {
|
|
19
|
-
log_user_id: user_id,
|
|
20
|
-
log_user_name: user_name,
|
|
21
|
-
log_action: action,
|
|
22
|
-
log_ipaddress: ipaddress,
|
|
23
|
-
log_module: moduleName,
|
|
24
|
-
log_table: tablename,
|
|
25
|
-
log_doc_id: id,
|
|
26
|
-
log_remark: remark,
|
|
27
|
-
log_executiontime: executionTimeMs,
|
|
19
|
+
log_user_id: user_id,
|
|
20
|
+
log_user_name: user_name,
|
|
21
|
+
log_action: action,
|
|
22
|
+
log_ipaddress: ipaddress,
|
|
23
|
+
log_module: moduleName,
|
|
24
|
+
log_table: tablename,
|
|
25
|
+
log_doc_id: id,
|
|
26
|
+
log_remark: remark,
|
|
27
|
+
log_executiontime: executionTimeMs,
|
|
28
28
|
log_metadata: metadata
|
|
29
29
|
}
|
|
30
30
|
|
package/src/notifier.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export default async function notifyClient(notifierServer, clientId, status, info) {
|
|
4
|
+
try {
|
|
5
|
+
|
|
6
|
+
const method = 'POST'
|
|
7
|
+
const data = { clientId, status, info }
|
|
8
|
+
const url = `${notifierServer}/notify`
|
|
9
|
+
const response = await fetch(url, {
|
|
10
|
+
method: method,
|
|
11
|
+
headers: {
|
|
12
|
+
'Content-Type': 'application/json',
|
|
13
|
+
},
|
|
14
|
+
body: JSON.stringify(data)
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
if (!response.ok) {
|
|
18
|
+
const httpErrorStatus = response.status
|
|
19
|
+
const httpErrorStatustext = response.statusText
|
|
20
|
+
const err = new Error(`${httpErrorStatus} ${httpErrorStatustext}: ${method} ${url}`)
|
|
21
|
+
err.code = httpErrorStatus
|
|
22
|
+
throw err
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return response
|
|
26
|
+
} catch (err) {
|
|
27
|
+
throw err
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -1,16 +1,22 @@
|
|
|
1
|
+
import context from './../context.js'
|
|
1
2
|
import * as helper from './../helper.js'
|
|
2
3
|
import { handleError } from './handleError.js'
|
|
4
|
+
import * as path from 'path'
|
|
5
|
+
|
|
3
6
|
|
|
4
7
|
export async function generatorApi(req, res, next) {
|
|
5
8
|
// res.status(200).send(`{"code":"1", "message":"api not implemented"}`)
|
|
6
9
|
const moduleName = 'generator'
|
|
7
10
|
const methodName = req.params.method
|
|
8
|
-
|
|
11
|
+
const options = {
|
|
12
|
+
apiDir: path.join(context.getWebappsDirectory(), 'src', 'apis')
|
|
13
|
+
}
|
|
14
|
+
|
|
9
15
|
try {
|
|
10
16
|
|
|
11
|
-
const ModuleClass = await helper.importApiModule(moduleName)
|
|
17
|
+
const ModuleClass = await helper.importApiModule(moduleName, options)
|
|
12
18
|
const method = helper.kebabToCamel(methodName);
|
|
13
|
-
if (ModuleClass===undefined) {
|
|
19
|
+
if (ModuleClass === undefined) {
|
|
14
20
|
throw new Error(`invalid module: '${moduleName}'`)
|
|
15
21
|
}
|
|
16
22
|
|
|
@@ -13,6 +13,7 @@ export async function generatorPage(req, res, next) {
|
|
|
13
13
|
const generatorListPath = path.join(__dirname, 'modules', 'generator', 'generatorList.html')
|
|
14
14
|
const generatorEditPath = path.join(__dirname, 'modules', 'generator', 'generatorEdit.html')
|
|
15
15
|
const generatorDesignPath = path.join(__dirname, 'modules', 'generator', 'generator-designtemplate.html')
|
|
16
|
+
const generatorModulePath = path.join(__dirname, 'modules', 'generator')
|
|
16
17
|
|
|
17
18
|
// load halaman html-nya
|
|
18
19
|
const variables = {
|
|
@@ -20,7 +21,8 @@ export async function generatorPage(req, res, next) {
|
|
|
20
21
|
...{
|
|
21
22
|
generatorListPath,
|
|
22
23
|
generatorEditPath,
|
|
23
|
-
generatorDesignPath
|
|
24
|
+
generatorDesignPath,
|
|
25
|
+
generatorModulePath
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
28
|
|
package/src/routers/moduleApi.js
CHANGED
|
@@ -15,7 +15,7 @@ export async function moduleApi(req, res, next) {
|
|
|
15
15
|
|
|
16
16
|
const ModuleClass = await helper.importApiModule(moduleName, options)
|
|
17
17
|
const method = helper.kebabToCamel(methodName);
|
|
18
|
-
if (ModuleClass===undefined) {
|
|
18
|
+
if (ModuleClass === undefined) {
|
|
19
19
|
throw new Error(`invalid module: '${moduleName}'`)
|
|
20
20
|
}
|
|
21
21
|
|
|
@@ -24,25 +24,39 @@ export async function modulePage(req, res) {
|
|
|
24
24
|
const moduleDir = path.join(__rootDir, 'public', 'modules', moduleName)
|
|
25
25
|
const ejsPath = path.join(__rootDir, 'public', 'modules', moduleName, `${moduleName}.ejs`)
|
|
26
26
|
const cssPath = path.join(__rootDir, 'public', 'modules', moduleName, `${moduleName}.css`);
|
|
27
|
+
const cssLayoutPath = path.join(__rootDir, 'public', 'modules', moduleName, `${moduleName}.layout.css`);
|
|
28
|
+
const cssApplicationPath = path.join(__rootDir, 'public', 'local', 'application.css');
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
const variance = req.query.variance;
|
|
32
|
+
const id = req.query.id;
|
|
27
33
|
|
|
28
34
|
|
|
29
35
|
// const mjsFileName = appDebugMode ? `${moduleName}.mjs` : `${moduleName}.min.mjs`
|
|
36
|
+
let useCssBundle
|
|
37
|
+
let cssBundleFileName
|
|
30
38
|
let mjsFileName
|
|
31
39
|
if (appDebugMode) {
|
|
32
40
|
// Default Debug
|
|
33
|
-
if (req.query.mode=='release') {
|
|
41
|
+
if (req.query.mode == 'release') {
|
|
34
42
|
const version = await getCurrentVersion(path.join(__rootDir, 'public', 'modules', moduleName, 'version.txt'))
|
|
35
43
|
mjsFileName = `${moduleName}-${version}.min.mjs`
|
|
44
|
+
cssBundleFileName = `${moduleName}-${version}.min.css`
|
|
45
|
+
useCssBundle = true
|
|
36
46
|
} else {
|
|
37
47
|
mjsFileName = `${moduleName}.mjs`
|
|
48
|
+
useCssBundle = false
|
|
38
49
|
}
|
|
39
50
|
} else {
|
|
40
51
|
// Default Production
|
|
41
|
-
if (req.query.mode=='debug') {
|
|
52
|
+
if (req.query.mode == 'debug') {
|
|
42
53
|
mjsFileName = `${moduleName}.mjs`
|
|
54
|
+
useCssBundle = false
|
|
43
55
|
} else {
|
|
44
56
|
const version = await getCurrentVersion(path.join(__rootDir, 'public', 'modules', moduleName, 'version.txt'))
|
|
45
57
|
mjsFileName = `${moduleName}-${version}.min.mjs`
|
|
58
|
+
cssBundleFileName = `${moduleName}-${version}.min.css`
|
|
59
|
+
useCssBundle = true
|
|
46
60
|
}
|
|
47
61
|
}
|
|
48
62
|
const mjsPath = path.join(__rootDir, 'public', 'modules', moduleName, mjsFileName);
|
|
@@ -51,24 +65,33 @@ export async function modulePage(req, res) {
|
|
|
51
65
|
const htmlExtenderFile = `${moduleName}-ext.html`
|
|
52
66
|
const htmlExtenderPath = path.join(__rootDir, 'public', 'modules', moduleName, htmlExtenderFile)
|
|
53
67
|
|
|
68
|
+
const iconFileName = `${moduleName}.svg`
|
|
69
|
+
const iconFilePath = path.join(__rootDir, 'public', 'modules', moduleName, iconFileName)
|
|
54
70
|
|
|
71
|
+
const cssLayoutExists = await helper.isFileExists(cssLayoutPath)
|
|
55
72
|
const cssExists = await helper.isFileExists(cssPath)
|
|
56
73
|
const mjsExists = await helper.isFileExists(mjsPath);
|
|
57
74
|
const htmlExtenderExists = await helper.isFileExists(htmlExtenderPath);
|
|
75
|
+
const iconFileExists = await helper.isFileExists(iconFilePath);
|
|
76
|
+
|
|
77
|
+
const cssApplicationExists = await helper.isFileExists(cssApplicationPath);
|
|
58
78
|
|
|
59
79
|
const mjsPrerenderPath = path.join(__rootDir, 'public', 'modules', moduleName, `${moduleName}-prerender.mjs`);
|
|
60
80
|
const mjsPrerenderExists = await helper.isFileExists(mjsPrerenderPath)
|
|
61
81
|
|
|
62
82
|
|
|
63
|
-
const ejsModuleExist = await helper.isFileExists(ejsPath)
|
|
83
|
+
const ejsModuleExist = await helper.isFileExists(ejsPath)
|
|
84
|
+
|
|
85
|
+
const additionalHeaderPath = path.join(__rootDir, 'public', 'modules', moduleName, `_htmlheader.ejs`);
|
|
86
|
+
const additionalHeaderExists = await helper.isFileExists(additionalHeaderPath)
|
|
64
87
|
|
|
65
88
|
try {
|
|
66
89
|
|
|
67
90
|
// coba cek request halaman
|
|
68
91
|
const fnParseModuleRequest = context.getFnParseModuleRequest()
|
|
69
|
-
if (typeof fnParseModuleRequest==='function') {
|
|
92
|
+
if (typeof fnParseModuleRequest === 'function') {
|
|
70
93
|
await fnParseModuleRequest(req, res)
|
|
71
|
-
}
|
|
94
|
+
}
|
|
72
95
|
|
|
73
96
|
|
|
74
97
|
// load halaman html-nya
|
|
@@ -77,18 +100,30 @@ export async function modulePage(req, res) {
|
|
|
77
100
|
err.status = 404
|
|
78
101
|
throw err
|
|
79
102
|
}
|
|
80
|
-
|
|
81
|
-
const variables
|
|
103
|
+
|
|
104
|
+
const variables = {
|
|
82
105
|
...helper.createDefaultEjsVariable(req),
|
|
83
106
|
...{
|
|
107
|
+
id,
|
|
108
|
+
variance,
|
|
84
109
|
moduleDir,
|
|
85
110
|
ejsPath,
|
|
86
111
|
mjsPrerenderExists,
|
|
112
|
+
cssLayoutExists,
|
|
87
113
|
cssExists,
|
|
88
114
|
mjsExists,
|
|
89
115
|
mjsFileName,
|
|
90
116
|
htmlExtenderExists,
|
|
91
117
|
htmlExtenderPath,
|
|
118
|
+
iconFileName,
|
|
119
|
+
iconFileExists,
|
|
120
|
+
additionalHeaderPath,
|
|
121
|
+
additionalHeaderExists,
|
|
122
|
+
cssApplicationPath,
|
|
123
|
+
cssApplicationExists,
|
|
124
|
+
setting: req.app.locals.appConfig,
|
|
125
|
+
useCssBundle,
|
|
126
|
+
cssBundleFileName,
|
|
92
127
|
}
|
|
93
128
|
}
|
|
94
129
|
|