@nocobase/cli 2.1.0-alpha.16 → 2.1.0-alpha.17

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.
Files changed (105) hide show
  1. package/LICENSE.txt +107 -0
  2. package/README.md +134 -63
  3. package/bin/run.cmd +3 -0
  4. package/bin/run.js +87 -0
  5. package/dist/commands/api/index.js +8 -0
  6. package/dist/commands/env/add.js +53 -0
  7. package/dist/commands/env/auth.js +36 -0
  8. package/dist/commands/env/index.js +27 -0
  9. package/dist/commands/env/list.js +31 -0
  10. package/dist/commands/env/remove.js +54 -0
  11. package/dist/commands/env/update.js +58 -0
  12. package/dist/commands/env/use.js +26 -0
  13. package/dist/commands/resource/create.js +15 -0
  14. package/dist/commands/resource/destroy.js +15 -0
  15. package/dist/commands/resource/get.js +15 -0
  16. package/dist/commands/resource/index.js +7 -0
  17. package/dist/commands/resource/list.js +16 -0
  18. package/dist/commands/resource/query.js +15 -0
  19. package/dist/commands/resource/update.js +15 -0
  20. package/dist/generated/command-registry.js +88 -0
  21. package/dist/lib/api-client.js +199 -0
  22. package/dist/lib/auth-store.js +155 -0
  23. package/dist/lib/bootstrap.js +349 -0
  24. package/dist/lib/build-config.js +10 -0
  25. package/dist/lib/cli-home.js +30 -0
  26. package/dist/lib/env-auth.js +405 -0
  27. package/dist/lib/generated-command.js +142 -0
  28. package/dist/lib/naming.js +70 -0
  29. package/dist/lib/openapi.js +254 -0
  30. package/dist/lib/post-processors.js +23 -0
  31. package/dist/lib/resource-command.js +335 -0
  32. package/dist/lib/resource-request.js +104 -0
  33. package/dist/lib/runtime-generator.js +408 -0
  34. package/dist/lib/runtime-store.js +56 -0
  35. package/dist/lib/ui.js +169 -0
  36. package/dist/post-processors/data-modeling.js +66 -0
  37. package/dist/post-processors/data-source-manager.js +114 -0
  38. package/dist/post-processors/index.js +19 -0
  39. package/nocobase-ctl.config.json +327 -0
  40. package/package.json +50 -25
  41. package/LICENSE +0 -201
  42. package/bin/index.js +0 -39
  43. package/nocobase.conf.tpl +0 -184
  44. package/src/cli.js +0 -28
  45. package/src/commands/benchmark.js +0 -73
  46. package/src/commands/build.js +0 -81
  47. package/src/commands/clean.js +0 -30
  48. package/src/commands/client.js +0 -168
  49. package/src/commands/create-nginx-conf.js +0 -53
  50. package/src/commands/create-plugin.js +0 -33
  51. package/src/commands/dev.js +0 -290
  52. package/src/commands/doc.js +0 -76
  53. package/src/commands/e2e.js +0 -265
  54. package/src/commands/global.js +0 -43
  55. package/src/commands/index.js +0 -45
  56. package/src/commands/instance-id.js +0 -47
  57. package/src/commands/locale/cronstrue.js +0 -122
  58. package/src/commands/locale/react-js-cron/en-US.json +0 -75
  59. package/src/commands/locale/react-js-cron/index.js +0 -17
  60. package/src/commands/locale/react-js-cron/zh-CN.json +0 -33
  61. package/src/commands/locale/react-js-cron/zh-TW.json +0 -33
  62. package/src/commands/locale.js +0 -81
  63. package/src/commands/p-test.js +0 -88
  64. package/src/commands/perf.js +0 -63
  65. package/src/commands/pkg.js +0 -321
  66. package/src/commands/pm2.js +0 -37
  67. package/src/commands/postinstall.js +0 -88
  68. package/src/commands/start.js +0 -148
  69. package/src/commands/tar.js +0 -36
  70. package/src/commands/test-coverage.js +0 -55
  71. package/src/commands/test.js +0 -107
  72. package/src/commands/umi.js +0 -33
  73. package/src/commands/update-deps.js +0 -72
  74. package/src/commands/upgrade.js +0 -47
  75. package/src/commands/view-license-key.js +0 -44
  76. package/src/index.js +0 -14
  77. package/src/license.js +0 -76
  78. package/src/logger.js +0 -75
  79. package/src/plugin-generator.js +0 -80
  80. package/src/util.js +0 -607
  81. package/templates/bundle-status.html +0 -338
  82. package/templates/create-app-package.json +0 -39
  83. package/templates/plugin/.npmignore.tpl +0 -2
  84. package/templates/plugin/README.md.tpl +0 -1
  85. package/templates/plugin/client-v2.d.ts +0 -2
  86. package/templates/plugin/client-v2.js +0 -1
  87. package/templates/plugin/client.d.ts +0 -2
  88. package/templates/plugin/client.js +0 -1
  89. package/templates/plugin/package.json.tpl +0 -12
  90. package/templates/plugin/server.d.ts +0 -2
  91. package/templates/plugin/server.js +0 -1
  92. package/templates/plugin/src/client/client.d.ts +0 -249
  93. package/templates/plugin/src/client/index.tsx.tpl +0 -1
  94. package/templates/plugin/src/client/locale.ts +0 -21
  95. package/templates/plugin/src/client/models/index.ts +0 -12
  96. package/templates/plugin/src/client/plugin.tsx.tpl +0 -10
  97. package/templates/plugin/src/client-v2/client.d.ts +0 -103
  98. package/templates/plugin/src/client-v2/index.tsx.tpl +0 -1
  99. package/templates/plugin/src/client-v2/plugin.tsx.tpl +0 -7
  100. package/templates/plugin/src/index.ts +0 -2
  101. package/templates/plugin/src/locale/en-US.json +0 -1
  102. package/templates/plugin/src/locale/zh-CN.json +0 -1
  103. package/templates/plugin/src/server/collections/.gitkeep +0 -0
  104. package/templates/plugin/src/server/index.ts.tpl +0 -1
  105. package/templates/plugin/src/server/plugin.ts.tpl +0 -19
