Merge branch 'next'
This commit is contained in:
commit
7df0c94f3e
10 changed files with 60 additions and 66 deletions
25
package-lock.json
generated
25
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "react-rest-request",
|
"name": "react-rest-request",
|
||||||
"version": "0.4.1",
|
"version": "0.5.1",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -5083,7 +5083,8 @@
|
||||||
"js-tokens": {
|
"js-tokens": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
|
||||||
"integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
|
"integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"js-yaml": {
|
"js-yaml": {
|
||||||
"version": "3.13.1",
|
"version": "3.13.1",
|
||||||
|
@ -5340,14 +5341,6 @@
|
||||||
"integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
|
"integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"loose-envify": {
|
|
||||||
"version": "1.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
|
|
||||||
"integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=",
|
|
||||||
"requires": {
|
|
||||||
"js-tokens": "^3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"make-dir": {
|
"make-dir": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
|
||||||
|
@ -5624,7 +5617,8 @@
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"object-copy": {
|
"object-copy": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
|
@ -6256,15 +6250,6 @@
|
||||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
|
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"react": {
|
|
||||||
"version": "17.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-17.0.1.tgz",
|
|
||||||
"integrity": "sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w==",
|
|
||||||
"requires": {
|
|
||||||
"loose-envify": "^1.1.0",
|
|
||||||
"object-assign": "^4.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"react-is": {
|
"react-is": {
|
||||||
"version": "17.0.1",
|
"version": "17.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.1.tgz",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "react-rest-request",
|
"name": "react-rest-request",
|
||||||
"version": "0.4.1",
|
"version": "0.5.3",
|
||||||
"description": "Minimalistic REST API client for React inspired by Apollo",
|
"description": "Minimalistic REST API client for React inspired by Apollo",
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"main": "./target/index.js",
|
"main": "./target/index.js",
|
||||||
|
|
|
@ -8,13 +8,16 @@ export enum Method {
|
||||||
DELETE = 'DELETE',
|
DELETE = 'DELETE',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Endpoint<R, _V, P = never> = Readonly<{
|
export type Endpoint<R, V, P = unknown> = Readonly<{
|
||||||
|
_?: V; // Temporary hack to extract the type of variables. Do not use it in real endpoints.
|
||||||
method: Method;
|
method: Method;
|
||||||
url: string | ((params: P) => string);
|
url: string | ((params: P) => string);
|
||||||
headers?: Record<string, string>;
|
headers?: Record<string, string>;
|
||||||
transformResponseData?: (data: any) => R;
|
transformResponseData?: (data: any) => R;
|
||||||
}>
|
}>
|
||||||
|
|
||||||
|
export type AnyEndpoint = Endpoint<any, any, any>
|
||||||
|
|
||||||
export type ExtractEndpointResponse<E> = E extends Endpoint<infer R, any, any> ? R : E extends Endpoint<infer R, any> ? R : never;
|
export type ExtractEndpointResponse<E> = E extends Endpoint<infer R, any, any> ? R : E extends Endpoint<infer R, any> ? R : never;
|
||||||
export type ExtractEndpointVariables<E> = E extends Endpoint<any, infer V, any> ? V : E extends Endpoint<any, infer V> ? V : never;
|
export type ExtractEndpointVariables<E> = E extends Endpoint<any, infer V, any> ? V : E extends Endpoint<any, infer V> ? V : never;
|
||||||
export type ExtractEndpointParams<E> = E extends Endpoint<any, any, infer P> ? P : never;
|
export type ExtractEndpointParams<E> = E extends Endpoint<any, any, infer P> ? P : never;
|
||||||
|
|
|
@ -2,13 +2,13 @@ import React from 'react';
|
||||||
import invariant from 'tiny-invariant';
|
import invariant from 'tiny-invariant';
|
||||||
import isEqual from 'lodash.isequal';
|
import isEqual from 'lodash.isequal';
|
||||||
import { useClient } from './client-hook';
|
import { useClient } from './client-hook';
|
||||||
import { Endpoint, ExtractEndpointParams, ExtractEndpointResponse, ExtractEndpointVariables } from './endpoint';
|
import { AnyEndpoint, ExtractEndpointParams, ExtractEndpointResponse, ExtractEndpointVariables } from './endpoint';
|
||||||
import { PublicRequestState, RequestAction, requestReducer, RequestState } from './reducer';
|
import { PublicRequestState, RequestReducer, requestReducer } from './reducer';
|
||||||
import { useRequestContext } from './request-context';
|
import { useRequestContext } from './request-context';
|
||||||
import { ClientResponse } from './client';
|
import { ClientResponse } from './client';
|
||||||
import { isFunction } from './misc';
|
import { isFunction } from './misc';
|
||||||
|
|
||||||
export type LazyRequestConfig<R, V, P = never> = Readonly<{
|
export type LazyRequestConfig<R, V, P> = Readonly<{
|
||||||
variables?: V;
|
variables?: V;
|
||||||
params?: P;
|
params?: P;
|
||||||
headers?: Record<string, string>;
|
headers?: Record<string, string>;
|
||||||
|
@ -16,29 +16,33 @@ export type LazyRequestConfig<R, V, P = never> = Readonly<{
|
||||||
onFailure?: (res: ClientResponse<R>) => unknown;
|
onFailure?: (res: ClientResponse<R>) => unknown;
|
||||||
}>
|
}>
|
||||||
|
|
||||||
export type LazyRequestHandlerConfig<R, V, P> = Readonly<
|
export type LazyRequestConfigFromEndpoint<E extends AnyEndpoint> = LazyRequestConfig<
|
||||||
LazyRequestConfig<R, V, P>
|
ExtractEndpointResponse<E>,
|
||||||
|
ExtractEndpointVariables<E>,
|
||||||
|
ExtractEndpointParams<E>
|
||||||
|
>;
|
||||||
|
|
||||||
|
export type LazyRequestHandlerConfig<E extends AnyEndpoint> = Readonly<
|
||||||
|
LazyRequestConfigFromEndpoint<E>
|
||||||
& { force?: boolean }
|
& { force?: boolean }
|
||||||
>
|
>
|
||||||
|
|
||||||
export type RequestHandler<R, V, P> = (config?: LazyRequestHandlerConfig<R, V, P>) => Promise<R | null>;
|
export type RequestHandler<E extends AnyEndpoint> =
|
||||||
|
(config?: LazyRequestHandlerConfig<E>) => Promise<ExtractEndpointResponse<E> | null>;
|
||||||
|
|
||||||
export type RefetchRequestHandler = () => void;
|
export type RefetchRequestHandler = () => void;
|
||||||
|
|
||||||
export type PublicRequestStateWithRefetch<R> = PublicRequestState<R> & { refetch: RefetchRequestHandler };
|
export type PublicRequestStateWithRefetch<E extends AnyEndpoint> =
|
||||||
|
PublicRequestState<ExtractEndpointResponse<E>>
|
||||||
|
& { refetch: RefetchRequestHandler };
|
||||||
|
|
||||||
export function useLazyRequest<
|
export function useLazyRequest<E extends AnyEndpoint>(
|
||||||
E extends Endpoint<R, V, P>,
|
|
||||||
R = ExtractEndpointResponse<E>,
|
|
||||||
V = ExtractEndpointVariables<E>,
|
|
||||||
P = ExtractEndpointParams<E>
|
|
||||||
>(
|
|
||||||
endpoint: E,
|
endpoint: E,
|
||||||
config?: LazyRequestConfig<R, V, P>,
|
config?: LazyRequestConfigFromEndpoint<E>,
|
||||||
): [RequestHandler<R, V, P>, PublicRequestStateWithRefetch<R>] {
|
): [RequestHandler<E>, PublicRequestStateWithRefetch<E>] {
|
||||||
const [client] = useClient();
|
const [client] = useClient();
|
||||||
const { defaultHeaders } = useRequestContext();
|
const { defaultHeaders } = useRequestContext();
|
||||||
const [state, dispatch] = React.useReducer<React.Reducer<RequestState<R>, RequestAction<R>>>(
|
const [state, dispatch] = React.useReducer<RequestReducer<ExtractEndpointResponse<E>>>(
|
||||||
requestReducer,
|
requestReducer,
|
||||||
{
|
{
|
||||||
data: null,
|
data: null,
|
||||||
|
@ -46,24 +50,24 @@ export function useLazyRequest<
|
||||||
isCalled: false,
|
isCalled: false,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const [prevHandlerConfig, setPrevHandlerConfig] = React.useState<LazyRequestHandlerConfig<R, V, P> | null>(null);
|
const [prevHandlerConfig, setPrevHandlerConfig] = React.useState<LazyRequestHandlerConfig<E> | null>(null);
|
||||||
|
|
||||||
const transformResponseData = React.useCallback(
|
const transformResponseData = React.useCallback(
|
||||||
(data: unknown): R => {
|
(data: unknown): ExtractEndpointResponse<E> => {
|
||||||
return isFunction(endpoint.transformResponseData) ?
|
return isFunction(endpoint.transformResponseData) ?
|
||||||
endpoint.transformResponseData(data)
|
endpoint.transformResponseData(data)
|
||||||
: data as R;
|
: data as ExtractEndpointResponse<E>;
|
||||||
},
|
},
|
||||||
[endpoint]
|
[endpoint]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handler = React.useCallback(
|
const handler = React.useCallback(
|
||||||
(handlerConfig?: LazyRequestHandlerConfig<R, V, P>) => {
|
(handlerConfig?: LazyRequestHandlerConfig<E>) => {
|
||||||
if (state?.loading) {
|
if (state?.loading) {
|
||||||
return Promise.resolve(null);
|
return Promise.resolve(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
let params: P | undefined;
|
let params: ExtractEndpointParams<E> | undefined;
|
||||||
let endpointUrl: string;
|
let endpointUrl: string;
|
||||||
let isSameRequest = true;
|
let isSameRequest = true;
|
||||||
if (isFunction(endpoint.url)) {
|
if (isFunction(endpoint.url)) {
|
||||||
|
@ -106,7 +110,7 @@ export function useLazyRequest<
|
||||||
setPrevHandlerConfig(handlerConfig ?? {});
|
setPrevHandlerConfig(handlerConfig ?? {});
|
||||||
|
|
||||||
return client
|
return client
|
||||||
.request<R>({
|
.request<ExtractEndpointResponse<E>>({
|
||||||
...endpoint,
|
...endpoint,
|
||||||
url: endpointUrl,
|
url: endpointUrl,
|
||||||
headers,
|
headers,
|
||||||
|
|
|
@ -28,6 +28,8 @@ export type RequestAction<R> =
|
||||||
response: ClientResponse<R>
|
response: ClientResponse<R>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type RequestReducer<R> = React.Reducer<RequestState<R>, RequestAction<R>>
|
||||||
|
|
||||||
export function requestReducer<R>(state: RequestState<R>, action: RequestAction<R>) {
|
export function requestReducer<R>(state: RequestState<R>, action: RequestAction<R>) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'call': {
|
case 'call': {
|
||||||
|
|
|
@ -1,23 +1,18 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import invariant from 'tiny-invariant';
|
import invariant from 'tiny-invariant';
|
||||||
import { Endpoint, ExtractEndpointParams, ExtractEndpointResponse, ExtractEndpointVariables, Method } from './endpoint';
|
import { AnyEndpoint, Method } from './endpoint';
|
||||||
import { LazyRequestConfig, useLazyRequest } from './lazy-request-hook';
|
import { LazyRequestConfigFromEndpoint, useLazyRequest } from './lazy-request-hook';
|
||||||
|
|
||||||
export type RequestConfig<R, V, P> = Readonly<
|
export type RequestConfigFromEndpoint<E extends AnyEndpoint> = Readonly<
|
||||||
LazyRequestConfig<R, V, P>
|
LazyRequestConfigFromEndpoint<E>
|
||||||
& {
|
& {
|
||||||
skip?: boolean,
|
skip?: boolean,
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|
||||||
export function useRequest<
|
export function useRequest<E extends AnyEndpoint>(
|
||||||
E extends Endpoint<R, V, P>,
|
|
||||||
R = ExtractEndpointResponse<E>,
|
|
||||||
V = ExtractEndpointVariables<E>,
|
|
||||||
P = ExtractEndpointParams<E>
|
|
||||||
>(
|
|
||||||
endpoint: E,
|
endpoint: E,
|
||||||
config?: RequestConfig<R, V, P>,
|
config?: RequestConfigFromEndpoint<E>,
|
||||||
) {
|
) {
|
||||||
invariant(
|
invariant(
|
||||||
endpoint.method !== Method.DELETE,
|
endpoint.method !== Method.DELETE,
|
||||||
|
|
4
target/endpoint.d.ts
vendored
4
target/endpoint.d.ts
vendored
|
@ -6,12 +6,14 @@ export declare enum Method {
|
||||||
PATCH = "PATCH",
|
PATCH = "PATCH",
|
||||||
DELETE = "DELETE"
|
DELETE = "DELETE"
|
||||||
}
|
}
|
||||||
export declare type Endpoint<R, _V, P = never> = Readonly<{
|
export declare type Endpoint<R, V, P = unknown> = Readonly<{
|
||||||
|
_?: V;
|
||||||
method: Method;
|
method: Method;
|
||||||
url: string | ((params: P) => string);
|
url: string | ((params: P) => string);
|
||||||
headers?: Record<string, string>;
|
headers?: Record<string, string>;
|
||||||
transformResponseData?: (data: any) => R;
|
transformResponseData?: (data: any) => R;
|
||||||
}>;
|
}>;
|
||||||
|
export declare type AnyEndpoint = Endpoint<any, any, any>;
|
||||||
export declare type ExtractEndpointResponse<E> = E extends Endpoint<infer R, any, any> ? R : E extends Endpoint<infer R, any> ? R : never;
|
export declare type ExtractEndpointResponse<E> = E extends Endpoint<infer R, any, any> ? R : E extends Endpoint<infer R, any> ? R : never;
|
||||||
export declare type ExtractEndpointVariables<E> = E extends Endpoint<any, infer V, any> ? V : E extends Endpoint<any, infer V> ? V : never;
|
export declare type ExtractEndpointVariables<E> = E extends Endpoint<any, infer V, any> ? V : E extends Endpoint<any, infer V> ? V : never;
|
||||||
export declare type ExtractEndpointParams<E> = E extends Endpoint<any, any, infer P> ? P : never;
|
export declare type ExtractEndpointParams<E> = E extends Endpoint<any, any, infer P> ? P : never;
|
||||||
|
|
13
target/lazy-request-hook.d.ts
vendored
13
target/lazy-request-hook.d.ts
vendored
|
@ -1,19 +1,20 @@
|
||||||
import { Endpoint, ExtractEndpointParams, ExtractEndpointResponse, ExtractEndpointVariables } from './endpoint';
|
import { AnyEndpoint, ExtractEndpointParams, ExtractEndpointResponse, ExtractEndpointVariables } from './endpoint';
|
||||||
import { PublicRequestState } from './reducer';
|
import { PublicRequestState } from './reducer';
|
||||||
import { ClientResponse } from './client';
|
import { ClientResponse } from './client';
|
||||||
export declare type LazyRequestConfig<R, V, P = never> = Readonly<{
|
export declare type LazyRequestConfig<R, V, P> = Readonly<{
|
||||||
variables?: V;
|
variables?: V;
|
||||||
params?: P;
|
params?: P;
|
||||||
headers?: Record<string, string>;
|
headers?: Record<string, string>;
|
||||||
onComplete?: (data: R) => unknown;
|
onComplete?: (data: R) => unknown;
|
||||||
onFailure?: (res: ClientResponse<R>) => unknown;
|
onFailure?: (res: ClientResponse<R>) => unknown;
|
||||||
}>;
|
}>;
|
||||||
export declare type LazyRequestHandlerConfig<R, V, P> = Readonly<LazyRequestConfig<R, V, P> & {
|
export declare type LazyRequestConfigFromEndpoint<E extends AnyEndpoint> = LazyRequestConfig<ExtractEndpointResponse<E>, ExtractEndpointVariables<E>, ExtractEndpointParams<E>>;
|
||||||
|
export declare type LazyRequestHandlerConfig<E extends AnyEndpoint> = Readonly<LazyRequestConfigFromEndpoint<E> & {
|
||||||
force?: boolean;
|
force?: boolean;
|
||||||
}>;
|
}>;
|
||||||
export declare type RequestHandler<R, V, P> = (config?: LazyRequestHandlerConfig<R, V, P>) => Promise<R | null>;
|
export declare type RequestHandler<E extends AnyEndpoint> = (config?: LazyRequestHandlerConfig<E>) => Promise<ExtractEndpointResponse<E> | null>;
|
||||||
export declare type RefetchRequestHandler = () => void;
|
export declare type RefetchRequestHandler = () => void;
|
||||||
export declare type PublicRequestStateWithRefetch<R> = PublicRequestState<R> & {
|
export declare type PublicRequestStateWithRefetch<E extends AnyEndpoint> = PublicRequestState<ExtractEndpointResponse<E>> & {
|
||||||
refetch: RefetchRequestHandler;
|
refetch: RefetchRequestHandler;
|
||||||
};
|
};
|
||||||
export declare function useLazyRequest<E extends Endpoint<R, V, P>, R = ExtractEndpointResponse<E>, V = ExtractEndpointVariables<E>, P = ExtractEndpointParams<E>>(endpoint: E, config?: LazyRequestConfig<R, V, P>): [RequestHandler<R, V, P>, PublicRequestStateWithRefetch<R>];
|
export declare function useLazyRequest<E extends AnyEndpoint>(endpoint: E, config?: LazyRequestConfigFromEndpoint<E>): [RequestHandler<E>, PublicRequestStateWithRefetch<E>];
|
||||||
|
|
2
target/reducer.d.ts
vendored
2
target/reducer.d.ts
vendored
|
@ -1,3 +1,4 @@
|
||||||
|
/// <reference types="react" />
|
||||||
import { ClientResponse } from './client';
|
import { ClientResponse } from './client';
|
||||||
export declare type PublicRequestState<R> = Readonly<{
|
export declare type PublicRequestState<R> = Readonly<{
|
||||||
data: R | null;
|
data: R | null;
|
||||||
|
@ -21,6 +22,7 @@ export declare type RequestAction<R> = {
|
||||||
type: 'failure';
|
type: 'failure';
|
||||||
response: ClientResponse<R>;
|
response: ClientResponse<R>;
|
||||||
};
|
};
|
||||||
|
export declare type RequestReducer<R> = React.Reducer<RequestState<R>, RequestAction<R>>;
|
||||||
export declare function requestReducer<R>(state: RequestState<R>, action: RequestAction<R>): {
|
export declare function requestReducer<R>(state: RequestState<R>, action: RequestAction<R>): {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
isCalled: boolean;
|
isCalled: boolean;
|
||||||
|
|
8
target/request-hook.d.ts
vendored
8
target/request-hook.d.ts
vendored
|
@ -1,6 +1,6 @@
|
||||||
import { Endpoint, ExtractEndpointParams, ExtractEndpointResponse, ExtractEndpointVariables } from './endpoint';
|
import { AnyEndpoint } from './endpoint';
|
||||||
import { LazyRequestConfig } from './lazy-request-hook';
|
import { LazyRequestConfigFromEndpoint } from './lazy-request-hook';
|
||||||
export declare type RequestConfig<R, V, P> = Readonly<LazyRequestConfig<R, V, P> & {
|
export declare type RequestConfigFromEndpoint<E extends AnyEndpoint> = Readonly<LazyRequestConfigFromEndpoint<E> & {
|
||||||
skip?: boolean;
|
skip?: boolean;
|
||||||
}>;
|
}>;
|
||||||
export declare function useRequest<E extends Endpoint<R, V, P>, R = ExtractEndpointResponse<E>, V = ExtractEndpointVariables<E>, P = ExtractEndpointParams<E>>(endpoint: E, config?: RequestConfig<R, V, P>): import("./lazy-request-hook").PublicRequestStateWithRefetch<R>;
|
export declare function useRequest<E extends AnyEndpoint>(endpoint: E, config?: RequestConfigFromEndpoint<E>): import("./lazy-request-hook").PublicRequestStateWithRefetch<E>;
|
||||||
|
|
Reference in a new issue