Repository: pmcelhaney/counterfact
Pull request #220 (2022-09-27 23:54:30)

put response-builder-factory.ts in the generated code so Counterfact doesn't depend on itself


Patch:
diff --git a/.changeset/beige-ducks-tan.md b/.changeset/beige-ducks-tan.md
new file mode 100644
index 0000000..c458442
--- /dev/null
+++ b/.changeset/beige-ducks-tan.md
@@ -0,0 +1,5 @@
+---
+"counterfact": patch
+---
+
+fix so that Counterfact no longer depends on itself
diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index 3ca591c..30e7460 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -36,14 +36,7 @@ const rules = {
 };
 
 module.exports = {
-  ignorePatterns: [
-    "/node_modules/",
-    "/coverage/",
-    "/reports/",
-    "/demo-ts",
-    "/templates/",
-    "/out/",
-  ],
+  ignorePatterns: ["/node_modules/", "/coverage/", "/reports/", "/out/"],
 
   extends: ["hardcore", "hardcore/ts", "hardcore/node"],
 
diff --git a/package.json b/package.json
index 7df5e26..66f63a0 100644
--- a/package.json
+++ b/package.json
@@ -60,7 +60,6 @@
     "@types/json-schema": "^7.0.11",
     "chokidar": "^3.5.3",
     "commander": "^9.4.0",
-    "counterfact": "*",
     "fs-extra": "^10.1.0",
     "js-yaml": "^4.1.0",
     "json-schema-faker": "^0.5.0-rcv.44",
diff --git a/src/counterfact.d.ts b/src/counterfact.d.ts
deleted file mode 100644
index 8b79efd..0000000
--- a/src/counterfact.d.ts
+++ /dev/null
@@ -1,144 +0,0 @@
-export type HttpStatusCode = 100 | 101 | 102 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 226 | 300 | 301 | 302 | 303 | 304 | 305 | 307 | 308 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 422 | 423 | 424 | 426 | 428 | 429 | 431 | 451 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 511;
-
-type StatusCodeWithDescription = `${number}${string}`;
-
-type OpenApiHeader = {
-  schema: unknown;
-};
-
-type OpenApiContent = {
-  schema: unknown;
-};
-
-type OmitValueWhenNever<Base> = Pick<
-  Base,
-  {
-    [Key in keyof Base]: [Base[Key]] extends [never] ? never : Key;
-  }[keyof Base]
->;
-
-type OpenApiResponse = {
-  headers: Record<string, OpenApiHeader>;
-  content: Record<MediaType, OpenApiContent>;
-};
-
-type OpenApiResponses = Record<string, OpenApiResponse>;
-
-type MediaType = `${string}/${string}`;
-
-type CounterfactResponse = {
-  status: number;
-  headers: Record<string, string | number>;
-  content: Array<{ type: MediaType; body: unknown }>;
-  isCounterfactResponse: true;
-};
-
-type IfHasKey<R, Key, Yes, No> = Key extends keyof R ? Yes : No;
-
-type MaybeShortcut<
-  ContentType extends MediaType,
-  Response extends OpenApiResponse
-> = IfHasKey<
-  Response["content"],
-  ContentType,
-  (body: Response["content"][ContentType]["schema"]) => ResponseBuilder<{
-    headers: Response["headers"];
-    content: Omit<Response["content"], ContentType>;
-  }>,
-  never
->;
-
-type MatchFunction<Response extends OpenApiResponse> = <
-  ContentType extends MediaType & keyof Response["content"]
->(
-  contentType: ContentType,
-  body: Response["content"][ContentType]["schema"]
-) => ResponseBuilder<{
-  headers: Response["headers"];
-  content: Omit<Response["content"], ContentType>;
-}>;
-
-type HeaderFunction<Response extends OpenApiResponse> = <
-  Header extends string & keyof Response["headers"]
->(
-  header: Header,
-  value: Response["headers"][Header]["schema"]
-) => ResponseBuilder<{
-  content: Response["content"];
-  headers: Omit<Response["headers"], Header>;
-}>;
-
-type ResponseBuilder<Response extends OpenApiResponse> = [
-  keyof Response["content"]
-] extends [never]
-  ? void
-  : OmitValueWhenNever<{
-      header: [keyof Response["headers"]] extends [never]
-        ? never
-        : HeaderFunction<Response>;
-      match: [keyof Response["content"]] extends [never]
-        ? never
-        : MatchFunction<Response>;
-      text: MaybeShortcut<"text/plain", Response>;
-      json: MaybeShortcut<"application/json", Response>;
-      html: MaybeShortcut<"text/html", Response>;
-      random: [keyof Response["content"]] extends [never]
-        ? never
-        : () => void;
-    }>;
-
-export type ResponseBuilderBuilder<Responses extends OpenApiResponses> = {
-  [StatusCode in keyof Responses]: ResponseBuilder<Responses[StatusCode]>;
-} & Record<string, ResponseBuilder<Responses["default"]>>;
-
-
-export function counterfact( basePath: string, context: any, openApiPath?: string);
-
-/* 
-// Usage:
-
-
-type Responses = {
-  "200": {
-    headers: {
-      "x-string": {
-        schema: string;
-      };
-      "x-number": {
-        schema: number;
-      };
-    };
-    content: {
-      "text/plain": {
-        schema: string;
-      };
-      "application/json": {
-        schema: number[];
-      };
-    };
-  };
-
-  default: {
-    headers: {};
-    content: {
-      "text/plain": {
-        schema: string;
-      };
-    };
-  };
-};
-
-type HTTP_GET = (
-  response: ResponseBuilderBuilder<Responses>
-) => CounterfactResponse;
-
-const GET: HTTP_GET = (response) => {
-  // return {content: [{ type: "text/plain", body: "x"}], headers: {}, status: 200 }
-
-  return response["200"]
-    .header("x-string", "x")
-    .json([2])
-    .header("x-number", 5)
-    .random();
-};
-*/
diff --git a/src/counterfact.js b/src/counterfact.js
index 4b96770..ef1993d 100644
--- a/src/counterfact.js
+++ b/src/counterfact.js
@@ -14,6 +14,9 @@ import { ModuleLoader } from "./module-loader.js";
 import { Transpiler } from "./transpiler.js";
 import { ContextRegistry } from "./context-registry.js";
 
+// eslint-disable-next-line no-underscore-dangle
+const __dirname = nodePath.dirname(new URL(import.meta.url).pathname);
+
 async function loadOpenApiDocument(source) {
   try {
     return $RefParser.dereference(await yaml.load(await readFile(source)));
@@ -35,6 +38,11 @@ export async function counterfact(
     nodePath.join(os.tmpdir(), "counterfact-")
   )}/`;
 
+  fs.copyFile(
+    nodePath.join(__dirname, "../templates/response-builder-factory.ts"),
+    nodePath.join(basePath, "response-builder-factory.ts")
+  );
+
   try {
     await fs.writeFile(
       nodePath.join(modulesPath, "package.json"),
diff --git a/src/typescript-generator/response-type-coder.js b/src/typescript-generator/response-type-coder.js
index f022353..516e55e 100644
--- a/src/typescript-generator/response-type-coder.js
+++ b/src/typescript-generator/response-type-coder.js
@@ -1,3 +1,5 @@
+import nodePath from "node:path";
+
 import { Coder } from "./coder.js";
 import { SchemaTypeCoder } from "./schema-type-coder.js";
 
@@ -75,9 +77,21 @@ export class ResponseTypeCoder extends Coder {
   }
 
   write(script) {
-    script.importExternalType("ResponseBuilderBuilder", "counterfact");
-    script.importExternalType("HttpStatusCode", "counterfact");
+    const basePath = script.path
+      .split("/")
+      .slice(0, -1)
+      .map(() => "..")
+      .join("/");
+
+    script.importExternalType(
+      "ResponseBuilderFactory",
+      nodePath.join(basePath, "response-builder-factory.js")
+    );
+    script.importExternalType(
+      "HttpStatusCode",
+      nodePath.join(basePath, "response-builder-factory.js")
+    );
 
-    return `ResponseBuilderBuilder<${this.buildResponseObjectType(script)}>`;
+    return `ResponseBuilderFactory<${this.buildResponseObjectType(script)}>`;
   }
 }
diff --git a/src/typescript-generator/tools-coder.js b/src/typescript-generator/tools-coder.js
deleted file mode 100644
index fdcb758..0000000
--- a/src/typescript-generator/tools-coder.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import { Coder } from "./coder.js";
-
-export class ToolsCoder extends Coder {
-  get id() {
-    return "tools";
-  }
-
-  delegate() {
-    return Promise.resolve(this);
-  }
-
-  names() {
-    return super.names("Tools");
-  }
-
-  write(script) {
-    script.importExternal("JSONSchema6", "json-schema");
-
-    return `
-    {
-        oneOf: (array: string[]) => string;
-        randomFromSchema: (schema: JSONSchema6 ) => unknown;
-        accepts: (contentType: string) => boolean;
-    }`;
-  }
-
-  modulePath() {
-    return "internal/tools.ts";
-  }
-}
diff --git a/templates/response-builder-factory.ts b/templates/response-builder-factory.ts
new file mode 100644
index 0000000..fd6cb8a
--- /dev/null
+++ b/templates/response-builder-factory.ts
@@ -0,0 +1,142 @@
+interface OpenApiHeader {
+  schema: unknown;
+}
+
+interface OpenApiContent {
+  schema: unknown;
+}
+
+type OmitValueWhenNever<Base> = Pick<
+  Base,
+  {
+    [Key in keyof Base]: [Base[Key]] extends [never] ? never : Key;
+  }[keyof Base]
+>;
+
+type MediaType = `${string}/${string}`;
+
+interface OpenApiResponse {
+  headers: { [key: string]: OpenApiHeader };
+  content: { [key: MediaType]: OpenApiContent };
+}
+
+interface OpenApiResponses {
+  [key: string]: OpenApiResponse;
+}
+
+type IfHasKey<SomeObject, Key, Yes, No> = Key extends keyof SomeObject
+  ? Yes
+  : No;
+
+type MaybeShortcut<
+  ContentType extends MediaType,
+  Response extends OpenApiResponse
+> = IfHasKey<
+  Response["content"],
+  ContentType,
+  (body: Response["content"][ContentType]["schema"]) => ResponseBuilder<{
+    headers: Response["headers"];
+    content: Omit<Response["content"], ContentType>;
+  }>,
+  never
+>;
+
+type MatchFunction<Response extends OpenApiResponse> = <
+  ContentType extends MediaType & keyof Response["content"]
+>(
+  contentType: ContentType,
+  body: Response["content"][ContentType]["schema"]
+) => ResponseBuilder<{
+  headers: Response["headers"];
+  content: Omit<Response["content"], ContentType>;
+}>;
+
+type HeaderFunction<Response extends OpenApiResponse> = <
+  Header extends string & keyof Response["headers"]
+>(
+  header: Header,
+  value: Response["headers"][Header]["schema"]
+) => ResponseBuilder<{
+  content: Response["content"];
+  headers: Omit<Response["headers"], Header>;
+}>;
+
+type ResponseBuilder<Response extends OpenApiResponse> = [
+  keyof Response["content"]
+] extends [never]
+  ? // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
+    void
+  : OmitValueWhenNever<{
+      header: [keyof Response["headers"]] extends [never]
+        ? never
+        : HeaderFunction<Response>;
+      match: [keyof Response["content"]] extends [never]
+        ? never
+        : MatchFunction<Response>;
+      text: MaybeShortcut<"text/plain", Response>;
+      json: MaybeShortcut<"application/json", Response>;
+      html: MaybeShortcut<"text/html", Response>;
+      random: [keyof Response["content"]] extends [never] ? never : () => void;
+    }>;
+
+export type ResponseBuilderFactory<Responses extends OpenApiResponses> = {
+  [StatusCode in keyof Responses]: ResponseBuilder<Responses[StatusCode]>;
+} & { [key: string]: ResponseBuilder<Responses["default"]> };
+
+export type HttpStatusCode =
+  | 100
+  | 101
+  | 102
+  | 200
+  | 201
+  | 202
+  | 203
+  | 204
+  | 205
+  | 206
+  | 207
+  | 226
+  | 300
+  | 301
+  | 302
+  | 303
+  | 304
+  | 305
+  | 307
+  | 308
+  | 400
+  | 401
+  | 402
+  | 403
+  | 404
+  | 405
+  | 406
+  | 407
+  | 408
+  | 409
+  | 410
+  | 411
+  | 412
+  | 413
+  | 414
+  | 415
+  | 416
+  | 417
+  | 418
+  | 422
+  | 423
+  | 424
+  | 426
+  | 428
+  | 429
+  | 431
+  | 451
+  | 500
+  | 501
+  | 502
+  | 503
+  | 504
+  | 505
+  | 506
+  | 507
+  | 511;
diff --git a/templates/typescript/.devcontainer/Dockerfile b/templates/typescript/.devcontainer/Dockerfile
deleted file mode 100644
index 49340db..0000000
--- a/templates/typescript/.devcontainer/Dockerfile
+++ /dev/null
@@ -1,14 +0,0 @@
-# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster
-ARG VARIANT=16-bullseye
-FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:0-${VARIANT}
-
-# [Optional] Uncomment this section to install additional OS packages.
-# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
-#     && apt-get -y install --no-install-recommends <your-package-list-here>
-
-# [Optional] Uncomment if you want to install an additional version of node using nvm
-# ARG EXTRA_NODE_VERSION=10
-# RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}"
-
-# [Optional] Uncomment if you want to install more global node packages
-RUN su node -c "npm install -g ts-node"
diff --git a/templates/typescript/.devcontainer/base.Dockerfile b/templates/typescript/.devcontainer/base.Dockerfile
deleted file mode 100644
index 35b6654..0000000
--- a/templates/typescript/.devcontainer/base.Dockerfile
+++ /dev/null
@@ -1,17 +0,0 @@
-# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster
-ARG VARIANT=16-bullseye
-FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT}
-
-# Install tslint, typescript. eslint is installed by javascript image
-ARG NODE_MODULES="tslint-to-eslint-config typescript"
-COPY library-scripts/meta.env /usr/local/etc/vscode-dev-containers
-RUN su node -c "umask 0002 && npm install -g ${NODE_MODULES}" \
-    && npm cache clean --force > /dev/null 2>&1
-
-# [Optional] Uncomment this section to install additional OS packages.
-# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
-#     && apt-get -y install --no-install-recommends <your-package-list-here>
-
-# [Optional] Uncomment if you want to install an additional version of node using nvm
-# ARG EXTRA_NODE_VERSION=10
-# RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}"
diff --git a/templates/typescript/.devcontainer/devcontainer.json b/templates/typescript/.devcontainer/devcontainer.json
deleted file mode 100644
index be94e8c..0000000
--- a/templates/typescript/.devcontainer/devcontainer.json
+++ /dev/null
@@ -1,47 +0,0 @@
-{
-  "name": "Counterfact",
-  "build": {
-    "dockerfile": "Dockerfile",
-    "args": {
-      "VARIANT": "16-bullseye"
-    }
-  },
-  "customizations": {
-    "vscode": {
-      "settings": {
-        "editor.formatOnSave": true,
-        "eslint.format.enable": true,
-        "eslint.packageManager": "yarn",
-        "eslint.codeActionsOnSave.mode": "problems",
-        "eslint.codeActionsOnSave.rules": [
-          "!import/namespace",
-          "!etc/no-deprecated",
-          "!import/no-cycle",
-          "!no-explicit-type-exports/no-explicit-type-exports",
-          "!import/no-deprecated",
-          "!import/no-self-import",
-          "!import/default",
-          "!import/no-named-as-default",
-          "*"
-        ],
-        "files.insertFinalNewline": true,
-        "jest.nodeEnv": {
-          "NODE_OPTIONS": "--experimental-vm-modules"
-        },
-        "[javascript]": {
-          "editor.defaultFormatter": "dbaeumer.vscode-eslint"
-        },
-        "[typescript]": {
-          "editor.defaultFormatter": "dbaeumer.vscode-eslint"
-        }
-      },
-      "extensions": [
-        "dbaeumer.vscode-eslint",
-        "ms-azuretools.vscode-docker",
-        "usernamehw.errorlens"
-      ]
-    }
-  },
-  "postCreateCommand": "yarn install",
-  "remoteUser": "node"
-}
diff --git a/templates/typescript/counterfact/context/context.ts b/templates/typescript/counterfact/context/context.ts
deleted file mode 100644
index c76be19..0000000
--- a/templates/typescript/counterfact/context/context.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-// Add whatever methods you want to this class.
-// Use it to store and retrieve data, implement logic, etc.
-// You can connect to a database, call other services, whatever makes sense.
-
-export class Context {
-  private greeting = "Hello";
-
-  public setGreeting(greeting: string): void {
-    this.greeting = greeting;
-  }
-
-  public message(): string {
-    return `${this.greeting} World!`;
-  }
-}
-
-// Counterfact will load this object and pass it into the GET() / POST() / PUT() / DELETE() functions.
-export const context = new Context();
diff --git a/templates/typescript/counterfact/public/index.html b/templates/typescript/counterfact/public/index.html
deleted file mode 100644
index fabf2fb..0000000
--- a/templates/typescript/counterfact/public/index.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <title>Counterfact</title>
-    <meta name="description" content="instructions for using Counterfact" />
-    <meta name="viewport" content="width=device-width, initial-scale=1" />
-  </head>
-  <body>
-    <h1>Welcome to Counterfact!</h1>
-
-    <p>
-      A future version of this page will contain more detailed instructions.
-    </p>
-
-    <p>For now, you can <a href="/docs">browse the API.</a></p>
-  </body>
-</html>
diff --git a/templates/typescript/counterfact/server.ts b/templates/typescript/counterfact/server.ts
deleted file mode 100644
index b4619fa..0000000
--- a/templates/typescript/counterfact/server.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-/* eslint-disable node/no-unsupported-features/node-builtins */
-
-import { fileURLToPath } from "node:url";
-
-import type { Middleware } from "koa";
-import Koa from "koa";
-import { counterfact } from "counterfact";
-import { koaSwagger } from "koa2-swagger-ui";
-import serve from "koa-static";
-import bodyParser from "koa-bodyparser";
-import open from "open";
-
-import { context } from "./context/context.js";
-
-const PORT = 3100;
-
-const PATHS_DIRECTORY = fileURLToPath(new URL("paths/", import.meta.url));
-
-const app = new Koa();
-
-app.use(serve(fileURLToPath(new URL("public", import.meta.url))));
-
-app.use(
-  koaSwagger({
-    routePrefix: "/docs",
-
-    swaggerOptions: {
-      url: "/openapi.yaml",
-    },
-  })
-);
-
-app.use(bodyParser());
-
-// eslint-disable-next-line @typescript-eslint/no-unsafe-call
-const { koaMiddleware } = (await counterfact(PATHS_DIRECTORY, context)) as {
-  koaMiddleware: Middleware;
-};
-
-app.use(koaMiddleware);
-
-app.listen(PORT);
-process.stdout.write("Counterfact is running.\n");
-process.stdout.write(`See docs at http://localhost:${PORT}/docs\n`);
-process.stdout.write(
-  `A copy of the Open API spec is at ${fileURLToPath(
-    new URL("public/openapi.yaml", import.meta.url)
-  )}\n`
-);
-process.stdout.write(
-  `The code that implements the API is under ${PATHS_DIRECTORY}\n`
-);
-
-if (process.argv.includes("--open")) {
-  await open(`http://localhost:${PORT}/index.html`);
-}
diff --git a/templates/typescript/eslintrc.yaml b/templates/typescript/eslintrc.yaml
deleted file mode 100644
index 7b6e9e3..0000000
--- a/templates/typescript/eslintrc.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
-env:
-  es2021: true
-  node: true
-extends:
-  - eslint:recommended
-  - plugin:@typescript-eslint/recommended
-parser: '@typescript-eslint/parser'
-parserOptions:
-  ecmaVersion: latest
-  sourceType: module
-plugins:
-  - '@typescript-eslint'
-rules: {}
diff --git a/templates/typescript/package.json b/templates/typescript/package.json
deleted file mode 100644
index 5cd83bc..0000000
--- a/templates/typescript/package.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-  "type": "module",
-  "private": true,
-  "description": "I was automatically generated by the 'counterfact' package from npm",
-  "dependencies": {
-    "@types/koa-bodyparser": "^4.3.7",
-    "counterfact": "^0.8.0",
-    "json-schema-faker": "^0.5.0-rcv.44",
-    "koa": "^2.13.4",
-    "koa-body-parser": "^1.1.2",
-    "koa-bodyparser": "^4.3.0",
-    "koa-static": "^5.0.0",
-    "koa2-swagger-ui": "^5.6.0",
-    "open": "^8.4.0"
-  },
-  "devDependencies": {
-    "@types/node": "^18.0.0",
-    "@typescript-eslint/eslint-plugin": "^5.30.7",
-    "@typescript-eslint/parser": "^5.30.7",
-    "eslint": "^8.20.0",
-    "typescript": "^4.7.4"
-  },
-  "scripts": {
-    "start": "ts-node counterfact/server.ts",
-    "lint": "eslint .",
-    "test": "echo \"Error: no test specified\" && exit 1"
-  }
-}
diff --git a/templates/typescript/tsconfig.json b/templates/typescript/tsconfig.json
deleted file mode 100644
index 6f27597..0000000
--- a/templates/typescript/tsconfig.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "compilerOptions": {
-    "moduleResolution": "node",
-    "module": "es2022",
-    "target": "es2022",
-    "strictNullChecks": true,
-    "allowSyntheticDefaultImports": true
-  },
-  "include": ["counterfact"],
-  "ts-node": {
-    "esm": true
-  }
-}
diff --git a/yarn.lock b/yarn.lock
index 3aa05f3..b14ce97 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3476,23 +3476,6 @@ cosmiconfig@^7.0.0, cosmiconfig@^7.0.1:
     path-type "^4.0.0"
     yaml "^1.10.0"
 
