2019-08-06 17:37:58 -04:00
'use strict' ;
Object . defineProperty ( exports , '__esModule' , { value : true });
function _interopDefault ( ex ) { return ( ex && ( typeof ex === 'object' ) && 'default' in ex ) ? ex [ 'default' ] : ex ; }
var isPlainObject = _interopDefault ( require ( 'is-plain-object' ));
2020-05-15 15:25:57 -04:00
var universalUserAgent = require ( 'universal-user-agent' );
2019-08-06 17:37:58 -04:00
function lowercaseKeys ( object ) {
if ( ! object ) {
return {};
}
return Object . keys ( object ). reduce (( newObj , key ) => {
newObj [ key . toLowerCase ()] = object [ key ];
return newObj ;
}, {});
}
2020-05-15 15:25:57 -04:00
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 ;
}
2019-08-06 17:37:58 -04:00
function merge ( defaults , route , options ) {
if ( typeof route === "string" ) {
let [ method , url ] = route . split ( " " );
options = Object . assign ( url ? {
method ,
url
} : {
url : method
}, options );
} else {
2020-05-15 15:25:57 -04:00
options = Object . assign ({}, route );
2019-08-06 17:37:58 -04:00
} // lowercase header names before merging with defaults to avoid duplicates
options . headers = lowercaseKeys ( options . headers );
2020-05-15 15:25:57 -04:00
const mergedOptions = mergeDeep ( defaults || {}, options ); // mediaType.previews arrays are merged, instead of overwritten
2019-08-06 17:37:58 -04:00
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 ;
}, {});
}
2020-05-15 15:25:57 -04:00
// 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 );
}
});
}
2019-08-06 17:37:58 -04:00
function parse ( options ) {
// https://fetch.spec.whatwg.org/#methods
let method = options . method . toUpperCase (); // replace :varname with {varname} to make it RFC 6570 compatible
2020-05-15 15:25:57 -04:00
let url = ( options . url || "/" ). replace ( /:([a-z]\w+)/g , "{+$1}" );
2019-08-06 17:37:58 -04:00
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 );
2020-05-15 15:25:57 -04:00
url = parseUrl ( url ). expand ( parameters );
2019-08-06 17:37:58 -04:00
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. ${ 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
});
}
2020-05-15 15:25:57 -04:00
const VERSION = "6.0.1" ;
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.
2019-08-06 17:37:58 -04:00
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 ;
2020-05-15 15:25:57 -04:00
//# sourceMappingURL=index.js.map