@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 +5 -4
- package/src/commands/index.js +2 -0
- package/src/commands/instance-id.js +46 -0
- package/src/commands/pkg.js +26 -2
- package/src/commands/view-license-key.js +44 -0
- package/src/util.js +91 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/cli",
|
|
3
|
-
"version": "1.
|
|
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.
|
|
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.
|
|
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": "
|
|
37
|
+
"gitHead": "71ebde8a27da3c5c4d64194571804eeab6e95ce0"
|
|
37
38
|
}
|
package/src/commands/index.js
CHANGED
|
@@ -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
|
+
};
|
package/src/commands/pkg.js
CHANGED
|
@@ -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
|
-
|
|
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 =
|
|
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(`
|
|
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
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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;
|