Skip to content

yn1323/snaperro

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

29 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

snaperro

snaperro Logo

A mock proxy server that records and replays responses from multiple APIs to streamline development and testing.

Name Origin

  • snap: snapshot, quickly capture
  • perro: Spanish for "dog"
  • The image of "a faithful dog that fetches data"

Features

  • 4 Modes: Proxy (passthrough) / Record (capture) / Mock (playback) / Smart (auto)
  • Parameter Matching: Accurate matching by path parameters and query parameters
  • State Persistence: Mode and scenario settings persist across server restarts
  • TypeScript Configuration: Type-safe configuration files

Why snaperro?

Are you facing these problems during development?

  • Depending on multiple APIs, making environment setup difficult
  • Local development stops due to external API outages
  • Preparing test data is tedious
  • "I want to reproduce this state" but manually operating each time is a hassle

snaperro is a mock proxy server that saves API responses as "snapshots" and can replay them anytime.


For Users

Quick Start

# Install
npm install -D snaperro

# Initialize (generates .snaperro/, snaperro.config.ts)
npx snaperro init

# Start server
npx snaperro start

Demo

We provide a demo environment where you can experience snaperro in action.

npx snaperro demo

Your browser will open http://localhost:3333/__snaperro__/demo.

Features You Can Try

Feature Description
Mode Switching Experience the differences between Proxy/Record/Mock modes
Path Parameter Save and return different responses for each ID with /users/:id
Query String Save and return different responses for each query with /posts?userId=1
Nested Resource Fetch nested resources with /posts/:id/comments

For detailed management (scenarios/files/JSON editing), use the GUI (/__snaperro__/client).

Built-in APIs

The following APIs are available without configuration:

API Target Routes
jsonPlaceholder https://jsonplaceholder.typicode.com /users, /posts, /comments, etc.

These are used by the demo page and can be overridden in your config if needed.

Web GUI

Intuitively operate snaperro from your browser.

snaperro GUI

Access

http://localhost:3333/__snaperro__/client

The browser opens automatically when the server starts.

Features

Feature Description
Mode Switch Switch between Proxy/Record/Mock with one click
Scenario Management Create, delete, duplicate, and rename scenarios
File Management List and delete recorded JSON files
JSON Editor View and edit responses
Real-time Updates Instantly reflect state changes via SSE

Configuration File

snaperro.config.ts

import { defineConfig } from 'snaperro'

export default defineConfig({
  port: 3333,

  apis: {
    userService: {
      name: "User Service",
      target: "https://api.example.com",
      headers: {
        "X-Api-Key": process.env.API_KEY!,
      },
      routes: [
        "/api/users",
        "/api/users/:id",
        "/api/users/:id/profile",
      ],
    },

    orderService: {
      name: "Order Service",
      target: "https://order-api.example.com",
      routes: [
        "/api/orders",
        "/api/orders/:id",
        "/api/users/:userId/orders",
      ],
    },
  },
})

.env

# Sensitive information such as API keys
API_KEY=your-api-key-here

Configuration Options

Option Type Description
port number Server port (default: 3333)
filesDir string File storage directory (default: .snaperro/files)
mockFallback string Fallback behavior when mock file is not found (default: "404")
maskRequestHeaders string[] Headers to mask when recording (applied to all APIs)
apis object API definitions object

API Definition

Option Type Required Description
name string Yes API display name
target string Yes Proxy target URL
routes string[] Yes Matching route patterns
headers object No Headers to add
maskRequestHeaders string[] No Headers to mask when recording

Upstream Proxy

If you're behind a corporate proxy, configure upstream proxy settings:

Via config file:

export default defineConfig({
  upstreamProxy: {
    url: "http://proxy.company.com:8080",
  },
  // ...
})

Via environment variable:

export HTTPS_PROXY=http://proxy.company.com:8080
# or with authentication
export HTTPS_PROXY=http://username:[email protected]:8080

Config file takes priority over environment variables.

Important: When using an upstream proxy, add localhost to NO_PROXY to ensure local requests bypass the proxy:

export NO_PROXY=localhost,127.0.0.1

CLI Commands

Command Description
npx snaperro init Initialize project
npx snaperro start Start server
npx snaperro start -p 4000 Start with specified port
npx snaperro demo Start demo environment
npx snaperro postman Export Postman collection

