@shijiu/jsview 2.2.373 → 2.3.0

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.
Files changed (33) hide show
  1. package/dom/bin/DroidNaskh-Regular.ttf +0 -0
  2. package/dom/bin/DroidSans.ttf +0 -0
  3. package/dom/bin/DroidSansFallback.ttf +0 -0
  4. package/dom/bin/NotoColorEmoji.ttf +0 -0
  5. package/dom/bin/jsview-dom-browser-engine-core.min.js +2 -0
  6. package/dom/bin/jsview-dom-browser-engine-modules.min.js +2 -0
  7. package/dom/bin/jsview-dom-browser-forge.1436.54c9.wasm +0 -0
  8. package/dom/bin/jsview-dom-browser-forge.min.js +1 -0
  9. package/dom/bin/jsview-dom-browser-forge.worker.min.js +1 -0
  10. package/dom/bin/jsview-dom-browser.min.js +1 -1
  11. package/dom/bin/jsview-dom-native.min.js +1 -1
  12. package/dom/bin/jsview-engine-js-browser.min.js +1 -22
  13. package/dom/bin/jsview-engine-js-native.min.js +1 -1
  14. package/dom/bin/jsview-forge-define.min.js +1 -1
  15. package/dom/index.mjs +8 -10
  16. package/dom/target_core_revision.mjs +3 -3
  17. package/loader/jsv-core-api/jsview-core-api-glue.js +74 -0
  18. package/loader/jsv-core-api/wasm/backgroundtask.js +66 -0
  19. package/loader/jsv-core-api/wasm/core-api.js +208 -0
  20. package/loader/jsv-core-api/wasm/wasm-extension.js +37 -0
  21. package/loader/jsview-config.js +4 -1
  22. package/loader/jsview-loader.js +67 -77
  23. package/loader/jsview-main.mjs +1 -1
  24. package/package.json +1 -1
  25. package/patches/node_modules/vite/dist/node/jsview-vite-extension.js +67 -6
  26. package/tools/https-server-config/cert.pem +61 -0
  27. package/tools/https-server-config/key.pem +27 -0
  28. package/tools/https-server-config/serve.config.json +16 -0
  29. package/tools/jsview-common.mjs +86 -3
  30. package/tools/jsview-post-build.mjs +153 -3
  31. package/tools/jsview-post-install.mjs +7 -4
  32. package/tools/jsview-retrieve-sourcemap.mjs +64 -49
  33. package/tools/jsview-run-tool.mjs +88 -10
@@ -7,6 +7,7 @@ import path from 'node:path';
7
7
  import url from 'node:url'
