@depup/msw 3.0.1-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.
Files changed (39) hide show
  1. package/README.md +5 -4
  2. package/changes.json +7 -3
  3. package/lib/_chunks/cookie-store.js +3 -2
  4. package/lib/_chunks/cookie-store.js.map +1 -1
  5. package/lib/_chunks/interceptor-source.d.ts +5 -1
  6. package/lib/_chunks/interceptor-source.js +18 -5
  7. package/lib/_chunks/interceptor-source.js.map +1 -1
  8. package/lib/_chunks/request-handler.d.ts +3 -2
  9. package/lib/browser/index.d.ts +4 -9
  10. package/lib/browser/index.js +21 -14
  11. package/lib/browser/index.js.map +1 -1
  12. package/lib/graphql/index.d.ts +19 -4
  13. package/lib/graphql/index.js +24 -12
  14. package/lib/graphql/index.js.map +1 -1
  15. package/lib/iife/index.js +66 -33
  16. package/lib/iife/index.js.map +1 -1
  17. package/lib/mockServiceWorker.js +1 -1
  18. package/lib/vite/index.js +10 -7
  19. package/lib/vite/index.js.map +1 -1
  20. package/lib/vite/runtime.d.ts +2 -3
  21. package/lib/vite/runtime.js +70 -68
  22. package/lib/vite/runtime.js.map +1 -1
  23. package/package.json +12 -9
  24. package/src/browser/default-network-options.ts +1 -1
  25. package/src/browser/setup-worker.ts +1 -4
  26. package/src/browser/sources/fallback-http-source.ts +11 -8
  27. package/src/browser/sources/service-worker-source.ts +12 -5
  28. package/src/browser/utils/should-invalidate-worker.test.ts +0 -16
  29. package/src/core/experimental/define-network.ts +1 -1
  30. package/src/core/experimental/handlers-controller.test.ts +61 -0
  31. package/src/core/experimental/handlers-controller.ts +39 -6
  32. package/src/core/experimental/sources/network-source.ts +8 -1
  33. package/src/core/handlers/handler.ts +3 -2
  34. package/src/graphql/graphql-subscription.ts +30 -12
  35. package/src/vite/plugin.test.ts +1 -1
  36. package/src/vite/plugin.ts +13 -10
  37. package/src/vite/runtime.ts +85 -85
  38. package/src/vite/tsconfig.build.json +1 -1
  39. package/src/vite/options.d.ts +0 -5
@@ -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 network is
36
- * disabled (e.g. `server.close()`). Override it in the handlers that
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
- * Drop this transport's subscribers and active subscriptions from the
589
- * sessions it participates in. The sessions themselves are left intact:
590
- * they are shared with the other transports of the same connection and
591
- * own the protocol listeners for as long as the client stays connected.
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
- let ownsConnection = false
599
-
600
- for (const [handler, entry] of connection.subscribers) {
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
@@ -784,7 +784,7 @@ test('serves only the worker in worker-only mode with an absolute base URL', asy
784
784
  server.environments.client.pluginContainer.resolveId('virtual:msw'),
785
785
  ).resolves.toBeNull()
786
786
  await expect(
787
- server.environments.ssr.pluginContainer.resolveId('virtual:msw/options'),
787
+ server.environments.ssr.pluginContainer.resolveId('virtual:msw'),
788
788
  ).resolves.toBeNull()
789
789
  })
790
790
 
@@ -5,7 +5,6 @@ import type { Plugin } from 'vite'
5
5
  const WORKER_FILENAME = 'mockServiceWorker.js'
6
6
  const WORKER_SCRIPT_PATH = new URL('../mockServiceWorker.js', import.meta.url)
7
7
  const VIRTUAL_MODULE_ID = 'virtual:msw'
8
- const VIRTUAL_OPTIONS_ID = 'virtual:msw/options'
9
8
  const RUNTIME_PATH = fileURLToPath(new URL('./runtime.js', import.meta.url))
10
9
 