@@ -1,81 +0,0 @@
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
- const { existsSync } = require('fs');
11
- const { resolve } = require('path');
12
- const { Command } = require('commander');
13
- const { run, nodeCheck, isPackageValid, buildIndexHtml } = require('../util');
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
-
38
- /**
39
- *
40
- * @param {Command} cli
41
- */
42
- module.exports = (cli) => {
43
- cli
44
- .command('build')
45
- .allowUnknownOption()
46
- .argument('[packages...]')
47
- .option('-v, --version', 'print version')
48
- .option('-c, --compile', 'compile the @nocobase/build package')
49
- .option('-r, --retry', 'retry the last failed package')
50
- .option('-w, --watch', 'watch compile the @nocobase/build package')
51
- .option('-s, --sourcemap', 'generate sourcemap')
52
- .option('--no-dts', 'not generate dts')
53
- .option('--client-v2-only', 'build client-v2 shell only')
54
- .action(async (pkgs, options) => {
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
-
64
- if (options.compile || options.watch || isPackageValid('@nocobase/build/src/index.ts')) {
65
- await run('yarn', ['build', options.watch ? '--watch' : ''], {
66
- cwd: resolve(process.cwd(), 'packages/core/build'),
67
- });
68
- if (options.watch) return;
69
- }
70
-
71
- await run('nocobase-build', [
72
- ...pkgs,
73
- options.version ? '--version' : '',
74
- !options.dts ? '--no-dts' : '',
75
- options.sourcemap ? '--sourcemap' : '',
76
- options.retry ? '--retry' : '',
77
- ]);
78
- buildIndexHtml(true);
79
- await buildClientV2();
80
- });
81
- };
@@ -1,30 +0,0 @@
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
- const chalk = require('chalk');
11
- const { Command } = require('commander');
12
- const { run, isDev } = require('../util');
13
-
14
- /**
15
- *
16
- * @param {Command} cli
17
- */
18
- module.exports = (cli) => {
19
- cli
20
- .command('clean')
21
- .allowUnknownOption()
22
- .action(() => {
23
- if (!isDev()) {
24
- return;
25
- }
26
- run('rimraf', ['-rf', './storage/app-dev']);
27
- run('rimraf', ['-rf', 'packages/*/*/{lib,esm,es,dist,node_modules}']);
28
- run('rimraf', ['-rf', 'packages/*/@*/*/{lib,esm,es,dist,node_modules}']);
29
- });
30
- };
@@ -1,168 +0,0 @@
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
- const chalk = require('chalk');
11
- const { Command } = require('commander');
12
- const fs = require('fs-extra');
13
- const { resolve } = require('path');
14
-
15
- /**
16
- * 复制主应用客户端文件
17
- * @param {string} source - 源目录路径
18
- * @param {string} target - 目标目录路径
19
- */
20
- async function copyMainClient(source, target) {
21
- if (!(await fs.exists(source))) {
22
- console.log(chalk.yellow(`Source directory does not exist: ${source}`));
23
- return;
24
- }
25
- // 确保目标目录存在且为空
26
- await fs.ensureDir(target);
27
- await fs.emptyDir(target);
28
- await fs.copy(source, target, { recursive: true });
29
- console.log(chalk.green(`Copied main client files from ${source} to ${target}`));
30
- }
31
-
32
- /**
33
- * 复制插件客户端文件
34
- * @param {string} pluginsBaseDir - 插件基础目录路径
35
- * @param {string} namespace - 命名空间(如 '@nocobase' 或 '@nocobase-example')
36
- * @param {string} target - 目标目录
37
- */
38
- async function copyPluginClients(pluginsBaseDir, namespace, target) {
39
- const pluginsDir = resolve(process.cwd(), pluginsBaseDir, namespace);
40
- if (await fs.exists(pluginsDir)) {
41
- const pluginNames = await fs.readdir(pluginsDir);
42
- for (const pluginName of pluginNames) {
43
- const pluginPath = resolve(pluginsDir, pluginName);
44
- for (const lane of ['client', 'client-v2']) {
45
- const pluginDistClient = resolve(pluginPath, `dist/${lane}`);
46
- if (await fs.exists(pluginDistClient)) {
47
- const pluginTarget = resolve(target, 'static/plugins', namespace, pluginName, 'dist', lane);
48
- await fs.mkdir(resolve(pluginTarget, '..'), { recursive: true });
49
- await fs.copy(pluginDistClient, pluginTarget, { recursive: true });
50
- console.log(chalk.green(`Copied ${namespace}/${pluginName} ${lane} files`));
51
- }
52
- }
53
- }
54
- }
55
- }
56
-
57
- /**
58
- * 递归上传目录到 OSS
59
- * @param {Client} client - OSS 客户端实例
60
- * @param {string} localDir - 本地目录路径
61
- * @param {string} ossPrefix - OSS 对象前缀(目录路径)
62
- */
63
- async function uploadDirectoryToOSS(client, localDir, ossPrefix = '') {
64
- if (!(await fs.exists(localDir))) {
65
- console.log(chalk.yellow(`Directory does not exist: ${localDir}`));
66
- return;
67
- }
68
-
69
- const stats = await fs.stat(localDir);
70
- if (!stats.isDirectory()) {
71
- throw new Error(`${localDir} is not a directory`);
72
- }
73
-
74
- const files = await fs.readdir(localDir);
75
- let uploadedCount = 0;
76
-
77
- for (const file of files) {
78
- const filePath = resolve(localDir, file);
79
- const fileStats = await fs.stat(filePath);
80
-
81
- if (fileStats.isDirectory()) {
82
- // 递归处理子目录
83
- const subOssPrefix = ossPrefix ? `${ossPrefix}/${file}` : file;
84
- const subCount = await uploadDirectoryToOSS(client, filePath, subOssPrefix);
85
- uploadedCount += subCount;
86
- } else {
87
- // 上传文件
88
- const ossKey = ossPrefix ? `${ossPrefix}/${file}` : file;
89
- try {
90
- await client.put(ossKey, filePath);
91
- // console.log(chalk.green(`Uploaded: ${ossKey}`));
92
- uploadedCount++;
93
- } catch (error) {
94
- console.error(chalk.red(`Failed to upload ${ossKey}:`), error.message);
95
- throw error;
96
- }
97
- }
98
- }
99
-
100
- return uploadedCount;
101
- }
102
-
103
- /**
104
- *
105
- * @param {Command} cli
106
- */
107
- module.exports = (cli) => {
108
- cli
109
- .command('client:extract')
110
- .allowUnknownOption()
111
- .action(async () => {
112
- const version = require('../../package.json').version;
113
- const target = resolve(process.cwd(), 'storage/dist-client', version);
114
- const mainClientSource = resolve(process.cwd(), 'node_modules/@nocobase/app/dist/client');
115
- await copyMainClient(mainClientSource, target);
116
- await copyPluginClients('packages/plugins', '@nocobase', target);
117
- await copyPluginClients('packages/plugins', '@nocobase-example', target);
118
- await copyPluginClients('packages/pro-plugins', '@nocobase', target);
119
- });
120
-
121
- cli
122
- .command('client:upload')
123
- .allowUnknownOption()
124
- .action(async () => {
125
- const version = require('../../package.json').version;
126
- const target = resolve(process.cwd(), 'storage/dist-client', version);
127
-
128
- // 检查必要的环境变量
129
- if (
130
- !process.env.CDN_ALI_OSS_ACCESS_KEY_ID ||
131
- !process.env.CDN_ALI_OSS_ACCESS_KEY_SECRET ||
132
- !process.env.CDN_ALI_OSS_BUCKET ||
133
- !process.env.CDN_ALI_OSS_REGION
134
- ) {
135
- console.error(
136
- chalk.red(
137
- 'Missing required environment variables: CDN_ALI_OSS_ACCESS_KEY_ID, CDN_ALI_OSS_ACCESS_KEY_SECRET, CDN_ALI_OSS_BUCKET, CDN_ALI_OSS_REGION',
138
- ),
139
- );
140
- process.exit(1);
141
- }
142
-
143
- const Client = require('ali-oss');
144
-
145
- const client = new Client({
146
- accessKeyId: process.env.CDN_ALI_OSS_ACCESS_KEY_ID,
147
- accessKeySecret: process.env.CDN_ALI_OSS_ACCESS_KEY_SECRET,
148
- bucket: process.env.CDN_ALI_OSS_BUCKET,
149
- region: process.env.CDN_ALI_OSS_REGION,
150
- });
151
-
152
- if (!(await fs.exists(target))) {
153
- console.error(chalk.red(`Target directory does not exist: ${target}`));
154
- console.log(chalk.yellow('Please run "client:extract" first to generate the client files.'));
155
- process.exit(1);
156
- }
157
-
158
- console.log(chalk.blue(`Uploading directory ${target} to OSS...`));
159
- const ossPrefix = `${version}`;
160
- try {
161
- const uploadedCount = await uploadDirectoryToOSS(client, target, ossPrefix);
162
- console.log(chalk.green(`Successfully uploaded ${uploadedCount} files to OSS`));
163
- } catch (error) {
164
- console.error(chalk.red('Upload failed:'), error);
165
- process.exit(1);
166
- }
167
- });
168
- };
@@ -1,53 +0,0 @@
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
- const { resolve, posix } = require('path');
11
- const { Command } = require('commander');
12
- const { readFileSync, writeFileSync } = require('fs');
13
- const { resolvePublicPath, resolveV2PublicPath } = require('../util');
14
-
15
- /**
16
- *
17
- * @param {Command} cli
18
- */
19
- module.exports = (cli) => {
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(/\/$/, '');
26
- const file = resolve(__dirname, '../../nocobase.conf.tpl');
27
- const data = readFileSync(file, 'utf-8');
28
- let otherLocation = '';
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 / {
39
- alias ${posix.resolve(process.cwd())}/node_modules/@nocobase/app/dist/client/;
40
- try_files $uri $uri/ /index.html;
41
- }`;
42
- }
43
- const replaced = data
44
- .replace(/\{\{cwd\}\}/g, posix.resolve(process.cwd()))
45
- .replace(/\{\{publicPath\}\}/g, appPublicPath)
46
- .replace(/\{\{v2PublicPath\}\}/g, v2PublicPath)
47
- .replace(/\{\{v2PublicPathNoTrailingSlash\}\}/g, v2PublicPathWithoutTrailingSlash)
48
- .replace(/\{\{apiPort\}\}/g, process.env.APP_PORT)
49
- .replace(/\{\{otherLocation\}\}/g, otherLocation);
50
- const targetFile = resolve(process.cwd(), 'storage', 'nocobase.conf');
51
- writeFileSync(targetFile, replaced);
52
- });
53
- };
@@ -1,33 +0,0 @@
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
- const { resolve } = require('path');
11
- const { Command } = require('commander');
12
- const { PluginGenerator } = require('../plugin-generator');
13
-
14
- /**
15
- *
16
- * @param {Command} cli
17
- */
18
- module.exports = (cli) => {
19
- cli
20
- .command('create-plugin')
21
- .argument('<name>')
22
- .allowUnknownOption()
23
- .action(async (name, options) => {
24
- const generator = new PluginGenerator({
25
- cwd: resolve(process.cwd(), name),
26
- args: options,
27
- context: {
28
- name,
29
- },
30
- });
31
- await generator.run();
32
- });
33
- };
@@ -1,290 +0,0 @@
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
- const _ = require('lodash');
10
- const { Command } = require('commander');
11
- const {
12
- generatePlugins,
13
- run,
14
- runWithPrefix,
15
- postCheck,
16
- nodeCheck,
17
- promptForTs,
18
- isPortReachable,
19
- buildWSURL,
20
- checkDBDialect,
21
- } = require('../util');
22
- const { getPortPromise } = require('portfinder');
23
- const chokidar = require('chokidar');
24
- const { uid } = require('@formily/shared');
25
- const path = require('path');
26
- const fs = require('fs');
27
-
28
- function sleep(ms = 1000) {
29
- return new Promise((resolve) => {
30
- setTimeout(resolve, ms);
31
- });
32
- }
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
-
43
- /**
44
- *
45
- * @param {Command} cli
46
- */
47
- module.exports = (cli) => {
48
- const { APP_PACKAGE_ROOT } = process.env;
49
- cli
50
- .command('dev')
51
- .option('-p, --port [port]')
52
- .option('-c, --client')
53
- .option('-s, --server')
54
- .option('--db-sync')
55
- .option('--rsbuild')
56
- .option('--client-v2-only')
57
- .option('-i, --inspect [port]')
58
- .allowUnknownOption()
59
- .action(async (opts) => {
60
- checkDBDialect();
61
- await buildBundleStatusHtml();
62
-
63
- promptForTs();
64
- const { SERVER_TSCONFIG_PATH } = process.env;
65
- process.env.IS_DEV_CMD = true;
66
-
67
- if (process.argv.includes('-h') || process.argv.includes('--help')) {
68
- run('ts-node', [
69
- '-P',
70
- SERVER_TSCONFIG_PATH,
71
- '-r',
72
- 'tsconfig-paths/register',
73
- `${APP_PACKAGE_ROOT}/src/index.ts`,
74
- ...process.argv.slice(2),
75
- ]);
76
- return;
77
- }
78
-
79
- const { port, client, server, inspect, clientV2Only, rsbuild } = opts;
80
-
81
- if (port) {
82
- process.env.APP_PORT = opts.port;
83
- }
84
-
85
- const APP_PORT = Number(process.env.APP_PORT);
86
-
87
- let clientPort = APP_PORT;
88
- let serverPort;
89
- let clientV2Port = APP_PORT;
90
-
91
- nodeCheck();
92
- await postCheck(opts);
93
-
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) {
100
- serverPort = APP_PORT;
101
- } else if (shouldRunServer) {
102
- serverPort = await getPortPromise({
103
- port: 1 * clientPort + 1,
104
- });
105
- }
106
-
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) {
240
- console.log('starting server', serverPort);
241
-
242
- const filteredArgs = process.argv.filter(
243
- (item, i) => !item.startsWith('--inspect') && !(process.argv[i - 1] === '--inspect' && Number.parseInt(item)),
244
- );
245
-
246
- const argv = [
247
- 'watch',
248
- ...(inspect ? [`--inspect=${inspect === true ? 9229 : inspect}`] : []),
249
- '--ignore=./storage/plugins/**',
250
- '--tsconfig',
251
- SERVER_TSCONFIG_PATH,
252
- '-r',
253
- 'tsconfig-paths/register',
254
- `${APP_PACKAGE_ROOT}/src/index.ts`,
255
- 'start',
256
- ...filteredArgs.slice(3),
257
- `--port=${serverPort}`,
258
- ];
259
-
260
- if (opts.dbSync) {
261
- argv.push('--db-sync');
262
- }
263
-
264
- const runDevServer = () => {
265
- run('tsx', argv, {
266
- env: {
267
- APP_PORT: serverPort,
268
- },
269
- }).catch((err) => {
270
- if (err.exitCode == 100) {
271
- console.log('Restarting server...');
272
- runDevServer();
273
- } else {
274
- console.error(err);
275
- }
276
- });
277
- };
278
-
279
- runDevServer();
280
- }
281
-
282
- if (shouldRunClient) {
283
- runDevClient();
284
- }
285
-
286
- if (shouldRunClientV2) {
287
- runDevClientV2();
288
- }
289
- });
290
- };