@monochromatic-dev/module-logger 0.2.0 → 0.3.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 (62) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +33 -8
  3. package/dist/final/neutral/browser.d.mts +60 -0
  4. package/dist/final/neutral/browser.mjs +1 -0
  5. package/dist/final/neutral/index.d.mts +360 -594
  6. package/dist/final/neutral/index.mjs +2 -3
  7. package/dist/final/neutral/indexed-db-hsIfv7Cv.mjs +2 -0
  8. package/dist/final/neutral/types-BkkBXgY3.d.mts +76 -0
  9. package/dist/final/node/file-CRGb1hDK.mjs +1 -0
  10. package/dist/final/node/index.d.mts +360 -594
  11. package/dist/final/node/index.mjs +3 -3
  12. package/dist/final/node/node.d.mts +103 -0
  13. package/dist/final/node/node.mjs +1 -0
  14. package/dist/final/node/types-BkkBXgY3.d.mts +76 -0
  15. package/package.json +18 -4
  16. package/src/artifact-platform-split.unit.test.ts +140 -0
  17. package/src/browser.ts +14 -0
  18. package/src/create-logger.ts +183 -183
  19. package/src/create-logger.unit.test.ts +112 -112
  20. package/src/default-sinks.neutral.ts +34 -0
  21. package/src/default-sinks.node.ts +32 -0
  22. package/src/error-format.ts +23 -23
  23. package/src/logger.ts +23 -50
  24. package/src/node.ts +23 -0
  25. package/src/sink/console-control-chars.ts +64 -64
  26. package/src/sink/console-control-chars.unit.test.ts +14 -14
  27. package/src/sink/console.ts +194 -194
  28. package/src/sink/console.unit.test.ts +18 -18
  29. package/src/sink/file.ts +136 -140
  30. package/src/sink/file.unit.test.ts +19 -26
  31. package/src/sink/index.ts +4 -7
  32. package/src/sink/indexed-db-util.ts +42 -42
  33. package/src/sink/indexed-db.browser.test.ts +7 -7
  34. package/src/sink/indexed-db.ts +109 -109
  35. package/src/sink/indexed-db.unit.test.ts +5 -13
  36. package/src/sink/local-storage-key.ts +73 -73
  37. package/src/sink/local-storage-key.unit.test.ts +8 -8
  38. package/src/sink/local-storage-quota.ts +37 -37
  39. package/src/sink/local-storage-quota.unit.test.ts +8 -8
  40. package/src/sink/local-storage-store.ts +113 -113
  41. package/src/sink/local-storage-store.unit.test.ts +35 -35
  42. package/src/sink/local-storage.ts +72 -72
  43. package/src/sink/local-storage.unit.test.ts +27 -27
  44. package/src/sink/noop.ts +20 -20
  45. package/src/sink/noop.unit.test.ts +1 -1
  46. package/src/sink/opfs.browser.test.ts +7 -7
  47. package/src/sink/opfs.ts +62 -62
  48. package/src/sink/opfs.unit.test.ts +5 -13
  49. package/src/sink/record-buffer.ts +84 -84
  50. package/src/sink/record-buffer.unit.test.ts +20 -20
  51. package/src/sink/session-storage-quota.ts +34 -34
  52. package/src/sink/session-storage-quota.unit.test.ts +8 -8
  53. package/src/sink/session-storage-store.ts +72 -72
  54. package/src/sink/session-storage.ts +48 -48
  55. package/src/sink/session-storage.unit.test.ts +39 -39
  56. package/src/sink/web-storage-quota-error.ts +22 -22
  57. package/src/sink/web-storage-quota-error.unit.test.ts +2 -2
  58. package/src/sink/web-storage-runtime.ts +24 -24
  59. package/src/startup.unit.test.ts +18 -18
  60. package/src/tagged.ts +35 -35
  61. package/src/tagged.unit.test.ts +8 -8
  62. package/src/types.ts +39 -39
@@ -1,68 +1,68 @@
1
1
  /**
2
- * Console-bound text crosses a syntax boundary: a terminal interprets C0 and
3
- * C1 control characters as commands (clear screen, set title, move cursor,
4
- * write clipboard). Log messages can carry attacker-influenced text, so the
5
- * console sink neutralizes every control character except newline and tab
6
- * before the text reaches `console.*` or `process.stderr`.
7
- *
8
- * @module
2
+ Console-bound text crosses a syntax boundary: a terminal interprets C0 and
3
+ C1 control characters as commands (clear screen, set title, move cursor,
4
+ write clipboard). Log messages can carry attacker-influenced text, so the
5
+ console sink neutralizes every control character except newline and tab
6
+ before the text reaches `console.*` or `process.stderr`.
7
+
8
+ @module
9
9
  */
10
10
 
11
11
  /**
12
- * First code unit above the C0 control range; everything below it except
13
- * newline and tab is neutralized.
12
+ First code unit above the C0 control range; everything below it except
13
+ newline and tab is neutralized.
14
14
  */
15
15
  const C0_CONTROL_LIMIT = 0x20;
16
16
 
