"use strict";;
const {
    __DEV__
} = require("@apollo/client/utilities/environment");

Object.defineProperty(exports, "__esModule", { value: true });
exports.createHttpLink = void 0;
const rxjs_1 = require("rxjs");
const core_1 = require("@apollo/client/link/core");
const utils_1 = require("@apollo/client/link/utils");
const utilities_1 = require("@apollo/client/utilities");
const utilities_2 = require("@apollo/client/utilities");
const environment_1 = require("@apollo/client/utilities/environment");
const invariant_1 = require("@apollo/client/utilities/invariant");
const checkFetcher_js_1 = require("./checkFetcher.cjs");
const parseAndCheckHttpResponse_js_1 = require("./parseAndCheckHttpResponse.cjs");
const rewriteURIForGET_js_1 = require("./rewriteURIForGET.cjs");
const selectHttpOptionsAndBody_js_1 = require("./selectHttpOptionsAndBody.cjs");
const selectURI_js_1 = require("./selectURI.cjs");
const serializeFetchParameter_js_1 = require("./serializeFetchParameter.cjs");
const backupFetch = (0, utilities_2.maybe)(() => fetch);
const createHttpLink = (linkOptions = {}) => {
    let { uri = "/graphql", 
    // use default global fetch if nothing passed in
    fetch: preferredFetch, print = selectHttpOptionsAndBody_js_1.defaultPrinter, includeExtensions, preserveHeaderCase, useGETForQueries, includeUnusedVariables = false, ...requestOptions } = linkOptions;
    if (environment_1.__DEV__) {
        // Make sure at least one of preferredFetch, window.fetch, or backupFetch is
        // defined, so requests won't fail at runtime.
        (0, checkFetcher_js_1.checkFetcher)(preferredFetch || backupFetch);
    }
    const linkConfig = {
        http: { includeExtensions, preserveHeaderCase },
        options: requestOptions.fetchOptions,
        credentials: requestOptions.credentials,
        headers: requestOptions.headers,
    };
    return new core_1.ApolloLink((operation) => {
        let chosenURI = (0, selectURI_js_1.selectURI)(operation, uri);
        const 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`.
        const clientAwarenessHeaders = {};
        if (context.clientAwareness) {
            const { name, version } = context.clientAwareness;
            if (name) {
                clientAwarenessHeaders["apollographql-client-name"] = name;
            }
            if (version) {
                clientAwarenessHeaders["apollographql-client-version"] = version;
            }
        }
        const contextHeaders = { ...clientAwarenessHeaders, ...context.headers };
        const contextConfig = {
            http: context.http,
            options: context.fetchOptions,
            credentials: context.credentials,
            headers: contextHeaders,
        };
        if ((0, utilities_1.hasDirectives)(["client"], operation.query)) {
            const transformedQuery = (0, utilities_2.removeClientSetsFromDocument)(operation.query);
            if (!transformedQuery) {
                return (0, rxjs_1.throwError)(() => 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
        const { options, body } = (0, selectHttpOptionsAndBody_js_1.selectHttpOptionsAndBodyInternal)(operation, print, selectHttpOptionsAndBody_js_1.fallbackHttpConfig, linkConfig, contextConfig);
        if (body.variables && !includeUnusedVariables) {
            body.variables = (0, utils_1.filterOperationVariables)(body.variables, operation.query);
        }
        let 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.
        const definitionIsMutation = (d) => {
            return d.kind === "OperationDefinition" && d.operation === "mutation";
        };
        const definitionIsSubscription = (d) => {
            return d.kind === "OperationDefinition" && d.operation === "subscription";
        };
        const isSubscription = definitionIsSubscription((0, utilities_2.getMainDefinition)(operation.query));
        // does not match custom directives beginning with @defer
        const hasDefer = (0, utilities_1.hasDirectives)(["defer"], operation.query);
        if (useGETForQueries &&
            !operation.query.definitions.some(definitionIsMutation)) {
            options.method = "GET";
        }
        if (hasDefer || isSubscription) {
            options.headers = options.headers || {};
            let 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) {
                __DEV__ && invariant_1.invariant.warn(53);
            }
            if (isSubscription) {
                acceptHeader +=
                    "boundary=graphql;subscriptionSpec=1.0,application/json";
            }
            else if (hasDefer) {
                acceptHeader += "deferSpec=20220824,application/json";
            }
            options.headers.accept = acceptHeader;
        }
        return new rxjs_1.Observable((observer) => {
            if (options.method === "GET") {
                const { newURI, parseError } = (0, rewriteURIForGET_js_1.rewriteURIForGET)(chosenURI, body);
                if (parseError) {
                    throw parseError;
                }
                chosenURI = newURI;
            }
            else {
                options.body = (0, serializeFetchParameter_js_1.serializeFetchParameter)(body, "Payload");
            }
            // 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.
            const currentFetch = preferredFetch || (0, utilities_2.maybe)(() => fetch) || backupFetch;
            const observerNext = observer.next.bind(observer);
            currentFetch(chosenURI, options)
                .then((response) => {
                operation.setContext({ response });
                const ctype = response.headers?.get("content-type");
                if (ctype !== null && /^multipart\/mixed/i.test(ctype)) {
                    return (0, parseAndCheckHttpResponse_js_1.readMultipartBody)(response, observerNext);
                }
                else {
                    return (0, parseAndCheckHttpResponse_js_1.parseAndCheckHttpResponse)(operation)(response).then(observerNext);
                }
            })
                .then(() => {
                controller = undefined;
                observer.complete();
            })
                .catch((err) => {
                controller = undefined;
                (0, parseAndCheckHttpResponse_js_1.handleError)(err, observer);
            });
            return () => {
                // XXX support canceling this request
                // https://developers.google.com/web/updates/2017/09/abortable-fetch
                if (controller)
                    controller.abort();
            };
        });
    });
};
exports.createHttpLink = createHttpLink;
//# sourceMappingURL=createHttpLink.cjs.map
