ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

NocoBase 用户数据同步插件:扩展同步目标资源(UserDataResource 与资源注册实战)

NocoBase 用户数据同步插件:扩展同步目标资源(UserDataResource 与资源注册实战) NocoBase 用户数据同步插件扩展同步目标资源UserDataResource 与资源注册实战【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase本篇基于 NocoBase 开发者文档「扩展同步目标资源」整理。NocoBase 的用户数据同步User Data Sync默认只把同步来的数据写入内置的用户表和部门表而通过plugin-user-data-sync提供的UserDataResource抽象接口开发者可以在自己的插件中把同一份用户/部门数据同步写入任意其他表或执行自定义业务逻辑。读完后你将掌握UserDataResource接口的完整字段与两个抽象方法的语义、resourceManager.registerResource的注册方式与拓扑排序参数、同步管理器驱动create/update的完整调用链以及一个可直接套用的自定义同步资源示例。1. 背景同步目标资源是什么NocoBase 的用户数据同步链路为同步源Sync Source拉取原始用户/部门数据 → 管理器把数据暂存为原始记录OriginRecord→ 遍历所有已注册的目标资源UserDataResource对每条原始记录调用其create或update方法把数据写入目标表 → 把原始记录 ↔ 目标资源主键的映射持久化供下一轮增量更新使用。内置插件分别注册了两个目标资源用户表资源plugin-users在加载时向resourceManager注册UserDataSyncResourcename usersaccepts [user]见 plugin-users 服务端入口部门表资源plugin-departments注册DepartmentDataSyncResourcename departmentsaccepts [department]见 plugin-departments 插件。扩展同步目标资源就是编写第三个、第 N 个这样的资源例如把同步来的用户数据再写一份到你的员工档案表或者同步部门数据到自建的组织表。2. 目标资源处理接口 UserDataResource所有目标资源必须继承UserDataResource抽象类。该接口定义在 user-data-resource-manager.ts第 7192 行完整结构如下export abstract class UserDataResource { name: string; accepts: SyncAccept[]; db: Database; logger: SystemLogger; constructor(db: Database, logger: SystemLogger) { this.db db; this.logger logger; } abstract update( record: OriginRecord, resourcePks: PrimaryKey[], matchKey?: string, ): PromiseRecordResourceChanged[]; abstract create( record: OriginRecord, matchKey: string, ): PromiseRecordResourceChanged[]; get syncRecordRepo() { return this.db.getRepository(userDataSyncRecords); } get syncRecordResourceRepo() { return this.db.getRepository(userDataSyncRecordsResources); } }各成员的含义name资源名是资源在管理器中的唯一标识也是同步映射表中resource字段存储的值。必填注册时若缺失会抛出错误见 resource-manager.test.ts 中对name for user data synchronize resource is required的断言。accepts该资源接受的数据类型数组取值为user或departmentSyncAccept user | department。必填同样会在注册时被校验。db/logger构造时注入的数据库实例与系统日志实现中直接可用。update(record, resourcePks, matchKey?)原始记录已经映射过本资源时调用。resourcePks是上一轮同步记录中已关联的目标资源主键列表实现中通常需要按这些主键加载目标表记录并更新。内置用户资源还会处理目标记录被手工删除的兜底逻辑——找不到记录时回退到create并返回{ resourcesPk: resourcePk, isDeleted: true }通知管理器清理旧映射见 用户表同步资源实现。create(record, matchKey)原始记录尚未映射本资源时调用。matchKey是同步源配置的匹配字段内置用户资源支持phone、email、username三种取值用于先查后更新实现可忽略它直接新建记录。syncRecordRepo/syncRecordResourceRepo内置快捷访问器分别指向userDataSyncRecords原始记录表与userDataSyncRecordsResources原始记录与目标资源主键的映射表你的资源如果需要自行读写同步元数据可直接使用。与接口配套的输入/输出类型同样定义在 user-data-resource-manager.ts 中export type OriginRecord { id: number; // userDataSyncRecords 主键 sourceName: string; // 同步源名称 sourceUk: string; // 同步源侧唯一标识uid dataType: SyncDataType; // user | department metaData: UserDataRecord; // 格式化后的用户/部门数据FormatUser / FormatDepartment resources: { // 该原始记录当前已关联的所有目标资源主键 resource: string; resourcePk: string; }[]; }; export type RecordResourceChanged { resourcesPk: PrimaryKey; // 你写入的目标资源主键number | string isDeleted: boolean; // true 表示让管理器移除该映射false 表示新增/保留映射 };create/update的返回值RecordResourceChanged[]是资源与管理器之间的回执管理器据此维护映射表。返回空数组表示无映射变化返回[{ resourcesPk: 12, isDeleted: false }]表示把主键 12 关联到当前原始记录。3. 同步管理器如何驱动资源updateOrCreate 调用链理解接口行为的关键在于 UserDataResourceManager.updateOrCreate第 213288 行其流程为落库原始记录saveOriginRecords先按sourceName sourceUk dataType查userDataSyncRecords存在则把旧metaData存到lastMetaData再更新不存在则新建。注意每条记录必须有uid否则直接抛错record must has uid。按注册顺序遍历资源只处理accepts包含当前dataType的资源。判定 create 还是 update从originRecord.resources中过滤出resource 资源名的映射有映射走update并传入全部resourcePk无映射走create。按回执维护映射对返回的每个RecordResourceChangedisDeleted为true时调用removeResourceFromOriginRecord删除映射否则调用addResourceToOriginRecord通过syncRecord.createResource({ resource, resourcePk })写入 userDataSyncRecordsResources 映射表。容错与统计单条记录create/update抛错不会中断整批同步错误被收集进SyncResult.failedRecords含record与message最终每个资源产出一个{ resource, detail: { count: { all, success, failed }, failedRecords } }的统计结果。另外两条值得注意的行为保持输入顺序findOriginRecords会按传入sourceUks的顺序对查出的原始记录排序确保父部门在子部门之前、先出现的记录先处理这类顺序语义成立。官方测试 resource-manager-order.test.ts 用create:10 → update:20父部门先于子部门验证了这一点。原始记录表结构userDataSyncRecords集合定义在 user-data-sync-records.ts字段为sourceName、sourceUk、dataType、metaDatajson、lastMetaDatajson以及hasMany关联resources你的资源实现可以依赖这张表做差异对比。4. 注册目标资源注册入口是UserDataResourceManager的registerResource(resource: UserDataResource, options?: ToposortOptions)其中options是ToposortOptions来自nocobase/utils用于声明资源间的执行顺序。资源在管理器中通过Toposort容器resources new ToposortUserDataResource()管理name作为拓扑节点的 tagoptions.after/options.before可指定在某资源之后/之前执行。内置部门资源就用了这个参数——部门数据依赖用户先落库所以声明在users之后执行见 plugin-departments 插件第 151 行userDataSyncPlugin.resourceManager.registerResource( new DepartmentDataSyncResource(this.db, this.app.logger), { // write department records after writing user records after: users, }, );在自定义插件中注册的推荐写法继承自官方文档示例import { Plugin } from nocobase/server; import PluginUserDataSyncServer from nocobase/plugin-user-data-sync; class CustomUserResourcePluginServer extends Plugin { async load() { const userDataSyncPlugin this.app.pm.get(PluginUserDataSyncServer); if (userDataSyncPlugin userDataSyncPlugin.enabled) { userDataSyncPlugin.resourceManager.registerResource( new CustomDataSyncResource(this.app.db, this.app.logger), { after: users }, // 可选声明执行顺序 ); } } }要点必须通过this.app.pm.get(PluginUserDataSyncServer)获取同步插件实例并确认其enabledresourceManager属性在插件load()中初始化见 plugin-user-data-sync 服务端入口注册时机放在本插件load()与同步插件的加载时序配合或对应生命周期钩子中即可若你的资源依赖users/departments先写入完成务必像部门资源那样传{ after: users }之类的顺序约束否则从源码结构看无约束资源按注册顺序进入拓扑容器顺序不保证。5. 完整示例一个自定义用户同步资源先给一个最小可运行骨架参考插件内测试用的 mock-resource.tsimport { OriginRecord, PrimaryKey, RecordResourceChanged, SyncAccept, UserDataResource, } from nocobase/plugin-user-data-sync; import Database from nocobase/database; import { SystemLogger } from nocobase/logger; export class MyStaffResource extends UserDataResource { name staff-archives; // 同步映射表中的 resource 值 accepts: SyncAccept[] [user]; // 只处理用户数据 constructor(db: Database, logger: SystemLogger) { super(db, logger); } get staffRepo() { return this.db.getRepository(staffArchives); // 假设你已有该集合 } async update(record: OriginRecord, resourcePks: PrimaryKey[]): PromiseRecordResourceChanged[] { const staff await this.staffRepo.findOne({ filterByTk: resourcePks[0] }); if (!staff) { // 目标记录被手工删除时回退为重建并通知管理器删除旧映射 const result await this.create(record, ); return [...result, { resourcesPk: resourcePks[0], isDeleted: true }]; } staff.nickname record.metaData.nickname ?? staff.nickname; await staff.save(); return []; // 映射无变化 } async create(record: OriginRecord, matchKey: string): PromiseRecordResourceChanged[] { const staff await this.staffRepo.create({ values: { uid: record.sourceUk, nickname: record.metaData.nickname, username: record.metaData.username, source: record.sourceName, }, }); // 回执把新建记录的主键与原始记录建立映射下轮同步即走 update return [{ resourcesPk: staff.id, isDeleted: false }]; } }如果想看生产级实现内置用户表同步资源 user-data-sync-resource.ts 值得精读它演示了三个实用技巧字段白名单过滤getFlteredSourceUser用lodash.omit剔除id、uid、password、createdAt等不应被覆盖的字段后再写入删除语义update时若sourceUser.isDeleted为真则销毁目标用户但保留带 root 角色的账号不删matchKey 去重create时若matchKey属于[phone, email, username]先按该字段查库查到则更新而不是重复创建避免同一人产生多个账号。6. 验证与排查单测参考resource-manager.test.ts 覆盖注册参数校验与after排序resource-manager-order.test.ts 覆盖记录处理顺序api.test.ts 展示在测试中用resourceManager.registerResource挂 mock 资源后走完整同步 API 的方式可作为你插件的集成测试模板。日志同步插件通过createLogger输出到user-data-sync/%DATE%.logjson 格式update/create的成功明细debug 级与单条失败原因warn 级含originRecord上下文都会写入便于定位某条记录同步失败的原因。落库验证同步后检查userDataSyncRecordsmetaData/lastMetaData是否随轮次滚动与userDataSyncRecordsResourcesresource 你的资源名resourcePk是否指向目标表主键两张表即可确认资源是否生效。7. 注意事项与限制该能力在官方文档中标注为实验性接口尤其方法签名与回执协议可能随版本调整name与accepts为必填项缺失会在注册时直接抛错name同时是拓扑排序的 tag重复或冲突会影响顺序声明资源间有数据依赖时如目标表外键引用用户表用ToposortOptions的after/before显式声明顺序不要依赖注册先后create/update中的异常会被管理器捕获并计入failedRecords不会中断整批同步——这意味着你的实现内部要处理好部分失败的事务边界例如多目标表写入需要时自行使用事务本文基于当前仓库nocobase/plugin-user-data-sync的源码整理接口细节以 user-data-resource-manager.ts 为准原始开发者文档见 扩展同步目标资源。【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表