@abtnode/core 1.16.0-beta-58020de5 → 1.16.0-beta-b741bcb3

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/team.js CHANGED
@@ -136,7 +136,7 @@ class TeamAPI extends EventEmitter {
136
136
  return doc;
137
137
  }
138
138
 
139
- async getUsers({ teamDid, query, paging: inputPaging, sort, dids }) {
139
+ async getUsers({ teamDid, query, paging: inputPaging, sort, dids, sourceIds }) {
140
140
  const state = await this.getUserState(teamDid);
141
141
 
142
142
  if (inputPaging?.pageSize > MAX_USER_PAGE_SIZE) {
@@ -158,6 +158,14 @@ class TeamAPI extends EventEmitter {
158
158
  pageCount: 1,
159
159
  page: 1,
160
160
  };
161
+ } else if (sourceIds) {
162
+ list = await state.getUsersBySourceIds({ query, sourceIds });
163
+ paging = {
164
+ total: list.length,
165
+ pageSize: sourceIds.length,
166
+ pageCount: 1,
167
+ page: 1,
168
+ };
161
169
  } else {
162
170
  const doc = await state.getUsers({ query, sort, paging: { pageSize: 20, ...inputPaging } });
163
171
  list = doc.list;
@@ -185,8 +193,7 @@ class TeamAPI extends EventEmitter {
185
193
  'locale',
186
194
  // oauth relate fields
187
195
  'source',
188
- 'derivedAccount',
189
- 'connectedAccounts',
196
+ 'extraConfigs',
190
197
  ])
191
198
  // eslint-disable-next-line function-paren-newline
192
199
  ),
@@ -647,7 +654,6 @@ class TeamAPI extends EventEmitter {
647
654
  }),
648
655
  ownerProfile: {
649
656
  ...currentUser,
650
- // avatar: await parseUserAvatar(currentUser.avatar, { dataDir: blocklet.env.dataDir }),
651
657
  },
652
658
  preferredColor: passportColor,
653
659
  });
@@ -11,12 +11,8 @@ const cloneDeep = require('lodash/cloneDeep');
11
11
  const { isNFTExpired, getNftExpirationDate } = require('@abtnode/util/lib/nft');
12
12
  const didDocument = require('@abtnode/util/lib/did-document');
13
13
  const { sign } = require('@arcblock/jwt');
14
- const { isEthereumDid } = require('@arcblock/did');
15
- const { toSvg: createDidLogo } =
16
- process.env.NODE_ENV !== 'test' ? require('@arcblock/did-motif') : require('@arcblock/did-motif/dist/did-motif.cjs');
17
- const getBlockletInfo = require('@blocklet/meta/lib/info');
18
- const { createBlockiesSvg } = require('@blocklet/meta/lib/blockies');
19
14
  const sleep = require('@abtnode/util/lib/sleep');
15
+ const getBlockletInfo = require('@blocklet/meta/lib/info');
20
16
 
21
17
  const logger = require('@abtnode/logger')('@abtnode/core:blocklet:manager');
