@abtnode/core 1.17.7-beta-20251227-001958-ea2ba3f5 → 1.17.7-beta-20251229-223813-e1e6c5e3

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.
Files changed (39) hide show
  1. package/lib/blocklet/manager/disk.js +74 -32
  2. package/lib/blocklet/manager/ensure-blocklet-running.js +1 -1
  3. package/lib/blocklet/manager/helper/blue-green-start-blocklet.js +1 -1
  4. package/lib/blocklet/manager/helper/install-application-from-general.js +2 -3
  5. package/lib/blocklet/manager/helper/install-component-from-url.js +7 -4
  6. package/lib/blocklet/migration-dist/migration.cjs +5 -4
  7. package/lib/blocklet/passport/index.js +10 -3
  8. package/lib/blocklet/project/index.js +7 -2
  9. package/lib/blocklet/security/index.js +2 -2
  10. package/lib/cert.js +6 -3
  11. package/lib/event/index.js +98 -87
  12. package/lib/event/util.js +7 -13
  13. package/lib/index.js +15 -26
  14. package/lib/migrations/1.5.0-site.js +3 -7
  15. package/lib/migrations/1.5.15-site.js +3 -7
  16. package/lib/monitor/blocklet-runtime-monitor.js +37 -5
  17. package/lib/monitor/node-runtime-monitor.js +4 -4
  18. package/lib/router/helper.js +525 -452
  19. package/lib/router/index.js +280 -104
  20. package/lib/router/manager.js +14 -28
  21. package/lib/states/blocklet-child.js +93 -1
  22. package/lib/states/blocklet-extras.js +1 -1
  23. package/lib/states/blocklet.js +429 -197
  24. package/lib/states/node.js +0 -10
  25. package/lib/states/site.js +87 -4
  26. package/lib/team/manager.js +2 -21
  27. package/lib/util/blocklet.js +39 -19
  28. package/lib/util/get-accessible-external-node-ip.js +21 -6
  29. package/lib/util/index.js +3 -3
  30. package/lib/util/ip.js +15 -1
  31. package/lib/util/launcher.js +11 -11
  32. package/lib/util/ready.js +2 -9
  33. package/lib/util/reset-node.js +6 -5
  34. package/lib/validators/router.js +0 -3
  35. package/lib/webhook/sender/api/index.js +5 -0
  36. package/package.json +23 -25
  37. package/lib/migrations/1.0.36-snapshot.js +0 -10
  38. package/lib/migrations/1.1.9-snapshot.js +0 -7
  39. package/lib/states/routing-snapshot.js +0 -146
@@ -103,6 +103,7 @@ const {
103
103
  APP_CONFIG_DIR,
104
104
  COMPONENT_ENV_FILE_NAME,
105
105
  BLOCKLET_PREFERENCE_PREFIX,
106
+ STATIC_SERVER_ENGINE_DID,
106
107
  LOGIN_PROVIDER,
107
108
  } = require('@blocklet/constant');
108
109
 
