@opengeoweb/api 4.10.0

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/index.esm.js ADDED
@@ -0,0 +1,544 @@
1
+ import * as React from 'react';
2
+ import axios from 'axios';
3
+ import { useIsMounted } from '@opengeoweb/shared';
4
+
5
+ function _slicedToArray(arr, i) {
6
+ return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
7
+ }
8
+
9
+ function _arrayWithHoles(arr) {
10
+ if (Array.isArray(arr)) return arr;
11
+ }
12
+
13
+ function _iterableToArrayLimit(arr, i) {
14
+ if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
15
+ var _arr = [];
16
+ var _n = true;
17
+ var _d = false;
18
+ var _e = undefined;
19
+
20
+ try {
21
+ for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
22
+ _arr.push(_s.value);
23
+
24
+ if (i && _arr.length === i) break;
25
+ }
26
+ } catch (err) {
27
+ _d = true;
28
+ _e = err;
29
+ } finally {
30
+ try {
31
+ if (!_n && _i["return"] != null) _i["return"]();
32
+ } finally {
33
+ if (_d) throw _e;
34
+ }
35
+ }
36
+
37
+ return _arr;
38
+ }
39
+
40
+ function _unsupportedIterableToArray(o, minLen) {
41
+ if (!o) return;
42
+ if (typeof o === "string") return _arrayLikeToArray(o, minLen);
43
+ var n = Object.prototype.toString.call(o).slice(8, -1);
44
+ if (n === "Object" && o.constructor) n = o.constructor.name;
45
+ if (n === "Map" || n === "Set") return Array.from(o);
46
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
47
+ }
48
+
49
+ function _arrayLikeToArray(arr, len) {
50
+ if (len == null || len > arr.length) len = arr.length;
51
+
52
+ for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
53
+
54
+ return arr2;
55
+ }
56
+
57
+ function _nonIterableRest() {
58
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
59
+ }
60
+
61
+ /*
62
+ Accepts a value and timeout and will debounce
63
+
64
+ @param {string} value: value of element
65
+ @param {timeout} number: timer
66
+ @return {value: string}
67
+
68
+ @example:
69
+ const debouncedName = useDebounce('testing', 2000)
70
+ */
71
+
72
+ var useDebounce = function useDebounce(value, timeout) {
73
+ var _React$useState = React.useState(value),
74
+ _React$useState2 = _slicedToArray(_React$useState, 2),
75
+ state = _React$useState2[0],
76
+ setState = _React$useState2[1];
77
+
78
+ React.useEffect(function () {
79
+ var handler = setTimeout(function () {
80
+ return setState(value);
81
+ }, timeout);
82
+ return function () {
83
+ return clearTimeout(handler);
84
+ };
85
+ }, [value, timeout]);
86
+ return state;
87
+ };
88
+
89
+ /*! *****************************************************************************
90
+ Copyright (c) Microsoft Corporation.
91
+
92
+ Permission to use, copy, modify, and/or distribute this software for any
93
+ purpose with or without fee is hereby granted.
94
+
95
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
96
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
97
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
98
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
99
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
100
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
101
+ PERFORMANCE OF THIS SOFTWARE.
102
+ ***************************************************************************** */
103
+
104
+ function __rest(s, e) {
105
+ var t = {};
106
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
107
+ t[p] = s[p];
108
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
109
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
110
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
111
+ t[p[i]] = s[p[i]];
112
+ }
113
+ return t;
114
+ }
115
+
116
+ function __awaiter(thisArg, _arguments, P, generator) {
117
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
118
+ return new (P || (P = Promise))(function (resolve, reject) {
119
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
120
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
121
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
122
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
123
+ });
124
+ }
125
+
126
+ var generateRandomId = function generateRandomId() {
127
+ return "-".concat(Math.random().toString(36).substr(2, 9));
128
+ }; // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
129
+
130
+
131
+ var useApi = function useApi(apiCall) {
132
+ var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
133
+
134
+ var _useIsMounted = useIsMounted(),
135
+ isMounted = _useIsMounted.isMounted;
136
+
137
+ var _React$useState = React.useState(generateRandomId()),
138
+ _React$useState2 = _slicedToArray(_React$useState, 1),
139
+ id = _React$useState2[0];
140
+
141
+ var _React$useState3 = React.useState(true),
142
+ _React$useState4 = _slicedToArray(_React$useState3, 2),
143
+ isLoading = _React$useState4[0],
144
+ setIsloading = _React$useState4[1];
145
+
146
+ var _React$useState5 = React.useState(null),
147
+ _React$useState6 = _slicedToArray(_React$useState5, 2),
148
+ error = _React$useState6[0],
149
+ setError = _React$useState6[1];
150
+
151
+ var _React$useState7 = React.useState(null),
152
+ _React$useState8 = _slicedToArray(_React$useState7, 2),
153
+ result = _React$useState8[0],
154
+ setResult = _React$useState8[1];
155
+
156
+ var debouncedParams = useDebounce(JSON.stringify(params), 300);
157
+
158
+ var fetchApiData = function fetchApiData() {
159
+ var _params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
160
+
161
+ return __awaiter(void 0, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
162
+ var response;
163
+ return regeneratorRuntime.wrap(function _callee$(_context) {
164
+ while (1) {
165
+ switch (_context.prev = _context.next) {
166
+ case 0:
167
+ _context.prev = 0;
168
+ setIsloading(true);
169
+ setError(null);
170
+ _context.next = 5;
171
+ return apiCall(_params, id);
172
+
173
+ case 5:
174
+ response = _context.sent;
175
+
176
+ if (isMounted.current) {
177
+ setResult(Array.isArray(response) ? response.map(function (d) {
178
+ return d.data;
179
+ }) : response.data);
180
+ setIsloading(false);
181
+ setError(null);
182
+ }
183
+
184
+ _context.next = 12;
185
+ break;
186
+
187
+ case 9:
188
+ _context.prev = 9;
189
+ _context.t0 = _context["catch"](0);
190
+
191
+ if (isMounted.current) {
192
+ if (axios.isCancel(_context.t0)) {
193
+ setIsloading(false);
194
+ } else {
195
+ setError(_context.t0);
196
+ setIsloading(false);
197
+ }
198
+ }
199
+
200
+ case 12:
201
+ case "end":
202
+ return _context.stop();
203
+ }
204
+ }
205
+ }, _callee, null, [[0, 9]]);
206
+ }));
207
+ };
208
+
209
+ React.useEffect(function () {
210
+ fetchApiData(params);
211
+ }, // eslint-disable-next-line react-hooks/exhaustive-deps
212
+ [debouncedParams]);
213
+
214
+ var clearResults = function clearResults() {
215
+ setIsloading(true);
216
+ setResult(null);
217
+ };
218
+
219
+ return {
220
+ isLoading: isLoading,
221
+ error: error,
222
+ result: result,
223
+ clearResults: clearResults,
224
+ fetchApiData: fetchApiData
225
+ };
226
+ };
227
+
228
+ var ApiContext = /*#__PURE__*/React.createContext({
229
+ api: null
230
+ });
231
+ var registeredApis = new Map();
232
+
233
+ function registerApi(name, api) {
234
+ registeredApis.set(name, api);
235
+ }
236
+
237
+ function unRegisterApi(name) {
238
+ registeredApis["delete"](name);
239
+ }
240
+
241
+ function getApi(name) {
242
+ return registeredApis.get(name);
243
+ }
244
+ var ApiProvider = function ApiProvider(_a) {
245
+ var children = _a.children,
246
+ createApi = _a.createApi,
247
+ name = _a.name,
248
+ apiModuleProps = __rest(_a, ["children", "createApi", "name"]);
249
+
250
+ var handleNewApi = React.useCallback(function () {
251
+ var newApi = createApi(apiModuleProps);
252
+
253
+ if (name) {
254
+ registerApi(name, newApi);
255
+ }
256
+
257
+ return newApi; // eslint-disable-next-line react-hooks/exhaustive-deps
258
+ }, [createApi, name]);
259
+
260
+ var _React$useState = React.useState(handleNewApi),
261
+ _React$useState2 = _slicedToArray(_React$useState, 2),
262
+ api = _React$useState2[0],
263
+ setApi = _React$useState2[1];
264
+
265
+ React.useEffect(function () {
266
+ setApi(handleNewApi);
267
+ return function () {
268
+ if (name) {
269
+ unRegisterApi(name);
270
+ }
271
+ };
272
+ }, [handleNewApi, name]);
273
+ return /*#__PURE__*/React.createElement(ApiContext.Provider, {
274
+ value: {
275
+ api: api
276
+ }
277
+ }, children);
278
+ };
279
+ function useApiContext() {
280
+ return React.useContext(ApiContext);
281
+ }
282
+
283
+ var DEFAULT_TIMEOUT = 15000;
284
+ var REFRESH_TOKEN_WHEN_PCT_EXPIRED = 75; // Refresh token when 75% expired. Set to (10 / 3600) * 100 = 0.2777778% to test with 10 second interval.
285
+
286
+ var DEFAULT_TOKEN_EXPIRES_IN = 3600; // Number of seconds a token expires by default
287
+
288
+ var MILLISECOND_TO_SECOND = 1 / 1000;
289
+ /**
290
+ * Creates a Credentials object based on the axios response from the token service.
291
+ *
292
+ * It will calculate the expires_at attribute based on the expires_in property found in the JWT.
293
+ *
294
+ * @param tokenResponse Response of the tokenservice as axios response object.
295
+ * @returns Credentials object.
296
+ */
297
+
298
+ var makeCredentialsFromTokenResponse = function makeCredentialsFromTokenResponse(tokenResponse) {
299
+ var token = tokenResponse.data.body || tokenResponse.data; // eslint-disable-next-line @typescript-eslint/naming-convention
300
+
301
+ var access_token = token.access_token,
302
+ refresh_token = token.refresh_token,
303
+ id_token = token.id_token,
304
+ expires_in = token.expires_in;
305
+
306
+ if (!access_token || !id_token) {
307
+ throw new Error('Login failed');
308
+ }
309
+
310
+ var userInfoString = atob(id_token.split('.')[1]);
311
+ var userInfo = JSON.parse(userInfoString);
312
+ var tokenExpirationInSeconds = expires_in && expires_in > 0 ? expires_in : DEFAULT_TOKEN_EXPIRES_IN; // If not set or zero in the token, assume valid for 1 hour.
313
+
314
+ var pctTokenExpirationInSeconds = tokenExpirationInSeconds * (REFRESH_TOKEN_WHEN_PCT_EXPIRED / 100);
315
+ var epochTimeTokenExpirationInSeconds = pctTokenExpirationInSeconds + Date.now() * MILLISECOND_TO_SECOND;
316
+ var isAuthCognito = userInfo.iss.includes('cognito');
317
+ var newAuth = {
318
+ username: isAuthCognito ? userInfo['cognito:username'] : userInfo.email,
319
+ token: access_token,
320
+ refresh_token: refresh_token || '',
321
+ expires_at: epochTimeTokenExpirationInSeconds
322
+ };
323
+ return newAuth;
324
+ };
325
+ var createApiInstance = function createApiInstance(_ref) {
326
+ var auth = _ref.auth,
327
+ onSetAuth = _ref.onSetAuth,
328
+ _ref$config = _ref.config;
329
+ _ref$config = _ref$config === void 0 ? {} : _ref$config;
330
+ var baseURL = _ref$config.baseURL,
331
+ appURL = _ref$config.appURL,
332
+ authTokenURL = _ref$config.authTokenURL,
333
+ authClientId = _ref$config.authClientId,
334
+ _ref$timeout = _ref.timeout,
335
+ timeout = _ref$timeout === void 0 ? DEFAULT_TIMEOUT : _ref$timeout;
336
+ var axiosInstance = axios.create({
337
+ baseURL: baseURL,
338
+ headers: {},
339
+ timeout: timeout
340
+ });
341
+
342
+ var refreshAccessToken = function refreshAccessToken() {
343
+ // Refresh token request with a new axios instance
344
+ // without request interceptor
345
+ var tokenAxiosInstance = axios.create({
346
+ headers: {},
347
+ timeout: timeout
348
+ });
349
+ var refreshPayload = {
350
+ refresh_token: auth.refresh_token,
351
+ redirect_uri: "".concat(appURL, "/code"),
352
+ grant_type: 'refresh_token',
353
+ client_id: authClientId
354
+ };
355
+ /* Send data in the "application/x-www-form-urlencoded" format.
356
+ If only JSON is supported, use Axios' default content type ("application/x-www-form-urlencoded"). */
357
+
358
+ var useDefaultContentType = authTokenURL.includes('amazonaws.com');
359
+ var data = useDefaultContentType ? refreshPayload : new URLSearchParams(refreshPayload);
360
+ var config = {
361
+ headers: {
362
+ 'Content-Type': useDefaultContentType ? 'application/json' : 'application/x-www-form-urlencoded'
363
+ }
364
+ };
365
+ return tokenAxiosInstance.post(authTokenURL, data, config);
366
+ }; // Request interceptor for API calls done BEFORE the request is made.
367
+
368
+
369
+ axiosInstance.interceptors.request.use(function (config) {
370
+ return __awaiter(void 0, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
371
+ var timeInSecondsLeftBeforeExpiration, refreshedToken, newAuth, newConfig;
372
+ return regeneratorRuntime.wrap(function _callee$(_context) {
373
+ while (1) {
374
+ switch (_context.prev = _context.next) {
375
+ case 0:
376
+ timeInSecondsLeftBeforeExpiration = auth && auth.expires_at ? auth.expires_at - Date.now() * MILLISECOND_TO_SECOND : 0; // If expires_at is not set, don't do anything. (set timeInSecondsLeftBeforeExpiration = 0 will skip refresh)
377
+
378
+ if (!(timeInSecondsLeftBeforeExpiration < 0)) {
379
+ _context.next = 9;
380
+ break;
381
+ }
382
+
383
+ _context.next = 4;
384
+ return refreshAccessToken();
385
+
386
+ case 4:
387
+ refreshedToken = _context.sent;
388
+ newAuth = makeCredentialsFromTokenResponse(refreshedToken);
389
+ /*
390
+ Note: Should not use the spread operator here on the auth object to create a new object.
391
+ Creating a new object and setting that via onSetAuth might change the auth object too late.
392
+ Instead assign the new token directly to the property and then use the onSetAuth.
393
+ */
394
+ // eslint-disable-next-line no-param-reassign
395
+
396
+ auth.token = newAuth.token; // eslint-disable-next-line no-param-reassign
397
+
398
+ auth.expires_at = newAuth.expires_at;
399
+ onSetAuth(auth);
400
+
401
+ case 9:
402
+ newConfig = Object.assign(Object.assign({}, config), {
403
+ headers: Object.assign({
404
+ 'Content-Type': 'application/json',
405
+ Authorization: "Bearer ".concat(auth.token),
406
+ Accept: 'application/json'
407
+ }, config.headers)
408
+ });
409
+ return _context.abrupt("return", newConfig);
410
+
411
+ case 11:
412
+ case "end":
413
+ return _context.stop();
414
+ }
415
+ }
416
+ }, _callee);
417
+ }));
418
+ }, function (error) {
419
+ Promise.reject(error);
420
+ }); // Response interceptor for API calls done AFTER the request is made.
421
+
422
+ axiosInstance.interceptors.response.use(function (response) {
423
+ return response;
424
+ }, function (error) {
425
+ return __awaiter(void 0, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee2() {
426
+ var originalRequest, refreshedToken, newAuth;
427
+ return regeneratorRuntime.wrap(function _callee2$(_context2) {
428
+ while (1) {
429
+ switch (_context2.prev = _context2.next) {
430
+ case 0:
431
+ originalRequest = error.config;
432
+
433
+ if (!(error.response && error.response.status && (error.response.status === 401 || error.response.status === 403) && !originalRequest.inRetry)) {
434
+ _context2.next = 10;
435
+ break;
436
+ }
437
+
438
+ originalRequest.inRetry = true;
439
+ _context2.next = 5;
440
+ return refreshAccessToken();
441
+
442
+ case 5:
443
+ refreshedToken = _context2.sent;
444
+ newAuth = makeCredentialsFromTokenResponse(refreshedToken);
445
+ /*
446
+ Note: Should not use the spread operator here on the auth object to create a new object.
447
+ Creating a new object and setting that via onSetAuth might change the auth object too late.
448
+ Instead assign the new token directly to the property and then use the onSetAuth.
449
+ */
450
+ // eslint-disable-next-line no-param-reassign
451
+
452
+ auth.token = newAuth.token;
453
+ onSetAuth(auth);
454
+ return _context2.abrupt("return", axiosInstance(originalRequest));
455
+
456
+ case 10:
457
+ return _context2.abrupt("return", Promise.reject(error));
458
+
459
+ case 11:
460
+ case "end":
461
+ return _context2.stop();
462
+ }
463
+ }
464
+ }, _callee2);
465
+ }));
466
+ });
467
+ return axiosInstance;
468
+ };
469
+ var createNonAuthApiInstance = function createNonAuthApiInstance(_ref2) {
470
+ var _ref2$config = _ref2.config;
471
+ _ref2$config = _ref2$config === void 0 ? {} : _ref2$config;
472
+ var baseURL = _ref2$config.baseURL,
473
+ _ref2$timeout = _ref2.timeout,
474
+ timeout = _ref2$timeout === void 0 ? DEFAULT_TIMEOUT : _ref2$timeout;
475
+ var axiosInstance = axios.create({
476
+ baseURL: baseURL,
477
+ headers: {},
478
+ timeout: timeout
479
+ }); // Request interceptor for API calls
480
+
481
+ axiosInstance.interceptors.request.use(function (config) {
482
+ return __awaiter(void 0, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee3() {
483
+ var newConfig;
484
+ return regeneratorRuntime.wrap(function _callee3$(_context3) {
485
+ while (1) {
486
+ switch (_context3.prev = _context3.next) {
487
+ case 0:
488
+ newConfig = Object.assign(Object.assign({}, config), {
489
+ headers: Object.assign({
490
+ 'Content-Type': 'application/json',
491
+ Accept: 'application/json'
492
+ }, config.headers)
493
+ });
494
+ return _context3.abrupt("return", newConfig);
495
+
496
+ case 2:
497
+ case "end":
498
+ return _context3.stop();
499
+ }
500
+ }
501
+ }, _callee3);
502
+ }));
503
+ }, function (error) {
504
+ Promise.reject(error);
505
+ });
506
+ return axiosInstance;
507
+ };
508
+ var fakeApiRequest = function fakeApiRequest(signal) {
509
+ return new Promise(function (resolve, reject) {
510
+ var timer = setTimeout(function () {
511
+ resolve();
512
+ }, 300);
513
+ signal === null || signal === void 0 ? void 0 : signal.signal.addEventListener('abort', function () {
514
+ clearTimeout(timer);
515
+ reject(new Error('canceled'));
516
+ });
517
+ });
518
+ };
519
+ var createFakeApiInstance = function createFakeApiInstance() {
520
+ return {
521
+ // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars,
522
+ get: function get(_url, _params) {
523
+ return fakeApiRequest();
524
+ },
525
+ // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars,
526
+ put: function put(_url, _params) {
527
+ return fakeApiRequest();
528
+ },
529
+ // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars,
530
+ post: function post(_url, _params) {
531
+ return fakeApiRequest();
532
+ },
533
+ // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
534
+ "delete": function _delete(_url, _params) {
535
+ return fakeApiRequest();
536
+ },
537
+ // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars, @typescript-eslint/explicit-module-boundary-types
538
+ patch: function patch(_url, _params, _signal) {
539
+ return fakeApiRequest(_signal);
540
+ }
541
+ };
542
+ };
543
+
544
+ export { ApiProvider, MILLISECOND_TO_SECOND, REFRESH_TOKEN_WHEN_PCT_EXPIRED, createApiInstance, createFakeApiInstance, createNonAuthApiInstance, fakeApiRequest, getApi, makeCredentialsFromTokenResponse, useApi, useApiContext, useDebounce };