@abtnode/core 1.16.52-beta-20250928-042319-ff3f0e04 → 1.16.52-beta-20250930-134044-9b691563

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 CHANGED
@@ -8,7 +8,7 @@ const cloneDeep = require('@abtnode/util/lib/deep-clone');
8
8
  const { joinURL, withoutTrailingSlash } = require('ufo');
9
9
  const { Op } = require('sequelize');
10
10
  const dayjs = require('@abtnode/util/lib/dayjs');
11
-
11
+ const Joi = require('joi');
12
12
  const logger = require('@abtnode/logger')('@abtnode/core:api:team');
13
13
  const {
14
14
  ROLES,
@@ -121,6 +121,19 @@ const formatTransferData = (data) => ({
121
121
  status: data.status || '',
122
122
  });
123
123
 
124
+ const taggingSchema = Joi.object({
125
+ tagId: Joi.number().required(),
126
+ taggableIds: Joi.array().items(Joi.string()).min(1).required().messages({
127
+ 'any.required': 'Must specify tagging.taggableIds to create',
128
+ 'array.base': 'taggableIds must be an array',
129
+ 'array.min': 'taggableIds must contain at least one element',
130
+ }),
131
+ taggableType: Joi.string().required().messages({
132
+ 'any.required': 'Must specify tagging.taggableType to create',
133
+ 'string.base': 'taggableType must be a string',
134
+ }),
135
+ });
136
+
124
137
  const validatePassportDisplay = async (role, display) => {
125
138
  if (role.extra?.display === 'custom') {
126
139
  if (!display) {
@@ -270,39 +283,113 @@ class TeamAPI extends EventEmitter {
270
283
  };
271
284
  }
272
285
 
286
+ // Tagging
287
+ async createTagging({ teamDid, tagging }) {
288
+ const state = await this.getTaggingState(teamDid);
289
+
290
+ const { error, value } = taggingSchema.validate(tagging, { stripUnknown: true });
291
+ if (error) {
292
+ throw new Error(error.details.map((d) => d.message).join('; '));
293
+ }
294
+
295
+ const fns = value.taggableIds.map(async (id) => {
296
+ const found = await state.findOne({ tagId: tagging.tagId, taggableId: id });
297
+ if (found) return found;
298
+
299
+ return state.insert({ tagId: tagging.tagId, taggableId: id, taggableType: tagging.taggableType });
300
+ });
301
+
302
+ const docs = await Promise.all(fns);
303
+ logger.info('tagging created successfully', { teamDid, tagging });
304
+ return docs;
305
+ }
306
+
307
+ async deleteTagging({ teamDid, tagging }) {
308
+ const { error, value } = taggingSchema.validate(tagging, { stripUnknown: true });
309
+ if (error) {
310
+ throw new Error(error.details.map((d) => d.message).join('; '));
311
+ }
312
+
313
+ const state = await this.getTaggingState(teamDid);
314
+
315
+ const { tagId, taggableIds } = value;
316
+ const fns = taggableIds.map((id) => {
317
+ return state.remove({ tagId, taggableId: id });
318
+ });
319
+
320
+ const docs = await Promise.all(fns);
321
+ logger.info('tagging deleted successfully', { teamDid, tagging });
322
+
323
+ return docs;
324
+ }
325
+
273
326
  // Tags
274
- async createTag({ teamDid, tag }) {
327
+ async createTag({ teamDid, tag }, context = {}) {
275
328
  if (!tag.title) {
276
329
  throw new Error('Must specify tag.title to create');
277
330
  }
278
331
  if (!tag.color || !tag.color.match(/^#[0-9a-f]{6}$/i)) {
279
332
  throw new Error('Must specify hex encoded tag.color to create');
280
333
  }
334
+ if (!tag.slug) {
335
+ throw new Error('Must specify tag.slug to create');
336
+ }
281
337
 
282
338
  const state = await this.getTagState(teamDid);
283
- const doc = await state.insert(pick(tag, ['title', 'color', 'description']));
339
+ const tagData = pick(tag, ['title', 'description', 'color', 'slug', 'type', 'componentDid', 'parentId']);
340
+ tagData.createdBy = context.user.did;
341
+ tagData.updatedBy = context.user.did;
342
+ const doc = await state.insert(tagData);
284
343
  logger.info('tags created successfully', { teamDid, tag });
285
344
  return doc;
286
345
  }
287
346
 
288
- async updateTag({ teamDid, tag }) {
347
+ async updateTag({ teamDid, tag }, context = {}) {
289
348
  if (!tag.id) {
290
349
  throw new Error('Must specify tag.id to update');
291
350
  }
292
351
 
352
+ const keys = ['title', 'description', 'color', 'slug', 'type', 'componentDid', 'parentId'];
353
+ const tagData = Object.fromEntries(keys.map((key) => [key, tag[key] ?? null]));
354
+ tagData.updatedBy = context.user.did;
355
+
293
356
  const state = await this.getTagState(teamDid);
294
- const result = await state.updateById(tag.id, pick(tag, ['title', 'color', 'description']));
357
+ const result = await state.updateById(tag.id, tagData);
295
358
  logger.info('tags updated successfully', { teamDid, tag, result });
296
359
  return state.findOne({ id: tag.id });
297
360
  }
298
361
 
299
- async deleteTag({ teamDid, tag }) {
362
+ async deleteTag({ teamDid, tag, moveTo }) {
300
363
  if (!tag.id) {
301
364
  throw new Error('Must specify tag.id to delete');
302
365
  }
303
366
 
304
367
  const state = await this.getTagState(teamDid);
368
+ const taggingState = await this.getTaggingState(teamDid);
369
+
370
+ if (moveTo) {
371
+ const records = await taggingState.find({ tagId: tag.id });
372
+
373
+ await Promise.all(
374
+ records.map(async (record) => {
375
+ const found = await taggingState.findOne({
376
+ tagId: moveTo,
377
+ taggableId: record.taggableId,
378
+ taggableType: record.taggableType,
379
+ });
380
+ if (found) {
381
+ await taggingState.remove(record);
382
+ logger.info('tag already at moveTo, deleted record', { teamDid, tag, record });
383
+ } else {
384
+ await taggingState.update({ tagId: record.tagId }, { $set: { tagId: moveTo } });
385
+ logger.info('tag moved successfully', { teamDid, tag, record, moveTo });
386
+ }
387
+ })
388
+ );
389
+ }
390
+
305
391
  const doc = await state.remove({ id: tag.id });
392
+ await taggingState.remove({ tagId: tag.id });
306
393
  logger.info('tags deleted successfully', { teamDid, tag });
307
394
  return doc;
308
395
  }
@@ -2042,6 +2129,10 @@ class TeamAPI extends EventEmitter {
2042
2129
  return this.teamManager.getTagState(did);
2043
2130
  }
2044
2131
 
2132
+ getTaggingState(did) {
2133
+ return this.teamManager.getTaggingState(did);
2134
+ }
2135
+
2045
2136
  getSessionState(did) {
2046
2137
  return this.teamManager.getSessionState(did);
2047
2138
  }
@@ -125,7 +125,7 @@ const toBlockletDid = require('@blocklet/meta/lib/did');
125
125
  const { updateComponentDid, removeUploadFile } = require('@abtnode/util/lib/upload-component');
126
126
 
127
127
  const groupBy = require('lodash/groupBy');
128
- const { isDidDomain, isCustomDomain } = require('@abtnode/util/lib/url-evaluation');
128
+ const { isDidDomain, isCustomDomain, getOriginUrl } = require('@abtnode/util/lib/url-evaluation');
129
129
  const { DBCache, getAbtNodeRedisAndSQLiteUrl } = require('@abtnode/db-cache');
130
130
  const { isInstanceWorker } = require('@abtnode/util/lib/pm2/is-instence-worker.js');
131
131
  const launcher = require('../../util/launcher');
@@ -2065,7 +2065,16 @@ class DiskBlockletManager extends BaseBlockletManager {
2065
2065
  throw new Error(error.message);
2066
2066
  }
2067
2067
 
2068
- await states.blockletExtras.setSettings(did, { theme: value });
2068
+ const currentSettings = await states.blockletExtras.getSettings(did);
2069
+ const currentTheme = currentSettings.theme || {};
2070
+
2071
+ // 锁定校验
2072
+ if (value.concepts && currentTheme.meta?.locked) {
2073
+ throw new CustomError(403, 'Theme is locked and cannot be modified');
2074
+ }
2075
+
2076
+ const updatedTheme = { ...currentTheme, ...value };
2077
+ await states.blockletExtras.setSettings(did, { theme: updatedTheme });
2069
2078
 
2070
2079
  const newState = await this.getBlocklet(did);
2071
2080
  this.emit(BlockletInternalEvents.appSettingChanged, { appDid: did });
@@ -2325,6 +2334,7 @@ class DiskBlockletManager extends BaseBlockletManager {
2325
2334
 
2326
2335
  async setInitialized({ did, owner, purpose = '' }, context) {
2327
2336
  if (!validateOwner(owner)) {
2337
+ logger.warn('Blocklet owner is invalid for setInitialized', { did, owner });
2328
2338
  throw new Error('Blocklet owner is invalid');
2329
2339
  }
2330
2340
 
@@ -2340,7 +2350,8 @@ class DiskBlockletManager extends BaseBlockletManager {
2340
2350
 
2341
2351
  async updateOwner({ did, owner }, context) {
2342
2352
  if (!validateOwner(owner)) {
2343
- throw new Error('owner is invalid');
2353
+ logger.warn('Blocklet owner is invalid for updateOwner', { did, owner });
2354
+ throw new Error('Blocklet owner is invalid');
2344
2355
  }
2345
2356
 
2346
2357
  const blocklet = await states.blocklet.getBlocklet(did);
@@ -2923,7 +2934,10 @@ class DiskBlockletManager extends BaseBlockletManager {
2923
2934
  if (key && !decryptedKey) {
2924
2935
  throw new CustomError(400, 'Save failed, the API key is not encrypted');
2925
2936
  }
2926
- params.aigne = aigne;
2937
+ params.aigne = {
2938
+ ...aigne,
2939
+ url: getOriginUrl(aigne.url),
2940
+ };
2927
2941
  }
2928
2942
  const keys = Object.keys(params);
2929
2943
  if (!keys.length) {
@@ -3023,7 +3037,9 @@ class DiskBlockletManager extends BaseBlockletManager {
3023
3037
  throw new CustomError(400, 'blocklet did invalid, no blocklet found');
3024
3038
  }
3025
3039
  const aigneSetting = get(blocklet, 'settings.aigne', {});
3026
- if (aigneSetting.key !== key && url !== aigneSetting.url) {
3040
+ const _url = getOriginUrl(url);
3041
+ const settingUrl = getOriginUrl(aigneSetting.url);
3042
+ if (aigneSetting.key !== key && _url !== settingUrl) {
3027
3043
  throw new CustomError(400, 'Invalid key or url provided');
3028
3044
  }
3029
3045
  await states.blockletExtras.setSettings(did, {
@@ -38946,7 +38946,7 @@ module.exports = require("zlib");
38946
38946
  /***/ ((module) => {
38947
38947
 
38948
38948
  "use strict";
38949
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@abtnode/core","publishConfig":{"access":"public"},"version":"1.16.51","description":"","main":"lib/index.js","files":["lib"],"scripts":{"lint":"eslint tests lib --ignore-pattern \'tests/assets/*\'","lint:fix":"eslint --fix tests lib","test":"node tools/jest.js","test:disk":"node tools/jest.js tests/blocklet/manager/disk.spec.js","coverage":"npm run test -- --coverage"},"keywords":[],"author":"wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)","license":"Apache-2.0","dependencies":{"@abtnode/analytics":"1.16.51","@abtnode/auth":"1.16.51","@abtnode/certificate-manager":"1.16.51","@abtnode/constant":"1.16.51","@abtnode/cron":"1.16.51","@abtnode/db-cache":"1.16.51","@abtnode/docker-utils":"1.16.51","@abtnode/logger":"1.16.51","@abtnode/models":"1.16.51","@abtnode/queue":"1.16.51","@abtnode/rbac":"1.16.51","@abtnode/router-provider":"1.16.51","@abtnode/static-server":"1.16.51","@abtnode/timemachine":"1.16.51","@abtnode/util":"1.16.51","@aigne/aigne-hub":"^0.8.10","@arcblock/did":"1.24.0","@arcblock/did-connect-js":"1.24.0","@arcblock/did-ext":"1.24.0","@arcblock/did-motif":"^1.1.14","@arcblock/did-util":"1.24.0","@arcblock/event-hub":"1.24.0","@arcblock/jwt":"1.24.0","@arcblock/pm2-events":"^0.0.5","@arcblock/validator":"1.24.0","@arcblock/vc":"1.24.0","@blocklet/constant":"1.16.51","@blocklet/did-space-js":"^1.1.24","@blocklet/env":"1.16.51","@blocklet/error":"^0.2.5","@blocklet/meta":"1.16.51","@blocklet/resolver":"1.16.51","@blocklet/sdk":"1.16.51","@blocklet/server-js":"1.16.51","@blocklet/store":"1.16.51","@blocklet/theme":"^3.1.41","@fidm/x509":"^1.2.1","@ocap/mcrypto":"1.24.0","@ocap/util":"1.24.0","@ocap/wallet":"1.24.0","@slack/webhook":"^5.0.4","archiver":"^7.0.1","axios":"^1.7.9","axon":"^2.0.3","chalk":"^4.1.2","cross-spawn":"^7.0.3","dayjs":"^1.11.13","deep-diff":"^1.0.2","detect-port":"^1.5.1","envfile":"^7.1.0","escape-string-regexp":"^4.0.0","fast-glob":"^3.3.2","filesize":"^10.1.1","flat":"^5.0.2","fs-extra":"^11.2.0","get-port":"^5.1.1","hasha":"^5.2.2","is-base64":"^1.1.0","is-cidr":"4","is-ip":"3","is-url":"^1.2.4","joi":"17.12.2","joi-extension-semver":"^5.0.0","js-yaml":"^4.1.0","kill-port":"^2.0.1","lodash":"^4.17.21","node-stream-zip":"^1.15.0","p-all":"^3.0.0","p-limit":"^3.1.0","p-map":"^4.0.0","p-retry":"^4.6.2","p-wait-for":"^3.2.0","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":{"expand-tilde":"^2.0.2","express":"^4.18.2","jest":"^29.7.0","unzipper":"^0.10.11"},"gitHead":"e5764f753181ed6a7c615cd4fc6682aacf0cb7cd"}');
38949
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@abtnode/core","publishConfig":{"access":"public"},"version":"1.16.51","description":"","main":"lib/index.js","files":["lib"],"scripts":{"lint":"eslint tests lib --ignore-pattern \'tests/assets/*\'","lint:fix":"eslint --fix tests lib","test":"node tools/jest.js","test:disk":"node tools/jest.js tests/blocklet/manager/disk.spec.js","coverage":"npm run test -- --coverage"},"keywords":[],"author":"wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)","license":"Apache-2.0","dependencies":{"@abtnode/analytics":"1.16.51","@abtnode/auth":"1.16.51","@abtnode/certificate-manager":"1.16.51","@abtnode/constant":"1.16.51","@abtnode/cron":"1.16.51","@abtnode/db-cache":"1.16.51","@abtnode/docker-utils":"1.16.51","@abtnode/logger":"1.16.51","@abtnode/models":"1.16.51","@abtnode/queue":"1.16.51","@abtnode/rbac":"1.16.51","@abtnode/router-provider":"1.16.51","@abtnode/static-server":"1.16.51","@abtnode/timemachine":"1.16.51","@abtnode/util":"1.16.51","@aigne/aigne-hub":"^0.8.10","@arcblock/did":"1.24.0","@arcblock/did-connect-js":"1.24.0","@arcblock/did-ext":"1.24.0","@arcblock/did-motif":"^1.1.14","@arcblock/did-util":"1.24.0","@arcblock/event-hub":"1.24.0","@arcblock/jwt":"1.24.0","@arcblock/pm2-events":"^0.0.5","@arcblock/validator":"1.24.0","@arcblock/vc":"1.24.0","@blocklet/constant":"1.16.51","@blocklet/did-space-js":"^1.1.28","@blocklet/env":"1.16.51","@blocklet/error":"^0.2.5","@blocklet/meta":"1.16.51","@blocklet/resolver":"1.16.51","@blocklet/sdk":"1.16.51","@blocklet/server-js":"1.16.51","@blocklet/store":"1.16.51","@blocklet/theme":"^3.1.44","@fidm/x509":"^1.2.1","@ocap/mcrypto":"1.24.0","@ocap/util":"1.24.0","@ocap/wallet":"1.24.0","@slack/webhook":"^5.0.4","archiver":"^7.0.1","axios":"^1.7.9","axon":"^2.0.3","chalk":"^4.1.2","cross-spawn":"^7.0.3","dayjs":"^1.11.13","deep-diff":"^1.0.2","detect-port":"^1.5.1","envfile":"^7.1.0","escape-string-regexp":"^4.0.0","fast-glob":"^3.3.2","filesize":"^10.1.1","flat":"^5.0.2","fs-extra":"^11.2.0","get-port":"^5.1.1","hasha":"^5.2.2","is-base64":"^1.1.0","is-cidr":"4","is-ip":"3","is-url":"^1.2.4","joi":"17.12.2","joi-extension-semver":"^5.0.0","js-yaml":"^4.1.0","kill-port":"^2.0.1","lodash":"^4.17.21","node-stream-zip":"^1.15.0","p-all":"^3.0.0","p-limit":"^3.1.0","p-map":"^4.0.0","p-retry":"^4.6.2","p-wait-for":"^3.2.0","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":{"expand-tilde":"^2.0.2","express":"^4.18.2","jest":"^29.7.0","unzipper":"^0.10.11"},"gitHead":"e5764f753181ed6a7c615cd4fc6682aacf0cb7cd"}');
38950
38950
 
38951
38951
  /***/ }),
38952
38952
 
package/lib/index.js CHANGED
@@ -552,6 +552,9 @@ function ABTNode(options) {
552
552
  deleteTag: teamAPI.deleteTag.bind(teamAPI),
553
553
  getTags: teamAPI.getTags.bind(teamAPI),
554
554
 
555
+ createTagging: teamAPI.createTagging.bind(teamAPI),
556
+ deleteTagging: teamAPI.deleteTagging.bind(teamAPI),
557
+
555
558
  // Access Control
556
559
  getRBAC: (did = options.nodeDid) => teamManager.getRBAC(did),
557
560
 
package/lib/locales/en.js CHANGED
@@ -1,19 +1,19 @@
1
1
  /* eslint-disable prettier/prettier */
2
2
  module.exports = {
3
3
  registry: {
4
- getListError: 'Get Blocklet list from registry "{registryUrl}" failed.',
4
+ getListError: 'Failed to get blocklet list from registry "{registryUrl}"',
5
5
  },
6
6
  backup: {
7
7
  space: {
8
8
  error: {
9
- title: 'Backup to DID Spaces encountered error',
9
+ title: 'Backup to DID Spaces Failed',
10
10
  forbidden:
11
- 'You do not have permission to perform the backup, try restoring the application license on DID Spaces or reconnect to DID Spaces and try again',
11
+ 'You don\'t have permission to back up. Try restoring the license on DID Spaces or reconnect.',
12
12
  },
13
- isFull: 'The current DID Space storage space is full, please expand the space and back up again',
13
+ isFull: 'Your DID Spaces storage is full. Expand storage and try again.',
14
14
  lackOfSpace:
15
- 'The current available space in the storage is insufficient, Please expand the space and perform the backup again',
16
- unableEnableAutoBackup: 'unable to enable auto backup, please connect to DID Spaces first',
15
+ 'Not enough storage space. Expand storage and try again.',
16
+ unableEnableAutoBackup: 'Connect to DID Spaces before enabling auto backup.',
17
17
  },
18
18
  },
19
19
  };
@@ -2,7 +2,7 @@ const maxBy = require('lodash/maxBy');
2
2
 
3
3
  const getHistoryList = ({ history, hours, recordIntervalSec, props = [] }) => {
4
4
  if (hours < 1 || hours > 24) {
5
- throw new Error('hours should between 1 to 24');
5
+ throw new Error('hours should be between 1 and 24');
6
6
  }
7
7
  const intHours = Math.floor(hours);
8
8
 
@@ -798,11 +798,11 @@ module.exports = function getRouterHelpers({
798
798
  const privateKeyFilePath = path.join(destFolder, 'privkey.pem');
799
799
 
800
800
  if (!fs.existsSync(certificateFilePath)) {
801
- throw new Error('dashboard certificate invalid: cert.pem not exists');
801
+ throw new Error('dashboard certificate invalid: cert.pem does not exist');
802
802
  }
803
803
 
804
804
  if (!fs.existsSync(privateKeyFilePath)) {
805
- throw new Error('dashboard certificate invalid: privkey.pem not exists');
805
+ throw new Error('dashboard certificate invalid: privkey.pem does not exist');
806
806
  }
807
807
 
808
808
  const certificate = fs.readFileSync(certificateFilePath).toString();
@@ -179,8 +179,7 @@ class RouterManager extends EventEmitter {
179
179
  async deleteRoutingSite({ id }, context = {}) {
180
180
  const site = await states.site.findOne({ id });
181
181
  if ([DOMAIN_FOR_IP_SITE, DOMAIN_FOR_DEFAULT_SITE].includes(site.domain)) {
182
- // eslint-disable-next-line quotes
183
- throw new Error("Can not delete this site because it's protected");
182
+ throw new Error('Cannot delete this site because it is protected');
184
183
  }
185
184
 
186
185
  const removedSiteCount = await states.site.remove({ id });
@@ -198,7 +197,7 @@ class RouterManager extends EventEmitter {
198
197
  const site = await validateUpdateSite(params, context);
199
198
  const existed = await states.site.findOne({ id: site.id });
200
199
  if (!existed) {
201
- throw new Error('Can not update non-existing site');
200
+ throw new Error('Cannot update non-existing site');
202
201
  }
203
202
 
204
203
  const updateSet = {};
@@ -101,7 +101,7 @@ class AccessKeyState extends BaseState {
101
101
  };
102
102
  }
103
103
 
104
- findPaginated({ remark, componentDid, resourceId, resourceType, paging } = {}, context) {
104
+ findPaginated({ remark: keywords, componentDid, resourceId, resourceType, paging } = {}, context) {
105
105
  validateOperator(context);
106
106
  const conditions = {
107
107
  where: {},
@@ -115,8 +115,12 @@ class AccessKeyState extends BaseState {
115
115
  if (resourceType) {
116
116
  conditions.where.resourceType = resourceType;
117
117
  }
118
- if (remark) {
119
- conditions.where.remark = { [Op.like]: `%${remark}%` };
118
+ // 模糊搜索
119
+ if (keywords) {
120
+ conditions.where[Op.or] = [
121
+ { remark: { [Op.like]: `%${keywords}%` } },
122
+ { accessKeyId: { [Op.like]: `%${keywords}%` } },
123
+ ];
120
124
  }
121
125
  const pathname = getEndpoint(context);
122
126
  const queryCreatedById = isUserCenterPath(pathname) ? context.user.did : '';
@@ -499,6 +499,10 @@ const getLogContent = async (action, args, context, result, info, node) => {
499
499
  return `deleted tag ${args.tag.id}`;
500
500
  case 'destroySelf':
501
501
  return `user ${result.did} initiated account deletion`;
502
+ case 'createTagging':
503
+ return `created tagging ${args.tagging.tagId} for ${args.tagging.taggableIds.join(', ')}`;
504
+ case 'deleteTagging':
505
+ return `deleted tagging ${args.tagging.tagId} for ${args.tagging.taggableIds.join(', ')}`;
502
506
 
503
507
  // accessKeys
504
508
  case 'createAccessKey':
@@ -0,0 +1,8 @@
1
+ const BaseState = require('./base');
2
+
3
+ /**
4
+ * @extends BaseState<import('@abtnode/models').TaggingState>
5
+ */
6
+ class Tagging extends BaseState {}
7
+
8
+ module.exports = Tagging;
@@ -41,6 +41,7 @@ const States = {
41
41
  ConnectedAccount: require('../states/connect-account'),
42
42
  Session: require('../states/session'),
43
43
  Tag: require('../states/tag'),
44
+ Tagging: require('../states/tagging'),
44
45
  Project: require('../states/project'),
45
46
  Release: require('../states/release'),
46
47
  Notification: require('../states/notification'),
@@ -67,6 +68,7 @@ const getDefaultTeamState = () => ({
67
68
  connectedAccount: null,
68
69
  session: null,
69
70
  tag: null,
71
+ tagging: null,
70
72
  project: null,
71
73
  release: null,
72
74
  notification: null,
@@ -140,6 +142,7 @@ class TeamManager extends EventEmitter {
140
142
  user: await this.createState(this.nodeDid, 'User'),
141
143
  userSession: await this.createState(this.nodeDid, 'UserSession'),
142
144
  tag: await this.createState(this.nodeDid, 'Tag'),
145
+ tagging: await this.createState(this.nodeDid, 'Tagging'),
143
146
  passport: await this.createState(this.nodeDid, 'Passport'),
144
147
  passportLog: await this.createState(this.nodeDid, 'PassportLog'),
145
148
  connectedAccount: await this.createState(this.nodeDid, 'ConnectedAccount'),
@@ -170,6 +173,10 @@ class TeamManager extends EventEmitter {
170
173
  return this.getState(teamDid, 'tag');
171
174
  }
172
175
 
176
+ getTaggingState(teamDid) {
177
+ return this.getState(teamDid, 'tagging');
178
+ }
179
+
173
180
  getPassportState(teamDid) {
174
181
  return this.getState(teamDid, 'passport');
175
182
  }
@@ -817,6 +824,7 @@ class TeamManager extends EventEmitter {
817
824
  const rbac = await this.getRBAC(did);
818
825
  const user = await this.createState(did, 'User');
819
826
  const tag = await this.createState(did, 'Tag');
827
+ const tagging = await this.createState(did, 'Tagging');
820
828
  const passport = await this.createState(did, 'Passport');
821
829
  const passportLog = await this.createState(did, 'PassportLog');
822
830
  const connectedAccount = await this.createState(did, 'ConnectedAccount');
@@ -828,6 +836,7 @@ class TeamManager extends EventEmitter {
828
836
  user,
829
837
  userSession,
830
838
  tag,
839
+ tagging,
831
840
  session,
832
841
  passport,
833
842
  passportLog,
@@ -329,7 +329,6 @@ const setupAppOwner = async ({
329
329
  },
330
330
  node
331
331
  );
332
- logger.info('Create owner for blocklet', { appDid, ownerDid, sessionId });
333
332
 
334
333
  if (passport) {
335
334
  await node.createPassportLog(appDid, {
@@ -358,8 +357,10 @@ const setupAppOwner = async ({
358
357
  });
359
358
 
360
359
  if (justCreate || autoStart) {
360
+ logger.info('Create owner for blocklet: setBlockletInitialized', { appDid, ownerDid, sessionId });
361
361
  await node.setBlockletInitialized({ did: appDid, owner: { did: ownerDid, pk: ownerPk } });
362
362
  } else {
363
+ logger.info('Create owner for blocklet: setBlockletOwner', { appDid, ownerDid, sessionId });
363
364
  await node.setBlockletOwner({ did: appDid, owner: { did: ownerDid, pk: ownerPk } });
364
365
  }
365
366
 
@@ -389,20 +390,6 @@ const setupAppOwner = async ({
389
390
 
390
391
  logger.info('created user session', { appDid, ownerDid, userSession });
391
392
 
392
- // FIXME: this always throw error
393
- // if (autoStart) {
394
- // node
395
- // .startBlocklet({
396
- // did: appDid,
397
- // checkHealthImmediately: false,
398
- // throwOnError: true,
399
- // atomic: false,
400
- // })
401
- // .catch((error) => {
402
- // logger.error('blocklet auto start failed', { error, appDid });
403
- // });
404
- // }
405
-
406
393
  return {
407
394
  session,
408
395
  blocklet,
@@ -187,12 +187,30 @@ const conceptSchema = Joi.object({
187
187
  editor: editorStateSchema.required(),
188
188
  }).options({ allowUnknown: true, stripUnknown: true });
189
189
 
190
- const blockletThemeSchema = Joi.object({
190
+ // Theme data schema (concepts and currentConceptId)
191
+ const themeDataSchema = Joi.object({
191
192
  concepts: Joi.array().items(conceptSchema).required(),
192
193
  currentConceptId: Joi.string().required(),
193
194
  }).options({ allowUnknown: true, stripUnknown: true });
194
195
 
196
+ // Theme meta schema for storing metadata like locked status
197
+ const themeMetaSchema = Joi.object({
198
+ meta: Joi.object({
199
+ locked: Joi.boolean().required(),
200
+ }).required(),
201
+ }).options({ allowUnknown: true, stripUnknown: true });
202
+
203
+ // Top-level blocklet theme schema - either theme data OR meta, not both
204
+ const blockletThemeSchema = Joi.alternatives().try(
205
+ // Theme data schema
206
+ themeDataSchema,
207
+ // Meta-only schema
208
+ themeMetaSchema
209
+ );
210
+
195
211
  module.exports = {
196
212
  muiThemeSchema,
197
213
  blockletThemeSchema,
214
+ themeDataSchema,
215
+ themeMetaSchema,
198
216
  };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.16.52-beta-20250928-042319-ff3f0e04",
6
+ "version": "1.16.52-beta-20250930-134044-9b691563",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -20,21 +20,21 @@
20
20
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
21
21
  "license": "Apache-2.0",
22
22
  "dependencies": {
23
- "@abtnode/analytics": "1.16.52-beta-20250928-042319-ff3f0e04",
24
- "@abtnode/auth": "1.16.52-beta-20250928-042319-ff3f0e04",
25
- "@abtnode/certificate-manager": "1.16.52-beta-20250928-042319-ff3f0e04",
26
- "@abtnode/constant": "1.16.52-beta-20250928-042319-ff3f0e04",
27
- "@abtnode/cron": "1.16.52-beta-20250928-042319-ff3f0e04",
28
- "@abtnode/db-cache": "1.16.52-beta-20250928-042319-ff3f0e04",
29
- "@abtnode/docker-utils": "1.16.52-beta-20250928-042319-ff3f0e04",
30
- "@abtnode/logger": "1.16.52-beta-20250928-042319-ff3f0e04",
31
- "@abtnode/models": "1.16.52-beta-20250928-042319-ff3f0e04",
32
- "@abtnode/queue": "1.16.52-beta-20250928-042319-ff3f0e04",
33
- "@abtnode/rbac": "1.16.52-beta-20250928-042319-ff3f0e04",
34
- "@abtnode/router-provider": "1.16.52-beta-20250928-042319-ff3f0e04",
35
- "@abtnode/static-server": "1.16.52-beta-20250928-042319-ff3f0e04",
36
- "@abtnode/timemachine": "1.16.52-beta-20250928-042319-ff3f0e04",
37
- "@abtnode/util": "1.16.52-beta-20250928-042319-ff3f0e04",
23
+ "@abtnode/analytics": "1.16.52-beta-20250930-134044-9b691563",
24
+ "@abtnode/auth": "1.16.52-beta-20250930-134044-9b691563",
25
+ "@abtnode/certificate-manager": "1.16.52-beta-20250930-134044-9b691563",
26
+ "@abtnode/constant": "1.16.52-beta-20250930-134044-9b691563",
27
+ "@abtnode/cron": "1.16.52-beta-20250930-134044-9b691563",
28
+ "@abtnode/db-cache": "1.16.52-beta-20250930-134044-9b691563",
29
+ "@abtnode/docker-utils": "1.16.52-beta-20250930-134044-9b691563",
30
+ "@abtnode/logger": "1.16.52-beta-20250930-134044-9b691563",
31
+ "@abtnode/models": "1.16.52-beta-20250930-134044-9b691563",
32
+ "@abtnode/queue": "1.16.52-beta-20250930-134044-9b691563",
33
+ "@abtnode/rbac": "1.16.52-beta-20250930-134044-9b691563",
34
+ "@abtnode/router-provider": "1.16.52-beta-20250930-134044-9b691563",
35
+ "@abtnode/static-server": "1.16.52-beta-20250930-134044-9b691563",
36
+ "@abtnode/timemachine": "1.16.52-beta-20250930-134044-9b691563",
37
+ "@abtnode/util": "1.16.52-beta-20250930-134044-9b691563",
38
38
  "@aigne/aigne-hub": "^0.8.10",
39
39
  "@arcblock/did": "1.24.0",
40
40
  "@arcblock/did-connect-js": "1.24.0",
@@ -46,16 +46,16 @@
46
46
  "@arcblock/pm2-events": "^0.0.5",
47
47
  "@arcblock/validator": "1.24.0",
48
48
  "@arcblock/vc": "1.24.0",
49
- "@blocklet/constant": "1.16.52-beta-20250928-042319-ff3f0e04",
50
- "@blocklet/did-space-js": "^1.1.24",
51
- "@blocklet/env": "1.16.52-beta-20250928-042319-ff3f0e04",
49
+ "@blocklet/constant": "1.16.52-beta-20250930-134044-9b691563",
50
+ "@blocklet/did-space-js": "^1.1.28",
51
+ "@blocklet/env": "1.16.52-beta-20250930-134044-9b691563",
52
52
  "@blocklet/error": "^0.2.5",
53
- "@blocklet/meta": "1.16.52-beta-20250928-042319-ff3f0e04",
54
- "@blocklet/resolver": "1.16.52-beta-20250928-042319-ff3f0e04",
55
- "@blocklet/sdk": "1.16.52-beta-20250928-042319-ff3f0e04",
56
- "@blocklet/server-js": "1.16.52-beta-20250928-042319-ff3f0e04",
57
- "@blocklet/store": "1.16.52-beta-20250928-042319-ff3f0e04",
58
- "@blocklet/theme": "^3.1.41",
53
+ "@blocklet/meta": "1.16.52-beta-20250930-134044-9b691563",
54
+ "@blocklet/resolver": "1.16.52-beta-20250930-134044-9b691563",
55
+ "@blocklet/sdk": "1.16.52-beta-20250930-134044-9b691563",
56
+ "@blocklet/server-js": "1.16.52-beta-20250930-134044-9b691563",
57
+ "@blocklet/store": "1.16.52-beta-20250930-134044-9b691563",
58
+ "@blocklet/theme": "^3.1.44",
59
59
  "@fidm/x509": "^1.2.1",
60
60
  "@ocap/mcrypto": "1.24.0",
61
61
  "@ocap/util": "1.24.0",
@@ -119,5 +119,5 @@
119
119
  "jest": "^29.7.0",
120
120
  "unzipper": "^0.10.11"
121
121
  },
122
- "gitHead": "2390501ff6e05cbf356f751ced062803e3562465"
122
+ "gitHead": "922d7f11acfdfafe4494f59add4884fe73954a0b"
123
123
  }