"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseHttpLink = void 0;
const rxjs_1 = require("rxjs");
const link_1 = require("@apollo/client/link");
const utils_1 = require("@apollo/client/link/utils");
const utilities_1 = require("@apollo/client/utilities");
const environment_1 = require("@apollo/client/utilities/environment");
const internal_1 = require("@apollo/client/utilities/internal");
const globals_1 = require("@apollo/client/utilities/internal/globals");
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, globals_1.maybe)(() => fetch);
class BaseHttpLink extends link_1.ApolloLink {
    constructor(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: (0, internal_1.compact)({ includeExtensions, preserveHeaderCase }),
            options: requestOptions.fetchOptions,
            credentials: requestOptions.credentials,
            headers: requestOptions.headers,
        };
        super((operation) => {
            let chosenURI = (0, selectURI_js_1.selectURI)(operation, uri);
            const context = operation.getContext();
            const http = (context.http ??= {});
            if ((0, utilities_1.isSubscriptionOperation)(operation.query)) {
                http.accept = [
                    "multipart/mixed;boundary=graphql;subscriptionSpec=1.0",
                    ...(http.accept || []),
                ];
            }
            const contextConfig = {
                http: context.http,
                options: context.fetchOptions,
                credentials: context.credentials,
                headers: context.headers,
            };
            //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 (useGETForQueries && !(0, utilities_1.isMutationOperation)(operation.query)) {
                options.method = "GET";
            }
            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, globals_1.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;
                    observer.error(err);
                });
                return () => {
                    // XXX support canceling this request
                    // https://developers.google.com/web/updates/2017/09/abortable-fetch
                    if (controller)
                        controller.abort();
                };
            });
        });
    }
}
exports.BaseHttpLink = BaseHttpLink;
//# sourceMappingURL=BaseHttpLink.cjs.map
