@noodleseed/one 0.22.0 → 0.23.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 (197) hide show
  1. package/dist/commands/author-loop.d.ts.map +1 -1
  2. package/dist/commands/author-loop.js +2 -2
  3. package/dist/commands/author-loop.js.map +1 -1
  4. package/dist/commands/catalog-dispatch.d.ts.map +1 -1
  5. package/dist/commands/catalog-dispatch.js +21 -2
  6. package/dist/commands/catalog-dispatch.js.map +1 -1
  7. package/dist/commands/deploy-ops.d.ts.map +1 -1
  8. package/dist/commands/deploy-ops.js +28 -11
  9. package/dist/commands/deploy-ops.js.map +1 -1
  10. package/dist/first-run.d.ts +11 -0
  11. package/dist/first-run.d.ts.map +1 -1
  12. package/dist/first-run.js +19 -4
  13. package/dist/first-run.js.map +1 -1
  14. package/dist/project-scaffold-templates.d.ts +11 -0
  15. package/dist/project-scaffold-templates.d.ts.map +1 -0
  16. package/dist/project-scaffold-templates.js +359 -0
  17. package/dist/project-scaffold-templates.js.map +1 -0
  18. package/dist/project.d.ts.map +1 -1
  19. package/dist/project.js +1 -323
  20. package/dist/project.js.map +1 -1
  21. package/dist/react.d.ts +2 -2
  22. package/dist/react.d.ts.map +1 -1
  23. package/dist/react.js +1 -1
  24. package/dist/react.js.map +1 -1
  25. package/dist/validate.d.ts +12 -0
  26. package/dist/validate.d.ts.map +1 -1
  27. package/dist/validate.js +11 -0
  28. package/dist/validate.js.map +1 -1
  29. package/node_modules/@noodle-borg/agent-kit/dist/skill-content.d.ts.map +1 -1
  30. package/node_modules/@noodle-borg/agent-kit/dist/skill-content.js +6 -9
  31. package/node_modules/@noodle-borg/agent-kit/dist/skill-content.js.map +1 -1
  32. package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
  33. package/node_modules/@noodle-borg/authoring/dist/index.d.ts +3 -3
  34. package/node_modules/@noodle-borg/authoring/dist/index.d.ts.map +1 -1
  35. package/node_modules/@noodle-borg/authoring/dist/index.js +1 -1
  36. package/node_modules/@noodle-borg/authoring/dist/index.js.map +1 -1
  37. package/node_modules/@noodle-borg/authoring/dist/react/components.d.ts +302 -7
  38. package/node_modules/@noodle-borg/authoring/dist/react/components.d.ts.map +1 -1
  39. package/node_modules/@noodle-borg/authoring/dist/react/components.js +39 -7
  40. package/node_modules/@noodle-borg/authoring/dist/react/components.js.map +1 -1
  41. package/node_modules/@noodle-borg/authoring/dist/react/index.d.ts +4 -2
  42. package/node_modules/@noodle-borg/authoring/dist/react/index.d.ts.map +1 -1
  43. package/node_modules/@noodle-borg/authoring/dist/react/index.js +2 -1
  44. package/node_modules/@noodle-borg/authoring/dist/react/index.js.map +1 -1
  45. package/node_modules/@noodle-borg/authoring/dist/react/semantic-components.d.ts +2618 -0
  46. package/node_modules/@noodle-borg/authoring/dist/react/semantic-components.d.ts.map +1 -0
  47. package/node_modules/@noodle-borg/authoring/dist/react/semantic-components.js +110 -0
  48. package/node_modules/@noodle-borg/authoring/dist/react/semantic-components.js.map +1 -0
  49. package/node_modules/@noodle-borg/authoring/dist/react.d.ts +2 -2
  50. package/node_modules/@noodle-borg/authoring/dist/react.d.ts.map +1 -1
  51. package/node_modules/@noodle-borg/authoring/dist/react.js +1 -1
  52. package/node_modules/@noodle-borg/authoring/dist/react.js.map +1 -1
  53. package/node_modules/@noodle-borg/authoring/dist/recording.d.ts +1 -1
  54. package/node_modules/@noodle-borg/authoring/dist/recording.d.ts.map +1 -1
  55. package/node_modules/@noodle-borg/authoring/dist/recording.js +14 -1
  56. package/node_modules/@noodle-borg/authoring/dist/recording.js.map +1 -1
  57. package/node_modules/@noodle-borg/authoring/dist/server.d.ts +25 -2
  58. package/node_modules/@noodle-borg/authoring/dist/server.d.ts.map +1 -1
  59. package/node_modules/@noodle-borg/authoring/dist/server.js +7 -3
  60. package/node_modules/@noodle-borg/authoring/dist/server.js.map +1 -1
  61. package/node_modules/@noodle-borg/compiler/dist/compile.d.ts.map +1 -1
  62. package/node_modules/@noodle-borg/compiler/dist/compile.js +20 -8
  63. package/node_modules/@noodle-borg/compiler/dist/compile.js.map +1 -1
  64. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts +2 -0
  65. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts.map +1 -1
  66. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js +6 -0
  67. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js.map +1 -1
  68. package/node_modules/@noodle-borg/connector-http/package.json +1 -1
  69. package/node_modules/@noodle-borg/protocol/dist/mapping.d.ts.map +1 -1
  70. package/node_modules/@noodle-borg/protocol/dist/mapping.js +8 -0
  71. package/node_modules/@noodle-borg/protocol/dist/mapping.js.map +1 -1
  72. package/node_modules/hono/dist/adapter/aws-lambda/handler.js +15 -21
  73. package/node_modules/hono/dist/adapter/bun/websocket.js +3 -1
  74. package/node_modules/hono/dist/adapter/lambda-edge/handler.js +8 -2
  75. package/node_modules/hono/dist/cjs/adapter/aws-lambda/handler.js +15 -21
  76. package/node_modules/hono/dist/cjs/adapter/bun/websocket.js +3 -1
  77. package/node_modules/hono/dist/cjs/adapter/lambda-edge/handler.js +8 -2
  78. package/node_modules/hono/dist/cjs/helper/css/common.js +3 -1
  79. package/node_modules/hono/dist/cjs/helper/css/index.js +9 -1
  80. package/node_modules/hono/dist/cjs/jsx/base.js +8 -14
  81. package/node_modules/hono/dist/cjs/jsx/components.js +41 -21
  82. package/node_modules/hono/dist/cjs/jsx/context.js +131 -5
  83. package/node_modules/hono/dist/cjs/jsx/streaming.js +9 -7
  84. package/node_modules/hono/dist/cjs/middleware/cors/index.js +2 -5
  85. package/node_modules/hono/dist/cjs/middleware/serve-static/index.js +2 -2
  86. package/node_modules/hono/dist/cjs/utils/body.js +12 -4
  87. package/node_modules/hono/dist/cjs/utils/buffer.js +2 -1
  88. package/node_modules/hono/dist/cjs/validator/validator.js +3 -3
  89. package/node_modules/hono/dist/helper/css/common.js +3 -1
  90. package/node_modules/hono/dist/helper/css/index.js +9 -1
  91. package/node_modules/hono/dist/jsx/base.js +15 -15
  92. package/node_modules/hono/dist/jsx/components.js +42 -22
  93. package/node_modules/hono/dist/jsx/context.js +129 -5
  94. package/node_modules/hono/dist/jsx/streaming.js +10 -8
  95. package/node_modules/hono/dist/middleware/cors/index.js +2 -5
  96. package/node_modules/hono/dist/middleware/serve-static/index.js +2 -2
  97. package/node_modules/hono/dist/types/adapter/aws-lambda/handler.d.ts +1 -1
  98. package/node_modules/hono/dist/types/jsx/base.d.ts +1 -3
  99. package/node_modules/hono/dist/types/jsx/context.d.ts +39 -0
  100. package/node_modules/hono/dist/types/middleware/context-storage/index.d.ts +2 -2
  101. package/node_modules/hono/dist/types/utils/body.d.ts +1 -1
  102. package/node_modules/hono/dist/utils/body.js +12 -4
  103. package/node_modules/hono/dist/utils/buffer.js +2 -1
  104. package/node_modules/hono/dist/validator/validator.js +3 -3
  105. package/node_modules/hono/package.json +9 -10
  106. package/node_modules/tailwindcss/dist/chunk-HMCCH6MG.mjs +1 -0
  107. package/node_modules/tailwindcss/dist/default-theme.mjs +1 -1
  108. package/node_modules/tailwindcss/dist/lib.js +13 -13
  109. package/node_modules/tailwindcss/dist/lib.mjs +18 -18
  110. package/node_modules/tailwindcss/package.json +2 -2
  111. package/node_modules/undici/README.md +3 -2
  112. package/node_modules/undici/docs/docs/api/Agent.md +248 -44
  113. package/node_modules/undici/docs/docs/api/BalancedPool.md +246 -48
  114. package/node_modules/undici/docs/docs/api/CacheStorage.md +171 -13
  115. package/node_modules/undici/docs/docs/api/CacheStore.md +294 -98
  116. package/node_modules/undici/docs/docs/api/Client.md +365 -178
  117. package/node_modules/undici/docs/docs/api/ClientStats.md +80 -14
  118. package/node_modules/undici/docs/docs/api/Connector.md +118 -36
  119. package/node_modules/undici/docs/docs/api/ContentType.md +65 -25
  120. package/node_modules/undici/docs/docs/api/Cookies.md +125 -47
  121. package/node_modules/undici/docs/docs/api/Debug.md +34 -18
  122. package/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +364 -164
  123. package/node_modules/undici/docs/docs/api/Dispatcher.md +479 -1093
  124. package/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +101 -87
  125. package/node_modules/undici/docs/docs/api/Errors.md +503 -40
  126. package/node_modules/undici/docs/docs/api/EventSource.md +294 -32
  127. package/node_modules/undici/docs/docs/api/Fetch.md +680 -31
  128. package/node_modules/undici/docs/docs/api/GlobalInstallation.md +78 -98
  129. package/node_modules/undici/docs/docs/api/H2CClient.md +298 -176
  130. package/node_modules/undici/docs/docs/api/Interceptors.md +355 -0
  131. package/node_modules/undici/docs/docs/api/MockAgent.md +314 -322
  132. package/node_modules/undici/docs/docs/api/MockCallHistory.md +272 -98
  133. package/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +189 -26
  134. package/node_modules/undici/docs/docs/api/MockClient.md +151 -33
  135. package/node_modules/undici/docs/docs/api/MockErrors.md +56 -5
  136. package/node_modules/undici/docs/docs/api/MockPool.md +299 -263
  137. package/node_modules/undici/docs/docs/api/Pool.md +235 -43
  138. package/node_modules/undici/docs/docs/api/PoolStats.md +119 -13
  139. package/node_modules/undici/docs/docs/api/ProxyAgent.md +179 -160
  140. package/node_modules/undici/docs/docs/api/RedirectHandler.md +238 -63
  141. package/node_modules/undici/docs/docs/api/RetryAgent.md +113 -26
  142. package/node_modules/undici/docs/docs/api/RetryHandler.md +161 -77
  143. package/node_modules/undici/docs/docs/api/RoundRobinPool.md +166 -72
  144. package/node_modules/undici/docs/docs/api/SnapshotAgent.md +264 -542
  145. package/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +162 -186
  146. package/node_modules/undici/docs/docs/api/Util.md +68 -11
  147. package/node_modules/undici/docs/docs/api/WebSocket.md +475 -80
  148. package/node_modules/undici/docs/docs/api/api-lifecycle.md +100 -32
  149. package/node_modules/undici/docs/docs/best-practices/client-certificate.md +2 -0
  150. package/node_modules/undici/docs/docs/best-practices/crawling.md +3 -1
  151. package/node_modules/undici/docs/docs/best-practices/migrating-from-v7-to-v8.md +6 -4
  152. package/node_modules/undici/docs/docs/best-practices/mocking-request.md +9 -7
  153. package/node_modules/undici/docs/docs/best-practices/proxy.md +3 -1
  154. package/node_modules/undici/docs/docs/best-practices/undici-vs-builtin-fetch.md +10 -8
  155. package/node_modules/undici/docs/docs/best-practices/writing-tests.md +2 -0
  156. package/node_modules/undici/docs/docs/{GettingStarted.md → getting-started.md} +22 -19
  157. package/node_modules/undici/docs/docs/index.md +779 -0
  158. package/node_modules/undici/docs/docs/site.json +125 -0
  159. package/node_modules/undici/docs/docs/type-map.json +79 -0
  160. package/node_modules/undici/lib/api/api-request.js +7 -1
  161. package/node_modules/undici/lib/api/readable.js +47 -2
  162. package/node_modules/undici/lib/core/errors.js +20 -0
  163. package/node_modules/undici/lib/core/request.js +1 -1
  164. package/node_modules/undici/lib/core/util.js +24 -1
  165. package/node_modules/undici/lib/dispatcher/client-h1.js +92 -1
  166. package/node_modules/undici/lib/dispatcher/client-h2.js +322 -118
  167. package/node_modules/undici/lib/dispatcher/client.js +6 -2
  168. package/node_modules/undici/lib/dispatcher/dispatcher-base.js +1 -0
  169. package/node_modules/undici/lib/dispatcher/proxy-agent.js +42 -7
  170. package/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +4 -2
  171. package/node_modules/undici/lib/handler/redirect-handler.js +1 -0
  172. package/node_modules/undici/lib/handler/retry-handler.js +57 -19
  173. package/node_modules/undici/lib/util/cache.js +8 -2
  174. package/node_modules/undici/lib/web/cookies/parse.js +20 -27
  175. package/node_modules/undici/lib/web/cookies/util.js +1 -1
  176. package/node_modules/undici/lib/web/eventsource/eventsource.js +7 -18
  177. package/node_modules/undici/lib/web/eventsource/util.js +32 -1
  178. package/node_modules/undici/lib/web/fetch/body.js +43 -0
  179. package/node_modules/undici/lib/web/fetch/constants.js +1 -1
  180. package/node_modules/undici/lib/web/fetch/index.js +11 -2
  181. package/node_modules/undici/lib/web/fetch/request.js +1 -0
  182. package/node_modules/undici/lib/web/fetch/util.js +4 -1
  183. package/node_modules/undici/lib/web/websocket/receiver.js +20 -3
  184. package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +8 -1
  185. package/node_modules/undici/lib/web/websocket/websocket.js +3 -1
  186. package/node_modules/undici/package.json +1 -1
  187. package/node_modules/undici/types/client.d.ts +6 -1
  188. package/node_modules/undici/types/cookies.d.ts +1 -1
  189. package/node_modules/undici/types/errors.d.ts +10 -0
  190. package/node_modules/undici/types/fetch.d.ts +1 -0
  191. package/node_modules/undici/types/handlers.d.ts +2 -0
  192. package/node_modules/undici/types/proxy-agent.d.ts +7 -0
  193. package/package.json +4 -4
  194. package/react/styles.css +510 -5
  195. package/react/styles.source.css +850 -0
  196. package/node_modules/hono/dist/tsconfig.build.tsbuildinfo +0 -1
  197. package/node_modules/tailwindcss/dist/chunk-XVOTX5KS.mjs +0 -1