17
17
  /**
18
- * Newline stays literal: multi-line messages (stack traces) are a core use.
18
+ Newline stays literal: multi-line messages (stack traces) are a core use.
19
19
  */
20
20
  const NEWLINE_CODE_UNIT = 0x0A;
21
21
 
22
22
  /**
23
- * Tab stays literal: indentation in multi-line messages is harmless.
23
+ Tab stays literal: indentation in multi-line messages is harmless.
24
24
  */
25
25
  const TAB_CODE_UNIT = 0x09;
26
26
 
27
27
  /**
28
- * DEL sits alone above the printable ASCII range and is a control character.
28
+ DEL sits alone above the printable ASCII range and is a control character.
29
29
  */
30
30
  const DELETE_CODE_UNIT = 0x7F;
31
31
 
32
32
  /**
33
- * First code unit of the C1 control range (8-bit CSI, OSC, and friends).
33
+ First code unit of the C1 control range (8-bit CSI, OSC, and friends).
34
34
  */
35
35
  const C1_CONTROL_START = 0x80;
36
36
 
37
37
  /**
38
- * Last code unit of the C1 control range.
38
+ Last code unit of the C1 control range.
39
39
  */
40
40
  const C1_CONTROL_END = 0x9F;
41
41
 
42
42
  /**
43
- * Radix for the hexadecimal digits inside a `\uXXXX` escape.
43
+ Radix for the hexadecimal digits inside a `\uXXXX` escape.
44
44
  */
45
45
  const HEX_RADIX = 16;
46
46
 
47
47
  /**
48
- * Digit count of a `\uXXXX` escape, zero-padded on the left.
48
+ Digit count of a `\uXXXX` escape, zero-padded on the left.
49
49
  */
50
50
  const UNICODE_ESCAPE_WIDTH = 4;
51
51
 
52
52
  /**
53
- * Reports whether one UTF-16 code unit is a control character the console
54
- * sink must neutralize.
55
- *
56
- * @param codeUnit - UTF-16 code unit read from the message.
57
- *
58
- * @returns Whether the code unit is a C0 control other than newline and tab,
59
- * DEL, or a C1 control.
60
- *
61
- * @example
62
- * ```ts
63
- * isNeutralizedControl(0x1B); // true (ESC)
64
- * isNeutralizedControl(0x0A); // false (newline stays)
65
- * ```
53
+ Reports whether one UTF-16 code unit is a control character the console
54
+ sink must neutralize.
55
+
56
+ @param codeUnit - UTF-16 code unit read from the message.
57
+
58
+ @returns Whether the code unit is a C0 control other than newline and tab,
59
+ DEL, or a C1 control.
60
+
61
+ @example
62
+ ```ts
63
+ isNeutralizedControl(0x1B); // true (ESC)
64
+ isNeutralizedControl(0x0A); // false (newline stays)
65
+ ```
66
66
  */