init Process

  1. Create .snaperro/ directory
  2. Create .snaperro/files/ directory
  3. Create snaperro.config.ts template (if it doesn't exist)
  4. Add .snaperro/ to .gitignore

start Options

Option Description
-p, --port <port> Specify port number
-c, --config <path> Specify config file path
-e, --env <path> Specify env file path (default: .env in config directory)
-v, --verbose Show detailed logs

4 Modes

Mode Real API Save JSON Returns
Proxy Access No Real response
Record Access Yes Real response
Mock No access No Saved JSON
Smart Conditional Conditional Mock or Real

Proxy Mode

Connects to the actual API with headers (API Key, etc.) defined in the configuration file.

Request β†’ snaperro β†’ Real API β†’ Response

Record Mode

Connects to the actual API while recording responses to JSON files.

Request β†’ snaperro β†’ Real API β†’ Response
                ↓
           Save to JSON file
  • Same endpoint, same parameters β†’ Overwrite
  • Same endpoint, different parameters β†’ Create new file

Mock Mode

Returns responses from saved JSON files. Does not access the actual API.

Request β†’ snaperro β†’ Search JSON files β†’ Response

Smart Mode

Automatically returns mock data if it exists, otherwise proxies to the real server and records the response.

Request β†’ snaperro β†’ Search mock files
                ↓
         Found? β†’ Yes β†’ Return mock (no API access)
                ↓ No
         Proxy to real API & Record
                ↓
         Return response

This is the recommended mode for daily development:

  • Prevents unnecessary API calls when mock data already exists
  • Automatically records new endpoints
  • Reduces API rate limit concerns

Mock Fallback Behavior

When a mock file is not found, you can configure the fallback behavior with mockFallback:

Value Description
"404" Return 404 error (default)
"proxy" Forward request to real server
"proxy&record" Forward to real server and record the response
export default defineConfig({
  mockFallback: "proxy&record",  // Fallback to proxy and record
  // ...
})

What is a Scenario?

A "scenario" is a folder that manages a set of mock data.

.snaperro/
β”œβ”€β”€ state.json              ← Server state (mode, scenario)
└── files/
    β”œβ”€β”€ normal-full/           ← Scenario "normal-full"
    β”‚   β”œβ”€β”€ api_users_001.json
    β”‚   β”œβ”€β”€ api_users_{id}_001.json
    β”‚   └── api_orders_001.json
    β”œβ”€β”€ empty-data/             ← Scenario "empty-data"
    β”‚   └── api_users_001.json
    └── error-cases/             ← Scenario "error-cases"
        └── api_users_001.json

By switching scenarios, you can use different mock data sets. The previous mode and scenario are restored even after server restart.

Route Definition and Matching

Path Parameters

Define path parameters with :param format.

routes: [
  "/api/users",           // Exact match
  "/api/users/:id",       // :id is a parameter
  "/api/users/:id/orders/:orderId",  // Multiple parameters
]

Matching Examples

routes: ["/api/users/:id"]
Request Match pathParams
/api/users/123 Yes { id: "123" }
/api/users/abc Yes { id: "abc" }
/api/users No -
/api/users/123/profile No -

Record Mode Behavior

  • Same parameter request β†’ Overwrite existing file
  • New parameter request β†’ Create new file

Mock Mode Behavior

  • Return file with exact match of path parameters and query parameters
  • Return 404 error if no matching file

File Structure

your-project/
β”œβ”€β”€ snaperro.config.ts     # Config file (Git managed)
β”œβ”€β”€ .env                   # Sensitive info (Not Git managed)
β”œβ”€β”€ .env.example           # Env template (Git managed)
└── .snaperro/             # Recorded data (Not Git managed)
    β”œβ”€β”€ state.json         # Server state
    └── files/
        β”œβ”€β”€ normal-full/
        β”‚   β”œβ”€β”€ api_users_001.json
        β”‚   └── api_users_{id}_001.json
        └── error-cases/
            └── api_users_001.json

SSE (Server-Sent Events)

An SSE endpoint is provided for GUI and clients to detect state changes in real-time.

Endpoint

GET /__snaperro__/events

Verification

# curl
curl -N http://localhost:3333/__snaperro__/events

# Browser console
const es = new EventSource('http://localhost:3333/__snaperro__/events');
es.addEventListener('connected', (e) => console.log(JSON.parse(e.data)));
es.addEventListener('file_created', (e) => console.log(JSON.parse(e.data)));

Event Types

Event Description
connected Connection complete (includes initial state)
mode_changed Mode changed
scenario_changed Scenario switched
file_created File created (during recording)
file_updated File updated
file_deleted File deleted
scenario_created Scenario created
scenario_deleted Scenario deleted
scenario_renamed Scenario renamed

For Developers

Local Development (Testing CLI without npm publish)

# 1. Install dependencies
pnpm install

# 2. Build
pnpm build

# 3. Run CLI locally
npx . init
npx . start

During development (run directly without build):

npx tsx src/cli/index.ts init
npx tsx src/cli/index.ts start

Development Commands

When you want to:

Goal Command
Watch code changes during development pnpm dev
Build for production pnpm build
Run tests pnpm test
Run tests in watch mode pnpm test:watch
Format code pnpm format
Check type errors pnpm type-check
Develop GUI pnpm dev:client
Build GUI pnpm build:client
Develop demo pnpm dev:demo
Build demo pnpm build:demo

Project Structure

snaperro/
β”œβ”€β”€ cli/                      # CLI commands
β”‚   β”œβ”€β”€ index.ts
β”‚   └── commands/
β”‚       β”œβ”€β”€ init.ts
β”‚       β”œβ”€β”€ postman.ts
β”‚       └── start.ts
β”œβ”€β”€ server/                   # Hono server
β”‚   β”œβ”€β”€ handlers/
β”‚   β”‚   β”œβ”€β”€ handler.ts
β”‚   β”‚   β”œβ”€β”€ proxy.ts
β”‚   β”‚   β”œβ”€β”€ recorder.ts
β”‚   β”‚   β”œβ”€β”€ mocker.ts
β”‚   β”‚   └── control-api.ts
β”‚   β”œβ”€β”€ core/
β”‚   β”‚   β”œβ”€β”€ config.ts
β”‚   β”‚   β”œβ”€β”€ state.ts
β”‚   β”‚   β”œβ”€β”€ storage.ts
β”‚   β”‚   └── matcher.ts
β”‚   └── types/
β”œβ”€β”€ client/                   # React GUI
β”‚   └── src/
β”œβ”€β”€ demo/                     # Demo application
β”‚   └── src/
└── doc/                      # Documentation

Tech Stack

Category Choice
Server Hono
CLI Commander
GUI React + Tailwind CSS
Schema Zod
Logging Consola
Path Matching Picomatch
Build tsup, Vite
Linter/Formatter Biome
Test Vitest

Requirements

  • Node.js 18 or higher
  • tsx must be installed (peerDependencies)

License

MIT

About

πŸ• Record real API responses, replay them anytime. Visual control included.

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages