@nocobase/sdk 0.7.0-alpha.80 → 0.7.0-alpha.83

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/es/APIClient.d.ts CHANGED
@@ -17,21 +17,54 @@ export interface IResource {
17
17
  destroy?: (params?: ActionParams) => Promise<any>;
18
18
  [key: string]: (params?: ActionParams) => Promise<any>;
19
19
  }
20
- declare class Auth {
20
+ export declare class Auth {
21
21
  protected api: APIClient;
22
- protected token: string;
23
- protected role: string;
22
+ protected options: {
23
+ token: any;
24
+ locale: any;
25
+ role: any;
26
+ };
24
27
  constructor(api: APIClient);
28
+ get locale(): string;
29
+ get role(): string;
30
+ get token(): string;
31
+ set locale(value: string);
32
+ set role(value: string);
33
+ set token(value: string);
34
+ middleware(config: AxiosRequestConfig): AxiosRequestConfig<any>;
35
+ getLocale(): string;
36
+ setLocale(locale: string): void;
37
+ getToken(): string;
25
38
  setToken(token: string): void;
39
+ getRole(): string;
26
40
  setRole(role: string): void;
27
- signIn(values: any): Promise<any>;
41
+ signIn(values: any): Promise<AxiosResponse<any>>;
28
42
  signOut(): Promise<void>;
29
43
  }
44
+ export declare abstract class Storage {
45
+ abstract clear(): void;
46
+ abstract getItem(key: string): string | null;
47
+ abstract removeItem(key: string): void;
48
+ abstract setItem(key: string, value: string): void;
49
+ }
50
+ export declare class MemoryStorage extends Storage {
51
+ items: Map<any, any>;
52
+ clear(): void;
53
+ getItem(key: string): any;
54
+ setItem(key: string, value: string): Map<any, any>;
55
+ removeItem(key: string): boolean;
56
+ }
57
+ interface ExtendedOptions {
58
+ authClass?: any;
59
+ storageClass?: any;
60
+ }
30
61
  export declare class APIClient {
31
62
  axios: AxiosInstance;
32
63
  auth: Auth;
33
- constructor(instance?: AxiosInstance | AxiosRequestConfig);
34
- qsMiddleware(): void;
64
+ storage: Storage;
65
+ constructor(instance?: AxiosInstance | (AxiosRequestConfig & ExtendedOptions));
66
+ private initStorage;
67
+ paramsSerializer(): void;
35
68
  request<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D> | ResourceActionOptions): Promise<R>;
36
69
  resource(name: string, of?: any): IResource;
37
70
  }
package/es/APIClient.js CHANGED
@@ -1,4 +1,5 @@
1
- const _excluded = ["values", "filter"];
1
+ const _excluded = ["authClass", "storageClass"],
2
+ _excluded2 = ["values", "filter"];
2
3
 
3
4
  function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
4
5
 
