@abtnode/core 1.6.18 → 1.6.22

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
@@ -93,7 +93,7 @@ class NodeAPI {
93
93
  async updateNodeInfo(entity = {}, context) {
94
94
  await validateNodeInfo(entity, context);
95
95
 
96
- if (entity.autoUpgrade) {
96
+ if (entity.autoUpgrade && process.env.NODE_ENV !== 'development') {
97
97
  try {
98
98
  canPackageReadWrite(process.env.ABT_NODE_BINARY_NAME, process.env.ABT_NODE_PACKAGE_NAME);
99
99
  } catch (err) {
@@ -20,11 +20,12 @@ 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 {
27
27
  isFreeBlocklet,
28
+ isComponentBlocklet,
28
29
  isDeletableBlocklet,
29
30
  getRequiredMissingConfigs,
30
31
  hasRunnableComponent,
@@ -88,6 +89,8 @@ const {
88
89
  checkDuplicateComponents,
89
90
  getDiffFiles,
90
91
  getBundleDir,
92
+ needBlockletDownload,
93
+ verifyPurchase,
91
94
  } = require('../../util/blocklet');
92
95
  const states = require('../../states');
93
96
  const BlockletRegistry = require('../registry');
@@ -195,6 +198,20 @@ class BlockletManager extends BaseBlockletManager {
195
198
  throw new Error('Unknown source');
196
199
  }
197
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
+ */
198
215
  async installComponent({ rootDid, mountPoint, url, file, did, diffVersion, deleteSet }, context = {}) {
199
216
  logger.debug('start install component', { rootDid, mountPoint, url });
200
217
 
@@ -242,8 +259,8 @@ class BlockletManager extends BaseBlockletManager {
242
259
  // FIXME: 这里的 trustedIssuers 相当于相信任何 VC,需要想更安全的方法
243
260
  verifyPresentation({ presentation: vcPresentation, trustedIssuers: [get(vc, 'issuer.id')], challenge });
244
261
 
245
- if (!vc.type.includes(BLOCKLET_PURCHASE_NFT_TYPE)) {
246
- 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`);
247
264
  }
248
265
 
249
266
  const blockletUrl = get(vc, 'credentialSubject.purchased.blocklet.url');
@@ -819,21 +836,23 @@ class BlockletManager extends BaseBlockletManager {
819
836
  };
820
837
  }
821
838
 
822
- async updateChildren({ updateId, did: inputDid, children: inputChildren }, context) {
839
+ async updateChildren({ updateId, did: inputDid, children: inputChildren, oldBlocklet: inputOldBlocklet }, context) {
823
840
  let did;
824
841
  let children;
842
+ let oldBlocklet;
825
843
  if (!updateId && inputDid && inputChildren) {
826
844
  did = inputDid;
827
845
  children = inputChildren;
846
+ oldBlocklet = inputOldBlocklet;
828
847
  } else {
829
848
  const sessionData = await states.session.end(updateId);
830
849
  did = sessionData.did;
831
850
  const { staticChildren = [], dynamicChildren = [] } = sessionData;
832
851
  children = [...staticChildren, ...dynamicChildren.map((x) => ({ ...x, dynamic: true }))];
852
+ oldBlocklet = await states.blocklet.getBlocklet(did);
833
853
  }
834
854
 
835
855
  // get old blocklet
836
- const oldBlocklet = await states.blocklet.getBlocklet(did);
837
856
  const { meta } = oldBlocklet;
838
857
  const { name, version } = meta;
839
858
 
@@ -1179,9 +1198,6 @@ class BlockletManager extends BaseBlockletManager {
1179
1198
  return;
1180
1199
  }
1181
1200
 
1182
- const blocklet1 = await states.blocklet.setBlockletStatus(did, BlockletStatus.downloading);
1183
- this.emit(BlockletEvents.statusChange, blocklet1);
1184
-
1185
1201
  preDownloadLock.release();
1186
1202
 
1187
1203
  const { isCancelled } = await this._downloadBlocklet(blocklet, oldBlocklet);
@@ -1327,14 +1343,15 @@ class BlockletManager extends BaseBlockletManager {
1327
1343
  const blocklet = await states.blocklet.getBlocklet(did);
1328
1344
  const nodeInfo = await states.node.read();
1329
1345
 
1330
- const rootSystemEnvironments = getRootSystemEnvironments(blockletWithEnv, nodeInfo);
1331
- const overwrittenEnvironments = getOverwrittenEnvironments(blockletWithEnv, nodeInfo);
1346
+ const rootSystemEnvironments = {
1347
+ ...getRootSystemEnvironments(blockletWithEnv, nodeInfo),
1348
+ ...getOverwrittenEnvironments(blockletWithEnv, nodeInfo),
1349
+ };
1332
1350
 
1333
1351
  // fill environments to blocklet and blocklet.children
1334
1352
  blocklet.environments = formatEnvironments({
1335
1353
  ...getSystemEnvironments(blockletWithEnv),
1336
1354
  ...rootSystemEnvironments,
1337
- ...overwrittenEnvironments,
1338
1355
  });
1339
1356
 
1340
1357
  for (const child of blocklet.children) {
@@ -1343,11 +1360,13 @@ class BlockletManager extends BaseBlockletManager {
1343
1360
  child.environments = formatEnvironments({
1344
1361
  ...getSystemEnvironments(childWithEnv), // system env of child blocklet
1345
1362
  ...rootSystemEnvironments, // system env of root blocklet
1346
- ...overwrittenEnvironments,
1347
1363
  });
1348
1364
  }
1349
1365
  }
1350
1366
 
1367
+ // put BLOCKLET_APP_ID at root level for indexing
1368
+ blocklet.appDid = rootSystemEnvironments.BLOCKLET_APP_ID;
1369
+
1351
1370
  // update state to db
1352
1371
  return states.blocklet.updateBlocklet(did, blocklet);
1353
1372
  }
@@ -1368,23 +1387,21 @@ class BlockletManager extends BaseBlockletManager {
1368
1387
 
1369
1388
  const registryUrl = registry || (await states.node.getBlockletRegistry());
1370
1389
  const info = await BlockletRegistry.getRegistryMeta(registryUrl);
1371
- const blocklet = await this.registry.getBlocklet(did, registryUrl);
1372
- if (!blocklet) {
1390
+ const meta = await this.registry.getBlocklet(did, registryUrl);
1391
+ if (!meta) {
1373
1392
  throw new Error('Can not install blocklet that not found in registry');
1374
1393
  }
1375
1394
 
1376
- const state = await states.blocklet.getBlocklet(blocklet.did);
1395
+ const state = await states.blocklet.getBlocklet(meta.did);
1377
1396
  if (state) {
1378
1397
  throw new Error('Can not install an already installed blocklet');
1379
1398
  }
1380
1399
 
1381
- if (isFreeBlocklet(blocklet) === false && !context.blockletPurchaseVerified) {
1382
- throw new Error('Can not install a non-free blocklet directly');
1383
- }
1400
+ verifyPurchase(meta, context);
1384
1401
 
1385
1402
  // install
1386
1403
  return this._install({
1387
- meta: blocklet,
1404
+ meta,
1388
1405
  source: BlockletSource.registry,
1389
1406
  deployedFrom: info.cdnUrl || registryUrl,
1390
1407
  context,
@@ -1434,6 +1451,12 @@ class BlockletManager extends BaseBlockletManager {
1434
1451
  throw new Error('Cannot add self as a component');
1435
1452
  }
1436
1453
 
1454
+ if (!isComponentBlocklet(meta)) {
1455
+ throw new Error('The blocklet cannot be a component');
1456
+ }
1457
+
1458
+ verifyPurchase(meta, context);
1459
+
1437
1460
  const newChildren = await parseChildren(blocklet.meta, {
1438
1461
  children: [
1439
1462
  {
@@ -1447,10 +1470,14 @@ class BlockletManager extends BaseBlockletManager {
1447
1470
 
1448
1471
  checkDuplicateComponents(blocklet.children, newChildren);
1449
1472
 
1473
+ // add component to db
1474
+ await states.blocklet.addChildren(rootDid, newChildren);
1475
+
1450
1476
  return this.updateChildren(
1451
1477
  {
1452
1478
  did: rootDid,
1453
1479
  children: [...blocklet.children, ...newChildren],
1480
+ oldBlocklet: blocklet,
1454
1481
  },
1455
1482
  context
1456
1483
  );
@@ -2272,7 +2299,7 @@ class BlockletManager extends BaseBlockletManager {
2272
2299
  } else {
2273
2300
  const status =
2274
2301
  oldBlocklet.status === BlockletStatus.installed ? BlockletStatus.installed : BlockletStatus.stopped;
2275
- await states.blocklet.setBlockletStatus(did, status);
2302
+ await states.blocklet.setBlockletStatus(did, status, { children: 'all' });
2276
2303
  }
2277
2304
 
2278
2305
  blocklet = await this.ensureBlocklet(did, context);
@@ -2496,10 +2523,7 @@ class BlockletManager extends BaseBlockletManager {
2496
2523
  } = blocklet;
2497
2524
 
2498
2525
  const metas = [];
2499
- if (
2500
- ![BlockletSource.upload, BlockletSource.local].includes(blocklet.source) &&
2501
- get(oldBlocklet, 'meta.dist.integrity') !== get(blocklet, 'meta.dist.integrity')
2502
- ) {
2526
+ if (needBlockletDownload(blocklet)) {
2503
2527
  metas.push(blocklet.meta);
2504
2528
  }
2505
2529
 
@@ -2510,16 +2534,17 @@ class BlockletManager extends BaseBlockletManager {
2510
2534
 
2511
2535
  for (const child of blocklet.children) {
2512
2536
  const oldChild = oldChildren[child.meta.did];
2513
- if (
2514
- !oldChild ||
2515
- (![BlockletSource.upload, BlockletSource.local].includes(child.source) &&
2516
- child.sourceUrl &&
2517
- get(oldChild, 'meta.dist.integrity') !== get(child, 'meta.dist.integrity'))
2518
- ) {
2537
+ if (needBlockletDownload(child, oldChild)) {
2519
2538
  metas.push(child.meta);
2520
2539
  }
2521
2540
  }
2522
2541
 
2542
+ // update children status
2543
+ const blocklet1 = await states.blocklet.setBlockletStatus(did, BlockletStatus.downloading, {
2544
+ children: metas.map((x) => ({ did: x.did })),
2545
+ });
2546
+ this.emit(BlockletEvents.statusChange, blocklet1);
2547
+
2523
2548
  try {
2524
2549
  logger.info('Download Blocklet', { name, did, bundles: metas.map((x) => get(x, 'dist.tarball')) });
2525
2550
  const tasks = [];
package/lib/event.js CHANGED
@@ -132,7 +132,7 @@ module.exports = ({
132
132
  onEvent(name, blocklet);
133
133
  };
134
134
 
135
- const handleCLIEvent = (eventName) => {
135
+ const handleServerEvent = (eventName) => {
136
136
  const [, status] = eventName.split('.');
137
137
  onEvent(eventName, {
138
138
  title: `Blocklet Server ${status}`,
@@ -209,7 +209,8 @@ module.exports = ({
209
209
 
210
210
  events.handleBlockletAdd = handleBlockletAdd;
211
211
  events.handleBlockletRemove = handleBlockletRemove;
212
- events.handleCLIEvent = handleCLIEvent;
212
+ events.handleServerEvent = handleServerEvent;
213
+ events.onEvent = onEvent;
213
214
 
214
215
  return events;
215
216
  };
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,35 @@
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 {
6
+ DEFAULT_WILDCARD_CERT_HOST,
7
+ DEFAULT_DID_DOMAIN,
8
+ DEFAULT_DID_REGISTRY,
9
+ DEFAULT_IP_DOMAIN,
10
+ } = require('@abtnode/constant');
11
+
12
+ module.exports = async ({ states, printInfo, configFile }) => {
13
+ printInfo('Try to rename dashboardDomain to ipWildcardDomain in db...');
14
+
15
+ let info = await states.node.read();
16
+ set(info, 'routing.ipWildcardDomain', info.routing.dashboardDomain || DEFAULT_IP_DOMAIN);
17
+ set(info, 'routing.wildcardCertHost', DEFAULT_WILDCARD_CERT_HOST);
18
+ set(info, 'didDomain', DEFAULT_DID_DOMAIN);
19
+ set(info, 'didRegistry', DEFAULT_DID_REGISTRY);
20
+ info = omit(info, 'routing.dashboardDomain');
21
+
22
+ await states.node.updateNodeInfo(info);
23
+
24
+ if (process.env.NODE_ENV !== 'development') {
25
+ let rawConfig = yaml.safeLoad(fs.readFileSync(configFile).toString());
26
+ set(rawConfig, 'node.routing.ipWildcardDomain', info.routing.ipWildcardDomain);
27
+ set(rawConfig, 'node.routing.wildcardCertHost', DEFAULT_WILDCARD_CERT_HOST);
28
+ set(rawConfig, 'node.didDomain', DEFAULT_DID_DOMAIN);
29
+ set(rawConfig, 'node.didRegistry', DEFAULT_DID_REGISTRY);
30
+ rawConfig = omit(rawConfig, 'node.routing.dashboardDomain');
31
+ fs.writeFileSync(configFile, yaml.dump(rawConfig));
32
+ }
33
+
34
+ printInfo(`> Persist new config to file: ${configFile}`);
35
+ };
@@ -132,9 +132,13 @@ const runMigrationScripts = async ({
132
132
  for (let i = 0; i < scripts.length; i++) {
133
133
  const { script, version } = scripts[i];
134
134
  try {
135
- const executed = await node.isMigrationExecuted({ script, version });
136
- if (executed === false) {
135
+ if (process.env.NODE_ENV === 'development') {
137
136
  pending.push(scripts[i]);
137
+ } else {
138
+ const executed = await node.isMigrationExecuted({ script, version });
139
+ if (executed === false) {
140
+ pending.push(scripts[i]);
141
+ }
138
142
  }
139
143
  } catch (err) {
140
144
  printError(`Failed to detect migration script execution status: ${script}, error: ${err.message}`);
@@ -223,6 +223,19 @@ const ensureServiceRule = async (sites) => {
223
223
  return site;
224
224
  });
225
225
  };
226
+ const ensureRootRule = async (sites) => {
227
+ return sites.map((site) => {
228
+ if (!isBasicSite(site.domain) && !site.rules.some((x) => x.from.pathPrefix === '/')) {
229
+ site.rules.push({
230
+ from: { pathPrefix: '/' },
231
+ to: {
232
+ type: ROUTING_RULE_TYPES.NONE,
233
+ },
234
+ });
235
+ }
236
+ return site;
237
+ });
238
+ };
226
239
 
227
240
  const ensureLatestNodeInfo = async (sites = [], { withDefaultCors = true } = {}) => {
228
241
  const info = await states.node.read();
@@ -419,6 +432,13 @@ const decompressCertificates = async (source, dest) => {
419
432
  return dest;
420
433
  };
421
434
 
435
+ const joinCertDownUrl = (baseUrl, name) => joinUrl(baseUrl, '/certs', name);
436
+
437
+ const getIpEchoCertDownloadUrl = (baseUrl) => joinCertDownUrl(baseUrl, 'ip-abtnet-io.tar.gz');
438
+ const getDidDomainCertDownloadUrl = (baseUrl) => joinCertDownUrl(baseUrl, 'did-abtnet-io.tar.gz');
439
+ const getDownloadCertBaseUrl = (info) =>
440
+ process.env.ABT_NODE_WILDCARD_CERT_HOST || get(info, 'routing.wildcardCertHost', '');
441
+
422
442
  module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerManager, blockletManager, certManager }) {
423
443
  const nodeState = states.node;
424
444
  const blockletState = states.blocklet;
@@ -428,46 +448,13 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
428
448
  // site level duplication detection
429
449
  const hasRuleByPrefix = (site, value) => site.rules.find((x) => x.isProtected && get(x, 'from.pathPrefix') === value);
430
450
 
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
-
451
+ const downloadCert = async ({ domain, url }) => {
465
452
  const destFolder = getTmpDirectory(path.join(`certificate-${Date.now()}`));
466
453
  try {
467
454
  const filename = path.join(destFolder, 'certificate.tar.gz');
468
455
  fs.ensureDirSync(destFolder);
469
456
 
470
- await downloadFile(certDownloadAddress, filename);
457
+ await downloadFile(url, filename);
471
458
  await decompressCertificates(filename, destFolder);
472
459
 
473
460
  const certificateFilePath = path.join(destFolder, 'cert.pem');
@@ -485,7 +472,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
485
472
  const privateKey = fs.readFileSync(privateKeyFilePath).toString();
486
473
 
487
474
  await certManager.upsertByDomain({
488
- domain: dashboardDomain,
475
+ domain,
489
476
  privateKey,
490
477
  certificate,
491
478
  isProtected: true,
@@ -499,23 +486,68 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
499
486
  }
500
487
  };
501
488
 
502
- const ensureDashboardCertificate = async () => {
489
+ const updateCert = async (domain, url) => {
490
+ try {
491
+ const cert = await routerManager.findCertificateByDomain(domain);
492
+ if (!cert) {
493
+ return;
494
+ }
495
+
496
+ const now = Date.now();
497
+ const certInfo = getHttpsCertInfo(cert.certificate);
498
+ if (certInfo.validTo - now >= CERTIFICATE_EXPIRES_OFFSET) {
499
+ logger.info('skip dashboard certificate update before not expired', { domain, url });
500
+ return;
501
+ }
502
+
503
+ await downloadCert({
504
+ domain,
505
+ url,
506
+ });
507
+ } catch (err) {
508
+ logger.error('failed to check dashboard certificate expiration', { error: err, domain, url });
509
+ }
510
+ };
511
+
512
+ const updateDashboardCertificates = async () => {
503
513
  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');
514
+ const provider = getProviderFromNodeInfo(info);
515
+ if (provider === ROUTER_PROVIDER_NONE) {
516
+ return;
508
517
  }
509
518
 
510
- const cert = await certManager.getByDomain(dashboardDomain);
511
- if (cert) {
512
- return { status: 'existed' };
519
+ const https = get(info, 'routing.https', true);
520
+ const ipWildcardDomain = get(info, 'routing.ipWildcardDomain', '');
521
+ const didDomain = info.didDomain;
522
+ const certDownloadAddress = getDownloadCertBaseUrl(info);
523
+ if (!https || !certDownloadAddress) {
524
+ return;
513
525
  }
514
526
 
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' };
527
+ await updateCert(ipWildcardDomain, getIpEchoCertDownloadUrl(certDownloadAddress));
528
+ await updateCert(`*.${didDomain}`, getDidDomainCertDownloadUrl(certDownloadAddress));
529
+ };
530
+
531
+ const ensureWildcardCerts = async () => {
532
+ const info = await nodeState.read();
533
+ const didDomain = info.didDomain;
534
+ const ipWildcardDomain = get(info, 'routing.ipWildcardDomain', '');
535
+
536
+ const ensureDomainCert = async (domain, url) => {
537
+ const cert = await certManager.getByDomain(domain);
538
+ if (!cert) {
539
+ await downloadCert({
540
+ domain,
541
+ url,
542
+ });
543
+ }
544
+ };
545
+
546
+ const certBaseUrl = getDownloadCertBaseUrl(info);
547
+ await Promise.all([
548
+ ensureDomainCert(ipWildcardDomain, getIpEchoCertDownloadUrl(certBaseUrl)),
549
+ ensureDomainCert(`*.${didDomain}`, getDidDomainCertDownloadUrl(certBaseUrl)),
550
+ ]);
519
551
  };
520
552
 
521
553
  const upsertSiteRule = async ({ site, rule }, context) => {
@@ -658,9 +690,9 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
658
690
  return domainAlias === item;
659
691
  });
660
692
 
661
- const dashboardDomain = get(info, 'routing.dashboardDomain', '');
693
+ const ipWildcardDomain = get(info, 'routing.ipWildcardDomain', '');
662
694
  const didDomain = `${info.did.toLowerCase()}.${info.didDomain}`;
663
- let dashboardAliasDomains = [dashboardDomain, didDomain];
695
+ let dashboardAliasDomains = [ipWildcardDomain, didDomain];
664
696
 
665
697
  dashboardAliasDomains = dashboardAliasDomains
666
698
  .filter((item) => item && !isExistsInAlias(item))
@@ -748,8 +780,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
748
780
 
749
781
  const existSite = await states.site.findOne({ domain: domainGroup });
750
782
  if (!existSite) {
751
- const ipEchoDnsDomain = getIpDnsDomainForBlocklet(blocklet, webInterface, nodeInfo.did);
752
- const domainAliases = [{ value: ipEchoDnsDomain, isProtected: true }];
783
+ const domainAliases = [];
753
784
 
754
785
  const didDomain = getDidDomainForBlocklet({
755
786
  name: blocklet.meta.name,
@@ -757,7 +788,10 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
757
788
  didDomain: nodeInfo.didDomain,
758
789
  });
759
790
 
760
- domainAliases.push({ value: didDomain, isProtected: true });
791
+ const ipEchoDnsDomain = getIpDnsDomainForBlocklet(blocklet, webInterface, nodeInfo.did);
792
+
793
+ // let didDomain in front of ipEchoDnsDomain
794
+ domainAliases.push({ value: didDomain, isProtected: true }, { value: ipEchoDnsDomain, isProtected: true });
761
795
 
762
796
  await routerManager.addRoutingSite(
763
797
  {
@@ -1157,6 +1191,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
1157
1191
  sites = await ensureLatestInfo(sites);
1158
1192
  sites = await ensureAuthService(sites, blockletManager);
1159
1193
  sites = await ensureServiceRule(sites);
1194
+ sites = await ensureRootRule(sites);
1160
1195
 
1161
1196
  const certificates = httpsEnabled ? await certManager.getAllNormal() : [];
1162
1197
 
@@ -1386,7 +1421,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
1386
1421
  getSitesFromSnapshot,
1387
1422
  getCertificates,
1388
1423
  checkDomain,
1389
- ensureDashboardCertificate,
1424
+ ensureWildcardCerts,
1390
1425
  addWellknownSite,
1391
1426
  upsertSiteRule,
1392
1427
 
@@ -1394,7 +1429,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
1394
1429
  {
1395
1430
  name: 'update-dashboard-certificate',
1396
1431
  time: '0 1 */6 * * *', // refetch on 0:00, 6:00, etc.
1397
- fn: () => updateDashboardCertificate({ checkExpire: true }),
1432
+ fn: () => updateDashboardCertificates(),
1398
1433
  options: { runOnInit: true },
1399
1434
  },
1400
1435
  {
@@ -5,7 +5,7 @@ const {
5
5
  DOMAIN_FOR_DEFAULT_SITE,
6
6
  DOMAIN_FOR_IP_SITE_REGEXP,
7
7
  ROUTING_RULE_TYPES,
8
- DEFAULT_DASHBOARD_DOMAIN,
8
+ DEFAULT_IP_DOMAIN,
9
9
  BLOCKLET_PROXY_PATH_PREFIX,
10
10
  BLOCKLET_SITE_GROUP_SUFFIX,
11
11
  } = require('@abtnode/constant');
@@ -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_IP_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) {
@@ -221,10 +221,10 @@ class RouterManager extends EventEmitter {
221
221
  }
222
222
  }
223
223
 
224
- const updateResult = await states.site.update(
225
- { _id: id },
226
- { $push: { domainAliases: { value: domainAlias, isProtected: false } } }
227
- );
224
+ // let custom domain in front of protected domain
225
+ const domainAliases = [{ value: domainAlias, isProtected: false }, ...dbSite.domainAliases];
226
+
227
+ const updateResult = await states.site.update({ _id: id }, { $set: { domainAliases } });
228
228
  logger.debug('add domain alias update result', { id, updateResult, domainAlias });
229
229
 
230
230
  const newSite = await states.site.findOne({ _id: id });
@@ -20,7 +20,7 @@ const {
20
20
  const logger = require('@abtnode/logger')('state-blocklet');
21
21
 
22
22
  const BaseState = require('./base');
23
- const { forEachBlocklet } = require('../util/blocklet');
23
+ const { forEachBlocklet, checkDuplicateComponents } = require('../util/blocklet');
24
24
  const { validateBlockletMeta } = require('../util');
25
25
 
26
26
  const lock = new Lock('blocklet-port-assign-lock');
@@ -80,7 +80,11 @@ class BlockletState extends BaseState {
80
80
 
81
81
  getBlocklet(did) {
82
82
  return new Promise((resolve, reject) => {
83
- this.db.findOne({ 'meta.did': did }, (err, doc) => {
83
+ if (!did) {
84
+ resolve(null);
85
+ }
86
+
87
+ this.db.findOne({ $or: [{ 'meta.did': did }, { appDid: did }] }, (err, doc) => {
84
88
  if (err) {
85
89
  return reject(err);
86
90
  }
@@ -160,6 +164,7 @@ class BlockletState extends BaseState {
160
164
  // add to db
161
165
  this.db.insert(
162
166
  {
167
+ appDid: null, // will updated later when updating blocklet environments
163
168
  mode,
164
169
  meta: omit(sanitized, ['htmlAst']),
165
170
  status,
@@ -391,13 +396,20 @@ class BlockletState extends BaseState {
391
396
  return result;
392
397
  }
393
398
 
394
- async setBlockletStatus(did, status) {
399
+ /**
400
+ * @param {String} did blocklet did
401
+ * @param {BlockletStatus} status blocklet status
402
+ *
403
+ * children status only different with parent before blocklet installation
404
+ * @param {Array<{did}>} children
405
+ */
406
+ async setBlockletStatus(did, status, { children } = {}) {
395
407
  if (typeof status === 'undefined') {
396
408
  throw new Error('Unsupported blocklet status');
397
409
  }
398
410
 
399
411
  const doc = await this.getBlocklet(did);
400
- if (doc.status === status) {
412
+ if (doc.status === status && !children) {
401
413
  return formatBlocklet(doc, 'onRead', this.options.dek);
402
414
  }
403
415
 
@@ -412,6 +424,28 @@ class BlockletState extends BaseState {
412
424
  updates.stoppedAt = new Date();
413
425
  }
414
426
 
427
+ // update children status
428
+ updates.children = doc.children.map((child) => {
429
+ if (children === 'all') {
430
+ child.status = status;
431
+ return child;
432
+ }
433
+
434
+ if (!children) {
435
+ if (![BlockletStatus.waiting, BlockletStatus.upgrading, BlockletStatus.installing].includes(status)) {
436
+ child.status = status;
437
+ }
438
+
439
+ return child;
440
+ }
441
+
442
+ const inputChild = children.find((x) => x.did === child.meta.did);
443
+ if (inputChild) {
444
+ child.status = status;
445
+ }
446
+ return child;
447
+ });
448
+
415
449
  await this.update(doc._id, { $set: updates });
416
450
  return formatBlocklet({ ...doc, ...updates }, 'onRead', this.options.dek);
417
451
  }
@@ -463,6 +497,48 @@ class BlockletState extends BaseState {
463
497
 
464
498
  return children;
465
499
  }
500
+
501
+ async addChildren(did, children) {
502
+ const parent = await this.getBlocklet(did);
503
+ if (!parent) {
504
+ throw new Error('Blocklet does not exist');
505
+ }
506
+
507
+ const oldChildren = parent.children || [];
508
+
509
+ const newChildren = [...oldChildren];
510
+ for (const child of children) {
511
+ const { meta, mountPoint, sourceUrl = '', source = '', deployedFrom = '' } = child;
512
+
513
+ if (!mountPoint) {
514
+ throw new Error(`mountPoint is required when adding component ${meta.title || meta.name}`);
515
+ }
516
+
517
+ if (meta.did === parent.meta.did) {
518
+ throw new Error('Cannot add self as a component');
519
+ }
520
+
521
+ checkDuplicateComponents([child], newChildren);
522
+
523
+ newChildren.push({
524
+ mountPoint,
525
+ meta,
526
+ sourceUrl,
527
+ source,
528
+ deployedFrom,
529
+ dynamic: true,
530
+ status: BlockletStatus.added,
531
+ });
532
+ }
533
+
534
+ // use upgradeBlocklet to assign ports to children and write new data to db
535
+ return this.upgradeBlocklet({
536
+ meta: parent.meta,
537
+ source: parent.source,
538
+ deployedFrom: parent.deployedFrom,
539
+ children: newChildren,
540
+ });
541
+ }
466
542
  }
467
543
 
468
544
  BlockletState.BlockletStatus = BlockletStatus;
@@ -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
 
@@ -1101,6 +1118,34 @@ const getDiffFiles = async (inputFiles, sourceDir) => {
1101
1118
 
1102
1119
  const getBundleDir = (installDir, bundle) => path.join(installDir, bundle.name, bundle.version);
1103
1120
 
1121
+ const needBlockletDownload = (blocklet, oldBlocklet) => {
1122
+ if ([BlockletSource.upload, BlockletSource.local, BlockletSource.custom].includes(blocklet.source)) {
1123
+ return false;
1124
+ }
1125
+
1126
+ if (!get(oldBlocklet, 'meta.dist.integrity')) {
1127
+ return true;
1128
+ }
1129
+
1130
+ if (get(oldBlocklet, 'meta.dist.integrity') === get(blocklet, 'meta.dist.integrity')) {
1131
+ return false;
1132
+ }
1133
+
1134
+ return true;
1135
+ };
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
+
1104
1149
  module.exports = {
1105
1150
  forEachBlocklet,
1106
1151
  getBlockletMetaFromUrl,
@@ -1135,4 +1180,6 @@ module.exports = {
1135
1180
  checkDuplicateComponents,
1136
1181
  getDiffFiles,
1137
1182
  getBundleDir,
1183
+ needBlockletDownload,
1184
+ verifyPurchase,
1138
1185
  };
@@ -1,9 +1,9 @@
1
1
  const joinUrl = require('url-join');
2
2
  const axios = require('@abtnode/util/lib/axios');
3
- const { DEFAULT_DASHBOARD_DOMAIN, DEFAULT_ADMIN_PATH } = require('@abtnode/constant');
3
+ const { DEFAULT_IP_DOMAIN, DEFAULT_ADMIN_PATH } = require('@abtnode/constant');
4
4
  const { get: getIp } = require('./ip');
5
5
 
6
- const getNodeDomain = (ip) => (ip ? DEFAULT_DASHBOARD_DOMAIN.replace(/^\*/, ip.replace(/\./g, '-')) : '');
6
+ const getNodeDomain = (ip) => (ip ? DEFAULT_IP_DOMAIN.replace(/^\*/, ip.replace(/\./g, '-')) : '');
7
7
 
8
8
  let cache = null;
9
9
 
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
  }));
@@ -27,9 +27,6 @@ const waitUpdaterRpc = async (message) =>
27
27
  const checkNewVersion = async (params, context) => {
28
28
  try {
29
29
  const info = await states.node.read();
30
- if (!info.autoUpgrade) {
31
- return '';
32
- }
33
30
 
34
31
  if (!process.env.ABT_NODE_PACKAGE_NAME) {
35
32
  logger.error('ABT_NODE_PACKAGE_NAME name was not found in environment');
@@ -176,7 +173,14 @@ const getCron = () => ({
176
173
  name: 'check-update',
177
174
  time: '0 0 8 * * *', // check every day
178
175
  // time: '0 */5 * * * *', // check every 5 minutes
179
- fn: checkNewVersion,
176
+ fn: async () => {
177
+ const info = await states.node.read();
178
+ if (!info.autoUpgrade) {
179
+ return;
180
+ }
181
+
182
+ checkNewVersion();
183
+ },
180
184
  options: { runOnInit: false },
181
185
  });
182
186
 
@@ -1,13 +1,13 @@
1
1
  const logger = require('@abtnode/logger')('@abtnode/core:webhook:index');
2
- const upperFirst = require('lodash/upperFirst');
3
2
 
3
+ const sortPriorityUrl = require('@abtnode/util/lib/sort-priority-url');
4
4
  const WebHookSender = require('./sender');
5
5
  const createQueue = require('../queue');
6
6
  const IP = require('../util/ip');
7
7
  const states = require('../states');
8
8
  const { getBaseUrls } = require('../util');
9
9
 
10
- const getSlackUrlInfo = (actionPath = '/notifications', urls) => {
10
+ const getSlackUrlInfo = async (actionPath = '/notifications', urls) => {
11
11
  const info = [];
12
12
 
13
13
  if (actionPath && actionPath.startsWith('/blocklet/')) {
@@ -28,29 +28,27 @@ const getSlackUrlInfo = (actionPath = '/notifications', urls) => {
28
28
  });
29
29
  }
30
30
 
31
- const httpUrls = urls.filter((x) => x.url.startsWith('http://'));
32
- const httpsUrls = urls.filter((x) => x.url.startsWith('https://'));
33
-
34
- const showUrls = httpsUrls.length ? httpsUrls : httpUrls;
35
- const elements = [];
36
- showUrls.forEach((x) => {
37
- const { protocol } = new URL(x.url);
38
- const normalized = `${x.url}${actionPath}`.replace(`${protocol}//`, '').replace(/\/+/g, '/');
39
- const url = `${protocol}//${normalized}`;
40
- elements.push({
41
- type: 'button',
42
- text: {
43
- type: 'plain_text',
44
- text: `${upperFirst(x.type)} Address`,
45
- },
46
- style: 'primary',
47
- value: `${upperFirst(x.type)} Address`,
48
- url,
49
- });
50
- });
31
+ const prioritys = await sortPriorityUrl(urls);
32
+ const priorityUrl = prioritys[0].url;
33
+
34
+ const { protocol } = new URL(priorityUrl);
35
+ const normalized = `${priorityUrl}${actionPath}`.replace(`${protocol}//`, '').replace(/\/+/g, '/');
36
+ const url = `${protocol}//${normalized}`;
37
+
51
38
  info.push({
52
39
  type: 'actions',
53
- elements,
40
+ elements: [
41
+ {
42
+ type: 'button',
43
+ text: {
44
+ type: 'plain_text',
45
+ text: 'Click Me',
46
+ },
47
+ style: 'primary',
48
+ value: 'Click Me',
49
+ url,
50
+ },
51
+ ],
54
52
  });
55
53
 
56
54
  return info;
@@ -79,7 +77,8 @@ module.exports = ({ events, dataDirs, instance }) => {
79
77
  const { name } = nodeInfo;
80
78
  const options = { ...message, nodeInfo: `*${name}*` };
81
79
  if (item.type === 'slack') {
82
- options.urlInfo = getSlackUrlInfo(message.action, baseUrls);
80
+ // eslint-disable-next-line
81
+ options.urlInfo = await getSlackUrlInfo(message.action, baseUrls);
83
82
  }
84
83
  try {
85
84
  // eslint-disable-next-line
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.6.18",
6
+ "version": "1.6.22",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,30 +19,30 @@
19
19
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "@abtnode/certificate-manager": "1.6.18",
23
- "@abtnode/constant": "1.6.18",
24
- "@abtnode/cron": "1.6.18",
25
- "@abtnode/db": "1.6.18",
26
- "@abtnode/logger": "1.6.18",
27
- "@abtnode/queue": "1.6.18",
28
- "@abtnode/rbac": "1.6.18",
29
- "@abtnode/router-provider": "1.6.18",
30
- "@abtnode/static-server": "1.6.18",
31
- "@abtnode/timemachine": "1.6.18",
32
- "@abtnode/util": "1.6.18",
33
- "@arcblock/did": "^1.14.8",
34
- "@arcblock/event-hub": "1.14.8",
22
+ "@abtnode/certificate-manager": "1.6.22",
23
+ "@abtnode/constant": "1.6.22",
24
+ "@abtnode/cron": "1.6.22",
25
+ "@abtnode/db": "1.6.22",
26
+ "@abtnode/logger": "1.6.22",
27
+ "@abtnode/queue": "1.6.22",
28
+ "@abtnode/rbac": "1.6.22",
29
+ "@abtnode/router-provider": "1.6.22",
30
+ "@abtnode/static-server": "1.6.22",
31
+ "@abtnode/timemachine": "1.6.22",
32
+ "@abtnode/util": "1.6.22",
33
+ "@arcblock/did": "^1.14.16",
34
+ "@arcblock/event-hub": "1.14.16",
35
35
  "@arcblock/pm2-events": "^0.0.5",
36
- "@arcblock/vc": "^1.14.8",
37
- "@blocklet/meta": "1.6.18",
36
+ "@arcblock/vc": "^1.14.16",
37
+ "@blocklet/meta": "1.6.22",
38
38
  "@fidm/x509": "^1.2.1",
39
39
  "@nedb/core": "^1.2.2",
40
40
  "@nedb/multi": "^1.2.2",
41
- "@ocap/mcrypto": "^1.14.8",
42
- "@ocap/util": "^1.14.8",
43
- "@ocap/wallet": "^1.14.8",
41
+ "@ocap/mcrypto": "^1.14.16",
42
+ "@ocap/util": "^1.14.16",
43
+ "@ocap/wallet": "^1.14.16",
44
44
  "@slack/webhook": "^5.0.3",
45
- "axios": "^0.21.4",
45
+ "axios": "^0.25.0",
46
46
  "axon": "^2.0.3",
47
47
  "chalk": "^4.0.0",
48
48
  "deep-diff": "^1.0.2",
@@ -53,7 +53,7 @@
53
53
  "is-base64": "^1.1.0",
54
54
  "is-ip": "^3.1.0",
55
55
  "is-url": "^1.2.4",
56
- "joi": "^17.5.0",
56
+ "joi": "^17.6.0",
57
57
  "js-yaml": "^3.14.0",
58
58
  "lodash": "^4.17.21",
59
59
  "lru-cache": "^6.0.0",
@@ -75,5 +75,5 @@
75
75
  "express": "^4.17.1",
76
76
  "jest": "^27.4.5"
77
77
  },
78
- "gitHead": "2f02f166869d8ebedc0466068f6ed90ab3e07b87"
78
+ "gitHead": "18ac52a439dbd04e4ace98d796b6de517503fb14"
79
79
  }