@depup/mswjs__interceptors 0.41.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 (248) hide show
  1. package/ClientRequest/package.json +11 -0
  2. package/LICENSE.md +9 -0
  3. package/README.md +31 -0
  4. package/RemoteHttpInterceptor/package.json +11 -0
  5. package/WebSocket/package.json +12 -0
  6. package/XMLHttpRequest/package.json +12 -0
  7. package/changes.json +10 -0
  8. package/fetch/package.json +12 -0
  9. package/lib/browser/Interceptor-Deczogc8.d.cts +65 -0
  10. package/lib/browser/Interceptor-gqKgs-aF.d.mts +65 -0
  11. package/lib/browser/XMLHttpRequest-BACqefB-.cjs +761 -0
  12. package/lib/browser/XMLHttpRequest-BACqefB-.cjs.map +1 -0
  13. package/lib/browser/XMLHttpRequest-BvxZV0WU.mjs +756 -0
  14. package/lib/browser/XMLHttpRequest-BvxZV0WU.mjs.map +1 -0
  15. package/lib/browser/bufferUtils-BiiO6HZv.mjs +20 -0
  16. package/lib/browser/bufferUtils-BiiO6HZv.mjs.map +1 -0
  17. package/lib/browser/bufferUtils-Uc0eRItL.cjs +38 -0
  18. package/lib/browser/bufferUtils-Uc0eRItL.cjs.map +1 -0
  19. package/lib/browser/createRequestId-Cs4oXfa1.cjs +205 -0
  20. package/lib/browser/createRequestId-Cs4oXfa1.cjs.map +1 -0
  21. package/lib/browser/createRequestId-DQcIlohW.mjs +170 -0
  22. package/lib/browser/createRequestId-DQcIlohW.mjs.map +1 -0
  23. package/lib/browser/fetch-DdKEdDOR.mjs +248 -0
  24. package/lib/browser/fetch-DdKEdDOR.mjs.map +1 -0
  25. package/lib/browser/fetch-U3v3Y4ap.cjs +253 -0
  26. package/lib/browser/fetch-U3v3Y4ap.cjs.map +1 -0
  27. package/lib/browser/getRawRequest-BTaNLFr0.mjs +218 -0
  28. package/lib/browser/getRawRequest-BTaNLFr0.mjs.map +1 -0
  29. package/lib/browser/getRawRequest-zx8rUJL2.cjs +259 -0
  30. package/lib/browser/getRawRequest-zx8rUJL2.cjs.map +1 -0
  31. package/lib/browser/glossary-BdLS4k1H.d.cts +70 -0
  32. package/lib/browser/glossary-DYwOrogs.d.mts +70 -0
  33. package/lib/browser/handleRequest-CvX2G-Lz.cjs +189 -0
  34. package/lib/browser/handleRequest-CvX2G-Lz.cjs.map +1 -0
  35. package/lib/browser/handleRequest-D7kpTI5U.mjs +178 -0
  36. package/lib/browser/handleRequest-D7kpTI5U.mjs.map +1 -0
  37. package/lib/browser/hasConfigurableGlobal-BvCTG97d.cjs +45 -0
  38. package/lib/browser/hasConfigurableGlobal-BvCTG97d.cjs.map +1 -0
  39. package/lib/browser/hasConfigurableGlobal-npXitu1-.mjs +33 -0
  40. package/lib/browser/hasConfigurableGlobal-npXitu1-.mjs.map +1 -0
  41. package/lib/browser/index.cjs +70 -0
  42. package/lib/browser/index.cjs.map +1 -0
  43. package/lib/browser/index.d.cts +96 -0
  44. package/lib/browser/index.d.mts +96 -0
  45. package/lib/browser/index.mjs +56 -0
  46. package/lib/browser/index.mjs.map +1 -0
  47. package/lib/browser/interceptors/WebSocket/index.cjs +622 -0
  48. package/lib/browser/interceptors/WebSocket/index.cjs.map +1 -0
  49. package/lib/browser/interceptors/WebSocket/index.d.cts +277 -0
  50. package/lib/browser/interceptors/WebSocket/index.d.mts +277 -0
  51. package/lib/browser/interceptors/WebSocket/index.mjs +615 -0
  52. package/lib/browser/interceptors/WebSocket/index.mjs.map +1 -0
  53. package/lib/browser/interceptors/XMLHttpRequest/index.cjs +7 -0
  54. package/lib/browser/interceptors/XMLHttpRequest/index.d.cts +15 -0
  55. package/lib/browser/interceptors/XMLHttpRequest/index.d.mts +15 -0
  56. package/lib/browser/interceptors/XMLHttpRequest/index.mjs +7 -0
  57. package/lib/browser/interceptors/fetch/index.cjs +6 -0
  58. package/lib/browser/interceptors/fetch/index.d.cts +13 -0
  59. package/lib/browser/interceptors/fetch/index.d.mts +13 -0
  60. package/lib/browser/interceptors/fetch/index.mjs +6 -0
  61. package/lib/browser/presets/browser.cjs +17 -0
  62. package/lib/browser/presets/browser.cjs.map +1 -0
  63. package/lib/browser/presets/browser.d.cts +12 -0
  64. package/lib/browser/presets/browser.d.mts +14 -0
  65. package/lib/browser/presets/browser.mjs +17 -0
  66. package/lib/browser/presets/browser.mjs.map +1 -0
  67. package/lib/browser/resolveWebSocketUrl-6K6EgqsA.cjs +31 -0
  68. package/lib/browser/resolveWebSocketUrl-6K6EgqsA.cjs.map +1 -0
  69. package/lib/browser/resolveWebSocketUrl-C83-x9iE.mjs +25 -0
  70. package/lib/browser/resolveWebSocketUrl-C83-x9iE.mjs.map +1 -0
  71. package/lib/node/BatchInterceptor-3LnAnLTx.cjs +49 -0
  72. package/lib/node/BatchInterceptor-3LnAnLTx.cjs.map +1 -0
  73. package/lib/node/BatchInterceptor-D7mXzHcQ.d.mts +26 -0
  74. package/lib/node/BatchInterceptor-DFaBPilf.mjs +44 -0
  75. package/lib/node/BatchInterceptor-DFaBPilf.mjs.map +1 -0
  76. package/lib/node/BatchInterceptor-D_YqR8qU.d.cts +26 -0
  77. package/lib/node/ClientRequest-2rDe54Ui.cjs +1043 -0
  78. package/lib/node/ClientRequest-2rDe54Ui.cjs.map +1 -0
  79. package/lib/node/ClientRequest-Ca8Qykuv.mjs +1034 -0
  80. package/lib/node/ClientRequest-Ca8Qykuv.mjs.map +1 -0
  81. package/lib/node/Interceptor-DEazpLJd.d.mts +133 -0
  82. package/lib/node/Interceptor-DJ2akVWI.d.cts +133 -0
  83. package/lib/node/RemoteHttpInterceptor.cjs +154 -0
  84. package/lib/node/RemoteHttpInterceptor.cjs.map +1 -0
  85. package/lib/node/RemoteHttpInterceptor.d.cts +39 -0
  86. package/lib/node/RemoteHttpInterceptor.d.mts +39 -0
  87. package/lib/node/RemoteHttpInterceptor.mjs +152 -0
  88. package/lib/node/RemoteHttpInterceptor.mjs.map +1 -0
  89. package/lib/node/XMLHttpRequest-B7kJdYYI.cjs +763 -0
  90. package/lib/node/XMLHttpRequest-B7kJdYYI.cjs.map +1 -0
  91. package/lib/node/XMLHttpRequest-C8dIZpds.mjs +757 -0
  92. package/lib/node/XMLHttpRequest-C8dIZpds.mjs.map +1 -0
  93. package/lib/node/bufferUtils-DiCTqG-7.cjs +38 -0
  94. package/lib/node/bufferUtils-DiCTqG-7.cjs.map +1 -0
  95. package/lib/node/bufferUtils-_8XfKIfX.mjs +20 -0
  96. package/lib/node/bufferUtils-_8XfKIfX.mjs.map +1 -0
  97. package/lib/node/chunk-CbDLau6x.cjs +34 -0
  98. package/lib/node/fetch-BmXpK10r.cjs +272 -0
  99. package/lib/node/fetch-BmXpK10r.cjs.map +1 -0
  100. package/lib/node/fetch-G1DVwDKG.mjs +265 -0
  101. package/lib/node/fetch-G1DVwDKG.mjs.map +1 -0
  102. package/lib/node/fetchUtils-BaY5iWXw.cjs +419 -0
  103. package/lib/node/fetchUtils-BaY5iWXw.cjs.map +1 -0
  104. package/lib/node/fetchUtils-CoU35g3M.mjs +359 -0
  105. package/lib/node/fetchUtils-CoU35g3M.mjs.map +1 -0
  106. package/lib/node/getRawRequest-BavnMWh_.cjs +36 -0
  107. package/lib/node/getRawRequest-BavnMWh_.cjs.map +1 -0
  108. package/lib/node/getRawRequest-DnwmXyOW.mjs +24 -0
  109. package/lib/node/getRawRequest-DnwmXyOW.mjs.map +1 -0
  110. package/lib/node/glossary-BLKRyLBd.cjs +12 -0
  111. package/lib/node/glossary-BLKRyLBd.cjs.map +1 -0
  112. package/lib/node/glossary-glQBRnVD.mjs +6 -0
  113. package/lib/node/glossary-glQBRnVD.mjs.map +1 -0
  114. package/lib/node/handleRequest-Bb7Y-XLw.cjs +220 -0
  115. package/lib/node/handleRequest-Bb7Y-XLw.cjs.map +1 -0
  116. package/lib/node/handleRequest-Y97UwBbF.mjs +190 -0
  117. package/lib/node/handleRequest-Y97UwBbF.mjs.map +1 -0
  118. package/lib/node/hasConfigurableGlobal-C97fWuaA.cjs +26 -0
  119. package/lib/node/hasConfigurableGlobal-C97fWuaA.cjs.map +1 -0
  120. package/lib/node/hasConfigurableGlobal-DBJA0vjm.mjs +20 -0
  121. package/lib/node/hasConfigurableGlobal-DBJA0vjm.mjs.map +1 -0
  122. package/lib/node/index-BMbJ8FXL.d.cts +113 -0
  123. package/lib/node/index-C0YAQ36w.d.mts +113 -0
  124. package/lib/node/index.cjs +54 -0
  125. package/lib/node/index.cjs.map +1 -0
  126. package/lib/node/index.d.cts +75 -0
  127. package/lib/node/index.d.mts +75 -0
  128. package/lib/node/index.mjs +40 -0
  129. package/lib/node/index.mjs.map +1 -0
  130. package/lib/node/interceptors/ClientRequest/index.cjs +6 -0
  131. package/lib/node/interceptors/ClientRequest/index.d.cts +2 -0
  132. package/lib/node/interceptors/ClientRequest/index.d.mts +3 -0
  133. package/lib/node/interceptors/ClientRequest/index.mjs +6 -0
  134. package/lib/node/interceptors/XMLHttpRequest/index.cjs +6 -0
  135. package/lib/node/interceptors/XMLHttpRequest/index.d.cts +14 -0
  136. package/lib/node/interceptors/XMLHttpRequest/index.d.mts +14 -0
  137. package/lib/node/interceptors/XMLHttpRequest/index.mjs +6 -0
  138. package/lib/node/interceptors/fetch/index.cjs +5 -0
  139. package/lib/node/interceptors/fetch/index.d.cts +12 -0
  140. package/lib/node/interceptors/fetch/index.d.mts +12 -0
  141. package/lib/node/interceptors/fetch/index.mjs +5 -0
  142. package/lib/node/node-DwCc6iuP.mjs +27 -0
  143. package/lib/node/node-DwCc6iuP.mjs.map +1 -0
  144. package/lib/node/node-dKdAf3tC.cjs +39 -0
  145. package/lib/node/node-dKdAf3tC.cjs.map +1 -0
  146. package/lib/node/presets/node.cjs +22 -0
  147. package/lib/node/presets/node.cjs.map +1 -0
  148. package/lib/node/presets/node.d.cts +13 -0
  149. package/lib/node/presets/node.d.mts +15 -0
  150. package/lib/node/presets/node.mjs +22 -0
  151. package/lib/node/presets/node.mjs.map +1 -0
  152. package/lib/node/utils/node/index.cjs +4 -0
  153. package/lib/node/utils/node/index.d.cts +16 -0
  154. package/lib/node/utils/node/index.d.mts +16 -0
  155. package/lib/node/utils/node/index.mjs +3 -0
  156. package/package.json +204 -0
  157. package/presets/browser/package.json +5 -0
  158. package/presets/node/package.json +11 -0
  159. package/src/BatchInterceptor.test.ts +255 -0
  160. package/src/BatchInterceptor.ts +95 -0
  161. package/src/Interceptor.test.ts +205 -0
  162. package/src/Interceptor.ts +249 -0
  163. package/src/InterceptorError.ts +7 -0
  164. package/src/RemoteHttpInterceptor.ts +251 -0
  165. package/src/RequestController.test.ts +104 -0
  166. package/src/RequestController.ts +109 -0
  167. package/src/createRequestId.test.ts +7 -0
  168. package/src/createRequestId.ts +9 -0
  169. package/src/getRawRequest.ts +21 -0
  170. package/src/glossary.ts +37 -0
  171. package/src/index.ts +15 -0
  172. package/src/interceptors/ClientRequest/MockHttpSocket.ts +724 -0
  173. package/src/interceptors/ClientRequest/agents.ts +110 -0
  174. package/src/interceptors/ClientRequest/index.test.ts +75 -0
  175. package/src/interceptors/ClientRequest/index.ts +193 -0
  176. package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.test.ts +54 -0
  177. package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.ts +45 -0
  178. package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.test.ts +427 -0
  179. package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts +268 -0
  180. package/src/interceptors/ClientRequest/utils/parserUtils.ts +48 -0
  181. package/src/interceptors/ClientRequest/utils/recordRawHeaders.test.ts +258 -0
  182. package/src/interceptors/ClientRequest/utils/recordRawHeaders.ts +262 -0
  183. package/src/interceptors/Socket/MockSocket.test.ts +264 -0
  184. package/src/interceptors/Socket/MockSocket.ts +58 -0
  185. package/src/interceptors/Socket/utils/baseUrlFromConnectionOptions.ts +26 -0
  186. package/src/interceptors/Socket/utils/normalizeSocketWriteArgs.test.ts +52 -0
  187. package/src/interceptors/Socket/utils/normalizeSocketWriteArgs.ts +33 -0
  188. package/src/interceptors/WebSocket/WebSocketClassTransport.ts +116 -0
  189. package/src/interceptors/WebSocket/WebSocketClientConnection.ts +152 -0
  190. package/src/interceptors/WebSocket/WebSocketOverride.ts +252 -0
  191. package/src/interceptors/WebSocket/WebSocketServerConnection.ts +420 -0
  192. package/src/interceptors/WebSocket/WebSocketTransport.ts +39 -0
  193. package/src/interceptors/WebSocket/index.ts +191 -0
  194. package/src/interceptors/WebSocket/utils/bindEvent.test.ts +27 -0
  195. package/src/interceptors/WebSocket/utils/bindEvent.ts +21 -0
  196. package/src/interceptors/WebSocket/utils/events.test.ts +101 -0
  197. package/src/interceptors/WebSocket/utils/events.ts +94 -0
  198. package/src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts +746 -0
  199. package/src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts +121 -0
  200. package/src/interceptors/XMLHttpRequest/index.ts +61 -0
  201. package/src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts +51 -0
  202. package/src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts +17 -0
  203. package/src/interceptors/XMLHttpRequest/utils/concatArrayBuffer.ts +12 -0
  204. package/src/interceptors/XMLHttpRequest/utils/concateArrayBuffer.test.ts +12 -0
  205. package/src/interceptors/XMLHttpRequest/utils/createEvent.test.ts +26 -0
  206. package/src/interceptors/XMLHttpRequest/utils/createEvent.ts +41 -0
  207. package/src/interceptors/XMLHttpRequest/utils/createResponse.ts +49 -0
  208. package/src/interceptors/XMLHttpRequest/utils/getBodyByteLength.test.ts +164 -0
  209. package/src/interceptors/XMLHttpRequest/utils/getBodyByteLength.ts +16 -0
  210. package/src/interceptors/XMLHttpRequest/utils/isDomParserSupportedType.ts +14 -0
  211. package/src/interceptors/fetch/index.ts +214 -0
  212. package/src/interceptors/fetch/utils/brotli-decompress.browser.ts +14 -0
  213. package/src/interceptors/fetch/utils/brotli-decompress.ts +31 -0
  214. package/src/interceptors/fetch/utils/createNetworkError.ts +5 -0
  215. package/src/interceptors/fetch/utils/decompression.ts +85 -0
  216. package/src/interceptors/fetch/utils/followRedirect.ts +114 -0
  217. package/src/presets/browser.ts +11 -0
  218. package/src/presets/node.ts +13 -0
  219. package/src/utils/bufferUtils.test.ts +21 -0
  220. package/src/utils/bufferUtils.ts +22 -0
  221. package/src/utils/canParseUrl.ts +13 -0
  222. package/src/utils/cloneObject.test.ts +94 -0
  223. package/src/utils/cloneObject.ts +36 -0
  224. package/src/utils/createProxy.test.ts +164 -0
  225. package/src/utils/createProxy.ts +104 -0
  226. package/src/utils/emitAsync.ts +25 -0
  227. package/src/utils/fetchUtils.ts +119 -0
  228. package/src/utils/findPropertySource.test.ts +27 -0
  229. package/src/utils/findPropertySource.ts +20 -0
  230. package/src/utils/getCleanUrl.test.ts +32 -0
  231. package/src/utils/getCleanUrl.ts +6 -0
  232. package/src/utils/getUrlByRequestOptions.test.ts +163 -0
  233. package/src/utils/getUrlByRequestOptions.ts +152 -0
  234. package/src/utils/getValueBySymbol.test.ts +14 -0
  235. package/src/utils/getValueBySymbol.ts +19 -0
  236. package/src/utils/handleRequest.ts +205 -0
  237. package/src/utils/hasConfigurableGlobal.test.ts +83 -0
  238. package/src/utils/hasConfigurableGlobal.ts +34 -0
  239. package/src/utils/isNodeLikeError.ts +13 -0
  240. package/src/utils/isObject.test.ts +21 -0
  241. package/src/utils/isObject.ts +8 -0
  242. package/src/utils/isPropertyAccessible.ts +19 -0
  243. package/src/utils/nextTick.ts +11 -0
  244. package/src/utils/node/index.ts +39 -0
  245. package/src/utils/parseJson.test.ts +10 -0
  246. package/src/utils/parseJson.ts +12 -0
  247. package/src/utils/resolveWebSocketUrl.ts +45 -0
  248. package/src/utils/responseUtils.ts +59 -0
