react-native-nitro-logger 0.1.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 (205) hide show
  1. package/LICENSE +20 -0
  2. package/NitroLogger.podspec +29 -0
  3. package/README.md +214 -0
  4. package/android/CMakeLists.txt +24 -0
  5. package/android/build.gradle +124 -0
  6. package/android/src/main/AndroidManifest.xml +2 -0
  7. package/android/src/main/cpp/cpp-adapter.cpp +11 -0
  8. package/android/src/main/java/com/margelo/nitro/nitrologger/AndroidPlatformIo.kt +100 -0
  9. package/android/src/main/java/com/margelo/nitro/nitrologger/HybridFileSink.kt +292 -0
  10. package/android/src/main/java/com/margelo/nitro/nitrologger/HybridNativeConsoleSink.kt +23 -0
  11. package/android/src/main/java/com/margelo/nitro/nitrologger/LogFileWriter.kt +1328 -0
  12. package/android/src/main/java/com/margelo/nitro/nitrologger/LogRotationPolicy.kt +186 -0
  13. package/android/src/main/java/com/margelo/nitro/nitrologger/LogSecureFile.kt +80 -0
  14. package/android/src/main/java/com/margelo/nitro/nitrologger/LogWriterRegistry.kt +420 -0
  15. package/android/src/main/java/com/margelo/nitro/nitrologger/NativeConsoleWriter.kt +237 -0
  16. package/android/src/main/java/com/margelo/nitro/nitrologger/NitroLoggerPackage.kt +22 -0
  17. package/android/src/main/java/com/margelo/nitro/nitrologger/PlatformIo.kt +165 -0
  18. package/docs/PARITY.md +330 -0
  19. package/docs/PRIVACY.md +341 -0
  20. package/eslint-plugin/README.md +238 -0
  21. package/eslint-plugin/index.js +62 -0
  22. package/eslint-plugin/rules/literal-subsystem.js +102 -0
  23. package/eslint-plugin/rules/no-computed-metadata-key.js +174 -0
  24. package/eslint-plugin/rules/no-derived-correlation.js +171 -0
  25. package/eslint-plugin/rules/no-dynamic-message.js +60 -0
  26. package/eslint-plugin/shared.js +1948 -0
  27. package/ios/Gzip.swift +203 -0
  28. package/ios/HybridFileSink.swift +291 -0
  29. package/ios/HybridNativeConsoleSink.swift +20 -0
  30. package/ios/LogFileWriter.swift +1280 -0
  31. package/ios/LogSecureFile.swift +296 -0
  32. package/ios/LogWriterRegistry.swift +444 -0
  33. package/ios/NativeConsoleWriter.swift +180 -0
  34. package/lib/module/Logger.js +381 -0
  35. package/lib/module/Logger.js.map +1 -0
  36. package/lib/module/ScopedLogger.js +70 -0
  37. package/lib/module/ScopedLogger.js.map +1 -0
  38. package/lib/module/config.js +23 -0
  39. package/lib/module/config.js.map +1 -0
  40. package/lib/module/destinations/Batcher.js +647 -0
  41. package/lib/module/destinations/Batcher.js.map +1 -0
  42. package/lib/module/destinations/ConsoleDestination.js +51 -0
  43. package/lib/module/destinations/ConsoleDestination.js.map +1 -0
  44. package/lib/module/destinations/FileDestination.js +360 -0
  45. package/lib/module/destinations/FileDestination.js.map +1 -0
  46. package/lib/module/destinations/NativeConsoleDestination.js +170 -0
  47. package/lib/module/destinations/NativeConsoleDestination.js.map +1 -0
  48. package/lib/module/destinations/types.js +4 -0
  49. package/lib/module/destinations/types.js.map +1 -0
  50. package/lib/module/formatters/DefaultFormatter.js +136 -0
  51. package/lib/module/formatters/DefaultFormatter.js.map +1 -0
  52. package/lib/module/formatters/JsonLinesFormatter.js +162 -0
  53. package/lib/module/formatters/JsonLinesFormatter.js.map +1 -0
  54. package/lib/module/formatters/timestamp.js +15 -0
  55. package/lib/module/formatters/timestamp.js.map +1 -0
  56. package/lib/module/formatters/types.js +4 -0
  57. package/lib/module/formatters/types.js.map +1 -0
  58. package/lib/module/index.js +31 -0
  59. package/lib/module/index.js.map +1 -0
  60. package/lib/module/integrations/appState.js +81 -0
  61. package/lib/module/integrations/appState.js.map +1 -0
  62. package/lib/module/integrations/errorHandler.js +166 -0
  63. package/lib/module/integrations/errorHandler.js.map +1 -0
  64. package/lib/module/integrations/sanitizeError.js +238 -0
  65. package/lib/module/integrations/sanitizeError.js.map +1 -0
  66. package/lib/module/levels.js +35 -0
  67. package/lib/module/levels.js.map +1 -0
  68. package/lib/module/metadata.js +52 -0
  69. package/lib/module/metadata.js.map +1 -0
  70. package/lib/module/package.json +1 -0
  71. package/lib/module/privacy.js +349 -0
  72. package/lib/module/privacy.js.map +1 -0
  73. package/lib/module/specs/FileSink.nitro.js +4 -0
  74. package/lib/module/specs/FileSink.nitro.js.map +1 -0
  75. package/lib/module/specs/NativeConsoleSink.nitro.js +4 -0
  76. package/lib/module/specs/NativeConsoleSink.nitro.js.map +1 -0
  77. package/lib/module/types.js +4 -0
  78. package/lib/module/types.js.map +1 -0
  79. package/lib/module/utf8.js +42 -0
  80. package/lib/module/utf8.js.map +1 -0
  81. package/lib/typescript/package.json +1 -0
  82. package/lib/typescript/src/Logger.d.ts +122 -0
  83. package/lib/typescript/src/Logger.d.ts.map +1 -0
  84. package/lib/typescript/src/ScopedLogger.d.ts +36 -0
  85. package/lib/typescript/src/ScopedLogger.d.ts.map +1 -0
  86. package/lib/typescript/src/config.d.ts +12 -0
  87. package/lib/typescript/src/config.d.ts.map +1 -0
  88. package/lib/typescript/src/destinations/Batcher.d.ts +244 -0
  89. package/lib/typescript/src/destinations/Batcher.d.ts.map +1 -0
  90. package/lib/typescript/src/destinations/ConsoleDestination.d.ts +27 -0
  91. package/lib/typescript/src/destinations/ConsoleDestination.d.ts.map +1 -0
  92. package/lib/typescript/src/destinations/FileDestination.d.ts +200 -0
  93. package/lib/typescript/src/destinations/FileDestination.d.ts.map +1 -0
  94. package/lib/typescript/src/destinations/NativeConsoleDestination.d.ts +86 -0
  95. package/lib/typescript/src/destinations/NativeConsoleDestination.d.ts.map +1 -0
  96. package/lib/typescript/src/destinations/types.d.ts +19 -0
  97. package/lib/typescript/src/destinations/types.d.ts.map +1 -0
  98. package/lib/typescript/src/formatters/DefaultFormatter.d.ts +22 -0
  99. package/lib/typescript/src/formatters/DefaultFormatter.d.ts.map +1 -0
  100. package/lib/typescript/src/formatters/JsonLinesFormatter.d.ts +73 -0
  101. package/lib/typescript/src/formatters/JsonLinesFormatter.d.ts.map +1 -0
  102. package/lib/typescript/src/formatters/timestamp.d.ts +6 -0
  103. package/lib/typescript/src/formatters/timestamp.d.ts.map +1 -0
  104. package/lib/typescript/src/formatters/types.d.ts +27 -0
  105. package/lib/typescript/src/formatters/types.d.ts.map +1 -0
  106. package/lib/typescript/src/index.d.ts +34 -0
  107. package/lib/typescript/src/index.d.ts.map +1 -0
  108. package/lib/typescript/src/integrations/appState.d.ts +33 -0
  109. package/lib/typescript/src/integrations/appState.d.ts.map +1 -0
  110. package/lib/typescript/src/integrations/errorHandler.d.ts +55 -0
  111. package/lib/typescript/src/integrations/errorHandler.d.ts.map +1 -0
  112. package/lib/typescript/src/integrations/sanitizeError.d.ts +89 -0
  113. package/lib/typescript/src/integrations/sanitizeError.d.ts.map +1 -0
  114. package/lib/typescript/src/levels.d.ts +9 -0
  115. package/lib/typescript/src/levels.d.ts.map +1 -0
  116. package/lib/typescript/src/metadata.d.ts +23 -0
  117. package/lib/typescript/src/metadata.d.ts.map +1 -0
  118. package/lib/typescript/src/privacy.d.ts +103 -0
  119. package/lib/typescript/src/privacy.d.ts.map +1 -0
  120. package/lib/typescript/src/specs/FileSink.nitro.d.ts +131 -0
  121. package/lib/typescript/src/specs/FileSink.nitro.d.ts.map +1 -0
  122. package/lib/typescript/src/specs/NativeConsoleSink.nitro.d.ts +21 -0
  123. package/lib/typescript/src/specs/NativeConsoleSink.nitro.d.ts.map +1 -0
  124. package/lib/typescript/src/types.d.ts +37 -0
  125. package/lib/typescript/src/types.d.ts.map +1 -0
  126. package/lib/typescript/src/utf8.d.ts +15 -0
  127. package/lib/typescript/src/utf8.d.ts.map +1 -0
  128. package/nitro.json +33 -0
  129. package/nitrogen/generated/android/c++/JAppendResult.hpp +79 -0
  130. package/nitrogen/generated/android/c++/JClearOutcome.hpp +88 -0
  131. package/nitrogen/generated/android/c++/JFlushOutcome.hpp +81 -0
  132. package/nitrogen/generated/android/c++/JHybridFileSinkSpec.cpp +120 -0
  133. package/nitrogen/generated/android/c++/JHybridFileSinkSpec.hpp +69 -0
  134. package/nitrogen/generated/android/c++/JHybridNativeConsoleSinkSpec.cpp +71 -0
  135. package/nitrogen/generated/android/c++/JHybridNativeConsoleSinkSpec.hpp +64 -0
  136. package/nitrogen/generated/android/c++/JRejectReason.hpp +64 -0
  137. package/nitrogen/generated/android/c++/JRotationConfig.hpp +77 -0
  138. package/nitrogen/generated/android/c++/JSinkStatus.hpp +69 -0
  139. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/AppendResult.kt +76 -0
  140. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/ClearOutcome.kt +66 -0
  141. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/FlushOutcome.kt +81 -0
  142. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/HybridFileSinkSpec.kt +80 -0
  143. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/HybridNativeConsoleSinkSpec.kt +58 -0
  144. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/RejectReason.kt +25 -0
  145. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/RotationConfig.kt +76 -0
  146. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/SinkStatus.kt +66 -0
  147. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/nitrologgerOnLoad.kt +35 -0
  148. package/nitrogen/generated/android/nitrologger+autolinking.cmake +83 -0
  149. package/nitrogen/generated/android/nitrologger+autolinking.gradle +27 -0
  150. package/nitrogen/generated/android/nitrologgerOnLoad.cpp +70 -0
  151. package/nitrogen/generated/android/nitrologgerOnLoad.hpp +34 -0
  152. package/nitrogen/generated/ios/NitroLogger+autolinking.rb +62 -0
  153. package/nitrogen/generated/ios/NitroLogger-Swift-Cxx-Bridge.cpp +50 -0
  154. package/nitrogen/generated/ios/NitroLogger-Swift-Cxx-Bridge.hpp +216 -0
  155. package/nitrogen/generated/ios/NitroLogger-Swift-Cxx-Umbrella.hpp +69 -0
  156. package/nitrogen/generated/ios/NitroLoggerAutolinking.mm +41 -0
  157. package/nitrogen/generated/ios/NitroLoggerAutolinking.swift +38 -0
  158. package/nitrogen/generated/ios/c++/HybridFileSinkSpecSwift.cpp +11 -0
  159. package/nitrogen/generated/ios/c++/HybridFileSinkSpecSwift.hpp +150 -0
  160. package/nitrogen/generated/ios/c++/HybridNativeConsoleSinkSpecSwift.cpp +11 -0
  161. package/nitrogen/generated/ios/c++/HybridNativeConsoleSinkSpecSwift.hpp +87 -0
  162. package/nitrogen/generated/ios/swift/AppendResult.swift +60 -0
  163. package/nitrogen/generated/ios/swift/ClearOutcome.swift +50 -0
  164. package/nitrogen/generated/ios/swift/FlushOutcome.swift +59 -0
  165. package/nitrogen/generated/ios/swift/HybridFileSinkSpec.swift +61 -0
  166. package/nitrogen/generated/ios/swift/HybridFileSinkSpec_cxx.swift +227 -0
  167. package/nitrogen/generated/ios/swift/HybridNativeConsoleSinkSpec.swift +56 -0
  168. package/nitrogen/generated/ios/swift/HybridNativeConsoleSinkSpec_cxx.swift +148 -0
  169. package/nitrogen/generated/ios/swift/RejectReason.swift +48 -0
  170. package/nitrogen/generated/ios/swift/RotationConfig.swift +93 -0
  171. package/nitrogen/generated/ios/swift/SinkStatus.swift +44 -0
  172. package/nitrogen/generated/shared/c++/AppendResult.hpp +105 -0
  173. package/nitrogen/generated/shared/c++/ClearOutcome.hpp +96 -0
  174. package/nitrogen/generated/shared/c++/FlushOutcome.hpp +107 -0
  175. package/nitrogen/generated/shared/c++/HybridFileSinkSpec.cpp +28 -0
  176. package/nitrogen/generated/shared/c++/HybridFileSinkSpec.hpp +84 -0
  177. package/nitrogen/generated/shared/c++/HybridNativeConsoleSinkSpec.cpp +22 -0
  178. package/nitrogen/generated/shared/c++/HybridNativeConsoleSinkSpec.hpp +64 -0
  179. package/nitrogen/generated/shared/c++/RejectReason.hpp +84 -0
  180. package/nitrogen/generated/shared/c++/RotationConfig.hpp +103 -0
  181. package/nitrogen/generated/shared/c++/SinkStatus.hpp +95 -0
  182. package/package.json +151 -0
  183. package/src/Logger.ts +417 -0
  184. package/src/ScopedLogger.ts +94 -0
  185. package/src/config.ts +25 -0
  186. package/src/destinations/Batcher.ts +805 -0
  187. package/src/destinations/ConsoleDestination.ts +60 -0
  188. package/src/destinations/FileDestination.ts +473 -0
  189. package/src/destinations/NativeConsoleDestination.ts +220 -0
  190. package/src/destinations/types.ts +19 -0
  191. package/src/formatters/DefaultFormatter.ts +150 -0
  192. package/src/formatters/JsonLinesFormatter.ts +195 -0
  193. package/src/formatters/timestamp.ts +12 -0
  194. package/src/formatters/types.ts +29 -0
  195. package/src/index.tsx +106 -0
  196. package/src/integrations/appState.ts +111 -0
  197. package/src/integrations/errorHandler.ts +223 -0
  198. package/src/integrations/sanitizeError.ts +287 -0
  199. package/src/levels.ts +35 -0
  200. package/src/metadata.ts +52 -0
  201. package/src/privacy.ts +389 -0
  202. package/src/specs/FileSink.nitro.ts +144 -0
  203. package/src/specs/NativeConsoleSink.nitro.ts +21 -0
  204. package/src/types.ts +45 -0
  205. package/src/utf8.ts +39 -0
