github.com/jfrog/frogbot@v1.1.1-0.20231221090046-821a26f50338/action/node_modules/@octokit/endpoint/dist-web/index.js (about) 1 import { isPlainObject } from 'is-plain-object'; 2 import { getUserAgent } from 'universal-user-agent'; 3 4 function lowercaseKeys(object) { 5 if (!object) { 6 return {}; 7 } 8 return Object.keys(object).reduce((newObj, key) => { 9 newObj[key.toLowerCase()] = object[key]; 10 return newObj; 11 }, {}); 12 } 13 14 function mergeDeep(defaults, options) { 15 const result = Object.assign({}, defaults); 16 Object.keys(options).forEach((key) => { 17 if (isPlainObject(options[key])) { 18 if (!(key in defaults)) 19 Object.assign(result, { [key]: options[key] }); 20 else 21 result[key] = mergeDeep(defaults[key], options[key]); 22 } 23 else { 24 Object.assign(result, { [key]: options[key] }); 25 } 26 }); 27 return result; 28 } 29 30 function removeUndefinedProperties(obj) { 31 for (const key in obj) { 32 if (obj[key] === undefined) { 33 delete obj[key]; 34 } 35 } 36 return obj; 37 } 38 39 function merge(defaults, route, options) { 40 if (typeof route === "string") { 41 let [method, url] = route.split(" "); 42 options = Object.assign(url ? { method, url } : { url: method }, options); 43 } 44 else { 45 options = Object.assign({}, route); 46 } 47 // lowercase header names before merging with defaults to avoid duplicates 48 options.headers = lowercaseKeys(options.headers); 49 // remove properties with undefined values before merging 50 removeUndefinedProperties(options); 51 removeUndefinedProperties(options.headers); 52 const mergedOptions = mergeDeep(defaults || {}, options); 53 // mediaType.previews arrays are merged, instead of overwritten 54 if (defaults && defaults.mediaType.previews.length) { 55 mergedOptions.mediaType.previews = defaults.mediaType.previews 56 .filter((preview) => !mergedOptions.mediaType.previews.includes(preview)) 57 .concat(mergedOptions.mediaType.previews); 58 } 59 mergedOptions.mediaType.previews = mergedOptions.mediaType.previews.map((preview) => preview.replace(/-preview/, "")); 60 return mergedOptions; 61 } 62 63 function addQueryParameters(url, parameters) { 64 const separator = /\?/.test(url) ? "&" : "?"; 65 const names = Object.keys(parameters); 66 if (names.length === 0) { 67 return url; 68 } 69 return (url + 70 separator + 71 names 72 .map((name) => { 73 if (name === "q") { 74 return ("q=" + parameters.q.split("+").map(encodeURIComponent).join("+")); 75 } 76 return `${name}=${encodeURIComponent(parameters[name])}`; 77 }) 78 .join("&")); 79 } 80 81 const urlVariableRegex = /\{[^}]+\}/g; 82 function removeNonChars(variableName) { 83 return variableName.replace(/^\W+|\W+$/g, "").split(/,/); 84 } 85 function extractUrlVariableNames(url) { 86 const matches = url.match(urlVariableRegex); 87 if (!matches) { 88 return []; 89 } 90 return matches.map(removeNonChars).reduce((a, b) => a.concat(b), []); 91 } 92 93 function omit(object, keysToOmit) { 94 return Object.keys(object) 95 .filter((option) => !keysToOmit.includes(option)) 96 .reduce((obj, key) => { 97 obj[key] = object[key]; 98 return obj; 99 }, {}); 100 } 101 102 // Based on https://github.com/bramstein/url-template, licensed under BSD 103 // TODO: create separate package. 104 // 105 // Copyright (c) 2012-2014, Bram Stein 106 // All rights reserved. 107 // Redistribution and use in source and binary forms, with or without 108 // modification, are permitted provided that the following conditions 109 // are met: 110 // 1. Redistributions of source code must retain the above copyright 111 // notice, this list of conditions and the following disclaimer. 112 // 2. Redistributions in binary form must reproduce the above copyright 113 // notice, this list of conditions and the following disclaimer in the 114 // documentation and/or other materials provided with the distribution. 115 // 3. The name of the author may not be used to endorse or promote products 116 // derived from this software without specific prior written permission. 117 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED 118 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 119 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 120 // EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 121 // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 122 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 123 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 124 // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 125 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 126 // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 127 /* istanbul ignore file */ 128 function encodeReserved(str) { 129 return str 130 .split(/(%[0-9A-Fa-f]{2})/g) 131 .map(function (part) { 132 if (!/%[0-9A-Fa-f]/.test(part)) { 133 part = encodeURI(part).replace(/%5B/g, "[").replace(/%5D/g, "]"); 134 } 135 return part; 136 }) 137 .join(""); 138 } 139 function encodeUnreserved(str) { 140 return encodeURIComponent(str).replace(/[!'()*]/g, function (c) { 141 return "%" + c.charCodeAt(0).toString(16).toUpperCase(); 142 }); 143 } 144 function encodeValue(operator, value, key) { 145 value = 146 operator === "+" || operator === "#" 147 ? encodeReserved(value) 148 : encodeUnreserved(value); 149 if (key) { 150 return encodeUnreserved(key) + "=" + value; 151 } 152 else { 153 return value; 154 } 155 } 156 function isDefined(value) { 157 return value !== undefined && value !== null; 158 } 159 function isKeyOperator(operator) { 160 return operator === ";" || operator === "&" || operator === "?"; 161 } 162 function getValues(context, operator, key, modifier) { 163 var value = context[key], result = []; 164 if (isDefined(value) && value !== "") { 165 if (typeof value === "string" || 166 typeof value === "number" || 167 typeof value === "boolean") { 168 value = value.toString(); 169 if (modifier && modifier !== "*") { 170 value = value.substring(0, parseInt(modifier, 10)); 171 } 172 result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : "")); 173 } 174 else { 175 if (modifier === "*") { 176 if (Array.isArray(value)) { 177 value.filter(isDefined).forEach(function (value) { 178 result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : "")); 179 }); 180 } 181 else { 182 Object.keys(value).forEach(function (k) { 183 if (isDefined(value[k])) { 184 result.push(encodeValue(operator, value[k], k)); 185 } 186 }); 187 } 188 } 189 else { 190 const tmp = []; 191 if (Array.isArray(value)) { 192 value.filter(isDefined).forEach(function (value) { 193 tmp.push(encodeValue(operator, value)); 194 }); 195 } 196 else { 197 Object.keys(value).forEach(function (k) { 198 if (isDefined(value[k])) { 199 tmp.push(encodeUnreserved(k)); 200 tmp.push(encodeValue(operator, value[k].toString())); 201 } 202 }); 203 } 204 if (isKeyOperator(operator)) { 205 result.push(encodeUnreserved(key) + "=" + tmp.join(",")); 206 } 207 else if (tmp.length !== 0) { 208 result.push(tmp.join(",")); 209 } 210 } 211 } 212 } 213 else { 214 if (operator === ";") { 215 if (isDefined(value)) { 216 result.push(encodeUnreserved(key)); 217 } 218 } 219 else if (value === "" && (operator === "&" || operator === "?")) { 220 result.push(encodeUnreserved(key) + "="); 221 } 222 else if (value === "") { 223 result.push(""); 224 } 225 } 226 return result; 227 } 228 function parseUrl(template) { 229 return { 230 expand: expand.bind(null, template), 231 }; 232 } 233 function expand(template, context) { 234 var operators = ["+", "#", ".", "/", ";", "?", "&"]; 235 return template.replace(/\{([^\{\}]+)\}|([^\{\}]+)/g, function (_, expression, literal) { 236 if (expression) { 237 let operator = ""; 238 const values = []; 239 if (operators.indexOf(expression.charAt(0)) !== -1) { 240 operator = expression.charAt(0); 241 expression = expression.substr(1); 242 } 243 expression.split(/,/g).forEach(function (variable) { 244 var tmp = /([^:\*]*)(?::(\d+)|(\*))?/.exec(variable); 245 values.push(getValues(context, operator, tmp[1], tmp[2] || tmp[3])); 246 }); 247 if (operator && operator !== "+") { 248 var separator = ","; 249 if (operator === "?") { 250 separator = "&"; 251 } 252 else if (operator !== "#") { 253 separator = operator; 254 } 255 return (values.length !== 0 ? operator : "") + values.join(separator); 256 } 257 else { 258 return values.join(","); 259 } 260 } 261 else { 262 return encodeReserved(literal); 263 } 264 }); 265 } 266 267 function parse(options) { 268 // https://fetch.spec.whatwg.org/#methods 269 let method = options.method.toUpperCase(); 270 // replace :varname with {varname} to make it RFC 6570 compatible 271 let url = (options.url || "/").replace(/:([a-z]\w+)/g, "{$1}"); 272 let headers = Object.assign({}, options.headers); 273 let body; 274 let parameters = omit(options, [ 275 "method", 276 "baseUrl", 277 "url", 278 "headers", 279 "request", 280 "mediaType", 281 ]); 282 // extract variable names from URL to calculate remaining variables later 283 const urlVariableNames = extractUrlVariableNames(url); 284 url = parseUrl(url).expand(parameters); 285 if (!/^http/.test(url)) { 286 url = options.baseUrl + url; 287 } 288 const omittedParameters = Object.keys(options) 289 .filter((option) => urlVariableNames.includes(option)) 290 .concat("baseUrl"); 291 const remainingParameters = omit(parameters, omittedParameters); 292 const isBinaryRequest = /application\/octet-stream/i.test(headers.accept); 293 if (!isBinaryRequest) { 294 if (options.mediaType.format) { 295 // e.g. application/vnd.github.v3+json => application/vnd.github.v3.raw 296 headers.accept = headers.accept 297 .split(/,/) 298 .map((preview) => preview.replace(/application\/vnd(\.\w+)(\.v3)?(\.\w+)?(\+json)?$/, `application/vnd$1$2.${options.mediaType.format}`)) 299 .join(","); 300 } 301 if (options.mediaType.previews.length) { 302 const previewsFromAcceptHeader = headers.accept.match(/[\w-]+(?=-preview)/g) || []; 303 headers.accept = previewsFromAcceptHeader 304 .concat(options.mediaType.previews) 305 .map((preview) => { 306 const format = options.mediaType.format 307 ? `.${options.mediaType.format}` 308 : "+json"; 309 return `application/vnd.github.${preview}-preview${format}`; 310 }) 311 .join(","); 312 } 313 } 314 // for GET/HEAD requests, set URL query parameters from remaining parameters 315 // for PATCH/POST/PUT/DELETE requests, set request body from remaining parameters 316 if (["GET", "HEAD"].includes(method)) { 317 url = addQueryParameters(url, remainingParameters); 318 } 319 else { 320 if ("data" in remainingParameters) { 321 body = remainingParameters.data; 322 } 323 else { 324 if (Object.keys(remainingParameters).length) { 325 body = remainingParameters; 326 } 327 else { 328 headers["content-length"] = 0; 329 } 330 } 331 } 332 // default content-type for JSON if body is set 333 if (!headers["content-type"] && typeof body !== "undefined") { 334 headers["content-type"] = "application/json; charset=utf-8"; 335 } 336 // GitHub expects 'content-length: 0' header for PUT/PATCH requests without body. 337 // fetch does not allow to set `content-length` header, but we can set body to an empty string 338 if (["PATCH", "PUT"].includes(method) && typeof body === "undefined") { 339 body = ""; 340 } 341 // Only return body/request keys if present 342 return Object.assign({ method, url, headers }, typeof body !== "undefined" ? { body } : null, options.request ? { request: options.request } : null); 343 } 344 345 function endpointWithDefaults(defaults, route, options) { 346 return parse(merge(defaults, route, options)); 347 } 348 349 function withDefaults(oldDefaults, newDefaults) { 350 const DEFAULTS = merge(oldDefaults, newDefaults); 351 const endpoint = endpointWithDefaults.bind(null, DEFAULTS); 352 return Object.assign(endpoint, { 353 DEFAULTS, 354 defaults: withDefaults.bind(null, DEFAULTS), 355 merge: merge.bind(null, DEFAULTS), 356 parse, 357 }); 358 } 359 360 const VERSION = "6.0.12"; 361 362 const userAgent = `octokit-endpoint.js/${VERSION} ${getUserAgent()}`; 363 // DEFAULTS has all properties set that EndpointOptions has, except url. 364 // So we use RequestParameters and add method as additional required property. 365 const DEFAULTS = { 366 method: "GET", 367 baseUrl: "https://api.github.com", 368 headers: { 369 accept: "application/vnd.github.v3+json", 370 "user-agent": userAgent, 371 }, 372 mediaType: { 373 format: "", 374 previews: [], 375 }, 376 }; 377 378 const endpoint = withDefaults(null, DEFAULTS); 379 380 export { endpoint }; 381 //# sourceMappingURL=index.js.map