Run npm ci --ignore-scripts to update dependencies (#254)

* Initial plan

* Run npm ci --ignore-scripts to update dependencies

Co-authored-by: dawidd6 <9713907+dawidd6@users.noreply.github.com>

* Convert CommonJS to ESM (#255)

* Initial plan

* Convert CommonJS imports to ESM

Co-authored-by: dawidd6 <9713907+dawidd6@users.noreply.github.com>

* Use node: protocol prefix for built-in modules

Co-authored-by: dawidd6 <9713907+dawidd6@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: dawidd6 <9713907+dawidd6@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: dawidd6 <9713907+dawidd6@users.noreply.github.com>
This commit is contained in:
Copilot
2026-01-30 13:31:20 +01:00
committed by GitHub
parent 85c1af852f
commit afe9786629
330 changed files with 13024 additions and 14665 deletions

View File

@@ -1,7 +1,7 @@
'use strict'
const { kClients } = require('../core/symbols')
const Agent = require('../agent')
const Agent = require('../dispatcher/agent')
const {
kAgent,
kMockAgentSet,
@@ -17,20 +17,10 @@ const MockClient = require('./mock-client')
const MockPool = require('./mock-pool')
const { matchValue, buildMockOptions } = require('./mock-utils')
const { InvalidArgumentError, UndiciError } = require('../core/errors')
const Dispatcher = require('../dispatcher')
const Dispatcher = require('../dispatcher/dispatcher')
const Pluralizer = require('./pluralizer')
const PendingInterceptorsFormatter = require('./pending-interceptors-formatter')
class FakeWeakRef {
constructor (value) {
this.value = value
}
deref () {
return this.value
}
}
class MockAgent extends Dispatcher {
constructor (opts) {
super(opts)
@@ -39,10 +29,10 @@ class MockAgent extends Dispatcher {
this[kIsMockActive] = true
// Instantiate Agent and encapsulate
if ((opts && opts.agent && typeof opts.agent.dispatch !== 'function')) {
if ((opts?.agent && typeof opts.agent.dispatch !== 'function')) {
throw new InvalidArgumentError('Argument opts.agent must implement Agent')
}
const agent = opts && opts.agent ? opts.agent : new Agent(opts)
const agent = opts?.agent ? opts.agent : new Agent(opts)
this[kAgent] = agent
this[kClients] = agent[kClients]
@@ -103,7 +93,7 @@ class MockAgent extends Dispatcher {
}
[kMockAgentSet] (origin, dispatcher) {
this[kClients].set(origin, new FakeWeakRef(dispatcher))
this[kClients].set(origin, dispatcher)
}
[kFactory] (origin) {
@@ -115,9 +105,9 @@ class MockAgent extends Dispatcher {
[kMockAgentGet] (origin) {
// First check if we can immediately find it
const ref = this[kClients].get(origin)
if (ref) {
return ref.deref()
const client = this[kClients].get(origin)
if (client) {
return client
}
// If the origin is not a string create a dummy parent pool and return to user
@@ -128,8 +118,7 @@ class MockAgent extends Dispatcher {
}
// If we match, create a pool and assign the same dispatches
for (const [keyMatcher, nonExplicitRef] of Array.from(this[kClients])) {
const nonExplicitDispatcher = nonExplicitRef.deref()
for (const [keyMatcher, nonExplicitDispatcher] of Array.from(this[kClients])) {
if (nonExplicitDispatcher && typeof keyMatcher !== 'string' && matchValue(keyMatcher, origin)) {
const dispatcher = this[kFactory](origin)
this[kMockAgentSet](origin, dispatcher)
@@ -147,7 +136,7 @@ class MockAgent extends Dispatcher {
const mockAgentClients = this[kClients]
return Array.from(mockAgentClients.entries())
.flatMap(([origin, scope]) => scope.deref()[kDispatches].map(dispatch => ({ ...dispatch, origin })))
.flatMap(([origin, scope]) => scope[kDispatches].map(dispatch => ({ ...dispatch, origin })))
.filter(({ pending }) => pending)
}

View File

@@ -1,7 +1,7 @@
'use strict'
const { promisify } = require('util')
const Client = require('../client')
const { promisify } = require('node:util')
const Client = require('../dispatcher/client')
const { buildMockDispatch } = require('./mock-utils')
const {
kDispatches,

View File

@@ -2,6 +2,11 @@
const { UndiciError } = require('../core/errors')
const kMockNotMatchedError = Symbol.for('undici.error.UND_MOCK_ERR_MOCK_NOT_MATCHED')
/**
* The request does not match any registered mock dispatches.
*/
class MockNotMatchedError extends UndiciError {
constructor (message) {
super(message)
@@ -10,6 +15,12 @@ class MockNotMatchedError extends UndiciError {
this.message = message || 'The request does not match any registered mock dispatches'
this.code = 'UND_MOCK_ERR_MOCK_NOT_MATCHED'
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kMockNotMatchedError] === true
}
[kMockNotMatchedError] = true
}
module.exports = {

View File

@@ -74,7 +74,7 @@ class MockInterceptor {
if (opts.query) {
opts.path = buildURL(opts.path, opts.query)
} else {
// Matches https://github.com/nodejs/undici/blob/main/lib/fetch/index.js#L1811
// Matches https://github.com/nodejs/undici/blob/main/lib/web/fetch/index.js#L1811
const parsedURL = new URL(opts.path, 'data://')
opts.path = parsedURL.pathname + parsedURL.search
}
@@ -90,7 +90,7 @@ class MockInterceptor {
this[kContentLength] = false
}
createMockScopeDispatchData (statusCode, data, responseOptions = {}) {
createMockScopeDispatchData ({ statusCode, data, responseOptions }) {
const responseData = getResponseData(data)
const contentLength = this[kContentLength] ? { 'content-length': responseData.length } : {}
const headers = { ...this[kDefaultHeaders], ...contentLength, ...responseOptions.headers }
@@ -99,14 +99,11 @@ class MockInterceptor {
return { statusCode, data, headers, trailers }
}
validateReplyParameters (statusCode, data, responseOptions) {
if (typeof statusCode === 'undefined') {
validateReplyParameters (replyParameters) {
if (typeof replyParameters.statusCode === 'undefined') {
throw new InvalidArgumentError('statusCode must be defined')
}
if (typeof data === 'undefined') {
throw new InvalidArgumentError('data must be defined')
}
if (typeof responseOptions !== 'object') {
if (typeof replyParameters.responseOptions !== 'object' || replyParameters.responseOptions === null) {
throw new InvalidArgumentError('responseOptions must be an object')
}
}
@@ -114,28 +111,28 @@ class MockInterceptor {
/**
* Mock an undici request with a defined reply.
*/
reply (replyData) {
reply (replyOptionsCallbackOrStatusCode) {
// Values of reply aren't available right now as they
// can only be available when the reply callback is invoked.
if (typeof replyData === 'function') {
if (typeof replyOptionsCallbackOrStatusCode === 'function') {
// We'll first wrap the provided callback in another function,
// this function will properly resolve the data from the callback
// when invoked.
const wrappedDefaultsCallback = (opts) => {
// Our reply options callback contains the parameter for statusCode, data and options.
const resolvedData = replyData(opts)
const resolvedData = replyOptionsCallbackOrStatusCode(opts)
// Check if it is in the right format
if (typeof resolvedData !== 'object') {
if (typeof resolvedData !== 'object' || resolvedData === null) {
throw new InvalidArgumentError('reply options callback must return an object')
}
const { statusCode, data = '', responseOptions = {} } = resolvedData
this.validateReplyParameters(statusCode, data, responseOptions)
const replyParameters = { data: '', responseOptions: {}, ...resolvedData }
this.validateReplyParameters(replyParameters)
// Since the values can be obtained immediately we return them
// from this higher order function that will be resolved later.
return {
...this.createMockScopeDispatchData(statusCode, data, responseOptions)
...this.createMockScopeDispatchData(replyParameters)
}
}
@@ -148,11 +145,15 @@ class MockInterceptor {
// we should have 1-3 parameters. So we spread the arguments of
// this function to obtain the parameters, since replyData will always
// just be the statusCode.
const [statusCode, data = '', responseOptions = {}] = [...arguments]
this.validateReplyParameters(statusCode, data, responseOptions)
const replyParameters = {
statusCode: replyOptionsCallbackOrStatusCode,
data: arguments[1] === undefined ? '' : arguments[1],
responseOptions: arguments[2] === undefined ? {} : arguments[2]
}
this.validateReplyParameters(replyParameters)
// Send in-already provided data like usual
const dispatchData = this.createMockScopeDispatchData(statusCode, data, responseOptions)
const dispatchData = this.createMockScopeDispatchData(replyParameters)
const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], dispatchData)
return new MockScope(newMockDispatch)
}

View File

@@ -1,7 +1,7 @@
'use strict'
const { promisify } = require('util')
const Pool = require('../pool')
const { promisify } = require('node:util')
const Pool = require('../dispatcher/pool')
const { buildMockDispatch } = require('./mock-utils')
const {
kDispatches,

View File

@@ -8,13 +8,13 @@ const {
kOrigin,
kGetNetConnect
} = require('./mock-symbols')
const { buildURL, nop } = require('../core/util')
const { STATUS_CODES } = require('http')
const { buildURL } = require('../core/util')
const { STATUS_CODES } = require('node:http')
const {
types: {
isPromise
}
} = require('util')
} = require('node:util')
function matchValue (match, value) {
if (typeof match === 'string') {
@@ -118,6 +118,10 @@ function matchKey (mockDispatch, { path, method, body, headers }) {
function getResponseData (data) {
if (Buffer.isBuffer(data)) {
return data
} else if (data instanceof Uint8Array) {
return data
} else if (data instanceof ArrayBuffer) {
return data
} else if (typeof data === 'object') {
return JSON.stringify(data)
} else {
@@ -138,19 +142,20 @@ function getMockDispatch (mockDispatches, key) {
// Match method
matchedMockDispatches = matchedMockDispatches.filter(({ method }) => matchValue(method, key.method))
if (matchedMockDispatches.length === 0) {
throw new MockNotMatchedError(`Mock dispatch not matched for method '${key.method}'`)
throw new MockNotMatchedError(`Mock dispatch not matched for method '${key.method}' on path '${resolvedPath}'`)
}
// Match body
matchedMockDispatches = matchedMockDispatches.filter(({ body }) => typeof body !== 'undefined' ? matchValue(body, key.body) : true)
if (matchedMockDispatches.length === 0) {
throw new MockNotMatchedError(`Mock dispatch not matched for body '${key.body}'`)
throw new MockNotMatchedError(`Mock dispatch not matched for body '${key.body}' on path '${resolvedPath}'`)
}
// Match headers
matchedMockDispatches = matchedMockDispatches.filter((mockDispatch) => matchHeaders(mockDispatch, key.headers))
if (matchedMockDispatches.length === 0) {
throw new MockNotMatchedError(`Mock dispatch not matched for headers '${typeof key.headers === 'object' ? JSON.stringify(key.headers) : key.headers}'`)
const headers = typeof key.headers === 'object' ? JSON.stringify(key.headers) : key.headers
throw new MockNotMatchedError(`Mock dispatch not matched for headers '${headers}' on path '${resolvedPath}'`)
}
return matchedMockDispatches[0]
@@ -188,11 +193,21 @@ function buildKey (opts) {
}
function generateKeyValues (data) {
return Object.entries(data).reduce((keyValuePairs, [key, value]) => [
...keyValuePairs,
Buffer.from(`${key}`),
Array.isArray(value) ? value.map(x => Buffer.from(`${x}`)) : Buffer.from(`${value}`)
], [])
const keys = Object.keys(data)
const result = []
for (let i = 0; i < keys.length; ++i) {
const key = keys[i]
const value = data[key]
const name = Buffer.from(`${key}`)
if (Array.isArray(value)) {
for (let j = 0; j < value.length; ++j) {
result.push(name, Buffer.from(`${value[j]}`))
}
} else {
result.push(name, Buffer.from(`${value}`))
}
}
return result
}
/**
@@ -274,10 +289,10 @@ function mockDispatch (opts, handler) {
const responseHeaders = generateKeyValues(headers)
const responseTrailers = generateKeyValues(trailers)
handler.abort = nop
handler.onHeaders(statusCode, responseHeaders, resume, getStatusText(statusCode))
handler.onData(Buffer.from(responseData))
handler.onComplete(responseTrailers)
handler.onConnect?.(err => handler.onError(err), null)
handler.onHeaders?.(statusCode, responseHeaders, resume, getStatusText(statusCode))
handler.onData?.(Buffer.from(responseData))
handler.onComplete?.(responseTrailers)
deleteMockDispatch(mockDispatches, key)
}
@@ -347,5 +362,6 @@ module.exports = {
buildMockDispatch,
checkNetConnect,
buildMockOptions,
getHeaderByName
getHeaderByName,
buildHeadersFromArray
}

View File

@@ -1,7 +1,10 @@
'use strict'
const { Transform } = require('stream')
const { Console } = require('console')
const { Transform } = require('node:stream')
const { Console } = require('node:console')
const PERSISTENT = process.versions.icu ? '✅' : 'Y '
const NOT_PERSISTENT = process.versions.icu ? '❌' : 'N '
/**
* Gets the output of `console.table(…)` as a string.
@@ -29,7 +32,7 @@ module.exports = class PendingInterceptorsFormatter {
Origin: origin,
Path: path,
'Status code': statusCode,
Persistent: persist ? '✅' : '❌',
Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
Invocations: timesInvoked,
Remaining: persist ? Infinity : times - timesInvoked
}))