import { FormattedNode, ErrorLike, DocumentInput, TypedDocumentNode, AnyVariables, RequestExtensions } from '@urql/core';
import { FragmentDefinitionNode, DocumentNode } from '@0no-co/graphql.web';
/*@ts-ignore*/
import * as GraphQL from 'graphql';

type OrNever<T> = void extends T ? never : T;
type IntrospectionQuery = {
    readonly __schema: {
        queryType: {
            name: string;
            kind?: any;
        };
        mutationType?: {
            name: string;
            kind?: any;
        } | null;
        subscriptionType?: {
            name: string;
            kind?: any;
        } | null;
        types?: readonly IntrospectionType[];
    };
} | OrNever<GraphQL.IntrospectionQuery>;
type IntrospectionTypeRef = {
    readonly kind: 'SCALAR' | 'OBJECT' | 'INTERFACE' | 'ENUM' | 'UNION' | 'INPUT_OBJECT';
    readonly name?: string;
    readonly ofType?: IntrospectionTypeRef;
} | OrNever<GraphQL.IntrospectionTypeRef>;
type IntrospectionInputTypeRef = {
    readonly kind: 'SCALAR' | 'ENUM' | 'INPUT_OBJECT';
    readonly name?: string;
    readonly ofType?: IntrospectionInputTypeRef;
} | OrNever<GraphQL.IntrospectionInputTypeRef>;
type IntrospectionInputValue = {
    readonly name: string;
    readonly description?: string | null;
    readonly defaultValue?: string | null;
    readonly type: IntrospectionInputTypeRef;
} | OrNever<GraphQL.IntrospectionInputValue>;
type IntrospectionType = {
    readonly kind: string;
    readonly name: string;
    readonly fields?: readonly any[];
    readonly interfaces?: readonly any[];
    readonly possibleTypes?: readonly any[];
} | OrNever<GraphQL.IntrospectionType>;

interface SchemaField {
    name: string;
    type: IntrospectionTypeRef;
    args(): Record<string, IntrospectionInputValue | void>;
}
interface SchemaObject {
    name: string;
    kind: 'INTERFACE' | 'OBJECT';
    interfaces(): Record<string, unknown>;
    fields(): Record<string, SchemaField | void>;
}
interface SchemaUnion {
    name: string;
    kind: 'UNION';
    types(): Record<string, unknown>;
}
interface SchemaIntrospector {
    query: string | null;
    mutation: string | null;
    subscription: string | null;
    types?: Map<string, SchemaObject | SchemaUnion>;
    isSubType(abstract: string, possible: string): boolean;
}
interface PartialIntrospectionSchema {
    queryType: {
        name: string;
        kind?: any;
    };
    mutationType?: {
        name: string;
        kind?: any;
    } | null;
    subscriptionType?: {
        name: string;
        kind?: any;
    } | null;
    types?: readonly any[];
}
type IntrospectionData = IntrospectionQuery | {
    __schema: PartialIntrospectionSchema;
};

/** Nullable GraphQL list types of `T`.
 *
 * @remarks
 * Any GraphQL list of a given type `T` that is nullable is
 * expected to contain nullable values. Nested lists are
 * also taken into account in Graphcache.
 */
type NullArray<T> = Array<null | T | NullArray<T>>;
/** Dictionary of GraphQL Fragment definitions by their names.
 *
 * @remarks
 * A map of {@link FragmentDefinitionNode | FragmentDefinitionNodes} by their
 * fragment names from the original GraphQL document that Graphcache is
 * executing.
 */
interface Fragments {
    [fragmentName: string]: void | FormattedNode<FragmentDefinitionNode>;
}
/** Non-object JSON values as serialized by a GraphQL API
 * @see {@link https://spec.graphql.org/October2021/#sel-DAPJDHAAEJHAKmzP} for the
 * GraphQL spec’s serialization format.
 */
type Primitive = null | number | boolean | string;
/** Any GraphQL scalar object
 *
 * @remarks
 * A GraphQL schema may define custom scalars that are resolved
 * and serialized as objects. These objects could also be turned
 * on the client-side into a non-JSON object, e.g. a `Date`.
 *
 * @see {@link https://spec.graphql.org/October2021/#sec-Scalars} for the
 * GraphQL spec’s information on custom scalars.
 */
interface ScalarObject {
    constructor?: Function;
    [key: string]: any;
}
/** GraphQL scalar value
 * @see {@link https://spec.graphql.org/October2021/#sec-Scalars} for the GraphQL
 * spec’s definition of scalars
 */
type Scalar = Primitive | ScalarObject;
/** Fields that Graphcache expects on GraphQL object (“entity”) results.
 *
 * @remarks
 * Any object that comes back from a GraphQL API will have
 * a `__typename` field from GraphQL Object types.
 *
 * The `__typename` field must be present as Graphcache updates
 * GraphQL queries with type name introspection.
 * Furthermore, Graphcache always checks for its default key
 * fields, `id` and `_id` to be present.
 */
