@abtnode/core 1.15.17 → 1.16.0-beta-8ee536d7
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/node.js +67 -69
- package/lib/api/team.js +386 -55
- package/lib/blocklet/downloader/blocklet-downloader.js +226 -0
- package/lib/blocklet/downloader/bundle-downloader.js +272 -0
- package/lib/blocklet/downloader/constants.js +3 -0
- package/lib/blocklet/downloader/resolve-download.js +199 -0
- package/lib/blocklet/extras.js +83 -26
- package/lib/blocklet/hooks.js +18 -65
- package/lib/blocklet/manager/base.js +10 -16
- package/lib/blocklet/manager/disk.js +1680 -1566
- package/lib/blocklet/manager/helper/install-application-from-backup.js +177 -0
- package/lib/blocklet/manager/helper/install-application-from-dev.js +94 -0
- package/lib/blocklet/manager/helper/install-application-from-general.js +188 -0
- package/lib/blocklet/manager/helper/install-component-from-dev.js +84 -0
- package/lib/blocklet/manager/helper/install-component-from-upload.js +181 -0
- package/lib/blocklet/manager/helper/install-component-from-url.js +173 -0
- package/lib/blocklet/manager/helper/migrate-application-to-struct-v2.js +450 -0
- package/lib/blocklet/manager/helper/rollback-cache.js +41 -0
- package/lib/blocklet/manager/helper/upgrade-components.js +152 -0
- package/lib/blocklet/migration.js +30 -52
- package/lib/blocklet/storage/backup/audit-log.js +27 -0
- package/lib/blocklet/storage/backup/base.js +62 -0
- package/lib/blocklet/storage/backup/blocklet-extras.js +92 -0
- package/lib/blocklet/storage/backup/blocklet.js +70 -0
- package/lib/blocklet/storage/backup/blocklets.js +74 -0
- package/lib/blocklet/storage/backup/data.js +19 -0
- package/lib/blocklet/storage/backup/logs.js +24 -0
- package/lib/blocklet/storage/backup/routing-rule.js +19 -0
- package/lib/blocklet/storage/backup/spaces.js +240 -0
- package/lib/blocklet/storage/restore/base.js +67 -0
- package/lib/blocklet/storage/restore/blocklet-extras.js +86 -0
- package/lib/blocklet/storage/restore/blocklet.js +56 -0
- package/lib/blocklet/storage/restore/blocklets.js +43 -0
- package/lib/blocklet/storage/restore/logs.js +21 -0
- package/lib/blocklet/storage/restore/spaces.js +156 -0
- package/lib/blocklet/storage/utils/hash.js +51 -0
- package/lib/blocklet/storage/utils/zip.js +43 -0
- package/lib/cert.js +206 -0
- package/lib/event.js +237 -64
- package/lib/index.js +191 -83
- package/lib/migrations/1.0.21-update-config.js +1 -1
- package/lib/migrations/1.0.22-max-memory.js +1 -1
- package/lib/migrations/1.0.25.js +1 -1
- package/lib/migrations/1.0.32-update-config.js +1 -1
- package/lib/migrations/1.0.33-blocklets.js +1 -1
- package/lib/migrations/1.5.20-registry.js +15 -0
- package/lib/migrations/1.6.17-blocklet-children.js +48 -0
- package/lib/migrations/1.6.21-rename-ip-echo-domain.js +35 -0
- package/lib/migrations/1.6.4-security.js +59 -0
- package/lib/migrations/1.6.5-security.js +60 -0
- package/lib/migrations/1.6.9-update-node-info-and-certificate.js +38 -0
- package/lib/migrations/1.7.1-blocklet-setup.js +18 -0
- package/lib/migrations/1.7.12-blocklet-meta.js +51 -0
- package/lib/migrations/1.7.15-blocklet-bundle-source.js +42 -0
- package/lib/migrations/1.7.20-blocklet-component.js +41 -0
- package/lib/migrations/1.8.33-blocklet-mem-limit.js +20 -0
- package/lib/migrations/README.md +1 -1
- package/lib/migrations/index.js +6 -2
- package/lib/monitor/blocklet-runtime-monitor.js +200 -0
- package/lib/monitor/get-history-list.js +37 -0
- package/lib/monitor/node-runtime-monitor.js +228 -0
- package/lib/router/helper.js +576 -500
- package/lib/router/index.js +85 -21
- package/lib/router/manager.js +146 -187
- package/lib/states/README.md +36 -1
- package/lib/states/access-key.js +39 -17
- package/lib/states/audit-log.js +462 -0
- package/lib/states/base.js +4 -213
- package/lib/states/blocklet-extras.js +195 -138
- package/lib/states/blocklet.js +371 -110
- package/lib/states/cache.js +8 -6
- package/lib/states/challenge.js +5 -5
- package/lib/states/index.js +19 -36
- package/lib/states/migration.js +4 -4
- package/lib/states/node.js +135 -46
- package/lib/states/notification.js +22 -35
- package/lib/states/session.js +17 -9
- package/lib/states/site.js +50 -25
- package/lib/states/user.js +74 -20
- package/lib/states/webhook.js +10 -6
- package/lib/team/manager.js +124 -7
- package/lib/util/blocklet.js +1223 -246
- package/lib/util/chain.js +1 -1
- package/lib/util/default-node-config.js +5 -23
- package/lib/util/disk-monitor.js +13 -10
- package/lib/util/domain-status.js +84 -15
- package/lib/util/get-accessible-external-node-ip.js +2 -2
- package/lib/util/get-domain-for-blocklet.js +13 -0
- package/lib/util/get-meta-from-url.js +33 -0
- package/lib/util/index.js +207 -272
- package/lib/util/ip.js +6 -0
- package/lib/util/maintain.js +233 -0
- package/lib/util/public-to-store.js +85 -0
- package/lib/util/ready.js +1 -1
- package/lib/util/requirement.js +28 -9
- package/lib/util/reset-node.js +22 -7
- package/lib/util/router.js +13 -0
- package/lib/util/rpc.js +16 -0
- package/lib/util/store.js +179 -0
- package/lib/util/sysinfo.js +44 -0
- package/lib/util/ua.js +54 -0
- package/lib/validators/blocklet-extra.js +24 -0
- package/lib/validators/node.js +25 -12
- package/lib/validators/permission.js +16 -1
- package/lib/validators/role.js +17 -3
- package/lib/validators/router.js +40 -20
- package/lib/validators/trusted-passport.js +1 -0
- package/lib/validators/util.js +22 -5
- package/lib/webhook/index.js +45 -35
- package/lib/webhook/sender/index.js +5 -0
- package/lib/webhook/sender/slack/index.js +1 -1
- package/lib/webhook/sender/wallet/index.js +48 -0
- package/package.json +54 -36
- package/lib/blocklet/registry.js +0 -205
- package/lib/states/https-cert.js +0 -67
- package/lib/util/get-ip-dns-domain-for-blocklet.js +0 -19
- package/lib/util/service.js +0 -66
- package/lib/util/upgrade.js +0 -178
- /package/lib/{queue.js → util/queue.js} +0 -0
package/lib/states/blocklet.js
CHANGED
|
@@ -1,83 +1,227 @@
|
|
|
1
|
+
/* eslint-disable no-async-promise-executor */
|
|
1
2
|
/* eslint-disable no-await-in-loop */
|
|
2
3
|
/* eslint-disable function-paren-newline */
|
|
3
4
|
/* eslint-disable no-underscore-dangle */
|
|
4
5
|
const omit = require('lodash/omit');
|
|
5
6
|
const uniq = require('lodash/uniq');
|
|
7
|
+
const cloneDeep = require('lodash/cloneDeep');
|
|
6
8
|
const detectPort = require('detect-port');
|
|
7
9
|
const Lock = require('@abtnode/util/lib/lock');
|
|
10
|
+
const security = require('@abtnode/util/lib/security');
|
|
8
11
|
const { fixPerson, fixInterfaces } = require('@blocklet/meta/lib/fix');
|
|
12
|
+
const { getDisplayName, forEachBlocklet, forEachBlockletSync, forEachChildSync } = require('@blocklet/meta/lib/util');
|
|
9
13
|
const {
|
|
10
14
|
BlockletStatus,
|
|
11
15
|
BlockletSource,
|
|
12
16
|
BLOCKLET_MODES,
|
|
13
17
|
BLOCKLET_DEFAULT_PORT_NAME,
|
|
14
18
|
BLOCKLET_INTERFACE_TYPE_SERVICE,
|
|
15
|
-
} = require('@blocklet/
|
|
19
|
+
} = require('@blocklet/constant');
|
|
20
|
+
const { APP_STRUCT_VERSION } = require('@abtnode/constant');
|
|
16
21
|
|
|
17
22
|
const logger = require('@abtnode/logger')('state-blocklet');
|
|
18
23
|
|
|
19
24
|
const BaseState = require('./base');
|
|
20
|
-
const {
|
|
21
|
-
const { validateBlockletMeta } = require('../util');
|
|
25
|
+
const { checkDuplicateComponents, ensureMeta } = require('../util/blocklet');
|
|
26
|
+
const { validateBlockletMeta } = require('../util/blocklet');
|
|
22
27
|
|
|
23
28
|
const lock = new Lock('blocklet-port-assign-lock');
|
|
24
29
|
|
|
30
|
+
const isHex = (str) => /^0x[0-9a-f]+$/i.test(str);
|
|
25
31
|
const getMaxPort = (ports = {}) => Math.max(Object.values(ports).map(Number));
|
|
26
32
|
|
|
33
|
+
// structV1Did is just for migration purpose and should be removed in the future
|
|
34
|
+
const getConditions = (did) => [{ 'meta.did': did }, { appDid: did }, { appPid: did }, { structV1Did: did }];
|
|
35
|
+
|
|
27
36
|
const getExternalPortsFromMeta = (meta) =>
|
|
28
37
|
(meta.interfaces || []).map((x) => x.port && x.port.external).filter(Boolean);
|
|
29
38
|
|
|
39
|
+
const formatBlocklet = (blocklet, phase, dek) => {
|
|
40
|
+
forEachBlockletSync(blocklet, (b) => {
|
|
41
|
+
if (b.meta) {
|
|
42
|
+
fixPerson(b.meta);
|
|
43
|
+
fixInterfaces(b.meta);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (phase === 'onRead') {
|
|
47
|
+
b.children = b.children || [];
|
|
48
|
+
b.environments = b.environments || [];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!b.environments || !b.meta || !dek) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
(Array.isArray(b.migratedFrom) ? b.migratedFrom : []).forEach((x) => {
|
|
56
|
+
if (phase === 'onUpdate' && isHex(x.appSk) === true) {
|
|
57
|
+
x.appSk = security.encrypt(x.appSk, b.meta.did, dek);
|
|
58
|
+
}
|
|
59
|
+
if (phase === 'onRead' && isHex(x.appSk) === false) {
|
|
60
|
+
x.appSk = security.decrypt(x.appSk, b.meta.did, dek);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
['BLOCKLET_APP_SK', 'BLOCKLET_APP_PSK'].forEach((key) => {
|
|
65
|
+
const env = b.environments.find((x) => x.key === key);
|
|
66
|
+
if (!env) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// salt in blocklet state is different from the salt in blocklet-extra state
|
|
70
|
+
// in blocklet-extra state, salt is app meta did in each component
|
|
71
|
+
// in blocklet state, salt is component meta did in each component
|
|
72
|
+
if (phase === 'onUpdate' && isHex(env.value) === true) {
|
|
73
|
+
env.value = security.encrypt(env.value, b.meta.did, dek);
|
|
74
|
+
}
|
|
75
|
+
if (phase === 'onRead' && isHex(env.value) === false) {
|
|
76
|
+
env.value = security.decrypt(env.value, b.meta.did, dek);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
return blocklet;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const fixChildren = (children) => {
|
|
85
|
+
if (!children) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
children.forEach((child) => {
|
|
90
|
+
child.mode = child.mode || BLOCKLET_MODES.PRODUCTION;
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// type Application = {
|
|
95
|
+
// appDid: DID,
|
|
96
|
+
// appPid: DID,
|
|
97
|
+
// meta: Meta,
|
|
98
|
+
// source: BlockletSource,
|
|
99
|
+
// deployedFrom: string,
|
|
100
|
+
// mode: BLOCKLET_MODES;
|
|
101
|
+
// status: BlockletStatus,
|
|
102
|
+
// children: Component,
|
|
103
|
+
// ports: Ports;
|
|
104
|
+
// mountPoint: string; // deprecated
|
|
105
|
+
// migratedFrom: Array<{ appSk: string, appDid: DID, at: Date }>,
|
|
106
|
+
// externalSk: boolean,
|
|
107
|
+
// structV1Did: DID, // just for migration purpose and should be removed in the future
|
|
108
|
+
// };
|
|
109
|
+
|
|
110
|
+
// type Component = {
|
|
111
|
+
// mountPoint: string;
|
|
112
|
+
// meta: Meta,
|
|
113
|
+
// bundleSource: ComponentSource,
|
|
114
|
+
// source: BlockletSource,
|
|
115
|
+
// deployedFrom: string,
|
|
116
|
+
// mode: BLOCKLET_MODES;
|
|
117
|
+
// status: BlockletStatus,
|
|
118
|
+
// children: Component,
|
|
119
|
+
// ports: Ports;
|
|
120
|
+
// dependents: Array<{
|
|
121
|
+
// did: DID, // blocklet did
|
|
122
|
+
// required: boolean,
|
|
123
|
+
// version: SemverRange,
|
|
124
|
+
// }>;
|
|
125
|
+
// dependencies: Array<{
|
|
126
|
+
// id: string, // format: <did1/did2/did3>
|
|
127
|
+
// required: boolean,
|
|
128
|
+
// }>;
|
|
129
|
+
// dynamic: boolean; // deprecated
|
|
130
|
+
// };
|
|
131
|
+
|
|
132
|
+
// type Ports = {
|
|
133
|
+
// [name: string]: Number; // name is in meta.interfaces[].port
|
|
134
|
+
// };
|
|
135
|
+
|
|
30
136
|
class BlockletState extends BaseState {
|
|
31
137
|
/**
|
|
32
138
|
* Creates an instance of BlockletState
|
|
33
139
|
* @param {string} baseDir
|
|
34
|
-
* @param {object}
|
|
35
|
-
* @param {string}
|
|
140
|
+
* @param {object} config
|
|
141
|
+
* @param {string} config.blockletPort - from which port to start new blocklets
|
|
36
142
|
* @memberof BlockletState
|
|
37
143
|
*/
|
|
38
|
-
constructor(baseDir,
|
|
39
|
-
super(baseDir, { filename: 'blocklet.db', ...
|
|
144
|
+
constructor(baseDir, config = {}) {
|
|
145
|
+
super(baseDir, { filename: 'blocklet.db', ...config });
|
|
40
146
|
|
|
41
|
-
this.defaultPort =
|
|
147
|
+
this.defaultPort = config.blockletPort || 5555;
|
|
42
148
|
}
|
|
43
149
|
|
|
44
|
-
getBlocklet(did) {
|
|
150
|
+
getBlocklet(did, { decryptSk = true } = {}) {
|
|
45
151
|
return new Promise((resolve, reject) => {
|
|
46
|
-
|
|
152
|
+
if (!did) {
|
|
153
|
+
resolve(null);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
this.findOne({ $or: getConditions(did) }, (err, doc) => {
|
|
47
157
|
if (err) {
|
|
48
158
|
return reject(err);
|
|
49
159
|
}
|
|
50
160
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
161
|
+
return resolve(doc ? formatBlocklet(doc, 'onRead', decryptSk ? this.config.dek : null) : null);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
getBlockletMetaDid(did) {
|
|
167
|
+
return new Promise((resolve, reject) => {
|
|
168
|
+
if (!did) {
|
|
169
|
+
resolve(null);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
this.findOne({ $or: getConditions(did) }, (err, doc) => {
|
|
173
|
+
if (err) {
|
|
174
|
+
return reject(err);
|
|
56
175
|
}
|
|
57
176
|
|
|
58
|
-
return resolve(doc);
|
|
177
|
+
return resolve(doc ? doc.meta.did : null);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async getBlockletStatus(did) {
|
|
183
|
+
return new Promise((resolve, reject) => {
|
|
184
|
+
if (!did) {
|
|
185
|
+
resolve(null);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
this.findOne({ $or: getConditions(did) }, { status: 1 }, (err, doc) => {
|
|
189
|
+
if (err) {
|
|
190
|
+
return reject(err);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return resolve(doc ? doc.status : null);
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
hasBlocklet(did) {
|
|
199
|
+
return new Promise((resolve, reject) => {
|
|
200
|
+
if (!did) {
|
|
201
|
+
resolve(false);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
this.count({ $or: getConditions(did) }, (err, count) => {
|
|
205
|
+
if (err) {
|
|
206
|
+
return reject(err);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return resolve(!!count);
|
|
59
210
|
});
|
|
60
211
|
});
|
|
61
212
|
}
|
|
62
213
|
|
|
63
214
|
getBlocklets(query = {}, projection) {
|
|
64
215
|
return new Promise((resolve, reject) => {
|
|
65
|
-
this.
|
|
66
|
-
.
|
|
67
|
-
.sort(
|
|
68
|
-
.exec((err, docs) => {
|
|
216
|
+
this.cursor(query)
|
|
217
|
+
.projection(projection)
|
|
218
|
+
.sort({ createdAt: -1 })
|
|
219
|
+
.exec((err, docs = []) => {
|
|
69
220
|
if (err) {
|
|
70
221
|
return reject(err);
|
|
71
222
|
}
|
|
72
223
|
|
|
73
|
-
return resolve(
|
|
74
|
-
docs.filter(Boolean).map((doc) => {
|
|
75
|
-
// TODO: this only exists for backward compatible
|
|
76
|
-
fixPerson(doc.meta);
|
|
77
|
-
fixInterfaces(doc.meta);
|
|
78
|
-
return doc;
|
|
79
|
-
})
|
|
80
|
-
);
|
|
224
|
+
return resolve(docs.filter(Boolean).map((doc) => formatBlocklet(doc, 'onRead', this.config.dek)));
|
|
81
225
|
});
|
|
82
226
|
});
|
|
83
227
|
}
|
|
@@ -91,32 +235,35 @@ class BlockletState extends BaseState {
|
|
|
91
235
|
return reject(new Error(`Try to remove non-existing blocklet ${did}`));
|
|
92
236
|
}
|
|
93
237
|
|
|
94
|
-
this.
|
|
238
|
+
this.remove({ _id: doc._id }, (err) => {
|
|
95
239
|
if (err) {
|
|
96
240
|
return reject(err);
|
|
97
241
|
}
|
|
98
242
|
|
|
99
243
|
this.emit('remove', doc);
|
|
100
|
-
return resolve(doc);
|
|
244
|
+
return resolve(formatBlocklet(doc, 'onRead', this.config.dek));
|
|
101
245
|
});
|
|
102
246
|
})
|
|
103
247
|
);
|
|
104
248
|
}
|
|
105
249
|
|
|
106
250
|
addBlocklet({
|
|
107
|
-
did,
|
|
108
251
|
meta,
|
|
109
252
|
source = BlockletSource.registry,
|
|
110
253
|
status = BlockletStatus.added,
|
|
111
|
-
deployedFrom,
|
|
254
|
+
deployedFrom = '',
|
|
112
255
|
mode = BLOCKLET_MODES.PRODUCTION,
|
|
113
|
-
|
|
256
|
+
children: rawChildren = [],
|
|
257
|
+
appPid = null, // the permanent appDid, which will not change after initial set
|
|
258
|
+
migratedFrom = [], // the complete migrate history
|
|
259
|
+
// whether sk is managed by some party beside server, such as did-wallet
|
|
260
|
+
// externalSk is always true in struct V2 blocklet
|
|
261
|
+
externalSk = true,
|
|
114
262
|
} = {}) {
|
|
115
|
-
return this.getBlocklet(did).then(
|
|
116
|
-
(
|
|
117
|
-
// eslint-disable-next-line no-async-promise-executor
|
|
263
|
+
return this.getBlocklet(meta.did).then(
|
|
264
|
+
(exist) =>
|
|
118
265
|
new Promise(async (resolve, reject) => {
|
|
119
|
-
if (
|
|
266
|
+
if (exist) {
|
|
120
267
|
reject(new Error('Blocklet already added'));
|
|
121
268
|
return;
|
|
122
269
|
}
|
|
@@ -124,39 +271,48 @@ class BlockletState extends BaseState {
|
|
|
124
271
|
try {
|
|
125
272
|
fixPerson(meta);
|
|
126
273
|
fixInterfaces(meta);
|
|
127
|
-
|
|
274
|
+
let sanitized = validateBlockletMeta(meta);
|
|
275
|
+
// bundle info
|
|
276
|
+
sanitized = ensureMeta(sanitized);
|
|
277
|
+
sanitized = omit(sanitized, ['htmlAst']);
|
|
128
278
|
|
|
129
279
|
// get ports
|
|
130
280
|
await lock.acquire();
|
|
131
281
|
|
|
132
282
|
const ports = await this.getBlockletPorts({ interfaces: sanitized.interfaces || [] });
|
|
133
283
|
|
|
134
|
-
const children = await this.fillChildrenPorts(
|
|
284
|
+
const children = await this.fillChildrenPorts(rawChildren, {
|
|
135
285
|
defaultPort: getMaxPort(ports),
|
|
136
286
|
});
|
|
137
287
|
|
|
288
|
+
fixChildren(children);
|
|
289
|
+
|
|
290
|
+
const data = {
|
|
291
|
+
appDid: null, // will updated later when updating blocklet environments
|
|
292
|
+
appPid,
|
|
293
|
+
mode,
|
|
294
|
+
meta: sanitized,
|
|
295
|
+
status,
|
|
296
|
+
source,
|
|
297
|
+
deployedFrom,
|
|
298
|
+
ports,
|
|
299
|
+
environments: [],
|
|
300
|
+
children,
|
|
301
|
+
migratedFrom,
|
|
302
|
+
externalSk,
|
|
303
|
+
structVersion: APP_STRUCT_VERSION,
|
|
304
|
+
};
|
|
305
|
+
|
|
138
306
|
// add to db
|
|
139
|
-
this.
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
status,
|
|
144
|
-
source,
|
|
145
|
-
deployedFrom,
|
|
146
|
-
ports,
|
|
147
|
-
environments: [],
|
|
148
|
-
children,
|
|
149
|
-
},
|
|
150
|
-
(err, newDoc) => {
|
|
151
|
-
lock.release();
|
|
152
|
-
if (err) {
|
|
153
|
-
return reject(err);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
this.emit('add', newDoc);
|
|
157
|
-
return resolve(newDoc);
|
|
307
|
+
this.insert(data, (err, doc) => {
|
|
308
|
+
lock.release();
|
|
309
|
+
if (err) {
|
|
310
|
+
return reject(err);
|
|
158
311
|
}
|
|
159
|
-
|
|
312
|
+
|
|
313
|
+
this.emit('add', doc);
|
|
314
|
+
return resolve(doc);
|
|
315
|
+
});
|
|
160
316
|
} catch (err) {
|
|
161
317
|
lock.release();
|
|
162
318
|
reject(err);
|
|
@@ -165,7 +321,28 @@ class BlockletState extends BaseState {
|
|
|
165
321
|
);
|
|
166
322
|
}
|
|
167
323
|
|
|
168
|
-
|
|
324
|
+
// FIXME: 这个接口比较危险,可能会修改一些本不应该修改的字段,后续需要考虑改进
|
|
325
|
+
updateBlocklet(did, updates) {
|
|
326
|
+
return this.getBlocklet(did).then(
|
|
327
|
+
(doc) =>
|
|
328
|
+
new Promise(async (resolve, reject) => {
|
|
329
|
+
if (!doc) {
|
|
330
|
+
reject(new Error('Blocklet does not exist'));
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
try {
|
|
335
|
+
const formatted = formatBlocklet(cloneDeep(updates), 'onUpdate', this.config.dek);
|
|
336
|
+
const newDoc = await this.updateById(doc._id, { $set: formatted });
|
|
337
|
+
resolve(newDoc);
|
|
338
|
+
} catch (err) {
|
|
339
|
+
reject(err);
|
|
340
|
+
}
|
|
341
|
+
})
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
upgradeBlocklet({ meta, source, deployedFrom = '', children } = {}) {
|
|
169
346
|
return this.getBlocklet(meta.did).then(
|
|
170
347
|
(doc) =>
|
|
171
348
|
// eslint-disable-next-line no-async-promise-executor
|
|
@@ -195,17 +372,18 @@ class BlockletState extends BaseState {
|
|
|
195
372
|
logger.info('Fill children ports when when upgrading blocklet', { name: doc.meta.name, did: doc.meta.did });
|
|
196
373
|
await this.fillChildrenPorts(children, { oldChildren: doc.children, defaultPort: getMaxPort(ports) });
|
|
197
374
|
|
|
375
|
+
fixChildren(children);
|
|
376
|
+
|
|
198
377
|
// add to db
|
|
199
|
-
const newDoc = await this.
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
ports,
|
|
206
|
-
},
|
|
378
|
+
const newDoc = await this.updateBlocklet(meta.did, {
|
|
379
|
+
meta: omit(sanitized, ['htmlAst']),
|
|
380
|
+
source,
|
|
381
|
+
deployedFrom,
|
|
382
|
+
children,
|
|
383
|
+
ports,
|
|
207
384
|
});
|
|
208
385
|
lock.release();
|
|
386
|
+
|
|
209
387
|
this.emit('upgrade', newDoc);
|
|
210
388
|
resolve(newDoc);
|
|
211
389
|
} catch (err) {
|
|
@@ -224,7 +402,7 @@ class BlockletState extends BaseState {
|
|
|
224
402
|
defaultPort = 0,
|
|
225
403
|
} = {}) {
|
|
226
404
|
try {
|
|
227
|
-
const blocklets = await this.getBlocklets({}, { port: 1, ports: 1, 'meta.interfaces': 1 });
|
|
405
|
+
const blocklets = await this.getBlocklets({}, { port: 1, ports: 1, 'meta.interfaces': 1, children: 1 });
|
|
228
406
|
|
|
229
407
|
const occupiedExternalPorts = new Map();
|
|
230
408
|
const occupiedInternalPorts = new Map();
|
|
@@ -331,31 +509,43 @@ class BlockletState extends BaseState {
|
|
|
331
509
|
* @return {Object} { <did> : { interfaceName } }
|
|
332
510
|
*/
|
|
333
511
|
async groupAllInterfaces() {
|
|
334
|
-
const blocklets = await this.getBlocklets({}, { meta: 1 });
|
|
512
|
+
const blocklets = await this.getBlocklets({}, { meta: 1, children: 1 });
|
|
335
513
|
const result = {};
|
|
336
|
-
|
|
337
|
-
const {
|
|
338
|
-
if (typeof result[
|
|
339
|
-
result[
|
|
514
|
+
const fillResult = (component, { id }) => {
|
|
515
|
+
const { interfaces } = component.meta;
|
|
516
|
+
if (typeof result[id] === 'undefined') {
|
|
517
|
+
result[id] = {};
|
|
340
518
|
}
|
|
341
519
|
|
|
342
520
|
(interfaces || []).forEach((x) => {
|
|
343
|
-
result[
|
|
521
|
+
result[id][x.name] = x;
|
|
344
522
|
});
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
blocklets.forEach((blocklet) => {
|
|
526
|
+
forEachBlockletSync(blocklet, fillResult);
|
|
345
527
|
});
|
|
346
528
|
|
|
347
529
|
return result;
|
|
348
530
|
}
|
|
349
531
|
|
|
350
|
-
|
|
532
|
+
/**
|
|
533
|
+
* @param {String} did blocklet did
|
|
534
|
+
* @param {BlockletStatus} status blocklet status
|
|
535
|
+
*
|
|
536
|
+
* children status only different with parent before blocklet installation
|
|
537
|
+
* @param {Array<componentId>} children
|
|
538
|
+
*/
|
|
539
|
+
async setBlockletStatus(did, status, { children } = {}) {
|
|
351
540
|
if (typeof status === 'undefined') {
|
|
352
541
|
throw new Error('Unsupported blocklet status');
|
|
353
542
|
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
if (
|
|
357
|
-
return
|
|
543
|
+
|
|
544
|
+
const doc = await this.getBlocklet(did);
|
|
545
|
+
if (doc.status === status && !children) {
|
|
546
|
+
return formatBlocklet(doc, 'onRead', this.config.dek);
|
|
358
547
|
}
|
|
548
|
+
|
|
359
549
|
const updates = { status, startedAt: undefined, stoppedAt: undefined };
|
|
360
550
|
if (status === BlockletStatus.running) {
|
|
361
551
|
updates.startedAt = new Date();
|
|
@@ -367,30 +557,46 @@ class BlockletState extends BaseState {
|
|
|
367
557
|
updates.stoppedAt = new Date();
|
|
368
558
|
}
|
|
369
559
|
|
|
370
|
-
|
|
371
|
-
|
|
560
|
+
// update children status
|
|
561
|
+
forEachChildSync(doc, (child, { id }) => {
|
|
562
|
+
if (children === 'all') {
|
|
563
|
+
child.status = status;
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
if (!children) {
|
|
568
|
+
if (
|
|
569
|
+
![
|
|
570
|
+
BlockletStatus.waiting,
|
|
571
|
+
BlockletStatus.upgrading,
|
|
572
|
+
BlockletStatus.installing,
|
|
573
|
+
BlockletStatus.starting,
|
|
574
|
+
].includes(status)
|
|
575
|
+
) {
|
|
576
|
+
child.status = status;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
if (children.includes(id)) {
|
|
583
|
+
child.status = status;
|
|
584
|
+
}
|
|
372
585
|
});
|
|
373
|
-
return res;
|
|
374
|
-
}
|
|
375
586
|
|
|
376
|
-
|
|
377
|
-
return
|
|
587
|
+
updates.children = doc.children;
|
|
588
|
+
return this.updateBlocklet(did, updates);
|
|
378
589
|
}
|
|
379
590
|
|
|
380
|
-
async fillChildrenPorts(children, { defaultPort = 0, oldChildren } = {}) {
|
|
591
|
+
async fillChildrenPorts(children, { defaultPort = 0, oldChildren, returnMaxPort } = {}) {
|
|
381
592
|
let _maxPort = defaultPort;
|
|
382
593
|
for (const child of children || []) {
|
|
383
594
|
// generate ports
|
|
384
595
|
const childMeta = child.meta;
|
|
596
|
+
const oldChild = (oldChildren || []).find((x) => x.meta.did === child.meta.did);
|
|
385
597
|
|
|
386
598
|
// get skipOccupiedCheckPorts
|
|
387
|
-
|
|
388
|
-
if (Array.isArray(oldChildren)) {
|
|
389
|
-
const oldChild = oldChildren.find((x) => x.meta.did === child.meta.did);
|
|
390
|
-
if (oldChild) {
|
|
391
|
-
skipOccupiedCheckPorts = getExternalPortsFromMeta(oldChild.meta);
|
|
392
|
-
}
|
|
393
|
-
}
|
|
599
|
+
const skipOccupiedCheckPorts = oldChild ? getExternalPortsFromMeta(oldChild.meta) : [];
|
|
394
600
|
|
|
395
601
|
const ports = await this.getBlockletPorts({
|
|
396
602
|
interfaces: childMeta.interfaces || [],
|
|
@@ -399,22 +605,17 @@ class BlockletState extends BaseState {
|
|
|
399
605
|
});
|
|
400
606
|
_maxPort = getMaxPort(ports);
|
|
401
607
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
ports[p] = oldChild.ports[p] || ports[p];
|
|
414
|
-
});
|
|
415
|
-
child.ports = ports;
|
|
416
|
-
continue; // eslint-disable-line
|
|
417
|
-
}
|
|
608
|
+
if (oldChild && oldChild.ports) {
|
|
609
|
+
// fill old child's port to new child
|
|
610
|
+
logger.info('Merge the previous ports to child blocklet', {
|
|
611
|
+
did: child.meta.did,
|
|
612
|
+
name: child.meta.name,
|
|
613
|
+
oldPorts: oldChild.ports,
|
|
614
|
+
ports,
|
|
615
|
+
});
|
|
616
|
+
Object.keys(ports).forEach((p) => {
|
|
617
|
+
ports[p] = oldChild.ports[p] || ports[p];
|
|
618
|
+
});
|
|
418
619
|
}
|
|
419
620
|
|
|
420
621
|
// assign a new port to child
|
|
@@ -422,10 +623,70 @@ class BlockletState extends BaseState {
|
|
|
422
623
|
child.ports = ports;
|
|
423
624
|
}
|
|
424
625
|
|
|
626
|
+
for (const child of children || []) {
|
|
627
|
+
const oldChild = (oldChildren || []).find((x) => x.meta.did === child.meta.did);
|
|
628
|
+
|
|
629
|
+
_maxPort = await this.fillChildrenPorts(child.children || [], {
|
|
630
|
+
defaultPort: _maxPort,
|
|
631
|
+
oldChildren: oldChild?.children,
|
|
632
|
+
returnMaxPort: true,
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
if (returnMaxPort) {
|
|
637
|
+
return _maxPort;
|
|
638
|
+
}
|
|
639
|
+
|
|
425
640
|
return children;
|
|
426
641
|
}
|
|
642
|
+
|
|
643
|
+
async addChildren(did, children) {
|
|
644
|
+
const parent = await this.getBlocklet(did);
|
|
645
|
+
if (!parent) {
|
|
646
|
+
throw new Error('Blocklet does not exist');
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
const oldChildren = parent.children || [];
|
|
650
|
+
|
|
651
|
+
const newChildren = [...oldChildren];
|
|
652
|
+
for (const child of children) {
|
|
653
|
+
const { meta, mountPoint, bundleSource = null, source = '', deployedFrom = '', mode } = child;
|
|
654
|
+
|
|
655
|
+
if (!mountPoint) {
|
|
656
|
+
throw new Error(`mountPoint is required when adding component ${getDisplayName(child, true)}`);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
checkDuplicateComponents([child, ...newChildren]);
|
|
660
|
+
|
|
661
|
+
newChildren.push({
|
|
662
|
+
mountPoint,
|
|
663
|
+
meta,
|
|
664
|
+
bundleSource,
|
|
665
|
+
source,
|
|
666
|
+
deployedFrom,
|
|
667
|
+
mode,
|
|
668
|
+
status: BlockletStatus.added,
|
|
669
|
+
children: child.children,
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
fixChildren(newChildren);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
// use upgradeBlocklet to assign ports to children and write new data to db
|
|
676
|
+
return this.upgradeBlocklet({
|
|
677
|
+
meta: parent.meta,
|
|
678
|
+
source: parent.source,
|
|
679
|
+
deployedFrom: parent.deployedFrom,
|
|
680
|
+
children: newChildren,
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
async updateStructV1Did(did, v1Did) {
|
|
685
|
+
return this.updateBlocklet(did, { structV1Did: v1Did });
|
|
686
|
+
}
|
|
427
687
|
}
|
|
428
688
|
|
|
429
689
|
BlockletState.BlockletStatus = BlockletStatus;
|
|
690
|
+
BlockletState.formatBlocklet = formatBlocklet;
|
|
430
691
|
|
|
431
692
|
module.exports = BlockletState;
|
package/lib/states/cache.js
CHANGED
|
@@ -5,13 +5,15 @@ const BaseState = require('./base');
|
|
|
5
5
|
* This db is used to save arbitrary cached data.
|
|
6
6
|
*/
|
|
7
7
|
class CacheState extends BaseState {
|
|
8
|
-
constructor(baseDir,
|
|
9
|
-
super(baseDir, { filename: 'cache.db', ...
|
|
8
|
+
constructor(baseDir, config = {}) {
|
|
9
|
+
super(baseDir, { filename: 'cache.db', ...config });
|
|
10
10
|
|
|
11
|
-
this.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
this.onReady(() => {
|
|
12
|
+
this.ensureIndex({ fieldName: 'key', unique: true }, (error) => {
|
|
13
|
+
if (error) {
|
|
14
|
+
logger.error('ensure index failed', { error });
|
|
15
|
+
}
|
|
16
|
+
});
|
|
15
17
|
});
|
|
16
18
|
}
|
|
17
19
|
|