关于 encore-api
encore-api 是使用 Encore.ts 构建类型化 API 端点的技能指南,适合在 TypeScript 中定义 HTTP 路由、请求验证、错误处理和静态资源服务。
主要功能
- 01定义类型化 HTTP 端点
- 02映射路径、查询、标头和 Cookie 输入
- 03使用约束验证请求
- 04通过 APIError 返回 HTTP 错误
- 05提供静态资源和 SPA 回退路由
适用场景
- 01构建类型化 CRUD 端点
- 02验证传入的用户输入
- 03处理身份验证和资源错误
- 04为应用提供静态文件
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ encoredev/ skills --skill encore-api安装后在 Claude Code 中输入/encore-api确认已加载。
详细介绍
Encore API 端点
说明
使用 Encore.ts 创建 API 端点时,请遵循以下模式:
1. 导入 API 模块
import { api } from "encore.dev/api";
2. 定义带类型的请求/响应接口
始终为请求和响应类型定义明确的 TypeScript 接口:
interface CreateUserRequest {
email: string;
name: string;
}
interface CreateUserResponse {
id: string;
email: string;
name: string;
}
3. 创建端点
export const createUser = api(
{ method: "POST", path: "/users", expose: true },
async (req: CreateUserRequest): Promise<CreateUserResponse> => {
// Implementation
}
);
API 选项
| 选项 | 类型 | 说明 |
|---|---|---|
method | string | HTTP 方法:GET、POST、PUT、PATCH、DELETE |
path | string | URL 路径,支持 :param 和 *wildcard |
expose | boolean | 若为 true,则可从外部访问(默认:false) |
auth | boolean | 若为 true,则需要身份验证 |
sensitive | boolean | 若为 true,则会从跟踪记录中隐去请求/响应负载 |
请求/响应模式
Encore 支持四种端点配置:
// Both request and response
export const createUser = api(
{ method: "POST", path: "/users", expose: true },
async (req: CreateRequest): Promise<CreateResponse> => { ... }
);
// Response only (no request body)
export const listUsers = api(
{ method: "GET", path: "/users", expose: true },
async (): Promise<ListResponse> => { ... }
);
// Request only (no response body)
export const deleteUser = api(
{ method: "DELETE", path: "/users/:id", expose: true },
async (req: DeleteRequest): Promise<void> => { ... }
);
// Neither request nor response
export const ping = api(
{ method: "GET", path: "/ping", expose: true },
async (): Promise<void> => { ... }
);
自定义 HTTP 状态码
在响应中加入 HttpStatus 字段,即可返回自定义状态码:
import { api, HttpStatus } from "encore.dev/api";
interface CreateResponse {
id: string;
status: HttpStatus;
}
export const create = api(
{ method: "POST", path: "/items", expose: true },
async (req: CreateRequest): Promise<CreateResponse> => {
const item = await createItem(req);
return { id: item.id, status: HttpStatus.Created }; // Returns 201
}
);
参数类型
路径参数
// Path: "/users/:id"
interface GetUserRequest {
id: string; // Automatically mapped from :id
}
查询参数
import { Query } from "encore.dev/api";
interface ListUsersRequest {
limit?: Query<number>;
offset?: Query<number>;
}
标头
import { Header } from "encore.dev/api";
interface WebhookRequest {
signature: Header<"X-Webhook-Signature">;
payload: string;
}
Cookie
import { Cookie } from "encore.dev/api";
interface SessionRequest {
session?: Cookie<"session">;
settings?: Cookie<"user-settings">;
}
请求验证
Encore 会在运行时使用 TypeScript 类型验证请求。添加约束以进行更严格的验证:
import { api } from "encore.dev/api";
import { Min, Max, MinLen, MaxLen, IsEmail, IsURL } from "encore.dev/validate";
interface CreateUserRequest {
email: string & IsEmail; // Must be valid email
username: string & MinLen<3> & MaxLen<20>; // 3-20 characters
age: number & Min<13> & Max<120>; // Between 13 and 120
website?: string & IsURL; // Optional, must be URL if provided
}
组合验证规则
使用 & 表示 AND 逻辑(必须通过所有规则),使用 | 表示 OR 逻辑(必须至少通过一条规则):
import { IsEmail, IsURL, MinLen, MaxLen } from "encore.dev/validate";
interface ContactRequest {
// Must be valid email OR valid URL
contact: string & (IsEmail | IsURL);
// Must be 5-100 chars AND be a valid URL
website: string & MinLen<5> & MaxLen<100> & IsURL;
}
可用验证器
| 验证器 | 适用于 | 示例 |
|---|---|---|
Min<N> | 数字 | age: number & Min<18> |
Max<N> | 数字 | count: number & Max<100> |
MinLen<N> | 字符串、数组 | name: string & MinLen<1> |
MaxLen<N> | 字符串、数组 | tags: string[] & MaxLen<10> |
IsEmail | 字符串 | email: string & IsEmail |
IsURL | 字符串 | link: string & IsURL |
StartsWith<S> | 字符串 | id: string & StartsWith<"usr_"> |
EndsWith<S> | 字符串 | file: string & EndsWith<".json"> |
MatchesRegexp<R> | 字符串 | code: string & MatchesRegexp<"^[A-Z]{3}$"> |
验证错误响应
无效请求会返回 400,并附带详细信息:
{
"code": "invalid_argument",
"message": "validation failed",
"details": { "field": "email", "error": "must be a valid email" }
}
错误处理
使用 APIError 返回正确的 HTTP 错误响应:
import { APIError, ErrCode } from "encore.dev/api";
// Throw with error code
throw new APIError(ErrCode.NotFound, "user not found");
// Or use shorthand
throw APIError.notFound("user not found");
throw APIError.invalidArgument("email is required");
throw APIError.unauthenticated("invalid token");
常见错误代码
| 代码 | HTTP 状态 | 用途 |
|---|---|---|
NotFound | 404 | 资源不存在 |
InvalidArgument | 400 | 输入无效 |
Unauthenticated | 401 | 缺少身份验证或身份验证无效 |
PermissionDenied | 403 | 不允许执行 |
AlreadyExists | 409 | 资源重复 |
静态资源
使用 api.static 提供静态文件(HTML、CSS、JS、图片):
import { api } from "encore.dev/api";
// Serve files from ./assets under /static/*
export const assets = api.static(
{ expose: true, path: "/static/*path", dir: "./assets" }
);
// Serve at root (use !path for fallback routing)
export const frontend = api.static(
{ expose: true, path: "/!path", dir: "./dist" }
);
// Custom 404 page
export const app = api.static(
{ expose: true, path: "/!path", dir: "./public", notFound: "./404.html" }
);
路径语法
*path- 标准通配符:匹配前缀下的所有路径(例如,/static/*path)!path- 回退路由:在域名根目录提供静态文件,且不会与其他 API 端点冲突。适用于未匹配的路由应提供index.html的 SPA
指南
- 始终使用
import,不要使用require - 定义明确的接口以确保类型安全
- 仅对公共端点使用
expose: true - 抛出
APIError,不要返回错误对象 - 对于入站 Webhook(Stripe、GitHub 等),使用
api.raw— 请参阅encore-webhook技能 - 路径参数会根据路径模式自动提取
- 对用户输入使用验证约束(
Min、MaxLen等)
评论
支持 Markdown