setup-v-action
Version:
GitHub action for setting up a V (Vlang) build environment by downloading and unpacking the V compiler or building it from sources.
1,711 lines (1,510 loc) • 1.16 MB
JavaScript
import { resolve, join, basename } from 'node:path';
import * as os from 'os';
import os__default from 'os';
import * as crypto from 'crypto';
import * as fs from 'fs';
import { promises } from 'fs';
import * as path from 'path';
import * as http from 'http';
import http__default from 'http';
import * as https from 'https';
import https__default from 'https';
import 'net';
import require$$1 from 'tls';
import * as events$1 from 'events';
import events__default from 'events';
import { ok } from 'assert';
import * as require$$6 from 'util';
import require$$6__default from 'util';
import require$$0$1 from 'node:assert';
import require$$0$3 from 'node:net';
import require$$2 from 'node:http';
import require$$0$2 from 'node:stream';
import require$$0 from 'node:buffer';
import require$$0$4 from 'node:util';
import require$$7 from 'node:querystring';
import require$$8 from 'node:events';
import require$$0$5 from 'node:diagnostics_channel';
import require$$5 from 'node:tls';
import require$$1$2 from 'node:zlib';
import require$$5$1 from 'node:perf_hooks';
import require$$8$1 from 'node:util/types';
import require$$1$1 from 'node:worker_threads';
import require$$1$3 from 'node:url';
import require$$5$2 from 'node:async_hooks';
import require$$1$4 from 'node:console';
import require$$1$5 from 'node:dns';
import require$$5$3 from 'string_decoder';
import * as child from 'child_process';
import { setTimeout as setTimeout$1 } from 'timers';
import * as stream from 'stream';
import { copyFile as copyFile$2, chmod as chmod$1, symlink as symlink$1, readFile, access as access$1 } from 'node:fs/promises';
import { spawn } from 'node:child_process';
// We use any as a valid input type
/* eslint-disable @typescript-eslint/no-explicit-any */
/**
* Sanitizes an input into a string so it can be passed into issueCommand safely
* @param input input to sanitize into a string
*/
function toCommandValue(input) {
if (input === null || input === undefined) {
return '';
}
else if (typeof input === 'string' || input instanceof String) {
return input;
}
return JSON.stringify(input);
}
/**
*
* @param annotationProperties
* @returns The command properties to send with the actual annotation command
* See IssueCommandProperties: https://github.com/actions/runner/blob/main/src/Runner.Worker/ActionCommandManager.cs#L646
*/
function toCommandProperties(annotationProperties) {
if (!Object.keys(annotationProperties).length) {
return {};
}
return {
title: annotationProperties.title,
file: annotationProperties.file,
line: annotationProperties.startLine,
endLine: annotationProperties.endLine,
col: annotationProperties.startColumn,
endColumn: annotationProperties.endColumn
};
}
/**
* Issues a command to the GitHub Actions runner
*
* @param command - The command name to issue
* @param properties - Additional properties for the command (key-value pairs)
* @param message - The message to include with the command
* @remarks
* This function outputs a specially formatted string to stdout that the Actions
* runner interprets as a command. These commands can control workflow behavior,
* set outputs, create annotations, mask values, and more.
*
* Command Format:
* ::name key=value,key=value::message
*
* @example
* ```typescript
* // Issue a warning annotation
* issueCommand('warning', {}, 'This is a warning message');
* // Output: ::warning::This is a warning message
*
* // Set an environment variable
* issueCommand('set-env', { name: 'MY_VAR' }, 'some value');
* // Output: ::set-env name=MY_VAR::some value
*
* // Add a secret mask
* issueCommand('add-mask', {}, 'secretValue123');
* // Output: ::add-mask::secretValue123
* ```
*
* @internal
* This is an internal utility function that powers the public API functions
* such as setSecret, warning, error, and exportVariable.
*/
function issueCommand(command, properties, message) {
const cmd = new Command(command, properties, message);
process.stdout.write(cmd.toString() + os.EOL);
}
const CMD_STRING = '::';
class Command {
constructor(command, properties, message) {
if (!command) {
command = 'missing.command';
}
this.command = command;
this.properties = properties;
this.message = message;
}
toString() {
let cmdStr = CMD_STRING + this.command;
if (this.properties && Object.keys(this.properties).length > 0) {
cmdStr += ' ';
let first = true;
for (const key in this.properties) {
if (this.properties.hasOwnProperty(key)) {
const val = this.properties[key];
if (val) {
if (first) {
first = false;
}
else {
cmdStr += ',';
}
cmdStr += `${key}=${escapeProperty(val)}`;
}
}
}
}
cmdStr += `${CMD_STRING}${escapeData(this.message)}`;
return cmdStr;
}
}
function escapeData(s) {
return toCommandValue(s)
.replace(/%/g, '%25')
.replace(/\r/g, '%0D')
.replace(/\n/g, '%0A');
}
function escapeProperty(s) {
return toCommandValue(s)
.replace(/%/g, '%25')
.replace(/\r/g, '%0D')
.replace(/\n/g, '%0A')
.replace(/:/g, '%3A')
.replace(/,/g, '%2C');
}
// For internal use, subject to change.
// We use any as a valid input type
/* eslint-disable @typescript-eslint/no-explicit-any */
function issueFileCommand(command, message) {
const filePath = process.env[`GITHUB_${command}`];
if (!filePath) {
throw new Error(`Unable to find environment variable for file command ${command}`);
}
if (!fs.existsSync(filePath)) {
throw new Error(`Missing file at path: ${filePath}`);
}
fs.appendFileSync(filePath, `${toCommandValue(message)}${os.EOL}`, {
encoding: 'utf8'
});
}
function prepareKeyValueMessage(key, value) {
const delimiter = `ghadelimiter_${crypto.randomUUID()}`;
const convertedValue = toCommandValue(value);
// These should realistically never happen, but just in case someone finds a
// way to exploit uuid generation let's not allow keys or values that contain
// the delimiter.
if (key.includes(delimiter)) {
throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`);
}
if (convertedValue.includes(delimiter)) {
throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`);
}
return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`;
}
function getProxyUrl(reqUrl) {
const usingSsl = reqUrl.protocol === 'https:';
if (checkBypass(reqUrl)) {
return undefined;
}
const proxyVar = (() => {
if (usingSsl) {
return process.env['https_proxy'] || process.env['HTTPS_PROXY'];
}
else {
return process.env['http_proxy'] || process.env['HTTP_PROXY'];
}
})();
if (proxyVar) {
try {
return new DecodedURL(proxyVar);
}
catch (_a) {
if (!proxyVar.startsWith('http://') && !proxyVar.startsWith('https://'))
return new DecodedURL(`http://${proxyVar}`);
}
}
else {
return undefined;
}
}
function checkBypass(reqUrl) {
if (!reqUrl.hostname) {
return false;
}
const reqHost = reqUrl.hostname;
if (isLoopbackAddress(reqHost)) {
return true;
}
const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || '';
if (!noProxy) {
return false;
}
// Determine the request port
let reqPort;
if (reqUrl.port) {
reqPort = Number(reqUrl.port);
}
else if (reqUrl.protocol === 'http:') {
reqPort = 80;
}
else if (reqUrl.protocol === 'https:') {
reqPort = 443;
}
// Format the request hostname and hostname with port
const upperReqHosts = [reqUrl.hostname.toUpperCase()];
if (typeof reqPort === 'number') {
upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`);
}
// Compare request host against noproxy
for (const upperNoProxyItem of noProxy
.split(',')
.map(x => x.trim().toUpperCase())
.filter(x => x)) {
if (upperNoProxyItem === '*' ||
upperReqHosts.some(x => x === upperNoProxyItem ||
x.endsWith(`.${upperNoProxyItem}`) ||
(upperNoProxyItem.startsWith('.') &&
x.endsWith(`${upperNoProxyItem}`)))) {
return true;
}
}
return false;
}
function isLoopbackAddress(host) {
const hostLower = host.toLowerCase();
return (hostLower === 'localhost' ||
hostLower.startsWith('127.') ||
hostLower.startsWith('[::1]') ||
hostLower.startsWith('[0:0:0:0:0:0:0:1]'));
}
class DecodedURL extends URL {
constructor(url, base) {
super(url, base);
this._decodedUsername = decodeURIComponent(super.username);
this._decodedPassword = decodeURIComponent(super.password);
}
get username() {
return this._decodedUsername;
}
get password() {
return this._decodedPassword;
}
}
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
var tunnel$1 = {};
var hasRequiredTunnel$1;
function requireTunnel$1 () {
if (hasRequiredTunnel$1) return tunnel$1;
hasRequiredTunnel$1 = 1;
var tls = require$$1;
var http = http__default;
var https = https__default;
var events = events__default;
var util = require$$6__default;
tunnel$1.httpOverHttp = httpOverHttp;
tunnel$1.httpsOverHttp = httpsOverHttp;
tunnel$1.httpOverHttps = httpOverHttps;
tunnel$1.httpsOverHttps = httpsOverHttps;
function httpOverHttp(options) {
var agent = new TunnelingAgent(options);
agent.request = http.request;
return agent;
}
function httpsOverHttp(options) {
var agent = new TunnelingAgent(options);
agent.request = http.request;
agent.createSocket = createSecureSocket;
agent.defaultPort = 443;
return agent;
}
function httpOverHttps(options) {
var agent = new TunnelingAgent(options);
agent.request = https.request;
return agent;
}
function httpsOverHttps(options) {
var agent = new TunnelingAgent(options);
agent.request = https.request;
agent.createSocket = createSecureSocket;
agent.defaultPort = 443;
return agent;
}
function TunnelingAgent(options) {
var self = this;
self.options = options || {};
self.proxyOptions = self.options.proxy || {};
self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets;
self.requests = [];
self.sockets = [];
self.on('free', function onFree(socket, host, port, localAddress) {
var options = toOptions(host, port, localAddress);
for (var i = 0, len = self.requests.length; i < len; ++i) {
var pending = self.requests[i];
if (pending.host === options.host && pending.port === options.port) {
// Detect the request to connect same origin server,
// reuse the connection.
self.requests.splice(i, 1);
pending.request.onSocket(socket);
return;
}
}
socket.destroy();
self.removeSocket(socket);
});
}
util.inherits(TunnelingAgent, events.EventEmitter);
TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) {
var self = this;
var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress));
if (self.sockets.length >= this.maxSockets) {
// We are over limit so we'll add it to the queue.
self.requests.push(options);
return;
}
// If we are under maxSockets create a new one.
self.createSocket(options, function(socket) {
socket.on('free', onFree);
socket.on('close', onCloseOrRemove);
socket.on('agentRemove', onCloseOrRemove);
req.onSocket(socket);
function onFree() {
self.emit('free', socket, options);
}
function onCloseOrRemove(err) {
self.removeSocket(socket);
socket.removeListener('free', onFree);
socket.removeListener('close', onCloseOrRemove);
socket.removeListener('agentRemove', onCloseOrRemove);
}
});
};
TunnelingAgent.prototype.createSocket = function createSocket(options, cb) {
var self = this;
var placeholder = {};
self.sockets.push(placeholder);
var connectOptions = mergeOptions({}, self.proxyOptions, {
method: 'CONNECT',
path: options.host + ':' + options.port,
agent: false,
headers: {
host: options.host + ':' + options.port
}
});
if (options.localAddress) {
connectOptions.localAddress = options.localAddress;
}
if (connectOptions.proxyAuth) {
connectOptions.headers = connectOptions.headers || {};
connectOptions.headers['Proxy-Authorization'] = 'Basic ' +
new Buffer(connectOptions.proxyAuth).toString('base64');
}
debug('making CONNECT request');
var connectReq = self.request(connectOptions);
connectReq.useChunkedEncodingByDefault = false; // for v0.6
connectReq.once('response', onResponse); // for v0.6
connectReq.once('upgrade', onUpgrade); // for v0.6
connectReq.once('connect', onConnect); // for v0.7 or later
connectReq.once('error', onError);
connectReq.end();
function onResponse(res) {
// Very hacky. This is necessary to avoid http-parser leaks.
res.upgrade = true;
}
function onUpgrade(res, socket, head) {
// Hacky.
process.nextTick(function() {
onConnect(res, socket, head);
});
}
function onConnect(res, socket, head) {
connectReq.removeAllListeners();
socket.removeAllListeners();
if (res.statusCode !== 200) {
debug('tunneling socket could not be established, statusCode=%d',
res.statusCode);
socket.destroy();
var error = new Error('tunneling socket could not be established, ' +
'statusCode=' + res.statusCode);
error.code = 'ECONNRESET';
options.request.emit('error', error);
self.removeSocket(placeholder);
return;
}
if (head.length > 0) {
debug('got illegal response body from proxy');
socket.destroy();
var error = new Error('got illegal response body from proxy');
error.code = 'ECONNRESET';
options.request.emit('error', error);
self.removeSocket(placeholder);
return;
}
debug('tunneling connection has established');
self.sockets[self.sockets.indexOf(placeholder)] = socket;
return cb(socket);
}
function onError(cause) {
connectReq.removeAllListeners();
debug('tunneling socket could not be established, cause=%s\n',
cause.message, cause.stack);
var error = new Error('tunneling socket could not be established, ' +
'cause=' + cause.message);
error.code = 'ECONNRESET';
options.request.emit('error', error);
self.removeSocket(placeholder);
}
};
TunnelingAgent.prototype.removeSocket = function removeSocket(socket) {
var pos = this.sockets.indexOf(socket);
if (pos === -1) {
return;
}
this.sockets.splice(pos, 1);
var pending = this.requests.shift();
if (pending) {
// If we have pending requests and a socket gets closed a new one
// needs to be created to take over in the pool for the one that closed.
this.createSocket(pending, function(socket) {
pending.request.onSocket(socket);
});
}
};
function createSecureSocket(options, cb) {
var self = this;
TunnelingAgent.prototype.createSocket.call(self, options, function(socket) {
var hostHeader = options.request.getHeader('host');
var tlsOptions = mergeOptions({}, self.options, {
socket: socket,
servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host
});
// 0 is dummy port for v0.6
var secureSocket = tls.connect(0, tlsOptions);
self.sockets[self.sockets.indexOf(socket)] = secureSocket;
cb(secureSocket);
});
}
function toOptions(host, port, localAddress) {
if (typeof host === 'string') { // since v0.10
return {
host: host,
port: port,
localAddress: localAddress
};
}
return host; // for v0.11 or later
}
function mergeOptions(target) {
for (var i = 1, len = arguments.length; i < len; ++i) {
var overrides = arguments[i];
if (typeof overrides === 'object') {
var keys = Object.keys(overrides);
for (var j = 0, keyLen = keys.length; j < keyLen; ++j) {
var k = keys[j];
if (overrides[k] !== undefined) {
target[k] = overrides[k];
}
}
}
}
return target;
}
var debug;
if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) {
debug = function() {
var args = Array.prototype.slice.call(arguments);
if (typeof args[0] === 'string') {
args[0] = 'TUNNEL: ' + args[0];
} else {
args.unshift('TUNNEL:');
}
console.error.apply(console, args);
};
} else {
debug = function() {};
}
tunnel$1.debug = debug; // for test
return tunnel$1;
}
var tunnel;
var hasRequiredTunnel;
function requireTunnel () {
if (hasRequiredTunnel) return tunnel;
hasRequiredTunnel = 1;
tunnel = requireTunnel$1();
return tunnel;
}
var tunnelExports = requireTunnel();
var undici = {};
var symbols$4;
var hasRequiredSymbols$4;
function requireSymbols$4 () {
if (hasRequiredSymbols$4) return symbols$4;
hasRequiredSymbols$4 = 1;
symbols$4 = {
kClose: Symbol('close'),
kDestroy: Symbol('destroy'),
kDispatch: Symbol('dispatch'),
kUrl: Symbol('url'),
kWriting: Symbol('writing'),
kResuming: Symbol('resuming'),
kQueue: Symbol('queue'),
kConnect: Symbol('connect'),
kConnecting: Symbol('connecting'),
kKeepAliveDefaultTimeout: Symbol('default keep alive timeout'),
kKeepAliveMaxTimeout: Symbol('max keep alive timeout'),
kKeepAliveTimeoutThreshold: Symbol('keep alive timeout threshold'),
kKeepAliveTimeoutValue: Symbol('keep alive timeout'),
kKeepAlive: Symbol('keep alive'),
kHeadersTimeout: Symbol('headers timeout'),
kBodyTimeout: Symbol('body timeout'),
kServerName: Symbol('server name'),
kLocalAddress: Symbol('local address'),
kHost: Symbol('host'),
kNoRef: Symbol('no ref'),
kBodyUsed: Symbol('used'),
kBody: Symbol('abstracted request body'),
kRunning: Symbol('running'),
kBlocking: Symbol('blocking'),
kPending: Symbol('pending'),
kSize: Symbol('size'),
kBusy: Symbol('busy'),
kQueued: Symbol('queued'),
kFree: Symbol('free'),
kConnected: Symbol('connected'),
kClosed: Symbol('closed'),
kNeedDrain: Symbol('need drain'),
kReset: Symbol('reset'),
kDestroyed: Symbol.for('nodejs.stream.destroyed'),
kResume: Symbol('resume'),
kOnError: Symbol('on error'),
kMaxHeadersSize: Symbol('max headers size'),
kRunningIdx: Symbol('running index'),
kPendingIdx: Symbol('pending index'),
kError: Symbol('error'),
kClients: Symbol('clients'),
kClient: Symbol('client'),
kParser: Symbol('parser'),
kOnDestroyed: Symbol('destroy callbacks'),
kPipelining: Symbol('pipelining'),
kSocket: Symbol('socket'),
kHostHeader: Symbol('host header'),
kConnector: Symbol('connector'),
kStrictContentLength: Symbol('strict content length'),
kMaxRedirections: Symbol('maxRedirections'),
kMaxRequests: Symbol('maxRequestsPerClient'),
kProxy: Symbol('proxy agent options'),
kCounter: Symbol('socket request counter'),
kInterceptors: Symbol('dispatch interceptors'),
kMaxResponseSize: Symbol('max response size'),
kHTTP2Session: Symbol('http2Session'),
kHTTP2SessionState: Symbol('http2Session state'),
kRetryHandlerDefaultRetry: Symbol('retry agent default retry'),
kConstruct: Symbol('constructable'),
kListeners: Symbol('listeners'),
kHTTPContext: Symbol('http context'),
kMaxConcurrentStreams: Symbol('max concurrent streams'),
kNoProxyAgent: Symbol('no proxy agent'),
kHttpProxyAgent: Symbol('http proxy agent'),
kHttpsProxyAgent: Symbol('https proxy agent')
};
return symbols$4;
}
var errors;
var hasRequiredErrors;
function requireErrors () {
if (hasRequiredErrors) return errors;
hasRequiredErrors = 1;
const kUndiciError = Symbol.for('undici.error.UND_ERR');
class UndiciError extends Error {
constructor (message) {
super(message);
this.name = 'UndiciError';
this.code = 'UND_ERR';
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kUndiciError] === true
}
[kUndiciError] = true
}
const kConnectTimeoutError = Symbol.for('undici.error.UND_ERR_CONNECT_TIMEOUT');
class ConnectTimeoutError extends UndiciError {
constructor (message) {
super(message);
this.name = 'ConnectTimeoutError';
this.message = message || 'Connect Timeout Error';
this.code = 'UND_ERR_CONNECT_TIMEOUT';
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kConnectTimeoutError] === true
}
[kConnectTimeoutError] = true
}
const kHeadersTimeoutError = Symbol.for('undici.error.UND_ERR_HEADERS_TIMEOUT');
class HeadersTimeoutError extends UndiciError {
constructor (message) {
super(message);
this.name = 'HeadersTimeoutError';
this.message = message || 'Headers Timeout Error';
this.code = 'UND_ERR_HEADERS_TIMEOUT';
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kHeadersTimeoutError] === true
}
[kHeadersTimeoutError] = true
}
const kHeadersOverflowError = Symbol.for('undici.error.UND_ERR_HEADERS_OVERFLOW');
class HeadersOverflowError extends UndiciError {
constructor (message) {
super(message);
this.name = 'HeadersOverflowError';
this.message = message || 'Headers Overflow Error';
this.code = 'UND_ERR_HEADERS_OVERFLOW';
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kHeadersOverflowError] === true
}
[kHeadersOverflowError] = true
}
const kBodyTimeoutError = Symbol.for('undici.error.UND_ERR_BODY_TIMEOUT');
class BodyTimeoutError extends UndiciError {
constructor (message) {
super(message);
this.name = 'BodyTimeoutError';
this.message = message || 'Body Timeout Error';
this.code = 'UND_ERR_BODY_TIMEOUT';
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kBodyTimeoutError] === true
}
[kBodyTimeoutError] = true
}
const kResponseStatusCodeError = Symbol.for('undici.error.UND_ERR_RESPONSE_STATUS_CODE');
class ResponseStatusCodeError extends UndiciError {
constructor (message, statusCode, headers, body) {
super(message);
this.name = 'ResponseStatusCodeError';
this.message = message || 'Response Status Code Error';
this.code = 'UND_ERR_RESPONSE_STATUS_CODE';
this.body = body;
this.status = statusCode;
this.statusCode = statusCode;
this.headers = headers;
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kResponseStatusCodeError] === true
}
[kResponseStatusCodeError] = true
}
const kInvalidArgumentError = Symbol.for('undici.error.UND_ERR_INVALID_ARG');
class InvalidArgumentError extends UndiciError {
constructor (message) {
super(message);
this.name = 'InvalidArgumentError';
this.message = message || 'Invalid Argument Error';
this.code = 'UND_ERR_INVALID_ARG';
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kInvalidArgumentError] === true
}
[kInvalidArgumentError] = true
}
const kInvalidReturnValueError = Symbol.for('undici.error.UND_ERR_INVALID_RETURN_VALUE');
class InvalidReturnValueError extends UndiciError {
constructor (message) {
super(message);
this.name = 'InvalidReturnValueError';
this.message = message || 'Invalid Return Value Error';
this.code = 'UND_ERR_INVALID_RETURN_VALUE';
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kInvalidReturnValueError] === true
}
[kInvalidReturnValueError] = true
}
const kAbortError = Symbol.for('undici.error.UND_ERR_ABORT');
class AbortError extends UndiciError {
constructor (message) {
super(message);
this.name = 'AbortError';
this.message = message || 'The operation was aborted';
this.code = 'UND_ERR_ABORT';
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kAbortError] === true
}
[kAbortError] = true
}
const kRequestAbortedError = Symbol.for('undici.error.UND_ERR_ABORTED');
class RequestAbortedError extends AbortError {
constructor (message) {
super(message);
this.name = 'AbortError';
this.message = message || 'Request aborted';
this.code = 'UND_ERR_ABORTED';
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kRequestAbortedError] === true
}
[kRequestAbortedError] = true
}
const kInformationalError = Symbol.for('undici.error.UND_ERR_INFO');
class InformationalError extends UndiciError {
constructor (message) {
super(message);
this.name = 'InformationalError';
this.message = message || 'Request information';
this.code = 'UND_ERR_INFO';
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kInformationalError] === true
}
[kInformationalError] = true
}
const kRequestContentLengthMismatchError = Symbol.for('undici.error.UND_ERR_REQ_CONTENT_LENGTH_MISMATCH');
class RequestContentLengthMismatchError extends UndiciError {
constructor (message) {
super(message);
this.name = 'RequestContentLengthMismatchError';
this.message = message || 'Request body length does not match content-length header';
this.code = 'UND_ERR_REQ_CONTENT_LENGTH_MISMATCH';
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kRequestContentLengthMismatchError] === true
}
[kRequestContentLengthMismatchError] = true
}
const kResponseContentLengthMismatchError = Symbol.for('undici.error.UND_ERR_RES_CONTENT_LENGTH_MISMATCH');
class ResponseContentLengthMismatchError extends UndiciError {
constructor (message) {
super(message);
this.name = 'ResponseContentLengthMismatchError';
this.message = message || 'Response body length does not match content-length header';
this.code = 'UND_ERR_RES_CONTENT_LENGTH_MISMATCH';
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kResponseContentLengthMismatchError] === true
}
[kResponseContentLengthMismatchError] = true
}
const kClientDestroyedError = Symbol.for('undici.error.UND_ERR_DESTROYED');
class ClientDestroyedError extends UndiciError {
constructor (message) {
super(message);
this.name = 'ClientDestroyedError';
this.message = message || 'The client is destroyed';
this.code = 'UND_ERR_DESTROYED';
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kClientDestroyedError] === true
}
[kClientDestroyedError] = true
}
const kClientClosedError = Symbol.for('undici.error.UND_ERR_CLOSED');
class ClientClosedError extends UndiciError {
constructor (message) {
super(message);
this.name = 'ClientClosedError';
this.message = message || 'The client is closed';
this.code = 'UND_ERR_CLOSED';
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kClientClosedError] === true
}
[kClientClosedError] = true
}
const kSocketError = Symbol.for('undici.error.UND_ERR_SOCKET');
class SocketError extends UndiciError {
constructor (message, socket) {
super(message);
this.name = 'SocketError';
this.message = message || 'Socket error';
this.code = 'UND_ERR_SOCKET';
this.socket = socket;
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kSocketError] === true
}
[kSocketError] = true
}
const kNotSupportedError = Symbol.for('undici.error.UND_ERR_NOT_SUPPORTED');
class NotSupportedError extends UndiciError {
constructor (message) {
super(message);
this.name = 'NotSupportedError';
this.message = message || 'Not supported error';
this.code = 'UND_ERR_NOT_SUPPORTED';
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kNotSupportedError] === true
}
[kNotSupportedError] = true
}
const kBalancedPoolMissingUpstreamError = Symbol.for('undici.error.UND_ERR_BPL_MISSING_UPSTREAM');
class BalancedPoolMissingUpstreamError extends UndiciError {
constructor (message) {
super(message);
this.name = 'MissingUpstreamError';
this.message = message || 'No upstream has been added to the BalancedPool';
this.code = 'UND_ERR_BPL_MISSING_UPSTREAM';
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kBalancedPoolMissingUpstreamError] === true
}
[kBalancedPoolMissingUpstreamError] = true
}
const kHTTPParserError = Symbol.for('undici.error.UND_ERR_HTTP_PARSER');
class HTTPParserError extends Error {
constructor (message, code, data) {
super(message);
this.name = 'HTTPParserError';
this.code = code ? `HPE_${code}` : undefined;
this.data = data ? data.toString() : undefined;
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kHTTPParserError] === true
}
[kHTTPParserError] = true
}
const kResponseExceededMaxSizeError = Symbol.for('undici.error.UND_ERR_RES_EXCEEDED_MAX_SIZE');
class ResponseExceededMaxSizeError extends UndiciError {
constructor (message) {
super(message);
this.name = 'ResponseExceededMaxSizeError';
this.message = message || 'Response content exceeded max size';
this.code = 'UND_ERR_RES_EXCEEDED_MAX_SIZE';
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kResponseExceededMaxSizeError] === true
}
[kResponseExceededMaxSizeError] = true
}
const kRequestRetryError = Symbol.for('undici.error.UND_ERR_REQ_RETRY');
class RequestRetryError extends UndiciError {
constructor (message, code, { headers, data }) {
super(message);
this.name = 'RequestRetryError';
this.message = message || 'Request retry error';
this.code = 'UND_ERR_REQ_RETRY';
this.statusCode = code;
this.data = data;
this.headers = headers;
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kRequestRetryError] === true
}
[kRequestRetryError] = true
}
const kResponseError = Symbol.for('undici.error.UND_ERR_RESPONSE');
class ResponseError extends UndiciError {
constructor (message, code, { headers, data }) {
super(message);
this.name = 'ResponseError';
this.message = message || 'Response error';
this.code = 'UND_ERR_RESPONSE';
this.statusCode = code;
this.data = data;
this.headers = headers;
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kResponseError] === true
}
[kResponseError] = true
}
const kSecureProxyConnectionError = Symbol.for('undici.error.UND_ERR_PRX_TLS');
class SecureProxyConnectionError extends UndiciError {
constructor (cause, message, options) {
super(message, { cause, ...(options ?? {}) });
this.name = 'SecureProxyConnectionError';
this.message = message || 'Secure Proxy Connection failed';
this.code = 'UND_ERR_PRX_TLS';
this.cause = cause;
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kSecureProxyConnectionError] === true
}
[kSecureProxyConnectionError] = true
}
const kMessageSizeExceededError = Symbol.for('undici.error.UND_ERR_WS_MESSAGE_SIZE_EXCEEDED');
class MessageSizeExceededError extends UndiciError {
constructor (message) {
super(message);
this.name = 'MessageSizeExceededError';
this.message = message || 'Max decompressed message size exceeded';
this.code = 'UND_ERR_WS_MESSAGE_SIZE_EXCEEDED';
}
static [Symbol.hasInstance] (instance) {
return instance && instance[kMessageSizeExceededError] === true
}
get [kMessageSizeExceededError] () {
return true
}
}
errors = {
AbortError,
HTTPParserError,
UndiciError,
HeadersTimeoutError,
HeadersOverflowError,
BodyTimeoutError,
RequestContentLengthMismatchError,
ConnectTimeoutError,
ResponseStatusCodeError,
InvalidArgumentError,
InvalidReturnValueError,
RequestAbortedError,
ClientDestroyedError,
ClientClosedError,
InformationalError,
SocketError,
NotSupportedError,
ResponseContentLengthMismatchError,
BalancedPoolMissingUpstreamError,
ResponseExceededMaxSizeError,
RequestRetryError,
ResponseError,
SecureProxyConnectionError,
MessageSizeExceededError
};
return errors;
}
var constants$5;
var hasRequiredConstants$5;
function requireConstants$5 () {
if (hasRequiredConstants$5) return constants$5;
hasRequiredConstants$5 = 1;
/** @type {Record<string, string | undefined>} */
const headerNameLowerCasedRecord = {};
// https://developer.mozilla.org/docs/Web/HTTP/Headers
const wellknownHeaderNames = [
'Accept',
'Accept-Encoding',
'Accept-Language',
'Accept-Ranges',
'Access-Control-Allow-Credentials',
'Access-Control-Allow-Headers',
'Access-Control-Allow-Methods',
'Access-Control-Allow-Origin',
'Access-Control-Expose-Headers',
'Access-Control-Max-Age',
'Access-Control-Request-Headers',
'Access-Control-Request-Method',
'Age',
'Allow',
'Alt-Svc',
'Alt-Used',
'Authorization',
'Cache-Control',
'Clear-Site-Data',
'Connection',
'Content-Disposition',
'Content-Encoding',
'Content-Language',
'Content-Length',
'Content-Location',
'Content-Range',
'Content-Security-Policy',
'Content-Security-Policy-Report-Only',
'Content-Type',
'Cookie',
'Cross-Origin-Embedder-Policy',
'Cross-Origin-Opener-Policy',
'Cross-Origin-Resource-Policy',
'Date',
'Device-Memory',
'Downlink',
'ECT',
'ETag',
'Expect',
'Expect-CT',
'Expires',
'Forwarded',
'From',
'Host',
'If-Match',
'If-Modified-Since',
'If-None-Match',
'If-Range',
'If-Unmodified-Since',
'Keep-Alive',
'Last-Modified',
'Link',
'Location',
'Max-Forwards',
'Origin',
'Permissions-Policy',
'Pragma',
'Proxy-Authenticate',
'Proxy-Authorization',
'RTT',
'Range',
'Referer',
'Referrer-Policy',
'Refresh',
'Retry-After',
'Sec-WebSocket-Accept',
'Sec-WebSocket-Extensions',
'Sec-WebSocket-Key',
'Sec-WebSocket-Protocol',
'Sec-WebSocket-Version',
'Server',
'Server-Timing',
'Service-Worker-Allowed',
'Service-Worker-Navigation-Preload',
'Set-Cookie',
'SourceMap',
'Strict-Transport-Security',
'Supports-Loading-Mode',
'TE',
'Timing-Allow-Origin',
'Trailer',
'Transfer-Encoding',
'Upgrade',
'Upgrade-Insecure-Requests',
'User-Agent',
'Vary',
'Via',
'WWW-Authenticate',
'X-Content-Type-Options',
'X-DNS-Prefetch-Control',
'X-Frame-Options',
'X-Permitted-Cross-Domain-Policies',
'X-Powered-By',
'X-Requested-With',
'X-XSS-Protection'
];
for (let i = 0; i < wellknownHeaderNames.length; ++i) {
const key = wellknownHeaderNames[i];
const lowerCasedKey = key.toLowerCase();
headerNameLowerCasedRecord[key] = headerNameLowerCasedRecord[lowerCasedKey] =
lowerCasedKey;
}
// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`.
Object.setPrototypeOf(headerNameLowerCasedRecord, null);
constants$5 = {
wellknownHeaderNames,
headerNameLowerCasedRecord
};
return constants$5;
}
var tree_1;
var hasRequiredTree;
function requireTree () {
if (hasRequiredTree) return tree_1;
hasRequiredTree = 1;
const {
wellknownHeaderNames,
headerNameLowerCasedRecord
} = requireConstants$5();
class TstNode {
/** @type {any} */
value = null
/** @type {null | TstNode} */
left = null
/** @type {null | TstNode} */
middle = null
/** @type {null | TstNode} */
right = null
/** @type {number} */
code
/**
* @param {string} key
* @param {any} value
* @param {number} index
*/
constructor (key, value, index) {
if (index === undefined || index >= key.length) {
throw new TypeError('Unreachable')
}
const code = this.code = key.charCodeAt(index);
// check code is ascii string
if (code > 0x7F) {
throw new TypeError('key must be ascii string')
}
if (key.length !== ++index) {
this.middle = new TstNode(key, value, index);
} else {
this.value = value;
}
}
/**
* @param {string} key
* @param {any} value
*/
add (key, value) {
const length = key.length;
if (length === 0) {
throw new TypeError('Unreachable')
}
let index = 0;
let node = this;
while (true) {
const code = key.charCodeAt(index);
// check code is ascii string
if (code > 0x7F) {
throw new TypeError('key must be ascii string')
}
if (node.code === code) {
if (length === ++index) {
node.value = value;
break
} else if (node.middle !== null) {
node = node.middle;
} else {
node.middle = new TstNode(key, value, index);
break
}
} else if (node.code < code) {
if (node.left !== null) {
node = node.left;
} else {
node.left = new TstNode(key, value, index);
break
}
} else if (node.right !== null) {
node = node.right;
} else {
node.right = new TstNode(key, value, index);
break
}
}
}
/**
* @param {Uint8Array} key
* @return {TstNode | null}
*/
search (key) {
const keylength = key.length;
let index = 0;
let node = this;
while (node !== null && index < keylength) {
let code = key[index];
// A-Z
// First check if it is bigger than 0x5a.
// Lowercase letters have higher char codes than uppercase ones.
// Also we assume that headers will mostly contain lowercase characters.
if (code <= 0x5a && code >= 0x41) {
// Lowercase for uppercase.
code |= 32;
}
while (node !== null) {
if (code === node.code) {
if (keylength === ++index) {
// Returns Node since it is the last key.
return node
}
node = node.middle;
break
}
node = node.code < code ? node.left : node.right;
}
}
return null
}
}
class TernarySearchTree {
/** @type {TstNode | null} */
node = null
/**
* @param {string} key
* @param {any} value
* */
insert (key, value) {
if (this.node === null) {
this.node = new TstNode(key, value, 0);
} else {
this.node.add(key, value);
}
}
/**
* @param {Uint8Array} key
* @return {any}
*/
lookup (key) {
return this.node?.search(key)?.value ?? null
}
}
const tree = new TernarySearchTree();
for (let i = 0; i < wellknownHeaderNames.length; ++i) {
const key = headerNameLowerCasedRecord[wellknownHeaderNames[i]];
tree.insert(key, key);
}
tree_1 = {
TernarySearchTree,
tree
};
return tree_1;
}
var util$7;
var hasRequiredUtil$7;
function requireUtil$7 () {
if (hasRequiredUtil$7) return util$7;
hasRequiredUtil$7 = 1;
const assert = require$$0$1;
const { kDestroyed, kBodyUsed, kListeners, kBody } = requireSymbols$4();
const { IncomingMessage } = require$$2;
const stream = require$$0$2;
const net = require$$0$3;
const { Blob } = require$$0;
const nodeUtil = require$$0$4;
const { stringify } = require$$7;
const { EventEmitter: EE } = require$$8;
const { InvalidArgumentError } = requireErrors();
const { headerNameLowerCasedRecord } = requireConstants$5();
const { tree } = requireTree();
const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(v => Number(v));
class BodyAsyncIterable {
constructor (body) {
this[kBody] = body;
this[kBodyUsed] = false;
}
async * [Symbol.asyncIterator] () {
assert(!this[kBodyUsed], 'disturbed');
this[kBodyUsed] = true;
yield * this[kBody];
}
}
function wrapRequestBody (body) {
if (isStream(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 (bodyLength(body) === 0) {
body
.on('data', function () {
assert(false);
});
}
if (typeof body.readableDidRead !== 'boolean') {
body[kBodyUsed] = false;
EE.prototype.on.call(body, 'data', function () {
this[kBodyUsed] = true;
});
}
return body
} else if (body && typeof 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.
return new BodyAsyncIterable(body)
} else if (
body &&
typeof body !== 'string' &&
!ArrayBuffer.isView(body) &&
isIterable(body)
) {
// TODO: Should we allow re-using iterable if !this.opts.idempotent
// or through some other flag?
return new BodyAsyncIterable(body)
} else {
return body
}
}
function nop () {}
function isStream (obj) {
return obj && typeof obj === 'object' && typeof obj.pipe === 'function' && typeof obj.on === 'function'
}
// based on https://github.com/node-fetch/fetch-blob/blob/8ab587d34080de94140b54f07168451e7d0b655e/index.js#L229-L241 (MIT License)
function isBlobLike (object) {
if (object === null) {
return false
} else if (object instanceof Blob) {
return true
} else if (typeof object !== 'object') {
return false
} else {
const sTag = object[Symbol.toStringTag];
return (sTag === 'Blob' || sTag === 'File') && (
('stream' in object && typeof object.stream === 'function') ||
('arrayBuffer' in object && typeof object.arrayBuffer === 'function')
)
}
}
function buildURL (url, queryParams) {
if (url.includes('?') || url.includes('#')) {
throw new Error('Query params cannot be passed when url already contains "?" or "#".')
}
const stringified = stringify(queryParams);
if (stringified) {
url += '?' + stringified;
}
return url
}
function isValidPort (port) {
const value = parseInt(port, 10);
return (
value === Number(port) &&
value >= 0 &&
value <= 65535
)
}
function isHttpOrHttpsPrefixed (value) {
return (
value != null &&
value[0] === 'h' &&
value[1] === 't' &&
value[2] === 't' &&
value[3] === 'p' &&
(
value[4] === ':' ||
(
value[4] === 's' &&
value[5] === ':'
)
)
)
}
function parseURL (url) {
if (typeof url === 'string') {
url = new URL(url);
if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.')
}
return url
}
if (!url || typeof url !== 'object') {
throw new InvalidArgumentError('Invalid URL: The URL argument must be a non-null object.')
}
if (!(url instanceof URL)) {
if (url.port != null && url.port !== '' && isValidPort(url.port) === false) {
throw new InvalidArgumentError('Invalid URL: port must be a valid integer or a string representation of an integer.')
}
if (url.path != null && typeof url.path !== 'string') {
throw new InvalidArgumentError('Invalid URL path: the path must be a string or null/undefined.')
}
if (url.pathname != null && typeof url.pathname !== 'string') {
throw new InvalidArgumentError('Invalid URL pathname: the pathname must be a string or null/undefined.')
}
if (url.hostname != null && typeof url.hostname !== 'string') {
throw new InvalidArgumentError('Invalid URL hostname: the hostname must be a string or null/undefined.')
}
if (url.origin != null && typeof url.origin !== 'string') {
throw new InvalidArgumentError('Invalid URL origin: the origin must be a string or null/undefined.')
}
if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.')
}
const port = url.port != null
? url.port
: (url.protocol === 'https:' ? 443 : 80);
let origin = url.origin != null
? url.origin
: `${url.protocol || ''}//${url.hostname || ''}:${port}`;
let path = url.path != null
? url.path
: `${url.pathname || ''}${url.search || ''}`;
if (origin[origin.length - 1] === '/') {
origin = origin.slice(0, origin.length - 1);
}
if (path && path[0] !== '/') {
path = `/${path}`;
}
// new URL(path, origin) is unsafe when `path` contains an absolute URL
// From https://developer.mozilla.org/en-US/docs/Web/API/URL/URL:
// If first parameter is a relative URL, second param is required, and will be used as the base URL.
// If first parameter is an absolute URL, a given second param will be ignored.
return new URL(`${origin}${path}`)
}
if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.')
}
return url
}
function parseOrigin (url) {
url = parseURL(url);
if (url.pathname !== '/' || url.search || url.hash) {
throw new InvalidArgumentError('invalid url')
}
return url
}
function getHostname (host) {
if (host[0] === '[') {
const idx = host.indexOf(']');
assert(idx !== -1);
return host.substring(1, idx)
}
const idx = host.indexOf(':');
if (idx === -1) return host
return host.substring(0, idx)
}
// IP addresses are not valid server names per RFC6066
// > Currently, the only server names supported are DNS hostnames
function getServerName (host) {
if (!host) {
return null
}
assert(typeof host === 'string');
const servername = getHostname(host);
if (net.isIP(servername)) {
return ''
}
return servername
}
function deepClone (obj) {
return JSON.parse(JSON.stringify(obj))
}
function isAsyncIterable (obj) {
return !!(obj != null && typeof obj[Symbol.asyncIterator] === 'function')
}
function isIterable (obj) {
return !!(obj != null && (typeof obj[Symbol.iterator] === 'function' || typeof obj[Symbol.asyncIterator] === 'function'))
}
function bodyLength (body) {
if (body == null) {
return 0
} else if (isStream(body)) {
const state = body._readableState;
return state && state.objectMode === false && state.ended === true && Number.isFinite(state.length)
? state.length
: null
} else if (isBlobLike(body)) {
return body.size != null ? body.size : null
} else if (isBuffer(body)) {
return body.byteLength
}
return null
}
function isDestroyed (body) {
return body && !!(body.destroyed || body[kDestroyed] || (stream.isDestroyed?.(body)))
}
function destroy (stream, err) {
if (stream == null || !isStream(stream) || isDestroyed(stream)) {
return
}
if (typeof stream.destroy === 'function') {
if (Object.getPrototypeOf(stream).constructor === IncomingMessage) {
// See: https://github.com/nodejs/node/pull/38505/files
stream.socket = null;
}
stream.destroy(err);
} else if (err) {
queueMicrotask(() => {
stream.emit('error', err);
});
}
if (stream.destroyed !== true) {
stream[kDestroyed] = true;
}
}
const KEEPALIVE_TIMEOUT_EXPR = /timeout=(\d+)/;
function parseKeepAliveTimeout (val) {
const m = val.toString().match(KEEPALIVE_TIMEOUT_EXPR);
return m ? parseInt(m[1], 10) * 1000 : null
}
/**
* Retrieves a header name and returns its lowercase value.
* @param {string | Buffer} value Header name
* @returns {string}
*/
function headerNameToString (value) {
return typeof value === 'string'
? headerNameLowerCasedRecord[value] ?? value.toLowerCase()
: tree.lookup(value) ?? value.toString('latin1').toLowerCase()
}
/**
* Receive the buffer as a string and return its lowercase value.
* @param {Buffer} value Header name
* @returns {string}
*/
function bufferToLowerCasedHeaderName (value) {
return tree.lookup(value) ?? value.toString('latin1').toLowerCase()
}
/**
* @param {Record<string, string | string[]> | (Buffer | string | (Buffer | string)[])[]} headers
* @param {Record<string, string | string[]>} [obj]
* @returns {Record<string, string | string[]>}
*/
function parseHeaders (headers, obj) {
if (obj === undefined) obj = {};
for (let i = 0; i < headers.length; i += 2) {
const key = headerNameToString(headers[i]);
l