@abtnode/core 1.8.36 → 1.8.38

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/event.js CHANGED
@@ -249,6 +249,8 @@ module.exports = ({
249
249
  }
250
250
  };
251
251
 
252
+ const listen = (subject, event, handler) => subject.on(event, (data) => handler(event, data));
253
+
252
254
  [
253
255
  BlockletEvents.added,
254
256
  BlockletEvents.downloadFailed,
@@ -265,12 +267,12 @@ module.exports = ({
265
267
  BlockletEvents.startFailed,
266
268
  BlockletEvents.stopped,
267
269
  ].forEach((eventName) => {
268
- blockletManager.on(eventName, (data) => handleBlockletEvent(eventName, data));
270
+ listen(blockletManager, eventName, handleBlockletEvent);
269
271
  });
270
272
 
271
- notificationState.on(EVENTS.NOTIFICATION_CREATE, (data) => onEvent(EVENTS.NOTIFICATION_CREATE, data));
273
+ listen(notificationState, EVENTS.NOTIFICATION_CREATE, onEvent);
272
274
 
273
- nodeState.on(BlockletEvents.purchaseChange, (data) => onEvent(BlockletEvents.purchaseChange, data));
275
+ listen(nodeState, BlockletEvents.purchaseChange, onEvent);
274
276
  nodeState.on(EVENTS.ROUTING_UPDATED, (nodeInfo) => onEvent(EVENTS.ROUTING_UPDATED, { routing: nodeInfo.routing }));
275
277
  nodeState.once(EVENTS.NODE_ADDED_OWNER, () => downloadAddedBlocklet());
276
278
  nodeState.on(EVENTS.NODE_UPDATED, (nodeInfo, oldInfo) => {
@@ -285,7 +287,8 @@ module.exports = ({
285
287
  });
286
288
  }
287
289
  });
288
- nodeState.on(EVENTS.NODE_UPGRADE_PROGRESS, (session) => onEvent(EVENTS.NODE_UPGRADE_PROGRESS, session));
290
+
291
+ listen(nodeState, EVENTS.NODE_UPGRADE_PROGRESS, onEvent);
289
292
  nodeState.on(EVENTS.RELOAD_GATEWAY, (nodeInfo) => {
290
293
  handleRouting(nodeInfo).catch((err) => {
291
294
  logger.error('Handle routing failed on node.updated', { error: err });
@@ -300,15 +303,16 @@ module.exports = ({
300
303
  });
301
304
  });
302
305
 
303
- teamAPI.on(EVENTS.USER_ADDED, (data) => onEvent(EVENTS.USER_ADDED, data));
304
- teamAPI.on(EVENTS.USER_REMOVED, (data) => onEvent(EVENTS.USER_REMOVED, data));
305
- teamAPI.on(EVENTS.USER_UPDATED, (data) => onEvent(EVENTS.USER_UPDATED, data));
306
- teamAPI.on(BlockletEvents.updated, (data) => onEvent(BlockletEvents.updated, data));
306
+ listen(teamAPI, EVENTS.USER_ADDED, onEvent);
307
+ listen(teamAPI, EVENTS.USER_REMOVED, onEvent);
308
+ listen(teamAPI, EVENTS.USER_UPDATED, onEvent);
309
+ listen(teamAPI, BlockletEvents.updated, onEvent);
310
+ listen(teamManager, BlockletEvents.storeChange, onEvent);
307
311
 
308
- certManager.on('cert.issued', (data) => onEvent(EVENTS.CERT_ISSUED, data));
309
- certManager.on('cert.error', (data) => onEvent(EVENTS.CERT_ERROR, data));
312
+ listen(certManager, EVENTS.CERT_ISSUED, onEvent);
313
+ listen(certManager, EVENTS.CERT_ERROR, onEvent);
310
314
 
311
- routerManager.on(BlockletEvents.updated, (data) => onEvent(BlockletEvents.updated, data));
315
+ listen(routerManager, BlockletEvents.updated, onEvent);
312
316
 
313
317
  events.setEventHandler = (handler) => {
314
318
  if (typeof handler === 'function') {
package/lib/index.js CHANGED
@@ -6,7 +6,6 @@ const Cron = require('@abtnode/cron');
6
6
 
7
7
  const logger = require('@abtnode/logger')('@abtnode/core');
8
8
  const { fromBlockletStatus, toBlockletStatus, fromBlockletSource, toBlockletSource } = require('@blocklet/constant');
9
- const { getServiceMetas } = require('@blocklet/meta/lib/service');
10
9
  const { listProviders } = require('@abtnode/router-provider');
11
10
  const { DEFAULT_CERTIFICATE_EMAIL, EVENTS } = require('@abtnode/constant');
12
11
 
@@ -236,9 +235,6 @@ function ABTNode(options) {
236
235
  getNodeInfo: nodeAPI.getInfo.bind(nodeAPI),
237
236
  getNodeEnv: nodeAPI.getEnv.bind(nodeAPI),
238
237
  updateNodeInfo: nodeAPI.updateNodeInfo.bind(nodeAPI),
239
- addBlockletStore: nodeAPI.addRegistry.bind(nodeAPI),
240
- deleteBlockletStore: nodeAPI.deleteRegistry.bind(nodeAPI),
241
- selectBlockletStore: nodeAPI.selectRegistry.bind(nodeAPI),
242
238
  getDelegationState: nodeAPI.getDelegationState.bind(nodeAPI),
243
239
  cleanupDirtyUpgradeState: states.node.cleanupDirtyUpgradeState.bind(states.node),
244
240
  updateNodeOwner: states.node.updateNodeOwner.bind(states.node),
@@ -307,6 +303,10 @@ function ABTNode(options) {
307
303
  configTrustedPassports: teamAPI.configTrustedPassports.bind(teamAPI),
308
304
  configPassportIssuance: teamAPI.configPassportIssuance.bind(teamAPI),
309
305
 
306
+ // Team Settings
307
+ addBlockletStore: teamAPI.addStore.bind(teamAPI),
308
+ deleteBlockletStore: teamAPI.deleteStore.bind(teamAPI),
309
+
310
310
  // Challenge
311
311
  generateChallenge: states.challenge.generate.bind(states.challenge),
312
312
  verifyChallenge: states.challenge.verify.bind(states.challenge),
@@ -383,9 +383,6 @@ function ABTNode(options) {
383
383
  ),
384
384
  endSession: (params, context) => states.session.end(params.id, context),
385
385
 
386
- // Services
387
- getServices: (params, context) => getServiceMetas({ stringifySchema: true }, context),
388
-
389
386
  // Utilities: moved here because some deps require native build
390
387
  getSysInfo,
391
388
  getSysInfoEmitter: (interval) => new SysInfoEmitter(interval),
@@ -410,7 +410,7 @@ class AuditLogState extends BaseState {
410
410
  }
411
411
 
412
412
  try {
413
- const { ip, ua, user } = context;
413
+ const { ip, ua, user = {} } = context;
414
414
  const [info, uaInfo] = await Promise.all([node.states.node.read(), parse(ua)]);
415
415
 
416
416
  fixActor(user);
@@ -106,6 +106,21 @@ class BlockletState extends BaseState {
106
106
  });
107
107
  }
108
108
 
109
+ async isExternalBlocklet(did) {
110
+ if (!did) {
111
+ return false;
112
+ }
113
+
114
+ const exist = await this.findOne({
115
+ $or: [{ 'meta.did': did }, { appDid: did }],
116
+ controller: {
117
+ $exists: true,
118
+ },
119
+ });
120
+
121
+ return !!exist;
122
+ }
123
+
109
124
  async getBlockletStatus(did) {
110
125
  return new Promise((resolve, reject) => {
111
126
  if (!did) {
@@ -302,10 +302,6 @@ class NodeState extends BaseState {
302
302
  }));
303
303
  }
304
304
 
305
- getBlockletRegistry() {
306
- return this.read().then((info) => info.blockletRegistryList.find((item) => item.selected).url);
307
- }
308
-
309
305
  async increaseCustomBlockletNumber() {
310
306
  const { _id, customBlockletNumber = 0 } = await this.read();
311
307
  const num = customBlockletNumber + 1;
@@ -76,44 +76,30 @@ class NotificationState extends BaseState {
76
76
  }
77
77
 
78
78
  // eslint-disable-next-line no-unused-vars
79
- read({ id }, context) {
79
+ async read({ id }, context) {
80
80
  const idList = id.split(',').map((x) => x.trim());
81
81
  logger.info('mark notification as read', { idList });
82
82
 
83
- return new Promise((resolve, reject) => {
84
- this.update(
85
- { _id: { $in: idList } },
86
- { $set: { read: true } },
87
- { multi: true, upsert: false, returnUpdatedDocs: false },
88
- (err, numAffected) => {
89
- if (err) {
90
- return reject(err);
91
- }
83
+ const [numAffected] = await this.update(
84
+ { _id: { $in: idList } },
85
+ { $set: { read: true } },
86
+ { multi: true, upsert: false, returnUpdatedDocs: false }
87
+ );
92
88
 
93
- return resolve(numAffected);
94
- }
95
- );
96
- });
89
+ return numAffected;
97
90
  }
98
91
 
99
92
  // eslint-disable-next-line no-unused-vars
100
- unread({ id }, context) {
93
+ async unread({ id }, context) {
101
94
  const idList = Array.isArray(id) ? id : [id];
102
95
 
103
- return new Promise((resolve, reject) => {
104
- this.update(
105
- { _id: { $in: idList } },
106
- { $set: { read: false } },
107
- { multi: true, upsert: false, returnUpdatedDocs: false },
108
- (err, numAffected) => {
109
- if (err) {
110
- return reject(err);
111
- }
96
+ const [numAffected] = await this.update(
97
+ { _id: { $in: idList } },
98
+ { $set: { read: false } },
99
+ { multi: true, upsert: false, returnUpdatedDocs: false }
100
+ );
112
101
 
113
- return resolve(numAffected);
114
- }
115
- );
116
- });
102
+ return numAffected;
117
103
  }
118
104
  }
119
105
 
@@ -5,10 +5,12 @@ const path = require('path');
5
5
  const { EventEmitter } = require('events');
6
6
  const upperFirst = require('lodash/upperFirst');
7
7
  const get = require('lodash/get');
8
+ const pick = require('lodash/pick');
8
9
 
9
10
  const { createRBAC, MemoryStorage, NedbStorage } = require('@abtnode/rbac');
10
11
  const logger = require('@abtnode/logger')('@abtnode/core:team:manager');
11
12
  const { ROLES, RBAC_CONFIG } = require('@abtnode/constant');
13
+ const { BlockletEvents } = require('@blocklet/constant');
12
14
  const Lock = require('@abtnode/util/lib/lock');
13
15
  const UserState = require('../states/user');
14
16
  const SessionState = require('../states/session');
@@ -280,6 +282,26 @@ class TeamManager extends EventEmitter {
280
282
  }
281
283
  }
282
284
 
285
+ async getStoreList(did) {
286
+ if (this.isNodeTeam(did)) {
287
+ const nodeInfo = await this.states.node.read();
288
+ return nodeInfo.blockletRegistryList || [];
289
+ }
290
+
291
+ const settings = await this.states.blockletExtras.getSettings(did);
292
+ return get(settings, 'storeList', []) || [];
293
+ }
294
+
295
+ async updateStoreList(did, list) {
296
+ if (this.isNodeTeam(did)) {
297
+ await this.states.node.updateNodeInfo({ blockletRegistryList: list });
298
+ return;
299
+ }
300
+
301
+ await this.states.blockletExtras.setSettings(did, { storeList: list });
302
+ this.emit(BlockletEvents.storeChange, { meta: { did } });
303
+ }
304
+
283
305
  async getOwner(did) {
284
306
  let owner;
285
307
  if (this.isNodeTeam(did)) {
@@ -293,6 +315,14 @@ class TeamManager extends EventEmitter {
293
315
  return owner;
294
316
  }
295
317
 
318
+ async getRoles(did) {
319
+ const rbac = await this.getRBAC(did);
320
+
321
+ const roles = await rbac.getRoles();
322
+
323
+ return roles.map((d) => pick(d, ['name', 'grants', 'title', 'description']));
324
+ }
325
+
296
326
  async initTeam(did) {
297
327
  if (!did) {
298
328
  logger.error('initTeam: did does not exist');
@@ -2,6 +2,7 @@
2
2
 
3
3
  const fs = require('fs-extra');
4
4
  const path = require('path');
5
+ const joinURL = require('url-join');
5
6
  const shelljs = require('shelljs');
6
7
  const os = require('os');
7
8
  const tar = require('tar');
@@ -10,19 +11,25 @@ const streamToPromise = require('stream-to-promise');
10
11
  const { Throttle } = require('stream-throttle');
11
12
  const ssri = require('ssri');
12
13
  const diff = require('deep-diff');
14
+ const axios = require('@abtnode/util/lib/axios');
15
+ const { stableStringify } = require('@arcblock/vc');
13
16
 
14
- const { toHex } = require('@ocap/util');
17
+ const { fromSecretKey, WalletType } = require('@ocap/wallet');
18
+ const { toHex, toBase58 } = require('@ocap/util');
19
+ const { types } = require('@ocap/mcrypto');
15
20
  const { isValid: isValidDid } = require('@arcblock/did');
16
21
  const logger = require('@abtnode/logger')('@abtnode/core:util:blocklet');
17
22
  const pm2 = require('@abtnode/util/lib/async-pm2');
18
23
  const sleep = require('@abtnode/util/lib/sleep');
24
+ const { formatEnv } = require('@abtnode/util/lib/security');
19
25
  const ensureEndpointHealthy = require('@abtnode/util/lib/ensure-endpoint-healthy');
20
26
  const CustomError = require('@abtnode/util/lib/custom-error');
21
27
  const getFolderSize = require('@abtnode/util/lib/get-folder-size');
22
28
  const normalizePathPrefix = require('@abtnode/util/lib/normalize-path-prefix');
23
29
  const hashFiles = require('@abtnode/util/lib/hash-files');
24
30
  const isPathPrefixEqual = require('@abtnode/util/lib/is-path-prefix-equal');
25
- const { BLOCKLET_MAX_MEM_LIMIT_IN_MB } = require('@abtnode/constant');
31
+ const { BLOCKLET_MAX_MEM_LIMIT_IN_MB, BLOCKLET_STORE } = require('@abtnode/constant');
32
+ const { BLOCKLET_PREFERENCE_FILE, BLOCKLET_PREFERENCE_PREFIX } = require('@blocklet/constant');
26
33
  const formatBackSlash = require('@abtnode/util/lib/format-back-slash');
27
34
 
28
35
  const SCRIPT_ENGINES_WHITE_LIST = ['npm', 'npx', 'pnpm', 'yarn'];
@@ -148,7 +155,7 @@ const getComponentDirs = (
148
155
  }
149
156
 
150
157
  if (validate && !main && !startFromDevEntry && group !== BlockletGroup.gateway) {
151
- throw new Error('Incorrect blocklet manifest: missing `main` field');
158
+ throw new Error('Incorrect blocklet.yml: missing `main` field');
152
159
  }
153
160
 
154
161
  let appDir = null;
@@ -380,7 +387,7 @@ const getRuntimeEnvironments = (blocklet, nodeEnvironments, ancestors) => {
380
387
  ? getBlockletWallet(blocklet.meta.did, nodeEnvironments.ABT_NODE_SK, undefined, 1)
381
388
  : null;
382
389
 
383
- return {
390
+ const env = {
384
391
  ...blocklet.configObj,
385
392
  ...getSharedConfigObj(blocklet, ancestors),
386
393
  ...blocklet.environmentObj,
@@ -392,6 +399,13 @@ const getRuntimeEnvironments = (blocklet, nodeEnvironments, ancestors) => {
392
399
  ...nodeEnvironments,
393
400
  ...safeNodeEnvironments,
394
401
  };
402
+
403
+ // ensure all envs are literals and do not contain line breaks
404
+ Object.keys(env).forEach((key) => {
405
+ env[key] = formatEnv(env[key]);
406
+ });
407
+
408
+ return env;
395
409
  };
396
410
 
397
411
  const isUsefulError = (err) =>
@@ -1248,7 +1262,7 @@ const needBlockletDownload = (blocklet, oldBlocklet) => {
1248
1262
  return true;
1249
1263
  }
1250
1264
 
1251
- return !(get(oldBlocklet, 'meta.dist.integrity') === get(blocklet, 'meta.dist.integrity'));
1265
+ return get(oldBlocklet, 'meta.dist.integrity') !== get(blocklet, 'meta.dist.integrity');
1252
1266
  };
1253
1267
 
1254
1268
  const findAvailableDid = (meta, siblings) => {
@@ -1330,6 +1344,15 @@ const getBlocklet = async ({
1330
1344
  blocklet.enablePassportIssuance = get(settings, 'enablePassportIssuance', true);
1331
1345
  blocklet.settings = settings || {};
1332
1346
 
1347
+ blocklet.settings.storeList = blocklet.settings.storeList || [];
1348
+
1349
+ if (!blocklet.settings.storeList.find((x) => x.url === BLOCKLET_STORE.url)) {
1350
+ blocklet.settings.storeList.unshift({
1351
+ ...BLOCKLET_STORE,
1352
+ protected: true,
1353
+ });
1354
+ }
1355
+
1333
1356
  // app site
1334
1357
  blocklet.site = await states.site.findOneByBlocklet(blocklet.meta.did);
1335
1358
 
@@ -1385,7 +1408,68 @@ const ensureEnvDefault = (environments, ancestors) => {
1385
1408
  return environments;
1386
1409
  };
1387
1410
 
1411
+ const fromProperty2Config = (properties = {}, result) => {
1412
+ Object.keys(properties).forEach((key) => {
1413
+ const prop = properties[key];
1414
+ if (prop.properties) {
1415
+ fromProperty2Config(prop.properties, result);
1416
+ } else if (prop['x-decorator'] === 'FormItem') {
1417
+ const secure = prop['x-component'] === 'Password';
1418
+ result.push({
1419
+ default: prop.default || '',
1420
+ description: prop.title || key,
1421
+ name: `${BLOCKLET_PREFERENCE_PREFIX}${key}`,
1422
+ required: prop.required || false,
1423
+ secure,
1424
+ shared: !secure,
1425
+ });
1426
+ }
1427
+ });
1428
+ };
1429
+ const getConfigFromPreferences = (blocklet) => {
1430
+ const result = [];
1431
+ const schemaFile = path.join(blocklet.env.appDir, BLOCKLET_PREFERENCE_FILE);
1432
+ if (fs.existsSync(schemaFile)) {
1433
+ try {
1434
+ const schema = JSON.parse(fs.readFileSync(schemaFile, 'utf8'));
1435
+ fromProperty2Config(schema.schema?.properties, result);
1436
+ } catch {
1437
+ // do nothing
1438
+ }
1439
+ }
1440
+
1441
+ return result;
1442
+ };
1443
+
1444
+ const consumeServerlessNFT = async ({ nftId, nodeInfo, blocklet }) => {
1445
+ try {
1446
+ const { url } = nodeInfo.launcher;
1447
+ const type = WalletType({
1448
+ role: types.RoleType.ROLE_APPLICATION,
1449
+ pk: types.KeyType.ED25519,
1450
+ hash: types.HashType.SHA3,
1451
+ });
1452
+ const wallet = fromSecretKey(nodeInfo.sk, type);
1453
+ const appURL = blocklet.environments.find((item) => item.key === 'BLOCKLET_APP_URL').value;
1454
+
1455
+ const body = { nftId, appURL };
1456
+
1457
+ const { data } = await axios.post(joinURL(url, '/api/serverless/consume'), body, {
1458
+ headers: {
1459
+ 'x-sig': toBase58(wallet.sign(stableStringify(body))),
1460
+ },
1461
+ });
1462
+
1463
+ logger.error('consume serverless nft success', { nftId, hash: data.hash });
1464
+ } catch (error) {
1465
+ logger.error('consume serverless nft failed', { nftId, error });
1466
+
1467
+ throw new Error(`consume nft ${nftId} failed`);
1468
+ }
1469
+ };
1470
+
1388
1471
  module.exports = {
1472
+ consumeServerlessNFT,
1389
1473
  forEachBlocklet,
1390
1474
  getBlockletMetaFromUrl: (url) => getBlockletMetaFromUrl(url, { logger }),
1391
1475
  parseChildrenFromMeta,
@@ -1425,4 +1509,5 @@ module.exports = {
1425
1509
  ensureMeta,
1426
1510
  getBlocklet,
1427
1511
  ensureEnvDefault,
1512
+ getConfigFromPreferences,
1428
1513
  };
@@ -1,4 +1,4 @@
1
- const { NODE_REGISTER_URL, BLOCKLET_STORE_URL, BLOCKLET_STORE_URL_DEV } = require('@abtnode/constant');
1
+ const { NODE_REGISTER_URL, BLOCKLET_STORE, BLOCKLET_STORE_DEV } = require('@abtnode/constant');
2
2
  const canPackageReadWrite = require('@abtnode/util/lib/can-pkg-rw');
3
3
 
4
4
  const getDefaultAutoUpgrade = () => {
@@ -16,21 +16,11 @@ const defaultNodeConfigs = {
16
16
  blockletRegistryList: {
17
17
  getDefaultValue: () => [
18
18
  {
19
- name: 'Official Store',
20
- description: 'ArcBlock official blocklet registry',
21
- url: BLOCKLET_STORE_URL,
22
- logoUrl: '/logo.png',
23
- maintainer: 'arcblock',
24
- selected: true,
19
+ ...BLOCKLET_STORE,
25
20
  protected: true,
26
21
  },
27
22
  {
28
- name: 'Dev Store',
29
- description: 'ArcBlock dev registry that contains demo and example blocklets',
30
- url: BLOCKLET_STORE_URL_DEV,
31
- maintainer: 'arcblock',
32
- logoUrl: '/logo.png',
33
- selected: false,
23
+ ...BLOCKLET_STORE_DEV,
34
24
  protected: false,
35
25
  },
36
26
  ],
package/lib/util/index.js CHANGED
@@ -394,6 +394,49 @@ const getDelegateState = async (chainHost, address) => {
394
394
  return get(result.data, 'data.getDelegateState.state');
395
395
  };
396
396
 
397
+ const getNFTState = async (chainHost, nftId) => {
398
+ const url = joinUrl(new URL(chainHost).origin, '/api/gql/');
399
+
400
+ const result = await axios.post(
401
+ url,
402
+ JSON.stringify({
403
+ query: `{
404
+ getAssetState(address: "${nftId}") {
405
+ state {
406
+ address
407
+ data {
408
+ typeUrl
409
+ value
410
+ }
411
+ display {
412
+ type
413
+ content
414
+ }
415
+ issuer
416
+ owner
417
+ parent
418
+ tags
419
+ }
420
+ }
421
+ }`,
422
+ }),
423
+ {
424
+ headers: {
425
+ 'Content-Type': 'application/json',
426
+ Accept: 'application/json',
427
+ },
428
+ timeout: 60 * 1000,
429
+ }
430
+ );
431
+
432
+ const state = get(result, 'data.data.getAssetState.state');
433
+ if (state && state.data.typeUrl === 'json') {
434
+ state.data.value = JSON.parse(state.data.value);
435
+ }
436
+
437
+ return state;
438
+ };
439
+
397
440
  const lib = {
398
441
  validateOwner,
399
442
  getProviderFromNodeInfo,
@@ -428,6 +471,7 @@ const lib = {
428
471
  memoizeAsync,
429
472
  getStateCrons,
430
473
  getDelegateState,
474
+ getNFTState,
431
475
  };
432
476
 
433
477
  module.exports = lib;
package/lib/util/store.js CHANGED
@@ -84,7 +84,7 @@ const parseSourceUrl = async (url) => {
84
84
  };
85
85
  };
86
86
 
87
- const resolveTarballURL = async ({ did, tarball = '', registryUrl = '' }) => {
87
+ const resolveTarballURL = async ({ did, tarball = '', storeUrl = '' }) => {
88
88
  if (!tarball) {
89
89
  return '';
90
90
  }
@@ -97,7 +97,7 @@ const resolveTarballURL = async ({ did, tarball = '', registryUrl = '' }) => {
97
97
  return tarball;
98
98
  }
99
99
 
100
- if (!registryUrl) {
100
+ if (!storeUrl) {
101
101
  return '';
102
102
  }
103
103
 
@@ -105,11 +105,11 @@ const resolveTarballURL = async ({ did, tarball = '', registryUrl = '' }) => {
105
105
  return '';
106
106
  }
107
107
 
108
- return joinURL(registryUrl, 'api', 'blocklets', did, tarball);
108
+ return joinURL(storeUrl, 'api', 'blocklets', did, tarball);
109
109
  };
110
110
 
111
- const getBlockletMeta = async ({ did, registryUrl }) => {
112
- const url = joinURL(registryUrl, BLOCKLET_STORE_API_PREFIX, `/blocklets/${did}/blocklet.json?__t__=${Date.now()}`);
111
+ const getBlockletMeta = async ({ did, storeUrl }) => {
112
+ const url = joinURL(storeUrl, BLOCKLET_STORE_API_PREFIX, `/blocklets/${did}/blocklet.json?__t__=${Date.now()}`);
113
113
 
114
114
  const { data } = await request.get(url);
115
115
  try {
@@ -122,7 +122,7 @@ const getBlockletMeta = async ({ did, registryUrl }) => {
122
122
  meta.dist.tarball = await resolveTarballURL({
123
123
  did,
124
124
  tarball: meta.dist.tarball,
125
- registryUrl,
125
+ storeUrl,
126
126
  });
127
127
 
128
128
  return meta;
@@ -4,11 +4,9 @@ const { didExtension } = require('@blocklet/meta/lib/extension');
4
4
  const Joi = JOI.extend(didExtension);
5
5
 
6
6
  const blockletController = Joi.object({
7
- id: Joi.DID().required(), // userDid
8
7
  nftId: Joi.DID().required(),
9
8
  nftOwner: Joi.DID().required(),
10
9
  appMaxCount: Joi.number().required().min(1),
11
- expireDate: Joi.date(),
12
10
  }).options({ stripUnknown: true });
13
11
 
14
12
  module.exports = {
@@ -10,6 +10,10 @@ const roleNameSchema = JOI.string()
10
10
  throw new Error('role name cannot start with "blocklet"');
11
11
  }
12
12
 
13
+ if (/[^a-zA-z0-9]/.test(value)) {
14
+ throw new Error('role name can include only numbers or letters');
15
+ }
16
+
13
17
  return value;
14
18
  });
15
19
 
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.8.36",
6
+ "version": "1.8.38",
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.36",
23
- "@abtnode/certificate-manager": "1.8.36",
24
- "@abtnode/constant": "1.8.36",
25
- "@abtnode/cron": "1.8.36",
26
- "@abtnode/db": "1.8.36",
27
- "@abtnode/logger": "1.8.36",
28
- "@abtnode/queue": "1.8.36",
29
- "@abtnode/rbac": "1.8.36",
30
- "@abtnode/router-provider": "1.8.36",
31
- "@abtnode/static-server": "1.8.36",
32
- "@abtnode/timemachine": "1.8.36",
33
- "@abtnode/util": "1.8.36",
34
- "@arcblock/did": "1.18.15",
22
+ "@abtnode/auth": "1.8.38",
23
+ "@abtnode/certificate-manager": "1.8.38",
24
+ "@abtnode/constant": "1.8.38",
25
+ "@abtnode/cron": "1.8.38",
26
+ "@abtnode/db": "1.8.38",
27
+ "@abtnode/logger": "1.8.38",
28
+ "@abtnode/queue": "1.8.38",
29
+ "@abtnode/rbac": "1.8.38",
30
+ "@abtnode/router-provider": "1.8.38",
31
+ "@abtnode/static-server": "1.8.38",
32
+ "@abtnode/timemachine": "1.8.38",
33
+ "@abtnode/util": "1.8.38",
34
+ "@arcblock/did": "1.18.18",
35
35
  "@arcblock/did-motif": "^1.1.10",
36
- "@arcblock/did-util": "1.18.15",
37
- "@arcblock/event-hub": "1.18.15",
38
- "@arcblock/jwt": "^1.18.15",
36
+ "@arcblock/did-util": "1.18.18",
37
+ "@arcblock/event-hub": "1.18.18",
38
+ "@arcblock/jwt": "^1.18.18",
39
39
  "@arcblock/pm2-events": "^0.0.5",
40
- "@arcblock/vc": "1.18.15",
41
- "@blocklet/constant": "1.8.36",
42
- "@blocklet/meta": "1.8.36",
43
- "@blocklet/sdk": "1.8.36",
40
+ "@arcblock/vc": "1.18.18",
41
+ "@blocklet/constant": "1.8.38",
42
+ "@blocklet/meta": "1.8.38",
43
+ "@blocklet/sdk": "1.8.38",
44
44
  "@fidm/x509": "^1.2.1",
45
- "@ocap/mcrypto": "1.18.15",
46
- "@ocap/util": "1.18.15",
47
- "@ocap/wallet": "1.18.15",
45
+ "@ocap/mcrypto": "1.18.18",
46
+ "@ocap/util": "1.18.18",
47
+ "@ocap/wallet": "1.18.18",
48
48
  "@slack/webhook": "^5.0.4",
49
49
  "axios": "^0.27.2",
50
50
  "axon": "^2.0.3",
@@ -82,5 +82,5 @@
82
82
  "express": "^4.18.2",
83
83
  "jest": "^27.5.1"
84
84
  },
85
- "gitHead": "507e974ce88bad1aa002c593130b32982207f803"
85
+ "gitHead": "cbb88f107eb6b403c8cd47a765920575860c7bc7"
86
86
  }