@abtnode/core 1.15.17 → 1.16.0-beta-b16cb035
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 +1679 -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 +572 -497
- 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 +194 -138
- package/lib/states/blocklet.js +361 -104
- 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();
|
|
@@ -347,15 +525,23 @@ class BlockletState extends BaseState {
|
|
|
347
525
|
return result;
|
|
348
526
|
}
|
|
349
527
|
|
|
350
|
-
|
|
528
|
+
/**
|
|
529
|
+
* @param {String} did blocklet did
|
|
530
|
+
* @param {BlockletStatus} status blocklet status
|
|
531
|
+
*
|
|
532
|
+
* children status only different with parent before blocklet installation
|
|
533
|
+
* @param {Array<componentId>} children
|
|
534
|
+
*/
|
|
535
|
+
async setBlockletStatus(did, status, { children } = {}) {
|
|
351
536
|
if (typeof status === 'undefined') {
|
|
352
537
|
throw new Error('Unsupported blocklet status');
|
|
353
538
|
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
if (
|
|
357
|
-
return
|
|
539
|
+
|
|
540
|
+
const doc = await this.getBlocklet(did);
|
|
541
|
+
if (doc.status === status && !children) {
|
|
542
|
+
return formatBlocklet(doc, 'onRead', this.config.dek);
|
|
358
543
|
}
|
|
544
|
+
|
|
359
545
|
const updates = { status, startedAt: undefined, stoppedAt: undefined };
|
|
360
546
|
if (status === BlockletStatus.running) {
|
|
361
547
|
updates.startedAt = new Date();
|
|
@@ -367,30 +553,46 @@ class BlockletState extends BaseState {
|
|
|
367
553
|
updates.stoppedAt = new Date();
|
|
368
554
|
}
|
|
369
555
|
|
|
370
|
-
|
|
371
|
-
|
|
556
|
+
// update children status
|
|
557
|
+
forEachChildSync(doc, (child, { id }) => {
|
|
558
|
+
if (children === 'all') {
|
|
559
|
+
child.status = status;
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
if (!children) {
|
|
564
|
+
if (
|
|
565
|
+
![
|
|
566
|
+
BlockletStatus.waiting,
|
|
567
|
+
BlockletStatus.upgrading,
|
|
568
|
+
BlockletStatus.installing,
|
|
569
|
+
BlockletStatus.starting,
|
|
570
|
+
].includes(status)
|
|
571
|
+
) {
|
|
572
|
+
child.status = status;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
if (children.includes(id)) {
|
|
579
|
+
child.status = status;
|
|
580
|
+
}
|
|
372
581
|
});
|
|
373
|
-
return res;
|
|
374
|
-
}
|
|
375
582
|
|
|
376
|
-
|
|
377
|
-
return
|
|
583
|
+
updates.children = doc.children;
|
|
584
|
+
return this.updateBlocklet(did, updates);
|
|
378
585
|
}
|
|
379
586
|
|
|
380
|
-
async fillChildrenPorts(children, { defaultPort = 0, oldChildren } = {}) {
|
|
587
|
+
async fillChildrenPorts(children, { defaultPort = 0, oldChildren, returnMaxPort } = {}) {
|
|
381
588
|
let _maxPort = defaultPort;
|
|
382
589
|
for (const child of children || []) {
|
|
383
590
|
// generate ports
|
|
384
591
|
const childMeta = child.meta;
|
|
592
|
+
const oldChild = (oldChildren || []).find((x) => x.meta.did === child.meta.did);
|
|
385
593
|
|
|
386
594
|
// 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
|
-
}
|
|
595
|
+
const skipOccupiedCheckPorts = oldChild ? getExternalPortsFromMeta(oldChild.meta) : [];
|
|
394
596
|
|
|
395
597
|
const ports = await this.getBlockletPorts({
|
|
396
598
|
interfaces: childMeta.interfaces || [],
|
|
@@ -399,22 +601,17 @@ class BlockletState extends BaseState {
|
|
|
399
601
|
});
|
|
400
602
|
_maxPort = getMaxPort(ports);
|
|
401
603
|
|
|
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
|
-
}
|
|
604
|
+
if (oldChild && oldChild.ports) {
|
|
605
|
+
// fill old child's port to new child
|
|
606
|
+
logger.info('Merge the previous ports to child blocklet', {
|
|
607
|
+
did: child.meta.did,
|
|
608
|
+
name: child.meta.name,
|
|
609
|
+
oldPorts: oldChild.ports,
|
|
610
|
+
ports,
|
|
611
|
+
});
|
|
612
|
+
Object.keys(ports).forEach((p) => {
|
|
613
|
+
ports[p] = oldChild.ports[p] || ports[p];
|
|
614
|
+
});
|
|
418
615
|
}
|
|
419
616
|
|
|
420
617
|
// assign a new port to child
|
|
@@ -422,10 +619,70 @@ class BlockletState extends BaseState {
|
|
|
422
619
|
child.ports = ports;
|
|
423
620
|
}
|
|
424
621
|
|
|
622
|
+
for (const child of children || []) {
|
|
623
|
+
const oldChild = (oldChildren || []).find((x) => x.meta.did === child.meta.did);
|
|
624
|
+
|
|
625
|
+
_maxPort = await this.fillChildrenPorts(child.children || [], {
|
|
626
|
+
defaultPort: _maxPort,
|
|
627
|
+
oldChildren: oldChild?.children,
|
|
628
|
+
returnMaxPort: true,
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
if (returnMaxPort) {
|
|
633
|
+
return _maxPort;
|
|
634
|
+
}
|
|
635
|
+
|
|
425
636
|
return children;
|
|
426
637
|
}
|
|
638
|
+
|
|
639
|
+
async addChildren(did, children) {
|
|
640
|
+
const parent = await this.getBlocklet(did);
|
|
641
|
+
if (!parent) {
|
|
642
|
+
throw new Error('Blocklet does not exist');
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
const oldChildren = parent.children || [];
|
|
646
|
+
|
|
647
|
+
const newChildren = [...oldChildren];
|
|
648
|
+
for (const child of children) {
|
|
649
|
+
const { meta, mountPoint, bundleSource = null, source = '', deployedFrom = '', mode } = child;
|
|
650
|
+
|
|
651
|
+
if (!mountPoint) {
|
|
652
|
+
throw new Error(`mountPoint is required when adding component ${getDisplayName(child, true)}`);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
checkDuplicateComponents([child, ...newChildren]);
|
|
656
|
+
|
|
657
|
+
newChildren.push({
|
|
658
|
+
mountPoint,
|
|
659
|
+
meta,
|
|
660
|
+
bundleSource,
|
|
661
|
+
source,
|
|
662
|
+
deployedFrom,
|
|
663
|
+
mode,
|
|
664
|
+
status: BlockletStatus.added,
|
|
665
|
+
children: child.children,
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
fixChildren(newChildren);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// use upgradeBlocklet to assign ports to children and write new data to db
|
|
672
|
+
return this.upgradeBlocklet({
|
|
673
|
+
meta: parent.meta,
|
|
674
|
+
source: parent.source,
|
|
675
|
+
deployedFrom: parent.deployedFrom,
|
|
676
|
+
children: newChildren,
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
async updateStructV1Did(did, v1Did) {
|
|
681
|
+
return this.updateBlocklet(did, { structV1Did: v1Did });
|
|
682
|
+
}
|
|
427
683
|
}
|
|
428
684
|
|
|
429
685
|
BlockletState.BlockletStatus = BlockletStatus;
|
|
686
|
+
BlockletState.formatBlocklet = formatBlocklet;
|
|
430
687
|
|
|
431
688
|
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
|
|
package/lib/states/challenge.js
CHANGED
|
@@ -9,17 +9,17 @@ class ChallengeState extends BaseState {
|
|
|
9
9
|
/**
|
|
10
10
|
* Creates an instance of ChallengeState
|
|
11
11
|
* @param {string} baseDir
|
|
12
|
-
* @param {object}
|
|
12
|
+
* @param {object} config
|
|
13
13
|
* @memberof ChallengeState
|
|
14
14
|
*/
|
|
15
|
-
constructor(baseDir,
|
|
16
|
-
super(baseDir, { filename: 'challenge.db', ...
|
|
15
|
+
constructor(baseDir, config = {}) {
|
|
16
|
+
super(baseDir, { filename: 'challenge.db', ...config });
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
generate() {
|
|
20
20
|
return new Promise((resolve, reject) => {
|
|
21
21
|
const challenge = stripHexPrefix(Mcrypto.getRandomBytes(16)).toUpperCase();
|
|
22
|
-
this.
|
|
22
|
+
this.insert({ challenge }, (err, data) => {
|
|
23
23
|
if (err) {
|
|
24
24
|
logger.error('generating error', { error: err });
|
|
25
25
|
return reject(err);
|
|
@@ -38,7 +38,7 @@ class ChallengeState extends BaseState {
|
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
this.
|
|
41
|
+
this.findOne({ challenge }, (err, data) => {
|
|
42
42
|
if (err) {
|
|
43
43
|
logger.error('error find challenge', { error: err });
|
|
44
44
|
}
|