interface SystemFields {
    /** GraphQL Object type name as returned by Type Name Introspection.
     * @see {@link https://spec.graphql.org/October2021/#sec-Type-Name-Introspection} for
     * more information on GraphQL’s Type Name introspection.
     */
    __typename: string;
    _id?: string | number | null;
    id?: string | number | null;
}
/** Scalar values are stored separately from relations between entities.
 * @internal
 */
type EntityField = undefined | Scalar | NullArray<Scalar>;
/** Values on GraphQL object (“entity”) results.
 *
 * @remarks
 * Any field that comes back from a GraphQL API will have
 * values that are scalars, other objects, or arrays
 * of scalars or objects.
 */
type DataField = Scalar | Data | NullArray<Scalar> | NullArray<Data>;
/** Definition of GraphQL object (“entity”) fields.
 *
 * @remarks
 * Any object that comes back from a GraphQL API will have
 * values that are scalars, other objects, or arrays
 * of scalars or objects, i.e. the {@link DataField} type.
 */
interface DataFields {
    [fieldName: string]: DataField;
}
/** Definition of GraphQL variables objects.
 * @remarks
 * Variables, as passed to GraphQL queries, can only contain scalar values.
 *
 * @see {@link https://spec.graphql.org/October2021/#sec-Coercing-Variable-Values} for the
 * GraphQL spec’s coercion of GraphQL variables.
 */
interface Variables {
    [name: string]: Scalar | Scalar[] | Variables | NullArray<Variables>;
}
/** Definition of GraphQL objects (“entities”).
 *
 * @remarks
 * An entity is expected to consist of a `__typename`
 * fields, optionally the default `id` or `_id` key
 * fields, and scalar values or other entities
 * otherwise.
 */
type Data = SystemFields & DataFields;
/** An entity, a key of an entity, or `null`
 *
 * @remarks
 * When Graphcache accepts a reference to an entity, you may pass it a key of an entity,
 * as retrieved for instance by {@link Cache.keyOfEntity} or a partial GraphQL object
 * (i.e. an object with a `__typename` and key field).
 */
type Entity = undefined | null | Data | string;
/** A key of an entity, or `null`; or a list of keys.
 *
 * @remarks
 * When Graphcache accepts a reference to one or more entities, you may pass it a
 * key, an entity, or a list of entities or keys. This is often passed to {@link Cache.link}
 * to update a field pointing to other GraphQL objects.
 */
type Link<Key = string> = null | Key | NullArray<Key>;
/** Arguments passed to a Graphcache field resolver.
 *
 * @remarks
 * Arguments a field receives are similar to variables and can
 * only contain scalars or other arguments objects. This
 * is equivalent to the {@link Variables} type.
 *
 * @see {@link https://spec.graphql.org/October2021/#sec-Coercing-Field-Arguments} for the
 * GraphQL spec’s coercion of field arguments.
 */
type FieldArgs = Variables | null | undefined;
/** Metadata about an entity’s cached field.
 *
 * @remarks
 * As returned by {@link Cache.inspectFields}, `FieldInfo` specifies an entity’s cached field,
 * split into the field’s key itself and the field’s original name and arguments.
 */
interface FieldInfo {
    /** The field’s key which combines `fieldName` and `arguments`. */
    fieldKey: string;
    /** The field’s name, as defined on a GraphQL Object type. */
    fieldName: string;
    /** The arguments passed to the field as found on the cache. */
    arguments: Variables | null;
}
/** A key to an entity field split back into the entity’s key and the field’s key part.
 * @internal
 */
interface KeyInfo {
    entityKey: string;
    fieldKey: string;
}
/** Abstract type for GraphQL requests.
 *
 * @remarks
 * Similarly to `@urql/core`’s `GraphQLRequest` type, `OperationRequest`
 * requires the minimum fields that Grapcache requires to execute a
 * GraphQL operation: its query document and variables.
 */
interface OperationRequest {
    query: FormattedNode<DocumentNode> | DocumentNode;
    variables?: any;
}
/** Metadata object passed to all resolver functions.
 *
 * @remarks
 * `ResolveInfo`, similar to GraphQL.js’ `GraphQLResolveInfo` object,
 * gives your resolvers a global state of the current GraphQL
 * document traversal.
 *
 * `parent`, `parenTypeName`, `parentKey`, and `parentFieldKey`
 * are particularly useful to make reusable resolver functions that
 * must know on which field and type they’re being called on.
 */
