Huly @hcengineering/api-client 版本演进与客户端 API 实战全解析 后端前端企业应用项目管理即时通讯CRM【免费下载链接】platformHuly — All-in-One Project Management Platform (alternative to Linear, Jira, Slack, Notion, Motion)项目地址https://gitcode.com/GitHub_Trending/platform80/platform点击查看免费下载hcengineering/api-client是 Huly 平台All-in-One 项目管理平台面向开发者的官方 TypeScript 客户端库封装了 WebSocket 与 REST 两种连接形态以及查询、文档 CRUD、集合、Mixin、富文本 Markup、文件存储等完整的平台 API。本文以该包在foundations/core/packages/api-client/CHANGELOG.md中记录的版本演进为线索结合同目录 README 与源码实现带你从零掌握 Huly 平台 API 客户端的安装、认证、核心调用与底层原理并理解0.7.18中新增的textColor/textStyle标记能力。一、从 CHANGELOG 看包的演进脉络foundations/core/packages/api-client/CHANGELOG.md是 rush 仓库自动生成的发布日志头部明确标注 should not be manually modified原始数据保存在同目录的 CHANGELOG.json 中。将日志中的版本记录汇总如下版本发布日期变更内容0.7.182025-10-27功能新增textColor与textStyle标记支持同步升级依赖hcengineering/text至0.7.180.7.172025-10-27仅版本更新Version update only跟随hcengineering/core升级至0.7.180.7.52025-10-14批量更新依赖update depsaccount-client、client、client-resources、collaborator-client、core、platform、text、text-markdown等全部升级0.7.42025-10-11升级到最新的 platform rigUpdate to latest platform rig0.7.32025-10-08初始发布Initial release从这份演进日志可以读出几个关键信号包是从 0.7.3 才开始发布的属于 Huly 平台较新的对外 API 层定位是给外部开发者/集成方使用的官方客户端而不是内部 UI 使用的私有连接层。0.7.17 的 Version update only说明该包是平台生态中高度依赖hcengineering/core的成员——核心模型一变客户端就跟着发版。0.7.18 的textColor/textStylemarks是第一个真正意义上的功能补丁它落在本文后面要讲的Markup 富文本 API上意味着客户端从 0.7.18 起可以读写带文字颜色、文字样式标记的富文本内容。当前 package.json 中的版本已是0.7.19说明 0.7.18 之后还经历了一次未记入 CHANGELOG 的发布使用时应以包管理器解析到的版本为准。二、包的定位与依赖结构从 package.json 看包名为hcengineering/api-client主入口为lib/index.js同时导出类型声明types/index.d.ts并支持require/import两种模块加载方式。它的依赖清晰地勾勒出客户端的能力边界hcengineering/account-client账号服务客户端用于登录与工作区选择hcengineering/client/hcengineering/client-resources底层连接与资源注册hcengineering/collaborator-client协作服务客户端负责 Markup 富文本的读写hcengineering/core领域核心模型Class、Doc、Ref、Tx等类型基础hcengineering/platform平台资源定位addLocation、getResourcehcengineering/text/hcengineering/text-markdown富文本格式转换markup / HTML / Markdown 互转snappyjsREST 响应的 Snappy 解压可选依赖wsNode.js 环境下的 WebSocket 实现。包的入口 src/index.ts 将client、markup、socket、types、rest、config、utils、storage全部导出正好对应connect/connectRest/connectStorage三条连接路径。三、两种客户端形态WebSocket 与 RESTREADME 明确指出该包提供两种主要客户端变体WebSocket 客户端对 Huly API 持有持久连接与REST 客户端使用标准 HTTP 请求执行操作。两者面向同一套 API 语义选择取决于你的使用场景实时性要求高、需要长连接复用选 WebSocket一次性脚本、批量任务、无状态集成选 REST。3.1 WebSocket 客户端connectimport { connect } from hcengineering/api-client // 连接 Huly const client await connect(https://huly.app, { email: johndoeexample.com, password: password, workspace: my-workspace }) // 使用 client 执行操作 // ... // 用完关闭连接 await client.close()从源码 src/client.ts 可以还原connect的完整调用链loadServerConfig(url)先请求url/config.json拿到服务端配置ACCOUNTS_URL、COLLABORATOR_URL、FILES_URL、UPLOAD_URL见 src/config.tsgetWorkspaceToken(url, options, config)完成登录并换取工作区级 token 与endpoint通过 account-client 获取账号的 socialIds并调用selectWorkspace(options.workspace)选定工作区若工作区不存在抛出Workspace ${options.workspace} not found组装Account对象后进入createClient为hcengineering/client-resources注册位置浏览器用动态importNode/Jest 环境退回require以避免--experimental-vm-modules问题再通过client.function.GetClient拿到底层连接工厂建立 WebSocket 连接最终返回PlatformClientImpl实例——它内部持有TxOperations事务操作层和MarkupOperations富文本操作层见 src/client.ts。3.2 REST 客户端connectRestimport { connectRest } from hcengineering/api-client const client await connectRest(https://huly.app, { email: johndoeexample.com, password: password, workspace: my-workspace }) // 使用 client 执行操作 // ...connectRest的实现见 src/rest/rest.ts同样先通过getWorkspaceToken换取 token 与 endpoint再构造RestClientImpl。值得注意的实现细节协议转换RestClientImpl构造时会把endpoint.replace(ws, http)即从工作区返回的wss://...端点转为 HTTP 端点使用鉴权头所有请求携带Authorization: Bearer token并声明accept-encoding: snappy, gzipSnappy 解压src/rest/utils.ts 中的extractJson检测content-encoding: snappy时用snappyjs解压后再解析 JSON同时通过rpcJSONReceiver还原TotalArray响应结构把value/total/lookupMap重新组装为带total属性的数组限流与重试客户端内置了限流保护——checkRate在剩余额度低于 1/3 时逐步增加延迟上限 50ms 递增收到 429 时读取Retry-After/Retry-After-ms/X-RateLimit-Reset头决定等待时间withRetry默认最多重试 3 次退避时间按2^attempt * 100ms指数增长且对限流错误不消耗重试次数见 src/rest/utils.ts 与 src/rest/rest.ts。REST 客户端内部还提供两个桥接层src/rest/tx.ts 的createRestTxOperations可将 REST 客户端包装成与 WebSocket 一致的TxOperations会先getAccountgetModel构建内存中的Hierarchy与ModelDbsrc/rest/adapter.ts 的RestClientAdapter则把RestClient适配为通用Client接口便于复用平台事务逻辑。四、认证方式邮箱密码或 Token客户端支持两种认证方式认证成功后拥有与对应用户相同的资源访问权限README 明确说明。两种方式共用ConnectOptions定义于 src/types.ts参数如下urlHuly 实例地址Huly Cloud 使用https://huly.appoptions.workspace工作区名称可在工作区 URL 中获取https://huly.app/workbench/workspace-nameoptions.token可选认证 tokenoptions.email/options.password可选账号邮箱与密码。4.1 邮箱 密码import { connect } from hcengineering/api-client const client await connect(https://huly.app, { email: johndoeexample.com, password: password, workspace: my-workspace })4.2 Tokenimport { connect } from hcengineering/api-client const client await connect(https://huly.app, { token: ..., workspace: my-workspace })README 提示以下示例均以 WebSocket 客户端connect演示如需使用 REST 客户端导入并调用connectRest传入相同参数即可。两种认证在 src/utils.ts 的getWorkspaceToken中统一处理若options含token则直接使用否则调用 account-client 的login(email, password)换取 token随后用 token 调用selectWorkspace(options.workspace)获得{ endpoint, token, workspace }三元组。AuthOptions类型src/types.ts正是PasswordAuthOptions | TokenAuthOptions的联合类型。此外ConnectOptions还支持两个可选连接参数ConnectSocketOptionssrc/types.tssocketFactory自定义 WebSocket 实现工厂Node.js 环境下可注入特定实现connectionTimeout连接超时时间毫秒。五、客户端 API 全景PlatformClientsrc/types.ts是FindOperations DocOperations CollectionOperations MixinOperations MarkupOperations的组合接口并附带getHierarchy/getModel/getAccount/close/[Symbol.asyncDispose]支持await using语法自动释放连接。下面按能力分组逐个讲解。5.1 查询 APIfindOne / findAllfindOne(_class, query, options?)查询满足条件的单个文档findAll(_class, query, options?)查询满足条件的多个文档返回FindResultT。参数说明以findAll为例findOne与之相同_class目标类引用结果会包含该类的全部子类query查询条件options查询选项limit限制返回条数sort排序条件lookup关联查询条件projection投影条件只返回指定字段total指定后返回总数。import { SortingOrder } from hcengineering/core import contact from hcengineering/contact const persons await client.findAll( contact.class.Person, { city: New York }, { limit: 10, sort: { name: SortingOrder.Ascending } } )单条查询const person await client.findOne( contact.class.Person, { _id: person-id } )REST 形态下findAll请求GET /api/v1/find-all/workspace将class、query、options序列化为查询参数返回后还会把服务端lookupMap还原为文档上的$lookup字段并回填查询条件中的简单值字符串/数字/布尔见 src/rest/rest.ts。findOne在 REST 实现中直接复用findAll并强制limit: 1后取首条src/rest/rest.ts。5.2 文档 CRUDcreateDoc / updateDoc / removeDoccreateDoc—— 在指定 space 中创建新文档参数_class对象类、space对象所属空间、attributes对象属性、id可选缺省时自动生成。import contact, { AvatarType } from hcengineering/contact const personId await client.createDoc( contact.class.Person, contact.space.Contacts, { name: Doe,John, city: New York, avatarType: AvatarType.COLOR } )updateDoc—— 更新已有文档参数_class、space、objectId、operations要更新的属性。await client.updateDoc( contact.class.Person, contact.space.Contacts, personId, { city: New York } )removeDoc—— 删除已有文档参数_class、space、objectId。await client.removeDoc( contact.class.Person, contact.space.Contacts, personId )三个方法的底层实现在 src/client.tscreateDoc缺省 id 时用generateId()生成然后委托给内部TxOperations执行事务型写入REST 形态下对应POST /api/v1/tx/workspace。5.3 集合 APIaddCollection / updateCollection / removeCollection集合Collection指挂载在某个父文档上的附属文档AttachedDoc例如为联系人添加多条联系方式。addCollection—— 在指定集合中创建附属文档参数_class、space、attachedTo父对象 id、attachedToClass父对象类、collection集合名、attributes、id可选。const personId await client.createDoc( contact.class.Person, contact.space.Contacts, { name: Doe,John, city: New York, avatarType: AvatarType.COLOR } ) await client.addCollection( contact.class.Channel, contact.space.Contacts, personId, contact.class.Person, channels, { provider: contact.channelProvider.Email, value: john.doeexample.com } )updateCollection—— 更新集合中的附属文档参数_class、space、objectId、attachedTo、attachedToClass、collection、attributes。await client.updateCollection( contact.class.Channel, contact.space.Contacts, channelId, personId, contact.class.Person, channels, { city: New York } )removeCollection—— 从集合中移除附属文档参数_class、space、objectId、attachedTo、attachedToClass、collection。await client.removeCollection( contact.class.Channel, contact.space.Contacts, channelId, personId, contact.class.Person, channels )5.4 Mixin APIcreateMixin / updateMixinMixin 允许在不修改原类模型的前提下为指定文档动态附加扩展属性是 Huly 平台模型体系的重要机制。createMixin—— 为文档创建 Mixin参数objectId、objectClass、objectSpace、mixinMixin 类型引用、attributes。await client.createMixin( personId, contact.class.Person, contact.space.Contacts, contact.mixin.Employee, { active: true, position: CEO } )updateMixin—— 更新已有 Mixin参数同createMixinattributes为要更新的属性。const person await client.findOne(contact.class.Person, { _id: person-id }) await client.updateMixin( personId, contact.class.Person, contact.space.Contacts, contact.mixin.Employee, { active: false } )5.5 Markup 富文本 APIfetchMarkup / uploadMarkupMarkup API 是客户端最特色的能力Huly 的富文本内容文档正文、评论等以协作文档形式存储在 Collaborator 服务中客户端通过MarkupRef即RefBlob引用。操作接口定义在 src/markup/types.tsfetchMarkup(objectClass, objectId, objectAttr, id, format)按指定格式markup/html/markdown拉取文档某属性的富文本内容uploadMarkup(objectClass, objectId, objectAttr, markup, format)以指定格式上传富文本内容并返回MarkupRef。同时提供了MarkupContent封装类与两个便捷工厂函数html(content)、markdown(content)src/markup/types.ts用于在createDoc/updateDoc/addCollection/createMixin等调用中直接传入富文本属性——这正是 CHANGELOG 0.7.18 中textColor/textStylemarks 功能所服务的路径。import { html } from hcengineering/api-client const docId await client.createDoc( document.class.Document, document.space.Documents, { title: My Doc, content: html(h1Title/h1pHello span stylecolor:redworld/span/p) } )底层实现在 src/markup/client.tsfetchMarkup先用makeCollabId(objectClass, objectId, objectAttr)构造协作文档 id通过CollaboratorClient.getMarkup取回平台内部 markupJSON 文档格式再按目标格式转换——markup原样返回、html用jsonToHTML、markdown用markupToMarkdown附带refUrl、imageUrl以便把内部引用/图片地址还原为可访问链接uploadMarkup反向转换——html经htmlToJSON → jsonToMarkupmarkdown经markdownToMarkup → jsonToMarkup最终通过CollaboratorClient.createMarkup落库并返回引用。textColor/textStyle这两个标记正是在 HTML/Markdown 与内部 JSON markup 互转时被识别并保真的因此从 0.7.18 开始通过该客户端读写富文本时文字颜色与文字样式如加粗、斜体、字号等不会再丢失。5.6 存储 APIconnectStorage除了文档数据客户端还提供文件存储能力StorageClient接口见 src/storage/types.tsstat(objectName)获取对象元信息Blobget(objectName)读取对象返回Readable流put(objectName, stream, contentType, size?)上传对象partial(objectName, offset, length?)按 Range 头进行分片读取remove(objectName)删除对象。connectStorage(url, options)src/storage/client.ts从服务端配置中解析FILES_URL/UPLOAD_URL支持以/开头的相对地址拼接到url上并将路径中的:workspace替换为工作区 id。错误处理上区分了NetworkError、StorageError、NotFoundError三类src/storage/error.ts404 时stat返回undefined而非抛错。六、跨环境的 WebSocket 适配包在 src/socket 下提供了两个开箱即用的 socket 工厂BrowserWebSocketFactory浏览器环境直接使用原生WebSocketNodeWebSocketFactoryNode.js 环境内部require(ws)未安装时抛出明确错误提示并把ws的事件message/close/open/error桥接为浏览器兼容的ClientSocket接口同时处理Blob消息转ArrayBuffer、Buffer转Uint8Array等差异。这意味着同一套客户端代码可以无缝运行在浏览器与 Node.js 中只需在 Node 侧通过connect的socketFactory传入NodeWebSocketFactory该包将ws声明为可选依赖正是为此。七、测试覆盖与质量保障包自带完整的 Jest 测试配置见 jest.config.js测试文件位于 src/testsmarkup-types.test.ts覆盖MarkupContent三种格式markup / html / markdown的构造与html()、markdown()工厂函数含空内容、特殊字符、Unicode、超长内容、多行等边界用例markup-client.test.ts通过 mockcollaborator-client与text/text-markdown验证fetchMarkup/uploadMarkup各格式的转换调用、未知格式报错、空内容以及 collaborator 错误传播rest-utils.test.ts验证withRetry的重试次数默认 3 次、指数退避时间约 100ms / 200ms、忽略限流错误不消耗重试次数以及extractJson对TotalArray还原、snappy 路径、嵌套对象、非法 JSON 的处理。这些测试从侧面印证了文中描述的行为重试策略、格式转换、限流处理均有可验证的单元级保障。八、版本迁移与使用建议综合 CHANGELOG 与当前仓库状态给出如下使用建议依赖版本对齐该包强依赖hcengineering/core、hcengineering/text等平台包升级时应保持版本组一致避免模型与客户端版本错位CHANGELOG 中 0.7.17 的 Version update only 即是这种联动关系的体现富文本能力边界如需读写textColor/textStyle标记请使用 0.7.18 及以上版本更早版本0.7.3 ~ 0.7.17不具备该标记支持按场景选择客户端长连接、实时交互场景用connect批量脚本、CI 集成等一次性任务用connectRest注意其内置限流退避任务量大时预留足够时间文件读写用connectStorage认证优先使用 TokengetWorkspaceToken的实现表明 Token 模式可跳过密码登录步骤更适合服务端集成且令牌权限与对应用户一致需妥善保管。如需查看完整 API 文档与更多示例可继续阅读包内 README.md并参考 src/types.ts 中的类型定义或阅读 src/client.ts、src/rest/rest.ts、src/markup/client.ts 等源码深入实现细节。赞分享后端前端企业应用项目管理即时通讯CRM【免费下载链接】platformHuly — All-in-One Project Management Platform (alternative to Linear, Jira, Slack, Notion, Motion)项目地址https://gitcode.com/GitHub_Trending/platform80/platform点击查看免费下载相关推荐Huly 平台账号服务客户端 hcengineering/account-client 源码解析RPC API 能力全景与版本演进Huly 平台账号服务客户端 hcengineering/account client 源码解析RPC API 能力全景与版本演进 hcengineeri后端前端企业应用项目管理即时通讯CRMHuly 服务端客户端库 hcengineering/server-client 深入解析从版本演进到源码实现Huly 服务端客户端库 hcengineering/server client 深入解析从版本演进到源码实现 hcengineering/server后端前端企业应用项目管理即时通讯CRMHuly 客户端连接层剖析hcengineering/client-resources 的架构、演进与源码实现Huly 客户端连接层剖析hcengineering/client resources 的架构、演进与源码实现 导读 hcengineering/clie后端前端企业应用项目管理即时通讯CRM上一篇终极指南如何用nvim-tree.lua快速创建文件与目录提升开发效率下一篇Python Cheat SheetCSV处理Python CSV文件操作指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考