Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 1 addition & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './lib/contentstack-error';
export * from './lib/api-error';
export * from './lib/request';
export * from './lib/retryPolicy/delivery-sdk-handlers';
export * from './lib/error-messages';
8 changes: 5 additions & 3 deletions src/lib/api-error.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ERROR_MESSAGES } from './error-messages';

/**
* Custom error class for API errors with optimized error handling
*/
Expand Down Expand Up @@ -27,10 +29,10 @@ export class APIError extends Error {
return APIError.fromResponseData(err.response.data, err.response.status);
} else if (err.message) {
// For network errors or other non-HTTP errors
return new APIError(err.message, err.code || 'NETWORK_ERROR', 0);
return new APIError(err.message, err.code || ERROR_MESSAGES.ERROR_CODES.NETWORK_ERROR, 0);
} else {
// Fallback for unknown errors
return new APIError('Unknown error occurred', 'UNKNOWN_ERROR', 0);
return new APIError(ERROR_MESSAGES.API.UNKNOWN_ERROR, ERROR_MESSAGES.ERROR_CODES.UNKNOWN_ERROR, 0);
}
}

Expand Down Expand Up @@ -58,7 +60,7 @@ export class APIError extends Error {
if (responseData.message) return responseData.message;
if (responseData.error) return responseData.error;
if (typeof responseData === 'string') return responseData;
return 'Request failed';
return ERROR_MESSAGES.API.REQUEST_FAILED();
}

/**
Expand Down
5 changes: 3 additions & 2 deletions src/lib/contentstack-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { cloneDeep } from 'lodash';
import { serialize } from './param-serializer';
import axios, { AxiosRequestHeaders, getAdapter } from 'axios';
import { AxiosInstance, HttpClientParams } from './types';
import { ERROR_MESSAGES } from './error-messages';

export function httpClient(options: HttpClientParams): AxiosInstance {
const defaultConfig = {
Expand All @@ -17,12 +18,12 @@ export function httpClient(options: HttpClientParams): AxiosInstance {
if (level === 'error') {
if (data) {
const title = [data.name, data.message].filter((a) => a).join(' - ');
console.error(`[error] ${title}`);
console.error(ERROR_MESSAGES.CONSOLE.ERROR_WITH_TITLE(title));
}
return;
}
if (data !== undefined) {
console.log(`[${level}] ${data}`);
console.log(ERROR_MESSAGES.CONSOLE.LEVEL_WITH_DATA(level, data));
}
},
retryCondition: (error: any) => {
Expand Down
43 changes: 43 additions & 0 deletions src/lib/error-messages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Centralized Error Messages
*
* This file contains all error messages used throughout the contentstack-js-core SDK.
* Centralizing error messages makes them easier to maintain, review, and localize.
*/

export const ERROR_MESSAGES = {
// Console Logging Messages
CONSOLE: {
ERROR_WITH_TITLE: (title: string) => `Error: ${title}. Review the error details and try again.`,
LEVEL_WITH_DATA: (level: string, data: any) => `${level}: ${data}. Review the details and try again.`,
},

// API Error Messages
API: {
NETWORK_ERROR: 'Network error occurred. Please check your internet connection and try again.',
UNKNOWN_ERROR: 'An unknown error occurred. Please try again or contact support if the issue persists.',
REQUEST_FAILED: (status?: number) =>
status
? `Request failed with status ${status}. Please review your request and try again.`
: 'Request failed. Please review your request and try again.',
},

// Request Handler Messages
REQUEST: {
HOST_REQUIRED_FOR_LIVE_PREVIEW: 'Host is required for live preview. Please provide a valid host parameter in the live_preview configuration.',
},

// Retry Policy Messages
RETRY: {
TIMEOUT_EXCEEDED: (timeout: number) =>
`Request timeout of ${timeout}ms exceeded. Please try again or increase the timeout value in your configuration.`,
},

// Error Codes
ERROR_CODES: {
NETWORK_ERROR: 'NETWORK_ERROR',
UNKNOWN_ERROR: 'UNKNOWN_ERROR',
TIMEOUT: 408,
},
} as const;

