@shijiu/jsview 2.1.435 → 2.1.476-test.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.
@@ -0,0 +1,354 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ import {
7
+ checkNodeVersion,
8
+ execCommand,
9
+ getOptions,
10
+ parseArguments,
11
+ Logger,
12
+ } from './jsview-common.mjs';
13
+ import { assert } from 'node:console';
14
+
15
+ async function updateToFederationBase(options)
16
+ {
17
+ Logger.Info('Updating package.json...');
18
+
19
+ const devDeps = '@originjs/vite-plugin-federation@1.3.4'
20
+ Logger.Info('Installing ' + devDeps + ' ...');
21
+ execCommand('npm install --save-dev ' + devDeps);
22
+ execCommand('npm ci');
23
+ }
24
+
25
+ function genFederationUrl(options)
26
+ {
27
+ var content = '';
28
+
29
+ if(options.mode == 'host') {
30
+ content = `
31
+ const remoteDomain = '${options.remoteDomain}' // 替换成你的 Remote 端 base url 或 ip:port;
32
+ const remoteEntryUrl = remoteDomain + '/js/remoteEntry.js'`;
33
+
34
+ if(options.jsviewMode == 'expose') {
35
+ content += `
36
+ const jsviewLoaderUrl = remoteDomain + '/js/JsViewLoader.js'`
37
+ }
38
+ }
39
+
40
+ return content;
41
+ }
42
+
43
+ function genConfigFunction(options)
44
+ {
45
+ var content = '';
46
+
47
+ if(options.mode == 'remote') {
48
+ content = `
49
+ function getRemoteConfig() {
50
+ const config = {
51
+ name: 'remote-lib',
52
+ filename: 'remoteEntry.js',
53
+ // 需要暴露的模块
54
+ exposes: {`;
55
+
56
+ if(options.jsviewMode == 'expose') {
57
+ content += `
58
+ // 必须模块,JsView 编译需要
59
+ './JsViewLoader': 'node_modules/@shijiu/jsview/loader/jsview-loader.js',
60
+ './JsViewVue': '/node_modules/@shijiu/jsview-vue/index.js',`;
61
+ content += '\n'
62
+ }
63
+
64
+ content += `
65
+ // 自定义模块,根据需要自行配置
66
+ './App.vue': './src/App.vue',
67
+ },`;
68
+ } else if(options.mode == 'host') {
69
+ content = `
70
+ function getHostConfig() {
71
+ const config = {
72
+ name: 'host-app',
73
+ remotes: {
74
+ 'RemoteEntry': remoteEntryUrl,
75
+ },`;
76
+ }
77
+
78
+ content += `
79
+ shared: {`;
80
+ if(options.jsviewMode == 'shared') {
81
+ content += `
82
+ '@shijiu/jsview-vue': {},
83
+ jsview: { packagePath: '@shijiu/jsview-vue' },`;
84
+ }
85
+ content += `
86
+ vue: {},
87
+ 'vue-router': {},
88
+ },
89
+ }
90
+
91
+ return config
92
+ }`;
93
+
94
+ return content;
95
+ }
96
+
97
+ function genChunkFileNameFunction(options)
98
+ {
99
+ var content = '';
100
+
101
+ if(options.mode == 'remote') {
102
+ if(options.jsviewMode == 'expose') {
103
+ content = `
104
+ function getChunkFileName(chunkInfo) {
105
+ if(chunkInfo.name == '__federation_expose_JsViewLoader') {
106
+ return 'js/JsViewLoader.js'
107
+ }
108
+ return (process.env['JSVIEW_KEEP_CHUNKNAME'] ? 'js/[name].[hash].js' : 'js/chunk.jsv.[hash].js')
109
+ }`;
110
+ }
111
+ }
112
+
113
+ return content;
114
+ }
115
+
116
+ function genFederationConfigFunction(options)
117
+ {
118
+ var content = '';
119
+ if(options.mode == 'remote') {
120
+ content += `
121
+ function setFederationRemoteConfig(config, federation) {`;
122
+ } else if(options.mode == 'host') {
123
+ content += `
124
+ function setFederationHostConfig(config, federation) {`;
125
+ }
126
+
127
+ content += `
128
+ config.build = (config.build || {})
129
+ config.build.rollupOptions = (config.build.rollupOptions || {})
130
+ config.build.rollupOptions.output = (config.build.rollupOptions.output || {})
131
+ config.build.rollupOptions.output.manualChunks = (config.build.rollupOptions.output.manualChunks || {})
132
+ config.build.rollupOptions.output.manualChunks["__federation_fn_import"] = ["__federation_fn_import"]`;
133
+
134
+ if(options.mode == 'remote') {
135
+ if(options.jsviewMode == 'expose') {
136
+ content += `
137
+ config.build.rollupOptions.output.chunkFileNames = getChunkFileName`;
138
+ }
139
+ }
140
+
141
+ content += '\n'
142
+ if(options.mode == 'remote') {
143
+ content += `
144
+ const federationConfig = getRemoteConfig()`;
145
+ } else if(options.mode == 'host') {
146
+ content += `
147
+ const federationConfig = getHostConfig()`;
148
+ }
149
+
150
+ content += `
151
+ config.plugins.push(federation(federationConfig))
152
+
153
+ }`;
154
+
155
+ return content;
156
+ }
157
+
158
+ function createFederationRemoteConfigFile(options)
159
+ {
160
+ const federationConfigName = 'federation.remote.config.ts';
161
+ Logger.Info('Creating ' + federationConfigName + ' ...');
162
+
163
+ var federationConfigContent = `
164
+ import federation from '@originjs/vite-plugin-federation'`;
165
+
166
+ federationConfigContent += '\n';
167
+ federationConfigContent += genConfigFunction(options);
168
+ federationConfigContent += '\n';
169
+ federationConfigContent += genChunkFileNameFunction(options);
170
+ federationConfigContent += '\n';
171
+ federationConfigContent += genFederationConfigFunction(options);
172
+ federationConfigContent += '\n';
173
+
174
+ federationConfigContent += `
175
+ export {
176
+ setFederationRemoteConfig,
177
+ }`;
178
+
179
+ fs.writeFileSync(path.resolve(options.projectDir, federationConfigName),
180
+ federationConfigContent,
181
+ 'utf-8');
182
+ }
183
+
184
+ function createFederationHostConfigFile(options)
185
+ {
186
+ const federationConfigName = 'federation.host.config.ts';
187
+ Logger.Info('Creating ' + federationConfigName + ' ...');
188
+
189
+ var federationConfigContent = '';
190
+
191
+ federationConfigContent += '\n';
192
+ federationConfigContent += genFederationUrl(options);
193
+ federationConfigContent += '\n';
194
+ federationConfigContent += genConfigFunction(options);
195
+ federationConfigContent += '\n';
196
+ federationConfigContent += genFederationConfigFunction(options);
197
+ federationConfigContent += '\n';
198
+
199
+ federationConfigContent += `
200
+ export {
201
+ setFederationHostConfig,`;
202
+ if(options.jsviewMode == 'expose') {
203
+ federationConfigContent += `
204
+ jsviewLoaderUrl,`;
205
+ }
206
+ federationConfigContent += `
207
+ }`;
208
+
209
+ fs.writeFileSync(path.resolve(options.projectDir, federationConfigName),
210
+ federationConfigContent,
211
+ 'utf-8');
212
+ }
213
+
214
+ async function updateViteConfigFile(options)
215
+ {
216
+ const viteConfigName = 'vite.config.ts';
217
+ Logger.Info('Updating ' + viteConfigName + ' ...');
218
+
219
+ const viteConfigPath = path.resolve(options.projectDir, viteConfigName);
220
+ var viteConfigContent = fs.readFileSync(viteConfigPath, 'utf-8');
221
+
222
+ const regex = /export default defineConfig(?!\(viteConfig\))/;
223
+ if(regex.test(viteConfigContent)) {
224
+ viteConfigContent = viteConfigContent.replace(regex, 'const viteConfig = ');
225
+
226
+ // 开头添加
227
+ viteConfigContent = "import federation from '@originjs/vite-plugin-federation'\n" + viteConfigContent;
228
+ if(options.mode == 'remote') {
229
+ viteConfigContent = "import { setFederationRemoteConfig } from './federation.remote.config'\n" + viteConfigContent;
230
+ } else if(options.mode == 'host') {
231
+ viteConfigContent = "import { setFederationHostConfig } from './federation.host.config'\n" + viteConfigContent;
232
+ }
233
+
234
+ // 末尾添加
235
+ viteConfigContent += '\n';
236
+ if(options.mode == 'remote') {
237
+ viteConfigContent += 'setFederationRemoteConfig(viteConfig, federation)\n';
238
+ } else if(options.mode == 'host') {
239
+ viteConfigContent += 'setFederationHostConfig(viteConfig, federation)\n';
240
+ }
241
+ viteConfigContent += '\n';
242
+ viteConfigContent += 'export default defineConfig(viteConfig)\n';
243
+ }
244
+
245
+ fs.writeFileSync(viteConfigPath, viteConfigContent, 'utf-8');
246
+
247
+ }
248
+
249
+ function updateJsviewConfigFile(options)
250
+ {
251
+ const jsviewConfigName = path.basename(options.appJsviewConfigFile);
252
+ Logger.Info('Updating ' + jsviewConfigName + ' ...');
253
+
254
+ if(options.mode == 'host') {
255
+ if(options.jsviewMode == 'expose') {
256
+ var jsviewConfigContent = fs.readFileSync(options.appJsviewConfigFile, 'utf-8');
257
+ const regex = /jsviewLoaderUrl/;
258
+ if(regex.test(jsviewConfigContent) == false) {
259
+ jsviewConfigContent = "import { jsviewLoaderUrl } from '../../federation.host.config'\n" + jsviewConfigContent;
260
+ jsviewConfigContent = jsviewConfigContent.replace(/remoteLoader.*?,/, 'remoteLoader: jsviewLoaderUrl,');
261
+ }
262
+ fs.writeFileSync(options.appJsviewConfigFile, jsviewConfigContent, 'utf-8');
263
+ }
264
+ }
265
+ }
266
+
267
+ function updateTsConfigFile(options)
268
+ {
269
+ const tsConfigName = 'tsconfig.json';
270
+ Logger.Info('Updating ' + tsConfigName + ' ...');
271
+
272
+ if(options.mode == 'host') {
273
+ if(options.jsviewMode == 'expose') {
274
+ const tsConfigPath = path.resolve(options.projectDir, tsConfigName);
275
+ var tsConfigContent = fs.readFileSync(tsConfigPath, 'utf-8');
276
+ const regex = /RemoteEntry/;
277
+ if(regex.test(tsConfigContent) == false) {
278
+ tsConfigContent = tsConfigContent.replace(/"jsview"/, '"RemoteEntry/JsViewVue": [ "./node_modules/@shijiu/jsview-vue" ],\n $&');
279
+ }
280
+ fs.writeFileSync(tsConfigPath, tsConfigContent, 'utf-8');
281
+ }
282
+ }
283
+ }
284
+
285
+ function updateToFederationRemote(options)
286
+ {
287
+ createFederationRemoteConfigFile(options);
288
+
289
+ updateViteConfigFile(options);
290
+ }
291
+
292
+ function updateToFederationHost(options)
293
+ {
294
+ createFederationHostConfigFile(options);
295
+
296
+ updateViteConfigFile(options);
297
+
298
+ updateJsviewConfigFile(options);
299
+
300
+ updateTsConfigFile(options);
301
+ }
302
+
303
+
304
+ async function main(argv)
305
+ {
306
+ checkNodeVersion();
307
+
308
+
309
+ const options = getOptions();
310
+
311
+ if(argv.mode != 'remote' && argv.mode != 'host') {
312
+ Logger.ErrorAndExit('Invalid --mode, its value can only be "remote" or "host".');
313
+ }
314
+ options.mode = argv.mode;
315
+
316
+ if(argv.jsview != 'shared' && argv.jsview != 'expose') {
317
+ Logger.ErrorAndExit('Invalid --jsview, its value can only be "shared" or "expose".');
318
+ }
319
+ options.jsviewMode = argv.jsview;
320
+
321
+ if(argv.mode == 'host' && !argv.remoteDomain) {
322
+ Logger.ErrorAndExit('--remote-domain is required for host mode.');
323
+ }
324
+ options.remoteDomain = argv.remoteDomain;
325
+
326
+ Logger.Info();
327
+ Logger.Info('Updating to module federation ' + options.mode + ' ...');
328
+ await updateToFederationBase(options);
329
+ if(options.mode == 'remote') {
330
+ await updateToFederationRemote(options);
331
+ } else if(options.mode == 'host') {
332
+ await updateToFederationHost(options);
333
+ } else {
334
+ assert(0);
335
+ }
336
+ Logger.Info('Success to update project to module federation.');
337
+ Logger.Info('Module federation info:');
338
+ Logger.Info(' Mode: ' + options.mode);
339
+ Logger.Info(' JsView: ' + options.jsviewMode);
340
+ if(options.mode == 'host') {
341
+ Logger.Info(' remote entry url: ' + options.remoteDomain + '/js/remoteEntry.js');
342
+ }
343
+ }
344
+
345
+
346
+ const requiredUsages = {
347
+ '--mode': 'Project mode. the value is "remote" or "host"',
348
+ '--jsview': 'jsview mode. the value is "shared" or "expose"',
349
+ };
350
+ const optionalUsages = {
351
+ '--remote-domain': 'remote domain. Host use this domain to access remote module.',
352
+ };
353
+ const argv = parseArguments(requiredUsages, optionalUsages);
354
+ main(argv)
@@ -8,7 +8,7 @@ import url from 'node:url'
8
8
  import {
9
9
  checkNodeVersion,
10
10
  getOptions,
11
- getPackageObject,
11
+ loadPackageObject,
12
12
  parseArguments,
13
13
  Logger,
14
14
  } from './jsview-common.mjs';
