Halo 前端 API 客户端 @halo-dev/api-client 完全指南:从插件接入到外部项目集成

Halo 前端 API 客户端 @halo-dev/api-client 完全指南:从插件接入到外部项目集成 Halo 前端 API 客户端 halo-dev/api-client 完全指南从插件接入到外部项目集成【免费下载链接】haloHalo 是一款强大易用的开源建站工具从个人博客、知识库到企业官网、在线商城Halo 都能助您轻松实现一站式满足您的多样化建站需求。项目地址: https://gitcode.com/GitHub_Trending/ha/halo本指南以 Halo 开源仓库中的 api-client 官方文档 为主体结合 api-client 包源码、生成配置 与 Console 侧的拦截器实现系统讲解halo-dev/api-client的四个预置客户端、四个工厂函数、默认 Axios 实例的底层行为以及它在 Halo 插件开发与外部第三方项目中的完整接入方案。读完本文你将掌握如何用一行pnpm install加几个 import 语句在插件或独立应用中直接调用 Halo 的 CRUD、Console、UC 与公开 API。一、什么是 halo-dev/api-clienthalo-dev/api-client是 Halo 2.x 的官方 JavaScript API 客户端请求库位于仓库 ui/packages/api-client 目录。它本身不是手写的封装而是基于 OpenAPI 规范、使用 OpenAPI Generator 以typescript-axios模板自动生成的一层类型安全的 HTTP 客户端。从 package.json 可以看到它的完整元信息包名halo-dev/api-client当前仓库版本为2.26.0许可证GPL-3.0模块格式type: moduleESM入口为./dist/index.js类型声明为./dist/index.d.ts运行时依赖仅qs用于查询参数序列化axios被声明为peerDependencies要求^1.16.0意味着 axios 由使用方Console、UC 或插件宿主统一提供避免多实例冲突sideEffects: false可安全地被摇树优化tree-shaking。1.1 生成链路从 OpenAPI 到 TypeScript客户端代码不是手工维护的其生成命令定义在 package.json 的gen脚本中rimraf --glob ./src/** openapi-generator-cli generate \ -i ../../../api-docs/openapi/v3_0/aggregated.json \ -g typescript-axios \ -c ./.openapi_config.yaml \ -o ./src \ --type-mappingssetArray \ --global-property apiDocsfalse,modelDocsfalse其中-i ../../../api-docs/openapi/v3_0/aggregated.json输入文件是仓库 api-docs/openapi/v3_0/aggregated.json即 Halo 后端所有分组apis_console、apis_extension、apis_public、apis_uc聚合后的 OpenAPI 描述文件-g typescript-axios生成基于 Axios 的 TypeScript 客户端--type-mappingssetArray将 OpenAPI 中的set类型映射为Array--global-property apiDocsfalse,modelDocsfalse跳过 API 与模型文档的生成只产出代码。生成器版本由 openapitools.json 锁定为7.17.0。生成结果落在src/目录src/api下是按资源划分的 API 类如 post-v1alpha1-api.ts、user-v1alpha1-api.tssrc/models下是请求/响应模型src/index.ts统一导出api、configuration与modelsexport * from ./api; export * from ./configuration; export * from ./models;1.2 构建产物构建由 vite.config.ts 驱动vp pack关键配置入口为./entry/index.tsneverBundle: [axios]axios 不打入产物交给宿主提供alwaysBundle: [qs]qs序列化逻辑直接打进产物同时产出esm与压缩后的iife两种格式IIFE 全局名为HaloApiClient方便 CDN 场景直接以script引入。二、九大导出预置客户端与工厂函数包的主入口entry/index.ts最终导出以下内容import { coreApiClient, consoleApiClient, ucApiClient, publicApiClient, createCoreApiClient, createConsoleApiClient, createUcApiClient, createPublicApiClient, axiosInstance, } from halo-dev/api-client;导出说明coreApiClient为 Halo 所有自定义模型extension自动生成的 CRUD 接口封装的 api clientconsoleApiClient为 Halo 针对 Console管理端提供的接口封装的 api clientucApiClient为 Halo 针对 UC用户中心提供的接口封装的 api clientpublicApiClient为 Halo 所有公开访问的接口封装的 api clientcreateCoreApiClient创建自定义模型 CRUD 接口的 api client需要传入 axios 实例createConsoleApiClient创建 Console 接口的 api client需要传入 axios 实例createUcApiClient创建 UC 接口的 api client需要传入 axios 实例createPublicApiClient创建公开访问接口的 api client需要传入 axios 实例axiosInstance包内部默认创建的 axios 实例其中coreApiClient、consoleApiClient、ucApiClient、publicApiClient四个预置实例本质上是createXxxApiClient(defaultAxiosInstance)的结果见 entry/api-client.ts它们共享同一个默认 Axios 实例开箱即用。2.1 默认 Axios 实例的底层配置默认实例在 entry/api-client.ts 中创建理解它对排查请求问题至关重要const defaultAxiosInstance axios.create({ baseURL: , withCredentials: true, paramsSerializer: (params) { return QueryString.stringify(params, { arrayFormat: repeat }); }, }); defaultAxiosInstance.defaults.headers.common[X-Requested-With] XMLHttpRequest;baseURL: 默认实例不写死后端地址。在 Console / UC 中请求走同源路径由部署环境决定实际地址withCredentials: true跨域请求携带 Cookie这是登录态Session能够生效的关键paramsSerializer使用qs且arrayFormat: repeat数组参数会序列化为?a1a2a3而不是?a[]1a[]2a[]3与 Halo 后端对列表参数如分类、标签 ID 集合的解析方式对齐统一附带X-Requested-With: XMLHttpRequest请求头用于区分 Ajax 请求。注意entry/index.ts中还通过export * from ./patch/thumbnail兼容性地导出了ThumbnailSpecSizeEnum。该枚举已被标记deprecated参见 entry/patch/thumbnail.ts请改用生成产物中的GetThumbnailByUriSizeEnum。三、四类客户端的职责边界与组织结构四类客户端对应 Halo 后端四组 OpenAPI 定义可对照 api-docs/openapi/v3_0 下的apis_console、apis_extension、apis_public、apis_uc四个文件覆盖四种完全不同的访问场景。3.1 coreApiClient自定义模型的 CRUDcreateCoreApiClient的实现见 entry/api-client.ts它按领域分组组织contentcategory、comment、post、reply、singlePage、snapshot、tagauthauthProvider、userConnectionstorageattachment、group、policy、policyTemplatepluginextensionDefinition、extensionPointDefinition、plugin、reverseProxymetricscounterthemethemenotificationnotification、notificationTemplate、notifierDescriptor、reason、reasonType、subscriptionmigrationbackupsecuritypersonalAccessToken顶层另有annotationSetting、menu、menuItem、setting、configMap、secret、user、role、roleBinding。从源码结构看content、auth、storage、plugin、metrics、theme、notification、migration、security这些命名对应 Halo 的 API 分组前缀content.halo.run、auth.halo.run、storage.halo.run、plugin.halo.run等每个字段对应的类均以V1alpha1Api结尾例如文章对应PostV1alpha1Api。这类接口通常面向插件开发者与内部模块用于对自定义模型做增删改查。3.2 consoleApiClient管理端专用接口createConsoleApiClient见 entry/api-client.ts它封装了 Console 管理后台独有的能力例如system、migration、uiPluginstorage.attachment、storage.policy注意 Console 侧策略类是PolicyAlpha1ConsoleApicontent下的category、comment、reply、indices、post、singlePage、tagnotification.notifier、plugin.plugin、theme.theme、configMap.system等。这些接口通常依赖管理员权限返回带权限过滤的数据形态如列表分页、发布状态管理、系统配置读写。3.3 ucApiClient用户中心专用接口createUcApiClient见 entry/api-client.ts服务登录用户本人的内容管理例如content.post如listMyPosts、content.snapshotsecurity.twoFactor、security.personalAccessToken、security.devicenotification.notificationuser.preference、user.currentUserstorage.attachment。3.4 publicApiClient免认证公开接口createPublicApiClient见 entry/api-client.ts无需登录即可访问典型用于门户站点、主题渲染与 SEO 场景menu、statsSystemV1alpha1PublicApicontent.category、content.tag、content.singlePage、content.postmetrics.metrics、notification、index顶层comment原先content.comment已被标记deprecated统一改用顶层comment。四、在 Halo 插件中使用推荐方式插件是halo-dev/api-client最主要的使用场景。安装依赖pnpm install halo-dev/api-client axios由于 Halo 的 Console 与 UC 项目已经引入该包并设置好了 Axios 拦截器详见下文拦截器链路插件内直接使用预置客户端即可无需自行创建实例import { coreApiClient } from halo-dev/api-client; coreApiClient.content.post.listPost().then((response) { // handle response });listPost()对应PostV1alpha1Api的列表方法response.data即分页列表数据含items与hasNext等字段。4.1 产物体积依赖自动外置README 特别强调在halo-dev/ui-plugin-bundler-kit2.17.0及以上版本中打包器已把halo-dev/api-client与axios列入排除名单插件最终产物中的这两项依赖会自动复用 Halo 宿主本身提供的版本插件作者无需关心产物大小也不存在多份 axios 实例导致的拦截器失效问题。这与 vite.config.ts 中neverBundle: [axios]的设计一脉相承。五、在外部项目中使用自定义实例如果你在 Halo 之外的独立应用如自建的管理后台、数据看板、移动端配套服务中调用 Halo API需要手动创建 axios 实例并指定后端地址pnpm install halo-dev/api-client axiosimport axios from axios; const axiosInstance axios.create({ baseURL: http://localhost:8090, }); const coreApiClient createCoreApiClient(axiosInstance); coreApiClient.content.post.listPost().then((response) { // handle response });几个关键点createCoreApiClient以及其他三个工厂函数会从传入的axiosInstance.defaults.baseURL中读取地址见 entry/api-client.ts因此务必在创建实例时配置baseURL外部项目通常需要自己处理认证可通过axiosInstance.interceptors.request.use(...)附加 Token如 Personal Access Token或配合withCredentials: true走 Halo 的 Session 认证推荐结合拦截器统一处理 401、网络错误与后端ProblemDetail错误体Halo 后端错误响应遵循 RFC 7807 格式包含title、detail、status等字段。5.1 分页工具 paginate包内还提供了一个实用的分页聚合工具导出自 entry/utils/paginate.ts由 entry/index.ts 一并导出export async function paginateTParams extends { page?: number }, TItem( listFn: (params: TParams) PromiseAxiosResponseListResponseTItem, params?: OmitTParams, page ): PromiseTItem[] { const result: TItem[] []; let page 1; let hasNext true; while (hasNext) { const { data } await listFn({ ...params, page } as TParams); result.push(...data.items); page 1; hasNext data.hasNext; } return result; }它基于 Halo 列表接口统一的响应结构itemshasNext逐页拉取全部数据适合导出、统计等需要全量数据的场景import { paginate } from halo-dev/api-client; import { coreApiClient } from halo-dev/api-client; const allPosts await paginate((params) coreApiClient.content.post.listPost(params) );六、拦截器链路Console/UC 已内置的错误处理README 提到已经在 Console 和 UC 项目中引入并设置好了 Axios 拦截器其真实实现位于 ui/src/setup/setupApiClient.ts。该文件通过setupApiClient()在应用启动时注册响应拦截器处理策略包括请求取消error.code ERR_CANCELED直接透传不弹任何提示网络错误匹配Network Error或没有error.response时弹出国际化后的网络错误 Toast静默请求若请求配置了mute标记errorResponse.config.mute直接 reject 而不提示用于后台静默刷新等场景401 未授权弹出登录已过期对话框确认后跳转/login?redirect_uri...并在登录后回跳原路径HTML 响应当响应头content-type为text/html典型来自反向代理或 WAF 的拦截页时用 iframe 弹窗展示原始内容避免误解析ProblemDetail 错误体从errorResponse.data读取title/detail并以 Toast 展示兜底以上都不命中时展示status: statusText或通用未知错误提示。因此插件在 Console/UC 环境内调用coreApiClient等预置客户端时认证失效、网络异常、后端错误都会得到统一且友好的 UI 反馈这是直接使用即可的底层保障。在外部项目中建议参照该实现自行注册拦截器以获得一致的错误体验。七、常见问题与最佳实践何时用预置客户端何时用工厂函数在 Console/UC 插件内一律使用coreApiClient、consoleApiClient等预置实例在外部独立项目中用createXxxApiClient(你的axios实例)绑定自己的baseURL与认证逻辑。为什么数组参数要用arrayFormat: repeat因为 Halo 后端对多值查询参数如?category1category2按重复键解析默认实例已内置该序列化行为自定义实例时建议保持同样的paramsSerializer配置避免传参被序列化成category[]1导致后端取不到值。升级后ThumbnailSpecSizeEnum失效它是为兼容旧版本保留的废弃导出见 entry/patch/thumbnail.ts请改用GetThumbnailByUriSizeEnum。保持 axios 单例由于包将 axios 声明为 peerDependency 且打包时排除项目中不要重复安装不同版本的 axios否则拦截器可能注册在另一份实例上而失效。跟进 API 变更客户端代码由 OpenAPI 聚合文件生成后端接口变更后需重新执行pnpm gen生成命令见 package.json并同步升级包版本。八、深入阅读指引官方使用文档ui/packages/api-client/README.md客户端工厂函数与默认实例实现ui/packages/api-client/entry/api-client.ts包入口导出含兼容性导出ui/packages/api-client/entry/index.ts分页聚合工具ui/packages/api-client/entry/utils/paginate.ts生成配置与构建配置package.json、openapitools.json、vite.config.tsOpenAPI 聚合描述文件api-docs/openapi/v3_0/aggregated.json以及同目录下apis_console、apis_extension、apis_public、apis_uc分组文件Console 侧拦截器实现错误处理参考ui/src/setup/setupApiClient.ts插件 UI 资源与打包依赖外置的配套机制openspec/specs/ui-plugin-bundler-provider/spec.md从插件内的一行import到外部项目的自定义实例halo-dev/api-client通过生成代码 预置实例 工厂函数的组合把 Halo 全部后端能力以类型安全、开箱即用的方式暴露给前端生态。掌握它的导出体系与默认实例行为是高效开发 Halo 插件与周边应用的第一步。【免费下载链接】haloHalo 是一款强大易用的开源建站工具从个人博客、知识库到企业官网、在线商城Halo 都能助您轻松实现一站式满足您的多样化建站需求。项目地址: https://gitcode.com/GitHub_Trending/ha/halo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考