https://github.com/khalic-lab/schmock
Schema Mocking Made Easy
https://github.com/khalic-lab/schmock
Last synced: 7 days ago
JSON representation
Schema Mocking Made Easy
- Host: GitHub
- URL: https://github.com/khalic-lab/schmock
- Owner: khalic-lab
- Created: 2025-07-27T11:21:55.000Z (11 months ago)
- Default Branch: develop
- Last Pushed: 2026-05-30T16:56:29.000Z (21 days ago)
- Last Synced: 2026-05-30T18:08:45.944Z (21 days ago)
- Language: TypeScript
- Size: 2.64 MB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- Audit: AUDIT.md
Awesome Lists containing this project
- fucking-awesome-angular - schmock - Create callable mock APIs from OpenAPI specs or hand-crafted routes using a plugin pipeline and framework adapters. (Testing / Helpers)
- awesome-angular - schmock - Create callable mock APIs from OpenAPI specs or hand-crafted routes using a plugin pipeline and framework adapters. (Testing / Helpers)
README
# Schmock
Mock APIs from OpenAPI specs or hand-crafted routes. Callable API, plugin pipeline, framework adapters.
```typescript
import { schmock } from '@schmock/core'
import { openapi } from '@schmock/openapi'
const mock = schmock({ state: {} })
mock.pipe(await openapi({
spec: './petstore.yaml',
seed: { pets: { count: 5 } }
}))
const res = await mock.handle('GET', '/pets')
// → { status: 200, body: [{ petId: 1, name: "Rex", ... }, ...] }
```
## Why Schmock?
- **OpenAPI-first**: Point at a spec, get a fully functional CRUD mock with stateful collections, seed data, security validation, and content negotiation
- **Callable API**: No HTTP server needed — call `mock.handle()` directly in tests
- **Plugin pipeline**: Chain plugins with `.pipe()` for validation, pagination, filtering, or custom logic
- **Framework adapters**: Drop into Express middleware or Angular HTTP interceptor
- **Smart data generation**: Field-name-aware faker generates realistic data from schemas
## Packages
| Package | Description |
|---------|-------------|
| [`@schmock/core`](./docs/getting-started.md) | Core mock builder, routing, and plugin pipeline |
| [`@schmock/openapi`](./docs/openapi.md) | Auto-register routes from OpenAPI/Swagger specs |
| [`@schmock/faker`](./docs/api.md#faker-plugin) | Faker-powered automatic data generation |
| [`@schmock/validation`](./docs/api.md#validation-plugin) | Request/response validation via AJV |
| [`@schmock/query`](./docs/api.md#query-plugin) | Pagination, sorting, and filtering |
| [`@schmock/express`](./docs/express.md) | Express middleware adapter |
| [`@schmock/angular`](./docs/angular.md) | Angular HTTP interceptor adapter |
| [`@schmock/cli`](./docs/cli.md) | Standalone CLI mock server |
## Quick Start
```sh
npm install @schmock/core
```
### Define routes, call them directly
```typescript
const mock = schmock()
mock('GET /users', [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
])
mock('GET /users/:id', ({ params }) => {
const users = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
return users.find(u => u.id === Number(params.id)) || [404, { error: 'Not found' }]
})
const res = await mock.handle('GET', '/users/1')
// → { status: 200, body: { id: 1, name: 'Alice' }, headers: {...} }
```
### Stateful mocks with CRUD
```typescript
const mock = schmock({ state: { items: [] } })
mock('POST /items', ({ body, state }) => {
const item = { id: state.items.length + 1, ...body }
state.items.push(item)
return [201, item]
})
mock('GET /items', ({ state }) => state.items)
await mock.handle('POST', '/items', { body: { name: 'Widget' } })
const list = await mock.handle('GET', '/items')
// list.body → [{ id: 1, name: 'Widget' }]
```
### Mock from an OpenAPI spec
```typescript
import { openapi } from '@schmock/openapi'
const mock = schmock({ state: {} })
mock.pipe(await openapi({
spec: './petstore.yaml',
seed: { pets: [{ petId: 1, name: 'Rex', tag: 'dog' }] },
security: true,
}))
await mock.handle('GET', '/pets') // list
await mock.handle('GET', '/pets/1') // get by id
await mock.handle('POST', '/pets', { // create
body: { name: 'Buddy', tag: 'dog' },
headers: { authorization: 'Bearer token' },
})
await mock.handle('DELETE', '/pets/1') // delete
```
### Request spying
```typescript
await mock.handle('POST', '/items', { body: { name: 'A' } })
await mock.handle('POST', '/items', { body: { name: 'B' } })
mock.called('POST', '/items') // true
mock.callCount('POST', '/items') // 2
mock.lastRequest('POST', '/items') // { body: { name: 'B' }, ... }
```
### Plugin pipeline
```typescript
import { validationPlugin } from '@schmock/validation'
import { queryPlugin } from '@schmock/query'
mock('GET /users', ({ state }) => state.users)
.pipe(validationPlugin({ request: { query: querySchema } }))
.pipe(queryPlugin({
pagination: { defaultLimit: 20 },
sorting: { allowed: ['name', 'created_at'] },
filtering: { allowed: ['role'] },
}))
// GET /users?filter[role]=admin&sort=name&page=2&limit=10
```
### Framework adapters
**Express:**
```typescript
import { toExpress } from '@schmock/express'
app.use('/api', toExpress(mock))
```
**Angular:**
```typescript
import { provideSchmockInterceptor } from '@schmock/angular'
providers: [provideSchmockInterceptor(mock, { baseUrl: '/api' })]
```
### CLI server
```sh
npm install -g @schmock/cli
schmock petstore.yaml --port 8080 --cors --seed seed.json
```
## Documentation
| Guide | Description |
|-------|-------------|
| [Getting Started](./docs/getting-started.md) | Installation, core concepts, first mock |
| [OpenAPI](./docs/openapi.md) | Auto-mocking, CRUD, seed data, Prefer header, security, schema patching |
| [Testing](./docs/testing.md) | Unit tests, integration tests, Angular & Express testing patterns |
| [Express Adapter](./docs/express.md) | Express middleware setup and options |
| [Angular Adapter](./docs/angular.md) | Angular interceptor, helpers, TestBed setup |
| [CLI](./docs/cli.md) | Command-line mock server |
| [Plugin Development](./docs/plugins.md) | Writing custom plugins |
| [API Reference](./docs/api.md) | Complete type and method reference |
| [Debug Mode](./docs/debug-mode.md) | Request lifecycle logging |
## Contributing
See [CONTRIBUTING.md](./CONTRIBUTING.md) for development setup and workflow.
## License
MIT