@nocobase/plugin-idp-oauth 2.1.0-alpha.17 → 2.1.0-alpha.19

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 (221) hide show
  1. package/build.config.ts +1 -1
  2. package/dist/externalVersion.js +6 -4
  3. package/dist/node_modules/light-my-request/package.json +1 -1
  4. package/dist/node_modules/undici/LICENSE +21 -0
  5. package/dist/node_modules/undici/README.md +741 -0
  6. package/dist/node_modules/undici/docs/docs/api/Agent.md +84 -0
  7. package/dist/node_modules/undici/docs/docs/api/BalancedPool.md +99 -0
  8. package/dist/node_modules/undici/docs/docs/api/CacheStorage.md +30 -0
  9. package/dist/node_modules/undici/docs/docs/api/CacheStore.md +164 -0
  10. package/dist/node_modules/undici/docs/docs/api/Client.md +285 -0
  11. package/dist/node_modules/undici/docs/docs/api/ClientStats.md +27 -0
  12. package/dist/node_modules/undici/docs/docs/api/Connector.md +115 -0
  13. package/dist/node_modules/undici/docs/docs/api/ContentType.md +57 -0
  14. package/dist/node_modules/undici/docs/docs/api/Cookies.md +101 -0
  15. package/dist/node_modules/undici/docs/docs/api/Debug.md +62 -0
  16. package/dist/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +315 -0
  17. package/dist/node_modules/undici/docs/docs/api/Dispatcher.md +1392 -0
  18. package/dist/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +159 -0
  19. package/dist/node_modules/undici/docs/docs/api/Errors.md +49 -0
  20. package/dist/node_modules/undici/docs/docs/api/EventSource.md +45 -0
  21. package/dist/node_modules/undici/docs/docs/api/Fetch.md +60 -0
  22. package/dist/node_modules/undici/docs/docs/api/GlobalInstallation.md +139 -0
  23. package/dist/node_modules/undici/docs/docs/api/H2CClient.md +263 -0
  24. package/dist/node_modules/undici/docs/docs/api/MockAgent.md +603 -0
  25. package/dist/node_modules/undici/docs/docs/api/MockCallHistory.md +197 -0
  26. package/dist/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +43 -0
  27. package/dist/node_modules/undici/docs/docs/api/MockClient.md +81 -0
  28. package/dist/node_modules/undici/docs/docs/api/MockErrors.md +12 -0
  29. package/dist/node_modules/undici/docs/docs/api/MockPool.md +555 -0
  30. package/dist/node_modules/undici/docs/docs/api/Pool.md +84 -0
  31. package/dist/node_modules/undici/docs/docs/api/PoolStats.md +35 -0
  32. package/dist/node_modules/undici/docs/docs/api/ProxyAgent.md +229 -0
  33. package/dist/node_modules/undici/docs/docs/api/RedirectHandler.md +93 -0
  34. package/dist/node_modules/undici/docs/docs/api/RetryAgent.md +50 -0
  35. package/dist/node_modules/undici/docs/docs/api/RetryHandler.md +118 -0
  36. package/dist/node_modules/undici/docs/docs/api/RoundRobinPool.md +145 -0
  37. package/dist/node_modules/undici/docs/docs/api/SnapshotAgent.md +616 -0
  38. package/dist/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +274 -0
  39. package/dist/node_modules/undici/docs/docs/api/Util.md +25 -0
  40. package/dist/node_modules/undici/docs/docs/api/WebSocket.md +141 -0
  41. package/dist/node_modules/undici/docs/docs/api/api-lifecycle.md +91 -0
  42. package/dist/node_modules/undici/docs/docs/best-practices/client-certificate.md +64 -0
  43. package/dist/node_modules/undici/docs/docs/best-practices/crawling.md +58 -0
  44. package/dist/node_modules/undici/docs/docs/best-practices/mocking-request.md +190 -0
  45. package/dist/node_modules/undici/docs/docs/best-practices/proxy.md +127 -0
  46. package/dist/node_modules/undici/docs/docs/best-practices/undici-vs-builtin-fetch.md +224 -0
  47. package/dist/node_modules/undici/docs/docs/best-practices/writing-tests.md +63 -0
  48. package/dist/node_modules/undici/index-fetch.js +65 -0
  49. package/dist/node_modules/undici/index.d.ts +3 -0
  50. package/dist/node_modules/undici/index.js +234 -0
  51. package/dist/node_modules/undici/lib/api/abort-signal.js +59 -0
  52. package/dist/node_modules/undici/lib/api/api-connect.js +110 -0
  53. package/dist/node_modules/undici/lib/api/api-pipeline.js +252 -0
  54. package/dist/node_modules/undici/lib/api/api-request.js +214 -0
  55. package/dist/node_modules/undici/lib/api/api-stream.js +209 -0
  56. package/dist/node_modules/undici/lib/api/api-upgrade.js +111 -0
  57. package/dist/node_modules/undici/lib/api/index.js +7 -0
  58. package/dist/node_modules/undici/lib/api/readable.js +580 -0
  59. package/dist/node_modules/undici/lib/cache/memory-cache-store.js +234 -0
  60. package/dist/node_modules/undici/lib/cache/sqlite-cache-store.js +461 -0
  61. package/dist/node_modules/undici/lib/core/connect.js +137 -0
  62. package/dist/node_modules/undici/lib/core/constants.js +143 -0
  63. package/dist/node_modules/undici/lib/core/diagnostics.js +227 -0
  64. package/dist/node_modules/undici/lib/core/errors.js +477 -0
  65. package/dist/node_modules/undici/lib/core/request.js +438 -0
  66. package/dist/node_modules/undici/lib/core/socks5-client.js +407 -0
  67. package/dist/node_modules/undici/lib/core/socks5-utils.js +203 -0
  68. package/dist/node_modules/undici/lib/core/symbols.js +75 -0
  69. package/dist/node_modules/undici/lib/core/tree.js +160 -0
  70. package/dist/node_modules/undici/lib/core/util.js +992 -0
  71. package/dist/node_modules/undici/lib/dispatcher/agent.js +158 -0
  72. package/dist/node_modules/undici/lib/dispatcher/balanced-pool.js +219 -0
  73. package/dist/node_modules/undici/lib/dispatcher/client-h1.js +1610 -0
  74. package/dist/node_modules/undici/lib/dispatcher/client-h2.js +995 -0
  75. package/dist/node_modules/undici/lib/dispatcher/client.js +659 -0
  76. package/dist/node_modules/undici/lib/dispatcher/dispatcher-base.js +165 -0
  77. package/dist/node_modules/undici/lib/dispatcher/dispatcher.js +48 -0
  78. package/dist/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +146 -0
  79. package/dist/node_modules/undici/lib/dispatcher/fixed-queue.js +135 -0
  80. package/dist/node_modules/undici/lib/dispatcher/h2c-client.js +51 -0
  81. package/dist/node_modules/undici/lib/dispatcher/pool-base.js +214 -0
  82. package/dist/node_modules/undici/lib/dispatcher/pool.js +118 -0
  83. package/dist/node_modules/undici/lib/dispatcher/proxy-agent.js +318 -0
  84. package/dist/node_modules/undici/lib/dispatcher/retry-agent.js +35 -0
  85. package/dist/node_modules/undici/lib/dispatcher/round-robin-pool.js +137 -0
  86. package/dist/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +249 -0
  87. package/dist/node_modules/undici/lib/encoding/index.js +33 -0
  88. package/dist/node_modules/undici/lib/global.js +50 -0
  89. package/dist/node_modules/undici/lib/handler/cache-handler.js +578 -0
  90. package/dist/node_modules/undici/lib/handler/cache-revalidation-handler.js +124 -0
  91. package/dist/node_modules/undici/lib/handler/decorator-handler.js +67 -0
  92. package/dist/node_modules/undici/lib/handler/deduplication-handler.js +460 -0
  93. package/dist/node_modules/undici/lib/handler/redirect-handler.js +238 -0
  94. package/dist/node_modules/undici/lib/handler/retry-handler.js +394 -0
  95. package/dist/node_modules/undici/lib/handler/unwrap-handler.js +100 -0
  96. package/dist/node_modules/undici/lib/handler/wrap-handler.js +105 -0
  97. package/dist/node_modules/undici/lib/interceptor/cache.js +495 -0
  98. package/dist/node_modules/undici/lib/interceptor/decompress.js +259 -0
  99. package/dist/node_modules/undici/lib/interceptor/deduplicate.js +117 -0
  100. package/dist/node_modules/undici/lib/interceptor/dns.js +571 -0
  101. package/dist/node_modules/undici/lib/interceptor/dump.js +112 -0
  102. package/dist/node_modules/undici/lib/interceptor/redirect.js +21 -0
  103. package/dist/node_modules/undici/lib/interceptor/response-error.js +95 -0
  104. package/dist/node_modules/undici/lib/interceptor/retry.js +19 -0
  105. package/dist/node_modules/undici/lib/llhttp/.gitkeep +0 -0
  106. package/dist/node_modules/undici/lib/llhttp/constants.d.ts +195 -0
  107. package/dist/node_modules/undici/lib/llhttp/constants.js +531 -0
  108. package/dist/node_modules/undici/lib/llhttp/llhttp-wasm.js +15 -0
  109. package/dist/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +15 -0
  110. package/dist/node_modules/undici/lib/llhttp/utils.d.ts +2 -0
  111. package/dist/node_modules/undici/lib/llhttp/utils.js +12 -0
  112. package/dist/node_modules/undici/lib/mock/mock-agent.js +232 -0
  113. package/dist/node_modules/undici/lib/mock/mock-call-history.js +248 -0
  114. package/dist/node_modules/undici/lib/mock/mock-client.js +68 -0
  115. package/dist/node_modules/undici/lib/mock/mock-errors.js +29 -0
  116. package/dist/node_modules/undici/lib/mock/mock-interceptor.js +209 -0
  117. package/dist/node_modules/undici/lib/mock/mock-pool.js +68 -0
  118. package/dist/node_modules/undici/lib/mock/mock-symbols.js +32 -0
  119. package/dist/node_modules/undici/lib/mock/mock-utils.js +486 -0
  120. package/dist/node_modules/undici/lib/mock/pending-interceptors-formatter.js +43 -0
  121. package/dist/node_modules/undici/lib/mock/snapshot-agent.js +353 -0
  122. package/dist/node_modules/undici/lib/mock/snapshot-recorder.js +588 -0
  123. package/dist/node_modules/undici/lib/mock/snapshot-utils.js +158 -0
  124. package/dist/node_modules/undici/lib/util/cache.js +407 -0
  125. package/dist/node_modules/undici/lib/util/date.js +653 -0
  126. package/dist/node_modules/undici/lib/util/promise.js +28 -0
  127. package/dist/node_modules/undici/lib/util/runtime-features.js +124 -0
  128. package/dist/node_modules/undici/lib/util/stats.js +32 -0
  129. package/dist/node_modules/undici/lib/util/timers.js +425 -0
  130. package/dist/node_modules/undici/lib/web/cache/cache.js +864 -0
  131. package/dist/node_modules/undici/lib/web/cache/cachestorage.js +152 -0
  132. package/dist/node_modules/undici/lib/web/cache/util.js +45 -0
  133. package/dist/node_modules/undici/lib/web/cookies/constants.js +12 -0
  134. package/dist/node_modules/undici/lib/web/cookies/index.js +199 -0
  135. package/dist/node_modules/undici/lib/web/cookies/parse.js +322 -0
  136. package/dist/node_modules/undici/lib/web/cookies/util.js +282 -0
  137. package/dist/node_modules/undici/lib/web/eventsource/eventsource-stream.js +399 -0
  138. package/dist/node_modules/undici/lib/web/eventsource/eventsource.js +501 -0
  139. package/dist/node_modules/undici/lib/web/eventsource/util.js +29 -0
  140. package/dist/node_modules/undici/lib/web/fetch/LICENSE +21 -0
  141. package/dist/node_modules/undici/lib/web/fetch/body.js +509 -0
  142. package/dist/node_modules/undici/lib/web/fetch/constants.js +131 -0
  143. package/dist/node_modules/undici/lib/web/fetch/data-url.js +596 -0
  144. package/dist/node_modules/undici/lib/web/fetch/formdata-parser.js +575 -0
  145. package/dist/node_modules/undici/lib/web/fetch/formdata.js +259 -0
  146. package/dist/node_modules/undici/lib/web/fetch/global.js +40 -0
  147. package/dist/node_modules/undici/lib/web/fetch/headers.js +719 -0
  148. package/dist/node_modules/undici/lib/web/fetch/index.js +2397 -0
  149. package/dist/node_modules/undici/lib/web/fetch/request.js +1115 -0
  150. package/dist/node_modules/undici/lib/web/fetch/response.js +641 -0
  151. package/dist/node_modules/undici/lib/web/fetch/util.js +1520 -0
  152. package/dist/node_modules/undici/lib/web/infra/index.js +229 -0
  153. package/dist/node_modules/undici/lib/web/subresource-integrity/Readme.md +9 -0
  154. package/dist/node_modules/undici/lib/web/subresource-integrity/subresource-integrity.js +307 -0
  155. package/dist/node_modules/undici/lib/web/webidl/index.js +1006 -0
  156. package/dist/node_modules/undici/lib/web/websocket/connection.js +329 -0
  157. package/dist/node_modules/undici/lib/web/websocket/constants.js +126 -0
  158. package/dist/node_modules/undici/lib/web/websocket/events.js +331 -0
  159. package/dist/node_modules/undici/lib/web/websocket/frame.js +133 -0
  160. package/dist/node_modules/undici/lib/web/websocket/permessage-deflate.js +118 -0
  161. package/dist/node_modules/undici/lib/web/websocket/receiver.js +450 -0
  162. package/dist/node_modules/undici/lib/web/websocket/sender.js +109 -0
  163. package/dist/node_modules/undici/lib/web/websocket/stream/websocketerror.js +104 -0
  164. package/dist/node_modules/undici/lib/web/websocket/stream/websocketstream.js +497 -0
  165. package/dist/node_modules/undici/lib/web/websocket/util.js +347 -0
  166. package/dist/node_modules/undici/lib/web/websocket/websocket.js +751 -0
  167. package/dist/node_modules/undici/package.json +152 -0
  168. package/dist/node_modules/undici/scripts/strip-comments.js +10 -0
  169. package/dist/node_modules/undici/types/README.md +6 -0
  170. package/dist/node_modules/undici/types/agent.d.ts +32 -0
  171. package/dist/node_modules/undici/types/api.d.ts +43 -0
  172. package/dist/node_modules/undici/types/balanced-pool.d.ts +30 -0
  173. package/dist/node_modules/undici/types/cache-interceptor.d.ts +179 -0
  174. package/dist/node_modules/undici/types/cache.d.ts +36 -0
  175. package/dist/node_modules/undici/types/client-stats.d.ts +15 -0
  176. package/dist/node_modules/undici/types/client.d.ts +123 -0
  177. package/dist/node_modules/undici/types/connector.d.ts +36 -0
  178. package/dist/node_modules/undici/types/content-type.d.ts +21 -0
  179. package/dist/node_modules/undici/types/cookies.d.ts +30 -0
  180. package/dist/node_modules/undici/types/diagnostics-channel.d.ts +74 -0
  181. package/dist/node_modules/undici/types/dispatcher.d.ts +273 -0
  182. package/dist/node_modules/undici/types/env-http-proxy-agent.d.ts +22 -0
  183. package/dist/node_modules/undici/types/errors.d.ts +177 -0
  184. package/dist/node_modules/undici/types/eventsource.d.ts +66 -0
  185. package/dist/node_modules/undici/types/fetch.d.ts +231 -0
  186. package/dist/node_modules/undici/types/formdata.d.ts +114 -0
  187. package/dist/node_modules/undici/types/global-dispatcher.d.ts +9 -0
  188. package/dist/node_modules/undici/types/global-origin.d.ts +7 -0
  189. package/dist/node_modules/undici/types/h2c-client.d.ts +73 -0
  190. package/dist/node_modules/undici/types/handlers.d.ts +14 -0
  191. package/dist/node_modules/undici/types/header.d.ts +160 -0
  192. package/dist/node_modules/undici/types/index.d.ts +91 -0
  193. package/dist/node_modules/undici/types/interceptors.d.ts +80 -0
  194. package/dist/node_modules/undici/types/mock-agent.d.ts +68 -0
  195. package/dist/node_modules/undici/types/mock-call-history.d.ts +111 -0
  196. package/dist/node_modules/undici/types/mock-client.d.ts +27 -0
  197. package/dist/node_modules/undici/types/mock-errors.d.ts +12 -0
  198. package/dist/node_modules/undici/types/mock-interceptor.d.ts +94 -0
  199. package/dist/node_modules/undici/types/mock-pool.d.ts +27 -0
  200. package/dist/node_modules/undici/types/patch.d.ts +29 -0
  201. package/dist/node_modules/undici/types/pool-stats.d.ts +19 -0
  202. package/dist/node_modules/undici/types/pool.d.ts +41 -0
  203. package/dist/node_modules/undici/types/proxy-agent.d.ts +29 -0
  204. package/dist/node_modules/undici/types/readable.d.ts +68 -0
  205. package/dist/node_modules/undici/types/retry-agent.d.ts +8 -0
  206. package/dist/node_modules/undici/types/retry-handler.d.ts +125 -0
  207. package/dist/node_modules/undici/types/round-robin-pool.d.ts +41 -0
  208. package/dist/node_modules/undici/types/snapshot-agent.d.ts +109 -0
  209. package/dist/node_modules/undici/types/socks5-proxy-agent.d.ts +25 -0
  210. package/dist/node_modules/undici/types/util.d.ts +18 -0
  211. package/dist/node_modules/undici/types/utility.d.ts +7 -0
  212. package/dist/node_modules/undici/types/webidl.d.ts +347 -0
  213. package/dist/node_modules/undici/types/websocket.d.ts +188 -0
  214. package/dist/server/collections/oidcStates.d.ts +10 -0
  215. package/dist/server/collections/oidcStates.js +96 -0
  216. package/dist/server/db-adapter.d.ts +25 -0
  217. package/dist/server/db-adapter.js +156 -0
  218. package/dist/server/service.js +11 -10
  219. package/package.json +2 -2
  220. package/dist/server/cache-adapter.d.ts +0 -33
  221. package/dist/server/cache-adapter.js +0 -159
