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);
 | |
| }
 |