undici 6.21.0 → 7.0.0-alpha.10

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 (156) hide show
  1. package/README.md +27 -46
  2. package/docs/docs/api/Agent.md +14 -17
  3. package/docs/docs/api/BalancedPool.md +16 -16
  4. package/docs/docs/api/CacheStore.md +131 -0
  5. package/docs/docs/api/Client.md +12 -14
  6. package/docs/docs/api/Debug.md +1 -1
  7. package/docs/docs/api/Dispatcher.md +98 -194
  8. package/docs/docs/api/EnvHttpProxyAgent.md +12 -13
  9. package/docs/docs/api/MockAgent.md +5 -3
  10. package/docs/docs/api/MockClient.md +5 -5
  11. package/docs/docs/api/MockPool.md +4 -3
  12. package/docs/docs/api/Pool.md +15 -16
  13. package/docs/docs/api/PoolStats.md +1 -1
  14. package/docs/docs/api/ProxyAgent.md +3 -3
  15. package/docs/docs/api/RedirectHandler.md +1 -1
  16. package/docs/docs/api/RetryAgent.md +1 -1
  17. package/docs/docs/api/RetryHandler.md +4 -4
  18. package/docs/docs/api/WebSocket.md +46 -4
  19. package/docs/docs/api/api-lifecycle.md +11 -11
  20. package/docs/docs/best-practices/mocking-request.md +2 -2
  21. package/docs/docs/best-practices/proxy.md +1 -1
  22. package/index.d.ts +1 -1
  23. package/index.js +23 -7
  24. package/lib/api/abort-signal.js +2 -0
  25. package/lib/api/api-connect.js +3 -1
  26. package/lib/api/api-pipeline.js +7 -6
  27. package/lib/api/api-request.js +33 -48
  28. package/lib/api/api-stream.js +39 -50
  29. package/lib/api/api-upgrade.js +5 -3
  30. package/lib/api/readable.js +235 -62
  31. package/lib/api/util.js +2 -0
  32. package/lib/cache/memory-cache-store.js +177 -0
  33. package/lib/cache/sqlite-cache-store.js +446 -0
  34. package/lib/core/constants.js +35 -10
  35. package/lib/core/diagnostics.js +122 -128
  36. package/lib/core/errors.js +6 -6
  37. package/lib/core/request.js +13 -11
  38. package/lib/core/symbols.js +2 -1
  39. package/lib/core/tree.js +9 -1
  40. package/lib/core/util.js +237 -49
  41. package/lib/dispatcher/agent.js +3 -17
  42. package/lib/dispatcher/balanced-pool.js +5 -8
  43. package/lib/dispatcher/client-h1.js +379 -134
  44. package/lib/dispatcher/client-h2.js +173 -107
  45. package/lib/dispatcher/client.js +19 -32
  46. package/lib/dispatcher/dispatcher-base.js +6 -35
  47. package/lib/dispatcher/dispatcher.js +7 -24
  48. package/lib/dispatcher/fixed-queue.js +91 -49
  49. package/lib/dispatcher/pool-stats.js +2 -0
  50. package/lib/dispatcher/pool.js +3 -6
  51. package/lib/dispatcher/proxy-agent.js +3 -6
  52. package/lib/handler/cache-handler.js +393 -0
  53. package/lib/handler/cache-revalidation-handler.js +124 -0
  54. package/lib/handler/decorator-handler.js +27 -0
  55. package/lib/handler/redirect-handler.js +54 -59
  56. package/lib/handler/retry-handler.js +77 -109
  57. package/lib/handler/unwrap-handler.js +96 -0
  58. package/lib/handler/wrap-handler.js +98 -0
  59. package/lib/interceptor/cache.js +350 -0
  60. package/lib/interceptor/dns.js +375 -0
  61. package/lib/interceptor/dump.js +2 -2
  62. package/lib/interceptor/redirect.js +11 -14
  63. package/lib/interceptor/response-error.js +18 -7
  64. package/lib/llhttp/constants.d.ts +97 -0
  65. package/lib/llhttp/constants.js +412 -192
  66. package/lib/llhttp/constants.js.map +1 -0
  67. package/lib/llhttp/llhttp-wasm.js +11 -1
  68. package/lib/llhttp/llhttp_simd-wasm.js +11 -1
  69. package/lib/llhttp/utils.d.ts +2 -0
  70. package/lib/llhttp/utils.js +9 -9
  71. package/lib/llhttp/utils.js.map +1 -0
  72. package/lib/mock/mock-agent.js +5 -8
  73. package/lib/mock/mock-client.js +9 -4
  74. package/lib/mock/mock-errors.js +3 -1
  75. package/lib/mock/mock-interceptor.js +8 -6
  76. package/lib/mock/mock-pool.js +9 -4
  77. package/lib/mock/mock-symbols.js +3 -1
  78. package/lib/mock/mock-utils.js +29 -5
  79. package/lib/util/cache.js +360 -0
  80. package/lib/web/cache/cache.js +24 -21
  81. package/lib/web/cache/cachestorage.js +1 -1
  82. package/lib/web/cookies/index.js +29 -14
  83. package/lib/web/cookies/parse.js +8 -3
  84. package/lib/web/eventsource/eventsource-stream.js +9 -8
  85. package/lib/web/eventsource/eventsource.js +10 -6
  86. package/lib/web/fetch/body.js +43 -41
  87. package/lib/web/fetch/constants.js +12 -5
  88. package/lib/web/fetch/data-url.js +3 -3
  89. package/lib/web/fetch/formdata-parser.js +72 -45
  90. package/lib/web/fetch/formdata.js +65 -54
  91. package/lib/web/fetch/headers.js +118 -86
  92. package/lib/web/fetch/index.js +58 -67
  93. package/lib/web/fetch/request.js +136 -77
  94. package/lib/web/fetch/response.js +87 -56
  95. package/lib/web/fetch/util.js +259 -109
  96. package/lib/web/fetch/webidl.js +113 -68
  97. package/lib/web/websocket/connection.js +76 -147
  98. package/lib/web/websocket/constants.js +70 -10
  99. package/lib/web/websocket/events.js +4 -2
  100. package/lib/web/websocket/frame.js +45 -3
  101. package/lib/web/websocket/receiver.js +29 -33
  102. package/lib/web/websocket/sender.js +18 -13
  103. package/lib/web/websocket/stream/websocketerror.js +83 -0
  104. package/lib/web/websocket/stream/websocketstream.js +485 -0
  105. package/lib/web/websocket/util.js +128 -77
  106. package/lib/web/websocket/websocket.js +234 -135
  107. package/package.json +24 -36
  108. package/scripts/strip-comments.js +3 -1
  109. package/types/agent.d.ts +7 -7
  110. package/types/api.d.ts +24 -24
  111. package/types/balanced-pool.d.ts +11 -11
  112. package/types/cache-interceptor.d.ts +172 -0
  113. package/types/client.d.ts +11 -12
  114. package/types/cookies.d.ts +2 -0
  115. package/types/diagnostics-channel.d.ts +10 -10
  116. package/types/dispatcher.d.ts +113 -90
  117. package/types/env-http-proxy-agent.d.ts +2 -2
  118. package/types/errors.d.ts +53 -47
  119. package/types/fetch.d.ts +17 -16
  120. package/types/formdata.d.ts +7 -7
  121. package/types/global-dispatcher.d.ts +4 -4
  122. package/types/global-origin.d.ts +5 -5
  123. package/types/handlers.d.ts +7 -7
  124. package/types/header.d.ts +157 -1
  125. package/types/index.d.ts +44 -46
  126. package/types/interceptors.d.ts +25 -8
  127. package/types/mock-agent.d.ts +21 -18
  128. package/types/mock-client.d.ts +4 -4
  129. package/types/mock-errors.d.ts +3 -3
  130. package/types/mock-interceptor.d.ts +19 -19
  131. package/types/mock-pool.d.ts +4 -4
  132. package/types/patch.d.ts +0 -4
  133. package/types/pool-stats.d.ts +8 -8
  134. package/types/pool.d.ts +12 -12
  135. package/types/proxy-agent.d.ts +4 -4
  136. package/types/readable.d.ts +18 -15
  137. package/types/retry-agent.d.ts +1 -1
  138. package/types/retry-handler.d.ts +10 -10
  139. package/types/util.d.ts +3 -3
  140. package/types/utility.d.ts +7 -0
  141. package/types/webidl.d.ts +44 -6
  142. package/types/websocket.d.ts +34 -1
  143. package/docs/docs/api/DispatchInterceptor.md +0 -60
  144. package/lib/interceptor/redirect-interceptor.js +0 -21
  145. package/lib/mock/pluralizer.js +0 -29
  146. package/lib/web/cache/symbols.js +0 -5
  147. package/lib/web/fetch/file.js +0 -126
  148. package/lib/web/fetch/symbols.js +0 -9
  149. package/lib/web/fileapi/encoding.js +0 -290
  150. package/lib/web/fileapi/filereader.js +0 -344
  151. package/lib/web/fileapi/progressevent.js +0 -78
  152. package/lib/web/fileapi/symbols.js +0 -10
  153. package/lib/web/fileapi/util.js +0 -391
  154. package/lib/web/websocket/symbols.js +0 -12
  155. package/types/file.d.ts +0 -39
  156. package/types/filereader.d.ts +0 -54
