@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.
- package/LICENSE +28 -0
- package/README.md +2 -0
- package/jsconfig.json +10 -0
- package/libs/fgta5js-dist/fgta5js-v1.8.3.min.css +2 -0
- package/libs/fgta5js-dist/fgta5js-v1.8.3.min.js +11 -0
- package/libs/fgta5js-dist/fgta5js-v1.8.3.min.js.map +1 -0
- package/libs/fgta5js-dist/fonts/karla-italic-latin-ext.woff2 +0 -0
- package/libs/fgta5js-dist/fonts/karla-italic-latin.woff2 +0 -0
- package/libs/fgta5js-dist/fonts/karla-normal-latin-ext.woff2 +0 -0
- package/libs/fgta5js-dist/fonts/karla-normal-latin.woff2 +0 -0
- package/libs/fgta5js-dist/fonts/karla.css +142 -0
- package/libs/webmodule/module-edit.css +163 -0
- package/libs/webmodule/module-footer.css +22 -0
- package/libs/webmodule/module-list.css +25 -0
- package/libs/webmodule/module.css +52 -0
- package/libs/webmodule/module.js +195 -0
- package/libs/webmodule/pagehelper.mjs +45 -0
- package/modules/generator/appgen-components.mjs +142 -0
- package/modules/generator/appgen-icons.mjs +6 -0
- package/modules/generator/appgen-io.mjs +784 -0
- package/modules/generator/appgen-ui-search.mjs +173 -0
- package/modules/generator/appgen-ui-unique.mjs +153 -0
- package/modules/generator/appgen-ui.mjs +1181 -0
- package/modules/generator/generator-context.mjs +18 -0
- package/modules/generator/generator-designtemplate.html +1508 -0
- package/modules/generator/generator-ext.html +0 -0
- package/modules/generator/generator-ext.mjs +3 -0
- package/modules/generator/generator.css +642 -0
- package/modules/generator/generator.mjs +195 -0
- package/modules/generator/generator.png +0 -0
- package/modules/generator/generatorEdit.html +185 -0
- package/modules/generator/generatorEdit.mjs +238 -0
- package/modules/generator/generatorList.html +32 -0
- package/modules/generator/generatorList.mjs +243 -0
- package/modules/login/login.css +11 -0
- package/modules/login/login.html +12 -0
- package/modules/login/login.mjs +111 -0
- package/package.json +46 -0
- package/percobaan/simmpan-ke-minio.js +24 -0
- package/src/api.js +80 -0
- package/src/apis/generator.api.js +226 -0
- package/src/apis/login.api.js +109 -0
- package/src/bucket.js +24 -0
- package/src/context.js +26 -0
- package/src/datalog.sql +22 -0
- package/src/datarecords.js +0 -0
- package/src/db.js +61 -0
- package/src/generator/createApiExtenderModule.js +54 -0
- package/src/generator/createApiModule.js +218 -0
- package/src/generator/createIcon.js +62 -0
- package/src/generator/createInfoAboutExtender.js +42 -0
- package/src/generator/createInfoLogs.js +41 -0
- package/src/generator/createInfoRecordExtender.js +41 -0
- package/src/generator/createModuleContext.js +48 -0
- package/src/generator/createModuleDetilEditHtml.js +110 -0
- package/src/generator/createModuleDetilEditMjs.js +172 -0
- package/src/generator/createModuleDetilListHtml.js +146 -0
- package/src/generator/createModuleDetilListMjs.js +73 -0
- package/src/generator/createModuleEjs.js +51 -0
- package/src/generator/createModuleExtenderHtml.js +43 -0
- package/src/generator/createModuleExtenderMjs.js +43 -0
- package/src/generator/createModuleHeaderEditHtml.js +148 -0
- package/src/generator/createModuleHeaderEditMjs.js +197 -0
- package/src/generator/createModuleHeaderListHtml.js +144 -0
- package/src/generator/createModuleHeaderListMjs.js +67 -0
- package/src/generator/createModuleMjs.js +67 -0
- package/src/generator/createModuleRollup.js +42 -0
- package/src/generator/createProgramData.js +96 -0
- package/src/generator/createTable.js +156 -0
- package/src/generator/ddl.js +475 -0
- package/src/generator/helper.js +149 -0
- package/src/generator/templates/__rollup-module.ejs +90 -0
- package/src/generator/templates/api-extender-module.js.ejs +0 -0
- package/src/generator/templates/api-module.js.ejs +818 -0
- package/src/generator/templates/module-context.ejs +16 -0
- package/src/generator/templates/module-ext-about.ejs +1 -0
- package/src/generator/templates/module-ext-record.ejs +1 -0
- package/src/generator/templates/module-ext.html.ejs +3 -0
- package/src/generator/templates/module-ext.mjs.ejs +21 -0
- package/src/generator/templates/module-logs.ejs +14 -0
- package/src/generator/templates/module.ejs.ejs +48 -0
- package/src/generator/templates/module.mjs.ejs +256 -0
- package/src/generator/templates/moduleDetilEdit.html.ejs +34 -0
- package/src/generator/templates/moduleDetilEdit.mjs.ejs +792 -0
- package/src/generator/templates/moduleDetilList.html.ejs +26 -0
- package/src/generator/templates/moduleDetilList.mjs.ejs +319 -0
- package/src/generator/templates/moduleHeaderEdit.html.ejs +53 -0
- package/src/generator/templates/moduleHeaderEdit.mjs.ejs +807 -0
- package/src/generator/templates/moduleHeaderList.html.ejs +24 -0
- package/src/generator/templates/moduleHeaderList.mjs.ejs +308 -0
- package/src/generator/templates/sqlAddField.ejs +3 -0
- package/src/generator/templates/sqlAddForeignKey.ejs +12 -0
- package/src/generator/templates/sqlAddUniqueIndex.ejs +4 -0
- package/src/generator/templates/sqlCreateTable.ejs +9 -0
- package/src/generator/templates/sqlDropForeignKey.ejs +3 -0
- package/src/generator/templates/sqlDropUniqueIndex.ejs +4 -0
- package/src/generator/templates/sqlModifyField.ejs +6 -0
- package/src/generator/trygenerate.js +83 -0
- package/src/generator/worker.js +389 -0
- package/src/helper.js +82 -0
- package/src/logger.js +39 -0
- package/src/router.js +84 -0
- package/src/routers/defaultLoginApi.js +29 -0
- package/src/routers/defaultLoginAsset.js +18 -0
- package/src/routers/defaultLoginPage.js +36 -0
- package/src/routers/defaultRootIndex.js +16 -0
- package/src/routers/downloadHandler.js +51 -0
- package/src/routers/fileUploadApi.js +15 -0
- package/src/routers/generatorApi.js +30 -0
- package/src/routers/generatorAsset.js +18 -0
- package/src/routers/generatorPage.js +37 -0
- package/src/routers/handleError.js +43 -0
- package/src/routers/handleModuleNotfound.js +12 -0
- package/src/routers/moduleApi.js +34 -0
- package/src/routers/modulePage.js +102 -0
- package/src/sequencerdoc.js +311 -0
- package/src/sequencerline.js +214 -0
- package/src/session.js +57 -0
- package/src/startup.js +59 -0
- package/src/webapps.js +239 -0
- package/src/workermanager.js +83 -0
- package/templates/_lib_debug.ejs +11 -0
- package/templates/_lib_production.ejs +5 -0
- package/templates/application.page.ejs +143 -0
- package/templates/generator.page.ejs +131 -0
- package/templates/index.page.ejs +24 -0
- package/templates/login.page.ejs +102 -0
- package/templates/moduleError.ejs +16 -0
- package/templates/moduleNotfound.ejs +14 -0
- package/webapps.code-workspace +11 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import pgp from 'pg-promise'
|
|
2
|
+
|
|
3
|
+
import * as path from 'path'
|
|
4
|
+
import db from '../db.js'
|
|
5
|
+
import Api from '../api.js'
|
|
6
|
+
import * as helper from '../helper.js'
|
|
7
|
+
import { runDetachedWorker } from '../workermanager.js'
|
|
8
|
+
import context from '../context.js'
|
|
9
|
+
import sqlUtil from '@agung_dhewe/pgsqlc'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
import jwt from 'jsonwebtoken';
|
|
13
|
+
|
|
14
|
+
const MINUTES = 60 * 1000
|
|
15
|
+
|
|
16
|
+
const moduleName = 'generator'
|
|
17
|
+
const generateTimeoutMs = 5 * MINUTES
|
|
18
|
+
|
|
19
|
+
// api: account
|
|
20
|
+
export default class extends Api {
|
|
21
|
+
constructor(req, res, next) {
|
|
22
|
+
super(req, res, next);
|
|
23
|
+
Api.cekLogin(req)
|
|
24
|
+
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// dipanggil dengan model snake syntax
|
|
28
|
+
// contoh: header-list
|
|
29
|
+
// header-open-data
|
|
30
|
+
async init(body) { return await generator_init(this, body) }
|
|
31
|
+
async list(body) { return await generator_list(this, body) }
|
|
32
|
+
async open(body) { return await generator_open(this, body) }
|
|
33
|
+
async save(body) { return await generator_save(this, body) }
|
|
34
|
+
async generate(body) { return await generator_generate(this, body) }
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
async function generator_init(self, body) {
|
|
40
|
+
const req = self.req
|
|
41
|
+
|
|
42
|
+
// set sid untuk session ini, diperlukan ini agar session aktif
|
|
43
|
+
req.session.sid = req.sessionID
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
// ambil data app dari database
|
|
48
|
+
const sql = 'select apps_id, apps_url, apps_name, apps_directory from core."apps"'
|
|
49
|
+
const result = await db.any(sql)
|
|
50
|
+
|
|
51
|
+
const appsUrls = {}
|
|
52
|
+
for (let row of result) {
|
|
53
|
+
appsUrls[row.apps_id] = {
|
|
54
|
+
url: row.apps_url,
|
|
55
|
+
directory: row.apps_directory,
|
|
56
|
+
name: row.apps_name
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
userId: req.session.user.userId,
|
|
62
|
+
userName: req.session.user.userName,
|
|
63
|
+
userFullname: req.session.userFullname,
|
|
64
|
+
sid: req.session.sid ,
|
|
65
|
+
notifierId: Api.generateNotifierId(moduleName, req.sessionID),
|
|
66
|
+
notifierSocket: req.app.locals.appConfig.notifierSocket,
|
|
67
|
+
targetDirectory: context.getRootDirectory(),
|
|
68
|
+
appsUrls: appsUrls
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
} catch (err) {
|
|
72
|
+
throw err
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
async function generator_list(self, body) {
|
|
80
|
+
const { criteria={}, limit=0, offset=0, columns=[], sort={} } = body
|
|
81
|
+
const searchMap = {
|
|
82
|
+
searchtext: `generator_modulename ILIKE '%' || \${searchtext} || '%' OR generator_id=try_cast_bigint(\${searchtext}, 0)`,
|
|
83
|
+
appname: `generator_appname=\${appname}`
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
|
|
88
|
+
// hilangkan criteria '' atau null
|
|
89
|
+
for (var cname in criteria) {
|
|
90
|
+
if (criteria[cname]==='' || criteria[cname]===null) {
|
|
91
|
+
delete criteria[cname]
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// const orderby = {
|
|
96
|
+
// _modifydate: 'desc',
|
|
97
|
+
// ...sort
|
|
98
|
+
// }
|
|
99
|
+
|
|
100
|
+
sort._modifydate = 'desc'
|
|
101
|
+
|
|
102
|
+
var max_rows = limit==0 ? 50 : limit
|
|
103
|
+
const tablename = 'core."generator"'
|
|
104
|
+
const {whereClause, queryParams} = sqlUtil.createWhereClause(criteria, searchMap)
|
|
105
|
+
const sql = sqlUtil.createSqlSelect({tablename, columns, whereClause, sort, limit:max_rows+1, offset, queryParams})
|
|
106
|
+
const rows = await db.any(sql, queryParams);
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
var i = 0
|
|
110
|
+
const data = []
|
|
111
|
+
for (var row of rows) {
|
|
112
|
+
i++
|
|
113
|
+
if (i>max_rows) { break }
|
|
114
|
+
data.push(row)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
var nextoffset = null
|
|
118
|
+
if (rows.length>max_rows) {
|
|
119
|
+
nextoffset = offset+max_rows
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
criteria: criteria,
|
|
124
|
+
limit: max_rows,
|
|
125
|
+
nextoffset: nextoffset,
|
|
126
|
+
data: data
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
} catch (err) {
|
|
130
|
+
throw err
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function generator_open(self, body) {
|
|
135
|
+
try {
|
|
136
|
+
const { id } = body
|
|
137
|
+
const queryParams = {generator_id: id}
|
|
138
|
+
const sql = 'select * from core."generator" where generator_id = \${generator_id}'
|
|
139
|
+
const data = await db.one(sql, queryParams);
|
|
140
|
+
|
|
141
|
+
if (data==null) { throw new Error("data tidak ditemukan") }
|
|
142
|
+
|
|
143
|
+
return data
|
|
144
|
+
} catch (err) {
|
|
145
|
+
throw err
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function generator_save(self, body) {
|
|
150
|
+
const { data } = body
|
|
151
|
+
const tablename = 'core."generator"'
|
|
152
|
+
const req = self.req
|
|
153
|
+
const user_id = req.session.user.userId
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
sqlUtil.connect(db)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
const id = `${data.id}`
|
|
162
|
+
|
|
163
|
+
delete data.id
|
|
164
|
+
const obj = {
|
|
165
|
+
generator_appname: data.appname,
|
|
166
|
+
generator_modulename: data.name,
|
|
167
|
+
generator_data: JSON.stringify(data),
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
let cmd
|
|
171
|
+
if (id=='') {
|
|
172
|
+
obj._createby = user_id
|
|
173
|
+
obj._createdate = (new Date()).toISOString()
|
|
174
|
+
cmd = sqlUtil.createInsertCommand(tablename, obj, ['generator_id'])
|
|
175
|
+
} else {
|
|
176
|
+
obj.generator_id = id
|
|
177
|
+
obj._modifyby = user_id
|
|
178
|
+
obj._modifydate = (new Date()).toISOString()
|
|
179
|
+
cmd = sqlUtil.createUpdateCommand(tablename, obj, ['generator_id'])
|
|
180
|
+
}
|
|
181
|
+
const result = await cmd.execute(obj)
|
|
182
|
+
|
|
183
|
+
return result
|
|
184
|
+
} catch (err) {
|
|
185
|
+
throw err
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
async function generator_generate(self, body) {
|
|
191
|
+
const req = self.req
|
|
192
|
+
const { data, clientId } = body
|
|
193
|
+
const id = `${data.id}`
|
|
194
|
+
const user_id = req.session.user.userId
|
|
195
|
+
const user_name = req.session.user.userFullname
|
|
196
|
+
const ipaddress = req.ip
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
if (id=='') {
|
|
200
|
+
throw new Error('save data dahulu sebelum generate')
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// sebelumnya save dahulu
|
|
204
|
+
const result = await generator_save(self, body)
|
|
205
|
+
const generator_id = result.generator_id
|
|
206
|
+
|
|
207
|
+
// generate di detached thread
|
|
208
|
+
const generatorWorker = path.join(context.getWebappsDirectory(), 'src', 'generator', 'worker.js')
|
|
209
|
+
const notifierServer = req.app.locals.appConfig.notifierServer
|
|
210
|
+
runDetachedWorker(generatorWorker, notifierServer, clientId, {
|
|
211
|
+
generator_id: generator_id,
|
|
212
|
+
user_id: user_id,
|
|
213
|
+
user_name: user_name,
|
|
214
|
+
ipaddress: ipaddress,
|
|
215
|
+
timeout: generateTimeoutMs,
|
|
216
|
+
jeda: 0.5, // jeda 1 detik per masing-masing generate
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
return {
|
|
221
|
+
generator_id: generator_id
|
|
222
|
+
}
|
|
223
|
+
} catch (err) {
|
|
224
|
+
throw err
|
|
225
|
+
}
|
|
226
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import pgp from 'pg-promise';
|
|
2
|
+
|
|
3
|
+
import sqlUtil from '@agung_dhewe/pgsqlc'
|
|
4
|
+
import context from '../context.js'
|
|
5
|
+
import db from '../db.js'
|
|
6
|
+
import Api from '../api.js'
|
|
7
|
+
import bcrypt from 'bcrypt';
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
export default class extends Api {
|
|
12
|
+
constructor(req, res, next) {
|
|
13
|
+
super(req, res, next);
|
|
14
|
+
|
|
15
|
+
this.currentState = {}
|
|
16
|
+
try {
|
|
17
|
+
Api.cekLogin(req)
|
|
18
|
+
this.currentState.isLogin = true
|
|
19
|
+
} catch (err) {
|
|
20
|
+
// tidak perlu throw error, karna hanya untuk cek sudah login apa belum
|
|
21
|
+
this.currentState.isLogin = false
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// dipanggil dengan model snake syntax
|
|
27
|
+
// contoh: header-list
|
|
28
|
+
// header-open-data
|
|
29
|
+
async init(body) { return await login_init(this, body) }
|
|
30
|
+
async doLogin(body) { return await login_doLogin(this, body) }
|
|
31
|
+
async doLogout(body) { return await login_doLogout(this, body) }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
async function login_init(self, body) {
|
|
36
|
+
const req = self.req
|
|
37
|
+
if (self.currentState.isLogin) {
|
|
38
|
+
req.session.sid = req.sessionID
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
isLogin: self.currentState.isLogin
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function login_doLogin(self, body) {
|
|
47
|
+
try {
|
|
48
|
+
const {username, password} = body
|
|
49
|
+
|
|
50
|
+
const sql = 'select * from core.user where user_name = ${username}'
|
|
51
|
+
const param = { username }
|
|
52
|
+
const row = await db.oneOrNone(sql, param)
|
|
53
|
+
|
|
54
|
+
if (row==null) {
|
|
55
|
+
return null
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
const userId = row.user_id
|
|
60
|
+
const userName = row.user_name
|
|
61
|
+
const userFullname = row.user_fullname
|
|
62
|
+
const hashedPassword = row.user_password
|
|
63
|
+
const developerAccess = row.user_isdev
|
|
64
|
+
|
|
65
|
+
const match = await bcrypt.compare(password, hashedPassword);
|
|
66
|
+
if (!match) {
|
|
67
|
+
return null
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
// simpan di session
|
|
72
|
+
self.req.session.user = {
|
|
73
|
+
userId,
|
|
74
|
+
userName,
|
|
75
|
+
userFullname,
|
|
76
|
+
developerAccess,
|
|
77
|
+
isLogin: true
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return self.req.session.user
|
|
81
|
+
|
|
82
|
+
// // dummy login dulu
|
|
83
|
+
// if (username=='agung') {
|
|
84
|
+
// // setup session
|
|
85
|
+
// const user_id = '2590000000000000001'
|
|
86
|
+
// self.req.session.user = {
|
|
87
|
+
// userId: user_id,
|
|
88
|
+
// userName: 'agung',
|
|
89
|
+
// userFullname: 'Agung Nugroho',
|
|
90
|
+
// isLogin: true
|
|
91
|
+
// }
|
|
92
|
+
|
|
93
|
+
// return self.req.session.user
|
|
94
|
+
// } else {
|
|
95
|
+
// return null
|
|
96
|
+
// }
|
|
97
|
+
} catch (err) {
|
|
98
|
+
throw err
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async function login_doLogout(self, body) {
|
|
103
|
+
try {
|
|
104
|
+
self.req.session.user = null
|
|
105
|
+
return true
|
|
106
|
+
} catch (err) {
|
|
107
|
+
throw err
|
|
108
|
+
}
|
|
109
|
+
}
|
package/src/bucket.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
|
+
import { Client } from 'minio';
|
|
3
|
+
|
|
4
|
+
dotenv.config();
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const bucketHost = process.env.BUCKET_HOST
|
|
8
|
+
const bucketPort = process.env.BUCKET_PORT
|
|
9
|
+
const bucketSecure = process.env.BUCKET_SECURE === 'true'
|
|
10
|
+
const bucketUsername = process.env.BUCKET_USERNAME
|
|
11
|
+
const bucketSecret = process.env.BUCKET_SECRET
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
const minioClient = new Client({
|
|
15
|
+
endPoint: bucketHost,
|
|
16
|
+
port: bucketPort,
|
|
17
|
+
useSSL: bucketSecure,
|
|
18
|
+
accessKey: bucketUsername,
|
|
19
|
+
secretKey: bucketSecret,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
export default minioClient
|
|
24
|
+
|
package/src/context.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
let __dir
|
|
2
|
+
let __rootDirectory
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
let fnParseModuleRequest
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
setWebappsDirectory: (dirname)=>{ __dir=dirname },
|
|
10
|
+
getWebappsDirectory: () => { return __dir },
|
|
11
|
+
|
|
12
|
+
setRootDirectory: (rootdir) => { __rootDirectory=rootdir },
|
|
13
|
+
getRootDirectory: () => { return __rootDirectory },
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
setFnParseModuleRequest: (fn) => {
|
|
17
|
+
fnParseModuleRequest = fn
|
|
18
|
+
},
|
|
19
|
+
getFnParseModuleRequest: (fn) => {
|
|
20
|
+
return fnParseModuleRequest
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
package/src/datalog.sql
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
create table datalog (
|
|
2
|
+
log_time timestamptz not null,
|
|
3
|
+
log_user_id text,
|
|
4
|
+
log_user_name text,
|
|
5
|
+
log_action text,
|
|
6
|
+
log_ipaddress text,
|
|
7
|
+
log_module text,
|
|
8
|
+
log_table text,
|
|
9
|
+
log_id text,
|
|
10
|
+
log_remark text,
|
|
11
|
+
log_executiontime int,
|
|
12
|
+
log_metadata JSONB
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
CREATE INDEX idx_datalog_module_table_id
|
|
16
|
+
ON datalog (log_module, log_table, log_id);
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
-- buat jadi hyper table
|
|
20
|
+
SELECT create_hypertable('datalog', 'log_time');
|
|
21
|
+
|
|
22
|
+
|
|
File without changes
|
package/src/db.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
|
+
import pgp from 'pg-promise';
|
|
3
|
+
|
|
4
|
+
dotenv.config();
|
|
5
|
+
|
|
6
|
+
const initOptions = {
|
|
7
|
+
// Misalnya, event untuk memantau query atau error
|
|
8
|
+
// query: (e) => {
|
|
9
|
+
// console.log('QUERY:', e.query);
|
|
10
|
+
// },
|
|
11
|
+
// error: (err, e) => {
|
|
12
|
+
// console.log('ERROR:', err, e.query);
|
|
13
|
+
// }
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const pgpInstance = pgp(initOptions); // <-- Panggil pgp() hanya satu kali di sini
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
const configDb = {
|
|
20
|
+
port: process.env.DB_PORT,
|
|
21
|
+
host: process.env.DB_HOST,
|
|
22
|
+
database: process.env.DB_NAME,
|
|
23
|
+
user: process.env.DB_USER,
|
|
24
|
+
password: process.env.DB_PASS,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const configDbLog = {
|
|
28
|
+
port: process.env.LOGGER_DB_PORT,
|
|
29
|
+
host: process.env.LOGGER_DB_HOST,
|
|
30
|
+
database: process.env.LOGGER_DB_NAME,
|
|
31
|
+
user: process.env.LOGGER_DB_USER,
|
|
32
|
+
password: process.env.LOGGER_DB_PASS,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
const db = pgpInstance(configDb);
|
|
37
|
+
export default db
|
|
38
|
+
|
|
39
|
+
export const dblog = pgpInstance(configDbLog);
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
db.connect()
|
|
44
|
+
.then(obj => {
|
|
45
|
+
console.log('Connected to Primary Database!');
|
|
46
|
+
obj.done(); // Klien dikembalikan ke pool
|
|
47
|
+
})
|
|
48
|
+
.catch(error => {
|
|
49
|
+
console.error("\n\x1b[31mError!\x1b[0m\ncannot connect to Database:", error.message || error, "\n");
|
|
50
|
+
process.exit(1);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
dblog.connect()
|
|
54
|
+
.then(obj => {
|
|
55
|
+
console.log('Connected to Logger Database!');
|
|
56
|
+
obj.done(); // Klien dikembalikan ke pool
|
|
57
|
+
})
|
|
58
|
+
.catch(error => {
|
|
59
|
+
console.error('\n\x1b[31mError!\x1b[0m cannot\nconnect to Logger Database:', error.message || error, "\n");
|
|
60
|
+
process.exit(1);
|
|
61
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { kebabToCamel, isFileExist, getSectionData } from './helper.js'
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import path from 'path'
|
|
4
|
+
import fs from 'fs/promises'
|
|
5
|
+
import ejs from 'ejs'
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
|
|
10
|
+
export async function createApiExtenderModule(context, options) {
|
|
11
|
+
const overwrite = options.overwrite===true
|
|
12
|
+
const moduleName = context.moduleName
|
|
13
|
+
const title = context.title
|
|
14
|
+
const targetFile = path.join(context.apiExtenderDir, `${moduleName}.apiext.js`)
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
// cek dulu apakah file ada
|
|
18
|
+
var fileExists = await isFileExist(targetFile)
|
|
19
|
+
if (fileExists && !overwrite) {
|
|
20
|
+
context.postMessage({message: `skip file: '${targetFile}`})
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// reporting progress to parent process
|
|
25
|
+
context.postMessage({message: `generating file: '${targetFile}`})
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
// start geneate program code
|
|
29
|
+
let sections = []
|
|
30
|
+
for (var entityName in context.entities) {
|
|
31
|
+
// console.log(context.entities[entityName])
|
|
32
|
+
sections.push(getSectionData(moduleName, entityName, context.entities[entityName], 'list'))
|
|
33
|
+
sections.push(getSectionData(moduleName, entityName, context.entities[entityName], 'edit'))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const variables = {
|
|
37
|
+
timeGenerated: context.timeGenerated,
|
|
38
|
+
title: title,
|
|
39
|
+
moduleName: moduleName,
|
|
40
|
+
sections: sections
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
const tplFilePath = path.join(__dirname, 'templates', 'api-extender-module.js.ejs')
|
|
45
|
+
const template = await fs.readFile(tplFilePath, 'utf-8');
|
|
46
|
+
const content = ejs.render(template, variables)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
await fs.writeFile(targetFile, content, 'utf8');
|
|
50
|
+
} catch (err) {
|
|
51
|
+
throw err
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
}
|