-
-
Notifications
You must be signed in to change notification settings - Fork 22
/
fetchOptionsGraphQL.mjs
70 lines (58 loc) · 2.09 KB
/
fetchOptionsGraphQL.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// @ts-check
/** @import { GraphQLOperation } from "./types.mjs" */
import extractFiles from "extract-files/extractFiles.mjs";
import isExtractableFile from "extract-files/isExtractableFile.mjs";
/**
* Creates default {@link RequestInit `fetch` options} for a
* {@link GraphQLOperation GraphQL operation}. If the operation contains files
* to upload, the options will be for a
* [GraphQL multipart request](https://github.com/jaydenseric/graphql-multipart-request-spec),
* otherwise they will be for a regular
* [GraphQL `POST` request](https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md#post).
*
* This utility exists for convenience in projects and isn’t used directly by
* this library. Avoid using it if there’s no chance the operation contains
* files.
* @param {GraphQLOperation} operation GraphQL operation.
* @returns {RequestInit} [`fetch`](https://developer.mozilla.org/docs/Web/API/Fetch_API) options.
*/
export default function fetchOptionsGraphQL(operation) {
/** @type {RequestInit} */
const fetchOptions = {
method: "POST",
headers: {
Accept: "application/json",
},
};
const { clone, files } = extractFiles(operation, isExtractableFile);
const operationJSON = JSON.stringify(clone);
if (files.size) {
// See the GraphQL multipart request spec:
// https://github.com/jaydenseric/graphql-multipart-request-spec
const form = new FormData();
form.set("operations", operationJSON);
/** @type {{ [formFieldName: string]: Array<string> }} */
const map = {};
let i = 0;
files.forEach((paths) => {
map[++i] = paths;
});
form.set("map", JSON.stringify(map));
i = 0;
files.forEach((paths, file) => {
form.set(
`${++i}`,
file,
// @ts-ignore It’s ok for `name` to be undefined for a `Blob` instance.
file.name,
);
});
fetchOptions.body = form;
} else {
/** @type {{ [headerName: string]: string }} */ (fetchOptions.headers)[
"Content-Type"
] = "application/json";
fetchOptions.body = operationJSON;
}
return fetchOptions;
}