create-upload-post-data.ts 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. import { DocumentNode, Kind, OperationDefinitionNode, print } from 'graphql';
  2. export interface FilePlaceholder {
  3. file: null;
  4. }
  5. export interface UploadPostData<V = any> {
  6. operations: {
  7. operationName: string;
  8. variables: V;
  9. query: string;
  10. };
  11. map: {
  12. [index: number]: string;
  13. };
  14. filePaths: Array<{
  15. name: string;
  16. file: string;
  17. }>;
  18. }
  19. /**
  20. * Creates a data structure which can be used to mae a curl request to upload files to a mutation using
  21. * the Upload type.
  22. */
  23. export function createUploadPostData<P extends string[] | string, V>(
  24. mutation: DocumentNode,
  25. filePaths: P,
  26. mapVariables: (filePaths: P) => V,
  27. ): UploadPostData<V> {
  28. const operationDef = mutation.definitions.find(
  29. d => d.kind === Kind.OPERATION_DEFINITION,
  30. ) as OperationDefinitionNode;
  31. const filePathsArray = (Array.isArray(filePaths) ? filePaths : [filePaths]) as string[];
  32. const variables = mapVariables(filePaths);
  33. const postData: UploadPostData = {
  34. operations: {
  35. operationName: operationDef.name ? operationDef.name.value : 'AnonymousMutation',
  36. variables,
  37. query: print(mutation),
  38. },
  39. map: filePathsArray.reduce(
  40. (output, filePath, i) => {
  41. return { ...output, [i.toString()]: objectPath(variables, i).join('.') };
  42. },
  43. {} as { [index: number]: string },
  44. ),
  45. filePaths: filePathsArray.map((filePath, i) => ({
  46. name: i.toString(),
  47. file: filePath,
  48. })),
  49. };
  50. return postData;
  51. }
  52. function objectPath(variables: any, i: number): Array<string | number> {
  53. const path: Array<string | number> = ['variables'];
  54. let current = variables;
  55. while (current !== null) {
  56. const props = Object.getOwnPropertyNames(current);
  57. if (props) {
  58. const firstProp = props[0];
  59. const val = current[firstProp];
  60. if (Array.isArray(val)) {
  61. path.push(firstProp);
  62. path.push(i);
  63. current = val[0];
  64. } else {
  65. path.push(firstProp);
  66. current = val;
  67. }
  68. }
  69. }
  70. return path;
  71. }