# fullstack-starter 一个**单二进制**的全栈应用 starter——`bun run compile` 出来的 `./server` 文件就是你要部署的全部产物,自带 HTTP 服务、SSR、API、嵌入式 SQL 迁移,运行时不依赖 Node、不依赖源码、不依赖外部 migration 目录。 技术栈:Bun · TanStack Start (React 19 SSR) · ORPC(契约优先 API)· Drizzle ORM · PostgreSQL 18+ · Tailwind v4 · Biome。 ## 为什么用这个 - **部署最简**:发布只拷一个二进制文件。先 `./server migrate` 再 `./server`,完事。 - **契约优先**:在 `*.contract.ts` 用 Zod 定义一次,前端、后端、OpenAPI 文档自动同步。 - **类型严格**:TypeScript strict,杜绝 `any` / `@ts-ignore` / `as any` 等类型逃逸。 - **开箱可跑**:路径别名、文件路由、ORPC 接线、Tailwind、热重载、错误页全部预接好。 ## 快速开始 > **需要 PostgreSQL 18+**——schema 用 PG 原生的 `uuidv7()` 生成主键(`compose.yaml` 已锁 `postgres:18-alpine`)。要兼容更老的 PG,把 `src/server/db/fields.ts` 里的 `default(sql\`uuidv7()\`)` 换成 `$defaultFn(() => Bun.randomUUIDv7())`,再跑 `bun run db:generate`。 ```bash cp .env.example .env # 把里面的 DATABASE_URL 改成你的 Postgres bun install bun run db:push # 开发期:把 schema 直接同步到 DB(不写 migration 文件) bun run dev # http://localhost:3000 ``` 打开浏览器: - `http://localhost:3000/` — Todo 示例页 - `http://localhost:3000/api/docs` — Scalar 渲染的 API 文档 ## 目录结构(你需要关心的部分) ``` src/ ├── routes/ # 文件路由:页面 + API 端点 ├── server/ │ ├── api/ │ │ ├── contracts/ # Zod 契约(client / server 共享) │ │ └── routers/ # 业务实现 │ └── db/ # Drizzle schema + 嵌入式 migrations ├── client/ # 前端 hooks、ORPC 客户端 └── components/ # UI 组件 ``` ## 加一个功能(以 `post` 为例) 每一步都很短,按顺序填即可: 1. **建表**:`src/server/db/schema/post.ts` 定义 `postTable`,记得展开 `...generatedFields`(自动注入 `id` / `createdAt` / `updatedAt`)。 2. **导出表**:在 `src/server/db/schema/index.ts` 加 `export * from './post'`。 3. **写契约**:`src/server/api/contracts/post.contract.ts` 用 `drizzle-zod` 从表派生 Zod schema。 4. **挂契约**:在 `src/server/api/contracts/index.ts` 把 `post` 加进 `contract` 对象。 5. **写实现**:`src/server/api/routers/post.router.ts` 实现 `os.post.*.handler(...)`。 6. **挂路由**:在 `src/server/api/routers/index.ts` 把 `post` 加进 `router` 对象。 7. **写前端 hook**:`src/client/queries/post.ts` 导出 `useInvalidatePosts` 等失效辅助。 8. **写页面**:`src/routes/.tsx` 用 `useSuspenseQuery` 读、`mutate` 写;mutation 的 `onSuccess` 调用第 7 步的 helper。 9. **生成 migration**:`bun run db:generate` 把 SQL 写到 `./drizzle/` 并嵌入二进制。 完工。`bun run dev` 已自动热重载。 ## 部署 **永远先 migrate 再 serve**。Migration 已嵌入二进制;部署只发一个 `./server` 文件。 ```bash ./server migrate # 应用嵌入式 migration(用 $DATABASE_URL) ./server # 启动 HTTP 服务(默认子命令) ./server --help # 列出所有子命令 ``` 仓库自带 `compose.yaml`(一次性 `migrate` 服务先跑完,再启动 `app`): ```bash docker compose up --build ``` Kubernetes 上:把 `./server migrate` 放进 initContainer 或 Helm `pre-upgrade` Job,主容器跑 `./server`。 ## 脚本一览 | 命令 | 作用 | | --- | --- | | `bun run dev` | Vite 开发服务器(默认端口 3000) | | `bun run build` | 构建到 `.output/`(`bun run compile` 会用到) | | `bun run compile` | 生成单二进制 `out/server-` | | `bun run typecheck` | TypeScript 类型检查 | | `bun run test` | 运行所有 `*.test.ts` | | `bun run fix` | Biome 格式化 + lint + 整理 imports | | `bun run db:push` | 开发期:直接同步 schema 到 DB(不写 migration 文件) | | `bun run db:generate` | 写 SQL migration 到 `./drizzle/` 并嵌入二进制 | | `bun run db:embed` | 仅重生 `migrations.gen.ts`(手改了 `./drizzle/*.sql` 后用) | | `bun run db:migrate` | 通过 drizzle-kit 在本地应用 migration(开发便利) | | `bun run db:studio` | Drizzle Studio(可视化 DB) | 跨平台编译:`bun run compile:{linux,darwin,windows}[:arch]`。 ## 端点 | 路径 | 用途 | | --- | --- | | `/` | Todo 示例 UI | | `/health` | 存活探针(不查 DB,纯文本 `ok`) | | `/api/rpc` | ORPC RPC 端点(client 直连) | | `/api/docs` | Scalar 渲染的 API 文档 | | `/api/spec.json` | OpenAPI spec | ## 提交前 ```bash bun run fix && bun run typecheck && bun run test ``` 没有 CI、没有 pre-commit hook——上面三条由你自觉跑。