@contrast/agent 4.16.2 → 4.18.0

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.
Files changed (147) hide show
  1. package/esm.mjs +21 -11
  2. package/lib/assess/policy/propagators.json +4 -0
  3. package/lib/assess/policy/signatures.json +5 -0
  4. package/lib/assess/propagators/fastify-static/allowed-path.js +85 -0
  5. package/lib/assess/sources/index.js +26 -5
  6. package/lib/cli-rewriter/index.js +1 -1
  7. package/lib/contrast.js +1 -1
  8. package/lib/core/config/options.js +14 -1
  9. package/lib/core/config/util.js +39 -11
  10. package/lib/core/rewrite/index.js +2 -2
  11. package/lib/protect/service.js +2 -0
  12. package/lib/util/trace-util.js +5 -4
  13. package/node_modules/@colors/colors/LICENSE +26 -0
  14. package/node_modules/@colors/colors/README.md +219 -0
  15. package/node_modules/@colors/colors/examples/normal-usage.js +83 -0
  16. package/node_modules/@colors/colors/examples/safe-string.js +80 -0
  17. package/node_modules/@colors/colors/index.d.ts +136 -0
  18. package/node_modules/@colors/colors/lib/colors.js +211 -0
  19. package/node_modules/@colors/colors/lib/custom/trap.js +46 -0
  20. package/node_modules/@colors/colors/lib/custom/zalgo.js +110 -0
  21. package/node_modules/@colors/colors/lib/extendStringPrototype.js +110 -0
  22. package/node_modules/@colors/colors/lib/index.js +13 -0
  23. package/node_modules/@colors/colors/lib/maps/america.js +10 -0
  24. package/node_modules/@colors/colors/lib/maps/rainbow.js +12 -0
  25. package/node_modules/@colors/colors/lib/maps/random.js +11 -0
  26. package/node_modules/@colors/colors/lib/maps/zebra.js +5 -0
  27. package/node_modules/@colors/colors/lib/styles.js +95 -0
  28. package/node_modules/@colors/colors/lib/system/has-flag.js +35 -0
  29. package/node_modules/@colors/colors/lib/system/supports-colors.js +151 -0
  30. package/node_modules/@colors/colors/package.json +49 -0
  31. package/node_modules/@colors/colors/safe.d.ts +48 -0
  32. package/node_modules/@colors/colors/safe.js +10 -0
  33. package/node_modules/@colors/colors/themes/generic-logging.js +12 -0
  34. package/node_modules/@dabh/diagnostics/README.md +16 -16
  35. package/node_modules/@dabh/diagnostics/package.json +9 -9
  36. package/node_modules/color/README.md +9 -0
  37. package/node_modules/color/index.js +4 -1
  38. package/node_modules/color/package.json +8 -8
  39. package/node_modules/color-string/README.md +6 -2
  40. package/node_modules/color-string/index.js +21 -13
  41. package/node_modules/color-string/package.json +4 -4
  42. package/node_modules/colorspace/package.json +5 -5
  43. package/node_modules/fecha/dist/fecha.min.js +1 -1
  44. package/node_modules/fecha/dist/fecha.min.js.map +1 -0
  45. package/node_modules/fecha/lib/fecha.d.ts +2 -2
  46. package/node_modules/fecha/lib/fecha.js +35 -18
  47. package/node_modules/fecha/lib/fecha.js.map +1 -0
  48. package/node_modules/fecha/lib/fecha.umd.js +35 -18
  49. package/node_modules/fecha/lib/fecha.umd.js.map +1 -0
  50. package/node_modules/fecha/package.json +9 -10
  51. package/node_modules/fecha/src/fecha.ts +524 -0
  52. package/node_modules/logform/.eslintrc +1 -1
  53. package/node_modules/logform/CHANGELOG.md +24 -0
  54. package/node_modules/logform/README.md +15 -17
  55. package/node_modules/logform/browser.js +3 -1
  56. package/node_modules/logform/cli.js +1 -1
  57. package/node_modules/logform/colorize.js +2 -2
  58. package/node_modules/logform/dist/browser.js +8 -2
  59. package/node_modules/logform/dist/cli.js +2 -2
  60. package/node_modules/logform/dist/colorize.js +5 -5
  61. package/node_modules/logform/dist/errors.js +1 -1
  62. package/node_modules/logform/dist/format.js +9 -5
  63. package/node_modules/logform/dist/index.js +53 -20
  64. package/node_modules/logform/dist/json.js +7 -6
  65. package/node_modules/logform/dist/logstash.js +1 -1
  66. package/node_modules/logform/dist/pad-levels.js +4 -4
  67. package/node_modules/logform/dist/printf.js +1 -1
  68. package/node_modules/logform/dist/simple.js +1 -1
  69. package/node_modules/logform/dist/splat.js +2 -2
  70. package/node_modules/logform/dist/uncolorize.js +1 -1
  71. package/node_modules/logform/errors.js +1 -1
  72. package/node_modules/logform/index.d.ts +36 -0
  73. package/node_modules/logform/index.js +19 -20
  74. package/node_modules/logform/json.js +7 -7
  75. package/node_modules/logform/logstash.js +1 -1
  76. package/node_modules/logform/package.json +10 -9
  77. package/node_modules/logform/simple.js +1 -1
  78. package/node_modules/logform/uncolorize.js +1 -1
  79. package/node_modules/safe-stable-stringify/CHANGELOG.md +75 -0
  80. package/node_modules/safe-stable-stringify/LICENSE +21 -0
  81. package/node_modules/safe-stable-stringify/esm/package.json +4 -0
  82. package/node_modules/safe-stable-stringify/esm/wrapper.js +6 -0
  83. package/node_modules/safe-stable-stringify/index.d.ts +18 -0
  84. package/node_modules/safe-stable-stringify/index.js +618 -0
  85. package/node_modules/safe-stable-stringify/package.json +69 -0
  86. package/node_modules/safe-stable-stringify/readme.md +170 -0
  87. package/node_modules/safe-stable-stringify/tsconfig.json +22 -0
  88. package/node_modules/winston/LICENSE +18 -18
  89. package/node_modules/winston/README.md +1231 -1230
  90. package/node_modules/winston/dist/winston/common.js +10 -10
  91. package/node_modules/winston/dist/winston/config/index.js +17 -17
  92. package/node_modules/winston/dist/winston/container.js +46 -46
  93. package/node_modules/winston/dist/winston/create-logger.js +28 -24
  94. package/node_modules/winston/dist/winston/exception-handler.js +49 -49
  95. package/node_modules/winston/dist/winston/exception-stream.js +27 -27
  96. package/node_modules/winston/dist/winston/logger.js +152 -138
  97. package/node_modules/winston/dist/winston/profiler.js +22 -22
  98. package/node_modules/winston/dist/winston/rejection-handler.js +54 -54
  99. package/node_modules/winston/dist/winston/tail-file.js +14 -14
  100. package/node_modules/winston/dist/winston/transports/console.js +31 -31
  101. package/node_modules/winston/dist/winston/transports/file.js +101 -101
  102. package/node_modules/winston/dist/winston/transports/http.js +119 -41
  103. package/node_modules/winston/dist/winston/transports/index.js +17 -17
  104. package/node_modules/winston/dist/winston/transports/stream.js +24 -24
  105. package/node_modules/winston/dist/winston.js +91 -97
  106. package/node_modules/winston/index.d.ts +213 -193
  107. package/node_modules/winston/lib/winston/common.js +61 -61
  108. package/node_modules/winston/lib/winston/config/index.d.ts +99 -98
  109. package/node_modules/winston/lib/winston/config/index.js +35 -35
  110. package/node_modules/winston/lib/winston/container.js +114 -114
  111. package/node_modules/winston/lib/winston/create-logger.js +104 -104
  112. package/node_modules/winston/lib/winston/exception-handler.js +245 -245
  113. package/node_modules/winston/lib/winston/exception-stream.js +54 -54
  114. package/node_modules/winston/lib/winston/logger.js +676 -667
  115. package/node_modules/winston/lib/winston/profiler.js +51 -51
  116. package/node_modules/winston/lib/winston/rejection-handler.js +251 -251
  117. package/node_modules/winston/lib/winston/tail-file.js +124 -124
  118. package/node_modules/winston/lib/winston/transports/console.js +117 -117
  119. package/node_modules/winston/lib/winston/transports/file.js +695 -695
  120. package/node_modules/winston/lib/winston/transports/http.js +267 -202
  121. package/node_modules/winston/lib/winston/transports/index.d.ts +103 -100
  122. package/node_modules/winston/lib/winston/transports/index.js +56 -56
  123. package/node_modules/winston/lib/winston/transports/stream.js +63 -63
  124. package/node_modules/winston/lib/winston.js +176 -182
  125. package/node_modules/winston/node_modules/winston-transport/.babelrc +3 -0
  126. package/node_modules/winston/node_modules/winston-transport/.eslintrc +7 -0
  127. package/node_modules/winston/node_modules/winston-transport/.gitattributes +1 -0
  128. package/node_modules/winston/node_modules/winston-transport/.nyc_output/c3d7ddb9-cc26-466b-a4f6-993ad69e86f6.json +1 -0
  129. package/node_modules/winston/node_modules/winston-transport/.nyc_output/processinfo/c3d7ddb9-cc26-466b-a4f6-993ad69e86f6.json +1 -0
  130. package/node_modules/winston/node_modules/winston-transport/.nyc_output/processinfo/index.json +1 -0
  131. package/node_modules/winston/node_modules/winston-transport/CHANGELOG.md +126 -0
  132. package/node_modules/winston/node_modules/winston-transport/LICENSE +22 -0
  133. package/node_modules/winston/node_modules/winston-transport/README.md +50 -0
  134. package/node_modules/winston/node_modules/winston-transport/dist/index.js +215 -0
  135. package/node_modules/winston/node_modules/winston-transport/dist/legacy.js +116 -0
  136. package/node_modules/winston/node_modules/winston-transport/index.d.ts +39 -0
  137. package/node_modules/winston/node_modules/winston-transport/index.js +215 -0
  138. package/node_modules/winston/node_modules/winston-transport/legacy.js +119 -0
  139. package/node_modules/winston/node_modules/winston-transport/package.json +56 -0
  140. package/node_modules/winston/package.json +76 -75
  141. package/package.json +9 -6
  142. package/node_modules/@dabh/diagnostics/example.png +0 -0
  143. package/node_modules/color-string/CHANGELOG.md +0 -18
  144. package/node_modules/colorspace/test.js +0 -14
  145. package/node_modules/fecha/CHANGELOG.md +0 -67
  146. package/node_modules/logform/.travis.yml +0 -17
  147. package/node_modules/winston/CHANGELOG.md +0 -560
