From cf6a1f7a91097fec9c9f201c684b203c242de356 Mon Sep 17 00:00:00 2001 From: Mostafa Date: Mon, 6 May 2024 17:29:32 +0300 Subject: [PATCH 1/3] SCKT-6 | Add the option of passing response type parameter to methods --- README.md | 13 +++++++++++-- src/ApiKitClient.ts | 46 +++++++++++++++++++++++++++++---------------- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 2d25e07..cf48633 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ A versatile, type-safe API client designed for TypeScript applications. It simpl - **Authorization Support**: Automatically includes authorization tokens in requests. - **Customizable Unauthorized Access Handling**: Executes a callback function when encountering a 401 Unauthorized response, allowing for custom reaction strategies such as redirecting to a login page. - **Simplified API Requests**: Offers methods for common HTTP requests (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`) with a straightforward, promise-based API. +- **Flexible Response Handling**: Allows specifying the `responseType` for requests, enabling direct handling of blobs, JSON, and other formats. ## Installation @@ -46,7 +47,7 @@ Use the `ApiKitClient` instance to make API requests. Here are some examples: ### Fetching Data -Fetch a list of resources: +Fetch a list of resources specifying the expected response type: ```ts interface User { @@ -68,6 +69,14 @@ ApiKitClient.getOne('/users/1') .catch(error => console.error(error)); ``` +Fetch a blob data: + +```ts +ApiKitClient.get('/download', undefined, 'blob') + .then(response => console.log(response.data)) // Expected to be of type Blob + .catch(error => console.error(error)); +``` + Fetch a paginated resource: ```ts @@ -86,7 +95,7 @@ const newUser: User = { email: 'john@example.com', }; -ApiKitClient.post('/users', newUser) +ApiKitClient.post('/users', newUser, 'json') .then(response => console.log(response.data)) // Expected to be of type User .catch(error => console.error(error)); ``` diff --git a/src/ApiKitClient.ts b/src/ApiKitClient.ts index 2302a80..73c334a 100644 --- a/src/ApiKitClient.ts +++ b/src/ApiKitClient.ts @@ -1,4 +1,4 @@ -import axios, { AxiosInstance, AxiosResponse, AxiosError } from 'axios'; +import axios, { AxiosInstance, AxiosResponse, AxiosError, AxiosRequestConfig } from 'axios'; import { PaginatedResponse } from './types'; type UnauthorizationCallback = () => void; @@ -41,38 +41,52 @@ export class ApiKitClient { } } - public static async get(endpoint: string, params?: URLSearchParams): Promise> { + private static createConfig(responseType?: AxiosRequestConfig['responseType'], params?: URLSearchParams): AxiosRequestConfig { + return { + responseType, + params + }; + } + + public static async get(endpoint: string, params?: URLSearchParams, responseType?: AxiosRequestConfig['responseType']): Promise> { this.checkInitialization(); - return this.instance!.get(endpoint, { params }); + const config = this.createConfig(responseType, params); + return this.instance!.get(endpoint, config); } - - public static async getOne(endpoint: string, params?: URLSearchParams): Promise> { + + public static async getOne(endpoint: string, params?: URLSearchParams, responseType?: AxiosRequestConfig['responseType']): Promise> { this.checkInitialization(); - return this.instance!.get(endpoint, { params }); + const config = this.createConfig(responseType, params); + return this.instance!.get(endpoint, config); } - public static async getPaginated(endpoint: string, params?: URLSearchParams): Promise>> { + public static async getPaginated(endpoint: string, params?: URLSearchParams, responseType?: AxiosRequestConfig['responseType']): Promise>> { this.checkInitialization(); - return this.instance!.get>(endpoint, { params }); + const config = this.createConfig(responseType, params); + return this.instance!.get>(endpoint, config); } - public static async post(endpoint: string, data: T): Promise> { + public static async post(endpoint: string, data: T, responseType?: AxiosRequestConfig['responseType']): Promise> { this.checkInitialization(); - return this.instance!.post(endpoint, data); + const config = this.createConfig(responseType); + return this.instance!.post(endpoint, data, config); } - public static async put(endpoint: string, data: T): Promise> { + public static async put(endpoint: string, data: T, responseType?: AxiosRequestConfig['responseType']): Promise> { this.checkInitialization(); - return this.instance!.put(endpoint, data); + const config = this.createConfig(responseType); + return this.instance!.put(endpoint, data, config); } - public static async patch(endpoint: string, data: T): Promise> { + public static async patch(endpoint: string, data: T, responseType?: AxiosRequestConfig['responseType']): Promise> { this.checkInitialization(); - return this.instance!.patch(endpoint, data); + const config = this.createConfig(responseType); + return this.instance!.patch(endpoint, data, config); } - public static async delete(endpoint: string): Promise> { + public static async delete(endpoint: string, responseType?: AxiosRequestConfig['responseType']): Promise> { this.checkInitialization(); - return this.instance!.delete(endpoint); + const config = this.createConfig(responseType); + return this.instance!.delete(endpoint, config); } } From 5c11d2dfc817dbfecca1ccdf9e840b6c3f2b8a04 Mon Sep 17 00:00:00 2001 From: Mostafa Date: Wed, 8 May 2024 11:21:04 +0300 Subject: [PATCH 2/3] SCKT-6 | Options - Add responseType and params to options object --- README.md | 4 ++-- src/ApiKitClient.ts | 34 +++++++++++++++++----------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index cf48633..462cf40 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ ApiKitClient.getOne('/users/1') Fetch a blob data: ```ts -ApiKitClient.get('/download', undefined, 'blob') +ApiKitClient.get('/download', { responseType: 'blob' }) .then(response => console.log(response.data)) // Expected to be of type Blob .catch(error => console.error(error)); ``` @@ -95,7 +95,7 @@ const newUser: User = { email: 'john@example.com', }; -ApiKitClient.post('/users', newUser, 'json') +ApiKitClient.post('/users', newUser, { responseType: 'json' }) // by default is json, so you don't need to explicitly set it unless you need a different type (like 'blob', 'document', 'arraybuffer', or 'text'). .then(response => console.log(response.data)) // Expected to be of type User .catch(error => console.error(error)); ``` diff --git a/src/ApiKitClient.ts b/src/ApiKitClient.ts index 73c334a..bc48e0f 100644 --- a/src/ApiKitClient.ts +++ b/src/ApiKitClient.ts @@ -41,52 +41,52 @@ export class ApiKitClient { } } - private static createConfig(responseType?: AxiosRequestConfig['responseType'], params?: URLSearchParams): AxiosRequestConfig { + private static createConfig(options?: { responseType?: AxiosRequestConfig['responseType'], params?: URLSearchParams }): AxiosRequestConfig { return { - responseType, - params + responseType: options?.responseType, + params: options?.params }; } - public static async get(endpoint: string, params?: URLSearchParams, responseType?: AxiosRequestConfig['responseType']): Promise> { + public static async get(endpoint: string, options?: { params?: URLSearchParams, responseType?: AxiosRequestConfig['responseType'] }): Promise> { this.checkInitialization(); - const config = this.createConfig(responseType, params); + const config = this.createConfig(options); return this.instance!.get(endpoint, config); } - public static async getOne(endpoint: string, params?: URLSearchParams, responseType?: AxiosRequestConfig['responseType']): Promise> { + public static async getOne(endpoint: string, options?: { params?: URLSearchParams, responseType?: AxiosRequestConfig['responseType'] }): Promise> { this.checkInitialization(); - const config = this.createConfig(responseType, params); + const config = this.createConfig(options); return this.instance!.get(endpoint, config); } - public static async getPaginated(endpoint: string, params?: URLSearchParams, responseType?: AxiosRequestConfig['responseType']): Promise>> { + public static async getPaginated(endpoint: string, options?: { params?: URLSearchParams, responseType?: AxiosRequestConfig['responseType'] }): Promise>> { this.checkInitialization(); - const config = this.createConfig(responseType, params); + const config = this.createConfig(options); return this.instance!.get>(endpoint, config); } - public static async post(endpoint: string, data: T, responseType?: AxiosRequestConfig['responseType']): Promise> { + public static async post(endpoint: string, data: T, options?: { responseType?: AxiosRequestConfig['responseType'] }): Promise> { this.checkInitialization(); - const config = this.createConfig(responseType); + const config = this.createConfig(options); return this.instance!.post(endpoint, data, config); } - public static async put(endpoint: string, data: T, responseType?: AxiosRequestConfig['responseType']): Promise> { + public static async put(endpoint: string, data: T, options?: { responseType?: AxiosRequestConfig['responseType'] }): Promise> { this.checkInitialization(); - const config = this.createConfig(responseType); + const config = this.createConfig(options); return this.instance!.put(endpoint, data, config); } - public static async patch(endpoint: string, data: T, responseType?: AxiosRequestConfig['responseType']): Promise> { + public static async patch(endpoint: string, data: T, options?: { responseType?: AxiosRequestConfig['responseType'] }): Promise> { this.checkInitialization(); - const config = this.createConfig(responseType); + const config = this.createConfig(options); return this.instance!.patch(endpoint, data, config); } - public static async delete(endpoint: string, responseType?: AxiosRequestConfig['responseType']): Promise> { + public static async delete(endpoint: string, options?: { responseType?: AxiosRequestConfig['responseType'] }): Promise> { this.checkInitialization(); - const config = this.createConfig(responseType); + const config = this.createConfig(options); return this.instance!.delete(endpoint, config); } } From bf1cd4ed3f5991382a8dc9260bd90195a4eedb32 Mon Sep 17 00:00:00 2001 From: Mostafa Date: Wed, 8 May 2024 11:36:53 +0300 Subject: [PATCH 3/3] SCKT-6 | Options - Add options type --- src/ApiKitClient.ts | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/ApiKitClient.ts b/src/ApiKitClient.ts index bc48e0f..b22aed1 100644 --- a/src/ApiKitClient.ts +++ b/src/ApiKitClient.ts @@ -3,6 +3,10 @@ import { PaginatedResponse } from './types'; type UnauthorizationCallback = () => void; type AuthTokenCallback = () => Promise; +type Options = { + responseType?: AxiosRequestConfig['responseType'], + params?: URLSearchParams +} export class ApiKitClient { private static instance: AxiosInstance; @@ -41,50 +45,50 @@ export class ApiKitClient { } } - private static createConfig(options?: { responseType?: AxiosRequestConfig['responseType'], params?: URLSearchParams }): AxiosRequestConfig { + private static createConfig(options?: Options): AxiosRequestConfig { return { responseType: options?.responseType, params: options?.params }; } - public static async get(endpoint: string, options?: { params?: URLSearchParams, responseType?: AxiosRequestConfig['responseType'] }): Promise> { + public static async get(endpoint: string, options?: Options): Promise> { this.checkInitialization(); const config = this.createConfig(options); return this.instance!.get(endpoint, config); } - public static async getOne(endpoint: string, options?: { params?: URLSearchParams, responseType?: AxiosRequestConfig['responseType'] }): Promise> { + public static async getOne(endpoint: string, options?: Options): Promise> { this.checkInitialization(); const config = this.createConfig(options); return this.instance!.get(endpoint, config); } - public static async getPaginated(endpoint: string, options?: { params?: URLSearchParams, responseType?: AxiosRequestConfig['responseType'] }): Promise>> { + public static async getPaginated(endpoint: string, options?: Options): Promise>> { this.checkInitialization(); const config = this.createConfig(options); return this.instance!.get>(endpoint, config); } - public static async post(endpoint: string, data: T, options?: { responseType?: AxiosRequestConfig['responseType'] }): Promise> { + public static async post(endpoint: string, data: T, options?: Options): Promise> { this.checkInitialization(); const config = this.createConfig(options); return this.instance!.post(endpoint, data, config); } - public static async put(endpoint: string, data: T, options?: { responseType?: AxiosRequestConfig['responseType'] }): Promise> { + public static async put(endpoint: string, data: T, options?: Options): Promise> { this.checkInitialization(); const config = this.createConfig(options); return this.instance!.put(endpoint, data, config); } - public static async patch(endpoint: string, data: T, options?: { responseType?: AxiosRequestConfig['responseType'] }): Promise> { + public static async patch(endpoint: string, data: T, options?: Options): Promise> { this.checkInitialization(); const config = this.createConfig(options); return this.instance!.patch(endpoint, data, config); } - public static async delete(endpoint: string, options?: { responseType?: AxiosRequestConfig['responseType'] }): Promise> { + public static async delete(endpoint: string, options?: Options): Promise> { this.checkInitialization(); const config = this.createConfig(options); return this.instance!.delete(endpoint, config);