关于 api-integration-builder
这项 Skill 会收集 API 需求,并生成包含类型、认证、重试、速率限制和错误处理的 TypeScript API 客户端,面向集成第三方或自定义 API 的开发者,减少重复样板代码。
主要功能
- 01生成带类型的 TypeScript API 客户端
- 02支持 API key、OAuth、Bearer 和 Basic 认证
- 03添加重试逻辑和速率限制
- 04创建错误类和模拟响应
- 05提供 Webhook 与分页辅助工具
- 06附带 README、测试和软件包配置
适用场景
- 01为第三方 REST API 创建客户端
- 02配置认证和请求重试
- 03为集成添加分页或 Webhook 验证
- 04为客户端测试准备模拟响应
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ jackspace/ claudeskillz --skill api-integration-builder安装后在 Claude Code 中输入/api-integration-builder确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
examples.mdreference.mdSKILL.json详细介绍
API 集成构建器
用途
生成完整的、可用于生产环境的 API 客户端,处理所有样板代码:TypeScript 类型、身份验证、重试逻辑、速率限制和错误处理。
面向 ADHD 用户:即时完成集成,无需阅读 API 文档并手动实现所有内容。 面向所有用户:节省数小时的样板代码编写时间,从第一天起就具备类型安全性,可用于生产环境。
触发条件
- 用户说:“集成 API”“API 客户端”“连接到服务”“创建 SDK”
- 请求集成 Stripe、SendGrid、Twilio 或任何第三方 API
- “设置 OAuth”或“实现 API 身份验证”
核心工作流
1. 收集需求
询问用户:
{
api_name: "Stripe",
api_base_url: "https://api.stripe.com/v1",
auth_type: "api_key|oauth|bearer|basic",
endpoints: [
{ method: "GET", path: "/customers", description: "List customers" },
{ method: "POST", path: "/customers", description: "Create customer" }
],
rate_limit: { requests: 100, per: "minute" } // optional
}
如果用户提供了 API 文档 URL,请获取文档并自动提取这些信息。
2. 生成 TypeScript 客户端
文件结构:
api-client/
├── client.ts # Main client class
├── types.ts # TypeScript types
├── auth.ts # Authentication handler
├── errors.ts # Custom error classes
├── retry.ts # Retry logic
├── rate-limiter.ts # Rate limiting
└── mocks.ts # Mock responses for testing
3. 客户端模板
// client.ts
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
import { AuthHandler } from './auth';
import { RateLimiter } from './rate-limiter';
import { RetryHandler } from './retry';
import { APIError, RateLimitError, AuthenticationError } from './errors';
import type { ClientConfig, APIResponse } from './types';
export class {APIName}Client {
private axios: AxiosInstance;
private auth: AuthHandler;
private rateLimiter: RateLimiter;
private retryHandler: RetryHandler;
constructor(config: ClientConfig) {
this.auth = new AuthHandler(config.apiKey);
this.rateLimiter = new RateLimiter(config.rateLimit);
this.retryHandler = new RetryHandler(config.retryConfig);
this.axios = axios.create({
baseURL: config.baseURL,
timeout: config.timeout || 30000,
headers: {
'Content-Type': 'application/json',
'User-Agent': '{APIName}-Client/1.0.0',
...config.defaultHeaders,
},
});
// Request interceptor for auth
this.axios.interceptors.request.use(
async (config) => {
await this.rateLimiter.wait();
return this.auth.addAuthHeaders(config);
},
(error) => Promise.reject(error)
);
// Response interceptor for retry logic
this.axios.interceptors.response.use(
(response) => response,
async (error) => {
if (this.retryHandler.shouldRetry(error)) {
return this.retryHandler.retry(error);
}
return Promise.reject(this.handleError(error));
}
);
}
private handleError(error: any): Error {
if (error.response?.status === 401) {
return new AuthenticationError('Invalid API credentials');
}
if (error.response?.status === 429) {
return new RateLimitError('Rate limit exceeded');
}
if (error.response?.data?.message) {
return new APIError(error.response.data.message, error.response.status);
}
return new APIError('Unknown API error', error.response?.status);
}
// Generated methods for each endpoint
async listCustomers(params?: ListCustomersParams): Promise<APIResponse<Customer[]>> {
const response = await this.axios.get('/customers', { params });
return response.data;
}
async createCustomer(data: CreateCustomerData): Promise<APIResponse<Customer>> {
const response = await this.axios.post('/customers', data);
return response.data;
}
// ... more generated methods
}
4. 身份验证处理程序
// auth.ts
import { AxiosRequestConfig } from 'axios';
export type AuthConfig =
| { type: 'api_key'; key: string; header?: string }
| { type: 'bearer'; token: string }
| { type: 'oauth'; clientId: string; clientSecret: string; tokenUrl: string }
| { type: 'basic'; username: string; password: string };
export class AuthHandler {
private config: AuthConfig;
private accessToken?: string;
private tokenExpiry?: Date;
constructor(config: AuthConfig) {
this.config = config;
}
async addAuthHeaders(axiosConfig: AxiosRequestConfig): Promise<AxiosRequestConfig> {
const headers = axiosConfig.headers || {};
switch (this.config.type) {
case 'api_key':
headers[this.config.header || 'Authorization'] = `Bearer ${this.config.key}`;
break;
case 'bearer':
headers['Authorization'] = `Bearer ${this.config.token}`;
break;
case 'oauth':
const token = await this.getOAuthToken();
headers['Authorization'] = `Bearer ${token}`;
break;
case 'basic':
const credentials = Buffer.from(
`${this.config.username}:${this.config.password}`
).toString('base64');
headers['Authorization'] = `Basic ${credentials}`;
break;
}
return { ...axiosConfig, headers };
}
private async getOAuthToken(): Promise<string> {
// Check if token is still valid
if (this.accessToken && this.tokenExpiry && this.tokenExpiry > new Date()) {
return this.accessToken;
}
// Fetch new token
const response = await axios.post(this.config.tokenUrl, {
grant_type: 'client_credentials',
client_id: this.config.clientId,
client_secret: this.config.clientSecret,
});
this.accessToken = response.data.access_token;
this.tokenExpiry = new Date(Date.now() + response.data.expires_in * 1000);
return this.accessToken;
}
}
5. 重试逻辑
// retry.ts
import { AxiosError, AxiosRequestConfig } from 'axios';
export interface RetryConfig {
maxRetries: number;
initialDelay: number; // ms
maxDelay: number; // ms
backoffFactor: number;
retryableStatuses: number[];
}
export class RetryHandler {
private config: RetryConfig;
private retryCount: Map<string, number> = new Map();
constructor(config?: Partial<RetryConfig>) {
this.config = {
maxRetries: config?.maxRetries || 3,
initialDelay: config?.initialDelay || 1000,
maxDelay: config?.maxDelay || 30000,
backoffFactor: config?.backoffFactor || 2,
retryableStatuses: config?.retryableStatuses || [408, 429, 500, 502, 503, 504],
};
}
shouldRetry(error: AxiosError): boolean {
if (!error.response) return true; // Network error, retry
if (!this.config.retryableStatuses.includes(error.response.status)) return false;
const key = this.getRequestKey(error.config);
const count = this.retryCount.get(key) || 0;
return count < this.config.maxRetries;
}
async retry(error: AxiosError): Promise<any> {
const key = this.getRequestKey(error.config);
const count = this.retryCount.get(key) || 0;
this.retryCount.set(key, count + 1);
const delay = Math.min(
this.config.initialDelay * Math.pow(this.config.backoffFactor, count),
this.config.maxDelay
);
await this.sleep(delay);
return axios.request(error.config);
}
private getRequestKey(config: AxiosRequestConfig): string {
return `${config.method}:${config.url}`;
}
private sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
}
6. 速率限制器
// rate-limiter.ts
export interface RateLimitConfig {
requests: number;
per: 'second' | 'minute' | 'hour';
}
export class RateLimiter {
private config: RateLimitConfig;
private timestamps: number[] = [];
constructor(config: RateLimitConfig) {
this.config = config;
}
async wait(): Promise<void> {
const now = Date.now();
const windowMs = this.getWindowMs();
// Remove timestamps outside the window
this.timestamps = this.timestamps.filter((ts) => now - ts < windowMs);
if (this.timestamps.length >= this.config.requests) {
const oldestTimestamp = this.timestamps[0];
const waitTime = oldestTimestamp + windowMs - now;
if (waitTime > 0) {
await this.sleep(waitTime);
return this.wait(); // Recursive call after waiting
}
}
this.timestamps.push(now);
}
private getWindowMs(): number {
switch (this.config.per) {
case 'second':
return 1000;
case 'minute':
return 60000;
case 'hour':
return 3600000;
}
}
private sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
}
7. TypeScript 类型
// types.ts
export interface ClientConfig {
baseURL: string;
apiKey?: string;
oauthConfig?: OAuthConfig;
timeout?: number;
rateLimit?: RateLimitConfig;
retryConfig?: Partial<RetryConfig>;
defaultHeaders?: Record<string, string>;
}
export interface OAuthConfig {
clientId: string;
clientSecret: string;
tokenUrl: string;
}
export interface APIResponse<T> {
data: T;
status: number;
headers: Record<string, string>;
}
export interface PaginatedResponse<T> {
data: T[];
page: number;
totalPages: number;
totalItems: number;
hasMore: boolean;
}
// Auto-generated types for each API entity
export interface Customer {
id: string;
email: string;
name: string;
created: number;
metadata?: Record<string, any>;
}
export interface CreateCustomerData {
email: string;
name?: string;
metadata?: Record<string, any>;
}
export interface ListCustomersParams {
limit?: number;
starting_after?: string;
ending_before?: string;
}
8. 自定义错误
// errors.ts
export class APIError extends Error {
constructor(
message: string,
public statusCode?: number,
public response?: any
) {
super(message);
this.name = 'APIError';
}
}
export class AuthenticationError extends APIError {
constructor(message: string) {
super(message, 401);
this.name = 'AuthenticationError';
}
}
export class RateLimitError extends APIError {
constructor(message: string, public retryAfter?: number) {
super(message, 429);
this.name = 'RateLimitError';
}
}
export class ValidationError extends APIError {
constructor(message: string, public fields?: Record<string, string[]>) {
super(message, 400);
this.name = 'ValidationError';
}
}
9. 模拟响应(用于测试)
// mocks.ts
export const mockCustomers: Customer[] = [
{
id: 'cus_test123',
email: '[email protected]',
name: 'Test User',
created: Date.now(),
},
];
export const mockResponses = {
'GET /customers': {
data: mockCustomers,
status: 200,
},
'POST /customers': {
data: mockCustomers[0],
status: 201,
},
};
export class Mock{APIName}Client {
async listCustomers(): Promise<APIResponse<Customer[]>> {
return mockResponses['GET /customers'];
}
async createCustomer(data: CreateCustomerData): Promise<APIResponse<Customer>> {
return mockResponses['POST /customers'];
}
}
附加功能
Webhook 处理
// webhooks.ts
import crypto from 'crypto';
export class WebhookHandler {
constructor(private secret: string) {}
verify(payload: string, signature: string): boolean {
const hmac = crypto.createHmac('sha256', this.secret);
const digest = hmac.update(payload).digest('hex');
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest));
}
parse<T>(payload: string, signature: string): T {
if (!this.verify(payload, signature)) {
throw new Error('Invalid webhook signature');
}
return JSON.parse(payload);
}
}
分页助手
// pagination.ts
export class PaginationHelper<T> {
constructor(
private client: any,
private endpoint: string,
private pageSize: number = 100
) {}
async *iterate(params?: any): AsyncGenerator<T> {
let hasMore = true;
let startingAfter: string | undefined;
while (hasMore) {
const response = await this.client[this.endpoint]({
...params,
limit: this.pageSize,
starting_after: startingAfter,
});
for (const item of response.data) {
yield item;
}
hasMore = response.has_more;
if (hasMore && response.data.length > 0) {
startingAfter = response.data[response.data.length - 1].id;
}
}
}
async all(params?: any): Promise<T[]> {
const items: T[] = [];
for await (const item of this.iterate(params)) {
items.push(item);
}
return items;
}
}
使用示例
请参阅 examples.md,了解完整的集成示例,包括:
- Stripe API 客户端
- SendGrid 邮件集成
- GitHub API 客户端
- 自定义 REST API
- GraphQL API 客户端
交付格式
生成的文件:
- 完整的 TypeScript API 客户端
- 包含使用示例的 README
- 包含模拟示例的测试文件
- 包含依赖项的 Package.json
包含的依赖项:
{
"dependencies": {
"axios": "^1.5.0"
},
"devDependencies": {
"typescript": "^5.2.0",
"@types/node": "^20.8.0",
"jest": "^29.7.0",
"@types/jest": "^29.5.0"
}
}
通知用户:
✅ **{API Name} Client** generated!
**Features:**
- ✅ TypeScript types
- ✅ {Auth type} authentication
- ✅ Automatic retries (up to 3x)
- ✅ Rate limiting ({X} requests per {Y})
- ✅ Error handling
- ✅ Mock responses for testing
**Generated files:**
- client.ts (main client)
- types.ts (TypeScript definitions)
- auth.ts (authentication)
- mocks.ts (test mocks)
**Usage:**
```typescript
import { {APIName}Client } from './client';
const client = new {APIName}Client({
baseURL: '{API_URL}',
apiKey: process.env.API_KEY,
rateLimit: { requests: 100, per: 'minute' }
});
const customers = await client.listCustomers();
后续步骤:
- 安装依赖项:
npm install - 在 .env 中设置 API 密钥
- 导入并使用客户端
## Integration with Other Skills
### Context Manager
Save API integration details:
记住:已集成 Stripe API 类型:流程 标签:api、stripe、payments、typescript 内容:已实现带重试逻辑、速率限制(100/min)的 Stripe 客户端, 已实现 webhook 验证
### Error Debugger
If API integration has issues:
自动调用 error-debugger 处理:
- 身份验证失败
- 速率限制错误
- 网络超时
### Rapid Prototyper
For testing integration:
rapid-prototyper 生成测试服务端 → 用于开发的模拟 API 响应
## Quality Checklist
Before delivering, verify:
- ✅ TypeScript types for all endpoints
- ✅ Authentication implemented correctly
- ✅ Retry logic with exponential backoff
- ✅ Rate limiting configured
- ✅ Custom error classes
- ✅ Mock responses for testing
- ✅ README with usage examples
- ✅ No hardcoded secrets
## Success Criteria
✅ Generated client compiles without errors
✅ All endpoints have TypeScript types
✅ Authentication works
✅ Retries happen automatically
✅ Rate limiting prevents 429 errors
✅ Errors are properly caught and typed
✅ Mock client available for testing
✅ Production-ready code
## Additional Resources
- **[Integration Examples](examples.md)** - Complete API client examples
- **[Reference Patterns](reference.md)** - Common API patterns and best practices
## Quick Reference
### Trigger Phrases
- "integrate API"
- "API client"
- "connect to service"
- "create SDK"
- "Stripe integration"
- "OAuth setup"
### Supported Auth Types
- API Key (Bearer, Custom Header)
- OAuth 2.0 (Client Credentials, Authorization Code)
- Basic Auth
- Custom (user provides implementation)
### Output Location
- Linux/macOS: `~/.claude-artifacts/api-client-{name}-{timestamp}/`
- Windows: `%USERPROFILE%\.claude-artifacts\api-client-{name}-{timestamp}\`
评论
支持 Markdown