@abtnode/core 1.7.6 → 1.7.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/api/team.js CHANGED
@@ -104,6 +104,19 @@ class TeamAPI extends EventEmitter {
104
104
  return state.getUser(user.did);
105
105
  }
106
106
 
107
+ async getOwner({ teamDid }) {
108
+ const owner = await this.teamManager.getOwner(teamDid);
109
+
110
+ if (!owner) {
111
+ return null;
112
+ }
113
+
114
+ const state = await this.getUserState(teamDid);
115
+
116
+ const full = await state.getUser(owner.did);
117
+ return full || owner;
118
+ }
119
+
107
120
  async updateUser({ teamDid, user }) {
108
121
  const state = await this.getUserState(teamDid);
109
122
 
@@ -211,7 +224,7 @@ class TeamAPI extends EventEmitter {
211
224
 
212
225
  // Invite member
213
226
 
214
- async createInvitation({ teamDid, role, remark, interfaceName }, context) {
227
+ async createInvitation({ teamDid, role, remark }, context) {
215
228
  await this.teamManager.checkEnablePassportIssuance(teamDid);
216
229
 
217
230
  if (!role) {
@@ -242,7 +255,6 @@ class TeamAPI extends EventEmitter {
242
255
  expireDate,
243
256
  inviter: user,
244
257
  teamDid,
245
- interfaceName,
246
258
  });
247
259
 
248
260
  logger.info('Create invite member', { role, user, inviteId });
@@ -254,7 +266,6 @@ class TeamAPI extends EventEmitter {
254
266
  expireDate: new Date(expireDate).toString(),
255
267
  inviter: user,
256
268
  teamDid,
257
- interfaceName,
258
269
  };
259
270
  }
260
271
 
@@ -271,7 +282,6 @@ class TeamAPI extends EventEmitter {
271
282
  expireDate: new Date(d.expireDate).toString(),
272
283
  inviter: d.inviter,
273
284
  teamDid: d.teamDid,
274
- interfaceName: d.interfaceName,
275
285
  }));
276
286
  }
277
287
 
@@ -15,7 +15,7 @@ const { isValid: isValidDid } = require('@arcblock/did');
15
15
  const { verifyPresentation } = require('@arcblock/vc');
16
16
  const { toBase58, isHex } = require('@ocap/util');
17
17
  const { fromSecretKey } = require('@ocap/wallet');
18
- const { toPng: createDidLogo } =
18
+ const { toSvg: createDidLogo } =
19
19
  process.env.NODE_ENV !== 'test' ? require('@arcblock/did-motif') : require('@arcblock/did-motif/dist/did-motif.cjs');
20
20
 
21
21
  const logger = require('@abtnode/logger')('@abtnode/core:blocklet:manager');
@@ -104,6 +104,7 @@ const blockletPm2Events = require('./pm2-events');
104
104
  const { getFactoryState } = require('../../util/chain');
105
105
  const runMigrationScripts = require('../migration');
106
106
  const hooks = require('../hooks');
107
+ const { formatName } = require('../../util/get-domain-for-blocklet');
107
108
 
108
109
  const {
109
110
  isInProgress,
@@ -113,6 +114,7 @@ const {
113
114
  shouldUpdateBlockletStatus,
114
115
  getBlockletMeta,
115
116
  validateBlockletMeta,
117
+ validateOwner,
116
118
  } = util;
117
119
 
118
120
  const preDownloadLock = new Lock('pre-download-lock');
@@ -255,7 +257,7 @@ class BlockletManager extends BaseBlockletManager {
255
257
  }
256
258
 
257
259
  const blocklet = await states.blocklet.getBlocklet(meta.did);
258
- const isRunning = blocklet?.status === BlockletStatus.running;
260
+ const isRunning = blocklet ? blocklet.status === BlockletStatus.running : false;
259
261
 
260
262
  return { meta, isFree, isInstalled: !!blocklet, isRunning };
261
263
  }
@@ -279,9 +281,9 @@ class BlockletManager extends BaseBlockletManager {
279
281
  return this._installFromStore({ did, registry }, { ...context, blockletPurchaseVerified: true });
280
282
  }
281
283
 
282
- async start({ did, checkHealthImmediately = false, throwOnError }, context) {
284
+ async start({ did, throwOnError, checkHealthImmediately = false, e2eMode = false }, context) {
283
285
  logger.info('start blocklet', { did });
284
- const blocklet = await this.ensureBlocklet(did);
286
+ const blocklet = await this.ensureBlocklet(did, e2eMode);
285
287
 
286
288
  try {
287
289
  if (!hasRunnableComponent(blocklet)) {
@@ -319,6 +321,7 @@ class BlockletManager extends BaseBlockletManager {
319
321
  }),
320
322
  nodeEnvironments,
321
323
  nodeInfo: await states.node.read(),
324
+ e2eMode,
322
325
  });
323
326
 
324
327
  // check blocklet healthy
@@ -481,6 +484,40 @@ class BlockletManager extends BaseBlockletManager {
481
484
  }
482
485
  }
