npx skills add https://github.com/encoredev/skills --skill encore-service每个 Encore 服务都需要一个 encore.service.ts 文件:
// encore.service.ts
import { Service } from "encore.dev/service";
export default new Service("my-service");
my-service/
├── encore.service.ts # 服务定义(必需)
├── api.ts # API 端点
└── db.ts # 数据库(如果需要)
最适合新项目 - 从简单开始,如果需要再拆分:
my-app/
├── package.json
├── encore.app
├── encore.service.ts
├── api.ts
├── db.ts
└── migrations/
└── 001_initial.up.sql
适用于具有清晰领域边界的分布式系统:
my-app/
├── encore.app
├── package.json
├── user/
│ ├── encore.service.ts
│ ├── api.ts
│ └── db.ts
├── order/
│ ├── encore.service.ts
│ ├── api.ts
│ └── db.ts
└── notification/
├── encore.service.ts
└── api.ts
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
将相关服务分组到系统中:
my-app/
├── encore.app
├── commerce/
│ ├── order/
│ │ └── encore.service.ts
│ ├── cart/
│ │ └── encore.service.ts
│ └── payment/
│ └── encore.service.ts
├── identity/
│ ├── user/
│ │ └── encore.service.ts
│ └── auth/
│ └── encore.service.ts
└── comms/
├── email/
│ └── encore.service.ts
└── push/
└── encore.service.ts
从 ~encore/clients 导入其他服务:
import { user } from "~encore/clients";
export const getOrderWithUser = api(
{ method: "GET", path: "/orders/:id", expose: true },
async ({ id }): Promise<OrderWithUser> => {
const order = await getOrder(id);
const orderUser = await user.get({ id: order.userId });
return { ...order, user: orderUser };
}
);
当出现以下情况时拆分:
| 信号 | 操作 |
|---|---|
| 不同的扩展需求 | 拆分(例如,认证与分析) |
| 不同的部署周期 | 拆分 |
| 清晰的领域边界 | 拆分 |
| 共享数据库表 | 保持在一起 |
| 紧密耦合的逻辑 | 保持在一起 |
| 仅用于代码组织 | 使用文件夹,而非服务 |
import { Service } from "encore.dev/service";
import { middleware } from "encore.dev/api";
const loggingMiddleware = middleware(
{ target: { all: true } },
async (req, next) => {
console.log(`Request: ${req.requestMeta?.path}`);
return next(req);
}
);
export default new Service("my-service", {
middlewares: [loggingMiddleware],
});
控制中间件应用于哪些端点:
// 应用于所有端点
middleware({ target: { all: true } }, handler);
// 仅应用于经过认证的端点
middleware({ target: { auth: true } }, handler);
// 仅应用于公开(公共)端点
middleware({ target: { expose: true } }, handler);
// 仅应用于原始端点
middleware({ target: { isRaw: true } }, handler);
// 仅应用于流式端点
middleware({ target: { isStream: true } }, handler);
// 应用于具有特定标签的端点
middleware({ target: { tags: ["admin", "internal"] } }, handler);
请求对象提供对以下内容的访问:
const myMiddleware = middleware(
{ target: { all: true } },
async (req, next) => {
// 对于类型化和流式 API
const meta = req.requestMeta; // { method, path, pathParams }
// 对于原始端点
const rawReq = req.rawRequest;
const rawRes = req.rawResponse;
// 对于流式端点
const stream = req.stream;
// 传递给处理器的自定义数据
req.data = { startTime: Date.now() };
const resp = await next(req);
// 修改响应头
resp.header.set("X-Response-Time", `${Date.now() - req.data.startTime}ms`);
return resp;
}
);
~encore/clients 进行跨服务调用(切勿直接导入)每周安装量
180
代码仓库
GitHub 星标数
20
首次出现
2026年1月21日
安全审计
安装于
codex141
opencode138
gemini-cli135
claude-code119
github-copilot118
cursor110
Every Encore service needs an encore.service.ts file:
// encore.service.ts
import { Service } from "encore.dev/service";
export default new Service("my-service");
my-service/
├── encore.service.ts # Service definition (required)
├── api.ts # API endpoints
└── db.ts # Database (if needed)
Best for new projects - start simple, split later if needed:
my-app/
├── package.json
├── encore.app
├── encore.service.ts
├── api.ts
├── db.ts
└── migrations/
└── 001_initial.up.sql
For distributed systems with clear domain boundaries:
my-app/
├── encore.app
├── package.json
├── user/
│ ├── encore.service.ts
│ ├── api.ts
│ └── db.ts
├── order/
│ ├── encore.service.ts
│ ├── api.ts
│ └── db.ts
└── notification/
├── encore.service.ts
└── api.ts
Group related services into systems:
my-app/
├── encore.app
├── commerce/
│ ├── order/
│ │ └── encore.service.ts
│ ├── cart/
│ │ └── encore.service.ts
│ └── payment/
│ └── encore.service.ts
├── identity/
│ ├── user/
│ │ └── encore.service.ts
│ └── auth/
│ └── encore.service.ts
└── comms/
├── email/
│ └── encore.service.ts
└── push/
└── encore.service.ts
Import other services from ~encore/clients:
import { user } from "~encore/clients";
export const getOrderWithUser = api(
{ method: "GET", path: "/orders/:id", expose: true },
async ({ id }): Promise<OrderWithUser> => {
const order = await getOrder(id);
const orderUser = await user.get({ id: order.userId });
return { ...order, user: orderUser };
}
);
Split when you have:
| Signal | Action |
|---|---|
| Different scaling needs | Split (e.g., auth vs analytics) |
| Different deployment cycles | Split |
| Clear domain boundaries | Split |
| Shared database tables | Keep together |
| Tightly coupled logic | Keep together |
| Just organizing code | Use folders, not services |
import { Service } from "encore.dev/service";
import { middleware } from "encore.dev/api";
const loggingMiddleware = middleware(
{ target: { all: true } },
async (req, next) => {
console.log(`Request: ${req.requestMeta?.path}`);
return next(req);
}
);
export default new Service("my-service", {
middlewares: [loggingMiddleware],
});
Control which endpoints middleware applies to:
// Apply to all endpoints
middleware({ target: { all: true } }, handler);
// Apply only to authenticated endpoints
middleware({ target: { auth: true } }, handler);
// Apply only to exposed (public) endpoints
middleware({ target: { expose: true } }, handler);
// Apply to raw endpoints only
middleware({ target: { isRaw: true } }, handler);
// Apply to streaming endpoints only
middleware({ target: { isStream: true } }, handler);
// Apply to endpoints with specific tags
middleware({ target: { tags: ["admin", "internal"] } }, handler);
The request object provides access to:
const myMiddleware = middleware(
{ target: { all: true } },
async (req, next) => {
// For typed and streaming APIs
const meta = req.requestMeta; // { method, path, pathParams }
// For raw endpoints
const rawReq = req.rawRequest;
const rawRes = req.rawResponse;
// For streaming endpoints
const stream = req.stream;
// Custom data to pass to handlers
req.data = { startTime: Date.now() };
const resp = await next(req);
// Modify response headers
resp.header.set("X-Response-Time", `${Date.now() - req.data.startTime}ms`);
return resp;
}
);
~encore/clients for cross-service calls (never direct imports)Weekly Installs
180
Repository
GitHub Stars
20
First Seen
Jan 21, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
codex141
opencode138
gemini-cli135
claude-code119
github-copilot118
cursor110
Azure RBAC 权限管理工具:查找最小角色、创建自定义角色与自动化分配
123,100 周安装