interface ResolveInfo {
    /** The parent GraphQL object.
     *
     * @remarks
     * The GraphQL object that the resolver has been called on. Because this is
     * a reference to raw GraphQL data, this may be incomplete or contain
     * aliased fields!
     */
    parent: Data;
    /** The parent object’s typename that the resolver has been called on. */
    parentTypeName: string;
    /** The parent object’s entity key that the resolver has been called on. */
    parentKey: string;
    /** Current field’s key that the resolver has been called on. */
    parentFieldKey: string;
    /** Current field that the resolver has been called on. */
    fieldName: string;
    /** Map of fragment definitions from the query document. */
    fragments: Fragments;
    /** Full original {@link Variables} object on the {@link OperationRequest}. */
    variables: Variables;
    /** Error that occurred for the current field, if any.
     *
     * @remarks
     * If a {@link GraphQLError.path} points at the current field, the error
     * will be set and provided here. This can be useful to recover from an
     * error on a specific field.
     */
    error: ErrorLike | undefined;
    /** Flag used to indicate whether the current GraphQL query is only partially cached.
     *
     * @remarks
     * When Graphcache has {@link CacheExchangeOpts.schema} introspection information,
     * it can automatically generate partial results and trigger a full API request
     * in the background.
     * Hence, this field indicates whether any data so far has only been partially
     * resolved from the cache, and is only in use on {@link Resolver | Resolvers}.
     *
     * However, you can also flip this flag to `true` manually to indicate to
     * the {@link cacheExchange} that it should still make a network request.
     */
    partial?: boolean;
    /** Flag used to indicate whether the current GraphQL mutation is optimistically executed.
     *
     * @remarks
     * An {@link UpdateResolver} is called for both API mutation responses and
     * optimistic mutation reuslts, as generated by {@link OptimisticMutationResolver}.
     *
     * Since an update sometimes needs to perform different actions if it’s run
     * optimistically, this flag is set to `true` during optimisti cupdates.
     */
    optimistic?: boolean;
    /** Internal state used by Graphcache.
     * @internal
     */
    __internal?: unknown;
}
/** GraphQL document and variables that should be queried against the cache.
 *
 * @remarks
 * `QueryInput` is a generic GraphQL request that should be executed against
 * cached data, as accepted by {@link cache.readQuery}.
 */
