react-relay-network-modern
Version:
Network Layer for React Relay and Express (Batch Queries, AuthToken, Logging, Retry)
330 lines (266 loc) • 8.96 kB
TypeScript
import { ExecuteFunction, QueryResponseCache } from 'relay-runtime';
export { QueryResponseCache };
export type FetchResponse = Response;
export type Variables = { [name: string]: any };
declare class RelayResponse {
_res: any;
data?: PayloadData;
errors?: GraphQLResponseErrors;
ok: any;
status: number;
statusText?: string;
headers?: Headers;
url?: string;
text?: string;
json: unknown;
static createFromFetch(res: FetchResponse): Promise<RelayResponse>;
static createFromGraphQL(res: { errors?: any; data?: any }): Promise<RelayResponse>;
processJsonData(json: unknown): void;
clone(): RelayResponse;
toString(): string;
}
export { RelayResponse as RelayNetworkLayerResponse };
export type Headers = { [name: string]: string };
export interface FetchOpts {
url?: string;
method: 'POST' | 'GET';
headers: Headers;
body: string | FormData;
credentials?: 'same-origin' | 'include' | 'omit';
mode?: 'cors' | 'websocket' | 'navigate' | 'no-cors' | 'same-origin';
cache?: 'default' | 'no-store' | 'reload' | 'no-cache' | 'force-cache' | 'only-if-cached';
redirect?: 'follow' | 'error' | 'manual';
signal?: AbortSignal;
[name: string]: any;
}
declare class RelayRequest {
static lastGenId: number;
id: string;
fetchOpts: FetchOpts;
operation: ConcreteBatch;
variables: Variables;
cacheConfig: CacheConfig;
uploadables: UploadableMap | null;
controller: AbortController | null;
getBody(): string | FormData;
prepareBody(): string | FormData;
getID(): string;
getQueryString(): string;
getVariables(): Variables;
isMutation(): boolean;
isFormData(): boolean;
cancel(): boolean;
clone(): RelayRequest;
}
export { RelayRequest as RelayNetworkLayerRequest };
declare class RelayRequestBatch {
fetchOpts: FetchOpts;
requests: RelayRequest[];
setFetchOption(name: string, value: any): void;
setFetchOptions(opts: {}): void;
getBody(): string;
prepareBody(): string;
getIds(): string[];
getID(): string;
isMutation(): boolean;
isFormData(): boolean;
clone(): RelayRequestBatch;
getVariables(): Variables;
getQueryString(): string;
}
export { RelayRequestBatch as RelayNetworkLayerRequestBatch };
export type RelayRequestAny = RelayRequest | RelayRequestBatch;
export type MiddlewareNextFn = (req: RelayRequestAny) => Promise<RelayResponse>;
export type Middleware = (next: MiddlewareNextFn) => MiddlewareNextFn;
export type UrlMiddlewareOpts = {
url: string | Promise<string> | ((req: RelayRequest) => string | Promise<string>);
method?: 'POST' | 'GET';
headers?: Headers | Promise<Headers> | ((req: RelayRequest) => Headers | Promise<Headers>);
// Available request modes in fetch options. For details see https://fetch.spec.whatwg.org/#requests
credentials?: FetchOpts['credentials'];
mode?: FetchOpts['mode'];
cache?: FetchOpts['cache'];
redirect?: FetchOpts['redirect'];
};
export function urlMiddleware(opts?: UrlMiddlewareOpts): Middleware;
export interface LoggerMiddlewareOpts {
logger?: Function;
}
export function loggerMiddleware(opts?: LoggerMiddlewareOpts): Middleware;
export interface PersistedQueriesMiddlewareOpts {
hash: string;
}
export function persistedQueriesMiddleware(opts?: PersistedQueriesMiddlewareOpts): Middleware;
export interface PerfMiddlewareOpts {
logger?: Function;
}
export function perfMiddleware(opts?: PerfMiddlewareOpts): Middleware;
export interface AuthMiddlewareOpts {
token?: string | Promise<string> | ((req: RelayRequestAny) => string | Promise<string>);
tokenRefreshPromise?: (req: RelayRequestAny, res: RelayResponse) => string | Promise<string>;
allowEmptyToken?: boolean;
prefix?: string;
header?: string;
}
export function authMiddleware(opts?: AuthMiddlewareOpts): Middleware;
interface RequestWrapper {
req: RelayRequest;
completeOk: (res: object) => void;
completeErr: (e: Error) => void;
done: boolean;
duplicates: RequestWrapper[];
}
interface BatchRequestMap {
[reqId: string]: RequestWrapper;
}
export type BatchMiddlewareOpts = {
batchUrl?: string | Promise<string> | ((requestMap: BatchRequestMap) => string | Promise<string>);
batchTimeout?: number;
maxBatchSize?: number;
allowMutations?: boolean;
method?: 'POST' | 'GET';
headers?: Headers | Promise<Headers> | ((req: RelayRequestBatch) => Headers | Promise<Headers>);
// Available request modes in fetch options. For details see https://fetch.spec.whatwg.org/#requests
credentials?: FetchOpts['credentials'];
mode?: FetchOpts['mode'];
cache?: FetchOpts['cache'];
redirect?: FetchOpts['redirect'];
};
export function batchMiddleware(opts?: BatchMiddlewareOpts): Middleware;
export interface CacheMiddlewareOpts {
size?: number;
ttl?: number;
onInit?: (cache: QueryResponseCache) => void;
allowMutations?: boolean;
allowFormData?: boolean;
clearOnMutation?: boolean;
cacheErrors?: boolean;
updateTTLOnGet?: boolean;
}
export function cacheMiddleware(opts?: CacheMiddlewareOpts): Middleware;
export interface GqlErrorMiddlewareOpts {
logger?: Function;
prefix?: string;
disableServerMiddlewareTip?: boolean;
}
export function errorMiddleware(opts?: GqlErrorMiddlewareOpts): Middleware;
export type RetryAfterFn = (attempt: number) => number | false;
export type ForceRetryFn = (runNow: Function, delay: number) => any;
export type AbortFn = (msg?: string) => any;
export type BeforeRetryCb = (meta: {
forceRetry: Function;
abort: AbortFn;
delay: number;
attempt: number;
lastError: Error | null;
req: RelayRequestAny;
}) => any;
export type StatusCheckFn = (
statusCode: number,
req: RelayRequestAny,
res: RelayResponse
) => boolean;
export interface RetryMiddlewareOpts {
fetchTimeout?: number;
retryDelays?: number[] | RetryAfterFn;
statusCodes?: number[] | false | StatusCheckFn;
logger?: Function | false;
allowMutations?: boolean;
allowFormData?: boolean;
forceRetry?: ForceRetryFn | false; // DEPRECATED in favor `beforeRetry`
beforeRetry?: BeforeRetryCb | false;
}
export function retryMiddleware(opts?: RetryMiddlewareOpts): Middleware;
export interface ProgressOpts {
sizeHeader?: string;
onProgress: (runningTotal: number, totalSize: number | null) => any;
}
export function progressMiddleware(opts?: ProgressOpts): Middleware;
export function uploadMiddleware(): Middleware;
export type MiddlewareRawNextFn = (req: RelayRequestAny) => Promise<FetchResponse>;
export type MiddlewareRaw = {
isRawMiddleware: true;
(): (next: MiddlewareRawNextFn) => MiddlewareRawNextFn;
};
export type ConcreteBatch = {
kind: 'Batch';
fragment: any;
id: string | null;
metadata: { [key: string]: any };
name: string;
query: any;
text: string | null;
operationKind: string;
};
export type CacheConfig = {
force?: boolean;
poll?: number;
// rerunParamExperimental?: any;
};
export type Uploadable = File | Blob;
export type UploadableMap = { [key: string]: Uploadable };
export type RelayObservable<T> = Promise<T>;
export type ObservableFromValue<T> = RelayObservable<T> | Promise<T> | T;
export type PayloadData = { [key: string]: any };
export type QueryPayload =
| {
data?: PayloadData | null;
errors?: any[];
rerunVariables?: Variables;
}
| RelayResponse;
export type MiddlewareSync = {
execute: (
operation: ConcreteBatch,
variables: Variables,
cacheConfig: CacheConfig,
uploadables: UploadableMap | null
) => ObservableFromValue<QueryPayload> | null;
};
export type FetchHookFunction = (
operation: ConcreteBatch,
variables: Variables,
cacheConfig: CacheConfig,
uploadables: UploadableMap | null
) => void | ObservableFromValue<QueryPayload>;
export interface Disposable {
dispose(): void;
}
export type SubscribeFunction = (
operation: ConcreteBatch,
variables: Variables,
cacheConfig: CacheConfig,
observer: any
) => RelayObservable<QueryPayload> | Disposable;
export type RelayNetworkLayerOpts = {
subscribeFn?: SubscribeFunction;
beforeFetch?: FetchHookFunction;
noThrow?: boolean;
};
export class RelayNetworkLayer {
execute: ExecuteFunction;
constructor(
middlewares: Array<Middleware | MiddlewareSync | MiddlewareRaw | null>,
opts?: RelayNetworkLayerOpts
);
}
export type GraphQLResponseErrors = Array<{
message: string;
locations?: [{ column: number; line: number }];
stack?: string[];
}>;
export class RRNLError extends Error {
constructor(msg: string);
}
export class RRNLRequestError extends RRNLError {
req: RelayRequestAny;
res?: RelayResponse;
constructor(msg: string);
}
export function createRequestError(
request: RelayRequestAny,
response?: RelayResponse
): RRNLRequestError;
export function formatGraphQLErrors(request: RelayRequest, errors: GraphQLResponseErrors): string;
type ExpressMiddleware = (req: any, res: any) => any;
export function graphqlBatchHTTPWrapper(middleware: ExpressMiddleware): ExpressMiddleware;