biz-a-cli 2.3.55 → 2.3.57

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 CHANGED
@@ -16,7 +16,7 @@ const keyFolderPath = process.argv[1].substring(0, process.argv[1].lastIndexOf("
16
16
  yargs(process.argv.slice(2))
17
17
  .option("s", {
18
18
  alias: "server",
19
- describe: "Server URL (ex: https://biz-a.herokuapp.com or http://192.168.1.1 or https://finaapi.imamatek.com)",
19
+ describe: `Server URL (ex: ${env.BIZA_SERVER_LINK} or http://192.168.1.1 or https://finaapi.imamatek.com)`,
20
20
  type: "string",
21
21
  demandOption: true
22
22
  })
package/bin/deleteApp.js CHANGED
@@ -2,11 +2,12 @@
2
2
 
3
3
  import yargs from "yargs";
4
4
  import axios from "axios";
5
+ import { env } from "../envs/env.js"
5
6
 
6
7
  const options = yargs(process.argv.slice(2))
7
8
  .option("s", {
8
9
  alias: "server",
9
- describe: "Server URL (ex: https://biz-a.herokuapp.com or http://192.168.1.1 or https://finaapi.imamatek.com)",
10
+ describe: `Server URL (ex: ${env.BIZA_SERVER_LINK} or http://192.168.1.1 or https://finaapi.imamatek.com)`,
10
11
  type: "string",
11
12
  demandOption: true
12
13
  })
package/bin/hub.js CHANGED
@@ -7,6 +7,7 @@ import { createLogger, transports, format } from "winston";
7
7
  import { Server as ioServer } from 'socket.io'
8
8
  import os from 'node:os'
9
9
  import { directHubEvent, localhostTunnel }from './directHubEvent.js'
10
+ import { env } from "../envs/env.js"
10
11
 
11
12
  const logger = createLogger({
12
13
  level: 'info',
@@ -35,7 +36,7 @@ const argv = yargs(process.argv.slice(2))
35
36
  .usage('Usage: $0 [options]')
36
37
  .options('s', {
37
38
  alias: 'server',
38
- default: 'https://biz-a.herokuapp.com',
39
+ default: env.BIZA_SERVER_LINK,
39
40
  describe: '(Required) Tunnel server endpoint',
40
41
  type: 'string',
41
42
  demandOption: false
@@ -87,7 +88,7 @@ const argv = yargs(process.argv.slice(2))
87
88
  demandOption: false
88
89
  })
89
90
  .options('hub', {
90
- default: 'https://biz-a-hub-ed77b066db87.herokuapp.com/',
91
+ default: `${env.BIZA_HUB_SERVER_LINK}`,
91
92
  describe: 'BizA hub',
92
93
  type: 'string',
93
94
  demandOption: false
package/bin/hubEvent.js CHANGED
@@ -8,18 +8,23 @@ import { Transform } from 'node:stream'
8
8
  // import { pipeline } from 'node:stream'
9
9
 
10
10
  const IDLE_SOCKET_TIMEOUT_MILLISECONDS = 1000 * 30;
11
+ const DISCONNECT_REASON_BY_SOCKET_SERVER = 'io server disconnect'
11
12
 
12
13
  export const socketAgent = isUsingHttps=>(isUsingHttps==true) ? tls : net
13
14
 
15
+ const getIdText = id=>id ? id+' ' : ''
16
+
14
17
  export const streamEvent = async (socket, argv) => new Promise((resolve, reject) => {
18
+ let id
15
19
 
16
20
  const connectCb = () => {
21
+ id = socket.id
17
22
  socket.emit('createTunnel', argv['subdomain'], (err) => {
18
23
  if (err) {
19
- console.log(new Date() + ': [error] ' + err);
24
+ console.log(`${new Date()}: ${getIdText(id)}connection error to BizA Server. Error : ${err}`);
20
25
  reject(err);
21
26
  } else {
22
- console.log(`${new Date()}: Connected to BizA Server at ${argv.server} using sub domain "${argv['subdomain']}"`)
27
+ console.log(`${new Date()}: ${getIdText(id)}connected to BizA Server at ${argv.server} using sub domain "${argv['subdomain']}"`)
23
28
  resolve(argv['server'].toString());
24
29
  }
25
30
  });
@@ -109,6 +114,18 @@ export const streamEvent = async (socket, argv) => new Promise((resolve, reject)
109
114
  socket.on('connect', connectCb);
110
115
  socket.on('incomingClient', incomingHubCb)
111
116
  socket.on('cli-req', cliReqCb);
117
+
118
+ socket.on('disconnect', reason=>{
119
+ console.log(`${new Date()}: ${getIdText(id)}disconnected from BizA Server. Reason: ${reason}`)
120
+ id = undefined
121
+ if (reason.toLowerCase()===DISCONNECT_REASON_BY_SOCKET_SERVER) {
122
+ socket.connect()
123
+ }
124
+ })
125
+
126
+ socket.io.on('reconnect', ()=>{
127
+ console.log(`${new Date()}: ${getIdText(id)}reconnecting to BizA Server`)
128
+ })
112
129
  })
113
130
 
114
131
  export const hubEvent = (socket, argv, notifier)=>{
@@ -116,13 +133,17 @@ export const hubEvent = (socket, argv, notifier)=>{
116
133
  socket.on('connect', ()=>{
117
134
  id = socket.id
118
135
  notifier(argv['hub'])
119
- console.log(`${new Date()}: Connected to BizA Hub at ${argv['hub']} using sub domain "${argv['subdomain']}" with id "${id}"`)
136
+ console.log(`${new Date()}: ${getIdText(id)}connected to BizA Hub at ${argv['hub']} using sub domain "${argv['subdomain']}"`)
120
137
  })
121
138
  socket.on('disconnect', (reason)=>{
122
139
  notifier('')
123
- console.log(`${new Date()}: ${id||''} disconnected from BizA Hub. Reason: ${reason}`)
140
+ console.log(`${new Date()}: ${getIdText(id)}disconnected from BizA Hub. Reason: ${reason}`)
141
+ id = undefined
142
+ if (reason.toLowerCase()===DISCONNECT_REASON_BY_SOCKET_SERVER) {
143
+ socket.connect()
144
+ }
124
145
  })
125
- const logError = msg=>{console.log(`${new Date()}: ${id||''} connection error to BizA Hub. Error : ${msg}`)}
146
+ const logError = msg=>{console.log(`${new Date()}: ${getIdText(id)}connection error to BizA Hub. Error : ${msg}`)}
126
147
  socket.on('connect_error', (error)=>{
127
148
  notifier('')
128
149
  logError(error.message)
@@ -131,29 +152,46 @@ export const hubEvent = (socket, argv, notifier)=>{
131
152
  notifier('')
132
153
  logError(error)
133
154
  })
155
+ socket.io.on('reconnect', ()=>{
156
+ notifier('')
157
+ console.log(`${new Date()}: ${getIdText(id)}reconnecting to BizA Hub`)
158
+ })
134
159
  apiRequestListener(socket, argv)
135
160
  }
136
161
 
137
162
  export const apiRequestListener = (socket, argv)=>{
138
163
  socket.on('apiRequest', (reqData, resCB)=>{
164
+
165
+ let apiAddress = `${argv['secure']==true ? 'https://' : 'http://'}${argv['hostname']}:${argv['port']}`
166
+ let reqBody = reqData.body
167
+ try{
168
+ let parsedBody = (typeof reqData.body==='object') ? reqBody : JSON.parse(reqBody)
169
+ if (parsedBody.apiAddress){
170
+ apiAddress = parsedBody.apiAddress
171
+ delete parsedBody.apiAddress
172
+ reqBody = (typeof reqData.body==='string') ? JSON.stringify(parsedBody) : parsedBody
173
+ }
174
+ } catch (error) {}
175
+
139
176
  const socketResponse = (resp)=>{return {
140
177
  status: resp.status,
141
178
  statusText: resp.statusText,
142
179
  headers: resp.headers,
143
- body: resp.data, url: `${argv['hostname']}:${argv['port']+resp.config.url}`
180
+ body: resp.data,
181
+ url: apiAddress + resp.config.url
144
182
  }}
183
+
145
184
  if (argv['subdomain'].localeCompare(reqData.subDomain)==0) {
146
- const apiAddress = `${argv['secure']==true ? 'https://' : 'http://'}${argv['hostname']}:${argv['port']}`
147
185
  axios.request({
148
- timeout: (reqData.timeout || IDLE_SOCKET_TIMEOUT_MILLISECONDS),
149
- baseURL: apiAddress,
150
- url: reqData.path,
151
- method: reqData.method,
152
- headers: reqData.headers,
153
- data: reqData.body,
154
- // decompress: false, // if we need to interfered default Agent compression
155
- responseType: reqData.responseType,
156
- maxContentLength: Infinity,
186
+ timeout : (reqData.timeout || IDLE_SOCKET_TIMEOUT_MILLISECONDS),
187
+ baseURL : apiAddress,
188
+ url : reqData.path,
189
+ method : reqData.method,
190
+ headers : reqData.headers,
191
+ data : reqBody,
192
+ // decompress : false, // if we need to interfered default Agent compression
193
+ responseType : reqData.responseType,
194
+ maxContentLength : Infinity,
157
195
  })
158
196
  .then(response=>{
159
197
  resCB(null, socketResponse(response))
@@ -163,7 +201,7 @@ export const apiRequestListener = (socket, argv)=>{
163
201
  })
164
202
  }
165
203
  else {
166
- resCB({status: 401, statusText: 'bad subdomain', url: `${argv['hostname']}:${argv['port']+reqData.path}`}, null)
204
+ resCB({status: 401, statusText: 'bad subdomain', url: apiAddress + reqData.path}, null)
167
205
  }
168
206
  })
169
207
  }
package/bin/index.js CHANGED
@@ -4,11 +4,12 @@ import yargs from "yargs";
4
4
  import axios from "axios";
5
5
  import { promises as fs } from "fs";
6
6
  import { runInThisContext } from "vm";
7
+ import { env } from "../envs/env.js"
7
8
 
8
9
  const options = yargs(process.argv.slice(2))
9
10
  .option("s", {
10
11
  alias: "server",
11
- describe: "Server URL (ex: https://biz-a.herokuapp.com or http://192.168.1.1 or https://finaapi.imamatek.com)",
12
+ describe: `Server URL (ex: ${env.BIZA_SERVER_LINK} or http://192.168.1.1 or https://finaapi.imamatek.com)`,
12
13
  type: "string",
13
14
  demandOption: true
14
15
  })
package/bin/uploadApp.js CHANGED
@@ -10,14 +10,13 @@ import {statSync, readFileSync} from 'fs';
10
10
  import { verify, sign, privateDecrypt, constants as cryptoConstants, randomBytes, createCipheriv } from 'node:crypto';
11
11
  import { basename } from "node:path"
12
12
  import { env } from '../envs/env.js';
13
- import { stringify } from "querystring";
14
13
 
15
14
  const keyFolderPath = process.argv[1].substring(0, process.argv[1].lastIndexOf("\\bin")) + "\\key"
16
15
 
17
16
  const options = yargs(process.argv.slice(2))
18
17
  .option("s", {
19
18
  alias: "server",
20
- describe: "Server URL (ex: https://biz-a.herokuapp.com or http://192.168.1.1 or https://finaapi.imamatek.com)",
19
+ describe: `Server URL (ex: ${env.BIZA_SERVER_LINK} or http://192.168.1.1 or https://finaapi.imamatek.com)`,
21
20
  type: "string",
22
21
  demandOption: true
23
22
  })
@@ -124,7 +123,6 @@ const getFileMinifiedData = async (fileName) => {
124
123
  stringifyData = JSON.stringify((typeof lib.default=='function') ? lib.default() : lib.default, replacer)
125
124
  stringifyData = stringifyData.replace(/ /g,'') // remove trailing whitespace
126
125
  // 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
126
  printInfo(['Stringify : \n', stringifyData].join(''))
129
127
  } catch (error){
130
128
  throw(error)
@@ -138,7 +136,6 @@ const prepareKeys = async ()=>{
138
136
  const data = Buffer.from(JSON.stringify({issuer: 'CLI', acquirer: 'Client'})).toString('base64')
139
137
  const privateKey = readFileSync(`${keyFolderPath}\\cliPrivate.pem`)
140
138
  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
139
  const res = await axios.get(env.BIZA_SERVER_LINK+'/api/issuerKey', {params: {data, signature}})
143
140
  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
141
  const resData = JSON.parse(Buffer.from(res.data.data, 'base64').toString())
package/envs/env.dev.js CHANGED
@@ -6,5 +6,5 @@ export const envDev = {
6
6
  encodeURIComponent('imm@2019') + '@imm-cdm-dev.rf6wr.mongodb.net/?retryWrites=true&w=majority',
7
7
  COMPANY_REGISTER: 'companyregister-dev',
8
8
  BIZA_SERVER_LINK: 'https://biz-a-dev-41e7c93a25e5.herokuapp.com',
9
- // BIZA_SERVER_LINK: 'http://localhost:3000',
9
+ BIZA_HUB_SERVER_LINK: 'https://hub.biz-a.id'
10
10
  };
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://server.biz-a.id',
9
+ BIZA_HUB_SERVER_LINK: 'https://hub.biz-a.id'
9
10
  };
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.55",
4
+ "version": "2.3.57",
5
5
  "versionDev": "0.0.34",
6
6
  "description": "",
7
7
  "main": "bin/index.js",
package/readme.md CHANGED
@@ -3,13 +3,13 @@
3
3
 
4
4
  ## I. Add BizA App
5
5
 
6
- ### a. Using Static IP
6
+ ### a. Using IP Address
7
7
 
8
8
  BizA add -s [IP of FINA API] -p [default: 212] -i [dbindex] -d [full or relative path to app folder]
9
9
 
10
10
  Example :
11
11
  BizA add -s http://192.168.1.1 -i 2 -d “c:\biza templates\imamatek”
12
- BizA add -s http://192.168.1.1 -p 1205 -i 2 -d “c:\biza templates\imamatek”
12
+ BizA add -s localhost -p 1205 -i 2 -d “c:\biza templates\imamatek”
13
13
 
14
14
  ### b. Using BizA Hub
15
15
 
@@ -70,16 +70,16 @@
70
70
  hub --server [BizA Hub Server] --sub [subdomain] --hostname [ip_API] --port [port_API]
71
71
 
72
72
  Example :
73
- hub --server https://biz-a.herokuapp.com --sub imamatek --hostname localhost --port 212
73
+ hub --server https://server.biz-a.id --sub imamatek --hostname localhost --port 212
74
74
 
75
75
  ### b. Using HTTPs (SSL)
76
76
  hub --server [BizA Hub Server] --sub [subdomain] --hostname [ip_API] --port [port_API] --secure
77
77
 
78
78
  Example :
79
- hub --server https://biz-a.herokuapp.com --sub imamatek --hostname localhost --port 212 --secure
80
-
79
+ hub --server https://server.biz-a.id --sub imamatek --hostname localhost --port 212 --secure
80
+
81
81
  ### c. Publish Hub
82
82
  hub --server [BizA Hub Server] --sub [subdomain] --hostname [ip_API] --port [port_API] --publish [true]
83
83
 
84
84
  Example :
85
- hub --server https://biz-a.herokuapp.com --sub imamatek --hostname localhost --port 212 --publish
85
+ hub --server https://server.biz-a.id --sub imamatek --hostname localhost --port 212 --publish
@@ -25,17 +25,6 @@ if (process.env.NODE_ENV !== 'production') {
25
25
  logger.add(new transports.Console({ format: format.simple(), level: 'info' }))
26
26
  }
27
27
 
28
-
29
-
30
- // let BIZA_SERVER_LINK;
31
-
32
- // // if ((process.env.NODE_ENV == undefined) || (process.env.NODE_ENV == 'development')) {
33
- // if ((MODE == undefined) || (MODE == 'development')) {
34
- // BIZA_SERVER_LINK = envDev.BIZA_SERVER_LINK;
35
- // } else {
36
- // BIZA_SERVER_LINK = env.BIZA_SERVER_LINK;
37
- // };
38
-
39
28
  export function mapData2Key(res, cols) {
40
29
  return res.map(e => {
41
30
  return cols.reduce((o, k) => {
package/tests/hub.test.js CHANGED
@@ -268,7 +268,7 @@ describe('Hub event tests', () => {
268
268
  statusText: 'Success',
269
269
  headers: {'res-header': 'aa'},
270
270
  body: 'body of response',
271
- url: `${apiAddress}:${port}/test`
271
+ url: `http://${apiAddress}:${port}/test`
272
272
  })
273
273
 
274
274
  expect(error).toBe(null)
@@ -335,7 +335,7 @@ describe('Hub event tests', () => {
335
335
  expect(error).toStrictEqual({
336
336
  status: 401,
337
337
  statusText: 'bad subdomain',
338
- url: `${apiAddress}:${port}/test`
338
+ url: `http://${apiAddress}:${port}/test`
339
339
  })
340
340
 
341
341
  expect(mockedRequest).not.toHaveBeenCalledWith()
@@ -349,16 +349,6 @@ describe('Hub event tests', () => {
349
349
  let hubServer
350
350
 
351
351
  try {
352
- mockedRequest = jest.spyOn(axios, 'request')
353
- mockedRequest.mockClear()
354
- mockedRequest.mockResolvedValueOnce({
355
- status: 200,
356
- statusText: 'Success',
357
- headers: {'res-header': 'aa'},
358
- data: 'body of response',
359
- config: {baseURL: 'localhost', url: '/test'}
360
- })
361
-
362
352
  hubServer = new ioServer(9998)
363
353
  hubServer.on('connection', (sock)=>hubToCLISocket = sock)
364
354
 
@@ -381,24 +371,37 @@ describe('Hub event tests', () => {
381
371
 
382
372
  await toPromise(resolve => cliToHubSocket.once('connect', ()=>resolve()))
383
373
 
384
- const [error, response] = await toPromise(resolve => {
374
+ const emitApiRequest = async (reqData)=>{
375
+ const [error, response] = await toPromise(resolve => {
385
376
  hubToCLISocket.emit(
386
- 'apiRequest'
387
- , {subDomain: subdomain, method: 'POST', path: '/test', headers: {'req-header': 'aa'}, body: 'body of request', responseType: 'json'}
388
- , (res, err)=>{resolve([res, err])}
389
- )
377
+ 'apiRequest'
378
+ , {subDomain: subdomain, method: 'POST', path: '/test', headers: {'req-header': 'aa'}, body: reqData, responseType: 'json'}
379
+ , (res, err)=>{resolve([res, err])}
380
+ )
381
+ })
382
+ return {error, response}
383
+ }
384
+
385
+ mockedRequest = jest.spyOn(axios, 'request')
386
+ mockedRequest.mockResolvedValue({
387
+ status: 200,
388
+ statusText: 'Success',
389
+ headers: {'res-header': 'aa'},
390
+ data: 'body of response',
391
+ config: {baseURL: 'localhost', url: '/test'}
390
392
  })
391
393
 
392
- expect(response).toStrictEqual({
394
+ // without parameterize apiAddress
395
+ mockedRequest.mockClear()
396
+ let result = await emitApiRequest('body of request')
397
+ expect(result.response).toStrictEqual({
393
398
  status: 200,
394
399
  statusText: 'Success',
395
400
  headers: {'res-header': 'aa'},
396
401
  body: 'body of response',
397
- url: `127.0.0.1:${port}/test`
402
+ url: `http://127.0.0.1:${port}/test`
398
403
  })
399
-
400
- expect(error).toBe(null)
401
-
404
+ expect(result.error).toBe(null)
402
405
  expect(mockedRequest).toHaveBeenCalledWith({
403
406
  timeout: 30*1000,
404
407
  baseURL: `http://127.0.0.1:${port}`,
@@ -409,6 +412,51 @@ describe('Hub event tests', () => {
409
412
  responseType: 'json',
410
413
  maxContentLength: Infinity,
411
414
  })
415
+
416
+ // parameterize API address as String
417
+ mockedRequest.mockClear()
418
+ result = await emitApiRequest(JSON.stringify({other: 'data', apiAddress: 'http://apiHost:apiPort'}))
419
+ expect(result.response).toStrictEqual({
420
+ status: 200,
421
+ statusText: 'Success',
422
+ headers: {'res-header': 'aa'},
423
+ body: 'body of response',
424
+ url: 'http://apiHost:apiPort/test'
425
+ })
426
+ expect(result.error).toBe(null)
427
+ expect(mockedRequest).toHaveBeenCalledWith({
428
+ timeout: 30*1000,
429
+ baseURL: 'http://apiHost:apiPort',
430
+ url: '/test',
431
+ method: "POST",
432
+ headers: {'req-header': 'aa'},
433
+ data: JSON.stringify({other: 'data'}),
434
+ responseType: 'json',
435
+ maxContentLength: Infinity,
436
+ })
437
+
438
+ // parameterize API address as Object
439
+ mockedRequest.mockClear()
440
+ result = await emitApiRequest({other: 'data', apiAddress: 'http://apiHost:apiPort'})
441
+ expect(result.response).toStrictEqual({
442
+ status: 200,
443
+ statusText: 'Success',
444
+ headers: {'res-header': 'aa'},
445
+ body: 'body of response',
446
+ url: 'http://apiHost:apiPort/test'
447
+ })
448
+ expect(result.error).toBe(null)
449
+ expect(mockedRequest).toHaveBeenCalledWith({
450
+ timeout: 30*1000,
451
+ baseURL: 'http://apiHost:apiPort',
452
+ url: '/test',
453
+ method: "POST",
454
+ headers: {'req-header': 'aa'},
455
+ data: {other: 'data'},
456
+ responseType: 'json',
457
+ maxContentLength: Infinity,
458
+ })
459
+
412
460
  }
413
461
  finally {
414
462
  freeSocketClient(cliToHubSocket)