interface QueryInput<T = Data, V = Variables> {
    query: DocumentInput<T, V>;
    variables?: V;
}
/** Interface to interact with cached data, which resolvers receive. */
interface Cache {
    /** Returns the cache key for a given entity or `null` if it’s unkeyable.
     *
     * @param entity - the {@link Entity} to generate a key for.
     * @returns the entity’s key or `null`.
     *
     * @remarks
     * `cache.keyOfEntity` may be called with a partial GraphQL object (“entity”)
     * and generates a key for it. It uses your {@link KeyingConfig} and otherwise
     * defaults to `id` and `_id` fields.
     *
     * If it’s passed a `string` or `null`, it will simply return what it’s been passed.
     * Objects that lack a `__typename` field will return `null`.
     */
    keyOfEntity(entity: Entity | undefined): string | null;
    /** Returns the cache key for a field.
     *
     * @param fieldName - the field’s name.
     * @param args - the field’s arguments, if any.
     * @returns the field key
     *
     * @remarks
     * `cache.keyOfField` is used to create a field’s cache key from a given
     * field name and its arguments. This is used internally by {@link cache.resolve}
     * to combine an entity key and a field key into a path that normalized data is
     * accessed on in Graphcache’s internal data structure.
     */
    keyOfField(fieldName: string, args?: FieldArgs): string | null;
    /** Returns a cached value on a given entity’s field.
     *
     * @param entity - a GraphQL object (“entity”) or an entity key.
     * @param fieldName - the field’s name.
     * @param args - the field’s arguments, if any.
     * @returns the field’s value or the entity key(s) this field is pointing at.
     *
     * @remarks
     * `cache.resolve` is used to retrieve either the cached value of a field, or
     * to get the relation of the field (“link”). When a cached field points at
     * another normalized entity, this method will return the related entity key
     * (or a list, if it’s pointing at a list of entities).
     *
     * As such, if you’re accessing a nested field, you may have to call
     * `cache.resolve` again and chain its calls.
     *
     * Hint: If you have a field key from {@link FieldInfo} or {@link cache.keyOfField},
     * you may pass it as a second argument.
     *
     * @example
     * ```ts
     * const authorName = cache.resolve(
     *   cache.resolve({ __typename: 'Book', id }, 'author'),
     *   'name'
     * );
     * ```
     */
    resolve(entity: Entity | undefined, fieldName: string, args?: FieldArgs): DataField | undefined;
    /** Returns a list of cached fields for a given GraphQL object (“entity”).
     *
     * @param entity - a GraphQL object (“entity”) or an entity key.
     * @returns a list of {@link FieldInfo} objects.
     *
     * @remarks
     * `cache.inspectFields` can be used to list out all known fields
     * of a given entity. This can be useful in an {@link UpdateResolver}
     * if you have a `Query` field that accepts many different arguments,
     * for instance a paginated field.
     *
     * The returned list of fields are all fields that the cache knows about,
     * and you may have to filter them by name or arguments to find only which
     * ones you need.
     *
     * Hint: This method is theoretically a slower operation than simple
     * cache lookups, as it has to decode field keys. It’s only recommended
     * to be used in updaters.
     */
    inspectFields(entity: Entity): FieldInfo[];
    /** Deletes a cached entity or an entity’s field.
     *
     * @param entity - a GraphQL object (“entity”) or an entity key.
     * @param fieldName - optionally, a field name.
     * @param args - optionally, the field’s arguments, if any.
     *
     * @remarks
     * `cache.invalidate` can be used in updaters to delete data from
     * the cache. This will cause the {@link cacheExchange} to reexecute
     * queries that contain the deleted data.
     *
     * If you only pass its first argument, the entire entity is deleted.
     * However, if a field name (and optionally, its arguments) are passed,
     * only a single field is erased.
     */
    invalidate(entity: Entity | undefined, fieldName?: string, args?: FieldArgs): void;
    /** Updates a GraphQL query‘s cached data.
     *
     * @param input - a {@link QueryInput}, which is a GraphQL query request.
     * @param updater - a function called with the query’s result or `null` in case of a cache miss, which
     * may return updated data, which is written to the cache using the query.
     *
     * @remarks
     * `cache.updateQuery` can be used to update data for an entire GraphQL query document.
     * When it's passed a GraphQL query request, it calls the passed `updater` function
     * with the cached result for this query. You may then modify and update the data and
     * return it, after which it’s written back to the cache.
     *
     * Hint: While this allows for large updates at once, {@link cache.link},
     * {@link cache.resolve}, and {@link cache.writeFragment} are often better
     * choices for more granular and compact updater code.
     *
     * @example
     * ```ts
     * cache.updateQuery({ query: TodoList }, data => {
     *   data.todos.push(newTodo);
     *   return data;
     * });
     * ```
     */
    updateQuery<T = Data, V = Variables>(input: QueryInput<T, V>, updater: (data: T | null) => T | null): void;
    /** Returns a GraphQL query‘s cached result.
     *
     * @param input - a {@link QueryInput}, which is a GraphQL query request.
     * @returns the cached data result of the query or `null`, in case of a cache miss.
     *
     * @remarks
     * `cache.readQuery` can be used to read an entire query’s data all at once
     * from the cache.
     *
     * This can be useful when typing out many {@link cache.resolve}
     * calls is too tedious.
     *
     * @example
     * ```ts
     * const data = cache.readQuery({
     *   query: TodosQuery,
     *   variables: { from: 0, limit: 10 }
     * });
     * ```
     */
    readQuery<T = Data, V = Variables>(input: QueryInput<T, V>): T | null;
    /** Returns a GraphQL fragment‘s cached result.
     *
     * @param fragment - a {@link DocumentNode} containing a fragment definition.
     * @param entity - a GraphQL object (“entity”) or an entity key to read the fragment on.
     * @param variables - optionally, GraphQL variables, if the fragments use any.
     * @returns the cached data result of the fragment or `null`, in case of a cache miss.
     *
     * @remarks
     * `cache.readFragment` can be used to read an entire query’s data all at once
     * from the cache.
     *
     * It attempts to read the fragment starting from the `entity` that’s passed to it.
     * If the entity can’t be resolved or has mismatching types, `null` is returned.
     *
     * This can be useful when typing out many {@link cache.resolve}
     * calls is too tedious.
     *
     * @example
     * ```ts
     * const data = cache.readFragment(
     *   gql`fragment _ on Todo { id, text }`,
     *   { id: '123' }
     * );
     * ```
     */
    readFragment<T = Data, V = Variables>(fragment: TypedDocumentNode<any, any> | TypedDocumentNode<T, V>, entity: string | Data | T, variables?: V): T | null;
    /** Writes a GraphQL fragment to the cache.
     *
     * @param fragment - a {@link DocumentNode} containing a fragment definition.
     * @param data - a GraphQL object to be written with the given fragment.
     * @param variables - optionally, GraphQL variables, if the fragments use any.
     *
     * @remarks
     * `cache.writeFragment` can be used to write an entity to the cache.
     * The method will generate a key for the `data` it’s passed, and start writing
     * it using the fragment.
     *
     * This method is used when writing scalar values to the cache.
     * Since it's rare for an updater to write values to the cache, {@link cache.link}
     * only allows relations (“links”) to be updated, and `cache.writeFragment` is
     * instead used when writing multiple scalars.
     *
     * @example
     * ```ts
     * const data = cache.writeFragment(
     *   gql`fragment _ on Todo { id, text }`,
     *   { id: '123', text: 'New Text' }
     * );
     * ```
     */
    writeFragment<T = Data, V = Variables>(fragment: TypedDocumentNode<any, any> | TypedDocumentNode<T, V>, data: T, variables?: V): void;
    /** Updates the relation (“link”) from an entity’s field to another entity.
     *
     * @param entity - a GraphQL object (“entity”) or an entity key.
     * @param fieldName - the field’s name.
     * @param args - optionally, the field’s arguments, if any.
     * @param link - the GraphQL object(s) that should be set on this field.
     *
     * @remarks
     * The normalized cache stores relations between GraphQL objects separately.
     * As such, a field can be updated using `cache.link` to point to a new entity,
     * or a list of entities.
     *
     * In other words, `cache.link` is used to set a field to point to another
     * entity or a list of entities.
     *
     * @example
     * ```ts
     * const todos = cache.resolve('Query', 'todos');
     * cache.link('Query', 'todos', [...todos, newTodo]);
     * ```
     */
    link(entity: Entity, field: string, args: FieldArgs, link: Link<Entity>): void;
    link(entity: Entity, field: string, value: Link<Entity>): void;
}
/** Values a {@link Resolver} may return.
 *
 * @remarks
 * A resolver may return any value that a GraphQL object may contain.
 *
 * Additionally however, a resolver may return `undefined` to indicate that data
 * isn’t available from the cache, i.e. to trigger a cache miss.
 */
