import type { ReadonlyJSONValue } from '../../shared/src/json.ts';
import { Zero } from '../../zero-client/src/client/zero.ts';
import type { Schema } from '../../zero-schema/src/builder/schema-builder.ts';
import { type HumanReadable, type Query } from '../../zql/src/query/query.ts';
import { type TTL } from '../../zql/src/query/ttl.ts';
export type QueryResultDetails = Readonly<{
    type: 'complete';
} | {
    type: 'unknown';
} | QueryErrorDetails>;
type QueryErrorDetails = {
    type: 'error';
    refetch: () => void;
    error: {
        type: 'app';
        queryName: string;
        details: ReadonlyJSONValue;
    } | {
        type: 'http';
        queryName: string;
        status: number;
        details: ReadonlyJSONValue;
    };
};
export type QueryResult<TReturn> = readonly [
    HumanReadable<TReturn>,
    QueryResultDetails
];
export type UseQueryOptions = {
    enabled?: boolean | undefined;
    /**
     * Time to live (TTL) in seconds. Controls how long query results are cached
     * after the query is removed. During this time, Zero continues to sync the query.
     * Default is 'never'.
     */
    ttl?: TTL | undefined;
};
export type UseSuspenseQueryOptions = UseQueryOptions & {
    /**
     * Whether to suspend until:
     * - 'partial': the query has partial results (partial array or defined
     *   value for singular results) which may be of result type 'unknown',
     *   or the query result type is 'complete' (in which case results may be
     *   empty).  This is useful for suspending until there are partial
     *   optimistic local results, or the query has completed loading from the
     *   server.
     * - 'complete': the query result type is 'complete'.
     *
     * Default is 'partial'.
     */
    suspendUntil?: 'complete' | 'partial';
};
export declare function useQuery<TSchema extends Schema, TTable extends keyof TSchema['tables'] & string, TReturn>(query: Query<TSchema, TTable, TReturn>, options?: UseQueryOptions | boolean): QueryResult<TReturn>;
export declare function useSuspenseQuery<TSchema extends Schema, TTable extends keyof TSchema['tables'] & string, TReturn>(query: Query<TSchema, TTable, TReturn>, options?: UseSuspenseQueryOptions | boolean): QueryResult<TReturn>;
export declare function getAllViewsSizeForTesting(store: ViewStore): number;
/**
 * A global store of all active views.
 *
 * React subscribes and unsubscribes to these views
 * via `useSyncExternalStore`.
 *
 * Managing views through `useEffect` or `useLayoutEffect` causes
 * inconsistencies because effects run after render.
 *
 * For example, if useQuery used use*Effect in the component below:
 * ```ts
 * function Foo({issueID}) {
 *   const issue = useQuery(z.query.issue.where('id', issueID).one());
 *   if (issue?.id !== undefined && issue.id !== issueID) {
 *     console.log('MISMATCH!', issue.id, issueID);
 *   }
 * }
 * ```
 *
 * `MISMATCH` will be printed whenever the `issueID` prop changes.
 *
 * This is because the component will render once with
 * the old state returned from `useQuery`. Then the effect inside
 * `useQuery` will run. The component will render again with the new
 * state. This inconsistent transition can cause unexpected results.
 *
 * Emulating `useEffect` via `useState` and `if` causes resource leaks.
 * That is:
 *
 * ```ts
 * function useQuery(q) {
 *   const [oldHash, setOldHash] = useState();
 *   if (hash(q) !== oldHash) {
 *      // make new view
 *   }
 *
 *   useEffect(() => {
 *     return () => view.destroy();
 *   }, []);
 * }
 * ```
 *
 * I'm not sure why but in strict mode the cleanup function
 * fails to be called for the first instance of the view and only
 * cleans up later instances.
 *
 * Swapping `useState` to `useRef` has similar problems.
 */
export declare class ViewStore {
    #private;
    constructor();
    getView<TSchema extends Schema, TTable extends keyof TSchema['tables'] & string, TReturn>(zero: Zero<TSchema>, query: Query<TSchema, TTable, TReturn>, enabled: boolean, ttl: TTL): {
        getSnapshot: () => QueryResult<TReturn>;
        subscribeReactInternals: (internals: () => void) => () => void;
        updateTTL: (ttl: TTL) => void;
        waitForComplete: () => Promise<void>;
        waitForNonEmpty: () => Promise<void>;
        complete: boolean;
        nonEmpty: boolean;
    };
}
export {};
//# sourceMappingURL=use-query.d.ts.map