Skip to content

Commit 1523b08

Browse files
committed
fix:added support for network error
Signed-off-by: Amitkanswal <[email protected]>
1 parent 72c3dcc commit 1523b08

File tree

3 files changed

+84
-92
lines changed

3 files changed

+84
-92
lines changed

src/uiLocation.ts

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { AxiosRequestConfig, AxiosResponse } from 'axios';
1+
import { AxiosRequestConfig, AxiosResponse } from "axios";
22
import postRobot from "post-robot";
33
import EventEmitter from "wolfy87-eventemitter";
44

@@ -34,7 +34,7 @@ import { GenericObjectType } from "./types/common.types";
3434
import { User } from "./types/user.types";
3535
import { formatAppRegion, onData, onError } from "./utils/utils";
3636
import Window from "./window";
37-
import { dispatchApiRequest, dispatchAdapter } from './utils/adapter';
37+
import { dispatchApiRequest, dispatchAdapter } from "./utils/adapter";
3838
import { ContentstackEndpoints } from "./types/api.type";
3939

4040
const emitter = new EventEmitter();
@@ -70,8 +70,7 @@ class UiLocation {
7070
*/
7171
private config: GenericObjectType;
7272

73-
74-
readonly endpoints: ContentstackEndpoints
73+
readonly endpoints: ContentstackEndpoints;
7574

7675
/**
7776
* This holds the instance of Cross-domain communication library for posting messages between windows.
@@ -158,7 +157,7 @@ class UiLocation {
158157
});
159158

160159
this.metadata = new Metadata(postRobot);
161-
160+
162161
this.config = initializationData.config ?? {};
163162

164163
this.ids = {
@@ -181,14 +180,14 @@ class UiLocation {
181180
FullPage: null,
182181
FieldModifierLocation: null,
183182
ContentTypeSidebarWidget: null,
184-
OrganizationFullPage: null
183+
OrganizationFullPage: null,
185184
};
186185

187186
window["postRobot"] = postRobot;
188187

189188
this.modal = new Modal();
190189

191-
this.region = formatAppRegion(initializationData.region);
190+
this.region = formatAppRegion(initializationData.region);
192191
this.endpoints = initializationData.endpoints;
193192

194193
const stack = new Stack(initializationData.stack, postRobot, {
@@ -292,10 +291,10 @@ class UiLocation {
292291

293292
case LocationType.ORGANIZATION_FULL_PAGE: {
294293
this.location.OrganizationFullPage = {
295-
currentOrganization: initializationData.organization,
294+
currentOrganization: initializationData.organization,
296295
};
297296
break;
298-
}
297+
}
299298

300299
case LocationType.CONTENT_TYPE_SIDEBAR_WIDGET: {
301300
this.location.ContentTypeSidebarWidget =
@@ -477,23 +476,28 @@ class UiLocation {
477476
return this.region;
478477
};
479478

480-
getEndpoints = ():ContentstackEndpoints => {
479+
getEndpoints = (): ContentstackEndpoints => {
481480
return this.endpoints;
482-
}
481+
};
483482
/**
484483
* Method used to make an API request to the Contentstack's CMA APIs.
485484
*/
486485

487-
api = (url: string, option?: RequestInit): Promise<Response> => dispatchApiRequest(url, option) as Promise<Response>;
486+
api = (url: string, option?: RequestInit): Promise<Response> =>
487+
dispatchApiRequest(url, option) as Promise<Response>;
488488

489489
/**
490490
* Method used to create an adapter for management sdk.
491491
*/
492-
createAdapter = (): (config: AxiosRequestConfig) => Promise<AxiosResponse> => {
492+
createAdapter = (): ((
493+
config: AxiosRequestConfig
494+
) => Promise<AxiosResponse>) => {
493495
return (config: AxiosRequestConfig): Promise<AxiosResponse> => {
494-
return dispatchAdapter(postRobot)(config)
496+
return dispatchAdapter(postRobot)(config) as Promise<
497+
AxiosResponse<any, any>
498+
>;
495499
};
496-
};
500+
};
497501

498502
/**
499503
* Method used to initialize the App SDK.

src/utils/adapter.ts

Lines changed: 62 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,59 @@ import PostRobot from "post-robot";
22
import { Response } from "node-fetch";
33
import {
44
AxiosError,
5+
AxiosHeaders,
56
AxiosRequestConfig,
67
AxiosResponse,
78
} from "axios";
89

9-
import {
10-
onError,
11-
fetchToAxiosConfig,
12-
handleApiError,
13-
sanitizeResponseHeader,
14-
} from "./utils";
10+
import { fetchToAxiosConfig } from "./utils";
1511

1612
/**
1713
* Dispatches a request using PostRobot.
1814
* @param postRobot - The PostRobot instance.
1915
* @returns A function that takes AxiosRequestConfig and returns a promise.
2016
*/
2117
export const dispatchAdapter =
22-
(postRobot: typeof PostRobot) =>
23-
(config: AxiosRequestConfig): Promise<AxiosResponse> => {
24-
return postRobot
25-
.sendToParent("apiAdapter", config)
26-
.then((event: unknown) => {
27-
const { data } = event as { data: AxiosResponse };
28-
if (data.status >= 400) {
29-
throw data
30-
}
31-
return data;
32-
})
33-
.catch((err)=>onError(err));
18+
(postRobot: typeof PostRobot) => (config: AxiosRequestConfig) => {
19+
return new Promise((resolve, reject) => {
20+
postRobot
21+
.sendToParent("apiAdapter", config)
22+
.then((event: unknown) => {
23+
const { data: response } = event as { data: AxiosResponse };
24+
25+
if (response.status >= 400) {
26+
return reject({ ...response, config });
27+
}
28+
resolve({
29+
data: response.data,
30+
status: response.status,
31+
statusText: response.statusText,
32+
headers: response.headers,
33+
config: config,
34+
});
35+
})
36+
.catch(() => {
37+
return reject(
38+
new AxiosError(
39+
"Something went wrong with the request",
40+
"ERR_INTERNAL_SERVER",
41+
{
42+
...config,
43+
headers: config.headers as AxiosHeaders,
44+
},
45+
null,
46+
undefined
47+
)
48+
);
49+
});
50+
});
3451
};
3552
/**
53+
GitHub Copilot
54+
To handle errors generically and robustly, we can refactor the code to ensure that all errors are properly processed and converted into a standardized format. Here's how you can fix and improve the error handling in the provided code:
55+
56+
Refactored Code
57+
3658
* Dispatches an API request using axios and PostRobot.
3759
* @param url - The URL of the API endpoint.
3860
* @param options - Optional request options.
@@ -44,20 +66,30 @@ export const dispatchApiRequest = async (
4466
): Promise<Response> => {
4567
try {
4668
const config = fetchToAxiosConfig(url, options);
47-
const responseData = (await dispatchAdapter(PostRobot)(
69+
const response = (await dispatchAdapter(PostRobot)(
4870
config
4971
)) as AxiosResponse;
50-
51-
52-
return new Response(responseData?.data, {
53-
status: responseData.status,
54-
statusText: responseData.statusText,
55-
url: responseData.config.url,
56-
headers: new Headers(
57-
sanitizeResponseHeader(responseData.config.headers || {})
58-
),
72+
73+
return new Response(response?.data, {
74+
status: response.status,
75+
statusText: response.statusText,
76+
url: response.config.url,
77+
headers: new Headers(Object.entries(response.headers ?? {})),
78+
});
79+
} catch (err: any) {
80+
if (err.response) {
81+
return new Response(err.response?.data, {
82+
status: err.status,
83+
statusText: err.statusText,
84+
headers: new Headers(
85+
Object.entries(err.response.headers ?? {})
86+
),
87+
});
88+
}
89+
return new Response(err.stack, {
90+
status: err.status || 500,
91+
statusText: err.message || "Internal Server Error",
92+
headers: new Headers(Object.entries(err.headers ?? {})),
5993
});
60-
} catch (error) {
61-
return handleApiError(error as AxiosResponse | AxiosError);
6294
}
6395
};

src/utils/utils.ts

Lines changed: 3 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,7 @@
1-
import {
2-
AxiosError,
3-
AxiosHeaders,
4-
AxiosRequestConfig,
5-
AxiosResponse,
6-
isAxiosError,
7-
RawAxiosRequestHeaders,
8-
} from "axios";
9-
import { Response } from "node-fetch";
1+
import { AxiosHeaders, AxiosRequestConfig } from "axios";
102

113
import { Region, RegionType } from "../types";
124

13-
const filterHeaders = [
14-
"api_key",
15-
"authorization",
16-
"auth_token",
17-
"x-api-key",
18-
"user-agent",
19-
];
20-
215
export function onData<Data extends Record<string, any>>(data: { data: Data }) {
226
if (typeof data.data === "string") {
237
return Promise.reject(data.data);
@@ -32,39 +16,11 @@ export function onError(error: Error) {
3216
export function sanitizeResponseHeader(axiosHeaders) {
3317
const fetchHeaders = new Headers();
3418
for (const key in axiosHeaders) {
35-
if (axiosHeaders.hasOwnProperty(key) && !filterHeaders.includes(key)) {
36-
fetchHeaders.append(key, axiosHeaders[key]);
37-
}
19+
fetchHeaders.append(key, axiosHeaders[key]);
3820
}
3921
return fetchHeaders;
40-
};
41-
export const handleApiError = (error: AxiosResponse | AxiosError): Response => {
42-
if (isAxiosError(error)) {
43-
const isServerError = (error?.status ?? 0) >= 500;
44-
const responseBody = isServerError
45-
? error.stack || "Internal Server Error"
46-
: (error as unknown as AxiosResponse)?.data || "An error occurred";
47-
const status = error?.status || 500;
48-
const statusText =
49-
isServerError
50-
? error.message || "Internal Server Error"
51-
: (error as unknown as AxiosResponse)?.statusText || "Error";
52-
const headers = new Headers(
53-
sanitizeResponseHeader(error.response?.headers || {})
54-
);
55-
return new Response(JSON.stringify(responseBody), {
56-
status,
57-
statusText,
58-
headers,
59-
});
60-
} else {
61-
const responseBody = error.statusText || "An error occurred";
62-
return new Response(JSON.stringify(responseBody), {
63-
status: 500,
64-
statusText: "Internal Server Error",
65-
});
66-
}
6722
}
23+
6824
export function formatAppRegion(region: string): RegionType {
6925
return region ?? Region.UNKNOWN;
7026
}

0 commit comments

Comments
 (0)