biz-a-cli 2.3.15 → 2.3.17
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/bin/app.js +313 -0
- package/bin/hub.js +1 -1
- package/bin/hubEvent.js +6 -5
- package/bin/proxy.js +1 -1
- package/bin/watcher.js +1 -1
- package/callbackController.js +15 -18
- package/envs/env.dev.js +2 -1
- package/envs/env.js +2 -1
- package/mailController.js +2 -2
- package/package.json +11 -6
- package/readme.md +60 -0
- package/scheduler/datalib.js +45 -49
- package/scheduler/timer.js +8 -14
- package/scheduler/watcherController.js +12 -22
- package/tests/app.test.js +384 -0
- package/tests/callback.test.js +8 -17
- package/tests/data.test.js +20 -2
- package/tests/hub.test.js +4 -8
- package/tests/watcherCtl.test.js +9 -12
- package/bin/log/debug.log +0 -0
- package/bin/log/error.log +0 -0
- package/bin/log/exception.log +0 -38
- package/bin/log/info.log +0 -0
package/bin/app.js
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import yargs from "yargs"
|
|
4
|
+
import axios from "axios"
|
|
5
|
+
import fs from "fs"
|
|
6
|
+
import { runInNewContext } from "vm"
|
|
7
|
+
import uglify from "uglify-js"
|
|
8
|
+
import * as tar from "tar"
|
|
9
|
+
import { verify, sign, privateDecrypt, constants as cryptoConstants, randomBytes, createCipheriv } from "node:crypto"
|
|
10
|
+
import { basename } from "node:path"
|
|
11
|
+
import { env } from "../envs/env.js"
|
|
12
|
+
import * as vm from 'node:vm'
|
|
13
|
+
|
|
14
|
+
const keyFolderPath = process.argv[1].substring(0, process.argv[1].lastIndexOf("\\bin")) + "\\key"
|
|
15
|
+
|
|
16
|
+
yargs(process.argv.slice(2))
|
|
17
|
+
.option("s", {
|
|
18
|
+
alias: "server",
|
|
19
|
+
describe: "Server URL (ex: https://biz-a.herokuapp.com or http://192.168.1.1 or https://finaapi.imamatek.com)",
|
|
20
|
+
type: "string",
|
|
21
|
+
demandOption: true
|
|
22
|
+
})
|
|
23
|
+
.option("i", {
|
|
24
|
+
alias: "dbIndex",
|
|
25
|
+
describe: "database index",
|
|
26
|
+
type: "number",
|
|
27
|
+
demandOption: true
|
|
28
|
+
})
|
|
29
|
+
.option("sub", {
|
|
30
|
+
alias: "subdomain",
|
|
31
|
+
describe: "Subdomain",
|
|
32
|
+
type: "string",
|
|
33
|
+
demandOption: false
|
|
34
|
+
})
|
|
35
|
+
.option("p", {
|
|
36
|
+
alias: "apiPort",
|
|
37
|
+
describe: "FINA API Port",
|
|
38
|
+
type: "string",
|
|
39
|
+
demandOption: false,
|
|
40
|
+
default : "212"
|
|
41
|
+
})
|
|
42
|
+
.command('add', 'Add Biz-A Application',
|
|
43
|
+
{
|
|
44
|
+
'd': {
|
|
45
|
+
alias: "workingDir",
|
|
46
|
+
describe: "Path to templates directory",
|
|
47
|
+
type: "string",
|
|
48
|
+
demandOption: false,
|
|
49
|
+
default: process.cwd(),
|
|
50
|
+
},
|
|
51
|
+
'v': {
|
|
52
|
+
alias: "verbose",
|
|
53
|
+
describe: "Print info to console",
|
|
54
|
+
type: "boolean",
|
|
55
|
+
demandOption: false,
|
|
56
|
+
default: false,
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
async (options)=>{
|
|
60
|
+
|
|
61
|
+
function printInfo(msg){if (options.verbose) {console.log(msg)}}
|
|
62
|
+
|
|
63
|
+
const prepareKeys = async ()=>{
|
|
64
|
+
const data = Buffer.from(JSON.stringify({issuer: 'CLI', acquirer: 'Client'})).toString('base64')
|
|
65
|
+
const privateKey = fs.readFileSync(`${keyFolderPath}\\cliPrivate.pem`)
|
|
66
|
+
const signature = sign('sha256', data, {key: privateKey, passphrase: 'Biz-A@cli', padding: cryptoConstants.RSA_PKCS1_PSS_PADDING}).toString('base64')
|
|
67
|
+
const res = await axios.get(env.BIZA_SERVER_LINK+'/api/issuerKey', {params: {data, signature}})
|
|
68
|
+
if ((res.data.data!=null) && verify('sha256', res.data.data, {key: fs.readFileSync(`${keyFolderPath}\\serverPublic.pem`), padding: cryptoConstants.RSA_PKCS1_PSS_PADDING}, Buffer.from(res.data.signature, 'base64'))) {
|
|
69
|
+
const resData = JSON.parse(Buffer.from(res.data.data, 'base64').toString())
|
|
70
|
+
const decryptedAESKey = privateDecrypt({key: privateKey, passphrase: 'Biz-A@cli', padding: cryptoConstants.RSA_PKCS1_OAEP_PADDING}, Buffer.from(resData.issuer.key, 'base64')).toString()
|
|
71
|
+
const cliSignature = (signedData)=>sign('sha256', signedData, {key: privateKey, passphrase: 'Biz-A@cli', padding: cryptoConstants.RSA_PKCS1_PSS_PADDING}).toString('base64')
|
|
72
|
+
const acquirerData = Buffer.from(JSON.stringify(resData.acquirer)).toString('base64')
|
|
73
|
+
const signature = cliSignature(acquirerData)
|
|
74
|
+
return {encryptKey: decryptedAESKey, metadata: {acquirer: {data: acquirerData, signature}}}
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
return null
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function replacer(key, value) {
|
|
82
|
+
/*
|
|
83
|
+
// with line break
|
|
84
|
+
if (typeof value == 'function') {
|
|
85
|
+
let arr = value.toString().replace(/(\r\n|\n|\r)/gm, "°").split("°");
|
|
86
|
+
if (arr.length < 3) throw 'Function must be minimal 3 lines';
|
|
87
|
+
return [
|
|
88
|
+
'window.Function',
|
|
89
|
+
getParam(arr[0]),
|
|
90
|
+
arr.slice(1, arr.length - 1)
|
|
91
|
+
];
|
|
92
|
+
} else {
|
|
93
|
+
return value;
|
|
94
|
+
}
|
|
95
|
+
*/
|
|
96
|
+
|
|
97
|
+
// without line break
|
|
98
|
+
if (typeof value == 'function') {
|
|
99
|
+
const fnScript = value.toString()
|
|
100
|
+
let params, body = ''
|
|
101
|
+
if (fnScript.indexOf('{')==-1) {
|
|
102
|
+
const arr = fnScript.split('=>')
|
|
103
|
+
params = arr[0]
|
|
104
|
+
body = arr.slice(1).join()
|
|
105
|
+
} else {
|
|
106
|
+
params = fnScript.split('{')[0]
|
|
107
|
+
body = fnScript.substring(fnScript.indexOf('{')+1, fnScript.lastIndexOf('}'))
|
|
108
|
+
}
|
|
109
|
+
params = params.replace(/(\s|=>|\(|\)|function)/gim, '')
|
|
110
|
+
printInfo(['window.Function', params, body])
|
|
111
|
+
return ['window.Function', params, body]
|
|
112
|
+
} else {
|
|
113
|
+
return value;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const minifiedIt = async (fileName) => {
|
|
118
|
+
const dataFile = fs.readFileSync(fileName);
|
|
119
|
+
printInfo(`===================\n${fileName.toUpperCase()}\n===================`)
|
|
120
|
+
|
|
121
|
+
const minifyResult = uglify.minify(dataFile.toString(), {compress: false, mangle: false})
|
|
122
|
+
if (minifyResult.error ) {throw (`${fileName} : ` + minifyResult.error)}
|
|
123
|
+
let jsMinData = minifyResult.code
|
|
124
|
+
jsMinData = jsMinData.replace('module.exports=get;', '') // Ex : at "executeBlockLib.js" of Imamatek App, will throw error. We need this line code for testing or debugging
|
|
125
|
+
const minifiedBuffer = Buffer.from(jsMinData)
|
|
126
|
+
printInfo(['Minify : \n', minifiedBuffer.toString()].join(''))
|
|
127
|
+
|
|
128
|
+
let stringifyData = ''
|
|
129
|
+
const isJsonFile = fileName.split('.').pop().toLowerCase().match(/^(json)$/)
|
|
130
|
+
|
|
131
|
+
// compile using node.js VM
|
|
132
|
+
try {
|
|
133
|
+
printInfo('Running script with VM')
|
|
134
|
+
if (isJsonFile) {
|
|
135
|
+
const vmResult = runInNewContext(minifiedBuffer.toString())
|
|
136
|
+
stringifyData = vmResult ? JSON.stringify((typeof vmResult=='function') ? vmResult() : (vmResult || ''), replacer) : ''
|
|
137
|
+
} else {
|
|
138
|
+
// for handling "get" function in local scope (let, var, const)
|
|
139
|
+
const sandbox = vm.createContext({script: ''});
|
|
140
|
+
vm.runInContext(
|
|
141
|
+
minifiedBuffer.toString() + "\n script = (typeof get=='undefined') ? '' : (typeof get=='function') ? get() : (get||'')",
|
|
142
|
+
sandbox
|
|
143
|
+
)
|
|
144
|
+
stringifyData = JSON.stringify(sandbox.script, replacer)
|
|
145
|
+
}
|
|
146
|
+
} catch (err){
|
|
147
|
+
printInfo(`${fileName} : ` + err) // Do not log it as error, we will try to compile the script using ES6 Import
|
|
148
|
+
stringifyData = ''
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const isEmptyScript = (scriptText)=>((typeof scriptText=='undefined') || (scriptText===null) || (scriptText.trim()==='""') || (typeof scriptText=='string' && scriptText.trim().length==0))
|
|
152
|
+
|
|
153
|
+
// compile using ES6 Import
|
|
154
|
+
if (isEmptyScript(stringifyData)) {
|
|
155
|
+
try {
|
|
156
|
+
printInfo('Running script with Import function')
|
|
157
|
+
const lib = await import(`file://${process.cwd()}\\${fileName}`, isJsonFile ? {assert: {type: "json"}} : {})
|
|
158
|
+
stringifyData = JSON.stringify((typeof lib.default=='function') ? lib.default() : (lib.default || ''), replacer).replace(/ /g,'') // remove trailing whitespace
|
|
159
|
+
// stringifyData = stringifyData.replace(/\\r\\n/g,'') // remove line break. We can not do this because "inline css" still requires line breaks
|
|
160
|
+
} catch (error){
|
|
161
|
+
throw(`${fileName} : ` + error)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (isEmptyScript(stringifyData)) {
|
|
166
|
+
throw(`${fileName} : ` + 'Failed to compile template script.\nPlease make sure the script is correct and not returning empty result')
|
|
167
|
+
} else {
|
|
168
|
+
printInfo('Array function :')
|
|
169
|
+
printInfo(['Stringify : \n', stringifyData].join(''))
|
|
170
|
+
}
|
|
171
|
+
// console.log('RESULT =>', stringifyData)
|
|
172
|
+
printInfo('===================')
|
|
173
|
+
return Buffer.from(stringifyData)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const encryptIt = (data, encryptKey)=>{
|
|
177
|
+
const initializeVector = randomBytes(16) // "iv" is unique for each template file
|
|
178
|
+
const cipher = createCipheriv('aes-256-cbc', Buffer.from(encryptKey, 'base64'), initializeVector)
|
|
179
|
+
return Buffer.concat([initializeVector, cipher.update(data), cipher.final()]) // we put "iv" at beginning of cipherText, seperate it when doing decryption
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const compressIt = (fileName, folderPath)=>{
|
|
183
|
+
// tar v7.1.0 -> tested 10x times, 2-3x times last compressed file have empty content
|
|
184
|
+
// tar v.7.4.0 -> tested 1000x times, all files have content (used app.test.js)
|
|
185
|
+
let compressSuccess = false
|
|
186
|
+
const maxRetry = 10
|
|
187
|
+
let retryCount = 0
|
|
188
|
+
do {
|
|
189
|
+
tar.c({file: fileName, cwd: folderPath, gzip: {level:9}, strict: true, sync: true}, fs.readdirSync(folderPath))
|
|
190
|
+
compressSuccess = true
|
|
191
|
+
tar.t({file: fileName, cwd: folderPath, sync: true, onentry: (entry)=>{
|
|
192
|
+
if (entry.size==0) {
|
|
193
|
+
compressSuccess = false
|
|
194
|
+
}
|
|
195
|
+
}})
|
|
196
|
+
if (compressSuccess==false) {
|
|
197
|
+
fs.unlinkSync(fileName)
|
|
198
|
+
retryCount++
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
while ((compressSuccess==false) && (retryCount<=maxRetry))
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const getFileList = ()=>{
|
|
205
|
+
return (fs.readdirSync(process.cwd())).filter((fileName)=>{
|
|
206
|
+
const stat = fs.statSync(fileName)
|
|
207
|
+
return stat.isFile() && (stat.size>0) && ((fileName.split('.').pop().toLowerCase().match(/^(js)$/) || (fileName.toLowerCase()=='menu.json')))
|
|
208
|
+
})
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
async function addApp() {
|
|
212
|
+
/*
|
|
213
|
+
hex => 2 char = 1 bytes => can be encrypted
|
|
214
|
+
base64 => 4 char = 3 bytes => can be encrypted. Smaller size compare to Hex
|
|
215
|
+
utf8 => 1 char = 1 - 4 bytes => can not be encrypted, encryption need precise bytes per Character. Smallest Size compare to Hex and base64
|
|
216
|
+
*/
|
|
217
|
+
process.chdir(options.workingDir)
|
|
218
|
+
try {
|
|
219
|
+
const bundlingStart = performance.now()
|
|
220
|
+
const rootFolder = './upload/'
|
|
221
|
+
const bundleName = basename(process.cwd()).trim().replace(' ', '').toLowerCase()
|
|
222
|
+
const bundleFolder = rootFolder+bundleName+'/'
|
|
223
|
+
const files = getFileList()
|
|
224
|
+
if (files.length>0) {
|
|
225
|
+
const keys = await prepareKeys()
|
|
226
|
+
let processedFile = 0
|
|
227
|
+
fs.rmSync(rootFolder, {force: true, recursive: true})
|
|
228
|
+
fs.mkdirSync(bundleFolder, {recursive: true})
|
|
229
|
+
for (const file of files) {
|
|
230
|
+
const fileName = file.toLowerCase();
|
|
231
|
+
// if (['finalib.js', 'solib.js'].indexOf(fileName)==-1) {continue}
|
|
232
|
+
const minifiedData = await minifiedIt(fileName);
|
|
233
|
+
const encryptedData = encryptIt(minifiedData, keys.encryptKey)
|
|
234
|
+
if (fileName=='menu.json') {
|
|
235
|
+
keys.metadata['menu'] = encryptedData.toString('base64')
|
|
236
|
+
} else {
|
|
237
|
+
fs.writeFileSync(bundleFolder+fileName, encryptedData.toString('base64'))
|
|
238
|
+
}
|
|
239
|
+
processedFile++
|
|
240
|
+
}
|
|
241
|
+
const bundleFile = `${rootFolder}${bundleName}.tgz`
|
|
242
|
+
compressIt(bundleFile, bundleFolder)
|
|
243
|
+
console.log(`Finished packing ${processedFile} files into "${bundleFile}" (${((performance.now()-bundlingStart)/1000).toFixed(2)}s)`)
|
|
244
|
+
|
|
245
|
+
// send to FINAPI
|
|
246
|
+
const uploadingStart = performance.now()
|
|
247
|
+
const data = (fs.readFileSync(bundleFile)).toString('base64') // *.tgz to base64String
|
|
248
|
+
const baseUrl = 'fina/rest/TOrmMethod/%22setApp%22'
|
|
249
|
+
const url = options.sub ?
|
|
250
|
+
`${options.server}/hub/${baseUrl}?subdomain=${options.sub}` :
|
|
251
|
+
`${options.server}:${options.apiPort}/${baseUrl}`
|
|
252
|
+
const headers = {'Content-Type': 'text/plain'}
|
|
253
|
+
const param = { _parameters: [options.dbIndex, bundleName, data, keys.metadata] }
|
|
254
|
+
const res = await axios.post(url, param, { headers: headers });
|
|
255
|
+
if (res.data.success) {
|
|
256
|
+
console.log(`Finished uploading "${bundleFile}" (${((performance.now()-uploadingStart)/1000).toFixed(2)}s)`)
|
|
257
|
+
fs.rmSync(rootFolder, {force: true, recursive: true})
|
|
258
|
+
} else {
|
|
259
|
+
console.error(res.data.error)
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
} catch (e) {
|
|
263
|
+
console.error(e.response?.data ? e.response.data : e)
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
await addApp()
|
|
268
|
+
}
|
|
269
|
+
)
|
|
270
|
+
.command('remove', 'Remove Biz-A Application',
|
|
271
|
+
{
|
|
272
|
+
'n': {
|
|
273
|
+
alias: "appName",
|
|
274
|
+
describe: "Application name",
|
|
275
|
+
type: "string",
|
|
276
|
+
demandOption: true,
|
|
277
|
+
default: ""
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
(options)=>{
|
|
281
|
+
(async () => {
|
|
282
|
+
try {
|
|
283
|
+
const baseUrl = 'fina/rest/TOrmMethod/%22deleteApp%22'
|
|
284
|
+
const url = options.sub ?
|
|
285
|
+
`${options.server}/hub/${baseUrl}?subdomain=${options.sub}` :
|
|
286
|
+
`${options.server}:${options.apiPort}/${baseUrl}`
|
|
287
|
+
const headers = {'Content-Type': 'text/plain'}
|
|
288
|
+
const deleteApps = options.appName.trim().replaceAll(' ', '').toLowerCase()
|
|
289
|
+
const param = { _parameters: [options.dbIndex, deleteApps] }
|
|
290
|
+
const res = await axios.post(url, param, { headers: headers });
|
|
291
|
+
if (res.data?.success) {
|
|
292
|
+
if (deleteApps=='') {
|
|
293
|
+
console.log('All apps removed')
|
|
294
|
+
} else {
|
|
295
|
+
const failedList = (res.data._f && (typeof res.data._f=='string')) ? res.data._f.trim().replaceAll(' ', '').toLowerCase().split(',') : []
|
|
296
|
+
const removeList = deleteApps.split(',')
|
|
297
|
+
removeList.forEach((app)=>{
|
|
298
|
+
console.log(`${app} ${failedList.indexOf(app)==-1 ? 'removed' : 'not found'}`)
|
|
299
|
+
})
|
|
300
|
+
}
|
|
301
|
+
} else {
|
|
302
|
+
console.error(res.data.error)
|
|
303
|
+
}
|
|
304
|
+
return res
|
|
305
|
+
} catch (e) {
|
|
306
|
+
const errMsg = (e.response?.data ? e.response.data : e)
|
|
307
|
+
console.error(errMsg)
|
|
308
|
+
return errMsg
|
|
309
|
+
}
|
|
310
|
+
})()
|
|
311
|
+
}
|
|
312
|
+
)
|
|
313
|
+
.parse();
|
package/bin/hub.js
CHANGED
package/bin/hubEvent.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import axios from 'axios';
|
|
2
2
|
import net from 'node:net';
|
|
3
3
|
import { createRequire } from "module";
|
|
4
4
|
const require = createRequire(import.meta.url);
|
|
@@ -57,16 +57,17 @@ export default async (socket, argv) => new Promise((resolve, reject) => {
|
|
|
57
57
|
s.end();
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
|
-
const cliReqCb = (data, callback) => {
|
|
60
|
+
const cliReqCb = async (data, callback) => {
|
|
61
61
|
const { path, method, ...remainData } = data;
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
const result = await axios.request({
|
|
64
64
|
method: data.method,
|
|
65
65
|
url: `${process.env.HOST || 'http://localhost'}:${argv.serverport}/cb${path || ''}`,
|
|
66
66
|
data: remainData
|
|
67
|
-
})
|
|
67
|
+
})
|
|
68
|
+
callback(result.data);
|
|
68
69
|
}
|
|
69
70
|
socket.on('connect', connectCb);
|
|
70
71
|
socket.on('incomingClient', incomingHubCb)
|
|
71
|
-
socket.on('cli-req', cliReqCb
|
|
72
|
+
socket.on('cli-req', cliReqCb);
|
|
72
73
|
})
|
package/bin/proxy.js
CHANGED
package/bin/watcher.js
CHANGED
package/callbackController.js
CHANGED
|
@@ -10,7 +10,7 @@ export function getInputScript(req) {
|
|
|
10
10
|
path: req.path,
|
|
11
11
|
query: req.body.query,
|
|
12
12
|
headers: req.body.headers,
|
|
13
|
-
socket
|
|
13
|
+
socket: req.app.settings.socket,
|
|
14
14
|
},
|
|
15
15
|
selectedConfig: {
|
|
16
16
|
url: `http://${args.hostname}:${args.port}`,
|
|
@@ -21,22 +21,19 @@ export function getInputScript(req) {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export async function runCliScript(req, res) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
res.send('CLI Script does not exist.');
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
error: error => {
|
|
38
|
-
console.error(error);
|
|
39
|
-
throw new Error(error);
|
|
24
|
+
try {
|
|
25
|
+
const { data, selectedConfig } = getInputScript(req);
|
|
26
|
+
let script = await loadCliScript(selectedConfig, req.body.query);
|
|
27
|
+
let functions = extractFunctionScript(script);
|
|
28
|
+
if (functions) {
|
|
29
|
+
let respon = await functions.onInit(data);
|
|
30
|
+
res.send(respon);
|
|
31
|
+
console.log(`Run Callback Successfully!`);
|
|
32
|
+
} else {
|
|
33
|
+
res.send('CLI Script does not exist.');
|
|
40
34
|
}
|
|
41
|
-
})
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error(error);
|
|
37
|
+
throw new Error(error);
|
|
38
|
+
}
|
|
42
39
|
}
|
package/envs/env.dev.js
CHANGED
|
@@ -5,7 +5,8 @@ export const envDev = {
|
|
|
5
5
|
CDM_MONGO_LINK: 'mongodb+srv://imm_cdm:' +
|
|
6
6
|
encodeURIComponent('imm@2019') + '@imm-cdm-dev.rf6wr.mongodb.net/?retryWrites=true&w=majority',
|
|
7
7
|
COMPANY_REGISTER: 'companyregister-dev',
|
|
8
|
-
BIZA_SERVER_LINK: 'https://biz-a-dev-41e7c93a25e5.herokuapp.com'
|
|
8
|
+
// BIZA_SERVER_LINK: 'https://biz-a-dev-41e7c93a25e5.herokuapp.com'
|
|
9
9
|
// BIZA_SERVER_LINK: 'https://www.ptimf.id/biz-a-dev.com'
|
|
10
10
|
// BIZA_SERVER_LINK: 'http://localhost:3000'
|
|
11
|
+
BIZA_SERVER_LINK: 'http://59.60.1.22:3000'
|
|
11
12
|
};
|
package/envs/env.js
CHANGED
|
@@ -5,5 +5,6 @@ export const env = {
|
|
|
5
5
|
CDM_MONGO_LINK: 'mongodb+srv://imm_cdm:' +
|
|
6
6
|
encodeURIComponent('imm@2019') + '@imm-cdm.ohcqt.mongodb.net/?retryWrites=true&w=majority',
|
|
7
7
|
COMPANY_REGISTER: 'companyregister',
|
|
8
|
-
BIZA_SERVER_LINK: 'https://biz-a.herokuapp.com'
|
|
8
|
+
// BIZA_SERVER_LINK: 'https://biz-a.herokuapp.com'
|
|
9
|
+
BIZA_SERVER_LINK: 'http://localhost:3000'
|
|
9
10
|
};
|
package/mailController.js
CHANGED
|
@@ -15,12 +15,12 @@ export function sendMailWatcher(req) {
|
|
|
15
15
|
console.log(err.message);
|
|
16
16
|
return err.message;
|
|
17
17
|
} else {
|
|
18
|
-
console.log(info);
|
|
18
|
+
console.log('Info:' + info);
|
|
19
19
|
return info;
|
|
20
20
|
}
|
|
21
21
|
})
|
|
22
22
|
} catch (err) {
|
|
23
|
-
console.log(err.message);
|
|
23
|
+
console.log('Error: ' + err.message);
|
|
24
24
|
return err.message;
|
|
25
25
|
}
|
|
26
26
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "biz-a-cli",
|
|
3
3
|
"nameDev": "biz-a-cli-dev",
|
|
4
|
-
"version": "2.3.
|
|
5
|
-
"versionDev": "0.0.
|
|
4
|
+
"version": "2.3.17",
|
|
5
|
+
"versionDev": "0.0.30",
|
|
6
6
|
"description": "",
|
|
7
7
|
"main": "bin/index.js",
|
|
8
8
|
"type": "module",
|
|
@@ -24,11 +24,11 @@
|
|
|
24
24
|
"hub": "bin/hub.js",
|
|
25
25
|
"watcher": "bin/watcher.js",
|
|
26
26
|
"uploadapp": "bin/uploadApp.js",
|
|
27
|
-
"deleteapp": "bin/deleteApp.js"
|
|
27
|
+
"deleteapp": "bin/deleteApp.js",
|
|
28
|
+
"biza": "bin/app.js"
|
|
28
29
|
},
|
|
29
30
|
"dependencies": {
|
|
30
31
|
"axios": "^1.6.8",
|
|
31
|
-
"axios-observable": "^2.0.0",
|
|
32
32
|
"cors": "^2.8.5",
|
|
33
33
|
"dayjs": "^1.11.10",
|
|
34
34
|
"express": "^4.18.3",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"nodemailer": "^6.9.12",
|
|
38
38
|
"socket.io-client": "^4.7.5",
|
|
39
39
|
"socket.io-stream": "^0.9.1",
|
|
40
|
-
"tar": "^7.
|
|
40
|
+
"tar": "^7.4.0",
|
|
41
41
|
"uglify-js": "^3.17.4",
|
|
42
42
|
"web-push": "^3.6.7",
|
|
43
43
|
"winston": "^3.13.0",
|
|
@@ -48,6 +48,11 @@
|
|
|
48
48
|
"socket.io": "^4.7.5"
|
|
49
49
|
},
|
|
50
50
|
"jest": {
|
|
51
|
-
"transform": {}
|
|
51
|
+
"transform": {},
|
|
52
|
+
"testMatch": [
|
|
53
|
+
"<rootDir>/tests/**",
|
|
54
|
+
"!<rootDir>/tests/mockData",
|
|
55
|
+
"!<rootDir>/tests/mockData/**"
|
|
56
|
+
]
|
|
52
57
|
}
|
|
53
58
|
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
This package is used to setup applications within your Biz-A Platform.
|
|
2
|
+
|
|
3
|
+
I. Add BizA App
|
|
4
|
+
|
|
5
|
+
a. Using Static IP
|
|
6
|
+
|
|
7
|
+
BizA Add -s [IP of FINA API] -p [default: 212] -i [dbindex] -d [full or relative path to app folder]
|
|
8
|
+
|
|
9
|
+
Example :
|
|
10
|
+
BizA add -s http://192.168.1.1 -i 2 -d “c:\biza templates\imamatek”
|
|
11
|
+
BizA Add -s http://192.168.1.1 -p 1205 -i 2 -d “c:\biza templates\imamatek”
|
|
12
|
+
|
|
13
|
+
b. Using BizA Hub
|
|
14
|
+
|
|
15
|
+
BizA Add -s [BizA Hub Server] -i [dbindex] --sub [subdomain of BizA Hub Server] -d [full or relative path to app folder]
|
|
16
|
+
|
|
17
|
+
Example :
|
|
18
|
+
BizA Add -s https://biz-a.hub.com -i 2 –-sub imm -d “c:\biza templates\imamatek”
|
|
19
|
+
|
|
20
|
+
c. Using Domain / Sub Domain
|
|
21
|
+
|
|
22
|
+
BizA Add -s [Domain] -i [dbindex] -d [full or relative path to app folder]
|
|
23
|
+
|
|
24
|
+
Example:
|
|
25
|
+
BizA Add-s https://my.domain.com -i 2 -d “c:\biza templates\imamatek”
|
|
26
|
+
|
|
27
|
+
To get list of full argument, please type
|
|
28
|
+
|
|
29
|
+
BizA Add --help
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
II. Remove BizA App
|
|
34
|
+
|
|
35
|
+
a. Using Static IP
|
|
36
|
+
|
|
37
|
+
BizA remove -s [IP of FINA API] -p [default: 212] -i [dbindex] -n [appname | multiple appname]
|
|
38
|
+
|
|
39
|
+
Example :
|
|
40
|
+
BizA Remove -s http://192.168.1.1 -i 2
|
|
41
|
+
BizA Remove -s http://192.168.1.1 -p 1205 -i 2 -n “imamatek”
|
|
42
|
+
BizA Remove -s http://192.168.1.1 -p 1205 -i 2 -n “imamatek, spos”
|
|
43
|
+
|
|
44
|
+
b. Using BizA Hub
|
|
45
|
+
|
|
46
|
+
BizA Remove -s [BizA Hub Server] -i [dbindex] --sub [subdomain of BizA Hub Server] -n [appname | multiple appname]
|
|
47
|
+
|
|
48
|
+
Example :
|
|
49
|
+
BizA Remove -s https://biz-a.hub.com -i 2 –sub imm -n “imamatek”
|
|
50
|
+
|
|
51
|
+
c. Using Domain / Sub Domain
|
|
52
|
+
|
|
53
|
+
BizA Remove -s [Domain] -i [dbindex] -n [appname | multiple appname]
|
|
54
|
+
|
|
55
|
+
Example:
|
|
56
|
+
BizA Remove -s https://my.domain.com -i 2 -n “imamatek”
|
|
57
|
+
|
|
58
|
+
To get list of full argument, please type
|
|
59
|
+
|
|
60
|
+
BizA Add --help
|