📄 Resource

api develop

July 17, 2025
2 views
Reading time: ~17 min
Preview
Live Preview
PagePreview Mode

api develop

By Admin
Published August 26, 2025
0 views

API开发与使用标准

🏗️ API架构原则

完整的API架构

Frontend → 统一API客户端 → API Routes → Services → Repositories → DAOs → Database

目录结构

  • API路由app/api/ - Next.js API路由
  • 服务端服务lib/services/server/ - 服务端业务逻辑
  • 客户端服务lib/services/client/ - 客户端业务逻辑
  • API客户端lib/api/ - 统一API调用层
  • 类型定义lib/api/types/ - API相关类型

📋 API类型定义约束

🚫 严格禁止的做法

1. 禁止在Service文件中定义API类型

绝对禁止lib/services/client/lib/services/server/中定义API响应类型:

// ❌ 错误:不要在service文件中定义API类型
// lib/services/client/order.service.ts
export interface OrderDetailsResponse {  // 🚫 禁止
  id: string;
  status: string;
  // ...
}

2. 禁止页面组件直接导入Service类型

绝对禁止页面组件直接从service文件导入类型:

// ❌ 错误:页面组件不应该直接导入service类型
import { OrderDetailsResponse } from '@/lib/services/client/order.service';

3. 禁止API类型定义分散

绝对禁止在多个地方重复定义相同的API类型:

// ❌ 错误:不要在多个地方定义ApiResponse
// lib/api/types.ts
export interface ApiResponse<T> { ... }

// lib/services/client/order.service.ts  
export interface ApiResponse<T> { ... }  // 🚫 重复定义

✅ 正确的类型定义层次结构

1. 核心层次结构

types/
├── core/                    # 核心业务类型(数据库映射后的业务对象)
│   ├── order.ts            # Order, OrderStatus, OrderItem等
│   ├── user.ts             # User, UserProfile, UserRole等
│   ├── product.ts          # Product, ProductType, ProductSpec等
│   ├── payment.ts          # Payment, PaymentStatus, PaymentMethod等
│   └── common.ts           # 通用类型和工具类型
│
├── api/                    # API专用类型(请求/响应)
│   ├── requests/           # API请求类型
│   │   ├── order.ts        # CreateOrderRequest, UpdateOrderRequest等
│   │   ├── user.ts         # CreateUserRequest, UpdateProfileRequest等
│   │   └── common.ts       # 通用请求类型
│   │
│   ├── responses/          # API响应类型  
│   │   ├── order.ts        # OrderDetailsResponse, OrderListResponse等
│   │   ├── user.ts         # UserProfileResponse, UserOrdersResponse等
│   │   └── common.ts       # ApiResponse, PaginatedResponse等
│   │
│   └── index.ts            # 统一导出
│
├── database/               # 数据库类型(Supabase生成+映射器)
└── index.ts                # 全局类型导出

2. API类型定义规则

A. 请求类型定义

// types/api/requests/order.ts
import { ProductType, Address } from '../../core';

export interface CreateOrderRequest {
  customerInfo: {
    email: string;
    phone: string;
    name?: string;
  };
  items: OrderItemRequest[];
  shippingAddress: Address;
  billingAddress?: Address;
  notes?: string;
}

export interface UpdateOrderRequest {
  phone?: string;
  shippingAddress?: Address;
  notes?: string;
}

export interface OrderListRequest {
  page?: number;
  pageSize?: number;
  status?: string;
  search?: string;
  sortBy?: string;
  sortOrder?: 'asc' | 'desc';
}

B. 响应类型定义

// types/api/responses/order.ts
import { Order, OrderStatus, ProductType } from '../../core';

export interface OrderDetailsResponse {
  id: string;
  orderNumber: string;
  userId: string;
  status: OrderStatus;
  items: OrderItemResponse[];
  shippingAddress: AddressResponse;
  billingAddress?: AddressResponse;
  pricing: PricingResponse;
  deliveryInfo: DeliveryResponse;
  physicalInfo?: PhysicalResponse;
  createdAt: string;
  updatedAt: string;
}

export interface OrderListResponse {
  orders: OrderDetailsResponse[];
  pagination: PaginationResponse;
}

export interface OrderStatsResponse {
  totalOrders: number;
  totalAmount: number;
  statusBreakdown: {
    status: OrderStatus;
    count: number;
  }[];
}

C. 通用响应类型

// types/api/responses/common.ts
export interface ApiResponse<T = unknown> {
  success: boolean;
  data?: T;
  error?: string;
  message?: string;
  code?: string;
  timestamp?: string;
  requestId?: string;
}

