@abtnode/core 1.6.20 → 1.6.21

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.
@@ -20,7 +20,7 @@ const logger = require('@abtnode/logger')('@abtnode/core:blocklet:manager');
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');
23
- const { BLOCKLET_PURCHASE_NFT_TYPE } = require('@abtnode/constant');
23
+ const { VC_TYPE_BLOCKLET_PURCHASE } = require('@abtnode/constant');
24
24
 
25
25
  const getBlockletEngine = require('@blocklet/meta/lib/engine');
26
26
  const {
@@ -90,6 +90,7 @@ const {
90
90
  getDiffFiles,
91
91
  getBundleDir,
92
92
  needBlockletDownload,
93
+ verifyPurchase,
93
94
  } = require('../../util/blocklet');
94
95
  const states = require('../../states');
95
96
  const BlockletRegistry = require('../registry');
@@ -197,6 +198,20 @@ class BlockletManager extends BaseBlockletManager {
197
198
  throw new Error('Unknown source');
198
199
  }
199
200
 
201
+ /**
202
+ * @param {String} rootDid
203
+ * @param {String} mountPoint
204
+ * @param {Boolean} context.blockletPurchaseVerified
205
+ *
206
+ * installFromUrl
207
+ * @param {String} url
208
+ *
209
+ * InstallFromUpload
210
+ * @param {Object} file
211
+ * @param {String} did for diff upload
212
+ * @param {String} diffVersion for diff upload
213
+ * @param {Array} deleteSet for diff upload
214
+ */
200
215
  async installComponent({ rootDid, mountPoint, url, file, did, diffVersion, deleteSet }, context = {}) {
201
216
  logger.debug('start install component', { rootDid, mountPoint, url });
202
217
 
@@ -244,8 +259,8 @@ class BlockletManager extends BaseBlockletManager {
244
259
  // FIXME: 这里的 trustedIssuers 相当于相信任何 VC,需要想更安全的方法
245
260
  verifyPresentation({ presentation: vcPresentation, trustedIssuers: [get(vc, 'issuer.id')], challenge });
246
261
 
247
- if (!vc.type.includes(BLOCKLET_PURCHASE_NFT_TYPE)) {
248
- throw new Error(`Expect ${BLOCKLET_PURCHASE_NFT_TYPE} VC type`);
262
+ if (!vc.type.includes(VC_TYPE_BLOCKLET_PURCHASE)) {
263
+ throw new Error(`Expect ${VC_TYPE_BLOCKLET_PURCHASE} VC type`);
249
264
  }
250
265
 
251
266
  const blockletUrl = get(vc, 'credentialSubject.purchased.blocklet.url');
@@ -1372,23 +1387,21 @@ class BlockletManager extends BaseBlockletManager {
1372
1387
 
1373
1388
  const registryUrl = registry || (await states.node.getBlockletRegistry());
1374
1389
  const info = await BlockletRegistry.getRegistryMeta(registryUrl);
1375
- const blocklet = await this.registry.getBlocklet(did, registryUrl);
1376
- if (!blocklet) {
1390
+ const meta = await this.registry.getBlocklet(did, registryUrl);
1391
+ if (!meta) {
1377
1392
  throw new Error('Can not install blocklet that not found in registry');
1378
1393
  }
1379
1394
 
1380
- const state = await states.blocklet.getBlocklet(blocklet.did);
1395
+ const state = await states.blocklet.getBlocklet(meta.did);
1381
1396
  if (state) {
1382
1397
  throw new Error('Can not install an already installed blocklet');
1383
1398
  }
1384
1399
 
1385
- if (isFreeBlocklet(blocklet) === false && !context.blockletPurchaseVerified) {
1386
- throw new Error('Can not install a non-free blocklet directly');
1387
- }
1400
+ verifyPurchase(meta, context);
1388
1401
 
1389
1402
  // install
1390
1403
  return this._install({
1391
- meta: blocklet,
1404
+ meta,
1392
1405
  source: BlockletSource.registry,
1393
1406
  deployedFrom: info.cdnUrl || registryUrl,
1394
1407
  context,
@@ -1442,6 +1455,8 @@ class BlockletManager extends BaseBlockletManager {
1442
1455
  throw new Error('The blocklet cannot be a component');
1443
1456
  }
1444
1457
 
1458
+ verifyPurchase(meta, context);
1459
+
1445
1460
  const newChildren = await parseChildren(blocklet.meta, {
1446
1461
  children: [
1447
1462
  {
package/lib/index.js CHANGED
@@ -147,7 +147,7 @@ function ABTNode(options) {
147
147
  getCertificates,
148
148
  getSitesFromSnapshot,
149
149
  getRoutingCrons,
150
- ensureDashboardCertificate,
150
+ ensureWildcardCerts,
151
151
  } = getRouterHelpers({ dataDirs, routingSnapshot, routerManager, blockletManager, certManager });
152
152
 
153
153
  const teamManager = new TeamManager({ nodeDid: options.nodeDid, dataDirs, states });
@@ -318,7 +318,7 @@ function ABTNode(options) {
318
318
  takeRoutingSnapshot,
319
319
  getSitesFromSnapshot,
320
320
  ensureDashboardRouting,
321
- ensureDashboardCertificate,
321
+ ensureWildcardCerts,
322
322
 
323
323
  addDomainAlias: routerManager.addDomainAlias.bind(routerManager),
324
324
  deleteDomainAlias: routerManager.deleteDomainAlias.bind(routerManager),
@@ -0,0 +1,27 @@
1
+ const yaml = require('js-yaml');
2
+ const fs = require('fs');
3
+ const set = require('lodash/set');
4
+ const omit = require('lodash/omit');
5
+ const { DEFAULT_WILDCARD_CERT_HOST, DEFAULT_DID_DOMAIN, DEFAULT_DID_REGISTRY } = require('@abtnode/constant');
6
+
7
+ module.exports = async ({ states, printInfo, configFile }) => {
8
+ printInfo('Try to rename dashboardDomain to ipWildcardDomain in db...');
9
+
10
+ let info = await states.node.read();
11
+ set(info, 'routing.ipWildcardDomain', info.routing.dashboardDomain);
12
+ set(info, 'routing.wildcardCertHost', DEFAULT_WILDCARD_CERT_HOST);
13
+ set(info, 'didDomain', DEFAULT_DID_DOMAIN);
14
+ set(info, 'didRegistry', DEFAULT_DID_REGISTRY);
15
+ info = omit(info, 'routing.dashboardDomain');
16
+
17
+ await states.node.updateNodeInfo(info);
18
+
19
+ let rawConfig = yaml.safeLoad(fs.readFileSync(configFile).toString());
20
+ set(rawConfig, 'node.routing.ipWildcardDomain', info.routing.ipWildcardDomain);
21
+ set(rawConfig, 'node.routing.wildcardCertHost', DEFAULT_WILDCARD_CERT_HOST);
22
+ set(rawConfig, 'node.didDomain', DEFAULT_DID_DOMAIN);
23
+ set(rawConfig, 'node.didRegistry', DEFAULT_DID_REGISTRY);
24
+ rawConfig = omit(rawConfig, 'node.routing.dashboardDomain');
25
+ fs.writeFileSync(configFile, yaml.dump(rawConfig));
26
+ printInfo(`> Persist new config to file: ${configFile}`);
27
+ };
@@ -419,6 +419,13 @@ const decompressCertificates = async (source, dest) => {
419
419
  return dest;
420
420
  };
421
421
 
422
+ const joinCertDownUrl = (baseUrl, name) => joinUrl(baseUrl, '/certs', name);
423
+
424
+ const getIpEchoCertDownloadUrl = (baseUrl) => joinCertDownUrl(baseUrl, 'ip-abtnet-io.tar.gz');
425
+ const getDidDomainCertDownloadUrl = (baseUrl) => joinCertDownUrl(baseUrl, 'did-abtnet-io.tar.gz');
426
+ const getDownloadCertBaseUrl = (info) =>
427
+ process.env.ABT_NODE_WILDCARD_CERT_HOST || get(info, 'routing.wildcardCertHost', '');
428
+
422
429
  module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerManager, blockletManager, certManager }) {
423
430
  const nodeState = states.node;
424
431
  const blockletState = states.blocklet;
@@ -428,46 +435,13 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
428
435
  // site level duplication detection
429
436
  const hasRuleByPrefix = (site, value) => site.rules.find((x) => x.isProtected && get(x, 'from.pathPrefix') === value);
430
437
 
431
- const updateDashboardCertificate = async ({ checkExpire = true }) => {
432
- const info = await nodeState.read();
433
- const provider = getProviderFromNodeInfo(info);
434
- if (provider === ROUTER_PROVIDER_NONE) {
435
- return;
436
- }
437
-
438
- const https = get(info, 'routing.https', true);
439
- const dashboardDomain = get(info, 'routing.dashboardDomain', '');
440
- const certDownloadAddress =
441
- process.env.ABT_NODE_DASHBOARD_CERT_DOWN_URL || get(info, 'routing.dashboardCertDownloadAddress', '');
442
- if (!https || !dashboardDomain || !certDownloadAddress) {
443
- return;
444
- }
445
-
446
- if (checkExpire) {
447
- try {
448
- const cert = await routerManager.findCertificateByDomain(dashboardDomain);
449
- if (!cert) {
450
- return;
451
- }
452
-
453
- const now = Date.now();
454
- const certInfo = getHttpsCertInfo(cert.certificate);
455
- if (certInfo.validTo - now >= CERTIFICATE_EXPIRES_OFFSET) {
456
- logger.info('skip dashboard certificate update before not expired');
457
- return;
458
- }
459
- } catch (err) {
460
- logger.error('failed to check dashboard certificate expiration', { error: err });
461
- return;
462
- }
463
- }
464
-
438
+ const downloadCert = async ({ domain, url }) => {
465
439
  const destFolder = getTmpDirectory(path.join(`certificate-${Date.now()}`));
466
440
  try {
467
441
  const filename = path.join(destFolder, 'certificate.tar.gz');
468
442
  fs.ensureDirSync(destFolder);
469
443
 
470
- await downloadFile(certDownloadAddress, filename);
444
+ await downloadFile(url, filename);
471
445
  await decompressCertificates(filename, destFolder);
472
446
 
473
447
  const certificateFilePath = path.join(destFolder, 'cert.pem');
@@ -485,7 +459,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
485
459
  const privateKey = fs.readFileSync(privateKeyFilePath).toString();
486
460
 
487
461
  await certManager.upsertByDomain({
488
- domain: dashboardDomain,
462
+ domain,
489
463
  privateKey,
490
464
  certificate,
491
465
  isProtected: true,
@@ -499,23 +473,68 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
499
473
  }
500
474
  };
501
475
 
502
- const ensureDashboardCertificate = async () => {
476
+ const updateCert = async (domain, url) => {
477
+ try {
478
+ const cert = await routerManager.findCertificateByDomain(domain);
479
+ if (!cert) {
480
+ return;
481
+ }
482
+
483
+ const now = Date.now();
484
+ const certInfo = getHttpsCertInfo(cert.certificate);
485
+ if (certInfo.validTo - now >= CERTIFICATE_EXPIRES_OFFSET) {
486
+ logger.info('skip dashboard certificate update before not expired', { domain, url });
487
+ return;
488
+ }
489
+
490
+ await downloadCert({
491
+ domain,
492
+ url,
493
+ });
494
+ } catch (err) {
495
+ logger.error('failed to check dashboard certificate expiration', { error: err, domain, url });
496
+ }
497
+ };
498
+
499
+ const updateDashboardCertificates = async () => {
503
500
  const info = await nodeState.read();
504
- const downloadUrl = get(info, 'routing.dashboardCertDownloadAddress', '');
505
- const dashboardDomain = get(info, 'routing.dashboardDomain', '');
506
- if (!dashboardDomain || !downloadUrl) {
507
- throw new Error('dashboardCertDownloadAddress and dashboardDomain are not found in the routing configs');
501
+ const provider = getProviderFromNodeInfo(info);
502
+ if (provider === ROUTER_PROVIDER_NONE) {
503
+ return;
508
504
  }
509
505
 
510
- const cert = await certManager.getByDomain(dashboardDomain);
511
- if (cert) {
512
- return { status: 'existed' };
506
+ const https = get(info, 'routing.https', true);
507
+ const ipWildcardDomain = get(info, 'routing.ipWildcardDomain', '');
508
+ const didDomain = info.didDomain;
509
+ const certDownloadAddress = getDownloadCertBaseUrl(info);
510
+ if (!https || !certDownloadAddress) {
511
+ return;
513
512
  }
514
513
 
515
- logger.debug('downloading dashboard ip-domain certificate', { url: downloadUrl, dashboardDomain });
516
- await updateDashboardCertificate({ checkExpire: false });
517
- logger.debug('downloaded dashboard ip-domain certificate', { url: downloadUrl, dashboardDomain });
518
- return { status: 'downloaded' };
514
+ await updateCert(ipWildcardDomain, getIpEchoCertDownloadUrl(certDownloadAddress));
515
+ await updateCert(`*.${didDomain}`, getDidDomainCertDownloadUrl(certDownloadAddress));
516
+ };
517
+
518
+ const ensureWildcardCerts = async () => {
519
+ const info = await nodeState.read();
520
+ const didDomain = info.didDomain;
521
+ const ipWildcardDomain = get(info, 'routing.ipWildcardDomain', '');
522
+
523
+ const ensureDomainCert = async (domain, url) => {
524
+ const cert = await certManager.getByDomain(domain);
525
+ if (!cert) {
526
+ await downloadCert({
527
+ domain,
528
+ url,
529
+ });
530
+ }
531
+ };
532
+
533
+ const certBaseUrl = getDownloadCertBaseUrl(info);
534
+ await Promise.all([
535
+ ensureDomainCert(ipWildcardDomain, getIpEchoCertDownloadUrl(certBaseUrl)),
536
+ ensureDomainCert(`*.${didDomain}`, getDidDomainCertDownloadUrl(certBaseUrl)),
537
+ ]);
519
538
  };
520
539
 
521
540
  const upsertSiteRule = async ({ site, rule }, context) => {
@@ -658,9 +677,9 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
658
677
  return domainAlias === item;
659
678
  });
660
679
 
661
- const dashboardDomain = get(info, 'routing.dashboardDomain', '');
680
+ const ipWildcardDomain = get(info, 'routing.ipWildcardDomain', '');
662
681
  const didDomain = `${info.did.toLowerCase()}.${info.didDomain}`;
663
- let dashboardAliasDomains = [dashboardDomain, didDomain];
682
+ let dashboardAliasDomains = [ipWildcardDomain, didDomain];
664
683
 
665
684
  dashboardAliasDomains = dashboardAliasDomains
666
685
  .filter((item) => item && !isExistsInAlias(item))
@@ -1388,7 +1407,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
1388
1407
  getSitesFromSnapshot,
1389
1408
  getCertificates,
1390
1409
  checkDomain,
1391
- ensureDashboardCertificate,
1410
+ ensureWildcardCerts,
1392
1411
  addWellknownSite,
1393
1412
  upsertSiteRule,
1394
1413
 
@@ -1396,7 +1415,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
1396
1415
  {
1397
1416
  name: 'update-dashboard-certificate',
1398
1417
  time: '0 1 */6 * * *', // refetch on 0:00, 6:00, etc.
1399
- fn: () => updateDashboardCertificate({ checkExpire: true }),
1418
+ fn: () => updateDashboardCertificates(),
1400
1419
  options: { runOnInit: true },
1401
1420
  },
1402
1421
  {
@@ -60,12 +60,12 @@ const getRoutingTable = ({ sites, nodeInfo }) => {
60
60
  let routingTable = Router.formatSites(sites);
61
61
  routingTable = expandSites(routingTable);
62
62
 
63
- // put dashboardDomain to last, to let blockletDomain match first
63
+ // put ipWildcardDomain to last, to let blockletDomain match first
64
64
  // e.g.
65
- // dashboardDomain: 192-168-3-2.ip.abtnet.io
65
+ // ipWildcardDomain: 192-168-3-2.ip.abtnet.io
66
66
  // blockletDomain: static-demo-xxx-192-168-3-2.ip.abtnet.io
67
- const dashboardDomain = get(nodeInfo, 'routing.dashboardDomain', '');
68
- const index = routingTable.findIndex((x) => x.domain === dashboardDomain);
67
+ const ipWildcardDomain = get(nodeInfo, 'routing.ipWildcardDomain', '');
68
+ const index = routingTable.findIndex((x) => x.domain === ipWildcardDomain);
69
69
  if (index > -1) {
70
70
  routingTable.push(...routingTable.splice(index, 1));
71
71
  }
@@ -219,11 +219,11 @@ Router.formatSites = (sites = []) => {
219
219
 
220
220
  Router.flattenSitesToRules = (sites = [], info = {}) => {
221
221
  const result = [];
222
- const dashboardDomain = get(info, 'routing.dashboardDomain', DEFAULT_DASHBOARD_DOMAIN);
222
+ const ipWildcardDomain = get(info, 'routing.ipWildcardDomain', DEFAULT_DASHBOARD_DOMAIN);
223
223
  sites.forEach((site) => {
224
224
  const aliases = (site.domainAliases || [])
225
225
  .map((x) => (typeof x === 'string' ? x : x.value))
226
- .filter((x) => x !== dashboardDomain)
226
+ .filter((x) => x !== ipWildcardDomain)
227
227
  .filter(Boolean);
228
228
 
229
229
  if (Array.isArray(site.rules) && site.rules.length > 0) {
@@ -92,7 +92,7 @@ class NodeState extends BaseState {
92
92
  mode,
93
93
  runtimeConfig,
94
94
  ownerNft,
95
- launcherInfo,
95
+ launcher,
96
96
  didRegistry,
97
97
  didDomain,
98
98
  enablePassportIssuance = true,
@@ -128,7 +128,7 @@ class NodeState extends BaseState {
128
128
  runtimeConfig,
129
129
  ownerNft,
130
130
  diskAlertThreshold: DISK_ALERT_THRESHOLD_PERCENT,
131
- launcherInfo: launcherInfo || undefined,
131
+ launcher: launcher || undefined,
132
132
  didRegistry,
133
133
  didDomain,
134
134
  enablePassportIssuance,
@@ -162,7 +162,8 @@ class NodeState extends BaseState {
162
162
  // FIXME: 这个接口比较危险,可能会修改一些本不应该修改的字段,后续需要考虑改进
163
163
  async updateNodeInfo(entity = {}) {
164
164
  const record = await this.read();
165
- const updateResult = await this.update(record._id, { $set: omit(entity, ['ownerNft']) });
165
+
166
+ const updateResult = await this.update(record._id, { $set: omit(entity, ['ownerNft', 'sk']) });
166
167
  this.emit('node.updated', updateResult, record);
167
168
  return updateResult;
168
169
  }
@@ -42,7 +42,7 @@ const validateBlockletEntry = require('@blocklet/meta/lib/entry');
42
42
  const getBlockletEngine = require('@blocklet/meta/lib/engine');
43
43
  const getBlockletInfo = require('@blocklet/meta/lib/info');
44
44
  const { validateMeta, fixAndValidateService } = require('@blocklet/meta/lib/validate');
45
- const { forEachBlocklet } = require('@blocklet/meta/lib/util');
45
+ const { forEachBlocklet, isFreeBlocklet } = require('@blocklet/meta/lib/util');
46
46
 
47
47
  const { validate: validateEngine, get: getEngine } = require('../blocklet/manager/engine');
48
48
 
@@ -951,7 +951,7 @@ const getRuntimeInfo = async (appId) => {
951
951
 
952
952
  /**
953
953
  * merge services
954
- * from meta.children[].mountPoints[].services
954
+ * from meta.children[].mountPoints[].services, meta.children[].services
955
955
  * to childrenMeta[].interfaces[].services
956
956
  *
957
957
  * @param {array<child>|object{children:array}} source e.g. [<config>] or { children: [<config>] }
@@ -993,6 +993,23 @@ const mergeMeta = (source, childrenMeta = []) => {
993
993
  childInterface.services = services;
994
994
  }
995
995
  });
996
+
997
+ if (config.services) {
998
+ const childInterface = findWebInterface(childMeta);
999
+ if (childInterface) {
1000
+ // merge
1001
+ const services = childInterface.services || [];
1002
+ config.services.forEach((x) => {
1003
+ const index = services.findIndex((y) => y.name === x.name);
1004
+ if (index >= 0) {
1005
+ services.splice(index, 1, x);
1006
+ } else {
1007
+ services.push(x);
1008
+ }
1009
+ });
1010
+ childInterface.services = services;
1011
+ }
1012
+ }
996
1013
  });
997
1014
  };
998
1015
 
@@ -1117,6 +1134,18 @@ const needBlockletDownload = (blocklet, oldBlocklet) => {
1117
1134
  return true;
1118
1135
  };
1119
1136
 
1137
+ const verifyPurchase = (meta, opts = {}) => {
1138
+ if (opts.blockletPurchaseVerified) {
1139
+ return true;
1140
+ }
1141
+
1142
+ if (isFreeBlocklet(meta)) {
1143
+ return true;
1144
+ }
1145
+
1146
+ throw new Error('Can not install a non-free blocklet directly');
1147
+ };
1148
+
1120
1149
  module.exports = {
1121
1150
  forEachBlocklet,
1122
1151
  getBlockletMetaFromUrl,
@@ -1152,4 +1181,5 @@ module.exports = {
1152
1181
  getDiffFiles,
1153
1182
  getBundleDir,
1154
1183
  needBlockletDownload,
1184
+ verifyPurchase,
1155
1185
  };
package/lib/util/index.js CHANGED
@@ -373,7 +373,7 @@ const getBaseUrls = async (node, ips) => {
373
373
  if (info.routing.provider !== ROUTER_PROVIDER_NONE && info.routing.snapshotHash && info.routing.adminPath) {
374
374
  const sites = await node.getSitesFromSnapshot();
375
375
 
376
- const { dashboardDomain } = info.routing;
376
+ const { ipWildcardDomain } = info.routing;
377
377
  const adminPath = normalizePathPrefix(info.routing.adminPath);
378
378
  const tmpHttpPort = getPort(httpPort, DEFAULT_HTTP_PORT);
379
379
 
@@ -383,12 +383,12 @@ const getBaseUrls = async (node, ips) => {
383
383
  };
384
384
  });
385
385
 
386
- if (dashboardDomain) {
387
- const site = sites.find((c) => (c.domainAliases || []).find((item) => item.value === dashboardDomain));
386
+ if (ipWildcardDomain) {
387
+ const site = sites.find((c) => (c.domainAliases || []).find((item) => item.value === ipWildcardDomain));
388
388
  if (site) {
389
- const httpInfo = await getHttpInfo(dashboardDomain);
389
+ const httpInfo = await getHttpInfo(ipWildcardDomain);
390
390
  const httpsUrls = availableIps.map((ip) => ({
391
- url: `${httpInfo.protocol}://${transformIPToDomain(ip)}.${dashboardDomain.substring(2)}${
391
+ url: `${httpInfo.protocol}://${transformIPToDomain(ip)}.${ipWildcardDomain.substring(2)}${
392
392
  httpInfo.port
393
393
  }${adminPath}`,
394
394
  }));
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.6.20",
6
+ "version": "1.6.21",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,22 +19,22 @@
19
19
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "@abtnode/certificate-manager": "1.6.20",
23
- "@abtnode/constant": "1.6.20",
24
- "@abtnode/cron": "1.6.20",
25
- "@abtnode/db": "1.6.20",
26
- "@abtnode/logger": "1.6.20",
27
- "@abtnode/queue": "1.6.20",
28
- "@abtnode/rbac": "1.6.20",
29
- "@abtnode/router-provider": "1.6.20",
30
- "@abtnode/static-server": "1.6.20",
31
- "@abtnode/timemachine": "1.6.20",
32
- "@abtnode/util": "1.6.20",
22
+ "@abtnode/certificate-manager": "1.6.21",
23
+ "@abtnode/constant": "1.6.21",
24
+ "@abtnode/cron": "1.6.21",
25
+ "@abtnode/db": "1.6.21",
26
+ "@abtnode/logger": "1.6.21",
27
+ "@abtnode/queue": "1.6.21",
28
+ "@abtnode/rbac": "1.6.21",
29
+ "@abtnode/router-provider": "1.6.21",
30
+ "@abtnode/static-server": "1.6.21",
31
+ "@abtnode/timemachine": "1.6.21",
32
+ "@abtnode/util": "1.6.21",
33
33
  "@arcblock/did": "^1.14.13",
34
34
  "@arcblock/event-hub": "1.14.13",
35
35
  "@arcblock/pm2-events": "^0.0.5",
36
36
  "@arcblock/vc": "^1.14.13",
37
- "@blocklet/meta": "1.6.20",
37
+ "@blocklet/meta": "1.6.21",
38
38
  "@fidm/x509": "^1.2.1",
39
39
  "@nedb/core": "^1.2.2",
40
40
  "@nedb/multi": "^1.2.2",
@@ -75,5 +75,5 @@
75
75
  "express": "^4.17.1",
76
76
  "jest": "^27.4.5"
77
77
  },
78
- "gitHead": "e695a9fa4e2cbf7fcef554be3309090c37919d94"
78
+ "gitHead": "864ae21711c119948475057a1f634fd7d16ae91a"
79
79
  }