Skip to content

Commit ec40987

Browse files
committed
feat(context): getResponseItem config
1 parent b5e9695 commit ec40987

File tree

4 files changed

+58
-29
lines changed

4 files changed

+58
-29
lines changed

src/context.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { InjectionKey } from "vue";
22
import { getCurrentInstance, inject } from "vue";
33

4-
import type { AxiosInstance } from "axios";
4+
import type { AxiosInstance, AxiosResponse } from "axios";
55
import axios from "axios";
66

77
import type { App } from "../demi";
@@ -12,6 +12,8 @@ const INJECT_INSIDE_WARN_MSG =
1212
export type RequestConfigType = {
1313
/** Axios instance. You can pass your axios with a custom config. */
1414
instance?: AxiosInstance;
15+
/** custom data value. @default response['data'] */
16+
getResponseItem?: (res?: any) => unknown;
1517
};
1618

1719
export const AXIOS_USE_VUE_PROVIDE_KEY = Symbol(
@@ -39,16 +41,17 @@ export const setUseRequestConfig = (app: App, options?: RequestConfigType) => {
3941
}
4042
};
4143

44+
const defaultGetResponseData = (res: AxiosResponse) => res?.data;
45+
4246
export const getUseRequestConfig = (): RequestConfigType &
43-
Required<Pick<RequestConfigType, "instance">> => {
47+
Required<Pick<RequestConfigType, "instance" | "getResponseItem">> => {
4448
const _isInside = Boolean(getCurrentInstance());
4549
if (!_isInside) {
4650
console.warn(INJECT_INSIDE_WARN_MSG);
4751
}
4852

49-
const { instance = axios } = _isInside
50-
? inject<RequestConfigType>(AXIOS_USE_VUE_PROVIDE_KEY, {})
51-
: {};
53+
const { instance = axios, getResponseItem = defaultGetResponseData } =
54+
_isInside ? inject<RequestConfigType>(AXIOS_USE_VUE_PROVIDE_KEY, {}) : {};
5255

53-
return { instance };
56+
return { instance, getResponseItem };
5457
};

src/request.ts

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,43 @@ import type {
66
} from "axios";
77
import axios from "axios";
88

9-
export type _ResponseDataItemType<T> = T extends AxiosResponse<infer D1>
10-
? D1
11-
: T extends { data: infer D2 } | { data?: infer D2 }
12-
? D2
13-
: undefined;
14-
15-
export interface Resource<T, D = any, W = AxiosResponse>
16-
extends AxiosRequestConfig<D> {
17-
_payload?: W extends AxiosResponse ? AxiosResponse<T, D> : T;
9+
export interface Resource<
10+
T = AxiosResponse,
11+
D = any,
12+
K1 extends keyof T = never,
13+
K2 extends keyof T[K1] = never,
14+
K3 extends keyof T[K1][K2] = never,
15+
K4 extends keyof T[K1][K2][K3] = never,
16+
K5 extends keyof T[K1][K2][K3][K4] = never,
17+
> extends AxiosRequestConfig<D> {
18+
_payload?: T;
19+
_payload_item?: [K5] extends [never]
20+
? [K4] extends [never]
21+
? [K3] extends [never]
22+
? [K2] extends [never]
23+
? [K1] extends [never]
24+
? T extends AxiosResponse<infer DD> | { data?: infer DD }
25+
? DD
26+
: undefined
27+
: T[K1]
28+
: T[K1][K2]
29+
: T[K1][K2][K3]
30+
: T[K1][K2][K3][K4]
31+
: T[K1][K2][K3][K4][K5];
1832
}
1933

20-
export type Request<T = any, D = any, W = any> = (
21-
...args: any[]
22-
) => Resource<T, D, W>;
34+
export type Request<
35+
T = any,
36+
D = any,
37+
K1 extends keyof T = never,
38+
K2 extends keyof T[K1] = never,
39+
K3 extends keyof T[K1][K2] = never,
40+
K4 extends keyof T[K1][K2][K3] = never,
41+
K5 extends keyof T[K1][K2][K3][K4] = never,
42+
> = (...args: any[]) => Resource<T, D, K1, K2, K3, K4, K5>;
2343

2444
export type Payload<T extends Request, Check = false> = Check extends true
25-
? _ResponseDataItemType<ReturnType<T>["_payload"]>
45+
? ReturnType<T>["_payload_item"]
2646
: ReturnType<T>["_payload"];
2747
export type BodyData<T extends Request> = ReturnType<T>["data"];
2848

@@ -71,18 +91,23 @@ export type RequestCallbackFn<T extends Request> = {
7191
/**
7292
* For TypeScript type deduction
7393
*/
74-
export function _request<T, D = any, W = false>(
75-
config: AxiosRequestConfig<D>,
76-
): Resource<T, D, W> {
94+
export function _request<
95+
T,
96+
D = any,
97+
K1 extends keyof T = never,
98+
K2 extends keyof T[K1] = never,
99+
K3 extends keyof T[K1][K2] = never,
100+
K4 extends keyof T[K1][K2][K3] = never,
101+
K5 extends keyof T[K1][K2][K3][K4] = never,
102+
>(config: AxiosRequestConfig<D>): Resource<T, D, K1, K2, K3, K4, K5> {
77103
return config;
78104
}
79105

80106
/**
81107
* For TypeScript type deduction
82108
*/
83-
export const request = <T, D = any, W = AxiosResponse<T, D>>(
84-
config: AxiosRequestConfig<D>,
85-
) => _request<T, D, W>(config);
109+
export const request = <T, D = any>(config: AxiosRequestConfig<D>) =>
110+
_request<AxiosResponse<T, D>, D>(config);
86111

87112
export function createRequestError<
88113
T = any,

src/useRequest.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ export function useRequest<T extends Request>(
7676
.then((res: NonNullable<Payload<T>>) => {
7777
removeCancelToken(_source.token);
7878

79-
onCompleted?.(res?.data, res);
80-
return [res?.data, res] as const;
79+
const _data = requestConfig.getResponseItem(res) as Payload<T, true>;
80+
onCompleted?.(_data, res);
81+
return [_data, res] as const;
8182
})
8283
.catch((err: AxiosError<Payload<T>, BodyData<T>>) => {
8384
removeCancelToken(_source.token);

tests/request.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ describe("type checking", () => {
7373
const rq2 = () => _request<DataType2>({});
7474

7575
it("request", () => {
76-
expectTypeOf(rq0()).toEqualTypeOf<Resource<DataType, any, false>>();
76+
expectTypeOf(rq0()).toEqualTypeOf<Resource<DataType, any>>();
7777
expectTypeOf(rq1()).toEqualTypeOf<
78-
Resource<DataType, any, AxiosResponse<DataType, any>>
78+
Resource<AxiosResponse<DataType>, any, "data">
7979
>();
8080

8181
const c0 = null as unknown as Payload<typeof rq0>;

0 commit comments

Comments
 (0)