Skip to content

Commit bbe5046

Browse files
committed
fix:update api implementation
Signed-off-by: Amitkanswal <[email protected]>
1 parent 802585e commit bbe5046

File tree

10 files changed

+5749
-5508
lines changed

10 files changed

+5749
-5508
lines changed

__test__/init.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import UiLocation from "../src/uiLocation";
33
import { version } from "../package.json";
44

55
jest.mock("../src/uiLocation");
6+
jest.mock("axios");
67

78
describe("ContentstackAppSDK", () => {
89
describe("init", () => {

__test__/uiLocation.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
Region,
1414
} from "../src/types";
1515
import { RequestOption } from '../src/types/common.types';
16-
import { ApiRequestParams } from '../src/types/api.type';
16+
import { ProxyConfig } from '../src/types/api.type';
1717

1818
jest.mock("post-robot");
1919
jest.mock("wolfy87-eventemitter");
@@ -189,7 +189,7 @@ describe("UI Location", () => {
189189

190190
describe("createSDKAdapter", () => {
191191
let mockPostRobot: typeof postRobot;
192-
let opts: ApiRequestParams;
192+
let opts: ProxyConfig;
193193
let uiLocationInstance: UiLocation;
194194
let onError: jest.Mock;
195195
beforeEach(() => {

jest.config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ module.exports = {
66
testEnvironment: "jsdom",
77
transform: {
88
"^.+\\.(ts|tsx)$": "ts-jest",
9+
"^.+\\.(js|jsx)$": "babel-jest",
10+
},
11+
moduleNameMapper: {
12+
"^axios$": "axios/dist/node/axios.cjs"
913
},
1014
collectCoverageFrom: ["./src/**"],
1115
coveragePathIgnorePatterns: ["<rootDir>.*types.ts"],

package-lock.json

Lines changed: 279 additions & 140 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
"webpack-dev-server": "^4.7.3"
5959
},
6060
"dependencies": {
61+
"axios": "^1.7.9",
6162
"jsonfile": "^6.1.0",
6263
"loader-utils": "^3.2.1",
6364
"post-robot": "^8.0.31",

src/types/api.type.ts

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,2 @@
1-
import { HTTPMethods } from './common.types';
2-
3-
export interface ApiRequestParams {
4-
url: string;
5-
method: HTTPMethods;
6-
baseURL?: string;
7-
headers?: Record<string, string>;
8-
data?: unknown;
9-
[key: string]: any;
10-
}
11-
12-
export interface ApiResponse<T = any> {
13-
data: T;
14-
status: number;
15-
statusText: string;
16-
headers: Record<string, string>;
17-
request?: any;
18-
}
1+
import { AxiosRequestConfig } from 'axios'
2+
export type ProxyConfig = AxiosRequestConfig

src/uiLocation.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ import { GenericObjectType, RequestOption } from "./types/common.types";
3333
import { User } from "./types/user.types";
3434
import { formatAppRegion, onData, onError } from "./utils/utils";
3535
import Window from "./window";
36-
import { createSDKAdapter, dispatchPostRobotRequest } from './utils/adapter';
37-
import {ApiRequestParams, ApiResponse } from './types/api.type';
36+
import { dispatchApiRequest, dispatchPostRobotRequest } from './utils/adapter';
37+
import {ProxyConfig } from './types/api.type';
3838

3939
const emitter = new EventEmitter();
4040

@@ -476,13 +476,13 @@ class UiLocation {
476476
* Method used to make an API request to the Contentstack's CMA APIs.
477477
*/
478478

479-
api = (url: string, option?: RequestOption) => dispatchPostRobotRequest(this.postRobot)(url, option );
479+
api = (url: string, option?: RequestInit): Promise<Response> => dispatchApiRequest(url, option) as Promise<Response>;
480480

481481
/**
482482
* Method used to create an adapter for management sdk.
483483
*/
484484

485-
createAdapter = <T>(config: unknown) => createSDKAdapter(this.postRobot)(config as unknown as ApiRequestParams) as Promise<ApiResponse<T>>;
485+
createAdapter = (config: ProxyConfig) => dispatchPostRobotRequest(this.postRobot)(config) as Promise<Response>;
486486

487487
/**
488488
* Method used to initialize the App SDK.

src/utils/adapter.ts

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,54 @@
11
import PostRobot from 'post-robot';
2-
import { onData, onError } from './utils';
3-
import { ApiRequestParams } from '../types/api.type';
4-
import { RequestOption, GenericObjectType } from '../types/common.types';
2+
import axios, { AxiosRequestConfig, AxiosResponse} from 'axios';
53

6-
export const dispatchPostRobotRequest = (postRobot: typeof PostRobot) => (url:string ,opts?: RequestOption): Promise<GenericObjectType> => {
4+
import { onData, onError, convertHeaders,convertAxiosHeadersToHeadersInit } from './utils';
5+
6+
/**
7+
* Dispatches a request using PostRobot.
8+
* @param postRobot - The PostRobot instance.
9+
* @returns A function that takes AxiosRequestConfig and returns a promise.
10+
*/
11+
export const dispatchPostRobotRequest = (postRobot: typeof PostRobot) => (config: AxiosRequestConfig)=> {
712
return postRobot
8-
.sendToParent("apiAdapter", {url, option:opts})
13+
.sendToParent("apiAdapter", config )
914
.then(onData)
1015
.catch(onError);
1116
};
1217

13-
export const createSDKAdapter = (postRobot: typeof PostRobot) => async (config: ApiRequestParams) => {
18+
/**
19+
* Dispatches an API request using axios and PostRobot.
20+
* @param url - The URL of the API endpoint.
21+
* @param options - Optional request options.
22+
* @returns A promise that resolves to a partial Response object.
23+
*/
24+
export const dispatchApiRequest = async (url: string, options?: RequestInit):Promise<Partial<Response>> => {
1425
try {
15-
const data = await dispatchPostRobotRequest(postRobot)(config.url, {
16-
baseURL: config.baseURL,
17-
url: config.url,
18-
method: config.method,
19-
headers: config.headers,
20-
body: config.data as BodyInit,
21-
});
22-
return {
23-
data,
24-
status: data?.status || 200,
25-
statusText: 'OK',
26-
headers: config.headers || {},
26+
const config: AxiosRequestConfig = {
27+
url,
28+
method: options?.method || "GET",
29+
...(options?.headers && { headers: convertHeaders(options.headers) }),
30+
...(options?.body && { data: options?.body })
2731
};
28-
} catch (error) {
29-
const typedError = error as GenericObjectType & { status?: number; statusText?: string; headers?: Record<string, string>; body?: any; message?: string };
30-
return {
31-
data: typedError.body || typedError.message || typedError.data,
32-
status: typedError.status || 500,
33-
statusText: typedError.statusText || 'Internal Server Error',
34-
headers: typedError.headers || {},
32+
33+
const responseData = await dispatchPostRobotRequest(PostRobot)(config) as AxiosResponse;
34+
35+
const fetchResponse: Partial<Response> = {
36+
ok: responseData.status >= 200 && responseData.status < 300,
37+
status: responseData.status,
38+
statusText: responseData.statusText,
39+
headers: new Headers(convertAxiosHeadersToHeadersInit(responseData.headers || {})),
40+
json: async () => responseData.data,
41+
text: async () => JSON.stringify(responseData.data),
3542
};
43+
44+
return fetchResponse;
45+
} catch (error) {
46+
if (axios.isAxiosError(error)) {
47+
console.error("API request failed:", error.message);
48+
throw new Error(`API request failed: ${error.message}`);
49+
} else {
50+
console.error("An error occurred:", error);
51+
throw new Error("An error occurred");
52+
}
3653
}
37-
};
54+
};

src/utils/utils.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Region } from "../types";
2+
import { AxiosHeaders } from "axios";
23

34
export function onData<Data extends Record<string, any>>(data: { data: Data }) {
45
if (typeof data.data === "string") {
@@ -48,3 +49,30 @@ export function getPreferredBodyElement(nodeCollection: HTMLCollection) {
4849
}
4950
return rootElement || nodeCollection[0];
5051
}
52+
53+
54+
export const convertHeaders = (headers: HeadersInit): AxiosHeaders => {
55+
const axiosHeaders = new AxiosHeaders();
56+
if (headers instanceof Headers) {
57+
headers.forEach((value, key) => {
58+
axiosHeaders.set(key, value);
59+
});
60+
} else if (Array.isArray(headers)) {
61+
headers.forEach(([key, value]) => {
62+
axiosHeaders.set(key, value);
63+
});
64+
} else {
65+
Object.entries(headers).forEach(([key, value]) => {
66+
axiosHeaders.set(key, value);
67+
});
68+
}
69+
return axiosHeaders;
70+
};
71+
72+
export const convertAxiosHeadersToHeadersInit = (axiosHeaders: any): HeadersInit => {
73+
const headers: HeadersInit = {};
74+
Object.keys(axiosHeaders).forEach(key => {
75+
headers[key] = axiosHeaders[key];
76+
});
77+
return headers;
78+
};

0 commit comments

Comments
 (0)