undici 7.11.0 → 7.13.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 (47) hide show
  1. package/README.md +15 -11
  2. package/docs/docs/api/DiagnosticsChannel.md +7 -4
  3. package/docs/docs/api/Dispatcher.md +2 -2
  4. package/docs/docs/api/ProxyAgent.md +1 -1
  5. package/docs/docs/api/SnapshotAgent.md +616 -0
  6. package/docs/docs/api/WebSocket.md +27 -0
  7. package/index.js +5 -1
  8. package/lib/api/readable.js +49 -29
  9. package/lib/core/request.js +6 -1
  10. package/lib/core/tree.js +1 -1
  11. package/lib/core/util.js +0 -1
  12. package/lib/dispatcher/client-h1.js +8 -17
  13. package/lib/dispatcher/proxy-agent.js +67 -71
  14. package/lib/handler/cache-handler.js +4 -1
  15. package/lib/handler/redirect-handler.js +12 -2
  16. package/lib/interceptor/cache.js +2 -2
  17. package/lib/interceptor/dump.js +2 -1
  18. package/lib/interceptor/redirect.js +1 -1
  19. package/lib/mock/mock-agent.js +10 -4
  20. package/lib/mock/snapshot-agent.js +333 -0
  21. package/lib/mock/snapshot-recorder.js +517 -0
  22. package/lib/util/cache.js +1 -1
  23. package/lib/util/promise.js +28 -0
  24. package/lib/web/cache/cache.js +10 -8
  25. package/lib/web/fetch/body.js +35 -24
  26. package/lib/web/fetch/formdata-parser.js +0 -3
  27. package/lib/web/fetch/formdata.js +0 -4
  28. package/lib/web/fetch/index.js +221 -225
  29. package/lib/web/fetch/request.js +15 -7
  30. package/lib/web/fetch/response.js +5 -3
  31. package/lib/web/fetch/util.js +21 -23
  32. package/lib/web/webidl/index.js +1 -1
  33. package/lib/web/websocket/connection.js +0 -9
  34. package/lib/web/websocket/receiver.js +2 -12
  35. package/lib/web/websocket/stream/websocketstream.js +7 -4
  36. package/lib/web/websocket/websocket.js +57 -1
  37. package/package.json +2 -2
  38. package/types/agent.d.ts +0 -4
  39. package/types/client.d.ts +0 -2
  40. package/types/dispatcher.d.ts +0 -6
  41. package/types/h2c-client.d.ts +0 -2
  42. package/types/index.d.ts +3 -1
  43. package/types/mock-interceptor.d.ts +0 -1
  44. package/types/snapshot-agent.d.ts +107 -0
  45. package/types/webidl.d.ts +10 -0
  46. package/types/websocket.d.ts +2 -0
  47. package/lib/web/fetch/dispatcher-weakref.js +0 -5
@@ -924,17 +924,6 @@ function sameOrigin (A, B) {
924
924
  return false
925
925
  }
926
926
 
927
- function createDeferredPromise () {
928
- let res
929
- let rej
930
- const promise = new Promise((resolve, reject) => {
931
- res = resolve
932
- rej = reject
933
- })
934
-
935
- return { promise, resolve: res, reject: rej }
936
- }
937
-
938
927
  function isAborted (fetchParams) {
939
928
  return fetchParams.controller.state === 'aborted'
940
929
  }
@@ -1177,6 +1166,11 @@ function iteratorMixin (name, object, kInternalIterator, keyIndex = 0, valueInde
1177
1166
  }
1178
1167
 
1179
1168
  /**
1169
+ * @param {import('./body').ExtractBodyResult} body
1170
+ * @param {(bytes: Uint8Array) => void} processBody
1171
+ * @param {(error: Error) => void} processBodyError
1172
+ * @returns {void}
1173
+ *
1180
1174
  * @see https://fetch.spec.whatwg.org/#body-fully-read
1181
1175
  */
