@bigbinary/neeto-commons-frontend 2.0.0 → 2.0.3

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/initializers.js CHANGED
@@ -1,23 +1,19 @@
1
- 'use strict';
1
+ import { curry, isNil, values, evolve, omit, modify, either, isEmpty, mergeDeepLeft } from 'ramda';
2
+ import { Toastr } from '@bigbinary/neetoui';
3
+ import axios from 'axios';
4
+ import i18next from 'i18next';
5
+ import mixpanel from 'mixpanel-browser';
6
+ import { initReactI18next } from 'react-i18next';
2
7
 
3
- var objects = require('pure/objects');
4
- var neetoui = require('@bigbinary/neetoui');
5
- var axios = require('axios');
6
- var i18next = require('i18next');
7
- var strings = require('pure/strings');
8
- var ramda = require('ramda');
9
- var mixpanel = require('mixpanel-browser');
10
- var reactI18next = require('react-i18next');
11
-
12
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
13
-
14
- var axios__default = /*#__PURE__*/_interopDefaultLegacy(axios);
15
- var i18next__default = /*#__PURE__*/_interopDefaultLegacy(i18next);
16
- var mixpanel__default = /*#__PURE__*/_interopDefaultLegacy(mixpanel);
8
+ function _typeof(obj) {
9
+ "@babel/helpers - typeof";
17
10
 
18
- var _document$getElements, _document$getElements2;
19
- window.globalProps = objects.keysToCamelCase(JSON.parse(((_document$getElements = document.getElementsByClassName("root-container")[0]) === null || _document$getElements === void 0 ? void 0 : (_document$getElements2 = _document$getElements.dataset) === null || _document$getElements2 === void 0 ? void 0 : _document$getElements2.reactProps) || "{}"));
20
- objects.deepFreezeObject(window.globalProps);
11
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
12
+ return typeof obj;
13
+ } : function (obj) {
14
+ return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
15
+ }, _typeof(obj);
16
+ }
21
17
 
22
18
  function _arrayWithHoles(arr) {
23
19
  if (Array.isArray(arr)) return arr;
@@ -80,14 +76,86 @@ function _slicedToArray(arr, i) {
80
76
  return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
81
77
  }
82
78
 
83
- function _typeof(obj) {
84
- "@babel/helpers - typeof";
79
+ var snakeToCamelCase = function snakeToCamelCase(string) {
80
+ return string.replace(/(_\w)/g, function (letter) {
81
+ return letter[1].toUpperCase();
82
+ });
83
+ };
84
+ var camelToSnakeCase = function camelToSnakeCase(string) {
85
+ return string.replace(/[A-Z]/g, function (letter) {
86
+ return "_".concat(letter.toLowerCase());
87
+ });
88
+ };
85
89
 
86
- return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
87
- return typeof obj;
88
- } : function (obj) {
89
- return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
90
- }, _typeof(obj);
90
+ var transformObjectDeep = function transformObjectDeep(object, keyValueTransformer) {
91
+ if (Array.isArray(object)) {
92
+ return object.map(function (obj) {
93
+ return transformObjectDeep(obj, keyValueTransformer);
94
+ });
95
+ } else if (object === null || _typeof(object) !== "object") {
96
+ return object;
97
+ }
98
+
99
+ return Object.fromEntries(Object.entries(object).map(function (_ref) {
100
+ var _ref2 = _slicedToArray(_ref, 2),
101
+ key = _ref2[0],
102
+ value = _ref2[1];
103
+
104
+ return keyValueTransformer(key, transformObjectDeep(value, keyValueTransformer));
105
+ }));
106
+ };
107
+ var keysToCamelCase = function keysToCamelCase(object) {
108
+ return transformObjectDeep(object, function (key, value) {
109
+ return [snakeToCamelCase(key), value];
110
+ });
111
+ };
112
+ var serializeKeysToSnakeCase = function serializeKeysToSnakeCase(object) {
113
+ if (Array.isArray(object)) {
114
+ return object.map(serializeKeysToSnakeCase);
115
+ } else if (object === null || _typeof(object) !== "object") {
116
+ return object;
117
+ }
118
+
119
+ return Object.fromEntries(Object.entries(object).map(function (_ref3) {
120
+ var _ref4 = _slicedToArray(_ref3, 2),
121
+ key = _ref4[0],
122
+ value = _ref4[1];
123
+
124
+ var val = typeof (value === null || value === void 0 ? void 0 : value.toJSON) === "function" ? value.toJSON() : value;
125
+ return [camelToSnakeCase(key), serializeKeysToSnakeCase(val)];
126
+ }));
127
+ };
128
+ var deepFreezeObject = function deepFreezeObject(object) {
129
+ if (object && _typeof(object) === "object" && !Object.isFrozen(object)) {
130
+ Object.keys(object).forEach(function (property) {
131
+ return deepFreezeObject(object[property]);
132
+ });
133
+ Object.freeze(object);
134
+ }
135
+
136
+ return object;
137
+ };
138
+ var matches = curry(function (pattern, object) {
139
+ var __parent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : object;
140
+
141
+ if (object === pattern) return true;
142
+ if (typeof pattern === "function" && pattern(object, __parent)) return true;
143
+ if (isNil(pattern) || isNil(object)) return false;
144
+ if (_typeof(pattern) !== "object") return false;
145
+ return Object.entries(pattern).every(function (_ref5) {
146
+ var _ref6 = _slicedToArray(_ref5, 2),
147
+ key = _ref6[0],
148
+ value = _ref6[1];
149
+
150
+ return matches(value, object[key], __parent);
151
+ });
152
+ });
153
+
154
+ function initializeGlobalProps() {
155
+ var _document$getElements, _document$getElements2;
156
+
157
+ window.globalProps = keysToCamelCase(JSON.parse(((_document$getElements = document.getElementsByClassName("root-container")[0]) === null || _document$getElements === void 0 ? void 0 : (_document$getElements2 = _document$getElements.dataset) === null || _document$getElements2 === void 0 ? void 0 : _document$getElements2.reactProps) || "{}"));
158
+ deepFreezeObject(window.globalProps);
91
159
  }
92
160
 
93
161
  function _defineProperty(obj, key, value) {
@@ -112,21 +180,19 @@ var HEADERS_KEYS = {
112
180
  };
113
181
 
114
182
  var resetAuthTokens = function resetAuthTokens() {
115
- ramda.values(HEADERS_KEYS).forEach(function (header) {
116
- delete axios__default["default"].defaults.headers[header];
183
+ values(HEADERS_KEYS).forEach(function (header) {
184
+ delete axios.defaults.headers[header];
117
185
  });
118
186
  };
119
187
 
120
- var setAxiosDefaults = function setAxiosDefaults() {
121
- axios__default["default"].defaults.baseURL = "/";
122
- setAuthHeaders();
123
- registerIntercepts();
188
+ var shouldNot = function shouldNot(skip) {
189
+ return _typeof(skip) === "object" || !skip;
124
190
  };
125
191
 
126
192
  var setAuthHeaders = function setAuthHeaders() {
127
193
  var _globalProps$user, _globalProps$user2;
128
194
 
129
- axios__default["default"].defaults.headers = _defineProperty({
195
+ axios.defaults.headers = _defineProperty({
130
196
  Accept: "application/json",
131
197
  "Content-Type": "application/json"
132
198
  }, HEADERS_KEYS.xCsrfToken, document.querySelector('[name="csrf-token"]').getAttribute("content"));
@@ -134,123 +200,157 @@ var setAuthHeaders = function setAuthHeaders() {
134
200
  var email = (_globalProps$user2 = globalProps.user) === null || _globalProps$user2 === void 0 ? void 0 : _globalProps$user2.email;
135
201
 
136
202
  if (token && email) {
137
- axios__default["default"].defaults.headers[HEADERS_KEYS.xAuthEmail] = email;
138
- axios__default["default"].defaults.headers[HEADERS_KEYS.xAuthToken] = token;
203
+ axios.defaults.headers[HEADERS_KEYS.xAuthEmail] = email;
204
+ axios.defaults.headers[HEADERS_KEYS.xAuthToken] = token;
139
205
  }
206
+ }; // pipe function from ramda doesn't accept array of functions.
207
+ // We can't use spread operator too. So this is a workaround.
208
+
209
+
210
+ var createPipe = function createPipe(functions) {
211
+ return function (data) {
212
+ return functions.reduce(function (acc, fn) {
213
+ return fn(acc);
214
+ }, data);
215
+ };
140
216
  };
141
217
 
142
- var handleSuccessResponse = function handleSuccessResponse(response) {
143
- var _response$config = response.config,
144
- _response$config$tran = _response$config.transformResponseCase,
145
- transformResponseCase = _response$config$tran === void 0 ? true : _response$config$tran,
146
- _response$config$incl = _response$config.includeMetadataInResponse,
147
- includeMetadataInResponse = _response$config$incl === void 0 ? false : _response$config$incl,
148
- _response$config$show = _response$config.showToastr,
149
- showToastr = _response$config$show === void 0 ? true : _response$config$show;
218
+ var transformKeysToCamelCase = function transformKeysToCamelCase(response) {
219
+ var _response$config$tran = response.config.transformResponseCase,
220
+ transformResponseCase = _response$config$tran === void 0 ? true : _response$config$tran;
150
221
 
151
- if (response.data) {
152
- if (transformResponseCase) response.data = objects.keysToCamelCase(response.data);
222
+ if (response.data && transformResponseCase) {
223
+ response.data = keysToCamelCase(response.data);
224
+ }
153
225
 
154
- if (showToastr && typeof response.data.notice === "string") {
155
- neetoui.Toastr.success(response.data.notice);
156
- }
226
+ return response;
227
+ };
228
+
229
+ var showSuccessToastr = function showSuccessToastr(response) {
230
+ var _response$config$show = response.config.showToastr,
231
+ showToastr = _response$config$show === void 0 ? true : _response$config$show;
232
+
233
+ if (showToastr && typeof response.data.notice === "string") {
234
+ Toastr.success(response.data.notice);
157
235
  }
158
236
 
237
+ return response;
238
+ };
239
+
240
+ var pullDataFromResponse = function pullDataFromResponse(response) {
241
+ var _response$config$incl = response.config.includeMetadataInResponse,
242
+ includeMetadataInResponse = _response$config$incl === void 0 ? false : _response$config$incl;
159
243
  return includeMetadataInResponse ? response : response.data;
160
244
  };
161
245
 
162
- var handleUnauthorizedErrorResponse = function handleUnauthorizedErrorResponse() {
246
+ var buildSuccessResponseHandler = function buildSuccessResponseHandler(skip) {
247
+ var interceptors = [];
248
+ if (!(skip !== null && skip !== void 0 && skip.transformCase)) interceptors.push(transformKeysToCamelCase);
249
+ if (!(skip !== null && skip !== void 0 && skip.showToastr)) interceptors.push(showSuccessToastr);
250
+ if (!(skip !== null && skip !== void 0 && skip.pullDataFromResponse)) interceptors.push(pullDataFromResponse);
251
+ return createPipe(interceptors);
252
+ };
253
+
254
+ var handleUnauthorizedErrorResponse = function handleUnauthorizedErrorResponse(error) {
163
255
  resetAuthTokens();
164
256
  setTimeout(function () {
165
257
  var redirectTo = window.location.pathname === "/login" ? "/login" : "/login?redirect_uri=".concat(encodeURIComponent(window.location.href));
166
258
  window.location.href = redirectTo;
167
259
  }, 300);
260
+ return error;
168
261
  };
169
262
 
170
263
  var showErrorToastr = function showErrorToastr(error) {
171
- if (axios__default["default"].isCancel(error)) {
172
- neetoui.Toastr.error(i18next__default["default"].t("neetoCommons.toastr.error.requestCanceled"));
264
+ if (axios.isCancel(error)) {
265
+ Toastr.error(i18next.t("neetoCommons.toastr.error.requestCanceled"));
173
266
  } else if (error.message === "Network Error") {
174
- neetoui.Toastr.error(i18next__default["default"].t("neetoCommons.toastr.error.networkError"));
267
+ Toastr.error(i18next.t("neetoCommons.toastr.error.networkError"));
175
268
  } else {
176
- neetoui.Toastr.error(error);
269
+ Toastr.error(error);
177
270
  }
178
- };
179
271
 
180
- var handleErrorResponse = function handleErrorResponse(error) {
181
- var _error$response, _error$response2;
272
+ return error;
273
+ };
182
274
 
183
- var _error$config$showToa = error.config.showToastr,
184
- showToastr = _error$config$showToa === void 0 ? true : _error$config$showToa;
275
+ var redirect404 = function redirect404(error) {
276
+ var _error$response;
185
277
 
186
278
  if (((_error$response = error.response) === null || _error$response === void 0 ? void 0 : _error$response.status) === 404) {
187
279
  window.location.href = "/page-not-found";
188
- } else if (((_error$response2 = error.response) === null || _error$response2 === void 0 ? void 0 : _error$response2.status) === 401) {
189
- handleUnauthorizedErrorResponse();
190
- } else if (showToastr) {
191
- showErrorToastr(error);
192
280
  }
193
281
 
194
- return Promise.reject(error);
282
+ return error;
283
+ };
284
+
285
+ var buildErrorResponseHandler = function buildErrorResponseHandler(skip) {
286
+ var interceptors = [];
287
+ if (!(skip !== null && skip !== void 0 && skip.redirectOn404)) interceptors.push(redirect404);
288
+ if (!(skip !== null && skip !== void 0 && skip.logoutOn401)) interceptors.push(handleUnauthorizedErrorResponse);
289
+ if (!(skip !== null && skip !== void 0 && skip.showToastr)) interceptors.push(showErrorToastr);
290
+ interceptors.push(Promise.reject.bind(Promise));
291
+ return createPipe(interceptors);
195
292
  };
196
293
 
197
294
  var cleanupCredentialsForCrossOrigin = function cleanupCredentialsForCrossOrigin(request) {
198
295
  if (!request.url.includes("://")) return request;
199
296
  if (request.url.includes(window.location.hostname)) return request;
200
- return ramda.evolve({
201
- headers: ramda.omit(ramda.values(HEADERS_KEYS))
297
+ return evolve({
298
+ headers: omit(values(HEADERS_KEYS))
202
299
  })(request);
203
300
  };
204
301
 
205
- var serializeKeysToSnakeCase = function serializeKeysToSnakeCase(object) {
206
- if (Array.isArray(object)) {
207
- return object.map(serializeKeysToSnakeCase);
208
- } else if (object === null || _typeof(object) !== "object") {
209
- return object;
210
- }
211
-
212
- return Object.fromEntries(Object.entries(object).map(function (_ref) {
213
- var _ref2 = _slicedToArray(_ref, 2),
214
- key = _ref2[0],
215
- value = _ref2[1];
216
-
217
- var val = typeof (value === null || value === void 0 ? void 0 : value.toJSON) === "function" ? value.toJSON() : value;
218
- return [strings.camelToSnakeCase(key), serializeKeysToSnakeCase(val)];
219
- }));
220
- };
221
-
222
302
  var transformDataToSnakeCase = function transformDataToSnakeCase(request) {
223
303
  var _request$transformReq = request.transformRequestCase,
224
304
  transformRequestCase = _request$transformReq === void 0 ? true : _request$transformReq;
225
305
  if (!transformRequestCase || !request.data) return request;
226
- return ramda.modify("data", serializeKeysToSnakeCase, request);
306
+ return modify("data", serializeKeysToSnakeCase, request);
307
+ };
308
+
309
+ var addRequestInterceptors = function addRequestInterceptors(skip) {
310
+ if (!(skip !== null && skip !== void 0 && skip.cleanCredentialsForCrossOrigin)) {
311
+ axios.interceptors.request.use(cleanupCredentialsForCrossOrigin);
312
+ }
313
+
314
+ if (!(skip !== null && skip !== void 0 && skip.transformCase)) {
315
+ axios.interceptors.request.use(transformDataToSnakeCase);
316
+ }
227
317
  };
228
318
 
229
- var registerIntercepts = function registerIntercepts() {
230
- axios__default["default"].interceptors.request.use(ramda.pipe(cleanupCredentialsForCrossOrigin, transformDataToSnakeCase));
231
- axios__default["default"].interceptors.response.use(handleSuccessResponse, handleErrorResponse);
319
+ var addResponseInterceptors = function addResponseInterceptors(skip) {
320
+ axios.interceptors.response.use(buildSuccessResponseHandler(skip), buildErrorResponseHandler(skip));
232
321
  };
233
322
 
234
- setAxiosDefaults();
323
+ var registerIntercepts = function registerIntercepts(skip) {
324
+ if (shouldNot(skip === null || skip === void 0 ? void 0 : skip.request)) addRequestInterceptors(skip === null || skip === void 0 ? void 0 : skip.request);
325
+ if (shouldNot(skip === null || skip === void 0 ? void 0 : skip.response)) addResponseInterceptors(skip === null || skip === void 0 ? void 0 : skip.response);
326
+ };
235
327
 
236
- var isProduction = process.env.NODE_ENV === "production";
237
- var isTokenPresent = !!process.env.MIXPANEL_TOKEN;
238
- var isUserLoggedIn = !ramda.either(ramda.isEmpty, ramda.isNil)(globalProps.user);
328
+ function initializeAxios(skip) {
329
+ if (!(skip !== null && skip !== void 0 && skip.baseURL)) axios.defaults.baseURL = "/";
330
+ if (!(skip !== null && skip !== void 0 && skip.authHeaders)) setAuthHeaders();
331
+ if (shouldNot(skip === null || skip === void 0 ? void 0 : skip.interceptors)) registerIntercepts(skip === null || skip === void 0 ? void 0 : skip.interceptors);
332
+ }
239
333
 
240
- if (isProduction && isTokenPresent && isUserLoggedIn) {
241
- mixpanel__default["default"].init(process.env.MIXPANEL_TOKEN);
242
- mixpanel__default["default"].people.set({
243
- $email: globalProps.user.email,
244
- $fist_name: globalProps.user.firstName,
245
- $last_name: globalProps.user.lastName
246
- });
247
- mixpanel__default["default"].identify(globalProps.user.email);
248
- } else {
249
- /*
250
- We need to initialize mixpanel with a bogus token in development and test environment to
251
- prevent mixpanel library from throwing an error when we use mixpanel.track() method in react components.
252
- */
253
- mixpanel__default["default"].init("TEST_TOKEN");
334
+ function initializeMixPanel() {
335
+ var isProduction = process.env.NODE_ENV === "production";
336
+ var isTokenPresent = !!process.env.MIXPANEL_TOKEN;
337
+ var isUserLoggedIn = !either(isEmpty, isNil)(globalProps.user);
338
+
339
+ if (isProduction && isTokenPresent && isUserLoggedIn) {
340
+ mixpanel.init(process.env.MIXPANEL_TOKEN || "");
341
+ mixpanel.people.set({
342
+ $email: globalProps.user.email,
343
+ $fist_name: globalProps.user.firstName,
344
+ $last_name: globalProps.user.lastName
345
+ });
346
+ mixpanel.identify(globalProps.user.email);
347
+ } else {
348
+ /*
349
+ We need to initialize mixpanel with a bogus token in development and test environment to
350
+ prevent mixpanel library from throwing an error when we use mixpanel.track() method in react components.
351
+ */
352
+ mixpanel.init("TEST_TOKEN");
353
+ }
254
354
  }
255
355
 
256
356
  var neetoCommons = {
@@ -293,8 +393,8 @@ var en = {
293
393
  };
294
394
 
295
395
  var initializeI18n = function initializeI18n(resources) {
296
- i18next__default["default"].use(reactI18next.initReactI18next).init({
297
- resources: ramda.mergeDeepLeft({
396
+ i18next.use(initReactI18next).init({
397
+ resources: mergeDeepLeft({
298
398
  en: {
299
399
  translation: en
300
400
  }
@@ -308,10 +408,23 @@ var initializeI18n = function initializeI18n(resources) {
308
408
  });
309
409
  };
310
410
 
311
- /* eslint-disable import/order */
411
+ var globalProps$1 = {};
312
412
  function initializeApplication(_ref) {
313
- var translationResources = _ref.translationResources;
314
- initializeI18n(translationResources);
413
+ var translationResources = _ref.translationResources,
414
+ skip = _ref.skip;
415
+
416
+ if (!(skip !== null && skip !== void 0 && skip.globalProps)) {
417
+ initializeGlobalProps();
418
+ globalProps$1 = window.globalProps;
419
+ }
420
+
421
+ if (!(skip !== null && skip !== void 0 && skip.mixpanel)) initializeMixPanel();
422
+
423
+ if (_typeof(skip === null || skip === void 0 ? void 0 : skip.axios) === "object" || !(skip !== null && skip !== void 0 && skip.axios)) {
424
+ initializeAxios(skip === null || skip === void 0 ? void 0 : skip.axios);
425
+ }
426
+
427
+ if (!(skip !== null && skip !== void 0 && skip.i18n)) initializeI18n(translationResources);
315
428
  }
316
429
 
317
- module.exports = initializeApplication;
430
+ export { initializeApplication as default, globalProps$1 as globalProps };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bigbinary/neeto-commons-frontend",
3
- "version": "2.0.0",
3
+ "version": "2.0.3",
4
4
  "description": "A package encapsulating common code across neeto projects including initializers, utility functions, common components and hooks and so on.",
5
5
  "repository": "git@github.com:bigbinary/neeto-commons-frontend.git",
6
6
  "author": "Amaljith K <amaljith.k@bigbinary.com>",
@@ -13,23 +13,41 @@
13
13
  "watch": "rollup -c rollup.config.js --watch"
14
14
  },
15
15
  "files": [
16
- "initializers*.js",
17
- "react*.js",
18
- "utils*.js",
19
- "pure*.js"
16
+ "initializers.*",
17
+ "react-utils.*",
18
+ "utils.*",
19
+ "pure.*"
20
20
  ],
21
21
  "lint-staged": {
22
22
  "**/*.{js,jsx,json}": [
23
23
  ".scripts/fix-lints.sh"
24
24
  ]
25
25
  },
26
+ "exports": {
27
+ "./react-utils": {
28
+ "import": "./react-utils.js",
29
+ "require": "./react-utils.cjs.js"
30
+ },
31
+ "./utils": {
32
+ "import": "./utils.js",
33
+ "require": "./utils.cjs.js"
34
+ },
35
+ "./pure": {
36
+ "import": "./pure.js",
37
+ "require": "./pure.cjs.js"
38
+ },
39
+ "./initializers": {
40
+ "import": "./initializers.js",
41
+ "require": "./initializers.cjs.js"
42
+ }
43
+ },
26
44
  "devDependencies": {
27
45
  "@babel/eslint-parser": "^7.18.2",
28
46
  "@babel/plugin-transform-runtime": "^7.18.5",
29
47
  "@babel/preset-env": "^7.17.10",
30
48
  "@babel/preset-react": "^7.16.7",
31
49
  "@bigbinary/neeto-icons": "^1.8.35",
32
- "@bigbinary/neetoui": "^3.5.11",
50
+ "@bigbinary/neetoui": "^3.5.14",
33
51
  "@honeybadger-io/react": "2.0.1",
34
52
  "@rollup/plugin-alias": "^3.1.9",
35
53
  "@rollup/plugin-babel": "^5.3.1",
@@ -63,6 +81,7 @@
63
81
  "lint-staged": "^12.3.7",
64
82
  "mixpanel-browser": "^2.45.0",
65
83
  "prettier": "^2.6.2",
84
+ "query-string": "^7.1.1",
66
85
  "ramda": "^0.28.0",
67
86
  "react": "^17.0.2",
68
87
  "react-dom": "17.0.2",
@@ -77,7 +96,7 @@
77
96
  "dependencies": {},
78
97
  "peerDependencies": {
79
98
  "@bigbinary/neeto-icons": "^1.8.35",
80
- "@bigbinary/neetoui": "^3.5.11",
99
+ "@bigbinary/neetoui": "^3.5.14",
81
100
  "@honeybadger-io/react": "2.0.1",
82
101
  "axios": "^0.27.2",
83
102
  "dayjs": "1.11.1",