@bigbinary/neeto-commons-frontend 2.0.1 → 2.0.2

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/README.md CHANGED
@@ -7,7 +7,7 @@ The commons frontend library for Neeto Applications.
7
7
  Install from npm:
8
8
 
9
9
  ```bash
10
- yarn add "@bigbinary/neeto-commons-frontend@2.0.1"
10
+ yarn add "@bigbinary/neeto-commons-frontend@2.0.2"
11
11
  ```
12
12
 
13
13
  This package relies on the host project's tailwind configuration. So add
@@ -0,0 +1,441 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var ramda = require('ramda');
6
+ var neetoui = require('@bigbinary/neetoui');
7
+ var axios = require('axios');
8
+ var i18next = require('i18next');
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);
17
+
18
+ function _typeof(obj) {
19
+ "@babel/helpers - typeof";
20
+
21
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
22
+ return typeof obj;
23
+ } : function (obj) {
24
+ return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
25
+ }, _typeof(obj);
26
+ }
27
+
28
+ function _arrayWithHoles(arr) {
29
+ if (Array.isArray(arr)) return arr;
30
+ }
31
+
32
+ function _iterableToArrayLimit(arr, i) {
33
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
34
+
35
+ if (_i == null) return;
36
+ var _arr = [];
37
+ var _n = true;
38
+ var _d = false;
39
+
40
+ var _s, _e;
41
+
42
+ try {
43
+ for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
44
+ _arr.push(_s.value);
45
+
46
+ if (i && _arr.length === i) break;
47
+ }
48
+ } catch (err) {
49
+ _d = true;
50
+ _e = err;
51
+ } finally {
52
+ try {
53
+ if (!_n && _i["return"] != null) _i["return"]();
54
+ } finally {
55
+ if (_d) throw _e;
56
+ }
57
+ }
58
+
59
+ return _arr;
60
+ }
61
+
62
+ function _arrayLikeToArray(arr, len) {
63
+ if (len == null || len > arr.length) len = arr.length;
64
+
65
+ for (var i = 0, arr2 = new Array(len); i < len; i++) {
66
+ arr2[i] = arr[i];
67
+ }
68
+
69
+ return arr2;
70
+ }
71
+
72
+ function _unsupportedIterableToArray(o, minLen) {
73
+ if (!o) return;
74
+ if (typeof o === "string") return _arrayLikeToArray(o, minLen);
75
+ var n = Object.prototype.toString.call(o).slice(8, -1);
76
+ if (n === "Object" && o.constructor) n = o.constructor.name;
77
+ if (n === "Map" || n === "Set") return Array.from(o);
78
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
79
+ }
80
+
81
+ function _nonIterableRest() {
82
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
83
+ }
84
+
85
+ function _slicedToArray(arr, i) {
86
+ return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
87
+ }
88
+
89
+ var snakeToCamelCase = function snakeToCamelCase(string) {
90
+ return string.replace(/(_\w)/g, function (letter) {
91
+ return letter[1].toUpperCase();
92
+ });
93
+ };
94
+ var camelToSnakeCase = function camelToSnakeCase(string) {
95
+ return string.replace(/[A-Z]/g, function (letter) {
96
+ return "_".concat(letter.toLowerCase());
97
+ });
98
+ };
99
+
100
+ var transformObjectDeep = function transformObjectDeep(object, keyValueTransformer) {
101
+ if (Array.isArray(object)) {
102
+ return object.map(function (obj) {
103
+ return transformObjectDeep(obj, keyValueTransformer);
104
+ });
105
+ } else if (object === null || _typeof(object) !== "object") {
106
+ return object;
107
+ }
108
+
109
+ return Object.fromEntries(Object.entries(object).map(function (_ref) {
110
+ var _ref2 = _slicedToArray(_ref, 2),
111
+ key = _ref2[0],
112
+ value = _ref2[1];
113
+
114
+ return keyValueTransformer(key, transformObjectDeep(value, keyValueTransformer));
115
+ }));
116
+ };
117
+ var keysToCamelCase = function keysToCamelCase(object) {
118
+ return transformObjectDeep(object, function (key, value) {
119
+ return [snakeToCamelCase(key), value];
120
+ });
121
+ };
122
+ var deepFreezeObject = function deepFreezeObject(object) {
123
+ if (object && _typeof(object) === "object" && !Object.isFrozen(object)) {
124
+ Object.keys(object).forEach(function (property) {
125
+ return deepFreezeObject(object[property]);
126
+ });
127
+ Object.freeze(object);
128
+ }
129
+
130
+ return object;
131
+ };
132
+ var matches = ramda.curry(function (pattern, object) {
133
+ var __parent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : object;
134
+
135
+ if (object === pattern) return true;
136
+ if (typeof pattern === "function" && pattern(object, __parent)) return true;
137
+ if (ramda.isNil(pattern) || ramda.isNil(object)) return false;
138
+ if (_typeof(pattern) !== "object") return false;
139
+ return Object.entries(pattern).every(function (_ref3) {
140
+ var _ref4 = _slicedToArray(_ref3, 2),
141
+ key = _ref4[0],
142
+ value = _ref4[1];
143
+
144
+ return matches(value, object[key], __parent);
145
+ });
146
+ });
147
+
148
+ function initializeGlobalProps() {
149
+ var _document$getElements, _document$getElements2;
150
+
151
+ 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) || "{}"));
152
+ deepFreezeObject(window.globalProps);
153
+ }
154
+
155
+ function _defineProperty(obj, key, value) {
156
+ if (key in obj) {
157
+ Object.defineProperty(obj, key, {
158
+ value: value,
159
+ enumerable: true,
160
+ configurable: true,
161
+ writable: true
162
+ });
163
+ } else {
164
+ obj[key] = value;
165
+ }
166
+
167
+ return obj;
168
+ }
169
+
170
+ var HEADERS_KEYS = {
171
+ xAuthEmail: "X-Auth-Email",
172
+ xAuthToken: "X-Auth-Token",
173
+ xCsrfToken: "X-CSRF-TOKEN"
174
+ };
175
+
176
+ var resetAuthTokens = function resetAuthTokens() {
177
+ ramda.values(HEADERS_KEYS).forEach(function (header) {
178
+ delete axios__default["default"].defaults.headers[header];
179
+ });
180
+ };
181
+
182
+ var shouldNot = function shouldNot(skip) {
183
+ return _typeof(skip) === "object" || !skip;
184
+ };
185
+
186
+ var setAuthHeaders = function setAuthHeaders() {
187
+ var _globalProps$user, _globalProps$user2;
188
+
189
+ axios__default["default"].defaults.headers = _defineProperty({
190
+ Accept: "application/json",
191
+ "Content-Type": "application/json"
192
+ }, HEADERS_KEYS.xCsrfToken, document.querySelector('[name="csrf-token"]').getAttribute("content"));
193
+ var token = (_globalProps$user = globalProps.user) === null || _globalProps$user === void 0 ? void 0 : _globalProps$user.authenticationToken;
194
+ var email = (_globalProps$user2 = globalProps.user) === null || _globalProps$user2 === void 0 ? void 0 : _globalProps$user2.email;
195
+
196
+ if (token && email) {
197
+ axios__default["default"].defaults.headers[HEADERS_KEYS.xAuthEmail] = email;
198
+ axios__default["default"].defaults.headers[HEADERS_KEYS.xAuthToken] = token;
199
+ }
200
+ }; // pipe function from ramda doesn't accept array of functions.
201
+ // We can't use spread operator too. So this is a workaround.
202
+
203
+
204
+ var createPipe = function createPipe(functions) {
205
+ return function (data) {
206
+ return functions.reduce(function (acc, fn) {
207
+ return fn(acc);
208
+ }, data);
209
+ };
210
+ };
211
+
212
+ var transformKeysToCamelCase = function transformKeysToCamelCase(response) {
213
+ var _response$config$tran = response.config.transformResponseCase,
214
+ transformResponseCase = _response$config$tran === void 0 ? true : _response$config$tran;
215
+
216
+ if (response.data && transformResponseCase) {
217
+ response.data = keysToCamelCase(response.data);
218
+ }
219
+
220
+ return response;
221
+ };
222
+
223
+ var showSuccessToastr = function showSuccessToastr(response) {
224
+ var _response$config$show = response.config.showToastr,
225
+ showToastr = _response$config$show === void 0 ? true : _response$config$show;
226
+
227
+ if (showToastr && typeof response.data.notice === "string") {
228
+ neetoui.Toastr.success(response.data.notice);
229
+ }
230
+
231
+ return response;
232
+ };
233
+
234
+ var pullDataFromResponse = function pullDataFromResponse(response) {
235
+ var _response$config$incl = response.config.includeMetadataInResponse,
236
+ includeMetadataInResponse = _response$config$incl === void 0 ? false : _response$config$incl;
237
+ return includeMetadataInResponse ? response : response.data;
238
+ };
239
+
240
+ var buildSuccessResponseHandler = function buildSuccessResponseHandler(skip) {
241
+ var interceptors = [];
242
+ if (!(skip !== null && skip !== void 0 && skip.transformCase)) interceptors.push(transformKeysToCamelCase);
243
+ if (!(skip !== null && skip !== void 0 && skip.showToastr)) interceptors.push(showSuccessToastr);
244
+ if (!(skip !== null && skip !== void 0 && skip.pullDataFromResponse)) interceptors.push(pullDataFromResponse);
245
+ return createPipe(interceptors);
246
+ };
247
+
248
+ var handleUnauthorizedErrorResponse = function handleUnauthorizedErrorResponse(error) {
249
+ resetAuthTokens();
250
+ setTimeout(function () {
251
+ var redirectTo = window.location.pathname === "/login" ? "/login" : "/login?redirect_uri=".concat(encodeURIComponent(window.location.href));
252
+ window.location.href = redirectTo;
253
+ }, 300);
254
+ return error;
255
+ };
256
+
257
+ var showErrorToastr = function showErrorToastr(error) {
258
+ if (axios__default["default"].isCancel(error)) {
259
+ neetoui.Toastr.error(i18next__default["default"].t("neetoCommons.toastr.error.requestCanceled"));
260
+ } else if (error.message === "Network Error") {
261
+ neetoui.Toastr.error(i18next__default["default"].t("neetoCommons.toastr.error.networkError"));
262
+ } else {
263
+ neetoui.Toastr.error(error);
264
+ }
265
+
266
+ return error;
267
+ };
268
+
269
+ var redirect404 = function redirect404(error) {
270
+ var _error$response;
271
+
272
+ if (((_error$response = error.response) === null || _error$response === void 0 ? void 0 : _error$response.status) === 404) {
273
+ window.location.href = "/page-not-found";
274
+ }
275
+
276
+ return error;
277
+ };
278
+
279
+ var buildErrorResponseHandler = function buildErrorResponseHandler(skip) {
280
+ var interceptors = [];
281
+ if (!(skip !== null && skip !== void 0 && skip.redirectOn404)) interceptors.push(redirect404);
282
+ if (!(skip !== null && skip !== void 0 && skip.logoutOn401)) interceptors.push(handleUnauthorizedErrorResponse);
283
+ if (!(skip !== null && skip !== void 0 && skip.showToastr)) interceptors.push(showErrorToastr);
284
+ interceptors.push(Promise.reject);
285
+ return createPipe(interceptors);
286
+ };
287
+
288
+ var cleanupCredentialsForCrossOrigin = function cleanupCredentialsForCrossOrigin(request) {
289
+ if (!request.url.includes("://")) return request;
290
+ if (request.url.includes(window.location.hostname)) return request;
291
+ return ramda.evolve({
292
+ headers: ramda.omit(ramda.values(HEADERS_KEYS))
293
+ })(request);
294
+ };
295
+
296
+ var serializeKeysToSnakeCase = function serializeKeysToSnakeCase(object) {
297
+ if (Array.isArray(object)) {
298
+ return object.map(serializeKeysToSnakeCase);
299
+ } else if (object === null || _typeof(object) !== "object") {
300
+ return object;
301
+ }
302
+
303
+ return Object.fromEntries(Object.entries(object).map(function (_ref) {
304
+ var _ref2 = _slicedToArray(_ref, 2),
305
+ key = _ref2[0],
306
+ value = _ref2[1];
307
+
308
+ var val = typeof (value === null || value === void 0 ? void 0 : value.toJSON) === "function" ? value.toJSON() : value;
309
+ return [camelToSnakeCase(key), serializeKeysToSnakeCase(val)];
310
+ }));
311
+ };
312
+
313
+ var transformDataToSnakeCase = function transformDataToSnakeCase(request) {
314
+ var _request$transformReq = request.transformRequestCase,
315
+ transformRequestCase = _request$transformReq === void 0 ? true : _request$transformReq;
316
+ if (!transformRequestCase || !request.data) return request;
317
+ return ramda.modify("data", serializeKeysToSnakeCase, request);
318
+ };
319
+
320
+ var addRequestInterceptors = function addRequestInterceptors(skip) {
321
+ if (!(skip !== null && skip !== void 0 && skip.cleanCredentialsForCrossOrigin)) {
322
+ axios__default["default"].interceptors.request.use(cleanupCredentialsForCrossOrigin);
323
+ }
324
+
325
+ if (!(skip !== null && skip !== void 0 && skip.transformCase)) {
326
+ axios__default["default"].interceptors.request.use(transformDataToSnakeCase);
327
+ }
328
+ };
329
+
330
+ var addResponseInterceptors = function addResponseInterceptors(skip) {
331
+ axios__default["default"].interceptors.response.use(buildSuccessResponseHandler(skip), buildErrorResponseHandler(skip));
332
+ };
333
+
334
+ var registerIntercepts = function registerIntercepts(skip) {
335
+ if (shouldNot(skip === null || skip === void 0 ? void 0 : skip.request)) addRequestInterceptors(skip === null || skip === void 0 ? void 0 : skip.request);
336
+ if (shouldNot(skip === null || skip === void 0 ? void 0 : skip.response)) addResponseInterceptors(skip === null || skip === void 0 ? void 0 : skip.response);
337
+ };
338
+
339
+ function initializeAxios(skip) {
340
+ if (!(skip !== null && skip !== void 0 && skip.baseURL)) axios__default["default"].defaults.baseURL = "/";
341
+ if (!(skip !== null && skip !== void 0 && skip.authHeaders)) setAuthHeaders();
342
+ if (shouldNot(skip === null || skip === void 0 ? void 0 : skip.interceptors)) registerIntercepts(skip === null || skip === void 0 ? void 0 : skip.interceptors);
343
+ }
344
+
345
+ function initializeMixPanel() {
346
+ var isProduction = process.env.NODE_ENV === "production";
347
+ var isTokenPresent = !!process.env.MIXPANEL_TOKEN;
348
+ var isUserLoggedIn = !ramda.either(ramda.isEmpty, ramda.isNil)(globalProps.user);
349
+
350
+ if (isProduction && isTokenPresent && isUserLoggedIn) {
351
+ mixpanel__default["default"].init(process.env.MIXPANEL_TOKEN || "");
352
+ mixpanel__default["default"].people.set({
353
+ $email: globalProps.user.email,
354
+ $fist_name: globalProps.user.firstName,
355
+ $last_name: globalProps.user.lastName
356
+ });
357
+ mixpanel__default["default"].identify(globalProps.user.email);
358
+ } else {
359
+ /*
360
+ We need to initialize mixpanel with a bogus token in development and test environment to
361
+ prevent mixpanel library from throwing an error when we use mixpanel.track() method in react components.
362
+ */
363
+ mixpanel__default["default"].init("TEST_TOKEN");
364
+ }
365
+ }
366
+
367
+ var neetoCommons = {
368
+ errorPage: {
369
+ pageDoesNotExist: "Page does not exist.",
370
+ goToHome: "Go home"
371
+ },
372
+ fallbackComponent: {
373
+ somethingWentWrong: "Sorry, something went wrong.",
374
+ tryReloading: "Please try reloading the page.",
375
+ reload: "Reload"
376
+ },
377
+ sidebar: {
378
+ profile: "Profile",
379
+ orgSettings: "Organization Settings",
380
+ logout: "Logout",
381
+ help: "Help"
382
+ },
383
+ common: {
384
+ actions: {
385
+ cancel: "Cancel",
386
+ save: "Save"
387
+ }
388
+ },
389
+ toastr: {
390
+ success: {
391
+ copiedToClipboard: "Copied to clipboard!"
392
+ },
393
+ error: {
394
+ requestCanceled: "Request cancelled",
395
+ networkError: "No Internet Connection"
396
+ }
397
+ },
398
+ notice: {
399
+ errorOccurred: "Some error occurred."
400
+ }
401
+ };
402
+ var en = {
403
+ neetoCommons: neetoCommons
404
+ };
405
+
406
+ var initializeI18n = function initializeI18n(resources) {
407
+ i18next__default["default"].use(reactI18next.initReactI18next).init({
408
+ resources: ramda.mergeDeepLeft({
409
+ en: {
410
+ translation: en
411
+ }
412
+ }, resources),
413
+ lng: "en",
414
+ fallbackLng: "en",
415
+ interpolation: {
416
+ escapeValue: false,
417
+ skipOnVariables: false
418
+ }
419
+ });
420
+ };
421
+
422
+ exports.globalProps = {};
423
+ function initializeApplication(_ref) {
424
+ var translationResources = _ref.translationResources,
425
+ skip = _ref.skip;
426
+
427
+ if (!(skip !== null && skip !== void 0 && skip.globalProps)) {
428
+ initializeGlobalProps();
429
+ exports.globalProps = window.globalProps;
430
+ }
431
+
432
+ if (!(skip !== null && skip !== void 0 && skip.mixpanel)) initializeMixPanel();
433
+
434
+ if (_typeof(skip === null || skip === void 0 ? void 0 : skip.axios) === "object" || !(skip !== null && skip !== void 0 && skip.axios)) {
435
+ initializeAxios(skip === null || skip === void 0 ? void 0 : skip.axios);
436
+ }
437
+
438
+ if (!(skip !== null && skip !== void 0 && skip.i18n)) initializeI18n(translationResources);
439
+ }
440
+
441
+ exports["default"] = initializeApplication;
@@ -0,0 +1,59 @@
1
+ type Skippable<T> = boolean | Partial<T>;
2
+
3
+ type Configurations = {
4
+ translationResources?: { en: { translation: object } };
5
+ skip?: Partial<{
6
+ globalProps: boolean;
7
+ mixpanel: boolean;
8
+ i18n: boolean;
9
+ axios: Skippable<{
10
+ baseURL: boolean;
11
+ authHeaders: boolean;
12
+ interceptors: Skippable<{
13
+ request: Skippable<{
14
+ cleanCredentialsForCrossOrigin: boolean;
15
+ transformCase: boolean;
16
+ }>;
17
+ response: Skippable<{
18
+ transformCase: boolean;
19
+ showToastr: boolean;
20
+ pullDataFromResponse: boolean;
21
+ redirectOn404: boolean;
22
+ logoutOn401: boolean;
23
+ }>;
24
+ }>;
25
+ }>;
26
+ }>;
27
+ };
28
+
29
+ type GlobalPropsType = {
30
+ nodeEnv: string;
31
+ honeybadgerApiKey: string;
32
+ organization: {
33
+ name: string;
34
+ subdomain: string;
35
+ faviconUrl: string;
36
+ [key: string]: any;
37
+ };
38
+ user?: {
39
+ id: string;
40
+ email: string;
41
+ lastName: string;
42
+ firstName: string;
43
+ profileImageUrl: string;
44
+ active: boolean;
45
+ authenticationToken: string;
46
+ [key: string]: any;
47
+ };
48
+ authenticated: boolean;
49
+ neetoApps: string[];
50
+ isOwner: boolean;
51
+ permissions: string[];
52
+ [key: string]: any;
53
+ };
54
+
55
+ export default function initializeApplication(
56
+ configurations: Configurations
57
+ ): void;
58
+
59
+ export const globalProps: GlobalPropsType;