@abtnode/core 1.17.7-beta-20251229-223813-e1e6c5e3 → 1.17.7-beta-20251230-120126-2836fe04
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/blocklet/manager/disk.js +37 -0
- package/lib/blocklet/manager/helper/blue-green-start-blocklet.js +3 -0
- package/lib/migrations/1.17.6-beta-2025123004-blocklet-updated-at.js +48 -0
- package/lib/router/helper.js +1 -2
- package/lib/states/blocklet-child.js +51 -0
- package/lib/states/blocklet.js +82 -4
- package/lib/util/ready.js +3 -22
- package/package.json +22 -22
|
@@ -980,6 +980,9 @@ class DiskBlockletManager extends BaseBlockletManager {
|
|
|
980
980
|
|
|
981
981
|
await pAll(tasks, { concurrency: 6 });
|
|
982
982
|
|
|
983
|
+
// Sync parent blocklet uptime status once after all components are processed
|
|
984
|
+
await states.blocklet.syncUptimeStatus(parentBlockletId);
|
|
985
|
+
|
|
983
986
|
const nextBlocklet = await this.ensureBlocklet(did, { e2eMode });
|
|
984
987
|
let errorDescription = '';
|
|
985
988
|
let resultBlocklet = nextBlocklet;
|
|
@@ -1271,6 +1274,9 @@ class DiskBlockletManager extends BaseBlockletManager {
|
|
|
1271
1274
|
for (const subDid of entryComponentIds) {
|
|
1272
1275
|
onError?.(subDid, err);
|
|
1273
1276
|
}
|
|
1277
|
+
if (throwOnError) {
|
|
1278
|
+
throw err;
|
|
1279
|
+
}
|
|
1274
1280
|
}
|
|
1275
1281
|
}
|
|
1276
1282
|
|
|
@@ -2474,6 +2480,30 @@ class DiskBlockletManager extends BaseBlockletManager {
|
|
|
2474
2480
|
});
|
|
2475
2481
|
this.configSynchronizer.throttledSyncAppConfig(blocklet.meta.did);
|
|
2476
2482
|
|
|
2483
|
+
// Restart blocklet if it's running to pick up the new mount point
|
|
2484
|
+
// Only restart the component that was modified (did)
|
|
2485
|
+
if (!isRootComponent && did) {
|
|
2486
|
+
const updatedBlocklet = await this.getBlocklet(rootDid);
|
|
2487
|
+
const updatedComponent = updatedBlocklet.children.find((x) => x.meta.did === did);
|
|
2488
|
+
|
|
2489
|
+
if (
|
|
2490
|
+
updatedComponent &&
|
|
2491
|
+
(updatedComponent.status === BlockletStatus.running || updatedComponent.greenStatus === BlockletStatus.running)
|
|
2492
|
+
) {
|
|
2493
|
+
try {
|
|
2494
|
+
await this.restart({ did: rootDid, componentDids: [did], operator: context?.user?.did }, context);
|
|
2495
|
+
logger.info('restarted blocklet after mount point update', { rootDid, componentDid: did });
|
|
2496
|
+
} catch (error) {
|
|
2497
|
+
logger.error('failed to restart blocklet after mount point update', {
|
|
2498
|
+
rootDid,
|
|
2499
|
+
componentDid: did,
|
|
2500
|
+
error,
|
|
2501
|
+
});
|
|
2502
|
+
// Don't throw error - mount point update succeeded, restart failure is logged but doesn't block the operation
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2506
|
+
|
|
2477
2507
|
return this.getBlocklet(rootDid);
|
|
2478
2508
|
}
|
|
2479
2509
|
|
|
@@ -3756,6 +3786,13 @@ class DiskBlockletManager extends BaseBlockletManager {
|
|
|
3756
3786
|
}
|
|
3757
3787
|
|
|
3758
3788
|
async _onRestart({ did, componentDids, context, operator }) {
|
|
3789
|
+
// 检查 blocklet 是否存在,如果不存在则跳过重启任务
|
|
3790
|
+
// 这可以防止在 blocklet 被删除后,队列中待处理的重启任务执行时出错
|
|
3791
|
+
if (!(await this.hasBlocklet({ did }))) {
|
|
3792
|
+
logger.warn('skip restart job: blocklet not found', { did });
|
|
3793
|
+
return;
|
|
3794
|
+
}
|
|
3795
|
+
|
|
3759
3796
|
if (process.env.ABT_NODE_DISABLE_BLUE_GREEN) {
|
|
3760
3797
|
await this.stop({ did, componentDids, context, operator });
|
|
3761
3798
|
await this.start({ did, componentDids, checkHealthImmediately: true });
|
|
@@ -401,6 +401,9 @@ const blueGreenStartBlocklet = async (
|
|
|
401
401
|
|
|
402
402
|
await pAll(tasks, { concurrency: 6 });
|
|
403
403
|
|
|
404
|
+
// Sync parent blocklet uptime status once after all components are processed
|
|
405
|
+
await states.blocklet.syncUptimeStatus(appId);
|
|
406
|
+
|
|
404
407
|
const lastBlocklet = await manager.getBlocklet(did, { e2eMode });
|
|
405
408
|
let errorDescription = '';
|
|
406
409
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/* eslint-disable no-await-in-loop */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Migration script to populate startedAt/stoppedAt for existing blocklets
|
|
5
|
+
*
|
|
6
|
+
* This migration:
|
|
7
|
+
* 1. Queries all blocklet IDs efficiently (only fetching `id` field)
|
|
8
|
+
* 2. For each blocklet, calls syncUptimeStatus to populate startedAt/stoppedAt
|
|
9
|
+
* based on the running state of its children
|
|
10
|
+
*
|
|
11
|
+
* Uses silent: true internally to prevent updatedAt from being modified
|
|
12
|
+
*/
|
|
13
|
+
module.exports = async ({ states, printInfo }) => {
|
|
14
|
+
printInfo('Try to populate blocklet uptime (startedAt/stoppedAt)...');
|
|
15
|
+
|
|
16
|
+
// Query only the id field for efficiency
|
|
17
|
+
const blocklets = await states.blocklet.model.findAll({
|
|
18
|
+
attributes: ['id'],
|
|
19
|
+
raw: true,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
if (!blocklets || blocklets.length === 0) {
|
|
23
|
+
printInfo('No blocklets found, skipping migration');
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
printInfo(`Found ${blocklets.length} blocklets to process`);
|
|
28
|
+
|
|
29
|
+
let updatedCount = 0;
|
|
30
|
+
let skippedCount = 0;
|
|
31
|
+
|
|
32
|
+
for (const blocklet of blocklets) {
|
|
33
|
+
try {
|
|
34
|
+
// syncUptimeStatus handles all the logic:
|
|
35
|
+
// - Checks if any child is running
|
|
36
|
+
// - If running and no startedAt: sets startedAt from earliest child startedAt
|
|
37
|
+
// - If not running and has startedAt without stoppedAt: sets stoppedAt = now
|
|
38
|
+
// - Uses silent: true to prevent updatedAt modification
|
|
39
|
+
await states.blocklet.syncUptimeStatus(blocklet.id);
|
|
40
|
+
updatedCount++;
|
|
41
|
+
} catch (err) {
|
|
42
|
+
printInfo(`Skipped blocklet ${blocklet.id}: ${err.message}`);
|
|
43
|
+
skippedCount++;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
printInfo(`Blocklet uptime migration completed: ${updatedCount} updated, ${skippedCount} skipped`);
|
|
48
|
+
};
|
package/lib/router/helper.js
CHANGED
|
@@ -508,8 +508,7 @@ const expandComponentRules = (sites = [], blocklets) => {
|
|
|
508
508
|
}
|
|
509
509
|
|
|
510
510
|
const blocklet = blocklets.find((x) => x.meta.did === site.blockletDid);
|
|
511
|
-
const
|
|
512
|
-
const expandedRules = components
|
|
511
|
+
const expandedRules = blocklet.children
|
|
513
512
|
.filter((x) => hasMountPoint(x.meta))
|
|
514
513
|
.map((x) => ({
|
|
515
514
|
id: UUID.v4(),
|
|
@@ -339,6 +339,57 @@ class BlockletChildState extends BaseState {
|
|
|
339
339
|
|
|
340
340
|
return results.map((x) => x.toJSON());
|
|
341
341
|
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Check if any child of a parent blocklet is in running state
|
|
345
|
+
* Uses efficient COUNT query instead of loading all children
|
|
346
|
+
* Checks both status and greenStatus for blue-green deployment support
|
|
347
|
+
* @param {string} parentBlockletId - The parent blocklet ID
|
|
348
|
+
* @returns {Promise<boolean>} - True if any child is running
|
|
349
|
+
*/
|
|
350
|
+
async hasAnyRunningChild(parentBlockletId) {
|
|
351
|
+
if (!parentBlockletId) {
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const { Op } = Sequelize;
|
|
356
|
+
const count = await this.model.count({
|
|
357
|
+
where: {
|
|
358
|
+
parentBlockletId,
|
|
359
|
+
[Op.or]: [{ status: BlockletStatus.running }, { greenStatus: BlockletStatus.running }],
|
|
360
|
+
},
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
return count > 0;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Get the earliest startedAt timestamp from running children
|
|
368
|
+
* Used to determine when the app first started running
|
|
369
|
+
* @param {string} parentBlockletId - The parent blocklet ID
|
|
370
|
+
* @returns {Promise<Date|null>} - Earliest startedAt or null if no running children
|
|
371
|
+
*/
|
|
372
|
+
async getEarliestRunningStartedAt(parentBlockletId) {
|
|
373
|
+
if (!parentBlockletId) {
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const { Op } = Sequelize;
|
|
378
|
+
const result = await this.model.findOne({
|
|
379
|
+
attributes: [[Sequelize.fn('MIN', Sequelize.col('startedAt')), 'earliestStartedAt']],
|
|
380
|
+
where: {
|
|
381
|
+
parentBlockletId,
|
|
382
|
+
[Op.or]: [{ status: BlockletStatus.running }, { greenStatus: BlockletStatus.running }],
|
|
383
|
+
startedAt: { [Op.not]: null },
|
|
384
|
+
},
|
|
385
|
+
raw: true,
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
if (result && result.earliestStartedAt) {
|
|
389
|
+
return new Date(result.earliestStartedAt);
|
|
390
|
+
}
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
342
393
|
}
|
|
343
394
|
|
|
344
395
|
module.exports = BlockletChildState;
|
package/lib/states/blocklet.js
CHANGED
|
@@ -646,7 +646,7 @@ class BlockletState extends BaseState {
|
|
|
646
646
|
*/
|
|
647
647
|
async findPaginated({ search, external, paging, sort } = {}) {
|
|
648
648
|
// Allowed sort fields whitelist
|
|
649
|
-
const ALLOWED_SORT_FIELDS = ['installedAt', 'updatedAt', 'status'];
|
|
649
|
+
const ALLOWED_SORT_FIELDS = ['installedAt', 'updatedAt', 'status', 'startedAt'];
|
|
650
650
|
const ALLOWED_SORT_DIRECTIONS = ['asc', 'desc'];
|
|
651
651
|
|
|
652
652
|
const conditions = { where: {} };
|
|
@@ -658,11 +658,25 @@ class BlockletState extends BaseState {
|
|
|
658
658
|
const escapedSearch = searchTerm.replace(/[%_]/g, '\\$&');
|
|
659
659
|
const searchLike = `%${escapedSearch}%`;
|
|
660
660
|
|
|
661
|
+
const dialect = this.model.sequelize.getDialect();
|
|
662
|
+
|
|
663
|
+
// Build search condition for meta column
|
|
664
|
+
// PostgreSQL: meta is JSONB, need to cast to text before using lower()
|
|
665
|
+
// SQLite: meta is stored as text, can use lower() directly
|
|
666
|
+
let metaSearchCondition;
|
|
667
|
+
if (dialect === 'postgres') {
|
|
668
|
+
// Cast JSONB to text before applying lower() using PostgreSQL-specific syntax
|
|
669
|
+
metaSearchCondition = Sequelize.where(Sequelize.literal('lower("meta"::text)'), { [Op.like]: searchLike });
|
|
670
|
+
} else {
|
|
671
|
+
// SQLite: meta is already text
|
|
672
|
+
metaSearchCondition = Sequelize.where(Sequelize.fn('lower', Sequelize.col('meta')), {
|
|
673
|
+
[Op.like]: searchLike,
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
|
|
661
677
|
conditions.where[Op.or] = [
|
|
662
678
|
// Search in meta column (JSON stored as text) - search the whole JSON string
|
|
663
|
-
|
|
664
|
-
[Op.like]: searchLike,
|
|
665
|
-
}),
|
|
679
|
+
metaSearchCondition,
|
|
666
680
|
// Search in appDid
|
|
667
681
|
Sequelize.where(Sequelize.fn('lower', Sequelize.col('appDid')), {
|
|
668
682
|
[Op.like]: searchLike,
|
|
@@ -1326,6 +1340,12 @@ class BlockletState extends BaseState {
|
|
|
1326
1340
|
}
|
|
1327
1341
|
}
|
|
1328
1342
|
|
|
1343
|
+
// Sync parent uptime for stable states (running, stopped, error)
|
|
1344
|
+
const stableStatuses = [BlockletStatus.running, BlockletStatus.stopped, BlockletStatus.error];
|
|
1345
|
+
if (stableStatuses.includes(status)) {
|
|
1346
|
+
await this.syncUptimeStatus(doc.id);
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1329
1349
|
const children = await this.loadChildren(doc.id);
|
|
1330
1350
|
|
|
1331
1351
|
res.children = children;
|
|
@@ -1340,6 +1360,64 @@ class BlockletState extends BaseState {
|
|
|
1340
1360
|
}
|
|
1341
1361
|
}
|
|
1342
1362
|
|
|
1363
|
+
/**
|
|
1364
|
+
* Synchronize parent blocklet's startedAt/stoppedAt based on children's running state
|
|
1365
|
+
*
|
|
1366
|
+
* Rules:
|
|
1367
|
+
* - If ANY child has status === RUNNING or greenStatus === RUNNING:
|
|
1368
|
+
* → App is running, startedAt = earliest child startedAt, stoppedAt = null
|
|
1369
|
+
* - If NO child is running (all stopped/error):
|
|
1370
|
+
* → App is stopped, stoppedAt = now, startedAt = null
|
|
1371
|
+
* - Only acts on stable states, ignores in-progress statuses
|
|
1372
|
+
*
|
|
1373
|
+
* @param {string} blockletId - The parent blocklet ID (not DID)
|
|
1374
|
+
* @returns {Promise<void>}
|
|
1375
|
+
*/
|
|
1376
|
+
async syncUptimeStatus(blockletId) {
|
|
1377
|
+
if (!blockletId) {
|
|
1378
|
+
return;
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
try {
|
|
1382
|
+
const blocklet = await this.findOne({ id: blockletId });
|
|
1383
|
+
if (!blocklet) {
|
|
1384
|
+
return;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
const hasRunning = await this.BlockletChildState.hasAnyRunningChild(blockletId);
|
|
1388
|
+
if (hasRunning) {
|
|
1389
|
+
// App is running - update startedAt if not already set
|
|
1390
|
+
if (!blocklet.startedAt) {
|
|
1391
|
+
const earliestStartedAt = await this.BlockletChildState.getEarliestRunningStartedAt(blockletId);
|
|
1392
|
+
const newStartedAt = earliestStartedAt || new Date();
|
|
1393
|
+
// Use silent: true to prevent updatedAt from being modified
|
|
1394
|
+
await this.model.update(
|
|
1395
|
+
{ startedAt: newStartedAt, stoppedAt: null },
|
|
1396
|
+
{ where: { id: blockletId }, silent: true }
|
|
1397
|
+
);
|
|
1398
|
+
logger.info('syncUptimeStatus: app started', {
|
|
1399
|
+
blockletId,
|
|
1400
|
+
appDid: blocklet.appDid,
|
|
1401
|
+
startedAt: newStartedAt,
|
|
1402
|
+
});
|
|
1403
|
+
}
|
|
1404
|
+
} else if (blocklet.startedAt && !blocklet.stoppedAt) {
|
|
1405
|
+
// App is not running - update stoppedAt if was previously running
|
|
1406
|
+
const now = new Date();
|
|
1407
|
+
// Use silent: true to prevent updatedAt from being modified
|
|
1408
|
+
await this.model.update({ stoppedAt: now, startedAt: null }, { where: { id: blockletId }, silent: true });
|
|
1409
|
+
logger.info('syncUptimeStatus: app stopped', {
|
|
1410
|
+
blockletId,
|
|
1411
|
+
appDid: blocklet.appDid,
|
|
1412
|
+
stoppedAt: now,
|
|
1413
|
+
});
|
|
1414
|
+
}
|
|
1415
|
+
} catch (error) {
|
|
1416
|
+
logger.error('syncUptimeStatus failed', { blockletId, error: error.message });
|
|
1417
|
+
// Don't throw - uptime sync failure shouldn't break status updates
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1343
1421
|
async setInstalledAt(did) {
|
|
1344
1422
|
logger.info('setInstalledAt', { did });
|
|
1345
1423
|
const blocklet = await this.getBlocklet(did);
|
package/lib/util/ready.js
CHANGED
|
@@ -1,37 +1,18 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
const logger = require('@abtnode/logger')('@abtnode/core:ready');
|
|
3
|
-
const chalk = require('chalk');
|
|
4
3
|
|
|
5
4
|
const createStateReadyHandler =
|
|
6
5
|
() =>
|
|
7
|
-
({ states
|
|
6
|
+
({ states }) => {
|
|
8
7
|
return states.node
|
|
9
8
|
.read()
|
|
10
|
-
.then(
|
|
9
|
+
.then((state) => {
|
|
11
10
|
// Set default sender/receiver for notification center
|
|
12
11
|
states.notification.setDefaultSender(state.did);
|
|
13
12
|
if (state.nodeOwner) {
|
|
14
13
|
states.notification.setDefaultReceiver(state.nodeOwner.did);
|
|
15
14
|
}
|
|
16
|
-
|
|
17
|
-
if (process.env.NODE_ENV === 'test' || process.env.CI || process.env.TRAVIS) {
|
|
18
|
-
// Do not validate data dir sharing in test env
|
|
19
|
-
} else {
|
|
20
|
-
const count = await states.node.count();
|
|
21
|
-
if (count > 1) {
|
|
22
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
23
|
-
await states.node.remove({ did: state.did });
|
|
24
|
-
console.error('\n\x1b[31m======================================================');
|
|
25
|
-
console.error(`Data dir: ${options.dataDir} is used by another Blocklet Server instance, abort!`);
|
|
26
|
-
console.error('Sharing data dir between Blocklet Server instances may break things!');
|
|
27
|
-
console.error('======================================================\x1b[0m');
|
|
28
|
-
console.log('\nIf you intend to use this dir:');
|
|
29
|
-
console.log(` 1. Stop Blocklet Server by ${chalk.cyan('blocklet server stop --force')}`);
|
|
30
|
-
console.log(` 2. Clear data dir by ${chalk.cyan(`rm -r ${options.dataDir}`)}`);
|
|
31
|
-
console.log(' 3. Reinitialize and start Blocklet Server');
|
|
32
|
-
process.exit(1);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
15
|
+
// deleted states.node.count() check
|
|
35
16
|
})
|
|
36
17
|
.catch((err) => {
|
|
37
18
|
console.error('Can not ready node state on Blocklet Server start:', err.message);
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.17.7-beta-
|
|
6
|
+
"version": "1.17.7-beta-20251230-120126-2836fe04",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -17,19 +17,19 @@
|
|
|
17
17
|
"author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
|
|
18
18
|
"license": "Apache-2.0",
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@abtnode/analytics": "1.17.7-beta-
|
|
21
|
-
"@abtnode/auth": "1.17.7-beta-
|
|
22
|
-
"@abtnode/certificate-manager": "1.17.7-beta-
|
|
23
|
-
"@abtnode/constant": "1.17.7-beta-
|
|
24
|
-
"@abtnode/cron": "1.17.7-beta-
|
|
25
|
-
"@abtnode/db-cache": "1.17.7-beta-
|
|
26
|
-
"@abtnode/docker-utils": "1.17.7-beta-
|
|
27
|
-
"@abtnode/logger": "1.17.7-beta-
|
|
28
|
-
"@abtnode/models": "1.17.7-beta-
|
|
29
|
-
"@abtnode/queue": "1.17.7-beta-
|
|
30
|
-
"@abtnode/rbac": "1.17.7-beta-
|
|
31
|
-
"@abtnode/router-provider": "1.17.7-beta-
|
|
32
|
-
"@abtnode/util": "1.17.7-beta-
|
|
20
|
+
"@abtnode/analytics": "1.17.7-beta-20251230-120126-2836fe04",
|
|
21
|
+
"@abtnode/auth": "1.17.7-beta-20251230-120126-2836fe04",
|
|
22
|
+
"@abtnode/certificate-manager": "1.17.7-beta-20251230-120126-2836fe04",
|
|
23
|
+
"@abtnode/constant": "1.17.7-beta-20251230-120126-2836fe04",
|
|
24
|
+
"@abtnode/cron": "1.17.7-beta-20251230-120126-2836fe04",
|
|
25
|
+
"@abtnode/db-cache": "1.17.7-beta-20251230-120126-2836fe04",
|
|
26
|
+
"@abtnode/docker-utils": "1.17.7-beta-20251230-120126-2836fe04",
|
|
27
|
+
"@abtnode/logger": "1.17.7-beta-20251230-120126-2836fe04",
|
|
28
|
+
"@abtnode/models": "1.17.7-beta-20251230-120126-2836fe04",
|
|
29
|
+
"@abtnode/queue": "1.17.7-beta-20251230-120126-2836fe04",
|
|
30
|
+
"@abtnode/rbac": "1.17.7-beta-20251230-120126-2836fe04",
|
|
31
|
+
"@abtnode/router-provider": "1.17.7-beta-20251230-120126-2836fe04",
|
|
32
|
+
"@abtnode/util": "1.17.7-beta-20251230-120126-2836fe04",
|
|
33
33
|
"@aigne/aigne-hub": "^0.10.15",
|
|
34
34
|
"@arcblock/did": "^1.27.16",
|
|
35
35
|
"@arcblock/did-connect-js": "^1.27.16",
|
|
@@ -41,15 +41,15 @@
|
|
|
41
41
|
"@arcblock/pm2-events": "^0.0.5",
|
|
42
42
|
"@arcblock/validator": "^1.27.16",
|
|
43
43
|
"@arcblock/vc": "^1.27.16",
|
|
44
|
-
"@blocklet/constant": "1.17.7-beta-
|
|
44
|
+
"@blocklet/constant": "1.17.7-beta-20251230-120126-2836fe04",
|
|
45
45
|
"@blocklet/did-space-js": "^1.2.12",
|
|
46
|
-
"@blocklet/env": "1.17.7-beta-
|
|
46
|
+
"@blocklet/env": "1.17.7-beta-20251230-120126-2836fe04",
|
|
47
47
|
"@blocklet/error": "^0.3.5",
|
|
48
|
-
"@blocklet/meta": "1.17.7-beta-
|
|
49
|
-
"@blocklet/resolver": "1.17.7-beta-
|
|
50
|
-
"@blocklet/sdk": "1.17.7-beta-
|
|
51
|
-
"@blocklet/server-js": "1.17.7-beta-
|
|
52
|
-
"@blocklet/store": "1.17.7-beta-
|
|
48
|
+
"@blocklet/meta": "1.17.7-beta-20251230-120126-2836fe04",
|
|
49
|
+
"@blocklet/resolver": "1.17.7-beta-20251230-120126-2836fe04",
|
|
50
|
+
"@blocklet/sdk": "1.17.7-beta-20251230-120126-2836fe04",
|
|
51
|
+
"@blocklet/server-js": "1.17.7-beta-20251230-120126-2836fe04",
|
|
52
|
+
"@blocklet/store": "1.17.7-beta-20251230-120126-2836fe04",
|
|
53
53
|
"@blocklet/theme": "^3.3.3",
|
|
54
54
|
"@fidm/x509": "^1.2.1",
|
|
55
55
|
"@ocap/mcrypto": "^1.27.16",
|
|
@@ -114,5 +114,5 @@
|
|
|
114
114
|
"express": "^4.18.2",
|
|
115
115
|
"unzipper": "^0.10.11"
|
|
116
116
|
},
|
|
117
|
-
"gitHead": "
|
|
117
|
+
"gitHead": "ee9edd47a6da9d6b47799357dca96814082f8065"
|
|
118
118
|
}
|