export interface PaginatedResponse<T> {
  data: T[];
  pagination: {
    page: number;
    pageSize: number;
    total: number;
    totalPages: number;
    hasNextPage: boolean;
    hasPreviousPage: boolean;
  };
}

export interface OperationResponse {
  success: boolean;
  message?: string;
  affectedRows?: number;
}

3. 统一导出规范

A. API类型统一导出

// types/api/index.ts
// 请求类型
export * from './requests/order';
export * from './requests/user';
export * from './requests/common';

// 响应类型
export * from './responses/order';
export * from './responses/user';
export * from './responses/common';

// 类型别名(便于使用)
export type {
  CreateOrderRequest,
  UpdateOrderRequest,
  OrderDetailsResponse,
  OrderListResponse,
  ApiResponse,
  PaginatedResponse
} from './requests/order';

B. 全局类型导出

// types/index.ts
// 核心业务类型
export * from './core';

// API类型
export * from './api';

// 数据库类型(仅服务端使用)
export type * from './database';

4. 页面组件导入规范

✅ 正确的导入方式

// app/profile/orders/[id]/components/OrderDetails.tsx
import type { 
  OrderDetailsResponse, 
  ApiResponse 
} from '@/types/api';

// 或者使用统一导出
import type { 
  OrderDetailsResponse, 
  ApiResponse 
} from '@/types';

interface OrderDetailsProps {
  order: OrderDetailsResponse;
}

5. 服务层类型使用规范

A. 客户端服务

// lib/services/client/order.service.ts
import { API } from '@/lib/api/client';
import type { 
  CreateOrderRequest,
  UpdateOrderRequest,
  OrderDetailsResponse,
  OrderListResponse,
  ApiResponse
} from '@/types/api';

export async function createOrder(
  request: CreateOrderRequest
): Promise<ApiResponse<OrderDetailsResponse>> {
  return await API.order.create<OrderDetailsResponse>(request);
}

export async function getOrderDetails(
  orderId: string
): Promise<ApiResponse<OrderDetailsResponse>> {
  return await API.order.getDetails<OrderDetailsResponse>(orderId);
}

B. 服务端服务

// lib/services/server/order.service.ts
import type { 
  CreateOrderRequest,
  OrderDetailsResponse,
  OrderListResponse 
} from '@/types/api';
import type { Order } from '@/types/core';

export class OrderService {
  async createOrder(request: CreateOrderRequest): Promise<OrderDetailsResponse> {
    // 业务逻辑
    const order = await this.orderRepository.create(request);
    return this.mapOrderToResponse(order);
  }

  private mapOrderToResponse(order: Order): OrderDetailsResponse {
    // 映射逻辑
    return {
      id: order.id,
      orderNumber: order.orderNumber,
      // ...其他字段映射
    };
  }
}

6. API路由类型使用规范

// app/api/order/create/route.ts
import { NextRequest, NextResponse } from 'next/server';
import type { 
  CreateOrderRequest,
  OrderDetailsResponse,
  ApiResponse 
} from '@/types/api';

export async function POST(request: NextRequest) {
  try {
    const body: CreateOrderRequest = await request.json();
    
    const orderService = new OrderService();
    const orderResponse = await orderService.createOrder(body);
    
    const response: ApiResponse<OrderDetailsResponse> = {
      success: true,
      data: orderResponse,
      timestamp: new Date().toISOString()
    };
    
    return NextResponse.json(response);
  } catch (error) {
    const errorResponse: ApiResponse<never> = {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error'
    };
    
    return NextResponse.json(errorResponse, { status: 500 });
  }
}

🔧 类型定义最佳实践

1. 命名约定

  • 请求类型{Resource}{Action}Request (如 CreateOrderRequest)
  • 响应类型{Resource}{Action}Response (如 OrderDetailsResponse)
  • 列表响应{Resource}ListResponse (如 OrderListResponse)
  • 统计响应{Resource}StatsResponse (如 OrderStatsResponse)

2. 类型继承和组合

// ✅ 正确:使用继承和组合
export interface BaseRequest {
  requestId?: string;
  timestamp?: string;
}

export interface CreateOrderRequest extends BaseRequest {
  customerInfo: CustomerInfo;
  items: OrderItemRequest[];
}

export interface UpdateOrderRequest extends BaseRequest {
  orderId: string;
  updates: Partial<CreateOrderRequest>;
}

3. 泛型约束

// ✅ 正确:使用泛型约束
export interface PaginatedRequest<T = Record<string, unknown>> {
  page?: number;
  pageSize?: number;
  filters?: T;
  sortBy?: keyof T;
  sortOrder?: 'asc' | 'desc';
}

export interface OrderListRequest extends PaginatedRequest<{
  status?: OrderStatus;
  dateRange?: { start: string; end: string };
  minAmount?: number;
  maxAmount?: number;
}> {}

