@logbrew/react-native 0.1.9 → 0.1.10

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.
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  React Native helpers for the public LogBrew JavaScript SDK.
8
8
 
9
- This package is intentionally thin. It keeps all event validation, retry, flush, and shutdown behavior in `@logbrew/sdk`, while adding mobile-friendly helpers for screen views, app-state changes, product actions, API milestones, handled JavaScript errors, app-owned Promise rejection reports, provider/hook usage, active W3C trace correlation, explicit W3C trace propagation, opt-in lifecycle spans, opt-in resource fetch spans, opt-in reversible global fetch spans, app-owned native bridge scope sync, and reversible instrumentation setup.
9
+ This package is intentionally thin. It keeps all event validation, retry, flush, and shutdown behavior in `@logbrew/sdk`, while adding mobile-friendly helpers for screen views, app-state changes, product actions, API milestones, handled JavaScript errors, opt-in Hermes Promise rejection tracking, app-owned Promise rejection callbacks, provider/hook usage, active W3C trace correlation, explicit W3C trace propagation, opt-in lifecycle spans, opt-in resource fetch spans, opt-in reversible global fetch spans, app-owned native bridge scope sync, and reversible instrumentation setup.
10
10
 
11
11
  ## Install
12
12
 
@@ -202,7 +202,49 @@ Installation is idempotent for the active React Native `ErrorUtils` object. The
202
202
 
203
203
  The React Native conditional export obtains LogBrew's synchronous native fatal store through the supported TurboModule or `NativeModules` seam. Before chaining a fatal report, it writes one bounded record to app-private storage that is excluded from operating-system archives. On a later installation it performs stable-ID at-least-once replay, and acknowledgement happens only after local queue admission is observable through the SDK queue counters. Filtered, dropped, unknown-admission, persistence-failed, and acknowledgement-failed records are retained. A failed acknowledgement is retried without admitting the same ID twice in one JavaScript runtime. Use `fatalHealth()` for frozen bounded counters and status, or `discardPendingFatalRecord()` for an explicit rollback discard. The Node ESM and CommonJS entries never import React Native; non-React-Native callers must inject `fatalStore` explicitly.
204
204
 
205
- Automatic events exclude the original error message, raw stack, arbitrary metadata, full URLs, hosts, query strings, local absolute paths, payloads, and native error text. `onDiagnostic` receives only a fixed code. This integration does not claim mathematically exactly-once delivery, backend-visible deduplication, native crash capture, automatic Promise rejection tracker ownership, ANR or hang detection, general offline queueing, or symbolication.
205
+ Automatic events exclude the original error message, raw stack, arbitrary metadata, full URLs, hosts, query strings, local absolute paths, payloads, and native error text. `onDiagnostic` receives only a fixed code. This integration does not claim mathematically exactly-once delivery, backend-visible deduplication, native crash capture, ANR or hang detection, general offline queueing, or symbolication.
206
+
207
+ ### Opt-in Hermes Promise rejection tracking
208
+
209
+ React Native exposes one Promise rejection tracker slot. Claim it explicitly
210
+ when LogBrew is the only tracker owner:
211
+
212
+ ```js
213
+ import {
214
+ installLogBrewReactNativePromiseRejectionTracker
215
+ } from "@logbrew/react-native";
216
+
217
+ const promiseRejectionTracker =
218
+ installLogBrewReactNativePromiseRejectionTracker({
219
+ client,
220
+ takeOwnership: true,
221
+ onDiagnostic({ code }) {
222
+ console.warn(`LogBrew Promise rejection tracker: ${code}`);
223
+ }
224
+ });
225
+
226
+ promiseRejectionTracker.health();
227
+ promiseRejectionTracker.rejectionHealth();
228
+ ```
229
+
230
+ The React Native export discovers the active Hermes runtime and uses its
231
+ native tracker without replacing `globalThis.Promise`. Installation is
232
+ idempotent for that runtime slot. It records fixed-content issues without
233
+ reading the rejection value or emitting the runtime rejection identifier.
234
+ `rejectionHealth()` returns bounded duplicate, eviction, and later-handled
235
+ counters.
236
+
237
+ Do not install this helper while Sentry or another integration owns the same
238
+ tracker slot. Use the app-owned callback composition below when another
239
+ integration must remain the owner. Hermes does not expose a previous-owner
240
+ restoration API. `deactivate()` therefore stops LogBrew capture through its
241
+ installed callbacks but cannot reinstate an earlier tracker. Install
242
+ the replacement owner after deactivation when switching integrations.
243
+
244
+ For JavaScriptCore or another runtime, pass an explicit `tracker` with an
245
+ `enable(options)` function that already controls the Promise implementation
246
+ used by the app. LogBrew does not replace the global Promise or add a hidden
247
+ Promise polyfill.
206
248
 
