@urql/exchange-graphcache
Version:
A normalized and configurable cache exchange for urql
146 lines (138 loc) • 7.53 kB
TypeScript
import { EntityField, Link, StorageAdapter, CacheExchangeOpts, Cache, Logger, DirectivesConfig, ResolverConfig, UpdatesConfig, OptimisticMutationConfig, KeyingConfig, SchemaIntrospector, FieldArgs, Entity, DataField, FieldInfo, Data, Variables, QueryInput } from './urql-exchange-graphcache-chunk.js';
export { DataFields, Dependencies, Directive, Fragments, KeyGenerator, KeyInfo, MakeFunctional, NullArray, OperationRequest, OperationType, OptimisticMutationResolver, PossibleTypesConfig, Primitive, ResolveInfo, Resolver, ResolverResult, Scalar, ScalarObject, SerializedEntries, SerializedRequest, SystemFields, UpdateResolver, WithTypename } from './urql-exchange-graphcache-chunk.js';
import { TypedDocumentNode, Exchange, CombinedError, OperationResult } from '@urql/core';
type Dict<T> = Record<string, T>;
type KeyMap<T> = Map<string, T>;
type OperationMap<T> = Map<number, T>;
interface NodeMap<T> {
optimistic: OperationMap<KeyMap<Dict<T | undefined>>>;
base: KeyMap<Dict<T>>;
}
interface InMemoryData {
/** Flag for whether the data is waiting for hydration */
hydrating: boolean;
/** Flag for whether deferred tasks have been scheduled yet */
defer: boolean;
/** A list of entities that have been flagged for gargabe collection since no references to them are left */
gc: Set<string>;
/** A list of entity+field keys that will be persisted */
persist: Set<string>;
/** The API's "Query" typename which is needed to filter dependencies */
queryRootKey: string;
/** Number of references to each entity (except "Query") */
refCount: KeyMap<number>;
/** A map of entity fields (key-value entries per entity) */
records: NodeMap<EntityField>;
/** A map of entity links which are connections from one entity to another (key-value entries per entity) */
links: NodeMap<Link>;
/** A map of typename to a list of entity-keys belonging to said type */
types: Map<string, Set<string>>;
/** A set of Query operation keys that are in-flight and deferred/streamed */
deferredKeys: Set<number>;
/** A set of Query operation keys that are in-flight and awaiting a result */
commutativeKeys: Set<number>;
/** A set of Query operation keys that have been written to */
dirtyKeys: Set<number>;
/** The order of optimistic layers */
optimisticOrder: number[];
/** This may be a persistence adapter that will receive changes in a batch */
storage: StorageAdapter | null;
/** A map of all the types we have encountered that did not map directly to a concrete type */
abstractToConcreteMap: Map<string, Set<string>>;
}
type DocumentNode = TypedDocumentNode<any, any>;
type RootField = 'query' | 'mutation' | 'subscription';
/** Implementation of the {@link Cache} interface as created internally by the {@link cacheExchange}.
* @internal
*/
declare class Store<C extends Partial<CacheExchangeOpts> = Partial<CacheExchangeOpts>> implements Cache {
data: InMemoryData;
logger?: Logger;
directives: DirectivesConfig;
resolvers: ResolverConfig;
updates: UpdatesConfig;
optimisticMutations: OptimisticMutationConfig;
keys: KeyingConfig;
globalIDs: Set<string> | boolean;
schema?: SchemaIntrospector;
possibleTypeMap?: Map<string, Set<string>>;
rootFields: {
query: string;
mutation: string;
subscription: string;
};
rootNames: {
[name: string]: RootField | void;
};
constructor(opts?: C);
keyOfField(fieldName: string, fieldArgs?: FieldArgs): string;
keyOfEntity(data: Entity): string | null;
resolve(entity: Entity, field: string, args?: FieldArgs): DataField | undefined;
invalidate(entity: Entity, field?: string, args?: FieldArgs): void;
inspectFields(entity: Entity): FieldInfo[];
updateQuery<T = Data, V = Variables>(input: QueryInput<T, V>, updater: (data: T | null) => T | null): void;
readQuery<T = Data, V = Variables>(input: QueryInput<T, V>): T | null;
readFragment<T = Data, V = Variables>(fragment: DocumentNode | TypedDocumentNode<T, V>, entity: string | Data | T, variables?: V, fragmentName?: string): T | null;
writeFragment<T = Data, V = Variables>(fragment: DocumentNode | TypedDocumentNode<T, V>, data: T, variables?: V, fragmentName?: string): void;
link(entity: Entity, field: string, args: FieldArgs, link: Link<Entity>): void;
link(entity: Entity, field: string, link: Link<Entity>): void;
}
/** Exchange factory that creates a normalized cache exchange.
*
* @param opts - A {@link CacheExchangeOpts} configuration object.
* @returns the created normalized cache {@link Exchange}.
*
* @remarks
* Graphcache is a normalized cache, enabled by using the `cacheExchange`
* in place of `@urql/core`’s. A normalized GraphQL cache uses typenames
* and key fields in the result to share a single copy for each unique
* entity across all queries.
*
* The `cacheExchange` may be passed a {@link CacheExchangeOpts} object
* to define custom resolvers, custom updates for mutations,
* optimistic updates, or to add custom key fields per type.
*
* @see {@link https://urql.dev/goto/docs/graphcache} for the full Graphcache docs.
*/
declare const cacheExchange: <C extends Partial<CacheExchangeOpts>>(opts?: C) => Exchange;
/** Input parameters for the {@link offlineExchange}.
* @remarks
* This configuration object extends the {@link CacheExchangeOpts}
* as the `offlineExchange` extends the regular {@link cacheExchange}.
*/
interface OfflineExchangeOpts extends CacheExchangeOpts {
/** 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.
*
* @see {@link https://urql.dev/goto/docs/graphcache/offline} for the full Offline Support docs.
*/
storage: StorageAdapter;
/** Predicate function to determine whether a {@link CombinedError} hints at a network error.
*
* @remarks
* Not ever {@link CombinedError} means that the device is offline and by default
* the `offlineExchange` will check for common network error messages and check
* `navigator.onLine`. However, when `isOfflineError` is passed it can replace
* the default offline detection.
*/
isOfflineError?(error: undefined | CombinedError, result: OperationResult): boolean;
}
/** Exchange factory that creates a normalized cache exchange in Offline Support mode.
*
* @param opts - A {@link OfflineExchangeOpts} configuration object.
* @returns the created normalized, offline cache {@link Exchange}.
*
* @remarks
* The `offlineExchange` is a wrapper around the regular {@link cacheExchange}
* which adds logic via the {@link OfflineExchangeOpts.storage} adapter to
* recognize when it’s offline, when to retry failed mutations, and how
* to handle longer periods of being offline.
*
* @see {@link https://urql.dev/goto/docs/graphcache/offline} for the full Offline Support docs.
*/
declare const offlineExchange: <C extends OfflineExchangeOpts>(opts: C) => Exchange;
export { Cache, CacheExchangeOpts, Data, DataField, DirectivesConfig, Entity, EntityField, FieldArgs, FieldInfo, KeyingConfig, Link, Logger, OptimisticMutationConfig, QueryInput, ResolverConfig, StorageAdapter, Store, UpdatesConfig, Variables, cacheExchange, offlineExchange };