@@ -1,5 +1,8 @@
1
1
  'use strict'
2
2
  const EventEmitter = require('node:events')
3
+ const WrapHandler = require('../handler/wrap-handler')
4
+
5
+ const wrapInterceptor = (dispatch) => (opts, handler) => dispatch(opts, WrapHandler.wrap(handler))
3
6
 
4
7
  class Dispatcher extends EventEmitter {
5
8
  dispatch () {
@@ -29,36 +32,16 @@ class Dispatcher extends EventEmitter {
29
32
  }
30
33
 
31
34
  dispatch = interceptor(dispatch)
35
+ dispatch = wrapInterceptor(dispatch)
32
36
 
33
37
  if (dispatch == null || typeof dispatch !== 'function' || dispatch.length !== 2) {
34
38
  throw new TypeError('invalid interceptor')
35
39
  }
36
40
  }
37
41
 
38
- return new ComposedDispatcher(this, dispatch)
39
- }
40
- }
41
-
42
- class ComposedDispatcher extends Dispatcher {
43
- #dispatcher = null
44
- #dispatch = null
45
-
46
- constructor (dispatcher, dispatch) {
47
- super()
48
- this.#dispatcher = dispatcher
49
- this.#dispatch = dispatch
50
- }
51
-
52
- dispatch (...args) {
53
- this.#dispatch(...args)
54
- }
55
-
56
- close (...args) {
57
- return this.#dispatcher.close(...args)
58
- }
59
-
60
- destroy (...args) {
61
- return this.#dispatcher.destroy(...args)
42
+ return new Proxy(this, {
43
+ get: (target, key) => key === 'dispatch' ? dispatch : target[key]
44
+ })
62
45
  }
63
46
  }
