openapi-clientlisted
Install: claude install-skill CloudyWing/ai-dotfiles
# 前後端 API 契約規範
## API 契約策略(Crucial)
### Code Generation 優先
前端的 API Client 與型別定義應盡可能從後端的 OpenAPI(Swagger)規格檔自動產生,而非手動撰寫。
**推薦工具鏈:**
| 工具 | 用途 |
| --- | --- |
| `openapi-typescript` | 從 OpenAPI spec 產生 TypeScript 型別定義 |
| `openapi-fetch` | 搭配 `openapi-typescript` 的型別安全 Fetch Client |
| NSwag | 從 ASP.NET Core 產生 TypeScript Client(含型別與方法) |
### 手動撰寫的適用情境
- 後端尚未產出 OpenAPI spec。
- API 來源為第三方,無法取得 spec。
- 專案規模小,API 數量少於 10 個。
## Axios 封裝
### 建立共用實例
```typescript
// lib/axios.ts
import axios from 'axios';
import type { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';
const apiClient: AxiosInstance = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL || '/api',
timeout: 30000,
headers: {
'Content-Type': 'application/json'
}
});
// Request Interceptor
apiClient.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error: AxiosError) => Promise.reject(error)
);
// Response Interceptor
apiClient.interceptors.response.use(
(response: AxiosResponse) => response,
(error: AxiosError) => {
if (error.response?.status === 401) {
// Token 過期,導向登入頁
window.location.href = '/login';
}
return Promise.reject(error);
}
);
export default apiClient;
```
### Axios 規範
- **禁止**在元件或 Store 中直接 `import axios from 'axios'`。統一透過封裝的 `apiClient`