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