8
8
  import {
9
9
  checkNodeVersion,
10
+ getJsViewBurdenDefaultBaseUrl,
10
11
  getOptions,
11
12
  loadPackageObject,
12
13
  parseArguments,
@@ -155,7 +156,7 @@ async function prepareMainAppData(options)
155
156
  const encryptBase64 = getEncryptBase64(options.appPrivKey, options.appPubKey, options.appEntryMd5);
156
157
 
157
158
  // 获取 预加载的文件名
158
- const filterKeys = [
159
+ const chunkFilterKeys = [
159
160
  'domNativePath',
160
161
  'NativePlatformDomBridge',
161
162
  'ForgeExtension',
@@ -164,7 +165,7 @@ async function prepareMainAppData(options)
164
165
  'mount("#app")',
165
166
  ];
166
167
  const preloadChunks = [];
167
- const jsFileNames = fs.readdirSync(options.distJsDir);
168
+ let jsFileNames = fs.readdirSync(options.distJsDir);
168
169
  for(const fileName of jsFileNames) {
169
170
  if (!fileName.startsWith('chunk.jsv') || !fileName.endsWith('.js')) {
170
171
  continue;
@@ -172,17 +173,32 @@ async function prepareMainAppData(options)
172
173
 
173
174
  const filePath = path.resolve(options.distJsDir, fileName);
174
175
  const sourceContent = fs.readFileSync(filePath, 'utf8');
175
- if(filterKeys.some(it => sourceContent.includes(it)) == false) {
176
+ if(chunkFilterKeys.some(it => sourceContent.includes(it)) == false) {
176
177
  continue;
177
178
  }
178
179
 
179
180
  preloadChunks.push(fileName);
180
181
  }
181
182
 
183
+ const preloadBurdenResources = [];
184
+ const bunderBaseUrl = process.env['JSVIEW_BURDEN_LOCAL'] ? '' : getBunderBaseUrl();
185
+ const burdenFilePathList = getBurdenFilePathList(options);
186
+ for(const filePath of burdenFilePathList) {
187
+ let fileName = path.basename(filePath);
188
+ if(process.env['JSVIEW_BURDEN_LOCAL']) {
189
+ fileName = path.relative(options.distJsDir, filePath);
190
+ }
191
+ preloadBurdenResources.push(fileName);
192
+ }
193
+
182
194
  // 组装AppData
183
195
  appConfig.PublicKeys = publicKeys; // 使用签名数组,支持后续追加签名
184
196
  appConfig.EncryptCodes = [encryptBase64]; // 同样使用数组,支持后续追加
185
197
  appConfig.PreloadChunks = preloadChunks;
198
+ appConfig.PreloadBurdens = {
199
+ BaseUrl: bunderBaseUrl,
200
+ Resources: preloadBurdenResources,
201
+ };
186
202
 
187
203
  return JSON.stringify(appConfig);
188
204
  }
@@ -253,6 +269,99 @@ async function signApp(options)
253
269
  }
254
270
  }
255
271
 
272
+ function getBunderBaseUrl()
273
+ {
274
+ if(process.env['JSVIEW_BURDEN_LOCAL']) {
275
+ return undefined;
276
+ }
277
+
278
+ let burdenBaseUrl = process.env['JSVIEW_BURDEN_BASEURL'];
279
+ if(!burdenBaseUrl) {
280
+ burdenBaseUrl = getJsViewBurdenDefaultBaseUrl();
281
+ }
282
+ if(!burdenBaseUrl.endsWith('/')) {
283
+ burdenBaseUrl += '/';
284
+ }
285
+
286
+ return burdenBaseUrl;
287
+ }
288
+
289
+ function getBurdenFilePathList(options)
290
+ {
291
+ const burdenFilterSuffixes = [
292
+ '.wasm',
293
+ '.ttf',
294
+ ];
295
+ const burdenFilePathList = [];
296
+
297
+ const assetFileNames = fs.readdirSync(options.distAssetsDir);
298
+ for(const fileName of assetFileNames) {
299
+ const fileExt = path.extname(fileName);
300
+ if (!burdenFilterSuffixes.includes(fileExt)) {
301
+ continue;
302
+ }
303
+ burdenFilePathList.push(path.resolve(options.distAssetsDir, fileName));
304
+ }
305
+ const jsFileNames = fs.readdirSync(options.distJsDir);
306
+ for(const fileName of jsFileNames) {
307
+ const fileExt = path.extname(fileName);
308
+ if (!burdenFilterSuffixes.includes(fileExt)) {
309
+ continue;
310
+ }
311
+ burdenFilePathList.push(path.resolve(options.distJsDir, fileName));
312
+ }
313
+
314
+ return burdenFilePathList;
315
+ }
316
+
317
+ function redirectBurdenResource(options)
318
+ {
319
+ let burdenBaseUrl = getBunderBaseUrl();
320
+ if(!burdenBaseUrl) { // use local
321
+ return;
322
+ }
323
+
324
+ const burdenFilePathList = getBurdenFilePathList(options);
325
+
326
+ const jsFileNames = fs.readdirSync(options.distJsDir);
327
+ for(const fileName of jsFileNames) {
328
+ if (!fileName.endsWith('.js') && !fileName.endsWith('.js.map')) {
329
+ continue;
330
+ }
331
+
332
+ const filePath = path.resolve(options.distJsDir, fileName);
333
+ let sourceContent = fs.readFileSync(filePath, 'utf8');
334
+
335
+ for(const burdenFilePath of burdenFilePathList) {
336
+ const relativeBurdenFilePath = path.relative(options.distJsDir, burdenFilePath);
337
+ if(!sourceContent.includes(relativeBurdenFilePath)) {
338
+ continue;
339
+ }
340
+
341
+ const burdenFileUrl = burdenBaseUrl + path.basename(burdenFilePath);
342
+
343
+ sourceContent = sourceContent.replaceAll(relativeBurdenFilePath, burdenFileUrl);
344
+ Logger.Info('Burdening ' + path.relative(options.projectDir, filePath) + ' for [' + relativeBurdenFilePath + ']');
345
+ }
346
+
347
+ fs.writeFileSync(filePath, sourceContent, 'utf8');
348
+ };
349
+ }
350
+
351
+ function cleanupBurdenResource(options)
352
+ {
353
+ let burdenBaseUrl = getBunderBaseUrl();
354
+ if(!burdenBaseUrl) { // 本地用不要清除
355
+ return;
356
+ }
357
+
358
+ const burdenFilePathList = getBurdenFilePathList(options);
359
+ for(const filePath of burdenFilePathList) {
360
+ fs.rmSync(filePath);
361
+ Logger.Info('Cleanup burden file: ' + path.relative(options.projectDir, filePath));
362
+ }
363
+ }
364
+
256
365
  function redirectSourceMappingURL(options)
257
366
  {
258
367
  const jsFileNames = fs.readdirSync(options.distJsDir);
@@ -307,6 +416,28 @@ function makeMainJsvMjs(options, framework)
307
416
  fs.copyFileSync(newEntryFilePath, debugEntryFilePath);
308
417
  }
309
418
 
419
+ function getWasmMapChunkName(options, wasmMapName)
420
+ {
421
+ let chunkName = wasmMapName;
422
+
423
+ const regex = new RegExp(`sourceMappingURL.${wasmMapName}`);
424
+ const jsFileNames = fs.readdirSync(options.distJsDir);
425
+ for(const fileName of jsFileNames) {
426
+ if (!fileName.endsWith('.wasm')) {
427
+ continue;
428
+ }
429
+
430
+ const filePath = path.resolve(options.distJsDir, fileName);
431
+ const content = fs.readFileSync(filePath, 'utf-8');
432
+ if(regex.test(content)) {
433
+ chunkName = fileName + '.map';
434
+ break;
435
+ }
436
+ };
437
+
438
+ return chunkName;
439
+ }
440
+
310
441
  function makeDebugMap(options, framework)
311
442
  {
312
443
  fs.mkdirSync(options.distDebugMapDir, { recursive: true });
@@ -323,6 +454,19 @@ function makeDebugMap(options, framework)
323
454
  fs.renameSync(from, to);
324
455
  };
325
456
 
457
+ const wasmFileNames = fs.readdirSync(options.jsviewDomBinDir);
458
+ for(const fileName of wasmFileNames) {
459
+ if (!fileName.endsWith('.wasm.map')) {
460
+ continue;
461
+ }
462
+
463
+ const chunkName = getWasmMapChunkName(options, fileName);
464
+ const from = path.resolve(options.jsviewDomBinDir, fileName);
465
+ const to = path.resolve(options.distDebugMapDir, chunkName);
466
+ Logger.Info(' -> ' + path.relative(options.projectDir, to));
467
+ fs.copyFileSync(from, to);
468
+ };
469
+
326
470
  const jsmapServeName = 'jsview-jsmap-serve.mjs';
327
471
  const jsmapServePath = path.resolve(options.jsviewToolsDir, jsmapServeName);
328
472
  if (!fs.existsSync(jsmapServePath)) {
@@ -407,6 +551,10 @@ async function main(argv)
407
551
  await checkDomDebugDisabled(options);
408
552
 
409
553
  Logger.Info();
554
+ Logger.Info('Redirecting JsView burden resource...');
555
+ redirectBurdenResource(options)
556
+ Logger.Info('Redirected JsView burden resource...');
557
+
410
558
  Logger.Info('Redirecting JsView source map...');
411
559
  redirectSourceMappingURL(options)
412
560
  Logger.Info('Redirected JsView source map...');
@@ -435,6 +583,8 @@ async function main(argv)
435
583
  await makeJsvInfo(options);
436
584
  Logger.Info('Made JsView info...');
437
585
 
586
+ cleanupBurdenResource(options);
587
+
438
588
  Logger.Info('Done...');
439
589
  }
440
590
 
@@ -245,7 +245,7 @@ async function printRevision(options)
245
245
  Logger.Info('**************************************************');
246
246
  }
