Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
fc8c4ba
feat(wip): implement the `defineNetwork` API
kettanaito Jan 10, 2026
30f32a8
fix(ws): implement the handler lookup handling
kettanaito Jan 10, 2026
f65e91d
fix: implement `setupServer` and `SetupServerCommonApi`
kettanaito Jan 11, 2026
2b64a7f
fix: implement `setupWorker`
kettanaito Jan 11, 2026
980f4be
chore: remove legacy `msw/node` apis
kettanaito Jan 11, 2026
92d4fb7
chore: comment on the `WebSocketInterceptor` type error
kettanaito Jan 11, 2026
28d69b4
fix: annotate network frames on source level as unknown
kettanaito Jan 13, 2026
c7bc89e
chore: use instanceof checks for frame handling
kettanaito Jan 13, 2026
9caaf66
chore: ignore `BatchInterceptor` listener type inference issue
kettanaito Jan 13, 2026
3f4b90f
chore: do not reference `~/core` in core
kettanaito Jan 13, 2026
d3659be
chore: use `rettime` for life cycle events
kettanaito Jan 13, 2026
2ee72e3
fix(ts): infer event maps from network sources
kettanaito Jan 13, 2026
c47b26f
chore: remove old `setupWorker`
kettanaito Jan 13, 2026
1a9a94b
chore: use `#core` import alias
kettanaito Jan 14, 2026
2d33af0
fix(setupWorker): add node.js environment check
kettanaito Jan 14, 2026
bfbe16c
chore: fix some tests
kettanaito Jan 14, 2026
12ddb9f
fix(onUnhandledFrame): check for common assets after function check
kettanaito Jan 14, 2026
48160ec
fix: use node 24, surface lookup errors
kettanaito Jan 14, 2026
7e2bf32
chore: fix type issues, run on node 22
kettanaito Jan 14, 2026
36d8f5a
fix(setupWorker): print stop message on `.disable()`
kettanaito Jan 14, 2026
cb28c95
fix(defineNetwork): merge `controller` and `handlers` options
kettanaito Jan 14, 2026
fd3776e
chore(setupWorker): reorder imports
kettanaito Jan 14, 2026
99cc047
fix(setupWorker): forward start options to service worker source
kettanaito Jan 14, 2026
6359d63
fix(setupWorker): print `worker.scriptURL` in the start message
kettanaito Jan 15, 2026
570a2ac
fix(defineNetwork): implement `.configure()` for late config options
kettanaito Jan 28, 2026
9ce2912
chore: fix signature overload type error by updating `rettime`
kettanaito Jan 28, 2026
a5e09f2
chore: fix formatting issues
kettanaito Jan 28, 2026
e289a7b
fix(defineNetwork): create handlers controller immediately
kettanaito Jan 28, 2026
4b26dbf
fix(setupWorker): print start message in `start`, add redundant start…
kettanaito Jan 28, 2026
8a8c121
fix(setupWorker): skip the start message in quiet mode
kettanaito Feb 2, 2026
fc62bed
Merge branch 'main' into fix/define-network
kettanaito Feb 4, 2026
4255969
test: remove `not.toBeAny` assertions from `define-network` tests
kettanaito Feb 4, 2026
29032f3
feat(handlers): store handlers as a kind-based map
kettanaito Feb 4, 2026
5534df7
fix: export `defaultNetworkOptions` from `/node` and `/native`
kettanaito Feb 4, 2026
87239cf
chore: fix formatting linting errors
kettanaito Feb 4, 2026
9bc1223
fix: export new apis under `msw/future`
kettanaito Feb 4, 2026
c85308b
chore: rename `new` to `future`
kettanaito Feb 4, 2026
4c8dd58
fix(worker): formatting of the integrity check
kettanaito Feb 6, 2026
0c77bfb
fix(worker): use `ResponseEvent` for life-cycle events
kettanaito Feb 6, 2026
a5b7c21
fix(WebSocketFrame): implement custom `WebSocketConnectionEvent`
kettanaito Feb 6, 2026
61e5443
fix(worker): return worker registration from `start`
kettanaito Feb 6, 2026
00ba8ba
fix(worker): dispatch "msw:worker/stop" on `stop`
kettanaito Feb 6, 2026
d676202
fix: forward `quiet` onto handled resolution context
kettanaito Feb 6, 2026
6572d07
Merge branch 'main' into fix/define-network
kettanaito Feb 9, 2026
061c3a6
chore: implement print start/stop messages as methods of sources
kettanaito Feb 9, 2026
570ad2d
fix(http-frame): emit `request:end` for bypassed requests
kettanaito Feb 9, 2026
847c837
fix(sw-source): set `url` on the response instance
kettanaito Feb 9, 2026
4985c5f
fix(setupWorker): dispatch `msw/worker:stop` after disabling network
kettanaito Feb 9, 2026
d6b6cb3
fix(setupWorker): support passthrough after stop
kettanaito Feb 9, 2026
56d48b7
test: refactor ws.clients test
kettanaito Feb 9, 2026
e2af5aa
fix(setupWorker): simplify the handler exception error message
kettanaito Feb 9, 2026
ea91f99
fix(setupWorker): add redundant `worker.stop()` warning
kettanaito Feb 9, 2026
4fefde8
Merge branch 'main' into fix/define-network
kettanaito Feb 11, 2026
96719b9
fix(setupWorker): add deprecated `waitUntilReady` start option
kettanaito Feb 13, 2026
56e59ab
fix(ws): attach logger before `connection` is emitted
kettanaito Feb 13, 2026
ed5e2ff
fix: execute unhandled frame handle as a part of `frame.resolve`
kettanaito Feb 13, 2026
31fe40f
fix(worker): add missing worker scope validation
kettanaito Feb 13, 2026
3b27f59
test(iframe): fix flaky test
kettanaito Feb 13, 2026
b7569e6
test(in-flight): polish the test
kettanaito Feb 13, 2026
e3c9560
fix(worker): do not call `super.disable()` to handle in-flight requests
kettanaito Feb 13, 2026
7e00faa
fix(worker): add a slight negative delay to `interceptedAt`
kettanaito Feb 13, 2026
b0c0e5f
test(post-formdata): simplify the test case
kettanaito Feb 13, 2026
6ae4a5e
chore: rename `/future` to `/experimental`
kettanaito Feb 13, 2026
98a53e9
fix(ws): iterate over `handlers` via `for` to propagate `kConnect` ex…
kettanaito Feb 13, 2026
5cc920c
fix(worker): remove `interceptedAt` compensation, improve test
kettanaito Feb 14, 2026
a4be9ac
test: add exception handling node.js tests
kettanaito Feb 15, 2026
b4539da
test: use `expect.fail`
kettanaito Feb 16, 2026
392665b
chore: polish, `NetworkFrameEvent`
kettanaito Feb 16, 2026
70d7f60
fix: revert `engines` in `package.json`
kettanaito Feb 16, 2026
c4c968f
fix: export http/ws event map types from `experimental`
kettanaito Feb 16, 2026
901f76f
test(onUnhandledFrame): add unit tests
kettanaito Feb 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: 'pnpm'

