17782: Fixes almost all tests (4 left) mostly by fixing namespace-type imports.
[arvados-workbench2.git] / src / services / common-service / common-service.ts
index 44233eb17bd2f683ecf4fcb48459160dd583119e..c19c19784bee4096011c29b834cfb4780db92200 100644 (file)
@@ -2,13 +2,14 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import * as _ from "lodash";
+import { camelCase, isPlainObject, isArray, snakeCase } from "lodash";
 import { AxiosInstance, AxiosPromise } from "axios";
-import * as uuid from "uuid/v4";
-import { ApiActions } from "~/services/api/api-actions";
-import * as QueryString from "query-string";
+import uuid from "uuid/v4";
+import { ApiActions } from "services/api/api-actions";
+import QueryString from "query-string";
 
 interface Errors {
+    status: number;
     errors: string[];
     errorToken: string;
 }
@@ -21,6 +22,7 @@ export interface ListArguments {
     select?: string[];
     distinct?: boolean;
     count?: string;
+    includeOldVersions?: boolean;
 }
 
 export interface ListResults<T> {
@@ -40,18 +42,18 @@ export class CommonService<T> {
 
     constructor(serverApi: AxiosInstance, resourceType: string, actions: ApiActions, readOnlyFields: string[] = []) {
         this.serverApi = serverApi;
-        this.resourceType = '/' + resourceType;
+        this.resourceType = resourceType;
         this.actions = actions;
         this.readOnlyFields = readOnlyFields;
     }
 
     static mapResponseKeys = (response: { data: any }) =>
-        CommonService.mapKeys(_.camelCase)(response.data)
+        CommonService.mapKeys(camelCase)(response.data)
 
     static mapKeys = (mapFn: (key: string) => string) =>
         (value: any): any => {
             switch (true) {
-                case _.isPlainObject(value):
+                case isPlainObject(value):
                     return Object
                         .keys(value)
                         .map(key => [key, mapFn(key)])
@@ -59,14 +61,20 @@ export class CommonService<T> {
                             ...newValue,
                             [newKey]: (key === 'items') ? CommonService.mapKeys(mapFn)(value[key]) : value[key]
                         }), {});
-                case _.isArray(value):
+                case isArray(value):
                     return value.map(CommonService.mapKeys(mapFn));
                 default:
                     return value;
             }
         }
 
-    static defaultResponse<R>(promise: AxiosPromise<R>, actions: ApiActions, mapKeys = true): Promise<R> {
+    private validateUuid(uuid: string) {
+        if (uuid === "") {
+            throw new Error('UUID cannot be empty string');
+        }
+    }
+
+    static defaultResponse<R>(promise: AxiosPromise<R>, actions: ApiActions, mapKeys = true, showErrors = true): Promise<R> {
         const reqId = uuid();
         actions.progressFn(reqId, true);
         return promise
@@ -80,46 +88,53 @@ export class CommonService<T> {
             .catch(({ response }) => {
                 actions.progressFn(reqId, false);
                 const errors = CommonService.mapResponseKeys(response) as Errors;
-                actions.errorFn(reqId, errors);
+                errors.status = response.status;
+                actions.errorFn(reqId, errors, showErrors);
                 throw errors;
             });
     }
 
-    create(data?: Partial<T>) {
+    create(data?: Partial<T>, showErrors?: boolean) {
         return CommonService.defaultResponse(
             this.serverApi
-                .post<T>(this.resourceType, data && CommonService.mapKeys(_.snakeCase)(data)),
-            this.actions
+                .post<T>(`/${this.resourceType}`, data && CommonService.mapKeys(snakeCase)(data)),
+            this.actions,
+            true, // mapKeys
+            showErrors
         );
     }
 
     delete(uuid: string): Promise<T> {
+        this.validateUuid(uuid);
         return CommonService.defaultResponse(
             this.serverApi
-                .delete(this.resourceType + '/' + uuid),
+                .delete(`/${this.resourceType}/${uuid}`),
             this.actions
         );
     }
 
-    get(uuid: string) {
+    get(uuid: string, showErrors?: boolean) {
+        this.validateUuid(uuid);
         return CommonService.defaultResponse(
             this.serverApi
-                .get<T>(this.resourceType + '/' + uuid),
-            this.actions
+                .get<T>(`/${this.resourceType}/${uuid}`),
+            this.actions,
+            true, // mapKeys
+            showErrors
         );
     }
 
     list(args: ListArguments = {}): Promise<ListResults<T>> {
         const { filters, order, ...other } = args;
         const params = {
-            ...other,
+            ...CommonService.mapKeys(snakeCase)(other),
             filters: filters ? `[${filters}]` : undefined,
             order: order ? order : undefined
         };
 
         if (QueryString.stringify(params).length <= 1500) {
             return CommonService.defaultResponse(
-                this.serverApi.get(this.resourceType, { params }),
+                this.serverApi.get(`/${this.resourceType}`, { params }),
                 this.actions
             );
         } else {
@@ -132,7 +147,7 @@ export class CommonService<T> {
                 }
             });
             return CommonService.defaultResponse(
-                this.serverApi.post(this.resourceType, formData, {
+                this.serverApi.post(`/${this.resourceType}`, formData, {
                     params: {
                         _method: 'GET'
                     }
@@ -143,9 +158,10 @@ export class CommonService<T> {
     }
 
     update(uuid: string, data: Partial<T>) {
+        this.validateUuid(uuid);
         return CommonService.defaultResponse(
             this.serverApi
-                .put<T>(this.resourceType + '/' + uuid, data && CommonService.mapKeys(_.snakeCase)(data)),
+                .put<T>(`/${this.resourceType}/${uuid}`, data && CommonService.mapKeys(snakeCase)(data)),
             this.actions
         );
     }