@abtnode/core 1.6.13 → 1.6.17
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 +397 -99
- package/lib/event.js +1 -1
- package/lib/index.js +3 -10
- package/lib/migrations/1.6.17-blocklet-children.js +48 -0
- package/lib/router/helper.js +27 -13
- package/lib/router/manager.js +64 -42
- package/lib/states/blocklet-extras.js +39 -3
- package/lib/states/blocklet.js +18 -20
- package/lib/states/node.js +18 -2
- package/lib/util/blocklet.js +276 -68
- package/lib/util/default-node-config.js +1 -1
- package/lib/util/router.js +13 -0
- package/lib/validators/node.js +11 -12
- package/lib/validators/permission.js +16 -1
- package/package.json +21 -21
|
@@ -3,20 +3,20 @@
|
|
|
3
3
|
const fs = require('fs-extra');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const get = require('lodash/get');
|
|
6
|
+
const pick = require('lodash/pick');
|
|
6
7
|
const cloneDeep = require('lodash/cloneDeep');
|
|
7
8
|
const semver = require('semver');
|
|
8
9
|
const capitalize = require('lodash/capitalize');
|
|
9
|
-
const diff = require('deep-diff');
|
|
10
10
|
const { Throttle } = require('stream-throttle');
|
|
11
11
|
const LRU = require('lru-cache');
|
|
12
|
+
const joi = require('joi');
|
|
12
13
|
|
|
13
14
|
const { isValid: isValidDid } = require('@arcblock/did');
|
|
14
15
|
const { verifyPresentation } = require('@arcblock/vc');
|
|
15
|
-
const { toBase58 } = require('@ocap/util');
|
|
16
|
+
const { toBase58, isHex } = require('@ocap/util');
|
|
16
17
|
const { fromSecretKey } = require('@ocap/wallet');
|
|
17
18
|
|
|
18
19
|
const logger = require('@abtnode/logger')('@abtnode/core:blocklet:manager');
|
|
19
|
-
const hashFiles = require('@abtnode/util/lib/hash-files');
|
|
20
20
|
const downloadFile = require('@abtnode/util/lib/download-file');
|
|
21
21
|
const Lock = require('@abtnode/util/lib/lock');
|
|
22
22
|
const { getVcFromPresentation } = require('@abtnode/util/lib/vc');
|
|
@@ -24,9 +24,17 @@ const { updateBlocklet: updateDidDocument } = require('@abtnode/util/lib/did-doc
|
|
|
24
24
|
const { BLOCKLET_PURCHASE_NFT_TYPE } = require('@abtnode/constant');
|
|
25
25
|
|
|
26
26
|
const getBlockletEngine = require('@blocklet/meta/lib/engine');
|
|
27
|
-
const {
|
|
27
|
+
const {
|
|
28
|
+
isFreeBlocklet,
|
|
29
|
+
isDeletableBlocklet,
|
|
30
|
+
getRequiredMissingConfigs,
|
|
31
|
+
hasRunnableComponent,
|
|
32
|
+
} = require('@blocklet/meta/lib/util');
|
|
28
33
|
const validateBlockletEntry = require('@blocklet/meta/lib/entry');
|
|
29
34
|
const { getBlockletInfo } = require('@blocklet/meta/lib');
|
|
35
|
+
const toBlockletDid = require('@blocklet/meta/lib/did');
|
|
36
|
+
const { validateMeta } = require('@blocklet/meta/lib/validate');
|
|
37
|
+
const { update: updateMetaFile } = require('@blocklet/meta/lib/file');
|
|
30
38
|
|
|
31
39
|
const {
|
|
32
40
|
BlockletStatus,
|
|
@@ -37,6 +45,15 @@ const {
|
|
|
37
45
|
BlockletGroup,
|
|
38
46
|
fromBlockletStatus,
|
|
39
47
|
fromBlockletSource,
|
|
48
|
+
BLOCKLET_DEFAULT_PORT_NAME,
|
|
49
|
+
BLOCKLET_INTERFACE_TYPE_WEB,
|
|
50
|
+
BLOCKLET_INTERFACE_PUBLIC,
|
|
51
|
+
BLOCKLET_DYNAMIC_PATH_PREFIX,
|
|
52
|
+
BLOCKLET_INTERFACE_PROTOCOL_HTTP,
|
|
53
|
+
BLOCKLET_DEFAULT_PATH_REWRITE,
|
|
54
|
+
BLOCKLET_DEFAULT_VERSION,
|
|
55
|
+
BLOCKLET_LATEST_SPEC_VERSION,
|
|
56
|
+
BLOCKLET_META_FILE,
|
|
40
57
|
} = require('@blocklet/meta/lib/constants');
|
|
41
58
|
const util = require('../../util');
|
|
42
59
|
const {
|
|
@@ -60,16 +77,19 @@ const {
|
|
|
60
77
|
getBlockletStatusFromProcess,
|
|
61
78
|
checkBlockletProcessHealthy,
|
|
62
79
|
validateBlocklet,
|
|
63
|
-
getChildrenMeta,
|
|
64
80
|
statusMap,
|
|
65
81
|
expandTarball,
|
|
66
82
|
verifyIntegrity,
|
|
67
83
|
pruneBlockletBundle,
|
|
68
84
|
getDiskInfo,
|
|
69
85
|
getRuntimeInfo,
|
|
70
|
-
mergeMeta,
|
|
71
86
|
getUpdateMetaList,
|
|
72
87
|
getRuntimeEnvironments,
|
|
88
|
+
getSourceFromInstallParams,
|
|
89
|
+
parseChildren,
|
|
90
|
+
checkDuplicateComponents,
|
|
91
|
+
getDiffFiles,
|
|
92
|
+
getBundleDir,
|
|
73
93
|
} = require('../../util/blocklet');
|
|
74
94
|
const states = require('../../states');
|
|
75
95
|
const BlockletRegistry = require('../registry');
|
|
@@ -153,20 +173,43 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
153
173
|
*/
|
|
154
174
|
async install(params, context) {
|
|
155
175
|
logger.debug('install blocklet', { params, context });
|
|
156
|
-
|
|
176
|
+
|
|
177
|
+
const source = getSourceFromInstallParams(params);
|
|
178
|
+
|
|
179
|
+
if (source === BlockletSource.url) {
|
|
157
180
|
return this._installFromUrl({ url: params.url, sync: params.sync }, context);
|
|
158
181
|
}
|
|
159
182
|
|
|
160
|
-
if (
|
|
183
|
+
if (source === BlockletSource.upload) {
|
|
161
184
|
const { file, did, diffVersion, deleteSet } = params;
|
|
162
185
|
return this._installFromUpload({ file, did, diffVersion, deleteSet, context });
|
|
163
186
|
}
|
|
164
187
|
|
|
165
|
-
if (
|
|
166
|
-
return this.
|
|
188
|
+
if (source === BlockletSource.registry) {
|
|
189
|
+
return this._installFromStore({ did: params.did }, context);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (source === BlockletSource.custom) {
|
|
193
|
+
return this._installFromCreate({ title: params.title, description: params.description }, context);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// should not be here
|
|
197
|
+
throw new Error('Unknown source');
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async installComponent({ rootDid, mountPoint, url, file, did, diffVersion, deleteSet }, context = {}) {
|
|
201
|
+
logger.debug('start install component', { rootDid, mountPoint, url });
|
|
202
|
+
|
|
203
|
+
if (file) {
|
|
204
|
+
return this._installComponentFromUpload({ rootDid, mountPoint, file, did, diffVersion, deleteSet, context });
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (url) {
|
|
208
|
+
return this._installComponentFromUrl({ rootDid, mountPoint, url, context });
|
|
167
209
|
}
|
|
168
210
|
|
|
169
|
-
|
|
211
|
+
// should not be here
|
|
212
|
+
throw new Error('Unknown source');
|
|
170
213
|
}
|
|
171
214
|
|
|
172
215
|
// eslint-disable-next-line no-unused-vars
|
|
@@ -189,9 +232,9 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
189
232
|
}
|
|
190
233
|
}
|
|
191
234
|
|
|
192
|
-
|
|
235
|
+
const blocklet = await states.blocklet.getBlocklet(meta.did);
|
|
193
236
|
|
|
194
|
-
return meta;
|
|
237
|
+
return { meta, isFree, isInstalled: !!blocklet };
|
|
195
238
|
}
|
|
196
239
|
|
|
197
240
|
async installBlockletFromVc({ vcPresentation, challenge }, context) {
|
|
@@ -210,7 +253,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
210
253
|
const did = get(vc, 'credentialSubject.purchased.blocklet.id');
|
|
211
254
|
const registry = urlObject.origin;
|
|
212
255
|
|
|
213
|
-
return this.
|
|
256
|
+
return this._installFromStore({ did, registry }, { ...context, blockletPurchaseVerified: true });
|
|
214
257
|
}
|
|
215
258
|
|
|
216
259
|
async start({ did, checkHealthImmediately = false, throwOnError }, context) {
|
|
@@ -218,6 +261,10 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
218
261
|
const blocklet = await this.ensureBlocklet(did);
|
|
219
262
|
|
|
220
263
|
try {
|
|
264
|
+
if (!hasRunnableComponent(blocklet)) {
|
|
265
|
+
throw new Error('No runnable component found');
|
|
266
|
+
}
|
|
267
|
+
|
|
221
268
|
// check required config
|
|
222
269
|
const missingProps = getRequiredMissingConfigs(blocklet);
|
|
223
270
|
if (missingProps.length) {
|
|
@@ -412,6 +459,22 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
412
459
|
}
|
|
413
460
|
}
|
|
414
461
|
|
|
462
|
+
async deleteComponent({ did, rootDid }, context) {
|
|
463
|
+
logger.info('delete blocklet component', { did, rootDid });
|
|
464
|
+
|
|
465
|
+
const doc = await states.blocklet.getBlocklet(rootDid);
|
|
466
|
+
|
|
467
|
+
doc.children = doc.children.filter((x) => x.meta.did !== did);
|
|
468
|
+
const children = (await this._getDynamicChildrenFromSettings(rootDid)).filter((x) => x.meta.did !== did);
|
|
469
|
+
|
|
470
|
+
await states.blocklet.updateBlocklet(rootDid, doc);
|
|
471
|
+
states.blockletExtras.setSettings(rootDid, { children });
|
|
472
|
+
|
|
473
|
+
const newBlocklet = await this.ensureBlocklet(rootDid);
|
|
474
|
+
this.emit(BlockletEvents.upgraded, { blocklet: newBlocklet, context }); // trigger router refresh
|
|
475
|
+
return newBlocklet;
|
|
476
|
+
}
|
|
477
|
+
|
|
415
478
|
async cancelDownload({ did }, context) {
|
|
416
479
|
await preDownloadLock.acquire();
|
|
417
480
|
try {
|
|
@@ -549,6 +612,14 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
549
612
|
}
|
|
550
613
|
}
|
|
551
614
|
|
|
615
|
+
if (x.key === 'BLOCKLET_PASSPORT_COLOR') {
|
|
616
|
+
if (x.value && x.value !== 'auto') {
|
|
617
|
+
if (x.value.length !== 7 || !isHex(x.value.slice(-6))) {
|
|
618
|
+
throw new Error('BLOCKLET_PASSPORT_COLOR must be a hex encoded color, eg. #ffeeaa');
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
552
623
|
blocklet.configObj[x.key] = x.value;
|
|
553
624
|
}
|
|
554
625
|
|
|
@@ -558,7 +629,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
558
629
|
hooks: Object.assign(blocklet.meta.hooks || {}, blocklet.meta.scripts || {}),
|
|
559
630
|
exitOnError: true,
|
|
560
631
|
env: { ...getRuntimeEnvironments(blocklet, nodeEnvironments), ...blocklet.configObj },
|
|
561
|
-
notification: states.notification,
|
|
562
632
|
did,
|
|
563
633
|
context,
|
|
564
634
|
progress: blocklet.mode === BLOCKLET_MODES.DEVELOPMENT,
|
|
@@ -657,56 +727,45 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
657
727
|
}
|
|
658
728
|
|
|
659
729
|
// eslint-disable-next-line no-unused-vars
|
|
660
|
-
async diff({ did, hashFiles: clientFiles }, context) {
|
|
730
|
+
async diff({ did, hashFiles: clientFiles, rootDid: inputRootDid }, context) {
|
|
661
731
|
if (!did) {
|
|
662
732
|
throw new Error('did is empty');
|
|
663
733
|
}
|
|
734
|
+
|
|
664
735
|
if (!clientFiles || !clientFiles.length) {
|
|
665
736
|
throw new Error('hashFiles is empty');
|
|
666
737
|
}
|
|
667
738
|
|
|
668
|
-
|
|
739
|
+
const rootDid = inputRootDid || did;
|
|
740
|
+
const childDid = inputRootDid ? did : '';
|
|
741
|
+
|
|
742
|
+
if (childDid === rootDid) {
|
|
743
|
+
throw new Error('Cannot add self as a component');
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
logger.info('Get blocklet diff', { rootDid, childDid, clientFilesNumber: clientFiles.length });
|
|
747
|
+
|
|
748
|
+
const rootBlocklet = await states.blocklet.getBlocklet(rootDid);
|
|
749
|
+
if (childDid && !rootBlocklet) {
|
|
750
|
+
throw new Error('Root blocklet does not exist');
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
const state = childDid ? await (rootBlocklet.children || []).find((x) => x.meta.did === childDid) : rootBlocklet;
|
|
669
754
|
|
|
670
|
-
const state = await states.blocklet.getBlocklet(did);
|
|
671
755
|
if (!state) {
|
|
672
756
|
return {
|
|
673
757
|
hasBlocklet: false,
|
|
674
758
|
};
|
|
675
759
|
}
|
|
760
|
+
|
|
676
761
|
if (state.source === BlockletSource.local) {
|
|
677
762
|
throw new Error(`Blocklet ${state.meta.name} is already deployed from local, can not deployed from remote.`);
|
|
678
763
|
}
|
|
679
|
-
const { name, version } = state.meta;
|
|
680
|
-
const installDir = path.join(this.installDir, name, version);
|
|
681
|
-
// eslint-disable-next-line no-param-reassign
|
|
682
|
-
clientFiles = clientFiles.reduce((obj, item) => {
|
|
683
|
-
obj[item.file] = item.hash;
|
|
684
|
-
return obj;
|
|
685
|
-
}, {});
|
|
686
764
|
|
|
687
|
-
const {
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
logger.info('Get files hash', { filesNum: Object.keys(files).length });
|
|
692
|
-
|
|
693
|
-
const addSet = [];
|
|
694
|
-
const changeSet = [];
|
|
695
|
-
const deleteSet = [];
|
|
696
|
-
const diffFiles = diff(files, clientFiles);
|
|
697
|
-
if (diffFiles) {
|
|
698
|
-
diffFiles.forEach((item) => {
|
|
699
|
-
if (item.kind === 'D') {
|
|
700
|
-
deleteSet.push(item.path[0]);
|
|
701
|
-
}
|
|
702
|
-
if (item.kind === 'E') {
|
|
703
|
-
changeSet.push(item.path[0]);
|
|
704
|
-
}
|
|
705
|
-
if (item.kind === 'N') {
|
|
706
|
-
addSet.push(item.path[0]);
|
|
707
|
-
}
|
|
708
|
-
});
|
|
709
|
-
}
|
|
765
|
+
const { version } = state.meta;
|
|
766
|
+
const bundleDir = getBundleDir(this.installDir, state.meta);
|
|
767
|
+
const { addSet, changeSet, deleteSet } = await getDiffFiles(clientFiles, bundleDir);
|
|
768
|
+
|
|
710
769
|
logger.info('Diff files', {
|
|
711
770
|
name: state.meta.name,
|
|
712
771
|
did: state.meta.did,
|
|
@@ -715,6 +774,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
715
774
|
changeNum: changeSet.length,
|
|
716
775
|
deleteNum: deleteSet.length,
|
|
717
776
|
});
|
|
777
|
+
|
|
718
778
|
return {
|
|
719
779
|
hasBlocklet: true,
|
|
720
780
|
version,
|
|
@@ -726,10 +786,20 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
726
786
|
|
|
727
787
|
async checkChildrenForUpdates({ did }) {
|
|
728
788
|
const blocklet = await states.blocklet.getBlocklet(did);
|
|
729
|
-
const
|
|
789
|
+
const newStaticChildren = await parseChildren(blocklet.meta);
|
|
790
|
+
|
|
791
|
+
const oldDynamicChildren = await this._getDynamicChildrenFromSettings(did);
|
|
792
|
+
const noneSourceUrlChildren = oldDynamicChildren.filter((x) => !x.sourceUrl);
|
|
793
|
+
const dynamicConfig = oldDynamicChildren
|
|
794
|
+
.filter((x) => x.sourceUrl)
|
|
795
|
+
.map((x) => ({ resolved: x.sourceUrl, name: x.meta.name, mountPoint: x.mountPoint }));
|
|
796
|
+
const newDynamicChildren = [...noneSourceUrlChildren, ...(await parseChildren(dynamicConfig, { dynamic: true }))];
|
|
797
|
+
|
|
798
|
+
checkDuplicateComponents(newDynamicChildren, newStaticChildren);
|
|
799
|
+
|
|
730
800
|
const updateList = getUpdateMetaList(
|
|
731
|
-
blocklet.children.map((x) => x.meta),
|
|
732
|
-
|
|
801
|
+
[...blocklet.children.map((x) => x.meta), ...oldDynamicChildren.map((x) => x.meta)],
|
|
802
|
+
[...newStaticChildren.map((x) => x.meta), ...newDynamicChildren.map((x) => x.meta)]
|
|
733
803
|
);
|
|
734
804
|
|
|
735
805
|
if (!updateList.length) {
|
|
@@ -739,7 +809,8 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
739
809
|
// start session
|
|
740
810
|
const { id: updateId } = await states.session.start({
|
|
741
811
|
did,
|
|
742
|
-
|
|
812
|
+
staticChildren: newStaticChildren,
|
|
813
|
+
dynamicChildren: newDynamicChildren,
|
|
743
814
|
});
|
|
744
815
|
|
|
745
816
|
return {
|
|
@@ -748,8 +819,18 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
748
819
|
};
|
|
749
820
|
}
|
|
750
821
|
|
|
751
|
-
async updateChildren({ updateId }, context) {
|
|
752
|
-
|
|
822
|
+
async updateChildren({ updateId, did: inputDid, children: inputChildren }, context) {
|
|
823
|
+
let did;
|
|
824
|
+
let children;
|
|
825
|
+
if (!updateId && inputDid && inputChildren) {
|
|
826
|
+
did = inputDid;
|
|
827
|
+
children = inputChildren;
|
|
828
|
+
} else {
|
|
829
|
+
const sessionData = await states.session.end(updateId);
|
|
830
|
+
did = sessionData.did;
|
|
831
|
+
const { staticChildren = [], dynamicChildren = [] } = sessionData;
|
|
832
|
+
children = [...staticChildren, ...dynamicChildren.map((x) => ({ ...x, dynamic: true }))];
|
|
833
|
+
}
|
|
753
834
|
|
|
754
835
|
// get old blocklet
|
|
755
836
|
const oldBlocklet = await states.blocklet.getBlocklet(did);
|
|
@@ -762,14 +843,13 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
762
843
|
did,
|
|
763
844
|
name,
|
|
764
845
|
version,
|
|
765
|
-
children:
|
|
846
|
+
children: children.map((x) => ({ name: x.meta.name, version: x.meta.version })),
|
|
766
847
|
});
|
|
767
848
|
|
|
768
849
|
// new blocklet
|
|
769
850
|
const newBlocklet = await states.blocklet.setBlockletStatus(did, BlockletStatus.waiting);
|
|
770
|
-
|
|
771
|
-
newBlocklet.
|
|
772
|
-
newBlocklet.children = await states.blocklet.getChildrenFromMetas(childrenMeta);
|
|
851
|
+
|
|
852
|
+
newBlocklet.children = children;
|
|
773
853
|
await validateBlocklet(newBlocklet);
|
|
774
854
|
|
|
775
855
|
this.emit(BlockletEvents.statusChange, newBlocklet);
|
|
@@ -842,19 +922,19 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
842
922
|
logger.error('failed to delete blocklet process for dev', { error: err });
|
|
843
923
|
}
|
|
844
924
|
|
|
845
|
-
const
|
|
846
|
-
mergeMeta(meta, childrenMeta);
|
|
925
|
+
const children = await this._getChildren(meta);
|
|
847
926
|
const blocklet = await states.blocklet.addBlocklet({
|
|
848
927
|
did,
|
|
849
928
|
meta,
|
|
850
929
|
source: BlockletSource.local,
|
|
851
930
|
deployedFrom: folder,
|
|
852
931
|
mode: BLOCKLET_MODES.DEVELOPMENT,
|
|
853
|
-
|
|
932
|
+
children,
|
|
854
933
|
});
|
|
855
934
|
logger.info('add blocklet for dev', { did, version, meta });
|
|
856
935
|
|
|
857
|
-
|
|
936
|
+
const oldBlocklet = { children: children.filter((x) => x.dynamic) }; // let downloader skip re-downloading dynamic blocklet
|
|
937
|
+
await this._downloadBlocklet(blocklet, oldBlocklet);
|
|
858
938
|
await states.blocklet.setBlockletStatus(did, BlockletStatus.installed);
|
|
859
939
|
|
|
860
940
|
// Add environments
|
|
@@ -997,7 +1077,8 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
997
1077
|
blocklet.diskInfo = await getDiskInfo(blocklet, { useFakeDiskInfo: !diskInfo });
|
|
998
1078
|
|
|
999
1079
|
try {
|
|
1000
|
-
const
|
|
1080
|
+
const app = blocklet.meta.group === BlockletGroup.gateway ? blocklet.children[0].env : blocklet.env;
|
|
1081
|
+
const { appId } = app;
|
|
1001
1082
|
blocklet.runtimeInfo = await getRuntimeInfo(appId);
|
|
1002
1083
|
if (blocklet.runtimeInfo.status && shouldUpdateBlockletStatus(blocklet.status)) {
|
|
1003
1084
|
blocklet.status = statusMap[blocklet.runtimeInfo.status];
|
|
@@ -1271,7 +1352,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1271
1352
|
}
|
|
1272
1353
|
}
|
|
1273
1354
|
|
|
1274
|
-
async
|
|
1355
|
+
async _installFromStore({ did, registry }, context) {
|
|
1275
1356
|
logger.debug('start install blocklet', { did });
|
|
1276
1357
|
if (!isValidDid(did)) {
|
|
1277
1358
|
throw new Error('Blocklet did is invalid');
|
|
@@ -1333,9 +1414,84 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1333
1414
|
});
|
|
1334
1415
|
}
|
|
1335
1416
|
|
|
1336
|
-
async
|
|
1337
|
-
|
|
1338
|
-
|
|
1417
|
+
async _installComponentFromUrl({ rootDid, mountPoint, url, context }) {
|
|
1418
|
+
const blocklet = await states.blocklet.getBlocklet(rootDid);
|
|
1419
|
+
if (!blocklet) {
|
|
1420
|
+
throw new Error('Root blocklet does not exist');
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
const meta = await getBlockletMetaFromUrl(url);
|
|
1424
|
+
|
|
1425
|
+
if (meta.did === rootDid) {
|
|
1426
|
+
throw new Error('Cannot add self as a component');
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
const newChildren = await parseChildren(blocklet.meta, {
|
|
1430
|
+
children: [
|
|
1431
|
+
{
|
|
1432
|
+
meta,
|
|
1433
|
+
mountPoint,
|
|
1434
|
+
sourceUrl: url,
|
|
1435
|
+
},
|
|
1436
|
+
],
|
|
1437
|
+
dynamic: true,
|
|
1438
|
+
});
|
|
1439
|
+
|
|
1440
|
+
checkDuplicateComponents(blocklet.children, newChildren);
|
|
1441
|
+
|
|
1442
|
+
return this.updateChildren(
|
|
1443
|
+
{
|
|
1444
|
+
did: rootDid,
|
|
1445
|
+
children: [...blocklet.children, ...newChildren],
|
|
1446
|
+
},
|
|
1447
|
+
context
|
|
1448
|
+
);
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
async _installFromCreate({ title, description }, context = {}) {
|
|
1452
|
+
logger.debug('create blocklet', { title, description });
|
|
1453
|
+
|
|
1454
|
+
await joi.string().label('title').max(20).required().validateAsync(title);
|
|
1455
|
+
await joi.string().label('description').max(80).required().validateAsync(description);
|
|
1456
|
+
|
|
1457
|
+
const { did, name } = await this._findNextCustomBlockletName();
|
|
1458
|
+
const rawMeta = {
|
|
1459
|
+
name,
|
|
1460
|
+
did,
|
|
1461
|
+
title,
|
|
1462
|
+
description,
|
|
1463
|
+
version: BLOCKLET_DEFAULT_VERSION,
|
|
1464
|
+
group: BlockletGroup.gateway,
|
|
1465
|
+
interfaces: [
|
|
1466
|
+
{
|
|
1467
|
+
type: BLOCKLET_INTERFACE_TYPE_WEB,
|
|
1468
|
+
name: BLOCKLET_INTERFACE_PUBLIC,
|
|
1469
|
+
path: BLOCKLET_DEFAULT_PATH_REWRITE,
|
|
1470
|
+
prefix: BLOCKLET_DYNAMIC_PATH_PREFIX,
|
|
1471
|
+
port: BLOCKLET_DEFAULT_PORT_NAME,
|
|
1472
|
+
protocol: BLOCKLET_INTERFACE_PROTOCOL_HTTP,
|
|
1473
|
+
},
|
|
1474
|
+
],
|
|
1475
|
+
specVersion: BLOCKLET_LATEST_SPEC_VERSION,
|
|
1476
|
+
};
|
|
1477
|
+
const meta = validateMeta(rawMeta);
|
|
1478
|
+
|
|
1479
|
+
await states.blocklet.addBlocklet({
|
|
1480
|
+
did: meta.did,
|
|
1481
|
+
meta,
|
|
1482
|
+
source: BlockletSource.custom,
|
|
1483
|
+
});
|
|
1484
|
+
await this._setConfigs(did);
|
|
1485
|
+
|
|
1486
|
+
// fake install bundle
|
|
1487
|
+
const bundleDir = getBundleDir(this.installDir, meta);
|
|
1488
|
+
fs.mkdirSync(bundleDir, { recursive: true });
|
|
1489
|
+
updateMetaFile(path.join(bundleDir, BLOCKLET_META_FILE), meta);
|
|
1490
|
+
|
|
1491
|
+
return this._installBlocklet({ did, context });
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
async _downloadFromUpload(file) {
|
|
1339
1495
|
// const { filename, mimetype, encoding, createReadStream } = await file;
|
|
1340
1496
|
const { filename, createReadStream } = await file;
|
|
1341
1497
|
const cwd = path.join(this.dataDirs.tmp, 'download');
|
|
@@ -1359,6 +1515,13 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1359
1515
|
writeStream.on('finish', resolve);
|
|
1360
1516
|
});
|
|
1361
1517
|
|
|
1518
|
+
return { cwd, tarFile };
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
async _installFromUpload({ file, did, diffVersion, deleteSet, context }) {
|
|
1522
|
+
logger.info('install blocklet', { from: 'upload file' });
|
|
1523
|
+
const { cwd, tarFile } = await this._downloadFromUpload(file);
|
|
1524
|
+
|
|
1362
1525
|
// diff deploy
|
|
1363
1526
|
if (did && diffVersion) {
|
|
1364
1527
|
const oldBlocklet = await states.blocklet.getBlocklet(did);
|
|
@@ -1379,14 +1542,12 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1379
1542
|
throw new Error(`Can not deploy blocklet when it is ${fromBlockletStatus(oldBlocklet.status)}`);
|
|
1380
1543
|
}
|
|
1381
1544
|
|
|
1382
|
-
const { meta } = await this._resolveDiffDownload(cwd, tarFile, deleteSet, oldBlocklet);
|
|
1383
|
-
const childrenMeta = await getChildrenMeta(meta);
|
|
1384
|
-
mergeMeta(meta, childrenMeta);
|
|
1545
|
+
const { meta } = await this._resolveDiffDownload(cwd, tarFile, deleteSet, oldBlocklet.meta);
|
|
1385
1546
|
const newBlocklet = await states.blocklet.getBlocklet(did);
|
|
1386
1547
|
newBlocklet.meta = meta;
|
|
1387
1548
|
newBlocklet.source = BlockletSource.upload;
|
|
1388
1549
|
newBlocklet.deployedFrom = `Upload by ${context.user.did}`;
|
|
1389
|
-
newBlocklet.children = await
|
|
1550
|
+
newBlocklet.children = await this._getChildren(meta);
|
|
1390
1551
|
await validateBlocklet(newBlocklet);
|
|
1391
1552
|
await this._downloadBlocklet(newBlocklet, oldBlocklet);
|
|
1392
1553
|
|
|
@@ -1401,19 +1562,18 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1401
1562
|
const { meta } = await this._resolveDownload(cwd, tarFile);
|
|
1402
1563
|
const oldBlocklet = await states.blocklet.getBlocklet(meta.did);
|
|
1403
1564
|
|
|
1565
|
+
// full deploy - upgrade
|
|
1404
1566
|
if (oldBlocklet) {
|
|
1405
1567
|
if (isInProgress(oldBlocklet.status)) {
|
|
1406
1568
|
logger.error(`Can not deploy blocklet when it is ${fromBlockletStatus(oldBlocklet.status)}`);
|
|
1407
1569
|
throw new Error(`Can not deploy blocklet when it is ${fromBlockletStatus(oldBlocklet.status)}`);
|
|
1408
1570
|
}
|
|
1409
1571
|
|
|
1410
|
-
const childrenMeta = await getChildrenMeta(meta);
|
|
1411
|
-
mergeMeta(meta, childrenMeta);
|
|
1412
1572
|
const newBlocklet = await states.blocklet.getBlocklet(meta.did);
|
|
1413
1573
|
newBlocklet.meta = meta;
|
|
1414
1574
|
newBlocklet.source = BlockletSource.upload;
|
|
1415
1575
|
newBlocklet.deployedFrom = `Upload by ${context.user.did}`;
|
|
1416
|
-
newBlocklet.children = await
|
|
1576
|
+
newBlocklet.children = await this._getChildren(meta);
|
|
1417
1577
|
|
|
1418
1578
|
await validateBlocklet(newBlocklet);
|
|
1419
1579
|
await this._downloadBlocklet(newBlocklet, oldBlocklet);
|
|
@@ -1425,14 +1585,14 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1425
1585
|
});
|
|
1426
1586
|
}
|
|
1427
1587
|
|
|
1428
|
-
|
|
1429
|
-
|
|
1588
|
+
// full deploy - install
|
|
1589
|
+
const children = await this._getChildren(meta);
|
|
1430
1590
|
const blocklet = await states.blocklet.addBlocklet({
|
|
1431
1591
|
did: meta.did,
|
|
1432
1592
|
meta,
|
|
1433
1593
|
source: BlockletSource.upload,
|
|
1434
1594
|
deployedFrom: `Upload by ${context.user.did}`,
|
|
1435
|
-
|
|
1595
|
+
children,
|
|
1436
1596
|
});
|
|
1437
1597
|
|
|
1438
1598
|
await validateBlocklet(blocklet);
|
|
@@ -1440,13 +1600,92 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1440
1600
|
await this._setConfigs(meta.did);
|
|
1441
1601
|
|
|
1442
1602
|
// download
|
|
1443
|
-
await this._downloadBlocklet(
|
|
1603
|
+
await this._downloadBlocklet(
|
|
1604
|
+
blocklet,
|
|
1605
|
+
// let downloader skip re-downloading dynamic blocklet
|
|
1606
|
+
{ children: children.filter((x) => x.dynamic) }
|
|
1607
|
+
);
|
|
1444
1608
|
return this._installBlocklet({
|
|
1445
1609
|
did: meta.did,
|
|
1446
1610
|
context,
|
|
1447
1611
|
});
|
|
1448
1612
|
}
|
|
1449
1613
|
|
|
1614
|
+
async _installComponentFromUpload({ rootDid, mountPoint, file, did, diffVersion, deleteSet, context }) {
|
|
1615
|
+
logger.info('install blocklet', { from: 'upload file' });
|
|
1616
|
+
// download
|
|
1617
|
+
const { cwd, tarFile } = await this._downloadFromUpload(file);
|
|
1618
|
+
|
|
1619
|
+
const oldBlocklet = await states.blocklet.getBlocklet(rootDid);
|
|
1620
|
+
if (!oldBlocklet) {
|
|
1621
|
+
throw new Error('Root blocklet does not exist');
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
if (isInProgress(oldBlocklet.status)) {
|
|
1625
|
+
logger.error(`Can not deploy blocklet when it is ${fromBlockletStatus(oldBlocklet.status)}`);
|
|
1626
|
+
throw new Error(`Can not deploy blocklet when it is ${fromBlockletStatus(oldBlocklet.status)}`);
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
let meta;
|
|
1630
|
+
// diff upload
|
|
1631
|
+
if (did && diffVersion) {
|
|
1632
|
+
const oldChild = oldBlocklet.children.find((x) => x.meta.did === did);
|
|
1633
|
+
if (!oldChild) {
|
|
1634
|
+
throw new Error(`Blocklet ${did} not found when diff deploying`);
|
|
1635
|
+
}
|
|
1636
|
+
if (oldChild.meta.version !== diffVersion) {
|
|
1637
|
+
logger.error('Diff deploy: Blocklet version changed', {
|
|
1638
|
+
preVersion: diffVersion,
|
|
1639
|
+
changedVersion: oldChild.meta.version,
|
|
1640
|
+
name: oldChild.meta.name,
|
|
1641
|
+
did: oldChild.meta.did,
|
|
1642
|
+
});
|
|
1643
|
+
throw new Error('Blocklet version changed when diff deploying');
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
meta = (await this._resolveDiffDownload(cwd, tarFile, deleteSet, oldChild.meta)).meta;
|
|
1647
|
+
} else {
|
|
1648
|
+
// full deploy
|
|
1649
|
+
meta = (await this._resolveDownload(cwd, tarFile)).meta;
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
if (meta.did === rootDid) {
|
|
1653
|
+
// should not be here
|
|
1654
|
+
throw new Error('Cannot add self as a component');
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
const newBlocklet = await states.blocklet.getBlocklet(rootDid);
|
|
1658
|
+
const dynamicChildren = await this._getDynamicChildrenFromSettings(rootDid);
|
|
1659
|
+
|
|
1660
|
+
const newChild = {
|
|
1661
|
+
meta,
|
|
1662
|
+
mountPoint,
|
|
1663
|
+
source: BlockletSource.upload,
|
|
1664
|
+
deployedFrom: `Upload by ${context.user.did}`,
|
|
1665
|
+
sourceUrl: '',
|
|
1666
|
+
dynamic: true,
|
|
1667
|
+
};
|
|
1668
|
+
const index = dynamicChildren.findIndex((child) => child.meta.did === meta.did);
|
|
1669
|
+
if (index >= 0) {
|
|
1670
|
+
dynamicChildren.splice(index, 1, newChild);
|
|
1671
|
+
} else {
|
|
1672
|
+
dynamicChildren.push(newChild);
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1675
|
+
const staticChildren = newBlocklet.children.filter((x) => !x.dynamic);
|
|
1676
|
+
checkDuplicateComponents(dynamicChildren, staticChildren);
|
|
1677
|
+
|
|
1678
|
+
newBlocklet.children = [...staticChildren, ...dynamicChildren.map((x) => ({ ...x, dynamic: true }))];
|
|
1679
|
+
|
|
1680
|
+
await validateBlocklet(newBlocklet);
|
|
1681
|
+
|
|
1682
|
+
return this._upgradeBlocklet({
|
|
1683
|
+
oldBlocklet,
|
|
1684
|
+
newBlocklet,
|
|
1685
|
+
context,
|
|
1686
|
+
});
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1450
1689
|
/**
|
|
1451
1690
|
* add to download job queue
|
|
1452
1691
|
* @param {string} did blocklet did
|
|
@@ -1481,7 +1720,14 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1481
1720
|
|
|
1482
1721
|
async prune() {
|
|
1483
1722
|
const blocklets = await states.blocklet.getBlocklets();
|
|
1484
|
-
await
|
|
1723
|
+
const settings = await states.blockletExtras.listSettings();
|
|
1724
|
+
await pruneBlockletBundle({
|
|
1725
|
+
installDir: this.dataDirs.blocklets,
|
|
1726
|
+
blocklets,
|
|
1727
|
+
blockletSettings: settings
|
|
1728
|
+
.filter((x) => x.settings.children && x.settings.children.length)
|
|
1729
|
+
.map((x) => x.settings),
|
|
1730
|
+
});
|
|
1485
1731
|
}
|
|
1486
1732
|
|
|
1487
1733
|
async getLatestBlockletVersion({ did, version }) {
|
|
@@ -1569,20 +1815,35 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1569
1815
|
blocklets.forEach(run);
|
|
1570
1816
|
}
|
|
1571
1817
|
|
|
1818
|
+
async _getChildren(meta) {
|
|
1819
|
+
const staticChildren = await parseChildren(meta);
|
|
1820
|
+
const dynamicChildren = await parseChildren(meta, {
|
|
1821
|
+
children: await states.blockletExtras.getSettings(meta.did, 'children', []),
|
|
1822
|
+
dynamic: true,
|
|
1823
|
+
});
|
|
1824
|
+
checkDuplicateComponents(dynamicChildren, staticChildren);
|
|
1825
|
+
|
|
1826
|
+
return [...staticChildren, ...dynamicChildren];
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
async _getDynamicChildrenFromSettings(did) {
|
|
1830
|
+
const children = await states.blockletExtras.getSettings(did, 'children', []);
|
|
1831
|
+
return children.map((x) => ({ ...x, dynamic: true }));
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1572
1834
|
async _install({ meta, source, deployedFrom, context, sync }) {
|
|
1573
1835
|
validateBlockletMeta(meta, { ensureDist: true });
|
|
1574
1836
|
|
|
1575
1837
|
const { name, did, version } = meta;
|
|
1576
1838
|
|
|
1577
|
-
const
|
|
1578
|
-
mergeMeta(meta, childrenMeta);
|
|
1839
|
+
const children = await this._getChildren(meta);
|
|
1579
1840
|
try {
|
|
1580
1841
|
const blocklet = await states.blocklet.addBlocklet({
|
|
1581
1842
|
did: meta.did,
|
|
1582
1843
|
meta,
|
|
1583
1844
|
source,
|
|
1584
1845
|
deployedFrom,
|
|
1585
|
-
|
|
1846
|
+
children,
|
|
1586
1847
|
});
|
|
1587
1848
|
|
|
1588
1849
|
await validateBlocklet(blocklet);
|
|
@@ -1597,6 +1858,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1597
1858
|
// download
|
|
1598
1859
|
const downloadParams = {
|
|
1599
1860
|
blocklet: { ...blocklet1 },
|
|
1861
|
+
oldBlocklet: { children: children.filter((x) => x.dynamic) }, // let downloader skip re-downloading dynamic blocklet
|
|
1600
1862
|
context,
|
|
1601
1863
|
postAction: 'install',
|
|
1602
1864
|
};
|
|
@@ -1655,7 +1917,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1655
1917
|
}
|
|
1656
1918
|
|
|
1657
1919
|
async _upgrade({ meta, source, deployedFrom, context, sync }) {
|
|
1658
|
-
validateBlockletMeta(meta, { ensureDist:
|
|
1920
|
+
validateBlockletMeta(meta, { ensureDist: meta.group !== BlockletGroup.gateway });
|
|
1659
1921
|
|
|
1660
1922
|
const { name, version, did } = meta;
|
|
1661
1923
|
|
|
@@ -1666,12 +1928,11 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1666
1928
|
logger.info(`${action} blocklet`, { did, version });
|
|
1667
1929
|
|
|
1668
1930
|
const newBlocklet = await states.blocklet.setBlockletStatus(did, BlockletStatus.waiting);
|
|
1669
|
-
|
|
1670
|
-
mergeMeta(meta, childrenMeta);
|
|
1931
|
+
|
|
1671
1932
|
newBlocklet.meta = meta;
|
|
1672
1933
|
newBlocklet.source = source;
|
|
1673
1934
|
newBlocklet.deployedFrom = deployedFrom;
|
|
1674
|
-
newBlocklet.children = await
|
|
1935
|
+
newBlocklet.children = await this._getChildren(meta);
|
|
1675
1936
|
|
|
1676
1937
|
await validateBlocklet(newBlocklet);
|
|
1677
1938
|
|
|
@@ -1774,7 +2035,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1774
2035
|
|
|
1775
2036
|
await ensureBlockletExpanded(meta, downloadDir);
|
|
1776
2037
|
|
|
1777
|
-
installDir =
|
|
2038
|
+
installDir = getBundleDir(this.installDir, meta);
|
|
1778
2039
|
if (fs.existsSync(installDir)) {
|
|
1779
2040
|
fs.removeSync(installDir);
|
|
1780
2041
|
logger.info('cleanup blocklet upgrade dir', { name, version, installDir });
|
|
@@ -1791,7 +2052,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1791
2052
|
return { meta, installDir };
|
|
1792
2053
|
}
|
|
1793
2054
|
|
|
1794
|
-
async _resolveDiffDownload(cwd, tarFile, deleteSet,
|
|
2055
|
+
async _resolveDiffDownload(cwd, tarFile, deleteSet, bundle) {
|
|
1795
2056
|
logger.info('Resolve diff download', { tarFile, cwd });
|
|
1796
2057
|
const downloadDir = path.join(cwd, `${path.basename(tarFile, path.extname(tarFile))}`);
|
|
1797
2058
|
const diffDir = `${downloadDir}-diff`;
|
|
@@ -1804,7 +2065,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1804
2065
|
throw error;
|
|
1805
2066
|
}
|
|
1806
2067
|
logger.info('Copy installDir to downloadDir', { installDir: this.installDir, downloadDir });
|
|
1807
|
-
await fs.copy(
|
|
2068
|
+
await fs.copy(getBundleDir(this.installDir, bundle), downloadDir);
|
|
1808
2069
|
try {
|
|
1809
2070
|
// delete
|
|
1810
2071
|
logger.info('Delete files from downloadDir', { fileNum: deleteSet.length });
|
|
@@ -1833,11 +2094,11 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1833
2094
|
|
|
1834
2095
|
await ensureBlockletExpanded(meta, downloadDir);
|
|
1835
2096
|
|
|
1836
|
-
const
|
|
1837
|
-
logger.info('Move downloadDir to installDir', { downloadDir,
|
|
1838
|
-
await fs.move(downloadDir,
|
|
2097
|
+
const bundleDir = getBundleDir(this.installDir, meta);
|
|
2098
|
+
logger.info('Move downloadDir to installDir', { downloadDir, bundleDir });
|
|
2099
|
+
await fs.move(downloadDir, bundleDir, { overwrite: true });
|
|
1839
2100
|
|
|
1840
|
-
return { meta, installDir };
|
|
2101
|
+
return { meta, installDir: bundleDir };
|
|
1841
2102
|
} catch (error) {
|
|
1842
2103
|
fs.removeSync(downloadDir);
|
|
1843
2104
|
fs.removeSync(diffDir);
|
|
@@ -1868,7 +2129,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1868
2129
|
hooks.preInstall({
|
|
1869
2130
|
hooks: Object.assign(b.meta.hooks || {}, b.meta.scripts || {}),
|
|
1870
2131
|
env: { ...nodeEnvironments },
|
|
1871
|
-
appDir:
|
|
2132
|
+
appDir: b.env.appDir,
|
|
1872
2133
|
did, // root blocklet did
|
|
1873
2134
|
notification: states.notification,
|
|
1874
2135
|
context,
|
|
@@ -1884,7 +2145,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1884
2145
|
hooks.postInstall({
|
|
1885
2146
|
hooks: Object.assign(b.meta.hooks || {}, b.meta.scripts || {}),
|
|
1886
2147
|
env: getRuntimeEnvironments(b, nodeEnvironments, blocklet),
|
|
1887
|
-
appDir:
|
|
2148
|
+
appDir: b.env.appDir,
|
|
1888
2149
|
did, // root blocklet did
|
|
1889
2150
|
notification: states.notification,
|
|
1890
2151
|
context,
|
|
@@ -1968,7 +2229,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1968
2229
|
hooks.preInstall({
|
|
1969
2230
|
hooks: Object.assign(b.meta.hooks || {}, b.meta.scripts || {}),
|
|
1970
2231
|
env: { ...nodeEnvironments },
|
|
1971
|
-
appDir:
|
|
2232
|
+
appDir: b.env.appDir,
|
|
1972
2233
|
did, // root blocklet did
|
|
1973
2234
|
notification: states.notification,
|
|
1974
2235
|
context,
|
|
@@ -2053,6 +2314,12 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2053
2314
|
logger.error('emit upgrade notification failed', { name, version, error });
|
|
2054
2315
|
}
|
|
2055
2316
|
|
|
2317
|
+
// Update dynamic component meta in blocklet settings
|
|
2318
|
+
const dynamicChildren = blocklet.children
|
|
2319
|
+
.filter((x) => x.dynamic)
|
|
2320
|
+
.map((x) => pick(x, ['meta', 'mountPoint', 'sourceUrl', 'source']));
|
|
2321
|
+
await states.blockletExtras.setSettings(did, { children: dynamicChildren });
|
|
2322
|
+
|
|
2056
2323
|
return blocklet;
|
|
2057
2324
|
} catch (err) {
|
|
2058
2325
|
const b = await this._rollback(action, did, oldBlocklet);
|
|
@@ -2259,12 +2526,18 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2259
2526
|
|
|
2260
2527
|
for (const child of blocklet.children) {
|
|
2261
2528
|
const oldChild = oldChildren[child.meta.did];
|
|
2262
|
-
if (
|
|
2529
|
+
if (
|
|
2530
|
+
!oldChild ||
|
|
2531
|
+
(![BlockletSource.upload, BlockletSource.local].includes(child.source) &&
|
|
2532
|
+
child.sourceUrl &&
|
|
2533
|
+
get(oldChild, 'meta.dist.integrity') !== get(child, 'meta.dist.integrity'))
|
|
2534
|
+
) {
|
|
2263
2535
|
metas.push(child.meta);
|
|
2264
2536
|
}
|
|
2265
2537
|
}
|
|
2266
2538
|
|
|
2267
2539
|
try {
|
|
2540
|
+
logger.info('Download Blocklet', { name, did, bundles: metas.map((x) => get(x, 'dist.tarball')) });
|
|
2268
2541
|
const tasks = [];
|
|
2269
2542
|
for (const meta of metas) {
|
|
2270
2543
|
const url = await this.registry.resolveTarballURL({
|
|
@@ -2332,7 +2605,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2332
2605
|
async _rollback(action, did, oldBlocklet) {
|
|
2333
2606
|
if (action === 'install') {
|
|
2334
2607
|
// remove blocklet
|
|
2335
|
-
return this._deleteBlocklet({ did, keepData:
|
|
2608
|
+
return this._deleteBlocklet({ did, keepData: true });
|
|
2336
2609
|
}
|
|
2337
2610
|
|
|
2338
2611
|
if (['upgrade', 'downgrade'].includes(action)) {
|
|
@@ -2374,7 +2647,18 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2374
2647
|
const result = await states.blocklet.deleteBlocklet(did);
|
|
2375
2648
|
logger.info('blocklet removed successfully', { did });
|
|
2376
2649
|
|
|
2377
|
-
|
|
2650
|
+
let keepRouting = true;
|
|
2651
|
+
if (keepData === false || keepConfigs === false) {
|
|
2652
|
+
keepRouting = false;
|
|
2653
|
+
}
|
|
2654
|
+
|
|
2655
|
+
this.emit(BlockletEvents.removed, {
|
|
2656
|
+
blocklet: result,
|
|
2657
|
+
context: {
|
|
2658
|
+
...context,
|
|
2659
|
+
keepRouting,
|
|
2660
|
+
},
|
|
2661
|
+
});
|
|
2378
2662
|
return blocklet;
|
|
2379
2663
|
}
|
|
2380
2664
|
|
|
@@ -2395,6 +2679,20 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2395
2679
|
await states.blockletExtras.delChildConfigs(did, child.meta.did);
|
|
2396
2680
|
}
|
|
2397
2681
|
}
|
|
2682
|
+
|
|
2683
|
+
async _findNextCustomBlockletName(leftTimes = 10) {
|
|
2684
|
+
if (leftTimes <= 0) {
|
|
2685
|
+
throw new Error('Generate custom blocklet did too many times');
|
|
2686
|
+
}
|
|
2687
|
+
const number = await states.node.increaseCustomBlockletNumber();
|
|
2688
|
+
const name = `custom-${number}`;
|
|
2689
|
+
const did = toBlockletDid(name);
|
|
2690
|
+
const blocklet = await states.blocklet.getBlocklet(did);
|
|
2691
|
+
if (blocklet) {
|
|
2692
|
+
return this._findNextCustomBlockletName(leftTimes - 1);
|
|
2693
|
+
}
|
|
2694
|
+
return { did, name };
|
|
2695
|
+
}
|
|
2398
2696
|
}
|
|
2399
2697
|
|
|
2400
2698
|
module.exports = BlockletManager;
|