UNPKG

5.07 kBJavaScriptView Raw
1import { ApolloLink, Observable, concat, toPromise, execute } from 'apollo-link';
2import { createUploadLink, isExtractableFile, formDataAppendFile } from 'apollo-upload-client';
3import FormData from 'form-data';
4import { fetch } from 'cross-fetch';
5import { observableToAsyncIterable } from '@graphql-tools/utils';
6import { GraphQLScalarType, GraphQLError } from 'graphql';
7import isPromise from 'is-promise';
8
9function getFinalPromise(object) {
10 return Promise.resolve(object).then(resolvedObject => {
11 if (resolvedObject == null) {
12 return resolvedObject;
13 }
14 if (Array.isArray(resolvedObject)) {
15 return Promise.all(resolvedObject.map(o => getFinalPromise(o)));
16 }
17 else if (typeof resolvedObject === 'object') {
18 const keys = Object.keys(resolvedObject);
19 return Promise.all(keys.map(key => getFinalPromise(resolvedObject[key]))).then(awaitedValues => {
20 for (let i = 0; i < keys.length; i++) {
21 resolvedObject[keys[i]] = awaitedValues[i];
22 }
23 return resolvedObject;
24 });
25 }
26 return resolvedObject;
27 });
28}
29class AwaitVariablesLink extends ApolloLink {
30 request(operation, forward) {
31 return new Observable(observer => {
32 let subscription;
33 getFinalPromise(operation.variables)
34 .then(resolvedVariables => {
35 operation.variables = resolvedVariables;
36 subscription = forward(operation).subscribe({
37 next: observer.next.bind(observer),
38 error: observer.error.bind(observer),
39 complete: observer.complete.bind(observer),
40 });
41 })
42 .catch(observer.error.bind(observer));
43 return () => {
44 if (subscription != null) {
45 subscription.unsubscribe();
46 }
47 };
48 });
49 }
50}
51
52class FormDataWithStreamSupport extends FormData {
53 constructor(options) {
54 super(options);
55 this.hasUnknowableLength = false;
56 }
57 append(key, value, optionsOrFilename = {}) {
58 // allow filename as single option
59 const options = typeof optionsOrFilename === 'string' ? { filename: optionsOrFilename } : optionsOrFilename;
60 // empty or either doesn't have path or not an http response
61 if (!options.knownLength &&
62 !Buffer.isBuffer(value) &&
63 typeof value !== 'string' &&
64 !value.path &&
65 !(value.readable && 'httpVersion' in value)) {
66 this.hasUnknowableLength = true;
67 }
68 super.append(key, value, options);
69 }
70 getLength(callback) {
71 if (this.hasUnknowableLength) {
72 return null;
73 }
74 return super.getLength(callback);
75 }
76 getLengthSync() {
77 if (this.hasUnknowableLength) {
78 return null;
79 }
80 // eslint-disable-next-line no-sync
81 return super.getLengthSync();
82 }
83}
84const createServerHttpLink = (options) => concat(new AwaitVariablesLink(), createUploadLink({
85 ...options,
86 fetch,
87 FormData: FormDataWithStreamSupport,
88 isExtractableFile: (value) => isExtractableFile(value) || (value === null || value === void 0 ? void 0 : value.createReadStream),
89 formDataAppendFile: (form, index, file) => {
90 if (file.createReadStream != null) {
91 form.append(index, file.createReadStream(), {
92 filename: file.filename,
93 contentType: file.mimetype,
94 });
95 }
96 else {
97 formDataAppendFile(form, index, file);
98 }
99 },
100}));
101
102const linkToExecutor = (link) => ({ document, variables, context, info, }) => toPromise(execute(link, {
103 query: document,
104 variables,
105 context: {
106 graphqlContext: context,
107 graphqlResolveInfo: info,
108 clientAwareness: {},
109 },
110}));
111
112const linkToSubscriber = (link) => async ({ document, variables, context, info, }) => observableToAsyncIterable(execute(link, {
113 query: document,
114 variables,
115 context: {
116 graphqlContext: context,
117 graphqlResolveInfo: info,
118 clientAwareness: {},
119 },
120}));
121
122const GraphQLUpload = new GraphQLScalarType({
123 name: 'Upload',
124 description: 'The `Upload` scalar type represents a file upload.',
125 parseValue: value => {
126 if (value != null && isPromise(value.promise)) {
127 // graphql-upload v10
128 return value.promise;
129 }
130 else if (isPromise(value)) {
131 // graphql-upload v9
132 return value;
133 }
134 throw new GraphQLError('Upload value invalid.');
135 },
136 // serialization requires to support schema stitching
137 serialize: value => value,
138 parseLiteral: ast => {
139 throw new GraphQLError('Upload literal unsupported.', ast);
140 },
141});
142
143export { AwaitVariablesLink, GraphQLUpload, createServerHttpLink, linkToExecutor, linkToSubscriber };
144//# sourceMappingURL=index.esm.js.map