feat: convert abstractService to ts

This commit is contained in:
Dominik Pschenitschni 2022-02-13 21:40:39 +01:00
parent 4994db4f77
commit 6e255c865c
Signed by: dpschen
GPG Key ID: B257AC0149F43A77
1 changed files with 53 additions and 104 deletions

View File

@ -1,8 +1,17 @@
import axios from 'axios' import axios, {Method} from 'axios'
import {objectToSnakeCase} from '@/helpers/case' import {objectToSnakeCase} from '@/helpers/case'
import {getToken} from '@/helpers/auth' import {getToken} from '@/helpers/auth'
import AbstractModel from '@/models/abstractModel'
function convertObject(o) { interface Paths {
create : string
get : string
getAll : string
update : string
delete : string
}
function convertObject(o: Record<string, unknown>) {
if (o instanceof Date) { if (o instanceof Date) {
return o.toISOString() return o.toISOString()
} }
@ -10,7 +19,7 @@ function convertObject(o) {
return o return o
} }
function prepareParams(params) { function prepareParams(params: Record<string, unknown | any[]>) {
if (typeof params !== 'object') { if (typeof params !== 'object') {
return params return params
} }
@ -27,16 +36,16 @@ function prepareParams(params) {
return objectToSnakeCase(params) return objectToSnakeCase(params)
} }
export default class AbstractService { export default class AbstractService<Model extends AbstractModel> {
///////////////////////////// /////////////////////////////
// Initial variable definitions // Initial variable definitions
/////////////////////////// ///////////////////////////
http = null http
loading = false loading = false
uploadProgress = 0 uploadProgress = 0
paths = { paths: Paths = {
create: '', create: '',
get: '', get: '',
getAll: '', getAll: '',
@ -53,14 +62,12 @@ export default class AbstractService {
/** /**
* The abstract constructor. * The abstract constructor.
* @param [paths] An object with all paths. Default values are specified above. * @param [paths] An object with all paths.
*/ */
constructor(paths) { constructor(paths : Partial<Paths> = {}) {
this.http = axios.create({ this.http = axios.create({
baseURL: window.API_URL, baseURL: window.API_URL,
headers: { headers: { 'Content-Type': 'application/json' },
'Content-Type': 'application/json',
},
}) })
// Set the interceptors to process every request // Set the interceptors to process every request
@ -94,38 +101,28 @@ export default class AbstractService {
this.http.defaults.headers.common['Authorization'] = `Bearer ${token}` this.http.defaults.headers.common['Authorization'] = `Bearer ${token}`
} }
if (paths) {
this.paths = { Object.assign(this.paths, paths)
create: paths.create !== undefined ? paths.create : '',
get: paths.get !== undefined ? paths.get : '',
getAll: paths.getAll !== undefined ? paths.getAll : '',
update: paths.update !== undefined ? paths.update : '',
delete: paths.delete !== undefined ? paths.delete : '',
}
}
} }
/** /**
* Whether or not to use the create interceptor which processes a request payload into json * Whether or not to use the create interceptor which processes a request payload into json
* @returns {boolean}
*/ */
useCreateInterceptor() { useCreateInterceptor(): boolean {
return true return true
} }
/** /**
* Whether or not to use the update interceptor which processes a request payload into json * Whether or not to use the update interceptor which processes a request payload into json
* @returns {boolean}
*/ */
useUpdateInterceptor() { useUpdateInterceptor(): boolean {
return true return true
} }
/** /**
* Whether or not to use the delete interceptor which processes a request payload into json * Whether or not to use the delete interceptor which processes a request payload into json
* @returns {boolean}
*/ */
useDeleteInterceptor() { useDeleteInterceptor(): boolean {
return true return true
} }
@ -135,11 +132,9 @@ export default class AbstractService {
/** /**
* Returns an object with all route parameters and their values. * Returns an object with all route parameters and their values.
* @param route
* @returns object
*/ */
getRouteReplacements(route, parameters = {}) { getRouteReplacements(route : string, parameters = {}) {
const replace$$1 = {} const replace$$1: {} = {}
let pattern = this.getRouteParameterPattern() let pattern = this.getRouteParameterPattern()
pattern = new RegExp(pattern instanceof RegExp ? pattern.source : pattern, 'g') pattern = new RegExp(pattern instanceof RegExp ? pattern.source : pattern, 'g')
@ -152,22 +147,18 @@ export default class AbstractService {
/** /**
* Holds the replacement pattern for url paths, can be overwritten by implementations. * Holds the replacement pattern for url paths, can be overwritten by implementations.
* @return {RegExp}
*/ */
getRouteParameterPattern() { getRouteParameterPattern(): RegExp {
return /{([^}]+)}/ return /{([^}]+)}/
} }
/** /**
* Returns a fully-ready-ready-to-make-a-request-to route with replaced parameters. * Returns a fully-ready-ready-to-make-a-request-to route with replaced parameters.
* @param path
* @param pathparams
* @return string
*/ */
getReplacedRoute(path, pathparams) { getReplacedRoute(path : string, pathparams : {}) : string {
const replacements = this.getRouteReplacements(path, pathparams) const replacements = this.getRouteReplacements(path, pathparams)
return Object.entries(replacements).reduce( return Object.entries(replacements).reduce(
(result, [parameter, value]) => result.replace(parameter, value), (result, [parameter, value]) => result.replace(parameter, value as string),
path, path,
) )
} }
@ -178,9 +169,8 @@ export default class AbstractService {
* case the api returns a response in < 100ms. * case the api returns a response in < 100ms.
* But because the timeout is created using setTimeout, it will still trigger even if the request is * But because the timeout is created using setTimeout, it will still trigger even if the request is
* already finished, so we return a method to call in that case. * already finished, so we return a method to call in that case.
* @returns {Function}
*/ */
setLoading() { setLoading(): Function {
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
this.loading = true this.loading = true
}, 100) }, 100)
@ -200,46 +190,36 @@ export default class AbstractService {
/** /**
* The modelFactory returns an model from an object. * The modelFactory returns an model from an object.
* This one here is the default one, usually the service definitions for a model will override this. * This one here is the default one, usually the service definitions for a model will override this.
* @param data
* @returns {*}
*/ */
modelFactory(data) { modelFactory(data : Partial<Model>) {
return data return new AbstractModel(data)
} }
/** /**
* This is the model factory for get requests. * This is the model factory for get requests.
* @param data
* @return {*}
*/ */
modelGetFactory(data) { modelGetFactory(data : Partial<Model>) {
return this.modelFactory(data) return this.modelFactory(data)
} }
/** /**
* This is the model factory for get all requests. * This is the model factory for get all requests.
* @param data
* @return {*}
*/ */
modelGetAllFactory(data) { modelGetAllFactory(data : Partial<Model>) {
return this.modelFactory(data) return this.modelFactory(data)
} }
/** /**
* This is the model factory for create requests. * This is the model factory for create requests.
* @param data
* @return {*}
*/ */
modelCreateFactory(data) { modelCreateFactory(data : Partial<Model>) {
return this.modelFactory(data) return this.modelFactory(data)
} }
/** /**
* This is the model factory for update requests. * This is the model factory for update requests.
* @param data
* @return {*}
*/ */
modelUpdateFactory(data) { modelUpdateFactory(data : Partial<Model>) {
return this.modelFactory(data) return this.modelFactory(data)
} }
@ -249,37 +229,29 @@ export default class AbstractService {
/** /**
* Default preprocessor for get requests * Default preprocessor for get requests
* @param model
* @return {*}
*/ */
beforeGet(model) { beforeGet(model : Model) {
return model return model
} }
/** /**
* Default preprocessor for create requests * Default preprocessor for create requests
* @param model
* @return {*}
*/ */
beforeCreate(model) { beforeCreate(model : Model) {
return model return model
} }
/** /**
* Default preprocessor for update requests * Default preprocessor for update requests
* @param model
* @return {*}
*/ */
beforeUpdate(model) { beforeUpdate(model : Model) {
return model return model
} }
/** /**
* Default preprocessor for delete requests * Default preprocessor for delete requests
* @param model
* @return {*}
*/ */
beforeDelete(model) { beforeDelete(model : Model) {
return model return model
} }
@ -291,9 +263,8 @@ export default class AbstractService {
* Performs a get request to the url specified before. * Performs a get request to the url specified before.
* @param model The model to use. The request path is built using the values from the model. * @param model The model to use. The request path is built using the values from the model.
* @param params Optional query parameters * @param params Optional query parameters
* @returns {Q.Promise<any>}
*/ */
get(model, params = {}) { get(model : Model, params = {}) {
if (this.paths.get === '') { if (this.paths.get === '') {
throw new Error('This model is not able to get data.') throw new Error('This model is not able to get data.')
} }
@ -304,12 +275,8 @@ export default class AbstractService {
/** /**
* This is a more abstract implementation which only does a get request. * This is a more abstract implementation which only does a get request.
* Services which need more flexibility can use this. * Services which need more flexibility can use this.
* @param url
* @param model
* @param params
* @returns {Q.Promise<unknown>}
*/ */
async getM(url, model = {}, params = {}) { async getM(url : string, model = new AbstractModel({}), params = {}) {
const cancel = this.setLoading() const cancel = this.setLoading()
model = this.beforeGet(model) model = this.beforeGet(model)
@ -325,12 +292,12 @@ export default class AbstractService {
} }
} }
async getBlobUrl(url, method = 'GET', data = {}) { async getBlobUrl(url : string, method = 'GET' as Method, data = {}) {
const response = await this.http({ const response = await this.http({
url: url, url,
method: method, method,
responseType: 'blob', responseType: 'blob',
data: data, data,
}) })
return window.URL.createObjectURL(new Blob([response.data])) return window.URL.createObjectURL(new Blob([response.data]))
} }
@ -341,9 +308,8 @@ export default class AbstractService {
* @param model The model to use. The request path is built using the values from the model. * @param model The model to use. The request path is built using the values from the model.
* @param params Optional query parameters * @param params Optional query parameters
* @param page The page to get * @param page The page to get
* @returns {Q.Promise<any>}
*/ */
async getAll(model = {}, params = {}, page = 1) { async getAll(model : Model = new AbstractModel({}), params = {}, page = 1) {
if (this.paths.getAll === '') { if (this.paths.getAll === '') {
throw new Error('This model is not able to get data.') throw new Error('This model is not able to get data.')
} }
@ -374,10 +340,9 @@ export default class AbstractService {
/** /**
* Performs a put request to the url specified before * Performs a put request to the url specified before
* @param model
* @returns {Promise<any | never>} * @returns {Promise<any | never>}
*/ */
async create(model) { async create(model : Model) {
if (this.paths.create === '') { if (this.paths.create === '') {
throw new Error('This model is not able to create data.') throw new Error('This model is not able to create data.')
} }
@ -400,11 +365,8 @@ export default class AbstractService {
/** /**
* An abstract implementation to send post requests. * An abstract implementation to send post requests.
* Services can use this to implement functions to do post requests other than using the update method. * Services can use this to implement functions to do post requests other than using the update method.
* @param url
* @param model
* @returns {Q.Promise<unknown>}
*/ */
async post(url, model) { async post(url : string, model : Model) {
const cancel = this.setLoading() const cancel = this.setLoading()
try { try {
@ -421,10 +383,8 @@ export default class AbstractService {
/** /**
* Performs a post request to the update url * Performs a post request to the update url
* @param model
* @returns {Q.Promise<any>}
*/ */
update(model) { update(model : Model) {
if (this.paths.update === '') { if (this.paths.update === '') {
throw new Error('This model is not able to update data.') throw new Error('This model is not able to update data.')
} }
@ -435,10 +395,8 @@ export default class AbstractService {
/** /**
* Performs a delete request to the update url * Performs a delete request to the update url
* @param model
* @returns {Q.Promise<any>}
*/ */
async delete(model) { async delete(model : Model) {
if (this.paths.delete === '') { if (this.paths.delete === '') {
throw new Error('This model is not able to delete data.') throw new Error('This model is not able to delete data.')
} }
@ -459,21 +417,15 @@ export default class AbstractService {
* @param url * @param url
* @param file * @param file
* @param fieldName The name of the field the file is uploaded to. * @param fieldName The name of the field the file is uploaded to.
* @returns {Q.Promise<unknown>}
*/ */
uploadFile(url, file, fieldName) { uploadFile(url : string, file, fieldName : string) {
return this.uploadBlob(url, new Blob([file]), fieldName, file.name) return this.uploadBlob(url, new Blob([file]), fieldName, file.name)
} }
/** /**
* Uploads a blob to a url. * Uploads a blob to a url.
* @param url
* @param blob
* @param fieldName
* @param filename
* @returns {Q.Promise<unknown>}
*/ */
uploadBlob(url, blob, fieldName, filename) { uploadBlob(url : string, blob: Blob, fieldName: string, filename : string) {
const data = new FormData() const data = new FormData()
data.append(fieldName, blob, filename) data.append(fieldName, blob, filename)
return this.uploadFormData(url, data) return this.uploadFormData(url, data)
@ -481,11 +433,8 @@ export default class AbstractService {
/** /**
* Uploads a form data object. * Uploads a form data object.
* @param url
* @param formData
* @returns {Q.Promise<unknown>}
*/ */
async uploadFormData(url, formData) { async uploadFormData(url : string, formData: Record<string, unknown>) {
const cancel = this.setLoading() const cancel = this.setLoading()
try { try {
const response = await this.http.put( const response = await this.http.put(