Skip to content

Expose Additional Internal Utilities and Types for Enhanced Customization #2556

@SerkanSipahi

Description

@SerkanSipahi

Scope

Improves an existing behavior

Compatibility

  • This is a breaking change

Feature description

I'd like to propose enhancing the modularity and extensibility of the msw (mock-service-worker) library by officially exposing a broader set of internal utilities and TypeScript types. This change will help advanced users extend or customize core functionality (such as building custom handlers modeled after HttpHandler) without relying on unstable deep imports. The proposal is based on prior discussions with @kettanaito (https://discord.com/channels/1147615585732132865/1345284805507547136/1371545502184767662) and practical experience from my own custom implementation.

Motivation

  • Reuse of Internal Logic: While extending HttpHandler, I found it extremely helpful to access certain internal utilities (e.g., cookie parsing, URL handling, logging, and string utilities). However, these are not publicly exposed and require cloning the project and exposing which can break with internal changes on any updates (git pull)
  • Type Safety & Autocomplete: Many useful TypeScript types and interfaces are not accessible via stable, public paths. This increases friction for contributors and advanced users who wish to build robust, type-safe extensions.
  • Community Impact: Streamlining access to these internals would unlock new integrations, tools, and customizations that are currently cumbersome or fragile to implement. It would empower the community to innovate on top of msw without risking compatibility issues from changing deep imports.

Functions & Types Proposed for Exposure

Utilities (already tested in my fork) exposed by myself in src/core/index.ts

export { devUtils } from './utils/internal/devUtils';
export { isStringEqual } from './utils/internal/isStringEqual';
export { getAllRequestCookies } from './utils/request/getRequestCookies';
export { toPublicUrl } from './utils/request/toPublicUrl';
export { serializeRequest } from './utils/logging/serializeRequest';
export { serializeResponse } from './utils/logging/serializeResponse';
export { getStatusCodeColor } from './utils/logging/getStatusCodeColor';
export { getTimestamp } from './utils/logging/getTimestamp';
export { getSearchParams } from './utils/url/cleanUrl';

Types/Interfaces (current situation: require deep import)

Instead of:

import type {
  HttpHandlerInfo,
  HttpRequestParsedResult,
  HttpRequestResolverExtras,
} from 'msw/lib/core/handlers/HttpHandler';

Suggest:

import type {
  HttpHandlerInfo,
  HttpRequestParsedResult,
  HttpRequestResolverExtras,
} from 'msw/types';
  • Other potential types/interfaces: request/response shapes, handler interfaces, payload types, URL-related types, etc.

Open Questions

  • Which Internal Utils to Expose?

    • Some utilities are tightly coupled to internals and should remain private.
    • Suggest reviewing all core utils and only exposing those that are broadly useful and unlikely to cause confusion/misuse.
    • Consider maintaining a whitelist and documenting each exposed function's intended usage.
  • How to Structure Type Exports?

    • Should core types (HttpHandler, request/response types, etc.) be grouped under a clearly named export (e.g., msw/core)?
    • What are the criteria for "public" vs. "internal" types?

Proposed Actions

  • Expose the listed utilities and document their intended usage with short code examples.
  • Identify and re-export the main TypeScript interfaces and generics required for advanced customization, making them available from a stable path (e.g., msw/core or msw/types).
  • Add a small note to the documentation warning that non-exposed internal utilities may change without notice and should not be imported via deep paths.

Feedback & Next Steps

I'd appreciate input on which functions or types might be unsuitable for exposure or whether a different exposure strategy would be preferred. Once there's consensus, I'm happy to help prepare the PR with documentation and migration notes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions