Obtain configuration from discovery endpoint
[arvados.git] / src / common / api / common-resource-service.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import * as _ from "lodash";
6 import { AxiosInstance, AxiosPromise } from "axios";
7 import { Resource } from "~/models/resource";
8
9 export interface ListArguments {
10     limit?: number;
11     offset?: number;
12     filters?: string;
13     order?: string;
14     select?: string[];
15     distinct?: boolean;
16     count?: string;
17 }
18
19 export interface ListResults<T> {
20     kind: string;
21     offset: number;
22     limit: number;
23     items: T[];
24     itemsAvailable: number;
25 }
26
27 export interface Errors {
28     errors: string[];
29     errorToken: string;
30 }
31
32 export class CommonResourceService<T extends Resource> {
33
34     static mapResponseKeys = (response: any): Promise<any> =>
35         CommonResourceService.mapKeys(_.camelCase)(response.data)
36
37     static mapKeys = (mapFn: (key: string) => string) =>
38         (value: any): any => {
39             switch (true) {
40                 case _.isPlainObject(value):
41                     return Object
42                         .keys(value)
43                         .map(key => [key, mapFn(key)])
44                         .reduce((newValue, [key, newKey]) => ({
45                             ...newValue,
46                             [newKey]: CommonResourceService.mapKeys(mapFn)(value[key])
47                         }), {});
48                 case _.isArray(value):
49                     return value.map(CommonResourceService.mapKeys(mapFn));
50                 default:
51                     return value;
52             }
53         }
54
55     static defaultResponse<R>(promise: AxiosPromise<R>): Promise<R> {
56         return promise
57             .then(CommonResourceService.mapResponseKeys)
58             .catch(({ response }) => Promise.reject<Errors>(CommonResourceService.mapResponseKeys(response)));
59     }
60
61     protected serverApi: AxiosInstance;
62     protected resourceType: string;
63
64     constructor(serverApi: AxiosInstance, resourceType: string) {
65         this.serverApi = serverApi;
66         this.resourceType = '/' + resourceType + '/';
67     }
68
69     create(data?: Partial<T> | any) {
70         return CommonResourceService.defaultResponse(
71             this.serverApi
72                 .post<T>(this.resourceType, data && CommonResourceService.mapKeys(_.snakeCase)(data)));
73     }
74
75     delete(uuid: string): Promise<T> {
76         return CommonResourceService.defaultResponse(
77             this.serverApi
78                 .delete(this.resourceType + uuid));
79     }
80
81     get(uuid: string) {
82         return CommonResourceService.defaultResponse(
83             this.serverApi
84                 .get<T>(this.resourceType + uuid));
85     }
86
87     list(args: ListArguments = {}): Promise<ListResults<T>> {
88         const { filters, order, ...other } = args;
89         const params = {
90             ...other,
91             filters: filters ? `[${filters}]` : undefined,
92             order: order ? order : undefined
93         };
94         return CommonResourceService.defaultResponse(
95             this.serverApi
96                 .get(this.resourceType, {
97                     params: CommonResourceService.mapKeys(_.snakeCase)(params)
98                 }));
99     }
100
101     update(uuid: string, data: any) {
102         return CommonResourceService.defaultResponse(
103             this.serverApi
104                 .put<T>(this.resourceType + uuid, data));
105
106     }
107 }
108