@@ -10,34 +11,91 @@ function _asyncToGenerator(fn) { return function () { var self = this, args = ar
10
11
 
11
12
  import axios from 'axios';
12
13
  import qs from 'qs';
13
-
14
- class Auth {
14
+ export class Auth {
15
15
  constructor(api) {
16
16
  this.api = void 0;
17
- this.token = void 0;
18
- this.role = void 0;
17
+ this.options = {
18
+ token: null,
19
+ locale: null,
20
+ role: null
21
+ };
19
22
  this.api = api;
20
- this.api.axios.interceptors.request.use(config => {
21
- config.headers['X-Hostname'] = window.location.hostname;
23
+ this.locale = this.getLocale();
24
+ this.role = this.getRole();
25
+ this.token = this.getToken();
26
+ this.api.axios.interceptors.request.use(this.middleware.bind(this));
27
+ }
22
28
 
23
- if (this.role) {
24
- config.headers['X-Role'] = this.role;
25
- }
29
+ get locale() {
30
+ return this.getLocale();
31
+ }
26
32
 
27
- if (this.token) {
28
- config.headers['Authorization'] = `Bearer ${this.token}`;
29
- }
33
+ get role() {
34
+ return this.getRole();
35
+ }
30
36
 
31
- return config;
32
- });
37
+ get token() {
38
+ return this.getToken();
39
+ }
40
+
41
+ set locale(value) {
42
+ this.setLocale(value);
43
+ }
44
+
45
+ set role(value) {
46
+ this.setRole(value);
47
+ }
48
+
49
+ set token(value) {
50
+ this.setToken(value);
51
+ }
52
+
53
+ middleware(config) {
54
+ if (this.locale) {
55
+ config.headers['X-Locale'] = this.locale;
56
+ }
57
+
58
+ if (this.role) {
59
+ config.headers['X-Role'] = this.role;
60
+ }
61
+
62
+ if (this.token) {
63
+ config.headers['Authorization'] = `Bearer ${this.token}`;
64
+ }
65
+
66
+ return config;
67
+ }
68
+
69
+ getLocale() {
70
+ return this.api.storage.getItem('NOCOBASE_LOCALE');
71
+ }
72
+
73
+ setLocale(locale) {
74
+ this.options.locale = locale;
75
+ this.api.storage.setItem('NOCOBASE_LOCALE', locale || '');
76
+ }
77
+
78
+ getToken() {
79
+ return this.api.storage.getItem('NOCOBASE_TOKEN');
33
80
  }
34
81
 
35
82
  setToken(token) {
36
- this.token = token;
83
+ this.options.token = token;
84
+ this.api.storage.setItem('NOCOBASE_TOKEN', token || '');
85
+
86
+ if (!token) {
87
+ this.setRole(null);
88
+ this.setLocale(null);
89
+ }
90
+ }
91
+
92
+ getRole() {
93
+ return this.api.storage.getItem('NOCOBASE_ROLE');
37
94
  }
38
95
 
39
96
  setRole(role) {
40
- this.role = role;
97
+ this.options.role = role;
98
+ this.api.storage.setItem('NOCOBASE_ROLE', role || '');
41
99
  }
42
100
 
43
101
  signIn(values) {
@@ -52,8 +110,10 @@ class Auth {
52
110
  data: values
53
111
  });
54
112
  const data = response === null || response === void 0 ? void 0 : (_response$data = response.data) === null || _response$data === void 0 ? void 0 : _response$data.data;
55
- _this.token = data;
56
- return data;
113
+
114
+ _this.setToken(data === null || data === void 0 ? void 0 : data.token);
115
+
116
+ return response;
57
117
  })();
58
118
  }
59
119
 
@@ -65,28 +125,80 @@ class Auth {
65
125
  method: 'post',
66
126
  url: 'users:signout'
67
127
  });
68
- _this2.token = null;
128
+
129
+ _this2.setToken(null);
69
130
  })();
70
131
  }
71
132
 
72
133
  }
