Skip to content

Repository files navigation

谗鼎 Mock API

一个开箱即用的 Mock REST API 开源产品:fork 仓库 → 在线修改 mocks/ 模板 → 提交 → CI 自动部署到 Cloudflare Pages,即可获得一套可用的 Mock API 服务,用于产品演示、前端开发、接口测试。

  • 框架:Next.js(App Router)Route Handlers
  • 数据生成:mock.js 语法(全量标签原子化)+ Faker.js(按需引用)
  • 构建:GitHub Actions 编译期静态分析 + 原子按需打包(Tailwind 模式)
  • 部署:Cloudflare Pages(重依赖不进运行时 bundle,规避体积限制)

特性

📁 目录即路径 mocks/users/[id]/get.tsGET /api/users/:id,1:1 映射
🧬 三种模板形态 .json(mock.js 数据模板)/ .ts(默认)/ .js
🎲 运行时随机渲染 每次请求原子方法现场生成,数据不固化
📦 按需打包 模板用到什么标签,bundle 只含对应原子(Faker 全量数 MB 不进运行时)
🔀 Route Handler 能力全集 状态码、自定义 Header、{ delay } 慢网络、请求 body/cookies 读取、Response 完全接管
📄 文档自动生成 构建产出 /openapi.json + /docs(Swagger UI + 样例预览)
构建缓存 模板 hash 比对 + actions cache + Next.js 增量缓存,只改一个文件的重活仅限该文件

快速开始(在线部署,无需本地环境)

  1. Fork 本仓库
  2. 在 fork 后的仓库 Settings → Secrets and variables → Actions 添加两个 secret:
    • CLOUDFLARE_API_TOKEN:Cloudflare 的 API Token(权限:Account → Cloudflare Pages → Edit)
    • CLOUDFLARE_ACCOUNT_ID:Cloudflare 账号 ID(Dashboard 首页右侧)
    • (可选)CLOUDFLARE_PROJECT_NAME:Pages 项目名,默认 mock-api
  3. 在 Cloudflare Dashboard 手动创建同名 Pages 项目一次(首次部署需要)
  4. 之后每次 push 到 main,CI 自动构建部署

也可以在 Cloudflare Pages 中直接连接 GitHub 仓库:构建命令 pnpm build:cf,输出目录 .vercel/output/static

本地开发

pnpm install
pnpm dev        # 自动编译 mocks/ 后启动 http://localhost:3000
  • API 根路径前缀 /api,如 GET http://localhost:3000/api/users
  • 文档页 http://localhost:3000/docs
  • 构建产物验证:pnpm build(Node 运行时)或 pnpm build:cf(Cloudflare Pages 产物)

AI 生成 Mock(Claude Code / Codex)

仓库内置 AI 指令文件(CLAUDE.md / AGENTS.md)与生成技能(.claude/skills/mock-generator/)。用 Claude Code 或 Codex 打开仓库后,直接口述需求:

"给我一个商品详情接口,路径 /api/products/:id,返回名称、价格、库存、图片"

