@blocklet/cli 1.17.10 → 1.17.11-beta-20260225-043848-68611a07
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 +1 -1
- package/lib/commands/blocklet/export.js +81 -0
- package/lib/commands/blocklet/import.js +108 -0
- package/lib/commands/index.js +15 -0
- package/package.json +17 -17
package/README.md
CHANGED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
const { isValid: isValidDid, toAddress } = require('@arcblock/did');
|
|
4
|
+
|
|
5
|
+
const { BlockletExporter } = require('@abtnode/core/lib/blocklet/storage/export/exporter');
|
|
6
|
+
const { printError, printInfo, printSuccess, getCLIBinaryName } = require('../../util');
|
|
7
|
+
const { getNode } = require('../../node');
|
|
8
|
+
const { checkRunning } = require('../../manager');
|
|
9
|
+
const { wrapSpinner } = require('../../ui');
|
|
10
|
+
|
|
11
|
+
const checkNodeRunning = async () => {
|
|
12
|
+
const isRunning = await checkRunning();
|
|
13
|
+
if (!isRunning) {
|
|
14
|
+
const startCommand = chalk.cyan(`${getCLIBinaryName()} server start`);
|
|
15
|
+
printError('Blocklet Server is not running!');
|
|
16
|
+
printInfo(`To start Blocklet Server, use ${startCommand}`);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const run = async ({ appDid: inputAppDid, outDir, includeLogs }) => {
|
|
22
|
+
try {
|
|
23
|
+
await checkNodeRunning();
|
|
24
|
+
|
|
25
|
+
if (!inputAppDid) {
|
|
26
|
+
printError('Please provide --app-did');
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
if (!isValidDid(inputAppDid)) {
|
|
30
|
+
printError(`appDid is not valid: ${inputAppDid}`);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
if (!outDir) {
|
|
34
|
+
printError('Please provide --out-dir');
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const appDid = toAddress(inputAppDid);
|
|
39
|
+
const resolvedOutDir = path.resolve(outDir);
|
|
40
|
+
|
|
41
|
+
printInfo(`Exporting blocklet ${chalk.cyan(appDid)} to ${chalk.cyan(resolvedOutDir)}`);
|
|
42
|
+
|
|
43
|
+
const { node, dataDir } = await getNode({ dir: process.cwd() });
|
|
44
|
+
|
|
45
|
+
node.onReady(async () => {
|
|
46
|
+
try {
|
|
47
|
+
const blocklet = await node.getBlocklet({ did: appDid });
|
|
48
|
+
if (!blocklet) {
|
|
49
|
+
printError(`Blocklet ${appDid} not found`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
printInfo(`Blocklet: ${chalk.cyan(blocklet.meta.title || blocklet.meta.name)} v${blocklet.meta.version}`);
|
|
54
|
+
|
|
55
|
+
const exporter = new BlockletExporter({
|
|
56
|
+
appDid,
|
|
57
|
+
outDir: resolvedOutDir,
|
|
58
|
+
serverDir: dataDir,
|
|
59
|
+
options: { includeLogs },
|
|
60
|
+
progressCallback: (msg) => printInfo(msg),
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const meta = await wrapSpinner('Exporting blocklet...', () => exporter.export());
|
|
64
|
+
|
|
65
|
+
printSuccess('Export completed successfully!');
|
|
66
|
+
printInfo(` Output: ${chalk.cyan(resolvedOutDir)}`);
|
|
67
|
+
printInfo(` AppDid: ${chalk.cyan(meta.appDid)}`);
|
|
68
|
+
printInfo(` Version: ${chalk.cyan(meta.blockletVersion)}`);
|
|
69
|
+
process.exit(0);
|
|
70
|
+
} catch (err) {
|
|
71
|
+
printError(`Export failed: ${err.message}`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
} catch (err) {
|
|
76
|
+
printError(err.message);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
exports.run = run;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const inquirer = require('inquirer');
|
|
5
|
+
const { BlockletEvents } = require('@blocklet/constant');
|
|
6
|
+
|
|
7
|
+
const { printError, printInfo, printSuccess, printWarning, getCLIBinaryName } = require('../../util');
|
|
8
|
+
const { getNode } = require('../../node');
|
|
9
|
+
const { checkRunning } = require('../../manager');
|
|
10
|
+
const { wrapSpinner } = require('../../ui');
|
|
11
|
+
|
|
12
|
+
const checkNodeRunning = async () => {
|
|
13
|
+
const isRunning = await checkRunning();
|
|
14
|
+
if (!isRunning) {
|
|
15
|
+
const startCommand = chalk.cyan(`${getCLIBinaryName()} server start`);
|
|
16
|
+
printError('Blocklet Server is not running!');
|
|
17
|
+
printInfo(`To start Blocklet Server, use ${startCommand}`);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const run = async (inputDir) => {
|
|
23
|
+
try {
|
|
24
|
+
await checkNodeRunning();
|
|
25
|
+
|
|
26
|
+
if (!inputDir) {
|
|
27
|
+
printError('Please provide <input-dir>');
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const resolvedDir = path.resolve(inputDir);
|
|
32
|
+
if (!fs.existsSync(resolvedDir)) {
|
|
33
|
+
printError(`Input directory does not exist: ${resolvedDir}`);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const metaPath = path.join(resolvedDir, 'export-meta.json');
|
|
38
|
+
if (!fs.existsSync(metaPath)) {
|
|
39
|
+
printError(`No export-meta.json found in: ${resolvedDir}`);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const meta = fs.readJSONSync(metaPath);
|
|
44
|
+
printInfo(`Importing blocklet: ${chalk.cyan(meta.blockletTitle || meta.blockletName)} v${meta.blockletVersion}`);
|
|
45
|
+
printInfo(` Source server: ${chalk.cyan(meta.sourceServerDid)}`);
|
|
46
|
+
printInfo(` AppDid: ${chalk.cyan(meta.appDid)}`);
|
|
47
|
+
printInfo(` Exported at: ${chalk.cyan(meta.exportedAt)}`);
|
|
48
|
+
|
|
49
|
+
const { node, publishEvent } = await getNode({ dir: process.cwd() });
|
|
50
|
+
|
|
51
|
+
node.onReady(async () => {
|
|
52
|
+
try {
|
|
53
|
+
let overwrite = false;
|
|
54
|
+
const existing = await node.hasBlocklet({ did: meta.blockletDid });
|
|
55
|
+
if (existing) {
|
|
56
|
+
printWarning(
|
|
57
|
+
`Blocklet ${chalk.cyan(meta.blockletTitle || meta.blockletName)} already exists on this server.`
|
|
58
|
+
);
|
|
59
|
+
const { confirmOverwrite } = await inquirer.prompt({
|
|
60
|
+
type: 'confirm',
|
|
61
|
+
name: 'confirmOverwrite',
|
|
62
|
+
message: 'Delete existing blocklet and import? All existing data will be lost.',
|
|
63
|
+
default: false,
|
|
64
|
+
});
|
|
65
|
+
if (!confirmOverwrite) {
|
|
66
|
+
printInfo('Import cancelled.');
|
|
67
|
+
process.exit(0);
|
|
68
|
+
}
|
|
69
|
+
overwrite = true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const result = await wrapSpinner('Importing blocklet...', () =>
|
|
73
|
+
node.importBlocklet({
|
|
74
|
+
inputDir: resolvedDir,
|
|
75
|
+
overwrite,
|
|
76
|
+
blockletDid: meta.blockletDid,
|
|
77
|
+
progressCallback: (msg) => printInfo(msg),
|
|
78
|
+
})
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
// Notify daemon to set up routing for the imported blocklet via WebSocket.
|
|
82
|
+
// The daemon's WS handler calls handleBlockletEvent which triggers ensureBlockletRouting
|
|
83
|
+
// and nginx config generation. The eventHub doesn't work for CLI→daemon because
|
|
84
|
+
// ABT_NODE_SK is not set in CLI mode (isCLI() depends on its absence).
|
|
85
|
+
try {
|
|
86
|
+
await publishEvent(BlockletEvents.installed, { blocklet: result.blocklet, context: {} });
|
|
87
|
+
printInfo(' Routing: daemon notified');
|
|
88
|
+
} catch (err) {
|
|
89
|
+
printWarning(` Could not notify daemon for routing setup: ${err.message}`);
|
|
90
|
+
printWarning(' You may need to restart the server for routing to take effect.');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
printSuccess('Import completed successfully!');
|
|
94
|
+
printInfo(` Blocklet: ${chalk.cyan(result.meta.blockletTitle || result.meta.blockletName)}`);
|
|
95
|
+
printInfo(` AppDid: ${chalk.cyan(result.meta.appDid)}`);
|
|
96
|
+
process.exit(0);
|
|
97
|
+
} catch (err) {
|
|
98
|
+
printError(`Import failed: ${err.message}`);
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
} catch (err) {
|
|
103
|
+
printError(err.message);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
exports.run = run;
|
package/lib/commands/index.js
CHANGED
|
@@ -51,6 +51,8 @@ const $debug = require('./blocklet/debug');
|
|
|
51
51
|
const add = require('./blocklet/add');
|
|
52
52
|
const remove = require('./blocklet/remove');
|
|
53
53
|
const cleanup = require('./blocklet/cleanup');
|
|
54
|
+
const exportCmd = require('./blocklet/export');
|
|
55
|
+
const importCmd = require('./blocklet/import');
|
|
54
56
|
const document = require('./blocklet/document');
|
|
55
57
|
const component = require('./blocklet/component');
|
|
56
58
|
const ServerCommand = require('./server/command');
|
|
@@ -301,6 +303,19 @@ program
|
|
|
301
303
|
.description('Do some blocklet level cleanup work')
|
|
302
304
|
.action(parseOptions(cleanup.run));
|
|
303
305
|
|
|
306
|
+
program
|
|
307
|
+
.command('export')
|
|
308
|
+
.requiredOption('--app-did <did>', 'The appDid of the blocklet to export')
|
|
309
|
+
.requiredOption('--out-dir <path>', 'Output directory for exported blocklet data')
|
|
310
|
+
.option('--include-logs', 'Include logs in the export', false)
|
|
311
|
+
.description('Export blocklet data for cross-server migration')
|
|
312
|
+
.action(parseOptions(exportCmd.run));
|
|
313
|
+
|
|
314
|
+
program
|
|
315
|
+
.command('import <input-dir>')
|
|
316
|
+
.description('Import blocklet data from an export directory')
|
|
317
|
+
.action(parseArgsAndOptions(importCmd.run));
|
|
318
|
+
|
|
304
319
|
function makeDocumentCommand() {
|
|
305
320
|
const documentCommand = new Command('document');
|
|
306
321
|
documentCommand.description('Manage DID document for the blocklet or the Blocklet Server');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/cli",
|
|
3
|
-
"version": "1.17.
|
|
3
|
+
"version": "1.17.11-beta-20260225-043848-68611a07",
|
|
4
4
|
"description": "Command line tools to manage Blocklet Server",
|
|
5
5
|
"homepage": "https://www.arcblock.io/docs/blocklet-cli",
|
|
6
6
|
"bin": {
|
|
@@ -33,28 +33,28 @@
|
|
|
33
33
|
"url": "https://github.com/ArcBlock/blocklet-server/issues"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@abtnode/blocklet-services": "1.17.
|
|
37
|
-
"@abtnode/constant": "1.17.
|
|
38
|
-
"@abtnode/core": "1.17.
|
|
39
|
-
"@abtnode/db-cache": "1.17.
|
|
40
|
-
"@abtnode/logger": "1.17.
|
|
41
|
-
"@abtnode/models": "1.17.
|
|
42
|
-
"@abtnode/router-provider": "1.17.
|
|
43
|
-
"@abtnode/util": "1.17.
|
|
44
|
-
"@abtnode/webapp": "1.17.
|
|
36
|
+
"@abtnode/blocklet-services": "1.17.11-beta-20260225-043848-68611a07",
|
|
37
|
+
"@abtnode/constant": "1.17.11-beta-20260225-043848-68611a07",
|
|
38
|
+
"@abtnode/core": "1.17.11-beta-20260225-043848-68611a07",
|
|
39
|
+
"@abtnode/db-cache": "1.17.11-beta-20260225-043848-68611a07",
|
|
40
|
+
"@abtnode/logger": "1.17.11-beta-20260225-043848-68611a07",
|
|
41
|
+
"@abtnode/models": "1.17.11-beta-20260225-043848-68611a07",
|
|
42
|
+
"@abtnode/router-provider": "1.17.11-beta-20260225-043848-68611a07",
|
|
43
|
+
"@abtnode/util": "1.17.11-beta-20260225-043848-68611a07",
|
|
44
|
+
"@abtnode/webapp": "1.17.11-beta-20260225-043848-68611a07",
|
|
45
45
|
"@arcblock/did": "1.29.8",
|
|
46
46
|
"@arcblock/event-hub": "1.29.8",
|
|
47
47
|
"@arcblock/ipfs-only-hash": "^0.0.2",
|
|
48
48
|
"@arcblock/jwt": "1.29.8",
|
|
49
49
|
"@arcblock/ws": "1.29.8",
|
|
50
|
-
"@blocklet/constant": "1.17.
|
|
50
|
+
"@blocklet/constant": "1.17.11-beta-20260225-043848-68611a07",
|
|
51
51
|
"@blocklet/error": "^0.3.5",
|
|
52
52
|
"@blocklet/form-collector": "^0.1.8",
|
|
53
|
-
"@blocklet/images": "1.17.
|
|
54
|
-
"@blocklet/meta": "1.17.
|
|
55
|
-
"@blocklet/resolver": "1.17.
|
|
56
|
-
"@blocklet/server-js": "1.17.
|
|
57
|
-
"@blocklet/store": "1.17.
|
|
53
|
+
"@blocklet/images": "1.17.11-beta-20260225-043848-68611a07",
|
|
54
|
+
"@blocklet/meta": "1.17.11-beta-20260225-043848-68611a07",
|
|
55
|
+
"@blocklet/resolver": "1.17.11-beta-20260225-043848-68611a07",
|
|
56
|
+
"@blocklet/server-js": "1.17.11-beta-20260225-043848-68611a07",
|
|
57
|
+
"@blocklet/store": "1.17.11-beta-20260225-043848-68611a07",
|
|
58
58
|
"@blocklet/theme-builder": "^0.4.8",
|
|
59
59
|
"@ocap/client": "1.29.8",
|
|
60
60
|
"@ocap/mcrypto": "1.29.8",
|
|
@@ -153,7 +153,7 @@
|
|
|
153
153
|
"engines": {
|
|
154
154
|
"node": ">=14"
|
|
155
155
|
},
|
|
156
|
-
"gitHead": "
|
|
156
|
+
"gitHead": "984a5f485c38205d8240b667cca26ddad0bbf6ac",
|
|
157
157
|
"devDependencies": {
|
|
158
158
|
"@types/fs-extra": "^11.0.4"
|
|
159
159
|
}
|