You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add JSDoc comments throughout the codebase, covering all major classes, functions, and interfaces in `src/server/`, `src/typescript-generator/`, `src/repl/`, and `src/util/`.
Moved `openapi-example.yaml` from the repository root into `test/fixtures/openapi-example.yaml` and expanded it with many OpenAPI edge cases: CRUD operations on `/users` and `/users/{userId}`, polymorphic events via `oneOf`/`allOf`/`discriminator`, nullable fields, enum types, integer formats, file upload via `multipart/form-data`, cookie parameters, deprecated endpoints, multiple response content types, a no-body `204` health-check endpoint, and free-form `additionalProperties` objects.
Replaced the five-minute walkthrough README with a concise, confident two-paragraph introduction. Added ten README variants under `docs/readme-variants/` for the team to review and choose from.
This is a five-minute walkthrough. By the end, you’ll have a **stateful, type-safe, hot-reloading API simulator** running locally—and you’ll understand why it’s different from traditional mock servers.
18
-
19
-
Built for frontend developers, test engineers, and AI agents that need a predictable API to work against.
11
+
You've used mock servers. You know where they stop being useful: static responses, no shared state, no way to inject a failure mid-run, no control without restarting. Counterfact picks up where they leave off.
20
12
21
-
22
-
23
-
## Minute 1 — Start the server
13
+
Point it at an OpenAPI spec and it generates TypeScript handlers for every endpoint—type-safe, hot-reloading, sharing state across routes. A built-in REPL gives you a live control surface: seed data, trigger error conditions, proxy individual routes to a real backend, all on a running server. Whether you're a frontend developer waiting on a backend, a test engineer who needs clean reproducible state, or an AI agent that needs a stable API to work against, Counterfact is the simulator that doesn't plateau.
24
14
25
15
```sh
26
16
npx counterfact@latest https://petstore3.swagger.io/api/v3/openapi.json api
27
17
```
28
18
29
-
> **Requires Node ≥ 22.0.0**
30
-
31
-
That’s it.
32
-
33
-
Counterfact reads your spec, generates a TypeScript handler for every endpoint, and starts a server at `http://localhost:3100`.
34
-
35
-
Open `http://localhost:3100/counterfact/swagger/`.
36
-
37
-
Every endpoint is already live, returning random, schema-valid responses. No code written yet.
Copy file name to clipboardExpand all lines: docs/adr/001-apply-command-with-function-injection.md
+5-5Lines changed: 5 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,4 +1,4 @@
1
-
# ADR 001: .apply Command Design — Minimalist Function Injection
1
+
# ADR 001: .scenario Command Design — Minimalist Function Injection
2
2
3
3
## Status
4
4
@@ -8,7 +8,7 @@ Accepted
8
8
9
9
Counterfact's REPL lets developers interact with the running mock server from the terminal. A common need is to transition the server into a specific state (e.g. "all pets sold", "service unavailable") in a reproducible, shareable way. Today, operators must manually call REPL commands one by one; there is no mechanism to save and replay a named scenario.
10
10
11
-
The `.apply` command is proposed to address this: given a path argument, it loads and executes a user-authored script that mutates REPL context and routes, then reports what changed.
11
+
The `.scenario` command is proposed to address this: given a path argument, it loads and executes a user-authored script that mutates REPL context and routes, then reports what changed.
12
12
13
13
Three designs were proposed as working documents in `.github/issue-proposals/`:
14
14
@@ -27,7 +27,7 @@ Three designs were proposed as working documents in `.github/issue-proposals/`:
27
27
28
28
**Solution 1 (Minimalist Function Injection) is selected.**
29
29
30
-
An apply script is a TypeScript file with one or more named function exports. When `.apply <path>` is run, Counterfact splits the argument on `/`, uses the last segment as the function name and the rest as the file path (relative to `<basePath>/repl/`), dynamically imports the module, and calls the named function with a live `ApplyContext` (`$`) object:
30
+
A scenario script is a TypeScript file with one or more named function exports. When `.scenario <path>` is run, Counterfact splits the argument on `/`, uses the last segment as the function name and the rest as the file path (relative to `<basePath>/repl/`), dynamically imports the module, and calls the named function with a live `ApplyContext` (`$`) object:
31
31
32
32
```ts
33
33
// repl/sold-pets.ts
@@ -55,7 +55,7 @@ Scripts export named functions that receive `$: ApplyContext`. Counterfact resol
55
55
56
56
### Solution 2: Scenario Class with Lifecycle Hooks
57
57
58
-
Scripts export a named class that implements a `Scenario` interface with `setup()` and optional `teardown()` methods. Counterfact instantiates the class, calls `setup()`, and tracks applied instances in a map for later `.unapply`. A static `dependencies` array enables ordered composition.
58
+
Scripts export a named class that implements a `Scenario` interface with `setup()` and optional `teardown()` methods. Counterfact instantiates the class, calls `setup()`, and tracks applied instances in a map for later `.unscenario`. A static `dependencies` array enables ordered composition.
59
59
60
60
**Why not chosen:** Class syntax and lifecycle coupling add complexity that is not justified until the need for teardown and dependency ordering is proven in practice. These concerns can be layered on top of Solution 1 once the basic command exists.
61
61
@@ -81,7 +81,7 @@ Identical surface syntax to Solution 1, but Counterfact wraps `context` and `rou
81
81
82
82
### Risks and downsides
83
83
84
-
- Without lifecycle hooks, accumulated state across many `.apply` calls may be difficult to reason about.
84
+
- Without lifecycle hooks, accumulated state across many `.scenario` calls may be difficult to reason about.
85
85
- If teardown proves to be a common need, adding it later will require extending the API in a backward-compatible way.
86
86
- Proxy-based auto-diffing (Solution 3) remains attractive for DX; deferring it means script authors will need to be disciplined about documenting context changes in the short term.
Copy file name to clipboardExpand all lines: docs/features/repl.md
+7-7Lines changed: 7 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -56,21 +56,21 @@ await req.send()
56
56
57
57
See the [Route Builder guide](./route-builder.md) for full documentation.
58
58
59
-
## Scenario scripts with `.apply`
59
+
## Scenario scripts with `.scenario`
60
60
61
-
For more complex setups you can automate REPL interactions by writing _scenario scripts_ — plain TypeScript files that export named functions. Run them with `.apply`:
61
+
For more complex setups you can automate REPL interactions by writing _scenario scripts_ — plain TypeScript files that export named functions. Run them with `.scenario`:
62
62
63
63
```
64
-
⬣> .apply soldPets
64
+
⬣> .scenario soldPets
65
65
```
66
66
67
-
**Path resolution:** the argument to `.apply` is a slash-separated path. The last segment is the function name; everything before it is the file path, resolved relative to `<basePath>/scenarios/` (with `index.ts` as the default file).
67
+
**Path resolution:** the argument to `.scenario` is a slash-separated path. The last segment is the function name; everything before it is the file path, resolved relative to `<basePath>/scenarios/` (with `index.ts` as the default file).
Counterfact turns an OpenAPI spec into a live, stateful API server you can program in TypeScript. Point it at a spec and every endpoint is immediately live—returning schema-valid responses, sharing state across routes, and hot-reloading when you edit a handler.
12
+
13
+
That's where traditional mock servers stop. Counterfact keeps going. A built-in REPL lets you inspect and manipulate the running server: seed data, trigger failure modes, flip a proxy on or off—without restarting. It's a direct control surface for a running API. It works for frontend developers who can't wait on a backend, for test engineers who need reproducible states, and for AI coding agents that need a programmable, predictable sandbox to iterate in.
14
+
15
+
```sh
16
+
npx counterfact@latest https://petstore3.swagger.io/api/v3/openapi.json api
17
+
```
18
+
19
+
> Requires Node ≥ 22.0.0
20
+
21
+
## Go deeper
22
+
23
+
|||
24
+
|---|---|
25
+
|[Getting started](../getting-started.md)| Detailed walkthrough with state, REPL, and proxy |
26
+
|[Usage](../usage.md)| Feature index: routes, context, REPL, proxy, middleware, and more |
27
+
|[Patterns](../patterns/index.md)| Failures, latency, AI sandboxes, integration tests |
The shift toward AI-assisted development changes what a mock server needs to be. Agents iterate fast, depend on state carrying over between requests, and need to simulate failures and edge cases on demand. Static mocks—fixed responses, no memory, no runtime control—aren't enough anymore.
12
+
13
+
Counterfact is a programmable API simulator built for this moment. It reads an OpenAPI spec and starts a stateful TypeScript server in one command. A built-in REPL lets you—or an agent—control the running system: seed data, trigger failures, proxy individual routes to a real backend. The handlers it generates are type-safe, hot-reloading, and share state across routes. It works equally well for human developers who can't wait on a backend and for AI agents that need a reliable sandbox to reason about.
14
+
15
+
```sh
16
+
npx counterfact@latest https://petstore3.swagger.io/api/v3/openapi.json api
17
+
```
18
+
19
+
> Requires Node ≥ 22.0.0
20
+
21
+
## Go deeper
22
+
23
+
|||
24
+
|---|---|
25
+
|[Getting started](../getting-started.md)| Detailed walkthrough with state, REPL, and proxy |
26
+
|[Usage](../usage.md)| Feature index: routes, context, REPL, proxy, middleware, and more |
27
+
|[Patterns](../patterns/index.md)| Failures, latency, AI sandboxes, integration tests |
0 commit comments