type ResolverResult = DataField | (DataFields & {
    __typename?: string;
}) | null | undefined;
type Logger = (severity: 'debug' | 'error' | 'warn', message: string) => void;
/** Input parameters for the {@link cacheExchange}. */
type CacheExchangeOpts = {
    /** Configure a custom-logger for graphcache, this function wll be called with a severity and a message.
     *
     * @remarks
     * By default we will invoke `console.warn` for warnings during development, however you might want to opt
     * out of this because you are re-using urql for a different library. This setting allows you to stub the logger
     * function or filter to only logs you want.
     */
    logger?: Logger;
    /** Configures update functions which are called when the mapped fields are written to the cache.
     *
     * @remarks
     * `updates` are commonly used to define additional changes to the cache for
     * mutation or subscription fields. It may commonly be used to invalidate
     * cached data or to modify lists after mutations.
     * This is a map of types to fields to {@link UpdateResolver} functions.
     *
     * @see {@link https://urql.dev/goto/docs/graphcache/cache-updates} for the full updates docs.
     */
    updates?: UpdatesConfig;
    /** Configures resolvers which replace cached reuslts with custom values.
     *
     * @remarks
     * `resolvers` is a map of types to fields to {@link Resolver} functions.
     * These functions allow us to replace cached field values with a custom
     * result, either to replace values on GraphQL results, or to resolve
     * entities from the cache for queries that haven't been sent to the API
     * yet.
     *
     * @see {@link https://urql.dev/goto/docs/graphcache/local-resolvers} for the full resolvers docs.
     */
    resolvers?: ResolverConfig;
    /** Configures directives which can perform custom logic on fields.
     *
     * @remarks
     * A {@link DirectivesConfig} may be passed to allow local directives to be used. For example, when `@_custom` is placed on a field and the configuration contains `custom` then this directive is executed by Graphcache.
     *
     * @see {@link https://urql.dev/goto/docs/graphcache/local-directives} for the full directives docs.
     */
    directives?: DirectivesConfig;
    /** Configures optimistic updates to react to mutations instantly before an API response.
     *
     * @remarks
     * `optimistic` is a map of mutation fields to {@link OptimisticMutationResolver} functions.
     * These functions allow us to return result data for mutations to optimistically apply them.
     * Optimistic updates are temporary updates to the cache’s data which allow an app to
     * instantly reflect changes that a mutation will make.
     *
     * @see {@link https://urql.dev/goto/docs/graphcache/cache-updates/#optimistic-updates} for the
     * full optimistic updates docs.
     */
    optimistic?: OptimisticMutationConfig;
    /** Configures keying functions for GraphQL types.
     *
     * @remarks
     * `keys` is a map of GraphQL object type names to {@link KeyGenerator} functions.
     * If a type in your API has no key field or a key field that isn't the default
     * `id` or `_id` fields, you may define a custom key generator for the type.
     *
     * Hint: Graphcache will log warnings when it finds objects that have no keyable
     * fields, which will remind you to define these functions gradually for every
     * type that needs them.
     *
     * @see {@link https://urql.dev/goto/docs/graphcache/normalized-caching/#custom-keys-and-non-keyable-entities} for
     * the full keys docs.
     */
    keys?: KeyingConfig;
    /** Enables global IDs for keying GraphQL types.
     *
     * @remarks
     * When `globalIDs` are enabled, GraphQL object type names will not contribute
     * to the keys of entities and instead only their ID fields (or `keys` return
     * values will be used.
     *
     * This is useful to overlap types of differing typenames. While this isn’t recommended
     * it can be necessary to represent more complex interface relationships.
     *
     * If this should only be applied to a limited set of type names, a list of
     * type names may be passed instead.
     */
    globalIDs?: string[] | boolean;
    /** Configures abstract to concrete types mapping for GraphQL types.
     *
     * @remarks
     * This will disable heuristic fragment matching, allowing Graphcache to match
     * fragment deterministically.
     *
     * When both `possibleTypes` and `schema` is set, `possibleTypes` value will be
     * ignored.
     */
    possibleTypes?: PossibleTypesConfig;
    /** Configures Graphcache with Schema Introspection data.
     *
     * @remarks
     * Passing a `schema` to Graphcache enables it to do non-heuristic fragment
     * matching, and be certain when a fragment matches against a union or interface
     * on your schema.
     *
     * It also enables a mode called “Schema Awareness”, which allows Graphcache to
     * return partial GraphQL results, `null`-ing out fields that aren’t in the cache
     * that are nullable on your schema, while requesting the full API response in
     * the background.
     *
     * @see {@link https://urql.dev/goto/urql/docs/graphcache/schema-awareness} for
     * the full keys docs on Schema Awareness.
     */
    schema?: IntrospectionData;
    /** Configures an offline storage adapter for Graphcache.
     *
     * @remarks
     * A {@link StorageAdapter} allows Graphcache to write data to an external,
     * asynchronous storage, and hydrate data from it when it first loads.
     * This allows you to preserve normalized data between restarts/reloads.
     *
     * Hint: If you’re trying to use Graphcache’s Offline Support, you may
     * want to swap out the `cacheExchange` with the {@link offlineExchange}.
     *
     * @see {@link https://urql.dev/goto/docs/graphcache/offline} for the full Offline Support docs.
     */
    storage?: StorageAdapter;
};
/** Cache Resolver, which may resolve or replace data during cache reads.
 *
 * @param parent - The GraphQL object that is currently being constructed from cache data.
 * @param args - This field’s arguments.
 * @param cache - {@link Cache} interface.
 * @param info - {@link ResolveInfo} interface.
 * @returns a {@link ResolverResult}, which is an updated value, partial entity, or entity key
 *
 * @remarks
 * A `Resolver`, as defined on the {@link ResolverConfig}, is called for
 * a field’s type during cache reads, and can be used to deserialize or replace
 * scalar values, or to resolve an entity from cached data, even if the
 * current field hasn’t been cached from an API response yet.
 *
 * For instance, if you have a `Query.picture(id: ID!)` field, you may define
 * a resolver that returns `{ __typename: 'Picture', id: args.id }`, since you
 * know the key fields of the GraphQL object.
 *
 * @example
 * ```ts
 * cacheExchange({
 *   resolvers: {
 *     Query: {
 *       // resolvers can be used to resolve cached entities without API requests
 *       todo: (_parent, args) => ({ __typename: 'Todo', id: args.id }),
 *     },
 *     Todo: {
 *       // resolvers can also be used to replace/deserialize scalars
 *       updatedAt: parent => new Date(parent.updatedAt),
 *     },
 *   },
 * });
 * ```
 *
 * @see {@link https://urql.dev/goto/docs/graphcache/local-resolvers} for the full resolvers docs.
 */