67
67
  function isNeutralizedControl(codeUnit: number,): boolean {
68
68
  if (codeUnit < C0_CONTROL_LIMIT)
@@ -75,18 +75,18 @@ function isNeutralizedControl(codeUnit: number,): boolean {
75
75
  }
76
76
 
77
77
  /**
78
- * Renders one code unit as a `\uXXXX` escape with uppercase hex digits (the
79
- * repository's escape-case convention) so the attempted control stays
80
- * visible for forensics instead of vanishing.
81
- *
82
- * @param codeUnit - UTF-16 code unit to escape.
83
- *
84
- * @returns Six-character escape such as `\u001B`.
85
- *
86
- * @example
87
- * ```ts
88
- * escapeCodeUnit(0x1B); // '\\u001B'
89
- * ```
78
+ Renders one code unit as a `\uXXXX` escape with uppercase hex digits (the
79
+ repository's escape-case convention) so the attempted control stays
80
+ visible for forensics instead of vanishing.
81
+
82
+ @param codeUnit - UTF-16 code unit to escape.
83
+
84
+ @returns Six-character escape such as `\u001B`.
85
+
86
+ @example
87
+ ```ts
88
+ escapeCodeUnit(0x1B); // '\\u001B'
89
+ ```
90
90
  */
91
91
  function escapeCodeUnit(codeUnit: number,): string {
92
92
  return `\\u${
@@ -101,36 +101,36 @@ function escapeCodeUnit(codeUnit: number,): string {
101
101
  }
102
102
 
103
103
  /**
104
- * Neutralizes terminal control characters in console-bound text. One linear
105
- * pass over the code points: each neutralized control becomes a `\uXXXX`
106
- * escape, everything else is copied through, and newline and tab pass
107
- * untouched. Well-formed and malformed escape sequences get no
108
- * special treatment because the introducer byte itself is neutralized, so a
109
- * trailing lone ESC, an unterminated OSC, and a nested ESC all lose their
110
- * teeth the same way.
111
- *
112
- * @param text - Message text destined for `console.*` or `process.stderr`.
113
- *
114
- * @returns Text with every neutralized control rendered as `\uXXXX`.
115
- *
116
- * @example
117
- * ```ts
118
- * neutralizeControlCharacters('title:\u001B]0;x\u0007 ok\n\tnext');
119
- * // => 'title:\\u001B]0;x\\u0007 ok\n\tnext'
120
- * ```
104
+ Neutralizes terminal control characters in console-bound text. One linear
105
+ pass over the code points: each neutralized control becomes a `\uXXXX`
106
+ escape, everything else is copied through, and newline and tab pass
107
+ untouched. Well-formed and malformed escape sequences get no
108
+ special treatment because the introducer byte itself is neutralized, so a
109
+ trailing lone ESC, an unterminated OSC, and a nested ESC all lose their
110
+ teeth the same way.
111
+
112
+ @param text - Message text destined for `console.*` or `process.stderr`.
113
+
114
+ @returns Text with every neutralized control rendered as `\uXXXX`.
115
+
116
+ @example
117
+ ```ts
118
+ neutralizeControlCharacters('title:\u001B]0;x\u0007 ok\n\tnext');
119
+ // => 'title:\\u001B]0;x\\u0007 ok\n\tnext'
120
+ ```
121
121
  */
122
122
  export function neutralizeControlCharacters(text: string,): string {
123
123
  /**
124
- * Output pieces in input order: each code point either verbatim or as its
125
- * escape, joined once at the end so no per-character string rebuild occurs.
124
+ Output pieces in input order: each code point either verbatim or as its
125
+ escape, joined once at the end so no per-character string rebuild occurs.
126
126
  */
127
127
  const pieces: string[] = [];
128
128
  for (const character of text) {
129
129
  /**
130
- * Leading code unit of this iteration element. String iteration walks
131
- * code points, so a surrogate pair arrives as one two-unit string whose
132
- * lead surrogate is never a control, and a lone surrogate passes the
133
- * same way.
130
+ Leading code unit of this iteration element. String iteration walks
131
+ code points, so a surrogate pair arrives as one two-unit string whose
132
+ lead surrogate is never a control, and a lone surrogate passes the
133
+ same way.
134
134
  */
135
135
  // oxlint-disable-next-line unicorn/prefer-code-point -- Classifier reads the lead code unit on purpose; controls below U+00A0 never sit inside a surrogate pair, so code-point decoding adds nothing.
136
136
  const codeUnit = character.charCodeAt(0,);
@@ -8,9 +8,9 @@ import {
8
8
  } from '@monochromatic-dev/module-logger';
9
9
 
10
10
  /**
11
- * Adversarial inputs at the terminal boundary paired with the exact output
12
- * the neutralizer must produce. Each case names the attack or the malformed
13
- * shape it pins.
11
+ Adversarial inputs at the terminal boundary paired with the exact output
12
+ the neutralizer must produce. Each case names the attack or the malformed
13
+ shape it pins.
14
14
  */
15
15
  const BOUNDARY_CASES: readonly {
16
16
  readonly name: string;
@@ -80,7 +80,7 @@ const BOUNDARY_CASES: readonly {
80
80
  ];
81
81
 
82
82
  /**
83
- * Inputs the neutralizer must return unchanged.
83
+ Inputs the neutralizer must return unchanged.
84
84
  */
85
85
  const PASSTHROUGH_CASES: readonly {
86
86
  readonly name: string;
@@ -117,17 +117,17 @@ const PASSTHROUGH_CASES: readonly {
117
117
  ];
118
118
 
119
119
  /**
120
- * One past the last C1 code unit; the exhaustive sweep covers every code unit
121
- * below it.
120
+ One past the last C1 code unit; the exhaustive sweep covers every code unit
121
+ below it.
122
122
  */
123
123
  const CONTROL_SWEEP_LENGTH = 0xA0;
124
124
 
125
125
  /**
126
- * Reports whether an output code unit is still a control the boundary forbids.
127
- *
128
- * @param codeUnit - UTF-16 code unit read from neutralizer output.
129
- *
130
- * @returns Whether the code unit should have been neutralized.
126
+ Reports whether an output code unit is still a control the boundary forbids.
127
+
128
+ @param codeUnit - UTF-16 code unit read from neutralizer output.
129
+
130
+ @returns Whether the code unit should have been neutralized.
131
131
  */
132
132
  function isForbiddenControl(codeUnit: number,): boolean {
133
133
  if (codeUnit < 0x20)
@@ -156,7 +156,7 @@ await describe({
156
156
  name: 'output never contains a neutralized control after the pass',
157
157
  fn: async () => {
158
158
  /**
159
- * Every code unit from NUL through U+009F, in one string.
159
+ Every code unit from NUL through U+009F, in one string.
160
160
  */
161
161
  const allControls = Array.from(
162
162
  { length: CONTROL_SWEEP_LENGTH, },
@@ -169,11 +169,11 @@ await describe({
169
169
  )
170
170
  .join('',);
171
171
  /**
172
- * Neutralized sweep; only newline and tab may survive as controls.
172
+ Neutralized sweep; only newline and tab may survive as controls.
173
173
  */
174
174
  const output = neutralizeControlCharacters(allControls,);
175
175
  /**
176
- * Output code units that are still forbidden controls; must stay empty.
176
+ Output code units that are still forbidden controls; must stay empty.
177
177
  */
178
178
  const leaked: number[] = [];
179
179
  for (const character of output) {