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,73 @@
1
+ import type { LogEntry } from '../types.js';
2
+ import type { LogFormatter } from './types.js';
3
+ import { utf8Length } from '../utf8.js';
4
+ export { utf8Length };
5
+ /**
6
+ * How the `timestamp` field renders.
7
+ *
8
+ * `iso8601` is UTC with milliseconds — `2026-07-27T12:15:30.842Z` — and is
9
+ * what the SwiftLogger goldens are written against. `epochSeconds` emits a
10
+ * JSON number of seconds, for aggregators that would only parse the string
11
+ * back again.
12
+ */
13
+ export type JsonTimestampStyle = 'iso8601' | 'epochSeconds';
14
+ export interface JsonLinesFormatterOptions {
15
+ readonly timestampStyle?: JsonTimestampStyle;
16
+ }
17
+ /**
18
+ * One JSON object per line, matching SwiftLogger's `JSONLogFormatter`.
19
+ *
20
+ * Keys come out in a fixed order — `timestamp`, `level`, `message`, then the
21
+ * optional `correlation`, `subsystem`, and `metadata` — so that output diffs
22
+ * cleanly and goldens are stable. Absent optionals are omitted rather than
23
+ * written as null, and metadata values keep their JSON type.
24
+ *
25
+ * Metadata keys are sorted, which is also why the object is assembled by hand
26
+ * rather than handed to `JSON.stringify`. JavaScript orders integer-like
27
+ * string keys before all others, so `JSON.stringify({ b: 1, '2': 2 })` puts
28
+ * `2` first no matter what order the keys went in. A metadata key is whatever
29
+ * the caller wrote, `'2'` included, and the Swift side sorts every key the
30
+ * same way.
31
+ *
32
+ * See `docs/PARITY.md` for the field-by-field comparison, including the three
33
+ * fields this formatter deliberately does not emit.
34
+ */
35
+ export declare class JsonLinesFormatter implements LogFormatter {
36
+ /**
37
+ * Every control character is escaped, so a record cannot contain a raw
38
+ * newline and native crash-tail trimming can find record boundaries.
39
+ */
40
+ readonly framing: "line";
41
+ private readonly timestampStyle;
42
+ constructor(options?: JsonLinesFormatterOptions);
43
+ format(entry: LogEntry): string;
44
+ /**
45
+ * Render within a byte budget, shedding content in a fixed order rather
46
+ * than slicing the finished string.
47
+ *
48
+ * Cutting a JSON record to length produces something no parser will accept,
49
+ * and a log line that cannot be parsed is worth less than one that is
50
+ * honestly incomplete. So: drop metadata from the end of sorted key order,
51
+ * then shorten the message, and mark the result `"truncated":true` either
52
+ * way. A reader can tell the difference between a short message and a
53
+ * shortened one.
54
+ *
55
+ * The budget counts UTF-8 bytes, because that is what the sink reserves.
56
+ * An unpaired surrogate never distorts the count here: `JSON.stringify` has
57
+ * already turned it into a six-character `\udXXX` escape by the time
58
+ * anything is measured.
59
+ *
60
+ * When even an empty message will not fit, the result comes back OVER
61
+ * budget: it is the smallest record that still identifies the entry, which
62
+ * is not quite the same as the smallest record possible. `correlation` and
63
+ * `subsystem` survive, because an entry no one can place is worth less than
64
+ * a short one — dropping them would save bytes and leave a line that says
65
+ * nothing about where it came from. Callers deciding whether an entry is
66
+ * renderable at all must therefore measure the result rather than assume it
67
+ * fits.
68
+ */
69
+ formatWithin(entry: LogEntry, maxBytes: number): string;
70
+ private render;
71
+ private renderTimestamp;
72
+ }
73
+ //# sourceMappingURL=JsonLinesFormatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonLinesFormatter.d.ts","sourceRoot":"","sources":["../../../../src/formatters/JsonLinesFormatter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAkC,MAAM,aAAU,CAAC;AACzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAS,CAAC;AAE5C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAS,CAAC;AAErC,OAAO,EAAE,UAAU,EAAE,CAAC;AAEtB;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,cAAc,CAAC;AAE5D,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,cAAc,CAAC,EAAE,kBAAkB,CAAC;CAC9C;AAKD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,kBAAmB,YAAW,YAAY;IACrD;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAG,MAAM,CAAU;IAEnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;gBAExC,OAAO,GAAE,yBAA8B;IAInD,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM;IAI/B;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IA0CvD,OAAO,CAAC,MAAM;IAmCd,OAAO,CAAC,eAAe;CAWxB"}
@@ -0,0 +1,6 @@
1
+ /** Local-time `HH:mm:ss.SSS`, matching SwiftLogger's console timestamp.
2
+ * Takes epoch milliseconds (see `LogEntry.timestamp`); plain Date getters +
3
+ * zero-pad — none of the Swift version's caching is needed, these are cheap
4
+ * in JS. */
5
+ export declare function formatTime(epochMs: number): string;
6
+ //# sourceMappingURL=timestamp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timestamp.d.ts","sourceRoot":"","sources":["../../../../src/formatters/timestamp.ts"],"names":[],"mappings":"AAAA;;;YAGY;AACZ,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOlD"}
@@ -0,0 +1,27 @@
1
+ import type { LogEntry } from '../types.js';
2
+ export interface LogFormatter {
3
+ /**
4
+ * Framing contract for file destinations: 'line' guarantees exactly one
5
+ * escaped record per line (newlines in content are escaped), which is what
6
+ * makes native crash-tail trimming safe. Formatters that cannot guarantee
7
+ * this omit it and are documented as having reduced crash-tail recovery.
8
+ */
9
+ readonly framing?: 'line';
10
+ format(entry: LogEntry): string;
11
+ /**
12
+ * Render `entry` within a UTF-8 byte budget by shedding content
13
+ * structurally — dropping whole fields, truncating a field at code-point
14
+ * boundaries — so the result is still well-formed in this format.
15
+ *
16
+ * A formatter that omits this is never sliced to fit: an entry too large
17
+ * for the destination's per-entry limit is replaced whole by a fixed
18
+ * notice, because cutting a rendered record to length is how a log file
19
+ * stops being parseable.
20
+ *
21
+ * Best effort. Returning something still over budget is allowed — a record
22
+ * has a floor below which it no longer identifies anything — and callers
23
+ * must measure the result rather than assume it fits.
24
+ */
25
+ formatWithin?(entry: LogEntry, maxBytes: number): string;
26
+ }
27
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/formatters/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAU,CAAC;AAEzC,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAE1B,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAAC;IAEhC;;;;;;;;;;;;;OAaG;IACH,YAAY,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1D"}
@@ -0,0 +1,34 @@
1
+ import type { FileSink } from './specs/FileSink.nitro.js';
2
+ import type { NativeConsoleSink } from './specs/NativeConsoleSink.nitro.js';
3
+ export { Log, Logger } from './Logger.js';
4
+ export type { LogOptions } from './Logger.js';
5
+ export { ScopedLogger } from './ScopedLogger.js';
6
+ export type { LogLevel, LazyMessage, LogPrimitive, LogValue, LogMetadata, RedactedMetadata, LogEntry, } from './types.js';
7
+ export { pub, priv } from './privacy.js';
8
+ export { METADATA_KEY_PATTERN_SOURCE, DROPPED_COUNT_KEY, MAX_CATALOG_SIZE, UNREADABLE_VALUE, } from './privacy.js';
9
+ export type { PublicValue, PrivateValue, PrivacyDefault } from './privacy.js';
10
+ export type { LogDestination } from './destinations/types.js';
11
+ export { ConsoleDestination } from './destinations/ConsoleDestination.js';
12
+ export { FileDestination } from './destinations/FileDestination.js';
13
+ export type { FileDestinationOptions, FileSinkLike, PurgeOutcome, } from './destinations/FileDestination.js';
14
+ export { NativeConsoleDestination } from './destinations/NativeConsoleDestination.js';
15
+ export type { NativeConsoleDestinationOptions, NativeConsoleSinkLike, } from './destinations/NativeConsoleDestination.js';
16
+ export { installErrorHandler } from './integrations/errorHandler.js';
17
+ export { ERROR_METADATA_KEYS, UNCAUGHT_ERROR_MESSAGE, } from './integrations/errorHandler.js';
18
+ export type { ErrorHandlerOptions, ErrorUtilsLike, Uninstall, } from './integrations/errorHandler.js';
19
+ export { flushOnBackground } from './integrations/appState.js';
20
+ export type { FlushOnBackgroundOptions, AppStateLike, } from './integrations/appState.js';
21
+ export { sanitizeError, DEFAULT_BUNDLE_NAMES, DEFAULT_MAX_FRAMES, REDACTED_FRAME, REDACTED_MESSAGE, UNKNOWN_ERROR_NAME, NON_ERROR_THROWN, } from './integrations/sanitizeError.js';
22
+ export type { SanitizedError, SanitizeErrorOptions, } from './integrations/sanitizeError.js';
23
+ export { Batcher } from './destinations/Batcher.js';
24
+ export type { BatchTarget, BatchFlushOutcome, BatcherOptions, FenceReason, LossCounts, } from './destinations/Batcher.js';
25
+ export { utf8Length } from './utf8.js';
26
+ export type { LogFormatter } from './formatters/types.js';
27
+ export { DefaultFormatter } from './formatters/DefaultFormatter.js';
28
+ export { JsonLinesFormatter } from './formatters/JsonLinesFormatter.js';
29
+ export type { JsonTimestampStyle, JsonLinesFormatterOptions, } from './formatters/JsonLinesFormatter.js';
30
+ export type { FileSink, RotationConfig, RejectReason, SinkStatus, AppendResult, FlushOutcome, ClearOutcome, } from './specs/FileSink.nitro.js';
31
+ export type { NativeConsoleSink } from './specs/NativeConsoleSink.nitro.js';
32
+ export declare function createFileSink(): FileSink;
33
+ export declare function createNativeConsoleSink(): NativeConsoleSink;
34
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oCAAiC,CAAC;AAGzE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,aAAU,CAAC;AACvC,YAAY,EAAE,UAAU,EAAE,MAAM,aAAU,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAgB,CAAC;AAC9C,YAAY,EACV,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,QAAQ,GACT,MAAM,YAAS,CAAC;AACjB,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,cAAW,CAAC;AACtC,OAAO,EACL,2BAA2B,EAC3B,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,cAAW,CAAC;AACnB,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAW,CAAC;AAC3E,YAAY,EAAE,cAAc,EAAE,MAAM,yBAAsB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAmC,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAgC,CAAC;AACjE,YAAY,EACV,sBAAsB,EACtB,YAAY,EACZ,YAAY,GACb,MAAM,mCAAgC,CAAC;AACxC,OAAO,EAAE,wBAAwB,EAAE,MAAM,4CAAyC,CAAC;AACnF,YAAY,EACV,+BAA+B,EAC/B,qBAAqB,GACtB,MAAM,4CAAyC,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAA6B,CAAC;AAClE,OAAO,EACL,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,gCAA6B,CAAC;AACrC,YAAY,EACV,mBAAmB,EACnB,cAAc,EACd,SAAS,GACV,MAAM,gCAA6B,CAAC;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAAyB,CAAC;AAC5D,YAAY,EACV,wBAAwB,EACxB,YAAY,GACb,MAAM,4BAAyB,CAAC;AACjC,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,iCAA8B,CAAC;AACtC,YAAY,EACV,cAAc,EACd,oBAAoB,GACrB,MAAM,iCAA8B,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,2BAAwB,CAAC;AACjD,YAAY,EACV,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,UAAU,GACX,MAAM,2BAAwB,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,WAAQ,CAAC;AACpC,YAAY,EAAE,YAAY,EAAE,MAAM,uBAAoB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAA+B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAiC,CAAC;AACrE,YAAY,EACV,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,oCAAiC,CAAC;AAKzC,YAAY,EACV,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,YAAY,GACb,MAAM,2BAAwB,CAAC;AAChC,YAAY,EAAE,iBAAiB,EAAE,MAAM,oCAAiC,CAAC;AAEzE,wBAAgB,cAAc,IAAI,QAAQ,CAEzC;AAED,wBAAgB,uBAAuB,IAAI,iBAAiB,CAI3D"}
@@ -0,0 +1,33 @@
1
+ import type { Logger } from '../Logger.js';
2
+ import type { Uninstall } from './errorHandler.js';
3
+ /** The part of RN's `AppState` this uses. Injected in tests. */
4
+ export interface AppStateLike {
5
+ addEventListener(type: 'change', listener: (state: string) => void): {
6
+ remove(): void;
7
+ } | undefined;
8
+ }
9
+ export interface FlushOnBackgroundOptions {
10
+ /** Defaults to the shared `Log`. */
11
+ readonly logger?: Logger;
12
+ /** Injected for tests; defaults to `require('react-native').AppState`. */
13
+ readonly appState?: AppStateLike;
14
+ /**
15
+ * Budget for the backgrounding flush. Default 2000 ms.
16
+ *
17
+ * Backgrounding is not a crash, but it is the last moment the JS thread is
18
+ * reliably scheduled: iOS may freeze timers immediately afterwards, and an
19
+ * entry still sitting in a 100 ms batch window can wait there until the app
20
+ * is next opened — or be lost if it is killed while suspended.
21
+ */
22
+ readonly deadlineMs?: number;
23
+ }
24
+ /**
25
+ * Flushes every destination when the app leaves the foreground.
26
+ *
27
+ * Returns an idempotent uninstall handle. Removing the listener matters more
28
+ * than it looks: `AppState` outlives any component, so a subscription left
29
+ * behind keeps a disposed logger reachable and flushes it on every transition
30
+ * for the rest of the process.
31
+ */
32
+ export declare function flushOnBackground(options?: FlushOnBackgroundOptions): Uninstall;
33
+ //# sourceMappingURL=appState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appState.d.ts","sourceRoot":"","sources":["../../../../src/integrations/appState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAW,CAAC;AAExC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAgB,CAAC;AAEhD,gEAAgE;AAChE,MAAM,WAAW,YAAY;IAC3B,gBAAgB,CACd,IAAI,EAAE,QAAQ,EACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAChC;QAAE,MAAM,IAAI,IAAI,CAAA;KAAE,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,wBAAwB;IACvC,oCAAoC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC;IACjC;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAiBD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,CAAC,EAAE,wBAAwB,GACjC,SAAS,CAgCX"}
@@ -0,0 +1,55 @@
1
+ import type { Logger } from '../Logger.js';
2
+ import type { SanitizeErrorOptions } from './sanitizeError.js';
3
+ /**
4
+ * React Native's global error hook.
5
+ *
6
+ * `ErrorUtils` is undocumented and has been de-facto stable for a decade, which
7
+ * is the whole risk: it is typed here rather than imported so the library never
8
+ * depends on a declaration file that may not exist, and every access is
9
+ * guarded so a runtime without it degrades to doing nothing.
10
+ */
11
+ export interface ErrorUtilsLike {
12
+ setGlobalHandler(handler: (error: unknown, isFatal?: boolean) => void): void;
13
+ getGlobalHandler?(): ((error: unknown, isFatal?: boolean) => void) | undefined;
14
+ }
15
+ /** Metadata keys this handler writes. Add them to a strict key catalog. */
16
+ export declare const ERROR_METADATA_KEYS: readonly ["errorName", "errorMessage", "errorFrames", "errorFrameCount", "errorFramesTruncated", "fatal"];
17
+ /** The message this handler logs. A literal, as the lint rule requires. */
18
+ export declare const UNCAUGHT_ERROR_MESSAGE = "uncaught error";
19
+ export interface ErrorHandlerOptions extends SanitizeErrorOptions {
20
+ /** Defaults to the shared `Log`. */
21
+ readonly logger?: Logger;
22
+ /** Injected for tests; defaults to the global `ErrorUtils`. */
23
+ readonly errorUtils?: ErrorUtilsLike;
24
+ /**
25
+ * How long a fatal error's flush may take. Default 2000 ms.
26
+ *
27
+ * This is the crash path and the only chance the buffered entries get, so it
28
+ * is worth more than a normal flush — but it runs on the JS thread while the
29
+ * app is already dying, and a watchdog kill loses the log entirely.
30
+ */
31
+ readonly fatalFlushMs?: number;
32
+ /** Subsystem to tag the entry with. */
33
+ readonly subsystem?: string;
34
+ /**
35
+ * Pass the error on to whatever handler was installed before. Default true:
36
+ * suppressing it removes the dev RedBox and, in production, converts a crash
37
+ * into a silently broken app.
38
+ */
39
+ readonly chain?: boolean;
40
+ }
41
+ /** Undoes an install. Idempotent; safe to call after another handler took over. */
42
+ export type Uninstall = () => void;
43
+ /**
44
+ * Logs uncaught errors, flushes on fatal ones, and hands the error onward.
45
+ *
46
+ * The flush is the reason this exists. A crash is precisely when the buffered
47
+ * entries explaining it are still in memory, and precisely when nothing will
48
+ * come along later to write them.
49
+ *
50
+ * Nothing about the error is trusted — see {@link sanitizeError}. What reaches
51
+ * the log is a built-in class name, a redacted message outside dev, and stack
52
+ * positions in files whose names were already known.
53
+ */
54
+ export declare function installErrorHandler(options?: ErrorHandlerOptions): Uninstall;
55
+ //# sourceMappingURL=errorHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errorHandler.d.ts","sourceRoot":"","sources":["../../../../src/integrations/errorHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAW,CAAC;AAGxC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAiB,CAAC;AAG5D;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IAC7E,gBAAgB,CAAC,IACf,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAC7D;AAED,2EAA2E;AAC3E,eAAO,MAAM,mBAAmB,2GAOtB,CAAC;AAEX,2EAA2E;AAC3E,eAAO,MAAM,sBAAsB,mBAAmB,CAAC;AAEvD,MAAM,WAAW,mBAAoB,SAAQ,oBAAoB;IAC/D,oCAAoC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,+DAA+D;IAC/D,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC;IACrC;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,uCAAuC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAID,mFAAmF;AACnF,MAAM,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC;AAEnC;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAqF5E"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Turning a thrown value into something a log file is allowed to contain.
3
+ *
4
+ * An uncaught error is the one place the logger handles a string it did not
5
+ * construct, cannot see the provenance of, and did not put through the privacy
6
+ * layer. `new Error(\`no chart for ${patient.mrn}\`)` is an entirely ordinary
7
+ * line of application code, and its message reaches here verbatim. So nothing
8
+ * from the error is trusted: the class name is allowlisted down to a fixed
9
+ * token, the message is dropped outside dev, and stack frames are reduced to a
10
+ * position in a file whose name we already knew.
11
+ *
12
+ * The result is safe enough to mark `pub()`, which is the point — sanitising is
13
+ * what earns an error the right to be rendered.
14
+ */
15
+ /** What an unrecognised error class is reported as. */
16
+ export declare const UNKNOWN_ERROR_NAME = "Error";
17
+ /** What a stack frame in a file we cannot vouch for is reported as. */
18
+ export declare const REDACTED_FRAME = "<frame>";
19
+ /** What an error message is reported as outside a dev build. */
20
+ export declare const REDACTED_MESSAGE = "<redacted>";
21
+ /** What a thrown non-Error is reported as. */
22
+ export declare const NON_ERROR_THROWN = "<non-error>";
23
+ /**
24
+ * Bundle basenames a frame may be named after.
25
+ *
26
+ * A frame is only useful if you can find the file, and the files an app ships
27
+ * are known in advance. Everything else — a path from `node_modules`, a
28
+ * `blob:` URL, a filename built at runtime — is reported positionally instead.
29
+ * R3's point stands on its own: a basename can be perfectly regex-valid and
30
+ * still be `patient-12345.js`.
31
+ */
32
+ export declare const DEFAULT_BUNDLE_NAMES: readonly string[];
33
+ /** Frames beyond this are dropped; the count of what was dropped is kept. */
34
+ export declare const DEFAULT_MAX_FRAMES = 12;
35
+ /**
36
+ * How much of a stack is read at all, regardless of how many frames are kept.
37
+ *
38
+ * `stack` is a property of an object someone threw, which means its size is
39
+ * chosen by whatever threw it and not by any engine limit. Splitting it whole
40
+ * to count frames we then discard hands an arbitrary allocation to the one
41
+ * code path that runs while the app is already crashing. A real Hermes or V8
42
+ * stack is a few kilobytes and a few dozen lines; anything past these bounds
43
+ * is reported as truncated rather than read.
44
+ */
45
+ export declare const MAX_STACK_CHARS: number;
46
+ export declare const MAX_STACK_LINES = 256;
47
+ /**
48
+ * How much of a single line the frame pattern is run against.
49
+ *
50
+ * Capping the whole stack is not enough on its own. {@link FRAME_TAIL} ends in
51
+ * `$`, and its leading `[^\s()]+` backtracks: given one very long line with no
52
+ * separator in it, the engine retries from every offset and the match becomes
53
+ * quadratic. A 64 KB line took four seconds to reject — inside the crash
54
+ * handler. The pattern is anchored at the end, so the last kilobyte decides it
55
+ * for any line that could really be a frame.
56
+ */
57
+ export declare const MAX_FRAME_LINE_CHARS = 1024;
58
+ export interface SanitizedError {
59
+ /** An allowlisted built-in name, or `'Error'`. */
60
+ readonly name: string;
61
+ /** The real message in a dev build; {@link REDACTED_MESSAGE} otherwise. */
62
+ readonly message: string;
63
+ /** Sanitised frames, newest first, at most `maxFrames` of them. */
64
+ readonly frames: readonly string[];
65
+ /** How many frames were found in the part of the stack that was read. */
66
+ readonly frameCount: number;
67
+ /**
68
+ * The stack was longer than {@link MAX_STACK_CHARS} or
69
+ * {@link MAX_STACK_LINES} and was not read to the end, so `frameCount` is a
70
+ * floor rather than a total.
71
+ */
72
+ readonly framesTruncated: boolean;
73
+ }
74
+ export interface SanitizeErrorOptions {
75
+ readonly bundleNames?: readonly string[];
76
+ readonly maxFrames?: number;
77
+ }
78
+ /** @internal Test/CI hook — non-empty only once the dev reveal branch ran. */
79
+ export declare function __errorRevealBranchSentinel(): string;
80
+ /**
81
+ * Reduces a thrown value to a name, a message, and a list of positions.
82
+ *
83
+ * Total by construction: every branch that could throw — a getter on `message`,
84
+ * a `stack` that is not a string, a `name` that is a Symbol — ends at a fixed
85
+ * token rather than propagating. An error handler that throws while reporting
86
+ * an error takes the crash report with it.
87
+ */
88
+ export declare function sanitizeError(thrown: unknown, options?: SanitizeErrorOptions): SanitizedError;
89
+ //# sourceMappingURL=sanitizeError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizeError.d.ts","sourceRoot":"","sources":["../../../../src/integrations/sanitizeError.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAsBH,uDAAuD;AACvD,eAAO,MAAM,kBAAkB,UAAU,CAAC;AAE1C,uEAAuE;AACvE,eAAO,MAAM,cAAc,YAAY,CAAC;AAExC,gEAAgE;AAChE,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAE7C,8CAA8C;AAC9C,eAAO,MAAM,gBAAgB,gBAAgB,CAAC;AAE9C;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAKjD,CAAC;AAEF,6EAA6E;AAC7E,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,QAAY,CAAC;AACzC,eAAO,MAAM,eAAe,MAAM,CAAC;AAEnC;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,yEAAyE;IACzE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAeD,8EAA8E;AAC9E,wBAAgB,2BAA2B,IAAI,MAAM,CAEpD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,OAAO,EACf,OAAO,CAAC,EAAE,oBAAoB,GAC7B,cAAc,CAwChB"}
@@ -0,0 +1,9 @@
1
+ import type { LogLevel } from './types.js';
2
+ /** Numeric severity order; also the codes that cross the bridge. */
3
+ export declare const LEVEL_ORDER: Record<LogLevel, number>;
4
+ export declare function levelAtLeast(level: LogLevel, minimum: LogLevel): boolean;
5
+ /** Fixed-width 5-character tags, byte-identical to SwiftLogger's. */
6
+ export declare const LEVEL_TAG: Record<LogLevel, string>;
7
+ /** Uppercase names used by the JSON formatter (SwiftLogger rawValue parity). */
8
+ export declare const LEVEL_NAME: Record<LogLevel, string>;
9
+ //# sourceMappingURL=levels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"levels.d.ts","sourceRoot":"","sources":["../../../src/levels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAS,CAAC;AAExC,oEAAoE;AACpE,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAOhD,CAAC;AAEF,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,GAAG,OAAO,CAExE;AAED,qEAAqE;AACrE,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAO9C,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAO/C,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { LogMetadata } from './types.js';
2
+ /**
3
+ * Copies caller metadata with per-property isolation, for the one place a
4
+ * snapshot is genuinely required: a scope's defaults, captured once at
5
+ * construction so later mutation of the caller's object cannot change what
6
+ * future messages report.
7
+ *
8
+ * Caller objects are untrusted. A Proxy with a throwing `ownKeys` trap
9
+ * yields `undefined` — the whole object is dropped, payload-free. A throwing
10
+ * property getter keeps the key but substitutes {@link UNREADABLE_VALUE}, so
11
+ * redaction still sees the key, rejects it, and counts it; dropping the key
12
+ * here would make it disappear from `droppedMetadataCount` entirely.
13
+ *
14
+ * The copy has a null prototype. Plain-object assignment would route a
15
+ * `__proto__` key through `Object.prototype`'s legacy setter, silently
16
+ * losing that value and letting a JS caller reshape the snapshot.
17
+ *
18
+ * Call-site metadata is deliberately NOT snapshotted — it goes to
19
+ * `redactMetadata` as a source so its keys are validated before any value
20
+ * is read.
21
+ */
22
+ export declare function safeSnapshotMetadata(metadata: LogMetadata | undefined): LogMetadata | undefined;
23
+ //# sourceMappingURL=metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../../src/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAS,CAAC;AAG3C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,WAAW,GAAG,SAAS,GAChC,WAAW,GAAG,SAAS,CA0BzB"}
@@ -0,0 +1,103 @@
1
+ import type { LogMetadata, LogPrimitive, LogValue, RedactedMetadata } from './types.js';
2
+ /**
3
+ * The privacy layer, deliberately a single module.
4
+ *
5
+ * Marker inspection and redaction live together so that payload recovery
6
+ * stays closure-private. If `inspectMarker` were exported, anyone could deep
7
+ * import the compiled module and read back a `priv()` payload in production,
8
+ * which would defeat the whole no-reveal contract regardless of what the
9
+ * package entry point re-exports. Nothing here that can return a payload
10
+ * crosses the module boundary.
11
+ */
12
+ /** What a redacted value renders as in a log line. */
13
+ export declare const PRIVATE_PLACEHOLDER = "<private>";
14
+ /** Source text of the key rule, for callers that want their own RegExp. */
15
+ export declare const METADATA_KEY_PATTERN_SOURCE = "^[A-Za-z0-9._-]{1,64}$";
16
+ /** Reserved key carrying the fixed diagnostic: how many entries this call
17
+ * dropped. A count only — never which keys, never why, never the values. */
18
+ export declare const DROPPED_COUNT_KEY = "droppedMetadataCount";
19
+ /** Upper bound on catalog size. A hostile or accidental infinite iterable
20
+ * must not be able to hang the JS thread inside a logging config call. */
21
+ export declare const MAX_CATALOG_SIZE = 4096;
22
+ declare const publicBrand: unique symbol;
23
+ declare const privateBrand: unique symbol;
24
+ /** A value explicitly marked safe to render. Opaque: the payload lives in a
25
+ * module-private WeakMap, never on the object. */
26
+ export interface PublicValue {
27
+ readonly [publicBrand]: true;
28
+ }
29
+ /** A value explicitly marked sensitive. Renders as `<private>` outside dev. */
30
+ export interface PrivateValue {
31
+ readonly [privateBrand]: true;
32
+ }
33
+ /**
34
+ * Mark a value safe to render even under a `'private'` privacy default.
35
+ *
36
+ * The payload is validated here AND again at emit: `pub(patient as any)`
37
+ * must not smuggle an object past the primitive check. An invalid payload
38
+ * does not throw — logging never crashes the caller — it produces a marker
39
+ * that is dropped at emit and counted in the fixed diagnostic.
40
+ */
41
+ export declare function pub(value: LogPrimitive): PublicValue;
42
+ /** Mark a value sensitive: renders as `<private>` outside dev builds, even
43
+ * under a `'public'` privacy default. Same fail-closed validation as `pub`. */
44
+ export declare function priv(value: LogPrimitive): PrivateValue;
45
+ /**
46
+ * Stands in for a value that could not be read when a snapshot was taken —
47
+ * a getter that threw while a scope was being constructed.
48
+ *
49
+ * It is registered as an invalid marker, so redaction drops it and counts
50
+ * it like any other rejected value. Without it the key would vanish at
51
+ * snapshot time and never appear in `droppedMetadataCount`, which is the
52
+ * one thing a silent drop must never do. It carries no payload.
53
+ */
54
+ export declare const UNREADABLE_VALUE: LogValue;
55
+ /** @internal Test/CI hook — non-empty only once the dev reveal branch ran.
56
+ * Returns a build-time marker, never a payload. */
57
+ export declare function __revealBranchSentinel(): string;
58
+ export type PrivacyDefault = 'public' | 'private';
59
+ export interface PrivacySettings {
60
+ /** `'private'` redacts bare values outside dev; `'public'` renders them. */
61
+ readonly privacyDefault: PrivacyDefault;
62
+ /** Kill switch: redact every value regardless of marker or build type. */
63
+ readonly redactAll: boolean;
64
+ /** Approved metadata keys. Undefined means "no catalog configured". */
65
+ readonly keyCatalog: ReadonlySet<string> | undefined;
66
+ }
67
+ /**
68
+ * Coerce a caller-supplied privacy default. TypeScript's union is not a
69
+ * runtime guarantee — JS callers, JSON config, and `any` all reach here — so
70
+ * anything that is not exactly `'public'` or `'private'` resolves to
71
+ * `'private'`. Ambiguity must never resolve toward disclosure.
72
+ */
73
+ export declare function normalizePrivacyDefault(value: unknown): PrivacyDefault;
74
+ /**
75
+ * Build a catalog from caller-supplied input without trusting it. A
76
+ * non-iterable, an iterator that throws mid-way, a non-string entry, or an
77
+ * iterable longer than {@link MAX_CATALOG_SIZE} all yield an empty set: the
78
+ * caller's tighten-only intent is honored in the safest possible direction,
79
+ * and a runaway iterable cannot hang the JS thread.
80
+ */
81
+ export declare function buildCatalog(keys: unknown): Set<string>;
82
+ /**
83
+ * Resolve caller metadata into what destinations may see.
84
+ *
85
+ * Takes metadata as ordered sources — a scope's defaults followed by the
86
+ * call site's — rather than a pre-merged object. Merging eagerly would read
87
+ * every value before any key was checked, which is exactly what this
88
+ * function exists to avoid: precedence is settled per key first, then the
89
+ * winning key is validated, and only a key that survives has its value read.
90
+ * A getter behind a malformed, reserved, or unapproved key therefore never
91
+ * runs, and neither does a getter the call site overrode.
92
+ *
93
+ * Every rejection — bad key, throwing getter, unsupported value —
94
+ * increments one count. The count is all that is reported: the diagnostic
95
+ * itself must not become the leak.
96
+ *
97
+ * The result is a frozen null-prototype object. A source whose keys cannot
98
+ * be enumerated at all (a Proxy with a throwing `ownKeys` trap) contributes
99
+ * nothing, since there is no key that could be safely counted or described.
100
+ */
101
+ export declare function redactMetadata(scopeMetadata: LogMetadata | undefined, callSiteMetadata: LogMetadata | undefined, settings: PrivacySettings): RedactedMetadata | undefined;
102
+ export {};
103
+ //# sourceMappingURL=privacy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"privacy.d.ts","sourceRoot":"","sources":["../../../src/privacy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,gBAAgB,EACjB,MAAM,YAAS,CAAC;AAEjB;;;;;;;;;GASG;AAEH,sDAAsD;AACtD,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAmB/C,2EAA2E;AAC3E,eAAO,MAAM,2BAA2B,2BAA2B,CAAC;AAMpE;4EAC4E;AAC5E,eAAO,MAAM,iBAAiB,yBAAyB,CAAC;AAExD;0EAC0E;AAC1E,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC,OAAO,CAAC,MAAM,WAAW,EAAE,OAAO,MAAM,CAAC;AACzC,OAAO,CAAC,MAAM,YAAY,EAAE,OAAO,MAAM,CAAC;AAE1C;kDACkD;AAClD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC;CAC9B;AAED,+EAA+E;AAC/E,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC;CAC/B;AA6CD;;;;;;;GAOG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,YAAY,GAAG,WAAW,CAQpD;AAED;+EAC+E;AAC/E,wBAAgB,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,CAQtD;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAI3B,CAAC;AA4CL;mDACmD;AACnD,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAID,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,CAAC;AAElD,MAAM,WAAW,eAAe;IAC9B,4EAA4E;IAC5E,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;CACtD;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAEtE;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAmBvD;AAmED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAC5B,aAAa,EAAE,WAAW,GAAG,SAAS,EACtC,gBAAgB,EAAE,WAAW,GAAG,SAAS,EACzC,QAAQ,EAAE,eAAe,GACxB,gBAAgB,GAAG,SAAS,CA8C9B"}
@@ -0,0 +1,131 @@
1
+ import type { HybridObject } from 'react-native-nitro-modules';
2
+ /**
3
+ * Rotation and retention policy for one log file.
4
+ *
5
+ * All numeric fields are validated in TypeScript (finite safe integers,
6
+ * positive sizes, bounded counts) AND re-clamped natively before integer
7
+ * conversion — a NaN/Infinity/negative must never trap a Swift/Kotlin cast.
8
+ */
9
+ export interface RotationConfig {
10
+ /** Soft threshold; overshoot bounded by one batch. */
11
+ maxFileSizeBytes: number;
12
+ /** Archives to retain by count; 0 keeps none. */
13
+ maxArchivedFilesCount: number;
14
+ /** Rotate the current file once this old, regardless of size. */
15
+ maxFileAgeSeconds?: number;
16
+ /** Gzip archives as they rotate out. */
17
+ compressArchives: boolean;
18
+ /** Delete archives older than this even if under the count cap. */
19
+ maxArchiveAgeSeconds?: number;
20
+ /** Bound on current file + all archives combined. */
21
+ maxTotalLogBytes?: number;
22
+ }
23
+ /** Why an appendBatch was not accepted. */
24
+ export type RejectReason = 'full' | 'staleGeneration' | 'closed' | 'failed';
25
+ /**
26
+ * Snapshot of sink health. MUST be served from atomics / a short non-I/O
27
+ * lock — never from the writer queue — so a paused Batcher can poll it while
28
+ * the writer is stalled on disk.
29
+ *
30
+ * Loss fields are per-handle observed counters (monotonic writer totals with
31
+ * per-handle cursors underneath); observing a loss here does NOT acknowledge
32
+ * it — acknowledgement happens only after the consolidated loss notice has
33
+ * durably flushed.
34
+ */
35
+ export interface SinkStatus {
36
+ queuedBytes: number;
37
+ lostBytes: number;
38
+ lostEntries: number;
39
+ /** Payload-free degradation bitmask: rotation|gzip|prune|sidecar|protection. */
40
+ degraded: number;
41
+ }
42
+ export interface AppendResult {
43
+ accepted: boolean;
44
+ /** Present only when accepted is false. */
45
+ rejectReason?: RejectReason;
46
+ queuedBytes: number;
47
+ lostBytes: number;
48
+ lostEntries: number;
49
+ degraded: number;
50
+ }
51
+ export interface FlushOutcome {
52
+ /** True when every previously accepted byte reached storage and fsync. */
53
+ durable: boolean;
54
+ timedOut: boolean;
55
+ pendingBytes: number;
56
+ queuedBytes: number;
57
+ lostBytes: number;
58
+ lostEntries: number;
59
+ degraded: number;
60
+ }
61
+ export interface ClearOutcome {
62
+ deletedCount: number;
63
+ failedPaths: string[];
64
+ /** False when any artifact survived or the deadline elapsed. */
65
+ durable: boolean;
66
+ /**
67
+ * Whether the writer came back with a usable file afterwards.
68
+ *
69
+ * Separate from `durable` because they are separate facts and the caller
70
+ * needs both. A purge can delete everything it was asked to — `durable` —
71
+ * and still fail to reopen, on a directory that has become unwritable or a
72
+ * volume that filled. Resuming on `durable` alone hands records to a writer
73
+ * with nowhere to put them: every one is accepted, then rejected as
74
+ * `staleGeneration`, then dropped.
75
+ *
76
+ * Resume only when both are true. `durable && !rebound` means the deletion
77
+ * is genuinely complete — which is what a compliance caller asked — but the
78
+ * destination must stay fenced until an explicit retry gets a live file back.
79
+ */
80
+ rebound: boolean;
81
+ }
82
+ /**
83
+ * Dumb native file sink. All intelligence (batching, backpressure, drop
84
+ * accounting, formatting, redaction) lives in TypeScript; this object only
85
+ * appends pre-batched text, rotates, compresses, and reports counters.
86
+ *
87
+ * One JS FileDestination = one FileSink handle; handles for the same
88
+ * canonical path share one process-global writer (registry, refcounted,
89
+ * generation-fenced). Batch = atomic loss unit.
90
+ */
91
+ export interface FileSink extends HybridObject<{
92
+ ios: 'swift';
93
+ android: 'kotlin';
94
+ }> {
95
+ readonly defaultLogDirectory: string;
96
+ /**
97
+ * Throws on open failure OR on config conflict with an existing writer.
98
+ *
99
+ * `lineFramed` declares that every batch handed to `appendBatch` contains
100
+ * whole records terminated by `\n`, with no raw newline inside a record.
101
+ * Only then may the startup scan trim an incomplete trailing record: with
102
+ * opaque multi-line text a writer cannot tell a torn record from an
103
+ * intentional one, and trimming would destroy good data. Absent — the
104
+ * default for a custom formatter that does not declare `framing: 'line'` —
105
+ * the file is left exactly as the crash left it and recovery is reduced.
106
+ */
107
+ open(path: string, rotation?: RotationConfig, lineFramed?: boolean): void;
108
+ /**
109
+ * Enqueue only — never performs I/O inline. Atomic accept/reject BEFORE
110
+ * enqueue against the hard shared payload cap; accepted bytes stay
111
+ * reserved until terminal write completion. entryCount travels with the
112
+ * queued item for exact loss accounting.
113
+ */
114
+ appendBatch(batch: string, entryCount: number): AppendResult;
115
+ /** Non-enqueuing health probe; safe to poll while the writer is stalled. */
116
+ getStatus(): SinkStatus;
117
+ /** Wall-clock-bounded synchronous drain + fsync. */
118
+ flush(deadlineMs: number): FlushOutcome;
119
+ /** Deadline-aware disposal; a hung write cannot block forever. */
120
+ close(deadlineMs: number): FlushOutcome;
121
+ /** Active file + archives, newest first. */
122
+ getLogFilePaths(): string[];
123
+ /**
124
+ * Registry-serialized purge of the COMPLETE artifact set (current file,
125
+ * sidecar, archives, gzip temporaries, staging/recovery files). Bumps the
126
+ * writer generation; the invoking handle rebinds only after durable
127
+ * success. Reached via the Logger-layer purge flow, never called ad hoc.
128
+ */
129
+ clearLogs(deadlineMs: number): ClearOutcome;
130
+ }
131
+ //# sourceMappingURL=FileSink.nitro.d.ts.map