@abtnode/core 1.8.32 → 1.8.34

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.
@@ -3,6 +3,7 @@
3
3
  const fs = require('fs-extra');
4
4
  const { fileURLToPath } = require('url');
5
5
  const path = require('path');
6
+ const urlHttp = require('url-http');
6
7
  const get = require('lodash/get');
7
8
  const pick = require('lodash/pick');
8
9
  const cloneDeep = require('lodash/cloneDeep');
@@ -70,6 +71,7 @@ const {
70
71
  BLOCKLET_META_FILE,
71
72
  BLOCKLET_CONFIGURABLE_KEY,
72
73
  } = require('@blocklet/constant');
74
+ const { isEmpty } = require('lodash');
73
75
  const util = require('../../util');
74
76
  const {
75
77
  refresh: refreshAccessibleExternalNodeIp,
@@ -122,7 +124,6 @@ const handleInstanceInStore = require('../../util/public-to-store');
122
124
  const {
123
125
  isInProgress,
124
126
  isBeforeInstalled,
125
- getBlockletInterfaces,
126
127
  formatEnvironments,
127
128
  shouldUpdateBlockletStatus,
128
129
  getBlockletMeta,
@@ -449,8 +450,14 @@ class BlockletManager extends BaseBlockletManager {
449
450
 
450
451
  if (blocklet.mode === BLOCKLET_MODES.DEVELOPMENT) {
451
452
  const { logsDir } = blocklet.env;
452
- fs.removeSync(logsDir);
453
- fs.mkdirSync(logsDir, { recursive: true });
453
+
454
+ try {
455
+ fs.removeSync(logsDir);
456
+ fs.mkdirSync(logsDir, { recursive: true });
457
+ } catch {
458
+ // Windows && Node.js 18.x 下会发生删除错误(ENOTEMPTY)
459
+ // 但是这个错误并不影响后续逻辑,所以这里对这个错误做了 catch
460
+ }
454
461
  }
455
462
 
456
463
  const getHookFn =
@@ -972,6 +979,16 @@ class BlockletManager extends BaseBlockletManager {
972
979
  }
973
980
  }
974
981
 
982
+ if (x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_STORAGE_ENDPOINT) {
983
+ if (isEmpty(x.value)) {
984
+ throw new Error(`${x.key} can not be empty`);
985
+ }
986
+
987
+ if (!urlHttp(x.value)) {
988
+ throw new Error(`${x.key}(${x.value}) is not a valid http address`);
989
+ }
990
+ }
991
+
975
992
  blocklet.configObj[x.key] = x.value;
976
993
  }
977
994
 
@@ -1563,12 +1580,6 @@ class BlockletManager extends BaseBlockletManager {
1563
1580
  }
1564
1581
  }
1565
1582
 
1566
- async getBlockletInterfaces({ blocklet, nodeInfo, context }) {
1567
- const routingRules = await this.getRoutingRulesByDid(blocklet.meta.did);
1568
- const nodeIp = await getAccessibleExternalNodeIp(nodeInfo);
1569
- return getBlockletInterfaces({ blocklet, context, routingRules, nodeIp });
1570
- }
1571
-
1572
1583
  async attachRuntimeInfo({ did, nodeInfo, diskInfo = true, context, cachedBlocklet }) {
1573
1584
  if (!did) {
1574
1585
  throw new Error('did should not be empty');
@@ -1597,8 +1608,6 @@ class BlockletManager extends BaseBlockletManager {
1597
1608
  }));
1598
1609
  }
1599
1610
 