- name: Install dependencies
Expand Down Expand Up @@ -93,7 +93,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: 'pnpm'

- name: Restore build cache
Expand Down Expand Up @@ -129,7 +129,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: 'pnpm'

- name: Restore build cache
Expand Down Expand Up @@ -195,7 +195,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: 'pnpm'

- name: Install dependencies
Expand All @@ -220,7 +220,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: 'pnpm'

- name: Restore build cache
Expand Down Expand Up @@ -263,7 +263,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: 'pnpm'

- name: Restore build cache
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/compat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22

- name: Set up pnpm
uses: pnpm/action-setup@v4
Expand Down Expand Up @@ -62,7 +62,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22

- uses: pnpm/action-setup@v4
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22

- name: Set up pnpm
uses: pnpm/action-setup@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/smoke-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22

- name: Set up pnpm
uses: pnpm/action-setup@v4
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/typescript-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22

- name: Get latest TypeScript version
id: get-versions
Expand Down Expand Up @@ -42,7 +42,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22

- name: Set up pnpm
uses: pnpm/action-setup@v4
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v20
v22
4 changes: 2 additions & 2 deletions config/replaceCoreImports.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const CORE_ESM_IMPORT_PATTERN = /from ["'](~\/core(.*))["'](;)?/gm
const CORE_CJS_IMPORT_PATTERN = /require\(["'](~\/core(.*))["']\)(;)?/gm
const CORE_ESM_IMPORT_PATTERN = /from ["'](#core(.*))["'](;)?/gm
const CORE_CJS_IMPORT_PATTERN = /require\(["'](#core(.*))["']\)(;)?/gm

function getCoreImportPattern(isEsm) {
return isEsm ? CORE_ESM_IMPORT_PATTERN : CORE_CJS_IMPORT_PATTERN
Expand Down
16 changes: 8 additions & 8 deletions config/scripts/patch-ts.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ async function patchTypeDefs() {

if (typeDefsWithCoreImports.length === 0) {
console.log(
'Found no .d.ts modules containing the "~/core" import, skipping...',
'Found no .d.ts modules containing the "#core" import, skipping...',
)
return process.exit(0)
}

console.log(
'Found %d module(s) with the "~/core" import, resolving...',
'Found %d module(s) with the "#core" import, resolving...',
typeDefsWithCoreImports.length,
)

Expand All @@ -56,9 +56,9 @@ async function patchTypeDefs() {
typeDefsWithCoreImports.length,
)

// Next, validate that we left no "~/core" imports unresolved.
// Next, validate that we left no "#core" imports unresolved.
const result = await execAsync(
`grep "~/core" ./**/*.d.{ts,mts} -R -l || exit 0`,
`grep "#core" ./**/*.d.{ts,mts} -R -l || exit 0`,
{
cwd: BUILD_DIR,
shell: '/bin/bash',
Expand All @@ -67,7 +67,7 @@ async function patchTypeDefs() {

invariant(
result.stderr === '',
'Failed to validate the .d.ts modules for the presence of the "~/core" import. See the original error below.',
'Failed to validate the .d.ts modules for the presence of the "#core" import. See the original error below.',
result.stderr,
)

Expand All @@ -77,7 +77,7 @@ async function patchTypeDefs() {
.filter(Boolean)

console.error(
`Found .d.ts modules containing unresolved "~/core" import after the patching:
`Found .d.ts modules containing unresolved "#core" import after the patching:

${modulesWithUnresolvedImports.map((path) => ` - ${new URL(path, BUILD_DIR).pathname}`).join('\n')}
`,
Expand All @@ -86,7 +86,7 @@ ${modulesWithUnresolvedImports.map((path) => ` - ${new URL(path, BUILD_DIR).pat
return process.exit(1)
}

// Ensure that the .d.ts files compile without errors after resolving the "~/core" imports.
// Ensure that the .d.ts files compile without errors after resolving the "#core" imports.
console.log('Compiling the .d.ts modules with tsc...')
const tscCompilation = await execAsync(
`tsc --noEmit --skipLibCheck ${typeDefsPaths.join(' ')}`,
Expand Down Expand Up @@ -135,7 +135,7 @@ ${modulesWithUnresolvedImports.map((path) => ` - ${new URL(path, BUILD_DIR).pat
}

console.log(
'The "~/core" imports resolved successfully in %d .d.ts modules! 🎉',
'The "#core" imports resolved successfully in %d .d.ts modules! 🎉',
typeDefsWithCoreImports.length,
)
}
Expand Down
13 changes: 13 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,22 @@
"default": "./lib/core/ws.js"
}
},
"./experimental": {
"import": {
"types": "./lib/core/experimental/index.d.mts",
"default": "./lib/core/experimental/index.mjs"
},
"default": {
"types": "./lib/core/experimental/index.d.ts",
"default": "./lib/core/experimental/index.js"
}
},
"./mockServiceWorker.js": "./lib/mockServiceWorker.js",
"./package.json": "./package.json"
},
"imports": {
"#core": "./src/core"
},
"bin": {
"msw": "cli/index.js"
},
Expand Down
50 changes: 17 additions & 33 deletions src/browser/setupWorker/glossary.ts → src/browser/glossary.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,13 @@
import { Emitter } from 'strict-event-emitter'
import type { HttpRequestEventMap, Interceptor } from '@mswjs/interceptors'
import type { DeferredPromise } from '@open-draft/deferred-promise'
import {
LifeCycleEventEmitter,
LifeCycleEventsMap,
SharedOptions,
} from '~/core/sharedOptions'
import { RequestHandler } from '~/core/handlers/RequestHandler'
import type { RequiredDeep } from '~/core/typeUtils'
import type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'
import type { WorkerChannel } from '../utils/workerChannel'
import type { LifeCycleEventEmitter, SharedOptions } from '#core/sharedOptions'
import type { RequiredDeep } from '#core/typeUtils'
import type { HttpNetworkFrameEventMap } from '#core/experimental/frames/http-frame'
import type { WebSocketNetworkFrameEventMap } from '#core/experimental/frames/websocket-frame'
import { AnyHandler } from '#core/experimental/handlers-controller'

export interface StringifiedResponse extends ResponseInit {
body: string | ArrayBuffer | ReadableStream<Uint8Array> | null
}

export type SetupWorkerInternalContext = {
isMockingEnabled: boolean
workerStoppedAt?: number
startOptions: RequiredDeep<StartOptions>
workerPromise: DeferredPromise<ServiceWorker>
registration: ServiceWorkerRegistration | undefined
getRequestHandlers: () => Array<RequestHandler | WebSocketHandler>
emitter: Emitter<LifeCycleEventsMap>
keepAliveInterval?: number
workerChannel: WorkerChannel
fallbackInterceptor?: Interceptor<HttpRequestEventMap>
}

export type ServiceWorkerInstanceTuple = [
ServiceWorker | null,
ServiceWorkerRegistration,
Expand Down Expand Up @@ -62,6 +42,7 @@ export interface StartOptions extends SharedOptions {
* Defers any network requests until the Service Worker
* instance is activated.
* @default true
* @deprecated
*/
waitUntilReady?: boolean

Expand All @@ -81,6 +62,9 @@ export type StartHandler = (

export type StopHandler = () => void

/**
* @deprecated Use the `SetupWorkerApi` type instead.
*/
export interface SetupWorker {
/**
* Registers and activates the mock Service Worker.
Expand All @@ -98,11 +82,11 @@ export interface SetupWorker {

/**
* Prepends given request handlers to the list of existing handlers.
* @param {RequestHandler[]} handlers List of runtime request handlers.
* @param {Array<AnyHandler>} handlers List of runtime request handlers.
*
* @see {@link https://mswjs.io/docs/api/setup-worker/use `worker.use()` API reference}
*/
use: (...handlers: Array<RequestHandler | WebSocketHandler>) => void
use: (...handlers: Array<AnyHandler>) => void

/**
* Marks all request handlers that respond using `res.once()` as unused.
Expand All @@ -113,26 +97,26 @@ export interface SetupWorker {

/**
* Resets request handlers to the initial list given to the `setupWorker` call, or to the explicit next request handlers list, if given.
* @param {RequestHandler[]} nextHandlers List of the new initial request handlers.
* @param {Array<AnyHandler>} nextHandlers List of the new initial request handlers.
*
* @see {@link https://mswjs.io/docs/api/setup-worker/reset-handlers `worker.resetHandlers()` API reference}
*/
resetHandlers: (
...nextHandlers: Array<RequestHandler | WebSocketHandler>
) => void
resetHandlers: (...nextHandlers: Array<AnyHandler>) => void

/**
* Returns a readonly list of currently active request handlers.
*
* @see {@link https://mswjs.io/docs/api/setup-worker/list-handlers `worker.listHandlers()` API reference}
*/
listHandlers(): ReadonlyArray<RequestHandler | WebSocketHandler>
listHandlers: () => ReadonlyArray<AnyHandler>

/**
* Life-cycle events.
* Life-cycle events allow you to subscribe to the internal library events occurring during the request/response handling.
*
* @see {@link https://mswjs.io/docs/api/life-cycle-events Life-cycle Events API reference}
*/
events: LifeCycleEventEmitter<LifeCycleEventsMap>
events: LifeCycleEventEmitter<
HttpNetworkFrameEventMap | WebSocketNetworkFrameEventMap
>
}
5 changes: 2 additions & 3 deletions src/browser/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export { setupWorker } from './setupWorker/setupWorker'
export type { SetupWorker, StartOptions } from './setupWorker/glossary'
export { SetupWorkerApi } from './setupWorker/setupWorker'
export { setupWorker, type SetupWorkerApi } from './setup-worker'
export type { SetupWorker, StartOptions } from './glossary'
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
/**
* @vitest-environment node
*/
import { setupWorker } from './setupWorker'
// @vitest-environment node
import { setupWorker } from './setup-worker'

test('returns an error when run in a Node.js environment', () => {
expect(setupWorker).toThrow(
Expand Down
Loading
Loading