1182
1176
  function fullyReadBody (body, processBody, processBodyError) {
@@ -1191,20 +1185,17 @@ function fullyReadBody (body, processBody, processBodyError) {
1191
1185
  // with taskDestination.
1192
1186
  const errorSteps = processBodyError
1193
1187
 
1188
+ try {
1194
1189
  // 4. Let reader be the result of getting a reader for body’s stream.
1195
1190
  // If that threw an exception, then run errorSteps with that
1196
1191
  // exception and return.
1197
- let reader
1192
+ const reader = body.stream.getReader()
1198
1193
 
1199
- try {
1200
- reader = body.stream.getReader()
1194
+ // 5. Read all bytes from reader, given successSteps and errorSteps.
1195
+ readAllBytes(reader, successSteps, errorSteps)
1201
1196
  } catch (e) {
1202
1197
  errorSteps(e)
1203
- return
1204
1198
  }
1205
-
1206
- // 5. Read all bytes from reader, given successSteps and errorSteps.
1207
- readAllBytes(reader, successSteps, errorSteps)
1208
1199
  }
1209
1200
 
1210
1201
  /**
@@ -1241,15 +1232,16 @@ function isomorphicEncode (input) {
1241
1232
  /**
1242
1233
  * @see https://streams.spec.whatwg.org/#readablestreamdefaultreader-read-all-bytes
1243
1234
  * @see https://streams.spec.whatwg.org/#read-loop
1244
- * @param {ReadableStreamDefaultReader} reader
1235
+ * @param {ReadableStream<Uint8Array<ArrayBuffer>>} reader
1245
1236
  * @param {(bytes: Uint8Array) => void} successSteps
1246
1237
  * @param {(error: Error) => void} failureSteps
1238
+ * @returns {Promise<void>}
1247
1239
  */
1248
1240
  async function readAllBytes (reader, successSteps, failureSteps) {
1249
- const bytes = []
1250
- let byteLength = 0
1251
-
1252
1241
  try {
1242
+ const bytes = []
1243
+ let byteLength = 0
1244
+
1253
1245
  do {
1254
1246
  const { done, value: chunk } = await reader.read()
1255
1247
 
@@ -1324,10 +1316,17 @@ function urlIsHttpHttpsScheme (url) {
1324
1316
  return protocol === 'http:' || protocol === 'https:'
1325
1317
  }
1326
1318
 
1319
+ /**
1320
+ * @typedef {Object} RangeHeaderValue
1321
+ * @property {number|null} rangeStartValue
1322
+ * @property {number|null} rangeEndValue
1323
+ */
1324
+
1327
1325
  /**
1328
1326
  * @see https://fetch.spec.whatwg.org/#simple-range-header-value
1329
1327
  * @param {string} value
1330
1328
  * @param {boolean} allowWhitespace
1329
+ * @return {RangeHeaderValue|'failure'}
1331
1330
  */
1332
1331
  function simpleRangeHeaderValue (value, allowWhitespace) {
1333
1332
  // 1. Let data be the isomorphic decoding of value.
@@ -1732,7 +1731,6 @@ module.exports = {
1732
1731
  isAborted,
1733
1732
  isCancelled,
1734
1733
  isValidEncodedURL,
1735
- createDeferredPromise,
1736
1734
  ReadableStreamFrom,
1737
1735
  tryUpgradeRequestToAPotentiallyTrustworthyURL,
1738
1736
  clampAndCoarsenConnectionTimingInfo,
@@ -509,7 +509,7 @@ webidl.is.USVString = function (value) {
509
509
  webidl.is.ReadableStream = webidl.util.MakeTypeAssertion(ReadableStream)
510
510
  webidl.is.Blob = webidl.util.MakeTypeAssertion(Blob)
511
511
  webidl.is.URLSearchParams = webidl.util.MakeTypeAssertion(URLSearchParams)
512
- webidl.is.File = webidl.util.MakeTypeAssertion(globalThis.File ?? require('node:buffer').File)
512
+ webidl.is.File = webidl.util.MakeTypeAssertion(File)
513
513
  webidl.is.URL = webidl.util.MakeTypeAssertion(URL)
514
514
  webidl.is.AbortSignal = webidl.util.MakeTypeAssertion(AbortSignal)
515
515
  webidl.is.MessagePort = webidl.util.MakeTypeAssertion(MessagePort)
@@ -2,7 +2,6 @@
2
2
 
3
3
  const { uid, states, sentCloseFrameState, emptyBuffer, opcodes } = require('./constants')
4
4
  const { parseExtensions, isClosed, isClosing, isEstablished, validateCloseCodeAndReason } = require('./util')
5
- const { channels } = require('../../core/diagnostics')
6
5
  const { makeRequest } = require('../fetch/request')
7
6
  const { fetching } = require('../fetch/index')
8
7
  const { Headers, getHeadersList } = require('../fetch/headers')
@@ -200,14 +199,6 @@ function establishWebSocketConnection (url, protocols, client, handler, options)
200
199
  response.socket.on('close', handler.onSocketClose)
201
200
  response.socket.on('error', handler.onSocketError)
202
201
 
203
- if (channels.open.hasSubscribers) {
204
- channels.open.publish({
205
- address: response.socket.address(),
206
- protocol: secProtocol,
207
- extensions: secExtension
208
- })
209
- }
210
-
211
202
  handler.wasEverConnected = true
212
203
  handler.onConnectionEstablished(response, extensions)
213
204
  }
@@ -3,7 +3,6 @@
3
3
  const { Writable } = require('node:stream')
4
4
  const assert = require('node:assert')
5
5
  const { parserStates, opcodes, states, emptyBuffer, sentCloseFrameState } = require('./constants')
6
- const { channels } = require('../../core/diagnostics')
7
6
  const {
8
7
  isValidStatusCode,
9
8
  isValidOpcode,
@@ -423,22 +422,13 @@ class ByteParser extends Writable {
423
422
 
424
423
  this.#handler.socket.write(frame.createFrame(opcodes.PONG))
425
424
 
426
- if (channels.ping.hasSubscribers) {
427
- channels.ping.publish({
428
- payload: body
429
- })
430
- }
425
+ this.#handler.onPing(body)
431
426
  }
432
427
  } else if (opcode === opcodes.PONG) {
433
428
  // A Pong frame MAY be sent unsolicited. This serves as a
434
429
  // unidirectional heartbeat. A response to an unsolicited Pong frame is
435
430
  // not expected.
436
-
437
- if (channels.pong.hasSubscribers) {
438
- channels.pong.publish({
439
- payload: body
440
- })
441
- }
431
+ this.#handler.onPong(body)
442
432
  }
443
433
 
444
434
  return true
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
- const { createDeferredPromise, environmentSettingsObject } = require('../../fetch/util')
3
+ const { createDeferredPromise } = require('../../../util/promise')
4
+ const { environmentSettingsObject } = require('../../fetch/util')
4
5
  const { states, opcodes, sentCloseFrameState } = require('../constants')
5
6
  const { webidl } = require('../../webidl')
6
7
  const { getURLRecord, isValidSubprotocol, isEstablished, utf8Decode } = require('../util')
@@ -21,11 +22,11 @@ class WebSocketStream {
21
22
  #url
22
23
 
23
24
  // Each WebSocketStream object has an associated opened promise , which is a promise.
24
- /** @type {ReturnType<typeof createDeferredPromise>} */
25
+ /** @type {import('../../../util/promise').DeferredPromise} */
25
26
  #openedPromise
26
27
 
27
28
  // Each WebSocketStream object has an associated closed promise , which is a promise.
28
- /** @type {ReturnType<typeof createDeferredPromise>} */
29
+ /** @type {import('../../../util/promise').DeferredPromise} */
29
30
  #closedPromise
30
31
 
31
32
  // Each WebSocketStream object has an associated readable stream , which is a ReadableStream .
@@ -64,6 +65,8 @@ class WebSocketStream {
64
65
  this.#handler.socket.destroy()
65
66
  },
66
67
  onSocketClose: () => this.#onSocketClose(),
68
+ onPing: () => {},
69
+ onPong: () => {},
67
70
 
68
71
  readyState: states.CONNECTING,
69
72
  socket: null,
@@ -388,7 +391,7 @@ class WebSocketStream {
388
391
  // 6. If the connection was closed cleanly ,
389
392
  if (wasClean) {
390
393
  // 6.1. Close stream ’s readable stream .
391
- this.#readableStream.cancel().catch(() => {})
394
+ this.#readableStreamController.close()
392
395
 
393
396
  // 6.2. Error stream ’s writable stream with an " InvalidStateError " DOMException indicating that a closed WebSocketStream cannot be written to.
394
397
  if (!this.#writableStream.locked) {
@@ -8,6 +8,7 @@ const {
8
8
  isConnecting,
9
9
  isEstablished,
10
10
  isClosing,
11
+ isClosed,
11
12
  isValidSubprotocol,
12
13
  fireEvent,
13
14
  utf8Decode,
@@ -21,6 +22,7 @@ const { getGlobalDispatcher } = require('../../global')
21
22
  const { types } = require('node:util')
22
23
  const { ErrorEvent, CloseEvent, createFastMessageEvent } = require('./events')
23
24
  const { SendQueue } = require('./sender')
25
+ const { WebsocketFrameSend } = require('./frame')
24
26
  const { channels } = require('../../core/diagnostics')
25
27
 
26
28
  /**
@@ -33,6 +35,8 @@ const { channels } = require('../../core/diagnostics')
33
35
  * @property {(chunk: Buffer) => void} onSocketData
34
36
  * @property {(err: Error) => void} onSocketError
35
37
  * @property {() => void} onSocketClose
38
+ * @property {(body: Buffer) => void} onPing
39
+ * @property {(body: Buffer) => void} onPong
36
40
  *
37
41
  * @property {number} readyState
38
42
  * @property {import('stream').Duplex} socket
@@ -79,6 +83,22 @@ class WebSocket extends EventTarget {
79
83
  this.#handler.socket.destroy()
80
84
  },
81
85
  onSocketClose: () => this.#onSocketClose(),
86
+ onPing: (body) => {
87
+ if (channels.ping.hasSubscribers) {
88
+ channels.ping.publish({
89
+ payload: body,
90
+ websocket: this
91
+ })
92
+ }
93
+ },
94
+ onPong: (body) => {
95
+ if (channels.pong.hasSubscribers) {
96
+ channels.pong.publish({
97
+ payload: body,
98
+ websocket: this
99
+ })
100
+ }
101
+ },
82
102
 
83
103
  readyState: states.CONNECTING,
84
104
  socket: null,
@@ -460,6 +480,15 @@ class WebSocket extends EventTarget {
460
480
 
461
481
  // 4. Fire an event named open at the WebSocket object.
462
482
  fireEvent('open', this)
483
+
484
+ if (channels.open.hasSubscribers) {
485
+ channels.open.publish({
486
+ address: response.socket.address(),
487
+ protocol: this.#protocol,
488
+ extensions: this.#extensions,
489
+ websocket: this
490
+ })
491
+ }
463
492
  }
464
493
 
465
494
  #onFail (code, reason, cause) {
@@ -586,8 +615,34 @@ class WebSocket extends EventTarget {
586
615
  })
587
616
  }
588
617
  }
618
+
619
+ /**
620
+ * @param {WebSocket} ws
621
+ * @param {Buffer|undefined} buffer
622
+ */
623
+ static ping (ws, buffer) {
624
+ if (Buffer.isBuffer(buffer)) {
625
+ if (buffer.length > 125) {
626
+ throw new TypeError('A PING frame cannot have a body larger than 125 bytes.')
627
+ }
628
+ } else if (buffer !== undefined) {
629
+ throw new TypeError('Expected buffer payload')
630
+ }
631
+
632
+ // An endpoint MAY send a Ping frame any time after the connection is
633
+ // established and before the connection is closed.
634
+ const readyState = ws.#handler.readyState
635
+
636
+ if (isEstablished(readyState) && !isClosing(readyState) && !isClosed(readyState)) {
637
+ const frame = new WebsocketFrameSend(buffer)
638
+ ws.#handler.socket.write(frame.createFrame(opcodes.PING))
639
+ }
640
+ }
589
641
  }
590
642
 
643
+ const { ping } = WebSocket
644
+ Reflect.deleteProperty(WebSocket, 'ping')
645
+
591
646
  // https://websockets.spec.whatwg.org/#dom-websocket-connecting
592
647
  WebSocket.CONNECTING = WebSocket.prototype.CONNECTING = states.CONNECTING
593
648
  // https://websockets.spec.whatwg.org/#dom-websocket-open
@@ -682,5 +737,6 @@ webidl.converters.WebSocketSendData = function (V) {
682
737
  }
683
738
 
684
739
  module.exports = {
685
- WebSocket
740
+ WebSocket,
741
+ ping
686
742
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "undici",
3
- "version": "7.11.0",
3
+ "version": "7.13.0",
4
4
  "description": "An HTTP/1.1 client, written from scratch for Node.js",
5
5
  "homepage": "https://undici.nodejs.org",
6
6
  "bugs": {
@@ -91,7 +91,7 @@
91
91
  "test:tdd:node-test": "borp -p \"test/node-test/**/*.js\" -w",
92
92
  "test:typescript": "tsd && tsc test/imports/undici-import.ts --typeRoots ./types --noEmit && tsc ./types/*.d.ts --noEmit --typeRoots ./types",
93
93
  "test:webidl": "borp -p \"test/webidl/*.js\"",
94
- "test:websocket": "borp -p \"test/websocket/*.js\"",
94
+ "test:websocket": "borp -p \"test/websocket/**/*.js\"",
95
95
  "test:websocket:autobahn": "node test/autobahn/client.js",
96
96
  "test:websocket:autobahn:report": "node test/autobahn/report.js",
97
97
  "test:wpt": "node test/wpt/start-fetch.mjs && node test/wpt/start-mimesniff.mjs && node test/wpt/start-xhr.mjs && node test/wpt/start-websockets.mjs && node test/wpt/start-cacheStorage.mjs && node test/wpt/start-eventsource.mjs",
package/types/agent.d.ts CHANGED
@@ -22,14 +22,10 @@ declare namespace Agent {
22
22
  export interface Options extends Pool.Options {
23
23
  /** Default: `(origin, opts) => new Pool(origin, opts)`. */
24
24
  factory?(origin: string | URL, opts: Object): Dispatcher;
25
- /** Integer. Default: `0` */
26
- maxRedirections?: number;
27
25
 
28
26
  interceptors?: { Agent?: readonly Dispatcher.DispatchInterceptor[] } & Pool.Options['interceptors']
29
27
  }
30
28
 
31
29
  export interface DispatchOptions extends Dispatcher.DispatchOptions {
32
- /** Integer. */
33
- maxRedirections?: number;
34
30
  }
35
31
  }
package/types/client.d.ts CHANGED
@@ -71,8 +71,6 @@ export declare namespace Client {
71
71
  /** TODO */
72
72
  maxCachedSessions?: number;
73
73
  /** TODO */
74
- maxRedirections?: number;
75
- /** TODO */
76
74
  connect?: Partial<buildConnector.BuildOptions> | buildConnector.connector;
77
75
  /** TODO */
78
76
  maxRequestsPerClient?: number;
@@ -135,8 +135,6 @@ declare namespace Dispatcher {
135
135
  signal?: AbortSignal | EventEmitter | null;
136
136
  /** This argument parameter is passed through to `ConnectData` */
137
137
  opaque?: TOpaque;
138
- /** Default: 0 */
139
- maxRedirections?: number;
140
138
  /** Default: false */
141
139
  redirectionLimitReached?: boolean;
142
140
  /** Default: `null` */
@@ -147,8 +145,6 @@ declare namespace Dispatcher {
147
145
  opaque?: TOpaque;
148
146
  /** Default: `null` */
149
147
  signal?: AbortSignal | EventEmitter | null;
150
- /** Default: 0 */
151
- maxRedirections?: number;
152
148
  /** Default: false */
153
149
  redirectionLimitReached?: boolean;
154
150
  /** Default: `null` */
@@ -172,8 +168,6 @@ declare namespace Dispatcher {
172
168
  protocol?: string;
173
169
  /** Default: `null` */
174
170
  signal?: AbortSignal | EventEmitter | null;
175
- /** Default: 0 */
176
- maxRedirections?: number;
177
171
  /** Default: false */
178
172
  redirectionLimitReached?: boolean;
179
173
  /** Default: `null` */
@@ -51,8 +51,6 @@ export declare namespace H2CClient {
51
51
  /** TODO */
52
52
  maxCachedSessions?: number;
53
53
  /** TODO */
54
- maxRedirections?: number;
55
- /** TODO */
56
54
  connect?: Omit<Partial<buildConnector.BuildOptions>, 'allowH2'> | buildConnector.connector;
57
55
  /** TODO */
58
56
  maxRequestsPerClient?: number;
package/types/index.d.ts CHANGED
@@ -13,6 +13,7 @@ import Agent from './agent'
13
13
  import MockClient from './mock-client'
14
14
  import MockPool from './mock-pool'
15
15
  import MockAgent from './mock-agent'
16
+ import { SnapshotAgent } from './snapshot-agent'
16
17
  import { MockCallHistory, MockCallHistoryLog } from './mock-call-history'
17
18
  import mockErrors from './mock-errors'
18
19
  import ProxyAgent from './proxy-agent'
@@ -33,7 +34,7 @@ export * from './content-type'
33
34
  export * from './cache'
34
35
  export { Interceptable } from './mock-interceptor'
35
36
 
36
- export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, setGlobalOrigin, getGlobalOrigin, interceptors, MockClient, MockPool, MockAgent, MockCallHistory, MockCallHistoryLog, mockErrors, ProxyAgent, EnvHttpProxyAgent, RedirectHandler, DecoratorHandler, RetryHandler, RetryAgent, H2CClient }
37
+ export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, setGlobalOrigin, getGlobalOrigin, interceptors, MockClient, MockPool, MockAgent, SnapshotAgent, MockCallHistory, MockCallHistoryLog, mockErrors, ProxyAgent, EnvHttpProxyAgent, RedirectHandler, DecoratorHandler, RetryHandler, RetryAgent, H2CClient }
37
38
  export default Undici
38
39
 
39
40
  declare namespace Undici {
@@ -58,6 +59,7 @@ declare namespace Undici {
58
59
  const MockClient: typeof import('./mock-client').default
59
60
  const MockPool: typeof import('./mock-pool').default
60
61
  const MockAgent: typeof import('./mock-agent').default
62
+ const SnapshotAgent: typeof import('./snapshot-agent').SnapshotAgent
61
63
  const MockCallHistory: typeof import('./mock-call-history').MockCallHistory
62
64
  const MockCallHistoryLog: typeof import('./mock-call-history').MockCallHistoryLog
63
65
  const mockErrors: typeof import('./mock-errors').default
@@ -69,7 +69,6 @@ declare namespace MockInterceptor {
69
69
  headers?: Headers | Record<string, string>;
70
70
  origin?: string;
71
71
  body?: BodyInit | Dispatcher.DispatchOptions['body'] | null;
72
- maxRedirections?: number;
73
72
  }
74
73
 
75
74
  export type MockResponseDataHandler<TData extends object = object> = (
@@ -0,0 +1,107 @@
1
+ import MockAgent from './mock-agent'
2
+
3
+ declare class SnapshotRecorder {
4
+ constructor (options?: SnapshotRecorder.Options)
5
+
6
+ record (requestOpts: any, response: any): Promise<void>
7
+ findSnapshot (requestOpts: any): SnapshotRecorder.Snapshot | undefined
8
+ loadSnapshots (filePath?: string): Promise<void>
9
+ saveSnapshots (filePath?: string): Promise<void>
10
+ clear (): void
11
+ getSnapshots (): SnapshotRecorder.Snapshot[]
12
+ size (): number
13
+ resetCallCounts (): void
14
+ deleteSnapshot (requestOpts: any): boolean
15
+ getSnapshotInfo (requestOpts: any): SnapshotRecorder.SnapshotInfo | null
16
+ replaceSnapshots (snapshotData: SnapshotRecorder.SnapshotData[]): void
17
+ destroy (): void
18
+ }
19
+
20
+ declare namespace SnapshotRecorder {
21
+ export interface Options {
22
+ snapshotPath?: string
23
+ mode?: 'record' | 'playback' | 'update'
24
+ maxSnapshots?: number
25
+ autoFlush?: boolean
26
+ flushInterval?: number
27
+ matchHeaders?: string[]
28
+ ignoreHeaders?: string[]
29
+ excludeHeaders?: string[]
30
+ matchBody?: boolean
31
+ matchQuery?: boolean
32
+ caseSensitive?: boolean
33
+ shouldRecord?: (requestOpts: any) => boolean
34
+ shouldPlayback?: (requestOpts: any) => boolean
35
+ excludeUrls?: (string | RegExp)[]
36
+ }
37
+
38
+ export interface Snapshot {
39
+ request: {
40
+ method: string
41
+ url: string
42
+ headers: Record<string, string>
43
+ body?: string
44
+ }
45
+ responses: {
46
+ statusCode: number
47
+ headers: Record<string, string>
48
+ body: string
49
+ trailers: Record<string, string>
50
+ }[]
51
+ callCount: number
52
+ timestamp: string
53
+ }
54
+
55
+ export interface SnapshotInfo {
56
+ hash: string
57
+ request: {
58
+ method: string
59
+ url: string
60
+ headers: Record<string, string>
61
+ body?: string
62
+ }
63
+ responseCount: number
64
+ callCount: number
65
+ timestamp: string
66
+ }
67
+
68
+ export interface SnapshotData {
69
+ hash: string
70
+ snapshot: Snapshot
71
+ }
72
+ }
73
+
74
+ declare class SnapshotAgent extends MockAgent {
75
+ constructor (options?: SnapshotAgent.Options)
76
+
77
+ saveSnapshots (filePath?: string): Promise<void>
78
+ loadSnapshots (filePath?: string): Promise<void>
79
+ getRecorder (): SnapshotRecorder
80
+ getMode (): 'record' | 'playback' | 'update'
81
+ clearSnapshots (): void
82
+ resetCallCounts (): void
83
+ deleteSnapshot (requestOpts: any): boolean
84
+ getSnapshotInfo (requestOpts: any): SnapshotRecorder.SnapshotInfo | null
85
+ replaceSnapshots (snapshotData: SnapshotRecorder.SnapshotData[]): void
86
+ }
87
+
88
+ declare namespace SnapshotAgent {
89
+ export interface Options extends MockAgent.Options {
90
+ mode?: 'record' | 'playback' | 'update'
91
+ snapshotPath?: string
92
+ maxSnapshots?: number
93
+ autoFlush?: boolean
94
+ flushInterval?: number
95
+ matchHeaders?: string[]
96
+ ignoreHeaders?: string[]
97
+ excludeHeaders?: string[]
98
+ matchBody?: boolean
99
+ matchQuery?: boolean
100
+ caseSensitive?: boolean
101
+ shouldRecord?: (requestOpts: any) => boolean
102
+ shouldPlayback?: (requestOpts: any) => boolean
103
+ excludeUrls?: (string | RegExp)[]
104
+ }
105
+ }
106
+
107
+ export { SnapshotAgent, SnapshotRecorder }
package/types/webidl.d.ts CHANGED
@@ -182,6 +182,16 @@ interface WebidlConverters {
182
182
 
183
183
  ['record<ByteString, ByteString>']: RecordConverter<string, string>
184
184
 
185
+ /**
186
+ * @see https://fetch.spec.whatwg.org/#requestinfo
187
+ */
188
+ RequestInfo (V: unknown): undici.Request | string
189
+
190
+ /**
191
+ * @see https://fetch.spec.whatwg.org/#requestinit
192
+ */
193
+ RequestInit (V: unknown): undici.RequestInit
194
+
185
195
  [Key: string]: (...args: any[]) => unknown
186
196
  }
187
197
 
@@ -182,3 +182,5 @@ export declare const WebSocketError: {
182
182
  prototype: WebSocketError
183
183
  new (type: string, init?: WebSocketCloseInfo): WebSocketError
184
184
  }
185
+
186
+ export declare const ping: (ws: WebSocket, body?: Buffer) => void
@@ -1,5 +0,0 @@
1
- 'use strict'
2
-
3
- module.exports = function () {
4
- return { WeakRef, FinalizationRegistry }
5
- }