UNPKG

11.8 kBJavaScriptView Raw
1import { __awaiter, __generator, __read, __values, __assign } from 'tslib';
2import { Kind, print } from 'graphql';
3import { observableToAsyncIterable } from '@graphql-tools/utils/es5';
4import { isWebUri } from 'valid-url';
5import { fetch } from 'cross-fetch';
6import { introspectSchema, wrapSchema } from '@graphql-tools/wrap/es5';
7import { SubscriptionClient } from 'subscriptions-transport-ws';
8import { w3cwebsocket } from 'websocket';
9
10/**
11 * This loader loads a schema from a URL. The loaded schema is a fully-executable,
12 * remote schema since it's created using [@graphql-tools/wrap](/docs/remote-schemas).
13 *
14 * ```
15 * const schema = await loadSchema('http://localhost:3000/graphql', {
16 * loaders: [
17 * new UrlLoader(),
18 * ]
19 * });
20 * ```
21 */
22var UrlLoader = /** @class */ (function () {
23 function UrlLoader() {
24 }
25 UrlLoader.prototype.loaderId = function () {
26 return 'url';
27 };
28 UrlLoader.prototype.canLoad = function (pointer, options) {
29 return __awaiter(this, void 0, void 0, function () {
30 return __generator(this, function (_a) {
31 return [2 /*return*/, this.canLoadSync(pointer, options)];
32 });
33 });
34 };
35 UrlLoader.prototype.canLoadSync = function (pointer, _options) {
36 return !!isWebUri(pointer);
37 };
38 UrlLoader.prototype.buildAsyncExecutor = function (_a) {
39 var _this = this;
40 var pointer = _a.pointer, fetch = _a.fetch, extraHeaders = _a.extraHeaders, defaultMethod = _a.defaultMethod, useGETForQueries = _a.useGETForQueries;
41 var HTTP_URL = switchProtocols(pointer, {
42 wss: 'https',
43 ws: 'http',
44 });
45 return function (_a) {
46 var document = _a.document, variables = _a.variables;
47 return __awaiter(_this, void 0, void 0, function () {
48 var method, _b, _c, definition, fetchResult, query, _d, urlObj, finalUrl;
49 var e_1, _e;
50 return __generator(this, function (_f) {
51 switch (_f.label) {
52 case 0:
53 method = defaultMethod;
54 if (useGETForQueries) {
55 method = 'GET';
56 try {
57 for (_b = __values(document.definitions), _c = _b.next(); !_c.done; _c = _b.next()) {
58 definition = _c.value;
59 if (definition.kind === Kind.OPERATION_DEFINITION) {
60 if (definition.operation !== 'query') {
61 method = defaultMethod;
62 }
63 }
64 }
65 }
66 catch (e_1_1) { e_1 = { error: e_1_1 }; }
67 finally {
68 try {
69 if (_c && !_c.done && (_e = _b.return)) _e.call(_b);
70 }
71 finally { if (e_1) throw e_1.error; }
72 }
73 }
74 query = print(document);
75 _d = method;
76 switch (_d) {
77 case 'GET': return [3 /*break*/, 1];
78 case 'POST': return [3 /*break*/, 3];
79 }
80 return [3 /*break*/, 5];
81 case 1:
82 urlObj = new URL(HTTP_URL);
83 urlObj.searchParams.set('query', query);
84 if (variables && Object.keys(variables).length > 0) {
85 urlObj.searchParams.set('variables', JSON.stringify(variables));
86 }
87 finalUrl = urlObj.toString();
88 return [4 /*yield*/, fetch(finalUrl, {
89 method: 'GET',
90 headers: extraHeaders,
91 })];
92 case 2:
93 fetchResult = _f.sent();
94 return [3 /*break*/, 5];
95 case 3: return [4 /*yield*/, fetch(HTTP_URL, {
96 method: 'POST',
97 body: JSON.stringify({
98 query: query,
99 variables: variables,
100 }),
101 headers: extraHeaders,
102 })];
103 case 4:
104 fetchResult = _f.sent();
105 return [3 /*break*/, 5];
106 case 5: return [2 /*return*/, fetchResult.json()];
107 }
108 });
109 });
110 };
111 };
112 UrlLoader.prototype.buildSubscriber = function (pointer, webSocketImpl) {
113 var _this = this;
114 var WS_URL = switchProtocols(pointer, {
115 https: 'wss',
116 http: 'ws',
117 });
118 var subscriptionClient = new SubscriptionClient(WS_URL, {}, webSocketImpl);
119 return function (_a) {
120 var document = _a.document, variables = _a.variables;
121 return __awaiter(_this, void 0, void 0, function () {
122 return __generator(this, function (_b) {
123 return [2 /*return*/, observableToAsyncIterable(subscriptionClient.request({
124 query: document,
125 variables: variables,
126 }))];
127 });
128 });
129 };
130 };
131 UrlLoader.prototype.getExecutorAndSubscriber = function (pointer, options) {
132 return __awaiter(this, void 0, void 0, function () {
133 var headers, fetch$1, defaultMethod, webSocketImpl, _a, moduleName, fetchFnName_1, _b, moduleName, webSocketImplName_1, extraHeaders, executor, subscriber;
134 return __generator(this, function (_c) {
135 switch (_c.label) {
136 case 0:
137 headers = {};
138 fetch$1 = fetch;
139 defaultMethod = 'POST';
140 webSocketImpl = w3cwebsocket;
141 if (!options) return [3 /*break*/, 7];
142 if (Array.isArray(options.headers)) {
143 headers = options.headers.reduce(function (prev, v) { return (__assign(__assign({}, prev), v)); }, {});
144 }
145 else if (typeof options.headers === 'object') {
146 headers = options.headers;
147 }
148 if (!options.customFetch) return [3 /*break*/, 3];
149 if (!(typeof options.customFetch === 'string')) return [3 /*break*/, 2];
150 _a = __read(options.customFetch.split('#'), 2), moduleName = _a[0], fetchFnName_1 = _a[1];
151 return [4 /*yield*/, import(moduleName).then(function (module) { return (fetchFnName_1 ? module[fetchFnName_1] : module); })];
152 case 1:
153 fetch$1 = _c.sent();
154 return [3 /*break*/, 3];
155 case 2:
156 fetch$1 = options.customFetch;
157 _c.label = 3;
158 case 3:
159 if (!options.webSocketImpl) return [3 /*break*/, 6];
160 if (!(typeof options.webSocketImpl === 'string')) return [3 /*break*/, 5];
161 _b = __read(options.webSocketImpl.split('#'), 2), moduleName = _b[0], webSocketImplName_1 = _b[1];
162 return [4 /*yield*/, import(moduleName).then(function (module) {
163 return webSocketImplName_1 ? module[webSocketImplName_1] : module;
164 })];
165 case 4:
166 webSocketImpl = _c.sent();
167 return [3 /*break*/, 6];
168 case 5:
169 webSocketImpl = options.webSocketImpl;
170 _c.label = 6;
171 case 6:
172 if (options.method) {
173 defaultMethod = options.method;
174 }
175 _c.label = 7;
176 case 7:
177 extraHeaders = __assign({ Accept: 'application/json', 'Content-Type': 'application/json' }, headers);
178 executor = this.buildAsyncExecutor({
179 pointer: pointer,
180 fetch: fetch$1,
181 extraHeaders: extraHeaders,
182 defaultMethod: defaultMethod,
183 useGETForQueries: options.useGETForQueries,
184 });
185 if (options.enableSubscriptions) {
186 subscriber = this.buildSubscriber(pointer, webSocketImpl);
187 }
188 return [2 /*return*/, {
189 executor: executor,
190 subscriber: subscriber,
191 }];
192 }
193 });
194 });
195 };
196 UrlLoader.prototype.getSubschemaConfig = function (pointer, options) {
197 return __awaiter(this, void 0, void 0, function () {
198 var _a, executor, subscriber;
199 var _b;
200 return __generator(this, function (_c) {
201 switch (_c.label) {
202 case 0: return [4 /*yield*/, this.getExecutorAndSubscriber(pointer, options)];
203 case 1:
204 _a = _c.sent(), executor = _a.executor, subscriber = _a.subscriber;
205 _b = {};
206 return [4 /*yield*/, introspectSchema(executor, undefined, options)];
207 case 2: return [2 /*return*/, (_b.schema = _c.sent(),
208 _b.executor = executor,
209 _b.subscriber = subscriber,
210 _b)];
211 }
212 });
213 });
214 };
215 UrlLoader.prototype.load = function (pointer, options) {
216 return __awaiter(this, void 0, void 0, function () {
217 var subschemaConfig, remoteExecutableSchema;
218 return __generator(this, function (_a) {
219 switch (_a.label) {
220 case 0: return [4 /*yield*/, this.getSubschemaConfig(pointer, options)];
221 case 1:
222 subschemaConfig = _a.sent();
223 remoteExecutableSchema = wrapSchema(subschemaConfig);
224 return [2 /*return*/, {
225 location: pointer,
226 schema: remoteExecutableSchema,
227 }];
228 }
229 });
230 });
231 };
232 UrlLoader.prototype.loadSync = function () {
233 throw new Error('Loader Url has no sync mode');
234 };
235 return UrlLoader;
236}());
237function switchProtocols(pointer, protocolMap) {
238 var protocols = Object.keys(protocolMap).map(function (source) { return [source, protocolMap[source]]; });
239 return protocols.reduce(function (prev, _a) {
240 var _b = __read(_a, 2), source = _b[0], target = _b[1];
241 return prev.replace(source + "://", target + "://").replace(source + ":\\", target + ":\\");
242 }, pointer);
243}
244
245export { UrlLoader };
246//# sourceMappingURL=index.esm.js.map