$npx -y skills add girijashankarj/cursor-handbook --skill api-mock-serverGenerate a mock API server from OpenAPI specs, TypeScript interfaces, or endpoint descriptions for frontend development and testing. Use when the user asks to create a mock server, fake API, or stub endpoints.
| 1 | # Skill: API Mock Server |
| 2 | |
| 3 | Generate a lightweight mock API server that returns realistic responses for frontend development and integration testing. |
| 4 | |
| 5 | ## Trigger |
| 6 | When the user asks to mock an API, create a fake backend, stub endpoints, or generate a dev server from a spec. |
| 7 | |
| 8 | ## Prerequisites |
| 9 | - [ ] API endpoints to mock identified |
| 10 | - [ ] Response shapes known (from OpenAPI spec, TypeScript types, or examples) |
| 11 | |
| 12 | ## Steps |
| 13 | |
| 14 | ### Step 1: Choose Approach |
| 15 | |
| 16 | | Approach | Tool | Best For | |
| 17 | |----------|------|----------| |
| 18 | | **JSON Server** | `json-server` | Quick REST mock from a JSON file | |
| 19 | | **MSW (Mock Service Worker)** | `msw` | Browser/Node request interception for tests | |
| 20 | | **Express mock** | `express` | Custom logic, delays, error simulation | |
| 21 | | **Prism** | `@stoplight/prism-cli` | Auto-mock from OpenAPI spec | |
| 22 | |
| 23 | ### Step 2: Generate Mock Data |
| 24 | - [ ] Use the `test-data-factory` skill to create realistic data |
| 25 | - [ ] Generate 10–50 records per resource |
| 26 | - [ ] Include relationships (foreign keys reference valid IDs) |
| 27 | |
| 28 | ### Step 3a: JSON Server (Simplest) |
| 29 | |
| 30 | ```json |
| 31 | // mock-db.json |
| 32 | { |
| 33 | "users": [ |
| 34 | { "id": "usr_001", "name": "Alice Johnson", "email": "alice@example.com", "role": "admin" }, |
| 35 | { "id": "usr_002", "name": "Bob Smith", "email": "bob@example.com", "role": "user" } |
| 36 | ], |
| 37 | "orders": [ |
| 38 | { "id": "ord_001", "userId": "usr_001", "status": "CONFIRMED", "total": 99.99 } |
| 39 | ] |
| 40 | } |
| 41 | ``` |
| 42 | |
| 43 | ```bash |
| 44 | npx json-server mock-db.json --port 3001 --delay 200 |
| 45 | ``` |
| 46 | |
| 47 | ### Step 3b: MSW Handlers (for Tests) |
| 48 | |
| 49 | ```typescript |
| 50 | // mocks/handlers.ts |
| 51 | import { http, HttpResponse } from 'msw'; |
| 52 | |
| 53 | export const handlers = [ |
| 54 | http.get('/api/v1/users', () => { |
| 55 | return HttpResponse.json({ |
| 56 | data: [ |
| 57 | { id: 'usr_001', name: 'Alice Johnson', email: 'alice@example.com' }, |
| 58 | ], |
| 59 | meta: { correlationId: 'mock-123', timestamp: new Date().toISOString() }, |
| 60 | }); |
| 61 | }), |
| 62 | |
| 63 | http.post('/api/v1/users', async ({ request }) => { |
| 64 | const body = await request.json(); |
| 65 | return HttpResponse.json( |
| 66 | { data: { id: 'usr_new', ...body }, meta: { correlationId: 'mock-456' } }, |
| 67 | { status: 201 } |
| 68 | ); |
| 69 | }), |
| 70 | |
| 71 | http.get('/api/v1/users/:id', ({ params }) => { |
| 72 | if (params.id === 'not-found') { |
| 73 | return HttpResponse.json( |
| 74 | { error: { code: 'NOT_FOUND', message: 'User not found' } }, |
| 75 | { status: 404 } |
| 76 | ); |
| 77 | } |
| 78 | return HttpResponse.json({ |
| 79 | data: { id: params.id, name: 'Alice Johnson' }, |
| 80 | }); |
| 81 | }), |
| 82 | ]; |
| 83 | ``` |
| 84 | |
| 85 | ```typescript |
| 86 | // mocks/server.ts (Node.js) |
| 87 | import { setupServer } from 'msw/node'; |
| 88 | import { handlers } from './handlers'; |
| 89 | export const server = setupServer(...handlers); |
| 90 | |
| 91 | // mocks/browser.ts (Browser) |
| 92 | import { setupWorker } from 'msw/browser'; |
| 93 | import { handlers } from './handlers'; |
| 94 | export const worker = setupWorker(...handlers); |
| 95 | ``` |
| 96 | |
| 97 | ### Step 3c: Express Mock (Custom Logic) |
| 98 | |
| 99 | ```typescript |
| 100 | // mock-server.ts |
| 101 | import express from 'express'; |
| 102 | |
| 103 | const app = express(); |
| 104 | app.use(express.json()); |
| 105 | |
| 106 | // Simulate latency |
| 107 | app.use((req, res, next) => { |
| 108 | setTimeout(next, 100 + Math.random() * 200); |
| 109 | }); |
| 110 | |
| 111 | app.get('/api/v1/resources', (req, res) => { |
| 112 | const page = parseInt(req.query.cursor as string) || 0; |
| 113 | res.json({ |
| 114 | data: generateResources(20), |
| 115 | meta: { |
| 116 | cursor: page + 20, |
| 117 | hasMore: page < 100, |
| 118 | correlationId: req.headers['x-correlation-id'] || 'mock', |
| 119 | }, |
| 120 | }); |
| 121 | }); |
| 122 | |
| 123 | // Error simulation |
| 124 | app.get('/api/v1/error', (req, res) => { |
| 125 | res.status(500).json({ error: { code: 'INTERNAL_ERROR', message: 'Simulated error' } }); |
| 126 | }); |
| 127 | |
| 128 | app.listen(3001, () => console.log('Mock server on http://localhost:3001')); |
| 129 | ``` |
| 130 | |
| 131 | ### Step 4: Add Error Scenarios |
| 132 | - [ ] 400 — validation error (missing required field) |
| 133 | - [ ] 401 — unauthorized (expired/missing token) |
| 134 | - [ ] 404 — resource not found |
| 135 | - [ ] 429 — rate limited |
| 136 | - [ ] 500 — internal server error |
| 137 | - [ ] Timeout simulation (delayed response) |
| 138 | |
| 139 | ### Step 5: Add to package.json Scripts |
| 140 | ```json |
| 141 | { |
| 142 | "scripts": { |
| 143 | "mock": "npx json-server mock-db.json --port 3001", |
| 144 | "mock:msw": "ts-node mocks/server.ts" |
| 145 | } |
| 146 | } |
| 147 | ``` |
| 148 | |
| 149 | ### Step 6: Document |
| 150 | - [ ] List all mocked endpoints |
| 151 | - [ ] Document special behaviors (error triggers, delays) |
| 152 | - [ ] Note any differences from real API |
| 153 | |
| 154 | ## Rules |
| 155 | - **NEVER** include real credentials or PII in mock data |
| 156 | - **ALWAYS** match the real API's response envelope format |
| 157 | - **ALWAYS** include realistic latency simulation (100–300ms) |
| 158 | - **ALWAYS** include error scenarios alongside happy paths |
| 159 | - Mock data should use `@example.com` emails, fake names, and UUID-style IDs |
| 160 | - Response shapes must match the real API contract exactly |
| 161 | |
| 162 | ## Completion |
| 163 | Working mock server with realistic data, error scenarios, and run instructions. |
| 164 | |
| 165 | ## If a Step Fails |
| 166 | - **No API spec:** Build from TypeScript interfaces or example responses |
| 167 | - **Complex aut |