22
18
  const {
@@ -100,6 +96,7 @@ const {
100
96
  isRotatingAppDid,
101
97
  checkVersionCompatibility,
102
98
  getBlockletKnownAs,
99
+ updateBlockletFallbackLogo,
103
100
  } = require('../../util/blocklet');
104
101
  const states = require('../../states');
105
102
  const BaseBlockletManager = require('./base');
@@ -551,21 +548,29 @@ class BlockletManager extends BaseBlockletManager {
551
548
  this.emit(BlockletEvents.statusChange, blocklet);
552
549
  }
553
550
 
554
- const nodeEnvironments = await states.node.getEnvironments();
555
-
556
- await stopBlockletProcess(blocklet, {
557
- preStop: (b, { ancestors }) =>
558
- hooks.preStop(b.env.processId, {
559
- appDir: b.env.appDir,
560
- hooks: Object.assign(b.meta.hooks || {}, b.meta.scripts || {}),
561
- env: getRuntimeEnvironments(b, nodeEnvironments, ancestors),
562
- did, // root blocklet did
563
- notification: states.notification,
564
- context,
565
- exitOnError: false,
566
- silent,
567
- }),
568
- });
551
+ try {
552
+ const nodeEnvironments = await states.node.getEnvironments();
553
+ await stopBlockletProcess(blocklet, {
554
+ preStop: (b, { ancestors }) =>
555
+ hooks.preStop(b.env.processId, {
556
+ appDir: b.env.appDir,
557
+ hooks: Object.assign(b.meta.hooks || {}, b.meta.scripts || {}),
558
+ env: getRuntimeEnvironments(b, nodeEnvironments, ancestors),
559
+ did, // root blocklet did
560
+ notification: states.notification,
561
+ context,
562
+ exitOnError: false,
563
+ silent,
564
+ }),
565
+ });
566
+ } catch (error) {
567
+ logger.error('Failed to stop blocklet', { error, did });
568
+ if (updateStatus) {
569
+ const res = await states.blocklet.setBlockletStatus(did, BlockletStatus.error);
570
+ this.emit(BlockletEvents.statusChange, res);
571
+ }
572
+ throw error;
573
+ }
569
574
 
570
575
  logger.info('blocklet stopped successfully', { processId, did });
571
576
 
@@ -1010,16 +1015,17 @@ class BlockletManager extends BaseBlockletManager {
1010
1015
  const [rootDid, ...childDids] = dids;
1011
1016
  logger.info('config blocklet', { dids });
1012
1017
 
1018
+ const ancestors = [];
1013
1019
  let blocklet = await this.getBlocklet(rootDid);
1014
1020
  for (const childDid of childDids) {
1021
+ ancestors.push(blocklet);
1015
1022
  blocklet = blocklet.children.find((x) => x.meta.did === childDid);
1016
1023
  if (!blocklet) {
1017
1024
  throw new Error('Child blocklet does not exist', { dids });
1018
1025
  }
1019
1026
  }
1020
1027
 
1021
- // run hook
1022
- const nodeEnvironments = await states.node.getEnvironments();
1028
+ const configObj = {};
1023
1029
  for (const x of newConfigs) {
1024
1030
  if (x.custom === true) {
1025
1031
  // custom key
@@ -1039,21 +1045,25 @@ class BlockletManager extends BaseBlockletManager {
1039
1045
  }
1040
1046
  }
1041
1047
 
1042
- blocklet.configObj[x.key] = x.value;
1048
+ configObj[x.key] = x.value;
1043
1049
  }
1044
1050
 
1051
+ // run hook
1045
1052
  if (!skipHook) {
1053
+ const nodeEnvironments = await states.node.getEnvironments();
1046
1054
  // FIXME: we should also call preConfig for child blocklets
1047
1055
  await hooks.preConfig(blocklet.env.processId, {
1048
1056
  appDir: blocklet.env.appDir,
1049
1057
  hooks: Object.assign(blocklet.meta.hooks || {}, blocklet.meta.scripts || {}),
1050
1058
  exitOnError: true,
1051
- env: { ...getRuntimeEnvironments(blocklet, nodeEnvironments), ...blocklet.configObj },
1059
+ env: { ...getRuntimeEnvironments(blocklet, nodeEnvironments, ancestors), ...configObj },
1052
1060
  did,
1053
1061
  context,
1054
1062
  });
1055
1063
  }
1056
1064
 
1065
+ Object.assign(blocklet.configObj, configObj);
1066
+
1057
1067
  const willAppSkChange = isRotatingAppSk(newConfigs, blocklet.configs, blocklet.externalSk);
1058
1068
  const willAppDidChange = isRotatingAppDid(newConfigs, blocklet.configs, blocklet.externalSk);
1059
1069
 
@@ -1407,6 +1417,7 @@ class BlockletManager extends BaseBlockletManager {
1407
1417
  {
1408
1418
  name: 'clean-expired-blocklet-data',
1409
1419
  time: '0 */20 0 * * *', // 每天凌晨 0 点的每 20 分钟
1420
+ options: { runOnInit: false },
1410
1421
  fn: () => this._cleanExpiredBlockletData(),
1411
1422
  },
1412
1423
  {
@@ -1723,6 +1734,7 @@ class BlockletManager extends BaseBlockletManager {
1723
1734
  }
1724
1735
 
1725
1736
  // update state to db
1737
+ await states.blockletExtras.updateByDid(did, { appDid: blocklet.appDid });
1726
1738
  return states.blocklet.updateBlocklet(did, blocklet);
1727
1739
  }
1728
1740
 
@@ -1854,24 +1866,46 @@ class BlockletManager extends BaseBlockletManager {
1854
1866
 
1855
1867
  const children = component ? await this._getChildrenForInstallation(component) : [];
1856
1868
 
1857
- if (children[0]?.meta?.logo) {
1869
+ // FIXME @linchen
1870
+ // 当应用本身是容器时, 下载这个容器, 因为容器可能除 blocklet.yml 额外的文件
1871
+ // 本身就是容器的应用, 在容器中添加额外文件可能不是合理的做法
1872
+ // 容器只在安装时有效, 安装后容器无法升级
1873
+ const containerSourceUrl =
1874
+ component && component.meta.group === BlockletGroup.gateway && component.meta.dist && component.bundleSource?.url;
1875
+
1876
+ if (containerSourceUrl) {
1877
+ meta.bundleDid = component.meta.did;
1878
+ meta.bundleName = component.meta.name;
1879
+ meta.version = component.meta.version;
1880
+ meta.dist = component.meta.dist;
1881
+ meta.logo = component.meta.logo;
1882
+ } else if (children[0]?.meta?.logo) {
1858
1883
  meta.logo = children[0].meta.logo;
1859
1884
  }
1860
1885
 
1861
1886
  await validateBlocklet({ meta, children });
1862
1887
 
1863
1888
  // fake install bundle
1864
- const bundleDir = getBundleDir(this.installDir, meta);
1865
- fs.mkdirSync(bundleDir, { recursive: true });
1866
- updateMetaFile(path.join(bundleDir, BLOCKLET_META_FILE), meta);
1889
+ if (!containerSourceUrl) {
1890
+ const bundleDir = getBundleDir(this.installDir, meta);
1891
+ fs.mkdirSync(bundleDir, { recursive: true });
1892
+ updateMetaFile(path.join(bundleDir, BLOCKLET_META_FILE), meta);
1893
+ }
1867
1894
 
1868
1895
  // add blocklet to db
1869
- const blocklet = await states.blocklet.addBlocklet({
1896
+ const params = {
1870
1897
  meta,
1871
1898
  source: BlockletSource.custom,
1872
1899
  children,
1873
1900
  mode,
1874
- });
1901
+ };
1902
+
1903
+ if (containerSourceUrl) {
1904
+ params.source = BlockletSource.url;
1905
+ params.deployedFrom = containerSourceUrl;
1906
+ }
1907
+
1908
+ const blocklet = await states.blocklet.addBlocklet(params);
1875
1909
 
1876
1910
  return blocklet;
1877
1911
  }
@@ -1909,18 +1943,14 @@ class BlockletManager extends BaseBlockletManager {
1909
1943
  logger.info('blocklet installed', { source, did: meta.did });
1910
1944
 
1911
1945
  // logo
1912
- if (blocklet.children[0]?.meta?.logo) {
1946
+ if (blocklet.source === BlockletSource.custom && blocklet.children[0]?.meta?.logo) {
1913
1947
  const fileName = blocklet.children[0].meta.logo;
1914
1948
  const src = path.join(getBundleDir(this.installDir, blocklet.children[0].meta), fileName);
1915
1949
  const dist = path.join(getBundleDir(this.installDir, blocklet.meta), fileName);
1916
1950
  await fs.copy(src, dist);
1917
1951
  }
1918
1952
 
1919
- if (isEthereumDid(blocklet.meta.did)) {
1920
- await fs.writeFile(path.join(blocklet.env.dataDir, 'logo.svg'), createBlockiesSvg(blocklet.meta.did));
1921
- } else {
1922
- await fs.writeFile(path.join(blocklet.env.dataDir, 'logo.svg'), createDidLogo(blocklet.meta.did));
1923
- }
1953
+ await updateBlockletFallbackLogo(blocklet);
1924
1954
 
1925
1955
  // Init db
1926
1956
  await this.teamManager.initTeam(blocklet.meta.did);
@@ -1945,12 +1975,13 @@ class BlockletManager extends BaseBlockletManager {
1945
1975
  if (blocklet.controller && process.env.NODE_ENV !== 'test') {
1946
1976
  const nodeInfo = await states.node.read();
1947
1977
  await consumeServerlessNFT({ nftId: blocklet.controller.nftId, nodeInfo, blocklet });
1978
+ this.emit(BlockletEvents.nftConsumed, { blocklet, context });
1948
1979
  }
1949
1980
 
1950
1981
  if (createNotification) {
1951
1982
  this._createNotification(did, {
1952
1983
  title: 'Blocklet Installed',
1953
- description: `Blocklet ${meta.name}@${meta.version} is installed successfully. (Source: ${
1984
+ description: `Blocklet ${meta.title} is installed successfully. (Source: ${
1954
1985
  deployedFrom || fromBlockletSource(source)
1955
1986
  })`,
1956
1987
  action: `/blocklets/${did}/overview`,
@@ -2065,7 +2096,7 @@ class BlockletManager extends BaseBlockletManager {
2065
2096
 
2066
2097
  blocklet = await this.getBlocklet(did, context);
2067
2098
 
2068
- await fs.writeFile(path.join(blocklet.env.dataDir, 'logo.svg'), createDidLogo(blocklet.meta.did));
2099
+ await updateBlockletFallbackLogo(blocklet);
2069
2100
 
2070
2101
  await this._updateDependents(did);
2071
2102
 
@@ -2394,7 +2425,7 @@ class BlockletManager extends BaseBlockletManager {
2394
2425
  controller: {
2395
2426
  $exists: true,
2396
2427
  },
2397
- 'controller.expiredAt': {
2428
+ expiredAt: {
2398
2429
  $exists: false,
2399
2430
  },
2400
2431
  },
@@ -2412,11 +2443,21 @@ class BlockletManager extends BaseBlockletManager {
2412
2443
  nftId: data.controller.nftId,
2413
2444
  });
2414
2445
 
2415
- await this.delete({ did: data.meta.did, keepData: true, keepConfigs: true, keepLogsDir: true });
2416
- logger.info('the expired blocklet already deleted', {
2417
- blockletDid: data.meta.did,
2418
- nftId: data.controller.nftId,
2419
- });
2446
+ const blocklet = await states.blocklet.getBlocklet(data.meta.did);
2447
+ if (blocklet) {
2448
+ // 预防 Blocklet 已经删除,但是 blocklet extra data 没有清理的场景
2449
+ await this._backupToDisk({ blocklet });
2450
+ logger.info('backed up the expired blocklet', {
2451
+ blockletDid: data.meta.did,
2452
+ nftId: data.controller.nftId,
2453
+ });
2454
+
2455
+ await this.delete({ did: data.meta.did, keepData: true, keepConfigs: true, keepLogsDir: true });
2456
+ logger.info('the expired blocklet already deleted', {
2457
+ blockletDid: data.meta.did,
2458
+ nftId: data.controller.nftId,
2459
+ });
2460
+ }
2420
2461
 
2421
2462
  const expiredAt = getNftExpirationDate(assetState);
2422
2463
  await states.blockletExtras.updateExpireInfo({ did: data.meta.did, expiredAt });
@@ -2441,7 +2482,7 @@ class BlockletManager extends BaseBlockletManager {
2441
2482
 
2442
2483
  logger.info('check expired external blocklet end');
2443
2484
  } catch (error) {
2444
- logger.info('check expired external blocklet failed', { error });
2485
+ logger.error('check expired external blocklet failed', { error });
2445
2486
  }
2446
2487
  }
2447
2488
 
@@ -2454,16 +2495,19 @@ class BlockletManager extends BaseBlockletManager {
2454
2495
  return;
2455
2496
  }
2456
2497
 
2457
- const tasks = blockletExtras.map(async ({ did }) => {
2458
- const blocklet = await states.blocklet.getBlocklet(did);
2459
- await this._cleanBlockletData({ blocklet, keepData: false, keepLogsDir: false, keepConfigs: false });
2498
+ const tasks = blockletExtras.map(async ({ appDid, meta }) => {
2499
+ await this._cleanBlockletData({ blocklet: { meta }, keepData: false, keepLogsDir: false, keepConfigs: false });
2500
+ logger.info(`clean blocklet ${meta.did} extra data`);
2501
+
2502
+ await removeBackup(this.dataDirs.data, appDid);
2503
+ logger.info(`removed blocklet ${meta.did} backup`);
2460
2504
 
2461
2505
  this.emit(BlockletEvents.dataCleaned, {
2462
- blocklet,
2506
+ blocklet: { meta },
2463
2507
  keepRouting: false,
2464
2508
  });
2465
2509
 
2466
- logger.info(`cleaned expired blocklet blocklet ${did} data`);
2510
+ logger.info(`cleaned expired blocklet blocklet ${meta.did} data`);
2467
2511
  });
2468
2512
 
2469
2513
  await Promise.all(tasks);
@@ -2578,16 +2622,32 @@ class BlockletManager extends BaseBlockletManager {
2578
2622
  const spacesRestore = new SpacesRestore({ ...input, event: this, userDid, referrer: context.referrer });
2579
2623
  const params = await spacesRestore.restore();
2580
2624
 
2625
+ const removeRestoreDir = () => {
2626
+ if (fs.existsSync(spacesRestore.restoreDir)) {
2627
+ fs.remove(spacesRestore.restoreDir).catch((err) => {
2628
+ logger.error('failed to remove restore dir', { error: err, dir: spacesRestore.restoreDir });
2629
+ });
2630
+ }
2631
+ };
2632
+
2581
2633
  this.emit(BlockletEvents.restoreProgress, { appDid: input.appDid, status: RESTORE_PROGRESS_STATUS.installing });
2582
- await installApplicationFromBackup({
2583
- url: `file://${spacesRestore.restoreDir}`,
2584
- moveDir: true,
2585
- ...merge(...params),
2586
- manager: this,
2587
- states,
2588
- controller: input.controller,
2589
- context: { ...context, startImmediately: true },
2590
- });
2634
+
2635
+ try {
2636
+ await installApplicationFromBackup({
2637
+ url: `file://${spacesRestore.restoreDir}`,
2638
+ moveDir: true,
2639
+ ...merge(...params),
2640
+ manager: this,
2641
+ states,
2642
+ controller: input.controller,
2643
+ context: { ...context, startImmediately: true },
2644
+ });
2645
+
2646
+ removeRestoreDir();
2647
+ } catch (error) {
2648
+ removeRestoreDir();
2649
+ throw error;
2650
+ }
2591
2651
 
2592
2652
  this.emit(BlockletEvents.restoreProgress, { appDid: input.appDid, status: RESTORE_PROGRESS_STATUS.completed });
2593
2653
  }
@@ -2600,14 +2660,28 @@ class BlockletManager extends BaseBlockletManager {
2600
2660
  const diskRestore = new DiskRestore({ ...input, event: this });
2601
2661
  const params = await diskRestore.restore();
2602
2662
 
2603
- await installApplicationFromBackup({
2604
- url: `file://${diskRestore.restoreDir}`,
2605
- ...merge(...params),
2606
- manager: this,
2607
- states,
2608
- move: true,
2609
- sync: false, // use queue to download and install application
2610
- });
2663
+ const removeRestoreDir = () => {
2664
+ if (fs.existsSync(diskRestore.restoreDir)) {
2665
+ fs.remove(diskRestore.restoreDir).catch((err) => {
2666
+ logger.error('failed to remove restore dir', { error: err, dir: diskRestore.restoreDir });
2667
+ });
2668
+ }
2669
+ };
2670
+
2671
+ try {
2672
+ await installApplicationFromBackup({
2673
+ url: `file://${diskRestore.restoreDir}`,
2674
+ ...merge(...params),
2675
+ manager: this,
2676
+ states,
2677
+ move: true,
2678
+ sync: false, // use queue to download and install application
2679
+ });
2680
+ removeRestoreDir();
2681
+ } catch (error) {
2682
+ removeRestoreDir();
2683
+ throw error;
2684
+ }
2611
2685
  }
2612
2686
  }
2613
2687
 
@@ -1,14 +1,7 @@
1
- const path = require('path');
2
- const fs = require('fs-extra');
3
- const { isEthereumDid } = require('@arcblock/did');
4
- const { createBlockiesSvg } = require('@blocklet/meta/lib/blockies');
5
-
6
- const { toSvg: createDidLogo } =
7
- process.env.NODE_ENV !== 'test' ? require('@arcblock/did-motif') : require('@arcblock/did-motif/dist/did-motif.cjs');
8
1
  const { BlockletStatus, BLOCKLET_MODES, fromBlockletStatus, BlockletSource } = require('@blocklet/constant');
9
2
 
10
3
  const logger = require('@abtnode/logger')('@abtnode/core:install-app-dev');
11
- const { ensureMeta } = require('../../../util/blocklet');
4
+ const { ensureMeta, updateBlockletFallbackLogo } = require('../../../util/blocklet');
12
5
 
13
6
  /**
14
7
  *
@@ -88,11 +81,7 @@ const installApplicationFromDev = async ({ folder, meta, states, manager } = {})
88
81
 
89
82
  blocklet = await manager.getBlocklet(did);
90
83
 
91
- if (isEthereumDid(blocklet.meta.did)) {
92
- await fs.writeFile(path.join(blocklet.env.dataDir, 'logo.svg'), createBlockiesSvg(blocklet.meta.did));
93
- } else {
94
- await fs.writeFile(path.join(blocklet.env.dataDir, 'logo.svg'), createDidLogo(blocklet.meta.did));
95
- }
84
+ await updateBlockletFallbackLogo(blocklet);
96
85
 
97
86
  return blocklet;
98
87
  };
package/lib/event.js CHANGED
@@ -327,6 +327,7 @@ module.exports = ({
327
327
  BlockletEvents.restoreProgress,
328
328
 
329
329
  BlockletEvents.spaceConnected,
330
+ BlockletEvents.nftConsumed,
330
331
  ].forEach((eventName) => {
331
332
  listen(blockletManager, eventName, handleBlockletEvent);
332
333
  });
@@ -291,6 +291,10 @@ class BlockletExtrasState extends BaseState {
291
291
 
292
292
  return data;
293
293
  }
294
+
295
+ updateByDid(did, data) {
296
+ return super.update({ did }, { $set: data });
297
+ }
294
298
  }
295
299
 
296
300
  module.exports = BlockletExtrasState;
@@ -193,7 +193,7 @@ class User extends BaseState {
193
193
 
194
194
  // 根据 derivedDid 查询 user 信息(wallet 账户绑定 oauth 账户后,会有该字段)
195
195
  if (derivedDid) {
196
- queryParam['derivedAccount.did'] = derivedDid;
196
+ queryParam['extraConfigs.derivedAccount.did'] = derivedDid;
197
197
  }
198
198
 
199
199
  const sortParam = pickBy(sort, (x) => !isNullOrUndefined(x));
@@ -232,6 +232,27 @@ class User extends BaseState {
232
232
  return this.find(queryParam);
233
233
  }
234
234
 
235
+ /**
236
+ * get user list by sourceId list
237
+ * @param {string[]} sourceIds user sourceId list
238
+ * @returns {BlockletUser[]}
239
+ */
240
+ async getUsersBySourceIds({ sourceIds, query } = {}) {
241
+ const { approved } = query || {};
242
+ const sourceIdList = sourceIds || [];
243
+
244
+ const queryParam = {
245
+ 'extraConfigs.sourceId': { $in: sourceIdList },
246
+ };
247
+
248
+ if (!isNullOrUndefined(approved)) {
249
+ queryParam.approved = !!approved;
250
+ }
251
+
252
+ // get data
253
+ return this.find(queryParam);
254
+ }
255
+
235
256
  /**
236
257
  * get user by did
237
258
  * @param {string} did user's did
@@ -5,6 +5,7 @@ const path = require('path');
5
5
  const joinURL = require('url-join');
6
6
  const shelljs = require('shelljs');
7
7
  const os = require('os');
8
+ const pRetry = require('p-retry');
8
9
  const tar = require('tar');
9
10
  const get = require('lodash/get');
10
11
  const isEmpty = require('lodash/isEmpty');
@@ -21,7 +22,7 @@ const { stableStringify } = require('@arcblock/vc');
21
22
  const { fromSecretKey, WalletType } = require('@ocap/wallet');
22
23
  const { toHex, toBase58, isHex, toDid } = require('@ocap/util');
23
24
  const { types } = require('@ocap/mcrypto');
24
- const { isValid: isValidDid } = require('@arcblock/did');
25
+ const { isValid: isValidDid, isEthereumDid } = require('@arcblock/did');
25
26
  const logger = require('@abtnode/logger')('@abtnode/core:util:blocklet');
26
27
  const pm2 = require('@abtnode/util/lib/async-pm2');
27
28
  const sleep = require('@abtnode/util/lib/sleep');
@@ -39,6 +40,9 @@ const {
39
40
  APP_STRUCT_VERSION,
40
41
  } = require('@abtnode/constant');
41
42
  const formatBackSlash = require('@abtnode/util/lib/format-back-slash');
43
+ const { toSvg: createDidLogo } =
44
+ process.env.NODE_ENV !== 'test' ? require('@arcblock/did-motif') : require('@arcblock/did-motif/dist/did-motif.cjs');
45
+ const { createBlockiesSvg } = require('@blocklet/meta/lib/blockies');
42
46
 
43
47
  const SCRIPT_ENGINES_WHITE_LIST = ['npm', 'npx', 'pnpm', 'yarn'];
44
48
 
@@ -456,7 +460,10 @@ const getRuntimeEnvironments = (blocklet, nodeEnvironments, ancestors) => {
456
460
  };
457
461
 
458
462
  const isUsefulError = (err) =>
459
- err && err.message !== 'process or namespace not found' && !/^Process \d+ not found$/.test(err.message);
463
+ err &&
464
+ err.message !== 'process or namespace not found' &&
465
+ !/id unknown/.test(err.message) &&
466
+ !/^Process \d+ not found$/.test(err.message);
460
467
 
461
468
  const getHealthyCheckTimeout = (blocklet, { checkHealthImmediately } = {}) => {
462
469
  let minConsecutiveTime = 5000;
@@ -607,6 +614,10 @@ const stopBlockletProcess = async (blocklet, { preStop = noop, skippedProcessIds
607
614
  await forEachBlocklet(
608
615
  blocklet,
609
616
  async (b, { ancestors }) => {
617
+ if (b.meta?.group === BlockletGroup.gateway) {
618
+ return;
619
+ }
620
+
610
621
  if (skippedProcessIds.includes(b.env.processId)) {
611
622
  logger.info(`skip stop process ${b.env.processId}`);
612
623
  return;
@@ -802,9 +813,7 @@ const parseComponents = async (component, context = {}) => {
802
813
  try {
803
814
  rawMeta = await getBlockletMetaFromUrls(urls, { logger });
804
815
  } catch (error) {
805
- throw new Error(
806
- `Failed get component meta. Component: ${rawMeta.title || rawMeta.did}, reason: ${error.message}`
807
- );
816
+ throw new Error(`Failed get component meta. Component: ${urls.join(', ')}, reason: ${error.message}`);
808
817
  }
809
818
 
810
819
  if (rawMeta.group === BlockletGroup.gateway) {
@@ -1510,13 +1519,28 @@ const consumeServerlessNFT = async ({ nftId, nodeInfo, blocklet }) => {
1510
1519
  const body = { nftId, appURL };
1511
1520
 
1512
1521
  const { launcherUrl } = state.data.value;
1513
- const { data } = await axios.post(joinURL(launcherUrl, '/api/serverless/consume'), body, {
1514
- headers: {
1515
- 'x-sig': toBase58(wallet.sign(stableStringify(body))),
1522
+
1523
+ const func = async () => {
1524
+ const { data } = await axios.post(joinURL(launcherUrl, '/api/serverless/consume'), body, {
1525
+ headers: {
1526
+ 'x-sig': toBase58(wallet.sign(stableStringify(body))),
1527
+ },
1528
+ });
1529
+
1530
+ return data;
1531
+ };
1532
+
1533
+ const delay = 10 * 1000;
1534
+ const result = await pRetry(func, {
1535
+ retries: 3,
1536
+ minTimeout: delay,
1537
+ maxTimeout: delay,
1538
+ onFailedAttempt: (error) => {
1539
+ logger.error(`attempt consume nft ${nftId} failed`, { error });
1516
1540
  },
1517
1541
  });
1518
1542
 
1519
- logger.error('consume serverless nft success', { nftId, hash: data.hash });
1543
+ logger.error('consume serverless nft success', { nftId, hash: result.hash });
1520
1544
  } catch (error) {
1521
1545
  logger.error('consume serverless nft failed', { nftId, error });
1522
1546
 
@@ -1863,7 +1887,16 @@ const getFixedBundleSource = (component) => {
1863
1887
  return null;
1864
1888
  };
1865
1889
 
1890
+ const updateBlockletFallbackLogo = async (blocklet) => {
1891
+ if (isEthereumDid(blocklet.meta.did)) {
1892
+ await fs.writeFile(path.join(blocklet.env.dataDir, 'logo.svg'), createBlockiesSvg(blocklet.meta.did));
1893
+ } else {
1894
+ await fs.writeFile(path.join(blocklet.env.dataDir, 'logo.svg'), createDidLogo(blocklet.meta.did));
1895
+ }
1896
+ };
1897
+
1866
1898
  module.exports = {
1899
+ updateBlockletFallbackLogo,
1867
1900
  consumeServerlessNFT,
1868
1901
  forEachBlocklet,
1869
1902
  getBlockletMetaFromUrl: (url) => getBlockletMetaFromUrl(url, { logger }),
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.16.0-beta-58020de5",
6
+ "version": "1.16.0-beta-b741bcb3",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,18 +19,18 @@
19
19
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "@abtnode/auth": "1.16.0-beta-58020de5",
23
- "@abtnode/certificate-manager": "1.16.0-beta-58020de5",
24
- "@abtnode/constant": "1.16.0-beta-58020de5",
25
- "@abtnode/cron": "1.16.0-beta-58020de5",
26
- "@abtnode/db": "1.16.0-beta-58020de5",
27
- "@abtnode/logger": "1.16.0-beta-58020de5",
28
- "@abtnode/queue": "1.16.0-beta-58020de5",
29
- "@abtnode/rbac": "1.16.0-beta-58020de5",
30
- "@abtnode/router-provider": "1.16.0-beta-58020de5",
31
- "@abtnode/static-server": "1.16.0-beta-58020de5",
32
- "@abtnode/timemachine": "1.16.0-beta-58020de5",
33
- "@abtnode/util": "1.16.0-beta-58020de5",
22
+ "@abtnode/auth": "1.16.0-beta-b741bcb3",
23
+ "@abtnode/certificate-manager": "1.16.0-beta-b741bcb3",
24
+ "@abtnode/constant": "1.16.0-beta-b741bcb3",
25
+ "@abtnode/cron": "1.16.0-beta-b741bcb3",
26
+ "@abtnode/db": "1.16.0-beta-b741bcb3",
27
+ "@abtnode/logger": "1.16.0-beta-b741bcb3",
28
+ "@abtnode/queue": "1.16.0-beta-b741bcb3",
29
+ "@abtnode/rbac": "1.16.0-beta-b741bcb3",
30
+ "@abtnode/router-provider": "1.16.0-beta-b741bcb3",
31
+ "@abtnode/static-server": "1.16.0-beta-b741bcb3",
32
+ "@abtnode/timemachine": "1.16.0-beta-b741bcb3",
33
+ "@abtnode/util": "1.16.0-beta-b741bcb3",
34
34
  "@arcblock/did": "1.18.64",
35
35
  "@arcblock/did-motif": "^1.1.10",
36
36
  "@arcblock/did-util": "1.18.64",
@@ -38,9 +38,9 @@
38
38
  "@arcblock/jwt": "^1.18.64",
39
39
  "@arcblock/pm2-events": "^0.0.5",
40
40
  "@arcblock/vc": "1.18.64",
41
- "@blocklet/constant": "1.16.0-beta-58020de5",
42
- "@blocklet/meta": "1.16.0-beta-58020de5",
43
- "@blocklet/sdk": "1.16.0-beta-58020de5",
41
+ "@blocklet/constant": "1.16.0-beta-b741bcb3",
42
+ "@blocklet/meta": "1.16.0-beta-b741bcb3",
43
+ "@blocklet/sdk": "1.16.0-beta-b741bcb3",
44
44
  "@did-space/client": "^0.2.45",
45
45
  "@fidm/x509": "^1.2.1",
46
46
  "@ocap/client": "1.18.64",
@@ -91,5 +91,5 @@
91
91
  "express": "^4.18.2",
92
92
  "jest": "^27.5.1"
93
93
  },
94
- "gitHead": "9d3f47f9827acf13e9efea38cd605d3b36f9f523"
94
+ "gitHead": "f41666daf2c499566ff2f8e76a2de4fa6e1122ba"
95
95
  }