@nocobase/cli 2.0.22 → 2.1.0-alpha.10
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/nocobase.conf.tpl +77 -1
- package/package.json +4 -4
- package/src/commands/build.js +34 -2
- package/src/commands/create-nginx-conf.js +19 -3
- package/src/commands/dev.js +118 -70
- package/src/util.js +15 -0
package/nocobase.conf.tpl
CHANGED
|
@@ -12,6 +12,11 @@ log_format apm '"$time_local" client=$remote_addr '
|
|
|
12
12
|
'upstream_connect_time=$upstream_connect_time '
|
|
13
13
|
'upstream_header_time=$upstream_header_time';
|
|
14
14
|
|
|
15
|
+
map $http_x_forwarded_proto $upstream_x_forwarded_proto {
|
|
16
|
+
default $http_x_forwarded_proto;
|
|
17
|
+
"" $scheme;
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
server {
|
|
16
21
|
listen 80;
|
|
17
22
|
server_name _;
|
|
@@ -50,6 +55,77 @@ server {
|
|
|
50
55
|
}
|
|
51
56
|
}
|
|
52
57
|
|
|
58
|
+
location = {{v2PublicPathNoTrailingSlash}} {
|
|
59
|
+
return 302 {{v2PublicPath}}$is_args$args;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
location {{v2PublicPath}}assets/ {
|
|
63
|
+
alias {{cwd}}/node_modules/@nocobase/app/dist/client/v2/assets/;
|
|
64
|
+
expires 365d;
|
|
65
|
+
add_header Cache-Control "public";
|
|
66
|
+
access_log off;
|
|
67
|
+
autoindex off;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
location {{v2PublicPath}} {
|
|
71
|
+
proxy_pass http://127.0.0.1:{{apiPort}};
|
|
72
|
+
proxy_http_version 1.1;
|
|
73
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
74
|
+
proxy_set_header Connection 'upgrade';
|
|
75
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
76
|
+
proxy_set_header X-Forwarded-Proto $upstream_x_forwarded_proto;
|
|
77
|
+
proxy_set_header Host $host;
|
|
78
|
+
proxy_set_header Referer $http_referer;
|
|
79
|
+
proxy_set_header User-Agent $http_user_agent;
|
|
80
|
+
add_header Cache-Control 'no-cache, no-store';
|
|
81
|
+
proxy_cache_bypass $http_upgrade;
|
|
82
|
+
proxy_connect_timeout 600;
|
|
83
|
+
proxy_send_timeout 600;
|
|
84
|
+
proxy_read_timeout 600;
|
|
85
|
+
send_timeout 600;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
# RFC 8414 root-mounted discovery compatibility for path-based issuers/resources.
|
|
89
|
+
location ~ ^/\.well-known/oauth-authorization-server/(.+)$ {
|
|
90
|
+
rewrite ^/\.well-known/oauth-authorization-server/(.+)$ /$1/.well-known/oauth-authorization-server break;
|
|
91
|
+
proxy_pass http://127.0.0.1:{{apiPort}};
|
|
92
|
+
proxy_http_version 1.1;
|
|
93
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
94
|
+
proxy_set_header Connection 'upgrade';
|
|
95
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
96
|
+
proxy_set_header X-Forwarded-Proto $upstream_x_forwarded_proto;
|
|
97
|
+
proxy_set_header Host $host;
|
|
98
|
+
proxy_set_header Referer $http_referer;
|
|
99
|
+
proxy_set_header User-Agent $http_user_agent;
|
|
100
|
+
add_header Cache-Control 'no-cache, no-store';
|
|
101
|
+
proxy_cache_bypass $http_upgrade;
|
|
102
|
+
proxy_connect_timeout 600;
|
|
103
|
+
proxy_send_timeout 600;
|
|
104
|
+
proxy_read_timeout 600;
|
|
105
|
+
send_timeout 600;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
location ~ ^/\.well-known/openid-configuration/(.+)$ {
|
|
109
|
+
rewrite ^/\.well-known/openid-configuration/(.+)$ /$1/.well-known/openid-configuration break;
|
|
110
|
+
proxy_pass http://127.0.0.1:{{apiPort}};
|
|
111
|
+
proxy_http_version 1.1;
|
|
112
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
113
|
+
proxy_set_header Connection 'upgrade';
|
|
114
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
115
|
+
proxy_set_header X-Forwarded-Proto $upstream_x_forwarded_proto;
|
|
116
|
+
proxy_set_header Host $host;
|
|
117
|
+
proxy_set_header Referer $http_referer;
|
|
118
|
+
proxy_set_header User-Agent $http_user_agent;
|
|
119
|
+
add_header Cache-Control 'no-cache, no-store';
|
|
120
|
+
proxy_cache_bypass $http_upgrade;
|
|
121
|
+
proxy_connect_timeout 600;
|
|
122
|
+
proxy_send_timeout 600;
|
|
123
|
+
proxy_read_timeout 600;
|
|
124
|
+
send_timeout 600;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
|
|
53
129
|
location {{publicPath}} {
|
|
54
130
|
alias {{cwd}}/node_modules/@nocobase/app/dist/client/;
|
|
55
131
|
try_files $uri $uri/ /index.html;
|
|
@@ -73,7 +149,7 @@ server {
|
|
|
73
149
|
proxy_set_header Upgrade $http_upgrade;
|
|
74
150
|
proxy_set_header Connection 'upgrade';
|
|
75
151
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
76
|
-
proxy_set_header X-Forwarded-Proto $
|
|
152
|
+
proxy_set_header X-Forwarded-Proto $upstream_x_forwarded_proto;
|
|
77
153
|
proxy_set_header Host $host;
|
|
78
154
|
proxy_set_header Referer $http_referer;
|
|
79
155
|
proxy_set_header User-Agent $http_user_agent;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/cli",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.1.0-alpha.10",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"nocobase": "./bin/index.js"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@nocobase/app": "2.0.
|
|
11
|
+
"@nocobase/app": "2.1.0-alpha.10",
|
|
12
12
|
"@nocobase/license-kit": "^0.3.8",
|
|
13
13
|
"@types/fs-extra": "^11.0.1",
|
|
14
14
|
"@umijs/utils": "3.5.20",
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"tsx": "^4.19.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@nocobase/devtools": "2.0.
|
|
30
|
+
"@nocobase/devtools": "2.1.0-alpha.10"
|
|
31
31
|
},
|
|
32
32
|
"repository": {
|
|
33
33
|
"type": "git",
|
|
34
34
|
"url": "git+https://github.com/nocobase/nocobase.git",
|
|
35
35
|
"directory": "packages/core/cli"
|
|
36
36
|
},
|
|
37
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "ce790d46c0a5768ca9618c7d0d77ab8300de75c8"
|
|
38
38
|
}
|
package/src/commands/build.js
CHANGED
|
@@ -7,10 +7,34 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
const { existsSync } = require('fs');
|
|
10
11
|
const { resolve } = require('path');
|
|
11
12
|
const { Command } = require('commander');
|
|
12
13
|
const { run, nodeCheck, isPackageValid, buildIndexHtml } = require('../util');
|
|
13
14
|
|
|
15
|
+
async function buildClientV2() {
|
|
16
|
+
const configPath = resolve(process.env.APP_PACKAGE_ROOT, 'client-v2/rsbuild.config.ts');
|
|
17
|
+
if (!existsSync(configPath)) {
|
|
18
|
+
console.log(`client-v2 config not found: ${configPath}`);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
await run('rsbuild', ['build', '--config', configPath], {
|
|
22
|
+
env: {
|
|
23
|
+
...process.env,
|
|
24
|
+
APP_ENV: 'production',
|
|
25
|
+
NODE_ENV: 'production',
|
|
26
|
+
API_BASE_URL: process.env.API_BASE_URL || process.env.API_BASE_PATH,
|
|
27
|
+
API_CLIENT_STORAGE_PREFIX: process.env.API_CLIENT_STORAGE_PREFIX,
|
|
28
|
+
API_CLIENT_STORAGE_TYPE: process.env.API_CLIENT_STORAGE_TYPE,
|
|
29
|
+
API_CLIENT_SHARE_TOKEN: process.env.API_CLIENT_SHARE_TOKEN || 'false',
|
|
30
|
+
WEBSOCKET_URL: process.env.WEBSOCKET_URL || '',
|
|
31
|
+
WS_PATH: process.env.WS_PATH,
|
|
32
|
+
ESM_CDN_BASE_URL: process.env.ESM_CDN_BASE_URL || 'https://esm.sh',
|
|
33
|
+
ESM_CDN_SUFFIX: process.env.ESM_CDN_SUFFIX || '',
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
14
38
|
/**
|
|
15
39
|
*
|
|
16
40
|
* @param {Command} cli
|
|
@@ -26,16 +50,23 @@ module.exports = (cli) => {
|
|
|
26
50
|
.option('-w, --watch', 'watch compile the @nocobase/build package')
|
|
27
51
|
.option('-s, --sourcemap', 'generate sourcemap')
|
|
28
52
|
.option('--no-dts', 'not generate dts')
|
|
53
|
+
.option('--client-v2-only', 'build client-v2 shell only')
|
|
29
54
|
.action(async (pkgs, options) => {
|
|
30
55
|
nodeCheck();
|
|
56
|
+
process.env['VITE_CJS_IGNORE_WARNING'] = 'true';
|
|
57
|
+
process.env.APP_ENV = 'production';
|
|
58
|
+
|
|
59
|
+
if (options.clientV2Only) {
|
|
60
|
+
await buildClientV2();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
31
64
|
if (options.compile || options.watch || isPackageValid('@nocobase/build/src/index.ts')) {
|
|
32
65
|
await run('yarn', ['build', options.watch ? '--watch' : ''], {
|
|
33
66
|
cwd: resolve(process.cwd(), 'packages/core/build'),
|
|
34
67
|
});
|
|
35
68
|
if (options.watch) return;
|
|
36
69
|
}
|
|
37
|
-
process.env['VITE_CJS_IGNORE_WARNING'] = 'true';
|
|
38
|
-
process.env.APP_ENV = 'production';
|
|
39
70
|
|
|
40
71
|
await run('nocobase-build', [
|
|
41
72
|
...pkgs,
|
|
@@ -45,5 +76,6 @@ module.exports = (cli) => {
|
|
|
45
76
|
options.retry ? '--retry' : '',
|
|
46
77
|
]);
|
|
47
78
|
buildIndexHtml(true);
|
|
79
|
+
await buildClientV2();
|
|
48
80
|
});
|
|
49
81
|
};
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
const { resolve, posix } = require('path');
|
|
11
11
|
const { Command } = require('commander');
|
|
12
12
|
const { readFileSync, writeFileSync } = require('fs');
|
|
13
|
+
const { resolvePublicPath, resolveV2PublicPath } = require('../util');
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
*
|
|
@@ -17,18 +18,33 @@ const { readFileSync, writeFileSync } = require('fs');
|
|
|
17
18
|
*/
|
|
18
19
|
module.exports = (cli) => {
|
|
19
20
|
cli.command('create-nginx-conf').action(async (name, options) => {
|
|
21
|
+
const rawAppPublicPath = process.env.APP_PUBLIC_PATH || '/';
|
|
22
|
+
const appPublicPath = resolvePublicPath(rawAppPublicPath);
|
|
23
|
+
const v2PublicPath = resolveV2PublicPath(rawAppPublicPath);
|
|
24
|
+
const appPublicPathWithoutTrailingSlash = appPublicPath.replace(/\/$/, '');
|
|
25
|
+
const v2PublicPathWithoutTrailingSlash = v2PublicPath.replace(/\/$/, '');
|
|
20
26
|
const file = resolve(__dirname, '../../nocobase.conf.tpl');
|
|
21
27
|
const data = readFileSync(file, 'utf-8');
|
|
22
28
|
let otherLocation = '';
|
|
23
|
-
if (
|
|
24
|
-
otherLocation = `location / {
|
|
29
|
+
if (appPublicPath !== '/') {
|
|
30
|
+
otherLocation = `location = /v2 {
|
|
31
|
+
return 302 ${v2PublicPath}$is_args$args;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
location /v2/ {
|
|
35
|
+
return 302 ${appPublicPathWithoutTrailingSlash}$uri$is_args$args;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
location / {
|
|
25
39
|
alias ${posix.resolve(process.cwd())}/node_modules/@nocobase/app/dist/client/;
|
|
26
40
|
try_files $uri $uri/ /index.html;
|
|
27
41
|
}`;
|
|
28
42
|
}
|
|
29
43
|
const replaced = data
|
|
30
44
|
.replace(/\{\{cwd\}\}/g, posix.resolve(process.cwd()))
|
|
31
|
-
.replace(/\{\{publicPath\}\}/g,
|
|
45
|
+
.replace(/\{\{publicPath\}\}/g, appPublicPath)
|
|
46
|
+
.replace(/\{\{v2PublicPath\}\}/g, v2PublicPath)
|
|
47
|
+
.replace(/\{\{v2PublicPathNoTrailingSlash\}\}/g, v2PublicPathWithoutTrailingSlash)
|
|
32
48
|
.replace(/\{\{apiPort\}\}/g, process.env.APP_PORT)
|
|
33
49
|
.replace(/\{\{otherLocation\}\}/g, otherLocation);
|
|
34
50
|
const targetFile = resolve(process.cwd(), 'storage', 'nocobase.conf');
|
package/src/commands/dev.js
CHANGED
|
@@ -42,74 +42,12 @@ module.exports = (cli) => {
|
|
|
42
42
|
.option('-c, --client')
|
|
43
43
|
.option('-s, --server')
|
|
44
44
|
.option('--db-sync')
|
|
45
|
+
.option('--client-v2-only')
|
|
45
46
|
.option('-i, --inspect [port]')
|
|
46
47
|
.allowUnknownOption()
|
|
47
48
|
.action(async (opts) => {
|
|
48
49
|
checkDBDialect();
|
|
49
50
|
await buildBundleStatusHtml();
|
|
50
|
-
let subprocess;
|
|
51
|
-
const runDevClient = () => {
|
|
52
|
-
console.log('starting client', 1 * clientPort);
|
|
53
|
-
subprocess = run('umi', ['dev'], {
|
|
54
|
-
env: {
|
|
55
|
-
...process.env,
|
|
56
|
-
stdio: 'inherit',
|
|
57
|
-
shell: true,
|
|
58
|
-
PORT: clientPort,
|
|
59
|
-
APP_ROOT: `${APP_PACKAGE_ROOT}/client`,
|
|
60
|
-
WEBSOCKET_URL:
|
|
61
|
-
process.env.WEBSOCKET_URL ||
|
|
62
|
-
(serverPort ? `ws://localhost:${serverPort}${process.env.WS_PATH}` : undefined),
|
|
63
|
-
PROXY_TARGET_URL:
|
|
64
|
-
process.env.PROXY_TARGET_URL || (serverPort ? `http://127.0.0.1:${serverPort}` : undefined),
|
|
65
|
-
},
|
|
66
|
-
});
|
|
67
|
-
};
|
|
68
|
-
const watcher = chokidar.watch('./storage/plugins/**/*', {
|
|
69
|
-
cwd: process.cwd(),
|
|
70
|
-
ignored: /(^|[\/\\])\../, // 忽略隐藏文件
|
|
71
|
-
persistent: true,
|
|
72
|
-
depth: 1, // 只监听第一层目录
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
await fs.promises.mkdir(path.dirname(process.env.WATCH_FILE), { recursive: true });
|
|
76
|
-
let isReady = false;
|
|
77
|
-
|
|
78
|
-
const restartClient = _.debounce(async () => {
|
|
79
|
-
if (!isReady) return;
|
|
80
|
-
generatePlugins();
|
|
81
|
-
if (subprocess) {
|
|
82
|
-
console.log('client restarting...');
|
|
83
|
-
subprocess.cancel();
|
|
84
|
-
let i = 0;
|
|
85
|
-
while (true) {
|
|
86
|
-
++i;
|
|
87
|
-
const result = await isPortReachable(clientPort);
|
|
88
|
-
if (!result) {
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
await sleep(500);
|
|
92
|
-
if (i > 10) {
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
runDevClient();
|
|
97
|
-
await fs.promises.writeFile(process.env.WATCH_FILE, `export const watchId = '${uid()}';`, 'utf-8');
|
|
98
|
-
}
|
|
99
|
-
}, 500);
|
|
100
|
-
|
|
101
|
-
watcher
|
|
102
|
-
.on('ready', () => {
|
|
103
|
-
isReady = true;
|
|
104
|
-
})
|
|
105
|
-
.on('addDir', async (pathname) => {
|
|
106
|
-
if (!isReady) return;
|
|
107
|
-
restartClient();
|
|
108
|
-
})
|
|
109
|
-
.on('unlinkDir', async (pathname) => {
|
|
110
|
-
if (!isReady) return;
|
|
111
|
-
restartClient();
|
|
112
|
-
});
|
|
113
51
|
|
|
114
52
|
promptForTs();
|
|
115
53
|
const { SERVER_TSCONFIG_PATH } = process.env;
|
|
@@ -127,30 +65,136 @@ module.exports = (cli) => {
|
|
|
127
65
|
return;
|
|
128
66
|
}
|
|
129
67
|
|
|
130
|
-
const { port, client, server, inspect } = opts;
|
|
68
|
+
const { port, client, server, inspect, clientV2Only } = opts;
|
|
131
69
|
|
|
132
70
|
if (port) {
|
|
133
71
|
process.env.APP_PORT = opts.port;
|
|
134
72
|
}
|
|
135
73
|
|
|
136
|
-
const
|
|
74
|
+
const APP_PORT = Number(process.env.APP_PORT);
|
|
137
75
|
|
|
138
76
|
let clientPort = APP_PORT;
|
|
139
77
|
let serverPort;
|
|
78
|
+
let clientV2Port = APP_PORT;
|
|
140
79
|
|
|
141
80
|
nodeCheck();
|
|
142
|
-
|
|
143
81
|
await postCheck(opts);
|
|
144
82
|
|
|
145
|
-
|
|
83
|
+
const shouldRunClientV2 = clientV2Only || client || !server;
|
|
84
|
+
const shouldRunClient = !clientV2Only && (client || !server);
|
|
85
|
+
const shouldRunServer = !clientV2Only && (server || !client);
|
|
86
|
+
|
|
87
|
+
if (shouldRunServer && server) {
|
|
146
88
|
serverPort = APP_PORT;
|
|
147
|
-
} else if (
|
|
89
|
+
} else if (shouldRunServer) {
|
|
148
90
|
serverPort = await getPortPromise({
|
|
149
91
|
port: 1 * clientPort + 1,
|
|
150
92
|
});
|
|
151
93
|
}
|
|
152
94
|
|
|
153
|
-
if (
|
|
95
|
+
if (shouldRunClientV2 && !clientV2Only) {
|
|
96
|
+
clientV2Port = await getPortPromise({
|
|
97
|
+
port: 1 * clientPort + 2,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const runDevClientV2 = () => {
|
|
102
|
+
console.log('starting client-v2', 1 * clientV2Port);
|
|
103
|
+
run('rsbuild', ['dev', '--config', `${APP_PACKAGE_ROOT}/client-v2/rsbuild.config.ts`], {
|
|
104
|
+
env: {
|
|
105
|
+
...process.env,
|
|
106
|
+
APP_V2_PORT: `${clientV2Port}`,
|
|
107
|
+
NODE_ENV: 'development',
|
|
108
|
+
RSPACK_HMR_CLIENT_PORT: `${clientV2Only ? clientV2Port : clientPort}`,
|
|
109
|
+
API_BASE_URL: process.env.API_BASE_URL || process.env.API_BASE_PATH,
|
|
110
|
+
API_CLIENT_STORAGE_PREFIX: process.env.API_CLIENT_STORAGE_PREFIX,
|
|
111
|
+
API_CLIENT_STORAGE_TYPE: process.env.API_CLIENT_STORAGE_TYPE,
|
|
112
|
+
API_CLIENT_SHARE_TOKEN: process.env.API_CLIENT_SHARE_TOKEN || 'false',
|
|
113
|
+
WEBSOCKET_URL:
|
|
114
|
+
process.env.WEBSOCKET_URL || (serverPort ? `ws://localhost:${serverPort}${process.env.WS_PATH}` : ''),
|
|
115
|
+
WS_PATH: process.env.WS_PATH,
|
|
116
|
+
ESM_CDN_BASE_URL: process.env.ESM_CDN_BASE_URL || 'https://esm.sh',
|
|
117
|
+
ESM_CDN_SUFFIX: process.env.ESM_CDN_SUFFIX || '',
|
|
118
|
+
PROXY_TARGET_URL:
|
|
119
|
+
process.env.PROXY_TARGET_URL || (serverPort ? `http://127.0.0.1:${serverPort}` : undefined),
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
if (clientV2Only) {
|
|
125
|
+
runDevClientV2();
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
let subprocess;
|
|
130
|
+
const runDevClient = () => {
|
|
131
|
+
console.log('starting client', 1 * clientPort);
|
|
132
|
+
subprocess = run('umi', ['dev'], {
|
|
133
|
+
env: {
|
|
134
|
+
...process.env,
|
|
135
|
+
stdio: 'inherit',
|
|
136
|
+
shell: true,
|
|
137
|
+
PORT: clientPort,
|
|
138
|
+
APP_ROOT: `${APP_PACKAGE_ROOT}/client`,
|
|
139
|
+
APP_V2_PORT: `${clientV2Port}`,
|
|
140
|
+
WEBSOCKET_URL:
|
|
141
|
+
process.env.WEBSOCKET_URL ||
|
|
142
|
+
(serverPort ? `ws://localhost:${serverPort}${process.env.WS_PATH}` : undefined),
|
|
143
|
+
PROXY_TARGET_URL:
|
|
144
|
+
process.env.PROXY_TARGET_URL || (serverPort ? `http://127.0.0.1:${serverPort}` : undefined),
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
if (shouldRunClient) {
|
|
150
|
+
const watcher = chokidar.watch('./storage/plugins/**/*', {
|
|
151
|
+
cwd: process.cwd(),
|
|
152
|
+
ignored: /(^|[\/\\])\../, // 忽略隐藏文件
|
|
153
|
+
persistent: true,
|
|
154
|
+
depth: 1, // 只监听第一层目录
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
await fs.promises.mkdir(path.dirname(process.env.WATCH_FILE), { recursive: true });
|
|
158
|
+
let isReady = false;
|
|
159
|
+
|
|
160
|
+
const restartClient = _.debounce(async () => {
|
|
161
|
+
if (!isReady) return;
|
|
162
|
+
generatePlugins();
|
|
163
|
+
if (subprocess) {
|
|
164
|
+
console.log('client restarting...');
|
|
165
|
+
subprocess.cancel();
|
|
166
|
+
let i = 0;
|
|
167
|
+
while (true) {
|
|
168
|
+
++i;
|
|
169
|
+
const result = await isPortReachable(clientPort);
|
|
170
|
+
if (!result) {
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
await sleep(500);
|
|
174
|
+
if (i > 10) {
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
runDevClient();
|
|
179
|
+
await fs.promises.writeFile(process.env.WATCH_FILE, `export const watchId = '${uid()}';`, 'utf-8');
|
|
180
|
+
}
|
|
181
|
+
}, 500);
|
|
182
|
+
|
|
183
|
+
watcher
|
|
184
|
+
.on('ready', () => {
|
|
185
|
+
isReady = true;
|
|
186
|
+
})
|
|
187
|
+
.on('addDir', async () => {
|
|
188
|
+
if (!isReady) return;
|
|
189
|
+
restartClient();
|
|
190
|
+
})
|
|
191
|
+
.on('unlinkDir', async () => {
|
|
192
|
+
if (!isReady) return;
|
|
193
|
+
restartClient();
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (shouldRunServer) {
|
|
154
198
|
console.log('starting server', serverPort);
|
|
155
199
|
|
|
156
200
|
const filteredArgs = process.argv.filter(
|
|
@@ -193,8 +237,12 @@ module.exports = (cli) => {
|
|
|
193
237
|
runDevServer();
|
|
194
238
|
}
|
|
195
239
|
|
|
196
|
-
if (
|
|
240
|
+
if (shouldRunClient) {
|
|
197
241
|
runDevClient();
|
|
198
242
|
}
|
|
243
|
+
|
|
244
|
+
if (shouldRunClientV2) {
|
|
245
|
+
runDevClientV2();
|
|
246
|
+
}
|
|
199
247
|
});
|
|
200
248
|
};
|
package/src/util.js
CHANGED
|
@@ -282,6 +282,21 @@ function parseEnv(name) {
|
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
+
function resolvePublicPath(appPublicPath = '/') {
|
|
286
|
+
const normalized = String(appPublicPath || '/').trim() || '/';
|
|
287
|
+
const withLeadingSlash = normalized.startsWith('/') ? normalized : `/${normalized}`;
|
|
288
|
+
return withLeadingSlash.endsWith('/') ? withLeadingSlash : `${withLeadingSlash}/`;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
exports.resolvePublicPath = resolvePublicPath;
|
|
292
|
+
|
|
293
|
+
function resolveV2PublicPath(appPublicPath = '/') {
|
|
294
|
+
const publicPath = resolvePublicPath(appPublicPath);
|
|
295
|
+
return `${publicPath.replace(/\/$/, '')}/v2/`;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
exports.resolveV2PublicPath = resolveV2PublicPath;
|
|
299
|
+
|
|
285
300
|
function buildIndexHtml(force = false) {
|
|
286
301
|
const file = `${process.env.APP_PACKAGE_ROOT}/dist/client/index.html`;
|
|
287
302
|
if (!fs.existsSync(file)) {
|