type Resolver<ParentData = DataFields, Args = Variables, Result = ResolverResult> = {
    bivarianceHack(parent: ParentData, args: Args, cache: Cache, info: ResolveInfo): Result;
}['bivarianceHack'];
/** Configures resolvers which replace cached reuslts with custom values.
 *
 * @remarks
 * A `ResolverConfig` is a map of types to fields to {@link Resolver} functions.
 * These functions allow us to replace cached field values with a custom
 * result, either to replace values on GraphQL results, or to resolve
 * entities from the cache for queries that haven't been sent to the API
 * yet.
 *
 * @see {@link https://urql.dev/goto/docs/graphcache/local-resolvers} for the full resolvers docs.
 */
type ResolverConfig = {
    [typeName: string]: {
        [fieldName: string]: Resolver | void;
    } | void;
};
type Directive = (directiveArguments: Record<string, unknown> | null) => Resolver;
type DirectivesConfig = {
    [directiveName: string]: Directive;
};
/** Cache Updater, which defines additional cache updates after cache writes.
 *
 * @param parent - The GraphQL object that is currently being written to the cache.
 * @param args - This field’s arguments.
 * @param cache - {@link Cache} interface.
 * @param info - {@link ResolveInfo} interface.
 *
 * @remarks
 * An `UpdateResolver` (“updater”), as defined on the {@link UpdatesConfig}, is
 * called for a field’s type during cache writes, and can be used to instruct
 * the {@link Cache} to perform other cache updates at the same time.
 *
 * This is often used, for instance, to update lists or invalidate entities
 * after a mutation response has come back from the API.
 *
 * @example
 * ```ts
 * cacheExchange({
 *   updates: {
 *     Mutation: {
 *       // updaters can invalidate data from the cache
 *       deleteAuthor: (_parent, args, cache) => {
 *         cache.invalidate({ __typename: 'Author', id: args.id });
 *       },
 *     },
 *   },
 * });
 * ```
 *
 * @see {@link https://urql.dev/goto/docs/graphcache/cache-updates} for the
 * full cache updates docs.
 */