AI 会自动:查标签注册表(packages/atoms/*/atoms.json)→ 按目录约定生成 mocks/products/[id]/get.json → 运行 pnpm build:mocks 验证 → 汇报结果。你 review 后提交即自动部署。

  • Claude Code:自动加载 CLAUDE.md;也可用 /mock-generator 显式触发
  • Codex:自动加载 AGENTS.md

正确性有硬兜底:pnpm build:mocks 是构建期校验器(未知标签、路径冲突、语法错误全部报错),AI 生成错误的文件根本部署不上去。

模板编写

目录结构

mocks/
├── users/
│   ├── get.ts                # GET    /api/users
│   └── [id]/                 # 动态段:/api/users/:id
│       ├── get.json          # GET    /api/users/:id
│       ├── put.ts            # PUT    /api/users/:id
│       └── delete.ts         # DELETE /api/users/:id
└── login/
    └── post.ts               # POST   /api/login
  • 方法文件:get / post / put / patch / delete(全小写),扩展名 .ts(默认)/ .js / .json
  • 同一路径下多个方法文件合并生成一个 Route Handler;请求未定义的方法自动 405
  • 同名方法文件同时存在多个扩展名(如 get.ts + get.json)会在构建期报错
  • 动态段:目录名 [id][...slug]

JSON 模板(mock.js 语法 + DSL)

{
  "page": "{{ctx.query.page:number}}",
  "list|10": [
    {
      "id|+1": 1,
      "name": "@cname",
      "avatar": "{{faker.image.avatar()}}",
      "address": "@city@county@cword(6, 12)号"
    }
  ]
}

mock.js 标签(原语法):@cname@datetime("yyyy-MM-dd")@pick(a, b, c) 等。全部标签见 packages/atoms/mockjs/atoms.json

mock.js 规则(key 内 |):

规则 示例 含义
|n "list|10": [...] 生成 n 个
|min-max "age|18-60": 1 / "list|2-4": [...] 随机 min–max 个
|min-max.dmin-dmax "price|10-9999.0-2": 1 随机浮点,小数位 dmin–dmax
|+step "id|+1": 1 从起始值递增

DSL{{...}} 表达式,见下文规范):Faker 引用、请求上下文注入。字符串内可混合拼接(如上例的 address)。

TS 模板(完整 Route Handler 能力)

export default (ctx: MockContext) => {
  const { params, headers, body } = ctx.request;

  if (headers["x-role"] !== "admin") {
    return { status: 403, body: { message: "forbidden" } };
  }

  return {
    status: 200,
    delay: 500, // 模拟慢网络(毫秒)
    headers: { "x-mock": "ok" },
    body: {
      id: params.id,
      name: "{{faker.person.fullName}}", // DSL 字符串照常可用
      updatedAt: "@now",
    },
  };
};
  • 模板必须 export default 一个接收 MockContext 的函数(全局类型,无需 import)
  • 返回值三种形式:
    1. 直接返回对象 → 200 + application/json
    2. { status, headers, body, delay } → 完整响应控制
    3. Response → 完全接管(重定向、流式响应、cookie 设置等任意能力)
  • 模板内不要直接调用 faker/mockjs 函数(会破坏静态分析),数据值一律用 DSL 字符串
  • ctx.requestmethod / url / params / query / headers / cookies / body(JSON 自动解析,原文在 bodyText

DSL 规范

{{domain.path[:type]}}
说明 示例
ctx 请求上下文(保留域) {{ctx.params.id}}{{ctx.query.page:number}}{{ctx.headers.x-token}}{{ctx.cookies.session}}{{ctx.body.field}}
faker Faker.js {{faker.person.fullName}}{{faker.number.int(1, 99)}}
@ 前缀 mock.js 标签(例外通道,原语法) @cname@email
  • 类型转换::number(v1),预留 :string / :boolean
  • 转义:\{{...}}\@xxx 按字面量输出
  • 新 mock 库接入协议:域注册 + 原子注册 + 解析器插件(见 docs/requirements.md 第 4.2 节)

内置 API 清单

模块 API 示范能力
基础 GET /api/health 静态 JSON
登录 POST /api/login body 读取、条件返回、错误状态码
用户 GET /api/users query 分页注入
用户 GET /api/users/[id] params 注入、混合字符串
用户 PUT /api/users/[id] body 回显更新
用户 DELETE /api/users/[id] header 检查、500 模拟
商品 GET /api/products Faker 商品数据
商品 GET /api/products/[id] 浮点规则、数组规则
订单 GET /api/orders |n|+1@pick
订单 GET /api/orders/[id] { delay } 慢网络

项目结构

mocks/                      # mock 模板(你编辑的目录)
app/api/                    # 生成的 Route Handlers(构建产物,勿手改)
app/docs/                   # /docs 页面(Swagger UI + 样例预览)
packages/atoms/mockjs/      # mock.js 全量标签原子库(注册表 atoms.json)
packages/atoms/faker/       # Faker 原子封装(注册表 faker-atoms.json)
packages/compiler/          # DSL 解析 + JSON/TS 模板编译器 + OpenAPI 生成
scripts/build-mocks.mjs     # 编译入口(hash 缓存 / 产物清理 / 样例渲染)
lib/mock-runtime.ts         # 运行时胶水(ctx 组装 / 返回值适配)
types/mock-context.d.ts     # MockContext 全局类型
docs/requirements.md        # 需求文档(决策记录见第 9 章)

构建流程

mocks/**                    模板源文件
   │  CI(Node 环境)
   │  ① 模板 hash 比对(未变更跳过)
   │  ② 静态分析标签集合
   │  ③ mock.js 规则翻译 + DSL 替换为原子调用
   │  ④ 生成 1:1 route.ts(TS 模板代码原样保留)
   ▼
app/api/**/route.ts         生成物(tree-shaking 按需打包原子)
   │  next build + @cloudflare/next-on-pages
   ▼
Cloudflare Pages            运行时每次请求原子现场生成,随机性保留

路线图

  • 更多 mock 库接入(DSL 接入协议已就绪)
  • 可视化编辑管理界面(触发条件:非开发者需要改 mock 数据的真实需求)
  • TS 模板的可选 export const meta 声明(OpenAPI schema 增强)

About

Fork 当前项目,直接在线上仓库写 JSON,会自动同步 MOCK API 部署到 cloudflare

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages