From e0756282b6a3611e63271a2162c91fb9099d633a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=20Jurmanovi=C4=87?= Date: Fri, 28 May 2021 19:08:11 +0200 Subject: [PATCH] create http client and base service --- src/common/index.ts | 0 src/components/index.ts | 0 src/configs/development/app-settings.json | 5 + src/core/index.ts | 0 src/core/services/base-service/BaseService.ts | 30 +++++ src/core/services/http-service/HttpClient.ts | 117 ++++++++++++++++++ src/core/services/index.ts | 2 + src/pages/index.ts | 0 tsconfig.json | 22 ++++ webpack.config.js | 11 +- 10 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 src/common/index.ts create mode 100644 src/components/index.ts create mode 100644 src/configs/development/app-settings.json create mode 100644 src/core/index.ts create mode 100644 src/core/services/base-service/BaseService.ts create mode 100644 src/core/services/http-service/HttpClient.ts create mode 100644 src/core/services/index.ts create mode 100644 src/pages/index.ts diff --git a/src/common/index.ts b/src/common/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/components/index.ts b/src/components/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/configs/development/app-settings.json b/src/configs/development/app-settings.json new file mode 100644 index 0000000..917f16f --- /dev/null +++ b/src/configs/development/app-settings.json @@ -0,0 +1,5 @@ +{ + "apiUrl": "localhost:4000", + "apiVersion": "v1", + "ssl": false +} \ No newline at end of file diff --git a/src/core/index.ts b/src/core/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/core/services/base-service/BaseService.ts b/src/core/services/base-service/BaseService.ts new file mode 100644 index 0000000..94d779b --- /dev/null +++ b/src/core/services/base-service/BaseService.ts @@ -0,0 +1,30 @@ +import { HttpClient } from "core/services"; + +class BaseService { + private httpClient: HttpClient; + constructor(private endpoint: string) { + this.httpClient = new HttpClient(); + } + + getAll = (headers: HeadersInit) => { + return this.httpClient.get(this.endpoint, null, headers); + }; + + get = (params: Object, headers: HeadersInit) => { + return this.httpClient.get(this.endpoint, params, headers); + }; + + put = (data: Object, headers: HeadersInit) => { + return this.httpClient.put(this.endpoint, data, headers); + }; + + post = (data: Object, headers: HeadersInit) => { + return this.httpClient.post(this.endpoint, data, headers); + }; + + delete = (data: Object, headers: HeadersInit) => { + return this.httpClient.delete(this.endpoint, data, headers); + }; +} + +export default BaseService; diff --git a/src/core/services/http-service/HttpClient.ts b/src/core/services/http-service/HttpClient.ts new file mode 100644 index 0000000..9d155d0 --- /dev/null +++ b/src/core/services/http-service/HttpClient.ts @@ -0,0 +1,117 @@ +import settings from "configs/development/app-settings.json"; + +class HttpClient { + private url: string; + constructor() { + this.url = `${settings.ssl ? "https" : "http"}://${settings.apiUrl}/${ + settings.apiVersion + }`; + } + + post(url: string, data: Object, headersParam: HeadersInit): Promise { + let headers: Headers = new Headers(headersParam); + let body: BodyType = null; + if (data instanceof FormData) { + body = data; + } else { + body = JSON.stringify(data); + headers.append("Content-Type", "application/json"); + } + let options: OptionsType = { + method: "POST", + headers: headers, + body: body, + }; + const req: Request = new Request(resolveUrl(this.url, url), options); + + return createRequest(req); + } + + put(url: string, data: Object, headersParam: HeadersInit): Promise { + let headers: Headers = new Headers(headersParam); + headers.append("Content-Type", "application/json"); + let options: OptionsType = { + method: "PUT", + headers: headers, + body: JSON.stringify(data), + }; + const req: Request = new Request(resolveUrl(this.url, url), options); + + return createRequest(req); + } + + delete(url: string, data: Object, headersParam: HeadersInit): Promise { + let headers: Headers = new Headers(headersParam); + headers.append("Content-Type", "application/json"); + let options: OptionsType = { + method: "DELETE", + headers: headers, + body: JSON.stringify(data), + }; + const req: Request = new Request(resolveUrl(this.url, url), options); + + return createRequest(req); + } + + get(url: string, params: Object, headersParam: HeadersInit): Promise { + let headers: Headers = new Headers(headersParam); + let options: OptionsType = { + method: "GET", + headers: headers, + }; + let paramsPath: string = ""; + if (params) { + let urlParams = new URLSearchParams(Object.entries(params)); + paramsPath = "?" + urlParams; + } + const req: Request = new Request( + resolveUrl(this.url, url + paramsPath), + options + ); + + return createRequest(req); + } +} + +export default HttpClient; + +async function createRequest(request: Request): Promise { + let response: Response = await fetch(request); + if (!response.ok && response.status !== 403 && response.status !== 400) { + throw new Error(`HTTP error! status: ${response.status}`); + } else { + if (response.headers.get("Content-Type") !== null) { + let newResponse: Response = await createResponse(response); + return newResponse; + } + return response; + } +} + +async function createResponse(response: Response): Promise { + const type: string = response.headers.get("Content-Type"); + const body = (): Promise => { + if (type.indexOf("application/json") !== -1) { + return response.json(); + } + return response.text(); + }; + + return body(); +} + +function resolveUrl(url: string, path: string): string { + if (path.includes("http") || path.includes("://")) { + return path; + } + const fixedPath = path.split("/").join("/"); + const urlWithPath = `${url.endsWith("/") ? url : `${url}/`}${path}`; + return urlWithPath; +} + +type BodyType = string | FormData; +type OptionsType = { + method: string; + headers?: Headers; + body?: BodyType; +}; diff --git a/src/core/services/index.ts b/src/core/services/index.ts new file mode 100644 index 0000000..85a8eef --- /dev/null +++ b/src/core/services/index.ts @@ -0,0 +1,2 @@ +export { default as HttpClient } from "./http-service/HttpClient"; +export { default as BaseService } from "./base-service/BaseService"; diff --git a/src/pages/index.ts b/src/pages/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/tsconfig.json b/tsconfig.json index b48fbea..85f7bd4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,8 +8,30 @@ "es2016" ], "moduleResolution": "node", + "resolveJsonModule": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "experimentalDecorators": true, + "baseUrl": ".", + "paths": { + "common*": [ + "src/common*" + ], + "core*": [ + "src/core*" + ], + "components*": [ + "src/components*" + ], + "configs*": [ + "src/configs*" + ], + "pages*": [ + "src/pages*" + ], + "@src*": [ + "src*" + ], + } } } \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index d876faf..49b3626 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,6 +1,14 @@ const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); +const alias = { + common: path.resolve(__dirname, '/common'), + core: path.resolve(__dirname, '/core'), + configs: path.resolve(__dirname, '/configs'), + components: path.resolve(__dirname, '/components'), + pages: path.resolve(__dirname, '/pages') +}; + module.exports = { entry: { app: ['babel-polyfill', './src/index'] @@ -47,7 +55,8 @@ module.exports = { }), ], resolve: { - extensions: ['.js', '.ts'] + extensions: ['.js', '.ts'], + alias: alias }, devServer: { historyApiFallback: true,