1600
- blocklet.interfaces = await this.getBlockletInterfaces({ blocklet, nodeInfo, context });
1601
-
1602
1611
  if (!fromCache) {
1603
1612
  blocklet.engine = getEngine(getBlockletEngineNameByPlatform(blocklet.meta)).describe();
1604
1613
  blocklet.diskInfo = await getDiskInfo(blocklet, { useFakeDiskInfo: !diskInfo });
package/lib/event.js CHANGED
@@ -27,6 +27,7 @@ module.exports = ({
27
27
  teamAPI,
28
28
  teamManager,
29
29
  certManager,
30
+ routerManager,
30
31
  node,
31
32
  }) => {
32
33
  const notificationState = states.notification;
@@ -248,7 +249,22 @@ module.exports = ({
248
249
  }
249
250
  };
250
251
 
251
- Object.values(BlockletEvents).forEach((eventName) => {
252
+ [
253
+ BlockletEvents.added,
254
+ BlockletEvents.downloadFailed,
255
+ BlockletEvents.installed,
256
+ BlockletEvents.installFailed,
257
+ BlockletEvents.upgraded,
258
+ BlockletEvents.upgradeFailed,
259
+ BlockletEvents.downgraded,
260
+ BlockletEvents.downgradeFailed,
261
+ BlockletEvents.updated,
262
+ BlockletEvents.statusChange,
263
+ BlockletEvents.removed,
264
+ BlockletEvents.started,
265
+ BlockletEvents.startFailed,
266
+ BlockletEvents.stopped,
267
+ ].forEach((eventName) => {
252
268
  blockletManager.on(eventName, (data) => handleBlockletEvent(eventName, data));
253
269
  });
254
270
 
@@ -276,10 +292,12 @@ module.exports = ({
276
292
  });
277
293
  });
278
294
 
279
- domainStatus.on(EVENTS.DOMAIN_STATUS, (data) => {
280
- if (data) {
281
- onEvent(EVENTS.DOMAIN_STATUS, data);
282
- }
295
+ [EVENTS.DOMAIN_STATUS, BlockletEvents.domainStatus].forEach((eventName) => {
296
+ domainStatus.on(eventName, (data) => {
297
+ if (data) {
298
+ onEvent(eventName, data);
299
+ }
300
+ });
283
301
  });
284
302
 
285
303
  teamAPI.on(EVENTS.USER_ADDED, (data) => onEvent(EVENTS.USER_ADDED, data));
@@ -290,6 +308,8 @@ module.exports = ({
290
308
  certManager.on('cert.issued', (data) => onEvent(EVENTS.CERT_ISSUED, data));
291
309
  certManager.on('cert.error', (data) => onEvent(EVENTS.CERT_ERROR, data));
292
310
 
311
+ routerManager.on(BlockletEvents.updated, (data) => onEvent(BlockletEvents.updated, data));
312
+
293
313
  events.setEventHandler = (handler) => {
294
314
  if (typeof handler === 'function') {
295
315
  eventHandler = handler;
package/lib/index.js CHANGED
@@ -136,8 +136,6 @@ function ABTNode(options) {
136
136
 
137
137
  const {
138
138
  handleRouting,
139
- getRoutingRulesByDid,
140
- getSiteByDid,
141
139
  resetSiteByDid,
142
140
  updateNodeRouting,
143
141
  takeRoutingSnapshot,
@@ -152,19 +150,25 @@ function ABTNode(options) {
152
150
  getRoutingCrons,
153
151
  ensureWildcardCerts,
154
152
  getRouterProvider,
153
+ addRoutingSite,
154
+ deleteRoutingSite,
155
+ updateRoutingSite,
156
+ addRoutingRule,
157
+ updateRoutingRule,
158
+ deleteRoutingRule,
159
+ addDomainAlias,
160
+ deleteDomainAlias,
155
161
  } = getRouterHelpers({ dataDirs, routingSnapshot, routerManager, blockletManager, certManager });
156
162
 
157
163
  const nodeAPI = new NodeAPI(states.node);
158
164
  const teamAPI = new TeamAPI({ states, teamManager, dataDirs });
159
165
 
160
- blockletManager.getRoutingRulesByDid = getRoutingRulesByDid;
161
- blockletManager.getSiteByDid = getSiteByDid;
162
166
  blockletManager.resetSiteByDid = resetSiteByDid;
163
167
 
164
168
  // Generate an on node ready callback
165
169
  const onStatesReady = createStateReadyQueue({ states, options, dataDirs });
166
170
  onStatesReady(createStateReadyHandler(routingSnapshot));
167
- const domainStatus = new DomainStatus(routerManager);
171
+ const domainStatus = new DomainStatus({ routerManager, states });
168
172
 
169
173
  const isInitialized = async () => {
170
174
  const state = await states.node.read();
@@ -318,12 +322,12 @@ function ABTNode(options) {
318
322
 
319
323
  // Routing
320
324
  routerManager,
321
- addRoutingSite: routerManager.addRoutingSite.bind(routerManager),
322
- deleteRoutingSite: routerManager.deleteRoutingSite.bind(routerManager),
323
- updateRoutingSite: routerManager.updateRoutingSite.bind(routerManager),
324
- addRoutingRule: routerManager.addRoutingRule.bind(routerManager),
325
- updateRoutingRule: routerManager.updateRoutingRule.bind(routerManager),
326
- deleteRoutingRule: routerManager.deleteRoutingRule.bind(routerManager),
325
+ addRoutingSite,
326
+ deleteRoutingSite,
327
+ updateRoutingSite,
328
+ addRoutingRule,
329
+ updateRoutingRule,
330
+ deleteRoutingRule,
327
331
  getRoutingRuleById: states.site.getRuleById.bind(states.site),
328
332
  getRoutingSites: (params, context) => getRoutingSites(params, context, { withDefaultCors: false }),
329
333
  getRoutingSnapshots: routingSnapshot.listSnapshots.bind(routingSnapshot),
@@ -333,8 +337,8 @@ function ABTNode(options) {
333
337
  ensureDashboardRouting,
334
338
  ensureWildcardCerts,
335
339
 
336
- addDomainAlias: routerManager.addDomainAlias.bind(routerManager),
337
- deleteDomainAlias: routerManager.deleteDomainAlias.bind(routerManager),
340
+ addDomainAlias,
341
+ deleteDomainAlias,
338
342
 
339
343
  getRoutingProviders: () => listProviders(dataDirs.router),
340
344
  checkDomains: domainStatus.checkDomainsStatus.bind(domainStatus),
@@ -398,6 +402,7 @@ function ABTNode(options) {
398
402
  teamAPI,
399
403
  teamManager,
400
404
  certManager,
405
+ routerManager,
401
406
  node: instance,
402
407
  });
403
408
 
@@ -0,0 +1,20 @@
1
+ /* eslint-disable no-await-in-loop */
2
+ /* eslint-disable no-continue */
3
+
4
+ const { BLOCKLET_MAX_MEM_LIMIT_IN_MB } = require('@abtnode/constant');
5
+
6
+ module.exports = async ({ states, printInfo }) => {
7
+ printInfo('Try to update blockletMaxMemoryLimit...');
8
+
9
+ const info = await states.node.read();
10
+ if (
11
+ info?.runtimeConfig?.blockletMaxMemoryLimit &&
12
+ info.runtimeConfig.blockletMaxMemoryLimit < BLOCKLET_MAX_MEM_LIMIT_IN_MB
13
+ ) {
14
+ info.runtimeConfig.blockletMaxMemoryLimit = BLOCKLET_MAX_MEM_LIMIT_IN_MB;
15
+ await states.node.updateNodeInfo(info);
16
+ printInfo(`Update blockletMaxMemoryLimit to ${BLOCKLET_MAX_MEM_LIMIT_IN_MB}MB`);
17
+ } else {
18
+ printInfo(`No need to update blockletMaxMemoryLimit (${info?.runtimeConfig?.blockletMaxMemoryLimit}MB)`);
19
+ }
20
+ };
@@ -37,19 +37,12 @@ const {
37
37
  BLOCKLET_INTERFACE_TYPE_WEB,
38
38
  BLOCKLET_INTERFACE_WELLKNOWN,
39
39
  BLOCKLET_INTERFACE_TYPE_WELLKNOWN,
40
+ BlockletEvents,
40
41
  } = require('@blocklet/constant');
41
42
 
42
43
  // eslint-disable-next-line global-require
43
44
  const logger = require('@abtnode/logger')(`${require('../../package.json').name}:router:helper`);
44
- const {
45
- getProviderFromNodeInfo,
46
- trimSlash,
47
- getInterfaceUrl,
48
- getBlockletHost,
49
- getHttpsCertInfo,
50
- findInterfacePortByName,
51
- getWellknownSitePort,
52
- } = require('../util');
45
+ const { getProviderFromNodeInfo, getHttpsCertInfo, findInterfacePortByName, getWellknownSitePort } = require('../util');
53
46
  const { getIpDnsDomainForBlocklet, getDidDomainForBlocklet } = require('../util/get-domain-for-blocklet');
54
47
  const { getFromCache: getAccessibleExternalNodeIp } = require('../util/get-accessible-external-node-ip');
55
48
 
@@ -61,6 +54,10 @@ const { getBlockletDomainGroupName, getDidFromDomainGroupName } = require('../ut
61
54
  * replace 888-888-888-888 with accessible ip for domain
62
55
  */
63
56
  const attachRuntimeDomainAliases = async ({ sites = [], context = {}, node }) => {
57
+ if (!sites) {
58
+ return [];
59
+ }
60
+
64
61
  let ip;
65
62
  const ipRegex = /\d+[-.]\d+[-.]\d+[-.]\d+/;
66
63
  const match = ipRegex.exec(context.hostname);
@@ -97,89 +94,6 @@ const attachRuntimeDomainAliases = async ({ sites = [], context = {}, node }) =>
97
94
  });
98
95
  };
99
96
 
100
- const attachInterfaceUrls = async ({ sites = [], context, node }) => {
101
- if (!sites) {
102
- return [];
103
- }
104
-
105
- attachRuntimeDomainAliases({ sites, context, node });
106
-
107
- const getUrl = (rule, domain = '') => {
108
- const host = getBlockletHost({ domain, context });
109
- const prefix = trimSlash(rule.from.pathPrefix);
110
- if (prefix) {
111
- return `http://${host}/${prefix}/`;
112
- }
113
-
114
- return `http://${host}/`;
115
- };
116
-
117
- const blocklets = await states.blocklet.getBlocklets();
118
- const getInterfaces = (site) =>
119
- (site.rules || []).map((tmpRule) => {
120
- const rule = { ...tmpRule };
121
-
122
- const ruleId = tmpRule.id;
123
- const baseUrl = getUrl(rule, site.domain);
124
-
125
- const interfaces = [];
126
- if (rule.to.type === ROUTING_RULE_TYPES.BLOCKLET) {
127
- const blocklet = blocklets.find((b) => b.meta.did === rule.to.did);
128
-
129
- if (!blocklet) {
130
- logger.warn(`can not attach interface urls for non-existing blocklet ${rule.to.did}`);
131
- rule.interfaces = interfaces;
132
- return rule;
133
- }
134
-
135
- if (!getBlockletHost({ domain: site.domain, context })) {
136
- logger.warn('blocklet host does not exist');
137
- rule.interfaces = interfaces;
138
- return rule;
139
- }
140
-
141
- (blocklet.meta.interfaces || []).forEach((x) => {
142
- if (x.port && !x.port.external) {
143
- interfaces.push({
144
- ruleId,
145
- type: x.type,
146
- name: x.name,
147
- url: getInterfaceUrl({ baseUrl, url: '/' }),
148
- });
149
- }
150
- });
151
- } else if (rule.to.type === ROUTING_RULE_TYPES.REDIRECT || rule.to.type === ROUTING_RULE_TYPES.NONE) {
152
- interfaces.push({
153
- ruleId,
154
- type: 'web',
155
- name: ROUTING_RULE_TYPES.REDIRECT,
156
- url: baseUrl,
157
- });
158
- } else {
159
- interfaces.push({
160
- ruleId,
161
- type: 'web',
162
- name: 'default',
163
- url: getUrl(rule),
164
- });
165
- }
166
-
167
- rule.interfaces = interfaces;
168
- return rule;
169
- });
170
-
171
- if (!Array.isArray(sites)) {
172
- sites.rules = getInterfaces(sites);
173
- return sites;
174
- }
175
-
176
- return sites.map((site) => {
177
- site.rules = getInterfaces(site);
178
-
179
- return site;
180
- });
181
- };
182
-
183
97
  const addCorsToSite = (site, rawUrl) => {
184
98
  if (!site || !rawUrl) {
185
99
  return;
@@ -1019,23 +933,6 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
1019
933
  return result;
1020
934
  }
1021
935
 
1022
- async function getRoutingRulesByDid(did) {
1023
- const info = await nodeState.read();
1024
- const { sites } = await readRoutingSites();
1025
- const domain = getBlockletDomainGroupName(did);
1026
- const rules = Router.flattenSitesToRules(
1027
- (sites || []).filter((x) => x.domain === domain),
1028
- info
1029
- );
1030
- return rules.filter((rule) => rule.to.did === did);
1031
- }
1032
-
1033
- async function getSiteByDid(did) {
1034
- const { sites } = await readRoutingSites();
1035
- const domain = getBlockletDomainGroupName(did);
1036
- return (sites || []).find((x) => x.domain === domain);
1037
- }
1038
-
1039
936
  async function resetSiteByDid(did, { refreshRouterProvider = true } = {}) {
1040
937
  const blocklet = await states.blocklet.getBlocklet(did);
1041
938
  await removeBlockletRouting(blocklet);
@@ -1246,7 +1143,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
1246
1143
  return sites;
1247
1144
  }
1248
1145
 
1249
- return attachInterfaceUrls({
1146
+ return attachRuntimeDomainAliases({
1250
1147
  sites: await ensureLatestInfo(sites, { withDefaultCors }),
1251
1148
  context,
1252
1149
  node: nodeState,
@@ -1255,7 +1152,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
1255
1152
 
1256
1153
  const getSnapshotSites = async ({ hash }, context = {}, { withDefaultCors = true } = {}) => {
1257
1154
  const sites = await routingSnapshot.readSnapshotSites(hash);
1258
- return attachInterfaceUrls({
1155
+ return attachRuntimeDomainAliases({
1259
1156
  sites: await ensureLatestInfo(sites, { withDefaultCors }),
1260
1157
  context,
1261
1158
  node: nodeState,
@@ -1284,14 +1181,41 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
1284
1181
  });
1285
1182
  };
1286
1183
 
1184
+ /**
1185
+ * proxy to routerManager and do takeRoutingSnapshot
1186
+ */
1187
+ const _proxyToRouterManager =
1188
+ (fnName) =>
1189
+ async (...args) => {
1190
+ const res = await routerManager[fnName](...args);
1191
+
1192
+ takeRoutingSnapshot({ message: fnName, dryRun: false }).catch((error) => {
1193
+ logger.error('failed to takeRoutingSnapshot', { error });
1194
+ });
1195
+
1196
+ const { teamDid: did } = args[0] || {};
1197
+ if (did) {
1198
+ routerManager.emit(BlockletEvents.updated, { meta: { did } });
1199
+ }
1200
+
1201
+ return res;
1202
+ };
1203
+
1204
+ const addRoutingSite = _proxyToRouterManager('addRoutingSite');
1205
+ const updateRoutingSite = _proxyToRouterManager('updateRoutingSite');
1206
+ const deleteRoutingSite = _proxyToRouterManager('deleteRoutingSite');
1207
+ const addRoutingRule = _proxyToRouterManager('addRoutingRule');
1208
+ const updateRoutingRule = _proxyToRouterManager('updateRoutingRule');
1209
+ const deleteRoutingRule = _proxyToRouterManager('deleteRoutingRule');
1210
+ const addDomainAlias = _proxyToRouterManager('addDomainAlias');
1211
+ const deleteDomainAlias = _proxyToRouterManager('deleteDomainAlias');
1212
+
1287
1213
  return {
1288
1214
  ensureDashboardRouting,
1289
1215
  ensureBlockletRouting,
1290
1216
  ensureBlockletRoutingForUpgrade,
1291
1217
  removeBlockletRouting,
1292
1218
  handleRouting,
1293
- getRoutingRulesByDid,
1294
- getSiteByDid,
1295
1219
  resetSiteByDid,
1296
1220
  updateNodeRouting,
1297
1221
  takeRoutingSnapshot,
@@ -1318,10 +1242,19 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
1318
1242
  options: { runOnInit: false },
1319
1243
  },
1320
1244
  ],
1245
+
1246
+ addRoutingSite,
1247
+ deleteRoutingSite,
1248
+ updateRoutingSite,
1249
+ addRoutingRule,
1250
+ updateRoutingRule,
1251
+ deleteRoutingRule,
1252
+ addDomainAlias,
1253
+ deleteDomainAlias,
1321
1254
  };
1322
1255
  };
1323
1256
 
1324
- module.exports.attachInterfaceUrls = attachInterfaceUrls;
1257
+ module.exports.attachRuntimeDomainAliases = attachRuntimeDomainAliases;
1325
1258
  module.exports.ensureLatestNodeInfo = ensureLatestNodeInfo;
1326
1259
  module.exports.ensureLatestInterfaceInfo = ensureLatestInterfaceInfo;
1327
1260
  module.exports.ensureLatestInfo = ensureLatestInfo;
@@ -39,7 +39,7 @@ const {
39
39
  } = require('../validators/router');
40
40
  const { getProviderFromNodeInfo, findInterfaceByName, isCLI, findInterfacePortByName } = require('../util');
41
41
  const { findWebInterface } = require('../util/blocklet');
42
- const { attachInterfaceUrls, ensureLatestInfo } = require('./helper');
42
+ const { attachRuntimeDomainAliases, ensureLatestInfo } = require('./helper');
43
43
  const Router = require('./index');
44
44
  const states = require('../states');
45
45
 
@@ -124,7 +124,7 @@ class RouterManager extends EventEmitter {
124
124
  await this.validateRouterConfig('addRoutingSite', { site: newSite });
125
125
 
126
126
  const result = await states.site.add(newSite);
127
- await attachInterfaceUrls({ sites: result, context, node: states.node });
127
+ await attachRuntimeDomainAliases({ sites: result, context, node: states.node });
128
128
 
129
129
  this.emit('router.site.created', result);
130
130
  return result;
@@ -184,7 +184,7 @@ class RouterManager extends EventEmitter {
184
184
  this.emit('router.site.updated', params.id);
185
185
 
186
186
  const dbSite = await states.site.findOne({ _id: params.id });
187
- await attachInterfaceUrls({ sites: dbSite, context, node: states.node });
187
+ await attachRuntimeDomainAliases({ sites: dbSite, context, node: states.node });
188
188
  return dbSite;
189
189
  }
190
190
 
@@ -228,7 +228,7 @@ class RouterManager extends EventEmitter {
228
228
  logger.debug('add domain alias update result', { id, updateResult, domainAlias });
229
229
 
230
230
  const newSite = await states.site.findOne({ _id: id });
231
- await attachInterfaceUrls({ sites: newSite, context, node: states.node });
231
+ await attachRuntimeDomainAliases({ sites: newSite, context, node: states.node });
232
232
 
233
233
  return newSite;
234
234
  }
@@ -251,7 +251,7 @@ class RouterManager extends EventEmitter {
251
251
  const updateResult = await states.site.update({ _id: id }, { $set: { domainAliases: dbSite.domainAliases } });
252
252
  logger.debug('remove domain alias update result', { id, updateResult, domainAlias });
253
253
 
254
- await attachInterfaceUrls({ sites: dbSite, context, node: states.node });
254
+ await attachRuntimeDomainAliases({ sites: dbSite, context, node: states.node });
255
255
 
256
256
  return dbSite;
257
257
  }
@@ -286,7 +286,7 @@ class RouterManager extends EventEmitter {
286
286
  }
287
287
 
288
288
  const newSite = await states.site.findOne({ _id: id });
289
- await attachInterfaceUrls({ sites: newSite, context, node: states.node });
289
+ await attachRuntimeDomainAliases({ sites: newSite, context, node: states.node });
290
290
 
291
291
  this.emit('router.rule.created', newSite);
292
292
  return newSite;
@@ -330,7 +330,7 @@ class RouterManager extends EventEmitter {
330
330
  logger.info('update result', { updateResult });
331
331
  const newSite = await states.site.findOne({ _id: id });
332
332
 
333
- await attachInterfaceUrls({ sites: newSite, context, node: states.node });
333
+ await attachRuntimeDomainAliases({ sites: newSite, context, node: states.node });
334
334
 
335
335
  this.emit('router.rule.updated', newSite);
336
336
 
@@ -359,7 +359,7 @@ class RouterManager extends EventEmitter {
359
359
  logger.info('router.rule.removed', { id, ruleId });
360
360
  const newSite = await states.site.findOne({ _id: id });
361
361
 
362
- await attachInterfaceUrls({ sites: newSite, context, node: states.node });
362
+ await attachRuntimeDomainAliases({ sites: newSite, context, node: states.node });
363
363
 
364
364
  this.emit('router.rule.removed', newSite);
365
365
  return newSite;
@@ -2,6 +2,7 @@ const logger = require('@abtnode/logger')('@abtnode/core:states:site');
2
2
  const { toSlotDomain } = require('@abtnode/router-provider/lib/util');
3
3
 
4
4
  const BaseState = require('./base');
5
+ const { getBlockletDomainGroupName } = require('../util/router');
5
6
 
6
7
  class SiteState extends BaseState {
7
8
  constructor(baseDir, config = {}) {
@@ -72,6 +73,16 @@ class SiteState extends BaseState {
72
73
  $or: [{ domain }, { domainAliases: domain }, { 'domainAliases.value': domain }],
73
74
  });
74
75
  }
76
+
77
+ async findOneByBlocklet(did) {
78
+ const result = await this.findOne({ domain: getBlockletDomainGroupName(did) });
79
+ return BaseState.renameIdFiledName(result);
80
+ }
81
+
82
+ async getBlockletDomains(did) {
83
+ const site = await this.findOneByBlocklet(did);
84
+ return site.domainAliases.map((x) => x.value).filter(Boolean);
85
+ }
75
86
  }
76
87
 
77
88
  module.exports = SiteState;
@@ -71,7 +71,6 @@ const { validate: validateEngine, get: getEngine } = require('../blocklet/manage
71
71
 
72
72
  const isRequirementsSatisfied = require('./requirement');
73
73
  const { getDidDomainForBlocklet } = require('./get-domain-for-blocklet');
74
- const { getBlockletDomainGroupName } = require('./router');
75
74
  const { isBeforeInstalled, expandBundle, findInterfacePortByName, validateBlockletMeta } = require('./index');
76
75
 
77
76
  const getComponentConfig = (meta) => meta.components || meta.children;
@@ -1332,9 +1331,7 @@ const getBlocklet = async ({
1332
1331
  blocklet.settings = settings || {};
1333
1332
 
1334
1333
  // app site
1335
- const sites = await states.site.getSites();
1336
- const domain = getBlockletDomainGroupName(blocklet.meta.did);
1337
- blocklet.site = (sites || []).find((x) => x.domain === domain);
1334
+ blocklet.site = await states.site.findOneByBlocklet(blocklet.meta.did);
1338
1335
 
1339
1336
  await forEachBlocklet(blocklet, async (component, { id, level, ancestors }) => {
1340
1337
  // component env
@@ -2,34 +2,48 @@ const https = require('https');
2
2
  const { EventEmitter } = require('events');
3
3
  const logger = require('@abtnode/logger')('@abtnode/domain-status');
4
4
  const { EVENTS, WELLKNOWN_PING_PREFIX } = require('@abtnode/constant');
5
+ const { BlockletEvents } = require('@blocklet/constant');
5
6
  const { checkDomainDNS } = require('./index');
6
7
 
7
8
  const dnsStatusStore = Object.create(null);
8
9
 
9
- const checkDomainDnsWrapper = async (domain) => {
10
- // 正在执行,并且离上次的执行时间小于 2 分钟则不请求
11
- if (dnsStatusStore[domain] && Date.now() - dnsStatusStore[domain] < 2 * 60 * 1000) {
12
- return {};
13
- }
14
-
10
+ const doCheckDomainDnsWrapper = async (domain) => {
15
11
  try {
16
- dnsStatusStore[domain] = Date.now();
17
12
  const status = await checkDomainDNS(domain);
18
13
  return status;
19
14
  } catch (error) {
20
15
  logger.error('check domain dns error', { domain, error });
21
16
  throw error;
22
17
  } finally {
23
- delete dnsStatusStore[domain];
24
18
  logger.debug('removed dns flag', { domain });
25
19
  }
26
20
  };
27
21
 
22
+ const checkDomainDnsWrapper = (domain) => {
23
+ // 正在执行或已成功,并且离上次的执行时间小于 2 分钟则不请求
24
+ if (dnsStatusStore[domain] && Date.now() - dnsStatusStore[domain].startAt < 2 * 60 * 1000) {
25
+ return dnsStatusStore[domain].promise;
26
+ }
27
+
28
+ const promise = doCheckDomainDnsWrapper(domain);
29
+ dnsStatusStore[domain] = {
30
+ promise,
31
+ startAt: Date.now(),
32
+ };
33
+
34
+ promise.catch(() => {
35
+ delete dnsStatusStore[domain];
36
+ });
37
+
38
+ return promise;
39
+ };
40
+
28
41
  class DomainStatus extends EventEmitter {
29
- constructor(routerManager) {
42
+ constructor({ routerManager, states }) {
30
43
  super();
31
44
 
32
45
  this.routerManager = routerManager;
46
+ this.states = states;
33
47
  }
34
48
 
35
49
  async getHttpsCert(domain) {
@@ -74,15 +88,26 @@ class DomainStatus extends EventEmitter {
74
88
  });
75
89
  }
76
90
 
77
- checkDomainsStatus({ domains } = {}) {
91
+ async checkDomainsStatus({ domains, did } = {}) {
92
+ if (did) {
93
+ // eslint-disable-next-line no-param-reassign
94
+ domains = await this.states.site.getBlockletDomains(did);
95
+ }
96
+
78
97
  (domains || []).forEach((domain) => {
79
98
  Promise.all([this.getHttpsCert(domain), checkDomainDnsWrapper(domain)])
80
- .then((data) => {
81
- const [matchedCert, dns] = data;
82
- this.emit(EVENTS.DOMAIN_STATUS, { domain, matchedCert, isHttps: !!matchedCert, dns });
99
+ .then(([matchedCert, dns]) => {
100
+ const eventData = { domain, matchedCert, isHttps: !!matchedCert, dns };
101
+
102
+ if (did) {
103
+ eventData.meta = { did };
104
+ this.emit(BlockletEvents.domainStatus, eventData);
105
+ } else {
106
+ this.emit(EVENTS.DOMAIN_STATUS, eventData);
107
+ }
83
108
  })
84
109
  .catch((error) => {
85
- logger.error('check domain status error', { domain, error });
110
+ logger.error('check domain status error', { domain, error, did });
86
111
  });
87
112
  });
88
113
 
package/lib/util/index.js CHANGED
@@ -6,7 +6,6 @@ const unzipper = require('unzipper');
6
6
  const crypto = require('crypto');
7
7
  const shell = require('shelljs');
8
8
  const get = require('lodash/get');
9
- const uniqBy = require('lodash/uniqBy');
10
9
  const pickBy = require('lodash/pickBy');
11
10
  const { isFromPublicKey } = require('@arcblock/did');
12
11
  const joinUrl = require('url-join');
@@ -17,7 +16,7 @@ const normalizePathPrefix = require('@abtnode/util/lib/normalize-path-prefix');
17
16
  const axios = require('@abtnode/util/lib/axios');
18
17
  const parseBlockletMeta = require('@blocklet/meta/lib/parse');
19
18
  const { validateMeta, fixAndValidateService } = require('@blocklet/meta/lib/validate');
20
- const { BlockletStatus, BLOCKLET_INTERFACE_WELLKNOWN } = require('@blocklet/constant');
19
+ const { BlockletStatus } = require('@blocklet/constant');
21
20
  const { replaceSlotToIp } = require('@blocklet/meta/lib/util');
22
21
  const {
23
22
  StatusCode,
@@ -26,10 +25,7 @@ const {
26
25
  DOMAIN_FOR_IP_SITE_REGEXP,
27
26
  DEFAULT_HTTP_PORT,
28
27
  DEFAULT_HTTPS_PORT,
29
- ROUTING_RULE_TYPES,
30
28
  SLOT_FOR_IP_DNS_SITE,
31
- DEFAULT_IP_DOMAIN_SUFFIX,
32
- BLOCKLET_SITE_GROUP_SUFFIX,
33
29
  } = require('@abtnode/constant');
34
30
 
35
31
  const DEFAULT_WELLKNOWN_PORT = 8088;
@@ -50,22 +46,6 @@ const fromStatus = (v) => {
50
46
  return match ? match[0] : 'unknown';
51
47
  };
52
48
 
53
- const getInterfaceUrl = ({ baseUrl, url }) => {
54
- if (!url) {
55
- return '';
56
- }
57
-
58
- if (url.startsWith('https://') || url.startsWith('http://')) {
59
- return url;
60
- }
61
-
62
- const parsed = new URL(joinUrl(baseUrl, url));
63
-
64
- return parsed.href;
65
- };
66
-
67
- const trimSlash = (str = '') => str.replace(/^\/+/, '').replace(/\/+$/, '');
68
-
69
49
  const replaceDomainSlot = ({ domain, context = {}, nodeIp }) => {
70
50
  let processed = domain;
71
51
  if (processed.includes(SLOT_FOR_IP_DNS_SITE)) {
@@ -110,71 +90,6 @@ const getBlockletHost = ({ domain, context, nodeIp }) => {
110
90
  return `${tmpDomain}:${port}`;
111
91
  };
112
92
 
113
- const getBlockletBaseUrls = ({ rules = [], context = {}, nodeIp }) => {
114
- if (!Array.isArray(rules) || !rules.length) {
115
- return [];
116
- }
117
-
118
- return rules
119
- .map((rule) => {
120
- const host = getBlockletHost({ domain: rule.from.domain, context, nodeIp });
121
- if (host) {
122
- let protocol = 'http'; // TODO: 这里固定为 http, 因为判断 url 是不是 https 和证书相关,这里实现的话比较复杂
123
- if (host.includes(DEFAULT_IP_DOMAIN_SUFFIX)) {
124
- protocol = 'https';
125
- }
126
-
127
- return {
128
- ruleId: rule.id,
129
- baseUrl: `${protocol}://${host}/${trimSlash(rule.from.pathPrefix)}`,
130
- interfaceName: get(rule, 'to.interfaceName', ''),
131
- };
132
- }
133
-
134
- return null;
135
- })
136
- .filter(Boolean);
137
- };
138
-
139
- const getBlockletInterfaces = ({ blocklet, context, routingRules, nodeIp }) => {
140
- const interfaces = [];
141
- (blocklet.meta.interfaces || [])
142
- .filter((x) => !get(x, 'port.external'))
143
- .forEach((x) => {
144
- // Otherwise, the url is composed with routing rules
145
- const baseUrls = getBlockletBaseUrls({
146
- rules: (routingRules || []).filter((r) => {
147
- return (
148
- // don't show group domain
149
- !(r.from.domain || '').endsWith(BLOCKLET_SITE_GROUP_SUFFIX) &&
150
- // don't show wellknown interface
151
- r.to.type !== ROUTING_RULE_TYPES.GENERAL_PROXY &&
152
- // LEGACY don't show wellknown interface
153
- r.to.interfaceName !== BLOCKLET_INTERFACE_WELLKNOWN &&
154
- // don't show child blocklet interface
155
- (!r.from.groupPathPrefix || r.from.pathPrefix === r.from.groupPathPrefix)
156
- );
157
- }),
158
- context,
159
- nodeIp,
160
- });
161
-
162
- baseUrls.forEach(({ baseUrl, ruleId, interfaceName }) => {
163
- if (interfaceName && interfaceName !== x.name) {
164
- return;
165
- }
166
- interfaces.push({
167
- ruleId,
168
- type: x.type,
169
- name: x.name,
170
- url: getInterfaceUrl({ baseUrl, url: '/' }),
171
- });
172
- });
173
- });
174
-
175
- return uniqBy(interfaces, 'url');
176
- };
177
-
178
93
  const isRoutingEnabled = (routing) => !!routing && !!routing.provider;
179
94
 
180
95
  const isInProgress = (status) =>
@@ -487,15 +402,11 @@ const lib = {
487
402
  formatEnvironments,
488
403
  isInProgress,
489
404
  isBeforeInstalled,
490
- getInterfaceUrl,
491
- getBlockletBaseUrls,
492
405
  replaceDomainSlot,
493
406
  getBlockletHost,
494
- getBlockletInterfaces,
495
407
  isRoutingEnabled,
496
408
  checkDomainDNS,
497
409
  asyncExec,
498
- trimSlash,
499
410
  isCLI,
500
411
  getHttpsCertInfo,
501
412
  ensureDataDirs,
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.8.32",
6
+ "version": "1.8.34",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,32 +19,32 @@
19
19
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "@abtnode/auth": "1.8.32",
23
- "@abtnode/certificate-manager": "1.8.32",
24
- "@abtnode/constant": "1.8.32",
25
- "@abtnode/cron": "1.8.32",
26
- "@abtnode/db": "1.8.32",
27
- "@abtnode/logger": "1.8.32",
28
- "@abtnode/queue": "1.8.32",
29
- "@abtnode/rbac": "1.8.32",
30
- "@abtnode/router-provider": "1.8.32",
31
- "@abtnode/static-server": "1.8.32",
32
- "@abtnode/timemachine": "1.8.32",
33
- "@abtnode/util": "1.8.32",
34
- "@arcblock/did": "1.18.1",
22
+ "@abtnode/auth": "1.8.34",
23
+ "@abtnode/certificate-manager": "1.8.34",
24
+ "@abtnode/constant": "1.8.34",
25
+ "@abtnode/cron": "1.8.34",
26
+ "@abtnode/db": "1.8.34",
27
+ "@abtnode/logger": "1.8.34",
28
+ "@abtnode/queue": "1.8.34",
29
+ "@abtnode/rbac": "1.8.34",
30
+ "@abtnode/router-provider": "1.8.34",
31
+ "@abtnode/static-server": "1.8.34",
32
+ "@abtnode/timemachine": "1.8.34",
33
+ "@abtnode/util": "1.8.34",
34
+ "@arcblock/did": "1.18.13",
35
35
  "@arcblock/did-motif": "^1.1.10",
36
- "@arcblock/did-util": "1.18.1",
37
- "@arcblock/event-hub": "1.18.1",
38
- "@arcblock/jwt": "^1.18.1",
36
+ "@arcblock/did-util": "1.18.13",
37
+ "@arcblock/event-hub": "1.18.13",
38
+ "@arcblock/jwt": "^1.18.13",
39
39
  "@arcblock/pm2-events": "^0.0.5",
40
- "@arcblock/vc": "1.18.1",
41
- "@blocklet/constant": "1.8.32",
42
- "@blocklet/meta": "1.8.32",
43
- "@blocklet/sdk": "1.8.32",
40
+ "@arcblock/vc": "1.18.13",
41
+ "@blocklet/constant": "1.8.34",
42
+ "@blocklet/meta": "1.8.34",
43
+ "@blocklet/sdk": "1.8.34",
44
44
  "@fidm/x509": "^1.2.1",
45
- "@ocap/mcrypto": "1.18.1",
46
- "@ocap/util": "1.18.1",
47
- "@ocap/wallet": "1.18.1",
45
+ "@ocap/mcrypto": "1.18.13",
46
+ "@ocap/util": "1.18.13",
47
+ "@ocap/wallet": "1.18.13",
48
48
  "@slack/webhook": "^5.0.4",
49
49
  "axios": "^0.27.2",
50
50
  "axon": "^2.0.3",
@@ -72,6 +72,7 @@
72
72
  "tar": "^6.1.11",
73
73
  "ua-parser-js": "^1.0.2",
74
74
  "unzipper": "^0.10.11",
75
+ "url-http": "^1.0.7",
75
76
  "url-join": "^4.0.1",
76
77
  "uuid": "7.0.3"
77
78
  },
@@ -81,5 +82,5 @@
81
82
  "express": "^4.18.2",
82
83
  "jest": "^27.5.1"
83
84
  },
84
- "gitHead": "8502244aeda5926b3433c1dd9142e63233e3c23c"
85
+ "gitHead": "c5fbb8e57493db62f212217cfde1980c82f00297"
85
86
  }