@@ -132,7 +133,7 @@ const { updateComponentDid, removeUploadFile } = require('@abtnode/util/lib/uplo
132
133
  const groupBy = require('lodash/groupBy');
133
134
  const { isDidDomain, isCustomDomain, getOriginUrl } = require('@abtnode/util/lib/url-evaluation');
134
135
  const { DBCache, getAbtNodeRedisAndSQLiteUrl } = require('@abtnode/db-cache');
135
- const { isInstanceWorker } = require('@abtnode/util/lib/pm2/is-instance-worker.js');
136
+ const { isWorkerInstance } = require('@abtnode/util/lib/pm2/is-instance-worker.js');
136
137
  const launcher = require('../../util/launcher');
137
138
  const util = require('../../util');
138
139
  const {
@@ -190,7 +191,7 @@ const BaseBlockletManager = require('./base');
190
191
  const { get: getEngine } = require('./engine');
191
192
  const runBlockletMigrationScripts = require('../migration');
192
193
  const hooks = require('../hooks');
193
- const { BlockletRuntimeMonitor } = require('../../monitor/blocklet-runtime-monitor');
194
+ const { BlockletRuntimeMonitor, isRuntimeMonitorDisabled } = require('../../monitor/blocklet-runtime-monitor');
194
195
  const getHistoryList = require('../../monitor/get-history-list');
195
196
  const { SpacesBackup } = require('../storage/backup/spaces');
196
197
  const { DiskBackup } = require('../storage/backup/disk');
@@ -422,7 +423,7 @@ class DiskBlockletManager extends BaseBlockletManager {
422
423
  }
423
424
 
424
425
  ensureBlockletRunning = () => {
425
- if (isInstanceWorker()) {
426
+ if (isWorkerInstance()) {
426
427
  return;
427
428
  }
428
429
  ensureBlockletRunning.initialize({
@@ -547,9 +548,8 @@ class DiskBlockletManager extends BaseBlockletManager {
547
548
  * @memberof BlockletManager
548
549
  */
549
550
  async install(params, context = {}) {
550
- logger.debug('install blocklet', { params, context });
551
-
552
551
  const type = getTypeFromInstallParams(params);
552
+ logger.info('install blocklet', { type, params: omit(params, ['appSk']), user: context.user });
553
553
 
554
554
  const { appSk } = params;
555
555
  if (!appSk) {
@@ -831,12 +831,12 @@ class DiskBlockletManager extends BaseBlockletManager {
831
831
  if (!baseComponentDids.includes(b.meta.did)) {
832
832
  continue;
833
833
  }
834
- const engine = getBlockletEngine(b.meta);
835
- if (engine.interpreter === 'blocklet') {
834
+ if (!hasStartEngine(b.meta)) {
836
835
  nonEntryComponentIds.push(b.meta.did);
837
836
  continue;
838
837
  }
839
- if (!hasStartEngine(b.meta)) {
838
+ const engine = getBlockletEngine(b.meta);
839
+ if (engine.interpreter === 'blocklet') {
840
840
  nonEntryComponentIds.push(b.meta.did);
841
841
  continue;
842
842
  }
@@ -878,7 +878,7 @@ class DiskBlockletManager extends BaseBlockletManager {
878
878
 
879
879
  // 根据情况更新 route table
880
880
  if (!['true', '1'].includes(process.env.ABT_NODE_DISABLE_BLUE_GREEN)) {
881
- this.emit(BlockletEvents.blurOrGreenStarted, {
881
+ this.emit(BlockletEvents.blueOrGreenStarted, {
882
882
  blocklet: finalBlocklet,
883
883
  componentDids: inputComponentDids,
884
884
  context,
@@ -1053,7 +1053,7 @@ class DiskBlockletManager extends BaseBlockletManager {
1053
1053
 
1054
1054
  // 根据情况更新 route table, 会判断只有包含多 interfaces 的 DID 才会更新 route table
1055
1055
  if (!['true', '1'].includes(process.env.ABT_NODE_DISABLE_BLUE_GREEN)) {
1056
- this.emit(BlockletEvents.blurOrGreenStarted, {
1056
+ this.emit(BlockletEvents.blueOrGreenStarted, {
1057
1057
  blocklet: resultBlocklet,
1058
1058
  componentDids: inputComponentDids,
1059
1059
  context,
@@ -1968,14 +1968,37 @@ class DiskBlockletManager extends BaseBlockletManager {
1968
1968
  }
1969
1969
  }
1970
1970
 
1971
- async list({ includeRuntimeInfo = true, query } = {}, context) {
1971
+ async list({ includeRuntimeInfo = true, query, paging, search, external, sort } = {}, context) {
1972
+ // Validate sort param structure (if provided)
1973
+ if (sort && typeof sort !== 'object') {
1974
+ throw new Error('sort must be an object with field and direction properties');
1975
+ }
1976
+
1977
+ // If pagination requested, use paginated query
1978
+ if (!isEmpty(paging)) {
1979
+ const result = await states.blocklet.findPaginated({ search, external, paging, sort });
1980
+
1981
+ if (includeRuntimeInfo) {
1982
+ result.list = await this._attachBlockletListRuntimeInfo({ blocklets: result.list }, context);
1983
+ }
1984
+
1985
+ return {
1986
+ blocklets: result.list,
1987
+ paging: result.paging,
1988
+ };
1989
+ }
1990
+
1991
+ // Legacy: return all blocklets (backward compatible)
1972
1992
  const condition = { ...flat(query || {}) };
1973
1993
  const blocklets = await states.blocklet.getBlocklets(condition);
1974
1994
  if (includeRuntimeInfo) {
1975
- return this._attachBlockletListRuntimeInfo({ blocklets }, context);
1995
+ return {
1996
+ blocklets: await this._attachBlockletListRuntimeInfo({ blocklets }, context),
1997
+ paging: { total: blocklets.length },
1998
+ };
1976
1999
  }
1977
2000
 
1978
- return blocklets;
2001
+ return { blocklets, paging: { total: blocklets.length } };
1979
2002
  }
1980
2003
 
1981
2004
  listBackups() {
@@ -2740,9 +2763,24 @@ class DiskBlockletManager extends BaseBlockletManager {
2740
2763
  );
2741
2764
  }
2742
2765
 
2766
+ /**
2767
+ * Update certificates for all blocklets in batches
2768
+ * Memory-efficient: processes 100 blocklets at a time
2769
+ */
2743
2770
  async updateAllBlockletCertificate() {
2744
- const blocklets = await states.blocklet.getBlocklets();
2745
- await Promise.all(blocklets.map((blocklet) => this._updateBlockletCertificate(blocklet.meta.did)));
2771
+ await states.blocklet.forEachBatch({
2772
+ projection: { appPid: 1 },
2773
+ batchSize: 100,
2774
+ onBatch: async (blocklets) => {
2775
+ try {
2776
+ await Promise.all(
2777
+ blocklets.filter(({ appPid }) => appPid).map(({ appPid }) => this._updateBlockletCertificate(appPid))
2778
+ );
2779
+ } catch (error) {
2780
+ logger.error('Failed to update certificate for blocklet', { error: error.message });
2781
+ }
2782
+ },
2783
+ });
2746
2784
  }
2747
2785
 
2748
2786
  /**
@@ -2808,11 +2846,6 @@ class DiskBlockletManager extends BaseBlockletManager {
2808
2846
  refreshAccessibleExternalNodeIp(nodeInfo);
2809
2847
  },
2810
2848
  },
2811
- {
2812
- name: 'record-blocklet-runtime-history',
2813
- time: `*/${MONITOR_RECORD_INTERVAL_SEC} * * * * *`, // 10s
2814
- fn: () => this.runtimeMonitor.monitAll(),
2815
- },
2816
2849
  {
2817
2850
  name: 'update-blocklet-certificate',
2818
2851
  time: '*/10 * * * *',
@@ -2824,6 +2857,14 @@ class DiskBlockletManager extends BaseBlockletManager {
2824
2857
  },
2825
2858
  ];
2826
2859
 
2860
+ if (!isRuntimeMonitorDisabled()) {
2861
+ crons.push({
2862
+ name: 'record-blocklet-runtime-history',
2863
+ time: `*/${MONITOR_RECORD_INTERVAL_SEC} * * * * *`, // 10s
2864
+ fn: () => this.runtimeMonitor.monitAll(),
2865
+ });
2866
+ }
2867
+
2827
2868
  if (isInServerlessMode(info)) {
2828
2869
  const serverlessJobs = [
2829
2870
  {
@@ -4255,6 +4296,7 @@ class DiskBlockletManager extends BaseBlockletManager {
4255
4296
  }
4256
4297
 
4257
4298
  async _attachBlockletListRuntimeInfo({ blocklets }, context) {
4299
+ const nodeInfo = await states.node.read();
4258
4300
  return (
4259
4301
  await Promise.all(
4260
4302
  blocklets.map((x) => {
@@ -4264,6 +4306,7 @@ class DiskBlockletManager extends BaseBlockletManager {
4264
4306
 
4265
4307
  return this._attachRuntimeInfo({
4266
4308
  did: x.meta.did,
4309
+ nodeInfo,
4267
4310
  diskInfo: false,
4268
4311
  context,
4269
4312
  });
@@ -4275,15 +4318,7 @@ class DiskBlockletManager extends BaseBlockletManager {
4275
4318
  // 处理 domainAliases#value SLOT_FOR_IP_DNS_SITE
4276
4319
  async getDomainAliases({ blocklet, nodeInfo }, context = {}) {
4277
4320
  if (blocklet?.site?.domainAliases?.length) {
4278
- let info = nodeInfo;
4279
- try {
4280
- if (!info && this.nodeAPI) {
4281
- info = await this.nodeAPI.getInfo();
4282
- }
4283
- } catch (error) {
4284
- logger.error('Failed to get node info', { error });
4285
- }
4286
- const nodeIp = await getAccessibleExternalNodeIp(info);
4321
+ const nodeIp = await getAccessibleExternalNodeIp(nodeInfo || (await states.node.read()));
4287
4322
  return blocklet.site.domainAliases.map((x) => ({
4288
4323
  ...x,
4289
4324
  value: util.replaceDomainSlot({ domain: x.value, context, nodeIp }),
@@ -4293,7 +4328,7 @@ class DiskBlockletManager extends BaseBlockletManager {
4293
4328
  return [];
4294
4329
  }
4295
4330
 
4296
- async _attachRuntimeInfo({ did, diskInfo = false, context, getOptionalComponents }) {
4331
+ async _attachRuntimeInfo({ did, nodeInfo, diskInfo = false, context, getOptionalComponents }) {
4297
4332
  if (!did) {
4298
4333
  throw new Error('did should not be empty');
4299
4334
  }
@@ -4306,7 +4341,10 @@ class DiskBlockletManager extends BaseBlockletManager {
4306
4341
  }
4307
4342
 
4308
4343
  if (blocklet.site) {
4309
- blocklet.site.domainAliases = await this.getDomainAliases({ blocklet }, context);
4344
+ blocklet.site.domainAliases = await this.getDomainAliases(
4345
+ { blocklet, nodeInfo: nodeInfo || (await states.node.read()) },
4346
+ context
4347
+ );
4310
4348
  }
4311
4349
 
4312
4350
  // app runtime info, app status
@@ -4344,7 +4382,7 @@ class DiskBlockletManager extends BaseBlockletManager {
4344
4382
  // FIXME: @wangshijun this should be dynamic
4345
4383
  logo: '',
4346
4384
  };
4347
- } else {
4385
+ } else if (engineId !== STATIC_SERVER_ENGINE_DID) {
4348
4386
  // Note: the component maybe in dev mode or removed
4349
4387
  logger.warn(`engine component ${engineId} not found for ${did}`);
4350
4388
  }
@@ -4400,6 +4438,7 @@ class DiskBlockletManager extends BaseBlockletManager {
4400
4438
  folder,
4401
4439
  onlyRequired,
4402
4440
  requirements,
4441
+ context,
4403
4442
  }) {
4404
4443
  const environments = component?.meta?.environments || [];
4405
4444
 
@@ -4501,6 +4540,8 @@ class DiskBlockletManager extends BaseBlockletManager {
4501
4540
  await states.blockletExtras.setConfigs(blocklet.meta.did, [chainTypeEnv]);
4502
4541
  await states.blockletExtras.setSettings(blocklet.meta.did, { session: { salt: generateRandomString(16) } });
4503
4542
 
4543
+ this.emit(BlockletEvents.added, { blocklet, context });
4544
+
4504
4545
  return blocklet;
4505
4546
  }
4506
4547
 
@@ -5772,6 +5813,7 @@ class DiskBlockletManager extends BaseBlockletManager {
5772
5813
  .map((key) => ({
5773
5814
  ...omit(blocklet.settings?.oauth[key], 'order'),
5774
5815
  type: 'oauth',
5816
+ provider: key,
5775
5817
  }))
5776
5818
  .filter((x) => x.enabled === true);
5777
5819
  authenticationList.push(...oauthList);
@@ -50,7 +50,7 @@ class EnsureBlockletRunning {
50
50
 
51
51
  waitingTimeout = +process.env.ABT_NODE_ENSURE_RUNNING_WAITING_TIMEOUT || 60 * 1000;
52
52
 
53
- downloadingTimeout = +process.env.ABT_NODE_ENSURE_RUNNING_DOWNLOADING_TIMEOUT || 3 * 60 * 1000;
53
+ downloadingTimeout = +process.env.ABT_NODE_ENSURE_RUNNING_DOWNLOADING_TIMEOUT || 10 * 60 * 1000;
54
54
 
55
55
  startingTimeout = +process.env.ABT_NODE_ENSURE_RUNNING_STARTING_TIMEOUT || 6 * 60 * 1000;
56
56
 
@@ -448,7 +448,7 @@ const blueGreenStartBlocklet = async (
448
448
  // 如果是蓝绿更新发起的,则不更新 route table,因为蓝绿更新会自动更新 route table
449
449
  if (!['true', '1'].includes(process.env.ABT_NODE_DISABLE_BLUE_GREEN) && !ignoreBlockletStartedEvent) {
450
450
  const latestBlocklet = await manager.getBlocklet(did, { e2eMode });
451
- manager.emit(BlockletEvents.blurOrGreenStarted, {
451
+ manager.emit(BlockletEvents.blueOrGreenStarted, {
452
452
  blocklet: latestBlocklet,
453
453
  componentDids,
454
454
  context,
@@ -1,6 +1,6 @@
1
1
  const { isInServerlessMode } = require('@abtnode/util/lib/serverless');
2
2
  const { BLOCKLET_INSTALL_TYPE, INSTALL_ACTIONS } = require('@abtnode/constant');
3
- const { BlockletStatus, BlockletEvents, BLOCKLET_CONFIGURABLE_KEY } = require('@blocklet/constant');
3
+ const { BlockletStatus, BLOCKLET_CONFIGURABLE_KEY } = require('@blocklet/constant');
4
4
 
5
5
  const logger = require('@abtnode/logger')('@abtnode/core:install-app-general');
6
6
  const { getApplicationWallet } = require('@blocklet/meta/lib/wallet');
@@ -124,6 +124,7 @@ const installApplicationFromGeneral = async ({
124
124
  skSource,
125
125
  onlyRequired,
126
126
  requirements,
127
+ context,
127
128
  });
128
129
  logger.info('blocklet added to database', { did: blocklet.meta.did });
129
130
 
@@ -178,8 +179,6 @@ const installApplicationFromGeneral = async ({
178
179
 
179
180
  try {
180
181
  const blocklet1 = await states.blocklet.setBlockletStatus(did, BlockletStatus.waiting);
181
- manager.emit(BlockletEvents.added, blocklet1);
182
-
183
182
  const action = INSTALL_ACTIONS.INSTALL;
184
183
  const downloadParams = {
185
184
  blocklet: { ...blocklet1 },
@@ -2,7 +2,8 @@ const { sign } = require('@arcblock/jwt');
2
2
 
3
3
  const logger = require('@abtnode/logger')('@abtnode/core:install-component-url');
4
4
  const uniq = require('lodash/uniq');
5
- const { isFreeBlocklet, hasStartEngine } = require('@blocklet/meta/lib/util');
5
+ const { isFreeBlocklet } = require('@blocklet/meta/lib/util');
6
+ const { hasMountPoint, hasStartEngine } = require('@blocklet/meta/lib/engine');
6
7
  const { titleSchema, updateMountPointSchema } = require('@blocklet/meta/lib/schema');
7
8
  const { hasReservedKey } = require('@blocklet/meta/lib/has-reserved-key');
8
9
  const formatName = require('@abtnode/util/lib/format-name');
@@ -89,9 +90,11 @@ const installComponentFromUrl = async ({
89
90
  : { url },
90
91
  };
91
92
 
92
- if (hasStartEngine(newChildMeta)) {
93
- const mountPoint = await updateMountPointSchema.validateAsync(tmpMountPoint);
94
- newChild.mountPoint = mountPoint || formatName(newChildMeta.title) || formatName(newChildMeta.name);
93
+ if (hasStartEngine(newChildMeta) || hasMountPoint(newChildMeta)) {
94
+ const mountPoint = tmpMountPoint
95
+ ? await updateMountPointSchema.validateAsync(tmpMountPoint)
96
+ : formatName(newChildMeta.title) || formatName(newChildMeta.name);
97
+ newChild.mountPoint = mountPoint;
95
98
  }
96
99
 
97
100
  const { dynamicComponents } = await parseComponents(newChild);
@@ -555,6 +555,8 @@ module.exports = Object.freeze({
555
555
  CONFIG_FOLDER_NAME_OLD: '.abtnode',
556
556
  EXPORTED_FOLDER_NAME: 'exported_blocklet_server',
557
557
 
558
+ DEFAULT_WELLKNOWN_PORT: 8088,
559
+
558
560
  StatusCode: Object.freeze({
559
561
  ok: 0,
560
562
 
@@ -591,7 +593,6 @@ module.exports = Object.freeze({
591
593
 
592
594
  DEFAULT_ADMIN_PATH: '/admin',
593
595
  WELLKNOWN_SERVER_ADMIN_PATH: '/.well-known/server/admin',
594
- DEFAULT_SERVICE_PATH: '/.abtnode/service',
595
596
  DEFAULT_HTTP_PORT: 80,
596
597
  DEFAULT_HTTPS_PORT: 443,
597
598
  MAX_UPLOAD_FILE_SIZE: 100, // unit: MB
@@ -680,8 +681,8 @@ module.exports = Object.freeze({
680
681
  // @link https://www.nginx.com/blog/nginx-caching-guide/
681
682
  ROUTER_CACHE_GROUPS: {
682
683
  blockletProxy: {
683
- minSize: '1m',
684
- maxSize: '2g',
684
+ minSize: '10m',
685
+ maxSize: '10g',
685
686
  period: '30d',
686
687
  },
687
688
  // TODO: disabled because we can not bust nginx cache effectively for now
@@ -39044,7 +39045,7 @@ module.exports = require("zlib");
39044
39045
  /***/ ((module) => {
39045
39046
 
39046
39047
  "use strict";
39047
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@abtnode/core","publishConfig":{"access":"public"},"version":"1.17.6","description":"","main":"lib/index.js","files":["lib"],"scripts":{"lint":"eslint tests lib --ignore-pattern \'tests/assets/*\'","lint:fix":"eslint --fix tests lib"},"keywords":[],"author":"wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)","license":"Apache-2.0","dependencies":{"@abtnode/analytics":"1.17.6","@abtnode/auth":"1.17.6","@abtnode/certificate-manager":"1.17.6","@abtnode/constant":"1.17.6","@abtnode/cron":"1.17.6","@abtnode/db-cache":"1.17.6","@abtnode/docker-utils":"1.17.6","@abtnode/logger":"1.17.6","@abtnode/models":"1.17.6","@abtnode/queue":"1.17.6","@abtnode/rbac":"1.17.6","@abtnode/router-provider":"1.17.6","@abtnode/static-server":"1.17.6","@abtnode/timemachine":"1.17.6","@abtnode/util":"1.17.6","@aigne/aigne-hub":"^0.10.15","@arcblock/did":"^1.27.16","@arcblock/did-connect-js":"^1.27.16","@arcblock/did-ext":"^1.27.16","@arcblock/did-motif":"^1.1.14","@arcblock/did-util":"^1.27.16","@arcblock/event-hub":"^1.27.16","@arcblock/jwt":"^1.27.16","@arcblock/pm2-events":"^0.0.5","@arcblock/validator":"^1.27.16","@arcblock/vc":"^1.27.16","@blocklet/constant":"1.17.6","@blocklet/did-space-js":"^1.2.12","@blocklet/env":"1.17.6","@blocklet/error":"^0.3.5","@blocklet/meta":"1.17.6","@blocklet/resolver":"1.17.6","@blocklet/sdk":"1.17.6","@blocklet/server-js":"1.17.6","@blocklet/store":"1.17.6","@blocklet/theme":"^3.3.0","@fidm/x509":"^1.2.1","@ocap/mcrypto":"^1.27.16","@ocap/util":"^1.27.16","@ocap/wallet":"^1.27.16","@slack/webhook":"^7.0.6","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","private-ip":"^2.3.4","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":"^11.1.0","valid-url":"^1.0.9","which":"^2.0.2","xbytes":"^1.8.0"},"devDependencies":{"axios-mock-adapter":"^2.1.0","expand-tilde":"^2.0.2","express":"^4.18.2","unzipper":"^0.10.11"},"gitHead":"e5764f753181ed6a7c615cd4fc6682aacf0cb7cd"}');
39048
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@abtnode/core","publishConfig":{"access":"public"},"version":"1.17.6","description":"","main":"lib/index.js","files":["lib"],"scripts":{"lint":"eslint tests lib --ignore-pattern \'tests/assets/*\'","lint:fix":"eslint --fix tests lib"},"keywords":[],"author":"wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)","license":"Apache-2.0","dependencies":{"@abtnode/analytics":"1.17.6","@abtnode/auth":"1.17.6","@abtnode/certificate-manager":"1.17.6","@abtnode/constant":"1.17.6","@abtnode/cron":"1.17.6","@abtnode/db-cache":"1.17.6","@abtnode/docker-utils":"1.17.6","@abtnode/logger":"1.17.6","@abtnode/models":"1.17.6","@abtnode/queue":"1.17.6","@abtnode/rbac":"1.17.6","@abtnode/router-provider":"1.17.6","@abtnode/util":"1.17.6","@aigne/aigne-hub":"^0.10.15","@arcblock/did":"^1.27.16","@arcblock/did-connect-js":"^1.27.16","@arcblock/did-ext":"^1.27.16","@arcblock/did-motif":"^1.1.14","@arcblock/did-util":"^1.27.16","@arcblock/event-hub":"^1.27.16","@arcblock/jwt":"^1.27.16","@arcblock/pm2-events":"^0.0.5","@arcblock/validator":"^1.27.16","@arcblock/vc":"^1.27.16","@blocklet/constant":"1.17.6","@blocklet/did-space-js":"^1.2.12","@blocklet/env":"1.17.6","@blocklet/error":"^0.3.5","@blocklet/meta":"1.17.6","@blocklet/resolver":"1.17.6","@blocklet/sdk":"1.17.6","@blocklet/server-js":"1.17.6","@blocklet/store":"1.17.6","@blocklet/theme":"^3.3.3","@fidm/x509":"^1.2.1","@ocap/mcrypto":"^1.27.16","@ocap/util":"^1.27.16","@ocap/wallet":"^1.27.16","@slack/webhook":"^7.0.6","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","private-ip":"^2.3.4","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":"^11.1.0","valid-url":"^1.0.9","which":"^2.0.2","xbytes":"^1.8.0"},"devDependencies":{"axios-mock-adapter":"^2.1.0","expand-tilde":"^2.0.2","express":"^4.18.2","unzipper":"^0.10.11"},"gitHead":"e5764f753181ed6a7c615cd4fc6682aacf0cb7cd"}');
39048
39049
 
39049
39050
  /***/ }),
39050
39051
 
@@ -129,8 +129,15 @@ class PassportAPI extends EventEmitter {
129
129
  async updatePassportExpire(nodeDid) {
130
130
  await this.updatePassport(nodeDid);
131
131
 
132
- const blocklets = await this.states.blocklet.getBlocklets({});
133
- await Promise.all(blocklets.map(({ meta: { did } }) => this.updatePassport(did)));
132
+ // Process blocklets in paginated batches to avoid loading all records at once
133
+ // Memory-efficient: only loads one batch at a time (100 records) instead of all 10K
134
+ await this.states.blocklet.forEachBatch({
135
+ projection: { appPid: 1 },
136
+ batchSize: 100,
137
+ onBatch: async (blocklets) => {
138
+ await Promise.all(blocklets.filter(({ appPid }) => appPid).map(({ appPid }) => this.updatePassport(appPid)));
139
+ },
140
+ });
134
141
  }
135
142
 
136
143
  getCron(nodeDid) {
@@ -138,7 +145,7 @@ class PassportAPI extends EventEmitter {
138
145
 
139
146
  return {
140
147
  name: 'check-passport-expire',
141
- time: '0 */10 * * * *',
148
+ time: '0 0 * * * *',
142
149
  fn: async () => {
143
150
  logger.info('check passport expire', { nodeDid });
144
151
  await updatePassportExpire(nodeDid).catch((error) => {
@@ -2,7 +2,12 @@ const path = require('path');
2
2
  const fs = require('fs-extra');
3
3
  const createArchive = require('archiver');
4
4
  const pick = require('lodash/pick');
5
- const { BLOCKLET_META_FILE, PROJECT, BLOCKLET_INTERFACE_TYPE_WEB } = require('@blocklet/constant');
5
+ const {
6
+ BLOCKLET_META_FILE,
7
+ PROJECT,
8
+ BLOCKLET_INTERFACE_TYPE_WEB,
9
+ STATIC_SERVER_ENGINE_DID,
10
+ } = require('@blocklet/constant');
6
11
  const { update: updateMetaFile, read: readMetaFile } = require('@blocklet/meta/lib/file');
7
12
  const { createRelease: createBlockletRelease } = require('@abtnode/util/lib/create-blocklet-release');
8
13
  const { titleSchema } = require('@blocklet/meta/lib/schema');
@@ -434,7 +439,7 @@ const createRelease = async ({
434
439
  interpreter: 'blocklet',
435
440
  source: {
436
441
  store: 'https://store.blocklet.dev',
437
- name: 'z2qa2dGC9EmsjB2WJtUcmuRWx43zTwPUZQF7g',
442
+ name: STATIC_SERVER_ENGINE_DID,
438
443
  version: 'latest',
439
444
  },
440
445
  };
@@ -197,7 +197,7 @@ class SecurityAPI extends EventEmitter {
197
197
  const upsertOrSkipSecurityRule = async (data) => {
198
198
  if (data.value === null) return;
199
199
 
200
- const genrateAccessPolicyId = `migrate-${data.id}`;
200
+ const generateAccessPolicyId = `migrate-${data.id}`;
201
201
  const isDefaultRule = data.id === SECURITY_RULE_DEFAULT_ID;
202
202
 
203
203
  const { securityRules } = await getBlockletSecurityRules({ teamManager: this.teamManager }, { did });
@@ -218,7 +218,7 @@ class SecurityAPI extends EventEmitter {
218
218
  {
219
219
  did,
220
220
  data: {
221
- id: genrateAccessPolicyId,
221
+ id: generateAccessPolicyId,
222
222
  name: roles.join(','),
223
223
  description: `Migrate from legacy whoCanAccess: ${data.rawValue}`,
224
224
  roles,
package/lib/cert.js CHANGED
@@ -131,9 +131,12 @@ class Cert extends EventEmitter {
131
131
  }
132
132
 
133
133
  async remove({ id }) {
134
- await this.manager.remove(id);
135
- logger.info('delete certificate', { id });
136
- this.emit(EVENTS.CERT_REMOVED);
134
+ const cert = await this.manager.findById(id);
135
+ if (cert) {
136
+ await this.manager.remove(id);
137
+ logger.info('delete certificate', { id });
138
+ this.emit(EVENTS.CERT_REMOVED, cert);
139
+ }
137
140
 
138
141
  return {};
139
142
  }