123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- import { isPlainObject } from 'is-plain-object';
- import { getUserAgent } from 'universal-user-agent';
- function lowercaseKeys(object) {
- if (!object) {
- return {};
- }
- return Object.keys(object).reduce((newObj, key) => {
- newObj[key.toLowerCase()] = object[key];
- return newObj;
- }, {});
- }
- function mergeDeep(defaults, options) {
- const result = Object.assign({}, defaults);
- Object.keys(options).forEach((key) => {
- if (isPlainObject(options[key])) {
- if (!(key in defaults))
- Object.assign(result, { [key]: options[key] });
- else
- result[key] = mergeDeep(defaults[key], options[key]);
- }
- else {
- Object.assign(result, { [key]: options[key] });
- }
- });
- return result;
- }
- function removeUndefinedProperties(obj) {
- for (const key in obj) {
- if (obj[key] === undefined) {
- delete obj[key];
- }
- }
- return obj;
- }
- function merge(defaults, route, options) {
- if (typeof route === "string") {
- let [method, url] = route.split(" ");
- options = Object.assign(url ? { method, url } : { url: method }, options);
- }
- else {
- options = Object.assign({}, route);
- }
- // lowercase header names before merging with defaults to avoid duplicates
- options.headers = lowercaseKeys(options.headers);
- // remove properties with undefined values before merging
- removeUndefinedProperties(options);
- removeUndefinedProperties(options.headers);
- const mergedOptions = mergeDeep(defaults || {}, options);
- // 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 `${name}=${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;
- }, {});
- }
- // Based on https://github.com/bramstein/url-template, licensed under BSD
- // TODO: create separate package.
- //
- // Copyright (c) 2012-2014, Bram Stein
- // All rights reserved.
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions
- // are met:
- // 1. Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- // 2. Redistributions in binary form must reproduce the above copyright
- // notice, this list of conditions and the following disclaimer in the
- // documentation and/or other materials provided with the distribution.
- // 3. The name of the author may not be used to endorse or promote products
- // derived from this software without specific prior written permission.
- // THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
- // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- // EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- /* istanbul ignore file */
- function encodeReserved(str) {
- return str
- .split(/(%[0-9A-Fa-f]{2})/g)
- .map(function (part) {
- if (!/%[0-9A-Fa-f]/.test(part)) {
- part = encodeURI(part).replace(/%5B/g, "[").replace(/%5D/g, "]");
- }
- return part;
- })
- .join("");
- }
- function encodeUnreserved(str) {
- return encodeURIComponent(str).replace(/[!'()*]/g, function (c) {
- return "%" + c.charCodeAt(0).toString(16).toUpperCase();
- });
- }
- function encodeValue(operator, value, key) {
- value =
- operator === "+" || operator === "#"
- ? encodeReserved(value)
- : encodeUnreserved(value);
- if (key) {
- return encodeUnreserved(key) + "=" + value;
- }
- else {
- return value;
- }
- }
- function isDefined(value) {
- return value !== undefined && value !== null;
- }
- function isKeyOperator(operator) {
- return operator === ";" || operator === "&" || operator === "?";
- }
- function getValues(context, operator, key, modifier) {
- var value = context[key], result = [];
- if (isDefined(value) && value !== "") {
- if (typeof value === "string" ||
- typeof value === "number" ||
- typeof value === "boolean") {
- value = value.toString();
- if (modifier && modifier !== "*") {
- value = value.substring(0, parseInt(modifier, 10));
- }
- result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : ""));
- }
- else {
- if (modifier === "*") {
- if (Array.isArray(value)) {
- value.filter(isDefined).forEach(function (value) {
- result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : ""));
- });
- }
- else {
- Object.keys(value).forEach(function (k) {
- if (isDefined(value[k])) {
- result.push(encodeValue(operator, value[k], k));
- }
- });
- }
- }
- else {
- const tmp = [];
- if (Array.isArray(value)) {
- value.filter(isDefined).forEach(function (value) {
- tmp.push(encodeValue(operator, value));
- });
- }
- else {
- Object.keys(value).forEach(function (k) {
- if (isDefined(value[k])) {
- tmp.push(encodeUnreserved(k));
- tmp.push(encodeValue(operator, value[k].toString()));
- }
- });
- }
- if (isKeyOperator(operator)) {
- result.push(encodeUnreserved(key) + "=" + tmp.join(","));
- }
- else if (tmp.length !== 0) {
- result.push(tmp.join(","));
- }
- }
- }
- }
- else {
- if (operator === ";") {
- if (isDefined(value)) {
- result.push(encodeUnreserved(key));
- }
- }
- else if (value === "" && (operator === "&" || operator === "?")) {
- result.push(encodeUnreserved(key) + "=");
- }
- else if (value === "") {
- result.push("");
- }
- }
- return result;
- }
- function parseUrl(template) {
- return {
- expand: expand.bind(null, template),
- };
- }
- function expand(template, context) {
- var operators = ["+", "#", ".", "/", ";", "?", "&"];
- return template.replace(/\{([^\{\}]+)\}|([^\{\}]+)/g, function (_, expression, literal) {
- if (expression) {
- let operator = "";
- const values = [];
- if (operators.indexOf(expression.charAt(0)) !== -1) {
- operator = expression.charAt(0);
- expression = expression.substr(1);
- }
- expression.split(/,/g).forEach(function (variable) {
- var tmp = /([^:\*]*)(?::(\d+)|(\*))?/.exec(variable);
- values.push(getValues(context, operator, tmp[1], tmp[2] || tmp[3]));
- });
- if (operator && operator !== "+") {
- var separator = ",";
- if (operator === "?") {
- separator = "&";
- }
- else if (operator !== "#") {
- separator = operator;
- }
- return (values.length !== 0 ? operator : "") + values.join(separator);
- }
- else {
- return values.join(",");
- }
- }
- else {
- return encodeReserved(literal);
- }
- });
- }
- 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 = parseUrl(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 isBinaryRequest = /application\/octet-stream/i.test(headers.accept);
- if (!isBinaryRequest) {
- 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.${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
- ? `.${options.mediaType.format}`
- : "+json";
- return `application/vnd.github.${preview}-preview${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 = "6.0.12";
- const userAgent = `octokit-endpoint.js/${VERSION} ${getUserAgent()}`;
- // DEFAULTS has all properties set that EndpointOptions has, except url.
- // So we use RequestParameters and add method as additional required property.
- 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 };
- //# sourceMappingURL=index.js.map
|