Comparing version 4.3.1 to 4.4.1
13
index.js
@@ -17,2 +17,4 @@ 'use strict' | ||
const nodeMajor = Number(process.versions.node.split('.')[0]) | ||
Object.assign(Dispatcher.prototype, api) | ||
@@ -88,2 +90,13 @@ | ||
if (nodeMajor >= 16) { | ||
const fetchImpl = require('./lib/fetch') | ||
module.exports.fetch = async function fetch (resource, init) { | ||
const dispatcher = getGlobalDispatcher() | ||
return fetchImpl.call(dispatcher, resource, init) | ||
} | ||
module.exports.Headers = require('./lib/fetch/headers').Headers | ||
module.exports.Response = require('./lib/fetch/response').Response | ||
module.exports.Request = require('./lib/fetch/request').Request | ||
} | ||
module.exports.request = makeDispatcher(api.request) | ||
@@ -90,0 +103,0 @@ module.exports.stream = makeDispatcher(api.stream) |
@@ -74,3 +74,4 @@ 'use strict' | ||
const body = new Readable(resume, abort) | ||
const parsedHeaders = util.parseHeaders(headers) | ||
const body = new Readable(resume, abort, parsedHeaders['content-type']) | ||
@@ -82,3 +83,3 @@ this.callback = null | ||
statusCode, | ||
headers: util.parseHeaders(headers), | ||
headers: parsedHeaders, | ||
trailers: this.trailers, | ||
@@ -85,0 +86,0 @@ opaque, |
@@ -8,2 +8,3 @@ // Ported from https://github.com/nodejs/undici/pull/907 | ||
const { RequestAbortedError, NotSupportedError } = require('../core/errors') | ||
const util = require('../core/util') | ||
@@ -16,5 +17,6 @@ let Blob | ||
const kAbort = Symbol('abort') | ||
const kContentType = Symbol('kContentType') | ||
module.exports = class BodyReadable extends Readable { | ||
constructor (resume, abort) { | ||
constructor (resume, abort, contentType = '') { | ||
super({ autoDestroy: true, read: resume }) | ||
@@ -27,2 +29,3 @@ | ||
this[kBody] = null | ||
this[kContentType] = contentType | ||
@@ -127,3 +130,3 @@ // Is stream being consumed through Readable API? | ||
get bodyUsed () { | ||
return isDisturbed(this) | ||
return util.isDisturbed(this) | ||
} | ||
@@ -134,3 +137,3 @@ | ||
if (!this[kBody]) { | ||
this[kBody] = Readable.toWeb(this) | ||
this[kBody] = util.toWeb(this) | ||
if (this[kConsume]) { | ||
@@ -152,17 +155,5 @@ // TODO: Is this the best way to force a lock? | ||
// https://streams.spec.whatwg.org/#readablestream-disturbed | ||
function isDisturbed (self) { | ||
// Waiting for: https://github.com/nodejs/node/pull/39589 | ||
const { _readableState: state } = self | ||
return !!( | ||
state.dataEmitted || | ||
state.endEmitted || | ||
state.errorEmitted || | ||
state.closeEmitted | ||
) | ||
} | ||
// https://fetch.spec.whatwg.org/#body-unusable | ||
function isUnusable (self) { | ||
return isDisturbed(self) || isLocked(self) | ||
return util.isDisturbed(self) || isLocked(self) | ||
} | ||
@@ -249,3 +240,3 @@ | ||
} | ||
resolve(new Blob(body)) | ||
resolve(new Blob(body, { type: stream[kContentType] })) | ||
} | ||
@@ -252,0 +243,0 @@ |
@@ -265,3 +265,3 @@ 'use strict' | ||
const { maxRedirections = this[kMaxRedirections] } = opts | ||
if (maxRedirections != null) { | ||
if (maxRedirections) { | ||
handler = new RedirectHandler(this, maxRedirections, opts, handler) | ||
@@ -275,3 +275,3 @@ } | ||
// Do nothing. | ||
} else if (util.isStream(request.body) || util.isStrictIterable(request.body)) { | ||
} else if (util.bodyLength(request.body) == null && util.isIterable(request.body)) { | ||
// Wait a tick in case stream/iterator is ended in the same tick. | ||
@@ -411,3 +411,6 @@ this[kResuming] = 1 | ||
wasm_on_status: (p, at, len) => { | ||
return 0 | ||
assert.strictEqual(currentParser.ptr, p) | ||
const start = at - currentBufferPtr | ||
const end = start + len | ||
return currentParser.onStatus(currentBufferRef.slice(start, end)) || 0 | ||
}, | ||
@@ -469,2 +472,3 @@ wasm_on_message_begin: (p) => { | ||
this.statusCode = null | ||
this.statusText = '' | ||
this.upgrade = false | ||
@@ -530,6 +534,16 @@ this.headers = [] | ||
this.paused = false | ||
this.socket.resume() | ||
this.execute(EMPTY_BUF) // Flush parser. | ||
this.execute(this.socket.read() || EMPTY_BUF) // Flush parser. | ||
this.readMore() | ||
} | ||
readMore () { | ||
while (!this.paused && this.ptr) { | ||
const chunk = this.socket.read() | ||
if (chunk === null) { | ||
break | ||
} | ||
this.execute(chunk) | ||
} | ||
} | ||
execute (data) { | ||
@@ -577,3 +591,2 @@ assert(this.ptr != null) | ||
this.paused = true | ||
socket.pause() | ||
socket.unshift(data.slice(offset)) | ||
@@ -653,2 +666,6 @@ } else if (ret !== constants.ERROR.OK) { | ||
onStatus (buf) { | ||
this.statusText = buf.toString() | ||
} | ||
onMessageBegin () { | ||
@@ -719,3 +736,2 @@ const { socket, client } = this | ||
assert(socket === client[kSocket]) | ||
assert(!socket.isPaused()) | ||
assert(!this.paused) | ||
@@ -725,2 +741,3 @@ assert(request.upgrade || request.method === 'CONNECT') | ||
this.statusCode = null | ||
this.statusText = '' | ||
this.shouldKeepAlive = null | ||
@@ -732,12 +749,2 @@ | ||
// _readableState.flowing might be `true` if the socket has been | ||
// explicitly `resume()`:d even if we never registered a 'data' | ||
// listener. | ||
// We need to stop unshift from emitting 'data'. However, we cannot | ||
// call pause() as that will stop socket from automatically resuming | ||
// when 'data' listener is registered. | ||
// Reset socket state to non flowing: | ||
socket._readableState.flowing = null | ||
socket.unshift(head) | ||
@@ -752,3 +759,3 @@ | ||
.removeListener('error', onSocketError) | ||
.removeListener('data', onSocketData) | ||
.removeListener('readable', onSocketReadable) | ||
.removeListener('end', onSocketEnd) | ||
@@ -771,3 +778,3 @@ .removeListener('close', onSocketClose) | ||
onHeadersComplete (statusCode, upgrade, shouldKeepAlive) { | ||
const { client, socket, headers } = this | ||
const { client, socket, headers, statusText } = this | ||
@@ -859,3 +866,3 @@ /* istanbul ignore next: difficult to make a test case for */ | ||
try { | ||
if (request.onHeaders(statusCode, headers, this.resume) === false) { | ||
if (request.onHeaders(statusCode, headers, this.resume, statusText) === false) { | ||
return constants.ERROR.PAUSED | ||
@@ -927,2 +934,3 @@ } | ||
this.statusCode = null | ||
this.statusText = '' | ||
this.bytesRead = 0 | ||
@@ -1012,5 +1020,5 @@ this.contentLength = '' | ||
function onSocketData (data) { | ||
function onSocketReadable (data) { | ||
const { [kParser]: parser } = this | ||
parser.execute(data) | ||
parser.readMore() | ||
} | ||
@@ -1156,3 +1164,3 @@ | ||
.on('error', onSocketError) | ||
.on('data', onSocketData) | ||
.on('readable', onSocketReadable) | ||
.on('end', onSocketEnd) | ||
@@ -1308,3 +1316,3 @@ .on('close', onSocketClose) | ||
if (client[kRunning] > 0 && | ||
(util.isStream(request.body) || util.isStrictIterable(request.body))) { | ||
(util.isStream(request.body) || util.isAsyncIterable(request.body))) { | ||
// Request with stream or iterator body can error while other requests | ||
@@ -1441,3 +1449,3 @@ // are inflight and indirectly error those as well. | ||
} else if (util.isBuffer(body)) { | ||
assert(contentLength !== null, 'buffer body must have content length') | ||
assert(contentLength === body.byteLength, 'buffer body must have content length') | ||
@@ -1452,5 +1460,7 @@ socket.cork() | ||
} | ||
} else if (util.isBlob(body)) { | ||
writeBlob({ client, request, socket, contentLength, header, expectsPayload }) | ||
} else if (util.isStream(body)) { | ||
writeStream({ client, request, socket, contentLength, header, expectsPayload }) | ||
} else if (util.isStrictIterable(body)) { | ||
} else if (util.isIterable(body)) { | ||
writeIterable({ client, request, socket, contentLength, header, expectsPayload }) | ||
@@ -1542,2 +1552,31 @@ } else { | ||
async function writeBlob ({ client, request, socket, contentLength, header, expectsPayload }) { | ||
const { body } = request | ||
assert(contentLength === body.size, 'blob body must have content length') | ||
try { | ||
if (contentLength != null && contentLength !== body.size) { | ||
throw new RequestContentLengthMismatchError() | ||
} | ||
const buffer = Buffer.from(await body.arrayBuffer()) | ||
socket.cork() | ||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'ascii') | ||
socket.write(buffer) | ||
socket.uncork() | ||
request.onBodySent(buffer) | ||
if (!expectsPayload) { | ||
socket[kReset] = true | ||
} | ||
resume(client) | ||
} catch (err) { | ||
util.destroy(socket, err) | ||
} | ||
} | ||
async function writeIterable ({ client, request, socket, contentLength, header, expectsPayload }) { | ||
@@ -1544,0 +1583,0 @@ const { body } = request |
'use strict' | ||
class AbortError extends Error { | ||
constructor () { | ||
super('The operation was aborted') | ||
this.code = 'ABORT_ERR' | ||
this.name = 'AbortError' | ||
} | ||
} | ||
class UndiciError extends Error { | ||
@@ -171,3 +179,31 @@ constructor (message) { | ||
class InvalidHTTPTokenError extends TypeError { | ||
constructor (name, token) { | ||
super(`${name} must be a valid HTTP token ["${token}"]`) | ||
Error.captureStackTrace(this, InvalidHTTPTokenError) | ||
this.name = 'InvalidHTTPToken' | ||
this.code = 'INVALID_HTTP_TOKEN' | ||
} | ||
} | ||
class HTTPInvalidHeaderValueError extends TypeError { | ||
constructor (name, value) { | ||
super(`Invalid value "${value}" for header "${name}"`) | ||
Error.captureStackTrace(this, HTTPInvalidHeaderValueError) | ||
this.name = 'HTTPInvalidHeaderValue' | ||
this.code = 'HTTP_INVALID_HEADER_VALUE' | ||
} | ||
} | ||
class InvalidThisError extends TypeError { | ||
constructor (type) { | ||
super(`Value of "this" must be of type ${type}`) | ||
Error.captureStackTrace(this, InvalidThisError) | ||
this.name = 'InvalidThis' | ||
this.code = 'INVALID_THIS' | ||
} | ||
} | ||
module.exports = { | ||
AbortError, | ||
HTTPParserError, | ||
@@ -189,3 +225,6 @@ UndiciError, | ||
NotSupportedError, | ||
ResponseContentLengthMismatchError | ||
ResponseContentLengthMismatchError, | ||
InvalidHTTPTokenError, | ||
HTTPInvalidHeaderValueError, | ||
InvalidThisError | ||
} |
@@ -53,9 +53,14 @@ 'use strict' | ||
this.body = null | ||
} else if (util.isReadable(body)) { | ||
} else if (util.isStream(body)) { | ||
this.body = body | ||
} else if (body instanceof DataView) { | ||
// TODO: Why is DataView special? | ||
this.body = body.buffer.byteLength ? Buffer.from(body.buffer) : null | ||
} else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) { | ||
this.body = body.byteLength ? Buffer.from(body) : null | ||
} else if (util.isBuffer(body)) { | ||
this.body = body.length ? body : null | ||
this.body = body.byteLength ? body : null | ||
} else if (typeof body === 'string') { | ||
this.body = body.length ? Buffer.from(body) : null | ||
} else if (util.isIterable(body)) { | ||
} else if (util.isIterable(body) || util.isBlob(body)) { | ||
this.body = body | ||
@@ -82,2 +87,4 @@ } else { | ||
this.contentType = null | ||
this.headers = '' | ||
@@ -102,2 +109,7 @@ | ||
if (util.isBlob(body) && this.contentType == null) { | ||
this.contentType = body.type | ||
this.headers += `content-type: ${body.type}\r\n` | ||
} | ||
util.validateHandler(handler, method, upgrade) | ||
@@ -127,7 +139,7 @@ | ||
onHeaders (statusCode, headers, resume) { | ||
onHeaders (statusCode, headers, resume, statusText) { | ||
assert(!this.aborted) | ||
assert(!this.completed) | ||
return this[kHandler].onHeaders(statusCode, headers, resume) | ||
return this[kHandler].onHeaders(statusCode, headers, resume, statusText) | ||
} | ||
@@ -189,2 +201,9 @@ | ||
} else if ( | ||
request.contentType === null && | ||
key.length === 12 && | ||
key.toLowerCase() === 'content-type' | ||
) { | ||
request.contentType = val | ||
request.headers += `${key}: ${val}\r\n` | ||
} else if ( | ||
key.length === 17 && | ||
@@ -191,0 +210,0 @@ key.toLowerCase() === 'transfer-encoding' |
@@ -8,2 +8,3 @@ module.exports = { | ||
kConnecting: Symbol('connecting'), | ||
kHeadersList: Symbol('headers list'), | ||
kKeepAliveDefaultTimeout: Symbol('default keep alive timeout'), | ||
@@ -19,2 +20,3 @@ kKeepAliveMaxTimeout: Symbol('max keep alive timeout'), | ||
kNoRef: Symbol('no ref'), | ||
kBodyUsed: Symbol('used'), | ||
kRunning: Symbol('running'), | ||
@@ -21,0 +23,0 @@ kPending: Symbol('pending'), |
'use strict' | ||
const assert = require('assert') | ||
const { kDestroyed } = require('./symbols') | ||
const { kDestroyed, kBodyUsed } = require('./symbols') | ||
const { IncomingMessage } = require('http') | ||
const stream = require('stream') | ||
const net = require('net') | ||
const { InvalidArgumentError } = require('./errors') | ||
const { Blob } = require('buffer') | ||
function nop () {} | ||
function isReadable (obj) { | ||
return !!(obj && typeof obj.pipe === 'function' && | ||
typeof obj.on === 'function') | ||
function isStream (obj) { | ||
return obj && typeof obj.pipe === 'function' | ||
} | ||
function isWritable (obj) { | ||
return !!(obj && typeof obj.write === 'function' && | ||
typeof obj.on === 'function') | ||
function isBlob (obj) { | ||
return obj && Blob && obj instanceof Blob | ||
} | ||
function isStream (obj) { | ||
return isReadable(obj) || isWritable(obj) | ||
} | ||
function parseURL (url) { | ||
@@ -114,2 +110,6 @@ if (typeof url === 'string') { | ||
function isAsyncIterable (obj) { | ||
return !!(obj != null && typeof obj[Symbol.asyncIterator] === 'function') | ||
} | ||
function isIterable (obj) { | ||
@@ -119,8 +119,6 @@ return !!(obj != null && (typeof obj[Symbol.iterator] === 'function' || typeof obj[Symbol.asyncIterator] === 'function')) | ||
function isStrictIterable (obj) { | ||
return obj && !isStream(obj) && typeof obj !== 'string' && !isBuffer(obj) && isIterable(obj) | ||
} | ||
function bodyLength (body) { | ||
if (body && typeof body.on === 'function') { | ||
if (body == null) { | ||
return 0 | ||
} else if (isStream(body)) { | ||
const state = body._readableState | ||
@@ -130,9 +128,9 @@ return state && state.ended === true && Number.isFinite(state.length) | ||
: null | ||
} else if (isStrictIterable(body)) { | ||
return null | ||
} else if (isBlob(body)) { | ||
return body.size | ||
} else if (isBuffer(body)) { | ||
return body.byteLength | ||
} | ||
assert(!body || Number.isFinite(body.byteLength)) | ||
return body ? body.byteLength : 0 | ||
return null | ||
} | ||
@@ -144,2 +142,7 @@ | ||
function isAborted (stream) { | ||
const state = stream && stream._readableState | ||
return isDestroyed(stream) && state && !state.endEmitted | ||
} | ||
function destroy (stream, err) { | ||
@@ -231,4 +234,22 @@ if (!isStream(stream) || isDestroyed(stream)) { | ||
// A body is disturbed if it has been read from and it cannot | ||
// be re-used without losing state or data. | ||
function isDisturbed (body) { | ||
const state = body && body._readableState | ||
return !!(body && ( | ||
(stream.isDisturbed && stream.isDisturbed(body)) || | ||
body[kBodyUsed] || | ||
body.readableDidRead || (state && state.dataEmitted) || | ||
isAborted(stream) | ||
)) | ||
} | ||
const kEnumerableProperty = Object.create(null) | ||
kEnumerableProperty.enumerable = true | ||
module.exports = { | ||
kEnumerableProperty, | ||
nop, | ||
isDisturbed, | ||
isAborted, | ||
parseOrigin, | ||
@@ -238,5 +259,4 @@ parseURL, | ||
isStream, | ||
isReadable, | ||
isIterable, | ||
isStrictIterable, | ||
isAsyncIterable, | ||
isDestroyed, | ||
@@ -249,3 +269,4 @@ parseHeaders, | ||
isBuffer, | ||
isBlob, | ||
validateHandler | ||
} |
'use strict' | ||
const util = require('../core/util') | ||
const { kBodyUsed } = require('../core/symbols') | ||
const assert = require('assert') | ||
@@ -9,2 +10,17 @@ const { InvalidArgumentError } = require('../core/errors') | ||
const kBody = Symbol('body') | ||
class BodyAsyncIterable { | ||
constructor (body) { | ||
this[kBody] = body | ||
this[kBodyUsed] = false | ||
} | ||
async * [Symbol.asyncIterator] () { | ||
assert(!this[kBodyUsed], 'disturbed') | ||
this[kBodyUsed] = true | ||
yield * this[kBody] | ||
} | ||
} | ||
class RedirectHandler { | ||
@@ -26,14 +42,34 @@ constructor (dispatcher, maxRedirections, opts, handler) { | ||
if (util.isStream(opts.body)) { | ||
if (util.isStream(this.opts.body)) { | ||
// TODO (fix): Provide some way for the user to cache the file to e.g. /tmp | ||
// so that it can be dispatched again? | ||
// TODO (fix): Do we need 100-expect support to provide a way to do this properly? | ||
if (util.bodyLength(opts.body) === 0) { | ||
opts.body | ||
if (util.bodyLength(this.opts.body) === 0) { | ||
this.opts.body | ||
.on('data', function () { | ||
assert(false) | ||
}) | ||
} else { | ||
this.maxRedirections = 0 | ||
} | ||
if (typeof this.opts.body.readableDidRead !== 'boolean') { | ||
this.opts.body[kBodyUsed] = false | ||
// TODO (fix): Don't mutate readable state... | ||
this.opts.body.on('data', function () { | ||
this[kBodyUsed] = true | ||
}) | ||
} | ||
} else if (this.opts.body && typeof this.opts.body.pipeTo === 'function') { | ||
// TODO (fix): We can't access ReadableStream internal state | ||
// to determine whether or not it has been disturbed. This is just | ||
// a workaround. | ||
this.opts.body = new BodyAsyncIterable(this.opts.body) | ||
} else if ( | ||
this.opts.body && | ||
typeof this.opts.body !== 'string' && | ||
!ArrayBuffer.isView(this.opts.body) && | ||
util.isIterable(this.opts.body) | ||
) { | ||
// TODO: Should we allow re-using iterable if !this.opts.idempotent | ||
// or through some other flag? | ||
this.opts.body = new BodyAsyncIterable(this.opts.body) | ||
} | ||
@@ -55,4 +91,4 @@ } | ||
onHeaders (statusCode, headers, resume) { | ||
this.location = this.history.length >= this.maxRedirections | ||
onHeaders (statusCode, headers, resume, statusText) { | ||
this.location = this.history.length >= this.maxRedirections || util.isDisturbed(this.opts.body) | ||
? null | ||
@@ -62,3 +98,3 @@ : parseLocation(statusCode, headers) | ||
if (!this.location) { | ||
return this.handler.onHeaders(statusCode, headers, resume) | ||
return this.handler.onHeaders(statusCode, headers, resume, statusText) | ||
} | ||
@@ -65,0 +101,0 @@ |
{ | ||
"name": "undici", | ||
"version": "4.3.1", | ||
"version": "4.4.1", | ||
"description": "An HTTP/1.1 client, written from scratch for Node.js", | ||
@@ -36,3 +36,6 @@ "homepage": "https://undici.nodejs.org", | ||
"lint:fix": "standard --fix | snazzy", | ||
"test": "tap test/*.js --no-coverage && jest test/jest/test", | ||
"test": "tap test/*.js --no-coverage && mocha test/node-fetch && jest test/jest/test", | ||
"test:node-fetch": "node scripts/test-node-fetch.js 16 && mocha test/node-fetch || echo Skipping", | ||
"test:jest": "jest test/jest/test", | ||
"test:tap": "tap test/*.js --no-coverage ", | ||
"test:tdd": "tap test/*.js -w --no-coverage-report", | ||
@@ -54,4 +57,10 @@ "test:typescript": "tsd", | ||
"abort-controller": "^3.0.0", | ||
"busboy": "^0.3.1", | ||
"chai": "^4.3.4", | ||
"chai-as-promised": "^7.1.1", | ||
"chai-iterator": "^3.0.2", | ||
"chai-string": "^1.5.0", | ||
"concurrently": "^6.1.0", | ||
"cronometro": "^0.8.0", | ||
"delay": "^5.0.0", | ||
"docsify-cli": "^4.4.2", | ||
@@ -62,2 +71,4 @@ "https-pem": "^2.0.0", | ||
"jsfuzz": "^1.0.15", | ||
"mocha": "^9.0.3", | ||
"p-timeout": "^3.2.0", | ||
"pre-commit": "^1.2.2", | ||
@@ -78,2 +89,5 @@ "proxy": "^1.0.2", | ||
"standard": { | ||
"env": [ | ||
"mocha" | ||
], | ||
"ignore": [ | ||
@@ -80,0 +94,0 @@ "lib/llhttp/constants.js", |
@@ -158,2 +158,13 @@ # undici | ||
### `undici.fetch(input[, init]): Promise` | ||
Implements [fetch](https://fetch.spec.whatwg.org/). | ||
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | ||
https://fetch.spec.whatwg.org/#fetch-method | ||
Only supported on Node 16+. | ||
This is [experimental](https://nodejs.org/api/documentation.html#documentation_stability_index) and is not yet fully compliant the Fetch Standard. We plan to ship breaking changes to this feature until it is out of experimental. | ||
### `undici.upgrade([url, options]): Promise` | ||
@@ -232,2 +243,3 @@ | ||
* [__Ethan Arrowood__](https://github.com/ethan-arrowood), <https://www.npmjs.com/~ethan_arrowood> | ||
* [__Matteo Collina__](https://github.com/mcollina), <https://www.npmjs.com/~matteo.collina> | ||
@@ -234,0 +246,0 @@ * [__Robert Nagy__](https://github.com/ronag), <https://www.npmjs.com/~ronag> |
@@ -5,2 +5,3 @@ import { URL } from 'url' | ||
import { IncomingHttpHeaders } from 'http' | ||
import { Blob } from 'buffer' | ||
@@ -43,3 +44,3 @@ type AbortSignal = unknown; | ||
path: string; | ||
method: string; | ||
method: HttpMethod; | ||
/** Default: `null` */ | ||
@@ -103,3 +104,3 @@ body?: string | Buffer | Uint8Array | Readable | null; | ||
headers: IncomingHttpHeaders; | ||
body: Readable; | ||
body: Readable & BodyMixin; | ||
trailers: Record<string, string>; | ||
@@ -149,2 +150,16 @@ opaque: unknown; | ||
export type PipelineHandler = (data: PipelineHandlerData) => Readable; | ||
export type HttpMethod = 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'CONNECT' | 'OPTIONS' | 'TRACE' | 'PATCH'; | ||
/** | ||
* @link https://fetch.spec.whatwg.org/#body-mixin | ||
*/ | ||
interface BodyMixin { | ||
readonly body?: never; // throws on node v16.6.0 | ||
readonly bodyUsed: boolean; | ||
arrayBuffer(): Promise<ArrayBuffer>; | ||
blob(): Promise<Blob>; | ||
formData(): Promise<never>; | ||
json(): Promise<any>; | ||
text(): Promise<string>; | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
557127
77
8395
249
28
7
7