82 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			82 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								import urlTemplate from "url-template";
							 | 
						||
| 
								 | 
							
								import { addQueryParameters } from "./util/add-query-parameters";
							 | 
						||
| 
								 | 
							
								import { extractUrlVariableNames } from "./util/extract-url-variable-names";
							 | 
						||
| 
								 | 
							
								import { omit } from "./util/omit";
							 | 
						||
| 
								 | 
							
								export 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.${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);
							 | 
						||
| 
								 | 
							
								}
							 |