@buka/nuxt-kit
v0.3.0
Published
Buka Nuxt/Vue Development Kit
Maintainers
Readme
@buka/nuxt-kit
Buka Nuxt/Vue 开发套件,提供 composables、工具函数和 Keq HTTP 中间件。
安装
pnpm add @buka/nuxt-kit本包为 ESM only,依赖 vue(>=3.3.0),keq 为可选 peer dependency。
模块
主入口 @buka/nuxt-kit
re-export 所有子模块。
import {
disposable,
useAsyncFn,
useCursorList,
useCursorPagination,
useOffsetList,
useOffsetPagination,
useOffsetPage,
useErrorMessage,
Pkce,
BukaRequestException,
throwOnResponseError,
} from "@buka/nuxt-kit";Composables @buka/nuxt-kit/composables
| 导出 | 说明 |
| ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| disposable(fn) | 将函数包装为只执行一次,缓存并复用返回值(支持同步/异步) |
| useAsyncFn(fn) | 追踪异步函数的 pending 和 error 状态 |
| useCursorPagination(defaultPageSize?) | 游标分页数据层,维护 startCursor/endCursor/hasNextPage 等 |
| useCursorList(fetchFn, options?) | 游标分页异步列表加载(无限滚动),items 累积、loading/error 状态、load/loadMore |
| useOffsetList(fetchFn, options?) | 偏移分页异步列表加载(表格翻页),items 替换、loading/error 状态、refresh/goToPage |
| useOffsetPagination(defaultPageSize?) | 偏移分页数据层,维护 limit/offset/total |
| useOffsetPage(state) | 将 limit/offset/total 转换为 page/pageSize/totalPages 展示用 |
| useErrorMessage(error, fallback?) | 将错误对象(响应式或静态)转换为可读消息字符串,无错误时返回 undefined |
import {
useAsyncFn,
useCursorList,
useCursorPagination,
useOffsetList,
useOffsetPagination,
useOffsetPage,
useErrorMessage,
} from "@buka/nuxt-kit/composables";
// 错误消息提取
const { error } = useOffsetList(fetchFn);
const errorMessage = useErrorMessage(error, "加载列表失败");
// errorMessage.value → undefined(无错误时)或 "网络错误" 等
// 异步函数追踪
const { pending, error, execute } = useAsyncFn(fetchUsers);
const result = await execute();
// 偏移分页(数据层 + 展示层)
const pagination = useOffsetPagination(20);
const { page, pageSize, totalPages } = useOffsetPage({
limit: pagination.limit,
offset: pagination.offset,
total: pagination.total,
});
// 游标分页(数据层)
const cursorPagination = useCursorPagination();
const { startCursor, endCursor, hasNextPage } = cursorPagination;
// 游标分页(异步列表加载,无限滚动)
const { items, loading, hasMore, load, loadMore } = useCursorList(
async ({ first, after }) => {
const result = await api.listData({ page: { first, after } });
return {
items: result.data ?? [],
endCursor: result.meta?.pagination?.endCursor ?? null,
hasNextPage: result.meta?.pagination?.hasNextPage ?? false,
};
},
);
// 偏移分页(异步列表加载,表格翻页)
const {
items: tableItems,
loading: tableLoading,
error: tableError,
page,
pageSize,
totalPages,
refresh,
goToPage,
} = useOffsetList(
async ({ limit, offset }) => {
const result = await api.listData({ page: { limit, offset } });
return {
items: result.data ?? [],
total: result.meta?.pagination?.total ?? 0,
};
},
{ pageSize: 20 },
);
// 初始加载
await goToPage(1);
// 翻到第三页
await goToPage(3);
// 刷新当前页
await refresh();工具函数 @buka/nuxt-kit/utils
| 导出 | 说明 |
| ----------------- | ------------------------------------------------------------ |
| Pkce.generate() | 生成 PKCE [codeVerifier, codeChallenge] 对(SHA-256 S256) |
import { Pkce } from "@buka/nuxt-kit/utils";
const [codeVerifier, codeChallenge] = await Pkce.generate();Keq 中间件 @buka/nuxt-kit/keq
提供 Keq HTTP 客户端的错误处理中间件和异常类,遵循 Buka 结构化错误码规范。
BukaRequestException
继承自 keq 的 RequestException,将后端返回的标准错误响应提升为类型可判别的异常:
class BukaRequestException extends RequestException {
code: string; // 错误码,如 "B0-0001-1012-00B"
errorCode: ErrorCode; // @buka/error-codes 解析后的结构化对象
details: ExceptionDetail[]; // 错误详情
}throwOnResponseError(options?)
错误处理中间件工厂函数。对 HTTP >= 400 的 JSON 响应自动解析 { error: { code, message, details } } 并抛出 BukaRequestException;非 JSON 响应降级为 createExceptionByStatusCode 的兜底异常。401/403/404 自动标记为 fatal。
支持错误码 → 异常子类分发。适用于需要按特定错误码抛出不同异常实例的业务场景:
import {
throwOnResponseError,
BukaRequestException,
} from "@buka/nuxt-kit/keq";
// 定义业务异常子类(空类体自动继承父类构造器)
class SessionExpiredException extends BukaRequestException {}
class PrincipalNotFoundException extends BukaRequestException {}
// 注册错误码分发
request.use(
throwOnResponseError({
errorDispatchers: {
"B0-0001-1012-00B": SessionExpiredException,
"V0-0001-1005-00M": PrincipalNotFoundException,
},
}),
);
// 业务层通过 instanceof 区分处理
try {
await someApiCall();
} catch (err) {
if (err instanceof SessionExpiredException) {
// 跳转登录页
} else if (err instanceof PrincipalNotFoundException) {
// 回退到注册流程
}
}处理流程:
- 无 response 或 status < 400 → 透传
- 非 JSON 响应 →
createExceptionByStatusCode()兜底 - JSON body 含
error→ 查errorDispatchers:命中则实例化注册的子类,未命中抛BukaRequestException - JSON body 不含
error→createExceptionByStatusCode()兜底
类型
| 类型 | 说明 |
| ----------------------------- | --------------------------------------------------------- |
| BukaRequestExceptionOptions | 构造选项,含 code、details、fatal、response |
| BukaExceptionConstructor | 异常子类构造器接口,约束 errorDispatchers 的 value 类型 |
| ThrowOneResponseErrorOptions | throwOnResponseError 配置项 |
Nuxt 配置
// nuxt.config.ts
export default defineNuxtConfig({
vite: {
optimizeDeps: {
include: ["@buka/nuxt-kit/keq"],
},
},
});许可
MIT