64
47
 
@@ -1,12 +1,10 @@
1
- /* eslint-disable */
2
-
3
1
  'use strict'
4
2
 
5
3
  // Extracted from node/lib/internal/fixed_queue.js
6
4
 
7
5
  // Currently optimal queue size, tested on V8 6.0 - 6.6. Must be power of two.
8
- const kSize = 2048;
9
- const kMask = kSize - 1;
6
+ const kSize = 2048
7
+ const kMask = kSize - 1
10
8
 
11
9
  // The FixedQueue is implemented as a singly-linked list of fixed-size
12
10
  // circular buffers. It looks something like this:
@@ -17,18 +15,18 @@ const kMask = kSize - 1;
17
15
  // +-----------+ <-----\ +-----------+ <------\ +-----------+
18
16
  // | [null] | \----- | next | \------- | next |
19
17
  // +-----------+ +-----------+ +-----------+
20
- // | item | <-- bottom | item | <-- bottom | [empty] |
21
- // | item | | item | | [empty] |
22
- // | item | | item | | [empty] |
23
- // | item | | item | | [empty] |
18
+ // | item | <-- bottom | item | <-- bottom | undefined |
19
+ // | item | | item | | undefined |
20
+ // | item | | item | | undefined |
21
+ // | item | | item | | undefined |
24
22
  // | item | | item | bottom --> | item |
25
23
  // | item | | item | | item |
26
24
  // | ... | | ... | | ... |
27
25
  // | item | | item | | item |
28
26
  // | item | | item | | item |
29
- // | [empty] | <-- top | item | | item |
30
- // | [empty] | | item | | item |
31
- // | [empty] | | [empty] | <-- top top --> | [empty] |
27
+ // | undefined | <-- top | item | | item |
28
+ // | undefined | | item | | item |
29
+ // | undefined | | undefined | <-- top top --> | undefined |
32
30
  // +-----------+ +-----------+ +-----------+
