{"id":13454804,"url":"https://github.com/pmcelhaney/counterfact","last_synced_at":"2026-01-16T13:09:11.443Z","repository":{"id":37067521,"uuid":"479515560","full_name":"pmcelhaney/counterfact","owner":"pmcelhaney","description":"OpenAPI / Swagger to TypeScript generator and mock server","archived":false,"fork":false,"pushed_at":"2026-01-13T20:25:35.000Z","size":7845,"stargazers_count":132,"open_issues_count":28,"forks_count":17,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-01-13T20:34:07.033Z","etag":null,"topics":["front-end-development","mock-server","openapi","openapi3","swagger","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pmcelhaney.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"License.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-04-08T19:32:15.000Z","updated_at":"2026-01-13T19:56:21.000Z","dependencies_parsed_at":"2026-01-06T17:09:28.505Z","dependency_job_id":null,"html_url":"https://github.com/pmcelhaney/counterfact","commit_stats":{"total_commits":654,"total_committers":10,"mean_commits":65.4,"dds":"0.25688073394495414","last_synced_commit":"2773a2fa084ec5e5f86c5fe3004734cbdb5f5356"},"previous_names":[],"tags_count":111,"template":false,"template_full_name":null,"purl":"pkg:github/pmcelhaney/counterfact","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmcelhaney%2Fcounterfact","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmcelhaney%2Fcounterfact/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmcelhaney%2Fcounterfact/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmcelhaney%2Fcounterfact/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pmcelhaney","download_url":"https://codeload.github.com/pmcelhaney/counterfact/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmcelhaney%2Fcounterfact/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28478936,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["front-end-development","mock-server","openapi","openapi3","swagger","typescript"],"created_at":"2024-07-31T08:00:58.081Z","updated_at":"2026-01-16T13:09:11.436Z","avatar_url":"https://github.com/pmcelhaney.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003cdiv align=\"center\" markdown=\"1\"\u003e\n\n\u003cimg src=\"./counterfact.svg\" alt=\"Counterfact\" border=0\u003e\n\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\n\u003c/div\u003e\n\n**Spin up a mock server instantly. No config, no fuss. Try it now:**\n\n```sh copy\nnpx counterfact@latest https://petstore3.swagger.io/api/v3/openapi.json mock-api\n```\n\nThis command reads an OpenAPI spec (the [Swagger Petstore](https://petstore.swagger.io)), generates TypeScript code for a mock server in `mock-api`, and starts the server.\n\n\u003cdetails\u003e\n\u003csummary\u003eExample of generated code\u003c/summary\u003e\n\n```ts\n// ./mock-api/routes/store/order/{orderID}.ts\nimport type { HTTP_GET } from \"../../../types/paths/store/order/{orderId}.types.js\";\nimport type { HTTP_DELETE } from \"../../../types/paths/store/order/{orderId}.types.js\";\n\nexport const GET: HTTP_GET = ($) =\u003e {\n  return $.response[200].random();\n};\n\nexport const DELETE: HTTP_DELETE = ($) =\u003e {\n  return $.response[200];\n};\n```\n\n\u003c/details\u003e\n\nWant control? Edit the generated route files (e.g. `./mock-api/routes/store/order/{orderID}.ts`) and define responses directly. A type-safe API from your spec speeds up prototyping.\n\n\u003cdetails\u003e\n\u003csummary\u003eEdit the code to define custom behavior and responses\u003c/summary\u003e\n\n```ts\n// ./mock-api/routes/store/order/{orderID}.ts\nimport { Order } from \"../../../types/components/schemas/Order.js\";\nimport type { HTTP_GET } from \"../../../types/paths/store/order/{orderId}.types.js\";\nimport type { HTTP_DELETE } from \"../../../types/paths/store/order/{orderId}.types.js\";\n\nexport const GET: HTTP_GET = ($) =\u003e {\n  const orders: Record\u003cnumber, Order\u003e = {\n    1: {\n      petId: 100,\n      status: \"placed\",\n    },\n    2: {\n      petId: 999,\n      status: \"approved\",\n    },\n    3: {\n      petId: 1234,\n      status: \"delivered\",\n    },\n  };\n\n  const order = orders[$.request.orderID];\n\n  if (order === undefined) {\n    return $.response[404];\n  }\n\n  return $.response[200].json(order);\n};\n\nexport const DELETE: HTTP_DELETE = ($) =\u003e {\n  return $.response[200];\n};\n```\n\n\u003c/details\u003e\n\nYou can also **proxy some paths to the real API** while mocking others — perfect when part of the backend isn’t finished or you need to simulate tricky scenarios. See [Proxying](./docs/usage.md#proxying-to-a-real-api) for details.\n\nUse `npx counterfact --help` to view CLI flags for customizing behavior (e.g. `--port`, `--proxy`, `--watch`).\n\nGo further with stateful mocks: POST data, then GET it back. Tweak backend data live with a REPL. Update code without restarting the server or losing state.\n\nWe believe strongly in API-first development and the Dependency Inversion Principle. When frontend and backend implement the same API spec, they can be built and tested independently. Most of the time, it’s best to test the front end against the real API and full stack. But there's always some part of the backend that isn't finished yet, or a scenario that's cumbersome to reproduce. For this reason, Counterfact supports proxying to the real API for some paths and using mocks for others.\n\nCounterfact was by built an engineer who spent decades writing frontend code and got tired of being slowed down by unfinished or unwieldy backend APIs. This is the fastest way to get unblocked, prototype ideas, and remember what it feels like to enjoy creating stuff.\n\n\u003e Requires Node ≥ 17.0.0\n\n\u003cdiv align=\"center\" markdown=\"1\"\u003e\n\n[Documentation](./docs/usage.md) | [Changelog](./CHANGELOG.md) | [Contributing](./CONTRIBUTING.md)\n\n\u003c/div\u003e\n\n\u003cbr\u003e\n\u003cdiv align=\"center\"  markdown=\"1\"\u003e\n\n![MIT License](https://img.shields.io/badge/license-MIT-blue) [![TypeScript](./typescript-badge.png)](https://github.com/ellerbrock/typescript-badges/) [![Coverage Status](https://coveralls.io/repos/github/pmcelhaney/counterfact/badge.svg)](https://coveralls.io/github/pmcelhaney/counterfact)\n\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmcelhaney%2Fcounterfact","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpmcelhaney%2Fcounterfact","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmcelhaney%2Fcounterfact/lists"}