@nocobase/cli-v1 2.2.0-alpha.10 → 2.2.0-alpha.11
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.2.0-alpha.
|
|
3
|
+
"version": "2.2.0-alpha.11",
|
|
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.2.0-alpha.
|
|
12
|
+
"@nocobase/cli": "2.2.0-alpha.11",
|
|
13
13
|
"@nocobase/license-kit": "^0.3.8",
|
|
14
|
-
"@nocobase/utils": "2.2.0-alpha.
|
|
14
|
+
"@nocobase/utils": "2.2.0-alpha.11",
|
|
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": "c9ff1f51e5c33bc6437b64eb779212be71b78f58"
|
|
37
37
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/* eslint-env jest */
|
|
11
|
+
|
|
12
|
+
const fs = require('fs-extra');
|
|
13
|
+
const os = require('os');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const { renderExtractedClientIndexHtml } = require('../commands/client');
|
|
16
|
+
|
|
17
|
+
describe('cli-v1 client:extract', () => {
|
|
18
|
+
const originalEnv = { ...process.env };
|
|
19
|
+
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
process.env = { ...originalEnv };
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('renders extracted root index with the current client entry mode', () => {
|
|
25
|
+
const target = fs.mkdtempSync(path.join(os.tmpdir(), 'nocobase-client-extract-'));
|
|
26
|
+
fs.writeFileSync(
|
|
27
|
+
path.join(target, 'index.html.tpl'),
|
|
28
|
+
[
|
|
29
|
+
'<html><head>',
|
|
30
|
+
"<script>window['__webpack_public_path__'] = '{{env.CDN_BASE_URL}}';",
|
|
31
|
+
"window['__nocobase_public_path__'] = '{{env.APP_PUBLIC_PATH}}';",
|
|
32
|
+
"window['__nocobase_modern_client_prefix__'] = '{{env.APP_MODERN_CLIENT_PREFIX}}';",
|
|
33
|
+
"window['__nocobase_app_client_entry_mode__'] = '{{env.APP_CLIENT_ENTRY_MODE}}';</script>",
|
|
34
|
+
'<script src="{{env.APP_PUBLIC_PATH}}browser-checker.js?v=1"></script>',
|
|
35
|
+
'<script type="module" src="assets/runtime.js"></script>',
|
|
36
|
+
'</head><body></body></html>',
|
|
37
|
+
].join(''),
|
|
38
|
+
'utf-8',
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
process.env.APP_PUBLIC_PATH = '/';
|
|
42
|
+
process.env.APP_MODERN_CLIENT_PREFIX = 'v';
|
|
43
|
+
process.env.APP_CLIENT_ENTRY_MODE = 'modern-only';
|
|
44
|
+
delete process.env.CDN_BASE_URL;
|
|
45
|
+
|
|
46
|
+
expect(renderExtractedClientIndexHtml(target, '2.2.0-beta.15')).toBe(true);
|
|
47
|
+
|
|
48
|
+
const html = fs.readFileSync(path.join(target, 'index.html'), 'utf-8');
|
|
49
|
+
expect(html).toContain("window['__nocobase_app_client_entry_mode__'] = 'modern-only';");
|
|
50
|
+
expect(html).toContain("window['__webpack_public_path__'] = '/dist/2.2.0-beta.15/';");
|
|
51
|
+
expect(html).toContain('src="/dist/2.2.0-beta.15/browser-checker.js?v=1"');
|
|
52
|
+
expect(html).toContain('src="/dist/2.2.0-beta.15/assets/runtime.js"');
|
|
53
|
+
fs.removeSync(target);
|
|
54
|
+
});
|
|
55
|
+
});
|
package/src/commands/client.js
CHANGED
|
@@ -11,7 +11,100 @@ const chalk = require('chalk');
|
|
|
11
11
|
const fs = require('fs-extra');
|
|
12
12
|
const { resolve } = require('path');
|
|
13
13
|
const { discoverPluginPackages } = require('@nocobase/utils/plugin-package');
|
|
14
|
-
const {
|
|
14
|
+
const {
|
|
15
|
+
normalizeModernClientPrefix,
|
|
16
|
+
resolveAppClientEntryMode,
|
|
17
|
+
resolvePublicPath,
|
|
18
|
+
storagePathJoin,
|
|
19
|
+
} = require('../util');
|
|
20
|
+
|
|
21
|
+
function replaceRuntimeEnvPlaceholders(data, values) {
|
|
22
|
+
return data
|
|
23
|
+
.replace(/\{\{env.CDN_BASE_URL\}\}/g, values.CDN_BASE_URL)
|
|
24
|
+
.replace(/\{\{env.APP_PUBLIC_PATH\}\}/g, values.APP_PUBLIC_PATH)
|
|
25
|
+
.replace(/\{\{env.APP_MODERN_CLIENT_PREFIX\}\}/g, values.APP_MODERN_CLIENT_PREFIX)
|
|
26
|
+
.replace(/\{\{env.APP_CLIENT_ENTRY_MODE\}\}/g, values.APP_CLIENT_ENTRY_MODE)
|
|
27
|
+
.replace(/\{\{env.API_CLIENT_SHARE_TOKEN\}\}/g, values.API_CLIENT_SHARE_TOKEN)
|
|
28
|
+
.replace(/\{\{env.API_CLIENT_STORAGE_TYPE\}\}/g, values.API_CLIENT_STORAGE_TYPE)
|
|
29
|
+
.replace(/\{\{env.API_CLIENT_STORAGE_PREFIX\}\}/g, values.API_CLIENT_STORAGE_PREFIX)
|
|
30
|
+
.replace(/\{\{env.API_BASE_URL\}\}/g, values.API_BASE_URL)
|
|
31
|
+
.replace(/\{\{env.WS_URL\}\}/g, values.WS_URL)
|
|
32
|
+
.replace(/\{\{env.WS_PATH\}\}/g, values.WS_PATH)
|
|
33
|
+
.replace(/\{\{env.NOCOBASE_APP_DEV\}\}/g, values.NOCOBASE_APP_DEV)
|
|
34
|
+
.replace(/\{\{env.ESM_CDN_BASE_URL\}\}/g, values.ESM_CDN_BASE_URL)
|
|
35
|
+
.replace(/\{\{env.ESM_CDN_SUFFIX\}\}/g, values.ESM_CDN_SUFFIX);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function replaceRuntimeAssignment(data, key, value) {
|
|
39
|
+
const literal =
|
|
40
|
+
typeof value === 'boolean' ? String(value) : `'${String(value).replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`;
|
|
41
|
+
const assignment = `window['${key}'] = ${literal};`;
|
|
42
|
+
const pattern = new RegExp(`window\\['${key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}'\\]\\s*=\\s*[^;]*;`);
|
|
43
|
+
|
|
44
|
+
return pattern.test(data) ? data.replace(pattern, assignment) : data;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function renderExtractedClientIndexHtml(target, version) {
|
|
48
|
+
const indexPath = resolve(target, 'index.html');
|
|
49
|
+
const tplPath = resolve(target, 'index.html.tpl');
|
|
50
|
+
if (!fs.existsSync(indexPath) && !fs.existsSync(tplPath)) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const appPublicPath = resolvePublicPath(process.env.APP_PUBLIC_PATH || '/');
|
|
55
|
+
const cdnBaseUrl =
|
|
56
|
+
process.env.CDN_BASE_URL || `${appPublicPath.replace(/\/$/, '')}/dist/${version}/`.replace(/^\/\//, '/');
|
|
57
|
+
const values = {
|
|
58
|
+
CDN_BASE_URL: cdnBaseUrl,
|
|
59
|
+
APP_PUBLIC_PATH: appPublicPath,
|
|
60
|
+
APP_MODERN_CLIENT_PREFIX: normalizeModernClientPrefix(process.env.APP_MODERN_CLIENT_PREFIX),
|
|
61
|
+
APP_CLIENT_ENTRY_MODE: resolveAppClientEntryMode(),
|
|
62
|
+
API_CLIENT_SHARE_TOKEN: process.env.API_CLIENT_SHARE_TOKEN || 'false',
|
|
63
|
+
API_CLIENT_STORAGE_TYPE: process.env.API_CLIENT_STORAGE_TYPE || 'localStorage',
|
|
64
|
+
API_CLIENT_STORAGE_PREFIX: process.env.API_CLIENT_STORAGE_PREFIX || 'NOCOBASE_',
|
|
65
|
+
API_BASE_URL: process.env.API_BASE_URL || process.env.API_BASE_PATH || '/api/',
|
|
66
|
+
WS_URL: process.env.WEBSOCKET_URL || '',
|
|
67
|
+
WS_PATH: process.env.WS_PATH || '/ws',
|
|
68
|
+
NOCOBASE_APP_DEV: 'false',
|
|
69
|
+
ESM_CDN_BASE_URL: process.env.ESM_CDN_BASE_URL || 'https://esm.sh',
|
|
70
|
+
ESM_CDN_SUFFIX: process.env.ESM_CDN_SUFFIX || '',
|
|
71
|
+
};
|
|
72
|
+
const sourcePath = fs.existsSync(tplPath) ? tplPath : indexPath;
|
|
73
|
+
let data = replaceRuntimeEnvPlaceholders(fs.readFileSync(sourcePath, 'utf-8'), values)
|
|
74
|
+
.replace(/((?:src|href)=")(?:\.\/)?assets\//g, `$1${values.APP_PUBLIC_PATH}assets/`)
|
|
75
|
+
.replace(/((?:src|href)=")\/assets\//g, `$1${values.APP_PUBLIC_PATH}assets/`)
|
|
76
|
+
.replace('src="/umi.', `src="${values.APP_PUBLIC_PATH}umi.`)
|
|
77
|
+
.replace(/((?:src|href)="[^"]*?)\/{2,}(assets\/)/g, '$1/$2');
|
|
78
|
+
|
|
79
|
+
if (values.CDN_BASE_URL) {
|
|
80
|
+
const appBaseUrl = values.CDN_BASE_URL.replace(/\/+$/, '');
|
|
81
|
+
const publicPath = values.APP_PUBLIC_PATH.replace(/\/+$/, '');
|
|
82
|
+
data = data
|
|
83
|
+
.replace(new RegExp(`src="${publicPath}/`, 'g'), `src="${appBaseUrl}/`)
|
|
84
|
+
.replace(new RegExp(`href="${publicPath}/`, 'g'), `href="${appBaseUrl}/`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
data = replaceRuntimeAssignment(data, '__webpack_public_path__', values.CDN_BASE_URL);
|
|
88
|
+
data = replaceRuntimeAssignment(data, '__nocobase_public_path__', values.APP_PUBLIC_PATH);
|
|
89
|
+
data = replaceRuntimeAssignment(data, '__nocobase_modern_client_prefix__', values.APP_MODERN_CLIENT_PREFIX);
|
|
90
|
+
data = replaceRuntimeAssignment(data, '__nocobase_app_client_entry_mode__', values.APP_CLIENT_ENTRY_MODE);
|
|
91
|
+
data = replaceRuntimeAssignment(data, '__nocobase_api_base_url__', values.API_BASE_URL);
|
|
92
|
+
data = replaceRuntimeAssignment(data, '__nocobase_api_client_storage_prefix__', values.API_CLIENT_STORAGE_PREFIX);
|
|
93
|
+
data = replaceRuntimeAssignment(data, '__nocobase_api_client_storage_type__', values.API_CLIENT_STORAGE_TYPE);
|
|
94
|
+
data = replaceRuntimeAssignment(
|
|
95
|
+
data,
|
|
96
|
+
'__nocobase_api_client_share_token__',
|
|
97
|
+
/^true$/i.test(values.API_CLIENT_SHARE_TOKEN),
|
|
98
|
+
);
|
|
99
|
+
data = replaceRuntimeAssignment(data, '__nocobase_ws_url__', values.WS_URL);
|
|
100
|
+
data = replaceRuntimeAssignment(data, '__nocobase_ws_path__', values.WS_PATH);
|
|
101
|
+
data = replaceRuntimeAssignment(data, '__nocobase_app_dev__', false);
|
|
102
|
+
data = replaceRuntimeAssignment(data, '__esm_cdn_base_url__', values.ESM_CDN_BASE_URL);
|
|
103
|
+
data = replaceRuntimeAssignment(data, '__esm_cdn_suffix__', values.ESM_CDN_SUFFIX);
|
|
104
|
+
|
|
105
|
+
fs.writeFileSync(indexPath, data, 'utf-8');
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
15
108
|
|
|
16
109
|
/**
|
|
17
110
|
* 复制主应用客户端文件
|
|
@@ -127,6 +220,7 @@ module.exports = (cli) => {
|
|
|
127
220
|
nodeModulesPath: resolve(process.cwd(), 'node_modules'),
|
|
128
221
|
});
|
|
129
222
|
const copiedMainClient = await copyMainClient(mainClientSource, target);
|
|
223
|
+
const renderedMainIndex = copiedMainClient ? renderExtractedClientIndexHtml(target, version) : false;
|
|
130
224
|
const copiedPluginBundles = await copyPluginClients(plugins, target);
|
|
131
225
|
const activeVersionFile = await writeActiveVersion(version);
|
|
132
226
|
|
|
@@ -145,7 +239,7 @@ module.exports = (cli) => {
|
|
|
145
239
|
chalk.green(
|
|
146
240
|
`Extracted client assets ${version} to ${target} (main client: ${
|
|
147
241
|
copiedMainClient ? 'yes' : 'no'
|
|
148
|
-
}, plugin bundles: ${copiedPluginBundles}).`,
|
|
242
|
+
}, rendered index: ${renderedMainIndex ? 'yes' : 'no'}, plugin bundles: ${copiedPluginBundles}).`,
|
|
149
243
|
),
|
|
150
244
|
);
|
|
151
245
|
});
|
|
@@ -198,3 +292,5 @@ module.exports = (cli) => {
|
|
|
198
292
|
}
|
|
199
293
|
});
|
|
200
294
|
};
|
|
295
|
+
|
|
296
|
+
module.exports.renderExtractedClientIndexHtml = renderExtractedClientIndexHtml;
|