@abtnode/core 1.8.65-beta-f7af64a4 → 1.8.65-beta-bfcc12ce
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/blocklet/downloader/blocklet-downloader.js +33 -12
- package/lib/blocklet/manager/disk.js +163 -93
- package/lib/blocklet/manager/helper/install-from-backup.js +11 -4
- package/lib/blocklet/manager/helper/rollback-cache.js +41 -0
- package/lib/blocklet/storage/backup/blocklet-extras.js +4 -0
- package/lib/blocklet/storage/backup/blocklets.js +23 -29
- package/lib/blocklet/storage/backup/data.js +2 -2
- package/lib/blocklet/storage/backup/logs.js +3 -2
- package/lib/blocklet/storage/backup/spaces.js +3 -14
- package/lib/blocklet/storage/restore/blocklet-extras.js +8 -3
- package/lib/blocklet/storage/restore/blocklets.js +29 -11
- package/lib/blocklet/storage/restore/logs.js +21 -0
- package/lib/blocklet/storage/restore/spaces.js +6 -1
- package/lib/blocklet/storage/utils/hash.js +51 -0
- package/lib/blocklet/storage/utils/zip.js +43 -0
- package/lib/router/helper.js +64 -12
- package/lib/router/index.js +4 -0
- package/lib/states/blocklet.js +2 -2
- package/lib/util/blocklet.js +1 -1
- package/package.json +27 -25
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
const {
|
|
2
|
-
const
|
|
3
|
-
const archiver = require('archiver');
|
|
1
|
+
const { join } = require('path');
|
|
2
|
+
const validUrl = require('valid-url');
|
|
4
3
|
const { BaseBackup } = require('./base');
|
|
4
|
+
const { dirToZip } = require('../utils/zip');
|
|
5
|
+
const { compareAndMove } = require('../utils/hash');
|
|
5
6
|
|
|
6
7
|
class BlockletsBackup extends BaseBackup {
|
|
7
8
|
/**
|
|
@@ -13,21 +14,25 @@ class BlockletsBackup extends BaseBackup {
|
|
|
13
14
|
const blockletMetas = this.getBlockletMetas(this.blocklet);
|
|
14
15
|
const serverBlockletsDir = join(this.serverDataDir, 'blocklets');
|
|
15
16
|
|
|
17
|
+
const blockletMetasFromLocal = blockletMetas.filter(
|
|
18
|
+
(b) => !validUrl.isHttpUri(b.tarball) && !validUrl.isHttpsUri(b.tarball)
|
|
19
|
+
);
|
|
20
|
+
|
|
16
21
|
const dirs = [];
|
|
17
|
-
for (const blockletMeta of
|
|
22
|
+
for (const blockletMeta of blockletMetasFromLocal) {
|
|
18
23
|
const sourceDir = join(serverBlockletsDir, blockletMeta.name, blockletMeta.version);
|
|
19
|
-
const
|
|
20
|
-
dirs.push({ sourceDir,
|
|
24
|
+
const zipPath = join(this.blockletBackupDir, 'blocklets', blockletMeta.name, `${blockletMeta.version}.zip`);
|
|
25
|
+
dirs.push({ sourceDir, zipPath });
|
|
21
26
|
}
|
|
22
27
|
|
|
23
|
-
await this.dirsToZip(dirs
|
|
28
|
+
await this.dirsToZip(dirs);
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
/**
|
|
27
32
|
*
|
|
28
33
|
*
|
|
29
34
|
* @param {import('@abtnode/client').BlockletState} blocklet
|
|
30
|
-
* @returns {Array<{name: string, version: string}>}
|
|
35
|
+
* @returns {Array<{name: string, version: string, tarball: string}>}
|
|
31
36
|
* @memberof BlockletsBackup
|
|
32
37
|
*/
|
|
33
38
|
getBlockletMetas(blocklet) {
|
|
@@ -39,6 +44,7 @@ class BlockletsBackup extends BaseBackup {
|
|
|
39
44
|
metas.push({
|
|
40
45
|
name: blocklet.meta.bundleName,
|
|
41
46
|
version: blocklet.meta.version,
|
|
47
|
+
tarball: blocklet?.meta?.dist?.tarball,
|
|
42
48
|
});
|
|
43
49
|
|
|
44
50
|
for (const child of blocklet.children) {
|
|
@@ -49,31 +55,19 @@ class BlockletsBackup extends BaseBackup {
|
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
/**
|
|
52
|
-
* @param {Array<{sourceDir: string,
|
|
58
|
+
* @param {Array<{sourceDir: string, zipPath: string}>} dirs: /some/folder/to/compress
|
|
53
59
|
* @param {String} zipPath: /path/to/created.zip
|
|
54
60
|
* @returns {Promise}
|
|
55
61
|
* @memberof BlockletsBackup
|
|
56
62
|
*/
|
|
57
|
-
async dirsToZip(dirs
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return new Promise((resolve, reject) => {
|
|
67
|
-
archive.on('error', (err) => reject(err));
|
|
68
|
-
stream.on('close', () => resolve());
|
|
69
|
-
|
|
70
|
-
for (const dir of dirs) {
|
|
71
|
-
archive.directory(dir.sourceDir, dir.destDir);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
archive.pipe(stream);
|
|
75
|
-
archive.finalize();
|
|
76
|
-
});
|
|
63
|
+
async dirsToZip(dirs) {
|
|
64
|
+
await Promise.all(
|
|
65
|
+
dirs.map(async (dir) => {
|
|
66
|
+
const tempZipPath = `${dir.zipPath}.bak`;
|
|
67
|
+
await dirToZip(dir.sourceDir, tempZipPath);
|
|
68
|
+
await compareAndMove(dir.zipPath, tempZipPath);
|
|
69
|
+
})
|
|
70
|
+
);
|
|
77
71
|
}
|
|
78
72
|
}
|
|
79
73
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { copy } = require('fs-extra');
|
|
2
2
|
const { join } = require('path');
|
|
3
3
|
const { BaseBackup } = require('./base');
|
|
4
4
|
|
|
@@ -12,7 +12,7 @@ class DataBackup extends BaseBackup {
|
|
|
12
12
|
const blockletDataDir = join(this.serverDataDir, 'data', this.blocklet.meta.name);
|
|
13
13
|
const blockletBackupDataDir = join(this.blockletBackupDir, 'data');
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
await copy(blockletDataDir, blockletBackupDataDir, { overwrite: true });
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
const { ensureDirSync,
|
|
1
|
+
const { ensureDirSync, copy, statSync } = require('fs-extra');
|
|
2
2
|
const { join } = require('path');
|
|
3
3
|
const { BaseBackup } = require('./base');
|
|
4
4
|
|
|
5
|
+
// note: 可以不需要备份
|
|
5
6
|
class LogsBackup extends BaseBackup {
|
|
6
7
|
async export() {
|
|
7
8
|
const sourceLogsDir = join(this.serverDataDir, 'logs', this.blocklet.meta.name);
|
|
@@ -9,7 +10,7 @@ class LogsBackup extends BaseBackup {
|
|
|
9
10
|
|
|
10
11
|
const targetLogsDir = join(this.blockletBackupDir, 'logs');
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
await copy(sourceLogsDir, targetLogsDir, {
|
|
13
14
|
overwrite: true,
|
|
14
15
|
filter: (src) => {
|
|
15
16
|
return !statSync(src).isSymbolicLink();
|
|
@@ -8,7 +8,7 @@ const { isValid } = require('@arcblock/did');
|
|
|
8
8
|
const { BLOCKLET_CONFIGURABLE_KEY } = require('@blocklet/constant');
|
|
9
9
|
const { getBlockletInfo } = require('@blocklet/meta');
|
|
10
10
|
const { SpaceClient, SyncFolderPushCommand } = require('@did-space/client');
|
|
11
|
-
const { ensureDirSync
|
|
11
|
+
const { ensureDirSync } = require('fs-extra');
|
|
12
12
|
const { isEmpty } = require('lodash');
|
|
13
13
|
const { join } = require('path');
|
|
14
14
|
const states = require('../../../states');
|
|
@@ -17,7 +17,6 @@ const { BlockletBackup } = require('./blocklet');
|
|
|
17
17
|
const { BlockletExtrasBackup } = require('./blocklet-extras');
|
|
18
18
|
const { BlockletsBackup } = require('./blocklets');
|
|
19
19
|
const { DataBackup } = require('./data');
|
|
20
|
-
const { LogsBackup } = require('./logs');
|
|
21
20
|
const { RoutingRuleBackup } = require('./routing-rule');
|
|
22
21
|
|
|
23
22
|
class SpacesBackup {
|
|
@@ -78,7 +77,6 @@ class SpacesBackup {
|
|
|
78
77
|
this.input = input;
|
|
79
78
|
this.storages = [
|
|
80
79
|
new AuditLogBackup(this.input),
|
|
81
|
-
new LogsBackup(this.input),
|
|
82
80
|
new BlockletBackup(this.input),
|
|
83
81
|
new BlockletsBackup(this.input),
|
|
84
82
|
new BlockletExtrasBackup(this.input),
|
|
@@ -107,7 +105,6 @@ class SpacesBackup {
|
|
|
107
105
|
await this.initialize();
|
|
108
106
|
await this.export();
|
|
109
107
|
await this.syncToSpaces();
|
|
110
|
-
await this.destroy();
|
|
111
108
|
}
|
|
112
109
|
|
|
113
110
|
async initialize() {
|
|
@@ -121,9 +118,6 @@ class SpacesBackup {
|
|
|
121
118
|
this.serverDataDir = process.env.ABT_NODE_DATA_DIR;
|
|
122
119
|
|
|
123
120
|
this.blockletBackupDir = join(process.env.ABT_NODE_DATA_DIR, 'tmp/backup', this.blocklet.meta.did);
|
|
124
|
-
if (existsSync(this.blockletBackupDir)) {
|
|
125
|
-
rmdirSync(this.blockletBackupDir, { recursive: true });
|
|
126
|
-
}
|
|
127
121
|
ensureDirSync(this.blockletBackupDir);
|
|
128
122
|
|
|
129
123
|
this.spacesEndpoint = this.blocklet.environments.find(
|
|
@@ -158,7 +152,8 @@ class SpacesBackup {
|
|
|
158
152
|
source: join(this.blockletBackupDir, '/'),
|
|
159
153
|
target: join('.did-objects', this.blocklet.appDid),
|
|
160
154
|
debug: true,
|
|
161
|
-
|
|
155
|
+
concurrency: 64,
|
|
156
|
+
retryCount: 100,
|
|
162
157
|
filter: (object) => {
|
|
163
158
|
return object.name !== '.DS_Store';
|
|
164
159
|
},
|
|
@@ -176,12 +171,6 @@ class SpacesBackup {
|
|
|
176
171
|
const { wallet } = getBlockletInfo(blockletInfo, nodeInfo.sk);
|
|
177
172
|
return wallet;
|
|
178
173
|
}
|
|
179
|
-
|
|
180
|
-
async destroy() {
|
|
181
|
-
if (existsSync(this.blockletBackupDir)) {
|
|
182
|
-
removeSync(this.blockletBackupDir);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
174
|
}
|
|
186
175
|
|
|
187
176
|
module.exports = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const { removeSync, outputJsonSync, readJSONSync } = require('fs-extra');
|
|
2
|
-
const { cloneDeep } = require('lodash');
|
|
2
|
+
const { cloneDeep, isArray } = require('lodash');
|
|
3
3
|
const { join } = require('path');
|
|
4
4
|
const security = require('@abtnode/util/lib/security');
|
|
5
5
|
const { BaseRestore } = require('./base');
|
|
@@ -61,6 +61,13 @@ class BlockletExtrasRestore extends BaseRestore {
|
|
|
61
61
|
* @memberof BlockletExtrasRestore
|
|
62
62
|
*/
|
|
63
63
|
useBlockletDecryptConfigs(configs) {
|
|
64
|
+
// eslint-disable-next-line no-console
|
|
65
|
+
console.log('debug', configs, !configs || !isArray(configs));
|
|
66
|
+
|
|
67
|
+
if (!configs || !isArray(configs)) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
64
71
|
for (const config of configs) {
|
|
65
72
|
// secure 为 true 的配置才需要被加密保存上次到 did spaces
|
|
66
73
|
if (config.secure) {
|
|
@@ -76,8 +83,6 @@ class BlockletExtrasRestore extends BaseRestore {
|
|
|
76
83
|
config.value = decryptByBlocklet;
|
|
77
84
|
}
|
|
78
85
|
}
|
|
79
|
-
|
|
80
|
-
return configs;
|
|
81
86
|
}
|
|
82
87
|
}
|
|
83
88
|
|
|
@@ -1,23 +1,41 @@
|
|
|
1
|
-
const { existsSync,
|
|
1
|
+
const { existsSync, remove } = require('fs-extra');
|
|
2
2
|
const { join } = require('path');
|
|
3
|
-
const
|
|
3
|
+
const fg = require('fast-glob');
|
|
4
4
|
const { BaseRestore } = require('./base');
|
|
5
|
+
const { zipToDir } = require('../utils/zip');
|
|
5
6
|
|
|
6
7
|
class BlockletsRestore extends BaseRestore {
|
|
7
|
-
filename = 'blocklets
|
|
8
|
+
filename = 'blocklets';
|
|
8
9
|
|
|
9
10
|
async import() {
|
|
10
|
-
const
|
|
11
|
+
const blockletsDir = join(this.blockletRestoreDir, this.filename);
|
|
11
12
|
|
|
12
|
-
if (!existsSync(
|
|
13
|
-
throw new Error(`
|
|
13
|
+
if (!existsSync(blockletsDir)) {
|
|
14
|
+
throw new Error(`dir not found: ${blockletsDir}`);
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
const paths = await fg('**/*.zip', {
|
|
18
|
+
cwd: blockletsDir,
|
|
19
|
+
onlyFiles: true,
|
|
20
|
+
absolute: true,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @type {{source: string, target: string}}
|
|
25
|
+
*/
|
|
26
|
+
const zipConfigs = paths.map((path) => {
|
|
27
|
+
return {
|
|
28
|
+
source: path,
|
|
29
|
+
target: path.replace(/.zip$/, ''),
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
await Promise.all(
|
|
34
|
+
zipConfigs.map(async (zipConfig) => {
|
|
35
|
+
await zipToDir(zipConfig.source, zipConfig.target);
|
|
36
|
+
await remove(zipConfig.source);
|
|
37
|
+
})
|
|
38
|
+
);
|
|
21
39
|
}
|
|
22
40
|
}
|
|
23
41
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const { removeSync, existsSync } = require('fs-extra');
|
|
2
|
+
const { join } = require('path');
|
|
3
|
+
const { BaseRestore } = require('./base');
|
|
4
|
+
const { zipToDir } = require('../utils/zip');
|
|
5
|
+
|
|
6
|
+
class LogsRestore extends BaseRestore {
|
|
7
|
+
filename = 'logs.zip';
|
|
8
|
+
|
|
9
|
+
async import() {
|
|
10
|
+
const blockletZipPath = join(this.blockletRestoreDir, this.filename);
|
|
11
|
+
|
|
12
|
+
if (!existsSync(blockletZipPath)) {
|
|
13
|
+
throw new Error(`file not found: ${blockletZipPath}`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
await zipToDir(blockletZipPath, join(this.blockletRestoreDir, 'logs'));
|
|
17
|
+
removeSync(blockletZipPath);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = { LogsRestore };
|
|
@@ -74,6 +74,10 @@ class SpacesRestore {
|
|
|
74
74
|
this.serverDataDir = process.env.ABT_NODE_DATA_DIR;
|
|
75
75
|
this.blockletWallet = await this.getBlockletWallet();
|
|
76
76
|
|
|
77
|
+
if (!this.input.endpoint.includes(this.blockletWallet.address)) {
|
|
78
|
+
throw new Error(`endpoint and blocklet.appDid(${this.blockletWallet.address}) do not match`);
|
|
79
|
+
}
|
|
80
|
+
|
|
77
81
|
this.blockletRestoreDir = join(process.env.ABT_NODE_DATA_DIR, 'tmp/restore', this.blockletWallet.address);
|
|
78
82
|
if (existsSync(this.blockletRestoreDir)) {
|
|
79
83
|
rmdirSync(this.blockletRestoreDir, { recursive: true });
|
|
@@ -113,7 +117,8 @@ class SpacesRestore {
|
|
|
113
117
|
source: join('.did-objects', this.blockletWallet.address, '/'),
|
|
114
118
|
target: this.blockletRestoreDir,
|
|
115
119
|
debug: true,
|
|
116
|
-
|
|
120
|
+
concurrency: 64,
|
|
121
|
+
retryCount: 100,
|
|
117
122
|
})
|
|
118
123
|
);
|
|
119
124
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const { removeSync, existsSync, move, createReadStream } = require('fs-extra');
|
|
2
|
+
const hasha = require('hasha');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
*
|
|
7
|
+
* @param {NodeJS.ReadableStream} stream1
|
|
8
|
+
* @param {NodeJS.ReadableStream} stream2
|
|
9
|
+
* @return {Promise<boolean>}
|
|
10
|
+
*/
|
|
11
|
+
async function compareHash(stream1, stream2) {
|
|
12
|
+
const hash1 = await hasha.fromStream(stream1, {
|
|
13
|
+
algorithm: 'md5',
|
|
14
|
+
});
|
|
15
|
+
const hash2 = await hasha.fromStream(stream2, {
|
|
16
|
+
algorithm: 'md5',
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
return hash1 === hash2;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @description 比对新文件和旧文件的hash,旧文件不存在或者hash不同时,使用新文件替换,hash相同,删除新文件
|
|
25
|
+
* @param {string} oldFilePath
|
|
26
|
+
* @param {string} newFilePath
|
|
27
|
+
* @returns {Promise<boolean>}
|
|
28
|
+
*/
|
|
29
|
+
async function compareAndMove(oldFilePath, newFilePath) {
|
|
30
|
+
if (!existsSync(oldFilePath)) {
|
|
31
|
+
await move(newFilePath, oldFilePath, { overwrite: true });
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!existsSync(newFilePath)) {
|
|
36
|
+
throw new Error(`newFilePath(${newFilePath}) not found`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const isSame = await compareHash(createReadStream(oldFilePath), createReadStream(newFilePath));
|
|
40
|
+
if (isSame) {
|
|
41
|
+
removeSync(newFilePath);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
await move(newFilePath, oldFilePath, { overwrite: true });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = {
|
|
49
|
+
compareHash,
|
|
50
|
+
compareAndMove,
|
|
51
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const archiver = require('archiver');
|
|
2
|
+
const { ensureDirSync, existsSync, removeSync, createWriteStream } = require('fs-extra');
|
|
3
|
+
const { dirname } = require('path');
|
|
4
|
+
const StreamZip = require('node-stream-zip');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
*
|
|
9
|
+
* @param {string} source ~/abc/ 通常是一个文件夹
|
|
10
|
+
* @param {string} target abc.zip 压缩包的名称
|
|
11
|
+
* @return {*}
|
|
12
|
+
*/
|
|
13
|
+
function dirToZip(source, target) {
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
ensureDirSync(dirname(target));
|
|
16
|
+
|
|
17
|
+
if (existsSync(target)) {
|
|
18
|
+
removeSync(target);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const output = createWriteStream(target);
|
|
22
|
+
const archive = archiver('zip', { level: 9 });
|
|
23
|
+
archive.on('error', (err) => reject(err));
|
|
24
|
+
output.on('close', () => resolve());
|
|
25
|
+
|
|
26
|
+
archive.directory(source, false);
|
|
27
|
+
|
|
28
|
+
archive.pipe(output);
|
|
29
|
+
archive.finalize();
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function zipToDir(source, target) {
|
|
34
|
+
// eslint-disable-next-line new-cap
|
|
35
|
+
const zip = new StreamZip.async({ file: source });
|
|
36
|
+
await zip.extract(null, target);
|
|
37
|
+
await zip.close();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = {
|
|
41
|
+
dirToZip,
|
|
42
|
+
zipToDir,
|
|
43
|
+
};
|
package/lib/router/helper.js
CHANGED
|
@@ -7,7 +7,7 @@ const get = require('lodash/get');
|
|
|
7
7
|
const cloneDeep = require('lodash/cloneDeep');
|
|
8
8
|
const isEqual = require('lodash/isEqual');
|
|
9
9
|
const joinUrl = require('url-join');
|
|
10
|
-
const { replaceSlotToIp } = require('@blocklet/meta/lib/util');
|
|
10
|
+
const { replaceSlotToIp, findComponentById, findWebInterface } = require('@blocklet/meta/lib/util');
|
|
11
11
|
const { getProvider } = require('@abtnode/router-provider');
|
|
12
12
|
const normalizePathPrefix = require('@abtnode/util/lib/normalize-path-prefix');
|
|
13
13
|
const getTmpDir = require('@abtnode/util/lib/get-tmp-directory');
|
|
@@ -41,9 +41,11 @@ const {
|
|
|
41
41
|
const {
|
|
42
42
|
BLOCKLET_DYNAMIC_PATH_PREFIX,
|
|
43
43
|
BLOCKLET_INTERFACE_TYPE_WEB,
|
|
44
|
+
BLOCKLET_INTERFACE_PUBLIC,
|
|
44
45
|
BLOCKLET_INTERFACE_WELLKNOWN,
|
|
45
46
|
BLOCKLET_INTERFACE_TYPE_WELLKNOWN,
|
|
46
47
|
BlockletEvents,
|
|
48
|
+
BLOCKLET_MODES,
|
|
47
49
|
} = require('@blocklet/constant');
|
|
48
50
|
|
|
49
51
|
// eslint-disable-next-line global-require
|
|
@@ -206,6 +208,9 @@ const ensureLatestInterfaceInfo = async (sites = []) => {
|
|
|
206
208
|
}
|
|
207
209
|
|
|
208
210
|
site.rules = site.rules.map((rule) => {
|
|
211
|
+
if (rule.dynamic) {
|
|
212
|
+
return rule;
|
|
213
|
+
}
|
|
209
214
|
// If a rule already has a target and target is WELLKNOWN_SERVICE_PATH_PREFIX, just return
|
|
210
215
|
// Indicates that the rule id generated by the system for auth service
|
|
211
216
|
if (rule.isProtected && rule.to.target === WELLKNOWN_SERVICE_PATH_PREFIX) {
|
|
@@ -279,6 +284,7 @@ const ensureWellknownRule = async (sites) => {
|
|
|
279
284
|
rule.from.pathPrefix = servicePathPrefix;
|
|
280
285
|
rule.to.target = servicePathPrefix;
|
|
281
286
|
rule.isProtected = true;
|
|
287
|
+
rule.dynamic = true; // mark as dynamic to avoid redundant generated rules
|
|
282
288
|
site.rules.push(rule);
|
|
283
289
|
}
|
|
284
290
|
|
|
@@ -290,6 +296,7 @@ const ensureWellknownRule = async (sites) => {
|
|
|
290
296
|
rule.to.cacheGroup = 'blockletProxy';
|
|
291
297
|
rule.to.target = avatarPathPrefix;
|
|
292
298
|
rule.isProtected = true;
|
|
299
|
+
rule.dynamic = true; // mark as dynamic to avoid redundant generated rules
|
|
293
300
|
site.rules.push(rule);
|
|
294
301
|
}
|
|
295
302
|
}
|
|
@@ -312,7 +319,7 @@ const ensureBlockletDid = async (sites) => {
|
|
|
312
319
|
return site;
|
|
313
320
|
}
|
|
314
321
|
|
|
315
|
-
site.blockletDid = site.domain
|
|
322
|
+
site.blockletDid = getDidFromDomainGroupName(site.domain);
|
|
316
323
|
|
|
317
324
|
return site;
|
|
318
325
|
});
|
|
@@ -329,30 +336,76 @@ const ensureCorsForWebWallet = async (sites) => {
|
|
|
329
336
|
return sites;
|
|
330
337
|
};
|
|
331
338
|
|
|
332
|
-
const filterSitesForRemovedBlocklets = async (sites = []) => {
|
|
333
|
-
const blocklets = await states.blocklet.getBlocklets();
|
|
339
|
+
const filterSitesForRemovedBlocklets = async (sites = [], blocklets) => {
|
|
334
340
|
return sites.filter((site) => {
|
|
335
341
|
if (!site.domain.endsWith(BLOCKLET_SITE_GROUP_SUFFIX)) {
|
|
336
342
|
return true;
|
|
337
343
|
}
|
|
338
344
|
|
|
339
|
-
const
|
|
340
|
-
const blocklet = blocklets.find((x) => x.meta.did === did);
|
|
341
|
-
if (blocklet) {
|
|
342
|
-
site.mode = blocklet.mode;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
+
const blocklet = blocklets.find((x) => x.meta.did === site.blockletDid);
|
|
345
346
|
return !!blocklet;
|
|
346
347
|
});
|
|
347
348
|
};
|
|
348
349
|
|
|
350
|
+
const ensureBlockletCache = async (sites = [], blocklets) => {
|
|
351
|
+
return sites
|
|
352
|
+
.map((site) => {
|
|
353
|
+
if (!site.domain.endsWith(BLOCKLET_SITE_GROUP_SUFFIX)) {
|
|
354
|
+
return site;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (site.cacheableGenerated) {
|
|
358
|
+
return site;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// For each rule, get component, check cacheable, clone and push new rule
|
|
362
|
+
const blocklet = blocklets.find((x) => x.meta.did === site.blockletDid);
|
|
363
|
+
const cacheRules = [];
|
|
364
|
+
site.rules
|
|
365
|
+
.filter(
|
|
366
|
+
(x) =>
|
|
367
|
+
x.to.type === ROUTING_RULE_TYPES.BLOCKLET &&
|
|
368
|
+
x.to.interfaceName === BLOCKLET_INTERFACE_PUBLIC &&
|
|
369
|
+
x.from.pathPrefix.startsWith(WELLKNOWN_SERVICE_PATH_PREFIX) === false
|
|
370
|
+
)
|
|
371
|
+
.forEach((rule) => {
|
|
372
|
+
const component = findComponentById(blocklet, rule.to.componentId);
|
|
373
|
+
if (component.mode !== BLOCKLET_MODES.PRODUCTION) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
const cacheable = get(findWebInterface(component), 'cacheable', []);
|
|
377
|
+
cacheable.forEach((cachePrefix) => {
|
|
378
|
+
const clone = cloneDeep(rule);
|
|
379
|
+
clone.from.pathPrefix = joinUrl(rule.from.pathPrefix, cachePrefix);
|
|
380
|
+
clone.to.cacheGroup = 'blockletProxy';
|
|
381
|
+
clone.to.target = cachePrefix;
|
|
382
|
+
clone.dynamic = true; // mark as dynamic to avoid redundant generated rules
|
|
383
|
+
cacheRules.push(clone);
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
site.rules = site.rules.concat(cacheRules);
|
|
388
|
+
site.mode = blocklet.mode;
|
|
389
|
+
site.cacheableGenerated = true;
|
|
390
|
+
|
|
391
|
+
return site;
|
|
392
|
+
})
|
|
393
|
+
.filter(Boolean);
|
|
394
|
+
};
|
|
395
|
+
|
|
349
396
|
const ensureLatestInfo = async (sites = [], { withDefaultCors = true } = {}) => {
|
|
397
|
+
const blocklets = await states.blocklet.getBlocklets();
|
|
398
|
+
|
|
399
|
+
// CAUTION: following steps are very important, please do not change the order
|
|
350
400
|
let result = await ensureLatestNodeInfo(sites, { withDefaultCors });
|
|
351
401
|
result = await ensureBlockletDid(result);
|
|
402
|
+
result = await filterSitesForRemovedBlocklets(sites, blocklets);
|
|
403
|
+
result = await ensureBlockletCache(result, blocklets);
|
|
352
404
|
result = await ensureWellknownRule(result);
|
|
353
405
|
result = await ensureCorsForWebWallet(result);
|
|
406
|
+
result = await ensureLatestInterfaceInfo(result);
|
|
354
407
|
|
|
355
|
-
return
|
|
408
|
+
return result;
|
|
356
409
|
};
|
|
357
410
|
|
|
358
411
|
const decompressCertificates = async (source, dest) => {
|
|
@@ -1064,7 +1117,6 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
1064
1117
|
try {
|
|
1065
1118
|
const info = await nodeState.read();
|
|
1066
1119
|
let { sites } = await readRoutingSites();
|
|
1067
|
-
sites = await filterSitesForRemovedBlocklets(sites);
|
|
1068
1120
|
sites = await ensureLatestInfo(sites);
|
|
1069
1121
|
sites = await ensureServiceRule(sites);
|
|
1070
1122
|
sites = await ensureRootRule(sites);
|
package/lib/router/index.js
CHANGED
package/lib/states/blocklet.js
CHANGED
|
@@ -92,7 +92,7 @@ class BlockletState extends BaseState {
|
|
|
92
92
|
this.defaultPort = config.blockletPort || 5555;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
getBlocklet(did) {
|
|
95
|
+
getBlocklet(did, { decryptSk = true } = {}) {
|
|
96
96
|
return new Promise((resolve, reject) => {
|
|
97
97
|
if (!did) {
|
|
98
98
|
resolve(null);
|
|
@@ -103,7 +103,7 @@ class BlockletState extends BaseState {
|
|
|
103
103
|
return reject(err);
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
return resolve(doc ? formatBlocklet(doc, 'onRead', this.config.dek) : null);
|
|
106
|
+
return resolve(doc ? formatBlocklet(doc, 'onRead', decryptSk ? this.config.dek : null) : null);
|
|
107
107
|
});
|
|
108
108
|
});
|
|
109
109
|
}
|
package/lib/util/blocklet.js
CHANGED
|
@@ -931,7 +931,7 @@ const verifyIntegrity = async ({ file, integrity: expected }) => {
|
|
|
931
931
|
|
|
932
932
|
/**
|
|
933
933
|
* @param {string} installDir
|
|
934
|
-
* @returns {Array<{ key: <[scope/]name/version>, dir
|
|
934
|
+
* @returns {Promise<Array<{ key: string, dir: string }>>} key is <[scope/]name/version>, dir is appDir
|
|
935
935
|
*/
|
|
936
936
|
const getAppDirs = async (installDir) => {
|
|
937
937
|
const appDirs = [];
|