npx pretendo start repo://simple-api.yml
Pretendo is a supercharged development tool for frontend developers who need a fully-featured REST API without the hassle of setting up a real backend.
Why we built this:
- Speed up development - Start building your frontend immediately without waiting for backend APIs
- Work offline - Develop without relying on external services
- Test edge cases easily - Simulate errors, latency, and various response scenarios
- Show realistic prototypes - Demo with real data flows and interactions
- Control complexity - Scale your mock API with your needs, from simple endpoints to complex relationships
With a simple YAML or JSON configuration, you get a complete RESTful service with CRUD operations, relationships, filtering, pagination, authentication, and more - all ready to use in seconds!
See our Introduction for a more detailed overview.
For comprehensive documentation, check out the docs directory:
- API Schema - How to define your API resources and fields
- API Design - REST principles and conventions used
- Filtering - Query and filter your data
- Sorting - Sort your collections
- Pagination - Paginate large datasets
- Relationships - Work with related resources
- Special Fields - Dynamic computed field values
- Configuration - Configure your mock API
- Authentication - Secure your endpoints
- π Zero Setup Required - Define your API with a straightforward YAML/JSON spec
- π Remote Schemas - Load schemas from local files or remote URLs (GitHub URLs supported!)
- π Full CRUD Operations - Auto-generated RESTful endpoints for all resources (CRUD docs)
- π Custom Routes - Define custom JSON and JavaScript routes alongside resource endpoints (Custom Routes docs)
- π Secure JavaScript Execution - Optional pluggable hooks for secure, isolated JavaScript execution (Custom Routes docs)
- β¨ Special Field Values - Computed dynamic values like timestamps, UUIDs, auto-increment, and more (Special Fields docs)
- π Advanced Relationships - Model one-to-many, many-to-many, and belongs-to relationships (Relationships docs)
- π Rich Querying Capabilities:
- Filtering with operators (
gt,lt,contains,startsWith, etc.) (Filtering docs) - Sorting by multiple fields with direction control (Sorting docs)
- Pagination with RFC-compliant Link headers (Pagination docs)
- Field selection for partial responses (Field Selection docs)
- Relationship expansion with nested data (Relationship Expansion docs)
- UUID support for primary keys (UUID Support docs)
- Filtering with operators (
- π Authentication & Authorization - Built-in JWT auth with configurable users and roles, plus robust RBAC (Authentication docs)
- π Network Simulation - Configurable latency and error rates for realistic testing (Network Simulation docs)
- πΎ Data Persistence - State saved to file for continued development (Persistence docs)
- β‘ Performance - Optimized for speed, even with large datasets
- π§ͺ Test-Friendly - Perfect for unit, integration and e2e testing
- π§ Highly Extensible - Use as CLI or programmatically in your code
# No installation needed! Run directly with npx:
npx pretendo start repo://blog-api.yml
# Global installation for CLI use
npm install -g pretendo
# Local project installation
npm install --save-dev pretendoSee the Installation Guide for more options.
Create a api.yml file:
resources:
- name: users
fields:
- name: id
type: number
- name: name
type: string
- name: email
type: string
relationships:
- type: hasMany
resource: posts
foreignKey: userId
- name: posts
fields:
- name: id
type: number
- name: title
type: string
- name: content
type: string
- name: userId
type: number
relationships:
- type: belongsTo
resource: users
foreignKey: userId
options:
port: 3000
latency:
enabled: true
min: 50
max: 200Start the server:
# Using npx (no installation required)
npx pretendo start api.yml
# Using installed CLI
pretendo start api.yml
# Start with remote URL (GitHub URLs auto-download)
npx pretendo start https://raw.githubusercontent.com/alexberriman/pretendo/main/examples/blog-api.yml
# Using repository shorthand
npx pretendo start repo://blog-api.yml
# Skip confirmation for non-GitHub URLs
npx pretendo start https://example.com/api.yml --no-promptFor a step-by-step tutorial, see our Quick Start Guide.
Pretendo can be used programmatically in your Node.js applications:
import { createMockApi } from "pretendo";
const spec = {
resources: [
{
name: "users",
fields: [
{ name: "id", type: "number" },
{ name: "name", type: "string" },
{ name: "email", type: "string" },
],
},
],
options: { port: 3000 },
};
async function startServer() {
const result = await createMockApi({ spec });
if (result.ok) {
console.log(`π Server running at: ${result.value.getUrl()}`);
// Shutdown when needed
// await result.value.stop();
}
}
startServer();Pretendo offers powerful programmatic features for advanced use cases:
import { createMockApi } from "pretendo";
const api = await createMockApi({
// API specification
spec: {
resources: [/* resources */],
options: {/* options */}
},
// Add custom routes
routes: (router) => {
router.get('/health', (req, res) => {
res.json({ status: 'ok' });
});
router.post('/webhook', (req, res) => {
// Process webhook
res.status(202).json({ received: true });
});
},
// Add lifecycle hooks
hooks: {
onRequest: (req, res, next) => {
// Log all requests
console.log(`${req.method} ${req.path}`);
next();
},
beforeRoute: (req, res, next) => {
// Add custom header
res.setHeader('X-Custom-Header', 'Value');
next();
}
},
// Custom JS execution (for secure isolation)
executeJs: async (context) => {
// Custom JavaScript execution
// This can be used to run code in a secure environment
return {
status: 200,
headers: {},
body: { result: 'secure execution' }
};
}
});
await api.listen();See the Custom Routes documentation for more details on programmatic usage.
The API design is based on RESTful principles from GitHub: alexberriman/rest-api-design. See the API Design Principles documentation for detailed conventions.
Pretendo provides comprehensive field validation to ensure data integrity:
fields:
- name: username
type: string
required: true
minLength: 3
maxLength: 50
pattern: "^[a-zA-Z0-9_]+$"
unique: true
- name: age
type: number
min: 18
max: 120
- name: role
type: string
enum: ["admin", "user", "editor"]See Resource Validation for complete documentation.
GET /users # List all users (paginated)
GET /users/123 # Get user with numeric ID
GET /users/550e8400-e29b-41d4-a716-446655440000 # Get user with UUID
POST /users # Create a new user
PUT /users/123 # Replace user
PATCH /users/123 # Update user
DELETE /users/123 # Delete user
See CRUD Operations for complete details.
# Simple equality
GET /users?role=admin
# Advanced operators
GET /users?age_gt=21
GET /users?name_like=john
GET /posts?title_startsWith=Hello
GET /products?price_gte=10&price_lte=100
GET /users?tags_in=developer,designer
See Filtering Documentation for more details.
# Ascending sort (default)
GET /users?sort=name
# Descending sort
GET /users?sort=-createdAt
# Multiple sort fields
GET /users?sort=role,-name
See Sorting Documentation for more details.
GET /users?page=2&limit=10
Response includes pagination metadata and RFC 5988 Link headers:
{
"data": [...],
"meta": {
"pagination": {
"currentPage": 2,
"limit": 10,
"totalPages": 5,
"totalItems": 48,
"links": {
"first": "http://localhost:3000/users?page=1&limit=10",
"prev": "http://localhost:3000/users?page=1&limit=10",
"next": "http://localhost:3000/users?page=3&limit=10",
"last": "http://localhost:3000/users?page=5&limit=10"
}
}
}
}See Pagination Documentation for more options.
GET /users?fields=id,name,email
See Field Selection Documentation for advanced usage.
# Single relationship
GET /posts?expand=author
# Multiple relationships
GET /posts?expand=author,comments
# Nested relationships
GET /posts?expand=author.profile,comments.user
See Relationship Expansion Documentation for more details.
# Global options
options:
# Server options
port: 3000
host: localhost
corsEnabled: true
# Authentication
auth:
enabled: true
jwt:
secret: "your-secret-key"
expiresIn: "1h"
users:
- username: admin
password: password
role: admin
# Network simulation
latency:
enabled: true
min: 50
max: 200
# Database options
dataFile: ./db.json
defaultPageSize: 10
maxPageSize: 100
# Custom routes at the API level
routes:
- path: "/status"
method: "get"
type: "json"
response:
status: "operational"
version: "1.0.0"
environment: "production"
- path: "/users/:id/profile"
method: "get"
type: "json"
response:
user:
id: "{id}"
profile:
bio: "Profile for user {id}"
avatar: "https://example.com/avatars/{id}.jpg"
- path: "/files/{*filePath}"
method: "get"
type: "javascript"
code: "// Will serve files from paths in the future"See Configuration Documentation for all available options.
Pretendo provides a comprehensive authentication and authorization system:
- Authentication: JWT-based authentication for user identity
- Role-Based Access Control (RBAC): Control access based on user roles
- Ownership-Based Permissions: Allow users to manage their own resources
When authentication is enabled:
- Login to get a token:
curl -X POST http://localhost:3000/auth/login \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "password"}'Response:
{
"token": "eyJhbGciOiJIUzI1...",
"user": {
"username": "admin",
"role": "admin",
"id": 1
},
"expiresAt": 1609459200000
}- Use token for protected endpoints:
curl http://localhost:3000/users \
-H "Authorization: Bearer eyJhbGciOiJIUzI1..."Configure different access levels for each resource:
resources:
- name: posts
ownedBy: authorId
access:
list: ["*"] # Any authenticated user can list
get: ["*"] # Any authenticated user can view
create: ["editor", "admin"] # Only editors and admins can create
update: ["admin", "owner"] # Admin or the author can update
delete: ["admin", "owner"] # Admin or the author can deleteSee Authentication Documentation and RBAC Documentation for more details.
pretendo start <file|url> [options]
Options:
-p, --port <number> Port to run the server on
-h, --host <string> Host to bind to
--no-cors Disable CORS support
-d, --db <path> Path to database file
--delay <ms> Add fixed delay to all responses
--error-rate <rate> Add random errors (0-1 probability)
--reset Reset database before starting
--no-interactive Disable interactive CLI mode
--no-prompt Skip download confirmation for URLs
When running in interactive mode, Pretendo provides a powerful command-line interface:
Available commands:
help Show this help message
routes List all API routes
request <method> <url> Make a request to the API
config Show current configuration
examples List available example specifications
logs [options] View server request logs
stats Show server statistics
clear Clear the console
exit Exit the application
You can use the repo:// URL scheme to quickly load example configurations:
# Load an example from the Pretendo repository (no installation needed)
npx pretendo start repo://simple-api.yml
# List all available examples
npx pretendo examples
# This automatically expands to:
# https://raw.githubusercontent.com/alexberriman/pretendo/refs/heads/main/examples/simple-api.ymlSee CLI Reference for complete documentation.
Check the examples directory for complete API specifications or run them directly:
# List all available examples
npx pretendo examples
# Run the simple API example
npx pretendo start repo://simple-api.yml
# Run the blog API example
npx pretendo start repo://blog-api.yml
# Run the e-commerce API example
npx pretendo start repo://e-commerce-api.yml
# Run the UUID API example
npx pretendo start repo://uuid-api.ymlExample specifications:
The mock API is perfect for integration and E2E testing:
// Example with testing framework
describe("User API", () => {
let server;
beforeAll(async () => {
const spec = {
/* Your test API spec */
};
const result = await createMockApi({ spec });
server = result.value;
});
afterAll(async () => {
await server.stop();
});
test("should create a new user", async () => {
const response = await fetch(`${server.getUrl()}/users`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "Test User", email: "test@example.com" }),
});
expect(response.status).toBe(201);
const data = await response.json();
expect(data.name).toBe("Test User");
});
});MIT
Contributions are welcome! Feel free to open issues or submit pull requests.
- Fork the repository
- Create your feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add some amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
Give a βοΈ if this project helped you!