@abtnode/core 1.16.45-beta-20250610-112229-2eb0face → 1.16.45-beta-20250614-101901-d1700f8d

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
@@ -70,6 +70,10 @@ class NodeAPI {
70
70
 
71
71
  async getDiskInfo() {
72
72
  let diskInfo = { app: 0, cache: 0, log: 0, data: 0, blocklets: 0 };
73
+ if (process.env.ABT_NODE_FAKE_DISK_INFO === '1') {
74
+ return diskInfo;
75
+ }
76
+
73
77
  try {
74
78
  const [app, cache, log, data, blocklets] = await Promise.all([
75
79
  getFolderSize(this.state.dataDirs.core),
@@ -100,6 +100,7 @@ const {
100
100
  SUSPENDED_REASON,
101
101
  APP_CONFIG_DIR,
102
102
  COMPONENT_ENV_FILE_NAME,
103
+ BLOCKLET_PREFERENCE_PREFIX,
103
104
  } = require('@blocklet/constant');
104
105
 
105
106
  const { WELLKNOWN_SERVICE_PATH_PREFIX, WELLKNOWN_BLOCKLET_ADMIN_PATH } = require('@abtnode/constant');
@@ -1669,10 +1670,12 @@ class DiskBlockletManager extends BaseBlockletManager {
1669
1670
  }
1670
1671
 
1671
1672
  // 对用户输入的配置进行 XSS 清理
1672
- const sanitizedConfigs = newConfigs.map((c) => ({
1673
- ...c,
1674
- value: sanitizeTag(c.value),
1675
- }));
1673
+ const sanitizedConfigs = newConfigs
1674
+ .map((c) => ({
1675
+ ...c,
1676
+ value: sanitizeTag(c.value),
1677
+ }))
1678
+ .filter((x) => (x.key.startsWith(BLOCKLET_PREFERENCE_PREFIX) ? omit(x, 'shared') : x));
1676
1679
 
1677
1680
  const tmpDids = Array.isArray(did) ? did : [did];
1678
1681
  const [rootDid, childDid] = tmpDids;
@@ -2768,8 +2771,32 @@ class DiskBlockletManager extends BaseBlockletManager {
2768
2771
  return summary;
2769
2772
  }
2770
2773
 
2771
- async updateInviteSettings({ did, invite }, context) {
2772
- await states.blockletExtras.setSettings(did, { invite });
2774
+ async updateBlockletSettings({ did, enableSessionHardening, invite, gateway }, context) {
2775
+ const params = {};
2776
+ if (!isNil(enableSessionHardening)) {
2777
+ params.enableSessionHardening = enableSessionHardening;
2778
+ }
2779
+
2780
+ if (!isNil(invite)) {
2781
+ params.invite = invite;
2782
+ }
2783
+
2784
+ if (!isNil(gateway)) {
2785
+ params.gateway = gateway;
2786
+ }
2787
+
2788
+ const keys = Object.keys(params);
2789
+ if (!keys.length) {
2790
+ throw new Error('No settings to update');
2791
+ }
2792
+
2793
+ await states.blockletExtras.setSettings(did, params);
2794
+
2795
+ if (!isNil(gateway)) {
2796
+ const nodeState = states.node;
2797
+ const doc = await nodeState.read();
2798
+ nodeState.emit(EVENTS.RELOAD_GATEWAY, doc);
2799
+ }
2773
2800
 
2774
2801
  const newState = await this.getBlocklet(did);
2775
2802
  this.emit(BlockletInternalEvents.appSettingChanged, { appDid: did });
@@ -12,6 +12,8 @@ const inProgressStatuses = [BlockletStatus.stopping, BlockletStatus.restarting,
12
12
  class EnsureBlockletRunning {
13
13
  initialized = false;
14
14
 
15
+ firstChecked = false;
16
+
15
17
  // 每次任务的最小间隔时间
16
18
  checkInterval = +process.env.ABT_NODE_ENSURE_RUNNING_CHECK_INTERVAL || 60 * 1000;
17
19
 
@@ -52,12 +54,15 @@ class EnsureBlockletRunning {
52
54
 
53
55
  isBlockletPortHealthyWithRetries = async (blocklet, isDoing = false) => {
54
56
  let error;
55
- for (let attempt = 0; attempt < 10; attempt++) {
57
+ const maxAttempts = this.firstChecked ? 10 : 2;
58
+ const timeout = this.firstChecked ? 6000 : 3000;
59
+
60
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
56
61
  try {
57
62
  // eslint-disable-next-line no-await-in-loop
58
63
  await this.isBlockletPortHealthy(blocklet, {
59
64
  minConsecutiveTime: 3000,
60
- timeout: 6000,
65
+ timeout,
61
66
  });
62
67
  return true;
63
68
  } catch (e) {
@@ -141,6 +146,7 @@ class EnsureBlockletRunning {
141
146
  logger.error('ensure blocklet status failed', e);
142
147
  }
143
148
  this.runningRootBlocklets = {};
149
+ this.firstChecked = true;
144
150
  };
145
151
 
146
152
  getRunningBlocklets = async () => {
@@ -762,6 +762,7 @@ module.exports = Object.freeze({
762
762
  readNotifications: true,
763
763
  unreadNotifications: true,
764
764
  launchBlockletByLauncher: true,
765
+ launchBlockletWithoutWallet: true,
765
766
  },
766
767
  NOTIFICATION_SEND_STATUS: {
767
768
  PENDING: 0, // 待发送
@@ -8202,7 +8203,7 @@ function save(namespaces) {
8202
8203
  function load() {
8203
8204
  let r;
8204
8205
  try {
8205
- r = exports.storage.getItem('debug');
8206
+ r = exports.storage.getItem('debug') || exports.storage.getItem('DEBUG') ;
8206
8207
  } catch (error) {
8207
8208
  // Swallow
8208
8209
  // XXX (@Qix-) should we be logging these?
@@ -8430,7 +8431,7 @@ function setup(env) {
8430
8431
 
8431
8432
  const split = (typeof namespaces === 'string' ? namespaces : '')
8432
8433
  .trim()
8433
- .replace(' ', ',')
8434
+ .replace(/\s+/g, ',')
8434
8435
  .split(',')
8435
8436
  .filter(Boolean);
8436
8437
 
@@ -38888,7 +38889,7 @@ module.exports = require("zlib");
38888
38889
  /***/ ((module) => {
38889
38890
 
38890
38891
  "use strict";
38891
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@abtnode/core","publishConfig":{"access":"public"},"version":"1.16.44","description":"","main":"lib/index.js","files":["lib"],"scripts":{"lint":"eslint tests lib --ignore-pattern \'tests/assets/*\'","lint:fix":"eslint --fix tests lib","test":"node tools/jest.js","coverage":"npm run test -- --coverage"},"keywords":[],"author":"wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)","license":"Apache-2.0","dependencies":{"@abtnode/analytics":"1.16.44","@abtnode/auth":"1.16.44","@abtnode/certificate-manager":"1.16.44","@abtnode/client":"1.16.44","@abtnode/constant":"1.16.44","@abtnode/cron":"1.16.44","@abtnode/db-cache":"1.16.44","@abtnode/docker-utils":"1.16.44","@abtnode/logger":"1.16.44","@abtnode/models":"1.16.44","@abtnode/queue":"1.16.44","@abtnode/rbac":"1.16.44","@abtnode/router-provider":"1.16.44","@abtnode/static-server":"1.16.44","@abtnode/timemachine":"1.16.44","@abtnode/util":"1.16.44","@arcblock/did":"1.20.14","@arcblock/did-auth":"1.20.14","@arcblock/did-ext":"1.20.14","@arcblock/did-motif":"^1.1.13","@arcblock/did-util":"1.20.14","@arcblock/event-hub":"1.20.14","@arcblock/jwt":"1.20.14","@arcblock/pm2-events":"^0.0.5","@arcblock/validator":"1.20.14","@arcblock/vc":"1.20.14","@blocklet/constant":"1.16.44","@blocklet/did-space-js":"^1.0.59","@blocklet/env":"1.16.44","@blocklet/error":"^0.2.5","@blocklet/meta":"1.16.44","@blocklet/resolver":"1.16.44","@blocklet/sdk":"1.16.44","@blocklet/store":"1.16.44","@blocklet/theme":"^2.13.63","@fidm/x509":"^1.2.1","@ocap/mcrypto":"1.20.14","@ocap/util":"1.20.14","@ocap/wallet":"1.20.14","@slack/webhook":"^5.0.4","archiver":"^7.0.1","axios":"^1.7.9","axon":"^2.0.3","chalk":"^4.1.2","cross-spawn":"^7.0.3","dayjs":"^1.11.13","deep-diff":"^1.0.2","detect-port":"^1.5.1","envfile":"^7.1.0","escape-string-regexp":"^4.0.0","fast-glob":"^3.3.2","filesize":"^10.1.1","flat":"^5.0.2","fs-extra":"^11.2.0","get-port":"^5.1.1","hasha":"^5.2.2","is-base64":"^1.1.0","is-cidr":"4","is-ip":"3","is-url":"^1.2.4","joi":"17.12.2","joi-extension-semver":"^5.0.0","js-yaml":"^4.1.0","kill-port":"^2.0.1","lodash":"^4.17.21","node-stream-zip":"^1.15.0","p-all":"^3.0.0","p-limit":"^3.1.0","p-map":"^4.0.0","p-retry":"^4.6.2","p-wait-for":"^3.2.0","rate-limiter-flexible":"^5.0.5","read-last-lines":"^1.8.0","semver":"^7.6.3","sequelize":"^6.35.0","shelljs":"^0.8.5","slugify":"^1.6.6","ssri":"^8.0.1","stream-throttle":"^0.1.3","stream-to-promise":"^3.0.0","systeminformation":"^5.23.3","tail":"^2.2.4","tar":"^6.1.11","transliteration":"^2.3.5","ua-parser-js":"^1.0.2","ufo":"^1.5.3","uuid":"^9.0.1","valid-url":"^1.0.9","which":"^2.0.2","xbytes":"^1.8.0"},"devDependencies":{"expand-tilde":"^2.0.2","express":"^4.18.2","jest":"^29.7.0","unzipper":"^0.10.11"},"gitHead":"e5764f753181ed6a7c615cd4fc6682aacf0cb7cd"}');
38892
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@abtnode/core","publishConfig":{"access":"public"},"version":"1.16.44","description":"","main":"lib/index.js","files":["lib"],"scripts":{"lint":"eslint tests lib --ignore-pattern \'tests/assets/*\'","lint:fix":"eslint --fix tests lib","test":"node tools/jest.js","coverage":"npm run test -- --coverage"},"keywords":[],"author":"wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)","license":"Apache-2.0","dependencies":{"@abtnode/analytics":"1.16.44","@abtnode/auth":"1.16.44","@abtnode/certificate-manager":"1.16.44","@abtnode/client":"1.16.44","@abtnode/constant":"1.16.44","@abtnode/cron":"1.16.44","@abtnode/db-cache":"1.16.44","@abtnode/docker-utils":"1.16.44","@abtnode/logger":"1.16.44","@abtnode/models":"1.16.44","@abtnode/queue":"1.16.44","@abtnode/rbac":"1.16.44","@abtnode/router-provider":"1.16.44","@abtnode/static-server":"1.16.44","@abtnode/timemachine":"1.16.44","@abtnode/util":"1.16.44","@arcblock/did":"1.20.14","@arcblock/did-auth":"1.20.14","@arcblock/did-ext":"1.20.14","@arcblock/did-motif":"^1.1.13","@arcblock/did-util":"1.20.14","@arcblock/event-hub":"1.20.14","@arcblock/jwt":"1.20.14","@arcblock/pm2-events":"^0.0.5","@arcblock/validator":"1.20.14","@arcblock/vc":"1.20.14","@blocklet/constant":"1.16.44","@blocklet/did-space-js":"^1.0.60","@blocklet/env":"1.16.44","@blocklet/error":"^0.2.5","@blocklet/meta":"1.16.44","@blocklet/resolver":"1.16.44","@blocklet/sdk":"1.16.44","@blocklet/store":"1.16.44","@blocklet/theme":"^2.13.67","@fidm/x509":"^1.2.1","@ocap/mcrypto":"1.20.14","@ocap/util":"1.20.14","@ocap/wallet":"1.20.14","@slack/webhook":"^5.0.4","archiver":"^7.0.1","axios":"^1.7.9","axon":"^2.0.3","chalk":"^4.1.2","cross-spawn":"^7.0.3","dayjs":"^1.11.13","deep-diff":"^1.0.2","detect-port":"^1.5.1","envfile":"^7.1.0","escape-string-regexp":"^4.0.0","fast-glob":"^3.3.2","filesize":"^10.1.1","flat":"^5.0.2","fs-extra":"^11.2.0","get-port":"^5.1.1","hasha":"^5.2.2","is-base64":"^1.1.0","is-cidr":"4","is-ip":"3","is-url":"^1.2.4","joi":"17.12.2","joi-extension-semver":"^5.0.0","js-yaml":"^4.1.0","kill-port":"^2.0.1","lodash":"^4.17.21","node-stream-zip":"^1.15.0","p-all":"^3.0.0","p-limit":"^3.1.0","p-map":"^4.0.0","p-retry":"^4.6.2","p-wait-for":"^3.2.0","rate-limiter-flexible":"^5.0.5","read-last-lines":"^1.8.0","semver":"^7.6.3","sequelize":"^6.35.0","shelljs":"^0.8.5","slugify":"^1.6.6","ssri":"^8.0.1","stream-throttle":"^0.1.3","stream-to-promise":"^3.0.0","systeminformation":"^5.23.3","tail":"^2.2.4","tar":"^6.1.11","transliteration":"^2.3.5","ua-parser-js":"^1.0.2","ufo":"^1.5.3","uuid":"^9.0.1","valid-url":"^1.0.9","which":"^2.0.2","xbytes":"^1.8.0"},"devDependencies":{"expand-tilde":"^2.0.2","express":"^4.18.2","jest":"^29.7.0","unzipper":"^0.10.11"},"gitHead":"e5764f753181ed6a7c615cd4fc6682aacf0cb7cd"}');
38892
38893
 
38893
38894
  /***/ }),
38894
38895
 
package/lib/index.js CHANGED
@@ -23,6 +23,7 @@ const {
23
23
  isLauncherSessionConsumed,
24
24
  setupAppOwner,
25
25
  launchBlockletByLauncher,
26
+ launchBlockletWithoutWallet,
26
27
  } = require('./util/launcher');
27
28
  const WebHook = require('./webhook');
28
29
  const states = require('./states');
@@ -287,7 +288,6 @@ function ABTNode(options) {
287
288
  const webhookAPI = new WebhookAPI({ states, teamManager });
288
289
 
289
290
  const {
290
- updateBlockletWafSettings,
291
291
  handleBlockletWafChange,
292
292
  handleRouting,
293
293
  resetSiteByDid,
@@ -454,8 +454,6 @@ function ABTNode(options) {
454
454
  // check update
455
455
  updateAutoCheckUpdate: blockletManager.updateAutoCheckUpdate.bind(blockletManager),
456
456
 
457
- updateInviteSettings: blockletManager.updateInviteSettings.bind(blockletManager),
458
-
459
457
  // Store
460
458
  getBlockletMeta: StoreUtil.getBlockletMeta,
461
459
  getStoreMeta: StoreUtil.getStoreMeta,
@@ -506,7 +504,7 @@ function ABTNode(options) {
506
504
  getConnectedAccount: teamAPI.getConnectedAccount.bind(teamAPI),
507
505
  getOwner: teamAPI.getOwner.bind(teamAPI),
508
506
  getNodeUsers: () => teamAPI.getUsers({ teamDid: options.nodeDid }),
509
- getNodeUser: (user) => teamAPI.getUser({ teamDid: options.nodeDid, user }),
507
+ getNodeUser: (user, _options) => teamAPI.getUser({ teamDid: options.nodeDid, user, options: _options }),
510
508
  addUser: teamAPI.addUser.bind(teamAPI),
511
509
  loginUser: teamAPI.loginUser.bind(teamAPI),
512
510
  disconnectUserAccount: teamAPI.disconnectUserAccount.bind(teamAPI),
@@ -719,6 +717,7 @@ function ABTNode(options) {
719
717
  isLauncherSessionConsumed,
720
718
  setupAppOwner,
721
719
  launchBlockletByLauncher: (params, context) => launchBlockletByLauncher(instance, params, context),
720
+ launchBlockletWithoutWallet: (params, context) => launchBlockletWithoutWallet(instance, params, context),
722
721
 
723
722
  // init security default data
724
723
  initializeSecurityDefaultData: securityAPI.initializeDefaultData.bind(securityAPI),
@@ -777,7 +776,7 @@ function ABTNode(options) {
777
776
  createOAuthClient: teamAPI.createOAuthClient.bind(teamAPI),
778
777
  updateOAuthClient: teamAPI.updateOAuthClient.bind(teamAPI),
779
778
 
780
- updateBlockletGateway: ({ teamDid, wafPolicy }) => updateBlockletWafSettings({ teamDid, wafPolicy }),
779
+ updateBlockletSettings: blockletManager.updateBlockletSettings.bind(blockletManager),
781
780
  };
782
781
 
783
782
  blockletManager.createAuditLog = (params) => states.auditLog.create(params, instance);
@@ -1444,7 +1444,7 @@ module.exports = function getRouterHelpers({
1444
1444
  entityType: 'server',
1445
1445
  severity: 'error',
1446
1446
  source: 'system',
1447
- sticky: true,
1447
+ sticky: false,
1448
1448
  });
1449
1449
  });
1450
1450
  }
@@ -1459,7 +1459,16 @@ module.exports = function getRouterHelpers({
1459
1459
  if (daemon && info.routing.blockPolicy?.autoBlocking?.enabled && providers[providerName].supportsModSecurity()) {
1460
1460
  scanner.stopLogWatcher();
1461
1461
  const logs = providers[providerName].getLogFilesForToday();
1462
- const limiter = createLimiter(info.routing.blockPolicy.autoBlocking);
1462
+ const limiter = createLimiter(info.routing.blockPolicy.autoBlocking, (entry) => {
1463
+ teamManager.createNotification({
1464
+ title: 'User IP Blocked',
1465
+ description: `User IP blocked: ${JSON.stringify(entry, null, 2)}`,
1466
+ entityType: 'server',
1467
+ severity: 'error',
1468
+ source: 'system',
1469
+ sticky: false,
1470
+ });
1471
+ });
1463
1472
  scanner.startLogWatcher(logs.error, async (logEntries) => {
1464
1473
  const blocked = [];
1465
1474
  const grouped = countBy(logEntries, 'ip');
@@ -1894,13 +1903,6 @@ module.exports = function getRouterHelpers({
1894
1903
  return uniq([...blacklist]);
1895
1904
  };
1896
1905
 
1897
- const updateBlockletWafSettings = async ({ teamDid, wafPolicy }) => {
1898
- await states.blockletExtras.setSettings(teamDid, { gateway: { wafPolicy } });
1899
-
1900
- const doc = await nodeState.read();
1901
- nodeState.emit(EVENTS.RELOAD_GATEWAY, doc);
1902
- };
1903
-
1904
1906
  const handleBlockletWafChange = async ({ teamDid, wafPolicy }) => {
1905
1907
  const blocklet = await blockletManager.detail({ did: teamDid });
1906
1908
  if (!blocklet) {
@@ -1925,7 +1927,6 @@ module.exports = function getRouterHelpers({
1925
1927
  };
1926
1928
 
1927
1929
  return {
1928
- updateBlockletWafSettings,
1929
1930
  handleBlockletWafChange,
1930
1931
  ensureDashboardRouting,
1931
1932
  ensureBlockletRouting,
@@ -16,9 +16,10 @@ const states = require('../../states');
16
16
  * windowQuota: number;
17
17
  * blockDuration: number;
18
18
  * }} options
19
+ * @param {(entry: { scope: string, key: string, expiresAt: number }) => void} onBlocked
19
20
  * @returns {{ check: (ip: string, points?: number) => Promise<number> }}
20
21
  */
21
- function createLimiter(options) {
22
+ function createLimiter(options, onBlocked = () => {}) {
22
23
  const limiter = new RateLimiterMemory({
23
24
  points: options.windowQuota,
24
25
  duration: options.windowSize,
@@ -35,8 +36,10 @@ function createLimiter(options) {
35
36
  logger.info('Rate limit has exceeded', { ip, err });
36
37
  const expiresAt = dayjs().add(err.msBeforeNext, 'ms').unix();
37
38
  const added = await states.blacklist.addItem(BLACKLIST_SCOPE.ROUTER, ip, expiresAt);
39
+
38
40
  if (added) {
39
41
  logger.info('User IP blocked', { ip, expiresAt });
42
+ onBlocked({ scope: BLACKLIST_SCOPE.ROUTER, key: ip, expiresAt });
40
43
  return err.msBeforeNext;
41
44
  }
42
45
  }
@@ -536,8 +536,20 @@ const getLogContent = async (action, args, context, result, info, node) => {
536
536
  case 'deleteOAuthClient':
537
537
  return `Delete ${args.teamDid} OAuth Client:(${args.clientId})`;
538
538
 
539
- case 'updateBlockletGateway':
540
- return `Update Blocklet WAF:(${args.teamDid} to ${args.wafPolicy?.enabled})`;
539
+ case 'updateBlockletSettings': {
540
+ const changes = [];
541
+ if (!isNil(args.enableSessionHardening)) {
542
+ changes.push(`* Session Hardening: ${args.enableSessionHardening}`);
543
+ }
544
+ if (!isNil(args.invite)) {
545
+ changes.push(`* Invite: ${JSON.stringify(args.invite)}`);
546
+ }
547
+ if (!isNil(args.gateway)) {
548
+ changes.push(`* Gateway: ${JSON.stringify(args.gateway)}`);
549
+ }
550
+
551
+ return `Update Blocklet Extras Settings:(${args.did} to ${changes.join(', ')})`;
552
+ }
541
553
 
542
554
  default:
543
555
  return action;
@@ -586,7 +598,7 @@ const getLogCategory = (action) => {
586
598
  case 'deleteOAuthClient':
587
599
  case 'createOAuthClient':
588
600
  case 'updateOAuthClient':
589
- case 'updateBlockletGateway':
601
+ case 'updateBlockletSettings':
590
602
  return 'blocklet';
591
603
 
592
604
  case 'addUploadEndpoint':
@@ -56,9 +56,9 @@ class NodeState extends BaseState {
56
56
  }
57
57
 
58
58
  cache = new DBCache(() => ({
59
- ...getAbtNodeRedisAndSQLiteUrl(),
60
59
  prefix: 'node-state',
61
60
  ttl: SERVER_CACHE_TTL,
61
+ ...getAbtNodeRedisAndSQLiteUrl(),
62
62
  }));
63
63
 
64
64
  isInitialized(doc) {
@@ -105,9 +105,9 @@ class TeamManager extends EventEmitter {
105
105
  this.init();
106
106
 
107
107
  this.lock = new DBCache(() => ({
108
- ...getAbtNodeRedisAndSQLiteUrl(),
109
108
  prefix: 'team-manager-locks',
110
109
  ttl: 1000 * 30,
110
+ ...getAbtNodeRedisAndSQLiteUrl(),
111
111
  }));
112
112
  }
113
113
 
@@ -222,15 +222,9 @@ class TeamManager extends EventEmitter {
222
222
  users = users.concat(roleUsers);
223
223
  }
224
224
  if (userDids.length > 0) {
225
- const queryUsers = await userState.getUsersByDids({
226
- dids: userDids,
227
- query: {
228
- approved: true,
229
- selection,
230
- includeConnectedAccounts,
231
- includePassports: true,
232
- },
233
- });
225
+ const queryUsers = await Promise.all(
226
+ userDids.map((did) => userState.getUser(did, { includePassports: true, enableConnectedAccount: true }))
227
+ );
234
228
 
235
229
  const validUsers = queryUsers.filter((user) => {
236
230
  const { passports = [] } = user;
@@ -147,9 +147,9 @@ const startLock = new DBCache(() => ({
147
147
  }));
148
148
 
149
149
  const blockletCache = new DBCache(() => ({
150
- ...getAbtNodeRedisAndSQLiteUrl(),
151
150
  prefix: 'blocklet-state',
152
151
  ttl: BLOCKLET_CACHE_TTL,
152
+ ...getAbtNodeRedisAndSQLiteUrl(),
153
153
  }));
154
154
 
155
155
  const getVersionScope = (meta) => {
@@ -1577,8 +1577,8 @@ const _getBlocklet = async ({
1577
1577
  blocklet.settings.storeList = blocklet.settings.storeList || [];
1578
1578
  blocklet.settings.theme = mergeWith(
1579
1579
  cloneDeep({
1580
- light: BLOCKLET_THEME_LIGHT,
1581
- dark: BLOCKLET_THEME_DARK,
1580
+ light: { palette: BLOCKLET_THEME_LIGHT.palette },
1581
+ dark: { palette: BLOCKLET_THEME_DARK.palette },
1582
1582
  prefer: 'light',
1583
1583
  }),
1584
1584
  blocklet.settings.theme,
@@ -1655,7 +1655,6 @@ const getBlocklet = ({
1655
1655
 
1656
1656
  if (useCache) {
1657
1657
  cacheKey = JSON.stringify({
1658
- did,
1659
1658
  ensureIntegrity,
1660
1659
  getOptionalComponents,
1661
1660
  });
@@ -2322,7 +2321,7 @@ const getConfigsFromInput = (configs = [], oldConfigs = []) => {
2322
2321
 
2323
2322
  configs.forEach((config) => {
2324
2323
  const oldConfig = oldConfigs.find((y) => y.key === config.key);
2325
- if (isEnvShareable(config) || isEnvShareable(oldConfig)) {
2324
+ if (!config.key.startsWith(BLOCKLET_PREFERENCE_PREFIX) && (isEnvShareable(config) || isEnvShareable(oldConfig))) {
2326
2325
  sharedConfigs.push(config);
2327
2326
  } else {
2328
2327
  selfConfigs.push(config);
package/lib/util/cache.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const fs = require('fs-extra');
2
2
  const path = require('path');
3
3
  const { getAppImageCacheDir, getAppOgCacheDir } = require('@abtnode/util/lib/blocklet');
4
+ const { DBCache, getAbtNodeRedisAndSQLiteUrl } = require('@abtnode/db-cache');
4
5
 
5
6
  const clearCacheDir = (dir) => {
6
7
  if (fs.existsSync(dir)) {
@@ -9,6 +10,15 @@ const clearCacheDir = (dir) => {
9
10
  }
10
11
  };
11
12
 
13
+ const clearDBCache = async () => {
14
+ const dbCache = new DBCache(() => ({
15
+ prefix: '*',
16
+ ttl: 1000 * 60,
17
+ ...getAbtNodeRedisAndSQLiteUrl(),
18
+ }));
19
+ await dbCache.flushAll();
20
+ };
21
+
12
22
  /**
13
23
  * The `clearCache` function is used to clear cache files based on different
14
24
  * parameters and directories.
@@ -18,6 +28,8 @@ const clearCacheDir = (dir) => {
18
28
  * @returns String[] list of files removed from the cache.
19
29
  */
20
30
  const clearCache = async (params, node, blockletManager) => {
31
+ await clearDBCache();
32
+
21
33
  const baseDir = path.dirname(node.dataDirs.core);
22
34
 
23
35
  // reset cache by pattern
@@ -1,17 +1,10 @@
1
1
  const dns = require('dns');
2
2
  const { promisify } = require('util');
3
- const { DBCache, getAbtNodeRedisAndSQLiteUrl } = require('@abtnode/db-cache');
4
3
  const logger = require('@abtnode/logger')('checkDNS');
5
4
 
6
5
  const resolveCname = promisify(dns.resolveCname);
7
6
  const resolve = promisify(dns.resolve);
8
7
 
9
- const cache = new DBCache(() => ({
10
- ...getAbtNodeRedisAndSQLiteUrl(),
11
- prefix: 'check-dns',
12
- ttl: 60 * 60 * 1000,
13
- }));
14
-
15
8
  async function checkDnsAndCname(domain, expectedCname = '') {
16
9
  try {
17
10
  await resolve(domain);
@@ -50,8 +43,4 @@ async function checkDnsAndCname(domain, expectedCname = '') {
50
43
  }
51
44
  }
52
45
 
53
- function getDNSInfo(domain, expectedCname) {
54
- return cache.autoCache(domain, () => checkDnsAndCname(domain, expectedCname));
55
- }
56
-
57
- module.exports = getDNSInfo;
46
+ module.exports = checkDnsAndCname;
@@ -11,9 +11,9 @@ const filterParentDirs = require('./filter-parent-dirs');
11
11
  const { createDockerImage } = require('./create-docker-image');
12
12
 
13
13
  const lockFile = new DBCache(() => ({
14
- ...getAbtNodeRedisAndSQLiteUrl(),
15
14
  prefix: 'docker-exec-chown-locks',
16
15
  ttl: 1000 * 60 * 2,
16
+ ...getAbtNodeRedisAndSQLiteUrl(),
17
17
  }));
18
18
 
19
19
  async function dockerExecChown({ name, dirs, code = 777, force = false }) {
@@ -5,9 +5,9 @@ const { DBCache, getAbtNodeRedisAndSQLiteUrl } = require('@abtnode/db-cache');
5
5
  const { checkDockerInstalled } = require('./check-docker-installed');
6
6
 
7
7
  const lockNetwork = new DBCache(() => ({
8
- ...getAbtNodeRedisAndSQLiteUrl(),
9
8
  prefix: 'docker-network-locks',
10
9
  ttl: 1000 * 10,
10
+ ...getAbtNodeRedisAndSQLiteUrl(),
11
11
  }));
12
12
 
13
13
  async function getDockerNetworks() {
@@ -15,6 +15,7 @@ const {
15
15
  getAvatarByUrl,
16
16
  getAppAvatarUrl,
17
17
  } = require('@abtnode/util/lib/user');
18
+ const { CustomError } = require('@blocklet/error');
18
19
  const { createLaunchBlockletHandler, createServerlessInstallGuard } = require('@abtnode/auth/lib/server');
19
20
  const { getDisplayName } = require('@blocklet/meta/lib/util');
20
21
  const { fromAppDid } = require('@arcblock/did-ext');
@@ -24,7 +25,7 @@ const { getBlockletLogos } = require('@abtnode/util/lib/blocklet');
24
25
  const { PASSPORT_SOURCE, PASSPORT_LOG_ACTION, PASSPORT_ISSUE_ACTION } = require('@abtnode/constant');
25
26
 
26
27
  const { getLauncherUser, getLauncherSession: getLauncherSessionRaw, doRequest } = require('@abtnode/auth/lib/launcher');
27
- const { createAuthToken, getPassportStatusEndpoint } = require('@abtnode/auth/lib/auth');
28
+ const { createAuthToken, getPassportStatusEndpoint, messages } = require('@abtnode/auth/lib/auth');
28
29
  const { createPassportVC, createPassport, createUserPassport } = require('@abtnode/auth/lib/passport');
29
30
 
30
31
  const { LOGIN_PROVIDER, fromBlockletStatus } = require('@blocklet/constant');
@@ -245,7 +246,7 @@ const setupAppOwner = async ({ node, sessionId, justCreate = false, context, pro
245
246
  appOwnerProfile.avatar = await extractUserAvatar(avatarBase64, { dataDir });
246
247
  logger.info('Create owner from launcher for blocklet', { appDid, ownerDid, ownerPk, sessionId, appOwnerProfile });
247
248
  } else {
248
- user = await node.getUser({ teamDid: info.did, user: { did: userDid } });
249
+ user = await node.getUser({ teamDid: info.did, user: { did: userDid }, options: { enableConnectedAccount: true } });
249
250
  if (!user) {
250
251
  throw new Error(`Owner user not found in server: ${userDid}`);
251
252
  }
@@ -537,6 +538,68 @@ const launchBlockletByLauncher = async (node, extraParams, context) => {
537
538
  return data;
538
539
  };
539
540
 
541
+ const launchBlockletWithoutWallet = async (node, extraParams, context) => {
542
+ logger.debug('launchBlockletWithoutWallet', { extraParams, context });
543
+
544
+ extraParams.locale = context.locale || 'en';
545
+
546
+ const { blockletMetaUrl, title, description, locale } = extraParams;
547
+
548
+ if (!blockletMetaUrl && !title && !description) {
549
+ logger.error('blockletMetaUrl | title + description must be provided');
550
+ throw new CustomError(400, messages.missingBlockletUrl[locale]);
551
+ }
552
+
553
+ const blocklet = blockletMetaUrl
554
+ ? await node.getBlockletMetaFromUrl({ url: blockletMetaUrl, checkPrice: true })
555
+ : {
556
+ meta: {
557
+ title,
558
+ description,
559
+ },
560
+ };
561
+
562
+ if (!blocklet) {
563
+ throw new Error('Blocklet not found');
564
+ }
565
+
566
+ // generate app key pair
567
+ const type = (blocklet?.meta?.environments || []).find((x) => x.name === 'CHAIN_TYPE')?.default || 'default';
568
+ const appWallet = fromRandom(type);
569
+
570
+ // use the server user to set up the app owner, this account only allows using the passkey to login
571
+ const { user } = context;
572
+
573
+ let data = {};
574
+
575
+ const handler = createLaunchBlockletHandler(node, 'session');
576
+ await handler(
577
+ {
578
+ extraParams,
579
+ userDid: user.did,
580
+ claims: [
581
+ {
582
+ type: 'keyPair',
583
+ secret: appWallet.secretKey,
584
+ userDid: user.did,
585
+ userPk: user.pk,
586
+ },
587
+ ],
588
+ didwallet: {
589
+ os: 'managed',
590
+ version,
591
+ },
592
+ updateSession: (updates) => {
593
+ data = merge(data, updates);
594
+ },
595
+ provider: LOGIN_PROVIDER.EMAIL,
596
+ },
597
+ context
598
+ );
599
+
600
+ return data;
601
+ };
602
+
540
603
  module.exports = {
541
604
  consumeServerlessNFT,
542
605
  consumeLauncherSession,
@@ -550,4 +613,5 @@ module.exports = {
550
613
  isBlockletTerminated,
551
614
  notifyBlockletUpdated,
552
615
  launchBlockletByLauncher,
616
+ launchBlockletWithoutWallet,
553
617
  };
@@ -59,15 +59,15 @@ const actionSchema = Joi.object({
59
59
  });
60
60
 
61
61
  const paletteSchema = Joi.object({
62
- mode: Joi.string().valid('light', 'dark').required(),
63
- primary: paletteColorSchema.required(),
64
- secondary: paletteColorSchema.required(),
65
- error: paletteColorSchema.required(),
66
- warning: paletteColorSchema.required(),
67
- info: paletteColorSchema.required(),
68
- success: paletteColorSchema.required(),
69
- grey: greySchema.required(),
70
- text: textSchema.required(),
62
+ mode: Joi.string().valid('light', 'dark').optional(),
63
+ primary: paletteColorSchema.optional(),
64
+ secondary: paletteColorSchema.optional(),
65
+ error: paletteColorSchema.optional(),
66
+ warning: paletteColorSchema.optional(),
67
+ info: paletteColorSchema.optional(),
68
+ success: paletteColorSchema.optional(),
69
+ grey: greySchema.optional(),
70
+ text: textSchema.optional(),
71
71
  divider: colorString.optional(),
72
72
  background: backgroundSchema.optional(),
73
73
  common: commonSchema.optional(),
@@ -148,6 +148,7 @@ const muiThemeSchema = Joi.object({
148
148
  }).options({ allowUnknown: true, stripUnknown: true });
149
149
 
150
150
  const blockletThemeSchema = Joi.object({
151
+ common: muiThemeSchema.required(),
151
152
  light: muiThemeSchema.required(),
152
153
  dark: muiThemeSchema.required(),
153
154
  prefer: Joi.string().valid('light', 'dark', 'system').default('light'),
@@ -2,9 +2,9 @@ const { DBCache, getAbtNodeRedisAndSQLiteUrl } = require('@abtnode/db-cache');
2
2
 
3
3
  // 确保多进程只会有一个任务在执行
4
4
  const reduceQueue = new DBCache(() => ({
5
- ...getAbtNodeRedisAndSQLiteUrl(),
6
5
  prefix: 'reduce-queue',
7
6
  ttl: 5 * 1000,
7
+ ...getAbtNodeRedisAndSQLiteUrl(),
8
8
  }));
9
9
 
10
10
  module.exports = reduceQueue;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.16.45-beta-20250610-112229-2eb0face",
6
+ "version": "1.16.45-beta-20250614-101901-d1700f8d",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,22 +19,22 @@
19
19
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
20
20
  "license": "Apache-2.0",
21
21
  "dependencies": {
22
- "@abtnode/analytics": "1.16.45-beta-20250610-112229-2eb0face",
23
- "@abtnode/auth": "1.16.45-beta-20250610-112229-2eb0face",
24
- "@abtnode/certificate-manager": "1.16.45-beta-20250610-112229-2eb0face",
25
- "@abtnode/client": "1.16.45-beta-20250610-112229-2eb0face",
26
- "@abtnode/constant": "1.16.45-beta-20250610-112229-2eb0face",
27
- "@abtnode/cron": "1.16.45-beta-20250610-112229-2eb0face",
28
- "@abtnode/db-cache": "1.16.45-beta-20250610-112229-2eb0face",
29
- "@abtnode/docker-utils": "1.16.45-beta-20250610-112229-2eb0face",
30
- "@abtnode/logger": "1.16.45-beta-20250610-112229-2eb0face",
31
- "@abtnode/models": "1.16.45-beta-20250610-112229-2eb0face",
32
- "@abtnode/queue": "1.16.45-beta-20250610-112229-2eb0face",
33
- "@abtnode/rbac": "1.16.45-beta-20250610-112229-2eb0face",
34
- "@abtnode/router-provider": "1.16.45-beta-20250610-112229-2eb0face",
35
- "@abtnode/static-server": "1.16.45-beta-20250610-112229-2eb0face",
36
- "@abtnode/timemachine": "1.16.45-beta-20250610-112229-2eb0face",
37
- "@abtnode/util": "1.16.45-beta-20250610-112229-2eb0face",
22
+ "@abtnode/analytics": "1.16.45-beta-20250614-101901-d1700f8d",
23
+ "@abtnode/auth": "1.16.45-beta-20250614-101901-d1700f8d",
24
+ "@abtnode/certificate-manager": "1.16.45-beta-20250614-101901-d1700f8d",
25
+ "@abtnode/client": "1.16.45-beta-20250614-101901-d1700f8d",
26
+ "@abtnode/constant": "1.16.45-beta-20250614-101901-d1700f8d",
27
+ "@abtnode/cron": "1.16.45-beta-20250614-101901-d1700f8d",
28
+ "@abtnode/db-cache": "1.16.45-beta-20250614-101901-d1700f8d",
29
+ "@abtnode/docker-utils": "1.16.45-beta-20250614-101901-d1700f8d",
30
+ "@abtnode/logger": "1.16.45-beta-20250614-101901-d1700f8d",
31
+ "@abtnode/models": "1.16.45-beta-20250614-101901-d1700f8d",
32
+ "@abtnode/queue": "1.16.45-beta-20250614-101901-d1700f8d",
33
+ "@abtnode/rbac": "1.16.45-beta-20250614-101901-d1700f8d",
34
+ "@abtnode/router-provider": "1.16.45-beta-20250614-101901-d1700f8d",
35
+ "@abtnode/static-server": "1.16.45-beta-20250614-101901-d1700f8d",
36
+ "@abtnode/timemachine": "1.16.45-beta-20250614-101901-d1700f8d",
37
+ "@abtnode/util": "1.16.45-beta-20250614-101901-d1700f8d",
38
38
  "@arcblock/did": "1.20.14",
39
39
  "@arcblock/did-auth": "1.20.14",
40
40
  "@arcblock/did-ext": "1.20.14",
@@ -45,15 +45,15 @@
45
45
  "@arcblock/pm2-events": "^0.0.5",
46
46
  "@arcblock/validator": "1.20.14",
47
47
  "@arcblock/vc": "1.20.14",
48
- "@blocklet/constant": "1.16.45-beta-20250610-112229-2eb0face",
49
- "@blocklet/did-space-js": "^1.0.59",
50
- "@blocklet/env": "1.16.45-beta-20250610-112229-2eb0face",
48
+ "@blocklet/constant": "1.16.45-beta-20250614-101901-d1700f8d",
49
+ "@blocklet/did-space-js": "^1.0.60",
50
+ "@blocklet/env": "1.16.45-beta-20250614-101901-d1700f8d",
51
51
  "@blocklet/error": "^0.2.5",
52
- "@blocklet/meta": "1.16.45-beta-20250610-112229-2eb0face",
53
- "@blocklet/resolver": "1.16.45-beta-20250610-112229-2eb0face",
54
- "@blocklet/sdk": "1.16.45-beta-20250610-112229-2eb0face",
55
- "@blocklet/store": "1.16.45-beta-20250610-112229-2eb0face",
56
- "@blocklet/theme": "^2.13.63",
52
+ "@blocklet/meta": "1.16.45-beta-20250614-101901-d1700f8d",
53
+ "@blocklet/resolver": "1.16.45-beta-20250614-101901-d1700f8d",
54
+ "@blocklet/sdk": "1.16.45-beta-20250614-101901-d1700f8d",
55
+ "@blocklet/store": "1.16.45-beta-20250614-101901-d1700f8d",
56
+ "@blocklet/theme": "^2.13.67",
57
57
  "@fidm/x509": "^1.2.1",
58
58
  "@ocap/mcrypto": "1.20.14",
59
59
  "@ocap/util": "1.20.14",
@@ -116,5 +116,5 @@
116
116
  "jest": "^29.7.0",
117
117
  "unzipper": "^0.10.11"
118
118
  },
119
- "gitHead": "d35fb6c907c29f4466fa965c079e1662dc77e582"
119
+ "gitHead": "5fb4c294b2754d660fa946ac85c962edb2deaad2"
120
120
  }