@nocobase/cli 0.18.0-alpha.9 → 0.19.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/package.json +5 -4
- package/src/commands/dev.js +3 -1
- package/src/commands/e2e.js +46 -4
- package/src/commands/p-test.js +12 -7
- package/src/commands/postinstall.js +12 -8
- package/src/commands/test.js +10 -10
- package/src/plugin-generator.js +7 -7
- package/src/util.js +18 -0
- package/templates/plugin/src/server/plugin.ts.tpl +4 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.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": "0.
|
|
11
|
+
"@nocobase/app": "0.19.0-alpha.10",
|
|
12
12
|
"@types/fs-extra": "^11.0.1",
|
|
13
13
|
"@umijs/utils": "3.5.20",
|
|
14
14
|
"chalk": "^4.1.1",
|
|
@@ -21,15 +21,16 @@
|
|
|
21
21
|
"pm2": "^5.2.0",
|
|
22
22
|
"portfinder": "^1.0.28",
|
|
23
23
|
"serve": "^13.0.2",
|
|
24
|
+
"tree-kill": "^1.2.2",
|
|
24
25
|
"tsx": "^4.6.2"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
|
-
"@nocobase/devtools": "0.
|
|
28
|
+
"@nocobase/devtools": "0.19.0-alpha.10"
|
|
28
29
|
},
|
|
29
30
|
"repository": {
|
|
30
31
|
"type": "git",
|
|
31
32
|
"url": "git+https://github.com/nocobase/nocobase.git",
|
|
32
33
|
"directory": "packages/core/cli"
|
|
33
34
|
},
|
|
34
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "d09d81eba67339da36bcec27939a85b35d180770"
|
|
35
36
|
}
|
package/src/commands/dev.js
CHANGED
|
@@ -106,7 +106,9 @@ module.exports = (cli) => {
|
|
|
106
106
|
env: {
|
|
107
107
|
PORT: clientPort,
|
|
108
108
|
APP_ROOT: `${APP_PACKAGE_ROOT}/client`,
|
|
109
|
-
WEBSOCKET_URL:
|
|
109
|
+
WEBSOCKET_URL:
|
|
110
|
+
process.env.WEBSOCKET_URL ||
|
|
111
|
+
(serverPort ? `ws://localhost:${serverPort}${process.env.WS_PATH}` : undefined),
|
|
110
112
|
PROXY_TARGET_URL:
|
|
111
113
|
process.env.PROXY_TARGET_URL || (serverPort ? `http://127.0.0.1:${serverPort}` : undefined),
|
|
112
114
|
},
|
package/src/commands/e2e.js
CHANGED
|
@@ -3,6 +3,9 @@ const { run, isPortReachable } = require('../util');
|
|
|
3
3
|
const { execSync } = require('node:child_process');
|
|
4
4
|
const axios = require('axios');
|
|
5
5
|
const { pTest } = require('./p-test');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
const treeKill = require('tree-kill');
|
|
8
|
+
const chalk = require('chalk');
|
|
6
9
|
|
|
7
10
|
/**
|
|
8
11
|
* 检查服务是否启动成功
|
|
@@ -32,7 +35,7 @@ const checkServer = async (duration = 1000, max = 60 * 10) => {
|
|
|
32
35
|
}
|
|
33
36
|
})
|
|
34
37
|
.catch((error) => {
|
|
35
|
-
console.error('Request error:', error
|
|
38
|
+
console.error('Request error:', error?.response?.data?.error);
|
|
36
39
|
});
|
|
37
40
|
}, duration);
|
|
38
41
|
});
|
|
@@ -90,6 +93,17 @@ async function runApp(options = {}) {
|
|
|
90
93
|
run('nocobase', [process.env.APP_ENV === 'production' ? 'start' : 'dev'], options);
|
|
91
94
|
}
|
|
92
95
|
|
|
96
|
+
process.on('SIGINT', async () => {
|
|
97
|
+
treeKill(process.pid, (error) => {
|
|
98
|
+
if (error) {
|
|
99
|
+
console.error(error);
|
|
100
|
+
} else {
|
|
101
|
+
console.log(chalk.yellow('Force killing...'));
|
|
102
|
+
}
|
|
103
|
+
process.exit();
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
93
107
|
const commonConfig = {
|
|
94
108
|
stdio: 'inherit',
|
|
95
109
|
};
|
|
@@ -127,6 +141,12 @@ const filterArgv = () => {
|
|
|
127
141
|
if (element === '--skip-reporter') {
|
|
128
142
|
continue;
|
|
129
143
|
}
|
|
144
|
+
if (element === '--build') {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (element === '--production') {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
130
150
|
argv.push(element);
|
|
131
151
|
}
|
|
132
152
|
return argv;
|
|
@@ -143,12 +163,23 @@ module.exports = (cli) => {
|
|
|
143
163
|
console.log('APP_BASE_URL:', process.env.APP_BASE_URL);
|
|
144
164
|
}
|
|
145
165
|
});
|
|
166
|
+
|
|
146
167
|
e2e
|
|
147
168
|
.command('test')
|
|
148
169
|
.allowUnknownOption()
|
|
149
170
|
.option('--url [url]')
|
|
150
171
|
.option('--skip-reporter')
|
|
172
|
+
.option('--build')
|
|
173
|
+
.option('--production')
|
|
151
174
|
.action(async (options) => {
|
|
175
|
+
process.env.__E2E__ = true;
|
|
176
|
+
if (options.production) {
|
|
177
|
+
process.env.APP_ENV = 'production';
|
|
178
|
+
}
|
|
179
|
+
if (options.build) {
|
|
180
|
+
process.env.APP_ENV = 'production';
|
|
181
|
+
await run('yarn', ['build']);
|
|
182
|
+
}
|
|
152
183
|
if (options.skipReporter) {
|
|
153
184
|
process.env.PLAYWRIGHT_SKIP_REPORTER = true;
|
|
154
185
|
}
|
|
@@ -183,8 +214,13 @@ module.exports = (cli) => {
|
|
|
183
214
|
e2e
|
|
184
215
|
.command('start-app')
|
|
185
216
|
.option('--production')
|
|
217
|
+
.option('--build')
|
|
186
218
|
.option('--port [port]')
|
|
187
219
|
.action(async (options) => {
|
|
220
|
+
process.env.__E2E__ = true;
|
|
221
|
+
if (options.build) {
|
|
222
|
+
await run('yarn', ['build']);
|
|
223
|
+
}
|
|
188
224
|
if (options.production) {
|
|
189
225
|
process.env.APP_ENV = 'production';
|
|
190
226
|
}
|
|
@@ -205,8 +241,14 @@ module.exports = (cli) => {
|
|
|
205
241
|
e2e
|
|
206
242
|
.command('p-test')
|
|
207
243
|
.option('--stop-on-error')
|
|
208
|
-
.option('--
|
|
209
|
-
.
|
|
210
|
-
|
|
244
|
+
.option('--build')
|
|
245
|
+
.option('--concurrency [concurrency]', '', os.cpus().length)
|
|
246
|
+
.action(async (options) => {
|
|
247
|
+
process.env.__E2E__ = true;
|
|
248
|
+
if (options.build) {
|
|
249
|
+
process.env.APP_ENV = 'production';
|
|
250
|
+
await run('yarn', ['build']);
|
|
251
|
+
}
|
|
252
|
+
await pTest({ ...options, concurrency: 1 * options.concurrency });
|
|
211
253
|
});
|
|
212
254
|
};
|
package/src/commands/p-test.js
CHANGED
|
@@ -3,7 +3,6 @@ const { resolve } = require('path');
|
|
|
3
3
|
const pAll = require('p-all');
|
|
4
4
|
const dotenv = require('dotenv');
|
|
5
5
|
const fs = require('fs');
|
|
6
|
-
const { Client } = require('pg');
|
|
7
6
|
const glob = require('glob');
|
|
8
7
|
const _ = require('lodash');
|
|
9
8
|
|
|
@@ -22,7 +21,7 @@ const config = {
|
|
|
22
21
|
async function runApp(dir, index = 0) {
|
|
23
22
|
// 一个进程需要占用两个端口? (一个是应用端口,一个是 socket 端口)
|
|
24
23
|
index = index * 2;
|
|
25
|
-
|
|
24
|
+
const { Client } = require('pg');
|
|
26
25
|
const database = `nocobase${index}`;
|
|
27
26
|
const client = new Client({
|
|
28
27
|
host: config['DB_HOST'],
|
|
@@ -35,7 +34,7 @@ async function runApp(dir, index = 0) {
|
|
|
35
34
|
await client.query(`DROP DATABASE IF EXISTS "${database}"`);
|
|
36
35
|
await client.query(`CREATE DATABASE "${database}";`);
|
|
37
36
|
await client.end();
|
|
38
|
-
return execa('yarn', ['nocobase', 'e2e', 'test', dir, '
|
|
37
|
+
return execa('yarn', ['nocobase', 'e2e', 'test', dir, '--skip-reporter'], {
|
|
39
38
|
shell: true,
|
|
40
39
|
stdio: 'inherit',
|
|
41
40
|
env: {
|
|
@@ -47,23 +46,29 @@ async function runApp(dir, index = 0) {
|
|
|
47
46
|
APP_ENV: 'production',
|
|
48
47
|
APP_PORT: 20000 + index,
|
|
49
48
|
DB_DATABASE: `nocobase${index}`,
|
|
50
|
-
SOCKET_PATH: `storage/gateway-e2e-${index}.sock`,
|
|
51
|
-
PM2_HOME: resolve(process.cwd(), `storage/.pm2-${index}`),
|
|
49
|
+
SOCKET_PATH: `storage/e2e/gateway-e2e-${index}.sock`,
|
|
50
|
+
PM2_HOME: resolve(process.cwd(), `storage/e2e/.pm2-${index}`),
|
|
52
51
|
PLAYWRIGHT_AUTH_FILE: resolve(process.cwd(), `storage/playwright/.auth/admin-${index}.json`),
|
|
53
52
|
},
|
|
54
53
|
});
|
|
55
54
|
}
|
|
56
55
|
|
|
57
56
|
exports.pTest = async (options) => {
|
|
57
|
+
const dir = resolve(process.cwd(), 'storage/e2e');
|
|
58
|
+
|
|
59
|
+
if (!fs.existsSync(dir)) {
|
|
60
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
61
|
+
}
|
|
62
|
+
|
|
58
63
|
const files = glob.sync('packages/**/__e2e__/**/*.test.ts', {
|
|
59
64
|
root: process.cwd(),
|
|
60
65
|
});
|
|
61
66
|
|
|
62
|
-
const commands = splitArrayIntoParts(files, options.concurrency ||
|
|
67
|
+
const commands = splitArrayIntoParts(_.shuffle(files), options.concurrency || 4).map((v, i) => {
|
|
63
68
|
return () => runApp(v.join(' '), i);
|
|
64
69
|
});
|
|
65
70
|
|
|
66
|
-
await pAll(commands, { concurrency:
|
|
71
|
+
await pAll(commands, { concurrency: 4, stopOnError: false, ...options });
|
|
67
72
|
};
|
|
68
73
|
|
|
69
74
|
function splitArrayIntoParts(array, parts) {
|
|
@@ -3,7 +3,7 @@ const { run, isDev, isPackageValid, generatePlaywrightPath } = require('../util'
|
|
|
3
3
|
const { resolve } = require('path');
|
|
4
4
|
const { existsSync } = require('fs');
|
|
5
5
|
const { readFile, writeFile } = require('fs').promises;
|
|
6
|
-
const { createStoragePluginsSymlink } = require('@nocobase/utils/plugin-symlink');
|
|
6
|
+
const { createStoragePluginsSymlink, createDevPluginsSymlink } = require('@nocobase/utils/plugin-symlink');
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @param {Command} cli
|
|
@@ -13,12 +13,14 @@ module.exports = (cli) => {
|
|
|
13
13
|
cli
|
|
14
14
|
.command('postinstall')
|
|
15
15
|
.allowUnknownOption()
|
|
16
|
-
.
|
|
16
|
+
.option('--skip-umi')
|
|
17
|
+
.action(async (options) => {
|
|
17
18
|
generatePlaywrightPath(true);
|
|
18
19
|
await createStoragePluginsSymlink();
|
|
19
20
|
if (!isDev()) {
|
|
20
21
|
return;
|
|
21
22
|
}
|
|
23
|
+
await createDevPluginsSymlink();
|
|
22
24
|
const cwd = process.cwd();
|
|
23
25
|
if (!existsSync(resolve(cwd, '.env')) && existsSync(resolve(cwd, '.env.example'))) {
|
|
24
26
|
const content = await readFile(resolve(cwd, '.env.example'), 'utf-8');
|
|
@@ -31,11 +33,13 @@ module.exports = (cli) => {
|
|
|
31
33
|
if (!isPackageValid('umi')) {
|
|
32
34
|
return;
|
|
33
35
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
if (!options.skipUmi) {
|
|
37
|
+
run('umi', ['generate', 'tmp'], {
|
|
38
|
+
stdio: 'pipe',
|
|
39
|
+
env: {
|
|
40
|
+
APP_ROOT: `${APP_PACKAGE_ROOT}/client`,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
}
|
|
40
44
|
});
|
|
41
45
|
};
|
package/src/commands/test.js
CHANGED
|
@@ -36,26 +36,26 @@ function addTestCommand(name, cli) {
|
|
|
36
36
|
if (!opts.watch && !opts.run) {
|
|
37
37
|
process.argv.push('--run');
|
|
38
38
|
}
|
|
39
|
+
const first = paths?.[0];
|
|
40
|
+
if (!process.env.TEST_ENV && first) {
|
|
41
|
+
const key = first.split(path.sep).join('/');
|
|
42
|
+
if (key.includes('/client/')) {
|
|
43
|
+
process.env.TEST_ENV = 'client-side';
|
|
44
|
+
} else {
|
|
45
|
+
process.env.TEST_ENV = 'server-side';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
39
48
|
if (process.env.TEST_ENV === 'server-side' && opts.singleThread !== 'false') {
|
|
40
49
|
process.argv.push('--poolOptions.threads.singleThread=true');
|
|
41
50
|
}
|
|
42
51
|
if (opts.singleThread === 'false') {
|
|
43
52
|
process.argv.splice(process.argv.indexOf('--single-thread=false'), 1);
|
|
44
53
|
}
|
|
45
|
-
const cliArgs = ['--max_old_space_size=
|
|
54
|
+
const cliArgs = ['--max_old_space_size=14096', './node_modules/.bin/vitest', ...process.argv.slice(3)];
|
|
46
55
|
if (process.argv.includes('-h') || process.argv.includes('--help')) {
|
|
47
56
|
await run('node', cliArgs);
|
|
48
57
|
return;
|
|
49
58
|
}
|
|
50
|
-
const first = paths?.[0];
|
|
51
|
-
if (!process.env.TEST_ENV && first) {
|
|
52
|
-
const key = first.split(path.sep).join('/');
|
|
53
|
-
if (key.includes('/client/')) {
|
|
54
|
-
process.env.TEST_ENV = 'client-side';
|
|
55
|
-
} else {
|
|
56
|
-
process.env.TEST_ENV = 'server-side';
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
59
|
if (process.env.TEST_ENV) {
|
|
60
60
|
console.log('process.env.TEST_ENV', process.env.TEST_ENV, cliArgs);
|
|
61
61
|
await run('node', cliArgs);
|
package/src/plugin-generator.js
CHANGED
|
@@ -29,9 +29,10 @@ async function getProjectVersion() {
|
|
|
29
29
|
|
|
30
30
|
class PluginGenerator extends Generator {
|
|
31
31
|
constructor(options) {
|
|
32
|
-
const { context = {}, ...opts } = options;
|
|
32
|
+
const { log, context = {}, ...opts } = options;
|
|
33
33
|
super(opts);
|
|
34
34
|
this.context = context;
|
|
35
|
+
this.log = log || console.log;
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
async getContext() {
|
|
@@ -51,20 +52,19 @@ class PluginGenerator extends Generator {
|
|
|
51
52
|
const { name } = this.context;
|
|
52
53
|
const target = resolve(process.cwd(), 'packages/plugins/', name);
|
|
53
54
|
if (existsSync(target)) {
|
|
54
|
-
|
|
55
|
+
this.log(chalk.red(`[${name}] plugin already exists.`));
|
|
55
56
|
return;
|
|
56
57
|
}
|
|
57
|
-
|
|
58
|
+
this.log('Creating plugin');
|
|
58
59
|
this.copyDirectory({
|
|
59
60
|
target,
|
|
60
61
|
context: await this.getContext(),
|
|
61
62
|
path: join(__dirname, '../templates/plugin'),
|
|
62
63
|
});
|
|
63
|
-
|
|
64
|
+
this.log('');
|
|
64
65
|
genTsConfigPaths();
|
|
65
|
-
execa.sync('yarn', ['
|
|
66
|
-
|
|
67
|
-
console.log(`The plugin folder is in ${chalk.green(`packages/plugins/${name}`)}`);
|
|
66
|
+
execa.sync('yarn', ['postinstall', '--skip-umi'], { shell: true, stdio: 'inherit' });
|
|
67
|
+
this.log(`The plugin folder is in ${chalk.green(`packages/plugins/${name}`)}`);
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
package/src/util.js
CHANGED
|
@@ -245,6 +245,18 @@ function generatePlaywrightPath(clean = false) {
|
|
|
245
245
|
|
|
246
246
|
exports.generatePlaywrightPath = generatePlaywrightPath;
|
|
247
247
|
|
|
248
|
+
function parseEnv(name) {
|
|
249
|
+
if (name === 'DB_UNDERSCORED') {
|
|
250
|
+
if (process.env.DB_UNDERSCORED === 'true') {
|
|
251
|
+
return 'true';
|
|
252
|
+
}
|
|
253
|
+
if (process.env.DB_UNDERSCORED) {
|
|
254
|
+
return 'true';
|
|
255
|
+
}
|
|
256
|
+
return 'false';
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
248
260
|
exports.initEnv = function initEnv() {
|
|
249
261
|
const env = {
|
|
250
262
|
APP_ENV: 'development',
|
|
@@ -254,15 +266,21 @@ exports.initEnv = function initEnv() {
|
|
|
254
266
|
DB_DIALECT: 'sqlite',
|
|
255
267
|
DB_STORAGE: 'storage/db/nocobase.sqlite',
|
|
256
268
|
DB_TIMEZONE: '+00:00',
|
|
269
|
+
DB_UNDERSCORED: parseEnv('DB_UNDERSCORED'),
|
|
257
270
|
DEFAULT_STORAGE_TYPE: 'local',
|
|
258
271
|
LOCAL_STORAGE_DEST: 'storage/uploads',
|
|
259
272
|
PLUGIN_STORAGE_PATH: resolve(process.cwd(), 'storage/plugins'),
|
|
260
273
|
MFSU_AD: 'none',
|
|
274
|
+
WS_PATH: '/ws',
|
|
275
|
+
SOCKET_PATH: 'storage/gateway.sock',
|
|
261
276
|
NODE_MODULES_PATH: resolve(process.cwd(), 'node_modules'),
|
|
262
277
|
PM2_HOME: resolve(process.cwd(), './storage/.pm2'),
|
|
263
278
|
PLUGIN_PACKAGE_PREFIX: '@nocobase/plugin-,@nocobase/plugin-sample-,@nocobase/preset-',
|
|
264
279
|
SERVER_TSCONFIG_PATH: './tsconfig.server.json',
|
|
265
280
|
PLAYWRIGHT_AUTH_FILE: resolve(process.cwd(), 'storage/playwright/.auth/admin.json'),
|
|
281
|
+
CACHE_DEFAULT_STORE: 'memory',
|
|
282
|
+
CACHE_MEMORY_MAX: 2000,
|
|
283
|
+
LOGGER_BASE_PATH: 'storage/logs',
|
|
266
284
|
};
|
|
267
285
|
|
|
268
286
|
if (
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Plugin } from '@nocobase/server';
|
|
2
2
|
|
|
3
3
|
export class {{{pascalCaseName}}}Server extends Plugin {
|
|
4
|
-
afterAdd() {}
|
|
4
|
+
async afterAdd() {}
|
|
5
5
|
|
|
6
|
-
beforeLoad() {}
|
|
6
|
+
async beforeLoad() {}
|
|
7
7
|
|
|
8
8
|
async load() {}
|
|
9
9
|
|
|
10
|
-
async install(
|
|
10
|
+
async install() {}
|
|
11
11
|
|
|
12
12
|
async afterEnable() {}
|
|
13
13
|
|