diff --git a/src/pages/api/find.ts b/src/pages/api/find.ts index 8190387..b290bda 100644 --- a/src/pages/api/find.ts +++ b/src/pages/api/find.ts @@ -3,7 +3,7 @@ import Find, { type FindQueryParams } from 'src/interfaces/shared/search'; import basicSearch from 'src/utils/fetchers/basicSearch'; import getOrSetApiCache from 'src/utils/getOrSetApiCache'; import { findKey } from 'src/utils/constants/keys'; -import { AppError, cleanQueryStr } from 'src/utils/helpers'; +import { AppError, cleanQueryStr, getErrorProperties } from 'src/utils/helpers'; import { findFilterable } from 'src/utils/constants/find'; type ResponseData = @@ -25,8 +25,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< const results = await getOrSetApiCache(findKey(queryStr), basicSearch, queryStr); res.status(200).json({ status: true, data: { title: query, results } }); - } catch (error: any) { - const { message = 'Not found', statusCode = 404 } = error; + } catch (error) { + const { message, statusCode } = getErrorProperties(error); res.status(statusCode).json({ status: false, message }); } } diff --git a/src/pages/api/name/[nameId].ts b/src/pages/api/name/[nameId].ts index 3351a8e..399706a 100644 --- a/src/pages/api/name/[nameId].ts +++ b/src/pages/api/name/[nameId].ts @@ -3,7 +3,7 @@ import type Name from 'src/interfaces/shared/name'; import name from 'src/utils/fetchers/name'; import getOrSetApiCache from 'src/utils/getOrSetApiCache'; import { nameKey } from 'src/utils/constants/keys'; -import { AppError } from 'src/utils/helpers'; +import { AppError, getErrorProperties } from 'src/utils/helpers'; type ResponseData = { status: true; data: Name } | { status: false; message: string }; @@ -15,8 +15,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< const data = await getOrSetApiCache(nameKey(nameId), name, nameId); res.status(200).json({ status: true, data }); - } catch (error: any) { - const { message = 'Not found', statusCode = 404 } = error; + } catch (error) { + const { message, statusCode } = getErrorProperties(error); + res.status(statusCode).json({ status: false, message }); } } diff --git a/src/pages/api/title/[titleId]/index.ts b/src/pages/api/title/[titleId]/index.ts index 9965a27..0b5b0ff 100644 --- a/src/pages/api/title/[titleId]/index.ts +++ b/src/pages/api/title/[titleId]/index.ts @@ -3,7 +3,7 @@ import type Title from 'src/interfaces/shared/title'; import title from 'src/utils/fetchers/title'; import getOrSetApiCache from 'src/utils/getOrSetApiCache'; import { titleKey } from 'src/utils/constants/keys'; -import { AppError } from 'src/utils/helpers'; +import { AppError, getErrorProperties } from 'src/utils/helpers'; type ResponseData = { status: true; data: Title } | { status: false; message: string }; @@ -14,8 +14,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< const titleId = req.query.titleId as string; const data = await getOrSetApiCache(titleKey(titleId), title, titleId); res.status(200).json({ status: true, data }); - } catch (error: any) { - const { message = 'Not found', statusCode = 404 } = error; + } catch (error) { + const { message, statusCode } = getErrorProperties(error); res.status(statusCode).json({ status: false, message }); } } diff --git a/src/pages/api/title/[titleId]/reviews/[paginationKey].ts b/src/pages/api/title/[titleId]/reviews/[paginationKey].ts index 23035a7..4e7eb27 100644 --- a/src/pages/api/title/[titleId]/reviews/[paginationKey].ts +++ b/src/pages/api/title/[titleId]/reviews/[paginationKey].ts @@ -3,7 +3,7 @@ import type { TitleReviewsCursored } from 'src/interfaces/shared/titleReviews'; import { cursoredReviews } from 'src/utils/fetchers/titleReviews'; import getOrSetApiCache from 'src/utils/getOrSetApiCache'; import { titleReviewsKey } from 'src/utils/constants/keys'; -import { AppError, cleanQueryStr } from 'src/utils/helpers'; +import { AppError, cleanQueryStr, getErrorProperties } from 'src/utils/helpers'; import { keys as titleReviewsQueryKeys } from 'src/utils/constants/titleReviewsFilters'; type ResponseData = @@ -26,8 +26,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< queryStr ); res.status(200).json({ status: true, data }); - } catch (error: any) { - const { message = 'Not found', statusCode = 404 } = error; + } catch (error) { + const { message, statusCode } = getErrorProperties(error); res.status(statusCode).json({ status: false, message }); } } diff --git a/src/pages/api/title/[titleId]/reviews/index.ts b/src/pages/api/title/[titleId]/reviews/index.ts index 23a5259..f992bd9 100644 --- a/src/pages/api/title/[titleId]/reviews/index.ts +++ b/src/pages/api/title/[titleId]/reviews/index.ts @@ -4,7 +4,7 @@ import reviews from 'src/utils/fetchers/titleReviews'; import getOrSetApiCache from 'src/utils/getOrSetApiCache'; import { titleReviewsKey } from 'src/utils/constants/keys'; import { keys } from 'src/utils/constants/titleReviewsFilters'; -import { AppError, cleanQueryStr } from 'src/utils/helpers'; +import { AppError, cleanQueryStr, getErrorProperties } from 'src/utils/helpers'; type ResponseData = { status: true; data: TitleReviews } | { status: false; message: string }; @@ -22,8 +22,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< queryStr ); res.status(200).json({ status: true, data }); - } catch (error: any) { - const { message = 'Not found', statusCode = 404 } = error; + } catch (error) { + const { message, statusCode } = getErrorProperties(error); res.status(statusCode).json({ status: false, message }); } } diff --git a/src/pages/find/index.tsx b/src/pages/find/index.tsx index 0a7e203..7d8dd0a 100644 --- a/src/pages/find/index.tsx +++ b/src/pages/find/index.tsx @@ -8,7 +8,7 @@ import Find, { FindQueryParams } from 'src/interfaces/shared/search'; import { AppError } from 'src/interfaces/shared/error'; import basicSearch from 'src/utils/fetchers/basicSearch'; import getOrSetApiCache from 'src/utils/getOrSetApiCache'; -import { cleanQueryStr } from 'src/utils/helpers'; +import { cleanQueryStr, getErrorProperties } from 'src/utils/helpers'; import { findKey } from 'src/utils/constants/keys'; import styles from 'src/styles/modules/pages/find/find.module.scss'; import { findFilterable } from 'src/utils/constants/find'; @@ -66,8 +66,8 @@ export const getServerSideProps: GetServerSideProps = asy return { props: { data: { title: query, results: res }, error: null, originalPath }, }; - } catch (error: any) { - const { message, statusCode } = error; + } catch (error) { + const { message, statusCode } = getErrorProperties(error); ctx.res.statusCode = statusCode; ctx.res.statusMessage = message; diff --git a/src/pages/name/[nameId]/index.tsx b/src/pages/name/[nameId]/index.tsx index fc7695d..b3967d9 100644 --- a/src/pages/name/[nameId]/index.tsx +++ b/src/pages/name/[nameId]/index.tsx @@ -8,7 +8,7 @@ import Name from 'src/interfaces/shared/name'; import { AppError } from 'src/interfaces/shared/error'; import name from 'src/utils/fetchers/name'; import getOrSetApiCache from 'src/utils/getOrSetApiCache'; -import { getProxiedIMDbImgUrl } from 'src/utils/helpers'; +import { getErrorProperties, getProxiedIMDbImgUrl } from 'src/utils/helpers'; import { nameKey } from 'src/utils/constants/keys'; import styles from 'src/styles/modules/pages/name/name.module.scss'; @@ -54,9 +54,8 @@ export const getServerSideProps: GetServerSideProps = async ctx => const data = await getOrSetApiCache(nameKey(nameId), name, nameId); return { props: { data, error: null, originalPath } }; - } catch (error: any) { - const { message, statusCode } = error; - + } catch (error) { + const { message, statusCode } = getErrorProperties(error); ctx.res.statusCode = statusCode; ctx.res.statusMessage = message; diff --git a/src/pages/title/[titleId]/index.tsx b/src/pages/title/[titleId]/index.tsx index 67ee92e..51ea836 100644 --- a/src/pages/title/[titleId]/index.tsx +++ b/src/pages/title/[titleId]/index.tsx @@ -8,7 +8,7 @@ import Title from 'src/interfaces/shared/title'; import { AppError } from 'src/interfaces/shared/error'; import getOrSetApiCache from 'src/utils/getOrSetApiCache'; import title from 'src/utils/fetchers/title'; -import { getProxiedIMDbImgUrl } from 'src/utils/helpers'; +import { getErrorProperties, getProxiedIMDbImgUrl } from 'src/utils/helpers'; import { titleKey } from 'src/utils/constants/keys'; import styles from 'src/styles/modules/pages/title/title.module.scss'; @@ -63,8 +63,8 @@ export const getServerSideProps: GetServerSideProps = async ctx => const data = await getOrSetApiCache(titleKey(titleId), title, titleId); return { props: { data, error: null, originalPath } }; - } catch (error: any) { - const { message, statusCode } = error; + } catch (error) { + const { message, statusCode } = getErrorProperties(error); ctx.res.statusCode = statusCode; ctx.res.statusMessage = message; diff --git a/src/pages/title/[titleId]/reviews/[paginationKey]/index.tsx b/src/pages/title/[titleId]/reviews/[paginationKey]/index.tsx index 32bb094..9b82288 100644 --- a/src/pages/title/[titleId]/reviews/[paginationKey]/index.tsx +++ b/src/pages/title/[titleId]/reviews/[paginationKey]/index.tsx @@ -6,7 +6,7 @@ import { BasicCard, Filters, Pagination, Reviews } from 'src/components/titleRev import { AppError } from 'src/interfaces/shared/error'; import getOrSetApiCache from 'src/utils/getOrSetApiCache'; import { cursoredReviews } from 'src/utils/fetchers/titleReviews'; -import { cleanQueryStr } from 'src/utils/helpers'; +import { cleanQueryStr, getErrorProperties } from 'src/utils/helpers'; import { titleReviewsKey } from 'src/utils/constants/keys'; import styles from 'src/styles/modules/pages/titleReviews/titleReviews.module.scss'; import { TitleReviewsCursored } from 'src/interfaces/shared/titleReviews'; @@ -60,8 +60,8 @@ export const getServerSideProps: GetServerSideProps = async ctx => ); return { props: { data, error: null, originalPath } }; - } catch (error: any) { - const { message, statusCode } = error; + } catch (error) { + const { message, statusCode } = getErrorProperties(error); ctx.res.statusCode = statusCode; ctx.res.statusMessage = message; diff --git a/src/pages/title/[titleId]/reviews/index.tsx b/src/pages/title/[titleId]/reviews/index.tsx index eb08fbf..d4b37c7 100644 --- a/src/pages/title/[titleId]/reviews/index.tsx +++ b/src/pages/title/[titleId]/reviews/index.tsx @@ -6,7 +6,7 @@ import { Filters, Pagination, Reviews, TitleCard } from 'src/components/titleRev import { AppError } from 'src/interfaces/shared/error'; import getOrSetApiCache from 'src/utils/getOrSetApiCache'; import titleReviews from 'src/utils/fetchers/titleReviews'; -import { cleanQueryStr, getProxiedIMDbImgUrl } from 'src/utils/helpers'; +import { cleanQueryStr, getErrorProperties, getProxiedIMDbImgUrl } from 'src/utils/helpers'; import { titleReviewsKey } from 'src/utils/constants/keys'; import styles from 'src/styles/modules/pages/titleReviews/titleReviews.module.scss'; import TitleReviews from 'src/interfaces/shared/titleReviews'; @@ -80,8 +80,8 @@ export const getServerSideProps: GetServerSideProps = async ctx => ); return { props: { data, error: null, originalPath } }; - } catch (error: any) { - const { message, statusCode } = error; + } catch (error) { + const { message, statusCode } = getErrorProperties(error); ctx.res.statusCode = statusCode; ctx.res.statusMessage = message; diff --git a/src/utils/axiosInstance.ts b/src/utils/axiosInstance.ts index 4ce7bfd..463a572 100644 --- a/src/utils/axiosInstance.ts +++ b/src/utils/axiosInstance.ts @@ -14,4 +14,7 @@ const axiosInstance = axios.create({ }, }); + +export const isSaneError = axios.isAxiosError; + export default axiosInstance; diff --git a/src/utils/fetchers/basicSearch.ts b/src/utils/fetchers/basicSearch.ts index e0e98e9..591883b 100644 --- a/src/utils/fetchers/basicSearch.ts +++ b/src/utils/fetchers/basicSearch.ts @@ -1,6 +1,6 @@ import * as cheerio from 'cheerio'; import RawFind from 'src/interfaces/misc/rawFind'; -import axiosInstance from 'src/utils/axiosInstance'; +import axiosInstance, { isSaneError } from 'src/utils/axiosInstance'; import { AppError } from 'src/utils/helpers'; import cleanFind from 'src/utils/cleaners/find'; @@ -14,11 +14,10 @@ const basicSearch = async (queryStr: string) => { const cleanData = cleanFind(parsedRawData); return cleanData; - } catch (err: any) { - if (err.response?.status === 404) - throw new AppError('not found', 404, err.cause); + } catch (err) { + if (isSaneError(err) && err.response?.status === 404) throw new AppError('not found', 404, err); - throw new AppError('something went wrong', 500, err.cause); + throw new AppError('something went wrong', 500, err); } }; diff --git a/src/utils/fetchers/name.ts b/src/utils/fetchers/name.ts index 8982bd1..e0a312b 100644 --- a/src/utils/fetchers/name.ts +++ b/src/utils/fetchers/name.ts @@ -1,6 +1,6 @@ import * as cheerio from 'cheerio'; import RawName from 'src/interfaces/misc/rawName'; -import axiosInstance from 'src/utils/axiosInstance'; +import axiosInstance, { isSaneError } from 'src/utils/axiosInstance'; import cleanName from 'src/utils/cleaners/name'; import { AppError } from 'src/utils/helpers'; @@ -15,10 +15,10 @@ const name = async (nameId: string) => { const cleanData = cleanName(parsedRawData); // returning return cleanData; - } catch (err: any) { - if (err.response?.status === 404) throw new AppError('not found', 404, err.cause); + } catch (err) { + if (isSaneError(err) && err.response?.status === 404) throw new AppError('not found', 404, err); - throw new AppError('something went wrong', 500, err.cause); + throw new AppError('something went wrong', 500, err); } }; diff --git a/src/utils/fetchers/title.ts b/src/utils/fetchers/title.ts index e42510e..ee37385 100644 --- a/src/utils/fetchers/title.ts +++ b/src/utils/fetchers/title.ts @@ -1,6 +1,6 @@ import * as cheerio from 'cheerio'; import RawTitle from 'src/interfaces/misc/rawTitle'; -import axiosInstance from 'src/utils/axiosInstance'; +import axiosInstance, { isSaneError } from 'src/utils/axiosInstance'; import cleanTitle from 'src/utils/cleaners/title'; import { AppError } from 'src/utils/helpers'; @@ -15,11 +15,10 @@ const title = async (titleId: string) => { const cleanData = cleanTitle(parsedRawData); // returning return cleanData; - } catch (err: any) { - if (err.response?.status === 404) - throw new AppError('not found', 404, err.cause); + } catch (err) { + if (isSaneError(err) && err.response?.status === 404) throw new AppError('not found', 404, err); - throw new AppError('something went wrong', 500, err.cause); + throw new AppError('something went wrong', 500, err); } }; diff --git a/src/utils/fetchers/titleReviews.ts b/src/utils/fetchers/titleReviews.ts index e28c4c3..3fac6f3 100644 --- a/src/utils/fetchers/titleReviews.ts +++ b/src/utils/fetchers/titleReviews.ts @@ -1,6 +1,6 @@ import { AxiosError } from 'axios'; import * as cheerio from 'cheerio'; -import axiosInstance from 'src/utils/axiosInstance'; +import axiosInstance, { isSaneError } from 'src/utils/axiosInstance'; import { AppError } from 'src/utils/helpers'; const reviews = async (titleId: string, queryStr = '') => { @@ -27,12 +27,12 @@ const reviews = async (titleId: string, queryStr = '') => { return { meta, list, cursor }; } catch (err) { - if (err instanceof AxiosError && err.response?.status === 404) - throw new AppError('not found', 404, err.cause); + if (isSaneError(err) && err.response?.status === 404) + throw new AppError('not found', 404, err); if (err instanceof AppError) throw err; - throw new AppError('something went wrong', 500, err instanceof Error ? err.cause : undefined); + throw new AppError('something went wrong', 500, err); } }; @@ -62,12 +62,12 @@ export const cursoredReviews = async ( return { meta: { title, titleId }, list, cursor }; } catch (err) { - if (err instanceof AxiosError && err.response?.status === 404) + if (isSaneError(err) && err.response?.status === 404) throw new AppError('not found', 404, err.cause); if (err instanceof AppError) throw err; - throw new AppError('something went wrong', 500, err instanceof Error ? err.cause : undefined); + throw new AppError('something went wrong', 500, err); } }; diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index c74bd8f..2a483ed 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -74,10 +74,12 @@ export const getProxiedIMDbImgUrl = (url: string) => { }; export const AppError = class extends Error { - constructor(message: string, public statusCode: number, cause?: any) { - super(message, cause); + constructor(message: string, public statusCode: number, errorOptions?: unknown) { + const saneErrorOptions = getErrorOptions(errorOptions); + super(message, saneErrorOptions); Error.captureStackTrace(this, AppError); + if (process.env.NODE_ENV === 'development') console.error(this); } }; @@ -90,10 +92,7 @@ export const cleanQueryStr = (record: Record, filterable: string return urlSearchParams.toString(); }; -export const getResTitleTypeHeading = ( - type: ResultMetaTypes, - titleType: ResultMetaTitleTypes -) => { +export const getResTitleTypeHeading = (type: ResultMetaTypes, titleType: ResultMetaTitleTypes) => { if (type !== 'TITLE') return 'Titles'; for (let i = 0; i < resultTitleTypes.types.length; i++) { @@ -102,7 +101,6 @@ export const getResTitleTypeHeading = ( } }; - export const isLocalStorageAvailable = () => { try { localStorage.getItem('test'); @@ -110,4 +108,26 @@ export const isLocalStorageAvailable = () => { } catch (e) { return false; } +}; + +const getErrorOptions = (error: unknown): ErrorOptions | undefined => { + if (!error || typeof error !== 'object') return undefined; + + let cause: unknown; + // @ts-expect-error it's not an error! just that project's ts version is old, which can't be upgraded + if ('cause' in error) cause = error.cause; + // @ts-expect-error it's not an error! just that project's ts version is old, which can't be upgraded + else if ('stack' in error) cause = error.stack; + + // @ts-expect-error it's not an error! just that project's ts version is old, which can't be upgraded + return { cause }; +}; + +export const getErrorProperties = ( + error: unknown, + message = 'Something went very wrong', + statusCode = 500 +) => { + if (error instanceof AppError) return error; + return new AppError(message, statusCode, error); }; \ No newline at end of file