247
247
 
248
- function doPostInstall(framework, pkgNeedPatch, skipCheckVersion)
248
+ function doPostInstall(framework, pkgNeedPatch, skipCheckVersion, skipCheckNpmcmd)
249
249
  {
250
250
  const options = getOptions(framework);
251
251
  options.projectDir = process.cwd();
@@ -260,7 +260,9 @@ function doPostInstall(framework, pkgNeedPatch, skipCheckVersion)
260
260
  '@shijiu/jsview-react-extra-samples',
261
261
  ];
262
262
 
263
- checkNpmCommand();
263
+ if(!skipCheckNpmcmd) {
264
+ checkNpmCommand();
265
+ }
264
266
 
265
267
  checkNpmLinkForDebug(options, linkablePkgNames);
266
268
 
@@ -304,14 +306,15 @@ function main(argv)
304
306
  Logger.ErrorAndExit('Failed to support framework: ' + framework);
305
307
  }
306
308
 
307
- doPostInstall(argv.framework, pkgNeedPatch, argv.skipCheckVersion);
309
+ doPostInstall(argv.framework, pkgNeedPatch, argv.skipCheckVersion, argv.skipCheckNpmcmd);
308
310
  }
309
311
 
310
312
  const requiredUsages = {
311
313
  '--framework': 'Select from [vue|react]',
312
314
  };