@@ -252,7 +252,7 @@ function makeJsvList(options)
252
252
 
253
253
  async function makeJsvInfo(options)
254
254
  {
255
- const jsviewPkgJson = getPackageObject(options.jsviewDir);
255
+ const jsviewPkgJson = loadPackageObject(options.jsviewDir);
256
256
 
257
257
  const jsviewVersionURL = url.pathToFileURL(options.jsviewDomRevisionFile);
258
258
  const { default: jsviewTargetVersion } = await import(jsviewVersionURL);
@@ -9,7 +9,7 @@ import {
9
9
  cpSync,
10
10
  execCommand,
11
11
  getOptions,
12
- getPackageObject,
12
+ loadPackageObject,
13
13
  isSymlinkSync,
14
14
  parseArguments,
15
15
  symlinkSync,
@@ -33,7 +33,7 @@ function checkNpmCommand()
33
33
 
34
34
  function checkNpmLinkForDebug(options, linkablePkgNames)
35
35
  {
36
- const pkgObj = getPackageObject(options.projectDir);
36
+ const pkgObj = loadPackageObject(options.projectDir);
37
37
 
38
38
  // node 16 不会安装本地包的二次依赖, 需要手动安装。
39
39
  let missingDepPkgs = '';
@@ -46,7 +46,7 @@ function checkNpmLinkForDebug(options, linkablePkgNames)
46
46
  }
47
47
 
48
48
  const linkablePath = path.resolve(options.modulesDir, linkableName);
49
- const linkablePkgObj = getPackageObject(linkablePath);
49
+ const linkablePkgObj = loadPackageObject(linkablePath);
50
50
 
51
51
  for (const dep in linkablePkgObj.dependencies ?? {}) {
52
52
  const depPath = path.resolve(options.modulesDir, dep);
@@ -98,11 +98,11 @@ function checkPatches(options, pkgNeedPatch, skipCheckVersion)
98
98
  for (const pkgName of pkgNeedPatch) {
99
99
  if (skipCheckVersion !== true) {
100
100
  const patchPkgDir = path.resolve(options.jsviewPatchModulesDir, pkgName);
101
- const patchPkgObj = getPackageObject(patchPkgDir);
101
+ const patchPkgObj = loadPackageObject(patchPkgDir);
102
102
  Logger.Info(' ' + pkgName + ': ' + patchPkgObj.version);
103
103
 
104
104
  const modulePkgDir = path.resolve(options.modulesDir, pkgName);
105
- const modulePkgObj = getPackageObject(modulePkgDir);
105
+ const modulePkgObj = loadPackageObject(modulePkgDir);
106
106
  if (modulePkgObj.version != patchPkgObj.version) {
107
107
  Logger.ErrorAndExit(pkgName + '@' + modulePkgObj.version + ' is not supported, required version is ' + patchPkgObj.version);
108
108
  }
@@ -114,7 +114,7 @@ function checkPatches(options, pkgNeedPatch, skipCheckVersion)
114
114
 
115
115
  function installPatches(options, pkgNeedPatch)
116
116
  {
117
- Logger.Info('Patching JsView:');
117
+ Logger.Info('Stage 1: Installing patches for JsView:');
118
118
  for (const pkgName of pkgNeedPatch) {
119
119
  const patchSrc = path.resolve(options.jsviewPatchModulesDir, pkgName);
120
120
  const patchDest = path.resolve(options.modulesDir, pkgName);
@@ -126,6 +126,86 @@ function installPatches(options, pkgNeedPatch)
126
126
  rmSync(options.projectDir, options.cacheDir);
127
127
  }
128
128
 
129
+ function getPatchListRecursive(patchDir)
130
+ {
131
+ var patchList = [];
132
+
133
+ const pkgNameArray = fs.readdirSync(patchDir);
134
+ for (const pkgName of pkgNameArray) {
135
+ const pkgFullPath = path.resolve(patchDir, pkgName);
136
+
137
+ const isDirectory = fs.statSync(pkgFullPath).isDirectory();
138
+ if(isDirectory) {
139
+ const subPatchList = getPatchListRecursive(pkgFullPath);
140
+ patchList = [...patchList, ...subPatchList];
141
+ } else {
142
+ if(pkgFullPath.endsWith('.patch') == false) {
143
+ continue;
144
+ }
145
+
146
+ patchList.push(pkgFullPath);
147
+ }
148
+ }
149
+
150
+ return patchList;
151
+ }
152
+
153
+ function autoPatchPackages(options)
154
+ {
155
+ Logger.Info('Stage 2: Auto patching packages:');
156
+
157
+ const patchCacheDir = path.resolve(options.cacheJsViewDir, 'patches');
158
+ fs.mkdirSync(patchCacheDir, { recursive: true, force: true });
159
+
160
+ const patchInfo = {};
161
+ const patchList = getPatchListRecursive(options.jsviewPatchModulesDir);
162
+ for (const patchFullPath of patchList) {
163
+ const patchRelativePath = path.relative(options.jsviewPatchModulesDir, patchFullPath);
164
+ const patchNameAndVersion = path.dirname(patchRelativePath);
165
+ const patchVersion = path.basename(patchNameAndVersion);
166
+ const patchName = path.dirname(patchNameAndVersion);
167
+
168
+ if(!patchInfo[patchName]) {
169
+ patchInfo[patchName] = [];
170
+ }
171
+ patchInfo[patchName].push(patchVersion);
172
+ }
173
+
174
+ for(const [patchName, patchVersions] of Object.entries(patchInfo)) {
175
+ const pkgFullDir = path.resolve(options.modulesDir, patchName);
176
+ const pkgJsonFullPath = path.resolve(pkgFullDir, 'package.json');
177
+ if(fs.existsSync(pkgJsonFullPath) == false) {
178
+ continue;
179
+ }
180
+
181
+ const pkgObj = loadPackageObject(pkgFullDir);
182
+ const pkgVersion = pkgObj.version;
183
+ if(patchVersions.includes(pkgVersion) == false) {
184
+ Logger.Warn(' Patch file for ' + patchName + '@' + pkgVersion + ' is not found.');
185
+ continue;
186
+ }
187
+
188
+ const patchFullDir = path.resolve(options.jsviewPatchModulesDir, patchName, pkgVersion);
189
+ const patchFiles = fs.readdirSync(patchFullDir);
190
+ for (const file of patchFiles) {
191
+ if(file.endsWith('.patch') == false) {
192
+ continue;
193
+ }
194
+
195
+ const copyFromPath = path.resolve(patchFullDir, file);
196
+ const copyToPath = path.resolve(patchCacheDir, file);
197
+ cpSync(options.projectDir, copyFromPath, copyToPath);
198
+ }
199
+ }
200
+
201
+ const hasPatches = fs.readdirSync(patchCacheDir);
202
+ if(hasPatches && hasPatches.length > 0) {
203
+ execCommand('npx patch-package --patch-dir ' + path.relative(options.projectDir, patchCacheDir));
204
+ } else {
205
+ Logger.Info(' No patch files found.');
206
+ }
207
+ }
208
+
129
209
  async function printRevision(options)
130
210
  {
131
211
  const jsviewVersionURL = url.pathToFileURL(options.jsviewDomRevisionFile);
@@ -188,6 +268,8 @@ function doPostInstall(framework, pkgNeedPatch, skipCheckVersion)
188
268
 
189
269
  installPatches(options, pkgNeedPatch);
190
270
 
271
+ autoPatchPackages(options);
272
+
191
273
  printRevision(options);
192
274
  }
193
275
 
@@ -4,59 +4,67 @@
4
4
  import {
5
5
  askAndAnswer,
6
6
  checkNodeVersion,
7
+ getNetworkIpv4Addresses,
7
8
  getOptions,
8
9
  parseArguments,
9
10
  Logger,
10
11
  execCommand,
12
+ printArgumentsUsages,
11
13
  } from './jsview-common.mjs';
12
14
 
13
15
  async function getExtraOptions(argv)
14
16
  {
15
17
  const options = getOptions(argv.framework);
18
+ options.argumentsLine = argv.argumentsLine;
19
+ options.help = argv.help;
16
20
  options.jsviewCoreRevision = null;
17
21
  options.jsviewEngineUrl = null;
18
22
  options.entryUrl = argv.url;
19
23
 
20
24
  let commandCount = 0;
25
+ commandCount += (argv.configApp ? 1 : 0);
21
26
  commandCount += (argv.genKeypair ? 1 : 0);
22
27
  commandCount += (argv.runonAndroid ? 1 : 0);
23
28
  commandCount += (argv.buildMinmap ? 1 : 0);
24
29
  commandCount += (argv.buildZip ? 1 : 0);
30
+ commandCount += (argv.moduleFederation ? 1 : 0);
31
+ commandCount += (argv.vueDevtools ? 1 : 0);
25
32
  if(commandCount == 0) {
33
+ if(argv.help || argv.h) {
34
+ printArgumentsUsages(requiredUsages, optionalUsages);
35
+ process.exit(0);
36
+ }
37
+
26
38
  const commandPrompt = [
27
- ' 1. runon-android',
28
- ' 2. gen-keypair',
29
- ' 3. build-minmap',
30
- ' 4. build-offline',
39
+ 'runonAndroid',
40
+ 'configApp',
41
+ 'genKeypair',
42
+ 'buildMinmap',
43
+ 'buildZip',
44
+ 'vueDevtools',
45
+ 'moduleFederation',
31
46
  ];
32
47
 
33
48
  Logger.Info();
34
49
  Logger.Info('Please choice a command:');
35
- for(const key in commandPrompt) {
36
- Logger.Info(key);
50
+ for(let idx = 0; idx < commandPrompt.length; idx++) {
51
+ Logger.Info(idx, ': ' + commandPrompt[idx].replace(/[A-Z]/g, match => `-${match.toLowerCase()}`));
37
52
  }
38
- const answer = askAndAnswer('Command Index: ');
39
- switch(answer) {
40
- case '1':
41
- options.runonAndroid = true;
42
- break;
43
- case '2':
44
- options.genKeypair = true;
45
- break;
46
- case '3':
47
- options.buildMinmap = true;
48
- break;
49
- case '4':
50
- options.buildZip = true;
51
- break;
52
- default:
53
- Logger.ErrorAndExitNoException("Unknown input: " + answer);
53
+ const answer = askAndAnswer(`Command Index (0~${commandPrompt.length-1}): `);
54
+ const command = commandPrompt[answer];
55
+ if(!command) {
56
+ Logger.ErrorAndExitNoException("Bad index: " + answer);
54
57
  }
58
+ Logger.Info('command:', command);
59
+ options[command] = true
55
60
  } else if(commandCount == 1) {
56
61
  options.runonAndroid = argv.runonAndroid;
62
+ options.configApp = argv.configApp;
57
63
  options.genKeypair = argv.genKeypair;
58
64
  options.buildMinmap = argv.buildMinmap;
59
65
  options.buildZip = argv.buildZip;
66
+ options.vueDevtools = argv.vueDevtools;
67
+ options.moduleFederation = argv.moduleFederation;
60
68
  } else if(commandCount > 1) {
61
69
  Logger.ErrorAndExitNoException("Only one command can be executed.");
62
70
  }
@@ -68,6 +76,17 @@ function doCommand(options) {
68
76
  let command;
69
77
  if(options.runonAndroid) {
70
78
  command = 'node node_modules/@shijiu/jsview/tools/jsview-run-android.mjs --framework=vue';
79
+ } else if(options.configApp) {
80
+ const defaultConfig = 'JsViewDemo:JsView示例';
81
+ const config = (typeof(options.configApp) === 'string' ? options.configApp : defaultConfig);
82
+ if(config !== options.configApp) {
83
+ Logger.Warn('App config is not set, use default value: ' + defaultConfig);
84
+ }
85
+
86
+ const configArray = config.split(':');
87
+ const appName = configArray[0];
88
+ const appTitle = configArray[1] ?? appName;
89
+ command = 'node node_modules/@shijiu/jsview/tools/jsview-config-app.mjs --app-name=' + appName + ' --app-title=' + appTitle;
71
90
  } else if(options.genKeypair) {
72
91
  command = 'node node_modules/@shijiu/jsview/tools/jsview-generate-keypair.mjs';
73
92
  } else if(options.buildMinmap) {
@@ -86,6 +105,19 @@ function doCommand(options) {
86
105
  }
87
106
 
88
107
  command = 'node node_modules/@shijiu/jsview/tools/jsview-build-zip.mjs --password=' + password;
108
+ } else if(options.vueDevtools) {
109
+ var defaultPort = 8098;
110
+ const port = (typeof(options.vueDevtools) === 'string' ? options.vueDevtools : defaultPort);
111
+ if(port !== options.vueDevtools) {
112
+ Logger.Warn('Vue Devtools server port is not set, use default value: ' + defaultPort);
113
+ }
114
+
115
+ command = 'node node_modules/@shijiu/jsview/tools/jsview-vue-devtools.mjs --port=' + port;
116
+ } else if(options.moduleFederation) {
117
+ var argumentsLine = options.argumentsLine.replace(/ --framework.*? /, ' ');
118
+ argumentsLine = argumentsLine.replace(' -f ', ' ').replace(' --module-federation ', ' ');
119
+
120
+ command = 'node node_modules/@shijiu/jsview/tools/jsview-module-federation.mjs' + argumentsLine;
89
121
  }
90
122
 
91
123
  execCommand(command);
@@ -105,9 +137,12 @@ const requiredUsages = {
105
137
  };
106
138
  const optionalUsages = {
107
139
  '-a | --runon-android': 'Run app on android devices.',
140
+ '-c | --config-app': 'Config app, like: -c or --config-app=[AppName:AppTitle].',
108
141
  '-g | --gen-keypair': 'Generate sign keypair.',
109
142
  '-m | --build-minmap': 'Build target with filter map, like: -m or --build-minmap=[filter].',
110
143
  '-z | --build-zip': 'Build target to offline zip package, like: -z or --build-zip=[password].',
144
+ '-d | --vue-devtools': 'Start vue dev server and vue-devtools standalone, like: -d or --vue-devtools=[port].',
145
+ '-f | --module-federation': 'Make project to module federation, use --module-federation --help for details.',
111
146
  };
112
- const argv = parseArguments(requiredUsages, optionalUsages, false);
147
+ const argv = parseArguments(requiredUsages, optionalUsages, true, true, true);
113
148
  main(argv)