graphql-request
Version:
Minimal GraphQL client supporting Node and browsers for scripts or simple apps
69 lines (55 loc) • 2.1 kB
text/typescript
import { isExtractableFile, extractFiles, ExtractableFile } from 'extract-files'
import FormDataNode from 'form-data'
import { defaultJsonSerializer } from './defaultJsonSerializer'
import { Variables } from './types'
/**
* Duck type if NodeJS stream
* https://github.com/sindresorhus/is-stream/blob/3750505b0727f6df54324784fe369365ef78841e/index.js#L3
*/
const isExtractableFileEnhanced = (value: any): value is ExtractableFile | { pipe: Function } =>
isExtractableFile(value) ||
(value !== null && typeof value === 'object' && typeof value.pipe === 'function')
/**
* Returns Multipart Form if body contains files
* (https://github.com/jaydenseric/graphql-multipart-request-spec)
* Otherwise returns JSON
*/
export default function createRequestBody(
query: string | string[],
variables?: Variables | Variables[],
operationName?: string,
jsonSerializer = defaultJsonSerializer
): string | FormData {
const { clone, files } = extractFiles({ query, variables, operationName }, '', isExtractableFileEnhanced)
if (files.size === 0) {
if (!Array.isArray(query)) {
return jsonSerializer.stringify(clone)
}
if (typeof variables !== 'undefined' && !Array.isArray(variables)) {
throw new Error('Cannot create request body with given variable type, array expected')
}
// Batch support
const payload = query.reduce<{ query: string; variables: Variables | undefined }[]>(
(accu, currentQuery, index) => {
accu.push({ query: currentQuery, variables: variables ? variables[index] : undefined })
return accu
},
[]
)
return jsonSerializer.stringify(payload)
}
const Form = typeof FormData === 'undefined' ? FormDataNode : FormData
const form = new Form()
form.append('operations', jsonSerializer.stringify(clone))
const map: { [key: number]: string[] } = {}
let i = 0
files.forEach((paths) => {
map[++i] = paths
})
form.append('map', jsonSerializer.stringify(map))
i = 0
files.forEach((paths, file) => {
form.append(`${++i}`, file as any)
})
return form as FormData
}