3 changes: 2 additions & 1 deletion src/lib/request.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AxiosInstance } from './types';
import { serialize } from './param-serializer';
import { APIError } from './api-error';
import { ERROR_MESSAGES } from './error-messages';

/**
* Handles array parameters properly with & separators
Expand Down Expand Up @@ -63,7 +64,7 @@ export async function getData(instance: AxiosInstance, url: string, data?: any)
// adds protocol so host is replaced and not appended
if (livePreviewParams.live_preview && livePreviewParams.live_preview !== 'init') {
if (!livePreviewParams.host) {
throw new Error('Host is required for live preview');
throw new Error(ERROR_MESSAGES.REQUEST.HOST_REQUIRED_FOR_LIVE_PREVIEW);
}
url = (livePreviewParams.host.startsWith('https://') ? '' : 'https://') + livePreviewParams.host + url;
}
Expand Down
5 changes: 3 additions & 2 deletions src/lib/retryPolicy/delivery-sdk-handlers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable @typescript-eslint/no-throw-literal */
import axios, { InternalAxiosRequestConfig, AxiosResponse, AxiosInstance } from 'axios';
import { ERROR_MESSAGES } from '../error-messages';

declare module 'axios' {
// eslint-disable-next-line @typescript-eslint/naming-convention
Expand Down Expand Up @@ -35,8 +36,8 @@ export const retryResponseErrorHandler = (error: any, config: any, axiosInstance
if (!response) {
if (error.code === 'ECONNABORTED') {
const customError = {
error_message: `Timeout of ${config.timeout}ms exceeded`,
error_code: 408,
error_message: ERROR_MESSAGES.RETRY.TIMEOUT_EXCEEDED(config.timeout),
error_code: ERROR_MESSAGES.ERROR_CODES.TIMEOUT,
errors: null,
};
throw customError; // Throw customError object
Expand Down
4 changes: 2 additions & 2 deletions test/api-error.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ describe('APIError', () => {
const error = APIError.fromAxiosError(axiosError);

expect(error).toBeInstanceOf(APIError);
expect(error.error_message).toBe('Unknown error occurred');
expect(error.error_message).toBe('An unknown error occurred. Please try again or contact support if the issue persists.');
expect(error.error_code).toBe('UNKNOWN_ERROR');
expect(error.status).toBe(0);
});
Expand Down Expand Up @@ -169,7 +169,7 @@ describe('APIError', () => {
const error = APIError.fromResponseData(responseData, 500);

expect(error).toBeInstanceOf(APIError);
expect(error.error_message).toBe('Request failed');
expect(error.error_message).toBe('Request failed. Please review your request and try again.');
expect(error.error_code).toBe(500);
expect(error.status).toBe(500);
});
Expand Down
4 changes: 2 additions & 2 deletions test/contentstack-core.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe('contentstackCore', () => {
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
httpClient({}).defaults.logHandler('error', error);

expect(consoleErrorSpy).toHaveBeenCalledWith('[error] Error - Something went wrong');
expect(consoleErrorSpy).toHaveBeenCalledWith('Error: Error - Something went wrong. Review the error details and try again.');

consoleErrorSpy.mockRestore();
});
Expand All @@ -36,7 +36,7 @@ describe('contentstackCore', () => {

httpClient({}).defaults.logHandler('info', 'Some message');

expect(consoleLogSpy).toHaveBeenCalledWith('[info] Some message');
expect(consoleLogSpy).toHaveBeenCalledWith('info: Some message. Review the details and try again.');

consoleLogSpy.mockRestore();
});
Expand Down
2 changes: 1 addition & 1 deletion test/retryPolicy/delivery-sdk-handlers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ describe('retryResponseErrorHandler', () => {
expect(err).toEqual(
expect.objectContaining({
error_code: 408,
error_message: `Timeout of ${config.timeout}ms exceeded`,
error_message: `Request timeout of ${config.timeout}ms exceeded. Please try again or increase the timeout value in your configuration.`,
errors: null,
})
);
Expand Down
Loading