483
486
 
487
+ async reset({ did }, context = {}) {
488
+ logger.info('reset blocklet', { did });
489
+
490
+ const blocklet = await this.ensureBlocklet(did);
491
+
492
+ if (isInProgress(blocklet.status)) {
493
+ throw new Error('Cannot reset when blocklet is in progress');
494
+ }
495
+
496
+ try {
497
+ await this.deleteProcess({ did }, context);
498
+ } catch {
499
+ // do nothing
500
+ }
501
+
502
+ // Cleanup disk storage
503
+ const { name } = blocklet.meta;
504
+ const dataDir = path.join(this.dataDirs.data, name);
505
+ const logsDir = path.join(this.dataDirs.logs, name);
506
+ const cacheDir = path.join(this.dataDirs.cache, name);
507
+ fs.removeSync(cacheDir);
508
+ fs.removeSync(dataDir);
509
+ fs.removeSync(logsDir);
510
+
511
+ // Reset config in db
512
+ await this._delExtras(did);
513
+ await this._setConfigs(did);
514
+ await this.updateBlockletEnvironment(did);
515
+ await this.resetSiteByDid(did, context);
516
+
517
+ logger.info('blocklet reset', { did });
518
+ return blocklet;
519
+ }
520
+
484
521
  async deleteComponent({ did, rootDid }, context) {
485
522
  logger.info('delete blocklet component', { did, rootDid });
486
523
 
@@ -928,14 +965,22 @@ class BlockletManager extends BaseBlockletManager {
928
965
  * After the dev function finished, the caller should send a BlockletEvents.deployed event to the daemon
929
966
  * @returns {Object} blocklet
930
967
  */
931
- async dev(folder) {
932
- logger.info('dev blocklet', { folder });
968
+ async dev(folder, { rootDid, mountPoint } = {}) {
969
+ logger.info('dev component', { folder, rootDid, mountPoint });
933
970
 
934
971
  const meta = getBlockletMeta(folder);
935
972
  if (meta.group !== 'static' && (!meta.scripts || !meta.scripts.dev)) {
936
973
  throw new Error('Incorrect blocklet manifest: missing `scripts.dev` field');
937
974
  }
938
975
 
976
+ if (rootDid) {
977
+ return this._devComponent({ folder, meta, rootDid, mountPoint });
978
+ }
979
+
980
+ return this._devBlocklet({ folder, meta });
981
+ }
982
+
983
+ async _devBlocklet({ folder, meta }) {
939
984
  const { did, version } = meta;
940
985
 
941
986
  const exist = await states.blocklet.getBlocklet(did);
@@ -985,10 +1030,63 @@ class BlockletManager extends BaseBlockletManager {
985
1030
 
986
1031
  const blocklet = await this.ensureBlocklet(did);
987
1032
 
1033
+ await fs.writeFile(path.join(blocklet.env.dataDir, 'logo.svg'), createDidLogo(blocklet.meta.did));
1034
+
988
1035
  return blocklet;
989
1036
  }
990
1037
 
991
- async ensureBlocklet(did) {
1038
+ async _devComponent({ folder, meta, rootDid, mountPoint }) {
1039
+ const { did, version } = meta;
1040
+
1041
+ const existRoot = await states.blocklet.getBlocklet(rootDid);
1042
+ if (!existRoot) {
1043
+ throw new Error('Root blocklet does not exist');
1044
+ }
1045
+
1046
+ const exist = existRoot.children.find((x) => x.meta.did === meta.did);
1047
+ if (exist) {
1048
+ if (exist.mode === BLOCKLET_MODES.PRODUCTION) {
1049
+ throw new Error('The blocklet component of production mode already exists, please remove it before developing');
1050
+ }
1051
+
1052
+ const status = fromBlockletStatus(exist.status);
1053
+ if (['starting', 'running'].includes(status)) {
1054
+ throw new Error(`The blocklet component is already on ${status}, please stop it before developing`);
1055
+ }
1056
+
1057
+ logger.info('remove blocklet component for dev', { did, version });
1058
+
1059
+ await this.deleteComponent({ did, rootDid });
1060
+ }
1061
+
1062
+ const defaultPath = formatName(meta.name);
1063
+ const children = await parseChildren(existRoot.meta, {
1064
+ children: [
1065
+ {
1066
+ meta,
1067
+ mountPoint: mountPoint || `/${defaultPath}`,
1068
+ source: BlockletSource.local,
1069
+ deployedFrom: folder,
1070
+ status: BlockletStatus.installed,
1071
+ mode: BLOCKLET_MODES.DEVELOPMENT,
1072
+ },
1073
+ ],
1074
+ dynamic: true,
1075
+ });
1076
+ await states.blocklet.addChildren(rootDid, children);
1077
+
1078
+ logger.info('add blocklet component for dev', { did, version, meta });
1079
+
1080
+ // Add environments
1081
+ await this._setConfigs(rootDid);
1082
+ await this.updateBlockletEnvironment(rootDid);
1083
+
1084
+ const rootBlocklet = await this.ensureBlocklet(rootDid);
1085
+
1086
+ return rootBlocklet;
1087
+ }
1088
+
1089
+ async ensureBlocklet(did, e2eMode = false) {
992
1090
  if (!isValidDid(did)) {
993
1091
  throw new Error(`Blocklet did is invalid: ${did}`);
994
1092
  }
@@ -1006,6 +1104,7 @@ class BlockletManager extends BaseBlockletManager {
1006
1104
  ...getBlockletDirs(blocklet, {
1007
1105
  dataDirs: this.dataDirs,
1008
1106
  ensure: true,
1107
+ e2eMode,
1009
1108
  }),
1010
1109
  };
1011
1110
 
@@ -1049,9 +1148,14 @@ class BlockletManager extends BaseBlockletManager {
1049
1148
  return blocklet;
1050
1149
  }
1051
1150
 
1052
- async setInitialized({ did }) {
1151
+ async setInitialized({ did, owner }) {
1152
+ if (!validateOwner(owner)) {
1153
+ throw new Error('Blocklet owner is invalid');
1154
+ }
1155
+
1053
1156
  const blocklet = await states.blocklet.getBlocklet(did);
1054
- await states.blockletExtras.setSettings(blocklet.meta.did, { initialized: true });
1157
+ await states.blockletExtras.setSettings(blocklet.meta.did, { initialized: true, owner });
1158
+ logger.info('Blocklet initialized', { did, owner });
1055
1159
 
1056
1160
  this.emit(BlockletEvents.updated, { meta: { did: blocklet.meta.did } });
1057
1161
 
@@ -1734,7 +1838,7 @@ class BlockletManager extends BaseBlockletManager {
1734
1838
  meta,
1735
1839
  mountPoint,
1736
1840
  source: BlockletSource.upload,
1737
- deployedFrom: `Upload by ${context.user.did}`,
1841
+ deployedFrom: `Upload by ${context.user.fullName}`,
1738
1842
  sourceUrl: '',
1739
1843
  dynamic: true,
1740
1844
  };
@@ -2216,7 +2320,7 @@ class BlockletManager extends BaseBlockletManager {
2216
2320
  blocklet = await this.ensureBlocklet(did);
2217
2321
  logger.info('blocklet installed', { source, did: meta.did });
2218
2322
 
2219
- await fs.writeFile(path.join(blocklet.env.dataDir, 'logo.png'), createDidLogo(blocklet.meta.did));
2323
+ await fs.writeFile(path.join(blocklet.env.dataDir, 'logo.svg'), createDidLogo(blocklet.meta.did));
2220
2324
 
2221
2325
  this.emit(BlockletEvents.installed, { blocklet, context });
2222
2326
 
@@ -2344,7 +2448,7 @@ class BlockletManager extends BaseBlockletManager {
2344
2448
 
2345
2449
  blocklet = await this.ensureBlocklet(did, context);
2346
2450
 
2347
- await fs.writeFile(path.join(blocklet.env.dataDir, 'logo.png'), createDidLogo(blocklet.meta.did));
2451
+ await fs.writeFile(path.join(blocklet.env.dataDir, 'logo.svg'), createDidLogo(blocklet.meta.did));
2348
2452
 
2349
2453
  this.refreshListCache();
2350
2454
 
@@ -21,6 +21,7 @@ async function runScripts({
21
21
  printSuccess,
22
22
  printError,
23
23
  }) {
24
+ // 获取所有待执行的脚本
24
25
  let scripts = [];
25
26
  try {
26
27
  scripts = await getScripts(scriptsDir);
@@ -37,13 +38,17 @@ async function runScripts({
37
38
  }
38
39
 
39
40
  printInfo('pending scripts', pendingScripts);
41
+ // 执行脚本前需要对数据库文件做一次备份
40
42
  try {
41
43
  await doBackup({ dbDir, backupDir, printInfo, printSuccess, printError });
42
44
  } catch (err) {
43
45
  printError(`Failed to backup state db due to ${err.message}, abort!`);
46
+ // 备份失败时,需要移除备份目录
47
+ fs.removeSync(backupDir);
44
48
  throw err;
45
49
  }
46
50
 
51
+ // 按照顺序依次执行 migration 脚本
47
52
  for (let i = 0; i < pendingScripts.length; i++) {
48
53
  const { script: scriptPath } = pendingScripts[i];
49
54
  try {
@@ -59,7 +64,10 @@ async function runScripts({
59
64
 
60
65
  try {
61
66
  await doRestore({ dbDir, backupDir, printInfo, printSuccess, printError });
67
+ // 恢复备份成功时,需要移除备份目录
68
+ fs.removeSync(backupDir);
62
69
  } catch (restoreErr) {
70
+ // 如果恢复备份失败,则保留备份目录,恢复数据
63
71
  printError(`Failed to restore state db due to: ${restoreErr.message}`);
64
72
  }
65
73
 
package/lib/event.js CHANGED
@@ -30,6 +30,8 @@ module.exports = ({
30
30
  const nodeState = states.node;
31
31
 
32
32
  const events = new EventEmitter();
33
+ events.setMaxListeners(0);
34
+
33
35
  // HACK: do not emit any events from CLI
34
36
  if (isCLI() && process.env.NODE_ENV !== 'test') {
35
37
  events.emit = (name) => logger.debug('stopped core state event in CLI', name);
@@ -123,6 +125,14 @@ module.exports = ({
123
125
  await teamAPI.refreshBlockletInterfacePermissions(blocklet.meta);
124
126
  } catch (error) {
125
127
  logger.error('upgrade blocklet routing rules error', { event: name, error });
128
+ notificationState.create({
129
+ title: 'Blocklet URL Mapping Error',
130
+ // eslint-disable-next-line max-len
131
+ description: `Failed to upgrade URL mapping for blocklet ${blocklet.meta.name}@${blocklet.meta.version}, due to: ${error.message}`,
132
+ entityType: 'blocklet',
133
+ entityId: blocklet.meta.did,
134
+ severity: 'error',
135
+ });
126
136
  }
127
137
 
128
138
  try {
package/lib/index.js CHANGED
@@ -133,11 +133,13 @@ function ABTNode(options) {
133
133
  registry: blockletRegistry,
134
134
  daemon: options.daemon,
135
135
  });
136
+ blockletManager.setMaxListeners(0);
136
137
 
137
138
  const {
138
139
  handleRouting,
139
140
  getRoutingRulesByDid,
140
141
  getSiteByDid,
142
+ resetSiteByDid,
141
143
  updateNodeRouting,
142
144
  takeRoutingSnapshot,
143
145
  getRoutingSites,
@@ -159,6 +161,7 @@ function ABTNode(options) {
159
161
 
160
162
  blockletManager.getRoutingRulesByDid = getRoutingRulesByDid;
161
163
  blockletManager.getSiteByDid = getSiteByDid;
164
+ blockletManager.resetSiteByDid = resetSiteByDid;
162
165
 
163
166
  // Generate an on node ready callback
164
167
  const onStatesReady = createStateReadyQueue({ states, options, dataDirs });
@@ -216,6 +219,7 @@ function ABTNode(options) {
216
219
  updateChildBlocklets: blockletManager.updateChildren.bind(blockletManager),
217
220
  getLatestBlockletVersion: blockletManager.getLatestBlockletVersion.bind(blockletManager),
218
221
  getBlockletMetaFromUrl: blockletManager.getMetaFromUrl.bind(blockletManager),
222
+ resetBlocklet: blockletManager.reset.bind(blockletManager),
219
223
 
220
224
  deleteBlockletProcess: blockletManager.deleteProcess.bind(blockletManager),
221
225
 
@@ -261,6 +265,7 @@ function ABTNode(options) {
261
265
  getUsers: teamAPI.getUsers.bind(teamAPI),
262
266
  getUsersCount: teamAPI.getUsersCount.bind(teamAPI),
263
267
  getUser: teamAPI.getUser.bind(teamAPI),
268
+ getOwner: teamAPI.getOwner.bind(teamAPI),
264
269
  getNodeUsers: () => teamAPI.getUsers({ teamDid: options.nodeDid }),
265
270
  getNodeUser: (user) => teamAPI.getUser({ teamDid: options.nodeDid, user }),
266
271
  addUser: teamAPI.addUser.bind(teamAPI),
@@ -7,7 +7,7 @@ module.exports = async ({ states, config, configFile, printInfo }) => {
7
7
  printInfo('Try to update node config to 1.0.21...');
8
8
  let changed = false;
9
9
 
10
- const rawConfig = yaml.safeLoad(fs.readFileSync(configFile).toString());
10
+ const rawConfig = yaml.load(fs.readFileSync(configFile).toString());
11
11
  const info = await states.node.read();
12
12
 
13
13
  const updates = [
@@ -13,7 +13,7 @@ module.exports = async ({ states, config, configFile, printInfo }) => {
13
13
  printInfo('Try to update node config to 1.0.22...');
14
14
  let changed = false;
15
15
 
16
- const rawConfig = yaml.safeLoad(fs.readFileSync(configFile).toString());
16
+ const rawConfig = yaml.load(fs.readFileSync(configFile).toString());
17
17
  const info = await states.node.read();
18
18
 
19
19
  const updates = [
@@ -10,7 +10,7 @@ module.exports = async ({ states, config, configFile, printInfo }) => {
10
10
  printInfo('Try to update node config to 1.0.25...');
11
11
  let changed = false;
12
12
 
13
- const rawConfig = yaml.safeLoad(fs.readFileSync(configFile).toString());
13
+ const rawConfig = yaml.load(fs.readFileSync(configFile).toString());
14
14
  const info = await states.node.read();
15
15
 
16
16
  const updates = [
@@ -7,7 +7,7 @@ module.exports = async ({ states, config, configFile, printInfo }) => {
7
7
  printInfo('Try to update node config to 1.0.32...');
8
8
  let changed = false;
9
9
 
10
- const rawConfig = yaml.safeLoad(fs.readFileSync(configFile).toString());
10
+ const rawConfig = yaml.load(fs.readFileSync(configFile).toString());
11
11
  const info = await states.node.read();
12
12
 
13
13
  const updates = [{ key: 'routing.https', value: true }];
@@ -22,7 +22,7 @@ module.exports = async ({ states, printInfo, configFile }) => {
22
22
  await states.node.updateNodeInfo(info);
23
23
 
24
24
  if (process.env.NODE_ENV !== 'development') {
25
- let rawConfig = yaml.safeLoad(fs.readFileSync(configFile).toString());
25
+ let rawConfig = yaml.load(fs.readFileSync(configFile).toString());
26
26
  set(rawConfig, 'node.routing.ipWildcardDomain', info.routing.ipWildcardDomain);
27
27
  set(rawConfig, 'node.routing.wildcardCertHost', DEFAULT_WILDCARD_CERT_HOST);
28
28
  set(rawConfig, 'node.didDomain', DEFAULT_DID_DOMAIN);
@@ -19,7 +19,7 @@ module.exports = async ({ states, configFile, dataDir }) => {
19
19
  try {
20
20
  fs.writeFileSync(file, crypto.randomBytes(32), { encoding: 'binary', mode: '0600' });
21
21
 
22
- const config = yaml.safeLoad(fs.readFileSync(configFile).toString(), { json: true });
22
+ const config = yaml.load(fs.readFileSync(configFile).toString(), { json: true });
23
23
  config.node.sk = security.encrypt(config.node.sk, config.node.did, fs.readFileSync(file));
24
24
  fs.writeFileSync(configFile, yaml.dump(config));
25
25
  await states.node.updateNodeInfo({ sk: config.node.sk });
@@ -41,7 +41,7 @@ module.exports = async ({ states, config, configFile, printInfo }) => {
41
41
  printInfo('Try to update node config to 1.0.21...');
42
42
  let changed = false;
43
43
 
44
- const rawConfig = yaml.safeLoad(fs.readFileSync(configFile).toString());
44
+ const rawConfig = yaml.load(fs.readFileSync(configFile).toString());
45
45
  const info = await states.node.read();
46
46
 
47
47
  const updates = [
@@ -863,88 +863,6 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
863
863
  return changes.some(Boolean);
864
864
  };
865
865
 
866
- /**
867
- * Add system routing rules for blocklet in dashboard site
868
- *
869
- * @returns {boolean} if routing changed
870
- * TODO: do we still need this?
871
- */
872
- const _ensureBlockletRulesForDashboardSite = async (blocklet, sites, nodeInfo, context = {}) => {
873
- // blocklet level duplication detection
874
- const findRulesByInterface = (site, value) =>
875
- site.rules.filter((x) => x.isProtected && x.to.did === blocklet.meta.did && get(x, 'to.interfaceName') === value);
876
-
877
- const ipSite = sites.find((x) => x.domain === DOMAIN_FOR_IP_SITE);
878
- if (!ipSite) {
879
- logger.warn(`Routing rule for dashboard not found, abort on ensure rules for blocklet ${blocklet.meta.did}`);
880
- return false;
881
- }
882
-
883
- // If we have rule for legacy path prefix, just return
884
- const pathPrefixLegacy = normalizePathPrefix(`/${nodeInfo.routing.adminPath}/${blocklet.meta.name}`);
885
- if (hasRuleByPrefix(ipSite, pathPrefixLegacy)) {
886
- return false;
887
- }
888
-
889
- const removedRuleIds = [];
890
- const changes = await Promise.all(
891
- blocklet.meta.interfaces.map(async (x) => {
892
- let changed = false; // if state db was mutated
893
- let pathPrefix = '';
894
- if (x.prefix === BLOCKLET_DYNAMIC_PATH_PREFIX) {
895
- // pathPrefix for dynamic path: `/{adminPath}/{blockletName}/{interfaceName}`
896
- pathPrefix = normalizePathPrefix(`/${pathPrefixLegacy}/${x.name}`);
897
- } else {
898
- // pathPrefix for fixed path: `/{interfacePrefix}`
899
- pathPrefix = normalizePathPrefix(x.prefix);
900
- }
901
-
902
- // Remove if we have rule with same interface
903
- const exists = findRulesByInterface(ipSite, x.name);
904
- if (exists.length) {
905
- // Note: we need to keep a list of removed rules since we might remove multiple rules in the loop
906
- exists.forEach((e) => removedRuleIds.push(e.id));
907
- await states.site.update(
908
- { _id: ipSite.id },
909
- { $set: { rules: ipSite.rules.filter((r) => removedRuleIds.includes(r.id) === false) } }
910
- );
911
- changed = true;
912
- } else if (hasRuleByPrefix(ipSite, pathPrefix)) {
913
- // Skip same pathPrefix rules
914
- return changed;
915
- }
916
-
917
- // 不在 dashboard site 中添加 path 和 prefix 都是根路径(/) 的路由
918
- if (x.path === '/' && x.prefix === '/') {
919
- return changed;
920
- }
921
-
922
- await routerManager.addRoutingRule(
923
- {
924
- id: ipSite.id,
925
- rule: {
926
- from: { pathPrefix },
927
- to: {
928
- type: ROUTING_RULE_TYPES.BLOCKLET,
929
- port: findInterfacePortByName(blocklet, x.name),
930
- did: blocklet.meta.did, // root blocklet did
931
- interfaceName: x.name, // root blocklet interface
932
- },
933
- isProtected: true,
934
- },
935
- skipCheckDynamicBlacklist: true,
936
- },
937
- context
938
- );
939
- changed = true;
940
-
941
- return changed;
942
- })
943
- );
944
-
945
- return changes.some(Boolean);
946
- };
947
-
948
866
  const _removeBlockletSites = async (blocklet, nodeInfo, context = {}) => {
949
867
  let changed = false;
950
868
 
@@ -980,14 +898,6 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
980
898
  _ensureBlockletSites(blocklet, sites, nodeInfo, context),
981
899
  ];
982
900
 
983
- if (nodeInfo.mode === NODE_MODES.DEBUG || ['e2e', 'test'].includes(process.env.NODE_ENV)) {
984
- logger.info('Add blocklet endpoint in dashboard site', {
985
- nodeMode: nodeInfo.mode,
986
- NODE_ENV: process.env.NODE_ENV,
987
- });
988
- tasks.push(_ensureBlockletRulesForDashboardSite(blocklet, sites, nodeInfo, context));
989
- }
990
-
991
901
  const changes = await Promise.all(tasks);
992
902
 
993
903
  return changes.some(Boolean);
@@ -1131,6 +1041,16 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
1131
1041
  return (sites || []).find((x) => x.domain === domain);
1132
1042
  }
1133
1043
 
1044
+ async function resetSiteByDid(did, { refreshRouterProvider = true } = {}) {
1045
+ const blocklet = await states.blocklet.getBlocklet(did);
1046
+ await removeBlockletRouting(blocklet);
1047
+ await ensureBlockletRouting(blocklet);
1048
+ if (refreshRouterProvider) {
1049
+ const hash = await takeRoutingSnapshot({ message: `Reset blocklet ${did}`, dryRun: false });
1050
+ logger.info('reset blocklet routing rules', { did, hash });
1051
+ }
1052
+ }
1053
+
1134
1054
  const providers = {}; // we need to keep reference for different router instances
1135
1055
  const handleRouting = async (nodeInfo) => {
1136
1056
  const providerName = get(nodeInfo, 'routing.provider', null);
@@ -1382,6 +1302,7 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
1382
1302
  handleRouting,
1383
1303
  getRoutingRulesByDid,
1384
1304
  getSiteByDid,
1305
+ resetSiteByDid,
1385
1306
  updateNodeRouting,
1386
1307
  takeRoutingSnapshot,
1387
1308
  getRoutingSites,
@@ -66,6 +66,16 @@ const formatBlocklet = (blocklet, phase, dek) => {
66
66
  return blocklet;
67
67
  };
68
68
 
69
+ const fixChildren = (children) => {
70
+ if (!children) {
71
+ return;
72
+ }
73
+
74
+ children.forEach((child) => {
75
+ child.mode = child.mode || BLOCKLET_MODES.PRODUCTION;
76
+ });
77
+ };
78
+
69
79
  class BlockletState extends BaseState {
70
80
  /**
71
81
  * Creates an instance of BlockletState
@@ -163,6 +173,8 @@ class BlockletState extends BaseState {
163
173
  defaultPort: getMaxPort(ports),
164
174
  });
165
175
 
176
+ fixChildren(children);
177
+
166
178
  // add to db
167
179
  this.db.insert(
168
180
  {
@@ -244,6 +256,8 @@ class BlockletState extends BaseState {
244
256
  logger.info('Fill children ports when when upgrading blocklet', { name: doc.meta.name, did: doc.meta.did });
245
257
  await this.fillChildrenPorts(children, { oldChildren: doc.children, defaultPort: getMaxPort(ports) });
246
258
 
259
+ fixChildren(children);
260
+
247
261
  // add to db
248
262
  const newDoc = await this.updateBlocklet(meta.did, {
249
263
  meta: omit(sanitized, ['htmlAst']),
@@ -506,7 +520,7 @@ class BlockletState extends BaseState {
506
520
 
507
521
  const newChildren = [...oldChildren];
508
522
  for (const child of children) {
509
- const { meta, mountPoint, sourceUrl = '', source = '', deployedFrom = '' } = child;
523
+ const { meta, mountPoint, sourceUrl = '', source = '', deployedFrom = '', mode } = child;
510
524
 
511
525
  if (!mountPoint) {
512
526
  throw new Error(`mountPoint is required when adding component ${getDisplayName(child, true)}`);
@@ -524,9 +538,12 @@ class BlockletState extends BaseState {
524
538
  sourceUrl,
525
539
  source,
526
540
  deployedFrom,
541
+ mode,
527
542
  dynamic: true,
528
543
  status: BlockletStatus.added,
529
544
  });
545
+
546
+ fixChildren(newChildren);
530
547
  }
531
548
 
532
549
  // use upgradeBlocklet to assign ports to children and write new data to db
@@ -267,6 +267,19 @@ class TeamManager extends EventEmitter {
267
267
  }
268
268
  }
269
269
 
270
+ async getOwner(did) {
271
+ let owner;
272
+ if (this.isNodeTeam(did)) {
273
+ const nodeInfo = await this.states.node.read();
274
+ owner = get(nodeInfo, 'nodeOwner');
275
+ } else {
276
+ const settings = await this.states.blockletExtras.getSettings(did);
277
+ owner = get(settings, 'owner');
278
+ }
279
+
280
+ return owner;
281
+ }
282
+
270
283
  // =======
271
284
  // Private
272
285
  // =======
@@ -104,7 +104,7 @@ const PRIVATE_NODE_ENVS = [
104
104
  * appMain: app entry file or script (run appMain to start blocklet process)
105
105
  * appCwd: cwd of appMain
106
106
  */
107
- const getBlockletDirs = (blocklet, { rootBlocklet, dataDirs, ensure = false } = {}) => {
107
+ const getBlockletDirs = (blocklet, { rootBlocklet, dataDirs, ensure = false, e2eMode = false } = {}) => {
108
108
  if (!rootBlocklet) {
109
109
  // eslint-disable-next-line no-param-reassign
110
110
  rootBlocklet = blocklet;
@@ -126,8 +126,13 @@ const getBlockletDirs = (blocklet, { rootBlocklet, dataDirs, ensure = false } =
126
126
 
127
127
  const { main, group } = blocklet.meta;
128
128
 
129
- const startFromDevEntry =
130
- blocklet.mode === BLOCKLET_MODES.DEVELOPMENT && blocklet.meta.scripts && blocklet.meta.scripts.dev;
129
+ let startFromDevEntry = '';
130
+ if (blocklet.mode === BLOCKLET_MODES.DEVELOPMENT && blocklet.meta.scripts) {
131
+ startFromDevEntry = blocklet.meta.scripts.dev;
132
+ if (e2eMode && blocklet.meta.scripts.e2eDev) {
133
+ startFromDevEntry = blocklet.meta.scripts.e2eDev;
134
+ }
135
+ }
131
136
 
132
137
  if (!main && !startFromDevEntry && group !== BlockletGroup.gateway) {
133
138
  throw new Error('Incorrect blocklet manifest: missing `main` field');
@@ -174,7 +179,7 @@ const getBlockletDirs = (blocklet, { rootBlocklet, dataDirs, ensure = false } =
174
179
  let appMain = null;
175
180
  let appCwd = null;
176
181
  if (startFromDevEntry) {
177
- appMain = blocklet.meta.scripts.dev;
182
+ appMain = startFromDevEntry;
178
183
  appCwd = appDir;
179
184
  } else if (group === 'dapp') {
180
185
  appMain = getBlockletEngine(blocklet.meta).script || BLOCKLET_ENTRY_FILE;
@@ -414,7 +419,7 @@ const getBlockletMetaFromUrl = async (url) => {
414
419
  * Start all precesses of a blocklet
415
420
  * @param {*} blocklet should contain env props
416
421
  */
417
- const startBlockletProcess = async (blocklet, { preStart = noop, nodeEnvironments, nodeInfo } = {}) => {
422
+ const startBlockletProcess = async (blocklet, { preStart = noop, nodeEnvironments, nodeInfo, e2eMode } = {}) => {
418
423
  if (!blocklet) {
419
424
  throw new Error('blocklet should not be empty');
420
425
  }
@@ -463,7 +468,7 @@ const startBlockletProcess = async (blocklet, { preStart = noop, nodeEnvironment
463
468
  }
464
469
 
465
470
  if (b.mode === BLOCKLET_MODES.DEVELOPMENT) {
466
- options.env.NODE_ENV = 'development';
471
+ options.env.NODE_ENV = e2eMode ? 'e2e' : 'development';
467
472
  options.env.BROWSER = 'none';
468
473
  options.env.PORT = options.env[BLOCKLET_DEFAULT_PORT_NAME];
469
474
  options.script = appMain;
@@ -23,4 +23,4 @@ const getDidDomainForBlocklet = ({ name, daemonDid, didDomain }) => {
23
23
  return `${prefix}-${daemonDid.toLowerCase()}.${didDomain}`;
24
24
  };
25
25
 
26
- module.exports = { getIpDnsDomainForBlocklet, getDidDomainForBlocklet };
26
+ module.exports = { getIpDnsDomainForBlocklet, getDidDomainForBlocklet, formatName };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.7.6",
6
+ "version": "1.7.9",
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/certificate-manager": "1.7.6",
23
- "@abtnode/constant": "1.7.6",
24
- "@abtnode/cron": "1.7.6",
25
- "@abtnode/db": "1.7.6",
26
- "@abtnode/logger": "1.7.6",
27
- "@abtnode/queue": "1.7.6",
28
- "@abtnode/rbac": "1.7.6",
29
- "@abtnode/router-provider": "1.7.6",
30
- "@abtnode/static-server": "1.7.6",
31
- "@abtnode/timemachine": "1.7.6",
32
- "@abtnode/util": "1.7.6",
33
- "@arcblock/did": "^1.16.0",
34
- "@arcblock/did-motif": "^1.1.3",
35
- "@arcblock/event-hub": "1.16.0",
22
+ "@abtnode/certificate-manager": "1.7.9",
23
+ "@abtnode/constant": "1.7.9",
24
+ "@abtnode/cron": "1.7.9",
25
+ "@abtnode/db": "1.7.9",
26
+ "@abtnode/logger": "1.7.9",
27
+ "@abtnode/queue": "1.7.9",
28
+ "@abtnode/rbac": "1.7.9",
29
+ "@abtnode/router-provider": "1.7.9",
30
+ "@abtnode/static-server": "1.7.9",
31
+ "@abtnode/timemachine": "1.7.9",
32
+ "@abtnode/util": "1.7.9",
33
+ "@arcblock/did": "^1.16.4",
34
+ "@arcblock/did-motif": "^1.1.5",
35
+ "@arcblock/event-hub": "1.16.4",
36
36
  "@arcblock/pm2-events": "^0.0.5",
37
- "@arcblock/vc": "^1.16.0",
38
- "@blocklet/meta": "1.7.6",
37
+ "@arcblock/vc": "^1.16.4",
38
+ "@blocklet/meta": "1.7.9",
39
39
  "@fidm/x509": "^1.2.1",
40
40
  "@nedb/core": "^1.2.2",
41
41
  "@nedb/multi": "^1.2.2",
42
- "@ocap/mcrypto": "^1.16.0",
43
- "@ocap/util": "^1.16.0",
44
- "@ocap/wallet": "^1.16.0",
42
+ "@ocap/mcrypto": "^1.16.4",
43
+ "@ocap/util": "^1.16.4",
44
+ "@ocap/wallet": "^1.16.4",
45
45
  "@slack/webhook": "^5.0.3",
46
46
  "ajv": "^7.0.3",
47
- "axios": "^0.25.0",
47
+ "axios": "^0.26.1",
48
48
  "axon": "^2.0.3",
49
49
  "chalk": "^4.0.0",
50
50
  "deep-diff": "^1.0.2",
@@ -56,7 +56,7 @@
56
56
  "is-ip": "^3.1.0",
57
57
  "is-url": "^1.2.4",
58
58
  "joi": "^17.6.0",
59
- "js-yaml": "^3.14.0",
59
+ "js-yaml": "^4.1.0",
60
60
  "lodash": "^4.17.21",
61
61
  "lru-cache": "^6.0.0",
62
62
  "pm2": "^5.1.2",
@@ -78,5 +78,5 @@
78
78
  "express": "^4.17.1",
79
79
  "jest": "^27.4.5"
80
80
  },
81
- "gitHead": "47a9dbd6ea74419ff586336824ebb9b2fe7694aa"
81
+ "gitHead": "285f4fedd41fcb8e1814ce5d8250ac10616e67e0"
82
82
  }