@nocobase/cli-v1 2.1.11 → 2.2.0-alpha.2
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/cli-v1",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0-alpha.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
"nocobase-v1": "./bin/index.js"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@nocobase/cli": "2.
|
|
12
|
+
"@nocobase/cli": "2.2.0-alpha.2",
|
|
13
13
|
"@nocobase/license-kit": "^0.3.8",
|
|
14
|
-
"@nocobase/utils": "2.
|
|
14
|
+
"@nocobase/utils": "2.2.0-alpha.2",
|
|
15
15
|
"chalk": "^4.1.1",
|
|
16
16
|
"commander": "^9.2.0",
|
|
17
17
|
"deepmerge": "^4.3.1",
|
|
@@ -33,5 +33,5 @@
|
|
|
33
33
|
"url": "git+https://github.com/nocobase/nocobase.git",
|
|
34
34
|
"directory": "packages/core/cli"
|
|
35
35
|
},
|
|
36
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "9dd5224bb8f6c1ac12d766b9f175bdc29bddd845"
|
|
37
37
|
}
|
|
@@ -24,6 +24,8 @@ function createAppPackageRoot() {
|
|
|
24
24
|
[
|
|
25
25
|
"window['__nocobase_app_dev__'] = {{env.NOCOBASE_APP_DEV}};",
|
|
26
26
|
"window['__nocobase_public_path__'] = '{{env.APP_PUBLIC_PATH}}';",
|
|
27
|
+
"window['__nocobase_modern_client_prefix__'] = '{{env.APP_MODERN_CLIENT_PREFIX}}';",
|
|
28
|
+
"window['__nocobase_app_client_entry_mode__'] = '{{env.APP_CLIENT_ENTRY_MODE}}';",
|
|
27
29
|
].join('\n'),
|
|
28
30
|
'utf-8',
|
|
29
31
|
);
|
|
@@ -73,11 +75,43 @@ describe('cli-v1 buildIndexHtml', () => {
|
|
|
73
75
|
process.env.APP_PACKAGE_ROOT = appRoot;
|
|
74
76
|
process.env.APP_PUBLIC_PATH = '/';
|
|
75
77
|
process.env.NOCOBASE_APP_DEV = '';
|
|
78
|
+
process.env.APP_MODERN_CLIENT_PREFIX = 'console';
|
|
79
|
+
process.env.APP_CLIENT_ENTRY_MODE = 'modern-default';
|
|
76
80
|
|
|
77
81
|
buildIndexHtml();
|
|
78
82
|
|
|
79
83
|
const html = fs.readFileSync(path.join(appRoot, 'dist/client/index.html'), 'utf-8');
|
|
80
84
|
expect(html).toContain("window['__nocobase_app_dev__'] = false;");
|
|
85
|
+
expect(html).toContain("window['__nocobase_modern_client_prefix__'] = 'console';");
|
|
86
|
+
expect(html).toContain("window['__nocobase_app_client_entry_mode__'] = 'modern-default';");
|
|
87
|
+
fs.removeSync(appRoot);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('refreshes cached tpl when new runtime placeholders are missing', () => {
|
|
91
|
+
const appRoot = createAppPackageRoot();
|
|
92
|
+
const tplPath = path.join(appRoot, 'dist/client/index.html.tpl');
|
|
93
|
+
const indexPath = path.join(appRoot, 'dist/client/index.html');
|
|
94
|
+
fs.writeFileSync(tplPath, "window['__nocobase_public_path__'] = '{{env.APP_PUBLIC_PATH}}';", 'utf-8');
|
|
95
|
+
fs.writeFileSync(
|
|
96
|
+
indexPath,
|
|
97
|
+
[
|
|
98
|
+
"window['__nocobase_public_path__'] = '{{env.APP_PUBLIC_PATH}}';",
|
|
99
|
+
"window['__nocobase_modern_client_prefix__'] = '{{env.APP_MODERN_CLIENT_PREFIX}}';",
|
|
100
|
+
"window['__nocobase_app_client_entry_mode__'] = '{{env.APP_CLIENT_ENTRY_MODE}}';",
|
|
101
|
+
].join('\n'),
|
|
102
|
+
'utf-8',
|
|
103
|
+
);
|
|
104
|
+
process.argv = ['node', 'nocobase-v1', 'start'];
|
|
105
|
+
process.env.APP_PACKAGE_ROOT = appRoot;
|
|
106
|
+
process.env.APP_PUBLIC_PATH = '/';
|
|
107
|
+
process.env.APP_MODERN_CLIENT_PREFIX = 'v';
|
|
108
|
+
process.env.APP_CLIENT_ENTRY_MODE = 'modern-only';
|
|
109
|
+
|
|
110
|
+
buildIndexHtml();
|
|
111
|
+
|
|
112
|
+
const tpl = fs.readFileSync(tplPath, 'utf-8');
|
|
113
|
+
expect(tpl).toContain('__nocobase_modern_client_prefix__');
|
|
114
|
+
expect(tpl).toContain('__nocobase_app_client_entry_mode__');
|
|
81
115
|
fs.removeSync(appRoot);
|
|
82
116
|
});
|
|
83
117
|
});
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
/* eslint-env jest */
|
|
11
11
|
|
|
12
|
-
const { buildAppDevForwardArgs, forwardDevToAppDev } = require('../commands/dev')._test;
|
|
12
|
+
const { buildAppDevForwardArgs, forwardDevToAppDev, resolveDevRuntimeMode } = require('../commands/dev')._test;
|
|
13
13
|
|
|
14
14
|
describe('cli-v1 dev command', () => {
|
|
15
15
|
test('buildAppDevForwardArgs rewrites dev argv to app-dev while preserving extra args', () => {
|
|
@@ -31,4 +31,31 @@ describe('cli-v1 dev command', () => {
|
|
|
31
31
|
|
|
32
32
|
expect(calls).toEqual([['nocobase-v1', ['app-dev', '--port', '13000', '--db-sync']]]);
|
|
33
33
|
});
|
|
34
|
+
|
|
35
|
+
test('resolveDevRuntimeMode keeps both clients in legacy-default', () => {
|
|
36
|
+
expect(resolveDevRuntimeMode({ appClientEntryMode: 'legacy-default' })).toMatchObject({
|
|
37
|
+
useModernOnlyEntryMode: false,
|
|
38
|
+
shouldRunClient: true,
|
|
39
|
+
shouldRunClientV2: true,
|
|
40
|
+
shouldRunServer: true,
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('resolveDevRuntimeMode only runs v2 client and server in modern-only', () => {
|
|
45
|
+
expect(resolveDevRuntimeMode({ appClientEntryMode: 'modern-only' })).toMatchObject({
|
|
46
|
+
useModernOnlyEntryMode: true,
|
|
47
|
+
shouldRunClient: false,
|
|
48
|
+
shouldRunClientV2: true,
|
|
49
|
+
shouldRunServer: true,
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('resolveDevRuntimeMode preserves explicit client-v2-only flag behavior', () => {
|
|
54
|
+
expect(resolveDevRuntimeMode({ clientV2Only: true, appClientEntryMode: 'legacy-default' })).toMatchObject({
|
|
55
|
+
useModernOnlyEntryMode: false,
|
|
56
|
+
shouldRunClient: false,
|
|
57
|
+
shouldRunClientV2: true,
|
|
58
|
+
shouldRunServer: false,
|
|
59
|
+
});
|
|
60
|
+
});
|
|
34
61
|
});
|
package/src/commands/dev.js
CHANGED
|
@@ -20,6 +20,7 @@ const {
|
|
|
20
20
|
isPortReachable,
|
|
21
21
|
buildWSURL,
|
|
22
22
|
checkDBDialect,
|
|
23
|
+
resolveAppClientEntryMode,
|
|
23
24
|
} = require('../util');
|
|
24
25
|
const { getPortPromise } = require('portfinder');
|
|
25
26
|
const chokidar = require('chokidar');
|
|
@@ -47,6 +48,25 @@ function buildAppDevForwardArgs(argv = process.argv) {
|
|
|
47
48
|
return ['app-dev', ...argv.slice(3)];
|
|
48
49
|
}
|
|
49
50
|
|
|
51
|
+
function resolveDevRuntimeMode(opts = {}) {
|
|
52
|
+
const appClientEntryMode = opts.appClientEntryMode || resolveAppClientEntryMode();
|
|
53
|
+
const useModernOnlyEntryMode = appClientEntryMode === 'modern-only';
|
|
54
|
+
const clientV2Only = !!opts.clientV2Only;
|
|
55
|
+
const forceClient = !!opts.client;
|
|
56
|
+
const forceServer = !!opts.server;
|
|
57
|
+
const shouldRunClientV2 = clientV2Only || useModernOnlyEntryMode || forceClient || !forceServer;
|
|
58
|
+
const shouldRunClient = !clientV2Only && !useModernOnlyEntryMode && (forceClient || !forceServer);
|
|
59
|
+
const shouldRunServer = !clientV2Only && (forceServer || !forceClient || useModernOnlyEntryMode);
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
appClientEntryMode,
|
|
63
|
+
useModernOnlyEntryMode,
|
|
64
|
+
shouldRunClientV2,
|
|
65
|
+
shouldRunClient,
|
|
66
|
+
shouldRunServer,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
50
70
|
async function forwardDevToAppDev({ argv = process.argv, runCommand = run } = {}) {
|
|
51
71
|
await runCommand('nocobase-v1', buildAppDevForwardArgs(argv));
|
|
52
72
|
}
|
|
@@ -107,9 +127,9 @@ module.exports = (cli) => {
|
|
|
107
127
|
nodeCheck();
|
|
108
128
|
await postCheck(opts);
|
|
109
129
|
|
|
110
|
-
const shouldRunClientV2
|
|
111
|
-
|
|
112
|
-
|
|
130
|
+
const { useModernOnlyEntryMode, shouldRunClientV2, shouldRunClient, shouldRunServer } = resolveDevRuntimeMode(
|
|
131
|
+
opts,
|
|
132
|
+
);
|
|
113
133
|
const shouldRunClientWithRsbuild = shouldRunClient && !!rsbuild;
|
|
114
134
|
|
|
115
135
|
if (shouldRunServer && server) {
|
|
@@ -120,12 +140,16 @@ module.exports = (cli) => {
|
|
|
120
140
|
});
|
|
121
141
|
}
|
|
122
142
|
|
|
123
|
-
if (shouldRunClientV2 && !clientV2Only) {
|
|
143
|
+
if (shouldRunClientV2 && !clientV2Only && !useModernOnlyEntryMode) {
|
|
124
144
|
clientV2Port = await getPortPromise({
|
|
125
145
|
port: 1 * clientPort + 2,
|
|
126
146
|
});
|
|
127
147
|
}
|
|
128
148
|
|
|
149
|
+
if (useModernOnlyEntryMode) {
|
|
150
|
+
clientV2Port = APP_PORT;
|
|
151
|
+
}
|
|
152
|
+
|
|
129
153
|
let subprocessClient;
|
|
130
154
|
let subprocessClientV2;
|
|
131
155
|
|
|
@@ -306,4 +330,5 @@ module.exports = (cli) => {
|
|
|
306
330
|
module.exports._test = {
|
|
307
331
|
buildAppDevForwardArgs,
|
|
308
332
|
forwardDevToAppDev,
|
|
333
|
+
resolveDevRuntimeMode,
|
|
309
334
|
};
|
package/src/util.js
CHANGED
|
@@ -432,6 +432,30 @@ const DEFAULT_MODERN_CLIENT_PREFIX = 'v';
|
|
|
432
432
|
|
|
433
433
|
exports.DEFAULT_MODERN_CLIENT_PREFIX = DEFAULT_MODERN_CLIENT_PREFIX;
|
|
434
434
|
|
|
435
|
+
const DEFAULT_APP_CLIENT_ENTRY_MODE = 'legacy-default';
|
|
436
|
+
const APP_CLIENT_ENTRY_MODES = new Set(['legacy-default', 'modern-default', 'modern-only']);
|
|
437
|
+
|
|
438
|
+
exports.DEFAULT_APP_CLIENT_ENTRY_MODE = DEFAULT_APP_CLIENT_ENTRY_MODE;
|
|
439
|
+
|
|
440
|
+
function isAppClientEntryMode(value) {
|
|
441
|
+
return APP_CLIENT_ENTRY_MODES.has(String(value || '').trim());
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
exports.isAppClientEntryMode = isAppClientEntryMode;
|
|
445
|
+
|
|
446
|
+
function normalizeAppClientEntryMode(value) {
|
|
447
|
+
const normalized = String(value || '').trim();
|
|
448
|
+
return isAppClientEntryMode(normalized) ? normalized : DEFAULT_APP_CLIENT_ENTRY_MODE;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
exports.normalizeAppClientEntryMode = normalizeAppClientEntryMode;
|
|
452
|
+
|
|
453
|
+
function resolveAppClientEntryMode() {
|
|
454
|
+
return normalizeAppClientEntryMode(process.env.APP_CLIENT_ENTRY_MODE);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
exports.resolveAppClientEntryMode = resolveAppClientEntryMode;
|
|
458
|
+
|
|
435
459
|
// Normalize APP_MODERN_CLIENT_PREFIX (accepts `v`, `/v`, `/v/`)
|
|
436
460
|
// down to a bare segment like `v`.
|
|
437
461
|
function normalizeModernClientPrefix(value) {
|
|
@@ -455,6 +479,13 @@ function isAppDevHtml() {
|
|
|
455
479
|
return process.argv[2] === 'app-dev' || process.env.NOCOBASE_APP_DEV === 'true';
|
|
456
480
|
}
|
|
457
481
|
|
|
482
|
+
function shouldRefreshLegacyIndexTemplate(data = '') {
|
|
483
|
+
return (
|
|
484
|
+
!data.includes("window['__nocobase_modern_client_prefix__']") ||
|
|
485
|
+
!data.includes("window['__nocobase_app_client_entry_mode__']")
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
|
|
458
489
|
function buildIndexHtml(force = false) {
|
|
459
490
|
const file = `${process.env.APP_PACKAGE_ROOT}/dist/client/index.html`;
|
|
460
491
|
if (!fs.existsSync(file)) {
|
|
@@ -466,11 +497,15 @@ function buildIndexHtml(force = false) {
|
|
|
466
497
|
}
|
|
467
498
|
if (!fs.existsSync(tpl)) {
|
|
468
499
|
fs.copyFileSync(file, tpl);
|
|
500
|
+
} else if (shouldRefreshLegacyIndexTemplate(fs.readFileSync(tpl, 'utf-8'))) {
|
|
501
|
+
fs.copyFileSync(file, tpl);
|
|
469
502
|
}
|
|
470
503
|
const data = fs.readFileSync(tpl, 'utf-8');
|
|
471
504
|
let replacedData = data
|
|
472
505
|
.replace(/\{\{env.CDN_BASE_URL\}\}/g, process.env.CDN_BASE_URL)
|
|
473
506
|
.replace(/\{\{env.APP_PUBLIC_PATH\}\}/g, process.env.APP_PUBLIC_PATH)
|
|
507
|
+
.replace(/\{\{env.APP_MODERN_CLIENT_PREFIX\}\}/g, normalizeModernClientPrefix(process.env.APP_MODERN_CLIENT_PREFIX))
|
|
508
|
+
.replace(/\{\{env.APP_CLIENT_ENTRY_MODE\}\}/g, resolveAppClientEntryMode())
|
|
474
509
|
.replace(/\{\{env.API_CLIENT_SHARE_TOKEN\}\}/g, process.env.API_CLIENT_SHARE_TOKEN || 'false')
|
|
475
510
|
.replace(/\{\{env.API_CLIENT_STORAGE_TYPE\}\}/g, process.env.API_CLIENT_STORAGE_TYPE)
|
|
476
511
|
.replace(/\{\{env.API_CLIENT_STORAGE_PREFIX\}\}/g, process.env.API_CLIENT_STORAGE_PREFIX)
|
|
@@ -611,6 +646,7 @@ exports.initEnv = function initEnv() {
|
|
|
611
646
|
CDN_BASE_URL: '',
|
|
612
647
|
APP_PUBLIC_PATH: '/',
|
|
613
648
|
APP_MODERN_CLIENT_PREFIX: DEFAULT_MODERN_CLIENT_PREFIX,
|
|
649
|
+
APP_CLIENT_ENTRY_MODE: DEFAULT_APP_CLIENT_ENTRY_MODE,
|
|
614
650
|
ESM_CDN_BASE_URL: 'https://esm.sh',
|
|
615
651
|
ESM_CDN_SUFFIX: '',
|
|
616
652
|
};
|
|
@@ -662,6 +698,14 @@ exports.initEnv = function initEnv() {
|
|
|
662
698
|
}
|
|
663
699
|
}
|
|
664
700
|
|
|
701
|
+
const rawAppClientEntryMode = String(process.env.APP_CLIENT_ENTRY_MODE || '').trim();
|
|
702
|
+
if (rawAppClientEntryMode && !isAppClientEntryMode(rawAppClientEntryMode)) {
|
|
703
|
+
console.warn(
|
|
704
|
+
`Unknown APP_CLIENT_ENTRY_MODE "${rawAppClientEntryMode}", falling back to ${DEFAULT_APP_CLIENT_ENTRY_MODE}.`,
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
process.env.APP_CLIENT_ENTRY_MODE = normalizeAppClientEntryMode(rawAppClientEntryMode);
|
|
708
|
+
|
|
665
709
|
if (!process.env.__env_modified__ && process.env.APP_PUBLIC_PATH) {
|
|
666
710
|
const publicPath = process.env.APP_PUBLIC_PATH.replace(/\/$/g, '');
|
|
667
711
|
const keys = ['API_BASE_PATH', 'WS_PATH', 'PLUGIN_STATICS_PATH'];
|