w-converhp 2.0.14 → 2.0.16

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.
@@ -73,6 +73,11 @@ import mergeFiles from './mergeFiles.wk.umd.js'
73
73
  // import mergeFiles from './mergeFiles.mjs'
74
74
 
75
75
 
76
+ //回傳前端stream時(POST或GET皆可), 前端會須等stream傳完才能判斷是否為大檔或錯誤訊息, 此會導致若回傳超大檔, 會需要對超大檔進行解析會有記憶體上限問題, 故需要通過header提供基本成功或失敗訊息, 讓前端能進行解析判斷
77
+ //回傳前端(nodejs)時, 針對超大檔, 只能用POST並用stream回傳
78
+ //回傳前端(browser)時, 針對超大檔, 可用POST並用stream回傳但還要處理進度條, 若要交由瀏覽器下載器處理, 只能用GET並用stream回傳, 且前端只能用window.location.href或a.href+a.click()下載
79
+
80
+
76
81
  /**
77
82
  * 建立Hapi伺服器
78
83
  *
@@ -83,6 +88,7 @@ import mergeFiles from './mergeFiles.wk.umd.js'
83
88
  * @param {String} [opt.pathStaticFiles='dist'] 輸入當useInert=true時提供瀏覽資料夾字串,預設'dist'
84
89
  * @param {String} [opt.apiName='api'] 輸入API名稱字串,預設'api'
85
90
  * @param {String} [opt.pathUploadTemp='./uploadTemp'] 輸入暫時存放切片上傳檔案資料夾字串,預設'./uploadTemp'
91
+ * @param {String} [opt.tokenType='Bearer'] 輸入token類型字串,預設'Bearer'
86
92
  * @param {Function} [opt.verifyConn=()=>{return true}] 輸入呼叫API時檢測函數,預設()=>{return true}
87
93
  * @param {Array} [opt.corsOrigins=['*']] 輸入允許跨域網域陣列,若給予['*']代表允許全部,預設['*']
88
94
  * @param {Integer} [opt.delayForBasic=0] 輸入基本API用延遲響應時間,單位ms,預設0
@@ -91,14 +97,24 @@ import mergeFiles from './mergeFiles.wk.umd.js'
91
97
  * @returns {Object} 回傳事件物件,可監聽事件execute、upload、handler
92
98
  * @example
93
99
  *
100
+ * import fs from 'fs'
94
101
  * import _ from 'lodash-es'
95
- * import WConverhpServer from 'w-converhp/dist/w-converhp-server.umd.js'
102
+ * import w from 'wsemi'
103
+ * import WConverhpServer from './src/WConverhpServer.mjs'
104
+ *
105
+ * let ms = []
96
106
  *
97
107
  * let opt = {
98
108
  * port: 8080,
99
109
  * apiName: 'api',
100
110
  * pathStaticFiles: '.', //要存取專案資料夾下web.html, 故不能給dist
101
- * verifyConn: () => {
111
+ * verifyConn: async ({ apiType, authorization, headers, query }) => {
112
+ * console.log('verifyConn', `apiType[${apiType}]`, `authorization[${authorization}]`)
113
+ * let token = w.strdelleft(authorization, 7) //刪除Bearer
114
+ * if (!w.isestr(token)) {
115
+ * return false
116
+ * }
117
+ * // await w.delay(3000)
102
118
  * return true
103
119
  * },
104
120
  * }
@@ -116,6 +132,7 @@ import mergeFiles from './mergeFiles.wk.umd.js'
116
132
  *
117
133
  * if (_.get(input, 'p.d.u8a', null)) {
118
134
  * console.log('input.p.d.u8a', input.p.d.u8a)
135
+ * ms.push({ 'input.p.d.u8a': input.p.d.u8a })
119
136
  * }
120
137
  *
121
138
  * let r = {
@@ -123,13 +140,7 @@ import mergeFiles from './mergeFiles.wk.umd.js'
123
140
  * _data: [11, 22.22, 'abc', { x: '21', y: 65.43, z: 'test中文' }],
124
141
  * _bin: {
125
142
  * name: 'zdata.b2',
126
- * u8a: new Uint8Array([66, 97, 115]),
127
- * // name: '100mb.7z',
128
- * // u8a: new Uint8Array(fs.readFileSync('D:\\開源-JS-006-2-w-converhp\\_temp\\100mb.7z')),
129
- * // name: '500mb.7z',
130
- * // u8a: new Uint8Array(fs.readFileSync('D:\\開源-JS-006-2-w-converhp\\_temp\\500mb.7z')),
131
- * // name: '1000mb.7z',
132
- * // u8a: new Uint8Array(fs.readFileSync('D:\\開源-JS-006-2-w-converhp\\_temp\\1000mb.7z')),
143
+ * u8a: new Uint8Array([52, 66, 97, 115]),
133
144
  * },
134
145
  * }
135
146
  *
@@ -152,6 +163,7 @@ import mergeFiles from './mergeFiles.wk.umd.js'
152
163
  * console.log(`Server[port:${opt.port}]: upload`, input)
153
164
  *
154
165
  * try {
166
+ * ms.push({ 'receive and return': input })
155
167
  * let output = input
156
168
  * pm.resolve(output)
157
169
  * }
@@ -164,29 +176,32 @@ import mergeFiles from './mergeFiles.wk.umd.js'
164
176
  * wo.on('download', (input, pm) => {
165
177
  * console.log(`Server[port:${opt.port}]: download`, input)
166
178
  *
179
+ * let streamRead = null
167
180
  * try {
168
181
  * ms.push({ 'download': input })
169
182
  *
170
183
  * //fp
171
184
  * let fp = `./test/1mb.7z`
172
185
  *
173
- * //streamRead
174
- * let streamRead = fs.createReadStream(fp)
175
- *
176
- * //fileName
177
- * let fileName = `1mb.7z`
186
+ * //check, 檔案存在才往下
178
187
  *
179
188
  * //fileSize
180
189
  * let stats = fs.statSync(fp)
181
190
  * let fileSize = stats.size
182
191
  *
192
+ * //streamRead
193
+ * streamRead = fs.createReadStream(fp)
194
+ *
195
+ * //filename
196
+ * let filename = `1mb中文.7z` //測試支援中文
197
+ *
183
198
  * //fileType
184
199
  * let fileType = 'application/x-7z-compressed'
185
200
  *
186
201
  * //output
187
202
  * let output = {
188
203
  * streamRead,
189
- * fileName,
204
+ * filename,
190
205
  * fileSize,
191
206
  * fileType,
192
207
  * }
@@ -195,14 +210,27 @@ import mergeFiles from './mergeFiles.wk.umd.js'
195
210
  * }
196
211
  * catch (err) {
197
212
  * console.log('download error', err)
213
+ * // try {
214
+ * // streamRead.destroy() //若fs.createReadStream早於fs.statSync執行, 但fs.statSync發生錯誤時, stream得要destroy
215
+ * // }
216
+ * // catch (err) {}
198
217
  * pm.reject('download error')
199
218
  * }
200
219
  *
201
220
  * })
221
+ * wo.on('error', (err) => {
222
+ * console.log(`Server[port:${opt.port}]: error`, err)
223
+ * })
202
224
  * wo.on('handler', (data) => {
203
225
  * // console.log(`Server[port:${opt.port}]: handler`, data)
204
226
  * })
205
227
  *
228
+ * setTimeout(() => {
229
+ * console.log('ms', ms)
230
+ * // console.log('ms', JSON.stringify(ms))
231
+ * wo.stop()
232
+ * }, 3000)
233
+ *
206
234
  */
