encore-infrastructure
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseEncore Infrastructure Declaration
Encore基础设施声明
Instructions
说明
Encore.ts uses declarative infrastructure - you define resources in code and Encore handles provisioning:
- Locally () - Encore runs infrastructure in Docker (Postgres, Redis, etc.)
encore run - Production - Deploy via Encore Cloud to your AWS/GCP, or self-host using generated infrastructure config
Encore.ts采用声明式基础设施方式——你在代码中定义资源,Encore负责处理资源部署:
- 本地环境()——Encore在Docker中运行基础设施(Postgres、Redis等)
encore run - 生产环境——通过Encore Cloud部署到你的AWS/GCP,或使用生成的基础设施配置进行自托管
Critical Rule
重要规则
All infrastructure must be declared at package level (top of file), not inside functions.
所有基础设施必须在包级别(文件顶部)声明,不能在函数内部。
Databases (PostgreSQL)
数据库(PostgreSQL)
typescript
import { SQLDatabase } from "encore.dev/storage/sqldb";
// CORRECT: Package level
const db = new SQLDatabase("mydb", {
migrations: "./migrations",
});
// WRONG: Inside function
async function setup() {
const db = new SQLDatabase("mydb", { migrations: "./migrations" });
}typescript
import { SQLDatabase } from "encore.dev/storage/sqldb";
// 正确:包级别声明
const db = new SQLDatabase("mydb", {
migrations: "./migrations",
});
// 错误:在函数内部声明
async function setup() {
const db = new SQLDatabase("mydb", { migrations: "./migrations" });
}Migrations
迁移
Create migrations in the directory:
migrations/service/
├── encore.service.ts
├── api.ts
├── db.ts
└── migrations/
├── 001_create_users.up.sql
└── 002_add_email_index.up.sqlMigration naming:
{number}_{description}.up.sql在目录中创建迁移文件:
migrations/service/
├── encore.service.ts
├── api.ts
├── db.ts
└── migrations/
├── 001_create_users.up.sql
└── 002_add_email_index.up.sql迁移文件命名规则:
{编号}_{描述}.up.sqlPub/Sub
Pub/Sub
Topics
主题
typescript
import { Topic } from "encore.dev/pubsub";
interface OrderCreatedEvent {
orderId: string;
userId: string;
total: number;
}
// Package level declaration
export const orderCreated = new Topic<OrderCreatedEvent>("order-created", {
deliveryGuarantee: "at-least-once",
});typescript
import { Topic } from "encore.dev/pubsub";
interface OrderCreatedEvent {
orderId: string;
userId: string;
total: number;
}
// 包级别声明
export const orderCreated = new Topic<OrderCreatedEvent>("order-created", {
deliveryGuarantee: "at-least-once",
});Publishing
发布消息
typescript
await orderCreated.publish({
orderId: "123",
userId: "user-456",
total: 99.99,
});typescript
await orderCreated.publish({
orderId: "123",
userId: "user-456",
total: 99.99,
});Subscriptions
订阅
typescript
import { Subscription } from "encore.dev/pubsub";
const _ = new Subscription(orderCreated, "send-confirmation-email", {
handler: async (event) => {
await sendEmail(event.userId, event.orderId);
},
});typescript
import { Subscription } from "encore.dev/pubsub";
const _ = new Subscription(orderCreated, "send-confirmation-email", {
handler: async (event) => {
await sendEmail(event.userId, event.orderId);
},
});Cron Jobs
定时任务(Cron Jobs)
typescript
import { CronJob } from "encore.dev/cron";
import { api } from "encore.dev/api";
// The endpoint to call
export const cleanupExpiredSessions = api(
{ expose: false },
async (): Promise<void> => {
// Cleanup logic
}
);
// Package level cron declaration
const _ = new CronJob("cleanup-sessions", {
title: "Clean up expired sessions",
schedule: "0 * * * *", // Every hour
endpoint: cleanupExpiredSessions,
});typescript
import { CronJob } from "encore.dev/cron";
import { api } from "encore.dev/api";
// 要调用的端点
export const cleanupExpiredSessions = api(
{ expose: false },
async (): Promise<void> => {
// 清理逻辑
}
);
// 包级别定时任务声明
const _ = new CronJob("cleanup-sessions", {
title: "清理过期会话",
schedule: "0 * * * *", // 每小时一次
endpoint: cleanupExpiredSessions,
});Schedule Formats
调度格式
| Format | Example | Description |
|---|---|---|
| | Simple interval (must divide 24h evenly) |
| | Cron expression (9am every Monday) |
| 格式 | 示例 | 描述 |
|---|---|---|
| | 简单时间间隔(必须能整除24小时) |
| | Cron表达式(每周一上午9点) |
Object Storage
对象存储
typescript
import { Bucket } from "encore.dev/storage/objects";
// Package level
export const uploads = new Bucket("user-uploads", {
versioned: false,
});
// Public bucket
export const publicAssets = new Bucket("public-assets", {
public: true,
versioned: false,
});typescript
import { Bucket } from "encore.dev/storage/objects";
// 包级别声明
export const uploads = new Bucket("user-uploads", {
versioned: false,
});
// 公共存储桶
export const publicAssets = new Bucket("public-assets", {
public: true,
versioned: false,
});Operations
操作示例
typescript
// Upload
await uploads.upload("path/to/file.jpg", buffer, {
contentType: "image/jpeg",
});
// Download
const data = await uploads.download("path/to/file.jpg");
// Check existence
const exists = await uploads.exists("path/to/file.jpg");
// Delete
await uploads.remove("path/to/file.jpg");
// Public URL (only for public buckets)
const url = publicAssets.publicUrl("image.jpg");typescript
// 上传
await uploads.upload("path/to/file.jpg", buffer, {
contentType: "image/jpeg",
});
// 下载
const data = await uploads.download("path/to/file.jpg");
// 检查是否存在
const exists = await uploads.exists("path/to/file.jpg");
// 删除
await uploads.remove("path/to/file.jpg");
// 公共URL(仅适用于公共存储桶)
const url = publicAssets.publicUrl("image.jpg");Secrets
密钥(Secrets)
typescript
import { secret } from "encore.dev/config";
// Package level
const stripeKey = secret("StripeSecretKey");
// Usage (call as function)
const key = stripeKey();Set secrets via CLI:
bash
encore secret set --type prod StripeSecretKeytypescript
import { secret } from "encore.dev/config";
// 包级别声明
const stripeKey = secret("StripeSecretKey");
// 使用方式(作为函数调用)
const key = stripeKey();通过CLI设置密钥:
bash
encore secret set --type prod StripeSecretKeyGuidelines
指南
- Infrastructure declarations MUST be at package level
- Use descriptive names for resources
- Keep migrations sequential and numbered
- Subscription handlers must be idempotent (at-least-once delivery)
- Secrets are accessed by calling the secret as a function
- Cron endpoints should be (internal only)
expose: false
- 基础设施声明必须在包级别
- 为资源使用描述性名称
- 保持迁移文件按顺序编号
- 订阅处理程序必须是幂等的(至少一次投递)
- 通过调用密钥函数来访问密钥
- 定时任务端点应设置为(仅内部访问)
expose: false