@abtnode/core 1.8.67-beta-f8b4c9ec → 1.8.67
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/manager/disk.js +48 -79
- package/lib/blocklet/manager/helper/install-from-backup.js +4 -4
- package/lib/blocklet/storage/backup/spaces.js +3 -3
- package/lib/blocklet/storage/restore/blocklets.js +2 -5
- package/lib/blocklet/storage/restore/spaces.js +5 -5
- package/lib/event.js +2 -2
- package/lib/index.js +1 -0
- package/lib/router/helper.js +1 -1
- package/lib/router/index.js +0 -27
- package/lib/router/manager.js +1 -1
- package/lib/states/node.js +1 -1
- package/lib/util/blocklet.js +8 -43
- package/package.json +27 -26
|
@@ -15,18 +15,20 @@ const { isNFTExpired, getNftExpirationDate } = require('@abtnode/util/lib/nft');
|
|
|
15
15
|
const didDocument = require('@abtnode/util/lib/did-document');
|
|
16
16
|
const { sign } = require('@arcblock/jwt');
|
|
17
17
|
const { isValid: isValidDid } = require('@arcblock/did');
|
|
18
|
+
const { verifyPresentation } = require('@arcblock/vc');
|
|
18
19
|
const { toSvg: createDidLogo } =
|
|
19
20
|
process.env.NODE_ENV !== 'test' ? require('@arcblock/did-motif') : require('@arcblock/did-motif/dist/did-motif.cjs');
|
|
20
21
|
const getBlockletInfo = require('@blocklet/meta/lib/info');
|
|
21
22
|
const sleep = require('@abtnode/util/lib/sleep');
|
|
22
23
|
|
|
23
24
|
const logger = require('@abtnode/logger')('@abtnode/core:blocklet:manager');
|
|
25
|
+
const { getVcFromPresentation } = require('@abtnode/util/lib/vc');
|
|
24
26
|
const {
|
|
27
|
+
VC_TYPE_BLOCKLET_PURCHASE,
|
|
25
28
|
WHO_CAN_ACCESS,
|
|
26
29
|
SERVER_ROLES,
|
|
27
30
|
WHO_CAN_ACCESS_PREFIX_ROLES,
|
|
28
31
|
BLOCKLET_INSTALL_TYPE,
|
|
29
|
-
NODE_MODES,
|
|
30
32
|
} = require('@abtnode/constant');
|
|
31
33
|
|
|
32
34
|
const getBlockletEngine = require('@blocklet/meta/lib/engine');
|
|
@@ -47,7 +49,7 @@ const getComponentProcessId = require('@blocklet/meta/lib/get-component-process-
|
|
|
47
49
|
const toBlockletDid = require('@blocklet/meta/lib/did');
|
|
48
50
|
const { validateMeta } = require('@blocklet/meta/lib/validate');
|
|
49
51
|
const { update: updateMetaFile } = require('@blocklet/meta/lib/file');
|
|
50
|
-
const { titleSchema,
|
|
52
|
+
const { titleSchema, mountPointSchema, environmentNameSchema } = require('@blocklet/meta/lib/schema');
|
|
51
53
|
const hasReservedKey = require('@blocklet/meta/lib/has-reserved-key');
|
|
52
54
|
const Lock = require('@abtnode/util/lib/lock');
|
|
53
55
|
|
|
@@ -109,8 +111,6 @@ const {
|
|
|
109
111
|
validateAppConfig,
|
|
110
112
|
checkDuplicateAppSk,
|
|
111
113
|
checkDuplicateMountPoint,
|
|
112
|
-
validateStore,
|
|
113
|
-
validateInServerless,
|
|
114
114
|
} = require('../../util/blocklet');
|
|
115
115
|
const StoreUtil = require('../../util/store');
|
|
116
116
|
const states = require('../../states');
|
|
@@ -242,8 +242,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
242
242
|
* did: string;
|
|
243
243
|
* title: string;
|
|
244
244
|
* description: string;
|
|
245
|
-
* storeUrl: string;
|
|
246
|
-
* appSk: string;
|
|
247
245
|
* sync: boolean = false; // download synchronously, not use queue
|
|
248
246
|
* delay: number; // push download task to queue after a delay
|
|
249
247
|
* downloadTokenList: Array<{did: string, token: string}>;
|
|
@@ -280,31 +278,28 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
280
278
|
context.startImmediately = !!params.startImmediately;
|
|
281
279
|
}
|
|
282
280
|
|
|
283
|
-
const { appSk } = params;
|
|
284
|
-
|
|
285
281
|
if (type === BLOCKLET_INSTALL_TYPE.URL) {
|
|
286
282
|
const { url, controller, sync, delay } = params;
|
|
287
|
-
return this._installFromUrl({ url, controller, sync, delay
|
|
283
|
+
return this._installFromUrl({ url, controller, sync, delay }, context);
|
|
288
284
|
}
|
|
289
285
|
|
|
290
286
|
if (type === BLOCKLET_INSTALL_TYPE.UPLOAD) {
|
|
291
287
|
const { file, did, diffVersion, deleteSet } = params;
|
|
292
|
-
return this._installFromUpload({ file, did, diffVersion, deleteSet,
|
|
288
|
+
return this._installFromUpload({ file, did, diffVersion, deleteSet, context });
|
|
293
289
|
}
|
|
294
290
|
|
|
295
291
|
if (type === BLOCKLET_INSTALL_TYPE.STORE) {
|
|
296
292
|
const { did, controller, sync, delay, storeUrl } = params;
|
|
297
|
-
return this._installFromStore({ did, controller, sync, delay, storeUrl
|
|
293
|
+
return this._installFromStore({ did, controller, sync, delay, storeUrl }, context);
|
|
298
294
|
}
|
|
299
295
|
|
|
300
296
|
if (type === BLOCKLET_INSTALL_TYPE.CREATE) {
|
|
301
|
-
|
|
302
|
-
return this._installFromCreate({ title, description, appSk }, context);
|
|
297
|
+
return this._installFromCreate({ title: params.title, description: params.description }, context);
|
|
303
298
|
}
|
|
304
299
|
|
|
305
300
|
if (type === BLOCKLET_INSTALL_TYPE.RESTORE) {
|
|
306
|
-
const { url } = params;
|
|
307
|
-
return this._installFromBackup({ url,
|
|
301
|
+
const { url, blockletSecretKey } = params;
|
|
302
|
+
return this._installFromBackup({ url, blockletSecretKey }, context);
|
|
308
303
|
}
|
|
309
304
|
|
|
310
305
|
// should not be here
|
|
@@ -348,16 +343,10 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
348
343
|
},
|
|
349
344
|
context = {}
|
|
350
345
|
) {
|
|
351
|
-
const mountPoint = await
|
|
346
|
+
const mountPoint = await mountPointSchema.validateAsync(tmpMountPoint);
|
|
352
347
|
logger.debug('start install component', { rootDid, mountPoint, url });
|
|
353
348
|
|
|
354
349
|
if (file) {
|
|
355
|
-
// TODO: 如何触发这种场景?
|
|
356
|
-
const info = await states.node.read();
|
|
357
|
-
if (info.mode === NODE_MODES.SERVERLESS) {
|
|
358
|
-
throw new Error("Can't install component in serverless-mode server via upload");
|
|
359
|
-
}
|
|
360
|
-
|
|
361
350
|
return this._installComponentFromUpload({
|
|
362
351
|
rootDid,
|
|
363
352
|
mountPoint,
|
|
@@ -371,11 +360,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
371
360
|
}
|
|
372
361
|
|
|
373
362
|
if (url) {
|
|
374
|
-
const info = await states.node.read();
|
|
375
|
-
if (info.mode === NODE_MODES.SERVERLESS) {
|
|
376
|
-
validateStore(info, url);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
363
|
return this._installComponentFromUrl({
|
|
380
364
|
rootDid,
|
|
381
365
|
mountPoint,
|
|
@@ -447,6 +431,25 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
447
431
|
return { isInstalled: !!blocklet, isRunning, blockletDid, isExternal };
|
|
448
432
|
}
|
|
449
433
|
|
|
434
|
+
async installBlockletFromVc({ vcPresentation, challenge }, context) {
|
|
435
|
+
logger.info('Install from vc');
|
|
436
|
+
const vc = getVcFromPresentation(vcPresentation);
|
|
437
|
+
|
|
438
|
+
// FIXME: 这里的 trustedIssuers 相当于相信任何 VC,需要想更安全的方法
|
|
439
|
+
verifyPresentation({ presentation: vcPresentation, trustedIssuers: [get(vc, 'issuer.id')], challenge });
|
|
440
|
+
|
|
441
|
+
if (!vc.type.includes(VC_TYPE_BLOCKLET_PURCHASE)) {
|
|
442
|
+
throw new Error(`Expect ${VC_TYPE_BLOCKLET_PURCHASE} VC type`);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
const blockletUrl = get(vc, 'credentialSubject.purchased.blocklet.url');
|
|
446
|
+
const urlObject = new URL(blockletUrl);
|
|
447
|
+
const did = get(vc, 'credentialSubject.purchased.blocklet.id');
|
|
448
|
+
const registry = urlObject.origin;
|
|
449
|
+
|
|
450
|
+
return this._installFromStore({ did, registry }, context);
|
|
451
|
+
}
|
|
452
|
+
|
|
450
453
|
async start({ did, throwOnError, checkHealthImmediately = false, e2eMode = false }, context) {
|
|
451
454
|
logger.info('start blocklet', { did });
|
|
452
455
|
// should check blocklet integrity
|
|
@@ -628,7 +631,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
628
631
|
// FIXME: 需要改成队列执行,本次失败,下次还需要重试,页面刷新后也能知道最新的状态
|
|
629
632
|
await this._installFromBackup({
|
|
630
633
|
url: `file://${spacesRestore.blockletRestoreDir}`,
|
|
631
|
-
|
|
634
|
+
blockletSecretKey: spacesRestore.blockletWallet.secretKey,
|
|
632
635
|
moveDir: true,
|
|
633
636
|
});
|
|
634
637
|
}
|
|
@@ -1001,7 +1004,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1001
1004
|
}
|
|
1002
1005
|
|
|
1003
1006
|
// eslint-disable-next-line no-unused-vars
|
|
1004
|
-
async config({ did, configs: newConfigs, skipHook
|
|
1007
|
+
async config({ did, configs: newConfigs, skipHook }, context) {
|
|
1005
1008
|
if (!Array.isArray(newConfigs)) {
|
|
1006
1009
|
throw new Error('configs list is not an array');
|
|
1007
1010
|
}
|
|
@@ -1061,7 +1064,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1061
1064
|
[BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_SK, BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_WALLET_TYPE].includes(item.key)
|
|
1062
1065
|
);
|
|
1063
1066
|
|
|
1064
|
-
if (isSkOrWalletTypeChanged
|
|
1067
|
+
if (isSkOrWalletTypeChanged) {
|
|
1065
1068
|
await this._updateDidDocument(blocklet);
|
|
1066
1069
|
}
|
|
1067
1070
|
|
|
@@ -1195,7 +1198,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1195
1198
|
}
|
|
1196
1199
|
|
|
1197
1200
|
async updateComponentMountPoint({ did, rootDid: inputRootDid, mountPoint: tmpMountPoint }, context) {
|
|
1198
|
-
const mountPoint = await
|
|
1201
|
+
const mountPoint = await mountPointSchema.validateAsync(tmpMountPoint);
|
|
1199
1202
|
|
|
1200
1203
|
const blocklet = await states.blocklet.getBlocklet(inputRootDid);
|
|
1201
1204
|
|
|
@@ -1676,13 +1679,13 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1676
1679
|
* /blocklet.json
|
|
1677
1680
|
* /blocklet_extras.json
|
|
1678
1681
|
* @see Blocklet 端到端备份方案的设计与实现(一期) https://team.arcblock.io/comment/discussions/e62084d5-fafa-489e-91d5-defcd6e93223
|
|
1679
|
-
* @param {{ url: string,
|
|
1682
|
+
* @param {{ url: string, blockletSecretKey: string, moveDir: boolean}} [{ url }={}]
|
|
1680
1683
|
* @param {Record<string, string>} [context={}]
|
|
1681
1684
|
* @return {Promise<any>}
|
|
1682
1685
|
* @memberof BlockletManager
|
|
1683
1686
|
*/
|
|
1684
|
-
async _installFromBackup({ url,
|
|
1685
|
-
return installFromBackup({ url,
|
|
1687
|
+
async _installFromBackup({ url, blockletSecretKey, moveDir } = {}, context = {}) {
|
|
1688
|
+
return installFromBackup({ url, blockletSecretKey, moveDir, context, manager: this, states });
|
|
1686
1689
|
}
|
|
1687
1690
|
|
|
1688
1691
|
async ensureBlocklet(did, opts = {}) {
|
|
@@ -2081,18 +2084,17 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2081
2084
|
*
|
|
2082
2085
|
* @param {{
|
|
2083
2086
|
* did: string;
|
|
2087
|
+
* registry: string;
|
|
2084
2088
|
* sync: boolean;
|
|
2085
2089
|
* delay: number;
|
|
2086
2090
|
* controller: Controller;
|
|
2087
|
-
* appSk: string;
|
|
2088
|
-
* storeUrl: string;
|
|
2089
2091
|
* }} params
|
|
2090
2092
|
* @param {*} context
|
|
2091
2093
|
* @return {*}
|
|
2092
2094
|
* @memberof BlockletManager
|
|
2093
2095
|
*/
|
|
2094
2096
|
async _installFromStore(params, context) {
|
|
2095
|
-
const { did, storeUrl, sync, delay, controller
|
|
2097
|
+
const { did, storeUrl, sync, delay, controller } = params;
|
|
2096
2098
|
|
|
2097
2099
|
logger.debug('start install blocklet', { did });
|
|
2098
2100
|
if (!isValidDid(did)) {
|
|
@@ -2136,7 +2138,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2136
2138
|
sync,
|
|
2137
2139
|
delay,
|
|
2138
2140
|
controller,
|
|
2139
|
-
appSk,
|
|
2140
2141
|
context,
|
|
2141
2142
|
});
|
|
2142
2143
|
}
|
|
@@ -2153,14 +2154,13 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2153
2154
|
* sync: boolean;
|
|
2154
2155
|
* delay: number;
|
|
2155
2156
|
* controller: Controller;
|
|
2156
|
-
* appSk: string;
|
|
2157
2157
|
* }} params
|
|
2158
2158
|
* @param {{}} context
|
|
2159
2159
|
* @return {*}
|
|
2160
2160
|
* @memberof BlockletManager
|
|
2161
2161
|
*/
|
|
2162
2162
|
async _installFromUrl(params, context) {
|
|
2163
|
-
const { url, sync, delay, controller
|
|
2163
|
+
const { url, sync, delay, controller } = params;
|
|
2164
2164
|
|
|
2165
2165
|
logger.debug('start install blocklet', { url });
|
|
2166
2166
|
|
|
@@ -2174,18 +2174,13 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2174
2174
|
|
|
2175
2175
|
// install from store if url is a store url
|
|
2176
2176
|
const { inStore, registryUrl, blockletDid: bundleDid } = await StoreUtil.parseSourceUrl(url, controller);
|
|
2177
|
-
|
|
2178
|
-
const nodeInfo = await states.node.read();
|
|
2179
|
-
|
|
2180
|
-
await validateStore(nodeInfo, registryUrl);
|
|
2181
|
-
|
|
2182
2177
|
if (inStore) {
|
|
2183
2178
|
const exist = await states.blocklet.getBlocklet(blockletDid);
|
|
2184
2179
|
if (exist) {
|
|
2185
2180
|
return this.upgrade({ did: blockletDid, storeUrl: registryUrl, sync, delay }, context);
|
|
2186
2181
|
}
|
|
2187
2182
|
|
|
2188
|
-
return this._installFromStore({ did: bundleDid, storeUrl: registryUrl, controller, sync, delay
|
|
2183
|
+
return this._installFromStore({ did: bundleDid, storeUrl: registryUrl, controller, sync, delay }, context);
|
|
2189
2184
|
}
|
|
2190
2185
|
|
|
2191
2186
|
const meta = ensureMeta(bundleMeta, { name: blockletName, did: blockletDid });
|
|
@@ -2211,7 +2206,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2211
2206
|
sync,
|
|
2212
2207
|
delay,
|
|
2213
2208
|
controller,
|
|
2214
|
-
appSk,
|
|
2215
2209
|
context,
|
|
2216
2210
|
});
|
|
2217
2211
|
}
|
|
@@ -2316,7 +2310,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2316
2310
|
);
|
|
2317
2311
|
}
|
|
2318
2312
|
|
|
2319
|
-
async _installFromCreate({ title, description
|
|
2313
|
+
async _installFromCreate({ title, description }, context = {}) {
|
|
2320
2314
|
logger.debug('create blocklet', { title, description });
|
|
2321
2315
|
|
|
2322
2316
|
await joi.string().label('title').max(20).required().validateAsync(title);
|
|
@@ -2344,9 +2338,11 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2344
2338
|
};
|
|
2345
2339
|
const meta = validateMeta(rawMeta);
|
|
2346
2340
|
|
|
2347
|
-
await states.blocklet.addBlocklet({
|
|
2341
|
+
await states.blocklet.addBlocklet({
|
|
2342
|
+
meta,
|
|
2343
|
+
source: BlockletSource.custom,
|
|
2344
|
+
});
|
|
2348
2345
|
await this._setConfigsFromMeta(did);
|
|
2349
|
-
await this._setAppSk(did, appSk);
|
|
2350
2346
|
|
|
2351
2347
|
// check duplicate appSk
|
|
2352
2348
|
await checkDuplicateAppSk({ did, states });
|
|
@@ -2386,7 +2382,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2386
2382
|
return { cwd, tarFile };
|
|
2387
2383
|
}
|
|
2388
2384
|
|
|
2389
|
-
async _installFromUpload({ file, did, diffVersion, deleteSet,
|
|
2385
|
+
async _installFromUpload({ file, did, diffVersion, deleteSet, context }) {
|
|
2390
2386
|
logger.info('install blocklet', { from: 'upload file' });
|
|
2391
2387
|
const { tarFile } = await this._downloadFromUpload(file);
|
|
2392
2388
|
|
|
@@ -2484,7 +2480,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2484
2480
|
const oldState = { extraState: oldExtraState };
|
|
2485
2481
|
try {
|
|
2486
2482
|
await this._setConfigsFromMeta(meta.did);
|
|
2487
|
-
await this._setAppSk(appSk);
|
|
2488
2483
|
await validateBlocklet(blocklet);
|
|
2489
2484
|
|
|
2490
2485
|
// check duplicate appSk
|
|
@@ -2781,7 +2776,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2781
2776
|
* meta: {}; // blocklet meta
|
|
2782
2777
|
* source: number; // example: BlockletSource.registry,
|
|
2783
2778
|
* deployedFrom: string;
|
|
2784
|
-
* appSk: string;
|
|
2785
2779
|
* context: {}
|
|
2786
2780
|
* sync: boolean = false;
|
|
2787
2781
|
* delay: number;
|
|
@@ -2791,15 +2785,10 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2791
2785
|
* @memberof BlockletManager
|
|
2792
2786
|
*/
|
|
2793
2787
|
async _install(params) {
|
|
2794
|
-
const { meta, source, deployedFrom, context, sync, delay, controller
|
|
2788
|
+
const { meta, source, deployedFrom, context, sync, delay, controller } = params;
|
|
2795
2789
|
|
|
2796
2790
|
validateBlockletMeta(meta, { ensureDist: true });
|
|
2797
2791
|
|
|
2798
|
-
const info = await states.node.read();
|
|
2799
|
-
if (info.mode === NODE_MODES.SERVERLESS) {
|
|
2800
|
-
validateInServerless({ blockletMeta: meta });
|
|
2801
|
-
}
|
|
2802
|
-
|
|
2803
2792
|
const { name, did, version } = meta;
|
|
2804
2793
|
|
|
2805
2794
|
const oldExtraState = await states.blockletExtras.findOne({ did: meta.did });
|
|
@@ -2819,7 +2808,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2819
2808
|
await states.blockletExtras.addMeta({ did, meta: { did, name }, controller });
|
|
2820
2809
|
|
|
2821
2810
|
await this._setConfigsFromMeta(did);
|
|
2822
|
-
await this._setAppSk(did, appSk);
|
|
2823
2811
|
|
|
2824
2812
|
// check duplicate appSk
|
|
2825
2813
|
await checkDuplicateAppSk({ did, states });
|
|
@@ -3417,31 +3405,12 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
3417
3405
|
}
|
|
3418
3406
|
}
|
|
3419
3407
|
|
|
3420
|
-
async _setAppSk(did, appSk, context) {
|
|
3421
|
-
if (process.env.NODE_ENV === 'production' && !appSk) {
|
|
3422
|
-
throw new Error(`appSk for blocklet ${did} is required`);
|
|
3423
|
-
}
|
|
3424
|
-
|
|
3425
|
-
if (appSk) {
|
|
3426
|
-
await this.config(
|
|
3427
|
-
{
|
|
3428
|
-
did,
|
|
3429
|
-
configs: [{ key: 'BLOCKLET_APP_SK', value: appSk, secure: true }],
|
|
3430
|
-
skipHook: true,
|
|
3431
|
-
skipDidDocument: true,
|
|
3432
|
-
},
|
|
3433
|
-
context
|
|
3434
|
-
);
|
|
3435
|
-
}
|
|
3436
|
-
}
|
|
3437
|
-
|
|
3438
3408
|
async _findNextCustomBlockletName(leftTimes = 10) {
|
|
3439
3409
|
if (leftTimes <= 0) {
|
|
3440
3410
|
throw new Error('Generate custom blocklet did too many times');
|
|
3441
3411
|
}
|
|
3442
3412
|
const number = await states.node.increaseCustomBlockletNumber();
|
|
3443
3413
|
const name = `custom-${number}`;
|
|
3444
|
-
// MEMO: 空壳 APP可以保留原有的 did 生成逻辑
|
|
3445
3414
|
const did = toBlockletDid(name);
|
|
3446
3415
|
const blocklet = await states.blocklet.getBlocklet(did);
|
|
3447
3416
|
if (blocklet) {
|
|
@@ -19,7 +19,7 @@ const { validateBlocklet, checkDuplicateAppSk, getAppDirs } = require('../../../
|
|
|
19
19
|
* }} param0
|
|
20
20
|
* @returns
|
|
21
21
|
*/
|
|
22
|
-
module.exports = async ({ url,
|
|
22
|
+
module.exports = async ({ url, blockletSecretKey, moveDir, context = {}, states, manager } = {}) => {
|
|
23
23
|
// TODO: support more url schema feature (http, did-spaces)
|
|
24
24
|
if (!url.startsWith('file://')) {
|
|
25
25
|
throw new Error('url must starts with file://');
|
|
@@ -71,17 +71,17 @@ module.exports = async ({ url, appSk, moveDir, context = {}, states, manager } =
|
|
|
71
71
|
throw new Error('blocklet is already exist');
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
if (
|
|
74
|
+
if (blockletSecretKey) {
|
|
75
75
|
extra.configs = extra.configs || [];
|
|
76
76
|
const skConfig = extra.configs.find((x) => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_SK);
|
|
77
77
|
if (skConfig) {
|
|
78
|
-
skConfig.value =
|
|
78
|
+
skConfig.value = blockletSecretKey;
|
|
79
79
|
skConfig.secure = true;
|
|
80
80
|
skConfig.shared = false;
|
|
81
81
|
} else {
|
|
82
82
|
extra.configs.push({
|
|
83
83
|
key: BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_SK,
|
|
84
|
-
value:
|
|
84
|
+
value: blockletSecretKey,
|
|
85
85
|
secure: true,
|
|
86
86
|
shared: false,
|
|
87
87
|
});
|
|
@@ -150,10 +150,10 @@ class SpacesBackup {
|
|
|
150
150
|
const { errorCount } = await spaceClient.send(
|
|
151
151
|
new SyncFolderPushCommand({
|
|
152
152
|
source: join(this.blockletBackupDir, '/'),
|
|
153
|
-
target: join('.did-objects', this.blocklet.appDid
|
|
153
|
+
target: join('.did-objects', this.blocklet.appDid),
|
|
154
154
|
debug: true,
|
|
155
|
-
concurrency:
|
|
156
|
-
retryCount:
|
|
155
|
+
concurrency: 64,
|
|
156
|
+
retryCount: 100,
|
|
157
157
|
filter: (object) => {
|
|
158
158
|
return object.name !== '.DS_Store';
|
|
159
159
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { existsSync, remove
|
|
1
|
+
const { existsSync, remove } = require('fs-extra');
|
|
2
2
|
const { join } = require('path');
|
|
3
3
|
const fg = require('fast-glob');
|
|
4
4
|
const { BaseRestore } = require('./base');
|
|
@@ -10,11 +10,8 @@ class BlockletsRestore extends BaseRestore {
|
|
|
10
10
|
async import() {
|
|
11
11
|
const blockletsDir = join(this.blockletRestoreDir, this.filename);
|
|
12
12
|
|
|
13
|
-
// blockletsDir 可以不存在, 因为还原的 blocklet 可能所有的组件都是来自 store 的
|
|
14
13
|
if (!existsSync(blockletsDir)) {
|
|
15
|
-
|
|
16
|
-
ensureDirSync(blockletsDir);
|
|
17
|
-
return;
|
|
14
|
+
throw new Error(`dir not found: ${blockletsDir}`);
|
|
18
15
|
}
|
|
19
16
|
|
|
20
17
|
const paths = await fg('**/*.zip', {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @typedef {{
|
|
3
3
|
* endpoint: string;
|
|
4
|
-
*
|
|
4
|
+
* blockletSecretKey: string;
|
|
5
5
|
* }} SpaceRestoreInput
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -98,7 +98,7 @@ class SpacesRestore {
|
|
|
98
98
|
|
|
99
99
|
async getBlockletWallet() {
|
|
100
100
|
// @FIXME: blocklet 钱包类型如何得知呢?
|
|
101
|
-
const wallet = fromSecretKey(this.input.
|
|
101
|
+
const wallet = fromSecretKey(this.input.blockletSecretKey, WalletType({ role: types.RoleType.ROLE_APPLICATION }));
|
|
102
102
|
|
|
103
103
|
return wallet;
|
|
104
104
|
}
|
|
@@ -115,10 +115,10 @@ class SpacesRestore {
|
|
|
115
115
|
const { errorCount } = await spaceClient.send(
|
|
116
116
|
new SyncFolderPullCommand({
|
|
117
117
|
source: join('.did-objects', this.blockletWallet.address, '/'),
|
|
118
|
-
target:
|
|
118
|
+
target: this.blockletRestoreDir,
|
|
119
119
|
debug: true,
|
|
120
|
-
concurrency:
|
|
121
|
-
retryCount:
|
|
120
|
+
concurrency: 64,
|
|
121
|
+
retryCount: 100,
|
|
122
122
|
})
|
|
123
123
|
);
|
|
124
124
|
|
package/lib/event.js
CHANGED
|
@@ -81,7 +81,7 @@ module.exports = ({
|
|
|
81
81
|
}
|
|
82
82
|
};
|
|
83
83
|
|
|
84
|
-
const
|
|
84
|
+
const handleBlockletAdd = async (name, { blocklet, context }) => {
|
|
85
85
|
try {
|
|
86
86
|
const changed = await ensureBlockletRouting(blocklet, context);
|
|
87
87
|
if (changed) {
|
|
@@ -173,7 +173,7 @@ module.exports = ({
|
|
|
173
173
|
const blocklet = payload.blocklet || payload;
|
|
174
174
|
|
|
175
175
|
if ([BlockletEvents.installed].includes(eventName)) {
|
|
176
|
-
await
|
|
176
|
+
await handleBlockletAdd(eventName, payload);
|
|
177
177
|
|
|
178
178
|
try {
|
|
179
179
|
await node.createAuditLog({
|
package/lib/index.js
CHANGED
|
@@ -192,6 +192,7 @@ function ABTNode(options) {
|
|
|
192
192
|
|
|
193
193
|
// Blocklet manager
|
|
194
194
|
installBlocklet: blockletManager.install.bind(blockletManager),
|
|
195
|
+
installBlockletFromVc: blockletManager.installBlockletFromVc.bind(blockletManager),
|
|
195
196
|
installComponent: blockletManager.installComponent.bind(blockletManager),
|
|
196
197
|
startBlocklet: blockletManager.start.bind(blockletManager),
|
|
197
198
|
stopBlocklet: blockletManager.stop.bind(blockletManager),
|
package/lib/router/helper.js
CHANGED
|
@@ -518,7 +518,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
518
518
|
|
|
519
519
|
const ensureDomainCert = async (domain, url) => {
|
|
520
520
|
const cert = await certManager.getByDomain(domain);
|
|
521
|
-
if (!cert
|
|
521
|
+
if (!cert) {
|
|
522
522
|
await downloadCert({
|
|
523
523
|
domain,
|
|
524
524
|
url,
|
package/lib/router/index.js
CHANGED
|
@@ -183,10 +183,6 @@ Router.formatSites = (sites = []) => {
|
|
|
183
183
|
result.forEach((site) => {
|
|
184
184
|
if (Array.isArray(site.rules) && site.rules.length > 0) {
|
|
185
185
|
const rules = cloneDeep(site.rules);
|
|
186
|
-
|
|
187
|
-
let hasRootPathBlockletRule = false;
|
|
188
|
-
let tmpBlockletRule;
|
|
189
|
-
|
|
190
186
|
rules.forEach((rule) => {
|
|
191
187
|
if ([ROUTING_RULE_TYPES.BLOCKLET].includes(rule.to.type) === false) {
|
|
192
188
|
return;
|
|
@@ -201,11 +197,6 @@ Router.formatSites = (sites = []) => {
|
|
|
201
197
|
}
|
|
202
198
|
|
|
203
199
|
if (daemonRule) {
|
|
204
|
-
if (rule.from.pathPrefix === '/') {
|
|
205
|
-
hasRootPathBlockletRule = true;
|
|
206
|
-
}
|
|
207
|
-
tmpBlockletRule = rule;
|
|
208
|
-
|
|
209
200
|
// Serve meta js: both prefix and suffix do not contain trailing slash
|
|
210
201
|
// NOTICE: 这里隐含了一个约定
|
|
211
202
|
// 如果安装的 blockletA 和 blockletB 都需要 __blocklet__.js
|
|
@@ -253,24 +244,6 @@ Router.formatSites = (sites = []) => {
|
|
|
253
244
|
});
|
|
254
245
|
}
|
|
255
246
|
});
|
|
256
|
-
|
|
257
|
-
// ensure /__blocklet__.js should be proxy to daemon
|
|
258
|
-
if (daemonRule && !hasRootPathBlockletRule && tmpBlockletRule) {
|
|
259
|
-
site.rules.push({
|
|
260
|
-
from: {
|
|
261
|
-
pathPrefix: '/',
|
|
262
|
-
groupPathPrefix: '/',
|
|
263
|
-
pathSuffix: '/__blocklet__.js',
|
|
264
|
-
},
|
|
265
|
-
to: {
|
|
266
|
-
type: ROUTING_RULE_TYPES.DAEMON,
|
|
267
|
-
port: daemonRule.to.port,
|
|
268
|
-
did: tmpBlockletRule.to.did,
|
|
269
|
-
componentId: tmpBlockletRule.to.did,
|
|
270
|
-
cacheGroup: site.mode === BLOCKLET_MODES.PRODUCTION ? 'blockletJs' : '',
|
|
271
|
-
},
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
247
|
}
|
|
275
248
|
});
|
|
276
249
|
|
package/lib/router/manager.js
CHANGED
|
@@ -559,8 +559,8 @@ class RouterManager extends EventEmitter {
|
|
|
559
559
|
await tempRouter.validateConfig();
|
|
560
560
|
await fse.remove(tmpDir);
|
|
561
561
|
} catch (error) {
|
|
562
|
+
// 如果出错,保留 Nginx 配置文件,方便定位问题
|
|
562
563
|
logger.error('validate router config failed', { error, action, data });
|
|
563
|
-
await fse.remove(tmpDir);
|
|
564
564
|
throw error;
|
|
565
565
|
}
|
|
566
566
|
}
|
package/lib/states/node.js
CHANGED
package/lib/util/blocklet.js
CHANGED
|
@@ -31,12 +31,7 @@ const getFolderSize = require('@abtnode/util/lib/get-folder-size');
|
|
|
31
31
|
const normalizePathPrefix = require('@abtnode/util/lib/normalize-path-prefix');
|
|
32
32
|
const hashFiles = require('@abtnode/util/lib/hash-files');
|
|
33
33
|
const isPathPrefixEqual = require('@abtnode/util/lib/is-path-prefix-equal');
|
|
34
|
-
const {
|
|
35
|
-
BLOCKLET_MAX_MEM_LIMIT_IN_MB,
|
|
36
|
-
BLOCKLET_STORE,
|
|
37
|
-
BLOCKLET_INSTALL_TYPE,
|
|
38
|
-
BLOCKLET_STORE_DEV,
|
|
39
|
-
} = require('@abtnode/constant');
|
|
34
|
+
const { BLOCKLET_MAX_MEM_LIMIT_IN_MB, BLOCKLET_STORE, BLOCKLET_INSTALL_TYPE } = require('@abtnode/constant');
|
|
40
35
|
const formatBackSlash = require('@abtnode/util/lib/format-back-slash');
|
|
41
36
|
|
|
42
37
|
const SCRIPT_ENGINES_WHITE_LIST = ['npm', 'npx', 'pnpm', 'yarn'];
|
|
@@ -840,7 +835,7 @@ const parseChildrenFromMeta = async (src, context = {}) => {
|
|
|
840
835
|
};
|
|
841
836
|
|
|
842
837
|
const validateBlocklet = (blocklet) =>
|
|
843
|
-
forEachBlocklet(blocklet,
|
|
838
|
+
forEachBlocklet(blocklet, (b) => {
|
|
844
839
|
isRequirementsSatisfied(b.meta.requirements);
|
|
845
840
|
validateEngine(getBlockletEngineNameByPlatform(b.meta));
|
|
846
841
|
});
|
|
@@ -1405,14 +1400,12 @@ const getBlocklet = async ({
|
|
|
1405
1400
|
|
|
1406
1401
|
blocklet.settings.storeList = blocklet.settings.storeList || [];
|
|
1407
1402
|
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
}
|
|
1415
|
-
});
|
|
1403
|
+
if (!blocklet.settings.storeList.find((x) => x.url === BLOCKLET_STORE.url)) {
|
|
1404
|
+
blocklet.settings.storeList.unshift({
|
|
1405
|
+
...BLOCKLET_STORE,
|
|
1406
|
+
protected: true,
|
|
1407
|
+
});
|
|
1408
|
+
}
|
|
1416
1409
|
|
|
1417
1410
|
// app site
|
|
1418
1411
|
blocklet.site = await states.site.findOneByBlocklet(blocklet.meta.did);
|
|
@@ -1697,32 +1690,6 @@ const checkDuplicateMountPoint = (blocklet, mountPoint) => {
|
|
|
1697
1690
|
}
|
|
1698
1691
|
};
|
|
1699
1692
|
|
|
1700
|
-
const validateStore = (nodeInfo, storeUrl) => {
|
|
1701
|
-
if (nodeInfo.mode !== 'serverless') {
|
|
1702
|
-
return;
|
|
1703
|
-
}
|
|
1704
|
-
|
|
1705
|
-
const inStoreList = nodeInfo.blockletRegistryList.find((item) => {
|
|
1706
|
-
const itemURLObj = new URL(item.url);
|
|
1707
|
-
const storeUrlObj = new URL(storeUrl);
|
|
1708
|
-
|
|
1709
|
-
return itemURLObj.host === storeUrlObj.host;
|
|
1710
|
-
});
|
|
1711
|
-
|
|
1712
|
-
if (!inStoreList) {
|
|
1713
|
-
throw new Error('Must be installed from the compliant blocklet store list');
|
|
1714
|
-
}
|
|
1715
|
-
};
|
|
1716
|
-
|
|
1717
|
-
const validateInServerless = ({ blockletMeta }) => {
|
|
1718
|
-
const { interfaces } = blockletMeta;
|
|
1719
|
-
const externalPortInterfaces = (interfaces || []).filter((item) => !!item.port?.external);
|
|
1720
|
-
|
|
1721
|
-
if (externalPortInterfaces.length > 0) {
|
|
1722
|
-
throw new Error('Blocklets with exposed ports cannot be installed');
|
|
1723
|
-
}
|
|
1724
|
-
};
|
|
1725
|
-
|
|
1726
1693
|
module.exports = {
|
|
1727
1694
|
consumeServerlessNFT,
|
|
1728
1695
|
forEachBlocklet,
|
|
@@ -1770,6 +1737,4 @@ module.exports = {
|
|
|
1770
1737
|
validateAppConfig,
|
|
1771
1738
|
checkDuplicateAppSk,
|
|
1772
1739
|
checkDuplicateMountPoint,
|
|
1773
|
-
validateStore,
|
|
1774
|
-
validateInServerless,
|
|
1775
1740
|
};
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.8.67
|
|
6
|
+
"version": "1.8.67",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,33 +19,33 @@
|
|
|
19
19
|
"author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@abtnode/auth": "1.8.67
|
|
23
|
-
"@abtnode/certificate-manager": "1.8.67
|
|
24
|
-
"@abtnode/constant": "1.8.67
|
|
25
|
-
"@abtnode/cron": "1.8.67
|
|
26
|
-
"@abtnode/db": "1.8.67
|
|
27
|
-
"@abtnode/logger": "1.8.67
|
|
28
|
-
"@abtnode/queue": "1.8.67
|
|
29
|
-
"@abtnode/rbac": "1.8.67
|
|
30
|
-
"@abtnode/router-provider": "1.8.67
|
|
31
|
-
"@abtnode/static-server": "1.8.67
|
|
32
|
-
"@abtnode/timemachine": "1.8.67
|
|
33
|
-
"@abtnode/util": "1.8.67
|
|
34
|
-
"@arcblock/did": "1.18.
|
|
22
|
+
"@abtnode/auth": "1.8.67",
|
|
23
|
+
"@abtnode/certificate-manager": "1.8.67",
|
|
24
|
+
"@abtnode/constant": "1.8.67",
|
|
25
|
+
"@abtnode/cron": "1.8.67",
|
|
26
|
+
"@abtnode/db": "1.8.67",
|
|
27
|
+
"@abtnode/logger": "1.8.67",
|
|
28
|
+
"@abtnode/queue": "1.8.67",
|
|
29
|
+
"@abtnode/rbac": "1.8.67",
|
|
30
|
+
"@abtnode/router-provider": "1.8.67",
|
|
31
|
+
"@abtnode/static-server": "1.8.67",
|
|
32
|
+
"@abtnode/timemachine": "1.8.67",
|
|
33
|
+
"@abtnode/util": "1.8.67",
|
|
34
|
+
"@arcblock/did": "1.18.42",
|
|
35
35
|
"@arcblock/did-motif": "^1.1.10",
|
|
36
|
-
"@arcblock/did-util": "1.18.
|
|
37
|
-
"@arcblock/event-hub": "1.18.
|
|
38
|
-
"@arcblock/jwt": "^1.18.
|
|
36
|
+
"@arcblock/did-util": "1.18.42",
|
|
37
|
+
"@arcblock/event-hub": "1.18.42",
|
|
38
|
+
"@arcblock/jwt": "^1.18.42",
|
|
39
39
|
"@arcblock/pm2-events": "^0.0.5",
|
|
40
|
-
"@arcblock/vc": "1.18.
|
|
41
|
-
"@blocklet/constant": "1.8.67
|
|
42
|
-
"@blocklet/meta": "1.8.67
|
|
43
|
-
"@blocklet/sdk": "1.8.67
|
|
44
|
-
"@did-space/client": "^0.1.
|
|
40
|
+
"@arcblock/vc": "1.18.42",
|
|
41
|
+
"@blocklet/constant": "1.8.67",
|
|
42
|
+
"@blocklet/meta": "1.8.67",
|
|
43
|
+
"@blocklet/sdk": "1.8.67",
|
|
44
|
+
"@did-space/client": "^0.1.66",
|
|
45
45
|
"@fidm/x509": "^1.2.1",
|
|
46
|
-
"@ocap/mcrypto": "1.18.
|
|
47
|
-
"@ocap/util": "1.18.
|
|
48
|
-
"@ocap/wallet": "1.18.
|
|
46
|
+
"@ocap/mcrypto": "1.18.42",
|
|
47
|
+
"@ocap/util": "1.18.42",
|
|
48
|
+
"@ocap/wallet": "1.18.42",
|
|
49
49
|
"@slack/webhook": "^5.0.4",
|
|
50
50
|
"archiver": "^5.3.1",
|
|
51
51
|
"axios": "^0.27.2",
|
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
"pm2": "^5.2.0",
|
|
73
73
|
"semver": "^7.3.8",
|
|
74
74
|
"shelljs": "^0.8.5",
|
|
75
|
+
"slugify": "^1.6.5",
|
|
75
76
|
"ssri": "^8.0.1",
|
|
76
77
|
"stream-throttle": "^0.1.3",
|
|
77
78
|
"stream-to-promise": "^3.0.0",
|
|
@@ -89,5 +90,5 @@
|
|
|
89
90
|
"express": "^4.18.2",
|
|
90
91
|
"jest": "^27.5.1"
|
|
91
92
|
},
|
|
92
|
-
"gitHead": "
|
|
93
|
+
"gitHead": "543dbadffd29dc4f096261e136a2a306885d6508"
|
|
93
94
|
}
|