@nocobase/cli 1.8.0-beta.9 → 1.9.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/cli",
3
- "version": "1.8.0-beta.9",
3
+ "version": "1.9.0-alpha.1",
4
4
  "description": "",
5
5
  "license": "AGPL-3.0",
6
6
  "main": "./src/index.js",
@@ -8,7 +8,8 @@
8
8
  "nocobase": "./bin/index.js"
9
9
  },
10
10
  "dependencies": {
11
- "@nocobase/app": "1.8.0-beta.9",
11
+ "@nocobase/app": "1.9.0-alpha.1",
12
+ "@nocobase/license-kit": "^0.2.3",
12
13
  "@types/fs-extra": "^11.0.1",
13
14
  "@umijs/utils": "3.5.20",
14
15
  "chalk": "^4.1.1",
@@ -26,12 +27,12 @@
26
27
  "tsx": "^4.19.0"
27
28
  },
28
29
  "devDependencies": {
29
- "@nocobase/devtools": "1.8.0-beta.9"
30
+ "@nocobase/devtools": "1.9.0-alpha.1"
30
31
  },
31
32
  "repository": {
32
33
  "type": "git",
33
34
  "url": "git+https://github.com/nocobase/nocobase.git",
34
35
  "directory": "packages/core/cli"
35
36
  },
36
- "gitHead": "a3449d646c72965845f8c52e52fff9dba759c564"
37
+ "gitHead": "71ebde8a27da3c5c4d64194571804eeab6e95ce0"
37
38
  }
@@ -35,6 +35,8 @@ module.exports = (cli) => {
35
35
  require('./upgrade')(cli);
36
36
  require('./postinstall')(cli);
37
37
  require('./pkg')(cli);
38
+ require('./instance-id')(cli);
39
+ require('./view-license-key')(cli);
38
40
  if (isPackageValid('@umijs/utils')) {
39
41
  require('./create-plugin')(cli);
40
42
  }
@@ -0,0 +1,46 @@
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
+ const { getInstanceIdAsync } = require('@nocobase/license-kit');
14
+ const path = require('path');
15
+ const fs = require('fs');
16
+
17
+ /**
18
+ *
19
+ * @param {Command} cli
20
+ */
21
+ module.exports = (cli) => {
22
+ cli
23
+ .command('generate-instance-id')
24
+ .description('Generate InstanceID')
25
+ .option('--force', 'Force generate InstanceID')
26
+ .action(async (options) => {
27
+ console.log('Generating InstanceID...');
28
+ const dir = path.resolve(process.cwd(), 'storage/.license');
29
+ const filePath = path.resolve(dir, 'instance-id');
30
+ if (fs.existsSync(filePath) && !options.force) {
31
+ console.log('InstanceID already exists at ' + filePath);
32
+ return;
33
+ } else {
34
+ if (!fs.existsSync(dir)) {
35
+ fs.mkdirSync(dir, { recursive: true });
36
+ }
37
+ try {
38
+ const instanceId = await getInstanceIdAsync();
39
+ fs.writeFileSync(filePath, instanceId + '\n');
40
+ console.log(chalk.greenBright(`InstanceID saved to ${filePath}`));
41
+ } catch (e) {
42
+ console.log(e);
43
+ }
44
+ }
45
+ });
46
+ };
@@ -15,6 +15,7 @@ const tar = require('tar');
15
15
  const path = require('path');
16
16
  const { createStoragePluginsSymlink } = require('@nocobase/utils/plugin-symlink');
17
17
  const chalk = require('chalk');
18
+ const { getAccessKeyPair, showLicenseInfo, LicenseKeyError } = require('../util');
18
19
 
19
20
  class Package {
20
21
  data;
@@ -142,6 +143,17 @@ class Package {
142
143
  });
143
144
  console.log(chalk.greenBright(`Downloaded: ${this.packageName}@${version}`));
144
145
  } catch (error) {
146
+ if (error?.response?.data && typeof error?.response?.data?.pipe === 'function') {
147
+ let errorMessageBuffer = '';
148
+ error.response.data.on?.('data', (chunk) => {
149
+ errorMessageBuffer += chunk.toString('utf8'); // 收集错误信息
150
+ });
151
+ error.response.data.on?.('end', () => {
152
+ if (error.response.status === 403) {
153
+ console.error(chalk.redBright('You do not have permission to download this package version.'));
154
+ }
155
+ });
156
+ }
145
157
  console.log(chalk.redBright(`Download failed: ${this.packageName}`));
146
158
  }
