SuperAPI AI 工具集

syncable-entity-cache-and-transform

编程与开发

查看项目

更新于 10-16 02:14

技能介绍

该技能属于 Twenty(twentyhq/twenty)服务端内部同步实体开发流程的第 2/6 步,主题为缓存与转换。其用途是在完成第 1 步(类型与常量)之后,创建缓存层与转换工具,用于在不同实体表示形式之间进行转换;它也是构建校验器与 action 处理器之前的必要环节。需要强调的是,本技能面向向 Twenty 代码库本身贡献代码(Twenty 服务端内部),而不是用于在 Twenty 之上构建应用。

本步骤创建三类内容:面向扁平实体映射(flat entity maps)的缓存服务、实体到扁平实体的转换工具,以及输入转换工具(DTO 转为通用扁平实体 Universal Flat Entity)。

关键原则:输入转换工具必须输出通用扁平实体,即带有 universalIdentifier,且外键需映射为通用标识符(universal identifiers)。

一、创建缓存服务 文件路径为 src/engine/metadata-modules/flat-my-entity/services/flat-my-entity-cache.service.ts。示例使用 NestJS 的 @Injectable、@InjectRepository,注入类型为 metadata 数据源的 Repository,并使用 @WorkspaceCache({ flatMapsKey: 'flatMyEntityMaps' }) 装饰器修饰 getFlatMyEntityMaps 方法。该方法通过 myEntityRepository.find({ withDeleted: true }) 查询实体(关键点:包含软删除实体),再用 fromMyEntityEntityToFlatMyEntity 映射,返回结构为 { byId, byName } 的映射对象。

关键规则:使用 @WorkspaceCache 装饰器并提供唯一的 flatMapsKey;始终使用 withDeleted: true 以包含软删除实体;缓存键模式为 flat{EntityName}Maps(驼峰命名)。

二、实体到扁平实体的转换 文件路径为 src/engine/metadata-modules/flat-my-entity/utils/from-my-entity-entity-to-flat-my-entity.util.ts。导出的 fromMyEntityEntityToFlatMyEntity 接收实体,返回扁平实体,字段包括 id、universalIdentifier、workspaceId、applicationId、name、label、description、isCustom、parentEntityId、settings、createdAt、updatedAt、deletedAt。其中 createdAt、updatedAt 通过 toISOString() 转换,deletedAt 使用可选链并在缺失时返回 null。关键点:universalIdentifier 必须是用 v4() 生成的新 UUID,而不是 entity.id。

三、输入转换工具(DTO 转为通用扁平实体) 文件路径为 src/engine/metadata-modules/flat-my-entity/utils/from-create-my-entity-input-to-universal-flat-my-entity.util.ts。导出的函数接收 { input, workspaceId, flatEntityMaps },其中 input 为 CreateMyEntityInput,workspaceId 为字符串,flatEntityMaps 可选。步骤包括:生成 id 与 universalIdentifier(均使用 v4());在 sanitize 之前提取外键(parentEntityId);使用 twenty-shared/string 的 sanitizeString 对所有字符串属性(name、label、description)进行清理,description 为空时置 null;构建基础扁平实体;若提供 flatEntityMaps,则调用 resolveEntityRelationUniversalIdentifiers 解析外键为通用标识符;若未提供映射,则返回 parentEntityUniversalIdentifier 为 null 的实体。

四、创建扁平实体模块 文件路径为 src/engine/metadata-modules/flat-my-entity/flat-my-entity.module.ts。使用 NestJS @Module,imports 中通过 TypeOrmModule.forFeature([MyEntityEntity], 'metadata') 导入实体,providers 与 exports 均为 FlatMyEntityCacheService。规则:使用 metadata 数据源导入实体;导出缓存服务供其他模块使用。

常见模式方面,资料给出三种:外键解析(在清理前先提取外键,构建基础实体后再解析为通用标识符);带 SerializedRelation 的 JSONB(对包含外键的 JSONB 属性,在解析后 JSONB 外键变为通用标识符);更新转换(from-update-my-entity-input-to-universal-flat-my-entity-updates.util.ts,按字段是否存在进行更新,设置 updatedAt,若有映射则解析外键)。

检查清单要求在进入第 3 步之前完成:缓存服务已创建并使用 @WorkspaceCache 装饰器;缓存使用 withDeleted: true;缓存键遵循 flat{EntityName}Maps 模式;实体到扁平转换已实现;universalIdentifier 正确设置(用 v4() 生成);创建输入转换已实现;更新输入转换已实现(如需要);外键在清理前提取;字符串属性已清理;外键已解析为通用标识符;扁平实体模块已创建并导出缓存服务。

完成缓存与转换工具后,下一步是 Syncable Entity: Builder & Validation(Step 3/6);完整工作流可参考 creating-syncable-entity 规则。