207
235
  function WConverhpServer(opt = {}) {
208
236
 
@@ -230,12 +258,6 @@ function WConverhpServer(opt = {}) {
230
258
  apiName = 'api'
231
259
  }
232
260
 
233
- //apiUploadSliceName
234
- let apiUploadSliceName = `${apiName}slc`
235
-
236
- //apiDownloadName
237
- let apiDownloadName = `${apiName}dw`
238
-
239
261
  //pathUploadTemp
240
262
  let pathUploadTemp = get(opt, 'pathUploadTemp')
241
263
  if (!isestr(pathUploadTemp)) {
@@ -245,6 +267,12 @@ function WConverhpServer(opt = {}) {
245
267
  fsCreateFolder(pathUploadTemp)
246
268
  }
247
269
 
270
+ //tokenType
271
+ let tokenType = get(opt, 'tokenType')
272
+ if (!isestr(tokenType)) {
273
+ tokenType = 'Bearer'
274
+ }
275
+
248
276
  //verifyConn
249
277
  let verifyConn = get(opt, 'verifyConn')
250
278
  if (!isfun(verifyConn)) {
@@ -605,7 +633,7 @@ function WConverhpServer(opt = {}) {
605
633
 
606
634
  //apiUploadSlice
607
635
  let apiUploadSlice = {
608
- path: `/${apiUploadSliceName}`,
636
+ path: `/${apiName}slc`,
609
637
  method: 'POST',
610
638
  options: {
611
639
  payload: {
@@ -747,7 +775,7 @@ function WConverhpServer(opt = {}) {
747
775
 
748
776
  //apiUploadSliceMerge
749
777
  let apiUploadSliceMerge = {
750
- path: `/${apiUploadSliceName}m`,
778
+ path: `/${apiName}slcm`,
751
779
  method: 'POST',
752
780
  options: {
753
781
  payload: {
@@ -755,7 +783,7 @@ function WConverhpServer(opt = {}) {
755
783
  maxParts: 1000 * 1000 * 1000, //預設為1000, 給予3次方
756
784
  timeout: false, //避免請求未完成時中斷
757
785
  // output: 'stream',
758
- parse: true, //前端送obj過來
786
+ parse: true, //前端送obj過來須自動解析
759
787
  },
760
788
  timeout: {
761
789
  server: false, //關閉伺服器超時
@@ -865,9 +893,263 @@ function WConverhpServer(opt = {}) {
865
893
  },
866
894
  }
867
895
 
896
+ //apiDownloadGetFilename
897
+ let apiDownloadGetFilename = {
898
+ path: `/${apiName}dwgfn`,
899
+ method: 'POST',
900
+ options: {
901
+ payload: {
902
+ maxBytes: 1024 * 1024 * 1024 * 1024, //預設為1mb, 調整至1tb, 也就是給予3次方
903
+ maxParts: 1000 * 1000 * 1000, //預設為1000, 給予3次方
904
+ timeout: false, //避免請求未完成時中斷
905
+ // output: 'stream',
906
+ parse: true, //前端送obj過來須自動解析
907
+ },
908
+ timeout: {
909
+ server: false, //關閉伺服器超時
910
+ socket: false, //關閉socket超時
911
+ },
912
+ },
913
+ handler: async function (req, res) {
914
+ // console.log(req, res)
915
+ // console.log('payload', req.payload)
916
+
917
+ //headers
918
+ let headers = get(req, 'headers')
919
+ headers = iseobj(headers) ? headers : ''
920
+ // console.log('headers', headers)
921
+
922
+ //query
923
+ let query = get(req, 'query')
924
+ query = iseobj(query) ? query : ''
925
+ // console.log('query', query)
926
+
927
+ //authorization
928
+ let authorization = get(headers, 'authorization', '')
929
+ authorization = isestr(authorization) ? authorization : ''
930
+
931
+ //check
932
+ if (true) {
933
+
934
+ //verifyConn
935
+ let m = verifyConn({ apiType: 'download-get-filename', authorization, headers, query })
936
+ if (ispm(m)) {
937
+ m = await m
938
+ }
939
+
940
+ //check
941
+ if (m !== true) {
942
+ return responseU8aStreamWithError(res, 'permission denied')
943
+ }
944
+
945
+ }
946
+
947
+ //eeEmit
948
+ eeEmit('handler', {
949
+ api: 'apiDownloadGetFilename',
950
+ headers,
951
+ query,
952
+ })
953
+
954
+ //fileId, 從payload接收
955
+ let fileId = get(req, 'payload.fileId', '')
956
+ // console.log('fileId', fileId)
957
+
958
+ //check
959
+ if (!isestr(fileId)) {
960
+ // console.log('invalid fileId in payload')
961
+ return responseU8aStreamWithError(res, 'invalid fileId in payload')
962
+ }
963
+
964
+ //inp
965
+ let inp = { fileId }
966
+
967
+ //procDownloadGetFilename
968
+ let out = {}
969
+ let returnType = ''
970
+ let returnMsg = ''
971
+ await procDownload(inp)
972
+ .then(function(msg) {
973
+ out.success = msg
974
+ returnType = 'success'
975
+ returnMsg = 'need to parse'
976
+ })
977
+ .catch(function(msg) {
978
+ out.error = msg
979
+ returnType = 'error'
980
+ returnMsg = 'need to parse'
981
+ })
982
+ // console.log('out', out)
983
+
984
+ //r
985
+ let r = get(out, 'success')
986
+
987
+ //streamRead
988
+ let streamRead = get(r, 'streamRead')
989
+
990
+ //destroy, 不提供stream故須預先destroy
991
+ try {
992
+ streamRead.destroy()
993
+ }
994
+ catch (err) {}
995
+
996
+ //filename
997
+ let filename = get(r, 'filename')
998
+ if (!isestr(filename)) {
999
+ //已於前面destroy
1000
+ return responseU8aStreamWithError(res, 'invalid filename')
1001
+ }
1002
+
1003
+ //重新提供out
1004
+ out = {
1005
+ success: {
1006
+ filename,
1007
+ },
1008
+ }
1009
+
1010
+ //u8aOut
1011
+ let u8aOut = obj2u8arr(out)
1012
+ // console.log('u8aOut', u8aOut)
1013
+
1014
+ return responseU8aStream(res, u8aOut, { returnType, returnMsg })
1015
+ },
1016
+ }
1017
+
1018
+ //apiDownloadGetFile
1019
+ let apiDownloadGetFile = {
1020
+ path: `/${apiName}dwgf`,
1021
+ method: 'GET',
1022
+ options: {
1023
+ timeout: {
1024
+ server: false, //關閉伺服器超時
1025
+ socket: false, //關閉socket超時
1026
+ },
1027
+ },
1028
+ handler: async function (req, res) {
1029
+ // console.log(req, res)
1030
+ // console.log('payload', req.payload)
1031
+
1032
+ //headers
1033
+ let headers = get(req, 'headers')
1034
+ headers = iseobj(headers) ? headers : ''
1035
+ // console.log('headers', headers)
1036
+
1037
+ //query
1038
+ let query = get(req, 'query')
1039
+ query = iseobj(query) ? query : ''
1040
+ // console.log('query', query)
1041
+
1042
+ //token
1043
+ let token = get(query, 'token', '')
1044
+ token = isestr(token) ? token : ''
1045
+ // console.log('token', token)
1046
+
1047
+ //authorization
1048
+ let authorization = ''
1049
+ if (isestr(token)) {
1050
+ authorization = `${tokenType} ${token}`
1051
+ }
1052
+
1053
+ //check
1054
+ if (true) {
1055
+
1056
+ //verifyConn
1057
+ let m = verifyConn({ apiType: 'download-get-file', authorization, headers, query })
1058
+ if (ispm(m)) {
1059
+ m = await m
1060
+ }
1061
+
1062
+ //check
1063
+ if (m !== true) {
1064
+ return responseU8aStreamWithError(res, 'permission denied')
1065
+ }
1066
+
1067
+ }
1068
+
1069
+ //eeEmit
1070
+ eeEmit('handler', {
1071
+ api: 'apiDownloadGetFilename',
1072
+ headers,
1073
+ query,
1074
+ })
1075
+
1076
+ //fileId
1077
+ let fileId = get(query, 'fileId', '')
1078
+ fileId = isestr(fileId) ? fileId : ''
1079
+ // console.log('fileId', fileId)
1080
+
1081
+ //check
1082
+ if (!isestr(fileId)) {
1083
+ // console.log('invalid fileId in query')
1084
+ return responseU8aStreamWithError(res, 'invalid fileId in query')
1085
+ }
1086
+
1087
+ //inp
1088
+ let inp = { fileId }
1089
+
1090
+ //procDownload
1091
+ let out = {}
1092
+ await procDownload(inp)
1093
+ .then(function(msg) {
1094
+ out.success = msg
1095
+ })
1096
+ .catch(function(msg) {
1097
+ out.error = msg
1098
+ })
1099
+ // console.log('out', out)
1100
+
1101
+ //return
1102
+ if (haskey(out, 'error')) {
1103
+ // console.log('out.error', out.error)
1104
+ return responseU8aStreamWithError(res, `can not get file from fileId`)
1105
+ }
1106
+
1107
+ //r
1108
+ let r = get(out, 'success')
1109
+
1110
+ //streamRead
1111
+ let streamRead = get(r, 'streamRead')
1112
+
1113
+ // //filename
1114
+ // let filename = get(r, 'filename')
1115
+ // if (!isestr(filename)) {
1116
+ // return responseU8aStreamWithError(res, 'invalid filename')
1117
+ // }
1118
+ // filename = str2b64(filename) //headers內對中文支援度不佳須用base64傳
1119
+ // console.log('filename', filename)
1120
+
1121
+ //fileSize
1122
+ let fileSize = get(r, 'fileSize')
1123
+ if (!isNumber(fileSize)) {
1124
+ try {
1125
+ streamRead.destroy() //提供stream前發生錯誤, 得強制destroy
1126
+ }
1127
+ catch (err) {}
1128
+ return responseU8aStreamWithError(res, 'invalid fileSize')
1129
+ }
1130
+ // fileSize = cstr(fileSize)
1131
+
1132
+ //fileType
1133
+ let fileType = get(r, 'fileType')
1134
+ if (!isestr(fileType)) {
1135
+ try {
1136
+ streamRead.destroy() //提供stream前發生錯誤, 得強制destroy
1137
+ }
1138
+ catch (err) {}
1139
+ return responseU8aStreamWithError(res, 'invalid fileType')
1140
+ }
1141
+ fileType = cstr(fileType)
1142
+
1143
+ return res.response(streamRead)
1144
+ .type(fileType)
1145
+ // .header('Content-Disposition', `attachment; filename="${filename}"`) //chrome會優先使用header內filename, 但header內支援中文度很差須用base64, 此導致chrome下載檔名只能為base64, 故一律改由前端(browser)先取得真實檔名後直接給予下載檔名, 避免用header提供真實檔名
1146
+ .header('Content-Length', fileSize)
1147
+ },
1148
+ }
1149
+
868
1150
  //apiDownload
869
1151
  let apiDownload = {
870
- path: `/${apiDownloadName}`,
1152
+ path: `/${apiName}dw`,
871
1153
  method: 'POST',
872
1154
  options: {
873
1155
  payload: {
@@ -875,7 +1157,7 @@ function WConverhpServer(opt = {}) {
875
1157
  maxParts: 1000 * 1000 * 1000, //預設為1000, 給予3次方
876
1158
  timeout: false, //避免請求未完成時中斷
877
1159
  // output: 'stream',
878
- parse: true, //前端送obj過來
1160
+ parse: true, //前端送obj過來須自動解析
879
1161
  },
880
1162
  timeout: {
881
1163
  server: false, //關閉伺服器超時
@@ -959,16 +1241,24 @@ function WConverhpServer(opt = {}) {
959
1241
  //streamRead
960
1242
  let streamRead = get(r, 'streamRead')
961
1243
 
962
- //fileName
963
- let fileName = get(r, 'fileName')
964
- if (!isestr(fileName)) {
965
- return responseU8aStreamWithError(res, 'invalid fileName')
1244
+ //filename
1245
+ let filename = get(r, 'filename')
1246
+ if (!isestr(filename)) {
1247
+ try {
1248
+ streamRead.destroy() //提供stream前發生錯誤, 得強制destroy
1249
+ }
1250
+ catch (err) {}
1251
+ return responseU8aStreamWithError(res, 'invalid filename')
966
1252
  }
967
- fileName = str2b64(fileName) //headers內對中文支援度不佳須用base64傳
1253
+ filename = str2b64(filename) //headers內對中文支援度不佳須用base64傳
968
1254
 
969
1255
  //fileSize
970
1256
  let fileSize = get(r, 'fileSize')
971
1257
  if (!isNumber(fileSize)) {
1258
+ try {
1259
+ streamRead.destroy() //提供stream前發生錯誤, 得強制destroy
1260
+ }
1261
+ catch (err) {}
972
1262
  return responseU8aStreamWithError(res, 'invalid fileSize')
973
1263
  }
974
1264
  // fileSize = cstr(fileSize)
@@ -976,13 +1266,17 @@ function WConverhpServer(opt = {}) {
976
1266
  //fileType
977
1267
  let fileType = get(r, 'fileType')
978
1268
  if (!isestr(fileType)) {
1269
+ try {
1270
+ streamRead.destroy() //提供stream前發生錯誤, 得強制destroy
1271
+ }
1272
+ catch (err) {}
979
1273
  return responseU8aStreamWithError(res, 'invalid fileType')
980
1274
  }
981
1275
  fileType = cstr(fileType)
982
1276
 
983
1277
  return res.response(streamRead)
984
1278
  .type(fileType)
985
- .header('Content-Disposition', `attachment; filename="${fileName}"`)
1279
+ .header('Content-Disposition', `attachment; filename="${filename}"`) //針對前端(nodejs)用POST下載, 可基於header內base64檔名解析出並直接給予檔名, 不用預先取得檔名
986
1280
  .header('Content-Length', fileSize)
987
1281
  },
988
1282
  }
@@ -1018,6 +1312,8 @@ function WConverhpServer(opt = {}) {
1018
1312
  apiMain,
1019
1313
  apiUploadSlice,
1020
1314
  apiUploadSliceMerge,
1315
+ apiDownloadGetFilename,
1316
+ apiDownloadGetFile,
1021
1317
  apiDownload,
1022
1318
  ]
1023
1319
  }
@@ -1034,8 +1330,7 @@ function WConverhpServer(opt = {}) {
1034
1330
 
1035
1331
  //start
1036
1332
  if (get(opt, 'serverHapi')) {
1037
- // opt.serverHapi.route([apiMain, apiUploadSlice, apiUploadSliceMerge, apiDownload])
1038
- server.route([apiMain, apiUploadSlice, apiUploadSliceMerge, apiDownload])
1333
+ server.route([apiMain, apiUploadSlice, apiUploadSliceMerge, apiDownloadGetFilename, apiDownloadGetFile, apiDownload])
1039
1334
  }
1040
1335
  else {
1041
1336
  startServer()
@@ -1068,7 +1363,7 @@ export default WConverhpServer
1068
1363
  <br class="clear">
1069
1364
 
1070
1365
  <footer>
1071
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.2</a> on Tue Apr 08 2025 14:22:58 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1366
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.2</a> on Wed Apr 09 2025 14:36:52 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1072
1367
  </footer>
1073
1368
 
1074
1369
  <script>prettyPrint();</script>
package/docs/index.html CHANGED
@@ -71,7 +71,7 @@
71
71
  <br class="clear">
72
72
 
73
73
  <footer>
74
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.2</a> on Tue Apr 08 2025 14:22:58 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
74
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.2</a> on Wed Apr 09 2025 14:36:52 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
75
75
  </footer>
76
76
 
77
77
  <script>prettyPrint();</script>
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "w-converhp",
3
- "version": "2.0.14",
3
+ "version": "2.0.16",
4
4
  "main": "dist/w-converhp-server.umd.js",
5
5
  "dependencies": {
6
6
  "@hapi/hapi": "^21.4.0",
7
7
  "@hapi/inert": "^7.1.0",
8
8
  "axios": "^1.8.4",
9
9
  "lodash-es": "^4.17.21",
10
- "wsemi": "^1.7.75"
10
+ "wsemi": "^1.7.77"
11
11
  },
12
12
  "devDependencies": {
13
13
  "form-data": "^4.0.2",
package/scld.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import path from 'path'
2
- import fs from 'fs'
3
- import _ from 'lodash-es'
4
- import w from 'wsemi'
1
+ // import path from 'path'
2
+ // import fs from 'fs'
3
+ // import _ from 'lodash-es'
4
+ // import w from 'wsemi'
5
5
  import FormData from 'form-data'
6
6
  import WConverhpClient from './src/WConverhpClient.mjs'
7
7