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

Object.defineProperty(exports, "__esModule", { value: true });
exports.useSuspenseQuery = useSuspenseQuery;
exports.useWatchQueryOptions = useWatchQueryOptions;
const tslib_1 = require("tslib");
const React = tslib_1.__importStar(require("react"));
const client_1 = require("@apollo/client");
const cache_1 = require("@apollo/client/cache");
const internal_1 = require("@apollo/client/react/internal");
const environment_1 = require("@apollo/client/utilities/environment");
const invariant_1 = require("@apollo/client/utilities/invariant");
const constants_js_1 = require("./constants.cjs");
const index_js_1 = require("./internal/index.cjs");
const useApolloClient_js_1 = require("./useApolloClient.cjs");
function useSuspenseQuery(query, options = {}) {
    return (0, index_js_1.wrapHook)("useSuspenseQuery", 
    // eslint-disable-next-line react-compiler/react-compiler
    useSuspenseQuery_, (0, useApolloClient_js_1.useApolloClient)(typeof options === "object" ? options.client : undefined))(query, options);
}
function useSuspenseQuery_(query, options) {
    const client = (0, useApolloClient_js_1.useApolloClient)(options.client);
    const suspenseCache = (0, internal_1.getSuspenseCache)(client);
    const watchQueryOptions = useWatchQueryOptions({
        client,
        query,
        options,
    });
    const { fetchPolicy, variables } = watchQueryOptions;
    const { queryKey = [] } = options;
    const cacheKey = [
        query,
        (0, cache_1.canonicalStringify)(variables),
        ...[].concat(queryKey),
    ];
    const queryRef = suspenseCache.getQueryRef(cacheKey, () => client.watchQuery(watchQueryOptions));
    let [current, setPromise] = React.useState([queryRef.key, queryRef.promise]);
    // This saves us a re-execution of the render function when a variable changed.
    if (current[0] !== queryRef.key) {
        // eslint-disable-next-line react-compiler/react-compiler
        current[0] = queryRef.key;
        current[1] = queryRef.promise;
    }
    let promise = current[1];
    if (queryRef.didChangeOptions(watchQueryOptions)) {
        current[1] = promise = queryRef.applyOptions(watchQueryOptions);
    }
    React.useEffect(() => {
        const dispose = queryRef.retain();
        const removeListener = queryRef.listen((promise) => {
            setPromise([queryRef.key, promise]);
        });
        return () => {
            removeListener();
            dispose();
        };
    }, [queryRef]);
    const skipResult = React.useMemo(() => {
        const error = queryRef.result.error;
        const complete = !!queryRef.result.data;
        return {
            loading: false,
            data: queryRef.result.data,
            networkStatus: error ? client_1.NetworkStatus.error : client_1.NetworkStatus.ready,
            error,
            complete,
            partial: !complete,
        };
    }, [queryRef.result]);
    const result = fetchPolicy === "standby" ? skipResult : (0, index_js_1.__use)(promise);
    const fetchMore = React.useCallback((options) => {
        const promise = queryRef.fetchMore(options);
        setPromise([queryRef.key, queryRef.promise]);
        return promise;
    }, [queryRef]);
    const refetch = React.useCallback((variables) => {
        const promise = queryRef.refetch(variables);
        setPromise([queryRef.key, queryRef.promise]);
        return promise;
    }, [queryRef]);
    // TODO: The internalQueryRef doesn't have TVariables' type information so we have to cast it here
    const subscribeToMore = queryRef.observable
        .subscribeToMore;
    return React.useMemo(() => {
        return {
            client,
            data: result.data,
            error: result.error,
            networkStatus: result.networkStatus,
            fetchMore,
            refetch,
            subscribeToMore,
        };
    }, [client, fetchMore, refetch, result, subscribeToMore]);
}
function validateOptions(options) {
    const { fetchPolicy, returnPartialData } = options;
    validateFetchPolicy(fetchPolicy);
    validatePartialDataReturn(fetchPolicy, returnPartialData);
}
function validateFetchPolicy(fetchPolicy = "cache-first") {
    const supportedFetchPolicies = [
        "cache-first",
        "network-only",
        "no-cache",
        "cache-and-network",
    ];
    (0, invariant_1.invariant)(supportedFetchPolicies.includes(fetchPolicy), 37, fetchPolicy);
}
function validatePartialDataReturn(fetchPolicy, returnPartialData) {
    if (fetchPolicy === "no-cache" && returnPartialData) {
        __DEV__ && invariant_1.invariant.warn(38);
    }
}
function useWatchQueryOptions({ client, query, options, }) {
    return (0, index_js_1.useDeepMemo)(() => {
        if (options === constants_js_1.skipToken) {
            return { query, fetchPolicy: "standby" };
        }
        const fetchPolicy = options.fetchPolicy ||
            client.defaultOptions.watchQuery?.fetchPolicy ||
            "cache-first";
        const watchQueryOptions = {
            ...options,
            fetchPolicy,
            query,
            notifyOnNetworkStatusChange: false,
            nextFetchPolicy: void 0,
        };
        if (environment_1.__DEV__) {
            validateOptions(watchQueryOptions);
        }
        // Assign the updated fetch policy after our validation since `standby` is
        // not a supported fetch policy on its own without the use of `skip`.
        if (options.skip) {
            watchQueryOptions.fetchPolicy = "standby";
        }
        return watchQueryOptions;
    }, [client, options, query]);
}
//# sourceMappingURL=useSuspenseQuery.cjs.map