-counterfact@*:
-  version "0.7.0"
-  resolved "https://registry.yarnpkg.com/counterfact/-/counterfact-0.7.0.tgz#cf4b93d06ae643a2cba463871b097f2b14e145a4"
-  integrity sha512-Tf+3v7sEd/23M/Gd0HQCQETRlTqabgseNwREsiwYEKB11sTHGVB82C9bSOOBoG6ap9FsUDiqcyqrIltVDdivLQ==
-  dependencies:
-    "@hapi/accept" "^6.0.0"
-    "@types/json-schema" "^7.0.11"
-    chokidar "^3.5.3"
-    fs-extra "^10.1.0"
-    js-yaml "^4.1.0"
-    json-schema-faker "^0.5.0-rcv.44"
-    jsonwebtoken "^8.5.1"
-    koa "^2.13.4"
-    koa-bodyparser "^4.3.0"
-    prettier "^2.7.1"
-    typescript "^4.8.2"
-
 crc-32@^1.2.0:
   version "1.2.2"
   resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff"


Test patch:
diff --git a/test/typescript-generator/__snapshots__/end-to-end.test.js.snap b/test/typescript-generator/__snapshots__/end-to-end.test.js.snap
index 5f54d63..c261a97 100644
--- a/test/typescript-generator/__snapshots__/end-to-end.test.js.snap
+++ b/test/typescript-generator/__snapshots__/end-to-end.test.js.snap
@@ -51,7 +51,7 @@ Map {
           },
           "exports": Map {
             "HTTP_POST" => Object {
-              "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Pet, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Pet, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -94,7 +94,7 @@ Map {
               "typeDeclaration": "",
             },
             "HTTP_PUT" => Object {
-              "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Pet, context: typeof Context2, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Pet, context: typeof Context2, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -158,13 +158,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -344,7 +344,7 @@ Map {
           },
           "exports": Map {
             "HTTP_POST" => Object {
-              "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Pet, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Pet, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -387,7 +387,7 @@ Map {
               "typeDeclaration": "",
             },
             "HTTP_PUT" => Object {
-              "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Pet, context: typeof Context2, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Pet, context: typeof Context2, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -451,13 +451,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -641,7 +641,7 @@ Map {
     },
     "exports": Map {
       "HTTP_POST" => Object {
-        "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Pet, context: typeof Context, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Pet, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -684,7 +684,7 @@ Map {
         "typeDeclaration": "",
       },
       "HTTP_PUT" => Object {
-        "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Pet, context: typeof Context2, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Pet, context: typeof Context2, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -748,13 +748,13 @@ Map {
       },
     },
     "externalImports": Map {
-      "ResponseBuilderBuilder" => Object {
+      "ResponseBuilderFactory" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../response-builder-factory.js",
       },
       "HttpStatusCode" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../response-builder-factory.js",
       },
     },
     "imports": Map {
@@ -952,7 +952,7 @@ Map {
           },
           "exports": Map {
             "HTTP_GET" => Object {
-              "code": "({ query, path, header, body, context }: { query: {status?: string}, path: never, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: {status?: string}, path: never, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -996,13 +996,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -1156,7 +1156,7 @@ Map {
     },
     "exports": Map {
       "HTTP_GET" => Object {
-        "code": "({ query, path, header, body, context }: { query: {status?: string}, path: never, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: {status?: string}, path: never, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -1200,13 +1200,13 @@ Map {
       },
     },
     "externalImports": Map {
-      "ResponseBuilderBuilder" => Object {
+      "ResponseBuilderFactory" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../response-builder-factory.js",
       },
       "HttpStatusCode" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../response-builder-factory.js",
       },
     },
     "imports": Map {
@@ -1376,7 +1376,7 @@ Map {
           },
           "exports": Map {
             "HTTP_GET" => Object {
-              "code": "({ query, path, header, body, context }: { query: {tags?: Array<string>}, path: never, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: {tags?: Array<string>}, path: never, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -1420,13 +1420,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -1580,7 +1580,7 @@ Map {
     },
     "exports": Map {
       "HTTP_GET" => Object {
-        "code": "({ query, path, header, body, context }: { query: {tags?: Array<string>}, path: never, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: {tags?: Array<string>}, path: never, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -1624,13 +1624,13 @@ Map {
       },
     },
     "externalImports": Map {
-      "ResponseBuilderBuilder" => Object {
+      "ResponseBuilderFactory" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../response-builder-factory.js",
       },
       "HttpStatusCode" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../response-builder-factory.js",
       },
     },
     "imports": Map {
@@ -1828,7 +1828,7 @@ Map {
           },
           "exports": Map {
             "HTTP_GET" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {petId: number}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {petId: number}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -1881,7 +1881,7 @@ Map {
               "typeDeclaration": "",
             },
             "HTTP_POST" => Object {
-              "code": "({ query, path, header, body, context }: { query: {name?: number, status?: string}, path: {petId: number}, header: never, body: undefined, context: typeof Context2, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: {name?: number, status?: string}, path: {petId: number}, header: never, body: undefined, context: typeof Context2, response: ResponseBuilderFactory<{
       405: {
           headers: {};
           content: {
@@ -1904,7 +1904,7 @@ Map {
               "typeDeclaration": "",
             },
             "HTTP_DELETE" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {petId: string}, header: {api_key?: string}, body: undefined, context: typeof Context3, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {petId: string}, header: {api_key?: string}, body: undefined, context: typeof Context3, response: ResponseBuilderFactory<{
       400: {
           headers: {};
           content: {
@@ -1928,13 +1928,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -2152,7 +2152,7 @@ Map {
           },
           "exports": Map {
             "HTTP_GET" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {petId: number}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {petId: number}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -2205,7 +2205,7 @@ Map {
               "typeDeclaration": "",
             },
             "HTTP_POST" => Object {
-              "code": "({ query, path, header, body, context }: { query: {name?: number, status?: string}, path: {petId: number}, header: never, body: undefined, context: typeof Context2, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: {name?: number, status?: string}, path: {petId: number}, header: never, body: undefined, context: typeof Context2, response: ResponseBuilderFactory<{
       405: {
           headers: {};
           content: {
@@ -2228,7 +2228,7 @@ Map {
               "typeDeclaration": "",
             },
             "HTTP_DELETE" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {petId: string}, header: {api_key?: string}, body: undefined, context: typeof Context3, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {petId: string}, header: {api_key?: string}, body: undefined, context: typeof Context3, response: ResponseBuilderFactory<{
       400: {
           headers: {};
           content: {
@@ -2252,13 +2252,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -2476,7 +2476,7 @@ Map {
           },
           "exports": Map {
             "HTTP_GET" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {petId: number}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {petId: number}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -2529,7 +2529,7 @@ Map {
               "typeDeclaration": "",
             },
             "HTTP_POST" => Object {
-              "code": "({ query, path, header, body, context }: { query: {name?: number, status?: string}, path: {petId: number}, header: never, body: undefined, context: typeof Context2, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: {name?: number, status?: string}, path: {petId: number}, header: never, body: undefined, context: typeof Context2, response: ResponseBuilderFactory<{
       405: {
           headers: {};
           content: {
@@ -2552,7 +2552,7 @@ Map {
               "typeDeclaration": "",
             },
             "HTTP_DELETE" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {petId: string}, header: {api_key?: string}, body: undefined, context: typeof Context3, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {petId: string}, header: {api_key?: string}, body: undefined, context: typeof Context3, response: ResponseBuilderFactory<{
       400: {
           headers: {};
           content: {
@@ -2576,13 +2576,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -2804,7 +2804,7 @@ Map {
     },
     "exports": Map {
       "HTTP_GET" => Object {
-        "code": "({ query, path, header, body, context }: { query: never, path: {petId: number}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: never, path: {petId: number}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -2857,7 +2857,7 @@ Map {
         "typeDeclaration": "",
       },
       "HTTP_POST" => Object {
-        "code": "({ query, path, header, body, context }: { query: {name?: number, status?: string}, path: {petId: number}, header: never, body: undefined, context: typeof Context2, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: {name?: number, status?: string}, path: {petId: number}, header: never, body: undefined, context: typeof Context2, response: ResponseBuilderFactory<{
       405: {
           headers: {};
           content: {
@@ -2880,7 +2880,7 @@ Map {
         "typeDeclaration": "",
       },
       "HTTP_DELETE" => Object {
-        "code": "({ query, path, header, body, context }: { query: never, path: {petId: string}, header: {api_key?: string}, body: undefined, context: typeof Context3, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: never, path: {petId: string}, header: {api_key?: string}, body: undefined, context: typeof Context3, response: ResponseBuilderFactory<{
       400: {
           headers: {};
           content: {
@@ -2904,13 +2904,13 @@ Map {
       },
     },
     "externalImports": Map {
-      "ResponseBuilderBuilder" => Object {
+      "ResponseBuilderFactory" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../response-builder-factory.js",
       },
       "HttpStatusCode" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../response-builder-factory.js",
       },
     },
     "imports": Map {
@@ -3144,7 +3144,7 @@ Map {
           },
           "exports": Map {
             "HTTP_POST" => Object {
-              "code": "({ query, path, header, body, context }: { query: {additionalMetadata?: number}, path: {petId: number}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: {additionalMetadata?: number}, path: {petId: number}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -3170,13 +3170,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -3267,7 +3267,7 @@ Map {
     },
     "exports": Map {
       "HTTP_POST" => Object {
-        "code": "({ query, path, header, body, context }: { query: {additionalMetadata?: number}, path: {petId: number}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: {additionalMetadata?: number}, path: {petId: number}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -3293,13 +3293,13 @@ Map {
       },
     },
     "externalImports": Map {
-      "ResponseBuilderBuilder" => Object {
+      "ResponseBuilderFactory" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../../response-builder-factory.js",
       },
       "HttpStatusCode" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../../response-builder-factory.js",
       },
     },
     "imports": Map {
@@ -3405,7 +3405,7 @@ Map {
           },
           "exports": Map {
             "HTTP_GET" => Object {
-              "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -3431,13 +3431,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -3497,7 +3497,7 @@ Map {
     },
     "exports": Map {
       "HTTP_GET" => Object {
-        "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -3523,13 +3523,13 @@ Map {
       },
     },
     "externalImports": Map {
-      "ResponseBuilderBuilder" => Object {
+      "ResponseBuilderFactory" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../response-builder-factory.js",
       },
       "HttpStatusCode" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../response-builder-factory.js",
       },
     },
     "imports": Map {
@@ -3606,7 +3606,7 @@ Map {
           },
           "exports": Map {
             "HTTP_POST" => Object {
-              "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Order, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Order, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -3642,13 +3642,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -3739,7 +3739,7 @@ Map {
     },
     "exports": Map {
       "HTTP_POST" => Object {
-        "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Order, context: typeof Context, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Order, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -3775,13 +3775,13 @@ Map {
       },
     },
     "externalImports": Map {
-      "ResponseBuilderBuilder" => Object {
+      "ResponseBuilderFactory" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../response-builder-factory.js",
       },
       "HttpStatusCode" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../response-builder-factory.js",
       },
     },
     "imports": Map {
@@ -3902,7 +3902,7 @@ Map {
           },
           "exports": Map {
             "HTTP_GET" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {orderId: number}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {orderId: number}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -3955,7 +3955,7 @@ Map {
               "typeDeclaration": "",
             },
             "HTTP_DELETE" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {orderId: number}, header: never, body: undefined, context: typeof Context2, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {orderId: number}, header: never, body: undefined, context: typeof Context2, response: ResponseBuilderFactory<{
       400: {
           headers: {};
           content: {
@@ -3989,13 +3989,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -4116,7 +4116,7 @@ Map {
           },
           "exports": Map {
             "HTTP_GET" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {orderId: number}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {orderId: number}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -4169,7 +4169,7 @@ Map {
               "typeDeclaration": "",
             },
             "HTTP_DELETE" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {orderId: number}, header: never, body: undefined, context: typeof Context2, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {orderId: number}, header: never, body: undefined, context: typeof Context2, response: ResponseBuilderFactory<{
       400: {
           headers: {};
           content: {
@@ -4203,13 +4203,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -4334,7 +4334,7 @@ Map {
     },
     "exports": Map {
       "HTTP_GET" => Object {
-        "code": "({ query, path, header, body, context }: { query: never, path: {orderId: number}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: never, path: {orderId: number}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -4387,7 +4387,7 @@ Map {
         "typeDeclaration": "",
       },
       "HTTP_DELETE" => Object {
-        "code": "({ query, path, header, body, context }: { query: never, path: {orderId: number}, header: never, body: undefined, context: typeof Context2, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: never, path: {orderId: number}, header: never, body: undefined, context: typeof Context2, response: ResponseBuilderFactory<{
       400: {
           headers: {};
           content: {
@@ -4421,13 +4421,13 @@ Map {
       },
     },
     "externalImports": Map {
-      "ResponseBuilderBuilder" => Object {
+      "ResponseBuilderFactory" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../../response-builder-factory.js",
       },
       "HttpStatusCode" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../../response-builder-factory.js",
       },
     },
     "imports": Map {
@@ -4566,7 +4566,7 @@ Map {
           },
           "exports": Map {
             "HTTP_POST" => Object {
-              "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: User, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: User, context: typeof Context, response: ResponseBuilderFactory<{
       [statusCode in HttpStatusCode]: {
           headers: {};
           content: {
@@ -4600,13 +4600,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -4695,7 +4695,7 @@ Map {
     },
     "exports": Map {
       "HTTP_POST" => Object {
-        "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: User, context: typeof Context, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: User, context: typeof Context, response: ResponseBuilderFactory<{
       [statusCode in HttpStatusCode]: {
           headers: {};
           content: {
@@ -4729,13 +4729,13 @@ Map {
       },
     },
     "externalImports": Map {
-      "ResponseBuilderBuilder" => Object {
+      "ResponseBuilderFactory" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../response-builder-factory.js",
       },
       "HttpStatusCode" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../response-builder-factory.js",
       },
     },
     "imports": Map {
@@ -4840,7 +4840,7 @@ Map {
           },
           "exports": Map {
             "HTTP_POST" => Object {
-              "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Array<User>, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Array<User>, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -4884,13 +4884,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -4981,7 +4981,7 @@ Map {
     },
     "exports": Map {
       "HTTP_POST" => Object {
-        "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Array<User>, context: typeof Context, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: undefined, path: undefined, header: undefined, body: Array<User>, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -5025,13 +5025,13 @@ Map {
       },
     },
     "externalImports": Map {
-      "ResponseBuilderBuilder" => Object {
+      "ResponseBuilderFactory" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../response-builder-factory.js",
       },
       "HttpStatusCode" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../response-builder-factory.js",
       },
     },
     "imports": Map {
@@ -5137,7 +5137,7 @@ Map {
           },
           "exports": Map {
             "HTTP_GET" => Object {
-              "code": "({ query, path, header, body, context }: { query: {username?: string, password?: string}, path: never, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: {username?: string, password?: string}, path: never, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {\\"X-Rate-Limit\\": { schema: number};\\"X-Expires-After\\": { schema: string}};
           content: {
@@ -5181,13 +5181,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -5247,7 +5247,7 @@ Map {
     },
     "exports": Map {
       "HTTP_GET" => Object {
-        "code": "({ query, path, header, body, context }: { query: {username?: string, password?: string}, path: never, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: {username?: string, password?: string}, path: never, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {\\"X-Rate-Limit\\": { schema: number};\\"X-Expires-After\\": { schema: string}};
           content: {
@@ -5291,13 +5291,13 @@ Map {
       },
     },
     "externalImports": Map {
-      "ResponseBuilderBuilder" => Object {
+      "ResponseBuilderFactory" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../response-builder-factory.js",
       },
       "HttpStatusCode" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../response-builder-factory.js",
       },
     },
     "imports": Map {
@@ -5371,7 +5371,7 @@ Map {
           },
           "exports": Map {
             "HTTP_GET" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: never, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: never, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       [statusCode in HttpStatusCode]: {
           headers: {};
           content: {
@@ -5395,13 +5395,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -5461,7 +5461,7 @@ Map {
     },
     "exports": Map {
       "HTTP_GET" => Object {
-        "code": "({ query, path, header, body, context }: { query: never, path: never, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: never, path: never, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       [statusCode in HttpStatusCode]: {
           headers: {};
           content: {
@@ -5485,13 +5485,13 @@ Map {
       },
     },
     "externalImports": Map {
-      "ResponseBuilderBuilder" => Object {
+      "ResponseBuilderFactory" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../response-builder-factory.js",
       },
       "HttpStatusCode" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../response-builder-factory.js",
       },
     },
     "imports": Map {
@@ -5596,7 +5596,7 @@ Map {
           },
           "exports": Map {
             "HTTP_GET" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -5649,7 +5649,7 @@ Map {
               "typeDeclaration": "",
             },
             "HTTP_PUT" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: User, context: typeof Context2, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: User, context: typeof Context2, response: ResponseBuilderFactory<{
       [statusCode in HttpStatusCode]: {
           headers: {};
           content: {
@@ -5672,7 +5672,7 @@ Map {
               "typeDeclaration": "",
             },
             "HTTP_DELETE" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: undefined, context: typeof Context3, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: undefined, context: typeof Context3, response: ResponseBuilderFactory<{
       400: {
           headers: {};
           content: {
@@ -5706,13 +5706,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -5867,7 +5867,7 @@ Map {
           },
           "exports": Map {
             "HTTP_GET" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -5920,7 +5920,7 @@ Map {
               "typeDeclaration": "",
             },
             "HTTP_PUT" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: User, context: typeof Context2, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: User, context: typeof Context2, response: ResponseBuilderFactory<{
       [statusCode in HttpStatusCode]: {
           headers: {};
           content: {
@@ -5943,7 +5943,7 @@ Map {
               "typeDeclaration": "",
             },
             "HTTP_DELETE" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: undefined, context: typeof Context3, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: undefined, context: typeof Context3, response: ResponseBuilderFactory<{
       400: {
           headers: {};
           content: {
@@ -5977,13 +5977,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -6138,7 +6138,7 @@ Map {
           },
           "exports": Map {
             "HTTP_GET" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -6191,7 +6191,7 @@ Map {
               "typeDeclaration": "",
             },
             "HTTP_PUT" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: User, context: typeof Context2, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: User, context: typeof Context2, response: ResponseBuilderFactory<{
       [statusCode in HttpStatusCode]: {
           headers: {};
           content: {
@@ -6214,7 +6214,7 @@ Map {
               "typeDeclaration": "",
             },
             "HTTP_DELETE" => Object {
-              "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: undefined, context: typeof Context3, response: ResponseBuilderBuilder<{
+              "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: undefined, context: typeof Context3, response: ResponseBuilderFactory<{
       400: {
           headers: {};
           content: {
@@ -6248,13 +6248,13 @@ Map {
             },
           },
           "externalImports": Map {
-            "ResponseBuilderBuilder" => Object {
+            "ResponseBuilderFactory" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
             "HttpStatusCode" => Object {
               "isType": true,
-              "modulePath": "counterfact",
+              "modulePath": "../../response-builder-factory.js",
             },
           },
           "imports": Map {
@@ -6413,7 +6413,7 @@ Map {
     },
     "exports": Map {
       "HTTP_GET" => Object {
-        "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: undefined, context: typeof Context, response: ResponseBuilderFactory<{
       200: {
           headers: {};
           content: {
@@ -6466,7 +6466,7 @@ Map {
         "typeDeclaration": "",
       },
       "HTTP_PUT" => Object {
-        "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: User, context: typeof Context2, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: User, context: typeof Context2, response: ResponseBuilderFactory<{
       [statusCode in HttpStatusCode]: {
           headers: {};
           content: {
@@ -6489,7 +6489,7 @@ Map {
         "typeDeclaration": "",
       },
       "HTTP_DELETE" => Object {
-        "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: undefined, context: typeof Context3, response: ResponseBuilderBuilder<{
+        "code": "({ query, path, header, body, context }: { query: never, path: {username: string}, header: never, body: undefined, context: typeof Context3, response: ResponseBuilderFactory<{
       400: {
           headers: {};
           content: {
@@ -6523,13 +6523,13 @@ Map {
       },
     },
     "externalImports": Map {
-      "ResponseBuilderBuilder" => Object {
+      "ResponseBuilderFactory" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../response-builder-factory.js",
       },
       "HttpStatusCode" => Object {
         "isType": true,
-        "modulePath": "counterfact",
+        "modulePath": "../../response-builder-factory.js",
       },
     },
     "imports": Map {
diff --git a/test/typescript-generator/__snapshots__/operation-type-coder.test.js.snap b/test/typescript-generator/__snapshots__/operation-type-coder.test.js.snap
index afb7a21..721a66e 100644
--- a/test/typescript-generator/__snapshots__/operation-type-coder.test.js.snap
+++ b/test/typescript-generator/__snapshots__/operation-type-coder.test.js.snap
@@ -13,7 +13,7 @@ exports[`an OperationTypeCoder generates a complex post operation 1`] = `
   header: { name?: string };
   body: Type;
   context: typeof default;
-  response: ResponseBuilderBuilder<{
+  response: ResponseBuilderFactory<{
     200: {
       headers: {};
       content: {
@@ -73,7 +73,7 @@ exports[`an OperationTypeCoder generates a simple get operation 1`] = `
   header: undefined;
   body: undefined;
   context: typeof default;
-  response: ResponseBuilderBuilder<{
+  response: ResponseBuilderFactory<{
     [statusCode in HttpStatusCode]: {
       headers: {};
       content: {
diff --git a/test/typescript-generator/__snapshots__/tools.coder.test.js.snap b/test/typescript-generator/__snapshots__/tools.coder.test.js.snap
deleted file mode 100644
index e4c1d3c..0000000
--- a/test/typescript-generator/__snapshots__/tools.coder.test.js.snap
+++ /dev/null
@@ -1,10 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`a ToolsCoder has all hard-coded return values 1`] = `
-"
-    {
-        oneOf: (array: string[]) => string;
-        randomFromSchema: (schema: JSONSchema6 ) => unknown;
-        accepts: (contentType: string) => boolean;
-    }"
-`;
diff --git a/test/typescript-generator/tools.coder.test.js b/test/typescript-generator/tools.coder.test.js
deleted file mode 100644
index 952cab8..0000000
--- a/test/typescript-generator/tools.coder.test.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/* eslint-disable jest/no-restricted-matchers */
-import { ToolsCoder } from "../../src/typescript-generator/tools-coder.js";
-import { Requirement } from "../../src/typescript-generator/requirement.js";
-
-describe("a ToolsCoder", () => {
-  it("has all hard-coded return values", async () => {
-    const coder = new ToolsCoder(new Requirement({}));
-
-    const [one, two, three] = coder.names();
-
-    expect([one, two, three]).toStrictEqual(["Tools", "Tools2", "Tools3"]);
-
-    expect(coder.id).toBe("tools");
-    expect(coder.modulePath()).toBe("internal/tools.ts");
-    await expect(coder.delegate()).resolves.toBe(coder);
-
-    expect(
-      coder.write({
-        importExternal(name, path) {
-          coder.imported = { name, path };
-        },
-      })
-    ).toMatchSnapshot();
-
-    expect(coder.imported).toStrictEqual({
-      name: "JSONSchema6",
-      path: "json-schema",
-    });
-  });
-});