313
315
  const optionalUsages = {
314
- '--skip-check-version': 'Skip check patches version.'
316
+ '--skip-check-version': 'Skip check patches version.',
317
+ '--skip-check-npmcmd': 'Skip check npm command.'
315
318
  };
316
319
  const argv = parseArguments(requiredUsages, optionalUsages);
317
320
  main(argv);
@@ -8,6 +8,7 @@ import {
8
8
  checkNodeVersion,
9
9
  convertHomeDirectory,
10
10
  execCommand,
11
+ execCommandPromise,
11
12
  getOptions,
12
13
  parseArguments,
13
14
  Logger,
@@ -24,13 +25,14 @@ function getExtraOptions(argv)
24
25
  options.inputFile = convertHomeDirectory(argv.inputFile);
25
26
  options.outputFile = convertHomeDirectory(argv.outputFile);
26
27
  options.sourcemapDir = convertHomeDirectory(argv.sourcemapDir) ?? getDefaultSourceMapDir();
28
+ options.debugWasmFile = argv.debugWasmFile;
27
29
  options.sourceMapMoudulePath = path.resolve(options.modulesDir, 'source-map', 'source-map.js');
28
30
 
29
31
  if(!argv.sourcemapDir) {
30
32
  Logger.Warn('Use default source map dir: ' + options.sourcemapDir);
31
33
  }
32
34
  if(fs.existsSync(options.sourcemapDir) == false) {
33
- Logger.ErrorAndExit('Source map dir is not exists. Please check dir: ' + options.sourcemapDir);
35
+ Logger.Warn('Source map dir is not exists. Please check dir: ' + options.sourcemapDir);
34
36
  }
35
37
 
36
38
  return options;
@@ -63,17 +65,17 @@ async function parseConsoleLog(options)
63
65
  const content = fs.readFileSync(options.inputFile, 'utf-8');
64
66
  const contentLines = content.split('\n');
65
67
 
66
- const regexCharAt = /^\s+at\s+(\S+)?\s?\(?(.*):(\d+):(\d+)\)?$/;
67
- const regexSymbolAt = /^(\S+) @ (.*?):(\d+)(?::(\d+))?$/;
68
+ const regexWasm = / at .* \(.*\.wasm.*:0x[0-9a-f]*\)/;
69
+ const regexJs = / at .* \((.*):(\d+):(\d+)\)/;
68
70
 
69
- var resultLines = [];
71
+ let resultLines = [];
70
72
  for(const line of contentLines) {
71
- var recovered = line.replace(/.*?:\d+ /, '');
73
+ let recovered = line.replace(/.*?:\d+ /, '');
72
74
 
73
- if(regexCharAt.test(recovered)) {
74
- recovered = await recoverCharAt(options, recovered, regexCharAt);
75
- } else if(regexSymbolAt.test(recovered)) {
76
- recovered = await recoverSymbolAt(options, recovered, regexSymbolAt);
75
+ if(regexWasm.test(recovered)) {
76
+ recovered = await recoverWasmLine(options, recovered);
77
+ } else if(regexJs.test(recovered)) {
78
+ recovered = await recoverJsLine(options, recovered);
77
79
  }
78
80
 
79
81
  if(!options.outputFile) {
@@ -89,57 +91,65 @@ async function parseConsoleLog(options)
89
91
  }
90
92
  }
91
93
 
92
- async function recoverCharAt(options, content, regex)
94
+ async function recoverWasmLine(options, content)
93
95
  {
94
- const matchResult = regex.exec(content);
95
- var funcName = matchResult?.[1];
96
- var fileName = matchResult?.[2];
97
- var fileRow = matchResult?.[3];
98
- var fileColumn = matchResult?.[4];
99
-
100
- // at file.js:row:column
101
- if(!fileName) {
102
- fileName = funcName;
103
- funcName = "";
104
- } else { // at func (file.js:row:column)
105
- // do nothing
96
+ if(!options.debugWasmFile) {
97
+ Logger.Warn('Debug wasm file is not exists. Please set by argument: --debug-wasm-file');
98
+ return content;
106
99
  }
107
100
 
108
- const origPos = await getOriginalPosition(options, fileName, fileRow, fileColumn);
109
- if(!origPos) {
101
+ const prefixIdx = content.lastIndexOf('(');
102
+ const suffixIdx = content.indexOf(')', prefixIdx);
103
+ if(prefixIdx < 0 || suffixIdx < 0) {
110
104
  return content;
111
105
  }
112
106
 
113
- funcName = (origPos.name ?? funcName);
114
- content = ' at ';
115
- content += funcName
116
- content += (funcName ? ' (' : '');
117
- content += (origPos.source + ':' + origPos.line + ':' + origPos.column);
118
- content += (funcName ? ') ' : '');
107
+ const fileInfo = content.slice(prefixIdx + 1).slice(0, suffixIdx - prefixIdx - 1);
108
+ const colonIdx = fileInfo.lastIndexOf(':');
109
+ const address = fileInfo.slice(colonIdx + 1);
110
+
111
+ const cmdline = `emsymbolizer ${options.debugWasmFile} ${address}`;
112
+ const origPos = await execCommandPromise(cmdline);
119
113
 
120
- return content;
114
+ let result = content.slice(0, prefixIdx + 1);
115
+ result += origPos;
116
+ result += content.slice(suffixIdx);
117
+
118
+ return result;
121
119
  }
122
120
 
123
- async function recoverSymbolAt(options, content, regex)
121
+ async function recoverJsLine(options, content)
124
122
  {
125
- // 忽略,拿不到column,不能解析出结果
126
- // const matchResult = regex.exec(content);
127
- // var funcName = matchResult?.[1];
128
- // var fileName = matchResult?.[2];
129
- // var fileRow = matchResult?.[3];
130
- // var fileColumn = matchResult?.[4];
131
-
132
- // const origPos = await getOriginalPosition(options, fileName, fileRow, fileColumn);
133
- // if(!origPos) {
134
- // return content;
123
+ const prefixIdx = content.lastIndexOf('(');
124
+ const suffixIdx = content.indexOf(')', prefixIdx);
125
+ if(prefixIdx < 0 || suffixIdx < 0) {
126
+ return content;
127
+ }
128
+
129
+ const fileInfo = content.slice(prefixIdx + 1).slice(0, suffixIdx - prefixIdx - 1);
130
+ const fileInfoArray = fileInfo.split(':');
131
+ let fileName = fileInfoArray[0];
132
+ let fileRow = fileInfoArray[1];
133
+ let fileColumn = fileInfoArray[2];
134
+
135
+ // // at file.js:row:column
136
+ // if(!fileName) {
137
+ // fileName = funcName;
138
+ // funcName = "";
139
+ // } else { // at func (file.js:row:column)
140
+ // // do nothing
135
141
  // }
136
142
 
137
- // funcName = (origPos.name ?? funcName);
138
- // content = funcName
139
- // content += ' @ '
140
- // content += (origPos.source + ':' + origPos.line + ':' + origPos.column);
143
+ const origPos = await getOriginalPosition(options, fileName, fileRow, fileColumn);
144
+ if(!origPos) {
145
+ return content;
146
+ }
141
147
 
142
- return content;
148
+ let result = content.slice(0, prefixIdx + 1);
149
+ result += (origPos.source + ':' + origPos.line + ':' + origPos.column);
150
+ result += content.slice(suffixIdx);
151
+
152
+ return result;
143
153
  }
144
154
 
145
155
  async function getOriginalPosition(options, fileName, fileRow, fileColumn)
@@ -148,13 +158,17 @@ async function getOriginalPosition(options, fileName, fileRow, fileColumn)
148
158
  return null;
149
159
  }
150
160
 
151
- const sourceMapFilePath = path.resolve(options.sourcemapDir, fileName + '.map');
161
+ if(fileName.endsWith('.map') == false) {
162
+ fileName = fileName + '.map';
163
+ }
164
+
165
+ const sourceMapFilePath = path.resolve(options.sourcemapDir, fileName);
152
166
  if(fs.existsSync(sourceMapFilePath) == false) {
153
167
  Logger.Warn('Source map file is not found: ' + sourceMapFilePath)
154
168
  return null;
155
169
  }
156
170
 
157
- var sourceMapConsumer = options.sourceMapConsumerMap[sourceMapFilePath];
171
+ let sourceMapConsumer = options.sourceMapConsumerMap[sourceMapFilePath];
158
172
  if(!sourceMapConsumer) {
159
173
  const sourceMapContent = fs.readFileSync(sourceMapFilePath, 'utf-8');
160
174
  sourceMapConsumer = new options.sourceMapModule.SourceMapConsumer(sourceMapContent);
@@ -188,6 +202,7 @@ const requiredUsages = {
188
202
  };
189
203
  const optionalUsages = {
190
204
  '-d | --sourcemap-dir': 'Source map dir. Default dir is: ' + getDefaultSourceMapDir(),
205
+ '-w | --debug-wasm-file': 'Debug wasm file path.',
191
206
  '-o | --output-file': 'Recovered console log file path.',
192
207
  };
193
208
  const argv = parseArguments(requiredUsages, optionalUsages, false);
@@ -1,15 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
+ import path from 'node:path';
4
5
  import {
5
6
  askAndAnswer,
6
7
  checkNodeVersion,
7
- getNetworkIpv4Addresses,
8
+ execCommand,
9
+ getExportPrefix,
8
10
  getOptions,
11
+ isCommandAvailable,
9
12
  parseArguments,
10
- Logger,
11
- execCommand,
12
13
  printArgumentsUsages,
14
+ Logger,
13
15
  } from './jsview-common.mjs';
14
16
 
15
17
  async function getExtraOptions(argv)
@@ -27,7 +29,14 @@ async function getExtraOptions(argv)
27
29
  commandCount += (argv.runonAndroid ? 1 : 0);
28
30
  commandCount += (argv.buildMinifyExclude ? 1 : 0);
29
31
  commandCount += (argv.buildZip ? 1 : 0);
32
+ commandCount += (argv.buildBurdenLocal ? 1 : 0);
33
+ commandCount += (argv.buildBurdenBaseurl ? 1 : 0);
30
34
  commandCount += (argv.moduleFederation ? 1 : 0);
35
+ commandCount += (argv.httpServer ? 1 : 0);
36
+ commandCount += (argv.httpsServer ? 1 : 0);
37
+ commandCount += (argv.httpVite ? 1 : 0);
38
+ commandCount += (argv.httpsVite ? 1 : 0);
39
+ commandCount += (argv.fowardArkweb ? 1 : 0);
31
40
  commandCount += (argv.vueDevtools ? 1 : 0);
32
41
  if(commandCount == 0) {
33
42
  if(argv.help || argv.h) {
@@ -41,7 +50,14 @@ async function getExtraOptions(argv)
41
50
  'genKeypair',
42
51
  'buildMinifyExclude',
43
52
  'buildZip',
53
+ 'buildBurdenLocal',
54
+ 'buildBurdenBaseurl',
44
55
  'vueDevtools',
56
+ 'httpServer',
57
+ 'httpsServer',
58
+ 'httpVite',
59
+ 'httpsVite',
60
+ 'fowardArkweb',
45
61
  'moduleFederation',
46
62
  ];
47
63
 
@@ -63,7 +79,14 @@ async function getExtraOptions(argv)
63
79
  options.genKeypair = argv.genKeypair;
64
80
  options.buildMinifyExclude = argv.buildMinifyExclude;
65
81
  options.buildZip = argv.buildZip;
82
+ options.buildBurdenLocal = argv.buildBurdenLocal;
83
+ options.buildBurdenBaseurl = argv.buildBurdenBaseurl;
66
84
  options.vueDevtools = argv.vueDevtools;
85
+ options.httpServer = argv.httpServer;
86
+ options.httpsServer = argv.httpsServer;
87
+ options.httpsVite = argv.httpsVite;
88
+ options.httpVite = argv.httpVite;
89
+ options.fowardArkweb = argv.fowardArkweb;
67
90
  options.moduleFederation = argv.moduleFederation;
68
91
  } else if(commandCount > 1) {
69
92
  Logger.ErrorAndExitNoException("Only one command can be executed.");
@@ -93,13 +116,13 @@ function doCommand(options, argv) {
93
116
  let filter = options.buildMinifyExclude;
94
117
  if(typeof(filter) !== 'string') {
95
118
  filter = 'jsview-';
96
- Logger.Warn('Minify filter is not set, use default value: ' + filter);
119
+ Logger.Warn(`Minify filter is not set, use default value: ${filter}`);
97
120
  }
98
121
 
99
122
  let script = argv.s ?? argv.script;
100
123
  if(typeof(script) !== 'string') {
101
124
  script = 'build';
102
- Logger.Warn('Build script is not set, use default value: ' + script);
125
+ Logger.Warn(`Build script is not set, use default value: ${script}`);
103
126
  }
104
127
 
105
128
  command = 'node node_modules/@shijiu/jsview/tools/jsview-build-minify-exclude.mjs --filter=' + filter + ' --script=' + script;
@@ -107,23 +130,71 @@ function doCommand(options, argv) {
107
130
  const defaultPassword = 'jsview.shijiu.com';
108
131
  const password = (typeof(options.buildZip) === 'string' ? options.buildZip : defaultPassword);
109
132
  if(password !== options.buildZip) {
110
- Logger.Warn('Zip password is not set, use default value: ' + defaultPassword);
133
+ Logger.Warn(`Zip password is not set, use default value: ${defaultPassword}`);
111
134
  }
112
135
 
113
- command = 'node node_modules/@shijiu/jsview/tools/jsview-build-zip.mjs --password=' + password;
136
+ command = `node node_modules/@shijiu/jsview/tools/jsview-build-zip.mjs --password=${password}`;
137
+ } else if(options.buildBurdenLocal) {
138
+ command = 'JSVIEW_BURDEN_LOCAL=true npm run build';
139
+ } else if(options.buildBurdenBaseurl) {
140
+ if(typeof options.buildBurdenBaseurl != 'string') {
141
+ Logger.ErrorAndExitNoException("Bad build burden base url, please set valid url such as: https://example.com/burden-dir.");
142
+ }
143
+ command = `JSVIEW_BURDEN_BASEURL=${options.buildBurdenBaseurl} npm run build`;
114
144
  } else if(options.vueDevtools) {
115
145
  var defaultPort = 8098;
116
146
  const port = (typeof(options.vueDevtools) === 'string' ? options.vueDevtools : defaultPort);
117
147
  if(port !== options.vueDevtools) {
118
- Logger.Warn('Vue Devtools server port is not set, use default value: ' + defaultPort);
148
+ Logger.Warn(`Vue Devtools server port is not set, use default value: ${port}`);
119
149
  }
120
150
 
121
- command = 'node node_modules/@shijiu/jsview/tools/jsview-vue-devtools.mjs --port=' + port;
151
+ command = `node node_modules/@shijiu/jsview/tools/jsview-vue-devtools.mjs --port=${port}`;
122
152
  } else if(options.moduleFederation) {
123
153
  var argumentsLine = options.argumentsLine.replace(/ --framework.*? /, ' ');
124
154
  argumentsLine = argumentsLine.replace(' -f ', ' ').replace(' --module-federation ', ' ');
125
155
 
126
- command = 'node node_modules/@shijiu/jsview/tools/jsview-module-federation.mjs' + argumentsLine;
156
+ command = `node node_modules/@shijiu/jsview/tools/jsview-module-federation.mjs ${argumentsLine}`;
157
+ } else if(options.httpServer) {
158
+ if(isCommandAvailable('serve') == false) {
159
+ Logger.ErrorAndExitNoException("Command 'serve' is not found, please install it first by 'npm install -g serve'.");
160
+ }
161
+ if(typeof options.httpServer !== 'string') {
162
+ Logger.ErrorAndExitNoException("Dir path is not found, please set dir by [-t|--http-server]=[DirPath].");
163
+ }
164
+ command = `serve -p 8080 --cors ${options.httpServer}`;
165
+ } else if(options.httpsServer) {
166
+ if(isCommandAvailable('serve') == false) {
167
+ Logger.ErrorAndExitNoException("Command 'serve' is not found, please install it first by 'npm install -g serve'.");
168
+ }
169
+ if(typeof options.httpsServer !== 'string') {
170
+ Logger.ErrorAndExitNoException("Dir path is not found, please set dir by [-s|--https-server]=[DirPath].");
171
+ }
172
+ const exportPrefix = getExportPrefix();
173
+ const certPath = path.resolve(options.jsviewToolsDir, 'https-server-config/cert.pem');
174
+ const keyPath = path.resolve(options.jsviewToolsDir, 'https-server-config/key.pem');
175
+ const configPath = path.resolve(options.jsviewToolsDir, 'https-server-config/serve.config.json');
176
+ command = `${exportPrefix} NODE_OPTIONS='--tls-min-v1.0 --tls-max-v1.2'`;
177
+ command += ` && serve -p 8080 --cors --ssl-cert ${certPath} --ssl-key ${keyPath} --config ${configPath} ${options.httpsServer}`;
178
+ } else if(options.httpVite) {
179
+ command = `npm start`;
180
+ } else if(options.httpsVite) {
181
+ const exportPrefix = getExportPrefix();
182
+ command = `${exportPrefix} JSVIEW_ENABLE_HTTPS=true && npm start`;
183
+ } else if(options.fowardArkweb) {
184
+ var defaultPort = 9220;
185
+ const port = (typeof(options.fowardArkweb) === 'string' ? options.fowardArkweb : defaultPort);
186
+ if(port !== options.fowardArkweb) {
187
+ Logger.Warn(`Foward webview port is not set, use default value: ${port}`);
188
+ }
189
+
190
+ command = `hdc shell cat /proc/net/unix | grep devtools`;
191
+ const output = execCommand(command, true);
192
+ if(output.includes('@webview_devtools_remote_') == false) {
193
+ Logger.ErrorAndThrow(`Failed to find foward webview process.`);
194
+ }
195
+ const webviewPid = output.substring(output.indexOf('@') + 1).trim();
196
+
197
+ command = `hdc fport tcp:${port} localabstract:${webviewPid}`;
127
198
  }
128
199
 
129
200
  execCommand(command);
@@ -147,7 +218,14 @@ const optionalUsages = {
147
218
  '-g | --gen-keypair': 'Generate sign keypair.',
148
219
  '-m | --build-minify-exclude': 'Build target with minify-exclude filter, like: -m or --build-minify-exclude=[filter], additional options: -s or --script=build:dev.',
149
220
  '-z | --build-zip': 'Build target to offline zip package, like: -z or --build-zip=[password].',
221
+ '-l | --build-burden-local': 'Build target with local burden files.',
222
+ '-b | --build-burden-baseurl': 'Build target with custom burden base url.',
150
223
  '-d | --vue-devtools': 'Start vue dev server and vue-devtools standalone, like: -d or --vue-devtools=[port].',
224
+ '-t | --http-server': '=[DirPath]. Start http server for debug, port is 8080.',
225
+ '-s | --https-server': '=[DirPath]. Start https server for debug, port is 8080.',
226
+ '-v | --http-vite': 'Start vite https server for debug, same as `npm start`',
227
+ '-i | --https-vite': 'Start vite https server for debug.',
228
+ '-p | --foward-arkweb': 'Foward port to openharmony webview devtools, like -p or --foward-arkweb=[port].',
151
229
  '-f | --module-federation': 'Make project to module federation, use --module-federation --help for details.',
152
230
  };
153
231
  const argv = parseArguments(requiredUsages, optionalUsages, true, true, true);