207
249
  ### App-owned Promise rejection reports
208
250
 
package/global-errors.cjs CHANGED
@@ -3,7 +3,8 @@
3
3
  const { createReactNativeErrorEvent } = require("./index.cjs");
4
4
  const { createFatalController } = require("./fatal-replay.cjs");
5
5
  const {
6
- createLogBrewReactNativePromiseRejectionHandlers
6
+ createLogBrewReactNativePromiseRejectionHandlers,
7
+ installLogBrewReactNativePromiseRejectionTracker
7
8
  } = require("./promise-rejections.cjs");
8
9
 
9
10
  const AUTOMATIC_ERROR_MESSAGE = "React Native global JavaScript report";
@@ -412,7 +413,8 @@ function isObjectLike(value) {
412
413
 
413
414
  const defaultExport = {
414
415
  createLogBrewReactNativePromiseRejectionHandlers,
415
- installLogBrewReactNativeGlobalErrorHandler
416
+ installLogBrewReactNativeGlobalErrorHandler,
417
+ installLogBrewReactNativePromiseRejectionTracker
416
418
  };
417
419
 
418
420
  module.exports = { ...defaultExport, default: defaultExport };
@@ -14,6 +14,9 @@ export type ReactNativePromiseRejectionDiagnosticCode =
14
14
  | "promise_rejection_handler_unavailable"
15
15
  | "promise_rejection_id_unavailable"
16
16
  | "promise_rejection_recursive_capture_suppressed"
17
+ | "promise_rejection_tracker_installation_failed"
18
+ | "promise_rejection_tracker_ownership_required"
19
+ | "promise_rejection_tracker_unavailable"
17
20
  | "promise_rejection_tracking_evicted";
18
21
 
19
22
  export type ReactNativePromiseRejectionDiagnostic = Readonly<{
@@ -96,6 +99,54 @@ export type LogBrewReactNativePromiseRejectionHandlers = Readonly<{
96
99
  onUnhandled(runtimeRejectionId: unknown, rejection?: unknown): void;
97
100
  }>;
98
101
 
102
+ export type ReactNativePromiseRejectionTrackerLike = {
103
+ enable(options: Readonly<{
104
+ allRejections: true;
105
+ onHandled(runtimeRejectionId: unknown): void;
106
+ onUnhandled(runtimeRejectionId: unknown, rejection?: unknown): void;
107
+ }>): void;
108
+ };
109
+
110
+ export type InstallLogBrewReactNativePromiseRejectionTrackerOptions = {
111
+ client: Pick<LogBrewClient, "issue">;
112
+ /**
113
+ * Confirms that LogBrew may claim the runtime's single Promise rejection
114
+ * tracker slot. Do not install another tracker owner at the same time.
115
+ */
116
+ takeOwnership: true;
117
+ /**
118
+ * Optional tracker seam. The React Native conditional export discovers the
119
+ * active Hermes tracker when this is omitted.
120
+ */
121
+ tracker?: ReactNativePromiseRejectionTrackerLike;
122
+ maxTrackedRejections?: number;
123
+ onDiagnostic?: (diagnostic: ReactNativePromiseRejectionDiagnostic) => void;
124
+ };
125
+
126
+ export type ReactNativePromiseRejectionTrackerHealth = Readonly<{
127
+ active: boolean;
128
+ available: boolean;
129
+ engine: "custom" | "hermes" | "unavailable";
130
+ lastOutcome:
131
+ | "deactivated"
132
+ | "handler_unavailable"
133
+ | "installation_failed"
134
+ | "installed"
135
+ | "ownership_required"
136
+ | "tracker_unavailable";
137
+ restoration: "deactivate_only";
138
+ }>;
139
+
140
+ export type LogBrewReactNativePromiseRejectionTrackerInstallation = Readonly<{
141
+ /**
142
+ * Stops LogBrew capture through the installed callbacks. Hermes does not
143
+ * expose a previous-owner restoration API, so this cannot restore one.
144
+ */
145
+ deactivate(): boolean;
146
+ health(): ReactNativePromiseRejectionTrackerHealth;
147
+ rejectionHealth(): ReactNativePromiseRejectionHealth;
148
+ }>;
149
+
99
150
  export type ReactNativeFatalRecord = Readonly<{
100
151
  corruptRecords: number;
101
152
  droppedRecords: number;
@@ -175,6 +226,17 @@ export declare function createLogBrewReactNativePromiseRejectionHandlers(
175
226
  options: CreateLogBrewReactNativePromiseRejectionHandlersOptions
176
227
  ): LogBrewReactNativePromiseRejectionHandlers;
177
228
 
229
+ /**
230
+ * Install privacy-safe automatic Promise rejection capture.
231
+ *
232
+ * Installation is opt-in because React Native runtimes expose one tracker slot.
233
+ * The React Native conditional export discovers Hermes without replacing the
234
+ * global Promise. Other runtimes can inject a compatible tracker explicitly.
235
+ */
236
+ export declare function installLogBrewReactNativePromiseRejectionTracker(
237
+ options: InstallLogBrewReactNativePromiseRejectionTrackerOptions
238
+ ): LogBrewReactNativePromiseRejectionTrackerInstallation;
239
+
178
240
  /**
179
241
  * Install reversible automatic capture for React Native global JavaScript errors.
180
242
  *
@@ -190,6 +252,7 @@ export declare function installLogBrewReactNativeGlobalErrorHandler(
190
252
  declare const logBrewReactNativeGlobalErrors: {
191
253
  createLogBrewReactNativePromiseRejectionHandlers: typeof createLogBrewReactNativePromiseRejectionHandlers;
192
254
  installLogBrewReactNativeGlobalErrorHandler: typeof installLogBrewReactNativeGlobalErrorHandler;
255
+ installLogBrewReactNativePromiseRejectionTracker: typeof installLogBrewReactNativePromiseRejectionTracker;
193
256
  };
194
257
 
195
258
  export default logBrewReactNativeGlobalErrors;
@@ -14,6 +14,9 @@ export type ReactNativePromiseRejectionDiagnosticCode =
14
14
  | "promise_rejection_handler_unavailable"
15
15
  | "promise_rejection_id_unavailable"
16
16
  | "promise_rejection_recursive_capture_suppressed"
17
+ | "promise_rejection_tracker_installation_failed"
18
+ | "promise_rejection_tracker_ownership_required"
19
+ | "promise_rejection_tracker_unavailable"
17
20
  | "promise_rejection_tracking_evicted";
18
21
 
19
22
  export type ReactNativePromiseRejectionDiagnostic = Readonly<{
@@ -96,6 +99,54 @@ export type LogBrewReactNativePromiseRejectionHandlers = Readonly<{
96
99
  onUnhandled(runtimeRejectionId: unknown, rejection?: unknown): void;
97
100
  }>;
98
101
 
102
+ export type ReactNativePromiseRejectionTrackerLike = {
103
+ enable(options: Readonly<{
104
+ allRejections: true;
105
+ onHandled(runtimeRejectionId: unknown): void;
106
+ onUnhandled(runtimeRejectionId: unknown, rejection?: unknown): void;
107
+ }>): void;
108
+ };
109
+
110
+ export type InstallLogBrewReactNativePromiseRejectionTrackerOptions = {
111
+ client: Pick<LogBrewClient, "issue">;
112
+ /**
113
+ * Confirms that LogBrew may claim the runtime's single Promise rejection
114
+ * tracker slot. Do not install another tracker owner at the same time.
115
+ */
116
+ takeOwnership: true;
117
+ /**
118
+ * Optional tracker seam. The React Native conditional export discovers the
119
+ * active Hermes tracker when this is omitted.
120
+ */
121
+ tracker?: ReactNativePromiseRejectionTrackerLike;
122
+ maxTrackedRejections?: number;
123
+ onDiagnostic?: (diagnostic: ReactNativePromiseRejectionDiagnostic) => void;
124
+ };
125
+
126
+ export type ReactNativePromiseRejectionTrackerHealth = Readonly<{
127
+ active: boolean;
128
+ available: boolean;
129
+ engine: "custom" | "hermes" | "unavailable";
130
+ lastOutcome:
131
+ | "deactivated"
132
+ | "handler_unavailable"
133
+ | "installation_failed"
134
+ | "installed"
135
+ | "ownership_required"
136
+ | "tracker_unavailable";
137
+ restoration: "deactivate_only";
138
+ }>;
139
+
140
+ export type LogBrewReactNativePromiseRejectionTrackerInstallation = Readonly<{
141
+ /**
142
+ * Stops LogBrew capture through the installed callbacks. Hermes does not
143
+ * expose a previous-owner restoration API, so this cannot restore one.
144
+ */
145
+ deactivate(): boolean;
146
+ health(): ReactNativePromiseRejectionTrackerHealth;
147
+ rejectionHealth(): ReactNativePromiseRejectionHealth;
148
+ }>;
149
+
99
150
  export type ReactNativeFatalRecord = Readonly<{
100
151
  corruptRecords: number;
101
152
  droppedRecords: number;
@@ -175,6 +226,17 @@ export declare function createLogBrewReactNativePromiseRejectionHandlers(
175
226
  options: CreateLogBrewReactNativePromiseRejectionHandlersOptions
176
227
  ): LogBrewReactNativePromiseRejectionHandlers;
177
228
 
229
+ /**
230
+ * Install privacy-safe automatic Promise rejection capture.
231
+ *
232
+ * Installation is opt-in because React Native runtimes expose one tracker slot.
233
+ * The React Native conditional export discovers Hermes without replacing the
234
+ * global Promise. Other runtimes can inject a compatible tracker explicitly.
235
+ */
236
+ export declare function installLogBrewReactNativePromiseRejectionTracker(
237
+ options: InstallLogBrewReactNativePromiseRejectionTrackerOptions
238
+ ): LogBrewReactNativePromiseRejectionTrackerInstallation;
239
+
178
240
  /**
179
241
  * Install reversible automatic capture for React Native global JavaScript errors.
180
242
  *
@@ -190,6 +252,7 @@ export declare function installLogBrewReactNativeGlobalErrorHandler(
190
252
  declare const logBrewReactNativeGlobalErrors: {
191
253
  createLogBrewReactNativePromiseRejectionHandlers: typeof createLogBrewReactNativePromiseRejectionHandlers;
192
254
  installLogBrewReactNativeGlobalErrorHandler: typeof installLogBrewReactNativeGlobalErrorHandler;
255
+ installLogBrewReactNativePromiseRejectionTracker: typeof installLogBrewReactNativePromiseRejectionTracker;
193
256
  };
194
257
 
195
258
  export default logBrewReactNativeGlobalErrors;
package/global-errors.js CHANGED
@@ -2,7 +2,8 @@ import implementation from "./global-errors.cjs";
2
2
 
3
3
  export const {
4
4
  createLogBrewReactNativePromiseRejectionHandlers,
5
- installLogBrewReactNativeGlobalErrorHandler
5
+ installLogBrewReactNativeGlobalErrorHandler,
6
+ installLogBrewReactNativePromiseRejectionTracker
6
7
  } = implementation;
7
8
 
8
9
  export default implementation;
@@ -2,13 +2,16 @@ import { NativeModules, TurboModuleRegistry } from "react-native";
2
2
 
3
3
  import {
4
4
  createLogBrewReactNativePromiseRejectionHandlers,
5
- installLogBrewReactNativeGlobalErrorHandler as installPlatformNeutralHandler
5
+ installLogBrewReactNativeGlobalErrorHandler as installPlatformNeutralHandler,
6
+ installLogBrewReactNativePromiseRejectionTracker as installPlatformNeutralTracker
6
7
  } from "./global-errors.js";
7
8
 
8
9
  export {
9
10
  createLogBrewReactNativePromiseRejectionHandlers
10
11
  };
11
12
 
13
+ const hermesTrackerAdapters = new WeakMap();
14
+
12
15
  function defaultFatalStore() {
13
16
  try {
14
17
  return TurboModuleRegistry?.get?.("LogBrewFatalStore")
@@ -18,6 +21,40 @@ function defaultFatalStore() {
18
21
  }
19
22
  }
20
23
 
24
+ function defaultPromiseRejectionTracker() {
25
+ let hermes;
26
+ let enable;
27
+ let hasPromise;
28
+ try {
29
+ hermes = globalThis?.HermesInternal;
30
+ if (hermes === null
31
+ || (typeof hermes !== "object" && typeof hermes !== "function")) {
32
+ return undefined;
33
+ }
34
+ enable = hermes.enablePromiseRejectionTracker;
35
+ hasPromise = hermes.hasPromise;
36
+ if (typeof enable !== "function"
37
+ || typeof hasPromise !== "function"
38
+ || hasPromise.call(hermes) !== true) {
39
+ return undefined;
40
+ }
41
+ } catch {
42
+ return undefined;
43
+ }
44
+
45
+ const existing = hermesTrackerAdapters.get(hermes);
46
+ if (existing) {
47
+ return existing;
48
+ }
49
+ const adapter = Object.freeze({
50
+ enable(options) {
51
+ return enable.call(hermes, options);
52
+ }
53
+ });
54
+ hermesTrackerAdapters.set(hermes, adapter);
55
+ return adapter;
56
+ }
57
+
21
58
  export function installLogBrewReactNativeGlobalErrorHandler(options = {}) {
22
59
  let forwarded;
23
60
  let hasInjectedStore = false;
@@ -37,9 +74,33 @@ export function installLogBrewReactNativeGlobalErrorHandler(options = {}) {
37
74
  });
38
75
  }
39
76
 
77
+ export function installLogBrewReactNativePromiseRejectionTracker(options = {}) {
78
+ let forwarded;
79
+ let hasInjectedTracker = false;
80
+ try {
81
+ const input = options !== null
82
+ && (typeof options === "object" || typeof options === "function")
83
+ ? options
84
+ : {};
85
+ hasInjectedTracker = Object.prototype.hasOwnProperty.call(input, "tracker");
86
+ forwarded = { ...input };
87
+ } catch {
88
+ forwarded = {};
89
+ }
90
+ const tracker = hasInjectedTracker
91
+ ? forwarded.tracker
92
+ : defaultPromiseRejectionTracker();
93
+ return installPlatformNeutralTracker({
94
+ ...forwarded,
95
+ tracker,
96
+ trackerKind: hasInjectedTracker ? "custom" : tracker ? "hermes" : undefined
97
+ });
98
+ }
99
+
40
100
  const logBrewReactNativeGlobalErrors = {
41
101
  createLogBrewReactNativePromiseRejectionHandlers,
42
- installLogBrewReactNativeGlobalErrorHandler
102
+ installLogBrewReactNativeGlobalErrorHandler,
103
+ installLogBrewReactNativePromiseRejectionTracker
43
104
  };
44
105
 
45
106
  export default logBrewReactNativeGlobalErrors;
package/index.native.d.ts CHANGED
@@ -1,2 +1,5 @@
1
1
  export * from "./index";
2
- export { installLogBrewReactNativeGlobalErrorHandler } from "./global-errors";
2
+ export {
3
+ installLogBrewReactNativeGlobalErrorHandler,
4
+ installLogBrewReactNativePromiseRejectionTracker
5
+ } from "./global-errors";
package/index.native.js CHANGED
@@ -10,7 +10,8 @@ import {
10
10
  getReactNativeContext
11
11
  } from "./index.js";
12
12
  export {
13
- installLogBrewReactNativeGlobalErrorHandler
13
+ installLogBrewReactNativeGlobalErrorHandler,
14
+ installLogBrewReactNativePromiseRejectionTracker
14
15
  } from "./global-errors.native.js";
15
16
 
16
17
  export * from "./index.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logbrew/react-native",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "React Native screen, error, trace, action, and network timeline helpers for LogBrew.",
5
5
  "type": "module",
6
6
  "main": "./index.cjs",
@@ -6,9 +6,17 @@ const AUTOMATIC_MESSAGE = "Unhandled Promise rejection";
6
6
  const DEFAULT_MAX_TRACKED_REJECTIONS = 128;
7
7
  const MAX_TRACKED_REJECTIONS = 1024;
8
8
  const MAX_STRING_ID_LENGTH = 128;
9
+ const activeTrackerInstallations = new WeakMap();
9
10
  let nextEventSequence = 0;
10
11
 
11
12
  function createLogBrewReactNativePromiseRejectionHandlers(options = {}) {
13
+ return createPromiseRejectionHandlers(
14
+ options,
15
+ "app_owned_promise_rejection_tracker"
16
+ );
17
+ }
18
+
19
+ function createPromiseRejectionHandlers(options, mechanism) {
12
20
  const input = isObjectLike(options) ? options : {};
13
21
  const client = safeReadProperty(input, "client");
14
22
  const issue = safeFunction(client, "issue");
@@ -92,7 +100,7 @@ function createLogBrewReactNativePromiseRejectionHandlers(options = {}) {
92
100
  if (key === undefined) {
93
101
  emitStateDiagnostic(state, onDiagnostic, "promise_rejection_id_unavailable");
94
102
  }
95
- const event = createEvent();
103
+ const event = createEvent(mechanism);
96
104
  issue.call(client, event.id, event.timestamp, event.attributes);
97
105
  state.capturedEvents = incrementBounded(state.capturedEvents);
98
106
 
@@ -124,7 +132,93 @@ function createLogBrewReactNativePromiseRejectionHandlers(options = {}) {
124
132
  });
125
133
  }
126
134
 
127
- function createEvent() {
135
+ function installLogBrewReactNativePromiseRejectionTracker(options = {}) {
136
+ const input = isObjectLike(options) ? options : {};
137
+ const onDiagnostic = safeFunction(input, "onDiagnostic");
138
+ if (safeReadProperty(input, "takeOwnership") !== true) {
139
+ emitDiagnostic(onDiagnostic, "promise_rejection_tracker_ownership_required");
140
+ return inactiveTrackerInstallation("ownership_required");
141
+ }
142
+
143
+ const tracker = safeReadProperty(input, "tracker");
144
+ const enable = safeFunction(tracker, "enable");
145
+ const engine = safeReadProperty(input, "trackerKind") === "hermes"
146
+ ? "hermes"
147
+ : isObjectLike(tracker) ? "custom" : "unavailable";
148
+ if (!isObjectLike(tracker) || !enable) {
149
+ emitDiagnostic(onDiagnostic, "promise_rejection_tracker_unavailable");
150
+ return inactiveTrackerInstallation("tracker_unavailable", engine);
151
+ }
152
+
153
+ const existing = activeTrackerInstallations.get(tracker);
154
+ if (existing?.health().active) {
155
+ return existing;
156
+ }
157
+
158
+ const handlers = createPromiseRejectionHandlers(
159
+ input,
160
+ "logbrew_owned_promise_rejection_tracker"
161
+ );
162
+ if (!handlers.health().available) {
163
+ return inactiveTrackerInstallation("handler_unavailable", engine, handlers);
164
+ }
165
+
166
+ const state = {
167
+ active: true,
168
+ lastOutcome: "installed"
169
+ };
170
+ const trackerOptions = Object.freeze({
171
+ allRejections: true,
172
+ onHandled(runtimeRejectionId) {
173
+ if (state.active) {
174
+ handlers.onHandled(runtimeRejectionId);
175
+ }
176
+ },
177
+ onUnhandled(runtimeRejectionId, rejection) {
178
+ if (state.active) {
179
+ handlers.onUnhandled(runtimeRejectionId, rejection);
180
+ }
181
+ }
182
+ });
183
+
184
+ const installation = Object.freeze({
185
+ deactivate() {
186
+ if (!state.active) {
187
+ return false;
188
+ }
189
+ state.active = false;
190
+ state.lastOutcome = "deactivated";
191
+ if (activeTrackerInstallations.get(tracker) === installation) {
192
+ activeTrackerInstallations.delete(tracker);
193
+ }
194
+ return true;
195
+ },
196
+ health() {
197
+ return trackerHealthSnapshot(state, engine, true);
198
+ },
199
+ rejectionHealth() {
200
+ return handlers.health();
201
+ }
202
+ });
203
+
204
+ try {
205
+ enable.call(tracker, trackerOptions);
206
+ } catch {
207
+ state.active = false;
208
+ state.lastOutcome = "installation_failed";
209
+ emitDiagnostic(onDiagnostic, "promise_rejection_tracker_installation_failed");
210
+ return inactiveTrackerInstallation(
211
+ "installation_failed",
212
+ engine,
213
+ handlers
214
+ );
215
+ }
216
+
217
+ activeTrackerInstallations.set(tracker, installation);
218
+ return installation;
219
+ }
220
+
221
+ function createEvent(mechanism) {
128
222
  const error = new Error(AUTOMATIC_MESSAGE);
129
223
  delete error.stack;
130
224
  const event = createReactNativeErrorEvent(error, {
@@ -142,7 +236,7 @@ function createEvent() {
142
236
  automatic: true,
143
237
  fatal: false,
144
238
  handled: false,
145
- mechanism: "app_owned_promise_rejection_tracker",
239
+ mechanism,
146
240
  source: "react-native.promise_rejection"
147
241
  }
148
242
  }
@@ -224,6 +318,35 @@ function inactiveHandlers() {
224
318
  });
225
319
  }
226
320
 
321
+ function inactiveTrackerInstallation(
322
+ lastOutcome,
323
+ engine = "unavailable",
324
+ handlers = inactiveHandlers()
325
+ ) {
326
+ const snapshot = Object.freeze({
327
+ active: false,
328
+ available: false,
329
+ engine,
330
+ lastOutcome,
331
+ restoration: "deactivate_only"
332
+ });
333
+ return Object.freeze({
334
+ deactivate: () => false,
335
+ health: () => snapshot,
336
+ rejectionHealth: () => handlers.health()
337
+ });
338
+ }
339
+
340
+ function trackerHealthSnapshot(state, engine, available) {
341
+ return Object.freeze({
342
+ active: state.active,
343
+ available,
344
+ engine,
345
+ lastOutcome: state.lastOutcome,
346
+ restoration: "deactivate_only"
347
+ });
348
+ }
349
+
227
350
  function healthSnapshot(state, trackedRejections, maxTrackedRejections) {
228
351
  return Object.freeze({
229
352
  available: true,
@@ -267,5 +390,6 @@ function isObjectLike(value) {
267
390
  }
268
391
 
269
392
  module.exports = {
270
- createLogBrewReactNativePromiseRejectionHandlers
393
+ createLogBrewReactNativePromiseRejectionHandlers,
394
+ installLogBrewReactNativePromiseRejectionTracker
271
395
  };