@abtnode/core 1.17.7-beta-20251225-073259-cb6ecf68 → 1.17.7-beta-20251229-085620-84f09930

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 (41) hide show
  1. package/lib/blocklet/manager/disk.js +150 -36
  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 +18 -27
  14. package/lib/migrations/1.17.7-beta-2025122601-settings-authentication.js +19 -0
  15. package/lib/migrations/1.5.0-site.js +3 -7
  16. package/lib/migrations/1.5.15-site.js +3 -7
  17. package/lib/monitor/blocklet-runtime-monitor.js +37 -5
  18. package/lib/monitor/node-runtime-monitor.js +4 -4
  19. package/lib/router/helper.js +525 -452
  20. package/lib/router/index.js +280 -104
  21. package/lib/router/manager.js +14 -28
  22. package/lib/states/audit-log.js +6 -3
  23. package/lib/states/blocklet-child.js +93 -1
  24. package/lib/states/blocklet-extras.js +1 -1
  25. package/lib/states/blocklet.js +429 -197
  26. package/lib/states/node.js +0 -10
  27. package/lib/states/site.js +87 -4
  28. package/lib/team/manager.js +2 -21
  29. package/lib/util/blocklet.js +71 -37
  30. package/lib/util/get-accessible-external-node-ip.js +21 -6
  31. package/lib/util/index.js +3 -3
  32. package/lib/util/ip.js +15 -1
  33. package/lib/util/launcher.js +11 -11
  34. package/lib/util/ready.js +2 -9
  35. package/lib/util/reset-node.js +6 -5
  36. package/lib/validators/router.js +0 -3
  37. package/lib/webhook/sender/api/index.js +5 -0
  38. package/package.json +35 -37
  39. package/lib/migrations/1.0.36-snapshot.js +0 -10
  40. package/lib/migrations/1.1.9-snapshot.js +0 -7
  41. package/lib/states/routing-snapshot.js +0 -146
@@ -66,6 +66,7 @@ const {
66
66
  getDisplayName,
67
67
  isExternalBlocklet,
68
68
  } = require('@blocklet/meta/lib/util');
69
+ const { getConfigs } = require('@blocklet/meta/lib/util-config');
69
70
  const { getComponentsInternalInfo } = require('@blocklet/meta/lib/blocklet');
70
71
  const { getRequiredComponentsLayers } = require('@blocklet/meta/lib/get-required-components-layers');
71
72
  const { update: updateMetaFile } = require('@blocklet/meta/lib/file');
@@ -102,6 +103,8 @@ const {
102
103
  APP_CONFIG_DIR,
103
104
  COMPONENT_ENV_FILE_NAME,
104
105
  BLOCKLET_PREFERENCE_PREFIX,
106
+ STATIC_SERVER_ENGINE_DID,
107
+ LOGIN_PROVIDER,
105
108
  } = require('@blocklet/constant');
106
109
 
107
110
  const { WELLKNOWN_SERVICE_PATH_PREFIX, WELLKNOWN_BLOCKLET_ADMIN_PATH } = require('@abtnode/constant');
