@blocklet/cli 1.16.33 → 1.16.34-beta-20241120-080738-bbbe036c
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/README.md +32 -25
- package/bin/blocklet.js +292 -1
- package/config.example.yml +33 -0
- package/lib/arcblock.js +53 -0
- package/lib/commands/blocklet/add.js +124 -0
- package/lib/commands/blocklet/assets/git-ignore +28 -0
- package/lib/commands/blocklet/assets/index.html +9 -0
- package/lib/commands/blocklet/assets/index.js +14 -0
- package/lib/commands/blocklet/assets/logo.png +0 -0
- package/lib/commands/blocklet/bundle/bundle.js +184 -0
- package/lib/commands/blocklet/bundle/bundlers/blocklet.js +138 -0
- package/lib/commands/blocklet/bundle/bundlers/changelog.js +100 -0
- package/lib/commands/blocklet/bundle/bundlers/logo.js +56 -0
- package/lib/commands/blocklet/bundle/bundlers/markdown.js +241 -0
- package/lib/commands/blocklet/bundle/bundlers/preference.js +50 -0
- package/lib/commands/blocklet/bundle/bundlers/readme.js +43 -0
- package/lib/commands/blocklet/bundle/bundlers/screenshots.js +94 -0
- package/lib/commands/blocklet/bundle/bundlers/simple.js +70 -0
- package/lib/commands/blocklet/bundle/compact/bundle-compact-file.js +48 -0
- package/lib/commands/blocklet/bundle/compact/bundle-merge-extra.js +66 -0
- package/lib/commands/blocklet/bundle/compact/default-external.js +5 -0
- package/lib/commands/blocklet/bundle/compact/index.js +88 -0
- package/lib/commands/blocklet/bundle/index.js +139 -0
- package/lib/commands/blocklet/bundle/pack.js +8 -0
- package/lib/commands/blocklet/bundle/parse-external-dependencies.js +97 -0
- package/lib/commands/blocklet/bundle/simple/index.js +62 -0
- package/lib/commands/blocklet/bundle/zip/archive.js +35 -0
- package/lib/commands/blocklet/bundle/zip/dependencies.js +333 -0
- package/lib/commands/blocklet/bundle/zip/index.js +165 -0
- package/lib/commands/blocklet/bundle/zip/main.js +124 -0
- package/lib/commands/blocklet/bundle/zip/node.js +59 -0
- package/lib/commands/blocklet/bundle/zip/resolve.js +93 -0
- package/lib/commands/blocklet/cleanup.js +52 -0
- package/lib/commands/blocklet/config.js +108 -0
- package/lib/commands/blocklet/connect.js +87 -0
- package/lib/commands/blocklet/create.js +38 -0
- package/lib/commands/blocklet/deploy.js +435 -0
- package/lib/commands/blocklet/dev.js +1000 -0
- package/lib/commands/blocklet/document.js +39 -0
- package/lib/commands/blocklet/exec.js +106 -0
- package/lib/commands/blocklet/init.js +300 -0
- package/lib/commands/blocklet/meta.js +22 -0
- package/lib/commands/blocklet/remove.js +35 -0
- package/lib/commands/blocklet/test.js +201 -0
- package/lib/commands/blocklet/upload.js +105 -0
- package/lib/commands/blocklet/version.js +81 -0
- package/lib/commands/server/cleanup.js +32 -0
- package/lib/commands/server/command.js +131 -0
- package/lib/commands/server/info.js +92 -0
- package/lib/commands/server/init.js +433 -0
- package/lib/commands/server/logs.js +99 -0
- package/lib/commands/server/rescue.js +71 -0
- package/lib/commands/server/start.js +821 -0
- package/lib/commands/server/status.js +107 -0
- package/lib/commands/server/stop.js +163 -0
- package/lib/commands/server/upgrade.js +123 -0
- package/lib/constant.js +21 -2
- package/lib/debug.js +20 -0
- package/lib/manager/config.js +122 -0
- package/lib/manager/deploy.js +75 -0
- package/lib/manager/index.js +23 -0
- package/lib/manager/process.js +47 -0
- package/lib/node.js +214 -0
- package/lib/port.js +19 -0
- package/lib/postinstall.js +3 -0
- package/lib/process/daemon.js +196 -0
- package/lib/process/service.js +86 -0
- package/lib/ui.js +137 -0
- package/lib/util/blocklet/config.js +78 -0
- package/lib/util/blocklet/env.js +172 -0
- package/lib/util/blocklet/meta.js +36 -0
- package/lib/util/blocklet/payment.js +88 -0
- package/lib/util/blocklet/sign.js +21 -0
- package/lib/util/blocklet/tar.js +119 -0
- package/lib/util/convert-to-nosources-sourcemap.js +37 -0
- package/lib/util/docker-status-log.js +17 -0
- package/lib/util/exit-when-server-stopped.js +44 -0
- package/lib/util/get-cli-binary-name.js +8 -0
- package/lib/util/get-download-bundle-step.js +36 -0
- package/lib/util/get-service-instance-number.js +12 -0
- package/lib/util/index.js +626 -0
- package/lib/util/print-error.js +11 -0
- package/lib/util/print.js +9 -0
- package/lib/util/what-uri.js +40 -0
- package/package.json +123 -27
- package/lib/run.d.ts +0 -2
- package/lib/run.js +0 -73
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const { BLOCKLET_STORE_URL } = require('@abtnode/constant');
|
|
5
|
+
const debug = require('debug')(require('../../../package.json').name);
|
|
6
|
+
const { upload } = require('@blocklet/store');
|
|
7
|
+
const { joinURL } = require('ufo');
|
|
8
|
+
const { printInfo, printSuccess, printError } = require('../../util');
|
|
9
|
+
const { logTar, getContents } = require('../../util/blocklet/tar');
|
|
10
|
+
const Config = require('../../util/blocklet/config');
|
|
11
|
+
const { wrapSpinner } = require('../../ui');
|
|
12
|
+
|
|
13
|
+
exports.run = async (originalMetaFile, { accessToken, profile }) => {
|
|
14
|
+
const config = new Config({
|
|
15
|
+
configFile: process.env.ABT_NODE_CONFIG_FILE,
|
|
16
|
+
section: profile === 'default' ? '' : profile,
|
|
17
|
+
});
|
|
18
|
+
const developerDoc = 'https://developer.blocklet.io/docs';
|
|
19
|
+
const storeUrl = config.get('store') || config.get('registry') || (profile === 'default' ? BLOCKLET_STORE_URL : '');
|
|
20
|
+
if (!storeUrl) {
|
|
21
|
+
printError('Can not find the store url to upload the blocklet!');
|
|
22
|
+
printInfo(`You can fix with: ${chalk.cyan('blocklet config set store [storeUrl]')}`);
|
|
23
|
+
printInfo(`To learn more: ${chalk.cyan(developerDoc)}`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
printInfo(`Upload using profile ${chalk.cyan(profile)} to store ${chalk.cyan(storeUrl)}`);
|
|
27
|
+
|
|
28
|
+
let metaFile = originalMetaFile;
|
|
29
|
+
if (!metaFile) {
|
|
30
|
+
metaFile = path.join(process.cwd(), '.blocklet', 'release', 'blocklet.json');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!fs.existsSync(metaFile)) {
|
|
34
|
+
printError(`Invalid meta file: '${metaFile}'`);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let realAccessToken = accessToken;
|
|
39
|
+
if (!realAccessToken) {
|
|
40
|
+
realAccessToken = config.get('accessToken');
|
|
41
|
+
debug('read access token from config');
|
|
42
|
+
if (!realAccessToken) {
|
|
43
|
+
// TODO: 添加 accessToken 不存在情况下自动去获取 accessToken 的逻辑
|
|
44
|
+
printError('accessToken is required to upload a blocklet');
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const response = await upload({
|
|
51
|
+
metaFile,
|
|
52
|
+
source: 'CLI',
|
|
53
|
+
accessToken: realAccessToken,
|
|
54
|
+
storeUrl,
|
|
55
|
+
config,
|
|
56
|
+
printInfo,
|
|
57
|
+
printSuccess,
|
|
58
|
+
printTar: async (meta, filePath) => {
|
|
59
|
+
const pkgContents = await getContents(meta, filePath);
|
|
60
|
+
logTar(pkgContents);
|
|
61
|
+
},
|
|
62
|
+
wrapSpinner,
|
|
63
|
+
debug,
|
|
64
|
+
});
|
|
65
|
+
if (response.status === 'published') {
|
|
66
|
+
printSuccess(
|
|
67
|
+
`Blocklet ${chalk.cyan(response.name)} ${chalk.cyan(
|
|
68
|
+
response.version
|
|
69
|
+
)} auto published successfully: ${chalk.cyan(joinURL(storeUrl, '/blocklets', response.did))} !`
|
|
70
|
+
);
|
|
71
|
+
} else {
|
|
72
|
+
printSuccess(
|
|
73
|
+
`Blocklet ${chalk.cyan(response.name)} ${chalk.cyan(response.version)} successfully uploaded to ${chalk.cyan(
|
|
74
|
+
storeUrl
|
|
75
|
+
)}!`
|
|
76
|
+
);
|
|
77
|
+
printInfo(
|
|
78
|
+
`${chalk.cyan('Tips:')} You need to publish the blocklet at ${chalk.cyan(
|
|
79
|
+
joinURL(storeUrl, '/developer/blocklets')
|
|
80
|
+
)} to make it public accessible`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
} catch (err) {
|
|
84
|
+
if (/\[NO-ACCESS\]/.test(err?.message || '')) {
|
|
85
|
+
printInfo(
|
|
86
|
+
`Blocklet store accessToken is used to authorize developers when uploading blocklets, you can generate your own accessToken from ${chalk.cyan(
|
|
87
|
+
storeUrl
|
|
88
|
+
)}`
|
|
89
|
+
);
|
|
90
|
+
printInfo('Please use the following two methods to specify');
|
|
91
|
+
printInfo(`Option 1: Set a access token locally: ${chalk.cyan('blocklet config set accessToken [accessToken]')}`);
|
|
92
|
+
printInfo(
|
|
93
|
+
`Option 2: By specifying the --access-token parameter: ${chalk.cyan(
|
|
94
|
+
'blocklet upload --access-token <access token>'
|
|
95
|
+
)}`
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
printError(err.message);
|
|
99
|
+
printInfo(`To learn more: ${chalk.cyan(developerDoc)}`);
|
|
100
|
+
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
process.exit(0);
|
|
105
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
const semver = require('semver');
|
|
2
|
+
const shell = require('shelljs');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const getBlockletMeta = require('@blocklet/meta/lib/parse');
|
|
5
|
+
const { BLOCKLET_DEFAULT_VERSION, BLOCKLET_LATEST_SPEC_VERSION } = require('@blocklet/constant');
|
|
6
|
+
const { select: getMetaFile, update: updateMetaFile } = require('@blocklet/meta/lib/file');
|
|
7
|
+
|
|
8
|
+
const { printSuccess, printError, printInfo } = require('../../util');
|
|
9
|
+
const debug = require('../../debug')('blocklet:version');
|
|
10
|
+
|
|
11
|
+
// eslint-disable-next-line default-param-last
|
|
12
|
+
exports.run = (newVersion = 'patch', { gitCommit = false, force = false }) => {
|
|
13
|
+
try {
|
|
14
|
+
const dir = process.cwd();
|
|
15
|
+
const file = getMetaFile(dir);
|
|
16
|
+
const meta = getBlockletMeta(dir, { ensureComponentStore: false });
|
|
17
|
+
const currentVersion = semver.clean(meta.version) || BLOCKLET_DEFAULT_VERSION;
|
|
18
|
+
const currentSpecVersion = meta.specVersion;
|
|
19
|
+
|
|
20
|
+
let nextVersion = null;
|
|
21
|
+
if (semver.valid(newVersion, { loose: true })) {
|
|
22
|
+
nextVersion = semver.clean(newVersion, { loose: true });
|
|
23
|
+
} else {
|
|
24
|
+
nextVersion = semver.inc(currentVersion, newVersion);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!nextVersion) {
|
|
28
|
+
printInfo('Failed to determine next version, abort!');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (currentVersion === nextVersion) {
|
|
33
|
+
printInfo('Bumping to same version, skipping');
|
|
34
|
+
process.exit(0);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
meta.version = nextVersion;
|
|
38
|
+
meta.specVersion = BLOCKLET_LATEST_SPEC_VERSION;
|
|
39
|
+
debug('bump blocklet version', { dir, newVersion, currentVersion, nextVersion });
|
|
40
|
+
|
|
41
|
+
if (semver.gt(currentSpecVersion, BLOCKLET_LATEST_SPEC_VERSION)) {
|
|
42
|
+
if (!force) {
|
|
43
|
+
// eslint-disable-next-line max-len
|
|
44
|
+
printError(
|
|
45
|
+
`The new specVersion of blocklet.yml (${chalk.cyan(
|
|
46
|
+
BLOCKLET_LATEST_SPEC_VERSION
|
|
47
|
+
)}) is smaller than the current specVersion (${chalk.cyan(currentSpecVersion)})\n`
|
|
48
|
+
);
|
|
49
|
+
printInfo(
|
|
50
|
+
`Please upgrade the version of the "blocklet" command by executing ${chalk.cyan('blocklet server upgrade')}`
|
|
51
|
+
);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// eslint-disable-next-line max-len
|
|
56
|
+
printInfo(
|
|
57
|
+
`The specVersion of blocklet.yml is about to be downgraded from ${chalk.cyan(
|
|
58
|
+
currentSpecVersion
|
|
59
|
+
)} to ${chalk.cyan(BLOCKLET_LATEST_SPEC_VERSION)}`
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
updateMetaFile(file, meta);
|
|
64
|
+
printSuccess(`Blocklet version bumped to ${nextVersion}`);
|
|
65
|
+
|
|
66
|
+
if (gitCommit) {
|
|
67
|
+
try {
|
|
68
|
+
shell.exec(`git add ${file.replace(dir, '')}`);
|
|
69
|
+
shell.exec(`git commit -nm "blocklet version ${nextVersion}`);
|
|
70
|
+
} catch (err) {
|
|
71
|
+
printError('Failed to commit to git', err.message);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
process.exit(0);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
debug('bump blocklet version failed', error);
|
|
78
|
+
printError('Bump blocklet version failed: ', error.message);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const { printSuccess, printError } = require('../../util');
|
|
2
|
+
const { getNode } = require('../../node');
|
|
3
|
+
|
|
4
|
+
exports.run = async ({ target }) => {
|
|
5
|
+
const { node } = await getNode({ dir: process.cwd() });
|
|
6
|
+
|
|
7
|
+
node.onReady(async () => {
|
|
8
|
+
const info = await node.getNodeInfo();
|
|
9
|
+
await node.handleRouting(info);
|
|
10
|
+
|
|
11
|
+
if (target === 'cache') {
|
|
12
|
+
const removed = await node.clearCache({ pattern: null, teamDid: info.did });
|
|
13
|
+
printSuccess(`Cache for server cleared: ${removed.join(',')}`);
|
|
14
|
+
process.exit(0);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (target === 'maintenance-status') {
|
|
18
|
+
await node.states.node.updateNodeInfo({
|
|
19
|
+
mode: info.previousMode || info.mode,
|
|
20
|
+
previousMode: '',
|
|
21
|
+
upgradeSessionId: '',
|
|
22
|
+
nextVersion: '',
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
printSuccess('Server maintenance status reset');
|
|
26
|
+
process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
printError(`Unknown cleanup target: ${target}`);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
});
|
|
32
|
+
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable global-require */
|
|
3
|
+
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
const { Command } = require('commander');
|
|
6
|
+
const last = require('lodash/last');
|
|
7
|
+
|
|
8
|
+
const { NODE_MODES, WEB_WALLET_URL } = require('@abtnode/constant');
|
|
9
|
+
const debug = require('debug')('@blocklet/cli:abtnode');
|
|
10
|
+
|
|
11
|
+
const { version } = require('../../../package.json');
|
|
12
|
+
const start = require('./start');
|
|
13
|
+
const stop = require('./stop');
|
|
14
|
+
const init = require('./init');
|
|
15
|
+
const info = require('./info');
|
|
16
|
+
const cleanup = require('./cleanup');
|
|
17
|
+
const logs = require('./logs');
|
|
18
|
+
const status = require('./status');
|
|
19
|
+
const upgrade = require('./upgrade');
|
|
20
|
+
const rescue = require('./rescue');
|
|
21
|
+
const { printVersionTip } = require('../../util');
|
|
22
|
+
|
|
23
|
+
module.exports = (parentCommand = '') => {
|
|
24
|
+
const program = new Command(parentCommand);
|
|
25
|
+
|
|
26
|
+
program.version(version);
|
|
27
|
+
program.description('Manage Blocklet Server');
|
|
28
|
+
program.option('-c --config [node-config]', 'Blocklet Server configuration file');
|
|
29
|
+
program.option('-y --yes', 'Automatic yes to prompts', false);
|
|
30
|
+
|
|
31
|
+
const parseOptions =
|
|
32
|
+
(handler) =>
|
|
33
|
+
async (...args) => {
|
|
34
|
+
printVersionTip();
|
|
35
|
+
|
|
36
|
+
const commonOptions = program.opts();
|
|
37
|
+
const options = last(args);
|
|
38
|
+
const allOptions = { ...commonOptions, ...options };
|
|
39
|
+
debug('parse options', allOptions);
|
|
40
|
+
await handler(...args.slice(0, args.length - 1), allOptions);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const modes = Object.values(NODE_MODES)
|
|
44
|
+
.map((d) => `"${d}"`)
|
|
45
|
+
.join(', ');
|
|
46
|
+
|
|
47
|
+
const forceIntranet = process.env.ABT_NODE_FORCE_INTRANET === '1';
|
|
48
|
+
|
|
49
|
+
program
|
|
50
|
+
.command('start')
|
|
51
|
+
.option('-u --update-db', 'Should we update Blocklet Server database with latest settings from config file')
|
|
52
|
+
.option('--update-blocklet-env', 'Should we update blocklet environments', false)
|
|
53
|
+
.option('-k --keep-alive', 'Should I keep running without exiting after starting success', false)
|
|
54
|
+
.option(
|
|
55
|
+
'-a --auto-init',
|
|
56
|
+
'If the configuration data directory does not exists, initialize it automatically.',
|
|
57
|
+
false
|
|
58
|
+
)
|
|
59
|
+
.option('-m --force-mode <forceMode>', `Update blocklet server mode to specified, allowed options can be ${modes}`)
|
|
60
|
+
.option('--force-intranet', 'Force blocklet server to run in intranet, ignore any external IP.', forceIntranet)
|
|
61
|
+
.description('Start Blocklet Server')
|
|
62
|
+
.action(parseOptions(start.run));
|
|
63
|
+
|
|
64
|
+
program
|
|
65
|
+
.command('init')
|
|
66
|
+
.option('-f --force', 'Initialize a Blocklet Server instance without having it ask any questions', false)
|
|
67
|
+
.option(
|
|
68
|
+
'-i --interactive',
|
|
69
|
+
'Should we run in interactive mode (default: false), if `--force` is enabled, the `--interactive` argument will be invalid',
|
|
70
|
+
false
|
|
71
|
+
)
|
|
72
|
+
.option(
|
|
73
|
+
'--mode <mode>',
|
|
74
|
+
`Initial server mode, allowed mode can be ${NODE_MODES.PRODUCTION}, ${NODE_MODES.DEBUG}`,
|
|
75
|
+
NODE_MODES.PRODUCTION
|
|
76
|
+
)
|
|
77
|
+
.option('--https', 'Enable default https support for dashboard and blocklets')
|
|
78
|
+
.option('--no-https', 'Disable default https support for dashboard and blocklets')
|
|
79
|
+
.option('--sk <custom-sk>', 'Customize the blocklet server secret key', '')
|
|
80
|
+
.option(
|
|
81
|
+
'--web-wallet-url <url>',
|
|
82
|
+
'Customize the web wallet url',
|
|
83
|
+
process.env.ABT_NODE_WEB_WALLET_URL || WEB_WALLET_URL
|
|
84
|
+
)
|
|
85
|
+
.option('--http-port <httpPort>', 'Http port of the service gateway', 80)
|
|
86
|
+
.option('--https-port <httpsPort>', 'Https port of the service gateway', 443)
|
|
87
|
+
.option('--owner-nft-holder <ownerNftHolderDid>', 'The did that holds the ownership NFT', '')
|
|
88
|
+
.option('--owner-nft-issuer <ownerNftIssuerDid>', 'The did that issued the ownership NFT', '')
|
|
89
|
+
.option('--trusted-passport-issuer <passportIssuerDid>', 'The passport issuer did that is trusted by this node', '')
|
|
90
|
+
.option('--disable-passport-issuance', 'Disable passport issuance by this node', false)
|
|
91
|
+
.description('Init Blocklet Server config')
|
|
92
|
+
.action(parseOptions(init.run));
|
|
93
|
+
|
|
94
|
+
program.command('status').description('Show Blocklet Server and blocklet status').action(parseOptions(status.run));
|
|
95
|
+
program.command('logs').description('Show Blocklet Server and blocklet log files').action(parseOptions(logs.run));
|
|
96
|
+
|
|
97
|
+
program
|
|
98
|
+
.command('stop')
|
|
99
|
+
.option('-f --force', 'Force stop all Blocklet Server related processes', false)
|
|
100
|
+
.description('Stop Blocklet Server and blocklets')
|
|
101
|
+
.action(parseOptions(stop.run));
|
|
102
|
+
|
|
103
|
+
program
|
|
104
|
+
.command('rescue')
|
|
105
|
+
.option('--stopped-after <datetime>', 'Only start blocklets that are stopped after the specified time')
|
|
106
|
+
.option('-f --force', 'Force start all blocklets, even if they are already running', false)
|
|
107
|
+
.description('Start all blocklets in current running server')
|
|
108
|
+
.action(parseOptions(rescue.run));
|
|
109
|
+
|
|
110
|
+
program
|
|
111
|
+
.command('info')
|
|
112
|
+
.option('-C --clipboard', 'Automatically copy environment information to clipboard', false)
|
|
113
|
+
.description('Get environment information for debugging and issue reporting')
|
|
114
|
+
.action(parseOptions(info.run));
|
|
115
|
+
|
|
116
|
+
program
|
|
117
|
+
.command('cleanup')
|
|
118
|
+
.option('--target <target>', 'Which target to cleanup, available options: cache, maintenance-status')
|
|
119
|
+
.description('Do some server level cleanup work')
|
|
120
|
+
.action(parseOptions(cleanup.run));
|
|
121
|
+
|
|
122
|
+
program.command('upgrade').description('Self-Upgrade Blocklet Server').action(parseOptions(upgrade.run));
|
|
123
|
+
|
|
124
|
+
program.on('--help', () => {
|
|
125
|
+
/* eslint-disable no-console */
|
|
126
|
+
console.log('');
|
|
127
|
+
console.log(`None of the above command seems help? Consider command line utility ${chalk.cyan('blocklet')}.`);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
return program;
|
|
131
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
const envinfo = require('envinfo');
|
|
2
|
+
const xbytes = require('xbytes');
|
|
3
|
+
const shell = require('shelljs');
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
const clipboardy = require('clipboardy');
|
|
6
|
+
const ip = require('@abtnode/core/lib/util/ip');
|
|
7
|
+
const info = require('@abtnode/core/lib/util/sysinfo');
|
|
8
|
+
|
|
9
|
+
const { canUseFileSystemIsolateApi } = require('@abtnode/util/lib/security');
|
|
10
|
+
const { print, printError, printInfo, getCLIBinaryName } = require('../../util');
|
|
11
|
+
const { readNodeConfigWithValidate, getNode } = require('../../node');
|
|
12
|
+
const getDockerStatusLog = require('../../util/docker-status-log');
|
|
13
|
+
|
|
14
|
+
exports.run = ({ clipboard }) => {
|
|
15
|
+
// Clipboard is not accessible when on a linux tty
|
|
16
|
+
const copyToClipboard = process.platform === 'linux' && !process.env.DISPLAY ? false : clipboard;
|
|
17
|
+
|
|
18
|
+
const printEnvInfo = (err) => {
|
|
19
|
+
if (err) {
|
|
20
|
+
console.error(err);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return envinfo
|
|
24
|
+
.run({
|
|
25
|
+
System: ['OS', 'CPU', 'Shell'],
|
|
26
|
+
Binaries: ['Node', 'npm', 'Yarn', 'pm2', 'pnpm', 'bun'],
|
|
27
|
+
Browsers: ['Chrome', 'Edge', 'Firefox', 'Safari'],
|
|
28
|
+
Servers: ['Apache', 'Nginx'],
|
|
29
|
+
Virtualization: ['Docker', 'Parallels', 'VirtualBox', 'VMware Fusion'],
|
|
30
|
+
npmPackages: ['@abtnode/*', '@arcblock/*'],
|
|
31
|
+
npmGlobalPackages: ['@abtnode/*', '@arcblock/*', 'pm2', 'npm', 'yarn'],
|
|
32
|
+
})
|
|
33
|
+
.then((output) => {
|
|
34
|
+
print(output);
|
|
35
|
+
|
|
36
|
+
if (copyToClipboard) {
|
|
37
|
+
clipboardy.writeSync(output);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
process.exit(0);
|
|
41
|
+
})
|
|
42
|
+
.catch((e) => {
|
|
43
|
+
printError(`Failed to fetch env info: ${e.message}`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
return readNodeConfigWithValidate(process.cwd())
|
|
49
|
+
.then(async ({ config, configFile }) => {
|
|
50
|
+
printInfo('Server binary from:', chalk.cyan(shell.which(getCLIBinaryName())?.stdout));
|
|
51
|
+
printInfo('Server config from:', chalk.cyan(configFile));
|
|
52
|
+
printInfo('Server router provider:', chalk.cyan(config.node.routing.provider));
|
|
53
|
+
printInfo('Server http port:', chalk.cyan(config.node.routing.httpPort));
|
|
54
|
+
printInfo('Server https port:', chalk.cyan(config.node.routing.httpsPort));
|
|
55
|
+
|
|
56
|
+
let result = await info.getSysInfo();
|
|
57
|
+
printInfo('Server host cpu:', chalk.cyan(result.cpu.physicalCores), '/', chalk.cyan(result.cpu.cpus.length));
|
|
58
|
+
printInfo(
|
|
59
|
+
'Server host memory:',
|
|
60
|
+
chalk.cyan(xbytes(result.mem.used, { iec: true })),
|
|
61
|
+
'/',
|
|
62
|
+
chalk.cyan(xbytes(result.mem.total, { iec: true }))
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
result = await ip.get();
|
|
66
|
+
printInfo('Server host IP:', chalk.cyan(JSON.stringify(result)));
|
|
67
|
+
const correct = await ip.isDnsIpMappingCorrect(config.node.did);
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @type {{node: import('@abtnode/client')}}
|
|
71
|
+
*/
|
|
72
|
+
const { node } = await getNode({ dir: process.cwd() });
|
|
73
|
+
|
|
74
|
+
const nodeInfo = await node.getNodeInfo();
|
|
75
|
+
const { enableFileSystemIsolation } = nodeInfo;
|
|
76
|
+
const canUseFileSystemIsolation = canUseFileSystemIsolateApi();
|
|
77
|
+
|
|
78
|
+
printInfo(
|
|
79
|
+
'Server file system isolation status:',
|
|
80
|
+
enableFileSystemIsolation
|
|
81
|
+
? `${canUseFileSystemIsolation ? chalk.green('on(available)') : chalk.yellow('on(unavailable, version must be >= 21.6.0)')}`
|
|
82
|
+
: chalk.red('off')
|
|
83
|
+
);
|
|
84
|
+
// 判断是否是mac
|
|
85
|
+
|
|
86
|
+
getDockerStatusLog(printInfo, nodeInfo);
|
|
87
|
+
printInfo('Server domain status:', correct ? chalk.green('correct') : chalk.red('mismatch'));
|
|
88
|
+
|
|
89
|
+
return printEnvInfo();
|
|
90
|
+
})
|
|
91
|
+
.catch(printEnvInfo);
|
|
92
|
+
};
|