import { DocumentNode, Kind, OperationDefinitionNode, print } from 'graphql'; export interface FilePlaceholder { file: null; } export interface UploadPostData { operations: { operationName: string; variables: V; query: string; }; map: { [index: number]: string; }; filePaths: Array<{ name: string; file: string; }>; } /** * Creates a data structure which can be used to mae a curl request to upload files to a mutation using * the Upload type. */ export function createUploadPostData

( mutation: DocumentNode, filePaths: P, mapVariables: (filePaths: P) => V, ): UploadPostData { const operationDef = mutation.definitions.find( d => d.kind === Kind.OPERATION_DEFINITION, ) as OperationDefinitionNode; const filePathsArray = (Array.isArray(filePaths) ? filePaths : [filePaths]) as string[]; const variables = mapVariables(filePaths); const postData: UploadPostData = { operations: { operationName: operationDef.name ? operationDef.name.value : 'AnonymousMutation', variables, query: print(mutation), }, map: filePathsArray.reduce( (output, filePath, i) => { return { ...output, [i.toString()]: objectPath(variables, i).join('.') }; }, {} as { [index: number]: string }, ), filePaths: filePathsArray.map((filePath, i) => ({ name: i.toString(), file: filePath, })), }; return postData; } function objectPath(variables: any, i: number): Array { const path: Array = ['variables']; let current = variables; while (current !== null) { const props = Object.getOwnPropertyNames(current); if (props) { const firstProp = props[0]; const val = current[firstProp]; if (Array.isArray(val)) { path.push(firstProp); path.push(i); current = val[0]; } else { path.push(firstProp); current = val; } } } return path; }