dce-reactkit 3.2.0-beta.3 → 3.2.0-beta.4
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/.vscode/settings.json +5 -0
- package/dist/cjs/index.js +156 -72
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/index.d.ts +2 -1
- package/dist/cjs/types/types/LogBuiltInCategory.d.ts +10 -0
- package/dist/esm/index.js +156 -73
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/index.d.ts +2 -1
- package/dist/esm/types/types/LogBuiltInCategory.d.ts +10 -0
- package/dist/index.d.ts +11 -1
- package/package.json +1 -1
- package/src/helpers/genRouteHandler.ts +181 -99
- package/src/index.ts +2 -0
- package/src/types/LogBuiltInCategory.ts +11 -0
|
@@ -23,6 +23,7 @@ import LogSource from '../types/LogSource';
|
|
|
23
23
|
import LogTypeSpecificInfo from '../types/Log/LogTypeSpecificInfo';
|
|
24
24
|
import LogMainInfo from '../types/Log/LogMainInfo';
|
|
25
25
|
import LogSourceSpecificInfo from '../types/Log/LogSourceSpecificInfo';
|
|
26
|
+
import LogBuiltInCategory from '../types/LogBuiltInCategory';
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
29
|
* Generate an express API route handler
|
|
@@ -469,109 +470,166 @@ const genRouteHandler = (
|
|
|
469
470
|
// that indicates that this is actually a client event, but we don't
|
|
470
471
|
// include that in the LogFunction type because this is internal and
|
|
471
472
|
// hidden from users
|
|
473
|
+
try {
|
|
474
|
+
// Parse user agent
|
|
475
|
+
const {
|
|
476
|
+
browser,
|
|
477
|
+
device,
|
|
478
|
+
} = parseUserAgent(req.headers['user-agent']);
|
|
479
|
+
|
|
480
|
+
// Get time info in ET
|
|
481
|
+
const {
|
|
482
|
+
timestamp,
|
|
483
|
+
year,
|
|
484
|
+
month,
|
|
485
|
+
day,
|
|
486
|
+
hour,
|
|
487
|
+
minute,
|
|
488
|
+
} = getTimeInfoInET();
|
|
489
|
+
|
|
490
|
+
// Main log info
|
|
491
|
+
const mainLogInfo: LogMainInfo = {
|
|
492
|
+
id: `${launchInfo.userId}-${Date.now()}-${Math.floor(Math.random() * 100000)}-${Math.floor(Math.random() * 100000)}`,
|
|
493
|
+
userFirstName: launchInfo.userFirstName,
|
|
494
|
+
userLastName: launchInfo.userLastName,
|
|
495
|
+
userEmail: launchInfo.userEmail,
|
|
496
|
+
userId: launchInfo.userId,
|
|
497
|
+
isLearner: !!launchInfo.isLearner,
|
|
498
|
+
isAdmin: !!launchInfo.isAdmin,
|
|
499
|
+
isTTM: !!launchInfo.isTTM,
|
|
500
|
+
courseId: launchInfo.courseId,
|
|
501
|
+
courseName: launchInfo.courseName,
|
|
502
|
+
browser,
|
|
503
|
+
device,
|
|
504
|
+
year,
|
|
505
|
+
month,
|
|
506
|
+
day,
|
|
507
|
+
hour,
|
|
508
|
+
minute,
|
|
509
|
+
timestamp,
|
|
510
|
+
category: (
|
|
511
|
+
typeof opts.category === 'string'
|
|
512
|
+
? opts.category
|
|
513
|
+
: opts.category.name
|
|
514
|
+
),
|
|
515
|
+
subcategory: (
|
|
516
|
+
typeof opts.category === 'string'
|
|
517
|
+
? opts.subcategory
|
|
518
|
+
: ((opts.subcategory as any) ?? {}).name
|
|
519
|
+
),
|
|
520
|
+
tags: opts.tags ?? [],
|
|
521
|
+
metadata: opts.metadata ?? {},
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
// Type-specific info
|
|
525
|
+
const typeSpecificInfo: LogTypeSpecificInfo = (
|
|
526
|
+
('error' in opts && opts.error)
|
|
527
|
+
? {
|
|
528
|
+
type: LogType.Error,
|
|
529
|
+
errorMessage: opts.error.message ?? 'Unknown message',
|
|
530
|
+
errorCode: opts.error.code ?? ReactKitErrorCode.NoCode,
|
|
531
|
+
errorStack: opts.error.stack ?? 'No stack',
|
|
532
|
+
}
|
|
533
|
+
: {
|
|
534
|
+
type: LogType.Action,
|
|
535
|
+
target: (opts as any).target ?? 'Unknown',
|
|
536
|
+
action: (opts as any).action ?? 'Unknown'
|
|
537
|
+
}
|
|
538
|
+
);
|
|
472
539
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
hour,
|
|
486
|
-
minute,
|
|
487
|
-
} = getTimeInfoInET();
|
|
488
|
-
|
|
489
|
-
// Main log info
|
|
490
|
-
const mainLogInfo: LogMainInfo = {
|
|
491
|
-
id: `${launchInfo.userId}-${Date.now()}-${Math.floor(Math.random() * 100000)}-${Math.floor(Math.random() * 100000)}`,
|
|
492
|
-
userFirstName: launchInfo.userFirstName,
|
|
493
|
-
userLastName: launchInfo.userLastName,
|
|
494
|
-
userEmail: launchInfo.userEmail,
|
|
495
|
-
userId: launchInfo.userId,
|
|
496
|
-
isLearner: !!launchInfo.isLearner,
|
|
497
|
-
isAdmin: !!launchInfo.isAdmin,
|
|
498
|
-
isTTM: !!launchInfo.isTTM,
|
|
499
|
-
courseId: launchInfo.courseId,
|
|
500
|
-
courseName: launchInfo.courseName,
|
|
501
|
-
browser,
|
|
502
|
-
device,
|
|
503
|
-
year,
|
|
504
|
-
month,
|
|
505
|
-
day,
|
|
506
|
-
hour,
|
|
507
|
-
minute,
|
|
508
|
-
timestamp,
|
|
509
|
-
category: (
|
|
510
|
-
typeof opts.category === 'string'
|
|
511
|
-
? opts.category
|
|
512
|
-
: opts.category.name
|
|
513
|
-
),
|
|
514
|
-
subcategory: (
|
|
515
|
-
typeof opts.category === 'string'
|
|
516
|
-
? opts.subcategory
|
|
517
|
-
: ((opts.subcategory as any) ?? { name: 'none' }).name
|
|
518
|
-
),
|
|
519
|
-
tags: opts.tags ?? [],
|
|
520
|
-
metadata: opts.metadata ?? {},
|
|
521
|
-
};
|
|
522
|
-
|
|
523
|
-
// Type-specific info
|
|
524
|
-
const typeSpecificInfo: LogTypeSpecificInfo = (
|
|
525
|
-
('error' in opts && opts.error)
|
|
526
|
-
? {
|
|
527
|
-
type: LogType.Error,
|
|
528
|
-
errorMessage: opts.error.message ?? 'Unknown message',
|
|
529
|
-
errorCode: opts.error.code ?? ReactKitErrorCode.NoCode,
|
|
530
|
-
errorStack: opts.error.stack ?? 'No stack',
|
|
531
|
-
}
|
|
532
|
-
: {
|
|
533
|
-
type: LogType.Action,
|
|
534
|
-
target: (opts as any).target ?? 'Unknown',
|
|
535
|
-
action: (opts as any).action ?? 'Unknown'
|
|
536
|
-
}
|
|
537
|
-
);
|
|
538
|
-
|
|
539
|
-
// Source-specific info
|
|
540
|
-
const sourceSpecificInfo: LogSourceSpecificInfo = (
|
|
541
|
-
(opts as any).overrideAsClientEvent
|
|
542
|
-
? {
|
|
543
|
-
source: LogSource.Client,
|
|
544
|
-
}
|
|
545
|
-
: {
|
|
546
|
-
source: LogSource.Server,
|
|
547
|
-
routePath: req.path,
|
|
548
|
-
routeTemplate: req.route.path,
|
|
549
|
-
}
|
|
550
|
-
);
|
|
540
|
+
// Source-specific info
|
|
541
|
+
const sourceSpecificInfo: LogSourceSpecificInfo = (
|
|
542
|
+
(opts as any).overrideAsClientEvent
|
|
543
|
+
? {
|
|
544
|
+
source: LogSource.Client,
|
|
545
|
+
}
|
|
546
|
+
: {
|
|
547
|
+
source: LogSource.Server,
|
|
548
|
+
routePath: req.path,
|
|
549
|
+
routeTemplate: req.route.path,
|
|
550
|
+
}
|
|
551
|
+
);
|
|
551
552
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
} else {
|
|
565
|
-
// Print to console
|
|
566
|
-
if (log.type === LogType.Error) {
|
|
567
|
-
console.error('dce-reactkit error log:', log);
|
|
553
|
+
// Build log event
|
|
554
|
+
const log: Log = {
|
|
555
|
+
...mainLogInfo,
|
|
556
|
+
...typeSpecificInfo,
|
|
557
|
+
...sourceSpecificInfo,
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
// Either print to console or save to db
|
|
561
|
+
const logCollection = internalGetLogCollection();
|
|
562
|
+
if (logCollection) {
|
|
563
|
+
// Store to the log collection
|
|
564
|
+
await logCollection.insert(log);
|
|
568
565
|
} else {
|
|
569
|
-
|
|
566
|
+
// Print to console
|
|
567
|
+
if (log.type === LogType.Error) {
|
|
568
|
+
console.error('dce-reactkit error log:', log);
|
|
569
|
+
} else {
|
|
570
|
+
console.log('dce-reactkit action log:', log);
|
|
571
|
+
}
|
|
570
572
|
}
|
|
571
|
-
}
|
|
572
573
|
|
|
573
|
-
|
|
574
|
-
|
|
574
|
+
// Return log entry
|
|
575
|
+
return log;
|
|
576
|
+
} catch (err) {
|
|
577
|
+
// Print because we cannot store the error
|
|
578
|
+
console.error('Could not log the following:', opts);
|
|
579
|
+
|
|
580
|
+
// Create a dummy log to return
|
|
581
|
+
const dummyMainInfo: LogMainInfo = {
|
|
582
|
+
id: '-1',
|
|
583
|
+
userFirstName: 'Unknown',
|
|
584
|
+
userLastName: 'Unknown',
|
|
585
|
+
userEmail: 'unknown@harvard.edu',
|
|
586
|
+
userId: 1,
|
|
587
|
+
isLearner: false,
|
|
588
|
+
isAdmin: false,
|
|
589
|
+
isTTM: false,
|
|
590
|
+
courseId: 1,
|
|
591
|
+
courseName: 'Unknown',
|
|
592
|
+
browser: {
|
|
593
|
+
name: 'Unknown',
|
|
594
|
+
version: 'Unknown',
|
|
595
|
+
},
|
|
596
|
+
device: {
|
|
597
|
+
isMobile: false,
|
|
598
|
+
os: 'Unknown',
|
|
599
|
+
},
|
|
600
|
+
year: 1,
|
|
601
|
+
month: 1,
|
|
602
|
+
day: 1,
|
|
603
|
+
hour: 1,
|
|
604
|
+
minute: 1,
|
|
605
|
+
timestamp: Date.now(),
|
|
606
|
+
tags: [],
|
|
607
|
+
metadata: {},
|
|
608
|
+
category: LogBuiltInCategory.Uncategorized,
|
|
609
|
+
subcategory: LogBuiltInCategory.Uncategorized,
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
const dummyTypeSpecificInfo: LogTypeSpecificInfo = {
|
|
613
|
+
type: LogType.Error,
|
|
614
|
+
errorMessage: 'Unknown',
|
|
615
|
+
errorCode: 'Unknown',
|
|
616
|
+
errorStack: 'No Stack',
|
|
617
|
+
};
|
|
618
|
+
|
|
619
|
+
const dummySourceSpecificInfo: LogSourceSpecificInfo = {
|
|
620
|
+
source: LogSource.Server,
|
|
621
|
+
routePath: req.path,
|
|
622
|
+
routeTemplate: req.route.path,
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
const log: Log = {
|
|
626
|
+
...dummyMainInfo,
|
|
627
|
+
...dummyTypeSpecificInfo,
|
|
628
|
+
...dummySourceSpecificInfo,
|
|
629
|
+
};
|
|
630
|
+
|
|
631
|
+
return log;
|
|
632
|
+
}
|
|
575
633
|
};
|
|
576
634
|
|
|
577
635
|
/*------------------------------------------------------------------------*/
|
|
@@ -625,6 +683,22 @@ const genRouteHandler = (
|
|
|
625
683
|
) => {
|
|
626
684
|
const html = genErrorPage(opts);
|
|
627
685
|
send(html, opts.status ?? 500);
|
|
686
|
+
|
|
687
|
+
// Log
|
|
688
|
+
logServerEvent({
|
|
689
|
+
category: LogBuiltInCategory.ServerRenderedErrorPage,
|
|
690
|
+
error: {
|
|
691
|
+
message: `${opts.title}: ${opts.description}`,
|
|
692
|
+
code: opts.code,
|
|
693
|
+
},
|
|
694
|
+
metadata: {
|
|
695
|
+
title: opts.title,
|
|
696
|
+
description: opts.description,
|
|
697
|
+
code: opts.code,
|
|
698
|
+
pageTitle: opts.pageTitle,
|
|
699
|
+
status: opts.status ?? 500,
|
|
700
|
+
},
|
|
701
|
+
});
|
|
628
702
|
};
|
|
629
703
|
|
|
630
704
|
// Call the handler
|
|
@@ -649,7 +723,15 @@ const genRouteHandler = (
|
|
|
649
723
|
} catch (err) {
|
|
650
724
|
// Send error to client (only if next wasn't called)
|
|
651
725
|
if (!responseSent) {
|
|
652
|
-
|
|
726
|
+
handleError(res, err);
|
|
727
|
+
|
|
728
|
+
// Log server-side error
|
|
729
|
+
logServerEvent({
|
|
730
|
+
category: LogBuiltInCategory.ServerEndpointError,
|
|
731
|
+
error: err,
|
|
732
|
+
});
|
|
733
|
+
|
|
734
|
+
return;
|
|
653
735
|
}
|
|
654
736
|
|
|
655
737
|
// Log error that was not responded with
|
package/src/index.ts
CHANGED
|
@@ -63,6 +63,7 @@ import Log from './types/Log';
|
|
|
63
63
|
import LogType from './types/LogType';
|
|
64
64
|
import LogSource from './types/LogSource';
|
|
65
65
|
import LogAction from './types/LogAction';
|
|
66
|
+
import LogBuiltInCategory from './types/LogBuiltInCategory';
|
|
66
67
|
|
|
67
68
|
// Component-specific-types
|
|
68
69
|
import PickableItem from './components/ItemPicker/types/PickableItem';
|
|
@@ -135,6 +136,7 @@ export {
|
|
|
135
136
|
LogType,
|
|
136
137
|
LogSource,
|
|
137
138
|
LogAction,
|
|
139
|
+
LogBuiltInCategory,
|
|
138
140
|
// Component-specific-types
|
|
139
141
|
PickableItem,
|
|
140
142
|
// Server types
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in categories for logs
|
|
3
|
+
* @author Gabe Abrams
|
|
4
|
+
*/
|
|
5
|
+
enum LogBuiltInCategory {
|
|
6
|
+
Uncategorized = 'n/a',
|
|
7
|
+
ServerRenderedErrorPage = '_server-rendered-error-page',
|
|
8
|
+
ServerEndpointError = '_server-endpoint-error',
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default LogBuiltInCategory;
|