@nocobase/cli 0.17.0-alpha.7 → 0.18.0-alpha.1

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/bin/index.js CHANGED
@@ -1,85 +1,30 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const dotenv = require('dotenv');
4
- const { resolve } = require('path');
5
- const fs = require('fs');
6
3
  const chalk = require('chalk');
7
- const { genTsConfigPaths } = require('../src/util');
8
-
9
- const env = {
10
- APP_ENV: 'development',
11
- APP_KEY: 'test-jwt-secret',
12
- APP_PORT: 13000,
13
- API_BASE_PATH: '/api/',
14
- DB_DIALECT: 'sqlite',
15
- DB_STORAGE: 'storage/db/nocobase.sqlite',
16
- DB_TIMEZONE: '+00:00',
17
- DEFAULT_STORAGE_TYPE: 'local',
18
- LOCAL_STORAGE_DEST: 'storage/uploads',
19
- PLUGIN_STORAGE_PATH: resolve(process.cwd(), 'storage/plugins'),
20
- MFSU_AD: 'none',
21
- NODE_MODULES_PATH: resolve(process.cwd(), 'node_modules'),
22
- PM2_HOME: resolve(process.cwd(), './storage/.pm2'),
23
- PLUGIN_PACKAGE_PREFIX: '@nocobase/plugin-,@nocobase/plugin-sample-,@nocobase/preset-',
24
- SERVER_TSCONFIG_PATH: './tsconfig.server.json',
25
- };
26
-
27
- if (!process.env.APP_ENV_PATH && process.argv[2] && process.argv[2] === 'test') {
28
- if (fs.existsSync(resolve(process.cwd(), '.env.test'))) {
29
- process.env.APP_ENV_PATH = '.env.test';
30
- }
31
- }
32
-
33
- if (process.argv[2] === 'e2e') {
34
- // 用于存放 playwright 自动生成的相关的文件
35
- if (!fs.existsSync('playwright')) {
36
- fs.mkdirSync('playwright');
37
- }
38
- if (!fs.existsSync('.env.e2e') && fs.existsSync('.env.e2e.example')) {
39
- const env = fs.readFileSync('.env.e2e.example');
40
- fs.writeFileSync('.env.e2e', env);
41
- }
42
- if (!fs.existsSync('.env.e2e')) {
43
- throw new Error('Please create .env.e2e file first!');
44
- }
45
- process.env.APP_ENV_PATH = '.env.e2e';
46
- }
4
+ const { initEnv, genTsConfigPaths } = require('../src/util');
47
5
 
6
+ initEnv();
48
7
  genTsConfigPaths();
49
8
 
50
- dotenv.config({
51
- path: resolve(process.cwd(), process.env.APP_ENV_PATH || '.env'),
52
- });
53
-
54
- for (const key in env) {
55
- if (!process.env[key]) {
56
- process.env[key] = env[key];
57
- }
58
- }
59
-
60
- if (process.argv[2] === 'e2e' && !process.env.APP_BASE_URL) {
61
- process.env.APP_BASE_URL = `http://127.0.0.1:${process.env.APP_PORT}`;
62
- }
63
-
64
9
  if (require('semver').satisfies(process.version, '<16')) {
65
10
  console.error(chalk.red('[nocobase cli]: Node.js version must be >= 16'));
66
11
  process.exit(1);
67
12
  }
68
13
 
69
- if (require('semver').satisfies(process.version, '>16') && !process.env.UNSET_NODE_OPTIONS) {
70
- if (process.env.NODE_OPTIONS) {
71
- let opts = process.env.NODE_OPTIONS;
72
- if (!opts.includes('--openssl-legacy-provider')) {
73
- opts = opts + ' --openssl-legacy-provider';
74
- }
75
- if (!opts.includes('--no-experimental-fetch')) {
76
- opts = opts + ' --no-experimental-fetch';
77
- }
78
- process.env.NODE_OPTIONS = opts;
79
- } else {
80
- process.env.NODE_OPTIONS = '--openssl-legacy-provider --no-experimental-fetch';
81
- }
82
- }
14
+ // if (require('semver').satisfies(process.version, '>16') && !process.env.UNSET_NODE_OPTIONS) {
15
+ // if (process.env.NODE_OPTIONS) {
16
+ // let opts = process.env.NODE_OPTIONS;
17
+ // if (!opts.includes('--openssl-legacy-provider')) {
18
+ // opts = opts + ' --openssl-legacy-provider';
19
+ // }
20
+ // if (!opts.includes('--no-experimental-fetch')) {
21
+ // opts = opts + ' --no-experimental-fetch';
22
+ // }
23
+ // process.env.NODE_OPTIONS = opts;
24
+ // } else {
25
+ // process.env.NODE_OPTIONS = '--openssl-legacy-provider --no-experimental-fetch';
26
+ // }
27
+ // }
83
28
 
