mock-api-generator
v1.0.4
Published
Mock API generator with typed decorators and fake data generation
Downloads
525
Maintainers
Readme
mock-api-generator
A TypeScript-first mock API server generator. Define your response shapes with decorators, map them to routes with a typed schema, and get a fully working HTTP server with realistic fake data — no config files, no manual fixtures.
Support this project
Installation
npm install mock-api-generator
# or
pnpm add mock-api-generator
# or
yarn add mock-api-generatorRequires
reflect-metadata. Add this to the top of your entry file:import "reflect-metadata";And enable these in your
tsconfig.json:{ "experimentalDecorators": true, "emitDecoratorMetadata": true }
Quick Start
import "reflect-metadata";
import {
createMockServer,
defineSchema,
StringField,
NumberField,
BooleanField,
} from "mock-api-generator";
class User {
@NumberField("id") id!: number;
@StringField("fullName") name!: string;
@StringField("email") email!: string;
@BooleanField() active!: boolean;
}
class ErrorResponse {
@StringField("text") message!: string;
}
const schema = defineSchema({
users: {
success: [User],
error: ErrorResponse,
},
});
const server = createMockServer(schema, { port: 3000 });
await server.start();
// GET http://localhost:3000/users → array of User objectsDecorators
Decorators describe how each field should be generated. Apply them to class properties.
@StringField(hint)
| Hint | Example output |
| ----------------------------------------------------------------- | ----------------------- |
| 'name' / 'firstName' / 'lastName' / 'fullName' | "Jane Doe" |
| 'email' | "[email protected]" |
| 'phone' | "+1-555-0100" |
| 'url' | "https://example.com" |
| 'uuid' | "a1b2c3..." |
| 'address' / 'city' / 'country' / 'zipCode' / 'location' | address parts |
| 'username' / 'password' / 'token' | auth-related strings |
| 'description' / 'text' | lorem-style text |
@NumberField(hint)
| Hint | Range |
| ---------------------------- | ---------------- |
| 'id' | positive integer |
| 'age' | 1–100 |
| 'price' | decimal |
| 'rating' | 0–5 |
| 'count' | positive integer |
| 'percentage' | 0–100 |
| 'latitude' / 'longitude' | geo coordinates |
| 'year' | recent year |
@BooleanField()
Generates a random true or false.
@DateField(hint)
| Hint | Description |
| -------------- | ----------------------- |
| 'pastDate' | a date in the past |
| 'futureDate' | a date in the future |
| 'recentDate' | within the last 30 days |
@ArrayField(ItemClass, min?, max?)
Generates an array of ItemClass instances. min and max control the array length (defaults: 1–5).
class Order {
@StringField("uuid") id!: string;
@ArrayField(OrderItem, 1, 5) items!: OrderItem[];
}@ObjectField(NestedClass)
Generates a single nested object.
class User {
@StringField("fullName") name!: string;
@ObjectField(Address) address!: Address;
}Schema
defineSchema(schema)
Validates the schema at runtime and returns it with full TypeScript inference.
const schema = defineSchema({ ... });Route entries
Each leaf in the schema is a route entry:
{
success: ResponseClass | [ResponseClass], // single object or array
error: ErrorClass,
successRate?: number, // 0–1, defaults to 1
}- Wrap
successin[]to return an array response. successRatecontrols how often the success shape is returned vs the error shape (on a500).
Path segments
Schema keys map to URL path segments:
| Key | Path segment |
| ----------- | ------------------------------------ |
| 'users' | /users |
| '$id' | /:id (dynamic param) |
| 'default' | `` (empty — matches the parent path) |
Nest keys to build up paths:
defineSchema({
users: {
// /users
success: [User],
error: ErrorResponse,
$id: {
// /users/:id
success: User,
error: ErrorResponse,
},
},
});HTTP methods
By default every route entry responds to GET. To handle other methods, use a $METHOD key:
defineSchema({
users: {
success: [User], // GET /users
error: ErrorResponse,
$POST: {
success: User, // POST /users
error: ErrorResponse,
},
$id: {
success: User, // GET /users/:id
error: ErrorResponse,
$PUT: {
success: User, // PUT /users/:id
error: ErrorResponse,
},
$DELETE: {
success: User, // DELETE /users/:id
error: ErrorResponse,
},
},
},
});Supported method keys: $GET, $POST, $PUT, $PATCH, $DELETE.
Server
createMockServer(schema, options?)
const server = createMockServer(schema, {
port: 3000, // default: 3000
seed: 42, // optional — makes fake data deterministic
});server.start()
Starts the HTTP server. Resolves when the server is listening.
server.stop()
Gracefully shuts down the server.
Full Example
import "reflect-metadata";
import {
createMockServer,
defineSchema,
StringField,
NumberField,
BooleanField,
DateField,
ArrayField,
ObjectField,
} from "mock-api-generator";
class Address {
@StringField("city") city!: string;
@StringField("country") country!: string;
@StringField("zipCode") zipCode!: string;
}
class User {
@NumberField("id") id!: number;
@StringField("fullName") name!: string;
@StringField("email") email!: string;
@BooleanField() active!: boolean;
@DateField("recentDate") createdAt!: Date;
@ObjectField(Address) address!: Address;
}
class ErrorResponse {
@StringField("text") message!: string;
}
const schema = defineSchema({
users: {
success: [User], // GET /users
error: ErrorResponse,
successRate: 0.95,
$POST: {
success: User, // POST /users
error: ErrorResponse,
},
$id: {
success: User, // GET /users/:id
error: ErrorResponse,
$PUT: {
success: User, // PUT /users/:id
error: ErrorResponse,
},
$DELETE: {
success: User, // DELETE /users/:id
error: ErrorResponse,
},
},
},
});
const server = createMockServer(schema, { port: 3000, seed: 42 });
(async () => {
await server.start();
console.log("Mock server running on http://localhost:3000");
})();Error Reference
| Error | When thrown |
| ------------------------- | ------------------------------------------------------ |
| InvalidHintError | A decorator is called with an unrecognised hint string |
| InvalidSuccessRateError | successRate is outside the [0, 1] range |
| RouteConflictError | Two schema keys resolve to the same method + path |
| CircularReferenceError | A class references itself (directly or indirectly) |
