msw 2.12.5 → 2.12.7
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/lib/browser/index.js +6 -0
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/index.mjs +6 -0
- package/lib/browser/index.mjs.map +1 -1
- package/lib/core/{HttpResponse-DC89RDb7.d.ts → HttpResponse-CVs3ngx3.d.ts} +18 -2
- package/lib/core/{HttpResponse-U6SfxBlj.d.mts → HttpResponse-Cw4ELwIN.d.mts} +18 -2
- package/lib/core/HttpResponse.d.mts +1 -1
- package/lib/core/HttpResponse.d.ts +1 -1
- package/lib/core/SetupApi.d.mts +1 -1
- package/lib/core/SetupApi.d.ts +1 -1
- package/lib/core/getResponse.d.mts +1 -1
- package/lib/core/getResponse.d.ts +1 -1
- package/lib/core/graphql.d.mts +21 -59
- package/lib/core/graphql.d.ts +21 -59
- package/lib/core/graphql.js +14 -15
- package/lib/core/graphql.js.map +1 -1
- package/lib/core/graphql.mjs +14 -15
- 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 +42 -17
- package/lib/core/handlers/GraphQLHandler.js.map +1 -1
- package/lib/core/handlers/GraphQLHandler.mjs +44 -17
- 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/RequestHandler.d.mts +1 -1
- package/lib/core/handlers/RequestHandler.d.ts +1 -1
- package/lib/core/http.d.mts +1 -1
- package/lib/core/http.d.ts +1 -1
- package/lib/core/index.d.mts +2 -2
- package/lib/core/index.d.ts +2 -2
- package/lib/core/index.js.map +1 -1
- package/lib/core/index.mjs.map +1 -1
- package/lib/core/passthrough.d.mts +1 -1
- package/lib/core/passthrough.d.ts +1 -1
- package/lib/core/sse.d.mts +1 -1
- package/lib/core/sse.d.ts +1 -1
- package/lib/core/sse.js +25 -21
- package/lib/core/sse.js.map +1 -1
- package/lib/core/sse.mjs +25 -21
- package/lib/core/sse.mjs.map +1 -1
- package/lib/core/utils/HttpResponse/decorators.d.mts +1 -1
- package/lib/core/utils/HttpResponse/decorators.d.ts +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.map +1 -1
- package/lib/core/utils/executeHandlers.mjs.map +1 -1
- package/lib/core/utils/handleRequest.d.mts +2 -9
- package/lib/core/utils/handleRequest.d.ts +2 -9
- package/lib/core/utils/handleRequest.js.map +1 -1
- package/lib/core/utils/handleRequest.mjs +3 -1
- package/lib/core/utils/handleRequest.mjs.map +1 -1
- 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/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/requestHandlerUtils.d.mts +1 -1
- package/lib/core/utils/internal/requestHandlerUtils.d.ts +1 -1
- package/lib/core/ws/handleWebSocketEvent.d.mts +1 -1
- package/lib/core/ws/handleWebSocketEvent.d.ts +1 -1
- package/lib/iife/index.js +88 -53
- package/lib/iife/index.js.map +1 -1
- package/lib/mockServiceWorker.js +1 -1
- package/package.json +2 -2
- package/src/browser/setupWorker/start/createFallbackRequestListener.ts +3 -0
- package/src/browser/setupWorker/start/createRequestListener.ts +3 -0
- package/src/core/graphql.ts +43 -52
- package/src/core/handlers/GraphQLHandler.test.ts +1 -1
- package/src/core/handlers/GraphQLHandler.ts +73 -25
- package/src/core/index.ts +6 -1
- package/src/core/sse.ts +38 -29
- package/src/core/utils/executeHandlers.ts +6 -0
- package/src/core/utils/handleRequest.ts +6 -9
package/lib/mockServiceWorker.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - Please do NOT modify this file.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
const PACKAGE_VERSION = '2.12.
|
|
10
|
+
const PACKAGE_VERSION = '2.12.7'
|
|
11
11
|
const INTEGRITY_CHECKSUM = '4db4a41e972cec1b64cc569c66952d82'
|
|
12
12
|
const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
|
|
13
13
|
const activeClientIds = new Set()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "msw",
|
|
3
|
-
"version": "2.12.
|
|
3
|
+
"version": "2.12.7",
|
|
4
4
|
"description": "Seamless REST/GraphQL API mocking library for browser and Node.js.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./lib/core/index.js",
|
|
@@ -285,7 +285,7 @@
|
|
|
285
285
|
"vitest-environment-miniflare": "^2.14.4",
|
|
286
286
|
"webpack": "^5.95.0",
|
|
287
287
|
"webpack-http-server": "^0.5.0",
|
|
288
|
-
"msw": "2.12.
|
|
288
|
+
"msw": "2.12.7"
|
|
289
289
|
},
|
|
290
290
|
"peerDependencies": {
|
|
291
291
|
"typescript": ">= 4.8.x"
|
|
@@ -29,6 +29,9 @@ export function createFallbackRequestListener(
|
|
|
29
29
|
options,
|
|
30
30
|
context.emitter,
|
|
31
31
|
{
|
|
32
|
+
resolutionContext: {
|
|
33
|
+
quiet: options.quiet,
|
|
34
|
+
},
|
|
32
35
|
onMockedResponse(_, { handler, parsedResult }) {
|
|
33
36
|
if (!options.quiet) {
|
|
34
37
|
context.emitter.once('response:mocked', ({ response }) => {
|
package/src/core/graphql.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { OperationTypeNode } from 'graphql'
|
|
2
2
|
import {
|
|
3
3
|
ResponseResolver,
|
|
4
4
|
RequestHandlerOptions,
|
|
@@ -7,32 +7,29 @@ import {
|
|
|
7
7
|
GraphQLHandler,
|
|
8
8
|
GraphQLVariables,
|
|
9
9
|
GraphQLOperationType,
|
|
10
|
-
GraphQLHandlerNameSelector,
|
|
11
10
|
GraphQLResolverExtras,
|
|
12
11
|
GraphQLResponseBody,
|
|
13
12
|
GraphQLQuery,
|
|
14
|
-
|
|
13
|
+
GraphQLPredicate,
|
|
15
14
|
} from './handlers/GraphQLHandler'
|
|
16
15
|
import type { Path } from './utils/matching/matchRequestUrl'
|
|
17
16
|
|
|
18
|
-
export interface TypedDocumentNode<
|
|
19
|
-
Result = { [key: string]: any },
|
|
20
|
-
Variables = { [key: string]: any },
|
|
21
|
-
> extends DocumentNode {
|
|
22
|
-
__apiType?: (variables: Variables) => Result
|
|
23
|
-
__resultType?: Result
|
|
24
|
-
__variablesType?: Variables
|
|
25
|
-
}
|
|
26
|
-
|
|
27
17
|
export type GraphQLRequestHandler = <
|
|
28
18
|
Query extends GraphQLQuery = GraphQLQuery,
|
|
29
19
|
Variables extends GraphQLVariables = GraphQLVariables,
|
|
30
20
|
>(
|
|
31
|
-
predicate:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
21
|
+
predicate: GraphQLPredicate<Query, Variables>,
|
|
22
|
+
resolver: GraphQLResponseResolver<
|
|
23
|
+
[Query] extends [never] ? GraphQLQuery : Query,
|
|
24
|
+
Variables
|
|
25
|
+
>,
|
|
26
|
+
options?: RequestHandlerOptions,
|
|
27
|
+
) => GraphQLHandler
|
|
28
|
+
|
|
29
|
+
export type GraphQLOperationHandler = <
|
|
30
|
+
Query extends GraphQLQuery = GraphQLQuery,
|
|
31
|
+
Variables extends GraphQLVariables = GraphQLVariables,
|
|
32
|
+
>(
|
|
36
33
|
resolver: GraphQLResponseResolver<
|
|
37
34
|
[Query] extends [never] ? GraphQLQuery : Query,
|
|
38
35
|
Variables
|
|
@@ -58,22 +55,28 @@ function createScopedGraphQLHandler(
|
|
|
58
55
|
}
|
|
59
56
|
}
|
|
60
57
|
|
|
61
|
-
function createGraphQLOperationHandler(url: Path) {
|
|
62
|
-
return
|
|
63
|
-
|
|
64
|
-
Variables extends GraphQLVariables = GraphQLVariables,
|
|
65
|
-
>(
|
|
66
|
-
resolver: ResponseResolver<
|
|
67
|
-
GraphQLResolverExtras<Variables>,
|
|
68
|
-
null,
|
|
69
|
-
GraphQLResponseBody<Query>
|
|
70
|
-
>,
|
|
71
|
-
) => {
|
|
72
|
-
return new GraphQLHandler('all', new RegExp('.*'), url, resolver)
|
|
58
|
+
function createGraphQLOperationHandler(url: Path): GraphQLOperationHandler {
|
|
59
|
+
return (resolver, options) => {
|
|
60
|
+
return new GraphQLHandler('all', new RegExp('.*'), url, resolver, options)
|
|
73
61
|
}
|
|
74
62
|
}
|
|
75
63
|
|
|
76
|
-
|
|
64
|
+
export interface GraphQLLinkHandlers {
|
|
65
|
+
query: GraphQLRequestHandler
|
|
66
|
+
mutation: GraphQLRequestHandler
|
|
67
|
+
operation: GraphQLOperationHandler
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* A namespace to intercept and mock GraphQL operations
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* graphql.query('GetUser', resolver)
|
|
75
|
+
* graphql.mutation('DeletePost', resolver)
|
|
76
|
+
*
|
|
77
|
+
* @see {@link https://mswjs.io/docs/api/graphql `graphql` API reference}
|
|
78
|
+
*/
|
|
79
|
+
export const graphql = {
|
|
77
80
|
/**
|
|
78
81
|
* Intercepts a GraphQL query by a given name.
|
|
79
82
|
*
|
|
@@ -110,27 +113,6 @@ const standardGraphQLHandlers = {
|
|
|
110
113
|
* @see {@link https://mswjs.io/docs/api/graphql#graphqloperationresolver `graphql.operation()` API reference}
|
|
111
114
|
*/
|
|
112
115
|
operation: createGraphQLOperationHandler('*'),
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function createGraphQLLink(url: Path): typeof standardGraphQLHandlers {
|
|
116
|
-
return {
|
|
117
|
-
operation: createGraphQLOperationHandler(url),
|
|
118
|
-
query: createScopedGraphQLHandler('query' as OperationTypeNode, url),
|
|
119
|
-
mutation: createScopedGraphQLHandler('mutation' as OperationTypeNode, url),
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* A namespace to intercept and mock GraphQL operations
|
|
125
|
-
*
|
|
126
|
-
* @example
|
|
127
|
-
* graphql.query('GetUser', resolver)
|
|
128
|
-
* graphql.mutation('DeletePost', resolver)
|
|
129
|
-
*
|
|
130
|
-
* @see {@link https://mswjs.io/docs/api/graphql `graphql` API reference}
|
|
131
|
-
*/
|
|
132
|
-
export const graphql = {
|
|
133
|
-
...standardGraphQLHandlers,
|
|
134
116
|
|
|
135
117
|
/**
|
|
136
118
|
* Intercepts GraphQL operations scoped by the given URL.
|
|
@@ -141,5 +123,14 @@ export const graphql = {
|
|
|
141
123
|
*
|
|
142
124
|
* @see {@link https://mswjs.io/docs/api/graphql#graphqllinkurl `graphql.link()` API reference}
|
|
143
125
|
*/
|
|
144
|
-
link:
|
|
126
|
+
link(url: Path): GraphQLLinkHandlers {
|
|
127
|
+
return {
|
|
128
|
+
operation: createGraphQLOperationHandler(url),
|
|
129
|
+
query: createScopedGraphQLHandler('query' as OperationTypeNode, url),
|
|
130
|
+
mutation: createScopedGraphQLHandler(
|
|
131
|
+
'mutation' as OperationTypeNode,
|
|
132
|
+
url,
|
|
133
|
+
),
|
|
134
|
+
}
|
|
135
|
+
},
|
|
145
136
|
}
|
|
@@ -139,7 +139,7 @@ describe('info', () => {
|
|
|
139
139
|
expect(
|
|
140
140
|
() => new GraphQLHandler(OperationTypeNode.QUERY, node, '*', resolver),
|
|
141
141
|
).toThrow(
|
|
142
|
-
'Failed to create a GraphQL handler: provided a DocumentNode with a mismatched operation type (expected "query"
|
|
142
|
+
'Failed to create a GraphQL handler: provided a DocumentNode with a mismatched operation type (expected "query" but got "mutation").',
|
|
143
143
|
)
|
|
144
144
|
})
|
|
145
145
|
})
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
parse,
|
|
3
|
+
type DocumentNode,
|
|
4
|
+
type GraphQLError,
|
|
5
|
+
type OperationTypeNode,
|
|
6
|
+
} from 'graphql'
|
|
2
7
|
import {
|
|
3
8
|
DefaultBodyType,
|
|
4
9
|
RequestHandler,
|
|
@@ -16,10 +21,21 @@ import {
|
|
|
16
21
|
GraphQLMultipartRequestBody,
|
|
17
22
|
parseGraphQLRequest,
|
|
18
23
|
parseDocumentNode,
|
|
24
|
+
ParsedGraphQLQuery,
|
|
19
25
|
} from '../utils/internal/parseGraphQLRequest'
|
|
20
26
|
import { toPublicUrl } from '../utils/request/toPublicUrl'
|
|
21
27
|
import { devUtils } from '../utils/internal/devUtils'
|
|
22
28
|
import { getAllRequestCookies } from '../utils/request/getRequestCookies'
|
|
29
|
+
import { invariant } from 'outvariant'
|
|
30
|
+
|
|
31
|
+
export interface DocumentTypeDecoration<
|
|
32
|
+
Result = { [key: string]: any },
|
|
33
|
+
Variables = { [key: string]: any },
|
|
34
|
+
> {
|
|
35
|
+
__apiType?: (variables: Variables) => Result
|
|
36
|
+
__resultType?: Result
|
|
37
|
+
__variablesType?: Variables
|
|
38
|
+
}
|
|
23
39
|
|
|
24
40
|
export type GraphQLOperationType = OperationTypeNode | 'all'
|
|
25
41
|
export type GraphQLHandlerNameSelector = DocumentNode | RegExp | string
|
|
@@ -88,8 +104,9 @@ export type GraphQLCustomPredicate = (args: {
|
|
|
88
104
|
|
|
89
105
|
export type GraphQLCustomPredicateResult = boolean | { matches: boolean }
|
|
90
106
|
|
|
91
|
-
export type GraphQLPredicate =
|
|
107
|
+
export type GraphQLPredicate<Query = any, Variables = any> =
|
|
92
108
|
| GraphQLHandlerNameSelector
|
|
109
|
+
| DocumentTypeDecoration<Query, Variables>
|
|
93
110
|
| GraphQLCustomPredicate
|
|
94
111
|
|
|
95
112
|
export function isDocumentNode(
|
|
@@ -102,6 +119,12 @@ export function isDocumentNode(
|
|
|
102
119
|
return typeof value === 'object' && 'kind' in value && 'definitions' in value
|
|
103
120
|
}
|
|
104
121
|
|
|
122
|
+
function isDocumentTypeDecoration(
|
|
123
|
+
value: any,
|
|
124
|
+
): value is DocumentTypeDecoration<any, any> {
|
|
125
|
+
return value instanceof String
|
|
126
|
+
}
|
|
127
|
+
|
|
105
128
|
export class GraphQLHandler extends RequestHandler<
|
|
106
129
|
GraphQLHandlerInfo,
|
|
107
130
|
GraphQLRequestParsedResult,
|
|
@@ -114,6 +137,45 @@ export class GraphQLHandler extends RequestHandler<
|
|
|
114
137
|
ParsedGraphQLRequest<GraphQLVariables>
|
|
115
138
|
>()
|
|
116
139
|
|
|
140
|
+
static #parseOperationName(
|
|
141
|
+
predicate: GraphQLPredicate,
|
|
142
|
+
operationType: GraphQLOperationType,
|
|
143
|
+
): GraphQLHandlerInfo['operationName'] {
|
|
144
|
+
const getOperationName = (node: ParsedGraphQLQuery): string => {
|
|
145
|
+
invariant(
|
|
146
|
+
node.operationType === operationType,
|
|
147
|
+
'Failed to create a GraphQL handler: provided a DocumentNode with a mismatched operation type (expected "%s" but got "%s").',
|
|
148
|
+
operationType,
|
|
149
|
+
node.operationType,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
invariant(
|
|
153
|
+
node.operationName,
|
|
154
|
+
'Failed to create a GraphQL handler: provided a DocumentNode without operation name',
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
return node.operationName
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (isDocumentNode(predicate)) {
|
|
161
|
+
return getOperationName(parseDocumentNode(predicate))
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (isDocumentTypeDecoration(predicate)) {
|
|
165
|
+
const documentNode = parse(predicate.toString())
|
|
166
|
+
|
|
167
|
+
invariant(
|
|
168
|
+
isDocumentNode(documentNode),
|
|
169
|
+
'Failed to create a GraphQL handler: given TypedDocumentString (%s) does not produce a valid DocumentNode',
|
|
170
|
+
predicate,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
return getOperationName(parseDocumentNode(documentNode))
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return predicate
|
|
177
|
+
}
|
|
178
|
+
|
|
117
179
|
constructor(
|
|
118
180
|
operationType: GraphQLOperationType,
|
|
119
181
|
predicate: GraphQLPredicate,
|
|
@@ -121,30 +183,13 @@ export class GraphQLHandler extends RequestHandler<
|
|
|
121
183
|
resolver: ResponseResolver<GraphQLResolverExtras<any>, any, any>,
|
|
122
184
|
options?: RequestHandlerOptions,
|
|
123
185
|
) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
if (parsedNode.operationType !== operationType) {
|
|
130
|
-
throw new Error(
|
|
131
|
-
`Failed to create a GraphQL handler: provided a DocumentNode with a mismatched operation type (expected "${operationType}", but got "${parsedNode.operationType}").`,
|
|
132
|
-
)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (!parsedNode.operationName) {
|
|
136
|
-
throw new Error(
|
|
137
|
-
`Failed to create a GraphQL handler: provided a DocumentNode with no operation name.`,
|
|
138
|
-
)
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
resolvedOperationName = parsedNode.operationName
|
|
142
|
-
}
|
|
186
|
+
const operationName = GraphQLHandler.#parseOperationName(
|
|
187
|
+
predicate,
|
|
188
|
+
operationType,
|
|
189
|
+
)
|
|
143
190
|
|
|
144
191
|
const displayOperationName =
|
|
145
|
-
typeof
|
|
146
|
-
? '[custom predicate]'
|
|
147
|
-
: resolvedOperationName
|
|
192
|
+
typeof operationName === 'function' ? '[custom predicate]' : operationName
|
|
148
193
|
|
|
149
194
|
const header =
|
|
150
195
|
operationType === 'all'
|
|
@@ -155,7 +200,10 @@ export class GraphQLHandler extends RequestHandler<
|
|
|
155
200
|
info: {
|
|
156
201
|
header,
|
|
157
202
|
operationType,
|
|
158
|
-
operationName:
|
|
203
|
+
operationName: GraphQLHandler.#parseOperationName(
|
|
204
|
+
predicate,
|
|
205
|
+
operationType,
|
|
206
|
+
),
|
|
159
207
|
},
|
|
160
208
|
resolver,
|
|
161
209
|
options,
|
package/src/core/index.ts
CHANGED
|
@@ -73,7 +73,12 @@ export type {
|
|
|
73
73
|
GraphQLOperationType,
|
|
74
74
|
GraphQLCustomPredicate,
|
|
75
75
|
} from './handlers/GraphQLHandler'
|
|
76
|
-
export type {
|
|
76
|
+
export type {
|
|
77
|
+
GraphQLRequestHandler,
|
|
78
|
+
GraphQLOperationHandler,
|
|
79
|
+
GraphQLResponseResolver,
|
|
80
|
+
GraphQLLinkHandlers,
|
|
81
|
+
} from './graphql'
|
|
77
82
|
|
|
78
83
|
export type { WebSocketData, WebSocketEventListener } from './ws'
|
|
79
84
|
|
package/src/core/sse.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
type HttpRequestResolverExtras,
|
|
7
7
|
type HttpRequestParsedResult,
|
|
8
8
|
} from './handlers/HttpHandler'
|
|
9
|
+
import type { ResponseResolutionContext } from '~/core/utils/executeHandlers'
|
|
9
10
|
import type { Path, PathParams } from './utils/matching/matchRequestUrl'
|
|
10
11
|
import { delay } from './delay'
|
|
11
12
|
import { getTimestamp } from './utils/logging/getTimestamp'
|
|
@@ -67,9 +68,19 @@ export const sse: ServerSentEventRequestHandler = (path, resolver) => {
|
|
|
67
68
|
return new ServerSentEventHandler(path, resolver)
|
|
68
69
|
}
|
|
69
70
|
|
|
71
|
+
const SSE_RESPONSE_INIT: ResponseInit = {
|
|
72
|
+
headers: {
|
|
73
|
+
'content-type': 'text/event-stream',
|
|
74
|
+
'cache-control': 'no-cache',
|
|
75
|
+
connection: 'keep-alive',
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
|
|
70
79
|
class ServerSentEventHandler<
|
|
71
80
|
EventMap extends EventMapConstraint,
|
|
72
81
|
> extends HttpHandler {
|
|
82
|
+
#emitter: Emitter<ServerSentEventClientEventMap>
|
|
83
|
+
|
|
73
84
|
constructor(path: Path, resolver: ServerSentEventResolver<EventMap, any>) {
|
|
74
85
|
invariant(
|
|
75
86
|
typeof EventSource !== 'undefined',
|
|
@@ -77,37 +88,12 @@ class ServerSentEventHandler<
|
|
|
77
88
|
path,
|
|
78
89
|
)
|
|
79
90
|
|
|
80
|
-
const clientEmitter = new Emitter<ServerSentEventClientEventMap>()
|
|
81
|
-
|
|
82
91
|
super('GET', path, async (info) => {
|
|
83
|
-
const responseInit: ResponseInit = {
|
|
84
|
-
headers: {
|
|
85
|
-
'content-type': 'text/event-stream',
|
|
86
|
-
'cache-control': 'no-cache',
|
|
87
|
-
connection: 'keep-alive',
|
|
88
|
-
},
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* @note Log the intercepted request early.
|
|
93
|
-
* Normally, the `this.log()` method is called when the handler returns a response.
|
|
94
|
-
* For SSE, call that method earlier so the logs are in correct order.
|
|
95
|
-
*/
|
|
96
|
-
await super.log({
|
|
97
|
-
request: info.request,
|
|
98
|
-
/**
|
|
99
|
-
* @note Construct a placeholder response since SSE response
|
|
100
|
-
* is being streamed and cannot be cloned/consumed for logging.
|
|
101
|
-
*/
|
|
102
|
-
response: new Response('[streaming]', responseInit),
|
|
103
|
-
})
|
|
104
|
-
this.#attachClientLogger(info.request, clientEmitter)
|
|
105
|
-
|
|
106
92
|
const stream = new ReadableStream({
|
|
107
|
-
async
|
|
93
|
+
start: async (controller) => {
|
|
108
94
|
const client = new ServerSentEventClient<EventMap>({
|
|
109
95
|
controller,
|
|
110
|
-
emitter:
|
|
96
|
+
emitter: this.#emitter,
|
|
111
97
|
})
|
|
112
98
|
const server = new ServerSentEventServer({
|
|
113
99
|
request: info.request,
|
|
@@ -122,19 +108,42 @@ class ServerSentEventHandler<
|
|
|
122
108
|
},
|
|
123
109
|
})
|
|
124
110
|
|
|
125
|
-
return new Response(stream,
|
|
111
|
+
return new Response(stream, SSE_RESPONSE_INIT)
|
|
126
112
|
})
|
|
113
|
+
|
|
114
|
+
this.#emitter = new Emitter<ServerSentEventClientEventMap>()
|
|
127
115
|
}
|
|
128
116
|
|
|
129
117
|
async predicate(args: {
|
|
130
118
|
request: Request
|
|
131
119
|
parsedResult: HttpRequestParsedResult
|
|
120
|
+
resolutionContext?: ResponseResolutionContext
|
|
132
121
|
}) {
|
|
133
122
|
if (args.request.headers.get('accept') !== 'text/event-stream') {
|
|
134
123
|
return false
|
|
135
124
|
}
|
|
136
125
|
|
|
137
|
-
|
|
126
|
+
const matches = await super.predicate(args)
|
|
127
|
+
|
|
128
|
+
if (matches && !args.resolutionContext?.quiet) {
|
|
129
|
+
/**
|
|
130
|
+
* @note Log the intercepted request early.
|
|
131
|
+
* Normally, the `this.log()` method is called when the handler returns a response.
|
|
132
|
+
* For SSE, call that method earlier so the logs are in correct order.
|
|
133
|
+
*/
|
|
134
|
+
await super.log({
|
|
135
|
+
request: args.request,
|
|
136
|
+
/**
|
|
137
|
+
* @note Construct a placeholder response since SSE response
|
|
138
|
+
* is being streamed and cannot be cloned/consumed for logging.
|
|
139
|
+
*/
|
|
140
|
+
response: new Response('[streaming]', SSE_RESPONSE_INIT),
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
this.#attachClientLogger(args.request, this.#emitter)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return matches
|
|
138
147
|
}
|
|
139
148
|
|
|
140
149
|
async log(_args: { request: Request; response: Response }): Promise<void> {
|
|
@@ -10,7 +10,13 @@ export interface HandlersExecutionResult {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export interface ResponseResolutionContext {
|
|
13
|
+
/**
|
|
14
|
+
* A base url to use when resolving relative urls.
|
|
15
|
+
* @note This is primarily used by the `@mswjs/http-middleware`
|
|
16
|
+
* to resolve relative urls in the context of the running server
|
|
17
|
+
*/
|
|
13
18
|
baseUrl?: string
|
|
19
|
+
quiet?: boolean
|
|
14
20
|
}
|
|
15
21
|
|
|
16
22
|
/**
|
|
@@ -3,7 +3,11 @@ import { Emitter } from 'strict-event-emitter'
|
|
|
3
3
|
import { LifeCycleEventsMap, SharedOptions } from '../sharedOptions'
|
|
4
4
|
import { RequiredDeep } from '../typeUtils'
|
|
5
5
|
import type { RequestHandler } from '../handlers/RequestHandler'
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
type HandlersExecutionResult,
|
|
8
|
+
type ResponseResolutionContext,
|
|
9
|
+
executeHandlers,
|
|
10
|
+
} from './executeHandlers'
|
|
7
11
|
import { onUnhandledRequest } from './request/onUnhandledRequest'
|
|
8
12
|
import { storeResponseCookies } from './request/storeResponseCookies'
|
|
9
13
|
|
|
@@ -13,14 +17,7 @@ export interface HandleRequestOptions {
|
|
|
13
17
|
* but is exposed to aid in creating extensions like
|
|
14
18
|
* `@mswjs/http-middleware`.
|
|
15
19
|
*/
|
|
16
|
-
resolutionContext?:
|
|
17
|
-
/**
|
|
18
|
-
* A base url to use when resolving relative urls.
|
|
19
|
-
* @note This is primarily used by the `@mswjs/http-middleware`
|
|
20
|
-
* to resolve relative urls in the context of the running server
|
|
21
|
-
*/
|
|
22
|
-
baseUrl?: string
|
|
23
|
-
}
|
|
20
|
+
resolutionContext?: ResponseResolutionContext
|
|
24
21
|
|
|
25
22
|
/**
|
|
26
23
|
* Invoked whenever a request is performed as-is.
|