@nocobase/cli 2.1.0-alpha.1 → 2.1.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/LICENSE +201 -661
- package/README.md +79 -10
- package/nocobase.conf.tpl +85 -1
- package/package.json +6 -6
- package/src/commands/build.js +34 -2
- package/src/commands/client.js +168 -0
- package/src/commands/create-nginx-conf.js +19 -3
- package/src/commands/dev.js +171 -71
- package/src/commands/index.js +1 -0
- package/src/commands/pkg.js +6 -1
- package/src/commands/pm2.js +1 -1
- package/src/commands/update-deps.js +1 -0
- package/src/license.js +1 -1
- package/src/util.js +115 -4
- package/templates/bundle-status.html +338 -0
- package/templates/create-app-package.json +1 -1
- package/templates/plugin/client-v2.d.ts +2 -0
- package/templates/plugin/client-v2.js +1 -0
- package/templates/plugin/package.json.tpl +1 -0
- package/templates/plugin/src/client-v2/client.d.ts +103 -0
- package/templates/plugin/src/client-v2/index.tsx.tpl +1 -0
- package/templates/plugin/src/client-v2/plugin.tsx.tpl +7 -0
package/src/commands/dev.js
CHANGED
|
@@ -8,7 +8,17 @@
|
|
|
8
8
|
*/
|
|
9
9
|
const _ = require('lodash');
|
|
10
10
|
const { Command } = require('commander');
|
|
11
|
-
const {
|
|
11
|
+
const {
|
|
12
|
+
generatePlugins,
|
|
13
|
+
run,
|
|
14
|
+
runWithPrefix,
|
|
15
|
+
postCheck,
|
|
16
|
+
nodeCheck,
|
|
17
|
+
promptForTs,
|
|
18
|
+
isPortReachable,
|
|
19
|
+
buildWSURL,
|
|
20
|
+
checkDBDialect,
|
|
21
|
+
} = require('../util');
|
|
12
22
|
const { getPortPromise } = require('portfinder');
|
|
13
23
|
const chokidar = require('chokidar');
|
|
14
24
|
const { uid } = require('@formily/shared');
|
|
@@ -21,6 +31,15 @@ function sleep(ms = 1000) {
|
|
|
21
31
|
});
|
|
22
32
|
}
|
|
23
33
|
|
|
34
|
+
async function buildBundleStatusHtml() {
|
|
35
|
+
const data = await fs.promises.readFile(path.resolve(__dirname, '../../templates/bundle-status.html'), 'utf-8');
|
|
36
|
+
await fs.promises.writeFile(
|
|
37
|
+
path.resolve(process.cwd(), 'node_modules/@umijs/preset-umi/assets/bundle-status.html'),
|
|
38
|
+
data,
|
|
39
|
+
'utf-8',
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
24
43
|
/**
|
|
25
44
|
*
|
|
26
45
|
* @param {Command} cli
|
|
@@ -33,73 +52,13 @@ module.exports = (cli) => {
|
|
|
33
52
|
.option('-c, --client')
|
|
34
53
|
.option('-s, --server')
|
|
35
54
|
.option('--db-sync')
|
|
55
|
+
.option('--rsbuild')
|
|
56
|
+
.option('--client-v2-only')
|
|
36
57
|
.option('-i, --inspect [port]')
|
|
37
58
|
.allowUnknownOption()
|
|
38
59
|
.action(async (opts) => {
|
|
39
60
|
checkDBDialect();
|
|
40
|
-
|
|
41
|
-
const runDevClient = () => {
|
|
42
|
-
console.log('starting client', 1 * clientPort);
|
|
43
|
-
subprocess = run('umi', ['dev'], {
|
|
44
|
-
env: {
|
|
45
|
-
...process.env,
|
|
46
|
-
stdio: 'inherit',
|
|
47
|
-
shell: true,
|
|
48
|
-
PORT: clientPort,
|
|
49
|
-
APP_ROOT: `${APP_PACKAGE_ROOT}/client`,
|
|
50
|
-
WEBSOCKET_URL:
|
|
51
|
-
process.env.WEBSOCKET_URL ||
|
|
52
|
-
(serverPort ? `ws://localhost:${serverPort}${process.env.WS_PATH}` : undefined),
|
|
53
|
-
PROXY_TARGET_URL:
|
|
54
|
-
process.env.PROXY_TARGET_URL || (serverPort ? `http://127.0.0.1:${serverPort}` : undefined),
|
|
55
|
-
},
|
|
56
|
-
});
|
|
57
|
-
};
|
|
58
|
-
const watcher = chokidar.watch('./storage/plugins/**/*', {
|
|
59
|
-
cwd: process.cwd(),
|
|
60
|
-
ignored: /(^|[\/\\])\../, // 忽略隐藏文件
|
|
61
|
-
persistent: true,
|
|
62
|
-
depth: 1, // 只监听第一层目录
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
await fs.promises.mkdir(path.dirname(process.env.WATCH_FILE), { recursive: true });
|
|
66
|
-
let isReady = false;
|
|
67
|
-
|
|
68
|
-
const restartClient = _.debounce(async () => {
|
|
69
|
-
if (!isReady) return;
|
|
70
|
-
generatePlugins();
|
|
71
|
-
if (subprocess) {
|
|
72
|
-
console.log('client restarting...');
|
|
73
|
-
subprocess.cancel();
|
|
74
|
-
let i = 0;
|
|
75
|
-
while (true) {
|
|
76
|
-
++i;
|
|
77
|
-
const result = await isPortReachable(clientPort);
|
|
78
|
-
if (!result) {
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
81
|
-
await sleep(500);
|
|
82
|
-
if (i > 10) {
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
runDevClient();
|
|
87
|
-
await fs.promises.writeFile(process.env.WATCH_FILE, `export const watchId = '${uid()}';`, 'utf-8');
|
|
88
|
-
}
|
|
89
|
-
}, 500);
|
|
90
|
-
|
|
91
|
-
watcher
|
|
92
|
-
.on('ready', () => {
|
|
93
|
-
isReady = true;
|
|
94
|
-
})
|
|
95
|
-
.on('addDir', async (pathname) => {
|
|
96
|
-
if (!isReady) return;
|
|
97
|
-
restartClient();
|
|
98
|
-
})
|
|
99
|
-
.on('unlinkDir', async (pathname) => {
|
|
100
|
-
if (!isReady) return;
|
|
101
|
-
restartClient();
|
|
102
|
-
});
|
|
61
|
+
await buildBundleStatusHtml();
|
|
103
62
|
|
|
104
63
|
promptForTs();
|
|
105
64
|
const { SERVER_TSCONFIG_PATH } = process.env;
|
|
@@ -117,30 +76,167 @@ module.exports = (cli) => {
|
|
|
117
76
|
return;
|
|
118
77
|
}
|
|
119
78
|
|
|
120
|
-
const { port, client, server, inspect } = opts;
|
|
79
|
+
const { port, client, server, inspect, clientV2Only, rsbuild } = opts;
|
|
121
80
|
|
|
122
81
|
if (port) {
|
|
123
82
|
process.env.APP_PORT = opts.port;
|
|
124
83
|
}
|
|
125
84
|
|
|
126
|
-
const
|
|
85
|
+
const APP_PORT = Number(process.env.APP_PORT);
|
|
127
86
|
|
|
128
87
|
let clientPort = APP_PORT;
|
|
129
88
|
let serverPort;
|
|
89
|
+
let clientV2Port = APP_PORT;
|
|
130
90
|
|
|
131
91
|
nodeCheck();
|
|
132
|
-
|
|
133
92
|
await postCheck(opts);
|
|
134
93
|
|
|
135
|
-
|
|
94
|
+
const shouldRunClientV2 = clientV2Only || client || !server;
|
|
95
|
+
const shouldRunClient = !clientV2Only && (client || !server);
|
|
96
|
+
const shouldRunServer = !clientV2Only && (server || !client);
|
|
97
|
+
const shouldRunClientWithRsbuild = shouldRunClient && !!rsbuild;
|
|
98
|
+
|
|
99
|
+
if (shouldRunServer && server) {
|
|
136
100
|
serverPort = APP_PORT;
|
|
137
|
-
} else if (
|
|
101
|
+
} else if (shouldRunServer) {
|
|
138
102
|
serverPort = await getPortPromise({
|
|
139
103
|
port: 1 * clientPort + 1,
|
|
140
104
|
});
|
|
141
105
|
}
|
|
142
106
|
|
|
143
|
-
if (
|
|
107
|
+
if (shouldRunClientV2 && !clientV2Only) {
|
|
108
|
+
clientV2Port = await getPortPromise({
|
|
109
|
+
port: 1 * clientPort + 2,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
let subprocessClient;
|
|
114
|
+
let subprocessClientV2;
|
|
115
|
+
|
|
116
|
+
const runDevClientV2 = () => {
|
|
117
|
+
console.log('starting client-v2', 1 * clientV2Port);
|
|
118
|
+
subprocessClientV2 = runWithPrefix(
|
|
119
|
+
'rsbuild',
|
|
120
|
+
['dev', '--config', `${APP_PACKAGE_ROOT}/client-v2/rsbuild.config.ts`],
|
|
121
|
+
{
|
|
122
|
+
prefix: 'client-v2',
|
|
123
|
+
color: 'magenta',
|
|
124
|
+
env: {
|
|
125
|
+
...process.env,
|
|
126
|
+
APP_V2_PORT: `${clientV2Port}`,
|
|
127
|
+
NODE_ENV: 'development',
|
|
128
|
+
RSPACK_HMR_CLIENT_PORT: `${clientV2Only ? clientV2Port : clientPort}`,
|
|
129
|
+
API_BASE_URL: process.env.API_BASE_URL || process.env.API_BASE_PATH,
|
|
130
|
+
API_CLIENT_STORAGE_PREFIX: process.env.API_CLIENT_STORAGE_PREFIX,
|
|
131
|
+
API_CLIENT_STORAGE_TYPE: process.env.API_CLIENT_STORAGE_TYPE,
|
|
132
|
+
API_CLIENT_SHARE_TOKEN: process.env.API_CLIENT_SHARE_TOKEN || 'false',
|
|
133
|
+
WEBSOCKET_URL: process.env.WEBSOCKET_URL || buildWSURL(process.env.API_BASE_URL, serverPort),
|
|
134
|
+
WS_PATH: process.env.WS_PATH,
|
|
135
|
+
ESM_CDN_BASE_URL: process.env.ESM_CDN_BASE_URL || 'https://esm.sh',
|
|
136
|
+
ESM_CDN_SUFFIX: process.env.ESM_CDN_SUFFIX || '',
|
|
137
|
+
PROXY_TARGET_URL:
|
|
138
|
+
process.env.PROXY_TARGET_URL || (serverPort ? `http://127.0.0.1:${serverPort}` : undefined),
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
if (clientV2Only) {
|
|
145
|
+
runDevClientV2();
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const runDevClient = () => {
|
|
150
|
+
console.log('starting client', 1 * clientPort);
|
|
151
|
+
const command = shouldRunClientWithRsbuild ? 'rsbuild' : 'umi';
|
|
152
|
+
const args = shouldRunClientWithRsbuild
|
|
153
|
+
? ['dev', '--config', `${APP_PACKAGE_ROOT}/client/rsbuild.config.ts`]
|
|
154
|
+
: ['dev'];
|
|
155
|
+
subprocessClient = runWithPrefix(command, args, {
|
|
156
|
+
prefix: 'client',
|
|
157
|
+
color: 'cyan',
|
|
158
|
+
env: {
|
|
159
|
+
...process.env,
|
|
160
|
+
stdio: 'inherit',
|
|
161
|
+
shell: true,
|
|
162
|
+
PORT: clientPort,
|
|
163
|
+
APP_PORT: `${clientPort}`,
|
|
164
|
+
APP_ROOT: `${APP_PACKAGE_ROOT}/client`,
|
|
165
|
+
APP_V2_PORT: `${clientV2Port}`,
|
|
166
|
+
NODE_ENV: 'development',
|
|
167
|
+
RSPACK_HMR_CLIENT_PORT: `${clientPort}`,
|
|
168
|
+
API_BASE_URL: process.env.API_BASE_URL || process.env.API_BASE_PATH,
|
|
169
|
+
API_CLIENT_STORAGE_PREFIX: process.env.API_CLIENT_STORAGE_PREFIX,
|
|
170
|
+
API_CLIENT_STORAGE_TYPE: process.env.API_CLIENT_STORAGE_TYPE,
|
|
171
|
+
API_CLIENT_SHARE_TOKEN: process.env.API_CLIENT_SHARE_TOKEN || 'false',
|
|
172
|
+
WEBSOCKET_URL: process.env.WEBSOCKET_URL || buildWSURL(process.env.API_BASE_URL, serverPort),
|
|
173
|
+
PROXY_TARGET_URL:
|
|
174
|
+
process.env.PROXY_TARGET_URL || (serverPort ? `http://127.0.0.1:${serverPort}` : undefined),
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const restartSubprocess = async (subprocessRef, port, start) => {
|
|
180
|
+
if (!subprocessRef) {
|
|
181
|
+
start();
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
subprocessRef.cancel();
|
|
185
|
+
let i = 0;
|
|
186
|
+
while (true) {
|
|
187
|
+
++i;
|
|
188
|
+
const result = await isPortReachable(port);
|
|
189
|
+
if (!result) {
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
await sleep(500);
|
|
193
|
+
if (i > 10) {
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
start();
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
if (shouldRunClient) {
|
|
201
|
+
const storagePluginPath = path.resolve(process.cwd(), 'storage/plugins');
|
|
202
|
+
const watcher = chokidar.watch(`${storagePluginPath}/**/*`, {
|
|
203
|
+
cwd: process.cwd(),
|
|
204
|
+
ignored: /(^|[\/\\])\../, // 忽略隐藏文件
|
|
205
|
+
persistent: true,
|
|
206
|
+
depth: 1, // 只监听第一层目录
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
await fs.promises.mkdir(path.dirname(process.env.WATCH_FILE), { recursive: true });
|
|
210
|
+
let isReady = false;
|
|
211
|
+
|
|
212
|
+
const restartClient = _.debounce(async () => {
|
|
213
|
+
if (!isReady) return;
|
|
214
|
+
generatePlugins();
|
|
215
|
+
if (shouldRunClient) {
|
|
216
|
+
await restartSubprocess(subprocessClient, clientPort, runDevClient);
|
|
217
|
+
}
|
|
218
|
+
if (shouldRunClientV2) {
|
|
219
|
+
await restartSubprocess(subprocessClientV2, clientV2Port, runDevClientV2);
|
|
220
|
+
}
|
|
221
|
+
await fs.promises.writeFile(process.env.WATCH_FILE, `export const watchId = '${uid()}';`, 'utf-8');
|
|
222
|
+
}, 500);
|
|
223
|
+
|
|
224
|
+
watcher
|
|
225
|
+
.on('ready', () => {
|
|
226
|
+
console.log('watching plugin folder changes...');
|
|
227
|
+
isReady = true;
|
|
228
|
+
})
|
|
229
|
+
.on('addDir', async () => {
|
|
230
|
+
if (!isReady) return;
|
|
231
|
+
restartClient();
|
|
232
|
+
})
|
|
233
|
+
.on('unlinkDir', async () => {
|
|
234
|
+
if (!isReady) return;
|
|
235
|
+
restartClient();
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (shouldRunServer) {
|
|
144
240
|
console.log('starting server', serverPort);
|
|
145
241
|
|
|
146
242
|
const filteredArgs = process.argv.filter(
|
|
@@ -183,8 +279,12 @@ module.exports = (cli) => {
|
|
|
183
279
|
runDevServer();
|
|
184
280
|
}
|
|
185
281
|
|
|
186
|
-
if (
|
|
282
|
+
if (shouldRunClient) {
|
|
187
283
|
runDevClient();
|
|
188
284
|
}
|
|
285
|
+
|
|
286
|
+
if (shouldRunClientV2) {
|
|
287
|
+
runDevClientV2();
|
|
288
|
+
}
|
|
189
289
|
});
|
|
190
290
|
};
|
package/src/commands/index.js
CHANGED
package/src/commands/pkg.js
CHANGED
|
@@ -208,7 +208,7 @@ class PackageManager {
|
|
|
208
208
|
showLicenseInfo(LicenseKeyError.notValid);
|
|
209
209
|
}
|
|
210
210
|
logger.error(`Login failed: ${this.baseURL}`);
|
|
211
|
-
logger.error(error?.message
|
|
211
|
+
logger.error(error?.message, { error });
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
214
|
|
|
@@ -283,7 +283,12 @@ module.exports = (cli) => {
|
|
|
283
283
|
NOCOBASE_PKG_URL = 'https://pkg.nocobase.com/',
|
|
284
284
|
NOCOBASE_PKG_USERNAME,
|
|
285
285
|
NOCOBASE_PKG_PASSWORD,
|
|
286
|
+
DISABLE_PKG_DOWNLOAD,
|
|
286
287
|
} = process.env;
|
|
288
|
+
if (DISABLE_PKG_DOWNLOAD === 'true') {
|
|
289
|
+
logger.info('Package download is disabled.');
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
287
292
|
let accessKeyId;
|
|
288
293
|
let accessKeySecret;
|
|
289
294
|
try {
|
package/src/commands/pm2.js
CHANGED
|
@@ -62,6 +62,7 @@ module.exports = (cli) => {
|
|
|
62
62
|
if (descJson['devDependencies']?.['@nocobase/devtools']) {
|
|
63
63
|
descJson['devDependencies']['@nocobase/devtools'] = stdout;
|
|
64
64
|
}
|
|
65
|
+
descJson['resolutions'] = sourceJson['resolutions'];
|
|
65
66
|
const json = deepmerge(descJson, sourceJson);
|
|
66
67
|
await writeJSON(descPath, json, { spaces: 2, encoding: 'utf8' });
|
|
67
68
|
await run('yarn', ['install']);
|
package/src/license.js
CHANGED
|
@@ -18,7 +18,7 @@ const { pick } = require('lodash');
|
|
|
18
18
|
exports.getAccessKeyPair = async function () {
|
|
19
19
|
const keyFile = resolve(process.cwd(), 'storage/.license/license-key');
|
|
20
20
|
if (!fs.existsSync(keyFile)) {
|
|
21
|
-
logger.
|
|
21
|
+
logger.info('License key not found');
|
|
22
22
|
return {};
|
|
23
23
|
}
|
|
24
24
|
logger.info('License key found');
|
package/src/util.js
CHANGED
|
@@ -83,6 +83,44 @@ exports.run = (command, args, options = {}) => {
|
|
|
83
83
|
});
|
|
84
84
|
};
|
|
85
85
|
|
|
86
|
+
exports.runWithPrefix = (command, args, options = {}) => {
|
|
87
|
+
if (command === 'tsx') {
|
|
88
|
+
command = 'node';
|
|
89
|
+
args = ['./node_modules/tsx/dist/cli.mjs'].concat(args || []);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const prefix = options.prefix || 'process';
|
|
93
|
+
const color = options.color || 'cyan';
|
|
94
|
+
const label = chalk[color](`[${prefix}]`);
|
|
95
|
+
const subprocess = execa(command, args, {
|
|
96
|
+
shell: true,
|
|
97
|
+
stdio: 'pipe',
|
|
98
|
+
...options,
|
|
99
|
+
env: {
|
|
100
|
+
...process.env,
|
|
101
|
+
...options.env,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
const writePrefixed = (chunk, writer) => {
|
|
106
|
+
const text = chunk.toString();
|
|
107
|
+
const lines = text.split(/\r?\n/);
|
|
108
|
+
const trailingNewline = text.endsWith('\n') || text.endsWith('\r');
|
|
109
|
+
|
|
110
|
+
lines.forEach((line, index) => {
|
|
111
|
+
if (!line && index === lines.length - 1 && trailingNewline) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
writer.write(`${label} ${line}\n`);
|
|
115
|
+
});
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
subprocess.stdout?.on('data', (chunk) => writePrefixed(chunk, process.stdout));
|
|
119
|
+
subprocess.stderr?.on('data', (chunk) => writePrefixed(chunk, process.stderr));
|
|
120
|
+
|
|
121
|
+
return subprocess;
|
|
122
|
+
};
|
|
123
|
+
|
|
86
124
|
exports.isPortReachable = async (port, { timeout = 1000, host } = {}) => {
|
|
87
125
|
const promise = new Promise((resolve, reject) => {
|
|
88
126
|
const socket = new net.Socket();
|
|
@@ -232,6 +270,7 @@ exports.genTsConfigPaths = function genTsConfigPaths() {
|
|
|
232
270
|
.split(sep)
|
|
233
271
|
.join('/');
|
|
234
272
|
paths[`${packageJsonName}/client`] = [`${relativePath}/src/client`];
|
|
273
|
+
paths[`${packageJsonName}/client-v2`] = [`${relativePath}/src/client-v2`];
|
|
235
274
|
paths[`${packageJsonName}/package.json`] = [`${relativePath}/package.json`];
|
|
236
275
|
paths[packageJsonName] = [`${relativePath}/src`];
|
|
237
276
|
if (packageJsonName === '@nocobase/test') {
|
|
@@ -282,6 +321,21 @@ function parseEnv(name) {
|
|
|
282
321
|
}
|
|
283
322
|
}
|
|
284
323
|
|
|
324
|
+
function resolvePublicPath(appPublicPath = '/') {
|
|
325
|
+
const normalized = String(appPublicPath || '/').trim() || '/';
|
|
326
|
+
const withLeadingSlash = normalized.startsWith('/') ? normalized : `/${normalized}`;
|
|
327
|
+
return withLeadingSlash.endsWith('/') ? withLeadingSlash : `${withLeadingSlash}/`;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
exports.resolvePublicPath = resolvePublicPath;
|
|
331
|
+
|
|
332
|
+
function resolveV2PublicPath(appPublicPath = '/') {
|
|
333
|
+
const publicPath = resolvePublicPath(appPublicPath);
|
|
334
|
+
return `${publicPath.replace(/\/$/, '')}/v2/`;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
exports.resolveV2PublicPath = resolveV2PublicPath;
|
|
338
|
+
|
|
285
339
|
function buildIndexHtml(force = false) {
|
|
286
340
|
const file = `${process.env.APP_PACKAGE_ROOT}/dist/client/index.html`;
|
|
287
341
|
if (!fs.existsSync(file)) {
|
|
@@ -295,14 +349,26 @@ function buildIndexHtml(force = false) {
|
|
|
295
349
|
fs.copyFileSync(file, tpl);
|
|
296
350
|
}
|
|
297
351
|
const data = fs.readFileSync(tpl, 'utf-8');
|
|
298
|
-
|
|
352
|
+
let replacedData = data
|
|
353
|
+
.replace(/\{\{env.CDN_BASE_URL\}\}/g, process.env.CDN_BASE_URL)
|
|
299
354
|
.replace(/\{\{env.APP_PUBLIC_PATH\}\}/g, process.env.APP_PUBLIC_PATH)
|
|
355
|
+
.replace(/\{\{env.API_CLIENT_SHARE_TOKEN\}\}/g, process.env.API_CLIENT_SHARE_TOKEN || 'false')
|
|
300
356
|
.replace(/\{\{env.API_CLIENT_STORAGE_TYPE\}\}/g, process.env.API_CLIENT_STORAGE_TYPE)
|
|
301
357
|
.replace(/\{\{env.API_CLIENT_STORAGE_PREFIX\}\}/g, process.env.API_CLIENT_STORAGE_PREFIX)
|
|
302
358
|
.replace(/\{\{env.API_BASE_URL\}\}/g, process.env.API_BASE_URL || process.env.API_BASE_PATH)
|
|
303
359
|
.replace(/\{\{env.WS_URL\}\}/g, process.env.WEBSOCKET_URL || '')
|
|
304
360
|
.replace(/\{\{env.WS_PATH\}\}/g, process.env.WS_PATH)
|
|
361
|
+
.replace(/\{\{env.ESM_CDN_BASE_URL\}\}/g, process.env.ESM_CDN_BASE_URL || '')
|
|
362
|
+
.replace(/\{\{env.ESM_CDN_SUFFIX\}\}/g, process.env.ESM_CDN_SUFFIX || '')
|
|
305
363
|
.replace('src="/umi.', `src="${process.env.APP_PUBLIC_PATH}umi.`);
|
|
364
|
+
|
|
365
|
+
if (process.env.CDN_BASE_URL) {
|
|
366
|
+
const appBaseUrl = process.env.CDN_BASE_URL.replace(/\/+$/, '');
|
|
367
|
+
const appPublicPath = process.env.APP_PUBLIC_PATH.replace(/\/+$/, '');
|
|
368
|
+
const re1 = new RegExp(`src="${appPublicPath}/`, 'g');
|
|
369
|
+
const re2 = new RegExp(`href="${appPublicPath}/`, 'g');
|
|
370
|
+
replacedData = replacedData.replace(re1, `src="${appBaseUrl}/`).replace(re2, `href="${appBaseUrl}/`);
|
|
371
|
+
}
|
|
306
372
|
fs.writeFileSync(file, replacedData, 'utf-8');
|
|
307
373
|
}
|
|
308
374
|
|
|
@@ -360,6 +426,7 @@ exports.initEnv = function initEnv() {
|
|
|
360
426
|
APP_PORT: 13000,
|
|
361
427
|
API_BASE_PATH: '/api/',
|
|
362
428
|
API_CLIENT_STORAGE_PREFIX: 'NOCOBASE_',
|
|
429
|
+
API_CLIENT_SHARE_TOKEN: 'false',
|
|
363
430
|
API_CLIENT_STORAGE_TYPE: 'localStorage',
|
|
364
431
|
// DB_DIALECT: 'sqlite',
|
|
365
432
|
DB_STORAGE: 'storage/db/nocobase.sqlite',
|
|
@@ -383,8 +450,12 @@ exports.initEnv = function initEnv() {
|
|
|
383
450
|
PLUGIN_STATICS_PATH: '/static/plugins/',
|
|
384
451
|
LOGGER_BASE_PATH: 'storage/logs',
|
|
385
452
|
APP_SERVER_BASE_URL: '',
|
|
453
|
+
APP_BASE_URL: '',
|
|
454
|
+
CDN_BASE_URL: '',
|
|
386
455
|
APP_PUBLIC_PATH: '/',
|
|
387
456
|
WATCH_FILE: resolve(process.cwd(), 'storage/app.watch.ts'),
|
|
457
|
+
ESM_CDN_BASE_URL: 'https://esm.sh',
|
|
458
|
+
ESM_CDN_SUFFIX: '',
|
|
388
459
|
};
|
|
389
460
|
|
|
390
461
|
if (
|
|
@@ -438,6 +509,16 @@ exports.initEnv = function initEnv() {
|
|
|
438
509
|
process.env.__env_modified__ = true;
|
|
439
510
|
}
|
|
440
511
|
|
|
512
|
+
if (!process.env.CDN_BASE_URL && process.env.APP_PUBLIC_PATH !== '/') {
|
|
513
|
+
process.env.CDN_BASE_URL = process.env.APP_PUBLIC_PATH;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
if (process.env.CDN_BASE_URL.includes('http') && process.env.CDN_VERSION === 'auto') {
|
|
517
|
+
const version = require('../package.json').version;
|
|
518
|
+
process.env.CDN_BASE_URL = process.env.CDN_BASE_URL.replace(/\/+$/, '') + '/' + version + '/';
|
|
519
|
+
process.env.CDN_VERSION = '';
|
|
520
|
+
}
|
|
521
|
+
|
|
441
522
|
if (!process.env.TZ) {
|
|
442
523
|
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
443
524
|
process.env.TZ = getTimezonesByOffset(process.env.DB_TIMEZONE || timeZone);
|
|
@@ -481,10 +562,40 @@ exports.checkDBDialect = function () {
|
|
|
481
562
|
|
|
482
563
|
exports.generatePlugins = function () {
|
|
483
564
|
try {
|
|
484
|
-
require.resolve('@nocobase/devtools/
|
|
485
|
-
const { generatePlugins } = require('@nocobase/devtools/
|
|
486
|
-
|
|
565
|
+
require.resolve('@nocobase/devtools/common');
|
|
566
|
+
const { generateAllPlugins, generatePlugins, generateV2Plugins } = require('@nocobase/devtools/common');
|
|
567
|
+
if (typeof generateAllPlugins === 'function') {
|
|
568
|
+
generateAllPlugins();
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
generatePlugins?.();
|
|
572
|
+
generateV2Plugins?.();
|
|
487
573
|
} catch (error) {
|
|
488
574
|
return;
|
|
489
575
|
}
|
|
490
576
|
};
|
|
577
|
+
|
|
578
|
+
exports.isURL = function isURL(str) {
|
|
579
|
+
let url;
|
|
580
|
+
|
|
581
|
+
try {
|
|
582
|
+
url = new URL(str);
|
|
583
|
+
} catch (e) {
|
|
584
|
+
return false;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
return url.protocol === 'http:' || url.protocol === 'https:';
|
|
588
|
+
};
|
|
589
|
+
|
|
590
|
+
exports.buildWSURL = function buildWSURL(urlString, serverPort) {
|
|
591
|
+
if (exports.isURL(urlString)) {
|
|
592
|
+
const parsedUrl = new URL(urlString);
|
|
593
|
+
parsedUrl.protocol = parsedUrl.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
594
|
+
parsedUrl.pathname =
|
|
595
|
+
process.env.WS_PATH || (process.env.APP_PUBLIC_PATH ? process.env.APP_PUBLIC_PATH + 'ws' : '/ws');
|
|
596
|
+
const url = parsedUrl.toString();
|
|
597
|
+
return url;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
return serverPort ? `ws://localhost:${serverPort}${process.env.WS_PATH}` : undefined;
|
|
601
|
+
};
|