@@ -0,0 +1,524 @@
1
+ const token = /d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|Z|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g;
2
+ const twoDigitsOptional = "\\d\\d?";
3
+ const twoDigits = "\\d\\d";
4
+ const threeDigits = "\\d{3}";
5
+ const fourDigits = "\\d{4}";
6
+ const word = "[^\\s]+";
7
+ const literal = /\[([^]*?)\]/gm;
8
+
9
+ type DateInfo = {
10
+ year: number;
11
+ month: number;
12
+ day: number;
13
+ hour: number;
14
+ minute: number;
15
+ second: number;
16
+ millisecond: number;
17
+ isPm: number | null;
18
+ timezoneOffset: number | null;
19
+ };
20
+
21
+ export type I18nSettings = {
22
+ amPm: [string, string];
23
+ dayNames: Days;
24
+ dayNamesShort: Days;
25
+ monthNames: Months;
26
+ monthNamesShort: Months;
27
+ DoFn(dayOfMonth: number): string;
28
+ };
29
+
30
+ export type I18nSettingsOptional = Partial<I18nSettings>;
31
+
32
+ export type Days = [string, string, string, string, string, string, string];
33
+ export type Months = [
34
+ string,
35
+ string,
36
+ string,
37
+ string,
38
+ string,
39
+ string,
40
+ string,
41
+ string,
42
+ string,
43
+ string,
44
+ string,
45
+ string
46
+ ];
47
+
48
+ function shorten<T extends string[]>(arr: T, sLen: number): string[] {
49
+ const newArr: string[] = [];
50
+ for (let i = 0, len = arr.length; i < len; i++) {
51
+ newArr.push(arr[i].substr(0, sLen));
52
+ }
53
+ return newArr;
54
+ }
55
+
56
+ const monthUpdate = (
57
+ arrName: "monthNames" | "monthNamesShort" | "dayNames" | "dayNamesShort"
58
+ ) => (v: string, i18n: I18nSettings): number | null => {
59
+ const lowerCaseArr = i18n[arrName].map(v => v.toLowerCase());
60
+ const index = lowerCaseArr.indexOf(v.toLowerCase());
61
+ if (index > -1) {
62
+ return index;
63
+ }
64
+ return null;
65
+ };
66
+
67
+ export function assign<A>(a: A): A;
68
+ export function assign<A, B>(a: A, b: B): A & B;
69
+ export function assign<A, B, C>(a: A, b: B, c: C): A & B & C;
70
+ export function assign<A, B, C, D>(a: A, b: B, c: C, d: D): A & B & C & D;
71
+ export function assign(origObj: any, ...args: any[]): any {
72
+ for (const obj of args) {
73
+ for (const key in obj) {
74
+ // @ts-ignore ex
75
+ origObj[key] = obj[key];
76
+ }
77
+ }
78
+ return origObj;
79
+ }
80
+
81
+ const dayNames: Days = [
82
+ "Sunday",
83
+ "Monday",
84
+ "Tuesday",
85
+ "Wednesday",
86
+ "Thursday",
87
+ "Friday",
88
+ "Saturday"
89
+ ];
90
+ const monthNames: Months = [
91
+ "January",
92
+ "February",
93
+ "March",
94
+ "April",
95
+ "May",
96
+ "June",
97
+ "July",
98
+ "August",
99
+ "September",
100
+ "October",
101
+ "November",
102
+ "December"
103
+ ];
104
+
105
+ const monthNamesShort: Months = shorten(monthNames, 3) as Months;
106
+ const dayNamesShort: Days = shorten(dayNames, 3) as Days;
107
+
108
+ const defaultI18n: I18nSettings = {
109
+ dayNamesShort,
110
+ dayNames,
111
+ monthNamesShort,
112
+ monthNames,
113
+ amPm: ["am", "pm"],
114
+ DoFn(dayOfMonth: number) {
115
+ return (
116
+ dayOfMonth +
117
+ ["th", "st", "nd", "rd"][
118
+ dayOfMonth % 10 > 3
119
+ ? 0
120
+ : ((dayOfMonth - (dayOfMonth % 10) !== 10 ? 1 : 0) * dayOfMonth) % 10
121
+ ]
122
+ );
123
+ }
124
+ };
125
+ let globalI18n = assign({}, defaultI18n);
126
+ const setGlobalDateI18n = (i18n: I18nSettingsOptional): I18nSettings =>
127
+ (globalI18n = assign(globalI18n, i18n));
128
+
129
+ const regexEscape = (str: string): string =>
130
+ str.replace(/[|\\{()[^$+*?.-]/g, "\\$&");
131
+
132
+ const pad = (val: string | number, len = 2): string => {
133
+ val = String(val);
134
+ while (val.length < len) {
135
+ val = "0" + val;
136
+ }
137
+ return val;
138
+ };
139
+
140
+ const formatFlags: Record<
141
+ string,
142
+ (dateObj: Date, i18n: I18nSettings) => string
143
+ > = {
144
+ D: (dateObj: Date): string => String(dateObj.getDate()),
145
+ DD: (dateObj: Date): string => pad(dateObj.getDate()),
146
+ Do: (dateObj: Date, i18n: I18nSettings): string =>
147
+ i18n.DoFn(dateObj.getDate()),
148
+ d: (dateObj: Date): string => String(dateObj.getDay()),
149
+ dd: (dateObj: Date): string => pad(dateObj.getDay()),
150
+ ddd: (dateObj: Date, i18n: I18nSettings): string =>
151
+ i18n.dayNamesShort[dateObj.getDay()],
152
+ dddd: (dateObj: Date, i18n: I18nSettings): string =>
153
+ i18n.dayNames[dateObj.getDay()],
154
+ M: (dateObj: Date): string => String(dateObj.getMonth() + 1),
155
+ MM: (dateObj: Date): string => pad(dateObj.getMonth() + 1),
156
+ MMM: (dateObj: Date, i18n: I18nSettings): string =>
157
+ i18n.monthNamesShort[dateObj.getMonth()],
158
+ MMMM: (dateObj: Date, i18n: I18nSettings): string =>
159
+ i18n.monthNames[dateObj.getMonth()],
160
+ YY: (dateObj: Date): string =>
161
+ pad(String(dateObj.getFullYear()), 4).substr(2),
162
+ YYYY: (dateObj: Date): string => pad(dateObj.getFullYear(), 4),
163
+ h: (dateObj: Date): string => String(dateObj.getHours() % 12 || 12),
164
+ hh: (dateObj: Date): string => pad(dateObj.getHours() % 12 || 12),
165
+ H: (dateObj: Date): string => String(dateObj.getHours()),
166
+ HH: (dateObj: Date): string => pad(dateObj.getHours()),
167
+ m: (dateObj: Date): string => String(dateObj.getMinutes()),
168
+ mm: (dateObj: Date): string => pad(dateObj.getMinutes()),
169
+ s: (dateObj: Date): string => String(dateObj.getSeconds()),
170
+ ss: (dateObj: Date): string => pad(dateObj.getSeconds()),
171
+ S: (dateObj: Date): string =>
172
+ String(Math.round(dateObj.getMilliseconds() / 100)),
173
+ SS: (dateObj: Date): string =>
174
+ pad(Math.round(dateObj.getMilliseconds() / 10), 2),
175
+ SSS: (dateObj: Date): string => pad(dateObj.getMilliseconds(), 3),
176
+ a: (dateObj: Date, i18n: I18nSettings): string =>
177
+ dateObj.getHours() < 12 ? i18n.amPm[0] : i18n.amPm[1],
178
+ A: (dateObj: Date, i18n: I18nSettings): string =>
179
+ dateObj.getHours() < 12
180
+ ? i18n.amPm[0].toUpperCase()
181
+ : i18n.amPm[1].toUpperCase(),
182
+ ZZ(dateObj: Date): string {
183
+ const offset = dateObj.getTimezoneOffset();
184
+ return (
185
+ (offset > 0 ? "-" : "+") +
186
+ pad(Math.floor(Math.abs(offset) / 60) * 100 + (Math.abs(offset) % 60), 4)
187
+ );
188
+ },
189
+ Z(dateObj: Date): string {
190
+ const offset = dateObj.getTimezoneOffset();
191
+ return (
192
+ (offset > 0 ? "-" : "+") +
193
+ pad(Math.floor(Math.abs(offset) / 60), 2) +
194
+ ":" +
195
+ pad(Math.abs(offset) % 60, 2)
196
+ );
197
+ }
198
+ };
199
+
200
+ type ParseInfo = [
201
+ keyof DateInfo,
202
+ string,
203
+ ((v: string, i18n: I18nSettings) => number | null)?,
204
+ string?
205
+ ];
206
+ const monthParse = (v: string): number => +v - 1;
207
+ const emptyDigits: ParseInfo = [null, twoDigitsOptional];
208
+ const emptyWord: ParseInfo = [null, word];
209
+ const amPm: ParseInfo = [
210
+ "isPm",
211
+ word,
212
+ (v: string, i18n: I18nSettings): number | null => {
213
+ const val = v.toLowerCase();
214
+ if (val === i18n.amPm[0]) {
215
+ return 0;
216
+ } else if (val === i18n.amPm[1]) {
217
+ return 1;
218
+ }
219
+ return null;
220
+ }
221
+ ];
222
+ const timezoneOffset: ParseInfo = [
223
+ "timezoneOffset",
224
+ "[^\\s]*?[\\+\\-]\\d\\d:?\\d\\d|[^\\s]*?Z?",
225
+ (v: string): number | null => {
226
+ const parts = (v + "").match(/([+-]|\d\d)/gi);
227
+
228
+ if (parts) {
229
+ const minutes = +parts[1] * 60 + parseInt(parts[2], 10);
230
+ return parts[0] === "+" ? minutes : -minutes;
231
+ }
232
+
233
+ return 0;
234
+ }
235
+ ];
236
+ const parseFlags: Record<string, ParseInfo> = {
237
+ D: ["day", twoDigitsOptional],
238
+ DD: ["day", twoDigits],
239
+ Do: ["day", twoDigitsOptional + word, (v: string): number => parseInt(v, 10)],
240
+ M: ["month", twoDigitsOptional, monthParse],
241
+ MM: ["month", twoDigits, monthParse],
242
+ YY: [
243
+ "year",
244
+ twoDigits,
245
+ (v: string): number => {
246
+ const now = new Date();
247
+ const cent = +("" + now.getFullYear()).substr(0, 2);
248
+ return +("" + (+v > 68 ? cent - 1 : cent) + v);
249
+ }
250
+ ],
251
+ h: ["hour", twoDigitsOptional, undefined, "isPm"],
252
+ hh: ["hour", twoDigits, undefined, "isPm"],
253
+ H: ["hour", twoDigitsOptional],
254
+ HH: ["hour", twoDigits],
255
+ m: ["minute", twoDigitsOptional],
256
+ mm: ["minute", twoDigits],
257
+ s: ["second", twoDigitsOptional],
258
+ ss: ["second", twoDigits],
259
+ YYYY: ["year", fourDigits],
260
+ S: ["millisecond", "\\d", (v: string): number => +v * 100],
261
+ SS: ["millisecond", twoDigits, (v: string): number => +v * 10],
262
+ SSS: ["millisecond", threeDigits],
263
+ d: emptyDigits,
264
+ dd: emptyDigits,
265
+ ddd: emptyWord,
266
+ dddd: emptyWord,
267
+ MMM: ["month", word, monthUpdate("monthNamesShort")],
268
+ MMMM: ["month", word, monthUpdate("monthNames")],
269
+ a: amPm,
270
+ A: amPm,
271
+ ZZ: timezoneOffset,
272
+ Z: timezoneOffset
273
+ };
274
+
275
+ // Some common format strings
276
+ const globalMasks: { [key: string]: string } = {
277
+ default: "ddd MMM DD YYYY HH:mm:ss",
278
+ shortDate: "M/D/YY",
279
+ mediumDate: "MMM D, YYYY",
280
+ longDate: "MMMM D, YYYY",
281
+ fullDate: "dddd, MMMM D, YYYY",
282
+ isoDate: "YYYY-MM-DD",
283
+ isoDateTime: "YYYY-MM-DDTHH:mm:ssZ",
284
+ shortTime: "HH:mm",
285
+ mediumTime: "HH:mm:ss",
286
+ longTime: "HH:mm:ss.SSS"
287
+ };
288
+ const setGlobalDateMasks = (masks: {
289
+ [key: string]: string;
290
+ }): { [key: string]: string } => assign(globalMasks, masks);
291
+
292
+ /***
293
+ * Format a date
294
+ * @method format
295
+ * @param {Date|number} dateObj
296
+ * @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate'
297
+ * @returns {string} Formatted date string
298
+ */
299
+ const format = (
300
+ dateObj: Date,
301
+ mask: string = globalMasks["default"],
302
+ i18n: I18nSettingsOptional = {}
303
+ ): string => {
304
+ if (typeof dateObj === "number") {
305
+ dateObj = new Date(dateObj);
306
+ }
307
+
308
+ if (
309
+ Object.prototype.toString.call(dateObj) !== "[object Date]" ||
310
+ isNaN(dateObj.getTime())
311
+ ) {
312
+ throw new Error("Invalid Date pass to format");
313
+ }
314
+
315
+ mask = globalMasks[mask] || mask;
316
+
317
+ const literals: string[] = [];
318
+
319
+ // Make literals inactive by replacing them with @@@
320
+ mask = mask.replace(literal, function($0, $1) {
321
+ literals.push($1);
322
+ return "@@@";
323
+ });
324
+
325
+ const combinedI18nSettings: I18nSettings = assign(
326
+ assign({}, globalI18n),
327
+ i18n
328
+ );
329
+ // Apply formatting rules
330
+ mask = mask.replace(token, $0 =>
331
+ formatFlags[$0](dateObj, combinedI18nSettings)
332
+ );
333
+ // Inline literal values back into the formatted value
334
+ return mask.replace(/@@@/g, () => literals.shift());
335
+ };
336
+
337
+ /**
338
+ * Parse a date string into a Javascript Date object /
339
+ * @method parse
340
+ * @param {string} dateStr Date string
341
+ * @param {string} format Date parse format
342
+ * @param {i18n} I18nSettingsOptional Full or subset of I18N settings
343
+ * @returns {Date|null} Returns Date object. Returns null what date string is invalid or doesn't match format
344
+ */
345
+ function parse(
346
+ dateStr: string,
347
+ format: string,
348
+ i18n: I18nSettingsOptional = {}
349
+ ): Date | null {
350
+ if (typeof format !== "string") {
351
+ throw new Error("Invalid format in fecha parse");
352
+ }
353
+
354
+ // Check to see if the format is actually a mask
355
+ format = globalMasks[format] || format;
356
+
357
+ // Avoid regular expression denial of service, fail early for really long strings
358
+ // https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS
359
+ if (dateStr.length > 1000) {
360
+ return null;
361
+ }
362
+
363
+ // Default to the beginning of the year.
364
+ const today = new Date();
365
+ const dateInfo: DateInfo = {
366
+ year: today.getFullYear(),
367
+ month: 0,
368
+ day: 1,
369
+ hour: 0,
370
+ minute: 0,
371
+ second: 0,
372
+ millisecond: 0,
373
+ isPm: null,
374
+ timezoneOffset: null
375
+ };
376
+ const parseInfo: ParseInfo[] = [];
377
+ const literals: string[] = [];
378
+
379
+ // Replace all the literals with @@@. Hopefully a string that won't exist in the format
380
+ let newFormat = format.replace(literal, ($0, $1) => {
381
+ literals.push(regexEscape($1));
382
+ return "@@@";
383
+ });
384
+ const specifiedFields: { [field: string]: boolean } = {};
385
+ const requiredFields: { [field: string]: boolean } = {};
386
+
387
+ // Change every token that we find into the correct regex
388
+ newFormat = regexEscape(newFormat).replace(token, $0 => {
389
+ const info = parseFlags[$0];
390
+ const [field, regex, , requiredField] = info;
391
+
392
+ // Check if the person has specified the same field twice. This will lead to confusing results.
393
+ if (specifiedFields[field]) {
394
+ throw new Error(`Invalid format. ${field} specified twice in format`);
395
+ }
396
+
397
+ specifiedFields[field] = true;
398
+
399
+ // Check if there are any required fields. For instance, 12 hour time requires AM/PM specified
400
+ if (requiredField) {
401
+ requiredFields[requiredField] = true;
402
+ }
403
+
404
+ parseInfo.push(info);
405
+ return "(" + regex + ")";
406
+ });
407
+
408
+ // Check all the required fields are present
409
+ Object.keys(requiredFields).forEach(field => {
410
+ if (!specifiedFields[field]) {
411
+ throw new Error(
412
+ `Invalid format. ${field} is required in specified format`
413
+ );
414
+ }
415
+ });
416
+
417
+ // Add back all the literals after
418
+ newFormat = newFormat.replace(/@@@/g, () => literals.shift());
419
+
420
+ // Check if the date string matches the format. If it doesn't return null
421
+ const matches = dateStr.match(new RegExp(newFormat, "i"));
422
+ if (!matches) {
423
+ return null;
424
+ }
425
+
426
+ const combinedI18nSettings: I18nSettings = assign(
427
+ assign({}, globalI18n),
428
+ i18n
429
+ );
430
+
431
+ // For each match, call the parser function for that date part
432
+ for (let i = 1; i < matches.length; i++) {
433
+ const [field, , parser] = parseInfo[i - 1];
434
+ const value = parser
435
+ ? parser(matches[i], combinedI18nSettings)
436
+ : +matches[i];
437
+
438
+ // If the parser can't make sense of the value, return null
439
+ if (value == null) {
440
+ return null;
441
+ }
442
+
443
+ dateInfo[field] = value;
444
+ }
445
+
446
+ if (dateInfo.isPm === 1 && dateInfo.hour != null && +dateInfo.hour !== 12) {
447
+ dateInfo.hour = +dateInfo.hour + 12;
448
+ } else if (dateInfo.isPm === 0 && +dateInfo.hour === 12) {
449
+ dateInfo.hour = 0;
450
+ }
451
+
452
+ let dateTZ: Date;
453
+ if (dateInfo.timezoneOffset == null) {
454
+ dateTZ = new Date(
455
+ dateInfo.year,
456
+ dateInfo.month,
457
+ dateInfo.day,
458
+ dateInfo.hour,
459
+ dateInfo.minute,
460
+ dateInfo.second,
461
+ dateInfo.millisecond
462
+ );
463
+ const validateFields: [
464
+ "month" | "day" | "hour" | "minute" | "second",
465
+ "getMonth" | "getDate" | "getHours" | "getMinutes" | "getSeconds"
466
+ ][] = [
467
+ ["month", "getMonth"],
468
+ ["day", "getDate"],
469
+ ["hour", "getHours"],
470
+ ["minute", "getMinutes"],
471
+ ["second", "getSeconds"]
472
+ ];
473
+ for (let i = 0, len = validateFields.length; i < len; i++) {
474
+ // Check to make sure the date field is within the allowed range. Javascript dates allows values
475
+ // outside the allowed range. If the values don't match the value was invalid
476
+ if (
477
+ specifiedFields[validateFields[i][0]] &&
478
+ dateInfo[validateFields[i][0]] !== dateTZ[validateFields[i][1]]()
479
+ ) {
480
+ return null;
481
+ }
482
+ }
483
+ } else {
484
+ dateTZ = new Date(
485
+ Date.UTC(
486
+ dateInfo.year,
487
+ dateInfo.month,
488
+ dateInfo.day,
489
+ dateInfo.hour,
490
+ dateInfo.minute - dateInfo.timezoneOffset,
491
+ dateInfo.second,
492
+ dateInfo.millisecond
493
+ )
494
+ );
495
+
496
+ // We can't validate dates in another timezone unfortunately. Do a basic check instead
497
+ if (
498
+ dateInfo.month > 11 ||
499
+ dateInfo.month < 0 ||
500
+ dateInfo.day > 31 ||
501
+ dateInfo.day < 1 ||
502
+ dateInfo.hour > 23 ||
503
+ dateInfo.hour < 0 ||
504
+ dateInfo.minute > 59 ||
505
+ dateInfo.minute < 0 ||
506
+ dateInfo.second > 59 ||
507
+ dateInfo.second < 0
508
+ ) {
509
+ return null;
510
+ }
511
+ }
512
+
513
+ // Don't allow invalid dates
514
+
515
+ return dateTZ;
516
+ }
517
+ export default {
518
+ format,
519
+ parse,
520
+ defaultI18n,
521
+ setGlobalDateI18n,
522
+ setGlobalDateMasks
523
+ };
524
+ export { format, parse, defaultI18n, setGlobalDateI18n, setGlobalDateMasks };
@@ -1,5 +1,5 @@
1
1
  {
2
- "extends": "populist",
2
+ "extends": "@dabh/eslint-config-populist",
3
3
  "rules": {
4
4
  "no-undefined": 0,
5
5
  "strict": 0
@@ -1,5 +1,29 @@
1
1
  # CHANGELOG
2
2
 
3
+ ### 2.4.0
4
+ **2022/02/12**
5
+
6
+ - Updated all dependencies
7
+ - [#135] Use CLI levels (not NPM levels) in `CliFormat` (this was likely a typo originally)
8
+ - [#134] Expose `safe-stable-stringify` 2.x options as parameters in `JsonOptions`
9
+
10
+ ### 2.3.2
11
+ **2022/01/09**
12
+
13
+ This update, which also used up version number 2.3.1, pinned the version of the `colors` dependency
14
+ due to vandalism by a developer of that package, as noted [here](https://www.bleepingcomputer.com/news/security/dev-corrupts-npm-libs-colors-and-faker-breaking-thousands-of-apps/).
15
+ [As discussed in the `winston` package](https://github.com/winstonjs/winston/issues/2011), all users should update to this (or a later version, should one exist) ASAP.
16
+
17
+ ### 2.3.0
18
+ **2021/09/21**
19
+
20
+ - Update dependencies
21
+ - Removing some superfluous semicolons & commas lint
22
+ - Avoid dynamic requires [#117]
23
+ - Replace JSON stringify library "fast-safe-stringify" by "safe-stable-stringify" [#98]
24
+ - More correctly format errors even if the “message” property is enumerable [#101]
25
+ - Fix errors and ms export for browsers [#106]
26
+
3
27
  ### 2.2.0
4
28
  **2020/06/21**
5
29
 
@@ -43,7 +43,7 @@ message. The object itself is mutable. Every `info` must have at least the
43
43
 
44
44
  ``` js
45
45
  const info = {
46
- level: 'info', // Level of the logging message
46
+ level: 'info', // Level of the logging message
47
47
  message: 'Hey! Log something?' // Descriptive message being logged.
48
48
  }
49
49
  ```
@@ -57,10 +57,10 @@ const { level, message, ...meta } = info;
57
57
  Several of the formats in `logform` itself add additional properties:
58
58
 
59
59
  | Property | Format added by | Description |
60
- | ----------- | --------------- | ----------- |
60
+ | ----------- | --------------- | ----------- |
61
61
  | `splat` | `splat()` | String interpolation splat for `%d %s`-style messages. |
62
62
  | `timestamp` | `timestamp()` | timestamp the message was received. |
63
- | `label` | `label()` | Custom label associated with each message. |
63
+ | `label` | `label()` | Custom label associated with each message. |
64
64
  | `ms` | `ms()` | Number of milliseconds since the previous log message. |
65
65
 
66
66
  As a consumer you may add whatever properties you wish – _internal state is
@@ -105,7 +105,7 @@ They are expected to return one of two things:
105
105
  - **An `info` Object** representing the modified `info` argument. Object references need not be preserved if immutability is preferred. All current built-in formats consider `info` mutable, but [immutablejs] is being considered for future releases.
106
106
  - **A falsey value** indicating that the `info` argument should be ignored by the caller. (See: [Filtering `info` Objects](#filtering-info-objects)) below.
107
107
 
108
- `logform.format` is designed to be as simple as possible. To define a new format simple pass it a `transform(info, opts)` function to get a new `Format`.
108
+ `logform.format` is designed to be as simple as possible. To define a new format simple pass it a `transform(info, opts)` function to get a new `Format`.
109
109
 
110
110
  The named `Format` returned can be used to create as many copies of the given `Format` as desired:
111
111
 
@@ -114,7 +114,7 @@ const { format } = require('logform');
114
114
 
115
115
  const volume = format((info, opts) => {
116
116
  if (opts.yell) {
117
- info.message = info.message.toUpperCase();
117
+ info.message = info.message.toUpperCase();
118
118
  } else if (opts.whisper) {
119
119
  info.message = info.message.toLowerCase();
120
120
  }
@@ -135,9 +135,9 @@ console.dir(scream.transform({
135
135
 
136
136
  // `volume` can be used multiple times to create different formats.
137
137
  const whisper = volume({ whisper: true });
138
- console.dir(whisper.transform({
139
- level: 'info',
140
- message: `WHY ARE THEY MAKING US YELL SO MUCH!`
138
+ console.dir(whisper.transform({
139
+ level: 'info',
140
+ message: `WHY ARE THEY MAKING US YELL SO MUCH!`
141
141
  }), whisper.options);
142
142
  // {
143
143
  // level: 'info'
@@ -369,12 +369,11 @@ console.log(info);
369
369
 
370
370
  ### JSON
371
371
 
372
- The `json` format uses `fast-safe-stringify` to finalize the message.
372
+ The `json` format uses `safe-stable-stringify` to finalize the message.
373
373
  It accepts the following options:
374
374
 
375
375
  * **replacer**: A function that influences how the `info` is stringified.
376
376
  * **space**: The number of white space used to format the json.
377
- * **stable**: If set to `true` the objects' attributes will always be stringified in alphabetical order.
378
377
 
379
378
  ```js
380
379
  const { format } = require('logform');
@@ -384,7 +383,6 @@ const jsonFormat = format.json();
384
383
  const info = jsonFormat.transform({
385
384
  level: 'info',
386
385
  message: 'my message',
387
- stable: true,
388
386
  });
389
387
  console.log(info);
390
388
  // { level: 'info',
@@ -494,7 +492,7 @@ This was previously exposed as `{ padLevels: true }` to transports in `winston <
494
492
  The `prettyPrint` format finalizes the message using `util.inspect`.
495
493
  It accepts the following options:
496
494
 
497
- * **depth**: A `number` that specifies the maximum depth of the `info` object being stringified by `util.inspect`. Defaults to `2`.
495
+ * **depth**: A `number` that specifies the maximum depth of the `info` object being stringified by `util.inspect`. Defaults to `2`.
498
496
  * **colorize**: Colorizes the message if set to `true`. Defaults to `false`.
499
497
 
500
498
  The `prettyPrint` format should not be used in production because it may impact performance negatively and block the event loop.
@@ -607,11 +605,11 @@ This was previously exposed implicitly in `winston < 3.0.0`.
607
605
 
608
606
  ### Timestamp
609
607
 
610
- The `timestamp` format adds a timestamp to the info.
608
+ The `timestamp` format adds a timestamp to the info.
611
609
  It accepts the following options:
612
610
 
613
611
  * **format**: Either the format as a string accepted by the [fecha](https://github.com/taylorhakes/fecha) module or a function that returns a formatted date. If no format is provided `new Date().toISOString()` will be used.
614
- * **alias**: The name of an alias for the timestamp property, that will be added to the `info` object.
612
+ * **alias**: The name of an alias for the timestamp property, that will be added to the `info` object.
615
613
 
616
614
  ```js
617
615
  const { format } = require('logform');
@@ -637,9 +635,9 @@ It was previously available in `winston < 3.0.0` as `{ timestamp: true }` and `{
637
635
  The `uncolorize` format strips colors from `info` objects.
638
636
  It accepts the following options:
639
637
 
640
- * **level**: Disables the uncolorize format for `info.level` if set to `false`.
641
- * **message**: Disables the uncolorize format for `info.message` if set to `false`.
642
- * **raw**: Disables the uncolorize format for `info[MESSAGE]` if set to `false`.
638
+ * **level**: Disables the uncolorize format for `info.level` if set to `false`.
639
+ * **message**: Disables the uncolorize format for `info.message` if set to `false`.
640
+ * **raw**: Disables the uncolorize format for `info[MESSAGE]` if set to `false`.
643
641
 
644
642
  This was previously exposed as `{ stripColors: true }` to transports in `winston < 3.0.0`.
645
643
 
@@ -21,12 +21,14 @@ exports.levels = require('././levels');
21
21
  //
22
22
  Object.defineProperty(format, 'align', { value: require('./align') });
23
23
  Object.defineProperty(format, 'cli', { value: require('./cli') });
24
- Object.defineProperty(format, 'combine', { value: require('./combine') });
25
24
  Object.defineProperty(format, 'colorize', { value: require('./colorize') });
25
+ Object.defineProperty(format, 'combine', { value: require('./combine') });
26
+ Object.defineProperty(format, 'errors', { value: require('./errors') });
26
27
  Object.defineProperty(format, 'json', { value: require('./json') });
27
28
  Object.defineProperty(format, 'label', { value: require('./label') });
28
29
  Object.defineProperty(format, 'logstash', { value: require('./logstash') });
29
30
  Object.defineProperty(format, 'metadata', { value: require('./metadata') });
31
+ Object.defineProperty(format, 'ms', { value: require('./ms') });
30
32
  Object.defineProperty(format, 'padLevels', { value: require('./pad-levels') });
31
33
  Object.defineProperty(format, 'prettyPrint', { value: require('./pretty-print') });
32
34
  Object.defineProperty(format, 'printf', { value: require('./printf') });
@@ -12,7 +12,7 @@ const { configs, MESSAGE } = require('triple-beam');
12
12
  class CliFormat {
13
13
  constructor(opts = {}) {
14
14
  if (!opts.levels) {
15
- opts.levels = configs.npm.levels;
15
+ opts.levels = configs.cli.levels;
16
16
  }
17
17
 
18
18
  this.colorizer = new Colorizer(opts);