84
29
  const cli = require('../src/cli');
85
30
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/cli",
3
- "version": "0.17.0-alpha.7",
3
+ "version": "0.18.0-alpha.1",
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.17.0-alpha.7",
11
+ "@nocobase/app": "0.18.0-alpha.1",
12
12
  "@types/fs-extra": "^11.0.1",
13
13
  "@umijs/utils": "3.5.20",
14
14
  "chalk": "^4.1.1",
@@ -23,12 +23,12 @@
23
23
  "tsx": "^4.6.2"
24
24
  },
25
25
  "devDependencies": {
26
- "@nocobase/devtools": "0.17.0-alpha.7"
26
+ "@nocobase/devtools": "0.18.0-alpha.1"
27
27
  },
28
28
  "repository": {
29
29
  "type": "git",
30
30
  "url": "git+https://github.com/nocobase/nocobase.git",
31
31
  "directory": "packages/core/cli"
32
32
  },
33
- "gitHead": "91377a3abd1124f79fb3819f2d0e80905e091a32"
33
+ "gitHead": "0f5f1c0a37dc397a9dc4c8eec0c4ec20fd8107b0"
34
34
  }
@@ -96,13 +96,13 @@ const commonConfig = {
96
96
  const runCodegenSync = () => {
97
97
  try {
98
98
  execSync(
99
- `npx playwright codegen --load-storage=playwright/.auth/codegen.auth.json ${process.env.APP_BASE_URL} --save-storage=playwright/.auth/codegen.auth.json`,
99
+ `npx playwright codegen --load-storage=storage/playwright/.auth/codegen.auth.json ${process.env.APP_BASE_URL} --save-storage=storage/playwright/.auth/codegen.auth.json`,
100
100
  commonConfig,
101
101
  );
102
102
  } catch (err) {
103
103
  if (err.message.includes('auth.json')) {
104
104
  execSync(
105
- `npx playwright codegen ${process.env.APP_BASE_URL} --save-storage=playwright/.auth/codegen.auth.json`,
105
+ `npx playwright codegen ${process.env.APP_BASE_URL} --save-storage=storage/playwright/.auth/codegen.auth.json`,
106
106
  commonConfig,
107
107
  );
108
108
  } else {
@@ -196,4 +196,8 @@ module.exports = (cli) => {
196
196
  e2e.command('reinstall-app').action(async (options) => {
197
197
  await run('nocobase', ['install', '-f'], options);
198
198
  });
199
+
200
+ e2e.command('install-deps').action(async () => {
201
+ await run('npx', ['playwright', 'install', '--with-deps']);
202
+ });
199
203
  };
@@ -12,10 +12,10 @@ module.exports = (cli) => {
12
12
  require('./tar')(cli);
13
13
  require('./dev')(cli);
14
14
  require('./start')(cli);
15
- require('./test')(cli);
16
15
  require('./e2e')(cli);
17
16
  require('./clean')(cli);
18
17
  require('./doc')(cli);
18
+ require('./test')(cli);
19
19
  require('./umi')(cli);
20
20
  require('./upgrade')(cli);
21
21
  require('./postinstall')(cli);
@@ -1,5 +1,5 @@
1
1
  const { Command } = require('commander');
2
- const { run, isDev, isPackageValid } = require('../util');
2
+ 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;
@@ -14,6 +14,7 @@ module.exports = (cli) => {
14
14
  .command('postinstall')
15
15
  .allowUnknownOption()
16
16
  .action(async () => {
17
+ generatePlaywrightPath(true);
17
18
  await createStoragePluginsSymlink();
18
19
  if (!isDev()) {
19
20
  return;
@@ -1,30 +1,87 @@
1
1
  const { Command } = require('commander');
2
- const { nodeCheck, runAppCommand, promptForTs, genTsConfigPaths } = require('../util');
2
+ const { run } = require('../util');
3
+ const path = require('path');
3
4
 
4
5
  /**
5
6
  *
7
+ * @param {String} name
6
8
  * @param {Command} cli
7
9
  */
8
- module.exports = (cli) => {
9
- cli
10
- .command('test')
11
- .option('-c, --db-clean')
10
+ function addTestCommand(name, cli) {
11
+ return cli
12
+ .command(name)
13
+ .option('-w, --watch')
14
+ .option('--run')
15
+ .option('--allowOnly')
16
+ .option('--bail')
17
+ .option('-h, --help')
18
+ .option('--single-thread [singleThread]')
19
+ .arguments('[paths...]')
12
20
  .allowUnknownOption()
13
- .action(async (options) => {
14
- nodeCheck();
15
- if (options.dbClean) {
16
- promptForTs();
17
- await runAppCommand('db:clean', ['-y']);
18
- }
19
- let index = process.argv.indexOf('-c');
20
- if (index > 0) {
21
- process.argv.splice(index, 1);
22
- }
23
- index = process.argv.indexOf('--db-clean');
24
- if (index > 0) {
25
- process.argv.splice(index, 1);
26
- }
27
- process.argv.splice(2, 1, '-i');
28
- require('jest-cli/bin/jest');
21
+ .action(async (paths, opts) => {
22
+ if (name === 'test:server') {
23
+ process.env.TEST_ENV = 'server-side';
24
+ } else if (name === 'test:client') {
25
+ process.env.TEST_ENV = 'client-side';
26
+ }
27
+ if (opts.server) {
28
+ process.env.TEST_ENV = 'server-side';
29
+ process.argv.splice(process.argv.indexOf('--server'), 1);
30
+ }
31
+ if (opts.client) {
32
+ process.env.TEST_ENV = 'client-side';
33
+ process.argv.splice(process.argv.indexOf('--client'), 1);
34
+ }
35
+ process.env.NODE_ENV = 'test';
36
+ if (!opts.watch && !opts.run) {
37
+ process.argv.push('--run');
38
+ }
39
+ if (process.env.TEST_ENV === 'server-side' && opts.singleThread !== 'false') {
40
+ process.argv.push('--poolOptions.threads.singleThread=true');
41
+ }
42
+ if (opts.singleThread === 'false') {
43
+ process.argv.splice(process.argv.indexOf('--single-thread=false'), 1);
44
+ }
45
+ const cliArgs = ['--max_old_space_size=4096', './node_modules/.bin/vitest', ...process.argv.slice(3)];
46
+ if (process.argv.includes('-h') || process.argv.includes('--help')) {
47
+ await run('node', cliArgs);
48
+ return;
49
+ }
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
+ if (process.env.TEST_ENV) {
60
+ console.log('process.env.TEST_ENV', process.env.TEST_ENV, cliArgs);
61
+ await run('node', cliArgs);
62
+ } else {
63
+ await Promise.all([
64
+ run('node', cliArgs, {
65
+ env: {
66
+ TEST_ENV: 'client-side',
67
+ },
68
+ }),
69
+ run('node', cliArgs, {
70
+ env: {
71
+ TEST_ENV: 'server-side',
72
+ },
73
+ }),
74
+ ]);
75
+ }
29
76
  });
77
+ }
78
+
79
+ /**
80
+ *
81
+ * @param {Command} cli
82
+ */
83
+ module.exports = (cli) => {
84
+ addTestCommand('test:server', cli);
85
+ addTestCommand('test:client', cli);
86
+ addTestCommand('test', cli).option('--client').option('--server');
30
87
  };
package/src/util.js CHANGED
@@ -5,10 +5,12 @@ const fg = require('fast-glob');
5
5
  const { dirname, join, resolve, sep } = require('path');
6
6
  const { readFile, writeFile } = require('fs').promises;
7
7
  const { existsSync, mkdirSync, cpSync, writeFileSync } = require('fs');
8
+ const dotenv = require('dotenv');
9
+ const fs = require('fs');
8
10
 
9
- exports.isPackageValid = (package) => {
11
+ exports.isPackageValid = (pkg) => {
10
12
  try {
11
- require.resolve(package);
13
+ require.resolve(pkg);
12
14
  return true;
13
15
  } catch (error) {
14
16
  return false;
@@ -177,6 +179,17 @@ exports.generateAppDir = function generateAppDir() {
177
179
  };
178
180
 
179
181
  exports.genTsConfigPaths = function genTsConfigPaths() {
182
+ try {
183
+ fs.unlinkSync(resolve(process.cwd(), 'node_modules/.bin/tsx'));
184
+ fs.symlinkSync(
185
+ resolve(process.cwd(), 'node_modules/tsx/dist/cli.mjs'),
186
+ resolve(process.cwd(), 'node_modules/.bin/tsx'),
187
+ 'file',
188
+ );
189
+ } catch (error) {
190
+ //
191
+ }
192
+
180
193
  const cwd = process.cwd();
181
194
  const cwdLength = cwd.length;
182
195
  const paths = {
@@ -193,8 +206,13 @@ exports.genTsConfigPaths = function genTsConfigPaths() {
193
206
  .slice(cwdLength + 1)
194
207
  .split(sep)
195
208
  .join('/');
196
- paths[packageJsonName] = [`${relativePath}/src`];
197
209
  paths[`${packageJsonName}/client`] = [`${relativePath}/src/client`];
210
+ paths[`${packageJsonName}/package.json`] = [`${relativePath}/package.json`];
211
+ paths[packageJsonName] = [`${relativePath}/src`];
212
+ if (packageJsonName === '@nocobase/test') {
213
+ paths[`${packageJsonName}/server`] = [`${relativePath}/src/server`];
214
+ paths[`${packageJsonName}/e2e`] = [`${relativePath}/src/e2e`];
215
+ }
198
216
  });
199
217
 
200
218
  const tsConfigJsonPath = join(cwd, './tsconfig.paths.json');
@@ -202,3 +220,78 @@ exports.genTsConfigPaths = function genTsConfigPaths() {
202
220
  writeFileSync(tsConfigJsonPath, JSON.stringify(content, null, 2), 'utf-8');
203
221
  return content;
204
222
  };
223
+
224
+ function generatePlaywrightPath(clean = false) {
225
+ try {
226
+ const playwright = resolve(process.cwd(), 'storage/playwright/tests');
227
+ if (clean && fs.existsSync(playwright)) {
228
+ fs.rmSync(dirname(playwright), { force: true, recursive: true });
229
+ }
230
+ if (!fs.existsSync(playwright)) {
231
+ const testPkg = require.resolve('@nocobase/test/package.json');
232
+ fs.cpSync(resolve(dirname(testPkg), 'playwright/tests'), playwright, { recursive: true });
233
+ }
234
+ } catch (error) {
235
+ // empty
236
+ }
237
+ }
238
+
239
+ exports.generatePlaywrightPath = generatePlaywrightPath;
240
+
241
+ exports.initEnv = function initEnv() {
242
+ const env = {
243
+ APP_ENV: 'development',
244
+ APP_KEY: 'test-jwt-secret',
245
+ APP_PORT: 13000,
246
+ API_BASE_PATH: '/api/',
247
+ DB_DIALECT: 'sqlite',
248
+ DB_STORAGE: 'storage/db/nocobase.sqlite',
249
+ DB_TIMEZONE: '+00:00',
250
+ DEFAULT_STORAGE_TYPE: 'local',
251
+ LOCAL_STORAGE_DEST: 'storage/uploads',
252
+ PLUGIN_STORAGE_PATH: resolve(process.cwd(), 'storage/plugins'),
253
+ MFSU_AD: 'none',
254
+ NODE_MODULES_PATH: resolve(process.cwd(), 'node_modules'),
255
+ PM2_HOME: resolve(process.cwd(), './storage/.pm2'),
256
+ PLUGIN_PACKAGE_PREFIX: '@nocobase/plugin-,@nocobase/plugin-sample-,@nocobase/preset-',
257
+ SERVER_TSCONFIG_PATH: './tsconfig.server.json',
258
+ PLAYWRIGHT_AUTH_FILE: resolve(process.cwd(), 'storage/playwright/.auth/admin.json'),
259
+ };
260
+
261
+ if (
262
+ !process.env.APP_ENV_PATH &&
263
+ process.argv[2] &&
264
+ ['test', 'test:client', 'test:server'].includes(process.argv[2])
265
+ ) {
266
+ if (fs.existsSync(resolve(process.cwd(), '.env.test'))) {
267
+ process.env.APP_ENV_PATH = '.env.test';
268
+ }
269
+ }
270
+
271
+ if (process.argv[2] === 'e2e') {
272
+ // 用于存放 playwright 自动生成的相关的文件
273
+ generatePlaywrightPath();
274
+ if (!fs.existsSync('.env.e2e') && fs.existsSync('.env.e2e.example')) {
275
+ const env = fs.readFileSync('.env.e2e.example');
276
+ fs.writeFileSync('.env.e2e', env);
277
+ }
278
+ if (!fs.existsSync('.env.e2e')) {
279
+ throw new Error('Please create .env.e2e file first!');
280
+ }
281
+ process.env.APP_ENV_PATH = '.env.e2e';
282
+ }
283
+
284
+ dotenv.config({
285
+ path: resolve(process.cwd(), process.env.APP_ENV_PATH || '.env'),
286
+ });
287
+
288
+ if (process.argv[2] === 'e2e' && !process.env.APP_BASE_URL) {
289
+ process.env.APP_BASE_URL = `http://127.0.0.1:${process.env.APP_PORT}`;
290
+ }
291
+
292
+ for (const key in env) {
293
+ if (!process.env[key]) {
294
+ process.env[key] = env[key];
295
+ }
296
+ }
297
+ };