@abtnode/core 1.7.9 → 1.7.12

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 CHANGED
@@ -10,7 +10,7 @@ const canPackageReadWrite = require('@abtnode/util/lib/can-pkg-rw');
10
10
  const logger = require('@abtnode/logger')('@abtnode/core:api:node');
11
11
 
12
12
  const IP = require('../util/ip');
13
- const { validateNodeInfo } = require('../validators/node');
13
+ const { validateNodeInfo, validateUpdateGateway } = require('../validators/node');
14
14
  const BlockletRegistry = require('../blocklet/registry');
15
15
  const { getAll } = require('../blocklet/manager/engine');
16
16
 
@@ -154,6 +154,12 @@ class NodeAPI {
154
154
 
155
155
  return res;
156
156
  }
157
+
158
+ async updateGateway(entity, context) {
159
+ const data = await validateUpdateGateway(entity, context);
160
+
161
+ return this.state.updateGateway(data);
162
+ }
157
163
  }
158
164
 
159
165
  module.exports = NodeAPI;
package/lib/api/team.js CHANGED
@@ -54,9 +54,9 @@ class TeamAPI extends EventEmitter {
54
54
  if (teamDid === nodeInfo.did && nodeInfo.nodeOwner && user.did !== nodeInfo.nodeOwner.did) {
55
55
  await this.notification.create({
56
56
  title: 'New member join',
57
- description: `User with Name (${user.fullName}) and DID (${user.did}) has joined this Node`,
57
+ description: `User with Name (${user.fullName}) and DID (${user.did}) has joined this server`,
58
58
  entityType: 'node',
59
- action: '/settings/team',
59
+ action: '/team/members',
60
60
  entityId: user.did,
61
61
  severity: 'success',
62
62
  });
@@ -31,6 +31,7 @@ const {
31
31
  isDeletableBlocklet,
32
32
  getRequiredMissingConfigs,
33
33
  hasRunnableComponent,
34
+ forEachBlocklet,
34
35
  } = require('@blocklet/meta/lib/util');
35
36
  const validateBlockletEntry = require('@blocklet/meta/lib/entry');
36
37
  const toBlockletDid = require('@blocklet/meta/lib/did');
@@ -63,7 +64,6 @@ const {
63
64
  getFromCache: getAccessibleExternalNodeIp,
64
65
  } = require('../../util/get-accessible-external-node-ip');
65
66
  const {
66
- forEachBlocklet,
67
67
  getBlockletDirs,
68
68
  getBlockletMetaFromUrl,
69
69
  fillBlockletConfigs,
@@ -88,12 +88,15 @@ const {
88
88
  getUpdateMetaList,
89
89
  getRuntimeEnvironments,
90
90
  getSourceFromInstallParams,
91
+ parseChildrenFromMeta,
91
92
  parseChildren,
92
93
  checkDuplicateComponents,
93
94
  getDiffFiles,
94
95
  getBundleDir,
95
96
  needBlockletDownload,
96
97
  verifyPurchase,
98
+ findAvailableDid,
99
+ ensureMeta,
97
100
  } = require('../../util/blocklet');
98
101
  const { parseSourceUrl } = require('../../util/registry');
99
102
  const states = require('../../states');
@@ -217,11 +220,15 @@ class BlockletManager extends BaseBlockletManager {
217
220
  *
218
221
  * InstallFromUpload
219
222
  * @param {Object} file
220
- * @param {String} did for diff upload
223
+ * @param {String} did for diff upload or custom component did
221
224
  * @param {String} diffVersion for diff upload
222
225
  * @param {Array} deleteSet for diff upload
226
+ *
227
+ * Custom info
228
+ * @param {String} title custom component title
229
+ * @param {String} name custom component name
223
230
  */
224
- async installComponent({ rootDid, mountPoint, url, file, did, diffVersion, deleteSet }, context = {}) {
231
+ async installComponent({ rootDid, mountPoint, url, file, did, diffVersion, deleteSet, title, name }, context = {}) {
225
232
  logger.debug('start install component', { rootDid, mountPoint, url });
226
233
 
227
234
  if (file) {
@@ -229,7 +236,7 @@ class BlockletManager extends BaseBlockletManager {
229
236
  }
230
237
 
231
238
  if (url) {
232
- return this._installComponentFromUrl({ rootDid, mountPoint, url, context });
239
+ return this._installComponentFromUrl({ rootDid, mountPoint, url, context, title, did, name });
233
240
  }
234
241
 
235
242
  // should not be here
@@ -283,7 +290,7 @@ class BlockletManager extends BaseBlockletManager {
283
290
 
284
291
  async start({ did, throwOnError, checkHealthImmediately = false, e2eMode = false }, context) {
285
292
  logger.info('start blocklet', { did });
286
- const blocklet = await this.ensureBlocklet(did, e2eMode);
293
+ const blocklet = await this.ensureBlocklet(did, { e2eMode });
287
294
 
288
295
  try {
289
296
  if (!hasRunnableComponent(blocklet)) {
@@ -452,7 +459,7 @@ class BlockletManager extends BaseBlockletManager {
452
459
  logger.info('delete blocklet', { did, keepData });
453
460
 
454
461
  try {
455
- const blocklet = await this.ensureBlocklet(did);
462
+ const blocklet = await this.ensureBlocklet(did, { validateEnv: false });
456
463
  if (isDeletableBlocklet(blocklet) === false) {
457
464
  throw new Error('Blocklet is protected from accidental deletion');
458
465
  }
@@ -521,14 +528,33 @@ class BlockletManager extends BaseBlockletManager {
521
528
  async deleteComponent({ did, rootDid }, context) {
522
529
  logger.info('delete blocklet component', { did, rootDid });
523
530
 
531
+ const blocklet = await this.ensureBlocklet(rootDid);
524
532
  const doc = await states.blocklet.getBlocklet(rootDid);
525
533
 
534
+ const child = doc.children.find((x) => x.meta.did === did);
535
+
536
+ if (!child) {
537
+ throw new Error('Component does not exist');
538
+ }
539
+
526
540
  doc.children = doc.children.filter((x) => x.meta.did !== did);
527
541
  const children = (await this._getDynamicChildrenFromSettings(rootDid)).filter((x) => x.meta.did !== did);
542
+ children.push({
543
+ meta: pick(child.meta, ['did', 'name', 'bundleDid', 'bundleName', 'version', 'title', 'description']),
544
+ mountPoint: child.mountPoint,
545
+ status: BlockletStatus.deleted,
546
+ deletedAt: new Date(),
547
+ });
528
548
 
529
549
  await states.blocklet.updateBlocklet(rootDid, doc);
530
550
  states.blockletExtras.setSettings(rootDid, { children });
531
551
 
552
+ // delete storage
553
+ const childBlocklet = blocklet.children.find((x) => x.meta.did === did);
554
+ const { cacheDir, logsDir } = childBlocklet.env;
555
+ fs.removeSync(cacheDir);
556
+ fs.removeSync(logsDir);
557
+
532
558
  const newBlocklet = await this.ensureBlocklet(rootDid);
533
559
  this.emit(BlockletEvents.upgraded, { blocklet: newBlocklet, context }); // trigger router refresh
534
560
  return newBlocklet;
@@ -627,7 +653,7 @@ class BlockletManager extends BaseBlockletManager {
627
653
  }
628
654
 
629
655
  // eslint-disable-next-line no-unused-vars
630
- async config({ did, childDid, configs: newConfigs }, context) {
656
+ async config({ did, childDid, configs: newConfigs, skipHook }, context) {
631
657
  logger.info('config blocklet', { did });
632
658
  if (!Array.isArray(newConfigs)) {
633
659
  throw new Error('configs list is not an array');
@@ -694,15 +720,17 @@ class BlockletManager extends BaseBlockletManager {
694
720
  blocklet.configObj[x.key] = x.value;
695
721
  }
696
722
 
697
- // FIXME: we should also call preConfig for child blocklets
698
- await hooks.preConfig(blocklet.env.appId, {
699
- appDir: blocklet.env.appDir,
700
- hooks: Object.assign(blocklet.meta.hooks || {}, blocklet.meta.scripts || {}),
701
- exitOnError: true,
702
- env: { ...getRuntimeEnvironments(blocklet, nodeEnvironments), ...blocklet.configObj },
703
- did,
704
- context,
705
- });
723
+ if (!skipHook) {
724
+ // FIXME: we should also call preConfig for child blocklets
725
+ await hooks.preConfig(blocklet.env.appId, {
726
+ appDir: blocklet.env.appDir,
727
+ hooks: Object.assign(blocklet.meta.hooks || {}, blocklet.meta.scripts || {}),
728
+ exitOnError: true,
729
+ env: { ...getRuntimeEnvironments(blocklet, nodeEnvironments), ...blocklet.configObj },
730
+ did,
731
+ context,
732
+ });
733
+ }
706
734
 
707
735
  // update db
708
736
  const configs = childDid
@@ -736,9 +764,9 @@ class BlockletManager extends BaseBlockletManager {
736
764
 
737
765
  const upgradeFromRegistry = registryUrl || blocklet.deployedFrom;
738
766
 
739
- const newVersionBlocklet = await this.registry.getBlockletMeta(
767
+ const newVersionMeta = await this.registry.getBlockletMeta(
740
768
  {
741
- did,
769
+ did: blocklet.meta.bundleDid,
742
770
  registryUrl: upgradeFromRegistry,
743
771
  },
744
772
  context
@@ -765,7 +793,7 @@ class BlockletManager extends BaseBlockletManager {
765
793
  }
766
794
 
767
795
  const currentDeveloperSignature = getSignature(blocklet.meta.signatures);
768
- const newVersionDeveloperSignature = getSignature(newVersionBlocklet.signatures, blocklet.meta.signatures);
796
+ const newVersionDeveloperSignature = getSignature(newVersionMeta.signatures, blocklet.meta.signatures);
769
797
 
770
798
  if (!newVersionDeveloperSignature) {
771
799
  throw new Error('Invalid upgrade blocklet signature');
@@ -781,15 +809,15 @@ class BlockletManager extends BaseBlockletManager {
781
809
  throw new Error('Invalid developer signature');
782
810
  }
783
811
 
784
- if (blocklet.meta.version === newVersionBlocklet.version) {
812
+ if (blocklet.meta.version === newVersionMeta.version) {
785
813
  throw new Error('Upgrade/downgrade blocklet to same version is noop');
786
814
  }
787
815
 
788
- const action = semver.gt(blocklet.meta.version, newVersionBlocklet.version) ? 'downgrade' : 'upgrade';
816
+ const action = semver.gt(blocklet.meta.version, newVersionMeta.version) ? 'downgrade' : 'upgrade';
789
817
  logger.info(`${action} blocklet`, { did });
790
818
 
791
819
  return this._upgrade({
792
- meta: newVersionBlocklet,
820
+ meta: newVersionMeta,
793
821
  source: BlockletSource.registry,
794
822
  deployedFrom: upgradeFromRegistry,
795
823
  context,
@@ -857,16 +885,19 @@ class BlockletManager extends BaseBlockletManager {
857
885
 
858
886
  async checkChildrenForUpdates({ did }) {
859
887
  const blocklet = await states.blocklet.getBlocklet(did);
860
- const newStaticChildren = await parseChildren(blocklet.meta);
888
+ const newStaticChildren = await parseChildrenFromMeta(blocklet.meta);
861
889
 
862
- const oldDynamicChildren = await this._getDynamicChildrenFromSettings(did);
890
+ const oldDynamicChildren = await this._getDynamicChildrenFromSettings(did, { skipDeleted: true });
863
891
  const noneSourceUrlChildren = oldDynamicChildren.filter((x) => !x.sourceUrl);
864
892
  const dynamicConfig = oldDynamicChildren
865
893
  .filter((x) => x.sourceUrl)
866
894
  .map((x) => ({ resolved: x.sourceUrl, name: x.meta.name, mountPoint: x.mountPoint }));
867
- const newDynamicChildren = [...noneSourceUrlChildren, ...(await parseChildren(dynamicConfig, { dynamic: true }))];
895
+ const newDynamicChildren = [
896
+ ...noneSourceUrlChildren,
897
+ ...(await parseChildrenFromMeta(dynamicConfig, { dynamic: true })),
898
+ ];
868
899
 
869
- checkDuplicateComponents(newDynamicChildren, newStaticChildren);
900
+ checkDuplicateComponents([...newDynamicChildren, ...newStaticChildren]);
870
901
 
871
902
  const updateList = getUpdateMetaList(
872
903
  [...blocklet.children.map((x) => x.meta), ...oldDynamicChildren.map((x) => x.meta)],
@@ -1011,7 +1042,6 @@ class BlockletManager extends BaseBlockletManager {
1011
1042
 
1012
1043
  const children = await this._getChildren(meta);
1013
1044
  const added = await states.blocklet.addBlocklet({
1014
- did,
1015
1045
  meta,
1016
1046
  source: BlockletSource.local,
1017
1047
  deployedFrom: folder,
@@ -1060,19 +1090,17 @@ class BlockletManager extends BaseBlockletManager {
1060
1090
  }
1061
1091
 
1062
1092
  const defaultPath = formatName(meta.name);
1063
- const children = await parseChildren(existRoot.meta, {
1064
- children: [
1065
- {
1066
- meta,
1067
- mountPoint: mountPoint || `/${defaultPath}`,
1068
- source: BlockletSource.local,
1069
- deployedFrom: folder,
1070
- status: BlockletStatus.installed,
1071
- mode: BLOCKLET_MODES.DEVELOPMENT,
1072
- },
1073
- ],
1074
- dynamic: true,
1075
- });
1093
+ const children = await parseChildren([
1094
+ {
1095
+ meta: ensureMeta(meta),
1096
+ mountPoint: mountPoint || `/${defaultPath}`,
1097
+ source: BlockletSource.local,
1098
+ deployedFrom: folder,
1099
+ status: BlockletStatus.installed,
1100
+ mode: BLOCKLET_MODES.DEVELOPMENT,
1101
+ dynamic: true,
1102
+ },
1103
+ ]);
1076
1104
  await states.blocklet.addChildren(rootDid, children);
1077
1105
 
1078
1106
  logger.info('add blocklet component for dev', { did, version, meta });
@@ -1086,7 +1114,7 @@ class BlockletManager extends BaseBlockletManager {
1086
1114
  return rootBlocklet;
1087
1115
  }
1088
1116
 
1089
- async ensureBlocklet(did, e2eMode = false) {
1117
+ async ensureBlocklet(did, { e2eMode = false, validateEnv = true } = {}) {
1090
1118
  if (!isValidDid(did)) {
1091
1119
  throw new Error(`Blocklet did is invalid: ${did}`);
1092
1120
  }
@@ -1096,6 +1124,7 @@ class BlockletManager extends BaseBlockletManager {
1096
1124
  throw new Error(`Can not find blocklet in database by did ${did}`);
1097
1125
  }
1098
1126
 
1127
+ // env
1099
1128
  blocklet.env = {
1100
1129
  appId: blocklet.meta.name,
1101
1130
  // dataDir is /dataDir.data/blocklet.meta.name
@@ -1105,18 +1134,23 @@ class BlockletManager extends BaseBlockletManager {
1105
1134
  dataDirs: this.dataDirs,
1106
1135
  ensure: true,
1107
1136
  e2eMode,
1137
+ validate: validateEnv,
1108
1138
  }),
1109
1139
  };
1110
1140
 
1141
+ // configs
1111
1142
  const configs = await states.blockletExtras.getConfigs(blocklet.meta.did);
1112
1143
  fillBlockletConfigs(blocklet, configs);
1113
1144
 
1114
- // merge settings to blocklet
1145
+ // settings
1115
1146
  const settings = await states.blockletExtras.getSettings(blocklet.meta.did);
1116
1147
  blocklet.trustedPassports = get(settings, 'trustedPassports') || [];
1117
1148
  blocklet.enablePassportIssuance = get(settings, 'enablePassportIssuance', true);
1118
1149
  blocklet.settings = settings || {};
1119
1150
 
1151
+ // site
1152
+ blocklet.site = await this.getSiteByDid(blocklet.meta.did);
1153
+
1120
1154
  // handle child env
1121
1155
  for (const child of blocklet.children) {
1122
1156
  const {
@@ -1126,11 +1160,9 @@ class BlockletManager extends BaseBlockletManager {
1126
1160
  meta: { name },
1127
1161
  } = blocklet;
1128
1162
 
1163
+ // child env
1129
1164
  child.env = {
1130
1165
  appId: `${encodeURIComponent(name)}/${encodeURIComponent(childName)}`,
1131
- // dataDir is /dataDir.data/blocklet.meta.name/child.meta.name
1132
- // cacheDir is /dataDirs.cache/blocklet.meta.name/child.meta.name
1133
- // logDir is /dataDirs.log/blocklet.meta.name
1134
1166
  ...getBlockletDirs(child, {
1135
1167
  dataDirs: this.dataDirs,
1136
1168
  ensure: true,
@@ -1138,13 +1170,11 @@ class BlockletManager extends BaseBlockletManager {
1138
1170
  }),
1139
1171
  };
1140
1172
 
1173
+ // child configs
1141
1174
  const childConfigs = await states.blockletExtras.getChildConfigs(blocklet.meta.did, childDid);
1142
1175
  fillBlockletConfigs(child, childConfigs, blocklet);
1143
1176
  }
1144
1177
 
1145
- // site
1146
- blocklet.site = await this.getSiteByDid(blocklet.meta.did);
1147
-
1148
1178
  return blocklet;
1149
1179
  }
1150
1180
 
@@ -1581,7 +1611,7 @@ class BlockletManager extends BaseBlockletManager {
1581
1611
  });
1582
1612
  }
1583
1613
 
1584
- async _installComponentFromUrl({ rootDid, mountPoint, url, context }) {
1614
+ async _installComponentFromUrl({ rootDid, mountPoint, url, context, title, name: inputName, did: inputDid }) {
1585
1615
  const blocklet = await states.blocklet.getBlocklet(rootDid);
1586
1616
  if (!blocklet) {
1587
1617
  throw new Error('Root blocklet does not exist');
@@ -1599,18 +1629,31 @@ class BlockletManager extends BaseBlockletManager {
1599
1629
 
1600
1630
  verifyPurchase(meta, context);
1601
1631
 
1602
- const newChildren = await parseChildren(blocklet.meta, {
1603
- children: [
1604
- {
1605
- meta,
1606
- mountPoint,
1607
- sourceUrl: url,
1608
- },
1609
- ],
1610
- dynamic: true,
1611
- });
1632
+ if (title) {
1633
+ meta.title = await titleSchema.validateAsync(title);
1634
+ }
1635
+
1636
+ let name = inputName;
1637
+ let did = inputDid;
1638
+ if (!inputName && !inputDid) {
1639
+ const found = findAvailableDid(meta, [
1640
+ ...blocklet.children.map((x) => x.meta),
1641
+ ...(await states.blockletExtras.getSettings(rootDid, 'children', [])).map((x) => x.meta),
1642
+ ]);
1643
+ name = found.name;
1644
+ did = found.did;
1645
+ }
1612
1646
 
1613
- checkDuplicateComponents(blocklet.children, newChildren);
1647
+ const newChildren = await parseChildren([
1648
+ {
1649
+ meta: ensureMeta(meta, { did, name }),
1650
+ mountPoint,
1651
+ sourceUrl: url,
1652
+ dynamic: true,
1653
+ },
1654
+ ]);
1655
+
1656
+ checkDuplicateComponents([...blocklet.children, ...newChildren]);
1614
1657
 
1615
1658
  // add component to db
1616
1659
  await states.blocklet.addChildren(rootDid, newChildren);
@@ -1654,7 +1697,6 @@ class BlockletManager extends BaseBlockletManager {
1654
1697
  const meta = validateMeta(rawMeta);
1655
1698
 
1656
1699
  await states.blocklet.addBlocklet({
1657
- did: meta.did,
1658
1700
  meta,
1659
1701
  source: BlockletSource.custom,
1660
1702
  });
@@ -1721,7 +1763,7 @@ class BlockletManager extends BaseBlockletManager {
1721
1763
 
1722
1764
  const { meta } = await this._resolveDiffDownload(cwd, tarFile, deleteSet, oldBlocklet.meta);
1723
1765
  const newBlocklet = await states.blocklet.getBlocklet(did);
1724
- newBlocklet.meta = meta;
1766
+ newBlocklet.meta = ensureMeta(meta);
1725
1767
  newBlocklet.source = BlockletSource.upload;
1726
1768
  newBlocklet.deployedFrom = `Upload by ${context.user.fullName}`;
1727
1769
  newBlocklet.children = await this._getChildren(meta);
@@ -1747,7 +1789,7 @@ class BlockletManager extends BaseBlockletManager {
1747
1789
  }
1748
1790
 
1749
1791
  const newBlocklet = await states.blocklet.getBlocklet(meta.did);
1750
- newBlocklet.meta = meta;
1792
+ newBlocklet.meta = ensureMeta(meta);
1751
1793
  newBlocklet.source = BlockletSource.upload;
1752
1794
  newBlocklet.deployedFrom = `Upload by ${context.user.fullName}`;
1753
1795
  newBlocklet.children = await this._getChildren(meta);
@@ -1765,7 +1807,6 @@ class BlockletManager extends BaseBlockletManager {
1765
1807
  // full deploy - install
1766
1808
  const children = await this._getChildren(meta);
1767
1809
  const blocklet = await states.blocklet.addBlocklet({
1768
- did: meta.did,
1769
1810
  meta,
1770
1811
  source: BlockletSource.upload,
1771
1812
  deployedFrom: `Upload by ${context.user.fullName}`,
@@ -1832,28 +1873,26 @@ class BlockletManager extends BaseBlockletManager {
1832
1873
  }
1833
1874
 
1834
1875
  const newBlocklet = await states.blocklet.getBlocklet(rootDid);
1835
- const dynamicChildren = await this._getDynamicChildrenFromSettings(rootDid);
1876
+
1877
+ if (newBlocklet.children.some((x) => !x.dynamic && x.meta.did === meta.did)) {
1878
+ throw new Error('Cannot add duplicate component defined in app meta');
1879
+ }
1836
1880
 
1837
1881
  const newChild = {
1838
- meta,
1882
+ meta: ensureMeta(meta),
1839
1883
  mountPoint,
1840
1884
  source: BlockletSource.upload,
1841
1885
  deployedFrom: `Upload by ${context.user.fullName}`,
1842
1886
  sourceUrl: '',
1843
1887
  dynamic: true,
1844
1888
  };
1845
- const index = dynamicChildren.findIndex((child) => child.meta.did === meta.did);
1889
+ const index = newBlocklet.children.findIndex((child) => child.meta.did === meta.did);
1846
1890
  if (index >= 0) {
1847
- dynamicChildren.splice(index, 1, newChild);
1891
+ newBlocklet.children.splice(index, 1, newChild);
1848
1892
  } else {
1849
- dynamicChildren.push(newChild);
1893
+ newBlocklet.children.push(newChild);
1850
1894
  }
1851
1895
 
1852
- const staticChildren = newBlocklet.children.filter((x) => !x.dynamic);
1853
- checkDuplicateComponents(dynamicChildren, staticChildren);
1854
-
1855
- newBlocklet.children = [...staticChildren, ...dynamicChildren.map((x) => ({ ...x, dynamic: true }))];
1856
-
1857
1896
  await validateBlocklet(newBlocklet);
1858
1897
 
1859
1898
  return this._upgradeBlocklet({
@@ -1900,13 +1939,15 @@ class BlockletManager extends BaseBlockletManager {
1900
1939
  throw new Error('the blocklet is not installed');
1901
1940
  }
1902
1941
 
1942
+ const { bundleDid } = blocklet.meta;
1943
+
1903
1944
  let versions = this.cachedBlockletVersions.get(did);
1904
1945
 
1905
1946
  if (!versions) {
1906
1947
  const { blockletRegistryList } = await states.node.read();
1907
1948
  const tasks = blockletRegistryList.map((registry) =>
1908
1949
  this.registry
1909
- .getBlockletMeta({ did, registryUrl: registry.url })
1950
+ .getBlockletMeta({ did: bundleDid, registryUrl: registry.url })
1910
1951
  .then((item) => ({ did, version: item.version, registryUrl: registry.url }))
1911
1952
  .catch((error) => {
1912
1953
  if (error.response && error.response.status === 404) {
@@ -1980,19 +2021,24 @@ class BlockletManager extends BaseBlockletManager {
1980
2021
  }
1981
2022
 
1982
2023
  async _getChildren(meta) {
1983
- const staticChildren = await parseChildren(meta);
1984
- const dynamicChildren = await parseChildren(meta, {
1985
- children: await states.blockletExtras.getSettings(meta.did, 'children', []),
1986
- dynamic: true,
1987
- });
1988
- checkDuplicateComponents(dynamicChildren, staticChildren);
2024
+ const staticChildren = await parseChildrenFromMeta(meta);
2025
+ const dynamicChildren = await parseChildren(
2026
+ await this._getDynamicChildrenFromSettings(meta.did, { skipDeleted: true }),
2027
+ meta,
2028
+ {
2029
+ dynamic: true,
2030
+ }
2031
+ );
2032
+ checkDuplicateComponents([...dynamicChildren, ...staticChildren]);
1989
2033
 
1990
2034
  return [...staticChildren, ...dynamicChildren];
1991
2035
  }
1992
2036
 
1993
- async _getDynamicChildrenFromSettings(did) {
2037
+ async _getDynamicChildrenFromSettings(did, { skipDeleted } = {}) {
1994
2038
  const children = await states.blockletExtras.getSettings(did, 'children', []);
1995
- return children.map((x) => ({ ...x, dynamic: true }));
2039
+ return children
2040
+ .map((x) => ({ ...x, dynamic: true }))
2041
+ .filter((x) => (skipDeleted ? x.status !== BlockletStatus.deleted : true));
1996
2042
  }
1997
2043
 
1998
2044
  async _install({ meta, source, deployedFrom, context, sync }) {
@@ -2003,7 +2049,6 @@ class BlockletManager extends BaseBlockletManager {
2003
2049
  const children = await this._getChildren(meta);
2004
2050
  try {
2005
2051
  const blocklet = await states.blocklet.addBlocklet({
2006
- did: meta.did,
2007
2052
  meta,
2008
2053
  source,
2009
2054
  deployedFrom,
@@ -2089,11 +2134,11 @@ class BlockletManager extends BaseBlockletManager {
2089
2134
 
2090
2135
  // NOTE: 目前的版本移除了降级通道,所以不需要考虑降级通道的情况
2091
2136
  const action = semver.gt(oldBlocklet.meta.version, version) ? 'downgrade' : 'upgrade';
2092
- logger.info(`${action} blocklet`, { did, version });
2137
+ logger.info(`${action} blocklet`, { did, name, version });
2093
2138
 
2094
2139
  const newBlocklet = await states.blocklet.setBlockletStatus(did, BlockletStatus.waiting);
2095
2140
 
2096
- newBlocklet.meta = meta;
2141
+ newBlocklet.meta = ensureMeta(meta);
2097
2142
  newBlocklet.source = source;
2098
2143
  newBlocklet.deployedFrom = deployedFrom;
2099
2144
  newBlocklet.children = await this._getChildren(meta);
@@ -2324,6 +2369,9 @@ class BlockletManager extends BaseBlockletManager {
2324
2369
 
2325
2370
  this.emit(BlockletEvents.installed, { blocklet, context });
2326
2371
 
2372
+ // Update dynamic component meta in blocklet settings
2373
+ await this._ensureDynamicChildrenInSettings(blocklet);
2374
+
2327
2375
  states.notification.create({
2328
2376
  title: 'Blocklet Installed',
2329
2377
  description: `Blocklet ${meta.name}@${meta.version} is installed successfully. (Source: ${
@@ -2473,10 +2521,7 @@ class BlockletManager extends BaseBlockletManager {
2473
2521
  }
2474
2522
 
2475
2523
  // Update dynamic component meta in blocklet settings
2476
- const dynamicChildren = blocklet.children
2477
- .filter((x) => x.dynamic)
2478
- .map((x) => pick(x, ['meta', 'mountPoint', 'sourceUrl', 'source']));
2479
- await states.blockletExtras.setSettings(did, { children: dynamicChildren });
2524
+ await this._ensureDynamicChildrenInSettings(blocklet);
2480
2525
 
2481
2526
  return blocklet;
2482
2527
  } catch (err) {
@@ -2494,6 +2539,23 @@ class BlockletManager extends BaseBlockletManager {
2494
2539
  }
2495
2540
  }
2496
2541
 
2542
+ // Update dynamic component meta in blocklet settings
2543
+ async _ensureDynamicChildrenInSettings(blocklet) {
2544
+ const { did } = blocklet.meta;
2545
+ const dynamicChildren = blocklet.children
2546
+ .filter((x) => x.dynamic)
2547
+ .map((x) => pick(x, ['meta', 'mountPoint', 'sourceUrl', 'source']));
2548
+
2549
+ // deleted blocklet
2550
+ let deletes = await states.blockletExtras.getSettings(did, 'children', []);
2551
+ deletes = deletes.filter(
2552
+ (x) => x.status === BlockletStatus.deleted && !blocklet.children.some((y) => y.meta.did === x.meta.did)
2553
+ );
2554
+ dynamicChildren.push(...deletes);
2555
+
2556
+ await states.blockletExtras.setSettings(did, { children: dynamicChildren });
2557
+ }
2558
+
2497
2559
  /**
2498
2560
  * for download: cwd, tarball, did
2499
2561
  * for verify: verify, integrity
@@ -2617,7 +2679,7 @@ class BlockletManager extends BaseBlockletManager {
2617
2679
  * @return {object} { isCancelled: Boolean }
2618
2680
  */
2619
2681
  async _downloadBundle(meta, rootDid, url) {
2620
- const { name, did, version, dist = {} } = meta;
2682
+ const { bundleName: name, bundleDid: did, version, dist = {} } = meta;
2621
2683
  const { tarball, integrity } = dist;
2622
2684
 
2623
2685
  const lockName = `download-${did}-${version}`;
@@ -11,7 +11,7 @@ const request = require('../util/request');
11
11
 
12
12
  const states = require('../states');
13
13
  const isRequirementsSatisfied = require('../util/requirement');
14
- const { fixAndVerifyBlockletMeta } = require('../util/blocklet');
14
+ const { fixAndVerifyMetaFromStore } = require('../util/blocklet');
15
15
  const { translate } = require('../locales');
16
16
  const { validateRegistryURL, getRegistryMeta } = require('../util/registry');
17
17
 
@@ -68,7 +68,11 @@ class BlockletRegistry {
68
68
 
69
69
  const { data } = await request.get(url);
70
70
  try {
71
- return fixAndVerifyBlockletMeta(data, did);
71
+ if (data.did !== did) {
72
+ throw new Error('Invalid blocklet meta: did does not match');
73
+ }
74
+
75
+ return fixAndVerifyMetaFromStore(data);
72
76
  } catch (err) {
73
77
  logger.error('failed to get blocklet meta', { did, data, error: err });
74
78
  throw err;
package/lib/cert.js CHANGED
@@ -37,6 +37,16 @@ const onCertIssued = (cert) => {
37
37
  });
38
38
  };
39
39
 
40
+ const onCertIssueFailed = (cert) => {
41
+ states.notification.create({
42
+ title: 'Certificate Issue Failed',
43
+ description: `Failed to issue certificate for ${cert.domain}`,
44
+ severity: 'error',
45
+ entityType: 'certificate',
46
+ entityId: cert.id,
47
+ });
48
+ };
49
+
40
50
  const getDomainFromInput = (input) => {
41
51
  if (Object.prototype.toString.call(input) === '[object Object]') {
42
52
  return input.domain;
@@ -58,6 +68,10 @@ class Cert extends EventEmitter {
58
68
 
59
69
  this.manager.on('cert.expired', onCertExpired);
60
70
  this.manager.on('cert.about_to_expire', onCertAboutExpire);
71
+ this.manager.on('cert.error', (cert) => {
72
+ this.emit('cert.error', cert);
73
+ onCertIssueFailed(cert);
74
+ });
61
75
  }
62
76
 
63
77
  start() {
package/lib/event.js CHANGED
@@ -25,6 +25,7 @@ module.exports = ({
25
25
  handleRouting,
26
26
  domainStatus,
27
27
  teamAPI,
28
+ certManager,
28
29
  }) => {
29
30
  const notificationState = states.notification;
30
31
  const nodeState = states.node;
@@ -209,6 +210,11 @@ module.exports = ({
209
210
  }
210
211
  });
211
212
  nodeState.on(EVENTS.NODE_UPGRADE_PROGRESS, (session) => onEvent(EVENTS.NODE_UPGRADE_PROGRESS, session));
213
+ nodeState.on(EVENTS.RELOAD_GATEWAY, (nodeInfo) => {
214
+ handleRouting(nodeInfo).catch((err) => {
215
+ logger.error('Handle routing failed on node.updated', { error: err });
216
+ });
217
+ });
212
218
 
213
219
  domainStatus.on(EVENTS.DOMAIN_STATUS, (data) => {
214
220
  if (data) {
@@ -230,5 +236,8 @@ module.exports = ({
230
236
  events.handleServerEvent = handleServerEvent;
231
237
  events.handleBlockletEvent = handleBlockletEvent;
232
238
 
239
+ certManager.on('cert.issued', (data) => onEvent(EVENTS.CERT_ISSUED, data));
240
+ certManager.on('cert.error', (data) => onEvent(EVENTS.CERT_ERROR, data));
241
+
233
242
  return events;
234
243
  };