@depup/msw 3.0.2-depup.0 → 3.0.3-depup.0
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 +5 -4
- package/changes.json +7 -3
- package/lib/_chunks/cookie-store.js +3 -2
- package/lib/_chunks/cookie-store.js.map +1 -1
- package/lib/_chunks/interceptor-source.d.ts +5 -1
- package/lib/_chunks/interceptor-source.js +18 -5
- package/lib/_chunks/interceptor-source.js.map +1 -1
- package/lib/_chunks/request-handler.d.ts +3 -2
- package/lib/browser/index.d.ts +4 -9
- package/lib/browser/index.js +21 -14
- package/lib/browser/index.js.map +1 -1
- package/lib/graphql/index.d.ts +19 -4
- package/lib/graphql/index.js +24 -12
- package/lib/graphql/index.js.map +1 -1
- package/lib/iife/index.js +66 -33
- package/lib/iife/index.js.map +1 -1
- package/lib/mockServiceWorker.js +1 -1
- package/package.json +12 -9
- package/src/browser/default-network-options.ts +1 -1
- package/src/browser/setup-worker.ts +1 -4
- package/src/browser/sources/fallback-http-source.ts +11 -8
- package/src/browser/sources/service-worker-source.ts +12 -5
- package/src/browser/utils/should-invalidate-worker.test.ts +0 -16
- package/src/core/experimental/define-network.ts +1 -1
- package/src/core/experimental/handlers-controller.test.ts +61 -0
- package/src/core/experimental/handlers-controller.ts +39 -6
- package/src/core/experimental/sources/network-source.ts +8 -1
- package/src/core/handlers/handler.ts +3 -2
- package/src/graphql/graphql-subscription.ts +30 -12
package/lib/mockServiceWorker.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@depup/msw",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3-depup.0",
|
|
4
4
|
"description": "The industry standard for API mocking in JavaScript. (with updated dependencies)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/core/index.js",
|
|
@@ -94,7 +94,6 @@
|
|
|
94
94
|
"funding": "https://github.com/sponsors/mswjs",
|
|
95
95
|
"files": [
|
|
96
96
|
"config/constants.js",
|
|
97
|
-
"config/scripts/postinstall.js",
|
|
98
97
|
"cli",
|
|
99
98
|
"lib",
|
|
100
99
|
"src",
|
|
@@ -123,9 +122,9 @@
|
|
|
123
122
|
],
|
|
124
123
|
"sideEffects": false,
|
|
125
124
|
"dependencies": {
|
|
126
|
-
"@inquirer/confirm": "^6.3.
|
|
125
|
+
"@inquirer/confirm": "^6.3.3",
|
|
127
126
|
"@msw/url": "^0.1.2",
|
|
128
|
-
"@mswjs/interceptors": "^0.45.
|
|
127
|
+
"@mswjs/interceptors": "^0.45.7",
|
|
129
128
|
"cookie": "^2.0.1",
|
|
130
129
|
"headers-polyfill": "^5.0.1",
|
|
131
130
|
"is-node-process": "^1.2.0",
|
|
@@ -167,7 +166,7 @@
|
|
|
167
166
|
"json-bigint": "^1.0.0",
|
|
168
167
|
"knip": "^6.34.0",
|
|
169
168
|
"lint-staged": "^17.1.1",
|
|
170
|
-
"msw": "^3.0.
|
|
169
|
+
"msw": "^3.0.3",
|
|
171
170
|
"oxlint": "^1.75.0",
|
|
172
171
|
"page-with": "^0.6.1",
|
|
173
172
|
"prettier": "^3.9.6",
|
|
@@ -229,17 +228,21 @@
|
|
|
229
228
|
"changes": {
|
|
230
229
|
"@inquirer/confirm": {
|
|
231
230
|
"from": "^6.0.11",
|
|
232
|
-
"to": "^6.3.
|
|
231
|
+
"to": "^6.3.3"
|
|
232
|
+
},
|
|
233
|
+
"@mswjs/interceptors": {
|
|
234
|
+
"from": "^0.45.6",
|
|
235
|
+
"to": "^0.45.7"
|
|
233
236
|
},
|
|
234
237
|
"type-fest": {
|
|
235
238
|
"from": "^5.5.0",
|
|
236
239
|
"to": "^5.10.0"
|
|
237
240
|
}
|
|
238
241
|
},
|
|
239
|
-
"depsUpdated":
|
|
242
|
+
"depsUpdated": 3,
|
|
240
243
|
"originalPackage": "msw",
|
|
241
|
-
"originalVersion": "3.0.
|
|
242
|
-
"processedAt": "2026-10-
|
|
244
|
+
"originalVersion": "3.0.3",
|
|
245
|
+
"processedAt": "2026-10-10T04:42:39.550Z",
|
|
243
246
|
"smokeTest": "passed"
|
|
244
247
|
}
|
|
245
248
|
}
|
|
@@ -17,7 +17,7 @@ export function createDefaultNetworkOptions(
|
|
|
17
17
|
sources: [
|
|
18
18
|
supportsServiceWorker()
|
|
19
19
|
? new ServiceWorkerSource({ serviceWorker: { url: workerUrl } })
|
|
20
|
-
: new FallbackHttpSource(
|
|
20
|
+
: new FallbackHttpSource(),
|
|
21
21
|
new InterceptorSource({
|
|
22
22
|
interceptors: [
|
|
23
23
|
new WebSocketInterceptor() as InterceptorSourceOptions['interceptors'][number],
|
|
@@ -56,11 +56,8 @@ export function setupWorker(...handlers: Array<AnyHandler>): SetupWorker {
|
|
|
56
56
|
options: options?.serviceWorker?.options,
|
|
57
57
|
},
|
|
58
58
|
findWorker: options?.findWorker,
|
|
59
|
-
quiet: options?.quiet,
|
|
60
|
-
})
|
|
61
|
-
: new FallbackHttpSource({
|
|
62
|
-
quiet: options?.quiet,
|
|
63
59
|
})
|
|
60
|
+
: new FallbackHttpSource()
|
|
64
61
|
|
|
65
62
|
network.configure({
|
|
66
63
|
sources: [
|
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
import { FetchInterceptor } from '@mswjs/interceptors/fetch'
|
|
2
2
|
import { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest'
|
|
3
3
|
import { InterceptorSource } from '#core/experimental/sources/interceptor-source'
|
|
4
|
+
import type { NetworkFrameResolutionContext } from '#core/experimental/frames/network-frame'
|
|
4
5
|
import { devUtils } from '#core/utils/internal/dev-utils'
|
|
5
6
|
|
|
6
|
-
interface FallbackHttpSourceOptions {
|
|
7
|
-
quiet?: boolean
|
|
8
|
-
}
|
|
9
|
-
|
|
10
7
|
export class FallbackHttpSource extends InterceptorSource {
|
|
11
|
-
|
|
8
|
+
/**
|
|
9
|
+
* The resolved context of the network this source was last enabled with.
|
|
10
|
+
*/
|
|
11
|
+
#context?: NetworkFrameResolutionContext
|
|
12
|
+
|
|
13
|
+
constructor() {
|
|
12
14
|
super({
|
|
13
15
|
interceptors: [new XMLHttpRequestInterceptor(), new FetchInterceptor()],
|
|
14
16
|
})
|
|
15
17
|
}
|
|
16
18
|
|
|
17
|
-
public enable(): void {
|
|
19
|
+
public enable(context?: NetworkFrameResolutionContext): void {
|
|
20
|
+
this.#context = context
|
|
18
21
|
super.enable()
|
|
19
22
|
|
|
20
|
-
if (!this
|
|
23
|
+
if (!this.#context?.quiet) {
|
|
21
24
|
this.#printStartMessage()
|
|
22
25
|
}
|
|
23
26
|
}
|
|
@@ -25,7 +28,7 @@ export class FallbackHttpSource extends InterceptorSource {
|
|
|
25
28
|
public disable(): void {
|
|
26
29
|
super.disable()
|
|
27
30
|
|
|
28
|
-
if (!this
|
|
31
|
+
if (!this.#context?.quiet) {
|
|
29
32
|
this.#printStopMessage()
|
|
30
33
|
}
|
|
31
34
|
}
|
|
@@ -2,6 +2,7 @@ import { invariant } from 'outvariant'
|
|
|
2
2
|
import type { Emitter } from 'rettime'
|
|
3
3
|
import { FetchResponse } from '@mswjs/interceptors'
|
|
4
4
|
import { NetworkSource } from '#core/experimental/sources/network-source'
|
|
5
|
+
import type { NetworkFrameResolutionContext } from '#core/experimental/frames/network-frame'
|
|
5
6
|
import { RequestHandler } from '#core/handlers/request-handler'
|
|
6
7
|
import {
|
|
7
8
|
HttpNetworkFrame,
|
|
@@ -23,7 +24,6 @@ import { validateWorkerScope } from '../utils/validate-worker-scope'
|
|
|
23
24
|
import { shouldInvalidateWorker } from '../utils/should-invalidate-worker'
|
|
24
25
|
|
|
25
26
|
export interface ServiceWorkerSourceOptions {
|
|
26
|
-
quiet?: boolean
|
|
27
27
|
serviceWorker: {
|
|
28
28
|
url: string
|
|
29
29
|
options?: RegistrationOptions
|
|
@@ -75,6 +75,10 @@ export class ServiceWorkerSource extends NetworkSource<ServiceWorkerHttpNetworkF
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
#options: ServiceWorkerSourceOptions
|
|
78
|
+
/**
|
|
79
|
+
* The resolved context of the network this source was last enabled with.
|
|
80
|
+
*/
|
|
81
|
+
#context?: NetworkFrameResolutionContext
|
|
78
82
|
/**
|
|
79
83
|
* @note We cannot use `WeakMap` here as request/response
|
|
80
84
|
* identity cannot be preserved through the client-worker channel.
|
|
@@ -109,7 +113,10 @@ export class ServiceWorkerSource extends NetworkSource<ServiceWorkerHttpNetworkF
|
|
|
109
113
|
})
|
|
110
114
|
}
|
|
111
115
|
|
|
112
|
-
public async enable(
|
|
116
|
+
public async enable(
|
|
117
|
+
context?: NetworkFrameResolutionContext,
|
|
118
|
+
): Promise<ServiceWorkerRegistration> {
|
|
119
|
+
this.#context = context
|
|
113
120
|
this.#channel.removeAllListeners()
|
|
114
121
|
this.#frames.clear()
|
|
115
122
|
|
|
@@ -147,7 +154,7 @@ export class ServiceWorkerSource extends NetworkSource<ServiceWorkerHttpNetworkF
|
|
|
147
154
|
})
|
|
148
155
|
await clientConfirmationPromise.promise
|
|
149
156
|
|
|
150
|
-
if (!this.#
|
|
157
|
+
if (!this.#context?.quiet) {
|
|
151
158
|
this.#printStartMessage()
|
|
152
159
|
}
|
|
153
160
|
|
|
@@ -178,7 +185,7 @@ export class ServiceWorkerSource extends NetworkSource<ServiceWorkerHttpNetworkF
|
|
|
178
185
|
* `#handleRequest`. `#startWorker` swaps in a fresh deferred on re-enable.
|
|
179
186
|
*/
|
|
180
187
|
|
|
181
|
-
if (!this.#
|
|
188
|
+
if (!this.#context?.quiet) {
|
|
182
189
|
this.#printStopMessage()
|
|
183
190
|
}
|
|
184
191
|
}
|
|
@@ -294,7 +301,7 @@ Please consider using a custom "serviceWorker.url" option to point to the actual
|
|
|
294
301
|
this.#channel.postMessage('KEEPALIVE_REQUEST')
|
|
295
302
|
}, 5000)
|
|
296
303
|
|
|
297
|
-
if (!this.#
|
|
304
|
+
if (!this.#context?.quiet) {
|
|
298
305
|
validateWorkerScope(registration)
|
|
299
306
|
}
|
|
300
307
|
|
|
@@ -104,19 +104,3 @@ test('returns false when findWorker is the same reference', () => {
|
|
|
104
104
|
),
|
|
105
105
|
).toBe(false)
|
|
106
106
|
})
|
|
107
|
-
|
|
108
|
-
test('returns false regardless of the "quiet" option', () => {
|
|
109
|
-
expect(
|
|
110
|
-
shouldInvalidateWorker(
|
|
111
|
-
createOptions({ quiet: true }),
|
|
112
|
-
createOptions({ quiet: true }),
|
|
113
|
-
),
|
|
114
|
-
).toBe(false)
|
|
115
|
-
|
|
116
|
-
expect(
|
|
117
|
-
shouldInvalidateWorker(
|
|
118
|
-
createOptions({ quiet: false }),
|
|
119
|
-
createOptions({ quiet: true }),
|
|
120
|
-
),
|
|
121
|
-
).toBe(false)
|
|
122
|
-
})
|
|
@@ -308,6 +308,67 @@ describe(InMemoryHandlersController.prototype.reset, () => {
|
|
|
308
308
|
expect(controller.getHandlersByKind('websocket')).toEqual([wsOne, wsTwo])
|
|
309
309
|
expect(controller.getHandlersByKind('request')).toEqual([upgradeHandler])
|
|
310
310
|
})
|
|
311
|
+
|
|
312
|
+
test('resets the kept handlers and disposes of the removed ones', () => {
|
|
313
|
+
const initialHandler = http.get('/initial', () => {})
|
|
314
|
+
initialHandler.reset = vi.fn()
|
|
315
|
+
initialHandler.dispose = vi.fn()
|
|
316
|
+
const runtimeHandler = http.get('/runtime', () => {})
|
|
317
|
+
runtimeHandler.reset = vi.fn()
|
|
318
|
+
runtimeHandler.dispose = vi.fn()
|
|
319
|
+
|
|
320
|
+
const controller = new InMemoryHandlersController([initialHandler])
|
|
321
|
+
controller.use([runtimeHandler])
|
|
322
|
+
controller.reset([])
|
|
323
|
+
|
|
324
|
+
expect.soft(initialHandler.reset).toHaveBeenCalledOnce()
|
|
325
|
+
expect.soft(initialHandler.dispose).not.toHaveBeenCalled()
|
|
326
|
+
expect.soft(runtimeHandler.reset).not.toHaveBeenCalled()
|
|
327
|
+
expect(runtimeHandler.dispose).toHaveBeenCalledOnce()
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
test('reports a rejected disposal of a removed handler', async () => {
|
|
331
|
+
vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
332
|
+
onTestFinished(() => vi.restoreAllMocks())
|
|
333
|
+
|
|
334
|
+
const runtimeHandler = http.get('/runtime', () => {})
|
|
335
|
+
runtimeHandler.dispose = () =>
|
|
336
|
+
Promise.reject(new Error('Handler disposal error'))
|
|
337
|
+
|
|
338
|
+
const controller = new InMemoryHandlersController([])
|
|
339
|
+
controller.use([runtimeHandler])
|
|
340
|
+
controller.reset([])
|
|
341
|
+
|
|
342
|
+
await expect
|
|
343
|
+
.poll(() => console.error)
|
|
344
|
+
.toHaveBeenCalledWith(
|
|
345
|
+
`[MSW] Failed to dispose of "request" handler removed during reset. Please see the original error below.\nError: Handler disposal error`,
|
|
346
|
+
)
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
test('removes the remaining handlers when a disposal throws', () => {
|
|
350
|
+
vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
351
|
+
onTestFinished(() => vi.restoreAllMocks())
|
|
352
|
+
|
|
353
|
+
const throwingHandler = http.get('/throwing', () => {})
|
|
354
|
+
throwingHandler.dispose = () => {
|
|
355
|
+
throw new Error('Handler disposal error')
|
|
356
|
+
}
|
|
357
|
+
const runtimeHandler = http.get('/runtime', () => {})
|
|
358
|
+
runtimeHandler.dispose = vi.fn()
|
|
359
|
+
|
|
360
|
+
const controller = new InMemoryHandlersController([])
|
|
361
|
+
controller.use([throwingHandler, runtimeHandler])
|
|
362
|
+
controller.reset([])
|
|
363
|
+
|
|
364
|
+
expect
|
|
365
|
+
.soft(console.error)
|
|
366
|
+
.toHaveBeenCalledWith(
|
|
367
|
+
`[MSW] Failed to dispose of "request" handler removed during reset. Please see the original error below.\nError: Handler disposal error`,
|
|
368
|
+
)
|
|
369
|
+
expect.soft(runtimeHandler.dispose).toHaveBeenCalledOnce()
|
|
370
|
+
expect(controller.currentHandlers()).toEqual([])
|
|
371
|
+
})
|
|
311
372
|
})
|
|
312
373
|
|
|
313
374
|
describe(InMemoryHandlersController.prototype.listHandlers, () => {
|
|
@@ -168,11 +168,38 @@ export abstract class HandlersController {
|
|
|
168
168
|
),
|
|
169
169
|
)
|
|
170
170
|
|
|
171
|
-
|
|
171
|
+
const { initialHandlers } = this.getState()
|
|
172
|
+
const nextInitialHandlers =
|
|
173
|
+
nextHandlers.length > 0
|
|
174
|
+
? groupHandlersByKind(nextHandlers)
|
|
175
|
+
: initialHandlers
|
|
176
|
+
const currentHandlers = new Set(this.currentHandlers())
|
|
177
|
+
const nextHandlersSet = new Set(
|
|
178
|
+
Object.values(nextInitialHandlers).flat().filter(Boolean),
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
for (const handler of currentHandlers.intersection(nextHandlersSet)) {
|
|
172
182
|
handler.reset()
|
|
173
183
|
}
|
|
174
184
|
|
|
175
|
-
|
|
185
|
+
// The handlers that leave the network with this reset release
|
|
186
|
+
// whatever they hold (e.g. live connection bindings).
|
|
187
|
+
// Resetting is synchronous, so their disposal is not awaited.
|
|
188
|
+
for (const handler of currentHandlers.difference(nextHandlersSet)) {
|
|
189
|
+
try {
|
|
190
|
+
const disposal = handler.dispose()
|
|
191
|
+
|
|
192
|
+
if (disposal instanceof Promise) {
|
|
193
|
+
disposal.catch((error) => {
|
|
194
|
+
this.#printDisposalError(handler, error)
|
|
195
|
+
})
|
|
196
|
+
}
|
|
197
|
+
} catch (error) {
|
|
198
|
+
// A failing disposal must not prevent the remaining handlers
|
|
199
|
+
// from being disposed of, nor the removed handlers from being cleared.
|
|
200
|
+
this.#printDisposalError(handler, error)
|
|
201
|
+
}
|
|
202
|
+
}
|
|
176
203
|
|
|
177
204
|
if (nextHandlers.length === 0) {
|
|
178
205
|
this.setState({
|
|
@@ -182,11 +209,9 @@ export abstract class HandlersController {
|
|
|
182
209
|
return
|
|
183
210
|
}
|
|
184
211
|
|
|
185
|
-
const normalizedNextHandlers = groupHandlersByKind(nextHandlers)
|
|
186
|
-
|
|
187
212
|
this.setState({
|
|
188
|
-
initialHandlers:
|
|
189
|
-
handlers: { ...
|
|
213
|
+
initialHandlers: nextInitialHandlers,
|
|
214
|
+
handlers: { ...nextInitialHandlers },
|
|
190
215
|
})
|
|
191
216
|
}
|
|
192
217
|
|
|
@@ -217,6 +242,14 @@ export abstract class HandlersController {
|
|
|
217
242
|
#validateHandlers(handlers: Array<AnyHandler>): boolean {
|
|
218
243
|
return handlers.every((handler) => !Array.isArray(handler))
|
|
219
244
|
}
|
|
245
|
+
|
|
246
|
+
#printDisposalError(handler: AnyHandler, error: unknown): void {
|
|
247
|
+
devUtils.error(
|
|
248
|
+
'Failed to dispose of "%s" handler removed during reset. Please see the original error below.\n%s',
|
|
249
|
+
handler.kind,
|
|
250
|
+
error,
|
|
251
|
+
)
|
|
252
|
+
}
|
|
220
253
|
}
|
|
221
254
|
|
|
222
255
|
export class InMemoryHandlersController extends HandlersController {
|
|
@@ -2,6 +2,7 @@ import { Emitter, TypedEvent, type TypedListenerOptions } from 'rettime'
|
|
|
2
2
|
import type {
|
|
3
3
|
AnyNetworkFrame,
|
|
4
4
|
ExtractFrameEvents,
|
|
5
|
+
NetworkFrameResolutionContext,
|
|
5
6
|
} from '../frames/network-frame'
|
|
6
7
|
|
|
7
8
|
class NetworkFrameEvent<
|
|
@@ -33,7 +34,13 @@ export abstract class NetworkSource<
|
|
|
33
34
|
this.emitter = new Emitter()
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Enable this network source.
|
|
39
|
+
* @param context The resolved context of the network this source belongs to.
|
|
40
|
+
*/
|
|
41
|
+
public abstract enable(
|
|
42
|
+
context?: NetworkFrameResolutionContext,
|
|
43
|
+
): unknown | Promise<unknown>
|
|
37
44
|
|
|
38
45
|
public async queue(frame: Frame): Promise<void> {
|
|
39
46
|
await this.emitter.emitAsPromise(
|
|
@@ -32,8 +32,9 @@ export abstract class Handler {
|
|
|
32
32
|
/**
|
|
33
33
|
* Release the resources held by this handler.
|
|
34
34
|
*
|
|
35
|
-
* @note This method is invoked automatically when the
|
|
36
|
-
* disabled (e.g. `server.close()`)
|
|
35
|
+
* @note This method is invoked automatically when the handler leaves
|
|
36
|
+
* the network: when the network is disabled (e.g. `server.close()`)
|
|
37
|
+
* or when a reset removes it (e.g. `server.resetHandlers()`). Override it in the handlers that
|
|
37
38
|
* hold onto anything beyond a single frame, like timers, connections,
|
|
38
39
|
* or event listeners. Returning a promise makes the network await
|
|
39
40
|
* this handler's disposal before it tears itself down.
|
|
@@ -585,24 +585,32 @@ export class GraphQLSubscriptionTransportHandler extends GraphQLWebSocketHandler
|
|
|
585
585
|
}
|
|
586
586
|
|
|
587
587
|
/**
|
|
588
|
-
*
|
|
589
|
-
*
|
|
590
|
-
*
|
|
591
|
-
|
|
588
|
+
* Remove the given handler from the subscribers of every session
|
|
589
|
+
* this transport participates in. The handler no longer matches
|
|
590
|
+
* subscriptions on the connections opened while it was registered.
|
|
591
|
+
*/
|
|
592
|
+
public unsubscribe(handler: WebSocketHandler): void {
|
|
593
|
+
for (const connection of connections.values()) {
|
|
594
|
+
connection.subscribers.delete(handler)
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* End the active subscriptions of the sessions this transport
|
|
600
|
+
* participates in. The sessions and their subscribers are left intact:
|
|
601
|
+
* the handlers that survive the reset keep serving the connections
|
|
602
|
+
* opened before it, while the removed handlers unsubscribe themselves
|
|
603
|
+
* on disposal. The sessions own the protocol listeners for as long as
|
|
604
|
+
* the client stays connected.
|
|
592
605
|
*
|
|
593
606
|
* @note This method is invoked automatically when the handlers
|
|
594
607
|
* controller resets the handlers (e.g. `server.resetHandlers()`).
|
|
595
608
|
*/
|
|
596
609
|
public reset(): void {
|
|
597
610
|
for (const connection of connections.values()) {
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
if (entry.transport === this) {
|
|
602
|
-
connection.subscribers.delete(handler)
|
|
603
|
-
ownsConnection = true
|
|
604
|
-
}
|
|
605
|
-
}
|
|
611
|
+
const ownsConnection = Array.from(connection.subscribers.values()).some(
|
|
612
|
+
(entry) => entry.transport === this,
|
|
613
|
+
)
|
|
606
614
|
|
|
607
615
|
// Resetting the handlers detaches the resolvers from their
|
|
608
616
|
// subscriptions, so run their cleanups instead of dropping them.
|
|
@@ -935,6 +943,16 @@ export class GraphQLSubscriptionHandler<
|
|
|
935
943
|
this.isUsed = false
|
|
936
944
|
}
|
|
937
945
|
|
|
946
|
+
/**
|
|
947
|
+
* Stop serving the connections this handler was bound to.
|
|
948
|
+
* @note This method is invoked automatically when the handler
|
|
949
|
+
* is removed from the network, either by resetting the handlers
|
|
950
|
+
* (e.g. `server.resetHandlers()`) or by disabling the network.
|
|
951
|
+
*/
|
|
952
|
+
public dispose(): void {
|
|
953
|
+
this.#transport.unsubscribe(this)
|
|
954
|
+
}
|
|
955
|
+
|
|
938
956
|
/**
|
|
939
957
|
* @note Individual subscription handlers stay silent. The subscription
|
|
940
958
|
* transport owns the GraphQL-aware logging for the entire connection
|