refactor(data): establish API contract guardrails
CI / Quality and Bundle Budgets (push) Has been cancelled
CI / Quality and Bundle Budgets (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import apiContract from "../api_contract.json";
|
||||
import { ApiPath } from "../api_path";
|
||||
|
||||
describe("ApiPath contract source", () => {
|
||||
it("uses the shared contract path for every static operation", () => {
|
||||
const staticOperations = Object.entries(apiContract).filter(
|
||||
([operationId]) => operationId !== "privateRoomAlbumUnlock",
|
||||
);
|
||||
|
||||
for (const [operationId, operation] of staticOperations) {
|
||||
expect(ApiPath[operationId as keyof typeof ApiPath]).toBe(
|
||||
operation.path,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("fills and encodes the private album path parameter", () => {
|
||||
expect(ApiPath.privateRoomAlbumUnlock("album/id 1")).toBe(
|
||||
"/api/private-room/albums/album%2Fid%201/unlock",
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"emailLogin": { "method": "post", "path": "/api/auth/login" },
|
||||
"register": { "method": "post", "path": "/api/auth/register" },
|
||||
"guestLogin": { "method": "post", "path": "/api/auth/guest" },
|
||||
"googleLogin": { "method": "post", "path": "/api/auth/login/google" },
|
||||
"facebookLogin": { "method": "post", "path": "/api/auth/login/facebook" },
|
||||
"facebookIdLogin": { "method": "post", "path": "/api/auth/login/facebook/by-id" },
|
||||
"facebookPsidLogin": { "method": "post", "path": "/api/auth/login/facebook/psid" },
|
||||
"refresh": { "method": "post", "path": "/api/auth/refresh" },
|
||||
"logout": { "method": "post", "path": "/api/auth/logout" },
|
||||
"getCurrentUser": { "method": "get", "path": "/api/auth/me" },
|
||||
"userProfile": { "method": "get", "path": "/api/user/profile" },
|
||||
"userEntitlements": { "method": "get", "path": "/api/user/entitlements" },
|
||||
"userFacebookIdentity": { "method": "post", "path": "/api/user/facebook/identity" },
|
||||
"paymentCreateOrder": { "method": "post", "path": "/api/payment/create-order" },
|
||||
"paymentOrderStatus": { "method": "get", "path": "/api/payment/order-status" },
|
||||
"paymentPlans": { "method": "get", "path": "/api/payment/plans" },
|
||||
"paymentTipPlans": { "method": "get", "path": "/api/payment/tip-plans" },
|
||||
"chatSend": { "method": "post", "path": "/api/chat/send" },
|
||||
"chatHistory": { "method": "get", "path": "/api/chat/history" },
|
||||
"chatUnlockPrivate": { "method": "post", "path": "/api/chat/unlock-private" },
|
||||
"chatUnlockHistory": { "method": "post", "path": "/api/chat/unlock-history" },
|
||||
"privateRoomAlbums": { "method": "get", "path": "/api/private-room/albums" },
|
||||
"privateRoomAlbumUnlock": { "method": "post", "path": "/api/private-room/albums/{albumId}/unlock" },
|
||||
"metricsPwaEvent": { "method": "post", "path": "/api/metrics/pwa/event" },
|
||||
"reportUserInfo": { "method": "post", "path": "/api/data/report-user-info" },
|
||||
"feedback": { "method": "post", "path": "/api/feedback" }
|
||||
}
|
||||
@@ -3,107 +3,99 @@
|
||||
* 统一管理所有接口路径
|
||||
*
|
||||
*/
|
||||
import apiContract from "./api_contract.json";
|
||||
|
||||
export class ApiPath {
|
||||
private constructor() {}
|
||||
|
||||
// API 基础路径
|
||||
private static readonly _baseUrl = "/api";
|
||||
|
||||
// ============ 功能模块分组 ============
|
||||
private static readonly _auth = `${ApiPath._baseUrl}/auth`;
|
||||
private static readonly _user = `${ApiPath._baseUrl}/user`;
|
||||
private static readonly _payment = `${ApiPath._baseUrl}/payment`;
|
||||
private static readonly _chat = `${ApiPath._baseUrl}/chat`;
|
||||
private static readonly _privateRoom = `${ApiPath._baseUrl}/private-room`;
|
||||
|
||||
// ============ 认证相关 ============
|
||||
/** 邮箱密码登录 */
|
||||
static readonly emailLogin = `${ApiPath._auth}/login`;
|
||||
static readonly emailLogin = apiContract.emailLogin.path;
|
||||
|
||||
/** 注册 */
|
||||
static readonly register = `${ApiPath._auth}/register`;
|
||||
static readonly register = apiContract.register.path;
|
||||
|
||||
/** 设备自动登录 */
|
||||
static readonly guestLogin = `${ApiPath._auth}/guest`;
|
||||
static readonly guestLogin = apiContract.guestLogin.path;
|
||||
|
||||
/** Google 登录 */
|
||||
static readonly googleLogin = `${ApiPath._auth}/login/google`;
|
||||
static readonly googleLogin = apiContract.googleLogin.path;
|
||||
|
||||
/** Facebook 登录 */
|
||||
static readonly facebookLogin = `${ApiPath._auth}/login/facebook`;
|
||||
static readonly facebookLogin = apiContract.facebookLogin.path;
|
||||
|
||||
/** Facebook ID 登录(v7.0 新增) */
|
||||
static readonly facebookIdLogin = `${ApiPath._auth}/login/facebook/by-id`;
|
||||
static readonly facebookIdLogin = apiContract.facebookIdLogin.path;
|
||||
|
||||
/** Facebook PSID 登录 */
|
||||
static readonly facebookPsidLogin = `${ApiPath._auth}/login/facebook/psid`;
|
||||
static readonly facebookPsidLogin = apiContract.facebookPsidLogin.path;
|
||||
|
||||
/** 刷新 Token */
|
||||
static readonly refresh = `${ApiPath._auth}/refresh`;
|
||||
static readonly refresh = apiContract.refresh.path;
|
||||
|
||||
/** 退出登录 */
|
||||
static readonly logout = `${ApiPath._auth}/logout`;
|
||||
static readonly logout = apiContract.logout.path;
|
||||
|
||||
/** 获取当前用户信息 */
|
||||
static readonly getCurrentUser = `${ApiPath._auth}/me`;
|
||||
static readonly getCurrentUser = apiContract.getCurrentUser.path;
|
||||
|
||||
// ============ 用户相关 ============
|
||||
/** 获取个人信息(与 /auth/me 等价) */
|
||||
static readonly userProfile = `${ApiPath._user}/profile`;
|
||||
static readonly userProfile = apiContract.userProfile.path;
|
||||
|
||||
/** 获取当前用户权益快照 */
|
||||
static readonly userEntitlements = `${ApiPath._user}/entitlements`;
|
||||
static readonly userEntitlements = apiContract.userEntitlements.path;
|
||||
|
||||
/** 绑定 Facebook ASID / PSID */
|
||||
static readonly userFacebookIdentity = `${ApiPath._user}/facebook/identity`;
|
||||
static readonly userFacebookIdentity =
|
||||
apiContract.userFacebookIdentity.path;
|
||||
|
||||
// ============ 支付相关 ============
|
||||
/** 创建充值订单 */
|
||||
static readonly paymentCreateOrder = `${ApiPath._payment}/create-order`;
|
||||
static readonly paymentCreateOrder = apiContract.paymentCreateOrder.path;
|
||||
|
||||
/** 查询订单状态 */
|
||||
static readonly paymentOrderStatus = `${ApiPath._payment}/order-status`;
|
||||
static readonly paymentOrderStatus = apiContract.paymentOrderStatus.path;
|
||||
|
||||
/** 获取商品套餐列表 */
|
||||
static readonly paymentPlans = `${ApiPath._payment}/plans`;
|
||||
static readonly paymentPlans = apiContract.paymentPlans.path;
|
||||
|
||||
/** 获取咖啡打赏套餐列表 */
|
||||
static readonly paymentTipPlans = `${ApiPath._payment}/tip-plans`;
|
||||
static readonly paymentTipPlans = apiContract.paymentTipPlans.path;
|
||||
|
||||
// ============ 聊天相关 ============
|
||||
/** 发送消息 */
|
||||
static readonly chatSend = `${ApiPath._chat}/send`;
|
||||
static readonly chatSend = apiContract.chatSend.path;
|
||||
|
||||
/** 获取聊天历史 */
|
||||
static readonly chatHistory = `${ApiPath._chat}/history`;
|
||||
static readonly chatHistory = apiContract.chatHistory.path;
|
||||
|
||||
/** 解锁私密消息 */
|
||||
static readonly chatUnlockPrivate = `${ApiPath._chat}/unlock-private`;
|
||||
static readonly chatUnlockPrivate = apiContract.chatUnlockPrivate.path;
|
||||
|
||||
/** 一键解锁历史锁定消息 */
|
||||
static readonly chatUnlockHistory = `${ApiPath._chat}/unlock-history`;
|
||||
static readonly chatUnlockHistory = apiContract.chatUnlockHistory.path;
|
||||
|
||||
// ============ 私密空间相关 ============
|
||||
/** 获取私密图片包列表 */
|
||||
static readonly privateRoomAlbums = `${ApiPath._privateRoom}/albums`;
|
||||
static readonly privateRoomAlbums = apiContract.privateRoomAlbums.path;
|
||||
|
||||
/** 解锁私密图片包 */
|
||||
static privateRoomAlbumUnlock(albumId: string): string {
|
||||
return `${ApiPath.privateRoomAlbums}/${encodeURIComponent(albumId)}/unlock`;
|
||||
return apiContract.privateRoomAlbumUnlock.path.replace(
|
||||
"{albumId}",
|
||||
encodeURIComponent(albumId),
|
||||
);
|
||||
}
|
||||
|
||||
// ============ 数据看板相关 ============
|
||||
private static readonly _metrics = `${ApiPath._baseUrl}/metrics`;
|
||||
|
||||
/** 上报 PWA 事件 */
|
||||
static readonly metricsPwaEvent = `${ApiPath._metrics}/pwa/event`;
|
||||
static readonly metricsPwaEvent = apiContract.metricsPwaEvent.path;
|
||||
|
||||
// ============ 数据上报相关(v7.0 新增) ============
|
||||
private static readonly _data = `${ApiPath._baseUrl}/data`;
|
||||
|
||||
/** 上报用户信息 */
|
||||
static readonly reportUserInfo = `${ApiPath._data}/report-user-info`;
|
||||
static readonly reportUserInfo = apiContract.reportUserInfo.path;
|
||||
|
||||
// ============ 用户反馈相关 ============
|
||||
static readonly feedback = `${ApiPath._baseUrl}/feedback`;
|
||||
static readonly feedback = apiContract.feedback.path;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user