UNPKG

@data-client/core

Version:

Async State Management without the Management. REST, GraphQL, SSE, Websockets, Fetch

355 lines (354 loc) 13.6 kB
import { ErrorTypes, SnapshotInterface, Schema, Denormalize, Queryable, SchemaArgs } from '@data-client/normalizr'; import { ExpiryStatus, EndpointInterface, FetchFunction, ResolveType, DenormalizeNullable, MemoCache } from '@data-client/normalizr'; import AbortOptimistic from './AbortOptimistic.js'; import { EndpointUpdateFunction } from './types.js'; import { ReduxMiddlewareAPI } from '../manager/applyManager.js'; import { GCInterface } from '../state/GCPolicy.js'; import { ActionTypes, State } from '../types.js'; export type GenericDispatch = (value: any) => Promise<void>; export type DataClientDispatch = (value: ActionTypes) => Promise<void>; export interface ControllerConstructorProps<D extends GenericDispatch = DataClientDispatch> { dispatch?: D; getState?: () => State<unknown>; memo?: Pick<MemoCache, 'denormalize' | 'query' | 'buildQueryKey'>; gcPolicy?: GCInterface; } /** * Imperative control of Reactive Data Client store * @see https://dataclient.io/docs/api/Controller */ export default class Controller<D extends GenericDispatch = DataClientDispatch> { /** * Dispatches an action to Reactive Data Client reducer. * * @see https://dataclient.io/docs/api/Controller#dispatch */ protected _dispatch: D; /** * Gets the latest state snapshot that is fully committed. * * This can be useful for imperative use-cases like event handlers. * This should *not* be used to render; instead useSuspense() or useCache() * @see https://dataclient.io/docs/api/Controller#getState */ getState: () => State<unknown>; /** * Singleton to maintain referential equality between calls */ readonly memo: Pick<MemoCache, 'denormalize' | 'query' | 'buildQueryKey'>; /** * Handles garbage collection */ readonly gcPolicy: GCInterface; constructor({ dispatch, getState, memo, gcPolicy, }?: ControllerConstructorProps<D>); dispatch: D; bindMiddleware({ dispatch, getState, }: { dispatch: D; getState: ReduxMiddlewareAPI['getState']; }): void; /*************** Action Dispatchers ***************/ /** * Fetches the endpoint with given args, updating the Reactive Data Client cache with the response or error upon completion. * @see https://dataclient.io/docs/api/Controller#fetch */ fetch: <E extends EndpointInterface & { update?: EndpointUpdateFunction<E>; }>(endpoint: E, ...args: readonly [ ...Parameters<E> ]) => E["schema"] extends undefined | null ? ReturnType<E> : Promise<Denormalize<E["schema"]>>; /** * Fetches only if endpoint is considered 'stale'; otherwise returns undefined * @see https://dataclient.io/docs/api/Controller#fetchIfStale */ fetchIfStale: <E extends EndpointInterface & { update?: EndpointUpdateFunction<E>; }>(endpoint: E, ...args: readonly [ ...Parameters<E> ]) => E["schema"] extends undefined | null ? ReturnType<E> | ResolveType<E> : Promise<Denormalize<E["schema"]>> | Denormalize<E["schema"]>; /** * Forces refetching and suspense on useSuspense with the same Endpoint and parameters. * @see https://dataclient.io/docs/api/Controller#invalidate */ invalidate: <E extends EndpointInterface>(endpoint: E, ...args: readonly [ ...Parameters<E> ] | readonly [ null ]) => Promise<void>; /** * Forces refetching and suspense on useSuspense on all matching endpoint result keys. * @see https://dataclient.io/docs/api/Controller#invalidateAll * @returns Promise that resolves when invalidation is commited. */ invalidateAll: (options: { testKey: (key: string) => boolean; }) => Promise<void>; /** * Sets all matching endpoint result keys to be STALE. * @see https://dataclient.io/docs/api/Controller#expireAll * @returns Promise that resolves when expiry is commited. *NOT* fetch promise */ expireAll: (options: { testKey: (key: string) => boolean; }) => Promise<void>; /** * Resets the entire Reactive Data Client cache. All inflight requests will not resolve. * @see https://dataclient.io/docs/api/Controller#resetEntireStore */ resetEntireStore: () => Promise<void>; /** * Sets value for the Queryable and args. * @see https://dataclient.io/docs/api/Controller#set */ set<S extends Queryable>(schema: S, ...rest: readonly [ ...SchemaArgs<S>, (previousValue: Denormalize<S>) => {} ]): Promise<void>; set<S extends Queryable>(schema: S, ...rest: readonly [ ...SchemaArgs<S>, {} ]): Promise<void>; /** * Sets response for the Endpoint and args. * @see https://dataclient.io/docs/api/Controller#setResponse */ setResponse: <E extends EndpointInterface & { update?: EndpointUpdateFunction<E>; }>(endpoint: E, ...rest: readonly [ ...Parameters<E>, any ]) => Promise<void>; /** * Sets an error response for the Endpoint and args. * @see https://dataclient.io/docs/api/Controller#setError */ setError: <E extends EndpointInterface & { update?: EndpointUpdateFunction<E>; }>(endpoint: E, ...rest: readonly [ ...Parameters<E>, Error ]) => Promise<void>; /** * Resolves an inflight fetch. * @see https://dataclient.io/docs/api/Controller#resolve */ resolve: <E extends EndpointInterface & { update?: EndpointUpdateFunction<E>; }>(endpoint: E, meta: { args: readonly [ ...Parameters<E> ]; response: Error; fetchedAt: number; error: true; } | { args: readonly [ ...Parameters<E> ]; response: any; fetchedAt: number; error?: false | undefined; }) => Promise<void>; /** * Marks a new subscription to a given Endpoint. * @see https://dataclient.io/docs/api/Controller#subscribe */ subscribe: <E extends EndpointInterface<FetchFunction, Schema | undefined, undefined | false>>(endpoint: E, ...args: readonly [ ...Parameters<E> ] | readonly [ null ]) => Promise<void>; /** * Marks completion of subscription to a given Endpoint. * @see https://dataclient.io/docs/api/Controller#unsubscribe */ unsubscribe: <E extends EndpointInterface<FetchFunction, Schema | undefined, undefined | false>>(endpoint: E, ...args: readonly [ ...Parameters<E> ] | readonly [ null ]) => Promise<void>; /*************** More ***************/ /** * Gets a snapshot (https://dataclient.io/docs/api/Snapshot) * @see https://dataclient.io/docs/api/Controller#snapshot */ snapshot: (state: State<unknown>, fetchedAt?: number) => Snapshot<unknown>; /** * Gets the error, if any, for a given endpoint. Returns undefined for no errors. * @see https://dataclient.io/docs/api/Controller#getError */ getError<E extends EndpointInterface>(endpoint: E, ...rest: readonly [ null, State<unknown> ] | readonly [ ...Parameters<E>, State<unknown> ]): ErrorTypes | undefined; getError<E extends Pick<EndpointInterface, 'key'>>(endpoint: E, ...rest: readonly [ null, State<unknown> ] | readonly [ ...Parameters<E['key']>, State<unknown> ]): ErrorTypes | undefined; /** * Gets the (globally referentially stable) response for a given endpoint/args pair from state given. * @see https://dataclient.io/docs/api/Controller#getResponse */ getResponse<E extends EndpointInterface>(endpoint: E, ...rest: readonly [ null, State<unknown> ] | readonly [ ...Parameters<E>, State<unknown> ]): { data: DenormalizeNullable<E['schema']>; expiryStatus: ExpiryStatus; expiresAt: number; countRef: () => () => void; }; getResponse<E extends Pick<EndpointInterface, 'key' | 'schema' | 'invalidIfStale'>>(endpoint: E, ...rest: readonly [ ...(readonly [ ...Parameters<E['key']> ] | readonly [ null ]), State<unknown> ]): { data: DenormalizeNullable<E['schema']>; expiryStatus: ExpiryStatus; expiresAt: number; countRef: () => () => void; }; /** * Gets the (globally referentially stable) response for a given endpoint/args pair from state given. * @see https://dataclient.io/docs/api/Controller#getResponseMeta */ getResponseMeta<E extends EndpointInterface>(endpoint: E, ...rest: readonly [ null, State<unknown> ] | readonly [ ...Parameters<E>, State<unknown> ]): { data: DenormalizeNullable<E['schema']>; expiryStatus: ExpiryStatus; expiresAt: number; countRef: () => () => void; }; getResponseMeta<E extends Pick<EndpointInterface, 'key' | 'schema' | 'invalidIfStale'>>(endpoint: E, ...rest: readonly [ ...(readonly [ ...Parameters<E['key']> ] | readonly [ null ]), State<unknown> ]): { data: DenormalizeNullable<E['schema']>; expiryStatus: ExpiryStatus; expiresAt: number; countRef: () => () => void; }; /** * Queries the store for a Querable schema * @see https://dataclient.io/docs/api/Controller#get */ get<S extends Queryable>(schema: S, ...rest: readonly [ ...SchemaArgs<S>, Pick<State<unknown>, 'entities' | 'entityMeta'> ]): DenormalizeNullable<S> | undefined; /** * Queries the store for a Querable schema; providing related metadata * @see https://dataclient.io/docs/api/Controller#getQueryMeta */ getQueryMeta<S extends Queryable>(schema: S, ...rest: readonly [ ...SchemaArgs<S>, Pick<State<unknown>, 'entities' | 'entityMeta'> ]): { data: DenormalizeNullable<S> | undefined; countRef: () => () => void; }; private getSchemaResponse; } export { ErrorTypes }; declare class Snapshot<T = unknown> implements SnapshotInterface { static readonly abort: AbortOptimistic; private state; private controller; readonly fetchedAt: number; readonly abort: AbortOptimistic; constructor(controller: Controller, state: State<T>, fetchedAt?: number); /*************** Data Access ***************/ /** @see https://dataclient.io/docs/api/Snapshot#getResponse */ getResponse<E extends EndpointInterface>(endpoint: E, ...args: readonly [ null ]): { data: DenormalizeNullable<E['schema']>; expiryStatus: ExpiryStatus; expiresAt: number; }; getResponse<E extends EndpointInterface>(endpoint: E, ...args: readonly [ ...Parameters<E> ]): { data: DenormalizeNullable<E['schema']>; expiryStatus: ExpiryStatus; expiresAt: number; }; getResponse<E extends Pick<EndpointInterface, 'key' | 'schema' | 'invalidIfStale'>>(endpoint: E, ...args: readonly [ ...Parameters<E['key']> ] | readonly [ null ]): { data: DenormalizeNullable<E['schema']>; expiryStatus: ExpiryStatus; expiresAt: number; }; /** @see https://dataclient.io/docs/api/Snapshot#getResponseMeta */ getResponseMeta<E extends EndpointInterface>(endpoint: E, ...args: readonly [ null ]): { data: DenormalizeNullable<E['schema']>; expiryStatus: ExpiryStatus; expiresAt: number; }; getResponseMeta<E extends EndpointInterface>(endpoint: E, ...args: readonly [ ...Parameters<E> ]): { data: DenormalizeNullable<E['schema']>; expiryStatus: ExpiryStatus; expiresAt: number; }; getResponseMeta<E extends Pick<EndpointInterface, 'key' | 'schema' | 'invalidIfStale'>>(endpoint: E, ...args: readonly [ ...Parameters<E['key']> ] | readonly [ null ]): { data: DenormalizeNullable<E['schema']>; expiryStatus: ExpiryStatus; expiresAt: number; }; /** @see https://dataclient.io/docs/api/Snapshot#getError */ getError<E extends EndpointInterface>(endpoint: E, ...args: readonly [ ...Parameters<E> ] | readonly [ null ]): ErrorTypes | undefined; getError<E extends Pick<EndpointInterface, 'key'>>(endpoint: E, ...args: readonly [ ...Parameters<E['key']> ] | readonly [ null ]): ErrorTypes | undefined; /** * Retrieved memoized value for any Querable schema * @see https://dataclient.io/docs/api/Snapshot#get */ get<S extends Queryable>(schema: S, ...args: SchemaArgs<S>): DenormalizeNullable<S> | undefined; /** * Queries the store for a Querable schema; providing related metadata * @see https://dataclient.io/docs/api/Snapshot#getQueryMeta */ getQueryMeta<S extends Queryable>(schema: S, ...args: SchemaArgs<S>): { data: DenormalizeNullable<S> | undefined; countRef: () => () => void; }; } //# sourceMappingURL=Controller.d.ts.map