mirror of
https://github.com/actions/setup-node
synced 2024-11-10 07:32:40 +00:00
234 lines
6.8 KiB
JavaScript
234 lines
6.8 KiB
JavaScript
|
import deepmerge from 'deepmerge';
|
||
|
import isPlainObject from 'is-plain-object';
|
||
|
import urlTemplate from 'url-template';
|
||
|
import getUserAgent from 'universal-user-agent';
|
||
|
|
||
|
function _slicedToArray(arr, i) {
|
||
|
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();
|
||
|
}
|
||
|
|
||
|
function _arrayWithHoles(arr) {
|
||
|
if (Array.isArray(arr)) return arr;
|
||
|
}
|
||
|
|
||
|
function _iterableToArrayLimit(arr, i) {
|
||
|
var _arr = [];
|
||
|
var _n = true;
|
||
|
var _d = false;
|
||
|
var _e = undefined;
|
||
|
|
||
|
try {
|
||
|
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
|
||
|
_arr.push(_s.value);
|
||
|
|
||
|
if (i && _arr.length === i) break;
|
||
|
}
|
||
|
} catch (err) {
|
||
|
_d = true;
|
||
|
_e = err;
|
||
|
} finally {
|
||
|
try {
|
||
|
if (!_n && _i["return"] != null) _i["return"]();
|
||
|
} finally {
|
||
|
if (_d) throw _e;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return _arr;
|
||
|
}
|
||
|
|
||
|
function _nonIterableRest() {
|
||
|
throw new TypeError("Invalid attempt to destructure non-iterable instance");
|
||
|
}
|
||
|
|
||
|
function lowercaseKeys(object) {
|
||
|
if (!object) {
|
||
|
return {};
|
||
|
}
|
||
|
|
||
|
return Object.keys(object).reduce((newObj, key) => {
|
||
|
newObj[key.toLowerCase()] = object[key];
|
||
|
return newObj;
|
||
|
}, {});
|
||
|
}
|
||
|
|
||
|
function merge(defaults, route, options) {
|
||
|
if (typeof route === "string") {
|
||
|
let _route$split = route.split(" "),
|
||
|
_route$split2 = _slicedToArray(_route$split, 2),
|
||
|
method = _route$split2[0],
|
||
|
url = _route$split2[1];
|
||
|
|
||
|
options = Object.assign(url ? {
|
||
|
method,
|
||
|
url
|
||
|
} : {
|
||
|
url: method
|
||
|
}, options);
|
||
|
} else {
|
||
|
options = route || {};
|
||
|
} // lowercase header names before merging with defaults to avoid duplicates
|
||
|
|
||
|
|
||
|
options.headers = lowercaseKeys(options.headers);
|
||
|
const mergedOptions = deepmerge.all([defaults, options].filter(Boolean), {
|
||
|
isMergeableObject: isPlainObject
|
||
|
}); // mediaType.previews arrays are merged, instead of overwritten
|
||
|
|
||
|
if (defaults && defaults.mediaType.previews.length) {
|
||
|
mergedOptions.mediaType.previews = defaults.mediaType.previews.filter(preview => !mergedOptions.mediaType.previews.includes(preview)).concat(mergedOptions.mediaType.previews);
|
||
|
}
|
||
|
|
||
|
mergedOptions.mediaType.previews = mergedOptions.mediaType.previews.map(preview => preview.replace(/-preview/, ""));
|
||
|
return mergedOptions;
|
||
|
}
|
||
|
|
||
|
function addQueryParameters(url, parameters) {
|
||
|
const separator = /\?/.test(url) ? "&" : "?";
|
||
|
const names = Object.keys(parameters);
|
||
|
|
||
|
if (names.length === 0) {
|
||
|
return url;
|
||
|
}
|
||
|
|
||
|
return url + separator + names.map(name => {
|
||
|
if (name === "q") {
|
||
|
return "q=" + parameters.q.split("+").map(encodeURIComponent).join("+");
|
||
|
}
|
||
|
|
||
|
return "".concat(name, "=").concat(encodeURIComponent(parameters[name]));
|
||
|
}).join("&");
|
||
|
}
|
||
|
|
||
|
const urlVariableRegex = /\{[^}]+\}/g;
|
||
|
|
||
|
function removeNonChars(variableName) {
|
||
|
return variableName.replace(/^\W+|\W+$/g, "").split(/,/);
|
||
|
}
|
||
|
|
||
|
function extractUrlVariableNames(url) {
|
||
|
const matches = url.match(urlVariableRegex);
|
||
|
|
||
|
if (!matches) {
|
||
|
return [];
|
||
|
}
|
||
|
|
||
|
return matches.map(removeNonChars).reduce((a, b) => a.concat(b), []);
|
||
|
}
|
||
|
|
||
|
function omit(object, keysToOmit) {
|
||
|
return Object.keys(object).filter(option => !keysToOmit.includes(option)).reduce((obj, key) => {
|
||
|
obj[key] = object[key];
|
||
|
return obj;
|
||
|
}, {});
|
||
|
}
|
||
|
|
||
|
function parse(options) {
|
||
|
// https://fetch.spec.whatwg.org/#methods
|
||
|
let method = options.method.toUpperCase(); // replace :varname with {varname} to make it RFC 6570 compatible
|
||
|
|
||
|
let url = options.url.replace(/:([a-z]\w+)/g, "{+$1}");
|
||
|
let headers = Object.assign({}, options.headers);
|
||
|
let body;
|
||
|
let parameters = omit(options, ["method", "baseUrl", "url", "headers", "request", "mediaType"]); // extract variable names from URL to calculate remaining variables later
|
||
|
|
||
|
const urlVariableNames = extractUrlVariableNames(url);
|
||
|
url = urlTemplate.parse(url).expand(parameters);
|
||
|
|
||
|
if (!/^http/.test(url)) {
|
||
|
url = options.baseUrl + url;
|
||
|
}
|
||
|
|
||
|
const omittedParameters = Object.keys(options).filter(option => urlVariableNames.includes(option)).concat("baseUrl");
|
||
|
const remainingParameters = omit(parameters, omittedParameters);
|
||
|
const isBinaryRequset = /application\/octet-stream/i.test(headers.accept);
|
||
|
|
||
|
if (!isBinaryRequset) {
|
||
|
if (options.mediaType.format) {
|
||
|
// e.g. application/vnd.github.v3+json => application/vnd.github.v3.raw
|
||
|
headers.accept = headers.accept.split(/,/).map(preview => preview.replace(/application\/vnd(\.\w+)(\.v3)?(\.\w+)?(\+json)?$/, "application/vnd$1$2.".concat(options.mediaType.format))).join(",");
|
||
|
}
|
||
|
|
||
|
if (options.mediaType.previews.length) {
|
||
|
const previewsFromAcceptHeader = headers.accept.match(/[\w-]+(?=-preview)/g) || [];
|
||
|
headers.accept = previewsFromAcceptHeader.concat(options.mediaType.previews).map(preview => {
|
||
|
const format = options.mediaType.format ? ".".concat(options.mediaType.format) : "+json";
|
||
|
return "application/vnd.github.".concat(preview, "-preview").concat(format);
|
||
|
}).join(",");
|
||
|
}
|
||
|
} // for GET/HEAD requests, set URL query parameters from remaining parameters
|
||
|
// for PATCH/POST/PUT/DELETE requests, set request body from remaining parameters
|
||
|
|
||
|
|
||
|
if (["GET", "HEAD"].includes(method)) {
|
||
|
url = addQueryParameters(url, remainingParameters);
|
||
|
} else {
|
||
|
if ("data" in remainingParameters) {
|
||
|
body = remainingParameters.data;
|
||
|
} else {
|
||
|
if (Object.keys(remainingParameters).length) {
|
||
|
body = remainingParameters;
|
||
|
} else {
|
||
|
headers["content-length"] = 0;
|
||
|
}
|
||
|
}
|
||
|
} // default content-type for JSON if body is set
|
||
|
|
||
|
|
||
|
if (!headers["content-type"] && typeof body !== "undefined") {
|
||
|
headers["content-type"] = "application/json; charset=utf-8";
|
||
|
} // GitHub expects 'content-length: 0' header for PUT/PATCH requests without body.
|
||
|
// fetch does not allow to set `content-length` header, but we can set body to an empty string
|
||
|
|
||
|
|
||
|
if (["PATCH", "PUT"].includes(method) && typeof body === "undefined") {
|
||
|
body = "";
|
||
|
} // Only return body/request keys if present
|
||
|
|
||
|
|
||
|
return Object.assign({
|
||
|
method,
|
||
|
url,
|
||
|
headers
|
||
|
}, typeof body !== "undefined" ? {
|
||
|
body
|
||
|
} : null, options.request ? {
|
||
|
request: options.request
|
||
|
} : null);
|
||
|
}
|
||
|
|
||
|
function endpointWithDefaults(defaults, route, options) {
|
||
|
return parse(merge(defaults, route, options));
|
||
|
}
|
||
|
|
||
|
function withDefaults(oldDefaults, newDefaults) {
|
||
|
const DEFAULTS = merge(oldDefaults, newDefaults);
|
||
|
const endpoint = endpointWithDefaults.bind(null, DEFAULTS);
|
||
|
return Object.assign(endpoint, {
|
||
|
DEFAULTS,
|
||
|
defaults: withDefaults.bind(null, DEFAULTS),
|
||
|
merge: merge.bind(null, DEFAULTS),
|
||
|
parse
|
||
|
});
|
||
|
}
|
||
|
|
||
|
const VERSION = "0.0.0-development";
|
||
|
|
||
|
const userAgent = "octokit-endpoint.js/".concat(VERSION, " ").concat(getUserAgent());
|
||
|
const DEFAULTS = {
|
||
|
method: "GET",
|
||
|
baseUrl: "https://api.github.com",
|
||
|
headers: {
|
||
|
accept: "application/vnd.github.v3+json",
|
||
|
"user-agent": userAgent
|
||
|
},
|
||
|
mediaType: {
|
||
|
format: "",
|
||
|
previews: []
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const endpoint = withDefaults(null, DEFAULTS);
|
||
|
|
||
|
export { endpoint };
|