diff --git a/package.json b/package.json index e3558d4..8733e2c 100644 --- a/package.json +++ b/package.json @@ -4,11 +4,9 @@ "private": true, "dependencies": { "@craco/craco": "^7.1.0", - "@reduxjs/toolkit": "^1.9.7", - "react-redux": "^8.1.3", - "redux-saga": "^1.2.3", "@fortawesome/react-fontawesome": "^0.2.0", "@icon-park/react": "^1.4.2", + "@reduxjs/toolkit": "^1.9.7", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", @@ -16,6 +14,8 @@ "@types/node": "^16.18.68", "@types/react": "^18.2.45", "@types/react-dom": "^18.2.18", + "axios": "^1.7.2", + "axios-retry": "^4.4.2", "i18next": "^23.7.11", "i18next-http-backend": "^2.4.2", "react": "^18.2.0", @@ -23,10 +23,13 @@ "react-dom": "^18.2.0", "react-i18next": "^13.5.0", "react-photo-album": "^2.3.0", + "react-redux": "^8.1.3", "react-router-dom": "^6.21.0", "react-scripts": "5.0.1", "react-tooltip": "^5.25.0", "redux": "^5.0.1", + "redux-saga": "^1.2.3", + "rss-parser": "^3.13.0", "typescript": "^4.9.5", "web-vitals": "^2.1.4" }, @@ -55,6 +58,7 @@ }, "devDependencies": { "@craco/types": "^7.1.0", + "@types/axios": "^0.14.0", "@types/node-sass": "^4.11.7", "@types/react-redux": "^7.1.33", "sass": "^1.69.5" diff --git a/src/modules/api.ts b/src/modules/api.ts new file mode 100644 index 0000000..0ee8641 --- /dev/null +++ b/src/modules/api.ts @@ -0,0 +1,17 @@ +import HttpClient from './http' + +const api = new HttpClient('') + +const getLatestMediums = async () => { + try { + const { data } = await api.get('https://medium.com/feed/@amirzenoozi') + return data + } catch (err: any) { + console.log('Error', err) + throw err + } +} + +export { + getLatestMediums, +} diff --git a/src/modules/http.ts b/src/modules/http.ts new file mode 100644 index 0000000..b648017 --- /dev/null +++ b/src/modules/http.ts @@ -0,0 +1,67 @@ +/* eslint-disable no-use-before-define */ +import axios, { type AxiosInstance, type AxiosRequestConfig, type AxiosResponse } from 'axios' +import axiosRetry from 'axios-retry' + +const RETRY_COUNT: number = 3 +const DEFAULT_DELAY: number = 1000 + +class HttpClient { + private readonly axiosInstance: AxiosInstance + + constructor (baseURL: string) { + this.axiosInstance = axios.create({ + baseURL, + headers: { + 'Content-Type': 'application/json' + } + }) + + // Adding Retry options to the queries + axiosRetry(this.axiosInstance, { + retries: RETRY_COUNT, + retryDelay: (...arg) => axiosRetry.exponentialDelay(...arg, 1000) + }) + + // Interceptors can be added for global request/response handling + this.axiosInstance.interceptors.response.use( + this.handleSuccessResponse, + this.handleErrorResponse + ) + } + + private readonly handleSuccessResponse = async (response: AxiosResponse): Promise => { + await new Promise(resolve => setTimeout(resolve, DEFAULT_DELAY)) + return response + } + + private readonly handleErrorResponse = (error: any): any => { + if (error.response) { + // The request was made and the server responded with a status code + const status = error.response.status + + if (status >= 500 && status < 600) { + return Promise.reject(error) + } else { + return Promise.reject(error) + } + } + } + + public async get(url: string, config?: AxiosRequestConfig) { + return await this.axiosInstance.get(url, config) + } + + public async post(url: string, data?: any, config?: AxiosRequestConfig) { + return await this.axiosInstance.post(url, data, config) + } + + public async put(url: string, data?: any, config?: AxiosRequestConfig) { + return await this.axiosInstance.put(url, data, config) + } + + public async delete(url: string, config?: AxiosRequestConfig) { + return await this.axiosInstance.delete(url, config) + } +} + +export default HttpClient diff --git a/yarn.lock b/yarn.lock index 5ca9bc3..be80681 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2055,6 +2055,13 @@ resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" integrity sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw== +"@types/axios@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@types/axios/-/axios-0.14.0.tgz#ec2300fbe7d7dddd7eb9d3abf87999964cafce46" + integrity sha512-KqQnQbdYE54D7oa/UmYVMZKq7CO4l8DEENzOKc4aBRwxCXSlJXGz83flFx5L7AWrOQnmuN3kVsRdt+GZPPjiVQ== + dependencies: + axios "*" + "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" @@ -3031,6 +3038,22 @@ axe-core@^4.9.1: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.9.1.tgz#fcd0f4496dad09e0c899b44f6c4bb7848da912ae" integrity sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw== +axios-retry@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/axios-retry/-/axios-retry-4.4.2.tgz#cef7c3eb1aa004f6a7e7b1a0918907b10a1986be" + integrity sha512-2fjo9uDNBQjX8+GMEGOFG5TrLMZ3QijjeRYcgBI2MhrsabnvcIAfLxxIhG7+CCD68vPEQY3IM2llV70ZsrqPvA== + dependencies: + is-retry-allowed "^2.2.0" + +axios@*, axios@^1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621" + integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + axobject-query@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.1.1.tgz#3b6e5c6d4e43ca7ba51c5babf99d22a9c68485e1" @@ -4279,7 +4302,7 @@ enhanced-resolve@^5.17.0: graceful-fs "^4.2.4" tapable "^2.2.0" -entities@^2.0.0: +entities@^2.0.0, entities@^2.0.3: version "2.2.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== @@ -4996,7 +5019,7 @@ flatted@^3.2.9: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== -follow-redirects@^1.0.0: +follow-redirects@^1.0.0, follow-redirects@^1.15.6: version "1.15.6" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== @@ -5044,6 +5067,15 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -5799,6 +5831,11 @@ is-regexp@^1.0.0: resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" integrity sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA== +is-retry-allowed@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz#88f34cbd236e043e71b6932d09b0c65fb7b4d71d" + integrity sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg== + is-root@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" @@ -8097,6 +8134,11 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + psl@^1.1.33: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" @@ -8620,6 +8662,14 @@ rollup@^2.43.1: optionalDependencies: fsevents "~2.3.2" +rss-parser@^3.13.0: + version "3.13.0" + resolved "https://registry.yarnpkg.com/rss-parser/-/rss-parser-3.13.0.tgz#f1f83b0a85166b8310ec531da6fbaa53ff0f50f0" + integrity sha512-7jWUBV5yGN3rqMMj7CZufl/291QAhvrrGpDNE4k/02ZchL0npisiYYqULF71jCEKoIiHvK/Q2e6IkDwPziT7+w== + dependencies: + entities "^2.0.3" + xml2js "^0.5.0" + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -8683,6 +8733,11 @@ sass@^1.69.5: immutable "^4.0.0" source-map-js ">=0.6.2 <2.0.0" +sax@>=0.6.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" + integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== + sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -10358,6 +10413,19 @@ xml-name-validator@^3.0.0: resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== +xml2js@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" + integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + +xmlbuilder@~11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" + integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + xmlchars@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"