dce-reactkit 3.2.1 → 3.2.2-beta.1

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/dist/esm/index.js CHANGED
@@ -491,6 +491,184 @@ class ErrorWithCode extends Error {
491
491
  }
492
492
  }
493
493
 
494
+ /**
495
+ * Path that all routes start with
496
+ * @author Gabe Abrams
497
+ */
498
+ const ROUTE_PATH_PREFIX = '/dce-reactkit';
499
+
500
+ /**
501
+ * Path of the route for storing client-side logs
502
+ * @author Gabe Abrams
503
+ */
504
+ const LOG_ROUTE_PATH = `${ROUTE_PATH_PREFIX}/log`;
505
+
506
+ /**
507
+ * Built-in metadata for logs
508
+ * @author Gabe Abrams
509
+ */
510
+ const LogBuiltInMetadata = {
511
+ // Contexts
512
+ Context: {
513
+ Uncategorized: 'n/a',
514
+ ServerRenderedErrorPage: '_server-rendered-error-page',
515
+ ServerEndpointError: '_server-endpoint-error',
516
+ ClientFatalError: '_client-fatal-error',
517
+ },
518
+ // Targets
519
+ Target: {
520
+ NoSpecificTarget: 'n/a',
521
+ },
522
+ };
523
+
524
+ // Keep track of whether or not session expiry has already been handled
525
+ let sessionAlreadyExpired = false;
526
+ /*------------------------------------------------------------------------*/
527
+ /* Stub Logic */
528
+ /*------------------------------------------------------------------------*/
529
+ // Stored stub responses
530
+ const stubResponses = {};
531
+ /**
532
+ * Add a stub response
533
+ * @author Gabe Abrams
534
+ * @param opts object containing all arguments
535
+ * @param [opts.method=GET] http request method
536
+ * @param opts.path pathname of the request
537
+ * @param [opts.body] body of the response if successful
538
+ * @param [opts.errorMessage] error message if not successful
539
+ * @param [opts.errorCode] error code if not successful
540
+ */
541
+ const _setStubResponse = (opts) => {
542
+ var _a, _b, _c;
543
+ const { path, body, } = opts;
544
+ const method = ((_a = opts.method) !== null && _a !== void 0 ? _a : 'GET').toUpperCase();
545
+ const errorMessage = ((_b = opts.errorMessage) !== null && _b !== void 0 ? _b : 'An unknown error has occurred.');
546
+ const errorCode = ((_c = opts.errorCode) !== null && _c !== void 0 ? _c : ReactKitErrorCode$1.NoCode);
547
+ // Store to stub responses
548
+ if (!stubResponses[method]) {
549
+ stubResponses[method] = {};
550
+ }
551
+ stubResponses[method][path] = ((opts.errorMessage || opts.errorCode)
552
+ ? {
553
+ success: false,
554
+ errorMessage,
555
+ errorCode,
556
+ }
557
+ : {
558
+ success: true,
559
+ body: body !== null && body !== void 0 ? body : undefined,
560
+ });
561
+ };
562
+ /*------------------------------------------------------------------------*/
563
+ /* Main */
564
+ /*------------------------------------------------------------------------*/
565
+ /**
566
+ * Visit an endpoint on the server [for client only]
567
+ * @author Gabe Abrams
568
+ * @param opts object containing all arguments
569
+ * @param opts.path - the path of the server endpoint
570
+ * @param [opts.method=GET] - the method of the endpoint
571
+ * @param [opts.params] - query/body parameters to include
572
+ * @returns response from server
573
+ */
574
+ const visitServerEndpoint = (opts) => __awaiter(void 0, void 0, void 0, function* () {
575
+ var _a, _b, _c;
576
+ const method = ((_a = opts.method) !== null && _a !== void 0 ? _a : 'GET');
577
+ // Handle stubs
578
+ const stubResponse = (_b = stubResponses[method]) === null || _b === void 0 ? void 0 : _b[opts.path];
579
+ if (stubResponse) {
580
+ // Remove from list
581
+ try {
582
+ stubResponses[method][opts.path] = undefined;
583
+ }
584
+ catch (err) {
585
+ // Ignore
586
+ }
587
+ // Success
588
+ if (stubResponse.success) {
589
+ return stubResponse.body;
590
+ }
591
+ // Error
592
+ throw new ErrorWithCode(stubResponse.errorMessage, stubResponse.errorCode);
593
+ }
594
+ // Send the request
595
+ const response = yield cacclSendRequest({
596
+ path: opts.path,
597
+ method: (_c = opts.method) !== null && _c !== void 0 ? _c : 'GET',
598
+ params: opts.params,
599
+ });
600
+ // Check for failure
601
+ if (!response || !response.body) {
602
+ throw new ErrorWithCode('We didn\'t get a response from the server. Please check your internet connection.', ReactKitErrorCode$1.NoResponse);
603
+ }
604
+ if (!response.body.success) {
605
+ // Session expired
606
+ if (response.body.code === ReactKitErrorCode$1.SessionExpired) {
607
+ // Skip notice if session was already expired
608
+ if (sessionAlreadyExpired) {
609
+ // Never return (browser is already reloading)
610
+ yield new Promise(() => {
611
+ // Promise that never returns
612
+ });
613
+ }
614
+ sessionAlreadyExpired = true;
615
+ // Show session expiration message
616
+ {
617
+ // Fallback to alert
618
+ // eslint-disable-next-line no-alert
619
+ alert('Your session has expired. Please start over.');
620
+ }
621
+ // Never return (don't continue execution)
622
+ yield new Promise(() => {
623
+ // Promise that never returns
624
+ });
625
+ }
626
+ // Other errors
627
+ throw new ErrorWithCode((response.body.message
628
+ || 'An unknown error occurred. Please contact an admin.'), (response.body.code
629
+ || ReactKitErrorCode$1.NoCode));
630
+ }
631
+ // Success! Extract the body
632
+ const { body } = response.body;
633
+ // Return
634
+ return body;
635
+ });
636
+
637
+ /**
638
+ * Log a user action on the client (cannot be used on the server)
639
+ * @author Gabe Abrams
640
+ */
641
+ const logClientEvent = (opts) => __awaiter(void 0, void 0, void 0, function* () {
642
+ var _a, _b, _c, _d, _e, _f;
643
+ return visitServerEndpoint({
644
+ path: LOG_ROUTE_PATH,
645
+ method: 'POST',
646
+ params: {
647
+ context: (typeof opts.context === 'string'
648
+ ? opts.context
649
+ : ((_b = ((_a = opts.context) !== null && _a !== void 0 ? _a : {})._) !== null && _b !== void 0 ? _b : LogBuiltInMetadata.Context.Uncategorized)),
650
+ subcontext: ((_c = opts.subcontext) !== null && _c !== void 0 ? _c : LogBuiltInMetadata.Context.Uncategorized),
651
+ tags: JSON.stringify((_d = opts.tags) !== null && _d !== void 0 ? _d : []),
652
+ metadata: JSON.stringify((_e = opts.metadata) !== null && _e !== void 0 ? _e : {}),
653
+ errorMessage: (opts.error
654
+ ? opts.error.message
655
+ : undefined),
656
+ errorCode: (opts.error
657
+ ? opts.error.code
658
+ : undefined),
659
+ errorStack: (opts.error
660
+ ? opts.error.stack
661
+ : undefined),
662
+ target: (opts.action
663
+ ? ((_f = opts.target) !== null && _f !== void 0 ? _f : LogBuiltInMetadata.Target.NoSpecificTarget)
664
+ : undefined),
665
+ action: (opts.action
666
+ ? opts.action
667
+ : undefined),
668
+ },
669
+ });
670
+ });
671
+
494
672
  /**
495
673
  * A wrapper for the entire React app that adds global functionality like
496
674
  * handling for fatal error messages, adds bootstrap support
@@ -610,6 +788,14 @@ const showFatalError = (error, errorTitle = 'An Error Occurred') => {
610
788
  const code = (typeof error === 'string'
611
789
  ? ReactKitErrorCode$1.NoCode
612
790
  : String((_b = error.code) !== null && _b !== void 0 ? _b : ReactKitErrorCode$1.NoCode));
791
+ // Add log
792
+ logClientEvent({
793
+ context: LogBuiltInMetadata.Context.ClientFatalError,
794
+ error,
795
+ metadata: {
796
+ errorTitle,
797
+ },
798
+ });
613
799
  // Handle case where app hasn't loaded
614
800
  if (!setFatalErrorMessage || !setFatalErrorCode) {
615
801
  alert$1(errorTitle, `${message} (code: ${code}). Please contact support.`);
@@ -2003,131 +2189,6 @@ const roundToNumDecimals = (num, numDecimals) => {
2003
2189
  return (Math.round(num * rounder) / rounder);
2004
2190
  };
2005
2191
 
2006
- // Keep track of whether or not session expiry has already been handled
2007
- let sessionAlreadyExpired = false;
2008
- /*------------------------------------------------------------------------*/
2009
- /* Stub Logic */
2010
- /*------------------------------------------------------------------------*/
2011
- // Stored stub responses
2012
- const stubResponses = {};
2013
- /**
2014
- * Add a stub response
2015
- * @author Gabe Abrams
2016
- * @param opts object containing all arguments
2017
- * @param [opts.method=GET] http request method
2018
- * @param opts.path pathname of the request
2019
- * @param [opts.body] body of the response if successful
2020
- * @param [opts.errorMessage] error message if not successful
2021
- * @param [opts.errorCode] error code if not successful
2022
- */
2023
- const _setStubResponse = (opts) => {
2024
- var _a, _b, _c;
2025
- const { path, body, } = opts;
2026
- const method = ((_a = opts.method) !== null && _a !== void 0 ? _a : 'GET').toUpperCase();
2027
- const errorMessage = ((_b = opts.errorMessage) !== null && _b !== void 0 ? _b : 'An unknown error has occurred.');
2028
- const errorCode = ((_c = opts.errorCode) !== null && _c !== void 0 ? _c : ReactKitErrorCode$1.NoCode);
2029
- // Store to stub responses
2030
- if (!stubResponses[method]) {
2031
- stubResponses[method] = {};
2032
- }
2033
- stubResponses[method][path] = ((opts.errorMessage || opts.errorCode)
2034
- ? {
2035
- success: false,
2036
- errorMessage,
2037
- errorCode,
2038
- }
2039
- : {
2040
- success: true,
2041
- body: body !== null && body !== void 0 ? body : undefined,
2042
- });
2043
- };
2044
- /*------------------------------------------------------------------------*/
2045
- /* Main */
2046
- /*------------------------------------------------------------------------*/
2047
- /**
2048
- * Visit an endpoint on the server [for client only]
2049
- * @author Gabe Abrams
2050
- * @param opts object containing all arguments
2051
- * @param opts.path - the path of the server endpoint
2052
- * @param [opts.method=GET] - the method of the endpoint
2053
- * @param [opts.params] - query/body parameters to include
2054
- * @returns response from server
2055
- */
2056
- const visitServerEndpoint = (opts) => __awaiter(void 0, void 0, void 0, function* () {
2057
- var _a, _b, _c;
2058
- const method = ((_a = opts.method) !== null && _a !== void 0 ? _a : 'GET');
2059
- // Handle stubs
2060
- const stubResponse = (_b = stubResponses[method]) === null || _b === void 0 ? void 0 : _b[opts.path];
2061
- if (stubResponse) {
2062
- // Remove from list
2063
- try {
2064
- stubResponses[method][opts.path] = undefined;
2065
- }
2066
- catch (err) {
2067
- // Ignore
2068
- }
2069
- // Success
2070
- if (stubResponse.success) {
2071
- return stubResponse.body;
2072
- }
2073
- // Error
2074
- throw new ErrorWithCode(stubResponse.errorMessage, stubResponse.errorCode);
2075
- }
2076
- // Send the request
2077
- const response = yield cacclSendRequest({
2078
- path: opts.path,
2079
- method: (_c = opts.method) !== null && _c !== void 0 ? _c : 'GET',
2080
- params: opts.params,
2081
- });
2082
- // Check for failure
2083
- if (!response || !response.body) {
2084
- throw new ErrorWithCode('We didn\'t get a response from the server. Please check your internet connection.', ReactKitErrorCode$1.NoResponse);
2085
- }
2086
- if (!response.body.success) {
2087
- // Session expired
2088
- if (response.body.code === ReactKitErrorCode$1.SessionExpired) {
2089
- // Skip notice if session was already expired
2090
- if (sessionAlreadyExpired) {
2091
- // Never return (browser is already reloading)
2092
- yield new Promise(() => {
2093
- // Promise that never returns
2094
- });
2095
- }
2096
- sessionAlreadyExpired = true;
2097
- // Show session expiration message
2098
- {
2099
- // Fallback to alert
2100
- // eslint-disable-next-line no-alert
2101
- alert('Your session has expired. Please start over.');
2102
- }
2103
- // Never return (don't continue execution)
2104
- yield new Promise(() => {
2105
- // Promise that never returns
2106
- });
2107
- }
2108
- // Other errors
2109
- throw new ErrorWithCode((response.body.message
2110
- || 'An unknown error occurred. Please contact an admin.'), (response.body.code
2111
- || ReactKitErrorCode$1.NoCode));
2112
- }
2113
- // Success! Extract the body
2114
- const { body } = response.body;
2115
- // Return
2116
- return body;
2117
- });
2118
-
2119
- /**
2120
- * Path that all routes start with
2121
- * @author Gabe Abrams
2122
- */
2123
- const ROUTE_PATH_PREFIX = '/dce-reactkit';
2124
-
2125
- /**
2126
- * Path of the route for storing client-side logs
2127
- * @author Gabe Abrams
2128
- */
2129
- const LOG_ROUTE_PATH = `${ROUTE_PATH_PREFIX}/log`;
2130
-
2131
2192
  /**
2132
2193
  * Server-side API param types
2133
2194
  * @author Gabe Abrams
@@ -2583,23 +2644,6 @@ var LogSource;
2583
2644
  })(LogSource || (LogSource = {}));
2584
2645
  var LogSource$1 = LogSource;
2585
2646
 
2586
- /**
2587
- * Built-in metadata for logs
2588
- * @author Gabe Abrams
2589
- */
2590
- const LogBuiltInMetadata = {
2591
- // Contexts
2592
- Context: {
2593
- Uncategorized: 'n/a',
2594
- ServerRenderedErrorPage: '_server-rendered-error-page',
2595
- ServerEndpointError: '_server-endpoint-error',
2596
- },
2597
- // Targets
2598
- Target: {
2599
- NoSpecificTarget: 'n/a',
2600
- },
2601
- };
2602
-
2603
2647
  /**
2604
2648
  * Types of actions
2605
2649
  * @author Gabe Abrams
@@ -3386,41 +3430,6 @@ const parallelLimit = (taskFunctions, limit) => __awaiter(void 0, void 0, void 0
3386
3430
  return results;
3387
3431
  });
3388
3432
 
3389
- /**
3390
- * Log a user action on the client (cannot be used on the server)
3391
- * @author Gabe Abrams
3392
- */
3393
- const logClientEvent = (opts) => __awaiter(void 0, void 0, void 0, function* () {
3394
- var _a, _b, _c, _d, _e, _f;
3395
- return visitServerEndpoint({
3396
- path: LOG_ROUTE_PATH,
3397
- method: 'POST',
3398
- params: {
3399
- context: (typeof opts.context === 'string'
3400
- ? opts.context
3401
- : ((_b = ((_a = opts.context) !== null && _a !== void 0 ? _a : {})._) !== null && _b !== void 0 ? _b : LogBuiltInMetadata.Context.Uncategorized)),
3402
- subcontext: ((_c = opts.subcontext) !== null && _c !== void 0 ? _c : LogBuiltInMetadata.Context.Uncategorized),
3403
- tags: JSON.stringify((_d = opts.tags) !== null && _d !== void 0 ? _d : []),
3404
- metadata: JSON.stringify((_e = opts.metadata) !== null && _e !== void 0 ? _e : {}),
3405
- errorMessage: (opts.error
3406
- ? opts.error.message
3407
- : undefined),
3408
- errorCode: (opts.error
3409
- ? opts.error.code
3410
- : undefined),
3411
- errorStack: (opts.error
3412
- ? opts.error.stack
3413
- : undefined),
3414
- target: (opts.action
3415
- ? ((_f = opts.target) !== null && _f !== void 0 ? _f : LogBuiltInMetadata.Target.NoSpecificTarget)
3416
- : undefined),
3417
- action: (opts.action
3418
- ? opts.action
3419
- : undefined),
3420
- },
3421
- });
3422
- });
3423
-
3424
3433
  /**
3425
3434
  * Initialize a log collection given the dce-mango Collection class
3426
3435
  * @author Gabe Abrams