Loading...
Loading...
Compare original and translation side by side
bknd-database-provisionbknd-env-configbknd-database-provisionbknd-env-config| Platform | Best For | Database Options | Cold Start |
|---|---|---|---|
| Cloudflare Workers | Edge, global low-latency | D1, Turso | ~0ms |
| Cloudflare Pages | Static + API | D1, Turso | ~0ms |
| Vercel | Next.js apps | Turso, Neon | ~200ms |
| Node.js/Bun VPS | Full control, dedicated | Any | N/A |
| Docker | Containerized, portable | Any | N/A |
| AWS Lambda | Serverless, pay-per-use | Turso, RDS | ~500ms |
| 平台 | 适用场景 | 数据库选项 | 冷启动 |
|---|---|---|---|
| Cloudflare Workers | 边缘计算、全球低延迟 | D1, Turso | ~0ms |
| Cloudflare Pages | 静态站点+API | D1, Turso | ~0ms |
| Vercel | Next.js应用 | Turso, Neon | ~200ms |
| Node.js/Bun VPS | 完全控制、专属服务器 | 任意 | N/A |
| Docker | 容器化、可移植 | 任意 | N/A |
| AWS Lambda | 无服务器、按使用付费 | Turso, RDS | ~500ms |
npm install -D wranglerwrangler.tomlname = "my-bknd-app"
main = "src/index.ts"
compatibility_date = "2024-01-01"
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "your-d1-database-id"npm install -D wranglerwrangler.tomlname = "my-bknd-app"
main = "src/index.ts"
compatibility_date = "2024-01-01"
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "your-d1-database-id"
**Step 3: Configure Adapter**
```typescript
// src/index.ts
import { hybrid, type CloudflareBkndConfig } from "bknd/adapter/cloudflare";
import { d1Sqlite } from "bknd/adapter/cloudflare";
import { em, entity, text } from "bknd";
const schema = em({
posts: entity("posts", {
title: text().required(),
}),
});
export default hybrid<CloudflareBkndConfig>({
app: (env) => ({
connection: d1Sqlite({ binding: env.DB }),
schema,
isProduction: true,
auth: {
jwt: {
secret: env.JWT_SECRET,
},
},
config: {
media: {
enabled: true,
adapter: {
type: "r2",
config: { bucket: env.R2_BUCKET },
},
},
},
}),
});undefined
**步骤3:配置适配器**
```typescript
// src/index.ts
import { hybrid, type CloudflareBkndConfig } from "bknd/adapter/cloudflare";
import { d1Sqlite } from "bknd/adapter/cloudflare";
import { em, entity, text } from "bknd";
const schema = em({
posts: entity("posts", {
title: text().required(),
}),
});
export default hybrid<CloudflareBkndConfig>({
app: (env) => ({
connection: d1Sqlite({ binding: env.DB }),
schema,
isProduction: true,
auth: {
jwt: {
secret: env.JWT_SECRET,
},
},
config: {
media: {
enabled: true,
adapter: {
type: "r2",
config: { bucket: env.R2_BUCKET },
},
},
},
}),
});undefined
**Step 5: Set Secrets**
```bash
wrangler secret put JWT_SECRET
**步骤5:设置密钥**
```bash
wrangler secret put JWT_SECRET
**Step 6: Deploy**
```bash
wrangler deploy
**步骤6:部署**
```bash
wrangler deployfunctions/api/[[bknd]].tsimport { hybrid, type CloudflareBkndConfig } from "bknd/adapter/cloudflare";
import { d1Sqlite } from "bknd/adapter/cloudflare";
import schema from "../../bknd.config";
export const onRequest = hybrid<CloudflareBkndConfig>({
app: (env) => ({
connection: d1Sqlite({ binding: env.DB }),
schema,
isProduction: true,
auth: {
jwt: { secret: env.JWT_SECRET },
},
}),
});functions/api/[[bknd]].tsimport { hybrid, type CloudflareBkndConfig } from "bknd/adapter/cloudflare";
import { d1Sqlite } from "bknd/adapter/cloudflare";
import schema from "../../bknd.config";
export const onRequest = hybrid<CloudflareBkndConfig>({
app: (env) => ({
connection: d1Sqlite({ binding: env.DB }),
schema,
isProduction: true,
auth: {
jwt: { secret: env.JWT_SECRET },
},
}),
});// index.ts
import { serve, type BunBkndConfig } from "bknd/adapter/bun";
// or for Node.js:
// import { serve } from "bknd/adapter/node";
const config: BunBkndConfig = {
connection: {
url: process.env.DB_URL!,
authToken: process.env.DB_TOKEN,
},
isProduction: true,
auth: {
jwt: {
secret: process.env.JWT_SECRET!,
expires: "7d",
},
},
config: {
media: {
enabled: true,
adapter: {
type: "s3",
config: {
bucket: process.env.S3_BUCKET!,
region: process.env.S3_REGION!,
accessKeyId: process.env.S3_ACCESS_KEY!,
secretAccessKey: process.env.S3_SECRET_KEY!,
},
},
},
guard: {
enabled: true,
},
},
};
serve(config);export DB_URL="libsql://your-db.turso.io"
export DB_TOKEN="your-turso-token"
export JWT_SECRET="your-32-char-minimum-secret"
export PORT=3000undefined// index.ts
import { serve, type BunBkndConfig } from "bknd/adapter/bun";
// 若使用Node.js则改为:
// import { serve } from "bknd/adapter/node";
const config: BunBkndConfig = {
connection: {
url: process.env.DB_URL!,
authToken: process.env.DB_TOKEN,
},
isProduction: true,
auth: {
jwt: {
secret: process.env.JWT_SECRET!,
expires: "7d",
},
},
config: {
media: {
enabled: true,
adapter: {
type: "s3",
config: {
bucket: process.env.S3_BUCKET!,
region: process.env.S3_REGION!,
accessKeyId: process.env.S3_ACCESS_KEY!,
secretAccessKey: process.env.S3_SECRET_KEY!,
},
},
},
guard: {
enabled: true,
},
},
};
serve(config);export DB_URL="libsql://your-db.turso.io"
export DB_TOKEN="your-turso-token"
export JWT_SECRET="your-32-char-minimum-secret"
export PORT=3000undefined
---
---DockerfileFROM oven/bun:1.0-alpine
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile --production
COPY . .DockerfileFROM oven/bun:1.0-alpine
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile --production
COPY . .
**Step 2: Create `docker-compose.yml`**
```yaml
version: "3.8"
services:
bknd:
build: .
ports:
- "3000:3000"
volumes:
- bknd-data:/app/data
environment:
- DB_URL=file:/app/data/bknd.db
- JWT_SECRET=${JWT_SECRET}
- NODE_ENV=production
restart: unless-stopped
volumes:
bknd-data:undefined
**步骤2:创建`docker-compose.yml`**
```yaml
version: "3.8"
services:
bknd:
build: .
ports:
- "3000:3000"
volumes:
- bknd-data:/app/data
environment:
- DB_URL=file:/app/data/bknd.db
- JWT_SECRET=${JWT_SECRET}
- NODE_ENV=production
restart: unless-stopped
volumes:
bknd-data:undefined
---
---// app/api/bknd/[[...bknd]]/route.ts
export { GET, POST, PUT, DELETE, PATCH } from "bknd/adapter/nextjs";bknd.config.tsimport type { NextjsBkndConfig } from "bknd/adapter/nextjs";
import { em, entity, text } from "bknd";
const schema = em({
posts: entity("posts", {
title: text().required(),
}),
});
type Database = (typeof schema)["DB"];
declare module "bknd" {
interface DB extends Database {}
}
export default {
app: (env) => ({
connection: {
url: env.DB_URL,
authToken: env.DB_TOKEN,
},
schema,
isProduction: env.NODE_ENV === "production",
auth: {
jwt: { secret: env.JWT_SECRET },
},
}),
} satisfies NextjsBkndConfig;vercel env add DB_URL
vercel env add DB_TOKEN
vercel env add JWT_SECRETvercel deploy --prod// app/api/bknd/[[...bknd]]/route.ts
export { GET, POST, PUT, DELETE, PATCH } from "bknd/adapter/nextjs";bknd.config.tsimport type { NextjsBkndConfig } from "bknd/adapter/nextjs";
import { em, entity, text } from "bknd";
const schema = em({
posts: entity("posts", {
title: text().required(),
}),
});
type Database = (typeof schema)["DB"];
declare module "bknd" {
interface DB extends Database {}
}
export default {
app: (env) => ({
connection: {
url: env.DB_URL,
authToken: env.DB_TOKEN,
},
schema,
isProduction: env.NODE_ENV === "production",
auth: {
jwt: { secret: env.JWT_SECRET },
},
}),
} satisfies NextjsBkndConfig;vercel env add DB_URL
vercel env add DB_TOKEN
vercel env add JWT_SECRETvercel deploy --prodnpm install -D serverless serverless-esbuildhandler.tsimport { createHandler } from "bknd/adapter/aws";
export const handler = createHandler({
connection: {
url: process.env.DB_URL!,
authToken: process.env.DB_TOKEN,
},
isProduction: true,
auth: {
jwt: { secret: process.env.JWT_SECRET! },
},
});serverless.ymlservice: bknd-api
provider:
name: aws
runtime: nodejs20.x
region: us-east-1
environment:
DB_URL: ${env:DB_URL}
DB_TOKEN: ${env:DB_TOKEN}
JWT_SECRET: ${env:JWT_SECRET}
plugins:
- serverless-esbuild
functions:
api:
handler: handler.handler
events:
- http:
path: /{proxy+}
method: ANY
- http:
path: /
method: ANYserverless deploy --stage prodnpm install -D serverless serverless-esbuildhandler.tsimport { createHandler } from "bknd/adapter/aws";
export const handler = createHandler({
connection: {
url: process.env.DB_URL!,
authToken: process.env.DB_TOKEN,
},
isProduction: true,
auth: {
jwt: { secret: process.env.JWT_SECRET! },
},
});serverless.ymlservice: bknd-api
provider:
name: aws
runtime: nodejs20.x
region: us-east-1
environment:
DB_URL: ${env:DB_URL}
DB_TOKEN: ${env:DB_TOKEN}
JWT_SECRET: ${env:JWT_SECRET}
plugins:
- serverless-esbuild
functions:
api:
handler: handler.handler
events:
- http:
path: /{proxy+}
method: ANY
- http:
path: /
method: ANYserverless deploy --stage produndefinedundefinedundefinedundefined| Variable | Required | Description |
|---|---|---|
| Yes | Database connection URL |
| Depends | Auth token (Turso/LibSQL) |
| Yes | Min 32 chars for security |
| No | Server port (default: 3000) |
| 变量名 | 是否必填 | 说明 |
|---|---|---|
| 是 | 数据库连接URL |
| 可选 | 认证令牌(Turso/LibSQL需提供) |
| 是 | 长度至少32字符,用于安全验证 |
| 否 | 服务器端口(默认:3000) |
better-sqlite3connection: {
url: "libsql://your-db.turso.io",
authToken: process.env.DB_TOKEN,
}better-sqlite3connection: {
url: "libsql://your-db.turso.io",
authToken: process.env.DB_TOKEN,
}undefinedundefinedundefinedundefinedenv.DB is undefined[[d1_databases]]
binding = "DB" # Must match env.DB in code
database_name = "my-database"
database_id = "actual-id-from-wrangler-d1-create"env.DB is undefined[[d1_databases]]
binding = "DB" # 必须与代码中的env.DB一致
database_name = "my-database"
database_id = "actual-id-from-wrangler-d1-create"config: {
media: {
adapter: {
type: "s3", // or "r2", "cloudinary"
config: { /* credentials */ },
},
},
}config: {
media: {
adapter: {
type: "s3", // 或 "r2", "cloudinary"
config: { /* 凭据信息 */ },
},
},
}// Most adapters handle this automatically
// For custom needs, check platform docs// 大多数适配器会自动处理此问题
// 如需自定义,请参考对应平台文档undefinedundefinedundefinedundefinedisProduction: true.envisProduction: true.env