33
31
  //
34
32
  // Or, if there is only one circular buffer, it looks something
@@ -40,12 +38,12 @@ const kMask = kSize - 1;
40
38
  // +-----------+ +-----------+
41
39
  // | [null] | | [null] |
42
40
  // +-----------+ +-----------+
43
- // | [empty] | | item |
44
- // | [empty] | | item |
45
- // | item | <-- bottom top --> | [empty] |
46
- // | item | | [empty] |
47
- // | [empty] | <-- top bottom --> | item |
48
- // | [empty] | | item |
41
+ // | undefined | | item |
42
+ // | undefined | | item |
43
+ // | item | <-- bottom top --> | undefined |
44
+ // | item | | undefined |
45
+ // | undefined | <-- top bottom --> | item |
46
+ // | undefined | | item |
49
47
  // +-----------+ +-----------+
50
48
  //
51
49
  // Adding a value means moving `top` forward by one, removing means
@@ -56,62 +54,106 @@ const kMask = kSize - 1;
56
54
  // `top + 1 === bottom` it's full. This wastes a single space of storage
57
55
  // but allows much quicker checks.
58
56
 
57
+ /**
58
+ * @type {FixedCircularBuffer}
59
+ * @template T
60
+ */
59
61
  class FixedCircularBuffer {
60
- constructor() {
61
- this.bottom = 0;
62
- this.top = 0;
63
- this.list = new Array(kSize);
64
- this.next = null;
62
+ constructor () {
63
+ /**
64
+ * @type {number}
65
+ */
66
+ this.bottom = 0
67
+ /**
68
+ * @type {number}
69
+ */
70
+ this.top = 0
71
+ /**
72
+ * @type {Array<T|undefined>}
73
+ */
74
+ this.list = new Array(kSize).fill(undefined)
75
+ /**
76
+ * @type {T|null}
77
+ */
78
+ this.next = null
65
79
  }
66
80
 
67
- isEmpty() {
68
- return this.top === this.bottom;
81
+ /**
82
+ * @returns {boolean}
83
+ */
84
+ isEmpty () {
85
+ return this.top === this.bottom
69
86
  }
70
87
 
71
- isFull() {
72
- return ((this.top + 1) & kMask) === this.bottom;
88
+ /**
89
+ * @returns {boolean}
90
+ */
91
+ isFull () {
92
+ return ((this.top + 1) & kMask) === this.bottom
73
93
  }
74
94
 
75
- push(data) {
76
- this.list[this.top] = data;
77
- this.top = (this.top + 1) & kMask;
95
+ /**
96
+ * @param {T} data
97
+ * @returns {void}
98
+ */
99
+ push (data) {
100
+ this.list[this.top] = data
101
+ this.top = (this.top + 1) & kMask
78
102
  }
79
103
 
80
- shift() {
81
- const nextItem = this.list[this.bottom];
82
- if (nextItem === undefined)
83
- return null;
84
- this.list[this.bottom] = undefined;
85
- this.bottom = (this.bottom + 1) & kMask;
86
- return nextItem;
104
+ /**
105
+ * @returns {T|null}
106
+ */
107
+ shift () {
108
+ const nextItem = this.list[this.bottom]
109
+ if (nextItem === undefined) { return null }
110
+ this.list[this.bottom] = undefined
111
+ this.bottom = (this.bottom + 1) & kMask
112
+ return nextItem
87
113
  }
88
114
  }
89
115
 
116
+ /**
117
+ * @template T
118
+ */
90
119
  module.exports = class FixedQueue {
91
- constructor() {
92
- this.head = this.tail = new FixedCircularBuffer();
120
+ constructor () {
121
+ /**
122
+ * @type {FixedCircularBuffer<T>}
123
+ */
124
+ this.head = this.tail = new FixedCircularBuffer()
93
125
  }
94
126
 
95
- isEmpty() {
96
- return this.head.isEmpty();
127
+ /**
128
+ * @returns {boolean}
129
+ */
130
+ isEmpty () {
131
+ return this.head.isEmpty()
97
132
  }
98
133
 
99
- push(data) {
134
+ /**
135
+ * @param {T} data
136
+ */
137
+ push (data) {
100
138
  if (this.head.isFull()) {
101
139
  // Head is full: Creates a new queue, sets the old queue's `.next` to it,
102
140
  // and sets it as the new main queue.
103
- this.head = this.head.next = new FixedCircularBuffer();
141
+ this.head = this.head.next = new FixedCircularBuffer()
104
142
  }
105
- this.head.push(data);
143
+ this.head.push(data)
106
144
  }
107
145
 
108
- shift() {
109
- const tail = this.tail;
110
- const next = tail.shift();
146
+ /**
147
+ * @returns {T|null}
148
+ */
149
+ shift () {
150
+ const tail = this.tail
151
+ const next = tail.shift()
111
152
  if (tail.isEmpty() && tail.next !== null) {
112
153
  // If there is another queue, it forms the new tail.
113
- this.tail = tail.next;
154
+ this.tail = tail.next
155
+ tail.next = null
114
156
  }
115
- return next;
157
+ return next
116
158
  }
117
- };
159
+ }
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const { kFree, kConnected, kPending, kQueued, kRunning, kSize } = require('../core/symbols')
2
4
  const kPool = Symbol('pool')
3
5
 
@@ -12,7 +12,7 @@ const {
12
12
  InvalidArgumentError
13
13
  } = require('../core/errors')
14
14
  const util = require('../core/util')
15
- const { kUrl, kInterceptors } = require('../core/symbols')
15
+ const { kUrl } = require('../core/symbols')
16
16
  const buildConnector = require('../core/connect')
17
17
 
18
18
  const kOptions = Symbol('options')
@@ -37,8 +37,6 @@ class Pool extends PoolBase {
37
37
  allowH2,
38
38
  ...options
39
39
  } = {}) {
40
- super()
41
-
42
40
  if (connections != null && (!Number.isFinite(connections) || connections < 0)) {
43
41
  throw new InvalidArgumentError('invalid connections')
44
42
  }
@@ -51,6 +49,8 @@ class Pool extends PoolBase {
51
49
  throw new InvalidArgumentError('connect must be a function or an object')
52
50
  }
53
51
 
52
+ super()
53
+
54
54
  if (typeof connect !== 'function') {
55
55
  connect = buildConnector({
56
56
  ...tls,
@@ -63,9 +63,6 @@ class Pool extends PoolBase {
63
63
  })
64
64
  }
65
65
 
66
- this[kInterceptors] = options.interceptors?.Pool && Array.isArray(options.interceptors.Pool)
67
- ? options.interceptors.Pool
68
- : []
69
66
  this[kConnections] = connections || null
70
67
  this[kUrl] = util.parseOrigin(origin)
71
68
  this[kOptions] = { ...util.deepClone(options), connect, allowH2 }
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const { kProxy, kClose, kDestroy, kInterceptors } = require('../core/symbols')
3
+ const { kProxy, kClose, kDestroy } = require('../core/symbols')
4
4
  const { URL } = require('node:url')
5
5
  const Agent = require('./agent')
6
6
  const Pool = require('./pool')
@@ -27,8 +27,6 @@ const noop = () => {}
27
27
 
28
28
  class ProxyAgent extends DispatcherBase {
29
29
  constructor (opts) {
30
- super()
31
-
32
30
  if (!opts || (typeof opts === 'object' && !(opts instanceof URL) && !opts.uri)) {
33
31
  throw new InvalidArgumentError('Proxy uri is mandatory')
34
32
  }
@@ -38,13 +36,12 @@ class ProxyAgent extends DispatcherBase {
38
36
  throw new InvalidArgumentError('Proxy opts.clientFactory must be a function.')
39
37
  }
40
38
 
39
+ super()
40
+
41
41
  const url = this.#getUrl(opts)
42
42
  const { href, origin, port, protocol, username, password, hostname: proxyHostname } = url
43
43
 
44
44
  this[kProxy] = { uri: href, protocol }
45
- this[kInterceptors] = opts.interceptors?.ProxyAgent && Array.isArray(opts.interceptors.ProxyAgent)
46
- ? opts.interceptors.ProxyAgent
47
- : []
48
45
  this[kRequestTls] = opts.requestTls
49
46
  this[kProxyTls] = opts.proxyTls
50
47
  this[kProxyHeaders] = opts.headers || {}