biz-a-cli 2.3.8 → 2.3.10
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/deleteApp.js +67 -0
- package/bin/hub.js +7 -2
- package/bin/hubEvent.js +9 -8
- package/bin/index.js +22 -3
- package/bin/uploadApp.js +263 -0
- package/callbackController.js +11 -4
- package/envs/env.dev.js +2 -1
- package/envs/env.js +2 -1
- package/key/cliPrivate.pem +54 -0
- package/key/serverPublic.pem +14 -0
- package/package.json +7 -3
- package/tests/callback.test.js +16 -3
- package/tests/hub.test.js +90 -88
package/bin/deleteApp.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import yargs from "yargs";
|
|
4
|
+
import axios from "axios";
|
|
5
|
+
|
|
6
|
+
const options = yargs(process.argv.slice(2))
|
|
7
|
+
.option("s", {
|
|
8
|
+
alias: "server",
|
|
9
|
+
describe: "Server URL (ex: https://biz-a.herokuapp.com or http://192.168.1.1 or https://finaapi.imamatek.com)",
|
|
10
|
+
type: "string",
|
|
11
|
+
demandOption: true
|
|
12
|
+
})
|
|
13
|
+
.option("i", {
|
|
14
|
+
alias: "dbindex",
|
|
15
|
+
describe: "database index",
|
|
16
|
+
type: "number",
|
|
17
|
+
demandOption: true
|
|
18
|
+
})
|
|
19
|
+
.option("n", {
|
|
20
|
+
alias: "appName",
|
|
21
|
+
describe: "Application name",
|
|
22
|
+
type: "string",
|
|
23
|
+
demandOption: true,
|
|
24
|
+
default: ""
|
|
25
|
+
})
|
|
26
|
+
.option("sub", {
|
|
27
|
+
alias: "subdomain",
|
|
28
|
+
describe: "Subdomain",
|
|
29
|
+
type: "string",
|
|
30
|
+
demandOption: false
|
|
31
|
+
})
|
|
32
|
+
.option("p", {
|
|
33
|
+
alias: "apiPort",
|
|
34
|
+
describe: "FINA API Port",
|
|
35
|
+
type: "string",
|
|
36
|
+
demandOption: false,
|
|
37
|
+
default : "212"
|
|
38
|
+
})
|
|
39
|
+
.argv;
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
const deleteApp = async () => {
|
|
44
|
+
try {
|
|
45
|
+
const baseUrl = 'fina/rest/TOrmMethod/%22deleteApp%22'
|
|
46
|
+
const url = options.sub ?
|
|
47
|
+
`${options.server}/hub/${baseUrl}?subdomain=${options.sub}` :
|
|
48
|
+
`${options.server}:${options.apiPort}/${baseUrl}`
|
|
49
|
+
const headers = {'Content-Type': 'text/plain'}
|
|
50
|
+
const deleteApps = options.appName.trim().replace(' ', '').toLowerCase()
|
|
51
|
+
const param = { _parameters: [options.dbindex, deleteApps] }
|
|
52
|
+
const res = await axios.post(url, param, { headers: headers });
|
|
53
|
+
if (res.data.success) {
|
|
54
|
+
console.log(`${deleteApps=='' ? 'All' : deleteApps} apps removed`)
|
|
55
|
+
} else {
|
|
56
|
+
console.error(res.data.error)
|
|
57
|
+
}
|
|
58
|
+
} catch (e) {
|
|
59
|
+
console.error(e.response?.data ? e.response.data : e)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
deleteApp()
|
|
64
|
+
|
|
65
|
+
// delete all apps ==>> deleteApp -s https://finaapi.imamatek.com:1205 -i 2
|
|
66
|
+
// delete specific apps ==>> deleteApp -s https://finaapi.imamatek.com:1205 -i 2 -n "imamatek"
|
|
67
|
+
// delete multiple apps ==>> deleteApp -s https://finaapi.imamatek.com:1205 -i 2 -n "imamatek, spos"
|
package/bin/hub.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import yargs from 'yargs';
|
|
4
4
|
import { io as ioc } from "socket.io-client";
|
|
@@ -77,6 +77,7 @@ app.use(express.json());
|
|
|
77
77
|
|
|
78
78
|
app.set('args', argv);
|
|
79
79
|
|
|
80
|
+
|
|
80
81
|
app.use('/cb', runCliScript);
|
|
81
82
|
|
|
82
83
|
app.listen((argv.serverport || port), () => {
|
|
@@ -85,4 +86,8 @@ app.listen((argv.serverport || port), () => {
|
|
|
85
86
|
//
|
|
86
87
|
|
|
87
88
|
let socket = ioc(argv['server']);
|
|
88
|
-
hubEvent(socket, argv);
|
|
89
|
+
hubEvent(socket, argv);
|
|
90
|
+
|
|
91
|
+
app.set('socket', socket)
|
|
92
|
+
|
|
93
|
+
export { app }
|
package/bin/hubEvent.js
CHANGED
|
@@ -8,7 +8,7 @@ const IDLE_SOCKET_TIMEOUT_MILLISECONDS = 1000 * 30;
|
|
|
8
8
|
|
|
9
9
|
// export default (argv) => {
|
|
10
10
|
export default async (socket, argv) => new Promise((resolve, reject) => {
|
|
11
|
-
|
|
11
|
+
const connectCb = () => {
|
|
12
12
|
console.log(new Date() + ': connected to socket server');
|
|
13
13
|
console.log(new Date() + ': requesting subdomain ' + argv['subdomain'] + ' via ' + argv['server']);
|
|
14
14
|
|
|
@@ -30,9 +30,8 @@ export default async (socket, argv) => new Promise((resolve, reject) => {
|
|
|
30
30
|
resolve(url);
|
|
31
31
|
}
|
|
32
32
|
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
socket.on('incomingClient', (clientId) => {
|
|
33
|
+
}
|
|
34
|
+
const incomingHubCb = (clientId) => {
|
|
36
35
|
console.log(clientId, 'incoming clientId')
|
|
37
36
|
let client = net.connect(argv['port'], argv['hostname']);
|
|
38
37
|
|
|
@@ -58,9 +57,8 @@ export default async (socket, argv) => new Promise((resolve, reject) => {
|
|
|
58
57
|
ss(socket).emit(clientId, s);
|
|
59
58
|
s.end();
|
|
60
59
|
});
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
socket.on('cli-req', (data, callback) => {
|
|
60
|
+
}
|
|
61
|
+
const cliReqCb = (data, callback) => {
|
|
64
62
|
const { path, method, ...remainData } = data;
|
|
65
63
|
|
|
66
64
|
Axios.request({
|
|
@@ -68,5 +66,8 @@ export default async (socket, argv) => new Promise((resolve, reject) => {
|
|
|
68
66
|
url: `${process.env.HOST || 'http://localhost'}:${argv.serverport}/cb${path || ''}`,
|
|
69
67
|
data: remainData
|
|
70
68
|
}).subscribe(result => callback(result.data));
|
|
71
|
-
}
|
|
69
|
+
}
|
|
70
|
+
socket.on('connect', connectCb);
|
|
71
|
+
socket.on('incomingClient', incomingHubCb)
|
|
72
|
+
socket.on('cli-req', cliReqCb );
|
|
72
73
|
})
|
package/bin/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import { runInThisContext } from "vm";
|
|
|
8
8
|
const options = yargs(process.argv.slice(2))
|
|
9
9
|
.option("s", {
|
|
10
10
|
alias: "server",
|
|
11
|
-
describe: "Server URL",
|
|
11
|
+
describe: "Server URL (ex: https://biz-a.herokuapp.com or http://192.168.1.1 or https://finaapi.imamatek.com)",
|
|
12
12
|
type: "string",
|
|
13
13
|
demandOption: true
|
|
14
14
|
})
|
|
@@ -30,13 +30,21 @@ const options = yargs(process.argv.slice(2))
|
|
|
30
30
|
type: "string",
|
|
31
31
|
demandOption: false
|
|
32
32
|
})
|
|
33
|
+
.option("p", {
|
|
34
|
+
alias: "apiPort",
|
|
35
|
+
describe: "FINA API Port",
|
|
36
|
+
type: "string",
|
|
37
|
+
demandOption: false,
|
|
38
|
+
default : "212"
|
|
39
|
+
})
|
|
33
40
|
.argv;
|
|
34
41
|
|
|
35
42
|
const sendFile = async (filename, data) => {
|
|
36
43
|
const baseUrl = 'fina/rest/TOrmMethod/%22setTemplate%22'
|
|
37
44
|
const url = options.sub ?
|
|
38
45
|
`${options.server}/hub/${baseUrl}?subdomain=${options.sub}` :
|
|
39
|
-
`http://${options.server}:212/${baseUrl}`
|
|
46
|
+
// `http://${options.server}:212/${baseUrl}`
|
|
47
|
+
`${options.server}:${options.apiPort}/${baseUrl}`
|
|
40
48
|
|
|
41
49
|
const headers = {
|
|
42
50
|
'Content-Type': 'text/plain'
|
|
@@ -51,6 +59,8 @@ function getParam(funcName) {
|
|
|
51
59
|
}
|
|
52
60
|
|
|
53
61
|
function replacer(key, value) {
|
|
62
|
+
// note : cannot handle inline function such as :
|
|
63
|
+
// onClick: $event=>this.router.navigate(['../list', 'listspk'])
|
|
54
64
|
if (typeof value == 'function') {
|
|
55
65
|
let arr = value.toString().replace(/(\r\n|\n|\r)/gm, "°").split("°");
|
|
56
66
|
if (arr.length < 3) throw 'Function must be minimal 3 lines';
|
|
@@ -76,7 +86,8 @@ const readTemplateFile = async (filename) => {
|
|
|
76
86
|
} catch (error) {
|
|
77
87
|
const fn = `file://${process.cwd()}\\${filename}`;
|
|
78
88
|
const lib = await import(fn);
|
|
79
|
-
result = JSON.stringify(lib.default(), replacer);
|
|
89
|
+
// result = JSON.stringify(lib.default(), replacer);
|
|
90
|
+
result = JSON.stringify((typeof lib.default=='function') ? lib.default() : lib.default, replacer);
|
|
80
91
|
}
|
|
81
92
|
|
|
82
93
|
return Buffer.from(result).toString('hex');
|
|
@@ -88,8 +99,10 @@ const readTemplateFile = async (filename) => {
|
|
|
88
99
|
}
|
|
89
100
|
|
|
90
101
|
const loopFiles = async (dir) => {
|
|
102
|
+
const uploadStart = performance.now()
|
|
91
103
|
try {
|
|
92
104
|
const files = await fs.readdir(dir);
|
|
105
|
+
let processedFile = 0
|
|
93
106
|
for (const file of files) {
|
|
94
107
|
//const p = path.join(dir, file);
|
|
95
108
|
if (file == 'package.json' || file == 'package-lock.json') continue;
|
|
@@ -101,11 +114,13 @@ const loopFiles = async (dir) => {
|
|
|
101
114
|
const res = await sendFile(file, data.toString('hex'));
|
|
102
115
|
if (res.data.success) {
|
|
103
116
|
console.log(`file: ${file} uploaded`);
|
|
117
|
+
processedFile++
|
|
104
118
|
} else {
|
|
105
119
|
console.error(res.data.error);
|
|
106
120
|
}
|
|
107
121
|
}
|
|
108
122
|
}
|
|
123
|
+
console.log(`Finished uploading ${processedFile} files (${((performance.now()-uploadStart)/1000).toFixed(2)}s)`)
|
|
109
124
|
} catch (e) {
|
|
110
125
|
// console.error(e.response && e.response.data ? e.response.data : e);
|
|
111
126
|
console.error(e.response?.data ? e.response.data : e);
|
|
@@ -113,3 +128,7 @@ const loopFiles = async (dir) => {
|
|
|
113
128
|
}
|
|
114
129
|
|
|
115
130
|
loopFiles('./');
|
|
131
|
+
|
|
132
|
+
// ex :
|
|
133
|
+
// uploadbiza -s https:\\finaapi.imamatek.com:1205 -i 2
|
|
134
|
+
// ..cli/bin/index.js -s https:\\finaapi.imamatek.com:1205 -i 2
|
package/bin/uploadApp.js
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import yargs from "yargs";
|
|
4
|
+
import axios from "axios";
|
|
5
|
+
import { promises as fs } from "fs";
|
|
6
|
+
import { runInNewContext, runInThisContext } from "vm";
|
|
7
|
+
import uglify from "uglify-js";
|
|
8
|
+
import * as tar from "tar";
|
|
9
|
+
import {statSync, readFileSync} from 'fs';
|
|
10
|
+
import { verify, sign, privateDecrypt, constants as cryptoConstants, randomBytes, createCipheriv } from 'node:crypto';
|
|
11
|
+
import { basename } from "node:path"
|
|
12
|
+
import { env } from '../envs/env.js';
|
|
13
|
+
import { stringify } from "querystring";
|
|
14
|
+
|
|
15
|
+
const keyFolderPath = process.argv[1].substring(0, process.argv[1].lastIndexOf("\\bin")) + "\\key"
|
|
16
|
+
|
|
17
|
+
const options = yargs(process.argv.slice(2))
|
|
18
|
+
.option("s", {
|
|
19
|
+
alias: "server",
|
|
20
|
+
describe: "Server URL (ex: https://biz-a.herokuapp.com or http://192.168.1.1 or https://finaapi.imamatek.com)",
|
|
21
|
+
type: "string",
|
|
22
|
+
demandOption: true
|
|
23
|
+
})
|
|
24
|
+
.option("i", {
|
|
25
|
+
alias: "dbindex",
|
|
26
|
+
describe: "database index",
|
|
27
|
+
type: "number",
|
|
28
|
+
demandOption: true
|
|
29
|
+
})
|
|
30
|
+
.option("d", {
|
|
31
|
+
alias: "workingDir",
|
|
32
|
+
describe: "Path to templates directory",
|
|
33
|
+
type: "string",
|
|
34
|
+
demandOption: false,
|
|
35
|
+
default: process.cwd(),
|
|
36
|
+
})
|
|
37
|
+
.option("sub", {
|
|
38
|
+
alias: "subdomain",
|
|
39
|
+
describe: "Subdomain",
|
|
40
|
+
type: "string",
|
|
41
|
+
demandOption: false
|
|
42
|
+
})
|
|
43
|
+
.option("v", {
|
|
44
|
+
alias: "verbose",
|
|
45
|
+
describe: "Print info to console",
|
|
46
|
+
type: "boolean",
|
|
47
|
+
demandOption: false,
|
|
48
|
+
default: false,
|
|
49
|
+
})
|
|
50
|
+
.option("p", {
|
|
51
|
+
alias: "apiPort",
|
|
52
|
+
describe: "FINA API Port",
|
|
53
|
+
type: "string",
|
|
54
|
+
demandOption: false,
|
|
55
|
+
default : "212"
|
|
56
|
+
})
|
|
57
|
+
.argv;
|
|
58
|
+
|
|
59
|
+
function printInfo(msg){if (options.verbose) {console.log(msg)}}
|
|
60
|
+
|
|
61
|
+
function replacer(key, value) {
|
|
62
|
+
/*
|
|
63
|
+
// with line break
|
|
64
|
+
if (typeof value == 'function') {
|
|
65
|
+
let arr = value.toString().replace(/(\r\n|\n|\r)/gm, "°").split("°");
|
|
66
|
+
if (arr.length < 3) throw 'Function must be minimal 3 lines';
|
|
67
|
+
return [
|
|
68
|
+
'window.Function',
|
|
69
|
+
getParam(arr[0]),
|
|
70
|
+
arr.slice(1, arr.length - 1)
|
|
71
|
+
];
|
|
72
|
+
} else {
|
|
73
|
+
return value;
|
|
74
|
+
}
|
|
75
|
+
*/
|
|
76
|
+
|
|
77
|
+
// without line break
|
|
78
|
+
if (typeof value == 'function') {
|
|
79
|
+
const fnScript = value.toString()
|
|
80
|
+
let params, body = ''
|
|
81
|
+
if (fnScript.indexOf('{')==-1) {
|
|
82
|
+
const arr = fnScript.split('=>')
|
|
83
|
+
params = arr[0]
|
|
84
|
+
body = arr.slice(1).join()
|
|
85
|
+
} else {
|
|
86
|
+
params = fnScript.split('{')[0]
|
|
87
|
+
body = fnScript.substring(fnScript.indexOf('{')+1, fnScript.lastIndexOf('}'))
|
|
88
|
+
}
|
|
89
|
+
params = params.replace(/(\s|=>|\(|\)|function)/gim, '')
|
|
90
|
+
printInfo(['window.Function', params, body])
|
|
91
|
+
return ['window.Function', params, body]
|
|
92
|
+
} else {
|
|
93
|
+
return value;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const getFileMinifiedData = async (fileName) => {
|
|
98
|
+
const dataFile = await fs.readFile(fileName);
|
|
99
|
+
printInfo(`===================\n${fileName.toUpperCase()}\n===================`)
|
|
100
|
+
|
|
101
|
+
let jsMinData = uglify.minify(dataFile.toString(), {compress: false, mangle: false}).code
|
|
102
|
+
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
|
|
103
|
+
const minifiedBuffer = Buffer.from(jsMinData)
|
|
104
|
+
|
|
105
|
+
printInfo(['Minify : \n', minifiedBuffer.toString()].join(''))
|
|
106
|
+
let stringifyData = ''
|
|
107
|
+
try {
|
|
108
|
+
printInfo('Running script with VM')
|
|
109
|
+
// const vmResult = runInThisContext(minifiedBuffer.toString())
|
|
110
|
+
const vmResult = runInNewContext(minifiedBuffer.toString()) // to handle if "let" function not using global scope
|
|
111
|
+
if (!vmResult) {
|
|
112
|
+
throw new Error('Undefined VM result')
|
|
113
|
+
}
|
|
114
|
+
printInfo('Array function :')
|
|
115
|
+
stringifyData = JSON.stringify((typeof vmResult=='function') ? vmResult() : vmResult, replacer)
|
|
116
|
+
printInfo(['Stringify : \n', stringifyData].join(''))
|
|
117
|
+
} catch (error) {
|
|
118
|
+
printInfo(error) // Do not log it as error
|
|
119
|
+
try {
|
|
120
|
+
printInfo('Running script with Import function')
|
|
121
|
+
const fn = `file://${process.cwd()}\\${fileName}`
|
|
122
|
+
const lib = await import(fn)
|
|
123
|
+
printInfo('Array function :')
|
|
124
|
+
stringifyData = JSON.stringify((typeof lib.default=='function') ? lib.default() : lib.default, replacer)
|
|
125
|
+
stringifyData = stringifyData.replace(/ /g,'') // remove trailing whitespace
|
|
126
|
+
// stringifyData = stringifyData.replace(/\\r\\n/g,'') // remove line break. We don't do this because "inline css" still requires line breaks
|
|
127
|
+
// console.log('RESULT =>', stringifyData)
|
|
128
|
+
printInfo(['Stringify : \n', stringifyData].join(''))
|
|
129
|
+
} catch (error){
|
|
130
|
+
throw(error)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
printInfo('===================')
|
|
134
|
+
return Buffer.from(stringifyData)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const prepareKeys = async ()=>{
|
|
138
|
+
const data = Buffer.from(JSON.stringify({issuer: 'CLI', acquirer: 'Client'})).toString('base64')
|
|
139
|
+
const privateKey = readFileSync(`${keyFolderPath}\\cliPrivate.pem`)
|
|
140
|
+
const signature = sign('sha256', data, {key: privateKey, passphrase: 'Biz-A@cli', padding: cryptoConstants.RSA_PKCS1_PSS_PADDING}).toString('base64')
|
|
141
|
+
// const res = await axios.get('https://biz-a.herokuapp.com/api/issuerKey', {data, signature})
|
|
142
|
+
const res = await axios.get(env.BIZA_SERVER_LINK+'/api/issuerKey', {params: {data, signature}})
|
|
143
|
+
if ((res.data.data!=null) && verify('sha256', res.data.data, {key: readFileSync(`${keyFolderPath}\\serverPublic.pem`), padding: cryptoConstants.RSA_PKCS1_PSS_PADDING}, Buffer.from(res.data.signature, 'base64'))) {
|
|
144
|
+
const resData = JSON.parse(Buffer.from(res.data.data, 'base64').toString())
|
|
145
|
+
const decryptedAESKey = privateDecrypt({key: privateKey, passphrase: 'Biz-A@cli', padding: cryptoConstants.RSA_PKCS1_OAEP_PADDING}, Buffer.from(resData.issuer.key, 'base64')).toString()
|
|
146
|
+
const cliSignature = (signedData)=>sign('sha256', signedData, {key: privateKey, passphrase: 'Biz-A@cli', padding: cryptoConstants.RSA_PKCS1_PSS_PADDING}).toString('base64')
|
|
147
|
+
const acquirerData = Buffer.from(JSON.stringify(resData.acquirer)).toString('base64')
|
|
148
|
+
const signature = cliSignature(acquirerData)
|
|
149
|
+
return {encryptKey: decryptedAESKey, metadata: {acquirer: {data: acquirerData, signature}}}
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
return null
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const encryptIt = (data, encryptKey)=>{
|
|
157
|
+
const initializeVector = randomBytes(16) // "iv" is unique for each template file
|
|
158
|
+
const cipher = createCipheriv('aes-256-cbc', Buffer.from(encryptKey, 'base64'), initializeVector)
|
|
159
|
+
return Buffer.concat([initializeVector, cipher.update(data), cipher.final()]) // we put "iv" at beginning of cipherText, seperate it when doing decryption
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const compressIt = async (fileName, folderPath)=>{
|
|
163
|
+
let compressSuccess = false
|
|
164
|
+
const maxRetry = 10
|
|
165
|
+
let retryCount = 0
|
|
166
|
+
do {
|
|
167
|
+
tar.c({file: fileName, cwd: folderPath, gzip: {level:9}, strict: true, sync: true}, await fs.readdir(folderPath))
|
|
168
|
+
compressSuccess = true
|
|
169
|
+
tar.t({file: fileName, cwd: folderPath, sync: true, onentry: (entry)=>{
|
|
170
|
+
if (entry.size==0) {
|
|
171
|
+
compressSuccess = false
|
|
172
|
+
}
|
|
173
|
+
}})
|
|
174
|
+
if (compressSuccess==false) {
|
|
175
|
+
await fs.unlink(fileName)
|
|
176
|
+
retryCount++
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
while ((compressSuccess==false) && (retryCount<=maxRetry))
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const uploadTemplateApps = async () => {
|
|
183
|
+
/*
|
|
184
|
+
hex => 2 char = 1 bytes => can be encrypted
|
|
185
|
+
base64 => 4 char = 3 bytes => can be encrypted. Smaller size compare to Hex
|
|
186
|
+
utf8 => 1 char = 1 - 4 bytes => can not be encrypted, encryption need precise bytes per Character. Smallest Size compare to Hex and base64
|
|
187
|
+
*/
|
|
188
|
+
process.chdir(options.workingDir)
|
|
189
|
+
try {
|
|
190
|
+
const bundlingStart = performance.now()
|
|
191
|
+
const rootFolder = './upload/'
|
|
192
|
+
const bundleName = basename(process.cwd()).trim().replace(' ', '').toLowerCase()
|
|
193
|
+
const bundleFolder = rootFolder+bundleName+'/'
|
|
194
|
+
const files = (await fs.readdir(process.cwd())).filter(fileName=>{
|
|
195
|
+
const stat = statSync(fileName)
|
|
196
|
+
return stat.isFile() && (stat.size>0) && ((fileName.split('.').pop().toLowerCase().match(/^(js)$/) || (fileName.toLowerCase()=='menu.json')))
|
|
197
|
+
})
|
|
198
|
+
if (files.length>0) {
|
|
199
|
+
const keys = await prepareKeys()
|
|
200
|
+
let processedFile = 0
|
|
201
|
+
await fs.rm(rootFolder, {force: true, recursive: true})
|
|
202
|
+
await fs.mkdir(bundleFolder, {recursive: true})
|
|
203
|
+
for (const file of files) {
|
|
204
|
+
const fileName = file.toLowerCase();
|
|
205
|
+
// if (['finalib.js', 'solib.js'].indexOf(fileName)==-1) {continue}
|
|
206
|
+
const minifiedData = await getFileMinifiedData(fileName);
|
|
207
|
+
const encryptedData = encryptIt(minifiedData, keys.encryptKey)
|
|
208
|
+
if (fileName=='menu.json') {
|
|
209
|
+
keys.metadata['menu'] = encryptedData.toString('base64')
|
|
210
|
+
} else {
|
|
211
|
+
fs.writeFile(bundleFolder+fileName, encryptedData.toString('base64'))
|
|
212
|
+
}
|
|
213
|
+
processedFile++
|
|
214
|
+
}
|
|
215
|
+
const bundleFile = `${rootFolder}${bundleName}.tgz`
|
|
216
|
+
await compressIt(bundleFile, bundleFolder)
|
|
217
|
+
console.log(`Finished packing ${processedFile} files into "${bundleFile}" (${((performance.now()-bundlingStart)/1000).toFixed(2)}s)`)
|
|
218
|
+
|
|
219
|
+
// send to FINAPI
|
|
220
|
+
const uploadingStart = performance.now()
|
|
221
|
+
const data = (await fs.readFile(bundleFile)).toString('base64') // *.tgz to base64String
|
|
222
|
+
const baseUrl = 'fina/rest/TOrmMethod/%22setApp%22'
|
|
223
|
+
const url = options.sub ?
|
|
224
|
+
`${options.server}/hub/${baseUrl}?subdomain=${options.sub}` :
|
|
225
|
+
`${options.server}:${options.apiPort}/${baseUrl}`
|
|
226
|
+
const headers = {'Content-Type': 'text/plain'}
|
|
227
|
+
const param = { _parameters: [options.dbindex, bundleName, data, keys.metadata] }
|
|
228
|
+
const res = await axios.post(url, param, { headers: headers });
|
|
229
|
+
if (res.data.success) {
|
|
230
|
+
console.log(`Finished uploading "${bundleFile}" (${((performance.now()-uploadingStart)/1000).toFixed(2)}s)`)
|
|
231
|
+
await fs.rm(rootFolder, {force: true, recursive: true})
|
|
232
|
+
} else {
|
|
233
|
+
console.error(res.data.error)
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
} catch (e) {
|
|
237
|
+
console.error(e.response?.data ? e.response.data : e)
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
await uploadTemplateApps()
|
|
242
|
+
|
|
243
|
+
/* const testCompressor = async ()=>{
|
|
244
|
+
const loopCount = 10000
|
|
245
|
+
let errorCount = 0
|
|
246
|
+
for(var i=1; i<=loopCount;i++){
|
|
247
|
+
console.log(i);
|
|
248
|
+
await uploadTemplateApps()
|
|
249
|
+
tar.t({file:'upload/spos.tgz', onentry: (entry)=>{
|
|
250
|
+
if (entry.size==0) {
|
|
251
|
+
console.log(`${i} : Empty file found...`, entry.type, entry.path, entry.size)
|
|
252
|
+
errorCount++
|
|
253
|
+
}
|
|
254
|
+
}})
|
|
255
|
+
}
|
|
256
|
+
console.log(`${errorCount} error of ${loopCount}`)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
testCompressor() */
|
|
260
|
+
|
|
261
|
+
// uploadApp -s https://finaapi.imamatek.com -p 1205 -i 2 -d "C:\agung\source\biza templates\imamatek"
|
|
262
|
+
// ..\cli\bin\uploadApp.js -s https://finaapi.imamatek.com:1205 -i 2 -d "C:\agung\source\biza templates\imamatek"
|
|
263
|
+
// uploadApp -s https://finaapi.imamatek.com:1205 -i 2 -d ".\imamatek"
|
package/callbackController.js
CHANGED
|
@@ -6,10 +6,14 @@ export function getInputScript(req) {
|
|
|
6
6
|
return {
|
|
7
7
|
data: {
|
|
8
8
|
arguments: args,
|
|
9
|
-
body: req.body.body
|
|
9
|
+
body: req.body.body,
|
|
10
|
+
path: req.path,
|
|
11
|
+
query: req.body.query,
|
|
12
|
+
headers: req.body.headers,
|
|
13
|
+
socket : req.app.settings.socket,
|
|
10
14
|
},
|
|
11
15
|
selectedConfig: {
|
|
12
|
-
|
|
16
|
+
url: `http://${args.hostname}:${args.port}`,
|
|
13
17
|
dbindex: args.dbindex,
|
|
14
18
|
subdomain: args.subdomain
|
|
15
19
|
}
|
|
@@ -17,13 +21,16 @@ export function getInputScript(req) {
|
|
|
17
21
|
}
|
|
18
22
|
|
|
19
23
|
export async function runCliScript(req, res) {
|
|
24
|
+
|
|
20
25
|
const { data, selectedConfig } = getInputScript(req);
|
|
21
|
-
|
|
26
|
+
// console.log('runCliScript data', data)
|
|
22
27
|
loadCliScript(selectedConfig, req.body.query).subscribe({
|
|
23
28
|
next: async script => {
|
|
24
29
|
let functions = extractFunctionScript(script);
|
|
25
30
|
if (functions) {
|
|
26
|
-
|
|
31
|
+
let respon = await functions.onInit(data);
|
|
32
|
+
// console.log('respon cb', respon)
|
|
33
|
+
res.send(respon);
|
|
27
34
|
console.log(`Run Callback Successfully!`);
|
|
28
35
|
} else {
|
|
29
36
|
res.send('CLI Script does not exist.');
|
package/envs/env.dev.js
CHANGED
|
@@ -5,6 +5,7 @@ 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
|
+
BIZA_SERVER_LINK: 'http://localhost:3000'
|
|
9
10
|
// BIZA_SERVER_LINK: 'http://localhost:3000'
|
|
10
11
|
};
|
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
|
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
|
2
|
+
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
|
|
54
|
+
-----END ENCRYPTED PRIVATE KEY-----
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
-----BEGIN PUBLIC KEY-----
|
|
2
|
+
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsygI0CgE30zwazWnM50i
|
|
3
|
+
otXV3FvisoG1oIlpCquhif6aJYCREy6gnn+RFxspMcrCX6dVGjWyEHC9yznOzzO+
|
|
4
|
+
xsPEtzyDWMtqxbfx1rTwVB60qBv1ewvGOWv9KBv8xaMyC+BreLL/iUTH3HjJLV5/
|
|
5
|
+
hcxYibMfGWzYaLAFnHSNwtDfTeraK2MEVjMreMR5tThCHbp/nGIUAWYp9Z/jj09X
|
|
6
|
+
6mbNHT4DL0SRwR7SKFmMmGmgxi8M4Qp6tRYYpx7QvmaXq8KDWL3cIvVwTBW6H+KW
|
|
7
|
+
yhhWvqyGZ9OKV5OLVzdSmeEesV3eTxv6EgRDIoODSn4MLIwHuIGOlRgeuNahm4nB
|
|
8
|
+
MwVkOBDMaf1k8bHrSf+CY7oyf0f1nlxdwZv5kmixEcifL8Ie7XhKO076duwpKyda
|
|
9
|
+
vuv5QdsCJ0aO3Kqq/F1QUYYJgtVsERKE+OFCjLaetqQXy+wlt+naAsUSKsNDBq0h
|
|
10
|
+
XsZPZZxP5+nNjkRyNtujz70iOm1s/oPmkJ1MeqLBFonCW8tkbwKbc2c+iMwXLqE7
|
|
11
|
+
g2TBHzpvJmW3V9h9nJkdits37mi8rP1DQHlhEH/PL6Rd6q+XJ4Owze0eCZOWaMD2
|
|
12
|
+
8FdeodSiQd7mDZssooGsFvjjklo9PMnQfwDJXWwc2GoyCzfJo3KKpeKT/4HuVtfn
|
|
13
|
+
zyxyuV/3sV3hnO7jvuNSILECAwEAAQ==
|
|
14
|
+
-----END PUBLIC KEY-----
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "biz-a-cli",
|
|
3
3
|
"nameDev": "biz-a-cli-dev",
|
|
4
|
-
"version": "2.3.
|
|
4
|
+
"version": "2.3.10",
|
|
5
5
|
"versionDev": "0.0.27",
|
|
6
6
|
"description": "",
|
|
7
7
|
"main": "bin/index.js",
|
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
"uploadbiza": "bin/index.js",
|
|
23
23
|
"proxy": "bin/proxy.js",
|
|
24
24
|
"hub": "bin/hub.js",
|
|
25
|
-
"watcher": "bin/watcher.js"
|
|
25
|
+
"watcher": "bin/watcher.js",
|
|
26
|
+
"uploadapp": "bin/uploadApp.js",
|
|
27
|
+
"deleteapp": "bin/deleteApp.js"
|
|
26
28
|
},
|
|
27
29
|
"dependencies": {
|
|
28
30
|
"axios": "^1.6.8",
|
|
@@ -36,6 +38,8 @@
|
|
|
36
38
|
"socket.io-client": "^4.7.5",
|
|
37
39
|
"socket.io-stream": "^0.9.1",
|
|
38
40
|
"web-push": "^3.6.7",
|
|
41
|
+
"tar": "^7.1.0",
|
|
42
|
+
"uglify-js": "^3.17.4",
|
|
39
43
|
"yargs": "^17.7.2"
|
|
40
44
|
},
|
|
41
45
|
"devDependencies": {
|
|
@@ -45,4 +49,4 @@
|
|
|
45
49
|
"jest": {
|
|
46
50
|
"transform": {}
|
|
47
51
|
}
|
|
48
|
-
}
|
|
52
|
+
}
|
package/tests/callback.test.js
CHANGED
|
@@ -20,21 +20,34 @@ describe('callback test', () => {
|
|
|
20
20
|
|
|
21
21
|
const request = {
|
|
22
22
|
app: { settings: { args: args } },
|
|
23
|
-
body: {
|
|
23
|
+
body: {
|
|
24
|
+
body: { body1: 'value1' },
|
|
25
|
+
headers:{connection:'keep-alive'}
|
|
26
|
+
},
|
|
27
|
+
path:'pqr',
|
|
28
|
+
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
expect(getInputScript(request)).toStrictEqual({
|
|
27
32
|
data: {
|
|
28
33
|
arguments: args,
|
|
29
|
-
body: { body1: 'value1' }
|
|
34
|
+
body: { body1: 'value1' },
|
|
35
|
+
path:'pqr',
|
|
36
|
+
query:undefined,
|
|
37
|
+
headers:{
|
|
38
|
+
connection:'keep-alive'
|
|
39
|
+
},
|
|
40
|
+
socket:undefined,
|
|
41
|
+
|
|
30
42
|
},
|
|
31
43
|
selectedConfig: {
|
|
32
|
-
|
|
44
|
+
url: 'http://localhost:212',
|
|
33
45
|
dbindex: 2,
|
|
34
46
|
subdomain: 'abc'
|
|
35
47
|
}
|
|
36
48
|
});
|
|
37
49
|
});
|
|
38
50
|
|
|
51
|
+
|
|
39
52
|
})
|
|
40
53
|
|
package/tests/hub.test.js
CHANGED
|
@@ -9,104 +9,106 @@ import { Axios } from "axios-observable";
|
|
|
9
9
|
let socketsBySubdomain = {};
|
|
10
10
|
|
|
11
11
|
const createSocket2CLI = (socket) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
return (subdomain, responseCb) => {
|
|
13
|
+
const responseCallback = (error) => { if (responseCb) responseCb(error) }
|
|
14
|
+
let subdomainStr = subdomain.toString();
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
socketsBySubdomain[subdomainStr] = socket;
|
|
17
|
+
socket.subdomain = subdomainStr;
|
|
18
|
+
// console.log(new Date() + ': ' + subdomainStr + ' registered successfully');
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
responseCallback(null);
|
|
21
|
+
}
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
const deleteSubdomain = (socket) => () => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
if (socket.subdomain) {
|
|
26
|
+
delete socketsBySubdomain[socket.subdomain];
|
|
27
|
+
console.log(new Date() + ': ' + socket.subdomain + ' unregistered');
|
|
28
|
+
}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
const toPromise = (cb) => new Promise((resolve, reject) => {
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
cb(resolve)
|
|
33
|
+
setTimeout(() => reject(new Error('timeout')), 1000)
|
|
34
34
|
})
|
|
35
35
|
|
|
36
36
|
describe('cli req test', () => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
beforeAll((done) => {
|
|
50
|
-
const httpServer = createServer()
|
|
51
|
-
io = startSocket(httpServer)
|
|
52
|
-
|
|
53
|
-
httpServer.listen(async () => {
|
|
54
|
-
port = httpServer.address().port;
|
|
55
|
-
done()
|
|
56
|
-
})
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
afterAll(() => {
|
|
60
|
-
io.close();
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
test('request to cli', async () => {
|
|
64
|
-
let mockedRequest = jest.spyOn(Axios, 'request').mockReturnValue(of({ data: 'OK' }));
|
|
65
|
-
|
|
66
|
-
let socket;
|
|
67
|
-
try {
|
|
68
|
-
socket = ioc(`http://localhost:${port}`);
|
|
69
|
-
await hubEvent(socket, {
|
|
70
|
-
server: `http://localhost:${port}`,
|
|
71
|
-
subdomain: 'scy',
|
|
72
|
-
hostname: 'localhost',
|
|
73
|
-
port: 212,
|
|
74
|
-
serverport: 3002
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
let result = await toPromise(resolve => socketsBySubdomain['scy'].emit(
|
|
78
|
-
'cli-req', {
|
|
79
|
-
// path: '/a/b',
|
|
80
|
-
method: 'POST',
|
|
81
|
-
query: { subdomain: 'abc' }, body: { data: 'xyz' }
|
|
82
|
-
}, cb => resolve(cb)
|
|
83
|
-
))
|
|
84
|
-
|
|
85
|
-
expect(result).toStrictEqual('OK');
|
|
86
|
-
expect(mockedRequest).toHaveBeenCalledWith({
|
|
87
|
-
data: { body: { data: "xyz" }, query: { subdomain: "abc" } },
|
|
88
|
-
method: "POST",
|
|
89
|
-
url: "http://localhost:3002/cb"
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
result = await toPromise(resolve => socketsBySubdomain['scy'].emit(
|
|
93
|
-
'cli-req', {
|
|
94
|
-
path: '/a/b',
|
|
95
|
-
method: 'POST',
|
|
96
|
-
query: { subdomain: 'abc' }, body: { data: 'xyz' }
|
|
97
|
-
}, cb => resolve(cb)
|
|
98
|
-
))
|
|
99
|
-
|
|
100
|
-
expect(result).toStrictEqual('OK');
|
|
101
|
-
expect(mockedRequest).toHaveBeenCalledWith({
|
|
102
|
-
data: { body: { data: "xyz" }, query: { subdomain: "abc" } },
|
|
103
|
-
method: "POST",
|
|
104
|
-
url: "http://localhost:3002/cb/a/b",
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
socket.disconnect();
|
|
108
|
-
} catch (error) {
|
|
109
|
-
console.log(error);
|
|
37
|
+
let io, port;
|
|
38
|
+
const startSocket = function startSocket(server) {
|
|
39
|
+
let io = new Server(server);
|
|
40
|
+
io.on('connection', (socket) => {
|
|
41
|
+
// console.log('socket client connect')
|
|
42
|
+
socket.on('createTunnel', createSocket2CLI(socket));
|
|
43
|
+
socket.on('disconnect', deleteSubdomain(socket));
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return io;
|
|
110
47
|
}
|
|
111
|
-
|
|
48
|
+
|
|
49
|
+
beforeAll((done) => {
|
|
50
|
+
const httpServer = createServer()
|
|
51
|
+
io = startSocket(httpServer)
|
|
52
|
+
|
|
53
|
+
httpServer.listen(async () => {
|
|
54
|
+
port = httpServer.address().port;
|
|
55
|
+
done()
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
afterAll(() => {
|
|
60
|
+
io.close();
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('request to cli', async () => {
|
|
64
|
+
let mockedRequest = jest.spyOn(Axios, 'request').mockReturnValue(of({ data: 'OK' }));
|
|
65
|
+
|
|
66
|
+
let socket;
|
|
67
|
+
try {
|
|
68
|
+
socket = ioc(`http://localhost:${port}`);
|
|
69
|
+
await hubEvent(socket, {
|
|
70
|
+
server: `http://localhost:${port}`,
|
|
71
|
+
subdomain: 'scy',
|
|
72
|
+
hostname: 'localhost',
|
|
73
|
+
port: 212,
|
|
74
|
+
serverport: 3002
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
let result = await toPromise(resolve => socketsBySubdomain['scy'].emit(
|
|
78
|
+
'cli-req',
|
|
79
|
+
{
|
|
80
|
+
// path: '/a/b',
|
|
81
|
+
method: 'POST',
|
|
82
|
+
query: { subdomain: 'abc' }, body: { data: 'xyz' }
|
|
83
|
+
},
|
|
84
|
+
cb => resolve(cb)
|
|
85
|
+
))
|
|
86
|
+
|
|
87
|
+
expect(result).toStrictEqual('OK');
|
|
88
|
+
expect(mockedRequest).toHaveBeenCalledWith({
|
|
89
|
+
data: { body: { data: "xyz" }, query: { subdomain: "abc" } },
|
|
90
|
+
method: "POST",
|
|
91
|
+
url: "http://localhost:3002/cb"
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
result = await toPromise(resolve => socketsBySubdomain['scy'].emit(
|
|
95
|
+
'cli-req', {
|
|
96
|
+
path: '/a/b',
|
|
97
|
+
method: 'POST',
|
|
98
|
+
query: { subdomain: 'abc' }, body: { data: 'xyz' }
|
|
99
|
+
}, cb => resolve(cb)
|
|
100
|
+
))
|
|
101
|
+
|
|
102
|
+
expect(result).toStrictEqual('OK');
|
|
103
|
+
expect(mockedRequest).toHaveBeenCalledWith({
|
|
104
|
+
data: { body: { data: "xyz" }, query: { subdomain: "abc" } },
|
|
105
|
+
method: "POST",
|
|
106
|
+
url: "http://localhost:3002/cb/a/b",
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
socket.disconnect();
|
|
110
|
+
} catch (error) {
|
|
111
|
+
console.log(error);
|
|
112
|
+
}
|
|
113
|
+
})
|
|
112
114
|
})
|