### Quick Start with openapi-msw and MSW Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/README.md Demonstrates how to set up typed HTTP handlers using `createOpenApiHttp` and integrate them with MSW's `setupServer`. This example shows defining handlers for GET and POST requests with full type inference from an OpenAPI schema. ```typescript import { createOpenApiHttp } from "openapi-msw"; import { setupServer } from "msw/node"; import type { paths } from "./openapi-schema"; // Create typed HTTP handler factory const http = createOpenApiHttp(); // Define a handler with full type inference const handlers = [ http.get("/users/{id}", ({ params, response }) => { return response(200).json({ id: params.id }); }), http.post("/users", async ({ request, response }) => { const data = await request.json(); return response(201).json(data); }), ]; // Use with MSW const server = setupServer(...handlers); server.listen(); ``` -------------------------------- ### Minimal openapi-msw Setup Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/usage-patterns.md This snippet shows the most basic setup for openapi-msw, including necessary imports and handler creation. ```typescript import { createOpenApiHttp } from "openapi-msw"; import type { paths } from "./openapi-schema"; const http = createOpenApiHttp(); export const handlers = [ http.get("/users", ({ response }) => { return response(200).json([ { id: 1, name: "Alice" }, { id: 2, name: "Bob" }, ]); }), ]; ``` -------------------------------- ### Example: JSON Response for User List Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OpenApiResponse.md Demonstrates constructing a JSON response for a GET request returning a list of users. ```typescript const handler = http.get("/users", ({ response }) => { return response(200).json([ { id: 1, name: "Alice" }, { id: 2, name: "Bob" } ]); }); ``` -------------------------------- ### Install OpenAPI-MSW Source: https://github.com/christoph-fricke/openapi-msw/blob/main/README.md Install OpenAPI-MSW as a development dependency. Ensure MSW v2 is also installed as a peer dependency. ```bash npm i -D openapi-msw ``` -------------------------------- ### Setup Server for Node/Testing Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/README.md Integrates MSW's setupServer with request handlers for use in Node.js environments and testing. ```typescript import { setupServer } from "msw/node"; const server = setupServer(...handlers); server.listen(); // In tests beforeAll(() => server.listen()); afterEach(() => server.resetHandlers()); afterAll(() => server.close()); ``` -------------------------------- ### Example: Text Response for Greeting Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OpenApiResponse.md Demonstrates constructing a simple text response for a GET request. ```typescript const handler = http.get("/greeting", ({ response }) => { return response(200).text("Hello World"); }); ``` -------------------------------- ### Complete Handler Example Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/ResponseResolverInfo.md A comprehensive example showcasing the integrated use of `ResponseResolverInfo` properties for accessing path parameters, query parameters, request bodies, and constructing typed responses. ```typescript import { createOpenApiHttp } from "openapi-msw"; import { HttpResponse } from "msw"; import type { paths } from "./your-openapi-schema"; const http = createOpenApiHttp(); const handler = http.post("/api/users/{id}/profile", async ({ params, request, query, response, }) => { // Type-safe access to path parameters const userId = params.id; // Type-safe query parameter access const includeDetails = query.has("details"); // Type-safe request body parsing const profileData = await request.json(); // Type-safe response construction if (includeDetails) { return response(200).json({ id: userId, ...profileData, details: { /* ... */ }, }); } return response(200).json({ id: userId, ...profileData, }); }); ``` -------------------------------- ### Integration with MSW Setup Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OVERVIEW.md Shows how to integrate openapi-msw handlers with MSW's `setupServer` for Node.js environments and `setupWorker` for browser environments. ```typescript import { setupServer } from "msw/node"; import { setupWorker } from "msw/browser"; const http = createOpenApiHttp(); const handlers = [ http.get("/users", ({ response }) => response(200).json([])), http.post("/users", ({ response }) => response(201).json({})), ]; // Node testing const server = setupServer(...handlers); server.listen(); // Browser testing const worker = setupWorker(...handlers); worker.start(); ``` -------------------------------- ### Example of PathsFor Usage Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/types.md Shows how to use the PathsFor utility type to get a union of all GET paths available from a handler factory. ```typescript const http = createOpenApiHttp(); type GetPaths = PathsFor; // Union of all GET paths ``` -------------------------------- ### Setup with Base URL Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/usage-patterns.md Configure openapi-msw with a base URL to prepend to all defined routes. This is useful for API versioning or organizing endpoints. ```typescript const http = createOpenApiHttp({ baseUrl: "/api/v1", }); // Handler matches: GET /api/v1/users export const getUsersHandler = http.get("/users", ({ response }) => { return response(200).json([]); }); ``` -------------------------------- ### MSW Integration Example Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/configuration.md Shows how to integrate openapi-msw handlers with MSW's setupServer for node environments. This includes setting up the server with handlers created by openapi-msw. ```typescript import { createOpenApiHttp } from "openapi-msw"; import { setupServer } from "msw/node"; import type { paths } from "./your-openapi-schema"; const http = createOpenApiHttp({ baseUrl: "/api" }); // Create handlers with openapi-msw const getUserHandler = http.get("/users/{id}", ({ params, response }) => { return response(200).json({ id: params.id }); }); // Set up MSW server const server = setupServer(getUserHandler); // Use with testing framework server.listen(); ``` -------------------------------- ### Setup Worker for Browser Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/README.md Integrates MSW's setupWorker with request handlers for use in browser environments. ```typescript import { setupWorker } from "msw/browser"; const worker = setupWorker(...handlers); worker.start(); ``` -------------------------------- ### Example Usage of AnyOpenApiHttpRequestHandler Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/types.md Demonstrates a simple usage of the AnyOpenApiHttpRequestHandler type alias. ```typescript type Handler = AnyOpenApiHttpRequestHandler; ``` -------------------------------- ### Base URL Examples Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/configuration.md Illustrates different ways to configure the baseUrl option for createOpenApiHttp, including subpaths, different domains, and no base URL. ```typescript // Subpath on same domain const httpSubpath = createOpenApiHttp({ baseUrl: "/api/v1" }); // Different domain (with protocol) const httpDomain = createOpenApiHttp({ baseUrl: "https://api.example.com" }); // No base URL (default) const httpRoot = createOpenApiHttp(); ``` -------------------------------- ### Example: JSON Response for Created User Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OpenApiResponse.md Shows how to construct a JSON response for a POST request, indicating a successful creation with a 201 status. ```typescript const handler = http.post("/users", ({ response }) => { return response(201).json({ id: 1, name: "Alice" }); }); ``` -------------------------------- ### Basic GET Request with JSON Response Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OpenApiResponse.md Demonstrates a successful GET request to retrieve user data, returning a JSON response with user details. ```APIDOC ## GET /users/{id} ### Description Retrieves user information based on the provided user ID. ### Method GET ### Endpoint /users/{id} ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the user. ### Request Example ```json { "example": "request body" } ``` ### Response #### Success Response (200) - **id** (string) - The user's unique identifier. - **name** (string) - The user's name. - **email** (string) - The user's email address. #### Response Example ```json { "id": "123", "name": "Alice", "email": "alice@example.com" } ``` ``` -------------------------------- ### Example Usage of ResponseResolverInfo Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/types.md Demonstrates how to use the ResponseResolverInfo to access path parameters, query parameters, and construct a typed JSON response. ```typescript const handler = http.post("/users", async (info) => { const userId = info.params.id; const sort = info.query.get("sort"); const body = await info.request.json(); return info.response(201).json(body); }); ``` -------------------------------- ### OpenAPI-TS Integration Example Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/configuration.md Shows how to configure OpenAPI-TS to generate types and then pass the generated 'paths' type to createOpenApiHttp. ```typescript import { defineConfig } from "openapi-typescript"; export default defineConfig({ input: "https://api.example.com/openapi.json", output: "src/types/openapi.ts", }); ``` ```typescript import { createOpenApiHttp } from "openapi-msw"; import type { paths } from "./types/openapi"; const http = createOpenApiHttp(); ``` -------------------------------- ### Define Typed GET Handler Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/createOpenApiHttp.md Example of defining a GET request handler with full type inference for parameters and responses. ```typescript import { HttpResponse } from "msw"; // Define a GET handler with full type inference const getResourceHandler = http.get("/resource/{id}", ({ params, response }) => { const id = params.id; // Typed as string return response(200).json({ id, name: "Resource" }); }); ``` -------------------------------- ### Example: Empty Response with Headers Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OpenApiResponse.md Shows how to construct an empty response with custom headers, still using the 204 status code. ```typescript const handler = http.delete("/items/{id}", ({ response }) => { return response(204).empty({ headers: { "X-Custom": "value" } }); }); ``` -------------------------------- ### Example: Text Response with Wildcard Status Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OpenApiResponse.md Shows how to construct a text response using a wildcard status code (e.g., '5XX') and providing an explicit status in the init options. ```typescript const handler = http.get("/error", ({ response }) => { return response("5XX").text("Internal Error", { status: 500 }); }); ``` -------------------------------- ### Instantiating QueryParams in a Handler Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/QueryParams.md Example of how the `query` object (an instance of QueryParams) is automatically instantiated within an http.get handler. ```typescript const http = createOpenApiHttp(); const handler = http.get("/users", ({ request, query }) => { // query is automatically instantiated internally return HttpResponse.json({}); }); ``` -------------------------------- ### Complete OpenAPI-MSW Response Example Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OpenApiResponse.md Demonstrates various response types including successful JSON, no content, wildcard error handling, and untyped fallbacks. Ensure your OpenAPI schema is imported correctly. ```typescript import { createOpenApiHttp } from "openapi-msw"; import { HttpResponse } from "msw"; import type { paths } from "./your-openapi-schema"; const http = createOpenApiHttp(); // Successful response with JSON const successHandler = http.get("/users/{id}", ({ params, response }) => { return response(200).json({ id: params.id, name: "Alice", email: "alice@example.com" }); }); // No content response const deleteHandler = http.delete("/users/{id}", ({ response }) => { return response(204).empty(); }); // Wildcard status code with specific status const errorHandler = http.get("/risky", ({ response }) => { return response("5XX").json( { error: "Service unavailable" }, { status: 503 } ); }); // Untyped fallback for undefined responses const undefHandler = http.get("/unknown", ({ response }) => { return response.untyped( HttpResponse.json({ status: "ok" }, { status: 418 }) ); }); ``` -------------------------------- ### Complete Handler Example with Different Request Types Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OpenApiRequest.md Demonstrates creating handlers for POST requests that accept JSON, text, or require cloning the request for multiple reads. Imports `createOpenApiHttp` and uses typed request bodies based on the OpenAPI schema. ```typescript import { createOpenApiHttp } from "openapi-msw"; import type { paths } from "./your-openapi-schema"; const http = createOpenApiHttp(); // Handler accepting JSON const jsonHandler = http.post("/api/users", async ({ request, response }) => { const userData = await request.json(); // userData is typed based on OpenAPI requestBody schema return response(201).json({ id: 1, ...userData }); }); // Handler accepting text const textHandler = http.post("/api/logs", async ({ request, response }) => { const logMessage = await request.text(); return response(200).json({ received: logMessage }); }); // Handler with clone for multiple reads const cloneHandler = http.post("/api/sync", async ({ request, response }) => { const clone = request.clone(); // First read const data1 = await request.json(); // Second read from clone const data2 = await clone.json(); return response(200).json({ data1, data2 }); }); ``` -------------------------------- ### Type Flow Example Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OVERVIEW.md Demonstrates how to create a typed HTTP handler factory and define a handler with automatic type inference for parameters, request body, and response. ```typescript import { createOpenApiHttp } from "openapi-msw"; import type { paths } from "./openapi-schema"; // 1. Create typed HTTP handler factory const http = createOpenApiHttp(); // 2. Define a handler with automatic type inference const handler = http.get( "/users/{id}", // TypeScript suggests only valid GET paths async ({ params, // { id: string } - extracted from schema query, // Type-safe QueryParams request, // Type-safe OpenApiRequest response, // Type-safe OpenApiResponse }) => { const userId = params.id; const filter = query.get("filter"); // Type-safe with optional/required distinction const data = await request.json(); // Type matches OpenAPI requestBody // response() only accepts valid status codes // response(200) only allows content types defined for 200 // response(200).json() only accepts matching response body type return response(200).json({ id: userId, ...data, }); } ); ``` -------------------------------- ### Base URL Prepending Example Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/configuration.md Demonstrates how a baseUrl is prepended to handler paths. The library automatically converts OpenAPI path parameters to MSW's colon notation. ```typescript const http = createOpenApiHttp({ baseUrl: "/api/v1" }); // This handler matches: GET /api/v1/users const handler = http.get("/users", ({ response }) => { return response(200).json([]); }); ``` -------------------------------- ### Example: Empty Response for Deletion Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OpenApiResponse.md Demonstrates constructing an empty response for a DELETE request, indicating successful deletion with a 204 status. ```typescript const handler = http.delete("/users/{id}", ({ response }) => { return response(204).empty(); }); ``` -------------------------------- ### Handling Multiple Request Content Types Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/usage-patterns.md This example shows how to handle requests that can accept multiple content types, such as JSON or plain text, based on the `content-type` header. ```typescript const handler = http.post("/data", async ({ request, response }) => { const contentType = request.headers.get("content-type"); if (contentType?.includes("application/json")) { const json = await request.json(); return response(201).json({ type: "json", ...json }); } else { const text = await request.text(); return response(201).json({ type: "text", content: text }); } }); ``` -------------------------------- ### HTTP Methods Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OVERVIEW.md Demonstrates the supported HTTP methods (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS) available through the `createOpenApiHttp` function, each with an identical signature for defining request handlers. ```APIDOC ## HTTP Methods Supported HTTP methods (aligned with both OpenAPI-TS and MSW): ```typescript const http = createOpenApiHttp(); http.get(path, resolver, options?) http.post(path, resolver, options?) http.put(path, resolver, options?) http.patch(path, resolver, options?) http.delete(path, resolver, options?) http.head(path, resolver, options?) http.options(path, resolver, options?) ``` Each method has identical signature but validates against different paths defined in the schema. ``` -------------------------------- ### Setup MSW Worker for Browser Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/usage-patterns.md Configure and use `setupWorker` from MSW for browser environments. This allows you to mock API requests directly in the browser during development or testing. ```typescript import { setupWorker } from "msw/browser"; import { createOpenApiHttp } from "openapi-msw"; import type { paths } from "./openapi-schema"; const http = createOpenApiHttp(); export const worker = setupWorker( http.get("/users", ({ response }) => response(200).json([])), http.post("/users", ({ request, response }) => response(201).json({})) ); // Start in your app worker.start(); ``` -------------------------------- ### Clone OpenApiRequest Example Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OpenApiRequest.md Demonstrates cloning an OpenApiRequest to allow for separate reads of the request body using different parsing methods. ```typescript const handler = http.post("/data", async ({ request }) => { const clone = request.clone(); const json = await request.json(); const text = await clone.text(); // Clone allows separate read return HttpResponse.json({ received: json }); }); ``` -------------------------------- ### RequestMap Type Definition Example Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OpenApiRequest.md Illustrates the structure of the RequestMap type, which maps content types to their corresponding body types. ```typescript type RequestMap = { "application/json": { id: number; name: string }; "text/plain": string; } ``` -------------------------------- ### Path Type Safety Example Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OVERVIEW.md Illustrates compile-time type safety for API paths, ensuring only defined paths for the specified HTTP method are accepted. ```typescript // ✓ Valid - path exists for GET in schema http.get("/users/{id}", ({ response }) => response(200).json({})); // ✗ Invalid - TypeScript error - path not defined or wrong method http.get("/unknown", ({ response }) => response(200).json({})); ``` -------------------------------- ### GET Request with Untyped Fallback Response Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OpenApiResponse.md Demonstrates how to handle responses not explicitly defined in the OpenAPI schema using an untyped fallback. ```APIDOC ## GET /unknown ### Description Handles requests for undefined endpoints or responses, providing a fallback mechanism. ### Method GET ### Endpoint /unknown ### Response #### Success Response (418) - **status** (string) - A status message. #### Response Example ```json { "status": "ok" } ``` ``` -------------------------------- ### Sequential Operations with Async Database Update Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/usage-patterns.md Handle sequential asynchronous operations in a POST request. This example simulates updating a user profile in a database after receiving request data. ```typescript const handler = http.post( "/users/{id}/profile", async ({ params, request, response }) => { const userId = params.id; const profileData = await request.json(); // Simulate async operations const updatedProfile = await updateDatabase(userId, profileData); return response(200).json(updatedProfile); } ); async function updateDatabase(id: string, data: any) { // Simulate async database call return new Promise((resolve) => { setTimeout(() => { resolve({ id, ...data, updated: true }); }, 100); }); } ``` -------------------------------- ### OpenAPI MSW Type Inference Example Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/module-architecture.md Demonstrates the type inference process when using createOpenApiHttp with an API specification, showing how TypeScript validates paths, extracts parameters, and types the resolver function. ```typescript Input: createOpenApiHttp() Step 1: Bind ApiSpec generic http: OpenApiHttpHandlers Step 2: Access handler method http.get: OpenApiHttpRequestHandler Step 3: Call handler with path http.get("/users/{id}", resolver) TypeScript: - Validates "/users/{id}" exists in paths for GET method - Extracts PathParams → { id: string } - Extracts RequestBody - Extracts ResponseBody - Types resolver: ResponseResolver Step 4: Resolver receives info ResponseResolverInfo Which contains: - params: { id: string } - query: QueryParams> - request: OpenApiRequest> - response: OpenApiResponse, ResponseBody<...>> ``` -------------------------------- ### Examples of Type-Safe Response Construction Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/types.md Illustrates various ways to use the OpenApiResponse helper to return responses with different status codes and content types, including JSON, empty, and text responses. ```typescript return response(200).json({ data: "value" }); return response(204).empty(); return response("5XX").text("Error", { status: 503 }); ``` -------------------------------- ### GET Request with Wildcard Status Code Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OpenApiResponse.md Shows how to handle a '5XX' wildcard status code for server errors, returning a specific 503 status. ```APIDOC ## GET /risky ### Description An example endpoint that might encounter server issues, demonstrating wildcard status code handling. ### Method GET ### Endpoint /risky ### Response #### Success Response (503) - **error** (string) - A message indicating the service is unavailable. #### Response Example ```json { "error": "Service unavailable" } ``` ``` -------------------------------- ### Combine Multiple Handlers Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/usage-patterns.md Group handlers for different resources (users, organizations) and combine them for server setup. This promotes modularity and organization of mock API endpoints. ```typescript const http = createOpenApiHttp(); const userHandlers = [ http.get("/users", ({ response }) => response(200).json([])), http.get("/users/{id}", ({ params, response }) => { return response(200).json({ id: params.id }); }), http.post("/users", async ({ request, response }) => { const userData = await request.json(); return response(201).json({ id: 1, ...userData }); }), ]; const organizationHandlers = [ http.get("/organizations", ({ response }) => response(200).json([])), http.get("/organizations/{id}", ({ params, response }) => { return response(200).json({ id: params.id }); }), ]; const allHandlers = [...userHandlers, ...organizationHandlers]; const server = setupServer(...allHandlers); ``` -------------------------------- ### Accessing Query Parameters Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/ResponseResolverInfo.md Illustrates type-safe access to query parameters using methods like `get`, `getAll`, and `has`. The `size` property provides the count of parameters. ```typescript const http = createOpenApiHttp(); const handler = http.get("/items", ({ query }) => { const filter = query.get("filter"); const tags = query.getAll("tags"); if (query.has("sort", "asc")) { // Handle sorting } return HttpResponse.json({ count: query.size }); }); ``` -------------------------------- ### Testing Wildcard Handlers Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/wildcard-status-codes.md Provides an example of how to test a handler that uses a wildcard '5XX' status code. This test verifies that the handler is defined and can correctly return a JSON response with a specified 5XX status. ```typescript it("handles 5XX errors", () => { const handler = http.get("/api", ({ response }) => { return response("5XX").json( { error: "Server error" }, { status: 503 } ); }); expect(handler).toBeDefined(); }); ``` -------------------------------- ### Extract All Valid Paths for a Method Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/usage-patterns.md Use `PathsFor` to get a union type of all valid paths for a specific HTTP method (e.g., GET). This is useful for creating type-safe helper functions. ```typescript import type { PathsFor } from "openapi-msw"; const http = createOpenApiHttp(); type GetPaths = PathsFor; type PostPaths = PathsFor; // Use in helper functions function describeGetPaths(p: GetPaths) { // Only accepts valid GET paths } ``` -------------------------------- ### Combine openapi-msw with MSW setupServer Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/configuration.md Integrate openapi-msw handlers with MSW's setupServer for mocking API requests. Ensure to set up server listeners and reset handlers appropriately. ```typescript import { setupServer } from "msw/node"; const http = createOpenApiHttp({ baseUrl: "/api" }); const handlers = [ http.get("/users", ({ response }) => response(200).json([])), http.post("/users", ({ response }) => response(201).json({ id: 1 })), ]; const server = setupServer(...handlers); beforeAll(() => server.listen()); afterEach(() => server.resetHandlers()); afterAll(() => server.close()); ``` -------------------------------- ### Integration with MSW Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OVERVIEW.md Demonstrates the seamless integration of `openapi-msw` handlers with MSW's `setupServer` for Node.js environments and `setupWorker` for browser environments. ```APIDOC ## Integration with MSW openapi-msw handlers are fully compatible with MSW: ```typescript import { setupServer } from "msw/node"; import { setupWorker } from "msw/browser"; const http = createOpenApiHttp(); const handlers = [ http.get("/users", ({ response }) => response(200).json([])), http.post("/users", ({ response }) => response(201).json({})), ]; // Node testing const server = setupServer(...handlers); server.listen(); // Browser testing const worker = setupWorker(...handlers); worker.start(); ``` ``` -------------------------------- ### Define Typed POST Handler Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/createOpenApiHttp.md Example of defining a POST request handler with type safety for the request body and response. ```typescript const createResourceHandler = http.post( "/resource", async ({ request, response }) => { const data = await request.json(); return response(201).json(data); }, ); ``` -------------------------------- ### HttpOptions Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/types.md Configuration options for `createOpenApiHttp`. ```APIDOC ## HttpOptions ### Description Configuration options for `createOpenApiHttp`. ### Properties | Property | Type | Required | Description | |----------|------|----------|-------------| | baseUrl | `string` | No | Optional base URL prepended to all handler paths. Useful for API subpaths or different domains. Converted to MSW's colon path notation (e.g., `/api/v1/users/{id}` becomes `/api/v1/users/:id`). | ### Example ```typescript const http = createOpenApiHttp({ baseUrl: "/api/v1" }); ``` ``` -------------------------------- ### PathsFor Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/types.md Utility type that extracts all valid paths from a handler factory. Used for getting paths available to a specific HTTP method. ```APIDOC ## PathsFor ### Description Utility type that extracts all valid paths from a handler factory. Used for getting paths available to a specific HTTP method. ### Generic Parameter - `Handler` - An OpenApiHttpRequestHandler instance ### Returns Union of all paths for the handler's HTTP method ### Example ```typescript const http = createOpenApiHttp(); type GetPaths = PathsFor; // Union of all GET paths ``` ``` -------------------------------- ### Advanced Configuration: Multiple Instances Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/configuration.md Demonstrates creating multiple openapi-msw instances with different base URLs for managing distinct API versions or endpoints. ```typescript const http = createOpenApiHttp(); const httpV2 = createOpenApiHttp({ baseUrl: "/api/v2" }); // Use http for v1 endpoints (no baseUrl) // Use httpV2 for v2 endpoints ``` -------------------------------- ### Respond with Custom Headers Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/usage-patterns.md Define a GET request handler that returns a JSON response along with custom headers like 'x-custom-header' and 'cache-control'. ```typescript const handler = http.get("/data", ({ response }) => { return response(200).json( { data: "value" }, { headers: { "x-custom-header": "custom-value", "cache-control": "max-age=3600", }, } ); }); ``` -------------------------------- ### Create HTTP Handlers with Base URL Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/createOpenApiHttp.md Demonstrates using the `baseUrl` option to prepend a path to all defined handlers. ```typescript const httpWithBase = createOpenApiHttp({ baseUrl: "/api/v1" }); const handler = httpWithBase.get("/users", ({ response }) => { // This handler will match requests to /api/v1/users return response(200).json([]); }); ``` -------------------------------- ### Multiple Instances with Different Base URLs Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/configuration.md Demonstrates how to create multiple instances of createOpenApiHttp, each with a distinct baseUrl, to manage different API versions or paths within the same application. ```typescript const httpApi = createOpenApiHttp({ baseUrl: "/api" }); const httpAdmin = createOpenApiHttp({ baseUrl: "/admin" }); const apiHandler = httpApi.get("/users", ({ response }) => { return response(200).json([]); }); const adminHandler = httpAdmin.get("/users", ({ response }) => { return response(200).json([]); }); ``` -------------------------------- ### Untyped Response Fallback Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/usage-patterns.md Bypass type checking for non-standard responses using `response.untyped`. This example returns a JSON response with a 418 status code. ```typescript import { HttpResponse } from "msw"; const handler = http.get("/api/unusual", ({ response }) => { // Bypass type checking for non-standard responses return response.untyped( HttpResponse.json( { status: "I'm a teapot" }, { status: 418 } ) ); }); ``` -------------------------------- ### Configure createOpenApiHttp with Base URL Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/types.md Defines configuration options for `createOpenApiHttp`, including an optional base URL. The baseUrl is prepended to all handler paths and converted to MSW's colon path notation. ```typescript interface HttpOptions { baseUrl?: string; } ``` ```typescript const http = createOpenApiHttp({ baseUrl: "/api/v1" }); ``` -------------------------------- ### OpenAPI MSW Request Handling Flow Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/module-architecture.md Illustrates the step-by-step process of how an HTTP request is handled by MSW, including interception by createResolverWrapper and enhancement of the request information object. ```text HTTP request matches handler ↓ createResolverWrapper intercepts MSW resolver call ↓ Enhances info object: - Cast request to OpenApiRequest - Create QueryParams from request - Create response helper ↓ Calls user's resolver function ↓ User accesses: - params: Typed path parameters - query: Type-safe query access - request: Type-safe request body - response: Type-safe response builder ↓ User returns HttpResponse ↓ MSW sends response to client ``` -------------------------------- ### Configuring Base URL for Handlers Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/README.md Shows how to configure a base URL for all HTTP handlers created by `createOpenApiHttp`. This prepends the specified base URL to all handler paths. ```typescript const http = createOpenApiHttp({ baseUrl: "/api/v1" // Prepended to all handler paths }); ``` -------------------------------- ### Multiple Base URLs Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OVERVIEW.md Illustrates how to configure multiple base URLs for different API clients, allowing distinct handlers for APIs served from different base paths. ```APIDOC ## Advanced Patterns ### Multiple Base URLs ```typescript const httpApi = createOpenApiHttp({ baseUrl: "/api" }); const httpAdmin = createOpenApiHttp({ baseUrl: "/admin" }); const apiHandlers = [ httpApi.get("/users", ({ response }) => response(200).json([])), ]; const adminHandlers = [ httpAdmin.get("/users", ({ response }) => response(200).json([])), ]; ``` ``` -------------------------------- ### Test with Multiple Handlers and Overrides Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/usage-patterns.md Set up a server with multiple handlers and demonstrate how to override existing handlers during testing. This is useful for isolating tests or simulating different server states. ```typescript const http = createOpenApiHttp(); const server = setupServer( http.get("/users", ({ response }) => response(200).json([])) ); beforeAll(() => server.listen()); afterEach(() => server.resetHandlers()); it("uses default handler", async () => { const response = await fetch("/users"); expect(response.status).toBe(200); }); it("can override handler", async () => { server.use( http.get("/users", ({ response }) => response(500).json({})) ); const response = await fetch("/users"); expect(response.status).toBe(500); }); ``` -------------------------------- ### Handle 4XX Client Error Status Codes Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/wildcard-status-codes.md Use the '4XX' wildcard for client-side errors. Provide a specific status code, for example, 422 for unprocessable entities. ```typescript const handler = http.post("/users", ({ response }) => { return response("4XX").json( { error: "Validation failed" }, { status: 422 } ); }); ``` -------------------------------- ### Create HTTP Client with Dynamic Base URL Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/configuration.md Construct a dynamic base URL before passing it to createOpenApiHttp. This is useful when the API version changes. ```typescript function createConfiguredHttp(apiVersion: string) { const baseUrl = `/api/${apiVersion}`; return createOpenApiHttp({ baseUrl }); } const httpV1 = createConfiguredHttp("v1"); const httpV2 = createConfiguredHttp("v2"); ``` -------------------------------- ### Per-Handler Configuration with MSW Options Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/configuration.md Illustrates how to apply MSW's RequestHandlerOptions, such as 'once: true', to individual handlers created by openapi-msw. ```typescript const handler = http.get("/users", ({ response }) => { return response(200).json([]); }, { // RequestHandlerOptions from MSW once: true, // Only match this handler once }); ``` -------------------------------- ### Add Handlers Dynamically to MSW Server Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/usage-patterns.md Demonstrates how to add new handlers or override existing ones dynamically to an MSW server instance after it has been set up. This is useful for updating mock behavior during testing. ```typescript const http = createOpenApiHttp(); const server = setupServer(); server.listen(); // Later, add more handlers server.use( http.get("/new-endpoint", ({ response }) => response(200).json({})) ); // Override existing handler server.use( http.get("/users", ({ response }) => response(200).json([])) ); ``` -------------------------------- ### Conditional Responses based on Request Body Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/usage-patterns.md Implement conditional logic within a POST request handler. This example checks for specific username and password credentials to return different responses. ```typescript const handler = http.post("/auth/login", async ({ request, response }) => { const { username, password } = await request.json(); if (username === "admin" && password === "correct") { return response(200).json({ token: "jwt-token-here", user: { id: 1, username: "admin" }, }); } return response(401).json({ error: "Invalid credentials", }); }); ``` -------------------------------- ### Component Relationships Diagram Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OVERVIEW.md Illustrates the relationship between createOpenApiHttp, OpenApiHttpHandlers, and individual HTTP method handlers. ```plaintext createOpenApiHttp() ↓ Creates OpenApiHttpHandlers ├── http.get/post/put/patch/delete/head/options │ └── Each is OpenApiHttpRequestHandler │ └── Takes path, resolver, options? │ └── resolver receives ResponseResolverInfo │ ├── params: PathParams │ ├── request: OpenApiRequest │ ├── query: QueryParams │ └── response: OpenApiResponse └── http.untyped └── Direct access to MSW's http object ``` -------------------------------- ### Query Parameters Class Definition Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/module-architecture.md Defines the `QueryParams` class for type-safe access to URL query parameters. It wraps the native `URLSearchParams` and provides methods like `get`, `getAll`, and `has` with type safety. ```typescript export class QueryParams { constructor(request: Request) { this.#searchParams = new URL(request.url).searchParams; } get size(): number get(name: Name): ParamValuesGet[Name] getAll(name: Name): ParamValuesGetAll[Name] has(name: Name, value?: Params[Name]): boolean } ``` -------------------------------- ### Handling Multiple Path Parameters Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/usage-patterns.md Shows how to extract multiple parameters from a URL path. Each parameter is available in the `params` object. ```typescript const handler = http.get( "/organizations/{orgId}/teams/{teamId}/members/{memberId}", ({ params, response }) => { const orgId = params.orgId; const teamId = params.teamId; const memberId = params.memberId; return response(200).json({ orgId, teamId, memberId, }); } ); ``` -------------------------------- ### Handle Empty Base URL Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/path-utilities.md Demonstrates that providing an empty string for the base URL does not alter the path conversion to MSW's colon notation. ```typescript convertToColonPath("/users/{id}", ""); // Returns: "/users/:id" (empty string doesn't affect result) ``` -------------------------------- ### Retrieving a Single Query Parameter Value Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/QueryParams.md Shows how to use the `get` method to retrieve a single value for a query parameter. It handles required and optional parameters, returning `null` for absent optional ones. ```typescript const handler = http.get("/items", ({ query }) => { // Assuming OpenAPI spec defines: // - filter (required string) // - sort (optional enum: "asc" | "desc") const filter = query.get("filter"); // string const sort = query.get("sort"); // "asc" | "desc" | null return HttpResponse.json({ filter, sort }); }); ``` -------------------------------- ### Handling Wildcard Status Codes Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/README.md Demonstrates how to use wildcard status codes (e.g., '5XX') and provide a specific matching status code. ```typescript response("5XX").json( { error: "Server error" }, { status: 503 } ); ``` -------------------------------- ### HTTP Handler Factory Creation Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/module-architecture.md Creates a generic HTTP handler wrapper for different methods. This function is used internally to generate specific handlers like 'get', 'post', etc., by abstracting common logic such as path conversion and resolver wrapping. ```typescript function createHttpWrapper(method, httpOptions) { return (path, resolver, options) => { const mswPath = convertToColonPath(path, httpOptions?.baseUrl); const mswResolver = createResolverWrapper(resolver); return http[method](mswPath, mswResolver, options); }; } export function createOpenApiHttp(options?) { return { get: createHttpWrapper("get", options), post: createHttpWrapper("post", options), // ... other methods untyped: http, }; } ``` -------------------------------- ### Type-Safe Query Parameter Access with 'query' Helper Source: https://github.com/christoph-fricke/openapi-msw/blob/main/README.md Use the 'query' helper for type-safe access to URL query parameters. It wraps URLSearchParams and supports methods like get(), getAll(), has(), and size. Ensure your OpenAPI spec defines the expected query parameters. ```typescript const http = createOpenApiHttp(); const handler = http.get("/query-example", ({ query }) => { const filter = query.get("filter"); // string const sort = query.get("sort"); // "asc" | "desc" | null const sortBy = query.getAll("sortBy"); // string[] // Supported methods from URLSearchParams: get(), getAll(), has(), size if (query.has("sort", "asc")) { /* ... */ } return HttpResponse.json({ /* ... */ }); }); ``` -------------------------------- ### Handling Response Status and Content Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OVERVIEW.md Demonstrates how to define responses with specific status codes and content types. Invalid status codes or content types will result in TypeScript errors. ```typescript // ✓ Valid - 200 is defined with json content response(200).json({ data: "value" }); // ✗ Invalid - 204 No Content can't have body response(204).json({ data: "value" }); // Type error // ✗ Invalid - status code not defined in schema response(999).json({}); // Type error ``` -------------------------------- ### Recommended TypeScript Configuration Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/configuration.md Provides essential tsconfig.json settings for optimal compatibility with openapi-msw and modern TypeScript features. ```json { "compilerOptions": { "target": "ES2020", "module": "ESNext", "moduleResolution": "bundler", "strict": true, "skipLibCheck": true, "esModuleInterop": true, "moduleDetection": "force" } } ``` -------------------------------- ### Status Constructor Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OpenApiResponse.md The `response(status)` method initiates the construction of typed HTTP responses. It accepts a status code defined in the OpenAPI specification and returns an object with methods for defining the response body and type. ```APIDOC ## Status Constructor ### Description Calling `response(status)` returns an object with methods for constructing typed responses. This method is used to specify the HTTP status code for the response, ensuring it aligns with the OpenAPI schema. ### Method Signature ```typescript response(status: Status) ``` ### Parameters #### Path Parameters - **status** (Status extends keyof ResponseMap) - Required - HTTP status code defined in the OpenAPI spec for this endpoint. Only valid status codes are accepted. Can be a numeric status code or a wildcard (e.g., "5XX", "default"). ### Return Type An object with the following methods: ```typescript { text: TextResponse, Status>; json: JsonResponse, Status>; empty: EmptyResponse; } ``` Each method's availability depends on whether that content type is defined for the given status in the OpenAPI spec. TypeScript will enforce these constraints. ``` -------------------------------- ### Use OpenAPI-MSW Handlers with MSW Server Source: https://github.com/christoph-fricke/openapi-msw/blob/main/README.md Handlers created with OpenAPI-MSW are instances of HttpHandler and can be used directly with MSW's setupServer function. ```typescript import { setupServer } from "msw/node"; // Use the handlers defined above const server = setupServer(getHandler, postHandler); server.listen(); ``` -------------------------------- ### Retrieving All Values of a Query Parameter Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/QueryParams.md Demonstrates using the `getAll` method to retrieve all values for a query parameter as an array, even if the parameter is not defined as an array in the schema. ```typescript const handler = http.get("/search", ({ query }) => { // Assuming OpenAPI spec defines: // - tags (optional array of strings) const tags = query.getAll("tags"); // string[] return HttpResponse.json({ tags }); }); ``` -------------------------------- ### Provide Base URL for Paths Source: https://github.com/christoph-fricke/openapi-msw/blob/main/README.md Configure a base URL when creating the http object to prepend it to all defined paths. This is useful for APIs hosted on subpaths or different domains. ```typescript const http = createOpenApiHttp({ baseUrl: "/api/rest" }); // Requests will be matched by MSW against "/api/rest/resource" export const getHandler = http.get("/resource", () => { return HttpResponse.json(/* ... */); }); ``` -------------------------------- ### Handling Single Path Parameter Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/usage-patterns.md Demonstrates how to access a single path parameter from the request. The parameter is typed as a string. ```typescript const handler = http.get("/users/{id}", ({ params, response }) => { const userId = params.id; // Type: string return response(200).json({ id: userId, name: "User " + userId, }); }); ``` -------------------------------- ### Catch-all Handler for Unknown Paths Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/usage-patterns.md Use `http.untyped.all` to create a catch-all handler for any path that is not explicitly defined in your OpenAPI schema. This handler logs the request URL. ```typescript const http = createOpenApiHttp(); // For paths not in OpenAPI spec const catchAllHandler = http.untyped.all("*/unknown", ({ request }) => { return HttpResponse.json({ message: "Caught unknown path", path: request.url, }); }); ``` -------------------------------- ### Accessing Untyped MSW Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/OVERVIEW.md Shows how to use the `untyped` property to create handlers for paths not defined in the OpenAPI schema, providing a catch-all mechanism for unknown routes. ```APIDOC ## Accessing Untyped MSW For paths not defined in your OpenAPI schema, use the `untyped` property: ```typescript const http = createOpenApiHttp(); // Catch-all handler using untyped MSW const catchAll = http.untyped.all("/unknown/*", ({ request }) => { return HttpResponse.json({ caught: true }); }); ``` ``` -------------------------------- ### Convert Path Notation Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/module-architecture.md Converts path notation from OpenAPI format (e.g., /users/{id}) to MSW format (e.g., /users/:id). Optionally prepends a base URL. ```typescript export function convertToColonPath(path: string, baseUrl?: string): string { const resolvedPath = path.replaceAll("{ ", ": ").replaceAll("}", ""); if (!baseUrl) return resolvedPath; return baseUrl + resolvedPath; } ``` -------------------------------- ### Using Specific Status Codes Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/wildcard-status-codes.md Illustrates how to use a specific HTTP status code. The status code is automatically inferred and does not require an explicit `status` property in the options. ```typescript return response(200).json({ data: "value" }); // Status code 200 is automatically set ``` -------------------------------- ### Convert OpenAPI Path to MSW Colon Path (With Base URL) Source: https://github.com/christoph-fricke/openapi-msw/blob/main/_autodocs/api-reference/path-utilities.md Converts OpenAPI path parameters to MSW's colon notation and prepends an optional base URL. Use this when your MSW handlers are nested under a specific API version or prefix. ```typescript convertToColonPath("/users/{id}", "/api/v1"); // Returns: "/api/v1/users/:id" convertToColonPath("/resource", "/api"); // Returns: "/api/resource" ```