@@ -0,0 +1,190 @@
1
+ # Mocking Request
2
+
3
+ Undici has its own mocking [utility](/docs/docs/api/MockAgent.md). It allow us to intercept undici HTTP requests and return mocked values instead. It can be useful for testing purposes.
4
+
5
+ Example:
6
+
7
+ ```js
8
+ // bank.mjs
9
+ import { request } from 'undici'
10
+
11
+ export async function bankTransfer(recipient, amount) {
12
+ const { body } = await request('http://localhost:3000/bank-transfer',
13
+ {
14
+ method: 'POST',
15
+ headers: {
16
+ 'X-TOKEN-SECRET': 'SuperSecretToken',
17
+ },
18
+ body: JSON.stringify({
19
+ recipient,
20
+ amount
21
+ })
22
+ }
23
+ )
24
+ return await body.json()
25
+ }
26
+ ```
27
+
28
+ And this is what the test file looks like:
29
+
30
+ ```js
31
+ // index.test.mjs
32
+ import { strict as assert } from 'node:assert'
33
+ import { MockAgent, setGlobalDispatcher, } from 'undici'
34
+ import { bankTransfer } from './bank.mjs'
35
+
36
+ const mockAgent = new MockAgent();
37
+
38
+ setGlobalDispatcher(mockAgent);
39
+
40
+ // Provide the base url to the request
41
+ const mockPool = mockAgent.get('http://localhost:3000');
42
+
43
+ // intercept the request
44
+ mockPool.intercept({
45
+ path: '/bank-transfer',
46
+ method: 'POST',
47
+ headers: {
48
+ 'X-TOKEN-SECRET': 'SuperSecretToken',
49
+ },
50
+ body: JSON.stringify({
51
+ recipient: '1234567890',
52
+ amount: '100'
53
+ })
54
+ }).reply(200, {
55
+ message: 'transaction processed'
56
+ })
57
+
58
+ const success = await bankTransfer('1234567890', '100')
59
+
60
+ assert.deepEqual(success, { message: 'transaction processed' })
61
+
62
+ // if you dont want to check whether the body or the headers contain the same value
63
+ // just remove it from interceptor
64
+ mockPool.intercept({
65
+ path: '/bank-transfer',
66
+ method: 'POST',
67
+ }).reply(400, {
68
+ message: 'bank account not found'
69
+ })
70
+
71
+ const badRequest = await bankTransfer('1234567890', '100')
72
+
73
+ assert.deepEqual(badRequest, { message: 'bank account not found' })
74
+ ```
75
+
76
+ Explore other MockAgent functionality [here](/docs/docs/api/MockAgent.md)
77
+
78
+ ## Access agent call history
79
+
80
+ Using a MockAgent also allows you to make assertions on the configuration used to make your request in your application.
81
+
82
+ Here is an example :
83
+
84
+ ```js
85
+ // index.test.mjs
86
+ import { strict as assert } from 'node:assert'
87
+ import { MockAgent, setGlobalDispatcher, fetch } from 'undici'
88
+ import { app } from './app.mjs'
89
+
90
+ // given an application server running on http://localhost:3000
91
+ await app.start()
92
+
93
+ // enable call history at instantiation
94
+ const mockAgent = new MockAgent({ enableCallHistory: true })
95
+ // or after instantiation
96
+ mockAgent.enableCallHistory()
97
+
98
+ setGlobalDispatcher(mockAgent)
99
+
100
+ // this call is made (not intercepted)
101
+ await fetch(`http://localhost:3000/endpoint?query='hello'`, {
102
+ method: 'POST',
103
+ headers: { 'content-type': 'application/json' }
104
+ body: JSON.stringify({ data: '' })
105
+ })
106
+
107
+ // access to the call history of the MockAgent (which register every call made intercepted or not)
108
+ assert.ok(mockAgent.getCallHistory()?.calls().length === 1)
109
+ assert.strictEqual(mockAgent.getCallHistory()?.firstCall()?.fullUrl, `http://localhost:3000/endpoint?query='hello'`)
110
+ assert.strictEqual(mockAgent.getCallHistory()?.firstCall()?.body, JSON.stringify({ data: '' }))
111
+ assert.deepStrictEqual(mockAgent.getCallHistory()?.firstCall()?.searchParams, { query: 'hello' })
112
+ assert.strictEqual(mockAgent.getCallHistory()?.firstCall()?.port, '3000')
113
+ assert.strictEqual(mockAgent.getCallHistory()?.firstCall()?.host, 'localhost:3000')
114
+ assert.strictEqual(mockAgent.getCallHistory()?.firstCall()?.method, 'POST')
115
+ assert.strictEqual(mockAgent.getCallHistory()?.firstCall()?.path, '/endpoint')
116
+ assert.deepStrictEqual(mockAgent.getCallHistory()?.firstCall()?.headers, { 'content-type': 'application/json' })
117
+
118
+ // clear all call history logs
119
+ mockAgent.clearCallHistory()
120
+
121
+ assert.ok(mockAgent.getCallHistory()?.calls().length === 0)
122
+ ```
123
+
124
+ Calling `mockAgent.close()` will automatically clear and delete every call history for you.
125
+
126
+ Explore other MockAgent functionality [here](/docs/docs/api/MockAgent.md)
127
+
128
+ Explore other MockCallHistory functionality [here](/docs/docs/api/MockCallHistory.md)
129
+
130
+ Explore other MockCallHistoryLog functionality [here](/docs/docs/api/MockCallHistoryLog.md)
131
+
132
+ ## Debug Mock Value
133
+
134
+ When the interceptor and the request options are not the same, undici will automatically make a real HTTP request. To prevent real requests from being made, use `mockAgent.disableNetConnect()`:
135
+
136
+ ```js
137
+ const mockAgent = new MockAgent();
138
+
139
+ setGlobalDispatcher(mockAgent);
140
+ mockAgent.disableNetConnect()
141
+
142
+ // Provide the base url to the request
143
+ const mockPool = mockAgent.get('http://localhost:3000');
144
+
145
+ mockPool.intercept({
146
+ path: '/bank-transfer',
147
+ method: 'POST',
148
+ }).reply(200, {
149
+ message: 'transaction processed'
150
+ })
151
+
152
+ const badRequest = await bankTransfer('1234567890', '100')
153
+ // Will throw an error
154
+ // MockNotMatchedError: Mock dispatch not matched for path '/bank-transfer':
155
+ // subsequent request to origin http://localhost:3000 was not allowed (net.connect disabled)
156
+ ```
157
+
158
+ ## Reply with data based on request
159
+
160
+ If the mocked response needs to be dynamically derived from the request parameters, you can provide a function instead of an object to `reply`:
161
+
162
+ ```js
163
+ mockPool.intercept({
164
+ path: '/bank-transfer',
165
+ method: 'POST',
166
+ headers: {
167
+ 'X-TOKEN-SECRET': 'SuperSecretToken',
168
+ },
169
+ body: JSON.stringify({
170
+ recipient: '1234567890',
171
+ amount: '100'
172
+ })
173
+ }).reply(200, (opts) => {
174
+ // do something with opts
175
+
176
+ return { message: 'transaction processed' }
177
+ })
178
+ ```
179
+
180
+ in this case opts will be
181
+
182
+ ```
183
+ {
184
+ method: 'POST',
185
+ headers: { 'X-TOKEN-SECRET': 'SuperSecretToken' },
186
+ body: '{"recipient":"1234567890","amount":"100"}',
187
+ origin: 'http://localhost:3000',
188
+ path: '/bank-transfer'
189
+ }
190
+ ```
@@ -0,0 +1,127 @@
1
+ # Connecting through a proxy
2
+
3
+ Connecting through a proxy is possible by:
4
+
5
+ - Using [ProxyAgent](/docs/docs/api/ProxyAgent.md).
6
+ - Configuring `Client` or `Pool` constructor.
7
+
8
+ The proxy url should be passed to the `Client` or `Pool` constructor, while the upstream server url
9
+ should be added to every request call in the `path`.
10
+ For instance, if you need to send a request to the `/hello` route of your upstream server,
11
+ the `path` should be `path: 'http://upstream.server:port/hello?foo=bar'`.
12
+
13
+ If you proxy requires basic authentication, you can send it via the `proxy-authorization` header.
14
+
15
+ ### Connect without authentication
16
+
17
+ ```js
18
+ import { Client } from 'undici'
19
+ import { createServer } from 'http'
20
+ import { createProxy } from 'proxy'
21
+
22
+ const server = await buildServer()
23
+ const proxyServer = await buildProxy()
24
+
25
+ const serverUrl = `http://localhost:${server.address().port}`
26
+ const proxyUrl = `http://localhost:${proxyServer.address().port}`
27
+
28
+ server.on('request', (req, res) => {
29
+ console.log(req.url) // '/hello?foo=bar'
30
+ res.setHeader('content-type', 'application/json')
31
+ res.end(JSON.stringify({ hello: 'world' }))
32
+ })
33
+
34
+ const client = new Client(proxyUrl)
35
+
36
+ const response = await client.request({
37
+ method: 'GET',
38
+ path: serverUrl + '/hello?foo=bar'
39
+ })
40
+
41
+ response.body.setEncoding('utf8')
42
+ let data = ''
43
+ for await (const chunk of response.body) {
44
+ data += chunk
45
+ }
46
+ console.log(response.statusCode) // 200
47
+ console.log(JSON.parse(data)) // { hello: 'world' }
48
+
49
+ server.close()
50
+ proxyServer.close()
51
+ client.close()
52
+
53
+ function buildServer () {
54
+ return new Promise((resolve, reject) => {
55
+ const server = createServer()
56
+ server.listen(0, () => resolve(server))
57
+ })
58
+ }
59
+
60
+ function buildProxy () {
61
+ return new Promise((resolve, reject) => {
62
+ const server = createProxy(createServer())
63
+ server.listen(0, () => resolve(server))
64
+ })
65
+ }
66
+ ```
67
+
68
+ ### Connect with authentication
69
+
70
+ ```js
71
+ import { Client } from 'undici'
72
+ import { createServer } from 'http'
73
+ import { createProxy } from 'proxy'
74
+
75
+ const server = await buildServer()
76
+ const proxyServer = await buildProxy()
77
+
78
+ const serverUrl = `http://localhost:${server.address().port}`
79
+ const proxyUrl = `http://localhost:${proxyServer.address().port}`
80
+
81
+ proxyServer.authenticate = function (req) {
82
+ return req.headers['proxy-authorization'] === `Basic ${Buffer.from('user:pass').toString('base64')}`
83
+ }
84
+
85
+ server.on('request', (req, res) => {
86
+ console.log(req.url) // '/hello?foo=bar'
87
+ res.setHeader('content-type', 'application/json')
88
+ res.end(JSON.stringify({ hello: 'world' }))
89
+ })
90
+
91
+ const client = new Client(proxyUrl)
92
+
93
+ const response = await client.request({
94
+ method: 'GET',
95
+ path: serverUrl + '/hello?foo=bar',
96
+ headers: {
97
+ 'proxy-authorization': `Basic ${Buffer.from('user:pass').toString('base64')}`
98
+ }
99
+ })
100
+
101
+ response.body.setEncoding('utf8')
102
+ let data = ''
103
+ for await (const chunk of response.body) {
104
+ data += chunk
105
+ }
106
+ console.log(response.statusCode) // 200
107
+ console.log(JSON.parse(data)) // { hello: 'world' }
108
+
109
+ server.close()
110
+ proxyServer.close()
111
+ client.close()
112
+
113
+ function buildServer () {
114
+ return new Promise((resolve, reject) => {
115
+ const server = createServer()
116
+ server.listen(0, () => resolve(server))
117
+ })
118
+ }
119
+
120
+ function buildProxy () {
121
+ return new Promise((resolve, reject) => {
122
+ const server = createProxy(createServer())
123
+ server.listen(0, () => resolve(server))
124
+ })
125
+ }
126
+ ```
127
+
@@ -0,0 +1,224 @@
1
+ # Undici Module vs. Node.js Built-in Fetch
2
+
3
+ Node.js has shipped a built-in `fetch()` implementation powered by undici since
4
+ Node.js v18. This guide explains the relationship between the `undici` npm
5
+ package and the built-in `fetch`, and when you should install one versus relying
6
+ on the other.
7
+
8
+ ## Background
9
+
10
+ The `fetch()`, `Request`, `Response`, `Headers`, and `FormData` globals in
11
+ Node.js v18+ are provided by a version of undici that is bundled into Node.js
12
+ itself. You can check which version is bundled with:
13
+
14
+ ```js
15
+ console.log(process.versions.undici); // e.g., "7.5.0"
16
+ ```
17
+
18
+ When you install undici from npm, you get the full library with all of its
19
+ additional APIs, and potentially a newer release than what your Node.js version
20
+ bundles.
21
+
22
+ ## Keep `fetch` and `FormData` from the same implementation
23
+
24
+ When you send a `FormData` body, keep `fetch` and `FormData` together from the
25
+ same implementation.
26
+
27
+ Use one of these patterns:
28
+
29
+ ### Built-in globals
30
+
31
+ ```js
32
+ const body = new FormData()
33
+ body.set('name', 'some')
34
+ body.set('someOtherProperty', '8000')
35
+
36
+ await fetch('https://example.com', {
37
+ method: 'POST',
38
+ body
39
+ })
40
+ ```
41
+
42
+ ### `undici` module imports
43
+
44
+ ```js
45
+ import { fetch, FormData } from 'undici'
46
+
47
+ const body = new FormData()
48
+ body.set('name', 'some')
49
+ body.set('someOtherProperty', '8000')
50
+
51
+ await fetch('https://example.com', {
52
+ method: 'POST',
53
+ body
54
+ })
55
+ ```
56
+
57
+ ### `undici.install()` globals
58
+
59
+ If you want the installed `undici` package to provide the globals, call
60
+ [`install()`](/docs/api/GlobalInstallation.md):
61
+
62
+ ```js
63
+ import { install } from 'undici'
64
+
65
+ install()
66
+
67
+ const body = new FormData()
68
+ body.set('name', 'some')
69
+ body.set('someOtherProperty', '8000')
70
+
71
+ await fetch('https://example.com', {
72
+ method: 'POST',
73
+ body
74
+ })
75
+ ```
76
+
77
+ `install()` replaces the global `fetch`, `Headers`, `Response`, `Request`, and
78
+ `FormData` implementations with undici's versions, and also installs undici's
79
+ `WebSocket`, `CloseEvent`, `ErrorEvent`, `MessageEvent`, and `EventSource`
80
+ globals.
81
+
82
+ Avoid mixing implementations in the same request, for example:
83
+
84
+ ```js
85
+ import { fetch } from 'undici'
86
+
87
+ const body = new FormData()
88
+
89
+ await fetch('https://example.com', {
90
+ method: 'POST',
91
+ body
92
+ })
93
+ ```
94
+
95
+ ```js
96
+ import { FormData } from 'undici'
97
+
98
+ const body = new FormData()
99
+
100
+ await fetch('https://example.com', {
101
+ method: 'POST',
102
+ body
103
+ })
104
+ ```
105
+
106
+ Those combinations may behave differently across Node.js and undici versions.
107
+ Using matching pairs keeps multipart handling predictable.
108
+
109
+ ## When you do NOT need to install undici
110
+
111
+ If all of the following are true, you can rely on the built-in globals and skip
112
+ adding undici to your dependencies:
113
+
114
+ - You only need the standard Fetch API (`fetch`, `Request`, `Response`,
115
+ `Headers`, `FormData`).
116
+ - You are running Node.js v18 or later.
117
+ - You do not depend on features or bug fixes introduced in a version of undici
118
+ newer than the one bundled with your Node.js release.
119
+ - You want zero additional runtime dependencies.
120
+ - You want cross-platform interoperability with browsers and other runtimes
121
+ (Deno, Bun, Cloudflare Workers, etc.) using the same Fetch API surface.
122
+
123
+ This is common in applications that make straightforward HTTP requests or in
124
+ libraries that target multiple JavaScript runtimes.
125
+
126
+ ## When you SHOULD install undici
127
+
128
+ Install undici from npm when you need capabilities beyond the standard Fetch API:
129
+
130
+ ### Advanced HTTP APIs
131
+
132
+ undici exposes `request`, `stream`, `pipeline`, and `connect` methods that
133
+ provide lower-level control and significantly better performance than `fetch`:
134
+
135
+ ```js
136
+ import { request } from 'undici';
137
+
138
+ const { statusCode, headers, body } = await request('https://example.com');
139
+ const data = await body.json();
140
+ ```
141
+
142
+ ### Connection pooling and dispatchers
143
+
144
+ `Client`, `Pool`, `BalancedPool`, `Agent`, and their configuration options
145
+ let you manage connection lifecycle, keep-alive behavior, pipelining depth,
146
+ and concurrency limits:
147
+
148
+ ```js
149
+ import { Pool } from 'undici';
150
+
151
+ const pool = new Pool('https://example.com', { connections: 10 });
152
+ const { body } = await pool.request({ path: '/', method: 'GET' });
153
+ ```
154
+
155
+ ### Proxy support
156
+
157
+ `ProxyAgent` and `EnvHttpProxyAgent` handle HTTP(S) proxying. Note that
158
+ Node.js v22.21.0+ and v24.0.0+ support environment-variable-based proxy
159
+ configuration for the built-in `fetch` via the `--use-env-proxy` flag (or
160
+ `NODE_USE_ENV_PROXY=1`). However, undici's `ProxyAgent` still provides
161
+ programmatic control through the dispatcher API:
162
+
163
+ ```js
164
+ import { ProxyAgent, fetch } from 'undici';
165
+
166
+ const proxyAgent = new ProxyAgent('https://my-proxy.example.com:8080');
167
+ const response = await fetch('https://example.com', { dispatcher: proxyAgent });
168
+ ```
169
+
170
+ ### Testing and mocking
171
+
172
+ `MockAgent`, `MockClient`, and `MockPool` let you intercept and mock HTTP
173
+ requests without patching globals or depending on external libraries:
174
+
175
+ ```js
176
+ import { MockAgent, setGlobalDispatcher, fetch } from 'undici';
177
+
178
+ const mockAgent = new MockAgent();
179
+ setGlobalDispatcher(mockAgent);
180
+
181
+ const pool = mockAgent.get('https://example.com');
182
+ pool.intercept({ path: '/api' }).reply(200, { message: 'mocked' });
183
+ ```
184
+
185
+ ### Interceptors and middleware
186
+
187
+ Custom dispatchers and interceptors (retry, redirect, cache, DNS) give you
188
+ fine-grained control over how requests are processed.
189
+
190
+ ### Newer version than what Node.js bundles
191
+
192
+ The npm package often includes features, performance improvements, and bug fixes
193
+ that have not yet landed in a Node.js release. If you need a specific fix or
194
+ feature, you can install a newer version directly.
195
+
196
+ ## Version compatibility
197
+
198
+ | Node.js version | Bundled undici version | Notes |
199
+ |---|---|---|
200
+ | v18.x | ~5.x | `fetch` is experimental (behind `--experimental-fetch` in early v18) |
201
+ | v20.x | ~6.x | `fetch` is stable |
202
+ | v22.x | ~6.x / ~7.x | `fetch` is stable |
203
+ | v24.x | ~7.x | `fetch` is stable; env-proxy support via `--use-env-proxy` |
204
+
205
+ You can always check the exact bundled version at runtime with
206
+ `process.versions.undici`.
207
+
208
+ Installing undici from npm does not replace the built-in globals. If you want
209
+ your installed version to replace the global `fetch` and related classes, use
210
+ [`install()`](/docs/api/GlobalInstallation.md). Otherwise, import `fetch`
211
+ directly from `'undici'`:
212
+
213
+ ```js
214
+ import { fetch } from 'undici' // uses your installed version, not the built-in
215
+ ```
216
+
217
+ ## Further reading
218
+
219
+ - [API Reference: Fetch](/docs/api/Fetch.md)
220
+ - [API Reference: Client](/docs/api/Client.md)
221
+ - [API Reference: Pool](/docs/api/Pool.md)
222
+ - [API Reference: ProxyAgent](/docs/api/ProxyAgent.md)
223
+ - [API Reference: MockAgent](/docs/api/MockAgent.md)
224
+ - [API Reference: Global Installation](/docs/api/GlobalInstallation.md)
@@ -0,0 +1,63 @@
1
+ # Writing tests
2
+
3
+ Undici is tuned for a production use case and its default will keep
4
+ a socket open for a few seconds after an HTTP request is completed to
5
+ remove the overhead of opening up a new socket. These settings that makes
6
+ Undici shine in production are not a good fit for using Undici in automated
7
+ tests, as it will result in longer execution times.
8
+
9
+ The following are good defaults that will keep the socket open for only 10ms:
10
+
11
+ ```js
12
+ import { request, setGlobalDispatcher, Agent } from 'undici'
13
+
14
+ const agent = new Agent({
15
+ keepAliveTimeout: 10, // milliseconds
16
+ keepAliveMaxTimeout: 10 // milliseconds
17
+ })
18
+
19
+ setGlobalDispatcher(agent)
20
+ ```
21
+
22
+ ## Guarding against unexpected disconnects
23
+
24
+ Undici's `Client` automatically reconnects after a socket error. This means
25
+ a test can silently disconnect, reconnect, and still pass. Unfortunately,
26
+ this could mask bugs like unexpected parser errors or protocol violations.
27
+ To catch these silent reconnections, add a disconnect guard after creating
28
+ a `Client`:
29
+
30
+ ```js
31
+ const { Client } = require('undici')
32
+ const { test, after } = require('node:test')
33
+ const { tspl } = require('@matteo.collina/tspl')
34
+
35
+ test('example with disconnect guard', async (t) => {
36
+ t = tspl(t, { plan: 1 })
37
+
38
+ const client = new Client('http://localhost:3000')
39
+ after(() => client.close())
40
+
41
+ client.on('disconnect', () => {
42
+ if (!client.closed && !client.destroyed) {
43
+ t.fail('unexpected disconnect')
44
+ }
45
+ })
46
+
47
+ // ... test logic ...
48
+ })
49
+ ```
50
+
51
+ `client.close()` and `client.destroy()` both emit `'disconnect'` events, but
52
+ those are expected. The guard only fails when a disconnect happens during the
53
+ active test (i.e., `!client.closed && !client.destroyed` is true).
54
+
55
+ Skip the guard for tests where a disconnect is expected behavior, such as:
56
+
57
+ - Signal aborts (`signal.emit('abort')`, `ac.abort()`)
58
+ - Server-side destruction (`res.destroy()`, `req.socket.destroy()`)
59
+ - Client-side body destruction mid-stream (`data.body.destroy()`)
60
+ - Timeout errors (`HeadersTimeoutError`, `BodyTimeoutError`)
61
+ - Successful upgrades (the socket is detached from the `Client`)
62
+ - Retry/reconnect tests where the disconnect triggers the retry
63
+ - HTTP parser errors from malformed responses (`HTTPParserError`)
@@ -0,0 +1,65 @@
1
+ 'use strict'
2
+
3
+ const { getGlobalDispatcher, setGlobalDispatcher } = require('./lib/global')
4
+ const EnvHttpProxyAgent = require('./lib/dispatcher/env-http-proxy-agent')
5
+ const fetchImpl = require('./lib/web/fetch').fetch
6
+
7
+ // Capture __filename at module load time for stack trace augmentation.
8
+ // This may be undefined when bundled in environments like Node.js internals.
9
+ const currentFilename = typeof __filename !== 'undefined' ? __filename : undefined
10
+
11
+ function appendFetchStackTrace (err, filename) {
12
+ if (!err || typeof err !== 'object') {
13
+ return
14
+ }
15
+
16
+ const stack = typeof err.stack === 'string' ? err.stack : ''
17
+ const normalizedFilename = filename.replace(/\\/g, '/')
18
+
19
+ if (stack && (stack.includes(filename) || stack.includes(normalizedFilename))) {
20
+ return
21
+ }
22
+
23
+ const capture = {}
24
+ Error.captureStackTrace(capture, appendFetchStackTrace)
25
+
26
+ if (!capture.stack) {
27
+ return
28
+ }
29
+
30
+ const captureLines = capture.stack.split('\n').slice(1).join('\n')
31
+
32
+ err.stack = stack ? `${stack}\n${captureLines}` : capture.stack
33
+ }
34
+
35
+ module.exports.fetch = function fetch (init, options = undefined) {
36
+ return fetchImpl(init, options).catch(err => {
37
+ if (currentFilename) {
38
+ appendFetchStackTrace(err, currentFilename)
39
+ } else if (err && typeof err === 'object') {
40
+ Error.captureStackTrace(err, module.exports.fetch)
41
+ }
42
+ throw err
43
+ })
44
+ }
45
+ module.exports.FormData = require('./lib/web/fetch/formdata').FormData
46
+ module.exports.Headers = require('./lib/web/fetch/headers').Headers
47
+ module.exports.Response = require('./lib/web/fetch/response').Response
48
+ module.exports.Request = require('./lib/web/fetch/request').Request
49
+
50
+ const { CloseEvent, ErrorEvent, MessageEvent, createFastMessageEvent } = require('./lib/web/websocket/events')
51
+ module.exports.WebSocket = require('./lib/web/websocket/websocket').WebSocket
52
+ module.exports.CloseEvent = CloseEvent
53
+ module.exports.ErrorEvent = ErrorEvent
54
+ module.exports.MessageEvent = MessageEvent
55
+ module.exports.createFastMessageEvent = createFastMessageEvent
56
+
57
+ module.exports.EventSource = require('./lib/web/eventsource/eventsource').EventSource
58
+
59
+ const api = require('./lib/api')
60
+ const Dispatcher = require('./lib/dispatcher/dispatcher')
61
+ Object.assign(Dispatcher.prototype, api)
62
+ // Expose the fetch implementation to be enabled in Node.js core via a flag
63
+ module.exports.EnvHttpProxyAgent = EnvHttpProxyAgent
64
+ module.exports.getGlobalDispatcher = getGlobalDispatcher
65
+ module.exports.setGlobalDispatcher = setGlobalDispatcher
@@ -0,0 +1,3 @@
1
+ import Undici from './types/index'
2
+ export default Undici
3
+ export * from './types/index'