@@ -0,0 +1,164 @@
1
+ import { vi, it, expect } from 'vitest'
2
+ import { createProxy } from './createProxy'
3
+
4
+ it('does not interfere with default constructors', () => {
5
+ const ProxyClass = createProxy(
6
+ class {
7
+ constructor(public name: string) {}
8
+ },
9
+ {}
10
+ )
11
+
12
+ const instance = new ProxyClass('John')
13
+ expect(instance.name).toBe('John')
14
+ })
15
+
16
+ it('does not interfere with default getters', () => {
17
+ const proxy = createProxy({ foo: 'initial' }, {})
18
+ expect(proxy.foo).toBe('initial')
19
+ })
20
+
21
+ it('does not interfere with default setters', () => {
22
+ const proxy = createProxy({ foo: 'initial' }, {})
23
+ proxy.foo = 'next'
24
+
25
+ expect(proxy.foo).toBe('next')
26
+ })
27
+
28
+ it('does not interfere with default methods', () => {
29
+ const proxy = createProxy({ getValue: () => 'initial' }, {})
30
+ expect(proxy.getValue()).toBe('initial')
31
+ })
32
+
33
+ it('does not interfere with existing descriptors', () => {
34
+ const target = {} as { foo: string; bar: number }
35
+ let internalBar = 0
36
+
37
+ Object.defineProperties(target, {
38
+ foo: {
39
+ get: () => 'initial',
40
+ },
41
+ bar: {
42
+ set: (value) => {
43
+ internalBar = value + 10
44
+ },
45
+ },
46
+ })
47
+
48
+ const proxy = createProxy(target, {
49
+ getProperty(data, next) {
50
+ return next()
51
+ },
52
+ })
53
+ expect(proxy.foo).toBe('initial')
54
+
55
+ proxy.bar = 5
56
+ expect(proxy.bar).toBeUndefined()
57
+ expect(internalBar).toBe(15)
58
+ })
59
+
60
+ it('infer prototype descriptors', () => {
61
+ class Child {
62
+ ok: boolean
63
+
64
+ set status(nextStatus: number) {
65
+ this.ok = nextStatus >= 200 && nextStatus < 300
66
+ }
67
+ }
68
+
69
+ Object.defineProperties(Child.prototype, {
70
+ status: { enumerable: true },
71
+ })
72
+
73
+ const scope = {} as { child: typeof Child }
74
+
75
+ Object.defineProperty(scope, 'child', {
76
+ enumerable: true,
77
+ value: Child,
78
+ })
79
+
80
+ const ProxyClass = createProxy(scope.child, {})
81
+ const instance = new ProxyClass()
82
+
83
+ instance.status = 201
84
+ expect(instance.ok).toBe(true)
85
+ })
86
+
87
+ it('spies on the constructor', () => {
88
+ const OriginalClass = class {
89
+ constructor(public name: string, public age: number) {}
90
+ }
91
+
92
+ const constructorCall = vi.fn<
93
+ (
94
+ args: ConstructorParameters<typeof OriginalClass>,
95
+ next: () => typeof OriginalClass
96
+ ) => typeof OriginalClass
97
+ >((args, next) => next())
98
+
99
+ const ProxyClass = createProxy(OriginalClass, {
100
+ constructorCall,
101
+ })
102
+
103
+ new ProxyClass('John', 32)
104
+
105
+ expect(constructorCall).toHaveBeenCalledTimes(1)
106
+ expect(constructorCall).toHaveBeenCalledWith(
107
+ ['John', 32],
108
+ expect.any(Function)
109
+ )
110
+ })
111
+
112
+ it('spies on property getters', () => {
113
+ const getProperty = vi.fn((args, next) => next())
114
+ const proxy = createProxy({ foo: 'initial' }, { getProperty })
115
+
116
+ proxy.foo
117
+
118
+ expect(getProperty).toHaveBeenCalledTimes(1)
119
+ expect(getProperty).toHaveBeenCalledWith(['foo', proxy], expect.any(Function))
120
+ })
121
+
122
+ it('spies on property setters', () => {
123
+ const setProperty = vi.fn((args, next) => next())
124
+ const proxy = createProxy({ foo: 'initial' }, { setProperty })
125
+
126
+ proxy.foo = 'next'
127
+
128
+ expect(setProperty).toHaveBeenCalledTimes(1)
129
+ expect(setProperty).toHaveBeenCalledWith(
130
+ ['foo', 'next'],
131
+ expect.any(Function)
132
+ )
133
+ })
134
+
135
+ it('spies on method calls', () => {
136
+ const methodCall = vi.fn((args, next) => next())
137
+ const proxy = createProxy(
138
+ {
139
+ greet: (name: string) => `hello ${name}`,
140
+ },
141
+ { methodCall }
142
+ )
143
+
144
+ proxy.greet('Clair')
145
+
146
+ expect(methodCall).toHaveBeenCalledTimes(1)
147
+ expect(methodCall).toHaveBeenCalledWith(
148
+ ['greet', ['Clair']],
149
+ expect.any(Function)
150
+ )
151
+ })
152
+
153
+ it('proxies properties on the prototype level', () => {
154
+ const method = vi.fn()
155
+ const prototype = { method }
156
+
157
+ const proxy = createProxy(Object.create(prototype), {})
158
+ const proxyMethod = vi.fn()
159
+ proxy.method = proxyMethod
160
+
161
+ prototype.method()
162
+ expect(method).toHaveBeenCalledTimes(0)
163
+ expect(proxyMethod).toHaveBeenCalledTimes(1)
164
+ })
@@ -0,0 +1,104 @@
1
+ import { findPropertySource } from './findPropertySource'
2
+
3
+ export interface ProxyOptions<Target extends Record<string, any>> {
4
+ constructorCall?(args: Array<unknown>, next: NextFunction<Target>): Target
5
+
6
+ methodCall?<F extends keyof Target>(
7
+ this: Target,
8
+ data: [methodName: F, args: Array<unknown>],
9
+ next: NextFunction<void>
10
+ ): void
11
+
12
+ setProperty?(
13
+ data: [propertyName: string | symbol, nextValue: unknown],
14
+ next: NextFunction<boolean>
15
+ ): boolean
16
+
17
+ getProperty?(
18
+ data: [propertyName: string | symbol, receiver: Target],
19
+ next: NextFunction<void>
20
+ ): void
21
+ }
22
+
23
+ export type NextFunction<ReturnType> = () => ReturnType
24
+
25
+ export function createProxy<Target extends object>(
26
+ target: Target,
27
+ options: ProxyOptions<Target>
28
+ ): Target {
29
+ const proxy = new Proxy(target, optionsToProxyHandler(options))
30
+
31
+ return proxy
32
+ }
33
+
34
+ function optionsToProxyHandler<T extends Record<string, any>>(
35
+ options: ProxyOptions<T>
36
+ ): ProxyHandler<T> {
37
+ const { constructorCall, methodCall, getProperty, setProperty } = options
38
+ const handler: ProxyHandler<T> = {}
39
+
40
+ if (typeof constructorCall !== 'undefined') {
41
+ handler.construct = function (target, args, newTarget) {
42
+ const next = Reflect.construct.bind(null, target as any, args, newTarget)
43
+ return constructorCall.call(newTarget, args, next)
44
+ }
45
+ }
46
+
47
+ handler.set = function (target, propertyName, nextValue) {
48
+ const next = () => {
49
+ const propertySource = findPropertySource(target, propertyName) || target
50
+ const ownDescriptors = Reflect.getOwnPropertyDescriptor(
51
+ propertySource,
52
+ propertyName
53
+ )
54
+
55
+ // Respect any custom setters present for this property.
56
+ if (typeof ownDescriptors?.set !== 'undefined') {
57
+ ownDescriptors.set.apply(target, [nextValue])
58
+ return true
59
+ }
60
+
61
+ // Otherwise, set the property on the source.
62
+ return Reflect.defineProperty(propertySource, propertyName, {
63
+ writable: true,
64
+ enumerable: true,
65
+ configurable: true,
66
+ value: nextValue,
67
+ })
68
+ }
69
+
70
+ if (typeof setProperty !== 'undefined') {
71
+ return setProperty.call(target, [propertyName, nextValue], next)
72
+ }
73
+
74
+ return next()
75
+ }
76
+
77
+ handler.get = function (target, propertyName, receiver) {
78
+ /**
79
+ * @note Using `Reflect.get()` here causes "TypeError: Illegal invocation".
80
+ */
81
+ const next = () => target[propertyName as any]
82
+
83
+ const value =
84
+ typeof getProperty !== 'undefined'
85
+ ? getProperty.call(target, [propertyName, receiver], next)
86
+ : next()
87
+
88
+ if (typeof value === 'function') {
89
+ return (...args: Array<any>) => {
90
+ const next = value.bind(target, ...args)
91
+
92
+ if (typeof methodCall !== 'undefined') {
93
+ return methodCall.call(target, [propertyName as any, args], next)
94
+ }
95
+
96
+ return next()
97
+ }
98
+ }
99
+
100
+ return value
101
+ }
102
+
103
+ return handler
104
+ }
@@ -0,0 +1,25 @@
1
+ import { Emitter, EventMap } from 'strict-event-emitter'
2
+
3
+ /**
4
+ * Emits an event on the given emitter but executes
5
+ * the listeners sequentially. This accounts for asynchronous
6
+ * listeners (e.g. those having "sleep" and handling the request).
7
+ */
8
+ export async function emitAsync<
9
+ Events extends EventMap,
10
+ EventName extends keyof Events
11
+ >(
12
+ emitter: Emitter<Events>,
13
+ eventName: EventName,
14
+ ...data: Events[EventName]
15
+ ): Promise<void> {
16
+ const listeners = emitter.listeners(eventName)
17
+
18
+ if (listeners.length === 0) {
19
+ return
20
+ }
21
+
22
+ for (const listener of listeners) {
23
+ await listener.apply(emitter, data)
24
+ }
25
+ }
@@ -0,0 +1,119 @@
1
+ import { canParseUrl } from './canParseUrl'
2
+ import { getValueBySymbol } from './getValueBySymbol'
3
+
4
+ export interface FetchResponseInit extends ResponseInit {
5
+ url?: string
6
+ }
7
+
8
+ interface UndiciFetchInternalState {
9
+ aborted: boolean
10
+ rangeRequested: boolean
11
+ timingAllowPassed: boolean
12
+ requestIncludesCredentials: boolean
13
+ type: ResponseType
14
+ status: number
15
+ statusText: string
16
+ timingInfo: unknown
17
+ cacheState: unknown
18
+ headersList: Record<symbol, Map<string, unknown>>
19
+ urlList: Array<URL>
20
+ body?: {
21
+ stream: ReadableStream
22
+ source: unknown
23
+ length: number
24
+ }
25
+ }
26
+
27
+ export class FetchResponse extends Response {
28
+ /**
29
+ * Response status codes for responses that cannot have body.
30
+ * @see https://fetch.spec.whatwg.org/#statuses
31
+ */
32
+ static readonly STATUS_CODES_WITHOUT_BODY = [101, 103, 204, 205, 304]
33
+
34
+ static readonly STATUS_CODES_WITH_REDIRECT = [301, 302, 303, 307, 308]
35
+
36
+ static isConfigurableStatusCode(status: number): boolean {
37
+ return status >= 200 && status <= 599
38
+ }
39
+
40
+ static isRedirectResponse(status: number): boolean {
41
+ return FetchResponse.STATUS_CODES_WITH_REDIRECT.includes(status)
42
+ }
43
+
44
+ /**
45
+ * Returns a boolean indicating whether the given response status
46
+ * code represents a response that can have a body.
47
+ */
48
+ static isResponseWithBody(status: number): boolean {
49
+ return !FetchResponse.STATUS_CODES_WITHOUT_BODY.includes(status)
50
+ }
51
+
52
+ static setUrl(url: string | undefined, response: Response): void {
53
+ if (!url || url === 'about:' || !canParseUrl(url)) {
54
+ return
55
+ }
56
+
57
+ const state = getValueBySymbol<UndiciFetchInternalState>('state', response)
58
+
59
+ if (state) {
60
+ // In Undici, push the URL to the internal list of URLs.
61
+ // This will respect the `response.url` getter logic correctly.
62
+ state.urlList.push(new URL(url))
63
+ } else {
64
+ // In other libraries, redefine the `url` property directly.
65
+ Object.defineProperty(response, 'url', {
66
+ value: url,
67
+ enumerable: true,
68
+ configurable: true,
69
+ writable: false,
70
+ })
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Parses the given raw HTTP headers into a Fetch API `Headers` instance.
76
+ */
77
+ static parseRawHeaders(rawHeaders: Array<string>): Headers {
78
+ const headers = new Headers()
79
+ for (let line = 0; line < rawHeaders.length; line += 2) {
80
+ headers.append(rawHeaders[line], rawHeaders[line + 1])
81
+ }
82
+ return headers
83
+ }
84
+
85
+ constructor(body?: BodyInit | null, init: FetchResponseInit = {}) {
86
+ const status = init.status ?? 200
87
+ const safeStatus = FetchResponse.isConfigurableStatusCode(status)
88
+ ? status
89
+ : 200
90
+ const finalBody = FetchResponse.isResponseWithBody(status) ? body : null
91
+
92
+ super(finalBody, {
93
+ status: safeStatus,
94
+ statusText: init.statusText,
95
+ headers: init.headers,
96
+ })
97
+
98
+ if (status !== safeStatus) {
99
+ /**
100
+ * @note Undici keeps an internal "Symbol(state)" that holds
101
+ * the actual value of response status. Update that in Node.js.
102
+ */
103
+ const state = getValueBySymbol<UndiciFetchInternalState>('state', this)
104
+
105
+ if (state) {
106
+ state.status = status
107
+ } else {
108
+ Object.defineProperty(this, 'status', {
109
+ value: status,
110
+ enumerable: true,
111
+ configurable: true,
112
+ writable: false,
113
+ })
114
+ }
115
+ }
116
+
117
+ FetchResponse.setUrl(init.url, this)
118
+ }
119
+ }
@@ -0,0 +1,27 @@
1
+ import { it, expect } from 'vitest'
2
+ import { findPropertySource } from './findPropertySource'
3
+
4
+ it('returns the source for objects without prototypes', () => {
5
+ const obj = Object.create(null)
6
+ obj.test = undefined
7
+ const source = findPropertySource(obj, 'test')
8
+ expect(source).toBe(obj)
9
+ })
10
+
11
+ it('returns the source for objects with prototypes', () => {
12
+ const prototype = Object.create(null)
13
+ prototype.test = undefined
14
+
15
+ const obj = Object.create(prototype)
16
+
17
+ const source = findPropertySource(obj, 'test')
18
+ expect(source).toBe(prototype)
19
+ })
20
+
21
+ it('returns null if the prototype chain does not contain the property', () => {
22
+ const prototype = Object.create(null)
23
+ const obj = Object.create(prototype)
24
+
25
+ const source = findPropertySource(obj, 'test')
26
+ expect(source).toBeNull()
27
+ })
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Returns the source object of the given property on the target object
3
+ * (the target itself, any parent in its prototype, or null).
4
+ */
5
+ export function findPropertySource(
6
+ target: object,
7
+ propertyName: string | symbol
8
+ ): object | null {
9
+ if (!(propertyName in target)) {
10
+ return null
11
+ }
12
+
13
+ const hasProperty = Object.prototype.hasOwnProperty.call(target, propertyName)
14
+ if (hasProperty) {
15
+ return target
16
+ }
17
+
18
+ const prototype = Reflect.getPrototypeOf(target)
19
+ return prototype ? findPropertySource(prototype, propertyName) : null
20
+ }
@@ -0,0 +1,32 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { getCleanUrl } from './getCleanUrl'
3
+
4
+ describe('getCleanUrl', () => {
5
+ describe('given a URL without query parameters', () => {
6
+ it('should return url href as-is', () => {
7
+ const url = new URL('https://github.com')
8
+ expect(getCleanUrl(url)).toEqual('https://github.com/')
9
+ })
10
+ })
11
+
12
+ describe('given a URL with query parameters', () => {
13
+ it('should return url without parameters', () => {
14
+ const url = new URL('https://github.com/mswjs/?userId=abc-123')
15
+ expect(getCleanUrl(url)).toEqual('https://github.com/mswjs/')
16
+ })
17
+ })
18
+
19
+ describe('given a URL with a hash', () => {
20
+ it('should return a url without hash', () => {
21
+ const url = new URL('https://github.com/mswjs/#hello-world')
22
+ expect(getCleanUrl(url)).toEqual('https://github.com/mswjs/')
23
+ })
24
+ })
25
+
26
+ describe('given an absolute URL ', () => {
27
+ it('should return a clean relative URL', () => {
28
+ const url = new URL('/login?query=value', 'https://github.com')
29
+ expect(getCleanUrl(url, false)).toEqual('/login')
30
+ })
31
+ })
32
+ })
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Removes query parameters and hashes from a given URL.
3
+ */
4
+ export function getCleanUrl(url: URL, isAbsolute: boolean = true): string {
5
+ return [isAbsolute && url.origin, url.pathname].filter(Boolean).join('')
6
+ }
@@ -0,0 +1,163 @@
1
+ import { it, expect } from 'vitest'
2
+ import { Agent as HttpAgent } from 'http'
3
+ import { RequestOptions, Agent as HttpsAgent } from 'https'
4
+ import { getUrlByRequestOptions } from './getUrlByRequestOptions'
5
+
6
+ it('returns a URL based on the basic RequestOptions', () => {
7
+ expect(
8
+ getUrlByRequestOptions({
9
+ protocol: 'https:',
10
+ host: '127.0.0.1',
11
+ path: '/resource',
12
+ }).href
13
+ ).toBe('https://127.0.0.1/resource')
14
+ })
15
+
16
+ it('inherits protocol and port from http.Agent, if set', () => {
17
+ expect(
18
+ getUrlByRequestOptions({
19
+ host: '127.0.0.1',
20
+ path: '/',
21
+ agent: new HttpAgent(),
22
+ }).href
23
+ ).toBe('http://127.0.0.1/')
24
+ })
25
+
26
+ it('inherits protocol and port from https.Agent, if set', () => {
27
+ expect(
28
+ getUrlByRequestOptions({
29
+ host: '127.0.0.1',
30
+ path: '/',
31
+ agent: new HttpsAgent({
32
+ port: 3080,
33
+ }),
34
+ }).href
35
+ ).toBe('https://127.0.0.1:3080/')
36
+ })
37
+
38
+ it('resolves protocol to "http" given no explicit protocol and no certificate', () => {
39
+ expect(
40
+ getUrlByRequestOptions({
41
+ host: '127.0.0.1',
42
+ path: '/',
43
+ }).href
44
+ ).toBe('http://127.0.0.1/')
45
+ })
46
+
47
+ it('resolves protocol to "https" given no explicit protocol, but certificate', () => {
48
+ expect(
49
+ getUrlByRequestOptions({
50
+ host: '127.0.0.1',
51
+ path: '/secure',
52
+ cert: '<!-- SSL certificate -->',
53
+ }).href
54
+ ).toBe('https://127.0.0.1/secure')
55
+ })
56
+
57
+ it('resolves protocol to "https" given no explicit protocol, but port is 443', () => {
58
+ expect(
59
+ getUrlByRequestOptions({
60
+ host: '127.0.0.1',
61
+ port: 443,
62
+ path: '/resource',
63
+ }).href
64
+ ).toBe('https://127.0.0.1/resource')
65
+ })
66
+
67
+ it('resolves protocol to "https" given no explicit protocol, but agent port is 443', () => {
68
+ expect(
69
+ getUrlByRequestOptions({
70
+ host: '127.0.0.1',
71
+ agent: new HttpsAgent({
72
+ port: 443,
73
+ }),
74
+ path: '/resource',
75
+ }).href
76
+ ).toBe('https://127.0.0.1/resource')
77
+ })
78
+
79
+ it('respects explicitly provided port', () => {
80
+ expect(
81
+ getUrlByRequestOptions({
82
+ protocol: 'http:',
83
+ host: '127.0.0.1',
84
+ port: 4002,
85
+ path: '/',
86
+ }).href
87
+ ).toBe('http://127.0.0.1:4002/')
88
+ })
89
+
90
+ it('inherits "username" and "password"', () => {
91
+ const url = getUrlByRequestOptions({
92
+ protocol: 'https:',
93
+ host: '127.0.0.1',
94
+ path: '/user',
95
+ auth: 'admin:abc-123',
96
+ })
97
+
98
+ expect(url).toBeInstanceOf(URL)
99
+ expect(url).toHaveProperty('username', 'admin')
100
+ expect(url).toHaveProperty('password', 'abc-123')
101
+ expect(url).toHaveProperty('href', 'https://admin:abc-123@127.0.0.1/user')
102
+ })
103
+
104
+ it('resolves hostname to localhost if none provided', () => {
105
+ expect(getUrlByRequestOptions({}).hostname).toBe('localhost')
106
+ })
107
+
108
+ it('resolves host to localhost if none provided', () => {
109
+ expect(getUrlByRequestOptions({}).host).toBe('localhost')
110
+ })
111
+
112
+ it('supports "hostname" and "port"', () => {
113
+ const options: RequestOptions = {
114
+ protocol: 'https:',
115
+ hostname: '127.0.0.1',
116
+ port: 1234,
117
+ path: '/resource',
118
+ }
119
+
120
+ expect(getUrlByRequestOptions(options).href).toBe(
121
+ 'https://127.0.0.1:1234/resource'
122
+ )
123
+ })
124
+
125
+ it('use "hostname" if both "hostname" and "host" are specified', () => {
126
+ const options: RequestOptions = {
127
+ protocol: 'https:',
128
+ host: 'host',
129
+ hostname: 'hostname',
130
+ path: '/resource',
131
+ }
132
+
133
+ expect(getUrlByRequestOptions(options).href).toBe(
134
+ 'https://hostname/resource'
135
+ )
136
+ })
137
+
138
+ it('parses "host" in IPv6', () => {
139
+ expect(
140
+ getUrlByRequestOptions({
141
+ host: '::1',
142
+ path: '/resource',
143
+ }).href
144
+ ).toBe('http://[::1]/resource')
145
+
146
+ expect(
147
+ getUrlByRequestOptions({
148
+ host: '[::1]',
149
+ path: '/resource',
150
+ }).href
151
+ ).toBe('http://[::1]/resource')
152
+
153
+ })
154
+
155
+ it('parses "host" and "port" in IPv6', () => {
156
+ expect(
157
+ getUrlByRequestOptions({
158
+ host: '::1',
159
+ port: 3001,
160
+ path: '/resource',
161
+ }).href
162
+ ).toBe('http://[::1]:3001/resource')
163
+ })