🖥️ 服务端API开发规范

API路由组织

app/api/
├── auth/               # 认证相关
├── quote/             # 报价相关
│   ├── calculate/     # 报价计算
│   ├── submit/        # 提交报价
│   └── [id]/          # 具体报价操作
├── admin/             # 管理员功能
├── payment/           # 支付相关
└── user/              # 用户相关

标准API路由结构

// ✅ 正确:标准API路由结构
import { NextRequest, NextResponse } from 'next/server';
import { createClient } from '@/utils/supabase/server';

export async function POST(request: NextRequest) {
  try {
    // 1. 认证检查
    const supabase = createClient();
    const { data: { user } } = await supabase.auth.getUser();
    
    if (!user) {
      return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
    }

    // 2. 数据验证
    const body = await request.json();
    const validatedData = validateRequestData(body);

    // 3. 业务逻辑(通过Service层)
    const service = new OrderService();
    const result = await service.processOrder(validatedData);

    // 4. 返回统一格式
    return NextResponse.json({
      success: true,
      data: result
    });

  } catch (error) {
    return NextResponse.json({
      success: false,
      error: error instanceof Error ? error.message : 'Internal server error'
    }, { status: 500 });
  }
}

服务层实现

// ✅ 正确:服务层实现
export class QuoteService {
  constructor(private supabase: SupabaseClient) {}

  async calculateQuote(data: QuoteCalculationRequest): Promise<QuoteCalculationResult> {
    // 验证数据
    this.validateQuoteData(data);
    
    // 调用价格计算逻辑
    const pricing = await this.calculatePricing(data);
    
    // 返回结果
    return {
      success: true,
      data: pricing,
      timestamp: new Date().toISOString()
    };
  }

  private validateQuoteData(data: QuoteCalculationRequest): void {
    if (!data.productType) {
      throw new Error('Product type is required');
    }
  }

  private async calculatePricing(data: QuoteCalculationRequest) {
    // 价格计算逻辑
  }
}

数据库操作规范

// ✅ 正确:API Routes 通过 Service 层访问数据库
export async function POST(request: Request) {
  const orderService = new OrderService();
  const result = await orderService.createOrder(data);
  return NextResponse.json(result);
}

📋 完整的数据库操作和分层架构规范请参考:数据层开发标准

📱 客户端API使用规范

🚫 强制禁令

1. 禁止直接使用fetch

绝对不要直接使用原生的 fetch API进行HTTP请求:

// ❌ 禁止这样做
const response = await fetch('/api/order/submit', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(payload),
});

2. 必须使用统一的API客户端

必须使用项目提供的统一API客户端:

方式1:使用结构化API客户端(推荐)
import { API } from '@/lib/api/client';

// 订单相关操作
const result = await API.order.submit(payload);
const orderDetails = await API.order.getDetails(orderId);
const updateResult = await API.order.update(orderId, updates);

// 用户相关操作
const profile = await API.user.getProfile();
const addresses = await API.user.getAddresses();
方式2:使用便捷方法
import { request } from '@/lib/request';

const result = await request.get('/api/user/profile');
const response = await request.post('/api/order/submit', payload);
方式3:使用封装的服务层
import { submitOrder, getOrderDetails } from '@/lib/services/client/order.service';

const result = await submitOrder(payload);
const details = await getOrderDetails(orderId);

客户端服务实现规范

服务文件要求

lib/services/client/ 目录下的服务文件必须:

  • ✅ 使用 API 客户端而不是直接的 requestClient
  • ✅ 包含必要的数据验证
  • ✅ 提供清晰的类型定义
  • ✅ 使用函数式编程而非类
// ✅ 正确的服务实现
export async function submitOrder(payload: CreateOrderPayload) {
  // 数据验证
  if (!payload.cartItems?.length) {
    throw new Error('Cart is empty');
  }
  
  // 使用API客户端
  return await API.order.submit<SubmitOrderResponse>(payload);
}

React中的API调用

// ✅ 正确:在React组件中使用API
export function useQuoteCalculation() {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  
  const calculateQuote = useCallback(async (data: QuoteCalculationRequest) => {
    try {
      setLoading(true);
      setError(null);
      
      const result = await API.quote.calculate<QuoteCalculationResult>(data);
      
      return result;
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Unknown error');
      throw err;
    } finally {
      setLoading(false);
    }
  }, []);

  return { calculateQuote, loading, error };
}

🔒 类型安全要求

强制类型定义

  • ✅ 必须为API调用指定明确的返回类型
  • ✅ 必须定义请求和响应的接口
  • ✅ 避免使用 any 类型
// ✅ 正确的类型使用
interface OrderResponse {
  success: boolean;
  orderId: string;
  message?: string;
}

