1 | import { ApolloLink, concat, execute } from '@apollo/client/link/core';
|
2 | import { createUploadLink, isExtractableFile, formDataAppendFile } from 'apollo-upload-client';
|
3 | import FormData from 'form-data';
|
4 | import { fetch } from 'cross-fetch';
|
5 | import { Observable } from '@apollo/client/utilities';
|
6 | import { toPromise } from '@apollo/client/core';
|
7 | import { observableToAsyncIterable } from '@graphql-tools/utils';
|
8 | import { GraphQLScalarType, GraphQLError } from 'graphql';
|
9 | import isPromise from 'is-promise';
|
10 |
|
11 | function getFinalPromise(object) {
|
12 | return Promise.resolve(object).then(resolvedObject => {
|
13 | if (resolvedObject == null) {
|
14 | return resolvedObject;
|
15 | }
|
16 | if (Array.isArray(resolvedObject)) {
|
17 | return Promise.all(resolvedObject.map(o => getFinalPromise(o)));
|
18 | }
|
19 | else if (typeof resolvedObject === 'object') {
|
20 | const keys = Object.keys(resolvedObject);
|
21 | return Promise.all(keys.map(key => getFinalPromise(resolvedObject[key]))).then(awaitedValues => {
|
22 | for (let i = 0; i < keys.length; i++) {
|
23 | resolvedObject[keys[i]] = awaitedValues[i];
|
24 | }
|
25 | return resolvedObject;
|
26 | });
|
27 | }
|
28 | return resolvedObject;
|
29 | });
|
30 | }
|
31 | class AwaitVariablesLink extends ApolloLink {
|
32 | request(operation, forward) {
|
33 | return new Observable(observer => {
|
34 | let subscription;
|
35 | getFinalPromise(operation.variables)
|
36 | .then(resolvedVariables => {
|
37 | operation.variables = resolvedVariables;
|
38 | subscription = forward(operation).subscribe({
|
39 | next: observer.next.bind(observer),
|
40 | error: observer.error.bind(observer),
|
41 | complete: observer.complete.bind(observer),
|
42 | });
|
43 | })
|
44 | .catch(observer.error.bind(observer));
|
45 | return () => {
|
46 | if (subscription != null) {
|
47 | subscription.unsubscribe();
|
48 | }
|
49 | };
|
50 | });
|
51 | }
|
52 | }
|
53 |
|
54 | const createServerHttpLink = (options) => concat(new AwaitVariablesLink(), createUploadLink({
|
55 | ...options,
|
56 | fetch,
|
57 | FormData,
|
58 | isExtractableFile: (value) => isExtractableFile(value) || (value === null || value === void 0 ? void 0 : value.createReadStream),
|
59 | formDataAppendFile: (form, index, file) => {
|
60 | if (file.createReadStream != null) {
|
61 | form.append(index, file.createReadStream(), {
|
62 | filename: file.filename,
|
63 | contentType: file.mimetype,
|
64 | });
|
65 | }
|
66 | else {
|
67 | formDataAppendFile(form, index, file);
|
68 | }
|
69 | },
|
70 | }));
|
71 |
|
72 | const linkToExecutor = (link) => async (params) => {
|
73 | const { document, variables, extensions, context, operationType, operationName, info } = params;
|
74 | const observable = execute(link, {
|
75 | query: document,
|
76 | variables,
|
77 | context: {
|
78 | graphqlContext: context,
|
79 | graphqlResolveInfo: info,
|
80 | clientAwareness: {},
|
81 | },
|
82 | extensions,
|
83 | operationName,
|
84 | });
|
85 | if (operationType === 'subscription') {
|
86 | return observableToAsyncIterable(observable)[Symbol.asyncIterator]();
|
87 | }
|
88 | return toPromise(observable);
|
89 | };
|
90 |
|
91 | const GraphQLUpload = new GraphQLScalarType({
|
92 | name: 'Upload',
|
93 | description: 'The `Upload` scalar type represents a file upload.',
|
94 | parseValue: value => {
|
95 | if (value != null && isPromise(value.promise)) {
|
96 |
|
97 | return value.promise;
|
98 | }
|
99 | else if (isPromise(value)) {
|
100 |
|
101 | return value;
|
102 | }
|
103 | throw new GraphQLError('Upload value invalid.');
|
104 | },
|
105 |
|
106 | serialize: value => value,
|
107 | parseLiteral: ast => {
|
108 | throw new GraphQLError('Upload literal unsupported.', ast);
|
109 | },
|
110 | });
|
111 |
|
112 | export { AwaitVariablesLink, GraphQLUpload, createServerHttpLink, linkToExecutor };
|