@data-client/core
Version:
Async State Management without the Management. REST, GraphQL, SSE, Websockets, Fetch
355 lines (354 loc) • 13.6 kB
TypeScript
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' | 'indexes'>
]): 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' | 'indexes'>
]): {
data: DenormalizeNullable<S> | undefined;
countRef: () => () => void;
};
private getExpiryStatus;
}
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