import { http, type HttpHandler, type RequestHandlerOptions } from "msw"; import type { AnyApiSpec, HttpMethod, PathsForMethod } from "./api-spec.ts"; import { convertToColonPath } from "./path-mapping.ts"; import { createResolverWrapper, type ResponseResolver, } from "./response-resolver.ts"; /** HTTP handler factory with type inference for provided api paths. */ export type OpenApiHttpRequestHandler< ApiSpec extends AnyApiSpec, Method extends HttpMethod, > = >( path: Path, resolver: ResponseResolver, options?: RequestHandlerOptions, ) => HttpHandler; function createHttpWrapper< ApiSpec extends AnyApiSpec, Method extends HttpMethod, >( method: Method, httpOptions?: HttpOptions, ): OpenApiHttpRequestHandler { return (path, resolver, options) => { const mswPath = convertToColonPath(path as string, httpOptions?.baseUrl); const mswResolver = createResolverWrapper(resolver); return http[method](mswPath, mswResolver, options); }; } /** Collection of enhanced HTTP handler factories for each available HTTP Method. */ export type OpenApiHttpHandlers = { [Method in HttpMethod]: OpenApiHttpRequestHandler; } & { untyped: typeof http }; export interface HttpOptions { /** Optional baseUrl that is prepended to the `path` of each HTTP handler. */ baseUrl?: string; } /** * Creates a wrapper around MSW's {@linkcode http} object, which is enhanced with * type inference from the provided OpenAPI-TS `paths` definition. * * **Usage** * ```typescript * import { HttpResponse } from "msw"; * import { createOpenApiHttp } from "openapi-msw"; * // 1. Import the paths from your OpenAPI schema definitions * import type { paths } from "./your-openapi-schema"; * * // 2. Provide your paths definition to enable type inference in HTTP handlers * const http = createOpenApiHttp(); * * // TS only suggests available GET paths * const handler = http.get("/resource/{id}", ({ params }) => { * const id = params.id; * return HttpResponse.json({ id, other: "..." }); * }); * ``` * * @param options Additional options that are used by all defined HTTP handlers. */ export function createOpenApiHttp( options?: HttpOptions, ): OpenApiHttpHandlers { return { get: createHttpWrapper("get", options), put: createHttpWrapper("put", options), post: createHttpWrapper("post", options), delete: createHttpWrapper("delete", options), options: createHttpWrapper("options", options), head: createHttpWrapper("head", options), patch: createHttpWrapper("patch", options), untyped: http, }; }