const result = await API.order.submit<OrderResponse>(payload);

统一响应格式

interface ApiResponse<T> {
  success: boolean;
  data?: T;
  error?: string;
  code?: string;
  timestamp?: string;
}

🚨 错误处理标准

统一错误处理

API客户端会自动处理HTTP错误,但业务层需要处理具体的业务错误:

// ✅ 正确的错误处理
try {
  const result = await API.order.submit(payload);
  return result;
} catch (error) {
  if (error.status === 400) {
    throw new Error('Invalid order data');
  } else if (error.status === 401) {
    throw new Error('Authentication required');
  }
  throw error;
}

服务端错误处理

// ✅ 正确:统一错误响应格式
export class APIError extends Error {
  constructor(
    message: string,
    public status: number = 500,
    public code?: string
  ) {
    super(message);
    this.name = 'APIError';
  }
}

// API路由中的错误处理
export async function POST(request: NextRequest) {
  try {
    // 业务逻辑
  } catch (error) {
    if (error instanceof APIError) {
      return NextResponse.json({
        success: false,
        error: error.message,
        code: error.code
      }, { status: error.status });
    }
    
    return NextResponse.json({
      success: false,
      error: 'Internal server error'
    }, { status: 500 });
  }
}

📁 文件组织规范

客户端服务位置

  • 所有客户端服务必须放在 lib/services/client/ 目录
  • 文件命名格式:{resource}.service.ts
  • 每个服务文件对应一个业务资源

API客户端扩展

如需添加新的API端点,请在 lib/api/client.ts 中添加:

// 添加新的API分组
public newResource: NewResourceAPI = {
  create: <T = any>(payload: any) => 
    request.post<T>('/api/new-resource', payload),
  
  getDetails: <T = any>(id: string) => 
    request.get<T>(`/api/new-resource/${id}`),
};

🔍 HTTP状态码规范

标准状态码使用

  • 200 - 请求成功
  • 201 - 资源创建成功
  • 400 - 客户端错误(验证失败等)
  • 401 - 未认证
  • 403 - 已认证但无权限
  • 404 - 资源不存在
  • 422 - 数据验证失败
  • 500 - 服务器内部错误

🔐 安全规范

认证和授权

// ✅ 正确:认证检查
export async function requireAuth(request: NextRequest) {
  const supabase = createClient();
  const { data: { user } } = await supabase.auth.getUser();
  
  if (!user) {
    throw new APIError('Authentication required', 401);
  }
  
  return user;
}

// ✅ 正确:管理员权限检查
export async function requireAdmin(request: NextRequest) {
  const user = await requireAuth(request);
  
  if (user.role !== 'admin') {
    throw new APIError('Admin access required', 403);
  }
  
  return user;
}

数据验证

// ✅ 正确:输入验证
export function validateQuoteData(data: unknown): QuoteCalculationRequest {
  if (!data || typeof data !== 'object') {
    throw new APIError('Invalid data format', 400);
  }
  
  // 使用Zod或类似库进行验证
  return data as QuoteCalculationRequest;
}

安全最佳实践

  • ✅ 所有API路由都进行认证检查
  • ✅ 敏感操作需要额外权限验证
  • ✅ 对所有用户输入进行验证和清理
  • ✅ 使用HTTPS传输敏感数据
  • ❌ 直接返回数据库错误给客户端
  • ❌ 在客户端存储敏感信息

📋 代码审查清单

API类型定义检查

  • 是否在正确的目录定义类型?(types/api/)
  • 是否使用了统一的命名约定?
  • 是否避免了类型定义的重复?
  • 页面组件是否直接导入了service类型?(❌ 禁止)
  • 是否正确导入了API类型?

API路由检查

  • 是否包含认证检查?
  • 是否通过Service层处理业务逻辑?
  • 是否使用统一的响应格式?
  • 是否包含适当的错误处理?

客户端使用检查

  • 是否使用了原生的 fetch API?
  • 是否正确导入了API客户端?
  • 是否提供了明确的类型定义?
  • 是否包含了必要的数据验证?
  • 错误处理是否恰当?
  • 是否遵循了文件组织规范?

📚 相关文档


遵循这些规范将确保项目的API开发和使用保持一致性、类型安全和易于维护。

  • 追踪错误率
  • 记录用户行为分析数据

💬 Need Help?

Our PCB experts are here to help with your questions.

📞 +86-181-2860-9108
✉️ support@speedxpcb.com
🕒 24/7 Expert Support

🏆 Industry Leader

✓ 50,000+ Happy Customers
✓ ISO 9001:2015 Certified
✓ 99.8% Quality Rate
✓ 24hr Fast Turnaround