@@ -130,7 +133,7 @@ const { updateComponentDid, removeUploadFile } = require('@abtnode/util/lib/uplo
130
133
  const groupBy = require('lodash/groupBy');
131
134
  const { isDidDomain, isCustomDomain, getOriginUrl } = require('@abtnode/util/lib/url-evaluation');
132
135
  const { DBCache, getAbtNodeRedisAndSQLiteUrl } = require('@abtnode/db-cache');
133
- const { isInstanceWorker } = require('@abtnode/util/lib/pm2/is-instance-worker.js');
136
+ const { isWorkerInstance } = require('@abtnode/util/lib/pm2/is-instance-worker.js');
134
137
  const launcher = require('../../util/launcher');
135
138
  const util = require('../../util');
136
139
  const {
@@ -188,7 +191,7 @@ const BaseBlockletManager = require('./base');
188
191
  const { get: getEngine } = require('./engine');
189
192
  const runBlockletMigrationScripts = require('../migration');
190
193
  const hooks = require('../hooks');
191
- const { BlockletRuntimeMonitor } = require('../../monitor/blocklet-runtime-monitor');
194
+ const { BlockletRuntimeMonitor, isRuntimeMonitorDisabled } = require('../../monitor/blocklet-runtime-monitor');
192
195
  const getHistoryList = require('../../monitor/get-history-list');
193
196
  const { SpacesBackup } = require('../storage/backup/spaces');
194
197
  const { DiskBackup } = require('../storage/backup/disk');
@@ -420,7 +423,7 @@ class DiskBlockletManager extends BaseBlockletManager {
420
423
  }
421
424
 
422
425
  ensureBlockletRunning = () => {
423
- if (isInstanceWorker()) {
426
+ if (isWorkerInstance()) {
424
427
  return;
425
428
  }
426
429
  ensureBlockletRunning.initialize({
@@ -545,9 +548,8 @@ class DiskBlockletManager extends BaseBlockletManager {
545
548
  * @memberof BlockletManager
546
549
  */
547
550
  async install(params, context = {}) {
548
- logger.debug('install blocklet', { params, context });
549
-
550
551
  const type = getTypeFromInstallParams(params);
552
+ logger.info('install blocklet', { type, params: omit(params, ['appSk']), user: context.user });
551
553
 
552
554
  const { appSk } = params;
553
555
  if (!appSk) {
@@ -829,12 +831,12 @@ class DiskBlockletManager extends BaseBlockletManager {
829
831
  if (!baseComponentDids.includes(b.meta.did)) {
830
832
  continue;
831
833
  }
832
- const engine = getBlockletEngine(b.meta);
833
- if (engine.interpreter === 'blocklet') {
834
+ if (!hasStartEngine(b.meta)) {
834
835
  nonEntryComponentIds.push(b.meta.did);
835
836
  continue;
836
837
  }
837
- if (!hasStartEngine(b.meta)) {
838
+ const engine = getBlockletEngine(b.meta);
839
+ if (engine.interpreter === 'blocklet') {
838
840
  nonEntryComponentIds.push(b.meta.did);
839
841
  continue;
840
842
  }
@@ -876,7 +878,7 @@ class DiskBlockletManager extends BaseBlockletManager {
876
878
 
877
879
  // 根据情况更新 route table
878
880
  if (!['true', '1'].includes(process.env.ABT_NODE_DISABLE_BLUE_GREEN)) {
879
- this.emit(BlockletEvents.blurOrGreenStarted, {
881
+ this.emit(BlockletEvents.blueOrGreenStarted, {
880
882
  blocklet: finalBlocklet,
881
883
  componentDids: inputComponentDids,
882
884
  context,
@@ -1051,7 +1053,7 @@ class DiskBlockletManager extends BaseBlockletManager {
1051
1053
 
1052
1054
  // 根据情况更新 route table, 会判断只有包含多 interfaces 的 DID 才会更新 route table
1053
1055
  if (!['true', '1'].includes(process.env.ABT_NODE_DISABLE_BLUE_GREEN)) {
1054
- this.emit(BlockletEvents.blurOrGreenStarted, {
1056
+ this.emit(BlockletEvents.blueOrGreenStarted, {
1055
1057
  blocklet: resultBlocklet,
1056
1058
  componentDids: inputComponentDids,
1057
1059
  context,
@@ -1966,14 +1968,37 @@ class DiskBlockletManager extends BaseBlockletManager {
1966
1968
  }
1967
1969
  }
1968
1970
 
1969
- 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)
1970
1992
  const condition = { ...flat(query || {}) };
1971
1993
  const blocklets = await states.blocklet.getBlocklets(condition);
1972
1994
  if (includeRuntimeInfo) {
1973
- return this._attachBlockletListRuntimeInfo({ blocklets }, context);
1995
+ return {
1996
+ blocklets: await this._attachBlockletListRuntimeInfo({ blocklets }, context),
1997
+ paging: { total: blocklets.length },
1998
+ };
1974
1999
  }
1975
2000
 
1976
- return blocklets;
2001
+ return { blocklets, paging: { total: blocklets.length } };
1977
2002
  }
1978
2003
 
1979
2004
  listBackups() {
@@ -2285,10 +2310,22 @@ class DiskBlockletManager extends BaseBlockletManager {
2285
2310
  return newState;
2286
2311
  }
2287
2312
 
2288
- async configOAuth({ did, oauth = {} }, context) {
2289
- const oldOAuth = await states.blockletExtras.getSettings(did, 'oauth', {});
2290
- const mergeConfig = defaultsDeep(JSON.parse(oauth), oldOAuth);
2291
- await states.blockletExtras.setSettings(did, { oauth: mergeConfig });
2313
+ async configAuthentication({ did, authentication = {} }, context) {
2314
+ const oldConfig = await states.blockletExtras.getSettings(did, 'authentication', {});
2315
+ const parsedData = JSON.parse(authentication);
2316
+ const mergeConfig = defaultsDeep(parsedData, oldConfig);
2317
+ await states.blockletExtras.setSettings(did, { authentication: mergeConfig });
2318
+ const newState = await this.getBlocklet(did);
2319
+ this.emit(BlockletInternalEvents.appSettingChanged, { appDid: did });
2320
+ this.emit(BlockletEvents.updated, { ...newState, context });
2321
+ return newState;
2322
+ }
2323
+
2324
+ async configDidConnect({ did, didConnect = {} }, context) {
2325
+ const oldConfig = await states.blockletExtras.getSettings(did, 'didConnect', {});
2326
+ const parsedData = JSON.parse(didConnect);
2327
+ const mergeConfig = defaultsDeep(parsedData, oldConfig);
2328
+ await states.blockletExtras.setSettings(did, { didConnect: mergeConfig });
2292
2329
  const newState = await this.getBlocklet(did);
2293
2330
  this.emit(BlockletInternalEvents.appSettingChanged, { appDid: did });
2294
2331
  this.emit(BlockletEvents.updated, { ...newState, context });
@@ -2726,9 +2763,24 @@ class DiskBlockletManager extends BaseBlockletManager {
2726
2763
  );
2727
2764
  }
2728
2765
 
2766
+ /**
2767
+ * Update certificates for all blocklets in batches
2768
+ * Memory-efficient: processes 100 blocklets at a time
2769
+ */
2729
2770
  async updateAllBlockletCertificate() {
2730
- const blocklets = await states.blocklet.getBlocklets();
2731
- 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
+ });
2732
2784
  }
2733
2785
 
2734
2786
  /**
@@ -2794,11 +2846,6 @@ class DiskBlockletManager extends BaseBlockletManager {
2794
2846
  refreshAccessibleExternalNodeIp(nodeInfo);
2795
2847
  },
2796
2848
  },
2797
- {
2798
- name: 'record-blocklet-runtime-history',
2799
- time: `*/${MONITOR_RECORD_INTERVAL_SEC} * * * * *`, // 10s
2800
- fn: () => this.runtimeMonitor.monitAll(),
2801
- },
2802
2849
  {
2803
2850
  name: 'update-blocklet-certificate',
2804
2851
  time: '*/10 * * * *',
@@ -2810,6 +2857,14 @@ class DiskBlockletManager extends BaseBlockletManager {
2810
2857
  },
2811
2858
  ];
2812
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
+
2813
2868
  if (isInServerlessMode(info)) {
2814
2869
  const serverlessJobs = [
2815
2870
  {
@@ -4241,6 +4296,7 @@ class DiskBlockletManager extends BaseBlockletManager {
4241
4296
  }
4242
4297
 
4243
4298
  async _attachBlockletListRuntimeInfo({ blocklets }, context) {
4299
+ const nodeInfo = await states.node.read();
4244
4300
  return (
4245
4301
  await Promise.all(
4246
4302
  blocklets.map((x) => {
@@ -4250,6 +4306,7 @@ class DiskBlockletManager extends BaseBlockletManager {
4250
4306
 
4251
4307
  return this._attachRuntimeInfo({
4252
4308
  did: x.meta.did,
4309
+ nodeInfo,
4253
4310
  diskInfo: false,
4254
4311
  context,
4255
4312
  });
@@ -4261,15 +4318,7 @@ class DiskBlockletManager extends BaseBlockletManager {
4261
4318
  // 处理 domainAliases#value SLOT_FOR_IP_DNS_SITE
4262
4319
  async getDomainAliases({ blocklet, nodeInfo }, context = {}) {
4263
4320
  if (blocklet?.site?.domainAliases?.length) {
4264
- let info = nodeInfo;
4265
- try {
4266
- if (!info && this.nodeAPI) {
4267
- info = await this.nodeAPI.getInfo();
4268
- }
4269
- } catch (error) {
4270
- logger.error('Failed to get node info', { error });
4271
- }
4272
- const nodeIp = await getAccessibleExternalNodeIp(info);
4321
+ const nodeIp = await getAccessibleExternalNodeIp(nodeInfo || (await states.node.read()));
4273
4322
  return blocklet.site.domainAliases.map((x) => ({
4274
4323
  ...x,
4275
4324
  value: util.replaceDomainSlot({ domain: x.value, context, nodeIp }),
@@ -4279,7 +4328,7 @@ class DiskBlockletManager extends BaseBlockletManager {
4279
4328
  return [];
4280
4329
  }
4281
4330
 
4282
- async _attachRuntimeInfo({ did, diskInfo = false, context, getOptionalComponents }) {
4331
+ async _attachRuntimeInfo({ did, nodeInfo, diskInfo = false, context, getOptionalComponents }) {
4283
4332
  if (!did) {
4284
4333
  throw new Error('did should not be empty');
4285
4334
  }
@@ -4292,7 +4341,10 @@ class DiskBlockletManager extends BaseBlockletManager {
4292
4341
  }
4293
4342
 
4294
4343
  if (blocklet.site) {
4295
- 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
+ );
4296
4348
  }
4297
4349
 
4298
4350
  // app runtime info, app status
@@ -4330,7 +4382,7 @@ class DiskBlockletManager extends BaseBlockletManager {
4330
4382
  // FIXME: @wangshijun this should be dynamic
4331
4383
  logo: '',
4332
4384
  };
4333
- } else {
4385
+ } else if (engineId !== STATIC_SERVER_ENGINE_DID) {
4334
4386
  // Note: the component maybe in dev mode or removed
4335
4387
  logger.warn(`engine component ${engineId} not found for ${did}`);
4336
4388
  }
@@ -4386,6 +4438,7 @@ class DiskBlockletManager extends BaseBlockletManager {
4386
4438
  folder,
4387
4439
  onlyRequired,
4388
4440
  requirements,
4441
+ context,
4389
4442
  }) {
4390
4443
  const environments = component?.meta?.environments || [];
4391
4444
 
@@ -4487,6 +4540,8 @@ class DiskBlockletManager extends BaseBlockletManager {
4487
4540
  await states.blockletExtras.setConfigs(blocklet.meta.did, [chainTypeEnv]);
4488
4541
  await states.blockletExtras.setSettings(blocklet.meta.did, { session: { salt: generateRandomString(16) } });
4489
4542
 
4543
+ this.emit(BlockletEvents.added, { blocklet, context });
4544
+
4490
4545
  return blocklet;
4491
4546
  }
4492
4547
 
@@ -4512,6 +4567,9 @@ class DiskBlockletManager extends BaseBlockletManager {
4512
4567
  await this._updateBlockletEnvironment(meta.did);
4513
4568
  blocklet = await this.getBlocklet(did);
4514
4569
 
4570
+ // Add initialize authentication settings
4571
+ await this.migrateBlockletAuthentication({ did });
4572
+
4515
4573
  // pre install
4516
4574
  await this._runUserHook('preInstall', blocklet, context);
4517
4575
 
@@ -5717,6 +5775,62 @@ class DiskBlockletManager extends BaseBlockletManager {
5717
5775
  const cnameDomain = (get(blocklet, 'site.domainAliases') || []).find((item) => isDidDomain(item.value));
5718
5776
  return this.routerManager.checkDomainDNS(domain, cnameDomain?.value);
5719
5777
  }
5778
+
5779
+ /**
5780
+ * used for 1.17.7-settings-authentication migrate, don't use in other places
5781
+ * @param {string} options.did blocklet did
5782
+ */
5783
+ async migrateBlockletAuthentication({ did }) {
5784
+ const blocklet = await this.getBlocklet(did);
5785
+ if (blocklet.settings?.authentication) return;
5786
+
5787
+ const authenticationList = [];
5788
+
5789
+ const configs = getConfigs(blocklet, did);
5790
+ const allowWallet = configs.find((x) => x.key === 'DID_CONNECT_ALLOW_WALLET')?.value;
5791
+ if (['1', 'true', undefined, null].includes(allowWallet)) {
5792
+ // 默认是允许使用 wallet
5793
+ authenticationList.push({
5794
+ enabled: true,
5795
+ showQrcode: true,
5796
+ type: 'builtin',
5797
+ provider: LOGIN_PROVIDER.WALLET,
5798
+ });
5799
+ }
5800
+
5801
+ const isEmailServiceEnabled = Boolean(getEmailServiceProvider(blocklet));
5802
+ if (isEmailServiceEnabled) {
5803
+ authenticationList.push({
5804
+ enabled: isEmailServiceEnabled,
5805
+ type: 'builtin',
5806
+ provider: LOGIN_PROVIDER.EMAIL,
5807
+ });
5808
+ }
5809
+
5810
+ // 对旧的数据进行转换,并保存
5811
+ if (blocklet.settings?.oauth) {
5812
+ const oauthList = Object.keys(blocklet.settings?.oauth)
5813
+ .map((key) => ({
5814
+ ...omit(blocklet.settings?.oauth[key], 'order'),
5815
+ type: 'oauth',
5816
+ }))
5817
+ .filter((x) => x.enabled === true);
5818
+ authenticationList.push(...oauthList);
5819
+ }
5820
+ authenticationList.push({
5821
+ enabled: true,
5822
+ type: 'builtin',
5823
+ provider: LOGIN_PROVIDER.PASSKEY,
5824
+ });
5825
+ const authentication = authenticationList.reduce((acc, curr, index) => {
5826
+ acc[curr.provider] = {
5827
+ ...omit(curr, ['provider']),
5828
+ order: index,
5829
+ };
5830
+ return acc;
5831
+ }, {});
5832
+ await this.configAuthentication({ did, authentication: JSON.stringify(authentication) });
5833
+ }
5720
5834
  }
5721
5835
 
5722
5836
  class FederatedBlockletManager extends DiskBlockletManager {
@@ -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.15","@arcblock/did-connect-js":"^1.27.15","@arcblock/did-ext":"^1.27.15","@arcblock/did-motif":"^1.1.14","@arcblock/did-util":"^1.27.15","@arcblock/event-hub":"^1.27.15","@arcblock/jwt":"^1.27.15","@arcblock/pm2-events":"^0.0.5","@arcblock/validator":"^1.27.15","@arcblock/vc":"^1.27.15","@blocklet/constant":"1.17.6","@blocklet/did-space-js":"^1.2.11","@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.2.19","@fidm/x509":"^1.2.1","@ocap/mcrypto":"^1.27.15","@ocap/util":"^1.27.15","@ocap/wallet":"^1.27.15","@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.1","@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
  }