@abtnode/core 1.16.50 → 1.16.51-beta-20250905-023351-70af144b
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/team.js +13 -2
- package/lib/blocklet/manager/disk.js +27 -18
- package/lib/blocklet/migration-dist/migration.cjs +456 -456
- package/lib/blocklet/webhook/event-bus.js +1 -1
- package/lib/states/user.js +41 -15
- package/lib/team/manager.js +9 -5
- package/lib/util/launcher.js +8 -2
- package/lib/util/validate-user-role-passport.js +27 -0
- package/lib/util/verify-access-key-user.js +4 -2
- package/lib/util/verify-user-private.js +42 -0
- package/package.json +26 -26
|
@@ -51,7 +51,7 @@ const init = ({ states, teamManager }) => {
|
|
|
51
51
|
const { event } = data;
|
|
52
52
|
const { type, source, object_id: objectId, object_type: objectType } = event;
|
|
53
53
|
|
|
54
|
-
const request = event.data;
|
|
54
|
+
const request = { ...event.data, $eventName: type };
|
|
55
55
|
logger.info('create webhook event', { type, source, request });
|
|
56
56
|
|
|
57
57
|
const { webhookEventState } = await teamManager.getWebhookState(appDid);
|
package/lib/states/user.js
CHANGED
|
@@ -11,12 +11,12 @@ const { updateConnectedAccount } = require('@abtnode/util/lib/user');
|
|
|
11
11
|
const { LOGIN_PROVIDER } = require('@blocklet/constant');
|
|
12
12
|
const { CustomError } = require('@blocklet/error');
|
|
13
13
|
const { Joi } = require('@arcblock/validator');
|
|
14
|
-
|
|
15
14
|
const logger = require('@abtnode/logger')('@abtnode/core:states:user');
|
|
16
15
|
|
|
17
16
|
const { validateOwner } = require('../util');
|
|
18
17
|
const { loginSchema, disconnectAccountSchema } = require('../validators/user');
|
|
19
18
|
const ExtendBase = require('./base');
|
|
19
|
+
const { isInDashboard, isUserPrivacyEnabled, isAdminUser } = require('../util/verify-user-private');
|
|
20
20
|
|
|
21
21
|
const isNullOrUndefined = (x) => x === undefined || x === null;
|
|
22
22
|
|
|
@@ -962,6 +962,8 @@ SELECT did,inviter,generation FROM UserTree`.trim();
|
|
|
962
962
|
|
|
963
963
|
const { user: contextUser } = context;
|
|
964
964
|
|
|
965
|
+
const contextUserDid = contextUser?.userInfo?.did || contextUser?.did;
|
|
966
|
+
|
|
965
967
|
await this._validateUsersExist([targetDid]);
|
|
966
968
|
|
|
967
969
|
const isFollowers = type === 'followers';
|
|
@@ -977,15 +979,15 @@ SELECT did,inviter,generation FROM UserTree`.trim();
|
|
|
977
979
|
const userDids = [...new Set(result.list.map((follow) => (isFollowers ? follow.followerDid : follow.userDid)))];
|
|
978
980
|
const users = await this.find({
|
|
979
981
|
where: { did: { [Op.in]: userDids } },
|
|
980
|
-
attributes: ['did', 'fullName', 'avatar'
|
|
982
|
+
attributes: ['did', 'fullName', 'avatar'],
|
|
981
983
|
});
|
|
982
984
|
userMap = new Map(users.map((user) => [user.did, user]));
|
|
983
985
|
}
|
|
984
986
|
|
|
985
987
|
// 准备关注状态映射
|
|
986
988
|
let followingStatusMap = {};
|
|
987
|
-
if (includeFollowStatus &&
|
|
988
|
-
if (
|
|
989
|
+
if (includeFollowStatus && contextUserDid) {
|
|
990
|
+
if (contextUserDid !== targetDid) {
|
|
989
991
|
// 查询当前用户对列表中所有用户的关注状态
|
|
990
992
|
const targetUserDids = result.list.map((follow) => (isFollowers ? follow.followerDid : follow.userDid));
|
|
991
993
|
followingStatusMap = await this.isFollowing(contextUser.did, targetUserDids);
|
|
@@ -1008,8 +1010,8 @@ SELECT did,inviter,generation FROM UserTree`.trim();
|
|
|
1008
1010
|
}
|
|
1009
1011
|
|
|
1010
1012
|
// 添加关注状态
|
|
1011
|
-
if (includeFollowStatus &&
|
|
1012
|
-
if (
|
|
1013
|
+
if (includeFollowStatus && contextUserDid) {
|
|
1014
|
+
if (contextUserDid !== targetDid) {
|
|
1013
1015
|
// 如果查看的是别人的关注列表,需要添加是否已关注的信息
|
|
1014
1016
|
enrichedFollow.isFollowing = followingStatusMap[userDid] || false;
|
|
1015
1017
|
} else if (isFollowers) {
|
|
@@ -1087,7 +1089,7 @@ SELECT did,inviter,generation FROM UserTree`.trim();
|
|
|
1087
1089
|
* @param {string[]} userDids - 用户的 DID 数组
|
|
1088
1090
|
* @returns {Promise<{[userDid: string]: {followers: number, following: number}}>} - 返回对象,键为用户DID,值为统计信息
|
|
1089
1091
|
*/
|
|
1090
|
-
async getFollowStats(userDids = []) {
|
|
1092
|
+
async getFollowStats({ userDids = [], teamDid, prefix }, context = {}) {
|
|
1091
1093
|
if (!this.userFollowers || !Array.isArray(userDids) || userDids.length === 0) {
|
|
1092
1094
|
return userDids.reduce(
|
|
1093
1095
|
(acc, userDid) => ({
|
|
@@ -1099,6 +1101,20 @@ SELECT did,inviter,generation FROM UserTree`.trim();
|
|
|
1099
1101
|
}
|
|
1100
1102
|
|
|
1101
1103
|
try {
|
|
1104
|
+
const { user: contextUser } = context;
|
|
1105
|
+
const contextUserDid = contextUser?.userInfo?.did || contextUser?.did;
|
|
1106
|
+
|
|
1107
|
+
const privacyMap = new Map();
|
|
1108
|
+
if (!(isInDashboard(teamDid, prefix, context) && isAdminUser(context))) {
|
|
1109
|
+
// 批量获取用户隐私设置
|
|
1110
|
+
const usersInfo = await this.find({ did: { $in: userDids } }, { did: 1, extra: 1 });
|
|
1111
|
+
|
|
1112
|
+
usersInfo.forEach((userInfo) => {
|
|
1113
|
+
const isPrivate = isUserPrivacyEnabled(userInfo);
|
|
1114
|
+
privacyMap.set(userInfo.did, isPrivate);
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1102
1118
|
// 使用原生 SQL 查询进行批量统计,提高性能
|
|
1103
1119
|
const followersQuery = `
|
|
1104
1120
|
SELECT "userDid", COUNT(*) as count
|
|
@@ -1123,15 +1139,25 @@ SELECT did,inviter,generation FROM UserTree`.trim();
|
|
|
1123
1139
|
const followersMap = new Map(followersResults.map((row) => [row.userDid, Number(row.count)]));
|
|
1124
1140
|
const followingMap = new Map(followingResults.map((row) => [row.followerDid, Number(row.count)]));
|
|
1125
1141
|
|
|
1126
|
-
// 使用 Object.fromEntries
|
|
1142
|
+
// 使用 Object.fromEntries 优化结果对象构建,并进行隐私判断
|
|
1127
1143
|
const result = Object.fromEntries(
|
|
1128
|
-
userDids.map((userDid) =>
|
|
1129
|
-
userDid
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1144
|
+
userDids.map((userDid) => {
|
|
1145
|
+
const isPrivate = privacyMap.get(userDid) || false;
|
|
1146
|
+
const isOwner = contextUserDid === userDid;
|
|
1147
|
+
|
|
1148
|
+
// 如果用户设置了隐私且查看者不是用户本人,返回 0
|
|
1149
|
+
if (isPrivate && !isOwner) {
|
|
1150
|
+
return [userDid, { followers: 0, following: 0 }];
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
return [
|
|
1154
|
+
userDid,
|
|
1155
|
+
{
|
|
1156
|
+
followers: followersMap.get(userDid) || 0,
|
|
1157
|
+
following: followingMap.get(userDid) || 0,
|
|
1158
|
+
},
|
|
1159
|
+
];
|
|
1160
|
+
})
|
|
1135
1161
|
);
|
|
1136
1162
|
|
|
1137
1163
|
return result;
|
package/lib/team/manager.js
CHANGED
|
@@ -226,10 +226,14 @@ class TeamManager extends EventEmitter {
|
|
|
226
226
|
userDids.map((did) => userState.getUser(did, { includePassports: true, enableConnectedAccount: true }))
|
|
227
227
|
);
|
|
228
228
|
|
|
229
|
-
const validUsers = queryUsers.filter((user) => {
|
|
229
|
+
const validUsers = queryUsers.filter((user, index) => {
|
|
230
|
+
if (!user) {
|
|
231
|
+
logger.warn('receiver is not exist: ', { userDid: userDids[index] });
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
230
234
|
const { passports = [] } = user;
|
|
231
235
|
// 如果用户没有 passport,或者 有一个 passport 没有过期,则返回 true
|
|
232
|
-
if (!passports
|
|
236
|
+
if (!passports?.length || passports.some((x) => !this.isPassportExpired(x))) {
|
|
233
237
|
return true;
|
|
234
238
|
}
|
|
235
239
|
logger.warn(`user's passports are all expired: ${user.did}`);
|
|
@@ -480,7 +484,7 @@ class TeamManager extends EventEmitter {
|
|
|
480
484
|
...(actorInfo ? { actorInfo } : {}),
|
|
481
485
|
options: typeof payload.options === 'object' && payload.options !== null ? payload.options : {},
|
|
482
486
|
});
|
|
483
|
-
logger.info('notification has been added to the push queue', { notificationId: doc.id });
|
|
487
|
+
logger.info('notification has been added to the push queue', { teamDid, notificationId: doc.id });
|
|
484
488
|
} catch (error) {
|
|
485
489
|
logger.error('Failed to emit notification events', { error });
|
|
486
490
|
throw new Error(`Failed to emit notification events: ${error.message}`);
|
|
@@ -538,14 +542,14 @@ class TeamManager extends EventEmitter {
|
|
|
538
542
|
|
|
539
543
|
const doc = await this._createNotificationDoc(notificationState, payload, receivers, source, isServices, teamDid);
|
|
540
544
|
|
|
541
|
-
logger.info('notification created successfully', { notificationId: doc.id });
|
|
545
|
+
logger.info('notification created successfully', { teamDid, notificationId: doc.id });
|
|
542
546
|
|
|
543
547
|
const defaultChannel = this._getDefaultChannels(isServices, source);
|
|
544
548
|
await this._emitNotificationEvents(doc, payload, receivers, teamDid, isServices, defaultChannel, actorInfo);
|
|
545
549
|
|
|
546
550
|
return doc;
|
|
547
551
|
} catch (error) {
|
|
548
|
-
logger.error('notification create failed', { error });
|
|
552
|
+
logger.error('notification create failed', { teamDid, error });
|
|
549
553
|
throw error;
|
|
550
554
|
}
|
|
551
555
|
}
|
package/lib/util/launcher.js
CHANGED
|
@@ -104,7 +104,7 @@ const reportComponentsEvent = async ({ blocklet, dids, type, time }) => {
|
|
|
104
104
|
}
|
|
105
105
|
};
|
|
106
106
|
|
|
107
|
-
const
|
|
107
|
+
const notifyLauncher = async (type, blocklet) => {
|
|
108
108
|
try {
|
|
109
109
|
const { controller } = blocklet;
|
|
110
110
|
|
|
@@ -120,7 +120,7 @@ const notifyBlockletUpdated = async (blocklet) => {
|
|
|
120
120
|
const { appLogo, appLogoRect } = getBlockletLogos(blocklet);
|
|
121
121
|
|
|
122
122
|
const payload = {
|
|
123
|
-
type
|
|
123
|
+
type,
|
|
124
124
|
payload: {
|
|
125
125
|
did: blocklet.appDid,
|
|
126
126
|
appId: blocklet.appDid,
|
|
@@ -152,6 +152,10 @@ const notifyBlockletUpdated = async (blocklet) => {
|
|
|
152
152
|
}
|
|
153
153
|
};
|
|
154
154
|
|
|
155
|
+
const notifyBlockletUpdated = (blocklet) => notifyLauncher('serverless.blocklet.updated', blocklet);
|
|
156
|
+
const notifyBlockletStarted = (blocklet) => notifyLauncher('serverless.blocklet.started', blocklet);
|
|
157
|
+
const notifyBlockletStopped = (blocklet) => notifyLauncher('serverless.blocklet.stopped', blocklet);
|
|
158
|
+
|
|
155
159
|
const consumeLauncherSession = async ({ params, blocklet }) => {
|
|
156
160
|
try {
|
|
157
161
|
const info = await states.node.read();
|
|
@@ -634,6 +638,8 @@ module.exports = {
|
|
|
634
638
|
isBlockletExpired,
|
|
635
639
|
isBlockletTerminated,
|
|
636
640
|
notifyBlockletUpdated,
|
|
641
|
+
notifyBlockletStarted,
|
|
642
|
+
notifyBlockletStopped,
|
|
637
643
|
launchBlockletByLauncher,
|
|
638
644
|
launchBlockletWithoutWallet,
|
|
639
645
|
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const { CustomError } = require('@blocklet/error');
|
|
2
|
+
|
|
3
|
+
const validateUserRolePassport = ({ role, passports }) => {
|
|
4
|
+
if (!Array.isArray(passports)) {
|
|
5
|
+
throw new CustomError(400, 'Invalid passports: must be an array');
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (!role || typeof role !== 'string') {
|
|
9
|
+
throw new CustomError(400, 'Invalid role: must be a non-empty string');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const filterPassports = passports.filter((x) => x.status === 'valid' && x.role === role);
|
|
13
|
+
|
|
14
|
+
if (filterPassports.length === 0) {
|
|
15
|
+
throw new CustomError(400, `No valid passport found: you don't have the required role "${role}".`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const isValid = filterPassports.every((x) => x.expirationDate);
|
|
19
|
+
if (isValid) {
|
|
20
|
+
throw new CustomError(
|
|
21
|
+
400,
|
|
22
|
+
`The passport for role "${role}" is only temporary and cannot be used to invite new members.`
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
module.exports = { validateUserRolePassport };
|
|
@@ -6,10 +6,12 @@ const {
|
|
|
6
6
|
WELLKNOWN_BLOCKLET_USER_PATH,
|
|
7
7
|
} = require('@abtnode/constant');
|
|
8
8
|
|
|
9
|
-
const { parseURL } = require('ufo');
|
|
9
|
+
const { parseURL, joinURL } = require('ufo');
|
|
10
10
|
|
|
11
11
|
const isAdminPath = (pathname) => pathname.startsWith(WELLKNOWN_BLOCKLET_ADMIN_PATH);
|
|
12
12
|
const isUserCenterPath = (pathname) => pathname.startsWith(WELLKNOWN_BLOCKLET_USER_PATH);
|
|
13
|
+
const isServerDashboardPath = (pathname, prefix, teamDid) =>
|
|
14
|
+
!teamDid ? false : pathname.startsWith(joinURL(prefix, 'blocklets', teamDid));
|
|
13
15
|
|
|
14
16
|
const getEndpoint = (context) => {
|
|
15
17
|
const { pathname } = parseURL(context.referrer);
|
|
@@ -54,4 +56,4 @@ const validateOperator = (context, operatorDid) => {
|
|
|
54
56
|
}
|
|
55
57
|
};
|
|
56
58
|
|
|
57
|
-
module.exports = { validateOperator, getEndpoint, isUserCenterPath, isAdminPath };
|
|
59
|
+
module.exports = { validateOperator, getEndpoint, isUserCenterPath, isAdminPath, isServerDashboardPath };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const { ROLES, SERVER_ROLES, WELLKNOWN_BLOCKLET_USER_PATH } = require('@abtnode/constant');
|
|
2
|
+
const get = require('lodash/get');
|
|
3
|
+
const { joinURL } = require('ufo');
|
|
4
|
+
const logger = require('@abtnode/logger')('@abtnode/core:util:verify-user-private');
|
|
5
|
+
|
|
6
|
+
const { getEndpoint, isServerDashboardPath, isAdminPath } = require('./verify-access-key-user');
|
|
7
|
+
|
|
8
|
+
const USER_FOLLOWERS_PATH = joinURL(WELLKNOWN_BLOCKLET_USER_PATH, 'user-followers');
|
|
9
|
+
|
|
10
|
+
const isAdminUser = (context) => {
|
|
11
|
+
const { user = {} } = context || {};
|
|
12
|
+
const role = user.userInfo?.role || user.role;
|
|
13
|
+
return [ROLES.ADMIN, ROLES.OWNER, SERVER_ROLES.BLOCKLET_ADMIN, SERVER_ROLES.BLOCKLET_OWNER].includes(role);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const isUserPrivacyEnabled = (userInfo) => {
|
|
17
|
+
// 在 server 的dashboard 和 service 的 dashboard 中,不需要判断
|
|
18
|
+
const privacyInfo = get(userInfo, 'extra.privacy', {});
|
|
19
|
+
return get(privacyInfo, USER_FOLLOWERS_PATH, false);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const isInDashboard = (teamDid, prefix, context = {}) => {
|
|
23
|
+
const { user = {}, hostname, referrer } = context || {};
|
|
24
|
+
if (user.role === SERVER_ROLES.BLOCKLET_SDK || !teamDid) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!hostname || !referrer) {
|
|
29
|
+
logger.warn('Missing hostname or referrer context');
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
const pathname = getEndpoint(context);
|
|
35
|
+
return isAdminPath(pathname) || isServerDashboardPath(pathname, prefix, teamDid);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
logger.warn('Failed to check if in dashboard', { error });
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
module.exports = { isInDashboard, isUserPrivacyEnabled, isAdminUser };
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.16.
|
|
6
|
+
"version": "1.16.51-beta-20250905-023351-70af144b",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,21 +19,21 @@
|
|
|
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.
|
|
23
|
-
"@abtnode/auth": "1.16.
|
|
24
|
-
"@abtnode/certificate-manager": "1.16.
|
|
25
|
-
"@abtnode/constant": "1.16.
|
|
26
|
-
"@abtnode/cron": "1.16.
|
|
27
|
-
"@abtnode/db-cache": "1.16.
|
|
28
|
-
"@abtnode/docker-utils": "1.16.
|
|
29
|
-
"@abtnode/logger": "1.16.
|
|
30
|
-
"@abtnode/models": "1.16.
|
|
31
|
-
"@abtnode/queue": "1.16.
|
|
32
|
-
"@abtnode/rbac": "1.16.
|
|
33
|
-
"@abtnode/router-provider": "1.16.
|
|
34
|
-
"@abtnode/static-server": "1.16.
|
|
35
|
-
"@abtnode/timemachine": "1.16.
|
|
36
|
-
"@abtnode/util": "1.16.
|
|
22
|
+
"@abtnode/analytics": "1.16.51-beta-20250905-023351-70af144b",
|
|
23
|
+
"@abtnode/auth": "1.16.51-beta-20250905-023351-70af144b",
|
|
24
|
+
"@abtnode/certificate-manager": "1.16.51-beta-20250905-023351-70af144b",
|
|
25
|
+
"@abtnode/constant": "1.16.51-beta-20250905-023351-70af144b",
|
|
26
|
+
"@abtnode/cron": "1.16.51-beta-20250905-023351-70af144b",
|
|
27
|
+
"@abtnode/db-cache": "1.16.51-beta-20250905-023351-70af144b",
|
|
28
|
+
"@abtnode/docker-utils": "1.16.51-beta-20250905-023351-70af144b",
|
|
29
|
+
"@abtnode/logger": "1.16.51-beta-20250905-023351-70af144b",
|
|
30
|
+
"@abtnode/models": "1.16.51-beta-20250905-023351-70af144b",
|
|
31
|
+
"@abtnode/queue": "1.16.51-beta-20250905-023351-70af144b",
|
|
32
|
+
"@abtnode/rbac": "1.16.51-beta-20250905-023351-70af144b",
|
|
33
|
+
"@abtnode/router-provider": "1.16.51-beta-20250905-023351-70af144b",
|
|
34
|
+
"@abtnode/static-server": "1.16.51-beta-20250905-023351-70af144b",
|
|
35
|
+
"@abtnode/timemachine": "1.16.51-beta-20250905-023351-70af144b",
|
|
36
|
+
"@abtnode/util": "1.16.51-beta-20250905-023351-70af144b",
|
|
37
37
|
"@aigne/aigne-hub": "^0.8.6",
|
|
38
38
|
"@arcblock/did": "1.24.0",
|
|
39
39
|
"@arcblock/did-connect-js": "1.24.0",
|
|
@@ -45,16 +45,16 @@
|
|
|
45
45
|
"@arcblock/pm2-events": "^0.0.5",
|
|
46
46
|
"@arcblock/validator": "1.24.0",
|
|
47
47
|
"@arcblock/vc": "1.24.0",
|
|
48
|
-
"@blocklet/constant": "1.16.
|
|
49
|
-
"@blocklet/did-space-js": "^1.1.
|
|
50
|
-
"@blocklet/env": "1.16.
|
|
48
|
+
"@blocklet/constant": "1.16.51-beta-20250905-023351-70af144b",
|
|
49
|
+
"@blocklet/did-space-js": "^1.1.22",
|
|
50
|
+
"@blocklet/env": "1.16.51-beta-20250905-023351-70af144b",
|
|
51
51
|
"@blocklet/error": "^0.2.5",
|
|
52
|
-
"@blocklet/meta": "1.16.
|
|
53
|
-
"@blocklet/resolver": "1.16.
|
|
54
|
-
"@blocklet/sdk": "1.16.
|
|
55
|
-
"@blocklet/server-js": "1.16.
|
|
56
|
-
"@blocklet/store": "1.16.
|
|
57
|
-
"@blocklet/theme": "^3.1.
|
|
52
|
+
"@blocklet/meta": "1.16.51-beta-20250905-023351-70af144b",
|
|
53
|
+
"@blocklet/resolver": "1.16.51-beta-20250905-023351-70af144b",
|
|
54
|
+
"@blocklet/sdk": "1.16.51-beta-20250905-023351-70af144b",
|
|
55
|
+
"@blocklet/server-js": "1.16.51-beta-20250905-023351-70af144b",
|
|
56
|
+
"@blocklet/store": "1.16.51-beta-20250905-023351-70af144b",
|
|
57
|
+
"@blocklet/theme": "^3.1.34",
|
|
58
58
|
"@fidm/x509": "^1.2.1",
|
|
59
59
|
"@ocap/mcrypto": "1.24.0",
|
|
60
60
|
"@ocap/util": "1.24.0",
|
|
@@ -118,5 +118,5 @@
|
|
|
118
118
|
"jest": "^29.7.0",
|
|
119
119
|
"unzipper": "^0.10.11"
|
|
120
120
|
},
|
|
121
|
-
"gitHead": "
|
|
121
|
+
"gitHead": "d19892df7ce4f08a4a7a3ce96dff3bc6b01925ad"
|
|
122
122
|
}
|