@@ -0,0 +1,355 @@
1
+ # Interceptors
2
+
3
+ Undici ships with a set of built-in interceptors that can be composed via
4
+ `dispatcher.compose()` to add cross-cutting behaviour such as automatic
5
+ retries, response decompression, redirect following, DNS caching, and more.
6
+
7
+ ## Usage
8
+
9
+ ```js
10
+ import { Agent, interceptors } from 'undici'
11
+
12
+ const { retry, redirect, decompress, dump, responseError, dns, cache, deduplicate } = interceptors
13
+
14
+ const agent = new Agent().compose([
15
+ retry({ maxRetries: 3 }),
16
+ redirect({ maxRedirections: 5 }),
17
+ decompress()
18
+ ])
19
+
20
+ const response = await agent.request({ origin: 'https://example.com', path: '/', method: 'GET' })
21
+ ```
22
+
23
+ You can also apply interceptors to a single `Client` or `Pool`:
24
+
25
+ ```js
26
+ import { Client, interceptors } from 'undici'
27
+
28
+ const client = new Client('https://example.com').compose(
29
+ interceptors.retry({ maxRetries: 2 })
30
+ )
31
+ ```
32
+
33
+ ---
34
+
35
+ ## `interceptors.dump([opts])`
36
+
37
+ Reads and discards the response body up to a configurable size limit. Useful
38
+ for keeping a connection alive after an error response without reading the
39
+ body yourself.
40
+
41
+ **Parameters**
42
+
43
+ * `opts` {Object} (optional)
44
+ * `maxSize` {number} Maximum number of bytes to read and discard. Responses
45
+ whose `Content-Length` exceeds this value are aborted. **Default:**
46
+ `1_048_576` (1 MiB).
47
+
48
+ Per-request override: set `dumpMaxSize` on the dispatch options to override
49
+ the global `maxSize` for a specific request.
50
+
51
+ **Returns:** {Dispatcher.DispatcherComposeInterceptor}
52
+
53
+ **Example**
54
+
55
+ ```js
56
+ import { Agent, interceptors } from 'undici'
57
+
58
+ const agent = new Agent().compose(
59
+ interceptors.dump({ maxSize: 128 * 1024 }) // discard up to 128 KiB
60
+ )
61
+ ```
62
+
63
+ ---
64
+
65
+ ## `interceptors.retry([opts])`
66
+
67
+ Automatically retries failed requests using the same options accepted by
68
+ [`RetryHandler`](./RetryHandler.md).
69
+
70
+ **Parameters**
71
+
72
+ * `opts` {RetryHandler.RetryOptions} (optional) Global retry options applied
73
+ to every request. Individual requests can override via `opts.retryOptions`.
74
+ See [`RetryOptions`](./RetryHandler.md#retryoptions) for the full list of
75
+ accepted fields.
76
+
77
+ **Returns:** {Dispatcher.DispatcherComposeInterceptor}
78
+
79
+ **Example**
80
+
81
+ ```js
82
+ import { Agent, interceptors } from 'undici'
83
+
84
+ const agent = new Agent().compose(
85
+ interceptors.retry({
86
+ maxRetries: 5,
87
+ minTimeout: 200,
88
+ maxTimeout: 5000,
89
+ timeoutFactor: 2,
90
+ statusCodes: [429, 502, 503, 504]
91
+ })
92
+ )
93
+ ```
94
+
95
+ ---
96
+
97
+ ## `interceptors.redirect([opts])`
98
+
99
+ Follows HTTP redirects (3xx responses) automatically.
100
+
101
+ **Parameters**
102
+
103
+ * `opts` {Object} (optional)
104
+ * `maxRedirections` {number} Maximum number of redirects to follow. Passing
105
+ `0` disables redirect following entirely. **Default:** `undefined`
106
+ (inherits from the per-request `maxRedirections` option).
107
+ * `throwOnMaxRedirect` {boolean} When `true`, throws an error once the
108
+ redirect limit is reached instead of returning the final redirect response.
109
+ **Default:** `false`.
110
+ * `stripHeadersOnRedirect` {string[]} List of header names to remove from
111
+ the request when following any redirect. **Default:** `[]`.
112
+ * `stripHeadersOnCrossOriginRedirect` {string[]} List of header names to
113
+ remove from the request when following a cross-origin redirect (i.e. the
114
+ redirect target has a different origin). Useful for stripping
115
+ `Authorization` on cross-origin hops. **Default:** `[]`.
116
+
117
+ Per-request override: any of the four options above can also be set directly
118
+ on the dispatch options to override the interceptor defaults for a specific
119
+ request.
120
+
121
+ **Returns:** {Dispatcher.DispatcherComposeInterceptor}
122
+
123
+ **Example**
124
+
125
+ ```js
126
+ import { Agent, interceptors } from 'undici'
127
+
128
+ const agent = new Agent().compose(
129
+ interceptors.redirect({
130
+ maxRedirections: 10,
131
+ throwOnMaxRedirect: true,
132
+ stripHeadersOnCrossOriginRedirect: ['authorization', 'cookie']
133
+ })
134
+ )
135
+ ```
136
+
137
+ ---
138
+
139
+ ## `interceptors.decompress([opts])`
140
+
141
+ Automatically decompresses response bodies encoded with `gzip`, `x-gzip`,
142
+ `br` (Brotli), `deflate`, `compress`, `x-compress`, or `zstd`.
143
+
144
+ > **Experimental:** This interceptor is experimental and subject to change.
145
+ > A one-time `ExperimentalWarning` is emitted on first use.
146
+
147
+ **Parameters**
148
+
149
+ * `opts` {Object} (optional)
150
+ * `skipStatusCodes` {number[]} Status codes for which decompression is
151
+ skipped. **Default:** `[204, 304]`.
152
+ * `skipErrorResponses` {boolean} When `true`, responses with a status code
153
+ >= 400 are not decompressed. **Default:** `true`.
154
+
155
+ **Returns:** {Dispatcher.DispatcherComposeInterceptor}
156
+
157
+ **Example**
158
+
159
+ ```js
160
+ import { Agent, interceptors } from 'undici'
161
+
162
+ const agent = new Agent().compose(
163
+ interceptors.decompress({
164
+ skipStatusCodes: [204, 304],
165
+ skipErrorResponses: false // decompress error bodies too
166
+ })
167
+ )
168
+ ```
169
+
170
+ ---
171
+
172
+ ## `interceptors.responseError([opts])`
173
+
174
+ Converts 4xx/5xx responses into thrown `ResponseError` instances, making it
175
+ easy to handle HTTP errors with a standard `try/catch` block.
176
+
177
+ The error body is automatically decoded for `application/json` and
178
+ `text/plain` responses. For JSON responses the body is parsed and exposed as
179
+ `error.body`.
180
+
181
+ **Parameters**
182
+
183
+ * `opts` {Object} (optional) — currently reserved for future use; may be
184
+ omitted.
185
+
186
+ **Returns:** {Dispatcher.DispatcherComposeInterceptor}
187
+
188
+ **Example**
189
+
190
+ ```js
191
+ import { Agent, interceptors, errors } from 'undici'
192
+
193
+ const agent = new Agent().compose(interceptors.responseError())
194
+
195
+ try {
196
+ await agent.request({ origin: 'https://example.com', path: '/not-found', method: 'GET' })
197
+ } catch (err) {
198
+ if (err instanceof errors.ResponseError) {
199
+ console.error(err.status, err.body)
200
+ }
201
+ }
202
+ ```
203
+
204
+ ---
205
+
206
+ ## `interceptors.dns([opts])`
207
+
208
+ Caches DNS lookups so that repeated requests to the same origin reuse the
209
+ resolved IP address instead of performing a fresh lookup every time. Supports
210
+ dual-stack (IPv4 + IPv6) and custom lookup/storage implementations.
211
+
212
+ **Parameters**
213
+
214
+ * `opts` {Object} (optional)
215
+ * `maxTTL` {number} Maximum number of milliseconds a DNS record is cached,
216
+ regardless of the TTL returned by the resolver. **Default:** `0`
217
+ (use the TTL from the DNS record).
218
+ * `maxItems` {number} Maximum number of origins to cache simultaneously.
219
+ Oldest entries are evicted when the limit is reached. **Default:**
220
+ `Infinity`.
221
+ * `dualStack` {boolean} When `true`, both IPv4 (`A`) and IPv6 (`AAAA`)
222
+ records are looked up and the interceptor picks between them based on
223
+ `affinity`. **Default:** `true`.
224
+ * `affinity` {4 | 6 | null} Preferred IP family when `dualStack` is
225
+ enabled. `null` lets the interceptor alternate between families.
226
+ **Default:** `null`.
227
+ * `lookup` {Function} (optional) Custom DNS resolution function with the
228
+ same signature as `node:dns`'s `lookup` callback form:
229
+ `(origin, options, callback) => void`.
230
+ * `pick` {Function} (optional) Custom record-selection function called with
231
+ `(origin, records, affinity)` to choose which resolved address to use.
232
+ * `storage` {DNSStorage} (optional) Custom storage backend. Must implement
233
+ `get`, `set`, `delete`, `full`, and `size`.
234
+
235
+ **`DNSStorage` interface**
236
+
237
+ ```ts
238
+ interface DNSStorage {
239
+ size: number
240
+ get(origin: string): DNSInterceptorOriginRecords | null
241
+ set(origin: string, records: DNSInterceptorOriginRecords | null, options: { ttl: number }): void
242
+ delete(origin: string): void
243
+ full(): boolean
244
+ }
245
+ ```
246
+
247
+ **Returns:** {Dispatcher.DispatcherComposeInterceptor}
248
+
249
+ **Example**
250
+
251
+ ```js
252
+ import { Agent, interceptors } from 'undici'
253
+
254
+ const agent = new Agent().compose(
255
+ interceptors.dns({
256
+ maxTTL: 60_000, // cache for at most 60 seconds
257
+ dualStack: true,
258
+ affinity: 4 // prefer IPv4
259
+ })
260
+ )
261
+ ```
262
+
263
+ ---
264
+
265
+ ## `interceptors.cache([opts])`
266
+
267
+ Caches HTTP responses according to RFC 9111 (HTTP Caching). See
268
+ [`CacheStore`](./CacheStore.md) for information on providing a custom
269
+ backing store.
270
+
271
+ **Parameters**
272
+
273
+ * `opts` {CacheHandler.CacheOptions} (optional) See the
274
+ [`CacheStore`](./CacheStore.md) documentation for accepted fields.
275
+
276
+ **Returns:** {Dispatcher.DispatcherComposeInterceptor}
277
+
278
+ **Example**
279
+
280
+ ```js
281
+ import { Agent, interceptors, cacheStores } from 'undici'
282
+
283
+ const agent = new Agent().compose(
284
+ interceptors.cache({ store: new cacheStores.MemoryCacheStore() })
285
+ )
286
+ ```
287
+
288
+ ---
289
+
290
+ ## `interceptors.deduplicate([opts])`
291
+
292
+ Deduplicates concurrent identical requests so that only one is sent over the
293
+ wire. All waiting callers receive the same response once the in-flight request
294
+ completes. Only safe HTTP methods (e.g. `GET`, `HEAD`) may be deduplicated.
295
+
296
+ **Parameters**
297
+
298
+ * `opts` {Object} (optional)
299
+ * `methods` {string[]} HTTP methods to deduplicate. Must be safe HTTP
300
+ methods (`GET`, `HEAD`, `OPTIONS`, `TRACE`). **Default:** `['GET']`.
301
+ * `skipHeaderNames` {string[]} Header names whose presence in a request
302
+ causes it to bypass deduplication entirely. Matching is
303
+ case-insensitive. **Default:** `[]`.
304
+ * `excludeHeaderNames` {string[]} Header names to exclude from the
305
+ deduplication key. Requests that differ only in these headers are still
306
+ deduplicated together. Useful for headers like `x-request-id` that vary
307
+ per request but should not prevent deduplication. Matching is
308
+ case-insensitive. **Default:** `[]`.
309
+ * `maxBufferSize` {number} Maximum number of bytes buffered per paused
310
+ waiting handler. If a waiting handler exceeds this threshold it is failed
311
+ with an `AbortError` to prevent unbounded memory growth. **Default:**
312
+ `5_242_880` (5 MiB).
313
+
314
+ **Returns:** {Dispatcher.DispatcherComposeInterceptor}
315
+
316
+ **Example**
317
+
318
+ ```js
319
+ import { Agent, interceptors } from 'undici'
320
+
321
+ const agent = new Agent().compose(
322
+ interceptors.deduplicate({
323
+ methods: ['GET', 'HEAD'],
324
+ excludeHeaderNames: ['x-request-id', 'x-trace-id'],
325
+ maxBufferSize: 2 * 1024 * 1024
326
+ })
327
+ )
328
+ ```
329
+
330
+ ---
331
+
332
+ ## Composing multiple interceptors
333
+
334
+ Interceptors are applied in the order they appear in the `compose()` call.
335
+ The first interceptor in the array wraps the outermost layer.
336
+
337
+ ```js
338
+ import { Agent, interceptors } from 'undici'
339
+
340
+ const agent = new Agent().compose([
341
+ interceptors.dns({ maxTTL: 30_000 }),
342
+ interceptors.retry({ maxRetries: 3 }),
343
+ interceptors.redirect({ maxRedirections: 5 }),
344
+ interceptors.decompress(),
345
+ interceptors.responseError()
346
+ ])
347
+ ```
348
+
349
+ In the example above the request flow is:
350
+
351
+ 1. **dns** — resolves and caches the target IP
352
+ 2. **retry** — retries the dispatch on transient failures
353
+ 3. **redirect** — follows any 3xx redirects
354
+ 4. **decompress** — decompresses the response body
355
+ 5. **responseError** — converts 4xx/5xx into thrown errors