@abtnode/core 1.16.17-beta-d282d63e → 1.16.17-beta-4f13d99d
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/lib/api/team.js +2 -1
- package/lib/blocklet/manager/helper/install-component-from-url.js +5 -2
- package/lib/blocklet/project/index.js +4 -4
- package/lib/blocklet/storage/backup/audit-log.js +19 -3
- package/lib/blocklet/storage/backup/base.js +31 -0
- package/lib/blocklet/storage/backup/blocklet-extras.js +20 -3
- package/lib/blocklet/storage/backup/blocklet.js +30 -5
- package/lib/blocklet/storage/backup/blocklets.js +32 -2
- package/lib/blocklet/storage/backup/data.js +23 -0
- package/lib/blocklet/storage/backup/routing-rule.js +31 -3
- package/lib/blocklet/storage/backup/spaces.js +11 -4
- package/lib/blocklet/storage/utils/disk.js +77 -10
- package/lib/util/blocklet.js +4 -1
- package/lib/validators/project.js +2 -2
- package/package.json +32 -32
package/lib/api/team.js
CHANGED
|
@@ -25,6 +25,7 @@ const {
|
|
|
25
25
|
createUserPassport,
|
|
26
26
|
} = require('@abtnode/auth/lib/passport');
|
|
27
27
|
const { getPassportStatusEndpoint } = require('@abtnode/auth/lib/auth');
|
|
28
|
+
const { hasActiveOwnerPassport } = require('@abtnode/util/lib/passport');
|
|
28
29
|
const getBlockletInfo = require('@blocklet/meta/lib/info');
|
|
29
30
|
const { getUserAvatarUrl, getAppAvatarUrl, extractUserAvatar, getAvatarByUrl } = require('@abtnode/util/lib/user');
|
|
30
31
|
const { getChainClient } = require('@abtnode/util/lib/get-chain-client');
|
|
@@ -399,7 +400,7 @@ class TeamAPI extends EventEmitter {
|
|
|
399
400
|
throw new Error('User does not exist');
|
|
400
401
|
}
|
|
401
402
|
|
|
402
|
-
if (doc
|
|
403
|
+
if (hasActiveOwnerPassport(doc)) {
|
|
403
404
|
throw new Error('Cannot update owner\'s approval'); // prettier-ignore
|
|
404
405
|
}
|
|
405
406
|
|
|
@@ -2,7 +2,7 @@ const { sign } = require('@arcblock/jwt');
|
|
|
2
2
|
|
|
3
3
|
const logger = require('@abtnode/logger')('@abtnode/core:install-component-url');
|
|
4
4
|
|
|
5
|
-
const { isFreeBlocklet } = require('@blocklet/meta/lib/util');
|
|
5
|
+
const { isFreeBlocklet, hasStartEngine } = require('@blocklet/meta/lib/util');
|
|
6
6
|
const { titleSchema } = require('@blocklet/meta/lib/schema');
|
|
7
7
|
const hasReservedKey = require('@blocklet/meta/lib/has-reserved-key');
|
|
8
8
|
|
|
@@ -75,7 +75,6 @@ const installComponentFromUrl = async ({
|
|
|
75
75
|
// children
|
|
76
76
|
const newChild = {
|
|
77
77
|
meta: newChildMeta,
|
|
78
|
-
mountPoint: mountPoint || formatName(newChildMeta.name),
|
|
79
78
|
bundleSource: inStore
|
|
80
79
|
? {
|
|
81
80
|
store: registryUrl,
|
|
@@ -86,6 +85,10 @@ const installComponentFromUrl = async ({
|
|
|
86
85
|
: { url },
|
|
87
86
|
};
|
|
88
87
|
|
|
88
|
+
if (hasStartEngine(newChildMeta)) {
|
|
89
|
+
newChild.mountPoint = mountPoint || formatName(newChildMeta.name);
|
|
90
|
+
}
|
|
91
|
+
|
|
89
92
|
const { dynamicComponents } = await parseComponents(newChild);
|
|
90
93
|
|
|
91
94
|
const index = blocklet.children.findIndex((child) => child.meta.did === meta.did);
|
|
@@ -136,8 +136,8 @@ const createRelease = async ({
|
|
|
136
136
|
const blocklet = await manager.getBlocklet(did);
|
|
137
137
|
const { projectState, releaseState } = await manager._getProjectState(did);
|
|
138
138
|
|
|
139
|
-
const
|
|
140
|
-
if (!
|
|
139
|
+
const project0 = await projectState.findOne({ id: projectId });
|
|
140
|
+
if (!project0) {
|
|
141
141
|
throw new Error('project not found');
|
|
142
142
|
}
|
|
143
143
|
|
|
@@ -158,7 +158,7 @@ const createRelease = async ({
|
|
|
158
158
|
throw new Error(`blockletVersion ${blockletVersion} already exists`);
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
const { blockletDid } =
|
|
161
|
+
const { blockletDid } = project0;
|
|
162
162
|
|
|
163
163
|
params.blockletDid = blockletDid;
|
|
164
164
|
|
|
@@ -168,7 +168,7 @@ const createRelease = async ({
|
|
|
168
168
|
releaseId,
|
|
169
169
|
status,
|
|
170
170
|
});
|
|
171
|
-
await projectState.updateProject(projectId, params);
|
|
171
|
+
const project = await projectState.updateProject(projectId, params);
|
|
172
172
|
|
|
173
173
|
const _releaseId = release.id;
|
|
174
174
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { outputJson } = require('fs-extra');
|
|
2
2
|
const { join } = require('path');
|
|
3
3
|
const states = require('../../../states');
|
|
4
4
|
const { BaseBackup } = require('./base');
|
|
5
|
+
const { getFileObject } = require('../utils/disk');
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
*
|
|
@@ -11,6 +12,10 @@ const { BaseBackup } = require('./base');
|
|
|
11
12
|
class AuditLogBackup extends BaseBackup {
|
|
12
13
|
filename = 'audit-log.json';
|
|
13
14
|
|
|
15
|
+
get auditLogsExportPath() {
|
|
16
|
+
return join(this.backupDir, this.filename);
|
|
17
|
+
}
|
|
18
|
+
|
|
14
19
|
async export() {
|
|
15
20
|
/**
|
|
16
21
|
* @type {import('@abtnode/client').AuditLog}
|
|
@@ -18,9 +23,20 @@ class AuditLogBackup extends BaseBackup {
|
|
|
18
23
|
const auditLogs = await states.auditLog.find({
|
|
19
24
|
scope: this.blocklet.meta.did,
|
|
20
25
|
});
|
|
26
|
+
await outputJson(this.auditLogsExportPath, auditLogs);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
* @returns {Promise<import('./base').SyncObject[]>}
|
|
32
|
+
* @memberof AuditLogBackup
|
|
33
|
+
*/
|
|
34
|
+
async collectSyncObjects() {
|
|
35
|
+
await this.export();
|
|
36
|
+
|
|
37
|
+
const objects = [getFileObject(this.auditLogsExportPath, this.backupDir)];
|
|
21
38
|
|
|
22
|
-
|
|
23
|
-
outputJsonSync(join(this.backupDir, this.filename), auditLogs);
|
|
39
|
+
return objects;
|
|
24
40
|
}
|
|
25
41
|
}
|
|
26
42
|
|
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
* }} BaseSecurityContext
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {import('@did-space/core').Object} SyncObject
|
|
15
|
+
*/
|
|
16
|
+
|
|
13
17
|
const { Hasher } = require('@ocap/mcrypto');
|
|
14
18
|
const { toBuffer } = require('@ocap/util');
|
|
15
19
|
const getBlockletInfo = require('@blocklet/meta/lib/info');
|
|
@@ -110,6 +114,33 @@ class BaseBackup {
|
|
|
110
114
|
})
|
|
111
115
|
);
|
|
112
116
|
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
*
|
|
120
|
+
* @param {BaseBackup} dataBackup
|
|
121
|
+
* @param {Array<BaseBackup>} storages
|
|
122
|
+
* @returns {Promise<SyncObject[]>}
|
|
123
|
+
* @memberof BaseBackup
|
|
124
|
+
*/
|
|
125
|
+
async collectSyncObjects(dataBackup, storages) {
|
|
126
|
+
/**
|
|
127
|
+
* @type {SyncObject[]}
|
|
128
|
+
*/
|
|
129
|
+
let syncObjects = [];
|
|
130
|
+
|
|
131
|
+
// @note: dataBackup 需要先于 blockletBackup 执行,并且 blockletBackup 与其他 backup的执行可以是无序的
|
|
132
|
+
dataBackup.ensureParams(this);
|
|
133
|
+
syncObjects = syncObjects.concat(await dataBackup.collectSyncObjects());
|
|
134
|
+
|
|
135
|
+
await Promise.all(
|
|
136
|
+
storages.map(async (storage) => {
|
|
137
|
+
storage.ensureParams(this);
|
|
138
|
+
syncObjects.push(...(await storage.collectSyncObjects()));
|
|
139
|
+
})
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
return syncObjects;
|
|
143
|
+
}
|
|
113
144
|
}
|
|
114
145
|
|
|
115
146
|
module.exports = {
|
|
@@ -1,18 +1,22 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { readFileSync, outputJson } = require('fs-extra');
|
|
2
2
|
const { isEmpty, cloneDeep } = require('lodash');
|
|
3
3
|
const { join } = require('path');
|
|
4
4
|
const security = require('@abtnode/util/lib/security');
|
|
5
5
|
|
|
6
6
|
const states = require('../../../states');
|
|
7
7
|
const { BaseBackup } = require('./base');
|
|
8
|
+
const { getFileObject } = require('../utils/disk');
|
|
8
9
|
|
|
9
10
|
class BlockletExtrasBackup extends BaseBackup {
|
|
10
11
|
filename = 'blocklet-extras.json';
|
|
11
12
|
|
|
13
|
+
get blockletExtraExportPath() {
|
|
14
|
+
return join(this.backupDir, this.filename);
|
|
15
|
+
}
|
|
16
|
+
|
|
12
17
|
async export() {
|
|
13
18
|
const blockletExtra = await this.getBlockletExtra();
|
|
14
|
-
|
|
15
|
-
outputJsonSync(join(this.backupDir, this.filename), blockletExtra);
|
|
19
|
+
await outputJson(this.blockletExtraExportPath, blockletExtra);
|
|
16
20
|
}
|
|
17
21
|
|
|
18
22
|
/**
|
|
@@ -87,6 +91,19 @@ class BlockletExtrasBackup extends BaseBackup {
|
|
|
87
91
|
}
|
|
88
92
|
}
|
|
89
93
|
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
*
|
|
97
|
+
* @returns {Promise<import('./base').SyncObject[]>}
|
|
98
|
+
* @memberof BlockletExtrasBackup
|
|
99
|
+
*/
|
|
100
|
+
async collectSyncObjects() {
|
|
101
|
+
await this.export();
|
|
102
|
+
|
|
103
|
+
const objects = [getFileObject(this.blockletExtraExportPath, this.backupDir)];
|
|
104
|
+
|
|
105
|
+
return objects;
|
|
106
|
+
}
|
|
90
107
|
}
|
|
91
108
|
|
|
92
109
|
module.exports = { BlockletExtrasBackup };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { outputJson, createWriteStream, createReadStream, ensureDir } = require('fs-extra');
|
|
2
2
|
const { cloneDeep } = require('lodash');
|
|
3
|
-
const { join, basename } = require('path');
|
|
3
|
+
const { join, basename, dirname } = require('path');
|
|
4
4
|
const { BLOCKLET_CONFIGURABLE_KEY } = require('@blocklet/constant');
|
|
5
5
|
const isEmpty = require('lodash/isEmpty');
|
|
6
6
|
const streamToPromise = require('stream-to-promise');
|
|
@@ -8,18 +8,26 @@ const axios = require('@abtnode/util/lib/axios');
|
|
|
8
8
|
const isUrl = require('is-url');
|
|
9
9
|
const { getLogoUrl } = require('@abtnode/util/lib/logo');
|
|
10
10
|
const { BaseBackup } = require('./base');
|
|
11
|
+
const { getFileObject } = require('../utils/disk');
|
|
11
12
|
|
|
12
13
|
class BlockletBackup extends BaseBackup {
|
|
13
14
|
filename = 'blocklet.json';
|
|
14
15
|
|
|
16
|
+
get blockletExportPath() {
|
|
17
|
+
return join(this.backupDir, this.filename);
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
async export() {
|
|
16
21
|
const blocklet = await this.cleanData();
|
|
17
22
|
|
|
18
23
|
const targetLogoPath = await this.writeLogoFile();
|
|
19
24
|
blocklet.meta.appLogo = basename(targetLogoPath);
|
|
20
25
|
|
|
21
|
-
|
|
22
|
-
|
|
26
|
+
await outputJson(this.blockletExportPath, blocklet);
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
targetLogoPath,
|
|
30
|
+
};
|
|
23
31
|
}
|
|
24
32
|
|
|
25
33
|
/**
|
|
@@ -78,7 +86,7 @@ class BlockletBackup extends BaseBackup {
|
|
|
78
86
|
|
|
79
87
|
/**
|
|
80
88
|
*
|
|
81
|
-
*
|
|
89
|
+
* @description 获取 blocklet 的 logo,并写入到备份文件夹的 data 目录下
|
|
82
90
|
* @param {string} target
|
|
83
91
|
* @returns {Promise<string>}
|
|
84
92
|
* @memberof DataBackup
|
|
@@ -100,6 +108,7 @@ class BlockletBackup extends BaseBackup {
|
|
|
100
108
|
|
|
101
109
|
const logoStream = await this.getLogoStream(logoUrl);
|
|
102
110
|
const targetLogoPath = join(this.backupDir, 'data', basename(logoUrl));
|
|
111
|
+
await ensureDir(dirname(targetLogoPath));
|
|
103
112
|
await streamToPromise(logoStream.pipe(createWriteStream(targetLogoPath)));
|
|
104
113
|
|
|
105
114
|
return targetLogoPath;
|
|
@@ -126,6 +135,22 @@ class BlockletBackup extends BaseBackup {
|
|
|
126
135
|
|
|
127
136
|
return createReadStream(logoUrl);
|
|
128
137
|
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
*
|
|
141
|
+
* @returns {Promise<import('./base').SyncObject[]>}
|
|
142
|
+
* @memberof BlockletBackup
|
|
143
|
+
*/
|
|
144
|
+
async collectSyncObjects() {
|
|
145
|
+
const { targetLogoPath } = await this.export();
|
|
146
|
+
|
|
147
|
+
const objects = [
|
|
148
|
+
getFileObject(this.blockletExportPath, this.backupDir),
|
|
149
|
+
getFileObject(targetLogoPath, this.backupDir),
|
|
150
|
+
];
|
|
151
|
+
|
|
152
|
+
return objects;
|
|
153
|
+
}
|
|
129
154
|
}
|
|
130
155
|
|
|
131
156
|
module.exports = { BlockletBackup };
|
|
@@ -3,11 +3,21 @@ const validUrl = require('valid-url');
|
|
|
3
3
|
const { BaseBackup } = require('./base');
|
|
4
4
|
const { dirToZip } = require('../utils/zip');
|
|
5
5
|
const { compareAndMove } = require('../utils/hash');
|
|
6
|
+
const { getFileObject } = require('../utils/disk');
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {{sourceDir: string, zipPath: string}} DirToZipMeta
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @description
|
|
14
|
+
* @class BlockletsBackup
|
|
15
|
+
* @extends {BaseBackup}
|
|
16
|
+
*/
|
|
7
17
|
class BlockletsBackup extends BaseBackup {
|
|
8
18
|
/**
|
|
9
19
|
*
|
|
10
|
-
* @returns {Promise<
|
|
20
|
+
* @returns {Promise<{dirs: DirToZipMeta[]}>}
|
|
11
21
|
* @memberof BlockletsBackup
|
|
12
22
|
*/
|
|
13
23
|
async export() {
|
|
@@ -18,6 +28,7 @@ class BlockletsBackup extends BaseBackup {
|
|
|
18
28
|
(b) => !validUrl.isHttpUri(b.tarball) && !validUrl.isHttpsUri(b.tarball)
|
|
19
29
|
);
|
|
20
30
|
|
|
31
|
+
/** @type {DirToZipMeta[]} */
|
|
21
32
|
const dirs = [];
|
|
22
33
|
for (const blockletMeta of blockletMetasFromLocal) {
|
|
23
34
|
const sourceDir = join(serverBlockletsDir, blockletMeta.name, blockletMeta.version);
|
|
@@ -26,6 +37,10 @@ class BlockletsBackup extends BaseBackup {
|
|
|
26
37
|
}
|
|
27
38
|
|
|
28
39
|
await this.dirsToZip(dirs);
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
dirs,
|
|
43
|
+
};
|
|
29
44
|
}
|
|
30
45
|
|
|
31
46
|
/**
|
|
@@ -55,7 +70,7 @@ class BlockletsBackup extends BaseBackup {
|
|
|
55
70
|
}
|
|
56
71
|
|
|
57
72
|
/**
|
|
58
|
-
* @param {
|
|
73
|
+
* @param {DirToZipMeta[]} dirs: /some/folder/to/compress
|
|
59
74
|
* @param {String} zipPath: /path/to/created.zip
|
|
60
75
|
* @returns {Promise}
|
|
61
76
|
* @memberof BlockletsBackup
|
|
@@ -69,6 +84,21 @@ class BlockletsBackup extends BaseBackup {
|
|
|
69
84
|
})
|
|
70
85
|
);
|
|
71
86
|
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
*
|
|
90
|
+
* @returns {Promise<import('./base').SyncObject[]>}
|
|
91
|
+
* @memberof BlockletsBackup
|
|
92
|
+
*/
|
|
93
|
+
async collectSyncObjects() {
|
|
94
|
+
const { dirs } = await this.export();
|
|
95
|
+
|
|
96
|
+
const objects = dirs.map((dir) => {
|
|
97
|
+
return getFileObject(dir.zipPath, this.backupDir);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
return objects;
|
|
101
|
+
}
|
|
72
102
|
}
|
|
73
103
|
|
|
74
104
|
module.exports = { BlockletsBackup };
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
const { copy } = require('fs-extra');
|
|
2
2
|
const { join } = require('path');
|
|
3
3
|
const { BaseBackup } = require('./base');
|
|
4
|
+
const { getFolderObjects } = require('../utils/disk');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {import('./base').FileIncludeStats} FileIncludeStats
|
|
8
|
+
*/
|
|
4
9
|
|
|
5
10
|
class DataBackup extends BaseBackup {
|
|
6
11
|
/**
|
|
@@ -14,6 +19,24 @@ class DataBackup extends BaseBackup {
|
|
|
14
19
|
|
|
15
20
|
await copy(blockletDataDir, blockletBackupDataDir, { overwrite: true });
|
|
16
21
|
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @description
|
|
25
|
+
* @return {Promise<import('@did-space/core').Object[]>}
|
|
26
|
+
* @memberof DataBackup
|
|
27
|
+
*/
|
|
28
|
+
collectSyncObjects() {
|
|
29
|
+
const blockletDataDir = join(this.serverDir, 'data', this.blocklet.meta.name);
|
|
30
|
+
|
|
31
|
+
const objects = getFolderObjects(blockletDataDir).map((x) => {
|
|
32
|
+
return {
|
|
33
|
+
...x,
|
|
34
|
+
key: join('/data', x.key),
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return objects;
|
|
39
|
+
}
|
|
17
40
|
}
|
|
18
41
|
|
|
19
42
|
module.exports = { DataBackup };
|
|
@@ -1,18 +1,46 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { outputJson } = require('fs-extra');
|
|
2
2
|
const { join } = require('path');
|
|
3
3
|
const states = require('../../../states');
|
|
4
4
|
const { BaseBackup } = require('./base');
|
|
5
|
+
const { getFileObject } = require('../utils/disk');
|
|
5
6
|
|
|
6
7
|
class RoutingRuleBackup extends BaseBackup {
|
|
7
8
|
filename = 'routing_rule.json';
|
|
8
9
|
|
|
10
|
+
/**
|
|
11
|
+
* @description
|
|
12
|
+
* @readonly
|
|
13
|
+
* @returns {string}
|
|
14
|
+
* @memberof RoutingRuleBackup
|
|
15
|
+
*/
|
|
16
|
+
get routingRuleExportPath() {
|
|
17
|
+
return join(this.backupDir, this.filename);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @description
|
|
22
|
+
* @returns {Promise<void>}
|
|
23
|
+
* @memberof RoutingRuleBackup
|
|
24
|
+
*/
|
|
9
25
|
async export() {
|
|
10
26
|
const routingRule = await states.site.findOne({
|
|
11
27
|
domain: `${this.blocklet.meta.did}.blocklet-domain-group`,
|
|
12
28
|
});
|
|
13
29
|
|
|
14
|
-
|
|
15
|
-
|
|
30
|
+
await outputJson(this.routingRuleExportPath, routingRule);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
* @returns {Promise<import('./base').SyncObject[]>}
|
|
36
|
+
* @memberof RoutingRuleBackup
|
|
37
|
+
*/
|
|
38
|
+
async collectSyncObjects() {
|
|
39
|
+
await this.export();
|
|
40
|
+
|
|
41
|
+
const objects = [getFileObject(this.routingRuleExportPath, this.backupDir)];
|
|
42
|
+
|
|
43
|
+
return objects;
|
|
16
44
|
}
|
|
17
45
|
}
|
|
18
46
|
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
const { isValid } = require('@arcblock/did');
|
|
21
21
|
const { BLOCKLET_CONFIGURABLE_KEY, BlockletEvents } = require('@blocklet/constant');
|
|
22
|
-
const { SpaceClient,
|
|
22
|
+
const { SpaceClient, IncrementalBackupBlockletCommand } = require('@did-space/client');
|
|
23
23
|
const { ensureDirSync, existsSync, remove } = require('fs-extra');
|
|
24
24
|
const { isEmpty } = require('lodash');
|
|
25
25
|
const { join, basename } = require('path');
|
|
@@ -90,6 +90,13 @@ class SpacesBackup extends BaseBackup {
|
|
|
90
90
|
|
|
91
91
|
dataBackup;
|
|
92
92
|
|
|
93
|
+
/**
|
|
94
|
+
* @type {import('@did-space/core').Object[]}
|
|
95
|
+
* @description
|
|
96
|
+
* @memberof SpacesBackup
|
|
97
|
+
*/
|
|
98
|
+
syncObjects;
|
|
99
|
+
|
|
93
100
|
/**
|
|
94
101
|
*
|
|
95
102
|
* @param {SpaceBackupInput} input
|
|
@@ -172,7 +179,7 @@ class SpacesBackup extends BaseBackup {
|
|
|
172
179
|
progress: 15,
|
|
173
180
|
});
|
|
174
181
|
|
|
175
|
-
await this.
|
|
182
|
+
this.syncObjects = await this.collectSyncObjects(this.dataBackup, this.storages);
|
|
176
183
|
|
|
177
184
|
this.input.event.emit(BlockletEvents.backupProgress, {
|
|
178
185
|
appDid: this.input.appDid,
|
|
@@ -230,7 +237,7 @@ class SpacesBackup extends BaseBackup {
|
|
|
230
237
|
});
|
|
231
238
|
|
|
232
239
|
const { errorCount, message, statusCode } = await spaceClient.send(
|
|
233
|
-
new
|
|
240
|
+
new IncrementalBackupBlockletCommand({
|
|
234
241
|
appDid: this.blocklet.appDid,
|
|
235
242
|
appName: getAppName(this.blocklet),
|
|
236
243
|
appDescription: getAppDescription(this.blocklet),
|
|
@@ -239,7 +246,7 @@ class SpacesBackup extends BaseBackup {
|
|
|
239
246
|
serverDid,
|
|
240
247
|
signerDid: this.securityContext.signer.address,
|
|
241
248
|
|
|
242
|
-
source:
|
|
249
|
+
source: this.syncObjects,
|
|
243
250
|
debug: true,
|
|
244
251
|
concurrency: 8,
|
|
245
252
|
retryCount: 10,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
1
|
const fs = require('fs-extra');
|
|
3
|
-
|
|
2
|
+
const { join, basename } = require('path');
|
|
4
3
|
const logger = require('@abtnode/logger')('@abtnode/core:storage:utils:disk');
|
|
5
4
|
|
|
6
5
|
const backupDirName = '_abtnode/backup';
|
|
@@ -12,12 +11,12 @@ const restoreDirName = 'tmp/restore-disk';
|
|
|
12
11
|
* @return {any[]}
|
|
13
12
|
*/
|
|
14
13
|
const getBackupList = (dataDir) => {
|
|
15
|
-
const baseBackupDir =
|
|
14
|
+
const baseBackupDir = join(dataDir, backupDirName);
|
|
16
15
|
const backupList = [];
|
|
17
16
|
const appDidList = fs.existsSync(baseBackupDir) ? fs.readdirSync(baseBackupDir) : [];
|
|
18
17
|
|
|
19
18
|
appDidList.forEach((appDid) => {
|
|
20
|
-
const metaFile =
|
|
19
|
+
const metaFile = join(baseBackupDir, appDid, 'meta.json');
|
|
21
20
|
if (fs.existsSync(metaFile)) {
|
|
22
21
|
try {
|
|
23
22
|
const meta = fs.readJsonSync(metaFile);
|
|
@@ -41,8 +40,8 @@ const getBackupList = (dataDir) => {
|
|
|
41
40
|
*/
|
|
42
41
|
const removeBackup = async (dataDir, appDid) => {
|
|
43
42
|
try {
|
|
44
|
-
const baseBackupDir =
|
|
45
|
-
const backupDir =
|
|
43
|
+
const baseBackupDir = join(dataDir, backupDirName);
|
|
44
|
+
const backupDir = join(baseBackupDir, appDid);
|
|
46
45
|
if (fs.existsSync(backupDir)) {
|
|
47
46
|
await fs.remove(backupDir);
|
|
48
47
|
return true;
|
|
@@ -55,9 +54,9 @@ const removeBackup = async (dataDir, appDid) => {
|
|
|
55
54
|
};
|
|
56
55
|
|
|
57
56
|
const getBackupDirs = (serverDir, appDid) => {
|
|
58
|
-
const baseBackupDir =
|
|
59
|
-
const backupDir =
|
|
60
|
-
const restoreDir =
|
|
57
|
+
const baseBackupDir = join(serverDir, 'data', backupDirName, appDid);
|
|
58
|
+
const backupDir = join(baseBackupDir, appDid);
|
|
59
|
+
const restoreDir = join(serverDir, restoreDirName, appDid);
|
|
61
60
|
return {
|
|
62
61
|
baseBackupDir,
|
|
63
62
|
backupDir,
|
|
@@ -83,7 +82,7 @@ function getFolderSize(folderPath) {
|
|
|
83
82
|
} else if (stats.isDirectory()) {
|
|
84
83
|
const files = fs.readdirSync(currentPath);
|
|
85
84
|
files.forEach((file) => {
|
|
86
|
-
const filePath =
|
|
85
|
+
const filePath = join(currentPath, file);
|
|
87
86
|
stack.push(filePath);
|
|
88
87
|
});
|
|
89
88
|
}
|
|
@@ -92,9 +91,77 @@ function getFolderSize(folderPath) {
|
|
|
92
91
|
return totalSize;
|
|
93
92
|
}
|
|
94
93
|
|
|
94
|
+
/**
|
|
95
|
+
* @description
|
|
96
|
+
* @param {string} path
|
|
97
|
+
* @return {import('@did-space/core').Object[]}
|
|
98
|
+
*/
|
|
99
|
+
function getFolderObjects(path) {
|
|
100
|
+
/**
|
|
101
|
+
* @type {import('@did-space/core').Object[]}
|
|
102
|
+
*/
|
|
103
|
+
const objects = [];
|
|
104
|
+
const stack = [path];
|
|
105
|
+
|
|
106
|
+
while (stack.length) {
|
|
107
|
+
const absolutePath = stack.pop();
|
|
108
|
+
const stats = fs.statSync(absolutePath);
|
|
109
|
+
|
|
110
|
+
if (stats.isFile()) {
|
|
111
|
+
const key = absolutePath.replace(path, '');
|
|
112
|
+
|
|
113
|
+
objects.push({
|
|
114
|
+
key,
|
|
115
|
+
name: basename(key),
|
|
116
|
+
isDir: false,
|
|
117
|
+
size: stats.size,
|
|
118
|
+
lastModified: new Date(stats.mtime).getTime(),
|
|
119
|
+
editable: true,
|
|
120
|
+
absolutePath,
|
|
121
|
+
});
|
|
122
|
+
} else if (stats.isDirectory()) {
|
|
123
|
+
const files = fs.readdirSync(absolutePath);
|
|
124
|
+
files.forEach((file) => {
|
|
125
|
+
const filePath = join(absolutePath, file);
|
|
126
|
+
stack.push(filePath);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return objects;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* @description
|
|
136
|
+
* @param {string} absolutePath
|
|
137
|
+
* @param {string} [prefix='']
|
|
138
|
+
* @return {import('@did-space/core').Object}
|
|
139
|
+
*/
|
|
140
|
+
function getFileObject(absolutePath, prefix = '') {
|
|
141
|
+
const stats = fs.statSync(absolutePath);
|
|
142
|
+
|
|
143
|
+
if (!stats.isFile()) {
|
|
144
|
+
throw new Error(`Path ${absolutePath} is not a path to a file`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const key = absolutePath.replace(prefix, '');
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
key,
|
|
151
|
+
name: basename(key),
|
|
152
|
+
isDir: false,
|
|
153
|
+
size: stats.size,
|
|
154
|
+
lastModified: new Date(stats.mtime).getTime(),
|
|
155
|
+
editable: true,
|
|
156
|
+
absolutePath,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
95
160
|
module.exports = {
|
|
96
161
|
getBackupList,
|
|
97
162
|
removeBackup,
|
|
98
163
|
getBackupDirs,
|
|
99
164
|
getFolderSize,
|
|
165
|
+
getFolderObjects,
|
|
166
|
+
getFileObject,
|
|
100
167
|
};
|
package/lib/util/blocklet.js
CHANGED
|
@@ -1525,7 +1525,10 @@ const checkDuplicateMountPoint = (blocklet, mountPoint) => {
|
|
|
1525
1525
|
}
|
|
1526
1526
|
|
|
1527
1527
|
for (const component of blocklet.children || []) {
|
|
1528
|
-
if (
|
|
1528
|
+
if (
|
|
1529
|
+
hasStartEngine(component.meta) &&
|
|
1530
|
+
normalizePathPrefix(component.mountPoint) === normalizePathPrefix(mountPoint)
|
|
1531
|
+
) {
|
|
1529
1532
|
throw err;
|
|
1530
1533
|
}
|
|
1531
1534
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const { Joi, titleSchema, descriptionSchema } = require('@blocklet/meta/lib/schema');
|
|
2
2
|
const { PROJECT } = require('@blocklet/constant');
|
|
3
3
|
|
|
4
|
-
const note = Joi.string().min(1).max(
|
|
5
|
-
const blockletIntroduction = Joi.string().max(
|
|
4
|
+
const note = Joi.string().min(1).max(PROJECT.MAX_NOTE_LENGTH);
|
|
5
|
+
const blockletIntroduction = Joi.string().max(PROJECT.MAX_INTRO_LENGTH).allow('').allow(null);
|
|
6
6
|
const blockletScreenshots = Joi.array().items(Joi.string().min(1).max(200));
|
|
7
7
|
const blockletLogo = Joi.string().max(200).allow(null).allow('');
|
|
8
8
|
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.16.17-beta-
|
|
6
|
+
"version": "1.16.17-beta-4f13d99d",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,39 +19,39 @@
|
|
|
19
19
|
"author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
|
|
20
20
|
"license": "Apache-2.0",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@abtnode/analytics": "1.16.17-beta-
|
|
23
|
-
"@abtnode/auth": "1.16.17-beta-
|
|
24
|
-
"@abtnode/certificate-manager": "1.16.17-beta-
|
|
25
|
-
"@abtnode/constant": "1.16.17-beta-
|
|
26
|
-
"@abtnode/cron": "1.16.17-beta-
|
|
27
|
-
"@abtnode/logger": "1.16.17-beta-
|
|
28
|
-
"@abtnode/models": "1.16.17-beta-
|
|
29
|
-
"@abtnode/queue": "1.16.17-beta-
|
|
30
|
-
"@abtnode/rbac": "1.16.17-beta-
|
|
31
|
-
"@abtnode/router-provider": "1.16.17-beta-
|
|
32
|
-
"@abtnode/static-server": "1.16.17-beta-
|
|
33
|
-
"@abtnode/timemachine": "1.16.17-beta-
|
|
34
|
-
"@abtnode/util": "1.16.17-beta-
|
|
35
|
-
"@arcblock/did": "1.18.
|
|
36
|
-
"@arcblock/did-auth": "1.18.
|
|
37
|
-
"@arcblock/did-ext": "^1.18.
|
|
22
|
+
"@abtnode/analytics": "1.16.17-beta-4f13d99d",
|
|
23
|
+
"@abtnode/auth": "1.16.17-beta-4f13d99d",
|
|
24
|
+
"@abtnode/certificate-manager": "1.16.17-beta-4f13d99d",
|
|
25
|
+
"@abtnode/constant": "1.16.17-beta-4f13d99d",
|
|
26
|
+
"@abtnode/cron": "1.16.17-beta-4f13d99d",
|
|
27
|
+
"@abtnode/logger": "1.16.17-beta-4f13d99d",
|
|
28
|
+
"@abtnode/models": "1.16.17-beta-4f13d99d",
|
|
29
|
+
"@abtnode/queue": "1.16.17-beta-4f13d99d",
|
|
30
|
+
"@abtnode/rbac": "1.16.17-beta-4f13d99d",
|
|
31
|
+
"@abtnode/router-provider": "1.16.17-beta-4f13d99d",
|
|
32
|
+
"@abtnode/static-server": "1.16.17-beta-4f13d99d",
|
|
33
|
+
"@abtnode/timemachine": "1.16.17-beta-4f13d99d",
|
|
34
|
+
"@abtnode/util": "1.16.17-beta-4f13d99d",
|
|
35
|
+
"@arcblock/did": "1.18.92",
|
|
36
|
+
"@arcblock/did-auth": "1.18.92",
|
|
37
|
+
"@arcblock/did-ext": "^1.18.92",
|
|
38
38
|
"@arcblock/did-motif": "^1.1.13",
|
|
39
|
-
"@arcblock/did-util": "1.18.
|
|
40
|
-
"@arcblock/event-hub": "1.18.
|
|
41
|
-
"@arcblock/jwt": "^1.18.
|
|
39
|
+
"@arcblock/did-util": "1.18.92",
|
|
40
|
+
"@arcblock/event-hub": "1.18.92",
|
|
41
|
+
"@arcblock/jwt": "^1.18.92",
|
|
42
42
|
"@arcblock/pm2-events": "^0.0.5",
|
|
43
|
-
"@arcblock/validator": "^1.18.
|
|
44
|
-
"@arcblock/vc": "1.18.
|
|
45
|
-
"@blocklet/constant": "1.16.17-beta-
|
|
46
|
-
"@blocklet/env": "1.16.17-beta-
|
|
47
|
-
"@blocklet/meta": "1.16.17-beta-
|
|
48
|
-
"@blocklet/resolver": "1.16.17-beta-
|
|
49
|
-
"@blocklet/sdk": "1.16.17-beta-
|
|
50
|
-
"@did-space/client": "^0.3.
|
|
43
|
+
"@arcblock/validator": "^1.18.92",
|
|
44
|
+
"@arcblock/vc": "1.18.92",
|
|
45
|
+
"@blocklet/constant": "1.16.17-beta-4f13d99d",
|
|
46
|
+
"@blocklet/env": "1.16.17-beta-4f13d99d",
|
|
47
|
+
"@blocklet/meta": "1.16.17-beta-4f13d99d",
|
|
48
|
+
"@blocklet/resolver": "1.16.17-beta-4f13d99d",
|
|
49
|
+
"@blocklet/sdk": "1.16.17-beta-4f13d99d",
|
|
50
|
+
"@did-space/client": "^0.3.11",
|
|
51
51
|
"@fidm/x509": "^1.2.1",
|
|
52
|
-
"@ocap/mcrypto": "1.18.
|
|
53
|
-
"@ocap/util": "1.18.
|
|
54
|
-
"@ocap/wallet": "1.18.
|
|
52
|
+
"@ocap/mcrypto": "1.18.92",
|
|
53
|
+
"@ocap/util": "1.18.92",
|
|
54
|
+
"@ocap/wallet": "1.18.92",
|
|
55
55
|
"@slack/webhook": "^5.0.4",
|
|
56
56
|
"archiver": "^5.3.1",
|
|
57
57
|
"axios": "^0.27.2",
|
|
@@ -101,5 +101,5 @@
|
|
|
101
101
|
"jest": "^27.5.1",
|
|
102
102
|
"unzipper": "^0.10.11"
|
|
103
103
|
},
|
|
104
|
-
"gitHead": "
|
|
104
|
+
"gitHead": "005478c4b14448f2ae896ae363972afbde1d7e7b"
|
|
105
105
|
}
|