| 'use strict'; | |
| Object.defineProperty(exports, '__esModule', { value: true }); | |
| var isPlainObject = require('is-plain-object'); | |
| var universalUserAgent = require('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.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} ${universalUserAgent.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); | |
| exports.endpoint = endpoint; | |
| //# sourceMappingURL=index.js.map |