w-converhp 2.0.4 → 2.0.6
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/README.md +6 -6
- package/dist/w-converhp-client.umd.js +2 -2
- package/dist/w-converhp-client.umd.js.map +1 -1
- package/dist/w-converhp-server.umd.js +2 -2
- package/dist/w-converhp-server.umd.js.map +1 -1
- package/docs/WConverhpClient.html +1 -1
- package/docs/WConverhpClient.mjs.html +4 -4
- package/docs/WConverhpServer.html +3 -3
- package/docs/WConverhpServer.mjs.html +33 -85
- package/docs/index.html +1 -1
- package/package.json +2 -2
- package/scla.mjs +8 -3
- package/sclb.mjs +9 -3
- package/sclc.mjs +10 -4
- package/src/WConverhpClient.mjs +3 -3
- package/src/WConverhpServer.mjs +31 -83
- package/src/mergeFiles.mjs +96 -0
- package/src/mergeFiles.wk.umd.js +1 -0
- package/srv.mjs +18 -13
- package/test/1mb.7z +0 -0
- package/test/executeWithFile.test.mjs +191 -0
- package/test/executeWithU8a.test.mjs +185 -0
- package/test/uploadLargeFile.test.mjs +149 -0
- package/toolg/gDistRollup.mjs +56 -47
- package/test/all.test.mjs +0 -10
package/src/WConverhpServer.mjs
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
1
|
import fs from 'fs'
|
|
2
|
+
import stream from 'stream'
|
|
3
3
|
import Hapi from '@hapi/hapi'
|
|
4
4
|
import Inert from '@hapi/inert' //提供靜態檔案
|
|
5
|
-
import stream from 'stream'
|
|
6
5
|
import get from 'lodash-es/get.js'
|
|
7
6
|
import genPm from 'wsemi/src/genPm.mjs'
|
|
8
7
|
import iseobj from 'wsemi/src/iseobj.mjs'
|
|
@@ -19,8 +18,8 @@ import obj2u8arr from 'wsemi/src/obj2u8arr.mjs'
|
|
|
19
18
|
import u8arr2obj from 'wsemi/src/u8arr2obj.mjs'
|
|
20
19
|
import fsIsFolder from 'wsemi/src/fsIsFolder.mjs'
|
|
21
20
|
import fsCreateFolder from 'wsemi/src/fsCreateFolder.mjs'
|
|
22
|
-
import
|
|
23
|
-
import
|
|
21
|
+
import mergeFiles from './mergeFiles.wk.umd.js'
|
|
22
|
+
// import mergeFiles from './mergeFiles.mjs'
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
/**
|
|
@@ -56,7 +55,7 @@ import fsDeleteFile from 'wsemi/src/fsDeleteFile.mjs'
|
|
|
56
55
|
* //new
|
|
57
56
|
* let wo = new WConverhpServer(opt)
|
|
58
57
|
*
|
|
59
|
-
* wo.on('execute',
|
|
58
|
+
* wo.on('execute', (func, input, pm) => {
|
|
60
59
|
* // console.log(`Server[port:${opt.port}]: execute`, func, input)
|
|
61
60
|
* console.log(`Server[port:${opt.port}]: execute`, func)
|
|
62
61
|
*
|
|
@@ -98,7 +97,7 @@ import fsDeleteFile from 'wsemi/src/fsDeleteFile.mjs'
|
|
|
98
97
|
* }
|
|
99
98
|
*
|
|
100
99
|
* })
|
|
101
|
-
* wo.on('upload',
|
|
100
|
+
* wo.on('upload', (input, pm) => {
|
|
102
101
|
* console.log(`Server[port:${opt.port}]: upload`, input)
|
|
103
102
|
*
|
|
104
103
|
* try {
|
|
@@ -106,12 +105,12 @@ import fsDeleteFile from 'wsemi/src/fsDeleteFile.mjs'
|
|
|
106
105
|
* pm.resolve(output)
|
|
107
106
|
* }
|
|
108
107
|
* catch (err) {
|
|
109
|
-
* console.log('
|
|
110
|
-
* pm.reject('
|
|
108
|
+
* console.log('upload error', err)
|
|
109
|
+
* pm.reject('upload error')
|
|
111
110
|
* }
|
|
112
111
|
*
|
|
113
112
|
* })
|
|
114
|
-
* wo.on('handler',
|
|
113
|
+
* wo.on('handler', (data) => {
|
|
115
114
|
* // console.log(`Server[port:${opt.port}]: handler`, data)
|
|
116
115
|
* })
|
|
117
116
|
*
|
|
@@ -197,6 +196,10 @@ function WConverhpServer(opt = {}) {
|
|
|
197
196
|
//host: 'localhost',
|
|
198
197
|
port,
|
|
199
198
|
routes: {
|
|
199
|
+
timeout: {
|
|
200
|
+
server: false, //關閉伺服器超時
|
|
201
|
+
socket: false, //關閉socket超時
|
|
202
|
+
},
|
|
200
203
|
cors: {
|
|
201
204
|
origin: corsOrigins, //Access-Control-Allow-Origin
|
|
202
205
|
credentials: false, //Access-Control-Allow-Credentials
|
|
@@ -313,8 +316,8 @@ function WConverhpServer(opt = {}) {
|
|
|
313
316
|
parse: false,
|
|
314
317
|
},
|
|
315
318
|
timeout: {
|
|
316
|
-
|
|
317
|
-
|
|
319
|
+
server: false, //關閉伺服器超時
|
|
320
|
+
socket: false, //關閉socket超時
|
|
318
321
|
},
|
|
319
322
|
},
|
|
320
323
|
handler: async function (req, res) {
|
|
@@ -471,8 +474,8 @@ function WConverhpServer(opt = {}) {
|
|
|
471
474
|
parse: false,
|
|
472
475
|
},
|
|
473
476
|
timeout: {
|
|
474
|
-
|
|
475
|
-
|
|
477
|
+
server: false, //關閉伺服器超時
|
|
478
|
+
socket: false, //關閉socket超時
|
|
476
479
|
},
|
|
477
480
|
},
|
|
478
481
|
handler: async function (req, res) {
|
|
@@ -617,8 +620,8 @@ function WConverhpServer(opt = {}) {
|
|
|
617
620
|
parse: true, //前端送obj過來
|
|
618
621
|
},
|
|
619
622
|
timeout: {
|
|
620
|
-
|
|
621
|
-
|
|
623
|
+
server: false, //關閉伺服器超時
|
|
624
|
+
socket: false, //關閉socket超時
|
|
622
625
|
},
|
|
623
626
|
},
|
|
624
627
|
handler: async function (req, res) {
|
|
@@ -692,78 +695,13 @@ function WConverhpServer(opt = {}) {
|
|
|
692
695
|
return res.response({ error: 'invalid packageId in payload' }).code(400)
|
|
693
696
|
}
|
|
694
697
|
|
|
695
|
-
//merge
|
|
696
|
-
let merge = async () => {
|
|
697
|
-
let errTemp = ''
|
|
698
|
-
|
|
699
|
-
//pathFileMerge
|
|
700
|
-
let pathFileMerge = path.join(pathUploadTemp, `${packageId}`)
|
|
701
|
-
// console.log('pathFileMerge', pathFileMerge)
|
|
702
|
-
|
|
703
|
-
//fileStream
|
|
704
|
-
let fileStream = fs.createWriteStream(pathFileMerge)
|
|
705
|
-
// console.log(`merge filename[${filename}] start`)
|
|
706
|
-
|
|
707
|
-
//使用try catch攔截,使stream能完整創造與結束
|
|
708
|
-
try {
|
|
709
|
-
for (let i = 0; i < chunkTotal; i++) {
|
|
710
|
-
// console.log(`merge ${i + 1}/${chunkTotal}`)
|
|
711
|
-
|
|
712
|
-
//chunkIndex
|
|
713
|
-
let chunkIndex = i
|
|
714
|
-
|
|
715
|
-
//pathFileChunk
|
|
716
|
-
let pathFileChunk = path.join(pathUploadTemp, `${packageId}_${chunkIndex}`)
|
|
717
|
-
|
|
718
|
-
//check
|
|
719
|
-
if (!fsIsFile(pathFileChunk)) {
|
|
720
|
-
// console.log(`pathFileChunk[${pathFileChunk}] is not a file`)
|
|
721
|
-
throw new Error(`Missing chunk ${i} of filename[${filename}]`)
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
// console.log(`merging chunk[${chunkIndex + 1}/${chunkTotal}]...`)
|
|
725
|
-
|
|
726
|
-
//chunkData
|
|
727
|
-
let chunkData = fs.readFileSync(pathFileChunk)
|
|
728
|
-
|
|
729
|
-
//write
|
|
730
|
-
fileStream.write(chunkData)
|
|
731
|
-
|
|
732
|
-
//fsDeleteFile
|
|
733
|
-
fsDeleteFile(pathFileChunk)
|
|
734
|
-
|
|
735
|
-
// console.log(`merge chunk[${chunkIndex + 1}/${chunkTotal}] done`)
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
catch (err) {
|
|
739
|
-
errTemp = err.message
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
//end
|
|
743
|
-
fileStream.end()
|
|
744
|
-
// console.log(`merge filename[${filename}] done`)
|
|
745
|
-
|
|
746
|
-
//check
|
|
747
|
-
if (isestr(errTemp)) {
|
|
748
|
-
return Promise.reject(errTemp)
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
//r
|
|
752
|
-
let r = {
|
|
753
|
-
// message: `Merged filename[${filename}] successfully`,
|
|
754
|
-
filename,
|
|
755
|
-
path: pathFileMerge,
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
return r
|
|
759
|
-
}
|
|
760
|
-
|
|
761
698
|
//core
|
|
762
699
|
let core = async() => {
|
|
763
700
|
|
|
764
701
|
//merge
|
|
765
702
|
// console.log('merge start')
|
|
766
|
-
let r = await merge()
|
|
703
|
+
// let r = await merge()
|
|
704
|
+
let r = await mergeFiles(pathUploadTemp, packageId, chunkTotal, filename)
|
|
767
705
|
// console.log('merge done', r)
|
|
768
706
|
|
|
769
707
|
//procUpload
|
|
@@ -781,6 +719,7 @@ function WConverhpServer(opt = {}) {
|
|
|
781
719
|
out.success = msg
|
|
782
720
|
})
|
|
783
721
|
.catch(function(msg) {
|
|
722
|
+
console.log('bbb msg', msg)
|
|
784
723
|
out.error = msg
|
|
785
724
|
})
|
|
786
725
|
// console.log('out', out)
|
|
@@ -839,12 +778,21 @@ function WConverhpServer(opt = {}) {
|
|
|
839
778
|
|
|
840
779
|
//start
|
|
841
780
|
if (get(opt, 'serverHapi')) {
|
|
842
|
-
opt.serverHapi.route([apiMain, apiSlice, apiSliceMerge])
|
|
781
|
+
// opt.serverHapi.route([apiMain, apiSlice, apiSliceMerge])
|
|
782
|
+
server.route([apiMain, apiSlice, apiSliceMerge])
|
|
843
783
|
}
|
|
844
784
|
else {
|
|
845
785
|
startServer()
|
|
846
786
|
}
|
|
847
787
|
|
|
788
|
+
//stop
|
|
789
|
+
let stop = () => {
|
|
790
|
+
server.stop()
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
//save
|
|
794
|
+
ee.stop = stop
|
|
795
|
+
|
|
848
796
|
return ee
|
|
849
797
|
}
|
|
850
798
|
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import genPm from 'wsemi/src/genPm.mjs'
|
|
4
|
+
import isestr from 'wsemi/src/isestr.mjs'
|
|
5
|
+
import fsIsFile from 'wsemi/src/fsIsFile.mjs'
|
|
6
|
+
import fsDeleteFile from 'wsemi/src/fsDeleteFile.mjs'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
let mergeFiles = async (pathUploadTemp, packageId, chunkTotal, filename) => {
|
|
10
|
+
let errTemp = ''
|
|
11
|
+
|
|
12
|
+
let pm = genPm()
|
|
13
|
+
|
|
14
|
+
//pathFileMerge
|
|
15
|
+
let pathFileMerge = path.join(pathUploadTemp, packageId)
|
|
16
|
+
// console.log('pathFileMerge', pathFileMerge)
|
|
17
|
+
|
|
18
|
+
//fileStream
|
|
19
|
+
let fileStream = fs.createWriteStream(pathFileMerge)
|
|
20
|
+
// console.log(`merge filename[${filename}] start`)
|
|
21
|
+
|
|
22
|
+
//使用try catch攔截,使stream能完整創造與結束
|
|
23
|
+
try {
|
|
24
|
+
for (let i = 0; i < chunkTotal; i++) {
|
|
25
|
+
// console.log(`merge ${i + 1}/${chunkTotal}`)
|
|
26
|
+
|
|
27
|
+
//chunkIndex
|
|
28
|
+
let chunkIndex = i
|
|
29
|
+
|
|
30
|
+
//pathFileChunk
|
|
31
|
+
let pathFileChunk = path.join(pathUploadTemp, `${packageId}_${chunkIndex}`)
|
|
32
|
+
|
|
33
|
+
//check
|
|
34
|
+
if (!fsIsFile(pathFileChunk)) {
|
|
35
|
+
// console.log(`pathFileChunk[${pathFileChunk}] is not a file`)
|
|
36
|
+
throw new Error(`missing chunk ${i} of filename[${filename}]`)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// console.log(`merging chunk[${chunkIndex + 1}/${chunkTotal}]...`)
|
|
40
|
+
|
|
41
|
+
//chunkData
|
|
42
|
+
let chunkData = fs.readFileSync(pathFileChunk)
|
|
43
|
+
|
|
44
|
+
//write
|
|
45
|
+
fileStream.write(chunkData)
|
|
46
|
+
|
|
47
|
+
//fsDeleteFile
|
|
48
|
+
fsDeleteFile(pathFileChunk)
|
|
49
|
+
|
|
50
|
+
// console.log(`merge chunk[${chunkIndex + 1}/${chunkTotal}] done`)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
errTemp = err.message
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//end
|
|
58
|
+
fileStream.end()
|
|
59
|
+
|
|
60
|
+
//error
|
|
61
|
+
fileStream.on('error', (err) => {
|
|
62
|
+
errTemp = err.message
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
//finish, end之後檔案未必完成寫入, 得要監聽finish才能確定寫入檔案完成
|
|
66
|
+
fileStream.on('finish', () => {
|
|
67
|
+
// console.log(`merge filename[${filename}] end`)
|
|
68
|
+
|
|
69
|
+
//check
|
|
70
|
+
if (isestr(errTemp)) {
|
|
71
|
+
|
|
72
|
+
//reject
|
|
73
|
+
pm.reject(errTemp)
|
|
74
|
+
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
|
|
78
|
+
//r
|
|
79
|
+
let r = {
|
|
80
|
+
filename,
|
|
81
|
+
path: pathFileMerge,
|
|
82
|
+
}
|
|
83
|
+
// let s = fs.statSync(pathFileMerge)
|
|
84
|
+
// console.log('s.size', s.size)
|
|
85
|
+
|
|
86
|
+
//resolve
|
|
87
|
+
pm.resolve(r)
|
|
88
|
+
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
return pm
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export default mergeFiles
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(g,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("worker_threads")):"function"==typeof define&&define.amd?define(["worker_threads"],e):(g="undefined"!=typeof globalThis?globalThis:g||self).mergeFiles=e(g.worker_threads)}(this,(function(g){"use strict";"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;var e={};!function(e,C){e.exports=function(g){var e={};!function(g){var e=Object.prototype.hasOwnProperty,C="~";function I(){}function t(g,e,C){this.fn=g,this.context=e,this.once=C||!1}function n(g,e,I,n,A){if("function"!=typeof I)throw new TypeError("The listener must be a function");var o=new t(I,n||g,A),c=C?C+e:e;return g._events[c]?g._events[c].fn?g._events[c]=[g._events[c],o]:g._events[c].push(o):(g._events[c]=o,g._eventsCount++),g}function A(g,e){0==--g._eventsCount?g._events=new I:delete g._events[e]}function o(){this._events=new I,this._eventsCount=0}Object.create&&(I.prototype=Object.create(null),(new I).__proto__||(C=!1)),o.prototype.eventNames=function(){var g,I,t=[];if(0===this._eventsCount)return t;for(I in g=this._events)e.call(g,I)&&t.push(C?I.slice(1):I);return Object.getOwnPropertySymbols?t.concat(Object.getOwnPropertySymbols(g)):t},o.prototype.listeners=function(g){var e=C?C+g:g,I=this._events[e];if(!I)return[];if(I.fn)return[I.fn];for(var t=0,n=I.length,A=new Array(n);t<n;t++)A[t]=I[t].fn;return A},o.prototype.listenerCount=function(g){var e=C?C+g:g,I=this._events[e];return I?I.fn?1:I.length:0},o.prototype.emit=function(g,e,I,t,n,A){var o=C?C+g:g;if(!this._events[o])return!1;var c,i,r=this._events[o],l=arguments.length;if(r.fn){switch(r.once&&this.removeListener(g,r.fn,void 0,!0),l){case 1:return r.fn.call(r.context),!0;case 2:return r.fn.call(r.context,e),!0;case 3:return r.fn.call(r.context,e,I),!0;case 4:return r.fn.call(r.context,e,I,t),!0;case 5:return r.fn.call(r.context,e,I,t,n),!0;case 6:return r.fn.call(r.context,e,I,t,n,A),!0}for(i=1,c=new Array(l-1);i<l;i++)c[i-1]=arguments[i];r.fn.apply(r.context,c)}else{var s,u=r.length;for(i=0;i<u;i++)switch(r[i].once&&this.removeListener(g,r[i].fn,void 0,!0),l){case 1:r[i].fn.call(r[i].context);break;case 2:r[i].fn.call(r[i].context,e);break;case 3:r[i].fn.call(r[i].context,e,I);break;case 4:r[i].fn.call(r[i].context,e,I,t);break;default:if(!c)for(s=1,c=new Array(l-1);s<l;s++)c[s-1]=arguments[s];r[i].fn.apply(r[i].context,c)}}return!0},o.prototype.on=function(g,e,C){return n(this,g,e,C,!1)},o.prototype.once=function(g,e,C){return n(this,g,e,C,!0)},o.prototype.removeListener=function(g,e,I,t){var n=C?C+g:g;if(!this._events[n])return this;if(!e)return A(this,n),this;var o=this._events[n];if(o.fn)o.fn!==e||t&&!o.once||I&&o.context!==I||A(this,n);else{for(var c=0,i=[],r=o.length;c<r;c++)(o[c].fn!==e||t&&!o[c].once||I&&o[c].context!==I)&&i.push(o[c]);i.length?this._events[n]=1===i.length?i[0]:i:A(this,n)}return this},o.prototype.removeAllListeners=function(g){var e;return g?(e=C?C+g:g,this._events[e]&&A(this,e)):(this._events=new I,this._eventsCount=0),this},o.prototype.off=o.prototype.removeListener,o.prototype.addListener=o.prototype.on,o.prefixed=C,o.EventEmitter=o,g.exports=o}({get exports(){return e},set exports(g){e=g}});var C=e;let I;!function(){if("nodejs"!=("undefined"!=typeof window&&void 0!==window.document?"browser":"nodejs"))return null;let e=(t="CgogICAgICAgIC8vaW1wb3J0IHsgcGFyZW50UG9ydCB9IGZyb20gJ3dvcmtlcl90aHJlYWRzJwogICAgICAgIGxldCB7IHBhcmVudFBvcnQgfSA9IHJlcXVpcmUoJ3dvcmtlcl90aHJlYWRzJykgLy/lm6BwYWNrYWdlLmpzb27kuI3ntaZ0eXBlPW1vZHVsZeaVheeEoeazleaUr+aPtGVzNiBpbXBvcnQsIOW+l+S9v+eUqHJlcXVpcmUKICAgICAgICAvL+iLpeimgeaWvG5vZGVqcyB3b3JrZXLlhafkvb/nlKjnhKHms5Xnt6jora/nmoTljp/nlJ/lpZfku7bkvovlpoJmcywg6YG/5YWN5L2/55So6aCC5bGkaW1wb3J05Yqg6LyJ5L2/55SoLCDlm6DnhKHms5Xnt6jora/mnIPnm7TmjqXkv53nlZkKICAgICAgICAvL+S4puWboGltcG9ydOS9jeaWvHdvcmtlcuWkluWxpOmZkOWumueCunJlcXVpcmXljYAocGFja2FnZS5qc29u5LiN57WmdHlwZT1tb2R1bGUpLCDmlYXlh7rnj77pjK/oqqTnhKHms5Xnt6jora8KICAgICAgICAKCiJ1c2Ugc3RyaWN0Ijt2YXIgZT1yZXF1aXJlKCJwYXRoIikscj1yZXF1aXJlKCJmcyIpO2Z1bmN0aW9uIHQoZSl7cmV0dXJuISghZnVuY3Rpb24oZSl7cmV0dXJuIltvYmplY3QgU3RyaW5nXSI9PT1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoZSl9KGUpfHwiIj09PWUpfWZ1bmN0aW9uIG4oZSl7cmV0dXJuISFyLmV4aXN0c1N5bmMoZSkmJighci5sc3RhdFN5bmMoZSkuaXNEaXJlY3RvcnkoKSYmIXIubHN0YXRTeW5jKGUpLmlzU3ltYm9saWNMaW5rKCkpfWZ1bmN0aW9uIGkoZSl7aWYoIXIuZXhpc3RzU3luYyhlKSlyZXR1cm57c3VjY2VzczoiZmlsZSBkb2VzIG5vdCBleGlzdDogIitlfTtpZighbihlKSlyZXR1cm57ZXJyb3I6ImlucHV0IHBhdGggaXMgbm90IGEgZmlsZTogIitlfTt0cnl7ci51bmxpbmtTeW5jKGUpfWNhdGNoKGUpe3JldHVybntlcnJvcjplfX1yZXR1cm57c3VjY2VzczoiZG9uZTogIitlfX1sZXQgbWVyZ2VGaWxlcz1hc3luYyhzLG8sYyx1KT0+e2xldCBsPSIiLGE9ZnVuY3Rpb24oKXtsZXQgZSxyLHQ9bmV3IFByb21pc2UoKGZ1bmN0aW9uKCl7ZT1hcmd1bWVudHNbMF0scj1hcmd1bWVudHNbMV19KSk7cmV0dXJuIHQucmVzb2x2ZT1lLHQucmVqZWN0PXIsdH0oKSxmPWUuam9pbihzLG8pLHk9ci5jcmVhdGVXcml0ZVN0cmVhbShmKTt0cnl7Zm9yKGxldCB0PTA7dDxjO3QrKyl7bGV0IGM9dCxsPWUuam9pbihzLGAke299XyR7Y31gKTtpZighbihsKSl0aHJvdyBuZXcgRXJyb3IoYG1pc3NpbmcgY2h1bmsgJHt0fSBvZiBmaWxlbmFtZVske3V9XWApO2xldCBhPXIucmVhZEZpbGVTeW5jKGwpO3kud3JpdGUoYSksaShsKX19Y2F0Y2goZSl7bD1lLm1lc3NhZ2V9cmV0dXJuIHkuZW5kKCkseS5vbigiZXJyb3IiLChlPT57bD1lLm1lc3NhZ2V9KSkseS5vbigiZmluaXNoIiwoKCk9PntpZih0KGwpKWEucmVqZWN0KGwpO2Vsc2V7bGV0IGU9e2ZpbGVuYW1lOnUscGF0aDpmfTthLnJlc29sdmUoZSl9fSkpLGF9OwoKCmxldCBpbnN0YW5jZSA9IG51bGwKZnVuY3Rpb24gaW5pdChpbnB1dCl7CgogICAgLy9pbml0CiAgICBsZXQgcgogICAgCiAgICAgICAgciA9IHsKICAgICAgICAgICAgbWFpbjogbWVyZ2VGaWxlcwogICAgICAgIH0KICAgICAgICAKCiAgICAvL29uCiAgICAKCiAgICAvL3NhdmUKICAgIGluc3RhbmNlID0gcgoKfQoKZnVuY3Rpb24gc2VuZE1lc3NhZ2UoZGF0YSkgewogICAgCiAgICAgICAgcGFyZW50UG9ydC5wb3N0TWVzc2FnZShkYXRhKQogICAgICAgIAp9Cgphc3luYyBmdW5jdGlvbiBydW4oZGF0YSkgewogICAgLy8gY29uc29sZS5sb2coJ2lubmVyIHdvcmtlciBydW4nLGRhdGEpCgogICAgLy9tb2RlCiAgICBsZXQgbW9kZSA9IGRhdGEubW9kZQoKICAgIC8vY2hlY2sKICAgIGlmKG1vZGUgIT09ICdpbml0JyAmJiBtb2RlICE9PSAnY2FsbCcpewogICAgICAgIHJldHVybgogICAgfQoKICAgIC8vaW5pdAogICAgaWYobW9kZSA9PT0gJ2luaXQnKXsKICAgICAgICAKICAgICAgICB0cnl7CgogICAgICAgICAgICAvL3R5cGUKICAgICAgICAgICAgbGV0IHR5cGUgPSBkYXRhLnR5cGUKCiAgICAgICAgICAgIC8vaW5wdXQKICAgICAgICAgICAgbGV0IGlucHV0ID0gZGF0YS5pbnB1dAogICAgCiAgICAgICAgICAgIC8vaW5zdGFuY2UKICAgICAgICAgICAgaWYodHlwZSA9PT0gJ2Z1bmN0aW9uJyl7CiAgICAgICAgICAgICAgICBpbml0KC4uLmlucHV0KQogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgaWYodHlwZSA9PT0gJ29iamVjdCcpewogICAgICAgICAgICAgICAgaW5zdGFuY2UgPSBtZXJnZUZpbGVzCiAgICAgICAgICAgIH0KCiAgICAgICAgfQogICAgICAgIGNhdGNoKGVycil7CiAgICAgICAgCiAgICAgICAgICAgIC8vc2VuZE1lc3NhZ2UKICAgICAgICAgICAgbGV0IHJlcyA9IHsKICAgICAgICAgICAgICAgIG1vZGU6ICdlbWl0JywKICAgICAgICAgICAgICAgIGV2TmFtZTogJ2Vycm9yJywKICAgICAgICAgICAgICAgIG1zZzogZXJyLAogICAgICAgICAgICB9CiAgICAgICAgICAgIHNlbmRNZXNzYWdlKHJlcykKCiAgICAgICAgfQogICAgICAgICAgICAKICAgIH0KCiAgICAvL2NoZWNrCiAgICBpZihtb2RlID09PSAnY2FsbCcpewogICAgICAgIGxldCBzdGF0ZSA9ICcnCiAgICAgICAgbGV0IG1zZyA9IG51bGwKCiAgICAgICAgdHJ5ewoKICAgICAgICAgICAgLy9mdW4KICAgICAgICAgICAgbGV0IGZ1biA9IGluc3RhbmNlW2RhdGEuZnVuXQoKICAgICAgICAgICAgLy9pbnB1dAogICAgICAgICAgICBsZXQgaW5wdXQgPSBkYXRhLmlucHV0CgogICAgICAgICAgICAvL2V4ZWMKICAgICAgICAgICAgYXdhaXQgZnVuKC4uLmlucHV0KQogICAgICAgICAgICAgICAgLnRoZW4oKHN1YykgPT4gewogICAgICAgICAgICAgICAgICAgIHN0YXRlPSdzdWNjZXNzJwogICAgICAgICAgICAgICAgICAgIG1zZz1zdWMKICAgICAgICAgICAgICAgIH0pCiAgICAgICAgICAgICAgICAuY2F0Y2goKGVycikgPT4gewogICAgICAgICAgICAgICAgICAgIHN0YXRlPSdlcnJvcicKICAgICAgICAgICAgICAgICAgICBtc2c9ZXJyCiAgICAgICAgICAgICAgICB9KQoKICAgICAgICB9CiAgICAgICAgY2F0Y2goZXJyKXsKICAgICAgICAgICAgc3RhdGUgPSAnZXJyb3InCiAgICAgICAgICAgIG1zZyA9IGVycgogICAgICAgIH0KICAgICAgICAKICAgICAgICAvL3NlbmRNZXNzYWdlCiAgICAgICAgbGV0IHJlcyA9IHsKICAgICAgICAgICAgbW9kZTogJ3JldHVybicsCiAgICAgICAgICAgIGlkOiBkYXRhLmlkLAogICAgICAgICAgICBmdW46IGRhdGEuZnVuLAogICAgICAgICAgICBzdGF0ZSwKICAgICAgICAgICAgbXNnLAogICAgICAgIH0KICAgICAgICBzZW5kTWVzc2FnZShyZXMpCgogICAgfQoKfQoKZnVuY3Rpb24gcmVjdk1lc3NhZ2UoZGF0YSkgewogICAgLy8gY29uc29sZS5sb2coJ2lubmVyIHdvcmtlciByZWN2OicsIGRhdGEpCgogICAgLy9kYXRhUmVjdgogICAgbGV0IGRhdGFSZWN2ID0gZGF0YQoKICAgIC8vcnVuCiAgICBydW4oZGF0YVJlY3YpCgp9CgoKICAgICAgICBwYXJlbnRQb3J0Lm9uKCdtZXNzYWdlJywgcmVjdk1lc3NhZ2UpCiAgICAgICAgCgp0cnl7CiAgICBwcm9jZXNzLm9uKCd1bmhhbmRsZWRSZWplY3Rpb24nLCAoZXJyKSA9PiB7CiAgICAgICAgY29uc29sZS5sb2coJ2lubmVyOnVuaGFuZGxlZFJlamVjdGlvbicsIGVycikKICAgIH0pCiAgICBwcm9jZXNzLm9uKCd1bmNhdWdodEV4Y2VwdGlvbicsIChlcnIpID0+IHsKICAgICAgICBjb25zb2xlLmxvZygnaW5uZXI6dW5jYXVnaHRFeGNlcHRpb24nLCBlcnIpCiAgICB9KQogICAgcHJvY2Vzcy5vbigndW5jYXVnaHRFeGNlcHRpb25Nb25pdG9yJywgKGVycikgPT4gewogICAgICAgIGNvbnNvbGUubG9nKCdpbm5lcjp1bmNhdWdodEV4Y2VwdGlvbk1vbml0b3InLCBlcnIpCiAgICB9KQp9CmNhdGNoKGVycil7fQoK",Buffer.from(t,"base64").toString("utf8"));var t;function n(){let I=new C,t=function(e){try{return new g.Worker(e,{eval:!0})}catch(g){A(g)}}(e);if(!t)return A("invalid worker"),null;function n(){let g=function(){let g,e,C=new Promise((function(){g=arguments[0],e=arguments[1]}));return C.resolve=g,C.reject=e,C}(),e=function(){let g=arguments.length>0&&void 0!==arguments[0]?arguments[0]:10,e=[],C="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),I=C.length;for(let t=0;t<g;t++)e[t]=C[0|Math.random()*I];return e.join("")}(),C={mode:"call",id:e,fun:"main",input:[...arguments]};return t.postMessage(C),I.once(e,(e=>{"success"===e.state?g.resolve(e.msg):g.reject(e.msg)})),g}function A(g){I.emit("error",g)}return t.on("message",(function(g){let e=g,C=e.mode;"emit"!==C&&"return"!==C||("emit"===C&&I.emit(e.evName,e.msg),"return"===C&&I.emit(e.id,e))})),t.on("error",A),t.on("exit",(g=>{1!==g&&A("exit code["+g+"] !== 1")})),function(){let g={mode:"init",type:"function",input:[...arguments]};t.postMessage(g)}([...arguments]),I.main=n,I.main=n,I.terminate=function(){t?(t.terminate(),t=void 0):A("worker has been terminated")},I}I=async function(){let g=[...arguments],e=n();return await e.main(...g).finally((()=>{e.terminate()}))}}();try{process.on("unhandledRejection",(g=>{console.log("outer:unhandledRejection",g)})),process.on("uncaughtException",(g=>{console.log("outer:uncaughtException",g)})),process.on("uncaughtExceptionMonitor",(g=>{console.log("outer:uncaughtExceptionMonitor",g)}))}catch(g){}return I}(g)}({get exports(){return e},set exports(g){e=g}});var C=e,I={};!function(g,e){g.exports=function(){const g="function"==typeof Buffer,e="function"==typeof TextDecoder?new TextDecoder:void 0,C=(g=>{let e={};return g.forEach(((g,C)=>e[g]=C)),e})(("function"==typeof TextEncoder&&new TextEncoder,Array.prototype.slice.call("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="))),I=/^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/,t=String.fromCharCode.bind(String),n="function"==typeof Uint8Array.from?Uint8Array.from.bind(Uint8Array):g=>new Uint8Array(Array.prototype.slice.call(g,0)),A=g=>g.replace(/[^A-Za-z0-9\+\/]/g,""),o=/[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g,c=g=>{switch(g.length){case 4:var e=((7&g.charCodeAt(0))<<18|(63&g.charCodeAt(1))<<12|(63&g.charCodeAt(2))<<6|63&g.charCodeAt(3))-65536;return t(55296+(e>>>10))+t(56320+(1023&e));case 3:return t((15&g.charCodeAt(0))<<12|(63&g.charCodeAt(1))<<6|63&g.charCodeAt(2));default:return t((31&g.charCodeAt(0))<<6|63&g.charCodeAt(1))}},i=g=>g.replace(o,c),r=g=>{if(g=g.replace(/\s+/g,""),!I.test(g))throw new TypeError("malformed base64.");g+="==".slice(2-(3&g.length));let e,n,A,o="";for(let I=0;I<g.length;)e=C[g.charAt(I++)]<<18|C[g.charAt(I++)]<<12|(n=C[g.charAt(I++)])<<6|(A=C[g.charAt(I++)]),o+=64===n?t(e>>16&255):64===A?t(e>>16&255,e>>8&255):t(e>>16&255,e>>8&255,255&e);return o},l="function"==typeof atob?g=>atob(A(g)):g?g=>Buffer.from(g,"base64").toString("binary"):r,s=g?g=>n(Buffer.from(g,"base64")):g=>n(l(g).split("").map((g=>g.charCodeAt(0)))),u=g?g=>Buffer.from(g,"base64").toString("utf8"):e?g=>e.decode(s(g)):g=>i(l(g)),a=g=>A(g.replace(/[-_]/g,(g=>"-"==g?"+":"/"))),d=g=>u(a(g)),p=d;var b={};!function(g){var e=Object.prototype.hasOwnProperty,C="~";function I(){}function t(g,e,C){this.fn=g,this.context=e,this.once=C||!1}function n(g,e,I,n,A){if("function"!=typeof I)throw new TypeError("The listener must be a function");var o=new t(I,n||g,A),c=C?C+e:e;return g._events[c]?g._events[c].fn?g._events[c]=[g._events[c],o]:g._events[c].push(o):(g._events[c]=o,g._eventsCount++),g}function A(g,e){0==--g._eventsCount?g._events=new I:delete g._events[e]}function o(){this._events=new I,this._eventsCount=0}Object.create&&(I.prototype=Object.create(null),(new I).__proto__||(C=!1)),o.prototype.eventNames=function(){var g,I,t=[];if(0===this._eventsCount)return t;for(I in g=this._events)e.call(g,I)&&t.push(C?I.slice(1):I);return Object.getOwnPropertySymbols?t.concat(Object.getOwnPropertySymbols(g)):t},o.prototype.listeners=function(g){var e=C?C+g:g,I=this._events[e];if(!I)return[];if(I.fn)return[I.fn];for(var t=0,n=I.length,A=new Array(n);t<n;t++)A[t]=I[t].fn;return A},o.prototype.listenerCount=function(g){var e=C?C+g:g,I=this._events[e];return I?I.fn?1:I.length:0},o.prototype.emit=function(g,e,I,t,n,A){var o=C?C+g:g;if(!this._events[o])return!1;var c,i,r=this._events[o],l=arguments.length;if(r.fn){switch(r.once&&this.removeListener(g,r.fn,void 0,!0),l){case 1:return r.fn.call(r.context),!0;case 2:return r.fn.call(r.context,e),!0;case 3:return r.fn.call(r.context,e,I),!0;case 4:return r.fn.call(r.context,e,I,t),!0;case 5:return r.fn.call(r.context,e,I,t,n),!0;case 6:return r.fn.call(r.context,e,I,t,n,A),!0}for(i=1,c=new Array(l-1);i<l;i++)c[i-1]=arguments[i];r.fn.apply(r.context,c)}else{var s,u=r.length;for(i=0;i<u;i++)switch(r[i].once&&this.removeListener(g,r[i].fn,void 0,!0),l){case 1:r[i].fn.call(r[i].context);break;case 2:r[i].fn.call(r[i].context,e);break;case 3:r[i].fn.call(r[i].context,e,I);break;case 4:r[i].fn.call(r[i].context,e,I,t);break;default:if(!c)for(s=1,c=new Array(l-1);s<l;s++)c[s-1]=arguments[s];r[i].fn.apply(r[i].context,c)}}return!0},o.prototype.on=function(g,e,C){return n(this,g,e,C,!1)},o.prototype.once=function(g,e,C){return n(this,g,e,C,!0)},o.prototype.removeListener=function(g,e,I,t){var n=C?C+g:g;if(!this._events[n])return this;if(!e)return A(this,n),this;var o=this._events[n];if(o.fn)o.fn!==e||t&&!o.once||I&&o.context!==I||A(this,n);else{for(var c=0,i=[],r=o.length;c<r;c++)(o[c].fn!==e||t&&!o[c].once||I&&o[c].context!==I)&&i.push(o[c]);i.length?this._events[n]=1===i.length?i[0]:i:A(this,n)}return this},o.prototype.removeAllListeners=function(g){var e;return g?(e=C?C+g:g,this._events[e]&&A(this,e)):(this._events=new I,this._eventsCount=0),this},o.prototype.off=o.prototype.removeListener,o.prototype.addListener=o.prototype.on,o.prefixed=C,o.EventEmitter=o,g.exports=o}({get exports(){return b},set exports(g){b=g}});var m=b;let Z;!function(){if("browser"!=("undefined"!=typeof window&&void 0!==window.document?"browser":"nodejs"))return null;let g=p("CgoKInVzZSBzdHJpY3QiO3ZhciBlPXJlcXVpcmUoInBhdGgiKSxyPXJlcXVpcmUoImZzIik7ZnVuY3Rpb24gdChlKXtyZXR1cm4hKCFmdW5jdGlvbihlKXtyZXR1cm4iW29iamVjdCBTdHJpbmddIj09PU9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChlKX0oZSl8fCIiPT09ZSl9ZnVuY3Rpb24gbihlKXtyZXR1cm4hIXIuZXhpc3RzU3luYyhlKSYmKCFyLmxzdGF0U3luYyhlKS5pc0RpcmVjdG9yeSgpJiYhci5sc3RhdFN5bmMoZSkuaXNTeW1ib2xpY0xpbmsoKSl9ZnVuY3Rpb24gaShlKXtpZighci5leGlzdHNTeW5jKGUpKXJldHVybntzdWNjZXNzOiJmaWxlIGRvZXMgbm90IGV4aXN0OiAiK2V9O2lmKCFuKGUpKXJldHVybntlcnJvcjoiaW5wdXQgcGF0aCBpcyBub3QgYSBmaWxlOiAiK2V9O3RyeXtyLnVubGlua1N5bmMoZSl9Y2F0Y2goZSl7cmV0dXJue2Vycm9yOmV9fXJldHVybntzdWNjZXNzOiJkb25lOiAiK2V9fWxldCBtZXJnZUZpbGVzPWFzeW5jKHMsbyxjLHUpPT57bGV0IGw9IiIsYT1mdW5jdGlvbigpe2xldCBlLHIsdD1uZXcgUHJvbWlzZSgoZnVuY3Rpb24oKXtlPWFyZ3VtZW50c1swXSxyPWFyZ3VtZW50c1sxXX0pKTtyZXR1cm4gdC5yZXNvbHZlPWUsdC5yZWplY3Q9cix0fSgpLGY9ZS5qb2luKHMsbykseT1yLmNyZWF0ZVdyaXRlU3RyZWFtKGYpO3RyeXtmb3IobGV0IHQ9MDt0PGM7dCsrKXtsZXQgYz10LGw9ZS5qb2luKHMsYCR7b31fJHtjfWApO2lmKCFuKGwpKXRocm93IG5ldyBFcnJvcihgbWlzc2luZyBjaHVuayAke3R9IG9mIGZpbGVuYW1lWyR7dX1dYCk7bGV0IGE9ci5yZWFkRmlsZVN5bmMobCk7eS53cml0ZShhKSxpKGwpfX1jYXRjaChlKXtsPWUubWVzc2FnZX1yZXR1cm4geS5lbmQoKSx5Lm9uKCJlcnJvciIsKGU9PntsPWUubWVzc2FnZX0pKSx5Lm9uKCJmaW5pc2giLCgoKT0+e2lmKHQobCkpYS5yZWplY3QobCk7ZWxzZXtsZXQgZT17ZmlsZW5hbWU6dSxwYXRoOmZ9O2EucmVzb2x2ZShlKX19KSksYX07CgoKbGV0IGluc3RhbmNlID0gbnVsbApmdW5jdGlvbiBpbml0KGlucHV0KXsKCiAgICAvL2luaXQKICAgIGxldCByCiAgICAKICAgICAgICByID0gewogICAgICAgICAgICBtYWluOiBtZXJnZUZpbGVzCiAgICAgICAgfQogICAgICAgIAoKICAgIC8vb24KICAgIAoKICAgIC8vc2F2ZQogICAgaW5zdGFuY2UgPSByCgp9CgpmdW5jdGlvbiBzZW5kTWVzc2FnZShkYXRhKSB7CiAgICAKICAgICAgICBzZWxmLnBvc3RNZXNzYWdlKGRhdGEpCiAgICAgICAgCn0KCmFzeW5jIGZ1bmN0aW9uIHJ1bihkYXRhKSB7CiAgICAvLyBjb25zb2xlLmxvZygnaW5uZXIgd29ya2VyIHJ1bicsZGF0YSkKCiAgICAvL21vZGUKICAgIGxldCBtb2RlID0gZGF0YS5tb2RlCgogICAgLy9jaGVjawogICAgaWYobW9kZSAhPT0gJ2luaXQnICYmIG1vZGUgIT09ICdjYWxsJyl7CiAgICAgICAgcmV0dXJuCiAgICB9CgogICAgLy9pbml0CiAgICBpZihtb2RlID09PSAnaW5pdCcpewogICAgICAgIAogICAgICAgIHRyeXsKCiAgICAgICAgICAgIC8vdHlwZQogICAgICAgICAgICBsZXQgdHlwZSA9IGRhdGEudHlwZQoKICAgICAgICAgICAgLy9pbnB1dAogICAgICAgICAgICBsZXQgaW5wdXQgPSBkYXRhLmlucHV0CiAgICAKICAgICAgICAgICAgLy9pbnN0YW5jZQogICAgICAgICAgICBpZih0eXBlID09PSAnZnVuY3Rpb24nKXsKICAgICAgICAgICAgICAgIGluaXQoLi4uaW5wdXQpCiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZih0eXBlID09PSAnb2JqZWN0Jyl7CiAgICAgICAgICAgICAgICBpbnN0YW5jZSA9IG1lcmdlRmlsZXMKICAgICAgICAgICAgfQoKICAgICAgICB9CiAgICAgICAgY2F0Y2goZXJyKXsKICAgICAgICAKICAgICAgICAgICAgLy9zZW5kTWVzc2FnZQogICAgICAgICAgICBsZXQgcmVzID0gewogICAgICAgICAgICAgICAgbW9kZTogJ2VtaXQnLAogICAgICAgICAgICAgICAgZXZOYW1lOiAnZXJyb3InLAogICAgICAgICAgICAgICAgbXNnOiBlcnIsCiAgICAgICAgICAgIH0KICAgICAgICAgICAgc2VuZE1lc3NhZ2UocmVzKQoKICAgICAgICB9CiAgICAgICAgICAgIAogICAgfQoKICAgIC8vY2hlY2sKICAgIGlmKG1vZGUgPT09ICdjYWxsJyl7CiAgICAgICAgbGV0IHN0YXRlID0gJycKICAgICAgICBsZXQgbXNnID0gbnVsbAoKICAgICAgICB0cnl7CgogICAgICAgICAgICAvL2Z1bgogICAgICAgICAgICBsZXQgZnVuID0gaW5zdGFuY2VbZGF0YS5mdW5dCgogICAgICAgICAgICAvL2lucHV0CiAgICAgICAgICAgIGxldCBpbnB1dCA9IGRhdGEuaW5wdXQKCiAgICAgICAgICAgIC8vZXhlYwogICAgICAgICAgICBhd2FpdCBmdW4oLi4uaW5wdXQpCiAgICAgICAgICAgICAgICAudGhlbigoc3VjKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGU9J3N1Y2Nlc3MnCiAgICAgICAgICAgICAgICAgICAgbXNnPXN1YwogICAgICAgICAgICAgICAgfSkKICAgICAgICAgICAgICAgIC5jYXRjaCgoZXJyKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGU9J2Vycm9yJwogICAgICAgICAgICAgICAgICAgIG1zZz1lcnIKICAgICAgICAgICAgICAgIH0pCgogICAgICAgIH0KICAgICAgICBjYXRjaChlcnIpewogICAgICAgICAgICBzdGF0ZSA9ICdlcnJvcicKICAgICAgICAgICAgbXNnID0gZXJyCiAgICAgICAgfQogICAgICAgIAogICAgICAgIC8vc2VuZE1lc3NhZ2UKICAgICAgICBsZXQgcmVzID0gewogICAgICAgICAgICBtb2RlOiAncmV0dXJuJywKICAgICAgICAgICAgaWQ6IGRhdGEuaWQsCiAgICAgICAgICAgIGZ1bjogZGF0YS5mdW4sCiAgICAgICAgICAgIHN0YXRlLAogICAgICAgICAgICBtc2csCiAgICAgICAgfQogICAgICAgIHNlbmRNZXNzYWdlKHJlcykKCiAgICB9Cgp9CgpmdW5jdGlvbiByZWN2TWVzc2FnZShkYXRhKSB7CiAgICAvLyBjb25zb2xlLmxvZygnaW5uZXIgd29ya2VyIHJlY3Y6JywgZGF0YSkKCiAgICAvL2RhdGFSZWN2CiAgICBsZXQgZGF0YVJlY3YgPSBkYXRhCgogICAgLy9ydW4KICAgIHJ1bihkYXRhUmVjdikKCn0KCgogICAgICAgIHNlbGYub25tZXNzYWdlID0gZnVuY3Rpb24gKGUpIHsKICAgICAgICAgICAgcmVjdk1lc3NhZ2UoZS5kYXRhKQogICAgICAgIH0KICAgICAgICAKCnRyeXsKICAgIHByb2Nlc3Mub24oJ3VuaGFuZGxlZFJlamVjdGlvbicsIChlcnIpID0+IHsKICAgICAgICBjb25zb2xlLmxvZygnaW5uZXI6dW5oYW5kbGVkUmVqZWN0aW9uJywgZXJyKQogICAgfSkKICAgIHByb2Nlc3Mub24oJ3VuY2F1Z2h0RXhjZXB0aW9uJywgKGVycikgPT4gewogICAgICAgIGNvbnNvbGUubG9nKCdpbm5lcjp1bmNhdWdodEV4Y2VwdGlvbicsIGVycikKICAgIH0pCiAgICBwcm9jZXNzLm9uKCd1bmNhdWdodEV4Y2VwdGlvbk1vbml0b3InLCAoZXJyKSA9PiB7CiAgICAgICAgY29uc29sZS5sb2coJ2lubmVyOnVuY2F1Z2h0RXhjZXB0aW9uTW9uaXRvcicsIGVycikKICAgIH0pCn0KY2F0Y2goZXJyKXt9Cgo=");function e(){let e=new m,C=function(g){try{let e=new Blob([g]),C=window.URL||window.webkitURL;return new Worker(C.createObjectURL(e))}catch(g){t(g)}}(g);if(!C)return t("invalid worker"),null;function I(){let g=function(){let g,e,C=new Promise((function(){g=arguments[0],e=arguments[1]}));return C.resolve=g,C.reject=e,C}(),I=function(){let g=arguments.length>0&&void 0!==arguments[0]?arguments[0]:10,e=[],C="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),I=C.length;for(let t=0;t<g;t++)e[t]=C[0|Math.random()*I];return e.join("")}(),t={mode:"call",id:I,fun:"main",input:[...arguments]};return C.postMessage(t),e.once(I,(e=>{"success"===e.state?g.resolve(e.msg):g.reject(e.msg)})),g}function t(g){e.emit("error",g)}return C.onmessage=function(g){!function(g){let C=g,I=C.mode;"emit"!==I&&"return"!==I||("emit"===I&&e.emit(C.evName,C.msg),"return"===I&&e.emit(C.id,C))}(g.data)},C.onerror=t,C.onmessageerror=function(g){t(g.data)},function(){let g={mode:"init",type:"function",input:[...arguments]};C.postMessage(g)}([...arguments]),e.main=I,e.main=I,e.terminate=function(){C?(C.terminate(),C=void 0):t("worker has been terminated")},e}Z=async function(){let g=[...arguments],C=e();return await C.main(...g).finally((()=>{C.terminate()}))}}();try{process.on("unhandledRejection",(g=>{console.log("outer:unhandledRejection",g)})),process.on("uncaughtException",(g=>{console.log("outer:uncaughtException",g)})),process.on("uncaughtExceptionMonitor",(g=>{console.log("outer:uncaughtExceptionMonitor",g)}))}catch(g){}return Z}()}({get exports(){return I},set exports(g){I=g}});var t=I;let n;return n="undefined"!=typeof window&&void 0!==window.document?t:C,n}));
|
package/srv.mjs
CHANGED
|
@@ -3,6 +3,8 @@ import _ from 'lodash-es'
|
|
|
3
3
|
import w from 'wsemi'
|
|
4
4
|
import WConverhpServer from './src/WConverhpServer.mjs'
|
|
5
5
|
|
|
6
|
+
let ms = []
|
|
7
|
+
|
|
6
8
|
let opt = {
|
|
7
9
|
port: 8080,
|
|
8
10
|
apiName: 'api',
|
|
@@ -21,7 +23,7 @@ let opt = {
|
|
|
21
23
|
//new
|
|
22
24
|
let wo = new WConverhpServer(opt)
|
|
23
25
|
|
|
24
|
-
wo.on('execute',
|
|
26
|
+
wo.on('execute', (func, input, pm) => {
|
|
25
27
|
// console.log(`Server[port:${opt.port}]: execute`, func, input)
|
|
26
28
|
console.log(`Server[port:${opt.port}]: execute`, func)
|
|
27
29
|
|
|
@@ -31,6 +33,7 @@ wo.on('execute', function(func, input, pm) {
|
|
|
31
33
|
|
|
32
34
|
if (_.get(input, 'p.d.u8a', null)) {
|
|
33
35
|
console.log('input.p.d.u8a', input.p.d.u8a)
|
|
36
|
+
ms.push({ 'input.p.d.u8a': input.p.d.u8a })
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
let r = {
|
|
@@ -38,13 +41,7 @@ wo.on('execute', function(func, input, pm) {
|
|
|
38
41
|
_data: [11, 22.22, 'abc', { x: '21', y: 65.43, z: 'test中文' }],
|
|
39
42
|
_bin: {
|
|
40
43
|
name: 'zdata.b2',
|
|
41
|
-
u8a: new Uint8Array([66, 97, 115]),
|
|
42
|
-
// name: '100mb.7z',
|
|
43
|
-
// u8a: new Uint8Array(fs.readFileSync('D:\\開源-JS-006-2-w-converhp\\_temp\\100mb.7z')),
|
|
44
|
-
// name: '500mb.7z',
|
|
45
|
-
// u8a: new Uint8Array(fs.readFileSync('D:\\開源-JS-006-2-w-converhp\\_temp\\500mb.7z')),
|
|
46
|
-
// name: '1000mb.7z',
|
|
47
|
-
// u8a: new Uint8Array(fs.readFileSync('D:\\開源-JS-006-2-w-converhp\\_temp\\1000mb.7z')),
|
|
44
|
+
u8a: new Uint8Array([52, 66, 97, 115]),
|
|
48
45
|
},
|
|
49
46
|
}
|
|
50
47
|
|
|
@@ -63,24 +60,32 @@ wo.on('execute', function(func, input, pm) {
|
|
|
63
60
|
}
|
|
64
61
|
|
|
65
62
|
})
|
|
66
|
-
wo.on('upload',
|
|
63
|
+
wo.on('upload', (input, pm) => {
|
|
67
64
|
console.log(`Server[port:${opt.port}]: upload`, input)
|
|
68
65
|
|
|
69
66
|
try {
|
|
67
|
+
ms.push({ 'receive and return': input })
|
|
70
68
|
let output = input
|
|
71
69
|
pm.resolve(output)
|
|
72
70
|
}
|
|
73
71
|
catch (err) {
|
|
74
|
-
console.log('
|
|
75
|
-
pm.reject('
|
|
72
|
+
console.log('upload error', err)
|
|
73
|
+
pm.reject('upload error')
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
})
|
|
79
|
-
wo.on('error',
|
|
77
|
+
wo.on('error', (err) => {
|
|
80
78
|
console.log(`Server[port:${opt.port}]: error`, err)
|
|
81
79
|
})
|
|
82
|
-
wo.on('handler',
|
|
80
|
+
wo.on('handler', (data) => {
|
|
83
81
|
// console.log(`Server[port:${opt.port}]: handler`, data)
|
|
84
82
|
})
|
|
85
83
|
|
|
84
|
+
setTimeout(() => {
|
|
85
|
+
console.log('ms', ms)
|
|
86
|
+
// console.log('ms', JSON.stringify(ms))
|
|
87
|
+
wo.stop()
|
|
88
|
+
}, 3000)
|
|
89
|
+
|
|
90
|
+
|
|
86
91
|
//node --experimental-modules srv.mjs
|
package/test/1mb.7z
ADDED
|
Binary file
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import assert from 'assert'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import _ from 'lodash-es'
|
|
4
|
+
import w from 'wsemi'
|
|
5
|
+
import WConverhpServer from '../src/WConverhpServer.mjs'
|
|
6
|
+
import WConverhpClient from '../src/WConverhpClient.mjs'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
describe('executeWithFile', function() {
|
|
10
|
+
|
|
11
|
+
let msAll = []
|
|
12
|
+
|
|
13
|
+
let runServer = () => {
|
|
14
|
+
|
|
15
|
+
let ms = []
|
|
16
|
+
|
|
17
|
+
let opt = {
|
|
18
|
+
port: 8081, //8080, //同時test故得要不同port
|
|
19
|
+
apiName: 'api',
|
|
20
|
+
pathStaticFiles: '.', //要存取專案資料夾下web.html, 故不能給dist
|
|
21
|
+
funCheck: async ({ apiType, authorization, headers, query }) => {
|
|
22
|
+
// console.log('funCheck', `apiType[${apiType}]`, `authorization[${authorization}]`)
|
|
23
|
+
let token = w.strdelleft(authorization, 7) //刪除Bearer
|
|
24
|
+
if (!w.isestr(token)) {
|
|
25
|
+
return false
|
|
26
|
+
}
|
|
27
|
+
// await w.delay(3000)
|
|
28
|
+
return true
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
//new
|
|
33
|
+
let wo = new WConverhpServer(opt)
|
|
34
|
+
|
|
35
|
+
wo.on('execute', (func, input, pm) => {
|
|
36
|
+
// console.log(`Server[port:${opt.port}]: execute`, func, input)
|
|
37
|
+
// console.log(`Server[port:${opt.port}]: execute`, func)
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
|
|
41
|
+
if (func === 'add') {
|
|
42
|
+
|
|
43
|
+
if (_.get(input, 'p.d.u8a', null)) {
|
|
44
|
+
// console.log('input.p.d.u8a', input.p.d.u8a)
|
|
45
|
+
let t = input.p.d.u8a
|
|
46
|
+
let ts = [t[0], t[1], t[2]]
|
|
47
|
+
ms.push({ 'input.p.d.u8a': ts })
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let r = {
|
|
51
|
+
_add: input.p.a + input.p.b,
|
|
52
|
+
_data: [11, 22.22, 'abc', { x: '21', y: 65.43, z: 'test中文' }],
|
|
53
|
+
_bin: {
|
|
54
|
+
name: 'zdata.b2',
|
|
55
|
+
u8a: new Uint8Array([52, 66, 97, 115]),
|
|
56
|
+
},
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
pm.resolve(r)
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// console.log('invalid func')
|
|
64
|
+
pm.reject('invalid func')
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
// console.log('execute error', err)
|
|
70
|
+
pm.reject('execute error')
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
})
|
|
74
|
+
wo.on('error', () => {
|
|
75
|
+
// console.log(`Server[port:${opt.port}]: error`, err)
|
|
76
|
+
})
|
|
77
|
+
wo.on('handler', (data) => {
|
|
78
|
+
// console.log(`Server[port:${opt.port}]: handler`, data)
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
setTimeout(() => {
|
|
82
|
+
// console.log('ms', JSON.stringify(ms))
|
|
83
|
+
msAll.push({ server: ms })
|
|
84
|
+
wo.stop()
|
|
85
|
+
}, 2000)
|
|
86
|
+
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let runClient = () => {
|
|
90
|
+
|
|
91
|
+
let ms = []
|
|
92
|
+
|
|
93
|
+
let opt = {
|
|
94
|
+
FormData,
|
|
95
|
+
url: 'http://localhost:8081', //'http://localhost:8080', //同時test故得要不同port
|
|
96
|
+
apiName: 'api',
|
|
97
|
+
getToken: () => {
|
|
98
|
+
return 'token-for-test'
|
|
99
|
+
},
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
//new
|
|
103
|
+
let wo = new WConverhpClient(opt)
|
|
104
|
+
|
|
105
|
+
wo.on('error', () => {
|
|
106
|
+
// console.log(`error`, err)
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
async function execute(name, u8a) {
|
|
110
|
+
|
|
111
|
+
//p
|
|
112
|
+
let p = {
|
|
113
|
+
a: 12,
|
|
114
|
+
b: 34.56,
|
|
115
|
+
c: 'test中文',
|
|
116
|
+
d: {
|
|
117
|
+
name,
|
|
118
|
+
u8a,
|
|
119
|
+
},
|
|
120
|
+
}
|
|
121
|
+
// console.log('p', p)
|
|
122
|
+
let t = p.d.u8a
|
|
123
|
+
let ts = [t[0], t[1], t[2]]
|
|
124
|
+
ms.push({ 'execute input': ts })
|
|
125
|
+
|
|
126
|
+
//execute
|
|
127
|
+
await wo.execute('add', { p },
|
|
128
|
+
function ({ prog, p, m }) {
|
|
129
|
+
if (m === 'upload') {
|
|
130
|
+
// console.log('client web: execute: prog', prog * 0.5, p, m)
|
|
131
|
+
}
|
|
132
|
+
if (m === 'download') {
|
|
133
|
+
// console.log('client web: execute: prog', 50 + prog * 0.5, p, m)
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
.then(function(r) {
|
|
137
|
+
// console.log('client web: execute: add', r)
|
|
138
|
+
// console.log('r._bin.name', r._bin.name, 'r._bin.u8a', r._bin.u8a)
|
|
139
|
+
// w.downloadFileFromU8Arr(r._bin.name, r._bin.u8a)
|
|
140
|
+
let t = r._bin.u8a
|
|
141
|
+
let ts = [t[0], t[1], t[2]]
|
|
142
|
+
ms.push({ 'execute output': ts })
|
|
143
|
+
})
|
|
144
|
+
.catch(function () {
|
|
145
|
+
// console.log('client web: execute: catch', err)
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function executeWithFile() {
|
|
151
|
+
let core = async() => {
|
|
152
|
+
|
|
153
|
+
//u8a
|
|
154
|
+
let u8a = new Uint8Array(fs.readFileSync('./test/1mb.7z')) //使用test內檔案
|
|
155
|
+
// console.log('executeWithFile u8a', u8a)
|
|
156
|
+
|
|
157
|
+
//execute
|
|
158
|
+
await execute('1mb.7z', u8a)
|
|
159
|
+
|
|
160
|
+
// console.log('ms', ms)
|
|
161
|
+
msAll.push({ client: ms })
|
|
162
|
+
|
|
163
|
+
}
|
|
164
|
+
core()
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
executeWithFile()
|
|
168
|
+
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
let run = () => {
|
|
172
|
+
let pm = w.genPm()
|
|
173
|
+
runServer()
|
|
174
|
+
runClient()
|
|
175
|
+
setTimeout(() => {
|
|
176
|
+
// console.log('msAll', JSON.stringify(msAll))
|
|
177
|
+
// fs.writeFileSync('./test_executeWithFile.json', JSON.stringify(msAll), 'utf8')
|
|
178
|
+
pm.resolve(msAll)
|
|
179
|
+
}, 4000)
|
|
180
|
+
return pm
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
let res = `[{"client":[{"execute input":[55,122,188]},{"execute output":[52,66,97]}]},{"server":[{"input.p.d.u8a":[55,122,188]}]}]`
|
|
184
|
+
it(`should return ${res} when test`, async function() {
|
|
185
|
+
let r = await run()
|
|
186
|
+
r = JSON.stringify(r)
|
|
187
|
+
let rr = res
|
|
188
|
+
assert.strict.deepEqual(r, rr)
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
})
|