1 | 'use strict';
|
---|
2 |
|
---|
3 | import {obj_remove_id, sortByKey, urlEncode} from "./library";
|
---|
4 | import Cookie from 'js-cookie';
|
---|
5 |
|
---|
6 |
|
---|
7 | class RestAPI {
|
---|
8 | static get BASE_URL() {
|
---|
9 | return '/api/';
|
---|
10 | }
|
---|
11 |
|
---|
12 | static get SAFE_METHODS() {
|
---|
13 | return ['GET', 'HEAD', 'OPTIONS', 'TRACE'];
|
---|
14 | }
|
---|
15 |
|
---|
16 | static get EXPECTED_CODE() {
|
---|
17 | return {
|
---|
18 | DELETE: 204,
|
---|
19 | POST: 201,
|
---|
20 | };
|
---|
21 | }
|
---|
22 |
|
---|
23 | static get JSON_TYPES() {
|
---|
24 | return ['application/json'];
|
---|
25 | }
|
---|
26 |
|
---|
27 | static request(method, resource, data = null, headers = null) {
|
---|
28 | method = method.toUpperCase();
|
---|
29 |
|
---|
30 | let url = `${this.BASE_URL}${resource}/`;
|
---|
31 |
|
---|
32 | if (data !== null && this.SAFE_METHODS.includes(method)) {
|
---|
33 | // need to add parameters to URL
|
---|
34 | url += '?' + urlEncode(data);
|
---|
35 | }
|
---|
36 |
|
---|
37 | return fetch(url, {
|
---|
38 | method: method,
|
---|
39 | credentials: 'same-origin',
|
---|
40 | headers: {...this.get_headers(method), ...headers},
|
---|
41 | body: this.get_body(method, data)
|
---|
42 | }).then(response => {
|
---|
43 | if (!response.ok) {
|
---|
44 | return Promise.reject([`Failed to ${method} ${resource}`, response]);
|
---|
45 | }
|
---|
46 |
|
---|
47 | let expected_code = this.EXPECTED_CODE[method];
|
---|
48 | if (expected_code && response.status !== expected_code) {
|
---|
49 | return Promise.reject([`Invalid response code: ${response.status} != ${expected_code}`, response]);
|
---|
50 | }
|
---|
51 |
|
---|
52 | let content_type = response.headers.get('Content-Type');
|
---|
53 |
|
---|
54 | if (content_type && this.JSON_TYPES.includes(content_type)) {
|
---|
55 | // return JSON only when we know that response is JSON (e.g. not empty response)
|
---|
56 | return response.json();
|
---|
57 | }
|
---|
58 |
|
---|
59 | return response.text().then(text => text || null);
|
---|
60 | });
|
---|
61 | }
|
---|
62 |
|
---|
63 | static get(resource, data, headers) {
|
---|
64 | return this.request('GET', resource, data, headers);
|
---|
65 | }
|
---|
66 |
|
---|
67 | static post(resource, data, headers) {
|
---|
68 | return this.request('POST', resource, data, headers);
|
---|
69 | }
|
---|
70 |
|
---|
71 | static patch(resource, data, headers) {
|
---|
72 | return this.request('PATCH', resource, data, headers);
|
---|
73 | }
|
---|
74 |
|
---|
75 | static options(resource, data, headers) {
|
---|
76 | return this.request('OPTIONS', resource, data, headers);
|
---|
77 | }
|
---|
78 |
|
---|
79 | static delete(resource, data, headers) {
|
---|
80 | return this.request('DELETE', resource, data, headers);
|
---|
81 | }
|
---|
82 |
|
---|
83 | static get_headers(method) {
|
---|
84 | if (this.SAFE_METHODS.includes(method)) {
|
---|
85 | return {};
|
---|
86 | }
|
---|
87 | return {
|
---|
88 | 'X-CSRFToken': Cookie.get('csrftoken'),
|
---|
89 | 'Content-Type': 'application/json; charset="utf-8"',
|
---|
90 | };
|
---|
91 | }
|
---|
92 |
|
---|
93 | static get_body(method, data) {
|
---|
94 | if (data === null || this.SAFE_METHODS.includes(method)) {
|
---|
95 | return null;
|
---|
96 | }
|
---|
97 | return JSON.stringify(data);
|
---|
98 | }
|
---|
99 | }
|
---|
100 |
|
---|
101 |
|
---|
102 | export class API {
|
---|
103 | static get DOMAIN() {
|
---|
104 | throw Error('You must define DOMAIN');
|
---|
105 | }
|
---|
106 |
|
---|
107 | static get ORDER_BY() {
|
---|
108 | return 'name';
|
---|
109 | }
|
---|
110 |
|
---|
111 | static create(obj) {
|
---|
112 | return RestAPI.post(this.DOMAIN, obj_remove_id(obj));
|
---|
113 | }
|
---|
114 |
|
---|
115 | static all() {
|
---|
116 | return RestAPI.get(this.DOMAIN).then(objects => objects.sort(sortByKey(this.ORDER_BY)));
|
---|
117 | }
|
---|
118 |
|
---|
119 | static get(obj) {
|
---|
120 | return RestAPI.get(`${this.DOMAIN}/${obj.id}`);
|
---|
121 | }
|
---|
122 |
|
---|
123 | static update(obj) {
|
---|
124 | return RestAPI.patch(`${this.DOMAIN}/${obj.id}`, obj);
|
---|
125 | }
|
---|
126 |
|
---|
127 | static delete(obj) {
|
---|
128 | return RestAPI.delete(`${this.DOMAIN}/${obj.id}`);
|
---|
129 | }
|
---|
130 |
|
---|
131 | static options(headers) {
|
---|
132 | return RestAPI.options(this.DOMAIN, null, headers);
|
---|
133 | }
|
---|
134 |
|
---|
135 | static extract_schema(metadata) {
|
---|
136 | return metadata.actions.POST;
|
---|
137 | }
|
---|
138 | }
|
---|