// Copyright (C) The Arvados Authors. All rights reserved. // // SPDX-License-Identifier: AGPL-3.0 import * as _ from "lodash"; import { AxiosInstance, AxiosPromise } from "axios"; import * as uuid from "uuid/v4"; import { ApiActions } from "~/services/api/api-actions"; interface Errors { errors: string[]; errorToken: string; } export interface ListArguments { limit?: number; offset?: number; filters?: string; order?: string; select?: string[]; distinct?: boolean; count?: string; } export interface ListResults { clusterId?: string; kind: string; offset: number; limit: number; items: T[]; itemsAvailable: number; } export class CommonService { protected serverApi: AxiosInstance; protected resourceType: string; protected actions: ApiActions; constructor(serverApi: AxiosInstance, resourceType: string, actions: ApiActions) { this.serverApi = serverApi; this.resourceType = '/' + resourceType; this.actions = actions; } static mapResponseKeys = (response: { data: any }) => CommonService.mapKeys(_.camelCase)(response.data) static mapKeys = (mapFn: (key: string) => string) => (value: any): any => { switch (true) { case _.isPlainObject(value): return Object .keys(value) .map(key => [key, mapFn(key)]) .reduce((newValue, [key, newKey]) => ({ ...newValue, [newKey]: (key === 'items') ? CommonService.mapKeys(mapFn)(value[key]) : value[key] }), {}); case _.isArray(value): return value.map(CommonService.mapKeys(mapFn)); default: return value; } } static defaultResponse(promise: AxiosPromise, actions: ApiActions, mapKeys = true): Promise { const reqId = uuid(); actions.progressFn(reqId, true); return promise .then(data => { actions.progressFn(reqId, false); return data; }) .then((response: { data: any }) => { return mapKeys ? CommonService.mapResponseKeys(response) : response.data; }) .catch(({ response }) => { actions.progressFn(reqId, false); const errors = CommonService.mapResponseKeys(response) as Errors; actions.errorFn(reqId, errors); throw errors; }); } create(data?: Partial) { return CommonService.defaultResponse( this.serverApi .post(this.resourceType, data && CommonService.mapKeys(_.snakeCase)(data)), this.actions ); } delete(uuid: string): Promise { return CommonService.defaultResponse( this.serverApi .delete(this.resourceType + '/' + uuid), this.actions ); } get(uuid: string) { return CommonService.defaultResponse( this.serverApi .get(this.resourceType + '/' + uuid), this.actions ); } list(args: ListArguments = {}): Promise> { const { filters, order, ...other } = args; const params = { ...other, filters: filters ? `[${filters}]` : undefined, order: order ? order : undefined }; return CommonService.defaultResponse( this.serverApi .get(this.resourceType, { params: CommonService.mapKeys(_.snakeCase)(params) }), this.actions ); } update(uuid: string, data: Partial) { return CommonService.defaultResponse( this.serverApi .put(this.resourceType + '/' + uuid, data && CommonService.mapKeys(_.snakeCase)(data)), this.actions ); } }