147
159
  }
@@ -174,6 +186,9 @@ class PackageManager {
174
186
  });
175
187
  this.token = res1.data.token;
176
188
  } catch (error) {
189
+ if (error?.response?.data?.error === 'license not valid') {
190
+ showLicenseInfo(LicenseKeyError.notValid);
191
+ }
177
192
  console.error(chalk.redBright(`Login failed: ${this.baseURL}`));
178
193
  }
179
194
  }
@@ -248,10 +263,19 @@ module.exports = (cli) => {
248
263
  NOCOBASE_PKG_USERNAME,
249
264
  NOCOBASE_PKG_PASSWORD,
250
265
  } = process.env;
251
- if (!(NOCOBASE_PKG_USERNAME && NOCOBASE_PKG_PASSWORD)) {
266
+ let accessKeyId;
267
+ let accessKeySecret;
268
+ try {
269
+ ({ accessKeyId, accessKeySecret } = await getAccessKeyPair());
270
+ } catch (e) {
271
+ return;
272
+ }
273
+ if (!(NOCOBASE_PKG_USERNAME && NOCOBASE_PKG_PASSWORD) && !(accessKeyId && accessKeySecret)) {
252
274
  return;
253
275
  }
254
- const credentials = { username: NOCOBASE_PKG_USERNAME, password: NOCOBASE_PKG_PASSWORD };
276
+ const credentials = accessKeyId
277
+ ? { username: accessKeyId, password: accessKeySecret }
278
+ : { username: NOCOBASE_PKG_USERNAME, password: NOCOBASE_PKG_PASSWORD };
255
279
  const pm = new PackageManager({ baseURL: NOCOBASE_PKG_URL });
256
280
  await pm.login(credentials);
257
281
  const file = path.resolve(__dirname, '../../package.json');
@@ -0,0 +1,44 @@
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 { keyDecrypt } = require('@nocobase/license-kit');
13
+ const path = require('path');
14
+ const fs = require('fs');
15
+
16
+ /**
17
+ *
18
+ * @param {Command} cli
19
+ */
20
+ module.exports = (cli) => {
21
+ cli
22
+ .command('view-license-key')
23
+ .description('View License Key')
24
+ .action(async (options) => {
25
+ const dir = path.resolve(process.cwd(), 'storage/.license');
26
+ const filePath = path.resolve(dir, 'license-key');
27
+ if (!fs.existsSync(filePath)) {
28
+ console.log('License key not found at ' + filePath);
29
+ return;
30
+ }
31
+ const key = fs.readFileSync(filePath, 'utf-8');
32
+ let keyDataStr;
33
+ try {
34
+ keyDataStr = keyDecrypt(key);
35
+ } catch (e) {
36
+ console.log('License key decrypt failed', e);
37
+ return;
38
+ }
39
+ const keyData = JSON.parse(keyDataStr);
40
+ const { accessKeyId, accessKeySecret } = keyData;
41
+ console.log(chalk.greenBright(`Access Key ID: ${accessKeyId}`));
42
+ console.log(chalk.greenBright(`Access Key Secret: ${accessKeySecret}`));
43
+ });
44
+ };
package/src/util.js CHANGED
@@ -18,6 +18,8 @@ const dotenv = require('dotenv');
18
18
  const fs = require('fs-extra');
19
19
  const os = require('os');
20
20
  const moment = require('moment-timezone');
21
+ const { keyDecrypt, getEnvAsync } = require('@nocobase/license-kit');
22
+ const omit = require('lodash/omit');
21
23
 
22
24
  exports.isPackageValid = (pkg) => {
23
25
  try {
@@ -114,7 +116,7 @@ exports.postCheck = async (opts) => {
114
116
  const port = opts.port || process.env.APP_PORT;
115
117
  const result = await exports.isPortReachable(port);
116
118
  if (result) {
117
- console.error(chalk.red(`post already in use ${port}`));
119
+ console.error(chalk.red(`Port ${port} already in use`));
118
120
  process.exit(1);
119
121
  }
120
122
  };
@@ -165,10 +167,11 @@ exports.promptForTs = () => {
165
167
  };
166
168
 
167
169
  exports.downloadPro = async () => {
168
- const { NOCOBASE_PKG_USERNAME, NOCOBASE_PKG_PASSWORD } = process.env;
169
- if (!(NOCOBASE_PKG_USERNAME && NOCOBASE_PKG_PASSWORD)) {
170
- return;
171
- }
170
+ // 此处不再判定,由pkgg命令处理
171
+ // const { NOCOBASE_PKG_USERNAME, NOCOBASE_PKG_PASSWORD } = process.env;
172
+ // if (!(NOCOBASE_PKG_USERNAME && NOCOBASE_PKG_PASSWORD)) {
173
+ // return;
174
+ // }
172
175
  await exports.run('yarn', ['nocobase', 'pkg', 'download-pro']);
173
176
  };
174
177
 
@@ -487,3 +490,86 @@ exports.generatePlugins = function () {
487
490
  return;
488
491
  }
489
492
  };
493
+
494
+ async function isEnvMatch(keyData) {
495
+ const env = await getEnvAsync();
496
+ if (env?.container?.id && keyData?.instanceData?.container?.id) {
497
+ return (
498
+ JSON.stringify(omit(env, ['timestamp', 'container', 'hostname'])) ===
499
+ JSON.stringify(omit(keyData?.instanceData, ['timestamp', 'container', 'hostname']))
500
+ );
501
+ }
502
+ return JSON.stringify(omit(env, ['timestamp'])) === JSON.stringify(omit(keyData?.instanceData, ['timestamp']));
503
+ }
504
+
505
+ exports.getAccessKeyPair = async function () {
506
+ const keyFile = resolve(process.cwd(), 'storage/.license/license-key');
507
+ if (!fs.existsSync(keyFile)) {
508
+ return {};
509
+ }
510
+
511
+ let keyData = {};
512
+ try {
513
+ const str = fs.readFileSync(keyFile, 'utf-8');
514
+ const keyDataStr = keyDecrypt(str);
515
+ keyData = JSON.parse(keyDataStr);
516
+ } catch (error) {
517
+ showLicenseInfo(LicenseKeyError.parseFailed);
518
+ throw new Error(LicenseKeyError.parseFailed.title);
519
+ }
520
+
521
+ const isEnvMatched = await isEnvMatch(keyData);
522
+ if (!isEnvMatched) {
523
+ showLicenseInfo(LicenseKeyError.notMatch);
524
+ throw new Error(LicenseKeyError.notMatch.title);
525
+ }
526
+
527
+ const { accessKeyId, accessKeySecret } = keyData;
528
+ return { accessKeyId, accessKeySecret };
529
+ };
530
+
531
+ const LicenseKeyError = {
532
+ notExist: {
533
+ title: 'License key not found',
534
+ content:
535
+ 'Please go to the license settings page to obtain the Instance ID for the current environment, and then generate the license key on the service platform.',
536
+ },
537
+ parseFailed: {
538
+ title: 'Invalid license key format',
539
+ content: 'Please check your license key, or regenerate the license key on the service platform.',
540
+ },
541
+ notMatch: {
542
+ title: 'License key mismatch',
543
+ content:
544
+ 'Please go to the license settings page to obtain the Instance ID for the current environment, and then regenerate the license key on the service platform.',
545
+ },
546
+ notValid: {
547
+ title: 'Invalid license key',
548
+ content:
549
+ 'Please go to the license settings page to obtain the Instance ID for the current environment, and then regenerate the license key on the service platform.',
550
+ },
551
+ };
552
+
553
+ exports.LicenseKeyError = LicenseKeyError;
554
+
555
+ function showLicenseInfo({ title, content }) {
556
+ const rows = [];
557
+ const length = 80;
558
+ let row = '';
559
+ content.split(' ').forEach((word) => {
560
+ if (row.length + word.length > length) {
561
+ rows.push(row);
562
+ row = '';
563
+ }
564
+ row += word + ' ';
565
+ });
566
+ if (row) {
567
+ rows.push(row);
568
+ }
569
+ console.log(Array(length).fill('-').join(''));
570
+ console.log(chalk.yellow(title));
571
+ console.log(chalk.yellow(rows.join('\n')));
572
+ console.log(Array(length).fill('-').join(''));
573
+ }
574
+
575
+ exports.showLicenseInfo = showLicenseInfo;