134
+ export class Storage {}
135
+ export class MemoryStorage extends Storage {
136
+ constructor(...args) {
137
+ super(...args);
138
+ this.items = new Map();
139
+ }
140
+
141
+ clear() {
142
+ this.items.clear();
143
+ }
144
+
145
+ getItem(key) {
146
+ return this.items.get(key);
147
+ }
148
+
149
+ setItem(key, value) {
150
+ return this.items.set(key, value);
151
+ }
73
152
 
153
+ removeItem(key) {
154
+ return this.items.delete(key);
155
+ }
156
+
157
+ }
74
158
  export class APIClient {
75
159
  constructor(instance) {
76
160
  this.axios = void 0;
77
161
  this.auth = void 0;
162
+ this.storage = void 0;
78
163
 
79
164
  if (typeof instance === 'function') {
80
165
  this.axios = instance;
81
166
  } else {
82
- this.axios = axios.create(instance);
167
+ const _ref = instance || {},
168
+ authClass = _ref.authClass,
169
+ storageClass = _ref.storageClass,
170
+ others = _objectWithoutProperties(_ref, _excluded);
171
+
172
+ this.axios = axios.create(others);
173
+ this.initStorage(storageClass);
174
+
175
+ if (authClass) {
176
+ this.auth = new authClass(this);
177
+ }
178
+ }
179
+
180
+ if (!this.storage) {
181
+ this.initStorage();
182
+ }
183
+
184
+ if (!this.auth) {
185
+ this.auth = new Auth(this);
83
186
  }
84
187
 
85
- this.auth = new Auth(this);
86
- this.qsMiddleware();
188
+ this.paramsSerializer();
189
+ }
190
+
191
+ initStorage(storage) {
192
+ if (storage) {
193
+ this.storage = new storage(this);
194
+ } else if (localStorage) {
195
+ this.storage = localStorage;
196
+ } else {
197
+ this.storage = new MemoryStorage();
198
+ }
87
199
  }
88
200
 
89
- qsMiddleware() {
201
+ paramsSerializer() {
90
202
  this.axios.interceptors.request.use(config => {
91
203
  config.paramsSerializer = params => {
92
204
  return qs.stringify(params, {
@@ -131,11 +243,11 @@ export class APIClient {
131
243
  }
132
244
 
133
245
  return /*#__PURE__*/function () {
134
- var _ref = _asyncToGenerator(function* (params) {
135
- const _ref2 = params || {},
136
- values = _ref2.values,
137
- filter = _ref2.filter,
138
- others = _objectWithoutProperties(_ref2, _excluded);
246
+ var _ref2 = _asyncToGenerator(function* (params) {
247
+ const _ref3 = params || {},
248
+ values = _ref3.values,
249
+ filter = _ref3.filter,
250
+ others = _objectWithoutProperties(_ref3, _excluded2);
139
251
 
140
252
  config['params'] = others;
141
253
 
@@ -155,7 +267,7 @@ export class APIClient {
155
267
  });
156
268
 
157
269
  return function (_x) {
158
- return _ref.apply(this, arguments);
270
+ return _ref2.apply(this, arguments);
159
271
  };
160
272
  }();
161
273
  }
@@ -17,21 +17,54 @@ export interface IResource {
17
17
  destroy?: (params?: ActionParams) => Promise<any>;
18
18
  [key: string]: (params?: ActionParams) => Promise<any>;
19
19
  }
20
- declare class Auth {
20
+ export declare class Auth {
21
21
  protected api: APIClient;
22
- protected token: string;
23
- protected role: string;
22
+ protected options: {
23
+ token: any;
24
+ locale: any;
25
+ role: any;
26
+ };
24
27
  constructor(api: APIClient);
28
+ get locale(): string;
29
+ get role(): string;
30
+ get token(): string;
31
+ set locale(value: string);
32
+ set role(value: string);
33
+ set token(value: string);
34
+ middleware(config: AxiosRequestConfig): AxiosRequestConfig<any>;
35
+ getLocale(): string;
36
+ setLocale(locale: string): void;
37
+ getToken(): string;
25
38
  setToken(token: string): void;
39
+ getRole(): string;
26
40
  setRole(role: string): void;
27
- signIn(values: any): Promise<any>;
41
+ signIn(values: any): Promise<AxiosResponse<any>>;
28
42
  signOut(): Promise<void>;
29
43
  }
44
+ export declare abstract class Storage {
45
+ abstract clear(): void;
46
+ abstract getItem(key: string): string | null;
47
+ abstract removeItem(key: string): void;
48
+ abstract setItem(key: string, value: string): void;
49
+ }
50
+ export declare class MemoryStorage extends Storage {
51
+ items: Map<any, any>;
52
+ clear(): void;
53
+ getItem(key: string): any;
54
+ setItem(key: string, value: string): Map<any, any>;
55
+ removeItem(key: string): boolean;
56
+ }
57
+ interface ExtendedOptions {
58
+ authClass?: any;
59
+ storageClass?: any;
60
+ }
30
61
  export declare class APIClient {
31
62
  axios: AxiosInstance;
32
63
  auth: Auth;
33
- constructor(instance?: AxiosInstance | AxiosRequestConfig);
34
- qsMiddleware(): void;
64
+ storage: Storage;
65
+ constructor(instance?: AxiosInstance | (AxiosRequestConfig & ExtendedOptions));
66
+ private initStorage;
67
+ paramsSerializer(): void;
35
68
  request<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D> | ResourceActionOptions): Promise<R>;
36
69
  resource(name: string, of?: any): IResource;
37
70
  }
package/lib/APIClient.js CHANGED
@@ -3,13 +3,14 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.APIClient = void 0;
6
+ exports.Storage = exports.MemoryStorage = exports.Auth = exports.APIClient = void 0;
7
7
 
8
8
  var _axios = _interopRequireDefault(require("axios"));
9
9
 
10
10
  var _qs = _interopRequireDefault(require("qs"));
11
11
 
12
- const _excluded = ["values", "filter"];
12
+ const _excluded = ["authClass", "storageClass"],
13
+ _excluded2 = ["values", "filter"];
13
14
 
14
15
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
16
 
@@ -24,30 +25,88 @@ function _asyncToGenerator(fn) { return function () { var self = this, args = ar
24
25
  class Auth {
25
26
  constructor(api) {
26
27
  this.api = void 0;
27
- this.token = void 0;
28
- this.role = void 0;
28
+ this.options = {
29
+ token: null,
30
+ locale: null,
31
+ role: null
32
+ };
29
33
  this.api = api;
30
- this.api.axios.interceptors.request.use(config => {
31
- config.headers['X-Hostname'] = window.location.hostname;
34
+ this.locale = this.getLocale();
35
+ this.role = this.getRole();
36
+ this.token = this.getToken();
37
+ this.api.axios.interceptors.request.use(this.middleware.bind(this));
38
+ }
32
39
 
33
- if (this.role) {
34
- config.headers['X-Role'] = this.role;
35
- }
40
+ get locale() {
41
+ return this.getLocale();
42
+ }
36
43
 
37
- if (this.token) {
38
- config.headers['Authorization'] = `Bearer ${this.token}`;
39
- }
44
+ get role() {
45
+ return this.getRole();
46
+ }
40
47
 
41
- return config;
42
- });
48
+ get token() {
49
+ return this.getToken();
50
+ }
51
+
52
+ set locale(value) {
53
+ this.setLocale(value);
54
+ }
55
+
56
+ set role(value) {
57
+ this.setRole(value);
58
+ }
59
+
60
+ set token(value) {
61
+ this.setToken(value);
62
+ }
63
+
64
+ middleware(config) {
65
+ if (this.locale) {
66
+ config.headers['X-Locale'] = this.locale;
67
+ }
68
+
69
+ if (this.role) {
70
+ config.headers['X-Role'] = this.role;
71
+ }
72
+
73
+ if (this.token) {
74
+ config.headers['Authorization'] = `Bearer ${this.token}`;
75
+ }
76
+
77
+ return config;
78
+ }
79
+
80
+ getLocale() {
81
+ return this.api.storage.getItem('NOCOBASE_LOCALE');
82
+ }
83
+
84
+ setLocale(locale) {
85
+ this.options.locale = locale;
86
+ this.api.storage.setItem('NOCOBASE_LOCALE', locale || '');
87
+ }
88
+
89
+ getToken() {
90
+ return this.api.storage.getItem('NOCOBASE_TOKEN');
43
91
  }
44
92
 
45
93
  setToken(token) {
46
- this.token = token;
94
+ this.options.token = token;
95
+ this.api.storage.setItem('NOCOBASE_TOKEN', token || '');
96
+
97
+ if (!token) {
98
+ this.setRole(null);
99
+ this.setLocale(null);
100
+ }
101
+ }
102
+
103
+ getRole() {
104
+ return this.api.storage.getItem('NOCOBASE_ROLE');
47
105
  }
48
106
 
49
107
  setRole(role) {
50
- this.role = role;
108
+ this.options.role = role;
109
+ this.api.storage.setItem('NOCOBASE_ROLE', role || '');
51
110
  }
52
111
 
53
112
  signIn(values) {
@@ -62,8 +121,10 @@ class Auth {
62
121
  data: values
63
122
  });
64
123
  const data = response === null || response === void 0 ? void 0 : (_response$data = response.data) === null || _response$data === void 0 ? void 0 : _response$data.data;
65
- _this.token = data;
66
- return data;
124
+
125
+ _this.setToken(data === null || data === void 0 ? void 0 : data.token);
126
+
127
+ return response;
67
128
  })();
68
129
  }
69
130
 
@@ -75,28 +136,89 @@ class Auth {
75
136
  method: 'post',
76
137
  url: 'users:signout'
77
138
  });
78
- _this2.token = null;
139
+
140
+ _this2.setToken(null);
79
141
  })();
80
142
  }
81
143
 
82
144
  }
83
145
 
146
+ exports.Auth = Auth;
147
+
148
+ class Storage {}
149
+
150
+ exports.Storage = Storage;
151
+
152
+ class MemoryStorage extends Storage {
153
+ constructor(...args) {
154
+ super(...args);
155
+ this.items = new Map();
156
+ }
157
+
158
+ clear() {
159
+ this.items.clear();
160
+ }
161
+
162
+ getItem(key) {
163
+ return this.items.get(key);
164
+ }
165
+
166
+ setItem(key, value) {
167
+ return this.items.set(key, value);
168
+ }
169
+
170
+ removeItem(key) {
171
+ return this.items.delete(key);
172
+ }
173
+
174
+ }
175
+
176
+ exports.MemoryStorage = MemoryStorage;
177
+
84
178
  class APIClient {
85
179
  constructor(instance) {
86
180
  this.axios = void 0;
87
181
  this.auth = void 0;
182
+ this.storage = void 0;
88
183
 
89
184
  if (typeof instance === 'function') {
90
185
  this.axios = instance;
91
186
  } else {
92
- this.axios = _axios.default.create(instance);
187
+ const _ref = instance || {},
188
+ authClass = _ref.authClass,
189
+ storageClass = _ref.storageClass,
190
+ others = _objectWithoutProperties(_ref, _excluded);
191
+
192
+ this.axios = _axios.default.create(others);
193
+ this.initStorage(storageClass);
194
+
195
+ if (authClass) {
196
+ this.auth = new authClass(this);
197
+ }
93
198
  }
94
199
 
95
- this.auth = new Auth(this);
96
- this.qsMiddleware();
200
+ if (!this.storage) {
201
+ this.initStorage();
202
+ }
203
+
204
+ if (!this.auth) {
205
+ this.auth = new Auth(this);
206
+ }
207
+
208
+ this.paramsSerializer();
209
+ }
210
+
211
+ initStorage(storage) {
212
+ if (storage) {
213
+ this.storage = new storage(this);
214
+ } else if (localStorage) {
215
+ this.storage = localStorage;
216
+ } else {
217
+ this.storage = new MemoryStorage();
218
+ }
97
219
  }
98
220
 
99
- qsMiddleware() {
221
+ paramsSerializer() {
100
222
  this.axios.interceptors.request.use(config => {
101
223
  config.paramsSerializer = params => {
102
224
  return _qs.default.stringify(params, {
@@ -141,11 +263,11 @@ class APIClient {
141
263
  }
142
264
 
143
265
  return /*#__PURE__*/function () {
144
- var _ref = _asyncToGenerator(function* (params) {
145
- const _ref2 = params || {},
146
- values = _ref2.values,
147
- filter = _ref2.filter,
148
- others = _objectWithoutProperties(_ref2, _excluded);
266
+ var _ref2 = _asyncToGenerator(function* (params) {
267
+ const _ref3 = params || {},
268
+ values = _ref3.values,
269
+ filter = _ref3.filter,
270
+ others = _objectWithoutProperties(_ref3, _excluded2);
149
271
 
150
272
  config['params'] = others;
151
273
 
@@ -165,7 +287,7 @@ class APIClient {
165
287
  });
166
288
 
167
289
  return function (_x) {
168
- return _ref.apply(this, arguments);
290
+ return _ref2.apply(this, arguments);
169
291
  };
170
292
  }();
171
293
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/sdk",
3
- "version": "0.7.0-alpha.80",
3
+ "version": "0.7.0-alpha.83",
4
4
  "license": "Apache-2.0",
5
5
  "licenses": [
6
6
  {
@@ -12,10 +12,11 @@
12
12
  "module": "es/index.js",
13
13
  "typings": "es/index.d.ts",
14
14
  "dependencies": {
15
- "axios": "^0.26.1"
15
+ "axios": "^0.26.1",
16
+ "qs": "^6.10.1"
16
17
  },
17
18
  "devDependencies": {
18
19
  "axios-mock-adapter": "^1.20.0"
19
20
  },
20
- "gitHead": "9ec196c514d958d2c32c0879def6b98f24bf92fc"
21
+ "gitHead": "838f4f18dcd9ed4fe2ae2660a4918e2a5bd3a869"
21
22
  }
package/src/APIClient.ts CHANGED
@@ -22,42 +22,100 @@ export interface IResource {
22
22
  [key: string]: (params?: ActionParams) => Promise<any>;
23
23
  }
24
24
 
25
- class Auth {
25
+ export class Auth {
26
26
  protected api: APIClient;
27
- protected token: string;
28
- protected role: string;
27
+
28
+ protected options = {
29
+ token: null,
30
+ locale: null,
31
+ role: null,
32
+ };
29
33
 
30
34
  constructor(api: APIClient) {
31
35
  this.api = api;
32
- this.api.axios.interceptors.request.use((config) => {
33
- config.headers['X-Hostname'] = window.location.hostname;
34
- if (this.role) {
35
- config.headers['X-Role'] = this.role;
36
- }
37
- if (this.token) {
38
- config.headers['Authorization'] = `Bearer ${this.token}`;
39
- }
40
- return config;
41
- });
36
+ this.locale = this.getLocale();
37
+ this.role = this.getRole();
38
+ this.token = this.getToken();
39
+ this.api.axios.interceptors.request.use(this.middleware.bind(this));
40
+ }
41
+
42
+ get locale() {
43
+ return this.getLocale();
44
+ }
45
+
46
+ get role() {
47
+ return this.getRole();
48
+ }
49
+
50
+ get token() {
51
+ return this.getToken();
52
+ }
53
+
54
+ set locale(value) {
55
+ this.setLocale(value);
56
+ }
57
+
58
+ set role(value) {
59
+ this.setRole(value);
60
+ }
61
+
62
+ set token(value) {
63
+ this.setToken(value);
64
+ }
65
+
66
+ middleware(config: AxiosRequestConfig) {
67
+ if (this.locale) {
68
+ config.headers['X-Locale'] = this.locale;
69
+ }
70
+ if (this.role) {
71
+ config.headers['X-Role'] = this.role;
72
+ }
73
+ if (this.token) {
74
+ config.headers['Authorization'] = `Bearer ${this.token}`;
75
+ }
76
+ return config;
77
+ }
78
+
79
+ getLocale() {
80
+ return this.api.storage.getItem('NOCOBASE_LOCALE');
81
+ }
82
+
83
+ setLocale(locale: string) {
84
+ this.options.locale = locale;
85
+ this.api.storage.setItem('NOCOBASE_LOCALE', locale || '');
86
+ }
87
+
88
+ getToken() {
89
+ return this.api.storage.getItem('NOCOBASE_TOKEN');
42
90
  }
43
91
 
44
92
  setToken(token: string) {
45
- this.token = token;
93
+ this.options.token = token;
94
+ this.api.storage.setItem('NOCOBASE_TOKEN', token || '');
95
+ if (!token) {
96
+ this.setRole(null);
97
+ this.setLocale(null);
98
+ }
99
+ }
100
+
101
+ getRole() {
102
+ return this.api.storage.getItem('NOCOBASE_ROLE');
46
103
  }
47
104
 
48
105
  setRole(role: string) {
49
- this.role = role;
106
+ this.options.role = role;
107
+ this.api.storage.setItem('NOCOBASE_ROLE', role || '');
50
108
  }
51
109
 
52
- async signIn(values) {
110
+ async signIn(values): Promise<AxiosResponse<any>> {
53
111
  const response = await this.api.request({
54
112
  method: 'post',
55
113
  url: 'users:signin',
56
114
  data: values,
57
115
  });
58
116
  const data = response?.data?.data;
59
- this.token = data;
60
- return data;
117
+ this.setToken(data?.token);
118
+ return response;
61
119
  }
62
120
 
63
121
  async signOut() {
@@ -65,25 +123,78 @@ class Auth {
65
123
  method: 'post',
66
124
  url: 'users:signout',
67
125
  });
68
- this.token = null;
126
+ this.setToken(null);
127
+ }
128
+ }
129
+
130
+ export abstract class Storage {
131
+ abstract clear(): void;
132
+ abstract getItem(key: string): string | null;
133
+ abstract removeItem(key: string): void;
134
+ abstract setItem(key: string, value: string): void;
135
+ }
136
+
137
+ export class MemoryStorage extends Storage {
138
+ items = new Map();
139
+
140
+ clear() {
141
+ this.items.clear();
142
+ }
143
+
144
+ getItem(key: string) {
145
+ return this.items.get(key);
146
+ }
147
+
148
+ setItem(key: string, value: string) {
149
+ return this.items.set(key, value);
150
+ }
151
+
152
+ removeItem(key: string) {
153
+ return this.items.delete(key);
69
154
  }
70
155
  }
71
156
 
157
+ interface ExtendedOptions {
158
+ authClass?: any;
159
+ storageClass?: any;
160
+ }
161
+
72
162
  export class APIClient {
73
163
  axios: AxiosInstance;
74
164
  auth: Auth;
165
+ storage: Storage;
75
166
 
76
- constructor(instance?: AxiosInstance | AxiosRequestConfig) {
167
+ constructor(instance?: AxiosInstance | (AxiosRequestConfig & ExtendedOptions)) {
77
168
  if (typeof instance === 'function') {
78
169
  this.axios = instance;
79
170
  } else {
80
- this.axios = axios.create(instance);
171
+ const { authClass, storageClass, ...others } = instance || {};
172
+ this.axios = axios.create(others);
173
+ this.initStorage(storageClass);
174
+ if (authClass) {
175
+ this.auth = new authClass(this);
176
+ }
177
+ }
178
+ if (!this.storage) {
179
+ this.initStorage();
180
+ }
181
+ if (!this.auth) {
182
+ this.auth = new Auth(this);
183
+ }
184
+ this.paramsSerializer();
185
+ }
186
+
187
+ private initStorage(storage?: any) {
188
+ if (storage) {
189
+ this.storage = new storage(this);
190
+ } else if (localStorage) {
191
+ this.storage = localStorage;
192
+ } else {
193
+ this.storage = new MemoryStorage();
81
194
  }
82
- this.auth = new Auth(this);
83
- this.qsMiddleware();
84
195
  }
85
196
 
86
- qsMiddleware() {
197
+ paramsSerializer() {
87
198
  this.axios.interceptors.request.use((config) => {
88
199
  config.paramsSerializer = (params) => {
89
200
  return qs.stringify(params, {
@@ -0,0 +1,116 @@
1
+ import { AxiosResponse } from 'axios';
2
+ import MockAdapter from 'axios-mock-adapter';
3
+ import { APIClient, Storage } from '../';
4
+ import { Auth } from '../APIClient';
5
+
6
+ describe('api-client', () => {
7
+ test('instance', async () => {
8
+ const api = new APIClient({
9
+ baseURL: 'https://localhost:8000/api',
10
+ });
11
+ const mock = new MockAdapter(api.axios);
12
+ mock.onGet('users:get').reply(200, {
13
+ data: { id: 1, name: 'John Smith' },
14
+ });
15
+ const response = await api.request({ url: 'users:get' });
16
+ expect(response.status).toBe(200);
17
+ expect(response.data).toMatchObject({
18
+ data: { id: 1, name: 'John Smith' },
19
+ });
20
+ });
21
+
22
+ test('signIn', async () => {
23
+ const api = new APIClient({
24
+ baseURL: 'https://localhost:8000/api',
25
+ });
26
+ const mock = new MockAdapter(api.axios);
27
+ mock.onPost('users:signin').reply(200, {
28
+ data: { id: 1, name: 'John Smith', token: '123' },
29
+ });
30
+ const response = await api.auth.signIn({});
31
+ expect(response.status).toBe(200);
32
+ expect(api.auth.token).toBe('123');
33
+ expect(localStorage.getItem('NOCOBASE_TOKEN')).toBe('123');
34
+ });
35
+
36
+ test('resource action', async () => {
37
+ const api = new APIClient({
38
+ baseURL: 'https://localhost:8000/api',
39
+ });
40
+ const mock = new MockAdapter(api.axios);
41
+ mock.onPost('users:test').reply(200, {
42
+ data: { id: 1, name: 'John Smith', token: '123' },
43
+ });
44
+ const response = await api.resource('users').test();
45
+ expect(response.status).toBe(200);
46
+ expect(response.data).toMatchObject({
47
+ data: { id: 1, name: 'John Smith', token: '123' },
48
+ });
49
+ });
50
+
51
+ test('custom storage', async () => {
52
+ const items = new Map();
53
+
54
+ class TestStorage extends Storage {
55
+ clear() {
56
+ items.clear();
57
+ }
58
+ getItem(key: string) {
59
+ return items.get(key);
60
+ }
61
+ setItem(key: string, value: string) {
62
+ return items.set(key, value);
63
+ }
64
+ removeItem(key: string) {
65
+ return items.delete(key);
66
+ }
67
+ }
68
+
69
+ const api = new APIClient({
70
+ baseURL: 'https://localhost:8000/api',
71
+ storageClass: TestStorage,
72
+ });
73
+
74
+ const mock = new MockAdapter(api.axios);
75
+ mock.onPost('users:signin').reply(200, {
76
+ data: { id: 1, name: 'John Smith', token: '123' },
77
+ });
78
+
79
+ const response = await api.auth.signIn({});
80
+ expect(response.status).toBe(200);
81
+ expect(api.auth.token).toBe('123');
82
+ expect(items.get('NOCOBASE_TOKEN')).toBe('123');
83
+ });
84
+
85
+ test('custom auth', async () => {
86
+ class TestAuth extends Auth {
87
+ async signIn(values: any): Promise<AxiosResponse<any, any>> {
88
+ const response = await this.api.request({
89
+ method: 'post',
90
+ url: 'users:test',
91
+ data: values,
92
+ });
93
+ const data = response?.data?.data;
94
+ this.setToken(data?.token);
95
+ return response;
96
+ }
97
+ }
98
+
99
+ const api = new APIClient({
100
+ baseURL: 'https://localhost:8000/api',
101
+ authClass: TestAuth,
102
+ });
103
+
104
+ expect(api.auth).toBeInstanceOf(TestAuth);
105
+
106
+ const mock = new MockAdapter(api.axios);
107
+ mock.onPost('users:test').reply(200, {
108
+ data: { id: 1, name: 'John Smith', token: '123' },
109
+ });
110
+
111
+ const response = await api.auth.signIn({});
112
+ expect(response.status).toBe(200);
113
+ expect(api.auth.token).toBe('123');
114
+ expect(localStorage.getItem('NOCOBASE_TOKEN')).toBe('123');
115
+ });
116
+ });