feat(data): add repository layer with Auth/Chat/User/Metrics + shared Result<T>
引入仓库层(`src/data/repositories/`),对齐原 Dart `lib/data/repositories/`
的四个仓库:Auth(hybrid: API+AuthStorage+UserStorage)、Chat(hybrid:
API+LocalChatStorage via Dexie)、User(纯远程)、Metrics(纯远程)。
同步抽取 4 个 `*_api.ts` 中重复的 envelope-unwrap 代码到
`src/data/api/response_helper.ts`,失败时抛 `ApiError`(之前抛裸 Error)。
新建 `src/data/result.ts` 提供仓库层统一 `Result<T>`(`{success,data}` 形态),
与 `src/data/storage/result.ts`(`{kind,value}` 形态)并存。
更新 `barrelsby.json` 让 `src/data/repositories/` 加入 barrel 生成。
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 共享的后端 envelope 解析工具
|
||||
*
|
||||
* 4 个 `*_api.ts` 文件中重复的 `interface ApiEnvelope<T>` 与 `function unwrap<T>`
|
||||
* 集中到这里。HTTP 拦截器(`http_client.ts`)已经对非 2xx 响应抛 `ApiError`;
|
||||
* 本工具处理第二种失败:2xx 但 `success: false` 的 envelope。
|
||||
*
|
||||
* 行为升级:失败时抛 `ApiError`(`ApiError extends Error`),而不是裸 `Error`。
|
||||
* 这样调用方在 `Result.err` 内能 `instanceof ApiError` 检查 `.code` / `.status`。
|
||||
*
|
||||
* 原始 Dart: lib/data/services/api/api_client.dart 的 `NetResult<T>` 解析。
|
||||
*/
|
||||
import { ApiError, ErrorCode } from "./api_result";
|
||||
|
||||
/** 后端统一响应包装。 */
|
||||
export interface ApiEnvelope<T> {
|
||||
success: boolean;
|
||||
data?: T;
|
||||
message?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解包 envelope,失败时抛 `ApiError`。
|
||||
* 用于:data 字段必有(API 一定返回业务数据)的端点。
|
||||
*/
|
||||
export function unwrap<T>(envelope: ApiEnvelope<T>): T {
|
||||
if (!envelope.success || envelope.data === undefined) {
|
||||
throw new ApiError(
|
||||
ErrorCode.unknownError,
|
||||
envelope.message ?? envelope.error ?? "API call failed",
|
||||
);
|
||||
}
|
||||
return envelope.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解包 envelope,但允许 `data` 字段为 `undefined`(用于 fire-and-forget 类端点)。
|
||||
* 失败时仍抛 `ApiError`。
|
||||
*/
|
||||
export function unwrapOptional<T>(envelope: ApiEnvelope<T>): T | undefined {
|
||||
if (!envelope.success) {
|
||||
throw new ApiError(
|
||||
ErrorCode.unknownError,
|
||||
envelope.message ?? envelope.error ?? "API call failed",
|
||||
);
|
||||
}
|
||||
return envelope.data;
|
||||
}
|
||||
Reference in New Issue
Block a user