Skip to content

v0.0.1: vite-plugin-httptape — record/replay HTTP for Vite dev servers #1

@tibtof

Description

@tibtof

Problem

A TS developer with a new Vite project wants httptape as their dev backend proxy — record once, replay deterministically, edit JSON fixtures by hand. Today the only path (in httptape/httptape's examples/ts-frontend-first) is docker-compose with three services, requires Docker, and lives outside vite.config.ts. Not competitive with Vite's native DX.

User story

As a TS developer with a Vite project, I want to add httptape() to my vite.config.ts plugins array so that during vite dev my API calls are transparently proxied through httptape — recorded on first hit, replayed from local JSON fixtures on subsequent runs, with secrets redacted before they hit disk.

Public API (the whole surface for v0.0.1)

```ts
import { defineConfig } from 'vite'
import httptape from 'vite-plugin-httptape'

export default defineConfig({
plugins: [
httptape({
upstream: 'https://api.example.com', // required when mode: 'proxy'
fixtures: './mocks', // default: './mocks'
sanitize: './sanitize.json', // default: undefined (no sanitization)
mode: 'proxy', // 'proxy' | 'serve' — default: 'proxy'
route: '/api', // Vite server.proxy key — default: '/api'
port: 0, // 0 = pick free port — default: 0
}),
],
})
```

That's the whole surface — six options, CORS hardcoded on, no DSL.

What the plugin does

  1. On `vite dev` start: spawn the httptape binary with the right CLI flags as a child process. If `port: 0`, picks a free port first via `net.createServer().listen(0)`.
  2. Wires `vite.config.server.proxy[route]` so requests forward to the local httptape port.
  3. Pipes httptape's stdout/stderr through Vite's logger with a `[httptape]` prefix.
  4. On `vite dev` stop (SIGINT, file-triggered restart, etc.): graceful shutdown of the httptape child (SIGTERM with 3s grace, then SIGKILL).
  5. `mode: 'serve'` swaps `httptape proxy` for `httptape serve` (no upstream needed) — frontend-first dev when there's no backend yet.

Out of scope for v0.0.1

  • Recording control (always records on miss in proxy mode; no per-route opt-out)
  • Hot-reload of `sanitize.json` (Vite restart picks it up)
  • `freeze: true` / replay-only mode (punted to v0.0.2)
  • Multiple upstreams (one plugin instance, one upstream)
  • Testcontainers-style usage from Vitest tests (separate package later)
  • Next.js / Remix / webpack integrations (separate packages later)

Acceptance criteria

  • `pnpm i -D vite-plugin-httptape` on macOS arm64, macOS x64, Linux x64, Linux arm64, Windows x64 installs and the correct platform binary lands in `node_modules`
  • Adding the plugin to `vite.config.ts` with only `upstream` set works against a real public API (e.g. `https://api.github.com\`) — first request records, second replays from `./mocks/`
  • `mode: 'serve'` works against a `./mocks/` directory of hand-written fixtures (no upstream reachable)
  • `Ctrl-C` on `vite dev` cleanly stops both Vite and the httptape child (no orphan processes)
  • `httptape` logs prefix correctly in Vite's terminal output
  • `examples/ts-frontend-first` in `httptape/httptape` converted to use the plugin — docker-compose deleted, one-line config in `vite.config.ts`, all behavior preserved (separate PR after this lands)
  • README with copy-pasteable quick-start (under 30 lines of config)

Validation gate

v0.0.1 is not published to npm until the converted `examples/ts-frontend-first` demo runs cleanly and the dev-server lifecycle is verified by hand. Same gating pattern as `httptape-jvm`.

Status

READY_FOR_DEV — see first comment for ADR-1 (architectural design).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions