@depup/msw 2.13.2-depup.0 → 2.15.0-depup.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -12
- package/changes.json +14 -26
- package/cli/init.js +1 -1
- package/lib/browser/index.js +547 -177
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/index.mjs +547 -177
- package/lib/browser/index.mjs.map +1 -1
- package/lib/core/{HttpResponse-DlRR1D-f.d.mts → HttpResponse-BE_Y2Ak9.d.mts} +52 -1
- package/lib/core/{HttpResponse-CksOMVAa.d.ts → HttpResponse-DL-P1EeG.d.ts} +52 -1
- package/lib/core/HttpResponse.d.mts +1 -1
- package/lib/core/HttpResponse.d.ts +1 -1
- package/lib/core/HttpResponse.js +2 -2
- package/lib/core/HttpResponse.js.map +1 -1
- package/lib/core/HttpResponse.mjs +2 -2
- package/lib/core/HttpResponse.mjs.map +1 -1
- package/lib/core/experimental/compat.d.mts +2 -2
- package/lib/core/experimental/compat.d.ts +2 -2
- package/lib/core/experimental/compat.js +1 -0
- package/lib/core/experimental/compat.js.map +1 -1
- package/lib/core/experimental/compat.mjs +1 -0
- package/lib/core/experimental/compat.mjs.map +1 -1
- package/lib/core/experimental/define-network.d.mts +2 -2
- package/lib/core/experimental/define-network.d.ts +2 -2
- package/lib/core/experimental/define-network.js +21 -11
- package/lib/core/experimental/define-network.js.map +1 -1
- package/lib/core/experimental/define-network.mjs +23 -11
- package/lib/core/experimental/define-network.mjs.map +1 -1
- package/lib/core/experimental/frames/http-frame.d.mts +2 -2
- package/lib/core/experimental/frames/http-frame.d.ts +2 -2
- package/lib/core/experimental/frames/http-frame.js +5 -2
- package/lib/core/experimental/frames/http-frame.js.map +1 -1
- package/lib/core/experimental/frames/http-frame.mjs +8 -3
- package/lib/core/experimental/frames/http-frame.mjs.map +1 -1
- package/lib/core/experimental/frames/network-frame.d.mts +2 -2
- package/lib/core/experimental/frames/network-frame.d.ts +2 -2
- package/lib/core/experimental/frames/network-frame.js +2 -0
- package/lib/core/experimental/frames/network-frame.js.map +1 -1
- package/lib/core/experimental/frames/network-frame.mjs +2 -0
- package/lib/core/experimental/frames/network-frame.mjs.map +1 -1
- package/lib/core/experimental/frames/websocket-frame.d.mts +2 -2
- package/lib/core/experimental/frames/websocket-frame.d.ts +2 -2
- package/lib/core/experimental/frames/websocket-frame.js +2 -0
- package/lib/core/experimental/frames/websocket-frame.js.map +1 -1
- package/lib/core/experimental/frames/websocket-frame.mjs +2 -0
- package/lib/core/experimental/frames/websocket-frame.mjs.map +1 -1
- package/lib/core/experimental/handlers-controller.d.mts +2 -1
- package/lib/core/experimental/handlers-controller.d.ts +2 -1
- package/lib/core/experimental/handlers-controller.js +31 -6
- package/lib/core/experimental/handlers-controller.js.map +1 -1
- package/lib/core/experimental/handlers-controller.mjs +31 -6
- package/lib/core/experimental/handlers-controller.mjs.map +1 -1
- package/lib/core/experimental/index.d.mts +5 -5
- package/lib/core/experimental/index.d.ts +5 -5
- package/lib/core/experimental/index.js +3 -1
- package/lib/core/experimental/index.js.map +1 -1
- package/lib/core/experimental/index.mjs +9 -2
- package/lib/core/experimental/index.mjs.map +1 -1
- package/lib/core/experimental/on-unhandled-frame.d.mts +2 -2
- package/lib/core/experimental/on-unhandled-frame.d.ts +2 -2
- package/lib/core/experimental/on-unhandled-frame.js +1 -0
- package/lib/core/experimental/on-unhandled-frame.js.map +1 -1
- package/lib/core/experimental/on-unhandled-frame.mjs +1 -0
- package/lib/core/experimental/on-unhandled-frame.mjs.map +1 -1
- package/lib/core/experimental/setup-api.d.mts +1 -1
- package/lib/core/experimental/setup-api.d.ts +1 -1
- package/lib/core/experimental/setup-api.js +2 -5
- package/lib/core/experimental/setup-api.js.map +1 -1
- package/lib/core/experimental/setup-api.mjs +2 -5
- package/lib/core/experimental/setup-api.mjs.map +1 -1
- package/lib/core/experimental/sources/interceptor-source.d.mts +2 -2
- package/lib/core/experimental/sources/interceptor-source.d.ts +2 -2
- package/lib/core/experimental/sources/interceptor-source.js +23 -10
- package/lib/core/experimental/sources/interceptor-source.js.map +1 -1
- package/lib/core/experimental/sources/interceptor-source.mjs +24 -13
- package/lib/core/experimental/sources/interceptor-source.mjs.map +1 -1
- package/lib/core/experimental/sources/network-source.d.mts +3 -3
- package/lib/core/experimental/sources/network-source.d.ts +3 -3
- package/lib/core/experimental/sources/network-source.js +1 -0
- package/lib/core/experimental/sources/network-source.js.map +1 -1
- package/lib/core/experimental/sources/network-source.mjs +2 -0
- package/lib/core/experimental/sources/network-source.mjs.map +1 -1
- package/lib/core/getResponse.d.mts +1 -1
- package/lib/core/getResponse.d.ts +1 -1
- package/lib/core/graphql.d.mts +1 -1
- package/lib/core/graphql.d.ts +1 -1
- package/lib/core/graphql.js +1 -0
- package/lib/core/graphql.js.map +1 -1
- package/lib/core/graphql.mjs +2 -0
- package/lib/core/graphql.mjs.map +1 -1
- package/lib/core/handlers/GraphQLHandler.d.mts +1 -1
- package/lib/core/handlers/GraphQLHandler.d.ts +1 -1
- package/lib/core/handlers/GraphQLHandler.js +1 -0
- package/lib/core/handlers/GraphQLHandler.js.map +1 -1
- package/lib/core/handlers/GraphQLHandler.mjs +4 -1
- package/lib/core/handlers/GraphQLHandler.mjs.map +1 -1
- package/lib/core/handlers/HttpHandler.d.mts +1 -1
- package/lib/core/handlers/HttpHandler.d.ts +1 -1
- package/lib/core/handlers/HttpHandler.js +1 -0
- package/lib/core/handlers/HttpHandler.js.map +1 -1
- package/lib/core/handlers/HttpHandler.mjs +1 -0
- package/lib/core/handlers/HttpHandler.mjs.map +1 -1
- package/lib/core/handlers/RequestHandler.d.mts +1 -1
- package/lib/core/handlers/RequestHandler.d.ts +1 -1
- package/lib/core/handlers/RequestHandler.js +197 -4
- package/lib/core/handlers/RequestHandler.js.map +1 -1
- package/lib/core/handlers/RequestHandler.mjs +198 -4
- package/lib/core/handlers/RequestHandler.mjs.map +1 -1
- package/lib/core/handlers/WebSocketHandler.d.mts +5 -2
- package/lib/core/handlers/WebSocketHandler.d.ts +5 -2
- package/lib/core/handlers/WebSocketHandler.js +30 -12
- package/lib/core/handlers/WebSocketHandler.js.map +1 -1
- package/lib/core/handlers/WebSocketHandler.mjs +30 -12
- package/lib/core/handlers/WebSocketHandler.mjs.map +1 -1
- package/lib/core/http.d.mts +1 -1
- package/lib/core/http.d.ts +1 -1
- package/lib/core/http.js +1 -0
- package/lib/core/http.js.map +1 -1
- package/lib/core/http.mjs +2 -0
- package/lib/core/http.mjs.map +1 -1
- package/lib/core/index.d.mts +1 -1
- package/lib/core/index.d.ts +1 -1
- package/lib/core/{network-frame-usYiHS0K.d.ts → on-unhandled-frame-0KmwUmeV.d.ts} +13 -13
- package/lib/core/{network-frame-B7A0ggXE.d.mts → on-unhandled-frame-gkokW4Rr.d.mts} +13 -13
- package/lib/core/passthrough.d.mts +1 -1
- package/lib/core/passthrough.d.ts +1 -1
- package/lib/core/sse.d.mts +4 -18
- package/lib/core/sse.d.ts +4 -18
- package/lib/core/sse.js +149 -66
- package/lib/core/sse.js.map +1 -1
- package/lib/core/sse.mjs +149 -66
- package/lib/core/sse.mjs.map +1 -1
- package/lib/core/utils/HttpResponse/decorators.d.mts +9 -4
- package/lib/core/utils/HttpResponse/decorators.d.ts +9 -4
- package/lib/core/utils/HttpResponse/decorators.js +18 -11
- package/lib/core/utils/HttpResponse/decorators.js.map +1 -1
- package/lib/core/utils/HttpResponse/decorators.mjs +18 -11
- package/lib/core/utils/HttpResponse/decorators.mjs.map +1 -1
- package/lib/core/utils/cookieStore.js.map +1 -1
- package/lib/core/utils/cookieStore.mjs.map +1 -1
- package/lib/core/utils/executeHandlers.d.mts +1 -1
- package/lib/core/utils/executeHandlers.d.ts +1 -1
- package/lib/core/utils/executeHandlers.js +1 -0
- package/lib/core/utils/executeHandlers.js.map +1 -1
- package/lib/core/utils/executeHandlers.mjs +1 -0
- package/lib/core/utils/executeHandlers.mjs.map +1 -1
- package/lib/core/utils/handleRequest.d.mts +1 -1
- package/lib/core/utils/handleRequest.d.ts +1 -1
- package/lib/core/utils/handleRequest.js.map +1 -1
- package/lib/core/utils/handleRequest.mjs.map +1 -1
- package/lib/core/utils/internal/Disposable.js +19 -1
- package/lib/core/utils/internal/Disposable.js.map +1 -1
- package/lib/core/utils/internal/Disposable.mjs +19 -1
- package/lib/core/utils/internal/Disposable.mjs.map +1 -1
- package/lib/core/utils/internal/attachSiblingHandlers.d.mts +15 -0
- package/lib/core/utils/internal/attachSiblingHandlers.d.ts +15 -0
- package/lib/core/utils/internal/attachSiblingHandlers.js +44 -0
- package/lib/core/utils/internal/attachSiblingHandlers.js.map +1 -0
- package/lib/core/utils/internal/attachSiblingHandlers.mjs +24 -0
- package/lib/core/utils/internal/attachSiblingHandlers.mjs.map +1 -0
- package/lib/core/utils/internal/isHandlerKind.d.mts +1 -1
- package/lib/core/utils/internal/isHandlerKind.d.ts +1 -1
- package/lib/core/utils/internal/observe-response-body-stream.d.mts +18 -0
- package/lib/core/utils/internal/observe-response-body-stream.d.ts +18 -0
- package/lib/core/utils/internal/observe-response-body-stream.js +64 -0
- package/lib/core/utils/internal/observe-response-body-stream.js.map +1 -0
- package/lib/core/utils/internal/observe-response-body-stream.mjs +44 -0
- package/lib/core/utils/internal/observe-response-body-stream.mjs.map +1 -0
- package/lib/core/utils/internal/parseGraphQLRequest.d.mts +1 -1
- package/lib/core/utils/internal/parseGraphQLRequest.d.ts +1 -1
- package/lib/core/utils/internal/parseMultipartData.d.mts +1 -1
- package/lib/core/utils/internal/parseMultipartData.d.ts +1 -1
- package/lib/core/utils/internal/parseMultipartData.js +1 -0
- package/lib/core/utils/internal/parseMultipartData.js.map +1 -1
- package/lib/core/utils/internal/parseMultipartData.mjs +1 -0
- package/lib/core/utils/internal/parseMultipartData.mjs.map +1 -1
- package/lib/core/utils/internal/pipeEvents.js +1 -0
- package/lib/core/utils/internal/pipeEvents.js.map +1 -1
- package/lib/core/utils/internal/pipeEvents.mjs +1 -0
- package/lib/core/utils/internal/pipeEvents.mjs.map +1 -1
- package/lib/core/utils/request/storeResponseCookies.js +1 -1
- package/lib/core/utils/request/storeResponseCookies.js.map +1 -1
- package/lib/core/utils/request/storeResponseCookies.mjs +2 -2
- package/lib/core/utils/request/storeResponseCookies.mjs.map +1 -1
- package/lib/core/ws/WebSocketClientManager.js +4 -0
- package/lib/core/ws/WebSocketClientManager.js.map +1 -1
- package/lib/core/ws/WebSocketClientManager.mjs +4 -0
- package/lib/core/ws/WebSocketClientManager.mjs.map +1 -1
- package/lib/core/ws/WebSocketIndexedDBClientStore.js +1 -0
- package/lib/core/ws/WebSocketIndexedDBClientStore.js.map +1 -1
- package/lib/core/ws/WebSocketIndexedDBClientStore.mjs +1 -0
- package/lib/core/ws/WebSocketIndexedDBClientStore.mjs.map +1 -1
- package/lib/core/ws/WebSocketMemoryClientStore.js +1 -0
- package/lib/core/ws/WebSocketMemoryClientStore.js.map +1 -1
- package/lib/core/ws/WebSocketMemoryClientStore.mjs +1 -0
- package/lib/core/ws/WebSocketMemoryClientStore.mjs.map +1 -1
- package/lib/core/ws/handleWebSocketEvent.d.mts +1 -1
- package/lib/core/ws/handleWebSocketEvent.d.ts +1 -1
- package/lib/core/ws/handleWebSocketEvent.js.map +1 -1
- package/lib/core/ws/handleWebSocketEvent.mjs.map +1 -1
- package/lib/core/ws.d.mts +17 -4
- package/lib/core/ws.d.ts +17 -4
- package/lib/core/ws.js +30 -5
- package/lib/core/ws.js.map +1 -1
- package/lib/core/ws.mjs +34 -6
- package/lib/core/ws.mjs.map +1 -1
- package/lib/iife/index.js +10138 -6034
- package/lib/iife/index.js.map +1 -1
- package/lib/mockServiceWorker.js +21 -9
- package/lib/native/index.js.map +1 -1
- package/lib/native/index.mjs.map +1 -1
- package/lib/node/index.d.mts +1 -1
- package/lib/node/index.d.ts +1 -1
- package/lib/node/index.js +2 -0
- package/lib/node/index.js.map +1 -1
- package/lib/node/index.mjs +1 -0
- package/lib/node/index.mjs.map +1 -1
- package/lib/shims/cookie.js +152 -62
- package/lib/shims/cookie.mjs +152 -62
- package/package.json +50 -69
- package/src/browser/glossary.ts +1 -1
- package/src/browser/setup-worker.ts +2 -2
- package/src/browser/sources/service-worker-source.ts +142 -40
- package/src/browser/utils/deserializeRequest.ts +2 -2
- package/src/browser/utils/pruneGetRequestBody.ts +3 -3
- package/src/browser/utils/should-invalidate-worker.test.ts +122 -0
- package/src/browser/utils/should-invalidate-worker.ts +13 -0
- package/src/browser/utils/workerChannel.ts +43 -21
- package/src/core/experimental/define-network.ts +44 -15
- package/src/core/experimental/frames/http-frame.test.ts +8 -2
- package/src/core/experimental/frames/http-frame.ts +12 -4
- package/src/core/experimental/frames/websocket-frame.test.ts +2 -4
- package/src/core/experimental/frames/websocket-frame.ts +3 -2
- package/src/core/experimental/handlers-controller.test.ts +139 -5
- package/src/core/experimental/handlers-controller.ts +39 -10
- package/src/core/experimental/index.ts +11 -1
- package/src/core/experimental/on-unhandled-frame.test.ts +2 -4
- package/src/core/experimental/setup-api.ts +4 -8
- package/src/core/experimental/sources/interceptor-source.ts +36 -16
- package/src/core/experimental/sources/network-source.ts +1 -1
- package/src/core/graphql.ts +8 -8
- package/src/core/handlers/GraphQLHandler.test.ts +3 -4
- package/src/core/handlers/GraphQLHandler.ts +15 -11
- package/src/core/handlers/HttpHandler.test.ts +92 -2
- package/src/core/handlers/HttpHandler.ts +7 -7
- package/src/core/handlers/RequestHandler.ts +329 -22
- package/src/core/handlers/WebSocketHandler.test.ts +58 -0
- package/src/core/handlers/WebSocketHandler.ts +37 -8
- package/src/core/http.ts +5 -5
- package/src/core/sse.ts +217 -73
- package/src/core/utils/HttpResponse/decorators.ts +28 -22
- package/src/core/utils/cookieStore.ts +1 -1
- package/src/core/utils/executeHandlers.ts +2 -4
- package/src/core/utils/handleRequest.test.ts +5 -4
- package/src/core/utils/handleRequest.ts +3 -3
- package/src/core/utils/internal/Disposable.ts +22 -1
- package/src/core/utils/internal/attachSiblingHandlers.ts +28 -0
- package/src/core/utils/internal/observe-response-body-stream.test.ts +64 -0
- package/src/core/utils/internal/observe-response-body-stream.ts +77 -0
- package/src/core/utils/internal/parseGraphQLRequest.test.ts +2 -4
- package/src/core/utils/internal/parseMultipartData.ts +1 -1
- package/src/core/utils/internal/pipeEvents.ts +2 -1
- package/src/core/utils/request/onUnhandledRequest.test.ts +2 -4
- package/src/core/utils/request/storeResponseCookies.ts +2 -4
- package/src/core/ws/WebSocketClientManager.test.ts +2 -4
- package/src/core/ws/WebSocketClientManager.ts +1 -1
- package/src/core/ws/WebSocketIndexedDBClientStore.ts +3 -5
- package/src/core/ws/WebSocketMemoryClientStore.ts +3 -5
- package/src/core/ws/handleWebSocketEvent.ts +3 -3
- package/src/core/ws.ts +66 -7
- package/src/mockServiceWorker.js +19 -7
- package/src/native/index.ts +2 -2
- package/src/node/async-handlers-controller.ts +2 -2
- package/src/node/index.ts +1 -0
- package/src/node/setup-server-common.ts +4 -4
- package/src/node/setup-server.ts +2 -2
- package/lib/core/utils/internal/requestHandlerUtils.d.mts +0 -12
- package/lib/core/utils/internal/requestHandlerUtils.d.ts +0 -12
- package/lib/core/utils/internal/requestHandlerUtils.js +0 -37
- package/lib/core/utils/internal/requestHandlerUtils.js.map +0 -1
- package/lib/core/utils/internal/requestHandlerUtils.mjs +0 -17
- package/lib/core/utils/internal/requestHandlerUtils.mjs.map +0 -1
- package/src/core/utils/internal/requestHandlerUtils.ts +0 -21
package/src/core/graphql.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import type { OperationTypeNode } from 'graphql'
|
|
2
2
|
import {
|
|
3
|
-
ResponseResolver,
|
|
4
|
-
RequestHandlerOptions,
|
|
3
|
+
type ResponseResolver,
|
|
4
|
+
type RequestHandlerOptions,
|
|
5
5
|
} from './handlers/RequestHandler'
|
|
6
6
|
import {
|
|
7
7
|
GraphQLHandler,
|
|
8
|
-
GraphQLVariables,
|
|
9
|
-
GraphQLOperationType,
|
|
10
|
-
GraphQLResolverExtras,
|
|
11
|
-
GraphQLResponseBody,
|
|
12
|
-
GraphQLQuery,
|
|
13
|
-
GraphQLPredicate,
|
|
8
|
+
type GraphQLVariables,
|
|
9
|
+
type GraphQLOperationType,
|
|
10
|
+
type GraphQLResolverExtras,
|
|
11
|
+
type GraphQLResponseBody,
|
|
12
|
+
type GraphQLQuery,
|
|
13
|
+
type GraphQLPredicate,
|
|
14
14
|
} from './handlers/GraphQLHandler'
|
|
15
15
|
import type { Path } from './utils/matching/matchRequestUrl'
|
|
16
16
|
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
// @vitest-environment jsdom
|
|
2
2
|
import { createRequestId, encodeBuffer } from '@mswjs/interceptors'
|
|
3
3
|
import { OperationTypeNode, parse } from 'graphql'
|
|
4
|
-
import {
|
|
5
|
-
GraphQLHandler,
|
|
4
|
+
import type {
|
|
6
5
|
GraphQLRequestBody,
|
|
7
6
|
GraphQLResolverExtras,
|
|
8
|
-
isDocumentNode,
|
|
9
7
|
} from './GraphQLHandler'
|
|
8
|
+
import { GraphQLHandler, isDocumentNode } from './GraphQLHandler'
|
|
10
9
|
import { HttpResponse } from '../HttpResponse'
|
|
11
|
-
import { ResponseResolver } from './RequestHandler'
|
|
10
|
+
import type { ResponseResolver } from './RequestHandler'
|
|
12
11
|
|
|
13
12
|
const resolver: ResponseResolver<GraphQLResolverExtras<{ userId: string }>> = ({
|
|
14
13
|
variables,
|
|
@@ -6,30 +6,34 @@ import {
|
|
|
6
6
|
type OperationTypeNode,
|
|
7
7
|
} from 'graphql'
|
|
8
8
|
import {
|
|
9
|
-
DefaultBodyType,
|
|
10
9
|
RequestHandler,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
type DefaultBodyType,
|
|
11
|
+
type RequestHandlerDefaultInfo,
|
|
12
|
+
type RequestHandlerExecutionResult,
|
|
13
|
+
type RequestHandlerOptions,
|
|
14
|
+
type ResponseResolver,
|
|
15
15
|
} from './RequestHandler'
|
|
16
16
|
import { getTimestamp } from '../utils/logging/getTimestamp'
|
|
17
17
|
import { getStatusCodeColor } from '../utils/logging/getStatusCodeColor'
|
|
18
18
|
import { serializeRequest } from '../utils/logging/serializeRequest'
|
|
19
19
|
import { serializeResponse } from '../utils/logging/serializeResponse'
|
|
20
|
-
import { Match, matchRequestUrl, Path } from '../utils/matching/matchRequestUrl'
|
|
21
20
|
import {
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
type Match,
|
|
22
|
+
matchRequestUrl,
|
|
23
|
+
type Path,
|
|
24
|
+
} from '../utils/matching/matchRequestUrl'
|
|
25
|
+
import {
|
|
26
|
+
type ParsedGraphQLRequest,
|
|
27
|
+
type GraphQLMultipartRequestBody,
|
|
24
28
|
parseGraphQLRequest,
|
|
25
29
|
parseDocumentNode,
|
|
26
|
-
ParsedGraphQLQuery,
|
|
30
|
+
type ParsedGraphQLQuery,
|
|
27
31
|
} from '../utils/internal/parseGraphQLRequest'
|
|
28
32
|
import { toPublicUrl } from '../utils/request/toPublicUrl'
|
|
29
33
|
import { devUtils } from '../utils/internal/devUtils'
|
|
30
34
|
import { getAllRequestCookies } from '../utils/request/getRequestCookies'
|
|
31
|
-
import { ResponseResolutionContext } from '
|
|
32
|
-
import { kDefaultContentType, StrictRequest } from '../HttpResponse'
|
|
35
|
+
import { type ResponseResolutionContext } from '../utils/executeHandlers'
|
|
36
|
+
import { kDefaultContentType, type StrictRequest } from '../HttpResponse'
|
|
33
37
|
import { getAllAcceptedMimeTypes } from '../utils/request/getAllAcceptedMimeTypes'
|
|
34
38
|
|
|
35
39
|
export interface DocumentTypeDecoration<
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// @vitest-environment jsdom
|
|
2
2
|
import { createRequestId } from '@mswjs/interceptors'
|
|
3
|
-
import {
|
|
3
|
+
import type { HttpRequestResolverExtras } from './HttpHandler'
|
|
4
|
+
import { HttpHandler } from './HttpHandler'
|
|
4
5
|
import { HttpResponse } from '..'
|
|
5
|
-
import { ResponseResolver } from './RequestHandler'
|
|
6
|
+
import type { ResponseResolver } from './RequestHandler'
|
|
6
7
|
|
|
7
8
|
const resolver: ResponseResolver<
|
|
8
9
|
HttpRequestResolverExtras<{ userId: string }>
|
|
@@ -251,3 +252,92 @@ describe('run', () => {
|
|
|
251
252
|
await expect(run()).resolves.toBe('complete')
|
|
252
253
|
})
|
|
253
254
|
})
|
|
255
|
+
|
|
256
|
+
describe('finalize', () => {
|
|
257
|
+
it('returns the exact response instance if the resolver never accesses finalize', async () => {
|
|
258
|
+
const response = new HttpResponse(
|
|
259
|
+
new ReadableStream({
|
|
260
|
+
start(controller) {
|
|
261
|
+
controller.enqueue(new TextEncoder().encode('hello'))
|
|
262
|
+
controller.close()
|
|
263
|
+
},
|
|
264
|
+
}),
|
|
265
|
+
)
|
|
266
|
+
const handler = new HttpHandler('GET', '/resource', () => {
|
|
267
|
+
return response
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
const result = await handler.run({
|
|
271
|
+
request: new Request(new URL('/resource', location.href)),
|
|
272
|
+
requestId: createRequestId(),
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
expect(result?.response).toBe(response)
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
it('returns the exact response instance if finalize is accessed but never called', async () => {
|
|
279
|
+
const response = new HttpResponse(
|
|
280
|
+
new ReadableStream({
|
|
281
|
+
start(controller) {
|
|
282
|
+
controller.close()
|
|
283
|
+
},
|
|
284
|
+
}),
|
|
285
|
+
)
|
|
286
|
+
const handler = new HttpHandler('GET', '/resource', ({ finalize }) => {
|
|
287
|
+
expect(finalize).toBeInstanceOf(Function)
|
|
288
|
+
return response
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
const result = await handler.run({
|
|
292
|
+
request: new Request(new URL('/resource', location.href)),
|
|
293
|
+
requestId: createRequestId(),
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
expect(result?.response).toBe(response)
|
|
297
|
+
})
|
|
298
|
+
|
|
299
|
+
it('defers the cleanup until the response stream settles', async () => {
|
|
300
|
+
const cleanup = vi.fn()
|
|
301
|
+
const response = new HttpResponse(
|
|
302
|
+
new ReadableStream({
|
|
303
|
+
start(controller) {
|
|
304
|
+
controller.enqueue(new TextEncoder().encode('hello'))
|
|
305
|
+
controller.close()
|
|
306
|
+
},
|
|
307
|
+
}),
|
|
308
|
+
)
|
|
309
|
+
const handler = new HttpHandler('GET', '/resource', ({ finalize }) => {
|
|
310
|
+
finalize(cleanup)
|
|
311
|
+
return response
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
const result = await handler.run({
|
|
315
|
+
request: new Request(new URL('/resource', location.href)),
|
|
316
|
+
requestId: createRequestId(),
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
// The observed response is a copy of the original response.
|
|
320
|
+
expect(result?.response).not.toBe(response)
|
|
321
|
+
expect(cleanup).not.toHaveBeenCalled()
|
|
322
|
+
|
|
323
|
+
await expect(result?.response?.text()).resolves.toBe('hello')
|
|
324
|
+
await vi.waitFor(() => {
|
|
325
|
+
expect(cleanup).toHaveBeenCalledOnce()
|
|
326
|
+
})
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
it('runs the cleanup immediately for responses without a body', async () => {
|
|
330
|
+
const cleanup = vi.fn()
|
|
331
|
+
const handler = new HttpHandler('GET', '/resource', ({ finalize }) => {
|
|
332
|
+
finalize(cleanup)
|
|
333
|
+
return new HttpResponse(null)
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
await handler.run({
|
|
337
|
+
request: new Request(new URL('/resource', location.href)),
|
|
338
|
+
requestId: createRequestId(),
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
expect(cleanup).toHaveBeenCalledOnce()
|
|
342
|
+
})
|
|
343
|
+
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ResponseResolutionContext } from '../utils/executeHandlers'
|
|
1
|
+
import { type ResponseResolutionContext } from '../utils/executeHandlers'
|
|
2
2
|
import { devUtils } from '../utils/internal/devUtils'
|
|
3
3
|
import { isStringEqual } from '../utils/internal/isStringEqual'
|
|
4
4
|
import { getStatusCodeColor } from '../utils/logging/getStatusCodeColor'
|
|
@@ -7,18 +7,18 @@ import { serializeRequest } from '../utils/logging/serializeRequest'
|
|
|
7
7
|
import { serializeResponse } from '../utils/logging/serializeResponse'
|
|
8
8
|
import {
|
|
9
9
|
matchRequestUrl,
|
|
10
|
-
Match,
|
|
11
|
-
Path,
|
|
12
|
-
PathParams,
|
|
10
|
+
type Match,
|
|
11
|
+
type Path,
|
|
12
|
+
type PathParams,
|
|
13
13
|
} from '../utils/matching/matchRequestUrl'
|
|
14
14
|
import { toPublicUrl } from '../utils/request/toPublicUrl'
|
|
15
15
|
import { getAllRequestCookies } from '../utils/request/getRequestCookies'
|
|
16
16
|
import { cleanUrl } from '../utils/url/cleanUrl'
|
|
17
17
|
import {
|
|
18
18
|
RequestHandler,
|
|
19
|
-
RequestHandlerDefaultInfo,
|
|
20
|
-
RequestHandlerOptions,
|
|
21
|
-
ResponseResolver,
|
|
19
|
+
type RequestHandlerDefaultInfo,
|
|
20
|
+
type RequestHandlerOptions,
|
|
21
|
+
type ResponseResolver,
|
|
22
22
|
} from './RequestHandler'
|
|
23
23
|
|
|
24
24
|
export type HttpHandlerMethod = string | RegExp
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
+
import { Headers as HeadersPolyfill } from 'headers-polyfill'
|
|
1
2
|
import { getCallFrame } from '../utils/internal/getCallFrame'
|
|
2
3
|
import {
|
|
3
|
-
AsyncIterable,
|
|
4
|
-
Iterable,
|
|
5
4
|
isIterable,
|
|
5
|
+
type AsyncIterable,
|
|
6
|
+
type Iterable,
|
|
6
7
|
} from '../utils/internal/isIterable'
|
|
7
8
|
import type { ResponseResolutionContext } from '../utils/executeHandlers'
|
|
8
9
|
import type { MaybePromise } from '../typeUtils'
|
|
10
|
+
import type { HttpResponse } from '../HttpResponse'
|
|
9
11
|
import {
|
|
10
|
-
StrictRequest,
|
|
11
|
-
|
|
12
|
-
DefaultUnsafeFetchResponse,
|
|
12
|
+
type StrictRequest,
|
|
13
|
+
type DefaultUnsafeFetchResponse,
|
|
13
14
|
} from '../HttpResponse'
|
|
14
15
|
import type { GraphQLRequestBody } from './GraphQLHandler'
|
|
16
|
+
import { devUtils } from '../utils/internal/devUtils'
|
|
17
|
+
import { getRawSetCookie } from '../utils/HttpResponse/decorators'
|
|
18
|
+
import { observeResponseBodyStream } from '../utils/internal/observe-response-body-stream'
|
|
15
19
|
|
|
16
20
|
export type DefaultRequestMultipartBody = Record<
|
|
17
21
|
string,
|
|
@@ -28,12 +32,7 @@ export type DefaultBodyType =
|
|
|
28
32
|
| undefined
|
|
29
33
|
|
|
30
34
|
export type JsonBodyType =
|
|
31
|
-
|
|
32
|
-
| string
|
|
33
|
-
| number
|
|
34
|
-
| boolean
|
|
35
|
-
| null
|
|
36
|
-
| undefined
|
|
35
|
+
Record<string, any> | string | number | boolean | null | undefined
|
|
37
36
|
|
|
38
37
|
export interface RequestHandlerDefaultInfo {
|
|
39
38
|
header: string
|
|
@@ -88,8 +87,26 @@ export type ResponseResolverInfo<
|
|
|
88
87
|
> = {
|
|
89
88
|
request: StrictRequest<RequestBodyType>
|
|
90
89
|
requestId: string
|
|
90
|
+
/**
|
|
91
|
+
* Schedule a callback to run after this response resolver completes.
|
|
92
|
+
* Handy for cleaning up the side effects introduced in the resolver.
|
|
93
|
+
*
|
|
94
|
+
* For responses with a `ReadableStream` body (including `sse()` handlers),
|
|
95
|
+
* the callback runs once the response stream settles: it is read to
|
|
96
|
+
* completion, errored, or canceled, or the request is aborted.
|
|
97
|
+
* @example
|
|
98
|
+
* sse('/', ({ client, finalize }) => {
|
|
99
|
+
* const interval = setInterval(() => client.send({ data: 'ping' }))
|
|
100
|
+
* finalize(() => clearInterval(interval))
|
|
101
|
+
* })
|
|
102
|
+
*/
|
|
103
|
+
finalize: ResponseResolverFinalizeFunction
|
|
91
104
|
} & ResolverExtraInfo
|
|
92
105
|
|
|
106
|
+
type ResponseResolverFinalizeFunction = (
|
|
107
|
+
callback: () => MaybePromise<void>,
|
|
108
|
+
) => void
|
|
109
|
+
|
|
93
110
|
export type ResponseResolver<
|
|
94
111
|
ResolverExtraInfo extends Record<string, unknown> = Record<string, unknown>,
|
|
95
112
|
RequestBodyType extends DefaultBodyType = DefaultBodyType,
|
|
@@ -147,7 +164,9 @@ export abstract class RequestHandler<
|
|
|
147
164
|
MaybeAsyncResponseResolverReturnType<any>
|
|
148
165
|
>
|
|
149
166
|
private resolverIteratorResult?: Response | HttpResponse<any>
|
|
167
|
+
private resolverIteratorCleanups?: Array<() => MaybePromise<void>>
|
|
150
168
|
private options?: HandlerOptions
|
|
169
|
+
private scheduledCleanups: Map<string, Array<() => MaybePromise<void>>>
|
|
151
170
|
|
|
152
171
|
public info: HandlerInfo & RequestHandlerInternalInfo
|
|
153
172
|
|
|
@@ -160,6 +179,7 @@ export abstract class RequestHandler<
|
|
|
160
179
|
constructor(args: RequestHandlerArgs<HandlerInfo, HandlerOptions>) {
|
|
161
180
|
this.resolver = args.resolver
|
|
162
181
|
this.options = args.options
|
|
182
|
+
this.scheduledCleanups = new Map()
|
|
163
183
|
|
|
164
184
|
const callFrame = getCallFrame(new Error())
|
|
165
185
|
|
|
@@ -171,6 +191,37 @@ export abstract class RequestHandler<
|
|
|
171
191
|
this.isUsed = false
|
|
172
192
|
}
|
|
173
193
|
|
|
194
|
+
/**
|
|
195
|
+
* Reset the runtime state accumulated during response resolution,
|
|
196
|
+
* such as generator iterator progress. Called when this handler is
|
|
197
|
+
* removed from the active handlers list so re-adding it later starts
|
|
198
|
+
* from a clean state.
|
|
199
|
+
*/
|
|
200
|
+
protected reset(): void {
|
|
201
|
+
this.scheduledCleanups.clear()
|
|
202
|
+
|
|
203
|
+
const iterator = this.resolverIterator
|
|
204
|
+
this.resolverIterator = undefined
|
|
205
|
+
this.resolverIteratorResult = undefined
|
|
206
|
+
this.resolverIteratorCleanups = undefined
|
|
207
|
+
|
|
208
|
+
if (typeof iterator?.return === 'function') {
|
|
209
|
+
void Promise.resolve(iterator.return())
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Restore this handler so it can match requests again after being
|
|
215
|
+
* exhausted (e.g. via `{ once: true }`). Also clears any accumulated
|
|
216
|
+
* resolution state.
|
|
217
|
+
*/
|
|
218
|
+
protected restore(): void {
|
|
219
|
+
if (this.options?.once) {
|
|
220
|
+
this.reset()
|
|
221
|
+
this.isUsed = false
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
174
225
|
/**
|
|
175
226
|
* Determine if the intercepted request should be mocked.
|
|
176
227
|
*/
|
|
@@ -302,24 +353,80 @@ export abstract class RequestHandler<
|
|
|
302
353
|
parsedResult,
|
|
303
354
|
})
|
|
304
355
|
|
|
356
|
+
const listenerController = new AbortController()
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* @note Initialize the `finalize` machinery lazily, on the first
|
|
360
|
+
* access of the `finalize` property by the resolver. If the resolver
|
|
361
|
+
* never accesses it, the handler behaves as if `finalize` never
|
|
362
|
+
* existed: no abort listeners, no scheduled cleanups, and no response
|
|
363
|
+
* body stream observation (see `this.complete()`).
|
|
364
|
+
*/
|
|
365
|
+
let finalizeFunction: ResponseResolverFinalizeFunction | undefined
|
|
366
|
+
|
|
367
|
+
const getFinalize = (): ResponseResolverFinalizeFunction => {
|
|
368
|
+
if (finalizeFunction == null) {
|
|
369
|
+
// Run any scheduled cleanups if the request gets aborted
|
|
370
|
+
// while the resolver is still executing.
|
|
371
|
+
if (!args.request.signal.aborted) {
|
|
372
|
+
args.request.signal.addEventListener(
|
|
373
|
+
'abort',
|
|
374
|
+
() => this.runScheduledCleanups(args.requestId),
|
|
375
|
+
{
|
|
376
|
+
once: true,
|
|
377
|
+
signal: listenerController.signal,
|
|
378
|
+
},
|
|
379
|
+
)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
finalizeFunction = (callback) => {
|
|
383
|
+
this.scheduleCleanup(args.requestId, callback)
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* @note Run the cleanup immediately if the request has already
|
|
387
|
+
* been aborted. The "abort" listener above never fires for an
|
|
388
|
+
* already-aborted signal (and fires at most once), while
|
|
389
|
+
* long-lived resolvers (streams, generators) may never settle
|
|
390
|
+
* to run the cleanups on completion.
|
|
391
|
+
*/
|
|
392
|
+
if (args.request.signal.aborted) {
|
|
393
|
+
void this.runScheduledCleanups(args.requestId)
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
return finalizeFunction
|
|
399
|
+
}
|
|
400
|
+
|
|
305
401
|
const mockedResponsePromise = (
|
|
306
402
|
executeResolver({
|
|
307
403
|
...resolverExtras,
|
|
404
|
+
get finalize(): ResponseResolverFinalizeFunction {
|
|
405
|
+
return getFinalize()
|
|
406
|
+
},
|
|
308
407
|
requestId: args.requestId,
|
|
309
408
|
request: args.request,
|
|
310
409
|
}) as Promise<Response>
|
|
311
|
-
)
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
410
|
+
)
|
|
411
|
+
.catch((errorOrResponse) => {
|
|
412
|
+
// Allow throwing a Response instance in a response resolver.
|
|
413
|
+
if (errorOrResponse instanceof Response) {
|
|
414
|
+
return errorOrResponse
|
|
415
|
+
}
|
|
316
416
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
417
|
+
// Otherwise, throw the error as-is.
|
|
418
|
+
throw errorOrResponse
|
|
419
|
+
})
|
|
420
|
+
.finally(() => {
|
|
421
|
+
listenerController.abort()
|
|
422
|
+
})
|
|
320
423
|
|
|
321
424
|
const mockedResponse = await mockedResponsePromise
|
|
322
425
|
|
|
426
|
+
if (mockedResponse) {
|
|
427
|
+
forwardResponseCookies(mockedResponse)
|
|
428
|
+
}
|
|
429
|
+
|
|
323
430
|
const executionResult = this.createExecutionResult({
|
|
324
431
|
// Pass the cloned request to the result so that logging
|
|
325
432
|
// and other consumers could read its body once more.
|
|
@@ -337,10 +444,42 @@ export abstract class RequestHandler<
|
|
|
337
444
|
): ResponseResolver<ResolverExtras> {
|
|
338
445
|
return async (info): Promise<ResponseResolverReturnType<any>> => {
|
|
339
446
|
if (!this.resolverIterator) {
|
|
340
|
-
|
|
447
|
+
let result
|
|
448
|
+
|
|
449
|
+
try {
|
|
450
|
+
result = await resolver(info)
|
|
451
|
+
} catch (error) {
|
|
452
|
+
// Ensure cleanup if the resolver throws, regardless of the returned type.
|
|
453
|
+
await this.runScheduledCleanups(info.requestId)
|
|
454
|
+
|
|
455
|
+
// Re-throw the error for the "run()" method to handle (e.g. thrown responses).
|
|
456
|
+
throw error
|
|
457
|
+
}
|
|
341
458
|
|
|
342
459
|
if (!isIterable(result)) {
|
|
343
|
-
|
|
460
|
+
// Otherwise, run the cleanups if it's a plain response resolver
|
|
461
|
+
// (deferred until the response stream settles for streamed responses).
|
|
462
|
+
return this.complete({
|
|
463
|
+
request: info.request,
|
|
464
|
+
requestId: info.requestId,
|
|
465
|
+
response: result,
|
|
466
|
+
})
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* @note Carry over any previously registered cleanups onto the iterator cleanups.
|
|
471
|
+
* This is only relevant if "finalize()" is called in a regular resolver that
|
|
472
|
+
* returns an iterator.
|
|
473
|
+
* @example
|
|
474
|
+
* http.get('/', async ({ finalize }) => {
|
|
475
|
+
* finalize(cleanup)
|
|
476
|
+
* return (async function*() {})()
|
|
477
|
+
* })
|
|
478
|
+
*/
|
|
479
|
+
const existingCleanups = this.scheduledCleanups.get(info.requestId)
|
|
480
|
+
if (existingCleanups != null && existingCleanups.length > 0) {
|
|
481
|
+
this.resolverIteratorCleanups = existingCleanups
|
|
482
|
+
this.scheduledCleanups.delete(info.requestId)
|
|
344
483
|
}
|
|
345
484
|
|
|
346
485
|
this.resolverIterator =
|
|
@@ -366,7 +505,11 @@ export abstract class RequestHandler<
|
|
|
366
505
|
|
|
367
506
|
// Clone the previously stored response so it can be read
|
|
368
507
|
// when receiving it repeatedly from the "done" generator.
|
|
369
|
-
return this.
|
|
508
|
+
return this.complete({
|
|
509
|
+
request: info.request,
|
|
510
|
+
requestId: info.requestId,
|
|
511
|
+
response: this.resolverIteratorResult?.clone(),
|
|
512
|
+
})
|
|
370
513
|
}
|
|
371
514
|
|
|
372
515
|
return nextResponse
|
|
@@ -387,4 +530,168 @@ export abstract class RequestHandler<
|
|
|
387
530
|
parsedResult: args.parsedResult,
|
|
388
531
|
}
|
|
389
532
|
}
|
|
533
|
+
|
|
534
|
+
private scheduleCleanup(
|
|
535
|
+
requestId: string,
|
|
536
|
+
callback: () => MaybePromise<void>,
|
|
537
|
+
): void {
|
|
538
|
+
if (this.resolverIterator) {
|
|
539
|
+
;(this.resolverIteratorCleanups ||= []).unshift(callback)
|
|
540
|
+
return
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
const cleanups = this.scheduledCleanups.get(requestId) || []
|
|
544
|
+
cleanups.unshift(callback)
|
|
545
|
+
this.scheduledCleanups.set(requestId, cleanups)
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
private async exhaustCleanups(
|
|
549
|
+
cleanups: Array<() => MaybePromise<void>>,
|
|
550
|
+
): Promise<void> {
|
|
551
|
+
const errors: Array<Error> = []
|
|
552
|
+
|
|
553
|
+
for (const cleanup of cleanups) {
|
|
554
|
+
try {
|
|
555
|
+
await cleanup()
|
|
556
|
+
} catch (error) {
|
|
557
|
+
if (error instanceof Error) {
|
|
558
|
+
errors.push(error)
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
if (errors.length > 0) {
|
|
564
|
+
devUtils.error(
|
|
565
|
+
'Failed to execute cleanup for request handler "%s"',
|
|
566
|
+
this.info.header,
|
|
567
|
+
new AggregateError(
|
|
568
|
+
errors,
|
|
569
|
+
`Failed to execute cleanup for request handler "${this.info.header}"`,
|
|
570
|
+
),
|
|
571
|
+
)
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Remove and return the cleanups scheduled for the given request
|
|
577
|
+
* (or the pending iterator cleanups for generator resolvers).
|
|
578
|
+
*/
|
|
579
|
+
private takeScheduledCleanups(
|
|
580
|
+
requestId: string,
|
|
581
|
+
): Array<() => MaybePromise<void>> | undefined {
|
|
582
|
+
if (
|
|
583
|
+
this.resolverIterator &&
|
|
584
|
+
this.resolverIteratorCleanups != null &&
|
|
585
|
+
this.resolverIteratorCleanups.length > 0
|
|
586
|
+
) {
|
|
587
|
+
const cleanups = this.resolverIteratorCleanups
|
|
588
|
+
this.resolverIteratorCleanups = undefined
|
|
589
|
+
return cleanups
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
const cleanups = this.scheduledCleanups.get(requestId)
|
|
593
|
+
|
|
594
|
+
if (!cleanups || cleanups.length === 0) {
|
|
595
|
+
return undefined
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
this.scheduledCleanups.delete(requestId)
|
|
599
|
+
return cleanups
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
private async runScheduledCleanups(requestId: string): Promise<void> {
|
|
603
|
+
const cleanups = this.takeScheduledCleanups(requestId)
|
|
604
|
+
|
|
605
|
+
if (cleanups) {
|
|
606
|
+
await this.exhaustCleanups(cleanups)
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* Conclude the response resolution for the given request.
|
|
612
|
+
* Runs the scheduled cleanups immediately for responses without a
|
|
613
|
+
* `ReadableStream` body. For streamed responses, returns an observed
|
|
614
|
+
* copy of the response and defers the cleanups until its body settles
|
|
615
|
+
* (is read to completion, errored, or canceled) or the request is
|
|
616
|
+
* aborted, whichever comes first.
|
|
617
|
+
*/
|
|
618
|
+
private async complete(args: {
|
|
619
|
+
request: StrictRequest<any>
|
|
620
|
+
requestId: string
|
|
621
|
+
response: Response | undefined | void
|
|
622
|
+
}): Promise<Response | undefined | void> {
|
|
623
|
+
const cleanups = this.takeScheduledCleanups(args.requestId)
|
|
624
|
+
|
|
625
|
+
if (!cleanups) {
|
|
626
|
+
return args.response
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
const observedResponse = args.response
|
|
630
|
+
? observeResponseBodyStream(args.response)
|
|
631
|
+
: null
|
|
632
|
+
|
|
633
|
+
if (!observedResponse) {
|
|
634
|
+
await this.exhaustCleanups(cleanups)
|
|
635
|
+
return args.response
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
const listenerController = new AbortController()
|
|
639
|
+
|
|
640
|
+
const runCleanupsOnce = (): void => {
|
|
641
|
+
if (listenerController.signal.aborted) {
|
|
642
|
+
return
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
listenerController.abort()
|
|
646
|
+
void this.exhaustCleanups(cleanups)
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
void observedResponse.settled.then(runCleanupsOnce)
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* @note Also run the cleanups when the request is aborted.
|
|
653
|
+
* Stream cancellation does not always propagate to the observed
|
|
654
|
+
* response (e.g. if an unconsumed clone of the response exists),
|
|
655
|
+
* while the request abort reliably means the response is unused.
|
|
656
|
+
*/
|
|
657
|
+
if (args.request.signal.aborted) {
|
|
658
|
+
runCleanupsOnce()
|
|
659
|
+
} else {
|
|
660
|
+
args.request.signal.addEventListener('abort', runCleanupsOnce, {
|
|
661
|
+
once: true,
|
|
662
|
+
signal: listenerController.signal,
|
|
663
|
+
})
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
return observedResponse.response
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
* Forwards the cookies from the given response to `document.cookie`.
|
|
672
|
+
*/
|
|
673
|
+
export function forwardResponseCookies(response: Response): void {
|
|
674
|
+
// Cookie forwarding is only relevant in the browser.
|
|
675
|
+
if (typeof document === 'undefined') {
|
|
676
|
+
return
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
const responseCookies = getRawSetCookie(response)
|
|
680
|
+
|
|
681
|
+
if (!responseCookies) {
|
|
682
|
+
return
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// Write the mocked response cookies to the document.
|
|
686
|
+
// Use `headers-polyfill` to get the Set-Cookie header value correctly.
|
|
687
|
+
// This is an alternative until TypeScript 5.2
|
|
688
|
+
// and Node.js v20 become the minimum supported versions
|
|
689
|
+
// and "Headers.prototype.getSetCookie" can be used directly.
|
|
690
|
+
const allResponseCookies = HeadersPolyfill.prototype.getSetCookie.call(
|
|
691
|
+
new Headers([['set-cookie', responseCookies]]),
|
|
692
|
+
)
|
|
693
|
+
|
|
694
|
+
for (const cookieString of allResponseCookies) {
|
|
695
|
+
document.cookie = cookieString
|
|
696
|
+
}
|
|
390
697
|
}
|