> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vibestrap.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# 开发工具链

> 一套有主张的工具链 —— Biome、Knip、Drizzle、Vitest、next-safe-action、server-only、t3-env —— 选型目标是把验证循环跑得飞快。

Vibestrap 在开发工具上很有主张，因为独立开发者没空伺候构建。每一项要么是
快（Biome 比 ESLint+Prettier 快约 10 倍），要么是承重（`server-only` 防止
密钥泄漏到客户端 bundle）。这页讲清楚装了什么、各自的职责、以及踩过的坑。

## 前置条件

* Node.js 20 或更新（看 `package.json` 的 `engines`）。
* pnpm 10（`corepack enable && corepack prepare pnpm@10.26.1 --activate`）。
* 一个 Postgres 数据库，用于 `db:push` / `db:migrate`。

## 工具栈

### Biome 2 —— 一个 binary 同时做 lint 和 format

用一个 Rust binary 替代 ESLint + Prettier，速度大约快 10 倍。配置在 `biome.json`。

```bash theme={null}
pnpm lint        # biome check .
pnpm lint:fix    # biome check --write .
pnpm format      # biome format --write .
```

风格：单引号、ES5 尾逗号、100 列。规则在 `biome.json` 的 `linter.rules` 调。

### Knip 6 —— 死代码检测

找出无用 export、未使用的依赖、孤儿文件。重构后跑一次。

```bash theme={null}
pnpm knip
```

配置在 `knip.config.ts`。误报加到 `ignore` / `ignoreDependencies` 列表。

### Drizzle ORM 0.45 —— 类型安全 SQL

Schema 拆成 `src/db/{auth,app,affiliate,ai,license}.schema.ts`。ID 用 nanoid
前缀的 `text`（如 `lic_xxx`），不用 `serial`。

```bash theme={null}
pnpm db:push        # dev —— 不生成迁移文件直接同步 schema
pnpm db:generate    # prod —— 从 schema diff 生成 SQL 迁移
pnpm db:migrate     # prod —— 应用待执行的迁移
pnpm db:studio      # 可视化数据库浏览器 localhost:4983
```

### Vitest 4 —— 单元测试

测试放在 `tests/unit/**` 和 `src/**/*.{test,spec}.ts`。Node 环境、开了 globals、
`@/` 别名可用。

```bash theme={null}
pnpm test           # 跑一次
pnpm test:watch     # watch 模式
```

### next-safe-action 三层 —— 类型化的 server action

所有写操作走 `src/lib/safe-action.ts` 里的三个 client 之一：

```ts theme={null}
actionClient        // 公开，无需登录
userActionClient    // 要求登录用户（ctx.user 可用）
adminActionClient   // 要求 user.role === 'admin'
```

每个 action 用 Zod 声明输入 schema，返回带类型的结果。

### server-only —— 防止客户端泄漏的运行时守卫

碰 DB 或密钥的模块在文件首行 `import 'server-only'`。如果不小心被 client
组件 import，构建会以清晰的报错失败，而不是把 `DATABASE_URL` 打进浏览器。

已经守护的：`src/db/index.ts`、`src/lib/auth.ts`、`src/payment/provider/*`、
`src/credits/server.ts`、`src/github/invite.ts`。

### @t3-oss/env-nextjs —— 类型化 env 变量

`src/env.ts` 用 Zod 声明每个必需和可选的 env 变量。缺必需变量时 app 拒绝
启动，配置错误在构建时就报，而不是在凌晨三点的生产环境。

永远从 `@/env` 引（不要 `process.env.X`），这样有类型和校验。

## 验证生效

每次 commit 前：

```bash theme={null}
pnpm typecheck && pnpm lint && pnpm build
```

任意一步失败时，报错信息会告诉你要修哪。不要 push 任何一步失败的代码——
生产 CI 跑的是同一条命令链。

## 常见坑

1. **新文件忘了 `import 'server-only'`**。任何读 `env.STRIPE_SECRET_KEY`、
   查 DB、调用密钥的文件，第一行就加。构建会抓泄漏。
2. **用 `process.env.X` 而不是 `env.X`**。你跳过了 Zod 校验、丢了类型，
   变量名拼错时会在生产挂掉。Biome 没有规则禁止它——靠 code review 或
   `grep -r 'process\.env\.'`。
3. **未登录路由调 `userActionClient` action**。会抛 `UNAUTHORIZED` 返回 401。
   要么外面套个 session 检查，要么换成 `actionClient`（如果 action 真的是公开的）。
4. **生产环境跑 `pnpm db:push`**。它直接 diff schema 并应用破坏性变更（drop、
   rename），不生成迁移文件。生产用 `db:generate` + `db:migrate`，加 `--strict`
   能在破坏性操作前要求确认。
5. **Knip 误报**。Skill registry、动态 import 的 provider 在静态分析里看着像
   没人用。把它们加到 `knip.config.ts` 的 `ignore` 列表——别真删了文件。

## 官方文档

* Biome：[biomejs.dev](https://biomejs.dev/)
* Knip：[knip.dev](https://knip.dev/)
* Drizzle ORM：[orm.drizzle.team](https://orm.drizzle.team/)
* Vitest：[vitest.dev](https://vitest.dev/)
* next-safe-action：[next-safe-action.dev](https://next-safe-action.dev/)
* t3-env：[env.t3.gg](https://env.t3.gg/)
