Add support for file uploads in Relay Environment

Add support for file uploads in RelayEnvironment by implementing
multipart form[1] handling via FormData when uploadables are
present. Maintain backward compatibility for standard GraphQL queries.

[1] https://github.com/jaydenseric/graphql-multipart-request-spec

Signed-off-by: gearnode <bryan@frimin.fr>
This commit is contained in:
gearnode
2025-02-28 10:57:35 +01:00
parent 9f03583edf
commit fc5a97cb64

View File

@@ -7,21 +7,60 @@ import {
} from "relay-runtime"; } from "relay-runtime";
import { buildEndpoint } from "./utils"; import { buildEndpoint } from "./utils";
const fetchRelay: FetchFunction = async (request, variables) => { const fetchRelay: FetchFunction = async (request, variables, _, uploadables) => {
const response = await fetch(buildEndpoint("/console/v1/query"), { const requestInit: RequestInit = {
method: "POST", method: 'POST',
credentials: "include", credentials: 'include',
headers: { headers: {},
Accept: };
"application/graphql-response+json; charset=utf-8, application/json; charset=utf-8",
"Content-Type": "application/json",
}, if (uploadables) {
body: JSON.stringify({ const formData = new FormData();
formData.append(
'operations',
JSON.stringify({
operationName: request.name,
query: request.text,
variables: variables,
})
);
const uploadableMap: {
[key: string]: string[];
} = {};
Object.keys(uploadables).forEach((key, index) => {
if (Object.prototype.hasOwnProperty.call(uploadables, key)) {
uploadableMap[index] = [`variables.${key}`];
}
});
formData.append('map', JSON.stringify(uploadableMap));
Object.keys(uploadables).forEach((key, index) => {
if (Object.prototype.hasOwnProperty.call(uploadables, key)) {
formData.append(index.toString(), uploadables[key]);
}
});
requestInit.body = formData;
} else {
requestInit.headers = {
"Accept": "application/graphql-response+json; charset=utf-8, application/json; charset=utf-8",
"Content-Type": "application/json"
}
requestInit.body = JSON.stringify({
operationName: request.name, operationName: request.name,
query: request.text, query: request.text,
variables, variables,
}),
}); });
}
const response = await fetch(buildEndpoint("/console/v1/query"), requestInit);
const json = await response.json(); const json = await response.json();