1
1
import { ApiDOMStructuredError } from '@swagger-api/apidom-error' ;
2
2
3
3
import STYLES , { Style } from './styles' ;
4
+ import type { LogRecordInstance } from './LogRecord' ;
4
5
5
6
export interface FormatterOptions {
6
7
readonly fmt ?: Style [ 'fmt' ] ;
@@ -10,11 +11,60 @@ export interface FormatterOptions {
10
11
readonly defaults ?: Record < string , unknown > ;
11
12
}
12
13
13
- class Formatter {
14
+ export interface FormatterInstance {
15
+ format ( record : LogRecordInstance ) : string ;
16
+ }
17
+
18
+ export interface FormatterConstructor {
19
+ new ( options : FormatterOptions ) : FormatterInstance ;
20
+ }
21
+
22
+ const momentToIntlFormat = ( momentFormat : string ) : Intl . DateTimeFormatOptions => {
23
+ if ( momentToIntlFormat . cache . has ( momentFormat ) ) {
24
+ return momentToIntlFormat . cache . get ( momentFormat ) ! ;
25
+ }
26
+
27
+ const mapping = {
28
+ YYYY : { year : 'numeric' } ,
29
+ YY : { year : '2-digit' } ,
30
+ MMMM : { month : 'long' } ,
31
+ MMM : { month : 'short' } ,
32
+ MM : { month : '2-digit' } ,
33
+ DD : { day : '2-digit' } ,
34
+ dddd : { weekday : 'long' } ,
35
+ ddd : { weekday : 'short' } ,
36
+ HH : { hour : '2-digit' , hour12 : false } ,
37
+ hh : { hour : '2-digit' , hour12 : true } ,
38
+ mm : { minute : '2-digit' } ,
39
+ ss : { second : '2-digit' } ,
40
+ A : { hour12 : true } ,
41
+ z : { timeZoneName : 'short' } , // abbreviated time zone name
42
+ Z : { timeZoneName : 'short' } , // offset from GMT
43
+ } ;
44
+ type MomentToken = keyof typeof mapping ;
45
+
46
+ const intlOptions : Intl . DateTimeFormatOptions = Object . keys ( mapping ) . reduce ( ( opts , token ) => {
47
+ if ( momentFormat . includes ( token ) ) {
48
+ return { ...opts , ...mapping [ token as MomentToken ] } ;
49
+ }
50
+ return opts ;
51
+ } , { } ) ;
52
+
53
+ momentToIntlFormat . cache . set ( momentFormat , intlOptions ) ;
54
+
55
+ return intlOptions ;
56
+ } ;
57
+ momentToIntlFormat . cache = new Map < string , Intl . DateTimeFormatOptions > ( ) ;
58
+
59
+ class Formatter implements FormatterInstance {
14
60
protected readonly style : Style ;
15
61
16
62
protected readonly datefmt ?: string ;
17
63
64
+ protected readonly defaultDateTimeFormat ! : 'DD MM YYYY hh:mm:ss' ;
65
+
66
+ protected readonly appendMsecInfo = true ;
67
+
18
68
constructor ( options : FormatterOptions = { } ) {
19
69
const style = options . style ?? '$' ;
20
70
@@ -37,6 +87,49 @@ class Formatter {
37
87
38
88
this . datefmt = options . datefmt ;
39
89
}
90
+
91
+ protected usesTime ( ) : boolean {
92
+ return this . style . usesTime ( ) ;
93
+ }
94
+
95
+ protected formatTime ( record : LogRecordInstance , datefmt ?: string ) : string {
96
+ const intlOptions = momentToIntlFormat ( datefmt ?? this . defaultDateTimeFormat ) ;
97
+ const formattedTime = new Intl . DateTimeFormat ( undefined , intlOptions ) . format ( record . created ) ;
98
+
99
+ if ( this . appendMsecInfo ) {
100
+ return `${ formattedTime } ,${ String ( record . msecs ) . padStart ( 3 , '0' ) } ` ;
101
+ }
102
+
103
+ return formattedTime ;
104
+ }
105
+
106
+ protected formatMessage ( record : LogRecordInstance ) : string {
107
+ return this . style . format ( record ) ;
108
+ }
109
+
110
+ // eslint-disable-next-line class-methods-use-this
111
+ protected formatError < T extends Error > ( error : T ) : string {
112
+ return `Error: ${ error . message } \nStack: ${ error . stack ?? 'No stack available' } ` ;
113
+ }
114
+
115
+ public format ( record : LogRecordInstance ) {
116
+ if ( this . usesTime ( ) ) {
117
+ record . asctime = this . formatTime ( record , this . datefmt ) ; // eslint-disable-line no-param-reassign
118
+ }
119
+
120
+ const formattedMessage = this . formatMessage ( record ) ;
121
+
122
+ if ( record . error && typeof record . error_text === 'undefined' ) {
123
+ record . error_text = this . formatError ( record . error ) ; // eslint-disable-line no-param-reassign
124
+ }
125
+
126
+ if ( record . error_text ) {
127
+ const separator = formattedMessage . endsWith ( '\n' ) ? '' : '\n' ;
128
+ return `${ formattedMessage } ${ separator } ${ record . error_text } ` ;
129
+ }
130
+
131
+ return formattedMessage ;
132
+ }
40
133
}
41
134
42
135
export default Formatter ;
0 commit comments