type UpdateResolver<ParentData = DataFields, Args = Variables> = {
    bivarianceHack(parent: ParentData, args: Args, cache: Cache, info: ResolveInfo): void;
}['bivarianceHack'];
/** A key functon, which is called to create a cache key for a GraphQL object (“entity”).
 *
 * @param data - The GraphQL object that a key is generated for.
 * @returns a key `string` or `null` or unkeyable objects.
 *
 * @remarks
 * By default, Graphcache will use an object’s `__typename`, and `id` or `_id` fields
 * to generate a key for an object. However, not all GraphQL objects will have a unique
 * field, and some objects don’t have a key at all.
 *
 * When one of your GraphQL object types has a different key field, you may define a
 * function on the {@link KeyingConfig} to return its key field.
 * You may also have objects that don’t have keys, like “Edge” objects, or scalar-like
 * objects. For these, you can define a function that returns `null`, which tells
 * Graphcache that it’s an embedded object, which only occurs on its parent and is
 * globally unique.
 *
 * @see {@link https://urql.dev/goto/docs/graphcache/normalized-caching/#custom-keys-and-non-keyable-entities} for
 * the full keys docs.
 *
 * @example
 * ```ts
 * cacheExchange({
 *   keys: {
 *     Image: data => data.url,
 *     LatLng: () => null,
 *   },
 * });
 * ```
 */
type KeyGenerator = {
    bivarianceHack(data: Data): string | null;
}['bivarianceHack'];
/** Configures update functions which are called when the mapped fields are written to the cache.
 *
 * @remarks
 * `UpdatesConfig` is a map of types to fields to {@link UpdateResolver} functions.
 * These update functions are defined to instruct the cache to make additional changes
 * when a field is written to the cache.
 *
 * As changes are often made after a mutation or subscription, the `typeName` is
 * often set to `'Mutation'` or `'Subscription'`.
 *
 * @see {@link https://urql.dev/goto/docs/graphcache/cache-updates} for the full updates docs.
 *
 * @example
 * ```ts
 * const updates = {
 *   Mutation: {
 *     deleteAuthor(_parent, args, cache) {
 *       // Delete the Author from the cache when Mutation.deleteAuthor is sent
 *       cache.invalidate({ __typename: 'Author', id: args.id });
 *     },
 *   },
 * };
 */
type UpdatesConfig = {
    [typeName: string | 'Query' | 'Mutation' | 'Subscription']: {
        [fieldName: string]: UpdateResolver | void;
    } | void;
};
/** Remaps result type to allow for nested optimistic mutation resolvers.
 *
 * @remarks
 * An {@link OptimisticMutationResolver} can not only return partial, nested
 * mutation result data, but may also contain more optimistic mutation resolvers
 * for nested fields, which allows fields with arguments to optimistically be
 * resolved to dynamic values.
 *
 * @see {@link OptimisticMutationConfig} for more information.
 */
type MakeFunctional<T> = T extends {
    __typename: string;
} ? WithTypename<{
    [P in keyof T]?: MakeFunctional<T[P]>;
}> : OptimisticMutationResolver<Variables, T> | T;
/** Optimistic mutation resolver, which may return data that a mutation response will return.
 *
 * @param args - This field’s arguments.
 * @param cache - {@link Cache} interface.
 * @param info - {@link ResolveInfo} interface.
 * @returns the field’s optimistic data
 *
 * @remarks
 * Graphcache can update its cache optimistically via the {@link OptimisticMutationConfig}.
 * An `OptimisticMutationResolver` should return partial data that a mutation will return
 * once it completes and we receive its result.
 *
 * For instance, it could return the data that a deletion mutation may return
 * optimistically, which might allow an updater to run early and your UI to update
 * instantly.
 *
 * The result that this function returns may miss some fields that your mutation may return,
 * especially if it contains GraphQL object that are already cached. It may also contain
 * other, nested resolvers, which allows you to handle fields that accept arguments.
 */
type OptimisticMutationResolver<Args = Variables, Result = Link<Data> | Scalar> = {
    bivarianceHack(args: Args, cache: Cache, info: ResolveInfo): MakeFunctional<Result>;
}['bivarianceHack'];
/** Configures optimistic result functions which are called to get a mutation’s optimistic result.
 *
 * @remarks
 * `OptimisticMutationConfig` is a map of mutation fields to {@link OptimisticMutationResolver}
 * functions, which return result data for mutations to optimistically apply them.
 * Optimistic updates are temporary updates to the cache’s data which allow an app to
 * instantly reflect changes that a mutation will make.
 *
 * Hint: Results returned from optimistic functions may be partial, and may contain functions.
 * If the returned optimistic object contains functions on fields, these are executed as nested
 * optimistic resolver functions.
 *
 * @see {@link https://urql.dev/goto/docs/graphcache/cache-updates/#optimistic-updates} for the
 * full optimistic updates docs.
 *
 * @example
 * ```ts
 * const optimistic = {
 *   updateProfile: (args) => ({
 *     __typename: 'UserProfile',
 *     id: args.id,
 *     name: args.newName,
 *   }),
 * };
 */
