biz-a-cli 2.3.72 → 2.3.74
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 +23 -0
- package/bin/directHubEvent.js +93 -79
- package/bin/hub.js +42 -2
- package/bin/hubEvent.js +102 -21
- package/bin/migrate.js +169 -0
- package/callbackController.js +58 -36
- package/db/db.js +37 -0
- package/db/ds.js +189 -0
- package/engine/bpm/routes.js +61 -0
- package/engine/bpm/workflow-runtime.js +1136 -0
- package/engine/bpm/workflow.js +235 -0
- package/migrations/1777727873750__apps.sql +16 -0
- package/migrations/1777727892577__bpm.sql +274 -0
- package/package.json +18 -2
- package/scheduler/datalib.js +267 -183
- package/worker/cliScriptWorker.js +63 -0
- package/worker/cliWorkerPool.js +71 -0
- package/.editorconfig +0 -16
- package/bin/log/debug.log +0 -12
- package/bin/log/error.log +0 -12
- package/bin/log/exception.log +0 -6
- package/bin/log/info.log +0 -12
- package/log/debug.log +0 -181
- package/log/error.log +0 -7
- package/log/exception.log +0 -3
- package/log/info.log +0 -6
- package/tests/app.test.js +0 -1208
- package/tests/callback.test.js +0 -42
- package/tests/config.test.js +0 -39
- package/tests/converter.test.js +0 -106
- package/tests/data.test.js +0 -487
- package/tests/deployment.test.js +0 -339
- package/tests/hub.test.js +0 -657
- package/tests/hubPublish.test.js +0 -231
- package/tests/mailCtl.test.js +0 -44
- package/tests/timer.test.js +0 -187
- package/tests/watcher.test.js +0 -352
- package/tests/watcherCtl.test.js +0 -124
package/tests/deployment.test.js
DELETED
|
@@ -1,339 +0,0 @@
|
|
|
1
|
-
import { Server as ioServer } from 'socket.io';
|
|
2
|
-
import { getAppData, onScriptChangeFromVsCode, onScriptChangeFromHubServer} from '../bin/deployEvent.js'
|
|
3
|
-
import { io as ioClient, Socket, Manager } from "socket.io-client";
|
|
4
|
-
import { expect, jest } from '@jest/globals';
|
|
5
|
-
import axios from "axios";
|
|
6
|
-
import { directHubEvent, CLIENT_ROOM } from '../bin/directHubEvent.js'
|
|
7
|
-
import { createDecipheriv } from 'node:crypto'
|
|
8
|
-
import { hubEvent } from '../bin/hubEvent.js';
|
|
9
|
-
|
|
10
|
-
describe('Deployment', () => {
|
|
11
|
-
|
|
12
|
-
const hostname = '127.0.0.1'
|
|
13
|
-
const port = 7778
|
|
14
|
-
const dbindex = 2
|
|
15
|
-
const subdomain = 'deploy'
|
|
16
|
-
|
|
17
|
-
const toPromise = (cb) => new Promise((resolve, reject) => {
|
|
18
|
-
cb(resolve)
|
|
19
|
-
setTimeout(() => reject(new Error('timeout')), 1000)
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
function freeSocketClient(sock){
|
|
23
|
-
if (sock) {
|
|
24
|
-
if (sock.connected) {
|
|
25
|
-
sock.off()
|
|
26
|
-
sock.disconnect()
|
|
27
|
-
}
|
|
28
|
-
sock.destroy()
|
|
29
|
-
sock = undefined
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
beforeEach(()=>{
|
|
34
|
-
jest.restoreAllMocks()
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
afterEach(()=>{
|
|
38
|
-
jest.restoreAllMocks()
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
it('shall get app list from database', async ()=>{
|
|
42
|
-
// Failed : check for error message
|
|
43
|
-
const requestSpy = jest.spyOn(axios, 'request').mockResolvedValueOnce({
|
|
44
|
-
status: 200,
|
|
45
|
-
statusText: 'Success',
|
|
46
|
-
data: {"recordsTotal": 2}
|
|
47
|
-
})
|
|
48
|
-
let result = await getAppData({hostname, port, dbindex, secure: true})
|
|
49
|
-
expect(requestSpy).toHaveBeenCalledWith({
|
|
50
|
-
timeout: 30*1000,
|
|
51
|
-
baseURL: `https://${hostname}:${port}`,
|
|
52
|
-
url: 'fina/rest/TOrmMethod/%22list%22',
|
|
53
|
-
method: "POST",
|
|
54
|
-
"data" : {"dbIndex":2, "object":{"columns":[
|
|
55
|
-
{"title":"app","data":"SYS$APPS.APPNAME"},
|
|
56
|
-
{"title":"metadata","data":"SYS$APPS.METADATA"}
|
|
57
|
-
]}}
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
expect(result.error).toBe('"undefined" is not valid JSON')
|
|
61
|
-
expect(result.apps).toStrictEqual([])
|
|
62
|
-
|
|
63
|
-
// Success : check for apps data
|
|
64
|
-
const expectedAppData = [
|
|
65
|
-
{'SYS$APPS.APPNAME': 'firstApp', "SYS$APPS.METADATA": {acquirer: {data: '', signature: ''}, menu: ''}},
|
|
66
|
-
{'SYS$APPS.APPNAME': 'secondApp', "SYS$APPS.METADATA": {acquirer: {data: '', signature: ''}, menu: ''}},
|
|
67
|
-
]
|
|
68
|
-
|
|
69
|
-
requestSpy.mockResolvedValueOnce({
|
|
70
|
-
status: 200,
|
|
71
|
-
statusText: 'Success',
|
|
72
|
-
data: {
|
|
73
|
-
"recordsTotal": 2,
|
|
74
|
-
data: JSON.stringify(expectedAppData)
|
|
75
|
-
}
|
|
76
|
-
})
|
|
77
|
-
result = await getAppData({hostname, port, dbindex})
|
|
78
|
-
expect(result.error).toBe(null)
|
|
79
|
-
expect(result.apps).toStrictEqual(expectedAppData)
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
it('shall log connect and disconnect', async ()=>{
|
|
83
|
-
const logSpy = jest.spyOn(console, 'log').mockImplementation()
|
|
84
|
-
let vsCodeToCLISock
|
|
85
|
-
let serverSideSock
|
|
86
|
-
const socketServer = new ioServer(1234)// mocking of CLI socket server
|
|
87
|
-
directHubEvent(socketServer, {subdomain, hostname, port: 1234, secure: false, dbindex, server: 'mockServer'})
|
|
88
|
-
try {
|
|
89
|
-
vsCodeToCLISock = await toPromise((resolve)=>{
|
|
90
|
-
const sock = ioClient(`http://${hostname}:${1234}`, {reconnection: false, query: {isDeploy: true}}).on('connect', async ()=>{
|
|
91
|
-
serverSideSock = (await socketServer.fetchSockets()).find(s=>s.id==sock.id)
|
|
92
|
-
resolve(sock)
|
|
93
|
-
})
|
|
94
|
-
})
|
|
95
|
-
expect(logSpy).toHaveBeenCalledTimes(1)
|
|
96
|
-
expect(logSpy).toHaveBeenCalledWith('<Deployer> ' + vsCodeToCLISock.id, 'connected')
|
|
97
|
-
|
|
98
|
-
logSpy.mockReset()
|
|
99
|
-
serverSideSock.disconnect()
|
|
100
|
-
expect(logSpy).toHaveBeenCalledTimes(1)
|
|
101
|
-
expect(logSpy).toHaveBeenCalledWith('<Deployer> ' + vsCodeToCLISock.id, 'disconnected. Reason : server namespace disconnect')
|
|
102
|
-
}
|
|
103
|
-
finally {
|
|
104
|
-
socketServer.close()
|
|
105
|
-
freeSocketClient(vsCodeToCLISock)
|
|
106
|
-
logSpy.mockRestore()
|
|
107
|
-
}
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
describe('from vs code', ()=>{
|
|
111
|
-
|
|
112
|
-
let cliSocketServer // mocking of CLI socket server
|
|
113
|
-
|
|
114
|
-
beforeAll(()=>{
|
|
115
|
-
cliSocketServer = new ioServer(port)// mocking of CLI socket server
|
|
116
|
-
directHubEvent(cliSocketServer, {subdomain, hostname, port, secure: false, dbindex, server: 'mockServer'})
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
afterAll(async ()=>{
|
|
120
|
-
if (cliSocketServer) {
|
|
121
|
-
(await cliSocketServer.of('').sockets).forEach((sock)=>{sock.removeAllListeners()})
|
|
122
|
-
await cliSocketServer.close()
|
|
123
|
-
}
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
it('shall have "appList" listener', async ()=>{
|
|
127
|
-
let vsCodeToCLISock
|
|
128
|
-
try {
|
|
129
|
-
jest.spyOn(console, 'log').mockImplementation()
|
|
130
|
-
jest.spyOn(axios, 'request').mockResolvedValueOnce({
|
|
131
|
-
status: 200,
|
|
132
|
-
statusText: 'Success',
|
|
133
|
-
data: {
|
|
134
|
-
"recordsTotal": 2,
|
|
135
|
-
data: JSON.stringify([
|
|
136
|
-
{'SYS$APPS.APPNAME': 'firstApp', "SYS$APPS.METADATA": {acquirer: {data: '', signature: ''}, menu: ''}},
|
|
137
|
-
{'SYS$APPS.APPNAME': 'secondApp', "SYS$APPS.METADATA": {acquirer: {data: '', signature: ''}, menu: ''}},
|
|
138
|
-
])
|
|
139
|
-
}
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
vsCodeToCLISock = await toPromise((resolve)=>{
|
|
143
|
-
const sock = ioClient(`http://${hostname}:${port}`, {query: {isDeploy:true}}).on('connect', ()=>{resolve(sock)})
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
const [error, apps] = await toPromise(resolve => {vsCodeToCLISock.emit('appList', {}, (err, data)=>{resolve([err, data])})});
|
|
147
|
-
expect(error).toBe(null);
|
|
148
|
-
expect(apps).toStrictEqual(['firstApp', 'secondApp']);
|
|
149
|
-
}
|
|
150
|
-
finally {
|
|
151
|
-
freeSocketClient(vsCodeToCLISock)
|
|
152
|
-
}
|
|
153
|
-
})
|
|
154
|
-
|
|
155
|
-
it('shall prepare deploy script', async ()=>{
|
|
156
|
-
let vsCodeToCLISock
|
|
157
|
-
let serverSideSock
|
|
158
|
-
let emitSpy
|
|
159
|
-
let broadcastSpy
|
|
160
|
-
let result
|
|
161
|
-
try {
|
|
162
|
-
jest.spyOn(console, 'log').mockImplementation()
|
|
163
|
-
|
|
164
|
-
vsCodeToCLISock = await toPromise((resolve)=>{
|
|
165
|
-
const sock = ioClient(`http://${hostname}:${port}`, {query: {isDeploy: true}}).on('connect', async ()=>{
|
|
166
|
-
serverSideSock = (await cliSocketServer.fetchSockets()).find((s)=>s.id==sock.id)
|
|
167
|
-
|
|
168
|
-
// if using socket.broadcast.emit()
|
|
169
|
-
// const mockedBroadcast = serverSideSock.newBroadcastOperator()
|
|
170
|
-
// broadcastSpy = jest.fn().mockReturnValue(mockedBroadcast) // mock it to return same broadcast object
|
|
171
|
-
// serverSideSock.newBroadcastOperator = broadcastSpy
|
|
172
|
-
|
|
173
|
-
// if using socket.to(roomName).emit()
|
|
174
|
-
const mockedBroadcast = serverSideSock.to(CLIENT_ROOM)
|
|
175
|
-
broadcastSpy = jest.spyOn(serverSideSock, 'to').mockReturnValue(mockedBroadcast) // mock it to return same broadcast object
|
|
176
|
-
|
|
177
|
-
emitSpy = jest.spyOn(mockedBroadcast, 'emit').mockImplementation()
|
|
178
|
-
|
|
179
|
-
resolve(sock)
|
|
180
|
-
})
|
|
181
|
-
})
|
|
182
|
-
const mockAESKey = Buffer.from('hAnHadaJXJaq/9fCFMNmjkrB61CBPXJid6vbtXgG8Ug=', 'base64')
|
|
183
|
-
const requestSpy = jest.spyOn(axios, 'request').mockResolvedValue({status: 200, statusText: 'Success', data: mockAESKey})
|
|
184
|
-
const deployData = {appName: 'app', fileName: 'filename.js', script: "put script here for testing"}
|
|
185
|
-
|
|
186
|
-
// Failed of empty script
|
|
187
|
-
emitSpy.mockReset()
|
|
188
|
-
result = await onScriptChangeFromVsCode(
|
|
189
|
-
serverSideSock,
|
|
190
|
-
'https://mock.server.com',
|
|
191
|
-
[{'SYS$APPS.APPNAME': 'app', "SYS$APPS.METADATA": JSON.stringify({acquirer: {data: '', signature: ''}, menu: ''})}],
|
|
192
|
-
{...deployData, ...{script: ""}}
|
|
193
|
-
)
|
|
194
|
-
expect(result.error).toBe("filename.js : Failed to compile template script.\nPlease make sure the script is correct and not returning empty result")
|
|
195
|
-
expect(result.script).toBeUndefined()
|
|
196
|
-
expect(requestSpy).not.toHaveBeenCalled()
|
|
197
|
-
expect(emitSpy).not.toHaveBeenCalled()
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
// Failed of invalid script syntax
|
|
201
|
-
emitSpy.mockReset()
|
|
202
|
-
result = await onScriptChangeFromVsCode(
|
|
203
|
-
serverSideSock,
|
|
204
|
-
'https://mock.server.com',
|
|
205
|
-
[{'SYS$APPS.APPNAME': 'app', "SYS$APPS.METADATA": JSON.stringify({acquirer: {data: '', signature: ''}, menu: ''})}],
|
|
206
|
-
{...deployData, ...{script: "invalidScript"}}
|
|
207
|
-
)
|
|
208
|
-
expect(result.error).toBe("filename.js : ReferenceError: invalidScript is not defined")
|
|
209
|
-
expect(result.script).toBeUndefined()
|
|
210
|
-
expect(requestSpy).not.toHaveBeenCalled()
|
|
211
|
-
expect(emitSpy).not.toHaveBeenCalled()
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
// Success : prepare script for BizA Client
|
|
215
|
-
emitSpy.mockReset()
|
|
216
|
-
const validScript = "get = function () {return {tableName: ''}}"
|
|
217
|
-
result = await onScriptChangeFromVsCode(
|
|
218
|
-
serverSideSock,
|
|
219
|
-
'https://mock.server.com',
|
|
220
|
-
[{'SYS$APPS.APPNAME': 'app', "SYS$APPS.METADATA": JSON.stringify({acquirer: {data: '', signature: ''}, menu: ''})}],
|
|
221
|
-
{...deployData, ...{script: validScript}}
|
|
222
|
-
)
|
|
223
|
-
expect(requestSpy).toHaveBeenCalledWith({
|
|
224
|
-
timeout: 30*1000,
|
|
225
|
-
baseURL: 'https://mock.server.com',
|
|
226
|
-
url: 'api/acquirerKey',
|
|
227
|
-
method: "POST",
|
|
228
|
-
data : {"metadata": JSON.stringify({data: '', signature: ''})}
|
|
229
|
-
})
|
|
230
|
-
expect(result.error).toBe(null)
|
|
231
|
-
|
|
232
|
-
const cipherText = Buffer.from(result.script, 'base64')
|
|
233
|
-
const decipher = createDecipheriv('aes-256-cbc', mockAESKey, cipherText.subarray(0, 16))
|
|
234
|
-
const decryptedScript = Buffer.concat([decipher.update(cipherText.subarray(16)), decipher.final()]).toString()
|
|
235
|
-
expect(decryptedScript).toBe('{"tableName":""}')
|
|
236
|
-
|
|
237
|
-
expect(emitSpy).toHaveBeenCalledTimes(1)
|
|
238
|
-
expect(emitSpy).toHaveBeenCalledWith('scriptDeploy', {appName: 'app', fileName: 'filename.js', script: result.script})
|
|
239
|
-
}
|
|
240
|
-
finally {
|
|
241
|
-
freeSocketClient(vsCodeToCLISock)
|
|
242
|
-
if (broadcastSpy) broadcastSpy.mockRestore()
|
|
243
|
-
}
|
|
244
|
-
})
|
|
245
|
-
|
|
246
|
-
it('shall have "scriptChange" listener', async ()=>{
|
|
247
|
-
let vsCodeToCLISock;
|
|
248
|
-
try {
|
|
249
|
-
jest.spyOn(console, 'log').mockImplementation()
|
|
250
|
-
vsCodeToCLISock = await toPromise((resolve)=>{
|
|
251
|
-
const sock = ioClient(`http://${hostname}:${port}`, {query: {isDeploy:true}}).on('connect', ()=>{resolve(sock)})
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
const requestSpy = jest.spyOn(axios, 'request');
|
|
255
|
-
requestSpy.mockResolvedValueOnce({
|
|
256
|
-
status: 200,
|
|
257
|
-
statusText: 'Success',
|
|
258
|
-
data: {
|
|
259
|
-
"recordsTotal": 2,
|
|
260
|
-
data: JSON.stringify([
|
|
261
|
-
{'SYS$APPS.APPNAME': 'firstApp', "SYS$APPS.METADATA": {acquirer: {data: '', signature: ''}, menu: ''}},
|
|
262
|
-
{'SYS$APPS.APPNAME': 'secondApp', "SYS$APPS.METADATA": {acquirer: {data: '', signature: ''}, menu: ''}},
|
|
263
|
-
])
|
|
264
|
-
}
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
const [error, script] = await toPromise(resolve => {vsCodeToCLISock.emit('scriptChange', {appName: 'firstApp', fileName: 'filename.js', script: ""}, (err, data)=>{resolve([err, data])})});
|
|
268
|
-
expect(error).toBe("filename.js : Failed to compile template script.\nPlease make sure the script is correct and not returning empty result");
|
|
269
|
-
expect(script).toBeNull();
|
|
270
|
-
}
|
|
271
|
-
finally {
|
|
272
|
-
freeSocketClient(vsCodeToCLISock);
|
|
273
|
-
};
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
describe('from Hub Server', ()=>{
|
|
279
|
-
|
|
280
|
-
it('shall prepare deploy script', async ()=>{
|
|
281
|
-
let result;
|
|
282
|
-
|
|
283
|
-
const mockAESKey = Buffer.from('hAnHadaJXJaq/9fCFMNmjkrB61CBPXJid6vbtXgG8Ug=', 'base64')
|
|
284
|
-
const requestSpy = jest.spyOn(axios, 'request').mockResolvedValue({status: 200, statusText: 'Success', data: mockAESKey})
|
|
285
|
-
const deployData = {appName: 'app', fileName: 'filename.js', script: "put script here for testing"}
|
|
286
|
-
|
|
287
|
-
// Failed of empty script
|
|
288
|
-
result = await onScriptChangeFromHubServer(
|
|
289
|
-
'https://mock.server.com',
|
|
290
|
-
[{'SYS$APPS.APPNAME': 'app', "SYS$APPS.METADATA": JSON.stringify({acquirer: {data: '', signature: ''}, menu: ''})}],
|
|
291
|
-
{...deployData, ...{script: ""}}
|
|
292
|
-
)
|
|
293
|
-
expect(result.error).toBe("filename.js : Failed to compile template script.\nPlease make sure the script is correct and not returning empty result")
|
|
294
|
-
expect(result.script).toBeUndefined()
|
|
295
|
-
expect(requestSpy).not.toHaveBeenCalled()
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
// Failed of invalid script syntax
|
|
299
|
-
result = await onScriptChangeFromHubServer(
|
|
300
|
-
'https://mock.server.com',
|
|
301
|
-
[{'SYS$APPS.APPNAME': 'app', "SYS$APPS.METADATA": JSON.stringify({acquirer: {data: '', signature: ''}, menu: ''})}],
|
|
302
|
-
{...deployData, ...{script: "invalidScript"}}
|
|
303
|
-
)
|
|
304
|
-
expect(result.error).toBe("filename.js : ReferenceError: invalidScript is not defined")
|
|
305
|
-
expect(result.script).toBeUndefined()
|
|
306
|
-
expect(requestSpy).not.toHaveBeenCalled()
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
// Success : prepare script for BizA Client
|
|
310
|
-
const validScript = "get = function () {return {tableName: ''}}"
|
|
311
|
-
result = await onScriptChangeFromHubServer(
|
|
312
|
-
'https://mock.server.com',
|
|
313
|
-
[{'SYS$APPS.APPNAME': 'app', "SYS$APPS.METADATA": JSON.stringify({acquirer: {data: '', signature: ''}, menu: ''})}],
|
|
314
|
-
{...deployData, ...{script: validScript}}
|
|
315
|
-
)
|
|
316
|
-
expect(requestSpy).toHaveBeenCalledWith({
|
|
317
|
-
timeout: 30*1000,
|
|
318
|
-
baseURL: 'https://mock.server.com',
|
|
319
|
-
url: 'api/acquirerKey',
|
|
320
|
-
method: "POST",
|
|
321
|
-
data : {"metadata": JSON.stringify({data: '', signature: ''})}
|
|
322
|
-
})
|
|
323
|
-
expect(result.error).toBe(null)
|
|
324
|
-
|
|
325
|
-
const cipherText = Buffer.from(result.script, 'base64')
|
|
326
|
-
const decipher = createDecipheriv('aes-256-cbc', mockAESKey, cipherText.subarray(0, 16))
|
|
327
|
-
const decryptedScript = Buffer.concat([decipher.update(cipherText.subarray(16)), decipher.final()]).toString()
|
|
328
|
-
expect(decryptedScript).toBe('{"tableName":""}')
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
it('shall have "scriptChange Listener"', ()=>{
|
|
332
|
-
const sock = new Socket(new Manager('', {autoConnect: false}), '');
|
|
333
|
-
hubEvent(sock, {subdomain, hostname, port, secure: false, dbindex, server: 'mockServer'}, ()=>{});
|
|
334
|
-
expect(sock.listeners('scriptChange').length).toBe(1);
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
})
|