扩展 NocoBase 用户数据同步数据源:SyncSource 接口实现与注册全流程

发布时间:2026/9/18 12:35:47
扩展 NocoBase 用户数据同步数据源:SyncSource 接口实现与注册全流程 扩展 NocoBase 用户数据同步数据源SyncSource 接口实现与注册全流程【免费下载链接】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/nocobaseNocoBase 的用户数据同步插件nocobase/plugin-user-data-sync提供了从外部系统拉取用户与部门数据的扩展点。本文围绕官方文档「扩展同步数据源」展开完整覆盖SyncSource抽象类的pull()接口、UserData返回结构、服务端registerType类型注册以及客户端AdminSettingsForm配置表单的注册方式并结合插件源码验证了options配置的实际来源、任务生命周期与同步落库流程读完即可在自研插件中接入一个完整的自定义同步数据源。概述数据源类型如何被管理和使用用户数据同步插件的服务端入口在 PluginUserDataSyncServer。它在beforeLoad阶段注册SyncSourceModel并创建SyncSourceManager数据源类型注册与管理与UserDataResourceManager同步数据落库在load阶段创建UserDataSyncService并对外定义userData资源挂载了四个核心 actionAction作用userData:listSyncTypes列出已注册的同步数据源类型客户端「新增」下拉列表的数据来源userData:pull按数据源名称触发一次拉取同步userData:push推送同步userData:retry重试失败的同步任务从源码结构看扩展一个数据源需要「两条腿走路」服务端实现SyncSource子类并向sourceManager注册类型负责真正去外部系统pull()数据客户端向客户端插件的sourceTypes注册AdminSettingsForm组件负责在管理界面渲染该类型的自定义配置表单。数据源实例本身持久化在 userDataSyncSources 集合中核心字段包括name唯一的数据源名称、sourceType对应注册的类型标识、enabled是否启用默认false、optionsjson 类型自定义配置默认{}以及指向userDataSyncTasks的tasks一对多关联。这正是下面服务端与客户端两半代码衔接起来的「中间层」。服务端扩展数据源接口继承 SyncSource 抽象类内置的用户数据同步插件提供了数据源类型的注册和管理。扩展数据源类型需要继承插件提供的SyncSource抽象类并实现抽象方法pull()import { SyncSource, UserData } from nocobase/plugin-user-data-sync; class CustomSyncSource extends SyncSource { async pull(): PromiseUserData[] { return []; } }对照 SyncSource 抽象类源码可以看到它通过构造参数SyncSourceConfig包含sourceInstance、options、ctx注入了三个实例属性属性说明instance当前数据源的SyncSourceModel实例即userDataSyncSources集合中的一条记录因此可以直接读取this.instance.name等字段options数据源的自定义配置对象即userDataSyncSources.options字段中的 json 内容ctx请求上下文可用于访问数据库、日志等应用上下文能力除抽象方法pull()外SyncSource还内置了同步任务生命周期辅助方法扩展方无需自行管理任务状态方法行为源码位置newTask()创建一个status: init的任务batch为时间戳随机数生成sync-source.ts#L43-L46beginTask(taskId)校验任务处于init后置为processing否则抛错sync-source.ts#L48-L59endTask({ taskId, success, cost, message })校验任务处于processing后置为success/failed并记录耗时与错误信息sync-source.ts#L61-L75retryTask(taskId)仅当任务为failed时重置为processingsync-source.ts#L77-L90读取自定义配置 optionsSyncSource提供了options属性用于获取数据源的自定义配置如第三方系统的appid、secretimport { SyncSource, UserData } from nocobase/plugin-user-data-sync; class CustomSyncSource extends SyncSource { async pull(): PromiseUserData[] { //... const { appid, secret } this.options; //... return []; } }options的流转链路可以从源码得到印证SyncSourceManager.create() 在实例化数据源时将集合记录的sourceInstance.options原样传入构造函数即new syncSource({ sourceInstance, options: sourceInstance.options, ctx })。这些options的值由客户端配置表单提交后写入userDataSyncSources.optionsjson 字段默认{}因此服务端this.options上能取到的键名必须与客户端AdminSettingsForm收集并提交的字段保持一致。UserData 字段说明pull()的返回值是UserData[]其通用字段说明如下字段说明dataType数据类型可选值为user和departmentuniqueKey唯一标识字段records数据记录sourceName数据源名称若dataType为user则records包含以下字段字段说明id用户 IDnickname用户昵称avatar用户头像email邮箱phone手机号departments所属部门 ID 数组若dataType为department则records包含以下字段字段说明id部门 IDname部门名称parentId父级部门 ID源码核对提示对照当前仓库中的类型定义 UserDatamatchKey为可选字段且落库前会校验每条记录必须包含uid字段——saveOriginRecords 中若record.uid undefined会直接抛出record must has uid错误。当前源码中的 FormatUser 与 FormatDepartment 分别以uid唯一标识、nickname、email、phone、departments以及uid、title、parentUid等字段承载数据并额外支持isDeleted软删除标记。实际开发时建议以源码类型定义为准保证每条记录携带uidsourceName使用this.instance.name。数据源接口实现示例结合第三方 API 的完整实现示例来自官方文档import { SyncSource, UserData } from nocobase/plugin-user-data-sync; class CustomSyncSource extends SyncSource { async pull(): PromiseUserData[] { // ... const ThirdClientApi new ThirdClientApi( this.options.appid, this.options.secret, ); const departments await this.clientapi.getDepartments(); const users await this.clientapi.getUsers(); // ... return [ { dataType: department, uniqueKey: id, records: departments, sourceName: this.instance.name, }, { dataType: user, uniqueKey: id, records: users, sourceName: this.instance.name, }, ]; } }要点说明一次pull()可以同时返回部门与用户两类UserData插件会按dataType分发给不同的目标资源处理sourceName使用this.instance.name即该数据源实例在userDataSyncSources中注册的唯一名称同步记录表userDataSyncRecords会按sourceName 唯一键 dataType三元组做增量比对与更新外部 API 客户端示例中的ThirdClientApi由扩展方自行实现认证凭据从this.options读取。数据源类型注册扩展的数据源需要向数据管理模块注册import UserDataSyncPlugin from nocobase/plugin-user-data-sync; class CustomSourcePlugin extends Plugin { async load() { const syncPlugin this.app.pm.get( UserDataSyncPlugin, ) as UserDataSyncPlugin; if (syncPlugin) { syncPlugin.sourceManager.registerType(custom-source-type, { syncSource: CustomSyncSource, title: Custom Source, }); } } }注官方文档原文示例中写的是reigsterType结合 SyncSourceManager 源码 核对实际方法名为registerType文档示例存在拼写笔误以源码为准。registerType(syncSourceType, { syncSource, title })内部将配置写入一个Registry注册后有两个直接收益title会随 listTypes() 一起返回经userData:listSyncTypesaction 提供给前端成为「新增数据源」下拉菜单中的展示名管理界面按name/id查找数据源并触发同步时SyncSourceManager.getByName/getById 会先按enabled: true过滤出启用状态的记录再用注册表中的构造函数实例化SyncSource子类——若类型未注册会抛出SyncSourceType [...] is not found。注册动作放在插件的load()生命周期中通过this.app.pm.get(UserDataSyncPlugin)获取已启用的同步插件实例由于依赖同步插件存在源码示例中保留了if (syncPlugin)的空值保护这一写法建议沿用。客户端扩展registerType 注册类型与 AdminSettingsForm客户端用户界面通过用户数据同步插件客户端提供的registerType接口注册import SyncPlugin from nocobase/plugin-user-data-sync/client; class CustomSourcePlugin extends Plugin { async load() { const sync this.app.pm.get(SyncPlugin); sync.registerType(custom-source-type, { components: { AdminSettingsForm, // 后台管理表单 }, }); } }从 客户端插件源码 看PluginUserDataSyncClient内部维护了一个sourceTypes注册表RegistrySourceOptionsSourceOptions的类型定义为{ components: Partial{ AdminSettingsForm: ComponentType } }。注册时的类型标识字符串必须与服务端registerType的第一个参数一致示例中均为custom-source-type这样客户端表单才能与服务端拉取逻辑对应到同一个数据源类型。该组件的渲染时机可在 Options.tsx 中确认useAdminSettingsForm(sourceType)按当前表单的sourceType新增或记录的sourceType编辑从注册表取出AdminSettingsForm组件Options组件在其存在时渲染之否则不渲染任何内容——因此未注册客户端组件的类型只能走通用配置无法收集自定义options。后台管理表单管理界面中数据源编辑表单的结构是「上通用 下自定义」上方为通用的数据源配置对应userDataSyncSources集合的基础字段数据源名称name、类型sourceType、显示名displayName、是否启用enabled等由插件内置的userDataSyncSourcesSchema表单 Schema 渲染见 UserDataSyncSource.tsx 中挂载的 SchemaComponent下方为可注册的自定义配置表单部分即扩展方注册的AdminSettingsForm组件用于收集该类型的专属配置如appid、secret提交后写入options字段并在服务端pull()时通过this.options取用。此外客户端插件在load()中还会通过app.pluginSettingsManager.add(users-permissions.sync, ...)把UserDataSyncSource页面挂到「用户与权限 → 同步」设置入口下client/index.tsx#L32-L40并绑定 ACL 片段pm.user-data-sync与服务端 plugin.ts 中注册的userData:*、userDataSyncSources:*、userDataSyncTasks:*权限片段配套。同步执行流程pull 之后的落库与任务管理理解扩展接口时有必要知道pull()返回的数据在插件内部如何流转可结合 UserDataResourceManager 与测试用例 resource-manager.test.ts、api.test.ts 验证落原始记录saveOriginRecords(data)将每条记录按sourceName uid dataType查重存在则把旧数据存入lastMetaData再覆盖metaData不存在则新建形成同步记录表userDataSyncRecords的增量基线分发给目标资源updateOrCreate(data)遍历注册的UserDataResource节点按拓扑排序天然支持「先部门后用户」这类依赖顺序对accepts匹配dataType的资源逐条执行update()或create()——已有本地映射走更新无映射走创建维护映射关系目标资源返回的资源主键会写回/移除userDataSyncRecordsResources映射表供下次同步判断「更新还是创建」任务与重试任务状态机为init → processing → success/failed失败后可在管理界面「Tasks」面板对failed状态任务点击重试客户端对应userData:retryaction任务耗时与错误信息记录在任务表的cost、message字段中。这也解释了为什么扩展SyncSource时只需要关心pull()任务状态、记录比对、资源分发、失败重试均由插件框架统一接管。关键文件索引文件内容src/server/sync-source.tsSyncSource抽象类、任务生命周期方法src/server/sync-source-manager.ts服务端类型注册表registerType/listTypes/实例化逻辑src/server/plugin.ts服务端插件入口userData资源与 ACL 片段注册src/server/user-data-resource-manager.tsUserData/FormatUser/FormatDepartment类型与落库分发逻辑src/server/collections/user-data-sync-sources.ts数据源集合字段定义options、enabled等src/client/index.tsx客户端插件入口与registerTypesrc/client/Options.tsxAdminSettingsForm组件的查找与渲染src/client/UserDataSyncSource.tsx管理界面新增/同步/任务/重试交互docs/docs/cn/users-permissions/sync/dev/source.md官方原始文档小结扩展一个 NocoBase 用户数据同步数据源的最小闭环是实现SyncSource子类并在load()中调用服务端sourceManager.registerType实现AdminSettingsForm并调用客户端插件registerType两端类型标识一致后管理界面即可新增该类型数据源、填写自定义options点击同步后由userData:pull触发pull()框架自动完成任务管理、记录比对与向用户/部门等目标资源的分发。实现时注意以当前源码类型定义核对记录字段尤其uid必填约束并保留对同步插件实例的空值保护。【免费下载链接】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),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询