type OptimisticMutationConfig = {
    [mutationFieldName: string]: OptimisticMutationResolver;
};
/** Configures keying functions for GraphQL types.
 *
 * @remarks
 * `KeyingConfig` is a map of GraphQL object type names to {@link KeyGenerator} functions.
 * If a type in your API has no key field or a key field that isn't the default
 * `id` or `_id` fields, you may define a custom key generator for the type.
 *
 * Keys are important to a normalized cache, because they’re the identity of the object
 * that is shared across the cache, and helps the cache recognize shared/normalized data.
 *
 * Hint: Graphcache will log warnings when it finds objects that have no keyable
 * fields, which will remind you to define these functions gradually for every
 * type that needs them.
 *
 * @see {@link https://urql.dev/goto/docs/graphcache/normalized-caching/#custom-keys-and-non-keyable-entities} for
 * the full keys docs.
 *
 * @example
 * ```ts
 * const keys = {
 *   Image: data => data.url,
 *   LatLng: () => null,
 * };
 * ```
 */
type KeyingConfig = {
    [typename: string]: KeyGenerator;
};
type PossibleTypesConfig = {
    [abstractType: string]: string[];
};
/** Serialized normalized caching data. */
interface SerializedEntries {
    [key: string]: string | undefined;
}
/** A serialized GraphQL request for offline storage. */
interface SerializedRequest {
    query: string;
    variables: AnyVariables | undefined;
    extensions?: RequestExtensions | undefined;
}
/** Interface for a storage adapter, used by the {@link offlineExchange} for Offline Support.
 * @see {@link https://urql.dev/goto/docs/graphcache/offline} for the full Offline Support docs.
 * @see `@urql/exchange-graphcache/default-storage` for an example implementation using IndexedDB.
 */
interface StorageAdapter {
    /** Called to rehydrate data when the {@link cacheExchange} first loads.
     * @remarks
     * `readData` is called when Graphcache first starts up, and loads cache entries
     * using which it'll repopulate its normalized cache data.
     */
    readData(): Promise<SerializedEntries>;
    /** Called by the {@link cacheExchange} to write new data to the offline storage.
     * @remarks
     * `writeData` is called when Graphcache updated its cached data and wishes to
     * persist this data to the offline storage. The data is a partial object and
     * Graphcache does not write all its data at once.
     */
    writeData(delta: SerializedEntries): Promise<any>;
    /** Called to rehydrate metadata when the {@link offlineExchange} first loads.
     * @remarks
     * `readMetadata` is called when Graphcache first starts up, and loads
     * metadata informing it of pending mutations that failed while the device
     * was offline.
     */
    readMetadata?(): Promise<null | SerializedRequest[]>;
    /** Called by the {@link offlineExchange} to persist failed mutations.
     * @remarks
     * `writeMetadata` is called when a mutation failed to persist a queue
     * of failed mutations to the offline storage that must be retried when
     * the application is reloaded.
     */
    writeMetadata?(json: SerializedRequest[]): void;
    /** Called to register a callback called when the device is back online.
     * @remarks
     * `onOnline` is called by the {@link offlineExchange} with a callback.
     * This callback must be called when the device comes back online and
     * will cause all failed mutations in the queue to be retried.
     */
    onOnline?(cb: () => void): any;
    /** Called when the cache has been hydrated with the data from `readData` */
    onCacheHydrated?(): any;
}
/** Set of keys that have been modified or accessed.
 * @internal
 */
type Dependencies = Set<string>;
/** The type of cache operation being executed.
 * @internal
 */
type OperationType = 'read' | 'write';
/** Casts a given object type to have a required typename field.
 * @internal
 */
type WithTypename<T extends {
    __typename?: any;
}> = T & {
    __typename: NonNullable<T['__typename']>;
};

export { Cache, CacheExchangeOpts, Data, DataField, DataFields, Dependencies, Directive, DirectivesConfig, Entity, EntityField, FieldArgs, FieldInfo, Fragments, KeyGenerator, KeyInfo, KeyingConfig, Link, Logger, MakeFunctional, NullArray, OperationRequest, OperationType, OptimisticMutationConfig, OptimisticMutationResolver, PossibleTypesConfig, Primitive, QueryInput, ResolveInfo, Resolver, ResolverConfig, ResolverResult, Scalar, ScalarObject, SchemaIntrospector, SerializedEntries, SerializedRequest, StorageAdapter, SystemFields, UpdateResolver, UpdatesConfig, Variables, WithTypename };