@@ -0,0 +1,238 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Turning a thrown value into something a log file is allowed to contain.
5
+ *
6
+ * An uncaught error is the one place the logger handles a string it did not
7
+ * construct, cannot see the provenance of, and did not put through the privacy
8
+ * layer. `new Error(\`no chart for ${patient.mrn}\`)` is an entirely ordinary
9
+ * line of application code, and its message reaches here verbatim. So nothing
10
+ * from the error is trusted: the class name is allowlisted down to a fixed
11
+ * token, the message is dropped outside dev, and stack frames are reduced to a
12
+ * position in a file whose name we already knew.
13
+ *
14
+ * The result is safe enough to mark `pub()`, which is the point — sanitising is
15
+ * what earns an error the right to be rendered.
16
+ */
17
+
18
+ /**
19
+ * Error constructors the language itself defines. A name from this set says
20
+ * only which built-in was thrown, which is a fact about the runtime rather than
21
+ * about the data.
22
+ *
23
+ * Anything else collapses to {@link UNKNOWN_ERROR_NAME}. A custom subclass is
24
+ * named by application code, and `class PatientNotFoundError` is a perfectly
25
+ * natural thing to write and a perfectly bad thing to log.
26
+ */
27
+ const BUILT_IN_ERROR_NAMES = new Set(['Error', 'AggregateError', 'EvalError', 'RangeError', 'ReferenceError', 'SyntaxError', 'TypeError', 'URIError']);
28
+
29
+ /** What an unrecognised error class is reported as. */
30
+ export const UNKNOWN_ERROR_NAME = 'Error';
31
+
32
+ /** What a stack frame in a file we cannot vouch for is reported as. */
33
+ export const REDACTED_FRAME = '<frame>';
34
+
35
+ /** What an error message is reported as outside a dev build. */
36
+ export const REDACTED_MESSAGE = '<redacted>';
37
+
38
+ /** What a thrown non-Error is reported as. */
39
+ export const NON_ERROR_THROWN = '<non-error>';
40
+
41
+ /**
42
+ * Bundle basenames a frame may be named after.
43
+ *
44
+ * A frame is only useful if you can find the file, and the files an app ships
45
+ * are known in advance. Everything else — a path from `node_modules`, a
46
+ * `blob:` URL, a filename built at runtime — is reported positionally instead.
47
+ * R3's point stands on its own: a basename can be perfectly regex-valid and
48
+ * still be `patient-12345.js`.
49
+ */
50
+ export const DEFAULT_BUNDLE_NAMES = ['index.bundle', 'main.jsbundle', 'index.android.bundle', 'index.ios.bundle'];
51
+
52
+ /** Frames beyond this are dropped; the count of what was dropped is kept. */
53
+ export const DEFAULT_MAX_FRAMES = 12;
54
+
55
+ /**
56
+ * How much of a stack is read at all, regardless of how many frames are kept.
57
+ *
58
+ * `stack` is a property of an object someone threw, which means its size is
59
+ * chosen by whatever threw it and not by any engine limit. Splitting it whole
60
+ * to count frames we then discard hands an arbitrary allocation to the one
61
+ * code path that runs while the app is already crashing. A real Hermes or V8
62
+ * stack is a few kilobytes and a few dozen lines; anything past these bounds
63
+ * is reported as truncated rather than read.
64
+ */
65
+ export const MAX_STACK_CHARS = 64 * 1024;
66
+ export const MAX_STACK_LINES = 256;
67
+
68
+ /**
69
+ * How much of a single line the frame pattern is run against.
70
+ *
71
+ * Capping the whole stack is not enough on its own. {@link FRAME_TAIL} ends in
72
+ * `$`, and its leading `[^\s()]+` backtracks: given one very long line with no
73
+ * separator in it, the engine retries from every offset and the match becomes
74
+ * quadratic. A 64 KB line took four seconds to reject — inside the crash
75
+ * handler. The pattern is anchored at the end, so the last kilobyte decides it
76
+ * for any line that could really be a frame.
77
+ */
78
+ export const MAX_FRAME_LINE_CHARS = 1024;
79
+ // The reveal branch exists only in dev builds. Metro substitutes a literal for
80
+ // `__DEV__`, so in a release bundle this whole block — sentinel included — is
81
+ // dead code and is stripped. CI greps the release bundle for the sentinel.
82
+ let revealBranchSentinel = '';
83
+ function messageRevealAllowed() {
84
+ if (typeof __DEV__ !== 'undefined' && __DEV__) {
85
+ revealBranchSentinel = '__NITRO_LOGGER_ERROR_REVEAL__';
86
+ return true;
87
+ }
88
+ return false;
89
+ }
90
+
91
+ /** @internal Test/CI hook — non-empty only once the dev reveal branch ran. */
92
+ export function __errorRevealBranchSentinel() {
93
+ return revealBranchSentinel;
94
+ }
95
+
96
+ /**
97
+ * Reduces a thrown value to a name, a message, and a list of positions.
98
+ *
99
+ * Total by construction: every branch that could throw — a getter on `message`,
100
+ * a `stack` that is not a string, a `name` that is a Symbol — ends at a fixed
101
+ * token rather than propagating. An error handler that throws while reporting
102
+ * an error takes the crash report with it.
103
+ */
104
+ export function sanitizeError(thrown, options) {
105
+ const bundleNames = new Set(options?.bundleNames ?? DEFAULT_BUNDLE_NAMES);
106
+ const maxFrames = boundedFrames(options?.maxFrames);
107
+
108
+ // Read each property exactly once, and touch the thrown value in no other
109
+ // way.
110
+ //
111
+ // Not `instanceof Error`: that consults the prototype chain, and a Proxy can
112
+ // throw from its `getPrototypeOf` trap — so the one operation meant to
113
+ // classify a hostile value safely is itself an operation it can hijack.
114
+ // Reading once also matters on its own: a getter is free to return something
115
+ // innocuous when classified and something else when rendered, so classifying
116
+ // and rendering must be the same read.
117
+ const source = typeof thrown === 'object' && thrown !== null ? thrown : undefined;
118
+ const stack = source ? readString(source, 'stack') : undefined;
119
+ const message = source ? readString(source, 'message') : undefined;
120
+ const name = source ? readString(source, 'name') : undefined;
121
+ if (stack === undefined && message === undefined) {
122
+ // A thrown string is the case that matters: `throw \`no chart for ${mrn}\``
123
+ // would otherwise arrive as the message. Its content never appears.
124
+ return {
125
+ name: NON_ERROR_THROWN,
126
+ message: REDACTED_MESSAGE,
127
+ frames: [],
128
+ frameCount: 0,
129
+ framesTruncated: false
130
+ };
131
+ }
132
+ const parsed = parseFrames(stack, bundleNames);
133
+ return {
134
+ name: sanitizeName(name),
135
+ message: messageRevealAllowed() ? message ?? '' : REDACTED_MESSAGE,
136
+ frames: parsed.frames.slice(0, maxFrames),
137
+ frameCount: parsed.frames.length,
138
+ framesTruncated: parsed.truncated
139
+ };
140
+ }
141
+
142
+ /**
143
+ * Property reads on a thrown value are not safe.
144
+ *
145
+ * `error.message` can be a getter, and a getter on an object someone threw can
146
+ * do anything — including throw again, from inside the handler that exists to
147
+ * report the first failure.
148
+ */
149
+ function readString(source, key) {
150
+ try {
151
+ const value = source[key];
152
+ return typeof value === 'string' ? value : undefined;
153
+ } catch {
154
+ return undefined;
155
+ }
156
+ }
157
+ function sanitizeName(name) {
158
+ if (name === undefined) return UNKNOWN_ERROR_NAME;
159
+ return BUILT_IN_ERROR_NAMES.has(name) ? name : UNKNOWN_ERROR_NAME;
160
+ }
161
+ function boundedFrames(value) {
162
+ if (value === undefined) return DEFAULT_MAX_FRAMES;
163
+ if (!Number.isSafeInteger(value) || value < 0) return DEFAULT_MAX_FRAMES;
164
+ return value;
165
+ }
166
+
167
+ /**
168
+ * The trailing `file:line:column` of a stack line, in any of the shapes
169
+ * JavaScriptCore, Hermes and V8 produce:
170
+ *
171
+ * at fn (/path/index.bundle:1:2)
172
+ * at /path/index.bundle:1:2
173
+ * fn@http://localhost:8081/index.bundle?platform=ios:1:2
174
+ * at fn (address at /path/index.android.bundle:1:2)
175
+ *
176
+ * Only the position is taken. The function name is discarded with everything
177
+ * else: it adds nothing a file and line does not already give, and it is one
178
+ * more string from application code that nobody has vetted.
179
+ */
180
+ const FRAME_TAIL = /([^\s()]+):(\d+):(\d+)\)?$/;
181
+
182
+ /**
183
+ * Walks the stack a line at a time within a fixed budget.
184
+ *
185
+ * Deliberately not `stack.split('\n')`: that materialises every line of a
186
+ * string whose length the thrown object chose, to produce frames almost all of
187
+ * which are then dropped. Scanning in place means an oversized stack costs a
188
+ * bounded amount of work and is reported as truncated.
189
+ */
190
+ function parseFrames(stack, bundleNames) {
191
+ if (stack === undefined) return {
192
+ frames: [],
193
+ truncated: false
194
+ };
195
+
196
+ // Cut to the budget up front, then never look at the original again.
197
+ //
198
+ // Bounding the loop was not enough on its own: `indexOf` searches to the end
199
+ // of whatever string it is given, so a multi-megabyte stack with no newline
200
+ // in it — or just a very long last line — was still scanned in full by the
201
+ // search for a line ending that was never going to come.
202
+ const input = stack.length > MAX_STACK_CHARS ? stack.slice(0, MAX_STACK_CHARS) : stack;
203
+ const truncatedInput = input.length < stack.length;
204
+ const frames = [];
205
+ let start = 0;
206
+ let lines = 0;
207
+ while (start < input.length && lines < MAX_STACK_LINES) {
208
+ let end = input.indexOf('\n', start);
209
+ if (end < 0) end = input.length;
210
+ // The tail, not the head: the pattern is anchored at the end of the line.
211
+ const from = Math.max(start, end - MAX_FRAME_LINE_CHARS);
212
+ const line = input.slice(from, end).trim();
213
+ start = end + 1;
214
+ lines += 1;
215
+ const match = FRAME_TAIL.exec(line);
216
+ // A line that does not parse is discarded rather than guessed at. The
217
+ // first line of a V8 stack is `Name: message`, which is exactly the string
218
+ // this module exists to keep out.
219
+ if (!match) continue;
220
+ const [, location, lineNumber, column] = match;
221
+ const file = basename(location);
222
+ frames.push(bundleNames.has(file) ? `${file}:${lineNumber}:${column}` : REDACTED_FRAME);
223
+ }
224
+ return {
225
+ frames,
226
+ truncated: truncatedInput || start < input.length
227
+ };
228
+ }
229
+
230
+ /** The filename part of a path or URL, without any query or fragment. */
231
+ function basename(location) {
232
+ const cut = Math.max(location.lastIndexOf('/'), location.lastIndexOf('\\'));
233
+ let name = cut >= 0 ? location.slice(cut + 1) : location;
234
+ const query = name.search(/[?#]/);
235
+ if (query >= 0) name = name.slice(0, query);
236
+ return name;
237
+ }
238
+ //# sourceMappingURL=sanitizeError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["BUILT_IN_ERROR_NAMES","Set","UNKNOWN_ERROR_NAME","REDACTED_FRAME","REDACTED_MESSAGE","NON_ERROR_THROWN","DEFAULT_BUNDLE_NAMES","DEFAULT_MAX_FRAMES","MAX_STACK_CHARS","MAX_STACK_LINES","MAX_FRAME_LINE_CHARS","revealBranchSentinel","messageRevealAllowed","__DEV__","__errorRevealBranchSentinel","sanitizeError","thrown","options","bundleNames","maxFrames","boundedFrames","source","undefined","stack","readString","message","name","frames","frameCount","framesTruncated","parsed","parseFrames","sanitizeName","slice","length","truncated","key","value","has","Number","isSafeInteger","FRAME_TAIL","input","truncatedInput","start","lines","end","indexOf","from","Math","max","line","trim","match","exec","location","lineNumber","column","file","basename","push","cut","lastIndexOf","query","search"],"sourceRoot":"../../../src","sources":["integrations/sanitizeError.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+
3
+ /** Numeric severity order; also the codes that cross the bridge. */
4
+ export const LEVEL_ORDER = {
5
+ verbose: 0,
6
+ debug: 1,
7
+ info: 2,
8
+ warning: 3,
9
+ error: 4,
10
+ todo: 5
11
+ };
12
+ export function levelAtLeast(level, minimum) {
13
+ return LEVEL_ORDER[level] >= LEVEL_ORDER[minimum];
14
+ }
15
+
16
+ /** Fixed-width 5-character tags, byte-identical to SwiftLogger's. */
17
+ export const LEVEL_TAG = {
18
+ verbose: 'TRACE',
19
+ debug: 'DEBUG',
20
+ info: ' INFO',
21
+ warning: ' WARN',
22
+ error: 'ERROR',
23
+ todo: ' TODO'
24
+ };
25
+
26
+ /** Uppercase names used by the JSON formatter (SwiftLogger rawValue parity). */
27
+ export const LEVEL_NAME = {
28
+ verbose: 'VERBOSE',
29
+ debug: 'DEBUG',
30
+ info: 'INFO',
31
+ warning: 'WARNING',
32
+ error: 'ERROR',
33
+ todo: 'TODO'
34
+ };
35
+ //# sourceMappingURL=levels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["LEVEL_ORDER","verbose","debug","info","warning","error","todo","levelAtLeast","level","minimum","LEVEL_TAG","LEVEL_NAME"],"sourceRoot":"../../src","sources":["levels.ts"],"mappings":";;AAEA;AACA,OAAO,MAAMA,WAAqC,GAAG;EACnDC,OAAO,EAAE,CAAC;EACVC,KAAK,EAAE,CAAC;EACRC,IAAI,EAAE,CAAC;EACPC,OAAO,EAAE,CAAC;EACVC,KAAK,EAAE,CAAC;EACRC,IAAI,EAAE;AACR,CAAC;AAED,OAAO,SAASC,YAAYA,CAACC,KAAe,EAAEC,OAAiB,EAAW;EACxE,OAAOT,WAAW,CAACQ,KAAK,CAAC,IAAIR,WAAW,CAACS,OAAO,CAAC;AACnD;;AAEA;AACA,OAAO,MAAMC,SAAmC,GAAG;EACjDT,OAAO,EAAE,OAAO;EAChBC,KAAK,EAAE,OAAO;EACdC,IAAI,EAAE,OAAO;EACbC,OAAO,EAAE,OAAO;EAChBC,KAAK,EAAE,OAAO;EACdC,IAAI,EAAE;AACR,CAAC;;AAED;AACA,OAAO,MAAMK,UAAoC,GAAG;EAClDV,OAAO,EAAE,SAAS;EAClBC,KAAK,EAAE,OAAO;EACdC,IAAI,EAAE,MAAM;EACZC,OAAO,EAAE,SAAS;EAClBC,KAAK,EAAE,OAAO;EACdC,IAAI,EAAE;AACR,CAAC","ignoreList":[]}
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+
3
+ import { UNREADABLE_VALUE } from "./privacy.js";
4
+
5
+ /**
6
+ * Copies caller metadata with per-property isolation, for the one place a
7
+ * snapshot is genuinely required: a scope's defaults, captured once at
8
+ * construction so later mutation of the caller's object cannot change what
9
+ * future messages report.
10
+ *
11
+ * Caller objects are untrusted. A Proxy with a throwing `ownKeys` trap
12
+ * yields `undefined` — the whole object is dropped, payload-free. A throwing
13
+ * property getter keeps the key but substitutes {@link UNREADABLE_VALUE}, so
14
+ * redaction still sees the key, rejects it, and counts it; dropping the key
15
+ * here would make it disappear from `droppedMetadataCount` entirely.
16
+ *
17
+ * The copy has a null prototype. Plain-object assignment would route a
18
+ * `__proto__` key through `Object.prototype`'s legacy setter, silently
19
+ * losing that value and letting a JS caller reshape the snapshot.
20
+ *
21
+ * Call-site metadata is deliberately NOT snapshotted — it goes to
22
+ * `redactMetadata` as a source so its keys are validated before any value
23
+ * is read.
24
+ */
25
+ export function safeSnapshotMetadata(metadata) {
26
+ if (!metadata) return undefined;
27
+ let keys;
28
+ try {
29
+ keys = Object.keys(metadata);
30
+ } catch {
31
+ return undefined;
32
+ }
33
+ const result = Object.create(null);
34
+ let count = 0;
35
+ for (const key of keys) {
36
+ let value;
37
+ try {
38
+ const read = metadata[key];
39
+ // An `undefined` value is a rejected value, not an absent key. Skipping
40
+ // it here would make the key vanish before redaction could count it,
41
+ // so scope defaults would under-report drops that direct metadata
42
+ // reports correctly.
43
+ value = read === undefined ? UNREADABLE_VALUE : read;
44
+ } catch {
45
+ value = UNREADABLE_VALUE;
46
+ }
47
+ result[key] = value;
48
+ count += 1;
49
+ }
50
+ return count > 0 ? result : undefined;
51
+ }
52
+ //# sourceMappingURL=metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["UNREADABLE_VALUE","safeSnapshotMetadata","metadata","undefined","keys","Object","result","create","count","key","value","read"],"sourceRoot":"../../src","sources":["metadata.ts"],"mappings":";;AACA,SAASA,gBAAgB,QAAQ,cAAW;;AAE5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,oBAAoBA,CAClCC,QAAiC,EACR;EACzB,IAAI,CAACA,QAAQ,EAAE,OAAOC,SAAS;EAC/B,IAAIC,IAAc;EAClB,IAAI;IACFA,IAAI,GAAGC,MAAM,CAACD,IAAI,CAACF,QAAQ,CAAC;EAC9B,CAAC,CAAC,MAAM;IACN,OAAOC,SAAS;EAClB;EACA,MAAMG,MAAmB,GAAGD,MAAM,CAACE,MAAM,CAAC,IAAI,CAAC;EAC/C,IAAIC,KAAK,GAAG,CAAC;EACb,KAAK,MAAMC,GAAG,IAAIL,IAAI,EAAE;IACtB,IAAIM,KAA0B;IAC9B,IAAI;MACF,MAAMC,IAAI,GAAGT,QAAQ,CAACO,GAAG,CAAoC;MAC7D;MACA;MACA;MACA;MACAC,KAAK,GAAGC,IAAI,KAAKR,SAAS,GAAGH,gBAAgB,GAAGW,IAAI;IACtD,CAAC,CAAC,MAAM;MACND,KAAK,GAAGV,gBAAgB;IAC1B;IACAM,MAAM,CAACG,GAAG,CAAC,GAAGC,KAAK;IACnBF,KAAK,IAAI,CAAC;EACZ;EACA,OAAOA,KAAK,GAAG,CAAC,GAAGF,MAAM,GAAGH,SAAS;AACvC","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"module"}