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,349 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * The privacy layer, deliberately a single module.
5
+ *
6
+ * Marker inspection and redaction live together so that payload recovery
7
+ * stays closure-private. If `inspectMarker` were exported, anyone could deep
8
+ * import the compiled module and read back a `priv()` payload in production,
9
+ * which would defeat the whole no-reveal contract regardless of what the
10
+ * package entry point re-exports. Nothing here that can return a payload
11
+ * crosses the module boundary.
12
+ */
13
+
14
+ /** What a redacted value renders as in a log line. */
15
+ export const PRIVATE_PLACEHOLDER = '<private>';
16
+
17
+ /** What a marker renders as if it is stringified directly (interpolated into
18
+ * a message, spread, inspected). Never the payload — a marker leaking its
19
+ * value through `String()` would defeat the whole contract. */
20
+ const MARKER_PLACEHOLDER = '<redacted>';
21
+
22
+ /**
23
+ * Metadata keys are structural, never data. Anything outside this shape is
24
+ * a sign a value was used as a key — the classic `patient123: …` leak.
25
+ *
26
+ * The enforcing RegExp is module-private and only its source is exported. A
27
+ * shared RegExp object is mutable: a consumer could assign an own `test`
28
+ * method or call `RegExp.prototype.compile` on it and silently disable key
29
+ * validation for the whole process. Callers that want to pre-check a key
30
+ * build their own from {@link METADATA_KEY_PATTERN_SOURCE}.
31
+ */
32
+ const METADATA_KEY_PATTERN = /^[A-Za-z0-9._-]{1,64}$/;
33
+
34
+ /** Source text of the key rule, for callers that want their own RegExp. */
35
+ export const METADATA_KEY_PATTERN_SOURCE = '^[A-Za-z0-9._-]{1,64}$';
36
+ function isValidMetadataKey(key) {
37
+ return METADATA_KEY_PATTERN.test(key);
38
+ }
39
+
40
+ /** Reserved key carrying the fixed diagnostic: how many entries this call
41
+ * dropped. A count only — never which keys, never why, never the values. */
42
+ export const DROPPED_COUNT_KEY = 'droppedMetadataCount';
43
+
44
+ /** Upper bound on catalog size. A hostile or accidental infinite iterable
45
+ * must not be able to hang the JS thread inside a logging config call. */
46
+ export const MAX_CATALOG_SIZE = 4096;
47
+
48
+ /** A value explicitly marked safe to render. Opaque: the payload lives in a
49
+ * module-private WeakMap, never on the object. */
50
+
51
+ /** A value explicitly marked sensitive. Renders as `<private>` outside dev. */
52
+
53
+ // Membership in these maps is the ONLY proof that an object is a marker.
54
+ // A foreign lookalike — same shape, same toString — fails naturally because
55
+ // it was never registered here, and no code outside this module can register
56
+ // one. WeakMaps also keep the payload unreachable: there is no enumerable
57
+ // field to spread, stringify, or inspect.
58
+ const publicPayloads = new WeakMap();
59
+ const privatePayloads = new WeakMap();
60
+ const invalidMarkers = new WeakSet();
61
+
62
+ /**
63
+ * Exactly the primitives the pipeline can render. Objects, arrays, proxies,
64
+ * functions, symbols, null/undefined, NaN and the infinities are all
65
+ * rejected — an object payload is the classic way PHI slips into a log.
66
+ */
67
+ function isLogPrimitive(value) {
68
+ const kind = typeof value;
69
+ return kind === 'string' || kind === 'boolean' || kind === 'number' && Number.isFinite(value);
70
+ }
71
+ function createMarker() {
72
+ const marker = {};
73
+ const hide = (key, value) => {
74
+ Object.defineProperty(marker, key, {
75
+ value,
76
+ enumerable: false,
77
+ writable: false,
78
+ configurable: false
79
+ });
80
+ };
81
+ const placeholder = () => MARKER_PLACEHOLDER;
82
+ // Non-enumerable, so `{...marker}` and `Object.keys(marker)` see nothing.
83
+ hide('toString', placeholder);
84
+ hide('toJSON', placeholder);
85
+ hide(Symbol.toPrimitive, placeholder);
86
+ hide(Symbol.for('nodejs.util.inspect.custom'), placeholder);
87
+ hide(Symbol.toStringTag, 'RedactedLogValue');
88
+ return Object.freeze(marker);
89
+ }
90
+
91
+ /**
92
+ * Mark a value safe to render even under a `'private'` privacy default.
93
+ *
94
+ * The payload is validated here AND again at emit: `pub(patient as any)`
95
+ * must not smuggle an object past the primitive check. An invalid payload
96
+ * does not throw — logging never crashes the caller — it produces a marker
97
+ * that is dropped at emit and counted in the fixed diagnostic.
98
+ */
99
+ export function pub(value) {
100
+ const marker = createMarker();
101
+ if (isLogPrimitive(value)) {
102
+ publicPayloads.set(marker, value);
103
+ } else {
104
+ invalidMarkers.add(marker);
105
+ }
106
+ return marker;
107
+ }
108
+
109
+ /** Mark a value sensitive: renders as `<private>` outside dev builds, even
110
+ * under a `'public'` privacy default. Same fail-closed validation as `pub`. */
111
+ export function priv(value) {
112
+ const marker = createMarker();
113
+ if (isLogPrimitive(value)) {
114
+ privatePayloads.set(marker, value);
115
+ } else {
116
+ invalidMarkers.add(marker);
117
+ }
118
+ return marker;
119
+ }
120
+
121
+ /**
122
+ * Stands in for a value that could not be read when a snapshot was taken —
123
+ * a getter that threw while a scope was being constructed.
124
+ *
125
+ * It is registered as an invalid marker, so redaction drops it and counts
126
+ * it like any other rejected value. Without it the key would vanish at
127
+ * snapshot time and never appear in `droppedMetadataCount`, which is the
128
+ * one thing a silent drop must never do. It carries no payload.
129
+ */
130
+ export const UNREADABLE_VALUE = (() => {
131
+ const marker = createMarker();
132
+ invalidMarkers.add(marker);
133
+ return marker;
134
+ })();
135
+ /** Module-private by design — see the note at the top of this file. */
136
+ function inspectMarker(value) {
137
+ if (value === null || typeof value !== 'object') return null;
138
+ const candidate = value;
139
+ if (publicPayloads.has(candidate)) {
140
+ const payload = publicPayloads.get(candidate);
141
+ return isLogPrimitive(payload) ? {
142
+ kind: 'public',
143
+ payload
144
+ } : {
145
+ kind: 'invalid'
146
+ };
147
+ }
148
+ if (privatePayloads.has(candidate)) {
149
+ const payload = privatePayloads.get(candidate);
150
+ return isLogPrimitive(payload) ? {
151
+ kind: 'private',
152
+ payload
153
+ } : {
154
+ kind: 'invalid'
155
+ };
156
+ }
157
+ if (invalidMarkers.has(candidate)) return {
158
+ kind: 'invalid'
159
+ };
160
+ return null;
161
+ }
162
+
163
+ // The reveal branch exists only in dev builds. Metro substitutes a literal
164
+ // for `__DEV__`, so in a release bundle the whole block — sentinel string
165
+ // included — is dead code and gets stripped. M7's CI job greps the release
166
+ // bundle for the sentinel to prove it.
167
+ let revealBranchSentinel = '';
168
+
169
+ /** True when private values may render as themselves: dev builds only.
170
+ * There is deliberately no runtime switch to turn this on in production. */
171
+ function privateRevealAllowed() {
172
+ if (typeof __DEV__ !== 'undefined' && __DEV__) {
173
+ revealBranchSentinel = '__NITRO_LOGGER_PRIVATE_REVEAL__';
174
+ return true;
175
+ }
176
+ return false;
177
+ }
178
+
179
+ /** @internal Test/CI hook — non-empty only once the dev reveal branch ran.
180
+ * Returns a build-time marker, never a payload. */
181
+ export function __revealBranchSentinel() {
182
+ return revealBranchSentinel;
183
+ }
184
+
185
+ // ── Configuration ───────────────────────────────────────────────────────────
186
+
187
+ /**
188
+ * Coerce a caller-supplied privacy default. TypeScript's union is not a
189
+ * runtime guarantee — JS callers, JSON config, and `any` all reach here — so
190
+ * anything that is not exactly `'public'` or `'private'` resolves to
191
+ * `'private'`. Ambiguity must never resolve toward disclosure.
192
+ */
193
+ export function normalizePrivacyDefault(value) {
194
+ return value === 'public' ? 'public' : 'private';
195
+ }
196
+
197
+ /**
198
+ * Build a catalog from caller-supplied input without trusting it. A
199
+ * non-iterable, an iterator that throws mid-way, a non-string entry, or an
200
+ * iterable longer than {@link MAX_CATALOG_SIZE} all yield an empty set: the
201
+ * caller's tighten-only intent is honored in the safest possible direction,
202
+ * and a runaway iterable cannot hang the JS thread.
203
+ */
204
+ export function buildCatalog(keys) {
205
+ const result = new Set();
206
+ if (keys === null || typeof keys !== 'object') return result;
207
+ try {
208
+ // Bound on entries CONSUMED, not on set size: an iterator that yields
209
+ // the same valid key forever never grows the set, so a size-based bound
210
+ // would spin the JS thread indefinitely.
211
+ let consumed = 0;
212
+ for (const key of keys) {
213
+ if (++consumed > MAX_CATALOG_SIZE) return new Set();
214
+ if (typeof key !== 'string' || !isValidMetadataKey(key)) {
215
+ return new Set();
216
+ }
217
+ result.add(key);
218
+ }
219
+ } catch {
220
+ return new Set();
221
+ }
222
+ return result;
223
+ }
224
+
225
+ /**
226
+ * Whether an unconfigured catalog blocks everything.
227
+ *
228
+ * Under a `'private'` default — the telehealth/strict profile — the catalog
229
+ * is mandatory and fail-closed: rejecting computed keys is not enough, since
230
+ * a literal key like `patient123` is still PHI. With no catalog configured,
231
+ * no key is approved and all metadata drops. That is deliberate; it forces
232
+ * the app to declare its keys rather than failing open.
233
+ */
234
+ function catalogRequired(settings) {
235
+ return settings.privacyDefault === 'private';
236
+ }
237
+
238
+ // ── Redaction ───────────────────────────────────────────────────────────────
239
+
240
+ const DROP = {
241
+ kind: 'drop'
242
+ };
243
+
244
+ /** Record which source owns each of its keys, without reading any value. */
245
+ function claimKeys(owner, source) {
246
+ if (!source) return;
247
+ let keys;
248
+ try {
249
+ keys = Object.keys(source);
250
+ } catch {
251
+ return;
252
+ }
253
+ for (const key of keys) {
254
+ owner.set(key, source);
255
+ }
256
+ }
257
+ function resolveValue(raw, settings) {
258
+ let visibility;
259
+ let payload;
260
+ const marker = inspectMarker(raw);
261
+ if (marker !== null) {
262
+ // A marker whose payload failed validation at construction or here —
263
+ // `pub(someObject as any)` — fails closed rather than rendering.
264
+ if (marker.kind === 'invalid') return DROP;
265
+ visibility = marker.kind;
266
+ payload = marker.payload;
267
+ } else if (isLogPrimitive(raw)) {
268
+ visibility = settings.privacyDefault;
269
+ payload = raw;
270
+ } else {
271
+ // Objects, arrays, proxies, functions, symbols, null, NaN, Infinity.
272
+ return DROP;
273
+ }
274
+ if (settings.redactAll) return {
275
+ kind: 'value',
276
+ value: PRIVATE_PLACEHOLDER
277
+ };
278
+ if (visibility === 'public') return {
279
+ kind: 'value',
280
+ value: payload
281
+ };
282
+ return {
283
+ kind: 'value',
284
+ value: privateRevealAllowed() ? payload : PRIVATE_PLACEHOLDER
285
+ };
286
+ }
287
+
288
+ /**
289
+ * Resolve caller metadata into what destinations may see.
290
+ *
291
+ * Takes metadata as ordered sources — a scope's defaults followed by the
292
+ * call site's — rather than a pre-merged object. Merging eagerly would read
293
+ * every value before any key was checked, which is exactly what this
294
+ * function exists to avoid: precedence is settled per key first, then the
295
+ * winning key is validated, and only a key that survives has its value read.
296
+ * A getter behind a malformed, reserved, or unapproved key therefore never
297
+ * runs, and neither does a getter the call site overrode.
298
+ *
299
+ * Every rejection — bad key, throwing getter, unsupported value —
300
+ * increments one count. The count is all that is reported: the diagnostic
301
+ * itself must not become the leak.
302
+ *
303
+ * The result is a frozen null-prototype object. A source whose keys cannot
304
+ * be enumerated at all (a Proxy with a throwing `ownKeys` trap) contributes
305
+ * nothing, since there is no key that could be safely counted or described.
306
+ */
307
+ export function redactMetadata(scopeMetadata, callSiteMetadata, settings) {
308
+ // Two explicit positional sources rather than a collection. A container
309
+ // in the signature would itself be caller-controlled — a hostile array
310
+ // could throw from Symbol.iterator, iterate forever, or be a revoked
311
+ // Proxy — and guarding it is strictly more work than not having one.
312
+ const owner = new Map();
313
+ claimKeys(owner, scopeMetadata);
314
+ // Second wins on collision: the call site overrides the scope's default.
315
+ claimKeys(owner, callSiteMetadata);
316
+ if (owner.size === 0) return undefined;
317
+ const catalog = settings.keyCatalog;
318
+ const requireCatalog = catalogRequired(settings);
319
+ const result = Object.create(null);
320
+ let dropped = 0;
321
+ for (const [key, source] of owner) {
322
+ if (key === DROPPED_COUNT_KEY || !isValidMetadataKey(key)) {
323
+ dropped += 1;
324
+ continue;
325
+ }
326
+ if (catalog !== undefined ? !catalog.has(key) : requireCatalog) {
327
+ dropped += 1;
328
+ continue;
329
+ }
330
+
331
+ // Only now — after the key has earned it — is the value touched.
332
+ let raw;
333
+ try {
334
+ raw = source[key];
335
+ } catch {
336
+ dropped += 1;
337
+ continue;
338
+ }
339
+ const resolution = resolveValue(raw, settings);
340
+ if (resolution.kind === 'drop') {
341
+ dropped += 1;
342
+ continue;
343
+ }
344
+ result[key] = resolution.value;
345
+ }
346
+ if (dropped > 0) result[DROPPED_COUNT_KEY] = dropped;
347
+ return Object.freeze(result);
348
+ }
349
+ //# sourceMappingURL=privacy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["PRIVATE_PLACEHOLDER","MARKER_PLACEHOLDER","METADATA_KEY_PATTERN","METADATA_KEY_PATTERN_SOURCE","isValidMetadataKey","key","test","DROPPED_COUNT_KEY","MAX_CATALOG_SIZE","publicPayloads","WeakMap","privatePayloads","invalidMarkers","WeakSet","isLogPrimitive","value","kind","Number","isFinite","createMarker","marker","hide","Object","defineProperty","enumerable","writable","configurable","placeholder","Symbol","toPrimitive","for","toStringTag","freeze","pub","set","add","priv","UNREADABLE_VALUE","inspectMarker","candidate","has","payload","get","revealBranchSentinel","privateRevealAllowed","__DEV__","__revealBranchSentinel","normalizePrivacyDefault","buildCatalog","keys","result","Set","consumed","catalogRequired","settings","privacyDefault","DROP","claimKeys","owner","source","resolveValue","raw","visibility","redactAll","redactMetadata","scopeMetadata","callSiteMetadata","Map","size","undefined","catalog","keyCatalog","requireCatalog","create","dropped","resolution"],"sourceRoot":"../../src","sources":["privacy.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export {};
4
+ //# sourceMappingURL=FileSink.nitro.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../../src","sources":["specs/FileSink.nitro.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export {};
4
+ //# sourceMappingURL=NativeConsoleSink.nitro.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../../src","sources":["specs/NativeConsoleSink.nitro.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * UTF-8 byte length, without allocating an encoder.
5
+ *
6
+ * `TextEncoder` is not guaranteed on every Hermes build this package targets,
7
+ * and counting is cheaper than encoding when the answer is all that is
8
+ * wanted. Every byte budget in this package — the sink's payload cap, the
9
+ * batcher's pending cap, a formatter's truncation limit — is a UTF-8 budget,
10
+ * because that is what actually reaches the file.
11
+ *
12
+ * An unpaired surrogate counts as 3, matching every standard encoder: it has
13
+ * no UTF-8 form of its own, so encoders substitute U+FFFD, which is three
14
+ * bytes.
15
+ */
16
+ export function utf8Length(text) {
17
+ let bytes = 0;
18
+ for (let i = 0; i < text.length; i += 1) {
19
+ const code = text.charCodeAt(i);
20
+ if (code < 0x80) {
21
+ bytes += 1;
22
+ } else if (code < 0x800) {
23
+ bytes += 2;
24
+ } else if (code >= 0xd800 && code <= 0xdbff) {
25
+ const next = text.charCodeAt(i + 1);
26
+ if (next >= 0xdc00 && next <= 0xdfff) {
27
+ bytes += 4;
28
+ i += 1;
29
+ } else {
30
+ // Lone high surrogate: encodes as U+FFFD.
31
+ bytes += 3;
32
+ }
33
+ } else if (code >= 0xdc00 && code <= 0xdfff) {
34
+ // Lone low surrogate: likewise.
35
+ bytes += 3;
36
+ } else {
37
+ bytes += 3;
38
+ }
39
+ }
40
+ return bytes;
41
+ }
42
+ //# sourceMappingURL=utf8.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["utf8Length","text","bytes","i","length","code","charCodeAt","next"],"sourceRoot":"../../src","sources":["utf8.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,UAAUA,CAACC,IAAY,EAAU;EAC/C,IAAIC,KAAK,GAAG,CAAC;EACb,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGF,IAAI,CAACG,MAAM,EAAED,CAAC,IAAI,CAAC,EAAE;IACvC,MAAME,IAAI,GAAGJ,IAAI,CAACK,UAAU,CAACH,CAAC,CAAC;IAC/B,IAAIE,IAAI,GAAG,IAAI,EAAE;MACfH,KAAK,IAAI,CAAC;IACZ,CAAC,MAAM,IAAIG,IAAI,GAAG,KAAK,EAAE;MACvBH,KAAK,IAAI,CAAC;IACZ,CAAC,MAAM,IAAIG,IAAI,IAAI,MAAM,IAAIA,IAAI,IAAI,MAAM,EAAE;MAC3C,MAAME,IAAI,GAAGN,IAAI,CAACK,UAAU,CAACH,CAAC,GAAG,CAAC,CAAC;MACnC,IAAII,IAAI,IAAI,MAAM,IAAIA,IAAI,IAAI,MAAM,EAAE;QACpCL,KAAK,IAAI,CAAC;QACVC,CAAC,IAAI,CAAC;MACR,CAAC,MAAM;QACL;QACAD,KAAK,IAAI,CAAC;MACZ;IACF,CAAC,MAAM,IAAIG,IAAI,IAAI,MAAM,IAAIA,IAAI,IAAI,MAAM,EAAE;MAC3C;MACAH,KAAK,IAAI,CAAC;IACZ,CAAC,MAAM;MACLA,KAAK,IAAI,CAAC;IACZ;EACF;EACA,OAAOA,KAAK;AACd","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,122 @@
1
+ import type { LazyMessage, LogLevel, LogMetadata } from './types.js';
2
+ import type { LogDestination } from './destinations/types.js';
3
+ import type { PrivacyDefault } from './privacy.js';
4
+ import { ScopedLogger } from './ScopedLogger.js';
5
+ export interface LogOptions {
6
+ level?: LogLevel;
7
+ subsystem?: string;
8
+ metadata?: LogMetadata;
9
+ /** Scope defaults, outranked by `metadata` on any key they share. Kept a
10
+ * separate field rather than pre-merged: redaction settles precedence per
11
+ * key and validates the winner before reading it, which a merge would
12
+ * defeat by reading everything first. `ScopedLogger` sets this. */
13
+ scopeMetadata?: LogMetadata;
14
+ correlation?: string;
15
+ }
16
+ /**
17
+ * The logger. Access through the `Log` singleton.
18
+ *
19
+ * Everything runs on the JS thread, so unlike the Swift original there is no
20
+ * lock or config-snapshot machinery — plain fields mutated by the fluent
21
+ * methods are safe by construction.
22
+ *
23
+ * Pipeline per message: resolve effective level (exact subsystem → parent
24
+ * walk → global) → collect destinations passing isEnabled AND minimumLevel →
25
+ * return BEFORE evaluating a lazy message when none remain → evaluate once,
26
+ * guarded → prepare metadata (redaction seam; M2 adds privacy wrappers) →
27
+ * freeze → fan out with per-destination isolation.
28
+ *
29
+ * Destinations are treated as untrusted: every property read and call is
30
+ * guarded so one faulty implementation can neither crash the app nor starve
31
+ * its siblings.
32
+ */
33
+ export declare class Logger {
34
+ private globalMinimum;
35
+ private readonly subsystemLevels;
36
+ private registrations;
37
+ /** Consecutive write-failure counts per destination label. */
38
+ private readonly failureCounts;
39
+ private readonly disabledLabels;
40
+ private privacyDefaultValue;
41
+ private privacyDefaultLocked;
42
+ private redactAll;
43
+ private keyCatalog;
44
+ /**
45
+ * Choose how bare (unmarked) metadata values are treated.
46
+ *
47
+ * `'public'` — the OSS default — renders them. `'private'` redacts every
48
+ * bare value outside dev builds unless wrapped in `pub()`, so a forgotten
49
+ * wrapper hides data instead of leaking it. Apps handling PHI set
50
+ * `'private'` in their entry point.
51
+ *
52
+ * First call wins; later calls may only tighten (`'public'` → `'private'`).
53
+ * A request to loosen is ignored, not obeyed. Anything that is not exactly
54
+ * `'public'` or `'private'` — a JS caller, JSON config, an `any` — resolves
55
+ * to `'private'`: ambiguity must never resolve toward disclosure.
56
+ *
57
+ * `'private'` also makes the metadata key catalog mandatory — see
58
+ * {@link metadataKeyCatalog}.
59
+ */
60
+ privacyDefault(value: PrivacyDefault): this;
61
+ /** Redact every metadata value from here on, marked or not, dev or not.
62
+ * One-way: there is no call that undoes it. */
63
+ redactAllMetadata(): this;
64
+ /**
65
+ * Restrict metadata to an approved set of keys; anything else is dropped
66
+ * and counted. Rejecting computed keys is not enough on its own — a
67
+ * literal key like `patient123` is still PHI — so the catalog checks exact
68
+ * membership at runtime.
69
+ *
70
+ * Tighten-only: repeat calls intersect with the existing catalog rather
71
+ * than replacing it. Mandatory under a `'private'` privacy default, where
72
+ * an unconfigured catalog approves nothing and all metadata drops.
73
+ *
74
+ * Input is not trusted: a non-iterable, a throwing iterator, a non-string
75
+ * or malformed entry, or an over-long iterable all yield an empty catalog
76
+ * rather than an exception or a hung JS thread.
77
+ */
78
+ metadataKeyCatalog(keys: Iterable<string>): this;
79
+ private privacySettings;
80
+ /** Global minimum level; messages below it are discarded. Default 'debug'. */
81
+ minimumLevel(level: LogLevel): this;
82
+ /** Minimum level for a dot-hierarchical subsystem (`network` covers
83
+ * `network.api` unless the child sets its own). */
84
+ subsystem(name: string, level: LogLevel): this;
85
+ resetSubsystem(name: string): this;
86
+ /** Toggle console printing. The console destination's test sink, when set,
87
+ * keeps receiving lines regardless. */
88
+ consoleLogging(enabled: boolean): this;
89
+ /**
90
+ * Register a destination. A *different* destination already holding the
91
+ * same label is flushed, disposed, and replaced; re-adding an instance
92
+ * that is already registered is a no-op, because disposing and re-pushing
93
+ * the same object would leave a live destination in a closed state.
94
+ */
95
+ addDestination(destination: LogDestination): this;
96
+ removeDestination(label: string): this;
97
+ /** Drain every destination synchronously (bounded per destination). */
98
+ flush(deadlineMs?: number): void;
99
+ /** Short-lived random correlation ID — the encouraged way to correlate.
100
+ * Never derive correlation IDs from patient/visit/record identifiers. */
101
+ newCorrelationId(): string;
102
+ /** A scoped logger tagging every message with a correlation ID, optional
103
+ * subsystem, and default metadata. Omit `correlation` to auto-generate. */
104
+ scoped(correlation?: string, subsystem?: string, metadata?: LogMetadata): ScopedLogger;
105
+ log(message: LazyMessage, options?: LogOptions): void;
106
+ verbose(message: LazyMessage, metadata?: LogMetadata, subsystem?: string): void;
107
+ debug(message: LazyMessage, metadata?: LogMetadata, subsystem?: string): void;
108
+ info(message: LazyMessage, metadata?: LogMetadata, subsystem?: string): void;
109
+ warning(message: LazyMessage, metadata?: LogMetadata, subsystem?: string): void;
110
+ error(message: LazyMessage, metadata?: LogMetadata, subsystem?: string): void;
111
+ /** Marks incomplete work; highest severity so it always surfaces. */
112
+ todo(message: LazyMessage, metadata?: LogMetadata, subsystem?: string): void;
113
+ /** Integration entry point (ScopedLogger, error handler, bridges). */
114
+ logMessage(message: LazyMessage, options?: LogOptions): void;
115
+ /** Count a consecutive failure; disable the destination at the threshold.
116
+ * The diagnostic is fixed text — labels are caller-controlled, so including
117
+ * one would break the payload-free contract and invite log injection. */
118
+ private noteFailure;
119
+ }
120
+ /** Global shorthand, mirroring SwiftLogger's `Log`. */
121
+ export declare const Log: Logger;
122
+ //# sourceMappingURL=Logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../../../src/Logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { LazyMessage, LogLevel, LogMetadata } from './types.js';
2
+ import type { Logger } from './Logger.js';
3
+ /**
4
+ * A lightweight logger that tags every message with a correlation ID,
5
+ * optional default subsystem, and default metadata. Direct port of
6
+ * SwiftLogger's ScopedLogger: immutable, delegates all work to the parent
7
+ * Logger, nests.
8
+ *
9
+ * Metadata semantics: the scope's metadata merges into every message;
10
+ * call-site keys win on collision (a message reporting `state: 'failed'`
11
+ * must not be masked by the scope's `state: 'running'`). Child scopes merge
12
+ * into — never replace — the parent's metadata.
13
+ */
14
+ export declare class ScopedLogger {
15
+ private readonly logger;
16
+ readonly correlation: string;
17
+ readonly subsystem?: string | undefined;
18
+ /** Frozen snapshot taken at construction — mutating the object the caller
19
+ * passed in (or this field) after the fact must not change future logs,
20
+ * matching SwiftLogger's value semantics. */
21
+ readonly metadata?: Readonly<LogMetadata>;
22
+ constructor(logger: Logger, correlation: string, subsystem?: string | undefined, metadata?: LogMetadata);
23
+ log(message: LazyMessage, level?: LogLevel, metadata?: LogMetadata): void;
24
+ verbose(message: LazyMessage, metadata?: LogMetadata): void;
25
+ debug(message: LazyMessage, metadata?: LogMetadata): void;
26
+ info(message: LazyMessage, metadata?: LogMetadata): void;
27
+ warning(message: LazyMessage, metadata?: LogMetadata): void;
28
+ error(message: LazyMessage, metadata?: LogMetadata): void;
29
+ todo(message: LazyMessage, metadata?: LogMetadata): void;
30
+ /** Child scope: inherits this scope's subsystem unless overridden, merges
31
+ * metadata (child keys win). The merge happens at construction, like any
32
+ * scope snapshot — both sides are materialized here so later mutation of
33
+ * the caller's object cannot change what the child reports. */
34
+ scoped(correlation: string, subsystem?: string, metadata?: LogMetadata): ScopedLogger;
35
+ }
36
+ //# sourceMappingURL=ScopedLogger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScopedLogger.d.ts","sourceRoot":"","sources":["../../../src/ScopedLogger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAS,CAAC;AAClE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAU,CAAC;AAGvC;;;;;;;;;;GAUG;AACH,qBAAa,YAAY;IAOrB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM;IAR7B;;iDAE6C;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;gBAGvB,MAAM,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,YAAA,EAC3B,QAAQ,CAAC,EAAE,WAAW;IAMxB,GAAG,CACD,OAAO,EAAE,WAAW,EACpB,KAAK,GAAE,QAAiB,EACxB,QAAQ,CAAC,EAAE,WAAW,GACrB,IAAI;IAcP,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,IAAI;IAI3D,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,IAAI;IAIzD,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,IAAI;IAIxD,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,IAAI;IAI3D,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,IAAI;IAIzD,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,IAAI;IAIxD;;;mEAG+D;IAC/D,MAAM,CACJ,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,WAAW,GACrB,YAAY;CAYhB"}
@@ -0,0 +1,12 @@
1
+ import type { LogLevel } from './types.js';
2
+ /**
3
+ * Resolves the effective minimum level for a subsystem by walking the
4
+ * dot-separated hierarchy: exact match, then each parent (`a.b.c` → `a.b` →
5
+ * `a`), then undefined so the caller falls back to the global minimum.
6
+ * Direct port of SwiftLogger's LoggerConfiguration.resolveSubsystemLevel.
7
+ *
8
+ * Single-threaded JS means no snapshot/locking machinery — a plain Map
9
+ * mutated by the fluent config methods is safe.
10
+ */
11
+ export declare function resolveSubsystemLevel(subsystemLevels: ReadonlyMap<string, LogLevel>, name: string): LogLevel | undefined;
12
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAS,CAAC;AAExC;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,EAC9C,IAAI,EAAE,MAAM,GACX,QAAQ,GAAG,SAAS,CAUtB"}