import { __assign, __rest } from "tslib"; import { invariant } from "../../utilities/globals/index.js"; import { ApolloLink } from "../core/index.js"; import { Observable, hasDirectives } from "../../utilities/index.js"; import { serializeFetchParameter } from "./serializeFetchParameter.js"; import { selectURI } from "./selectURI.js"; import { handleError, readMultipartBody, parseAndCheckHttpResponse, } from "./parseAndCheckHttpResponse.js"; import { checkFetcher } from "./checkFetcher.js"; import { selectHttpOptionsAndBodyInternal, defaultPrinter, fallbackHttpConfig, } from "./selectHttpOptionsAndBody.js"; import { rewriteURIForGET } from "./rewriteURIForGET.js"; import { fromError, filterOperationVariables } from "../utils/index.js"; import { maybe, getMainDefinition, removeClientSetsFromDocument, } from "../../utilities/index.js"; var backupFetch = maybe(function () { return fetch; }); export var createHttpLink = function (linkOptions) { if (linkOptions === void 0) { linkOptions = {}; } var _a = linkOptions.uri, uri = _a === void 0 ? "/graphql" : _a, // use default global fetch if nothing passed in preferredFetch = linkOptions.fetch, _b = linkOptions.print, print = _b === void 0 ? defaultPrinter : _b, includeExtensions = linkOptions.includeExtensions, preserveHeaderCase = linkOptions.preserveHeaderCase, useGETForQueries = linkOptions.useGETForQueries, _c = linkOptions.includeUnusedVariables, includeUnusedVariables = _c === void 0 ? false : _c, requestOptions = __rest(linkOptions, ["uri", "fetch", "print", "includeExtensions", "preserveHeaderCase", "useGETForQueries", "includeUnusedVariables"]); if (globalThis.__DEV__ !== false) { // Make sure at least one of preferredFetch, window.fetch, or backupFetch is // defined, so requests won't fail at runtime. checkFetcher(preferredFetch || backupFetch); } var linkConfig = { http: { includeExtensions: includeExtensions, preserveHeaderCase: preserveHeaderCase }, options: requestOptions.fetchOptions, credentials: requestOptions.credentials, headers: requestOptions.headers, }; return new ApolloLink(function (operation) { var chosenURI = selectURI(operation, uri); var context = operation.getContext(); // `apollographql-client-*` headers are automatically set if a // `clientAwareness` object is found in the context. These headers are // set first, followed by the rest of the headers pulled from // `context.headers`. If desired, `apollographql-client-*` headers set by // the `clientAwareness` object can be overridden by // `apollographql-client-*` headers set in `context.headers`. var clientAwarenessHeaders = {}; if (context.clientAwareness) { var _a = context.clientAwareness, name_1 = _a.name, version = _a.version; if (name_1) { clientAwarenessHeaders["apollographql-client-name"] = name_1; } if (version) { clientAwarenessHeaders["apollographql-client-version"] = version; } } var contextHeaders = __assign(__assign({}, clientAwarenessHeaders), context.headers); var contextConfig = { http: context.http, options: context.fetchOptions, credentials: context.credentials, headers: contextHeaders, }; if (hasDirectives(["client"], operation.query)) { var transformedQuery = removeClientSetsFromDocument(operation.query); if (!transformedQuery) { return fromError(new Error("HttpLink: Trying to send a client-only query to the server. To send to the server, ensure a non-client field is added to the query or set the `transformOptions.removeClientFields` option to `true`.")); } operation.query = transformedQuery; } //uses fallback, link, and then context to build options var _b = selectHttpOptionsAndBodyInternal(operation, print, fallbackHttpConfig, linkConfig, contextConfig), options = _b.options, body = _b.body; if (body.variables && !includeUnusedVariables) { body.variables = filterOperationVariables(body.variables, operation.query); } var controller; if (!options.signal && typeof AbortController !== "undefined") { controller = new AbortController(); options.signal = controller.signal; } // If requested, set method to GET if there are no mutations. var definitionIsMutation = function (d) { return d.kind === "OperationDefinition" && d.operation === "mutation"; }; var definitionIsSubscription = function (d) { return d.kind === "OperationDefinition" && d.operation === "subscription"; }; var isSubscription = definitionIsSubscription(getMainDefinition(operation.query)); // does not match custom directives beginning with @defer var hasDefer = hasDirectives(["defer"], operation.query); if (useGETForQueries && !operation.query.definitions.some(definitionIsMutation)) { options.method = "GET"; } if (hasDefer || isSubscription) { options.headers = options.headers || {}; var acceptHeader = "multipart/mixed;"; // Omit defer-specific headers if the user attempts to defer a selection // set on a subscription and log a warning. if (isSubscription && hasDefer) { globalThis.__DEV__ !== false && invariant.warn(38); } if (isSubscription) { acceptHeader += "boundary=graphql;subscriptionSpec=1.0,application/json"; } else if (hasDefer) { acceptHeader += "deferSpec=20220824,application/json"; } options.headers.accept = acceptHeader; } if (options.method === "GET") { var _c = rewriteURIForGET(chosenURI, body), newURI = _c.newURI, parseError = _c.parseError; if (parseError) { return fromError(parseError); } chosenURI = newURI; } else { try { options.body = serializeFetchParameter(body, "Payload"); } catch (parseError) { return fromError(parseError); } } return new Observable(function (observer) { // Prefer linkOptions.fetch (preferredFetch) if provided, and otherwise // fall back to the *current* global window.fetch function (see issue // #7832), or (if all else fails) the backupFetch function we saved when // this module was first evaluated. This last option protects against the // removal of window.fetch, which is unlikely but not impossible. var currentFetch = preferredFetch || maybe(function () { return fetch; }) || backupFetch; var observerNext = observer.next.bind(observer); currentFetch(chosenURI, options) .then(function (response) { var _a; operation.setContext({ response: response }); var ctype = (_a = response.headers) === null || _a === void 0 ? void 0 : _a.get("content-type"); if (ctype !== null && /^multipart\/mixed/i.test(ctype)) { return readMultipartBody(response, observerNext); } else { return parseAndCheckHttpResponse(operation)(response).then(observerNext); } }) .then(function () { controller = undefined; observer.complete(); }) .catch(function (err) { controller = undefined; handleError(err, observer); }); return function () { // XXX support canceling this request // https://developers.google.com/web/updates/2017/09/abortable-fetch if (controller) controller.abort(); }; }); }); }; //# sourceMappingURL=createHttpLink.js.map