Releases: counterfact/api-simulator
v2.14.0
Minor Changes
- ddfa05f: export the types from the package so that clients can import { couterfact } from "counterfact"
Patch Changes
- 42d5660: Updated dependency
@swc/coreto1.15.40. - 3ec43b8: Updated dependency
astroto6.3.8. - d9e1130: Updated dependency
posthog-nodeto5.35.3. - b896d80: Updated dependency
@typescript-eslint/eslint-pluginto8.60.0.
Updated dependency@typescript-eslint/parserto8.60.0. - 15e6503: Updated dependency
posthog-nodeto5.35.0. - f740c2a: Updated dependency
koato3.2.1. - a46fcdf: Updated dependency
astroto6.3.7. - d0b1616: Updated dependency
json-schema-fakerto0.6.2. - bb1b4d5: Updated dependency
posthog-nodeto5.35.1. - 2c04e5d: Updated dependency
posthog-nodeto5.35.4. - 4eb0314: Updated dependency
posthog-nodeto5.35.2. - ffbde4b: Updated dependency
posthog-nodeto5.34.7. - 1261a8f: Updated dependency
posthog-nodeto5.34.8. - 5a5206e: Updated dependency
posthog-nodeto5.35.5.
v2.12.0
Minor Changes
-
3502d41: Add native support for the
QUERYHTTP method (OpenAPI 3.2). TheQUERYmethod is safe and idempotent but allows a request body, making it useful for complex search and filter operations.HttpMethodsinsrc/server/registry.tsnow includes"QUERY".- The
Moduleinterface exposes aQUERYhandler that receives a request body. HTTP_METHODSinsrc/migrate/update-route-types.tsnow includes"QUERY"so the migration helper recognisesHTTP_QUERYtype imports.- The MSW integration's
allowedMethodslist now includes"query". - The Koa middleware already passes the request body for any method that is not
GETorHEAD, soQUERYrequests forward their body to the handler automatically.
-
5aa3326: Add support for OpenAPI 3.2
querystringparameter location: generates a typed$.querystringproperty on the route handler argument and populates it at runtime with the full parsed query string -
8e15211: Add support for OpenAPI 3.2 streaming responses and Server-Sent Events (SSE) via
itemSchema.SchemaTypeCodernow recognisesitemSchemain a schema object and emitsAsyncIterable<T>.ResponseTypeCoderandOperationTypeCoderdetectitemSchemaon streaming content types (text/event-stream,application/jsonl,application/x-ndjson,application/ndjson,application/json-seq) and emitAsyncIterable<T>as the body type instead of a plain schema type.CounterfactResponseObject.bodynow acceptsAsyncIterable<unknown>in addition toUint8Array | string.- The response builder (
$.response[200].stream(iterable, contentType?)) exposes astream()helper that returns a response with the async iterable as the body. The content type defaults totext/event-stream. routes-middlewareconvertsAsyncIterableresponse bodies into Node.jsReadablestreams, serialising each item in the appropriate wire format:text/event-stream→data: <json>\n\napplication/json-seq→\x1e<json>\n- everything else (JSONL / ndjson) →
<json>\n
- SSE responses also receive
Cache-Control: no-cacheandX-Accel-Buffering: noheaders automatically. - The JSON-serialisation middleware in
create-koa-appnow skips Node.jsReadablestream bodies so they are piped directly to the client.
-
1329973: Support OpenAPI 3.2
xml.nodeTypefield in JSON-to-XML serialisation.nodeType: "attribute"serialises the value as an XML attribute.nodeType: "text"serialises the value as an XML text node (no child element wrapper).nodeType: "cdata"serialises the value as a CDATA section.nodeType: "none"omits the property from the XML output entirely.nodeType: "element"wraps the value in a child element (default behaviour); for arrays it is a synonym for the deprecatedxml.wrapped: true.- The deprecated
xml.attribute: truecontinues to behave identically tonodeType: "attribute". - The deprecated
xml.wrapped: truecontinues to behave identically tonodeType: "element"for arrays.
Patch Changes
-
1302457: Add regression tests confirming that
$refreferences to#/components/mediaTypes/...entries (OpenAPI 3.2) are resolved correctly during bundling and code generation.specification.test.tsnow includes two tests: one that navigates to acomponents/mediaTypesentry viagetRequirement, and one that verifies transparent$reffollowing through such an entry.generate.test.tsnow includes two end-to-end tests: one that verifies code generation completes without error for a spec using a$refto a media type component, and one that verifies the generated TypeScript types include the correct schema from the referenced media type.
-
7bbcf63: OpenAPI 3.2: include
discriminator.defaultMappingschema in generated union types foranyOf/oneOfschemas -
63dd7b2: Add privacy-preserving telemetry for startup options, file-change categories, and REPL command usage.
-
fda8f18: Add "Multiple API Versions" pattern to docs/patterns/. The new page explains how to configure multiple versioned specs and use
$.minVersion()to share route handlers across versions without duplication.Also rewrites the patterns index introduction: the single long paragraph is now split into labelled sections (Getting started, Organizing state, Runtime control, Versioned and multi-spec APIs, Long-term reliability, Integration strategies) followed by a complete pattern table.
-
1a868ba: Document support for Swagger 2.0 and OpenAPI 3.0, 3.1, and 3.2 in the README and getting started docs.
-
16f890f: Prefer
dataValueovervaluein OpenAPI 3.2 Example ObjectsWhen building example responses, Counterfact now checks for the
dataValue
field (introduced in OpenAPI 3.2) and uses it in preference to the existing
valuefield. IfdataValueis absent, the existingvaluefield is used as
before, maintaining full backward compatibility with OpenAPI 3.0 and 3.1 specs. -
b024920: Add regression tests verifying that OpenAPI 3.2
$selfdocument-identity field is preserved through bundling and that relative$refvalues in specs with$selfresolve correctly. CoversSpecification.fromFile(), the OpenAPI middleware, and end-to-end code generation. -
0cb8959: Support OpenAPI 3.2 additionalOperations generation and runtime routing for custom HTTP methods.
-
424fbf0: Remove patch-package dependency and postinstall script. The patches for http-proxy and tsutils are no longer needed since those packages are no longer direct dependencies. Removing the postinstall script also eliminates a potential security concern with pnpm's strictDepBuilds setting.
-
a6dc7e8: Updated dependency
precinctto12.3.1. -
b435371: Updated dependency
@jest/globalsto30.4.0.
Updated dependencyjestto30.4.0. -
fd5914c: Updated dependency
@swc/coreto1.15.33. -
da1de4b: Updated dependency
posthog-nodeto5.33.7. -
a71e047: Updated dependency
@apidevtools/json-schema-ref-parserto15.3.1. -
4224be0: Updated dependency
@swc/coreto1.15.32. -
eed59b8: Updated dependency
astroto^6.0.0. -
01ff516: Updated dependency
precinctto12.3.2. -
f282f46: Updated dependency
@typescript-eslint/eslint-pluginto8.59.3.
Updated dependency@typescript-eslint/parserto8.59.3. -
e88e792: Updated dependency
@jest/globalsto30.3.0.
Updated dependency@types/debugto4.1.12.
Updated dependency@typescript-eslint/eslint-pluginto8.58.0.
Updated dependency@typescript-eslint/parserto8.58.0.
Updated dependencyeslint-plugin-nto17.24.0.
Updated dependencyeslint-plugin-promiseto7.2.1.
Updated dependencyeslint-plugin-regexpto3.0.0.
Updated dependencyeslint-plugin-securityto4.0.0.
Updated dependencyposthog-nodeto5.28.11.
Updated dependencytsxto4.21.0. -
3a312a1: Updated dependency
eslint-plugin-nto18.0.1. -
ca7c067: Updated dependency
@typescript-eslint/eslint-pluginto8.59.1.
Updated dependency@typescript-eslint/parserto8.59.1. -
c08ddca: Updated dependency
posthog-nodeto5.34.0. -
68b730f: Updated dependency
json-schema-fakerto0.6.1. -
15b4c1b: Updated dependency
typescriptto6.0.3. -
ae5328c: Updated dependency
posthog-nodeto5.33.4. -
96e36c5: Updated dependency
astroto6.3.1.
Updated dependencylinkinatorto7.6.1. -
7379948: Updated dependency
astroto^6.3.0. -
dd4e758: Updated dependency
prettierto3.8.3. -
10148fd: Updated dependency
posthog-nodeto5.33.3. -
d8258a9: Updated dependency
eslint-plugin-jestto29.15.2. -
7a38b14: Updated dependency
@types/debugto4.1.13. -
7b937f7: Updated dependency
@jest/globalsto30.4.1.
Updated dependencyjestto30.4.1. -
47d07e4: Updated dependency
@changesets/clito2.31.0. -
1516af8: Updated dependency
jestto30.4.2. -
ba32e07: Updated dependency
posthog-nodeto5.34.1. -
6d582b4: Updated dependency
eslintto10.3.0. -
89d4554: Updated dependency
fs-extrato11.3.5. -
1a51c4f: Updated dependency
@typescript-eslint/eslint-pluginto8.59.2.
Updated dependency@typescript-eslint/parserto8.59.2. -
e1bad83: Updated dependency
eslint-plugin-regexpto3.1.0. -
b459631: Set
name: "Counterfact"on the injected server entry in the served OpenAPI document. OpenAPI 3.2-aware tools (e.g. Swagger UI) use thenamefield as the primary label for a server entry in the server selector. -
35abb32: Upgrade
@apidevtools/json-schema-ref-parserfrom 15.1.3 to 15.3.5. The new version includes a built-in fix for Windows paths using forward slashes (C:/...), making thepatch-packagepatch unnecessary.
v2.11.0
Minor Changes
-
6c383c9: Admin API is now disabled by default. Use the
--admin-apiflag to opt in. -
a58241f: generator: emit
types/versions.tswithVersions,VersionsGTE, andVersionedtypesWhen at least one
SpecConfigentry has a non-emptyversionfield, the code generator now writestypes/versions.tsto thebasePathroot. The file exports:Versions— a union of all distinct version strings in config-declaration orderVersionsGTE— a map from each version to the set of versions that are >= itVersioned<T, V>— a utility type that narrows the$argument of a route handler to a specific API version
Versionedis also exported fromcounterfact-types/index.tsin its generic form (with explicitTVersionsandTVersionsGTEtype parameters) for use outside of the generated file.No file is written when no spec defines a
version. -
4bb9493: Add runtime implementation of
$.minVersion()for versioned route handlers.When multiple versioned specs share the same API group, each request's
$
argument now includes:version— a string identifying which version is handling the request
(e.g."v1","v2").minVersion(min)— a method that returnstruewhen the current version
is greater than or equal tominin the declared version order, and
falseotherwise.
The version order is determined by the position of each spec in the
specs
array passed tocounterfact()(first entry = oldest version).For unversioned runners (
versionis not set), neitherversionnor
minVersionis present on$. -
af44d5b:
OperationTypeCodernow emits version-mapped handler types for multi-version APIs.When two or more versioned specs share the same operation path, the shared
types/paths/<path>.types.tsfile exports a mergedHTTP_<METHOD>type
whose$argument isVersioned<{ v1: …; v2: … }>(a union of each
version's strongly-typed argument object). Each version's$-argument type
is emitted totypes/<version>/paths/<path>.types.tsand imported by the
shared file.Single-spec (unversioned) output is unchanged for full backwards compatibility.
A new
Versioned<T>utility type is exported fromcounterfact-types/index.js. -
142bcdd: When a
SpecConfigentry declares bothgroupandversion, the server now automatically mounts that spec's routes under/<group>/<version>without requiring an explicitprefix.The derivation rules are:
prefixprovided?groupset?versionset?Derived prefix Yes any any use the explicit prefix No Yes Yes /<group>/<version>No Yes No /<group>No No No ""(root)Two specs with the same
groupbut differentversionvalues can coexist on a single server instance — validation now checks uniqueness on the(group, version)pair instead ofgroupalone.Migration note:
SpecConfig.prefixis now an optional field (prefix?: string). Specs that omitprefixwill have it derived automatically; pass an explicitprefix: ""to force the root prefix.
Patch Changes
-
825b65d: Cast parameters at runtime: parameters defined with OAS3-style schema types (e.g.
schema: { type: "integer" }) are now correctly cast to their declared JavaScript types in route handlers. For example, whenGET /pet/1is called,$.path.petIdwill be a number rather than a string when the OpenAPI spec declares it asinteger. -
161deca: Fix documentation inconsistencies: complete CLI reference table, correct programmatic API example in FAQ, fix invalid JS syntax and broken link in without-openapi guide, and fix formatting in programmatic-api guide.
-
6d19132: Fix TypeScript error caused by combining a mapped type and explicit properties in the same generated response object type.
When an OpenAPI spec defines a
defaultresponse alongside explicit status codes (e.g.200,400), the generatedResponseBuilderFactorytype argument now uses an intersection ({ 200: ..., 400: ... } & { [statusCode in Exclude<HttpStatusCode, 200 | 400>]: ... }) instead of mixing both in a single object literal, which TypeScript does not allow. -
ee38734: Fix: parameters defined at the path item level in an OpenAPI spec are now included in generated TypeScript types.
Previously, parameters declared under a path item (e.g.
/stuff/{stuffId}: parameters: [...]) were ignored during type generation, causing the route handler'spath(and other) argument types to benever. Now those path-item-level parameters are merged with any operation-level parameters (operation-level takes precedence when both declare the same name and location), producing the correct strongly-typed handler signatures. -
3e0fbc1: Telemetry is now always enabled (removed the pre-May-2026 date gate)
-
bce607e: Update usage link in REPL and CLI banner to point to the new GitHub docs URL.
-
dd4abb8: Generated
$-arg types now include aversionproperty. For versioned specs the property is a string literal (e.g.version: "v3"); for unversioned specs it isnever(omitted at runtime byOmitValueWhenNever).
v2.10.0
Minor Changes
- 43b0e34: The type system no longer allows responses constructed without $.response
Patch Changes
- 68b2c8f: Fix: query parameters of type object with exploded form style (the OpenAPI default) are now properly supported. The request validator no longer falsely reports required object parameters as missing when their properties are sent as individual query params (e.g.
?page=0&size=100). The handler receives the object assembled under the parameter name ($.query.pageable) rather than only the flat individual keys.
v2.9.0
Minor Changes
-
ffc7d53: Add
ApiRunnerclass insrc/api-runner.tsthat encapsulates the creation and lifecycle management of all Counterfact sub-systems (Registry, ContextRegistry, ScenarioRegistry, ScenarioFileGenerator, CodeGenerator, Dispatcher, Transpiler, ModuleLoader, and OpenApiDocument) for a single API specification.Each sub-system is exposed as a public property. The class provides four composite methods —
generate(),load(),watch(), andstopWatching()— that coordinate across multiple sub-systems based on the supplied configuration. Use the static asyncApiRunner.create(config)factory method to construct an instance.counterfact()inapp.tsnow usesApiRunnerinternally. -
a6bb5bc: Add support for multiple API specifications via
ApiRunner.ApiRunner.create(config, group?)now accepts an optionalgroupstring (default"") that places generated code in a subdirectory ofconfig.basePath.ApiRunnerexposesgroupas a public readonly property andsubdirectoryas a computed getter (returns""when group is empty, or"/${group}").CodeGeneratorreceivesconfig.basePath + runner.subdirectoryso each spec's generated files land in the right subdirectory.createKoaAppnow acceptsrunners: ApiRunner[](an array) instead of a singlerunner. It loops over all runners to mount per-spec OpenAPI document, Swagger UI, Admin API, and route-dispatching middleware.counterfact()accepts an optionalspecs: SpecConfig[]second argument (each entry hassource,prefix, andgroup). When omitted, a single spec is derived fromconfig.openApiPathandconfig.prefixfor full backward compatibility. The REPL is configured using the first spec's runner.- The
speckey incounterfact.yamlcan now be a single{source, prefix, group}object or an array of such objects to configure multiple APIs from the config file.
-
26e00eb: Add
openApiPathandprefixas public readonly properties onApiRunner.Refactor
createKoaAppto acceptrunner: ApiRunner(providing the dispatcher, registry, context registry, OpenAPI path, and route prefix) instead of aconfig: Configmonolith plus separate sub-system refs. All other config fields used bycreateKoaAppare now explicit named arguments, laying the groundwork for passing multiple runners tocreateKoaAppin the future.
Patch Changes
- aa23b79: Support
.scenario <group> <path>in multi-API REPL sessions while preserving single-runner syntax. - d0dff90: Warn and skip loading context modules when they fail to import, including syntax errors in _.context files.
- 75938e3: Prefer OpenAPI route paths for REPL tab completion and refactor completer lookups into focused helpers.
- 7a8c0b6: Move MSW (Mock Service Worker) code out of
app.tsinto a dedicatedsrc/msw.tsmodule. TheMockRequesttype,handleMswRequest, andcreateMswHandlersare still re-exported fromapp.tsfor backward compatibility. Tests for these functions have been moved totest/msw.test.ts. - 4894f18: Organized Koa middleware into a dedicated
src/server/web-server/directory. Each middleware constructor now takes its path prefix as the first argument, makingcreateKoaAppeasier to read at a glance.openapiMiddlewaresimplified to handle a single path only. - 3aa8416: Expose grouped REPL context and routes for multi-API runners, and require non-empty unique group names when configuring multiple APIs.
- b270516: Move CLI logic from bin/counterfact.js into src/cli/ as TypeScript modules
- a3d16ab: Update REPL
.scenariotab completion to suggest groups first in multi-API mode and group-scoped scenarios after selection.
v2.8.1
v2.6.0
Minor Changes
-
3b0334a: Add JSDoc comment generation for types from OpenAPI metadata
Generated TypeScript types now include inline JSDoc comments derived from the OpenAPI spec:
- Schema-level JSDoc from
description/summary - Property-level JSDoc including
description,@example,@default,@format, and@deprecated - Operation-level JSDoc from operation
summary/description
This improves IDE hover documentation and AI-assisted development workflows.
- Schema-level JSDoc from
-
a3b24f0: Add request validation against the OpenAPI spec. Incoming requests are now validated by default — missing required query parameters, missing required headers, and request bodies that do not match the declared schema all result in a 400 response with a descriptive error message. Validation can be disabled with the
--no-validate-requestCLI flag. -
3c5c284: Add lightweight telemetry using PostHog to track usage of Counterfact. Fires a single
counterfact_startedevent on startup. Telemetry is disabled by default before May 1, 2026, disabled in CI, and can be controlled with theCOUNTERFACT_TELEMETRY_DISABLEDenvironment variable. A one-time warning is shown before the rollout date. -
6c9e30f: Add REPL-native request builder (
route()) with fluent API, OpenAPI introspection, and autocomplete support.The new
route()function is available in the REPL and allows users to discover, construct, and execute API requests interactively:const pet = route("/pet/{petId}").method("get").path({ petId: 1 }); await pet.send();
Key capabilities:
- Fluent, immutable builder API (
.method(),.path(),.query(),.headers(),.body()) - OpenAPI-backed introspection via
.help(),.ready(), and.missing() - Actionable feedback when required parameters are absent
- Custom REPL display showing parameter status
- Autocomplete for
route("in addition to existingclient.*patterns
- Fluent, immutable builder API (
Patch Changes
- 7a89d27: Refactor internal plain objects to Maps where appropriate:
Directory.directoriesandDirectory.filesinmodule-tree.tsare nowMap<string, Directory>andMap<string, File>ParameterTypesinner types indispatcher.tsare nowMap<string, string>castParametersinregistry.tsnow acceptsMap<string, string>for parameter types
- 5b7d8b3: Improve error messages for malformed or missing OpenAPI specs. Instead of showing a JavaScript stack trace, Counterfact now displays a clear, actionable message that includes the spec path and the underlying reason for the failure.
- ff2ba80: Auto-detect TypeScript native runtime support (tsx, ts-node, node --experimental-strip-types) instead of requiring a --use-tsx flag
v2.5.1
v2.5.0
Minor Changes
- f440a20: Display the current version on startup and warn when a newer version is available on npm. The version check runs non-blocking in the background after the server starts, and can be suppressed with
--no-update-checkor by setting theCIenvironment variable.
Patch Changes
- cdb4c42: Fix import path in generated route handler files when the OpenAPI path contains a colon (e.g.
/stuff:action). Previously, the import statement used a literal:but the type file was written to disk with the Unicode ratio symbol∶(U+2236), causing TypeScript to fail to resolve the type and fall back toany. - eb65932: Fix
Access-Control-Allow-MethodsCORS header to reflect only the HTTP methods actually implemented by the route handler, instead of hardcodingGET,HEAD,PUT,POST,DELETE,PATCHfor every route. - d522f6f: Fix crash when a route file is deleted while the server is running. Previously, the file-watch handler would attempt to re-import the deleted file after removing it from the registry, causing a
TypeError. Now the handler returns immediately after processing theunlinkevent. - d306720: Fix crash when a route file has a syntax error. Previously, Counterfact would crash with an unhandled promise rejection when a CommonJS route file had a syntax error. Now the server stays running and requests to that route return a 500 response with a message indicating which file has the error.
- 6ca6998: Fix request body parsing:
RawHttpClientnow automatically setsContent-Type: application/jsonwhen the body is an object, so$.bodyis populated correctly in route handlers. - df8abcf: Fix TypeError when a response content entry has no schema defined. Previously, the TypeScript type generator would crash with
TypeError: Cannot read properties of undefined (reading 'data')and emit an empty error comment type. Now it gracefully falls back tounknownfor the body type. - 37dec24: Updated dependency
koato3.2.0. - a1973c7: Updated dependency
lodashto4.18.1.
v2.4.0
Minor Changes
-
cb931d6: When multiple wildcard route handlers exist at the same path level (e.g.
/{x}and/{y}as siblings), Counterfact now:- Logs an error to stderr at load time listing the conflicting wildcard names.
- Returns an HTTP 500 response when a request could be routed to two or more handlers due to the ambiguity.
-
0a3039b: Add support for binary data in responses. Route handlers can now return binary content using the new
binary()method on the response builder, which accepts aBufferor a base64-encoded string. OpenAPI schemas withformat: "binary"(v3) ortype: "file"(v2) now generateBuffer | stringTypeScript types. -
d53f4c3: Break REPL out of
counterfact()and expose it as a callablestartRepl()on the returned object. This enables programmatic usage (e.g. from Playwright tests) without automatically starting an interactive terminal session.import { counterfact } from "counterfact"; const { contextRegistry, start, startRepl } = await counterfact(config); await start(config); // Manipulate server state directly from test code: const rootContext = contextRegistry.find("/"); rootContext.passwordResponse = "expired";
The CLI (
bin/counterfact.js) now explicitly callsstartRepl()when--replis passed, preserving existing behaviour. -
861c4db: Add route autocomplete to REPL for
client.<method>("...")patterns.When typing
client.get("/pin the REPL and pressing Tab, the REPL now suggests available routes (e.g./pets,/pets/{petId}) derived from the route registry.This works for all HTTP methods:
get,post,put,patch, anddelete. -
1e4d5cf: Add chainable
$.response.cookie()helper for setting response cookies.Route handlers can now set one or more cookies without manually building
Set-Cookieheader strings:return $.response[200] .cookie("sessionId", "abc123", { httpOnly: true, secure: true, sameSite: "lax", path: "/", maxAge: 3600, }) .cookie("theme", "dark") .json({ ok: true });
Supported options:
path,domain,maxAge,expires,httpOnly,secure,sameSite.
Patch Changes
-
578faab: Fix REPL tab completion for built-in Node.js completions (e.g.
context.<Tab>).The custom route completer previously replaced Node's built-in REPL completer entirely, breaking property completion for objects like
contextandclient. The completer now delegates to the built-in completer when the input doesn't match theclient.<method>("...")pattern. -
76d3103: Updated dependency
json-schema-fakerto0.6.0. -
4229034: Updated dependency
eslintto10.0.3. -
635071c: Updated dependency
eslint-plugin-jestto29.15.1. -
ff36c53: Updated dependency
handlebarsto4.7.9. -
9e2b147: Updated dependency
typescriptto6.0.2. -
7f9ce73: Updated dependency
@swc/coreto1.15.21. -
a7a56a2: Updated dependency
eslintto10.1.0.