Skip to content

Commit 924fda2

Browse files
committed
refactor: update FetchClient and BookService for improved type safety and consistency
1 parent 0a712f5 commit 924fda2

File tree

4 files changed

+29
-29
lines changed

4 files changed

+29
-29
lines changed

apps/react-kit-demo/src/services/BookService.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { Book } from '../types/Book';
2-
import { fetchClient } from '@react-kit/*';
1+
import { FetchClient } from '@react-kit/*';
32
import { BASE_API_URL, BOOK_API_URL } from '../constants/ApiConstants';
3+
import { Book } from '../types/Book';
44

55
/**
66
* Utility class for Books operations
@@ -16,6 +16,6 @@ export class BookService {
1616
* @since 1.0.0
1717
*/
1818
static async getAllBooks(): Promise<Book[]> {
19-
return await fetchClient<Book[]>(`${BASE_API_URL + BOOK_API_URL}/books`);
19+
return await FetchClient<Book[]>(`${BASE_API_URL + BOOK_API_URL}/books`);
2020
}
2121
}

react-kit/src/lib/config/fetch/FetchClient.ts

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { createFormattedError } from './FetchInterceptor';
88
* @param params Query parameters
99
* @returns Complete URL with query parameters
1010
*/
11-
const buildURL = (baseURL: string, url: string, params?: Record<string, any>): string => {
11+
const buildURL = (baseURL: string, url: string, params?: Record<string, string | number | boolean>): string => {
1212
const fullURL = url.startsWith('http') ? url : `${baseURL}${url}`;
1313

1414
if (!params) return fullURL;
@@ -28,7 +28,7 @@ const buildURL = (baseURL: string, url: string, params?: Record<string, any>): s
2828
* @param response Fetch response
2929
* @returns Parsed data
3030
*/
31-
const parseResponseData = async (response: Response): Promise<any> => {
31+
const parseResponseData = async (response: Response): Promise<unknown> => {
3232
const contentType = response.headers.get('content-type');
3333

3434
if (contentType?.includes('application/json')) {
@@ -49,7 +49,7 @@ const parseResponseData = async (response: Response): Promise<any> => {
4949
class FetchInstance {
5050
private readonly baseURL: string;
5151
private requestInterceptors: Array<(config: RequestConfig) => RequestConfig | Promise<RequestConfig>> = [];
52-
private responseInterceptors: Array<(response: FetchResponse) => FetchResponse | Promise<FetchResponse>> = [];
52+
private responseInterceptors: Array<(response: FetchResponse<unknown>) => FetchResponse<unknown> | Promise<FetchResponse<unknown>>> = [];
5353
private errorInterceptors: Array<(error: FetchError) => FetchError | Promise<FetchError> | void | Promise<void>> = [];
5454
/**
5555
* Add request interceptor
@@ -62,7 +62,7 @@ class FetchInstance {
6262
},
6363
response: {
6464
use: (
65-
successInterceptor?: (response: FetchResponse) => FetchResponse | Promise<FetchResponse>,
65+
successInterceptor?: (response: FetchResponse<unknown>) => FetchResponse<unknown> | Promise<FetchResponse<unknown>>,
6666
errorInterceptor?: (error: FetchError) => FetchError | Promise<FetchError> | void | Promise<void>
6767
) => {
6868
if (successInterceptor) {
@@ -82,45 +82,49 @@ class FetchInstance {
8282
/**
8383
* GET request
8484
*/
85-
async get<T = any>(url: string, config?: Omit<RequestConfig, 'method' | 'url'>): Promise<FetchResponse<T>> {
85+
async get<T = unknown>(url: string, config?: Omit<RequestConfig, 'method' | 'url'>): Promise<FetchResponse<T>> {
8686
return this.executeRequest({ ...config, method: 'GET', url });
8787
}
8888

8989
/**
9090
* POST request
9191
*/
92-
async post<T = any>(url: string, data?: any, config?: Omit<RequestConfig, 'method' | 'url' | 'body'>): Promise<FetchResponse<T>> {
92+
async post<T = unknown>(url: string, data?: unknown, config?: Omit<RequestConfig, 'method' | 'url' | 'body'>): Promise<FetchResponse<T>> {
9393
const body = data ? JSON.stringify(data) : undefined;
9494
return this.executeRequest({ ...config, method: 'POST', url, body });
9595
}
9696

9797
/**
9898
* PUT request
9999
*/
100-
async put<T = any>(url: string, data?: any, config?: Omit<RequestConfig, 'method' | 'url' | 'body'>): Promise<FetchResponse<T>> {
100+
async put<T = unknown>(url: string, data?: unknown, config?: Omit<RequestConfig, 'method' | 'url' | 'body'>): Promise<FetchResponse<T>> {
101101
const body = data ? JSON.stringify(data) : undefined;
102102
return this.executeRequest({ ...config, method: 'PUT', url, body });
103103
}
104104

105105
/**
106106
* DELETE request
107107
*/
108-
async delete<T = any>(url: string, config?: Omit<RequestConfig, 'method' | 'url'>): Promise<FetchResponse<T>> {
108+
async delete<T = unknown>(url: string, config?: Omit<RequestConfig, 'method' | 'url'>): Promise<FetchResponse<T>> {
109109
return this.executeRequest({ ...config, method: 'DELETE', url });
110110
}
111111

112112
/**
113113
* PATCH request
114114
*/
115-
async patch<T = any>(url: string, data?: any, config?: Omit<RequestConfig, 'method' | 'url' | 'body'>): Promise<FetchResponse<T>> {
115+
async patch<T = unknown>(
116+
url: string,
117+
data?: unknown,
118+
config?: Omit<RequestConfig, 'method' | 'url' | 'body'>
119+
): Promise<FetchResponse<T>> {
116120
const body = data ? JSON.stringify(data) : undefined;
117121
return this.executeRequest<T>({ ...config, method: 'PATCH', url, body });
118122
}
119123

120124
/**
121125
* Generic request method
122126
*/
123-
async request<T = any>(config: RequestConfig): Promise<FetchResponse<T>> {
127+
async request<T = unknown>(config: RequestConfig): Promise<FetchResponse<T>> {
124128
return this.executeRequest(config);
125129
}
126130

@@ -152,15 +156,13 @@ class FetchInstance {
152156
// Apply response interceptors
153157
let processedResponse = fetchResponse;
154158
for (const interceptor of this.responseInterceptors) {
155-
processedResponse = await interceptor(processedResponse);
159+
processedResponse = (await interceptor(processedResponse)) as FetchResponse<T>;
156160
}
157161

158162
return processedResponse;
159163
} catch (error) {
160-
const fetchError = createFormattedError(error as Error, 0, 'Network error. Please check your connection and try again.');
161-
162164
// Apply error interceptors
163-
let processedError = fetchError;
165+
let processedError = createFormattedError(error as Error, 0, 'Network error. Please check your connection and try again.');
164166
for (const interceptor of this.errorInterceptors) {
165167
const result = await interceptor(processedError);
166168
if (result !== undefined) {
@@ -181,12 +183,10 @@ const fetchInstance = new FetchInstance();
181183
/**
182184
* Callable fetch client that defaults to GET requests
183185
*/
184-
export const FetchClient = Object.assign(
185-
async <T = any>(url: string, config?: Omit<RequestConfig, 'method' | 'url'>): Promise<FetchResponse<T>> => {
186-
return fetchInstance.get(url, config);
187-
},
188-
fetchInstance
189-
);
186+
export const FetchClient = Object.assign(async <T = unknown>(url: string, config?: Omit<RequestConfig, 'method' | 'url'>): Promise<T> => {
187+
const response = await fetchInstance.request<T>({ ...config, method: 'GET', url });
188+
return response.data;
189+
}, fetchInstance);
190190

191191
// Export the client instance for direct use
192192
export default FetchClient;

react-kit/src/lib/config/fetch/FetchClientTypes.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export interface ErrorResponse {
77
status: string;
88
statusCode: number;
99
timestamp: string;
10-
errors: any[] | null;
10+
errors: unknown[] | null;
1111
path: string | null;
1212
}
1313

@@ -17,13 +17,13 @@ export interface ErrorResponse {
1717
export interface RequestConfig extends RequestInit {
1818
baseURL?: string;
1919
url?: string;
20-
params?: Record<string, any>;
20+
params?: Record<string, string | number | boolean>;
2121
}
2222

2323
/**
2424
* Interface for response structure
2525
*/
26-
export interface FetchResponse<T = any> {
26+
export interface FetchResponse<T = unknown> {
2727
data: T;
2828
status: number;
2929
statusText: string;

react-kit/src/lib/config/fetch/FetchInterceptor.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import React from 'react';
21
import { useOidc, useOidcIdToken } from '@axa-fr/react-oidc';
3-
import FetchClient from './FetchClient';
4-
import { ErrorResponse, FetchError, FetchResponse } from './FetchClientTypes';
2+
import React from 'react';
53
import {
64
HTTP_401,
75
HTTP_403,
@@ -15,6 +13,8 @@ import {
1513
HTTP_504,
1614
HTTP_505,
1715
} from '../../constants/HttpConstants';
16+
import FetchClient from './FetchClient';
17+
import { ErrorResponse, FetchError, FetchResponse } from './FetchClientTypes';
1818

1919
/**
2020
* Adds error handling interceptor

0 commit comments

Comments
 (0)