11
10
  export interface MswPluginOptions {
@@ -53,33 +52,37 @@ export function msw(options: MswPluginOptions = {}): Plugin {
53
52
 
54
53
  return {
55
54
  name: 'msw',
56
- async resolveId(id) {
55
+ resolveId(id) {
57
56
  if (mode === 'worker-only') {
58
57
  return
59
58
  }
60
59
 
61
- if (id === VIRTUAL_OPTIONS_ID) {
62
- return `\0${VIRTUAL_OPTIONS_ID}`
63
- }
64
-
65
60
  if (id === VIRTUAL_MODULE_ID) {
66
- return this.resolve(RUNTIME_PATH)
61
+ return `\0${VIRTUAL_MODULE_ID}`
67
62
  }
68
63
  },
69
64
  load(id) {
70
- if (mode === 'worker-only' || id !== `\0${VIRTUAL_OPTIONS_ID}`) {
65
+ if (mode === 'worker-only' || id !== `\0${VIRTUAL_MODULE_ID}`) {
71
66
  return
72
67
  }
73
68
 
69
+ // Tools like Vitest import the runtime natively when it's installed
70
+ // in "node_modules". Provide it with the environment's options from here
71
+ // so it never has to import a virtual module that only Vite can resolve.
74
72
  if (this.environment.config.consumer === 'server') {
75
- return `export { defaultNetworkOptions } from 'msw/node'`
73
+ return `
74
+ import { defaultNetworkOptions } from 'msw/node'
75
+ import { createNetwork } from ${JSON.stringify(RUNTIME_PATH)}
76
+ export const network = await createNetwork(defaultNetworkOptions)
77
+ `
76
78
  }
77
79
 
78
80
  environmentsUsingNetwork.add(this.environment.name)
79
81
 
80
82
  return `
81
83
  import { createDefaultNetworkOptions } from 'msw/browser'
82
- export const defaultNetworkOptions = createDefaultNetworkOptions(${JSON.stringify(workerUrl)})
84
+ import { createNetwork } from ${JSON.stringify(RUNTIME_PATH)}
85
+ export const network = await createNetwork(createDefaultNetworkOptions(${JSON.stringify(workerUrl)}))
83
86
  `
84
87
  },
85
88
  configResolved(config) {
@@ -1,117 +1,117 @@
1
1
  /// <reference types="vite/client" />
2
2
 
3
- import {
4
- defineNetwork,
5
- NetworkReadyState,
6
- type NetworkApi,
7
- } from 'msw/experimental'
8
- import { defaultNetworkOptions } from 'virtual:msw/options'
3
+ import { defineNetwork, NetworkReadyState } from 'msw/experimental'
9
4
 
10
5
  const hot = import.meta.hot
11
6
  const hotData: { disposeNetwork?: () => Promise<void> } | undefined = hot?.data
12
7
 
13
- // SSR imports can re-evaluate this module before the old HMR listener runs.
14
- while (hotData?.disposeNetwork) {
15
- const disposePrevious = hotData.disposeNetwork
16
- await disposePrevious()
8
+ export async function createNetwork(
9
+ options: Parameters<typeof defineNetwork>[0],
10
+ ): Promise<ReturnType<typeof defineNetwork>> {
11
+ // SSR imports can re-evaluate the network before the old HMR listener runs.
12
+ while (hotData?.disposeNetwork) {
13
+ const disposePrevious = hotData.disposeNetwork
14
+ await disposePrevious()
17
15
 
18
- if (hotData.disposeNetwork === disposePrevious) {
19
- break
16
+ if (hotData.disposeNetwork === disposePrevious) {
17
+ break
18
+ }
20
19
  }
21
- }
22
20
 
23
- export const network: NetworkApi<typeof defaultNetworkOptions.sources> =
24
- defineNetwork<typeof defaultNetworkOptions.sources>(defaultNetworkOptions)
21
+ const network = defineNetwork(options)
25
22
 
26
- if (hot && hotData) {
27
- let resumeAfterUpdate = false
28
- let retired = false
29
- let pendingOperation: Promise<void> | undefined
30
- const configure = network.configure
31
- const enable = network.enable
32
- const disable = network.disable
23
+ if (hot && hotData) {
24
+ let resumeAfterUpdate = false
25
+ let retired = false
26
+ let pendingOperation: Promise<void> | undefined
27
+ const configure = network.configure
28
+ const enable = network.enable
29
+ const disable = network.disable
33
30
 
34
- const runOperation = (action: () => void | Promise<void>) => {
35
- const result = pendingOperation ? pendingOperation.then(action) : action()
31
+ const runOperation = (action: () => void | Promise<void>) => {
32
+ const result = pendingOperation ? pendingOperation.then(action) : action()
36
33
 
37
- if (result instanceof Promise) {
38
- const operation = result.finally(() => {
39
- if (pendingOperation === operation) {
40
- pendingOperation = undefined
41
- }
42
- })
43
- pendingOperation = operation
34
+ if (result instanceof Promise) {
35
+ const operation = result.finally(() => {
36
+ if (pendingOperation === operation) {
37
+ pendingOperation = undefined
38
+ }
39
+ })
40
+ pendingOperation = operation
44
41
 
45
- return operation
42
+ return operation
43
+ }
46
44
  }
47
- }
48
45
 
49
- const stop = () => {
50
- if (network.readyState === NetworkReadyState.ENABLED) {
51
- return disable()
46
+ const stop = () => {
47
+ if (network.readyState === NetworkReadyState.ENABLED) {
48
+ return disable()
49
+ }
52
50
  }
53
- }
54
51
 
55
- // An SSR entry may be re-evaluated while this module remains cached.
56
- network.configure = (options) => {
57
- void runOperation(() => {
58
- if (retired) {
59
- return
60
- }
52
+ // An SSR entry may be re-evaluated while this module remains cached.
53
+ network.configure = (options) => {
54
+ void runOperation(() => {
55
+ if (retired) {
56
+ return
57
+ }
61
58
 
62
- const stopped = stop()
59
+ const stopped = stop()
63
60
 
64
- if (stopped instanceof Promise) {
65
- return stopped.then(() => configure(options))
66
- }
61
+ if (stopped instanceof Promise) {
62
+ return stopped.then(() => configure(options))
63
+ }
67
64
 
68
- configure(options)
69
- })
70
- }
71
- network.enable = async () => {
72
- await runOperation(() => {
73
- if (!retired && network.readyState === NetworkReadyState.DISABLED) {
74
- return enable()
75
- }
76
- })
77
- }
78
- network.disable = async () => {
79
- await runOperation(stop)
80
- }
65
+ configure(options)
66
+ })
67
+ }
68
+ network.enable = async () => {
69
+ await runOperation(() => {
70
+ if (!retired && network.readyState === NetworkReadyState.DISABLED) {
71
+ return enable()
72
+ }
73
+ })
74
+ }
75
+ network.disable = async () => {
76
+ await runOperation(stop)
77
+ }
81
78
 
82
- const disableNetwork = async () => {
83
- await network.disable()
84
- }
79
+ const disableNetwork = async () => {
80
+ await network.disable()
81
+ }
85
82
 
86
- const beforeUpdate = async () => {
87
- resumeAfterUpdate = network.readyState === NetworkReadyState.ENABLED
88
- await disableNetwork()
89
- }
83
+ const beforeUpdate = async () => {
84
+ resumeAfterUpdate = network.readyState === NetworkReadyState.ENABLED
85
+ await disableNetwork()
86
+ }
90
87
 
91
- const afterUpdate = async () => {
92
- const shouldResume = resumeAfterUpdate
93
- resumeAfterUpdate = false
88
+ const afterUpdate = async () => {
89
+ const shouldResume = resumeAfterUpdate
90
+ resumeAfterUpdate = false
94
91
 
95
- if (shouldResume && network.readyState === NetworkReadyState.DISABLED) {
96
- await network.enable()
92
+ if (shouldResume && network.readyState === NetworkReadyState.DISABLED) {
93
+ await network.enable()
94
+ }
97
95
  }
98
- }
99
96
 
100
- hot.on('vite:beforeUpdate', beforeUpdate)
101
- hot.on('vite:afterUpdate', afterUpdate)
102
- hot.on('vite:beforeFullReload', disableNetwork)
97
+ hot.on('vite:beforeUpdate', beforeUpdate)
98
+ hot.on('vite:afterUpdate', afterUpdate)
99
+ hot.on('vite:beforeFullReload', disableNetwork)
100
+
101
+ const disposeNetwork = async () => {
102
+ retired = true
103
+ resumeAfterUpdate = false
103
104
 
104
- const disposeNetwork = async () => {
105
- retired = true
106
- resumeAfterUpdate = false
105
+ hot.off('vite:beforeUpdate', beforeUpdate)
106
+ hot.off('vite:afterUpdate', afterUpdate)
107
+ hot.off('vite:beforeFullReload', disableNetwork)
107
108
 
108
- hot.off('vite:beforeUpdate', beforeUpdate)
109
- hot.off('vite:afterUpdate', afterUpdate)
110
- hot.off('vite:beforeFullReload', disableNetwork)
109
+ await disableNetwork()
110
+ }
111
111
 
112
- await disableNetwork()
112
+ hotData.disposeNetwork = disposeNetwork
113
+ hot.dispose(disposeNetwork)
113
114
  }
114
115
 
115
- hotData.disposeNetwork = disposeNetwork
116
- hot.dispose(disposeNetwork)
116
+ return network
117
117
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "extends": "../../tsconfig.base.json",
3
- "include": ["./index.ts", "./plugin.ts", "./runtime.ts", "./options.d.ts"],
3
+ "include": ["./index.ts", "./plugin.ts", "./runtime.ts"],
4
4
  "compilerOptions": {
5
5
  "types": ["node"]
6
6
  }
@@ -1,5 +0,0 @@
1
- declare module 'virtual:msw/options' {
2
- export const defaultNetworkOptions:
3
- | typeof import('msw/browser').defaultNetworkOptions
4
- | typeof import('msw/node').defaultNetworkOptions
5
- }