@flareapp/react-native 2.11.0 → 2.12.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.
package/dist/index.cjs CHANGED
@@ -5,13 +5,6 @@ let _flareapp_react_inject = require("@flareapp/react/inject");
5
5
  let react = require("react");
6
6
 
7
7
  //#region src/context/expo.ts
8
- /**
9
- * Lazy, synchronous Expo load. The `require(...)` calls MUST be direct string literals: Metro statically
10
- * collects only literal `require('pkg')` calls, treating those inside a try/catch as optional deps
11
- * (`allowOptionalDependencies` is on by default), so a missing package degrades to a caught throw not a
12
- * build error. Do NOT alias `require` to a local; that defeats the static collection and the module never
13
- * resolves even when installed. The `typeof require` guard keeps non-Metro/ESM envs (some test runners) safe.
14
- */
15
8
  function loadExpoModules() {
16
9
  const mods = {};
17
10
  if (typeof require === "undefined") return mods;
@@ -23,14 +16,12 @@ function loadExpoModules() {
23
16
  } catch {}
24
17
  return mods;
25
18
  }
26
- /** Expo's `DeviceType` enum (UNKNOWN=0, PHONE=1, TABLET=2, DESKTOP=3, TV=4). */
27
19
  const DEVICE_TYPE_LABELS = {
28
20
  1: "phone",
29
21
  2: "tablet",
30
22
  3: "desktop",
31
23
  4: "tv"
32
24
  };
33
- /** Normalise the synchronous Expo constants into `DeviceInfo`. Only present (non-null) fields are set. */
34
25
  function expoToDeviceInfo(expo) {
35
26
  const info = {};
36
27
  const device = expo.device;
@@ -56,7 +47,6 @@ function expoToDeviceInfo(expo) {
56
47
 
57
48
  //#endregion
58
49
  //#region src/context/deviceInfo.ts
59
- /** Expo constants (resolved once) override the per-call RN-core `Platform`/`Dimensions` values. */
60
50
  var ReactNativeDeviceInfoProvider = class {
61
51
  expoInfo;
62
52
  constructor(expo = loadExpoModules()) {
@@ -87,7 +77,6 @@ var ReactNativeDeviceInfoProvider = class {
87
77
  return info;
88
78
  }
89
79
  };
90
- /** Android device model from `Platform.constants`, maker-prefixed (e.g. `Google Pixel 7`). iOS core exposes none. */
91
80
  function nativeModelName() {
92
81
  if (react_native.Platform.OS !== "android") return;
93
82
  const constants = react_native.Platform.constants;
@@ -105,15 +94,6 @@ function makeReactNativeContextCollector(expo = loadExpoModules()) {
105
94
 
106
95
  //#endregion
107
96
  //#region src/handlers/appStateFlush.ts
108
- /**
109
- * Flush the log buffer when the app backgrounds. Gate on `background` only: iOS fires `inactive` on every
110
- * transient interruption (app-switcher peek, Control Center, incoming call), so gating avoids flooding the
111
- * network. Mirrors the browser scheduler gating on `hidden`, not every blur. Delivery is best-effort (see
112
- * `ReactNativeFlushScheduler`).
113
- *
114
- * Returns an uninstaller that removes the listener via the subscription handle (modern RN API; do NOT use
115
- * the removed `AppState.removeEventListener`).
116
- */
117
97
  function installAppStateFlush(getFlush) {
118
98
  const subscription = react_native.AppState.addEventListener("change", (state) => {
119
99
  if (state === "background") getFlush()?.();
@@ -123,7 +103,6 @@ function installAppStateFlush(getFlush) {
123
103
 
124
104
  //#endregion
125
105
  //#region src/devMode.ts
126
- /** True only in a React Native dev bundle. Safe (false) everywhere else. */
127
106
  function inDevMode() {
128
107
  return typeof __DEV__ !== "undefined" && __DEV__ === true;
129
108
  }
@@ -133,16 +112,6 @@ function inDevMode() {
133
112
  function getErrorUtils() {
134
113
  return globalThis.ErrorUtils;
135
114
  }
136
- /**
137
- * Wraps RN's `ErrorUtils` global handler: observe, do not swallow. The wrapper reports and then delegates
138
- * to the previous handler, so RN's own behaviour (red box in dev, crash in prod) is preserved.
139
- *
140
- * `onFatal` exists because a production fatal tears the app down while our report is still an async fetch
141
- * the OS kills, so a bare report rarely sends. With it, the previous handler is deferred until the
142
- * transport drains. Skipped in `__DEV__` so it does not fight the red box, and it only runs for the
143
- * first fatal, so a second one mid-flush hands straight over instead of starting a second shutdown.
144
- * Mirrors Sentry's RN SDK.
145
- */
146
115
  function installGlobalErrorHandler(report, onFatal) {
147
116
  const errorUtils = getErrorUtils();
148
117
  if (!errorUtils) return () => {};
@@ -173,24 +142,15 @@ function installGlobalErrorHandler(report, onFatal) {
173
142
 
174
143
  //#endregion
175
144
  //#region src/handlers/rejectionTracking.ts
176
- /** An injected `null` means "engine absent" and must win over the live global, so this tests for
177
- * `undefined` rather than falsiness. */
178
145
  function resolveHermes(deps) {
179
146
  if (deps.hermes !== void 0) return deps.hermes;
180
147
  return globalThis.HermesInternal;
181
148
  }
182
- /** Same `undefined`-not-falsy rule as `resolveHermes`. */
183
149
  function resolveRequire(deps) {
184
150
  if (deps.requirePolyfill !== void 0) return deps.requirePolyfill;
185
151
  if (typeof require === "undefined") return null;
186
152
  return require;
187
153
  }
188
- /**
189
- * The rejection enabler for the active JS engine, null when neither is reachable. Order matters: on
190
- * Hermes the `promise` npm polyfill is not the runtime Promise, so its `rejection-tracking.enable()`
191
- * would hook unused objects and never fire. On JSC, RN does polyfill `global.Promise` with that package,
192
- * making it the real hook. Exported with injectable deps so the ordering is unit-testable.
193
- */
194
154
  function resolveRejectionEnabler(deps = {}) {
195
155
  const hermes = resolveHermes(deps);
196
156
  if (hermes && typeof hermes.enablePromiseRejectionTracker === "function") return (options) => hermes.enablePromiseRejectionTracker(options);
@@ -202,16 +162,6 @@ function resolveRejectionEnabler(deps = {}) {
202
162
  } catch {}
203
163
  return null;
204
164
  }
205
- /**
206
- * Best-effort, engine-aware capture of unhandled rejections. RN routes these through the engine's tracker
207
- * rather than `window.onunhandledrejection`. With no engine hook reachable this is a no-op; uncaught
208
- * throws still arrive via ErrorUtils.
209
- *
210
- * Enabling REPLACES the engine's current callbacks, including RN's own dev warning, and neither engine
211
- * exposes a getter for the previous ones, so chaining is impossible. `onUnhandled` re-emits a
212
- * `console.warn` in dev to avoid swallowing that signal. For the same reason the uninstaller re-enables
213
- * with no-op callbacks: neither engine offers a clean disable.
214
- */
215
165
  function installRejectionTracking(reporter, deps = {}) {
216
166
  const enable = deps.enable !== void 0 ? deps.enable : resolveRejectionEnabler();
217
167
  if (!enable) {
@@ -244,11 +194,6 @@ function installRejectionTracking(reporter, deps = {}) {
244
194
 
245
195
  //#endregion
246
196
  //#region src/ReactNativeFlushScheduler.ts
247
- /**
248
- * Passive: the AppState -> background trigger is wired separately in `Flare.install()`, to stay symmetric
249
- * with handler teardown. Flushes without `{ keepalive: true }` because RN's fetch runs over XMLHttpRequest
250
- * and does not reliably honour it, so a backgrounding flush is best-effort.
251
- */
252
197
  var ReactNativeFlushScheduler = class {
253
198
  flushFn = null;
254
199
  register(flush) {
@@ -266,13 +211,11 @@ var ReactNativeFlushScheduler = class {
266
211
  //#endregion
267
212
  //#region src/Flare.ts
268
213
  const RN_SDK_NAME = "@flareapp/react-native";
269
- const RN_SDK_VERSION = "2.11.0";
270
- /** How long a fatal JS crash holds the app open to drain the transport before RN's default handler runs. */
214
+ const RN_SDK_VERSION = "2.12.0";
271
215
  const FATAL_FLUSH_TIMEOUT_MS = 2e3;
272
216
  /**
273
- * The RN `Flare` singleton, exposed as `flare` from the package root. Uses `NullFileReader` because there
274
- * are no runtime snippets on a device (sourcemaps are a Metro follow-up) and `GlobalScopeProvider` because
275
- * RN has a single app scope.
217
+ * The RN `Flare` singleton, exposed as `flare`. Uses `NullFileReader` (no runtime snippets on device) and
218
+ * `GlobalScopeProvider` (RN has a single app scope).
276
219
  */
277
220
  var ReactNativeFlare = class extends _flareapp_core.Flare {
278
221
  scheduler;
@@ -338,10 +281,9 @@ const flare = new ReactNativeFlare();
338
281
  //#endregion
339
282
  //#region src/FlareErrorBoundary.ts
340
283
  /**
341
- * React Native error boundary: a thin wrapper over `@flareapp/react`'s `/inject` boundary that injects the
342
- * RN `flare` singleton. `flare` is applied after `{...props}` so a consumer cannot override it. The
343
- * `as unknown as Flare` cast is needed because the prop is typed against `@flareapp/js/browser`'s `Flare`
344
- * (a superset); safe at runtime since the boundary only calls `reportSilently`, which RN inherits.
284
+ * Wraps `@flareapp/react`'s `/inject` boundary with the RN `flare` singleton, applied after `{...props}`
285
+ * so callers can't override it. The `Flare` cast is safe: the boundary only calls `reportSilently`, which
286
+ * RN implements too.
345
287
  */
346
288
  function FlareErrorBoundary(props) {
347
289
  return (0, react.createElement)(_flareapp_react_inject.FlareErrorBoundary, {
package/dist/index.d.cts CHANGED
@@ -15,9 +15,8 @@ type RejectionDeps = {
15
15
  //#endregion
16
16
  //#region src/Flare.d.ts
17
17
  /**
18
- * The RN `Flare` singleton, exposed as `flare` from the package root. Uses `NullFileReader` because there
19
- * are no runtime snippets on a device (sourcemaps are a Metro follow-up) and `GlobalScopeProvider` because
20
- * RN has a single app scope.
18
+ * The RN `Flare` singleton, exposed as `flare`. Uses `NullFileReader` (no runtime snippets on device) and
19
+ * `GlobalScopeProvider` (RN has a single app scope).
21
20
  */
22
21
  declare class ReactNativeFlare extends Flare$1 {
23
22
  private readonly scheduler;
@@ -46,10 +45,9 @@ declare const flare: ReactNativeFlare;
46
45
  //#endregion
47
46
  //#region src/FlareErrorBoundary.d.ts
48
47
  /**
49
- * React Native error boundary: a thin wrapper over `@flareapp/react`'s `/inject` boundary that injects the
50
- * RN `flare` singleton. `flare` is applied after `{...props}` so a consumer cannot override it. The
51
- * `as unknown as Flare` cast is needed because the prop is typed against `@flareapp/js/browser`'s `Flare`
52
- * (a superset); safe at runtime since the boundary only calls `reportSilently`, which RN inherits.
48
+ * Wraps `@flareapp/react`'s `/inject` boundary with the RN `flare` singleton, applied after `{...props}`
49
+ * so callers can't override it. The `Flare` cast is safe: the boundary only calls `reportSilently`, which
50
+ * RN implements too.
53
51
  */
54
52
  declare function FlareErrorBoundary(props: Omit<FlareErrorBoundaryProps, 'flare'>): ReactElement;
55
53
  //#endregion
package/dist/index.d.mts CHANGED
@@ -15,9 +15,8 @@ type RejectionDeps = {
15
15
  //#endregion
16
16
  //#region src/Flare.d.ts
17
17
  /**
18
- * The RN `Flare` singleton, exposed as `flare` from the package root. Uses `NullFileReader` because there
19
- * are no runtime snippets on a device (sourcemaps are a Metro follow-up) and `GlobalScopeProvider` because
20
- * RN has a single app scope.
18
+ * The RN `Flare` singleton, exposed as `flare`. Uses `NullFileReader` (no runtime snippets on device) and
19
+ * `GlobalScopeProvider` (RN has a single app scope).
21
20
  */
22
21
  declare class ReactNativeFlare extends Flare$1 {
23
22
  private readonly scheduler;
@@ -46,10 +45,9 @@ declare const flare: ReactNativeFlare;
46
45
  //#endregion
47
46
  //#region src/FlareErrorBoundary.d.ts
48
47
  /**
49
- * React Native error boundary: a thin wrapper over `@flareapp/react`'s `/inject` boundary that injects the
50
- * RN `flare` singleton. `flare` is applied after `{...props}` so a consumer cannot override it. The
51
- * `as unknown as Flare` cast is needed because the prop is typed against `@flareapp/js/browser`'s `Flare`
52
- * (a superset); safe at runtime since the boundary only calls `reportSilently`, which RN inherits.
48
+ * Wraps `@flareapp/react`'s `/inject` boundary with the RN `flare` singleton, applied after `{...props}`
49
+ * so callers can't override it. The `Flare` cast is safe: the boundary only calls `reportSilently`, which
50
+ * RN implements too.
53
51
  */
54
52
  declare function FlareErrorBoundary(props: Omit<FlareErrorBoundaryProps, 'flare'>): ReactElement;
55
53
  //#endregion
package/dist/index.mjs CHANGED
@@ -9,13 +9,6 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
9
9
 
10
10
  //#endregion
11
11
  //#region src/context/expo.ts
12
- /**
13
- * Lazy, synchronous Expo load. The `require(...)` calls MUST be direct string literals: Metro statically
14
- * collects only literal `require('pkg')` calls, treating those inside a try/catch as optional deps
15
- * (`allowOptionalDependencies` is on by default), so a missing package degrades to a caught throw not a
16
- * build error. Do NOT alias `require` to a local; that defeats the static collection and the module never
17
- * resolves even when installed. The `typeof require` guard keeps non-Metro/ESM envs (some test runners) safe.
18
- */
19
12
  function loadExpoModules() {
20
13
  const mods = {};
21
14
  if (typeof __require === "undefined") return mods;
@@ -27,14 +20,12 @@ function loadExpoModules() {
27
20
  } catch {}
28
21
  return mods;
29
22
  }
30
- /** Expo's `DeviceType` enum (UNKNOWN=0, PHONE=1, TABLET=2, DESKTOP=3, TV=4). */
31
23
  const DEVICE_TYPE_LABELS = {
32
24
  1: "phone",
33
25
  2: "tablet",
34
26
  3: "desktop",
35
27
  4: "tv"
36
28
  };
37
- /** Normalise the synchronous Expo constants into `DeviceInfo`. Only present (non-null) fields are set. */
38
29
  function expoToDeviceInfo(expo) {
39
30
  const info = {};
40
31
  const device = expo.device;
@@ -60,7 +51,6 @@ function expoToDeviceInfo(expo) {
60
51
 
61
52
  //#endregion
62
53
  //#region src/context/deviceInfo.ts
63
- /** Expo constants (resolved once) override the per-call RN-core `Platform`/`Dimensions` values. */
64
54
  var ReactNativeDeviceInfoProvider = class {
65
55
  expoInfo;
66
56
  constructor(expo = loadExpoModules()) {
@@ -91,7 +81,6 @@ var ReactNativeDeviceInfoProvider = class {
91
81
  return info;
92
82
  }
93
83
  };
94
- /** Android device model from `Platform.constants`, maker-prefixed (e.g. `Google Pixel 7`). iOS core exposes none. */
95
84
  function nativeModelName() {
96
85
  if (Platform.OS !== "android") return;
97
86
  const constants = Platform.constants;
@@ -109,15 +98,6 @@ function makeReactNativeContextCollector(expo = loadExpoModules()) {
109
98
 
110
99
  //#endregion
111
100
  //#region src/handlers/appStateFlush.ts
112
- /**
113
- * Flush the log buffer when the app backgrounds. Gate on `background` only: iOS fires `inactive` on every
114
- * transient interruption (app-switcher peek, Control Center, incoming call), so gating avoids flooding the
115
- * network. Mirrors the browser scheduler gating on `hidden`, not every blur. Delivery is best-effort (see
116
- * `ReactNativeFlushScheduler`).
117
- *
118
- * Returns an uninstaller that removes the listener via the subscription handle (modern RN API; do NOT use
119
- * the removed `AppState.removeEventListener`).
120
- */
121
101
  function installAppStateFlush(getFlush) {
122
102
  const subscription = AppState.addEventListener("change", (state) => {
123
103
  if (state === "background") getFlush()?.();
@@ -127,7 +107,6 @@ function installAppStateFlush(getFlush) {
127
107
 
128
108
  //#endregion
129
109
  //#region src/devMode.ts
130
- /** True only in a React Native dev bundle. Safe (false) everywhere else. */
131
110
  function inDevMode() {
132
111
  return typeof __DEV__ !== "undefined" && __DEV__ === true;
133
112
  }
@@ -137,16 +116,6 @@ function inDevMode() {
137
116
  function getErrorUtils() {
138
117
  return globalThis.ErrorUtils;
139
118
  }
140
- /**
141
- * Wraps RN's `ErrorUtils` global handler: observe, do not swallow. The wrapper reports and then delegates
142
- * to the previous handler, so RN's own behaviour (red box in dev, crash in prod) is preserved.
143
- *
144
- * `onFatal` exists because a production fatal tears the app down while our report is still an async fetch
145
- * the OS kills, so a bare report rarely sends. With it, the previous handler is deferred until the
146
- * transport drains. Skipped in `__DEV__` so it does not fight the red box, and it only runs for the
147
- * first fatal, so a second one mid-flush hands straight over instead of starting a second shutdown.
148
- * Mirrors Sentry's RN SDK.
149
- */
150
119
  function installGlobalErrorHandler(report, onFatal) {
151
120
  const errorUtils = getErrorUtils();
152
121
  if (!errorUtils) return () => {};
@@ -177,24 +146,15 @@ function installGlobalErrorHandler(report, onFatal) {
177
146
 
178
147
  //#endregion
179
148
  //#region src/handlers/rejectionTracking.ts
180
- /** An injected `null` means "engine absent" and must win over the live global, so this tests for
181
- * `undefined` rather than falsiness. */
182
149
  function resolveHermes(deps) {
183
150
  if (deps.hermes !== void 0) return deps.hermes;
184
151
  return globalThis.HermesInternal;
185
152
  }
186
- /** Same `undefined`-not-falsy rule as `resolveHermes`. */
187
153
  function resolveRequire(deps) {
188
154
  if (deps.requirePolyfill !== void 0) return deps.requirePolyfill;
189
155
  if (typeof __require === "undefined") return null;
190
156
  return __require;
191
157
  }
192
- /**
193
- * The rejection enabler for the active JS engine, null when neither is reachable. Order matters: on
194
- * Hermes the `promise` npm polyfill is not the runtime Promise, so its `rejection-tracking.enable()`
195
- * would hook unused objects and never fire. On JSC, RN does polyfill `global.Promise` with that package,
196
- * making it the real hook. Exported with injectable deps so the ordering is unit-testable.
197
- */
198
158
  function resolveRejectionEnabler(deps = {}) {
199
159
  const hermes = resolveHermes(deps);
200
160
  if (hermes && typeof hermes.enablePromiseRejectionTracker === "function") return (options) => hermes.enablePromiseRejectionTracker(options);
@@ -206,16 +166,6 @@ function resolveRejectionEnabler(deps = {}) {
206
166
  } catch {}
207
167
  return null;
208
168
  }
209
- /**
210
- * Best-effort, engine-aware capture of unhandled rejections. RN routes these through the engine's tracker
211
- * rather than `window.onunhandledrejection`. With no engine hook reachable this is a no-op; uncaught
212
- * throws still arrive via ErrorUtils.
213
- *
214
- * Enabling REPLACES the engine's current callbacks, including RN's own dev warning, and neither engine
215
- * exposes a getter for the previous ones, so chaining is impossible. `onUnhandled` re-emits a
216
- * `console.warn` in dev to avoid swallowing that signal. For the same reason the uninstaller re-enables
217
- * with no-op callbacks: neither engine offers a clean disable.
218
- */
219
169
  function installRejectionTracking(reporter, deps = {}) {
220
170
  const enable = deps.enable !== void 0 ? deps.enable : resolveRejectionEnabler();
221
171
  if (!enable) {
@@ -248,11 +198,6 @@ function installRejectionTracking(reporter, deps = {}) {
248
198
 
249
199
  //#endregion
250
200
  //#region src/ReactNativeFlushScheduler.ts
251
- /**
252
- * Passive: the AppState -> background trigger is wired separately in `Flare.install()`, to stay symmetric
253
- * with handler teardown. Flushes without `{ keepalive: true }` because RN's fetch runs over XMLHttpRequest
254
- * and does not reliably honour it, so a backgrounding flush is best-effort.
255
- */
256
201
  var ReactNativeFlushScheduler = class {
257
202
  flushFn = null;
258
203
  register(flush) {
@@ -270,13 +215,11 @@ var ReactNativeFlushScheduler = class {
270
215
  //#endregion
271
216
  //#region src/Flare.ts
272
217
  const RN_SDK_NAME = "@flareapp/react-native";
273
- const RN_SDK_VERSION = "2.11.0";
274
- /** How long a fatal JS crash holds the app open to drain the transport before RN's default handler runs. */
218
+ const RN_SDK_VERSION = "2.12.0";
275
219
  const FATAL_FLUSH_TIMEOUT_MS = 2e3;
276
220
  /**
277
- * The RN `Flare` singleton, exposed as `flare` from the package root. Uses `NullFileReader` because there
278
- * are no runtime snippets on a device (sourcemaps are a Metro follow-up) and `GlobalScopeProvider` because
279
- * RN has a single app scope.
221
+ * The RN `Flare` singleton, exposed as `flare`. Uses `NullFileReader` (no runtime snippets on device) and
222
+ * `GlobalScopeProvider` (RN has a single app scope).
280
223
  */
281
224
  var ReactNativeFlare = class extends Flare$1 {
282
225
  scheduler;
@@ -342,10 +285,9 @@ const flare = new ReactNativeFlare();
342
285
  //#endregion
343
286
  //#region src/FlareErrorBoundary.ts
344
287
  /**
345
- * React Native error boundary: a thin wrapper over `@flareapp/react`'s `/inject` boundary that injects the
346
- * RN `flare` singleton. `flare` is applied after `{...props}` so a consumer cannot override it. The
347
- * `as unknown as Flare` cast is needed because the prop is typed against `@flareapp/js/browser`'s `Flare`
348
- * (a superset); safe at runtime since the boundary only calls `reportSilently`, which RN inherits.
288
+ * Wraps `@flareapp/react`'s `/inject` boundary with the RN `flare` singleton, applied after `{...props}`
289
+ * so callers can't override it. The `Flare` cast is safe: the boundary only calls `reportSilently`, which
290
+ * RN implements too.
349
291
  */
350
292
  function FlareErrorBoundary(props) {
351
293
  return createElement(FlareErrorBoundary$1, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flareapp/react-native",
3
- "version": "2.11.0",
3
+ "version": "2.12.0",
4
4
  "description": "React Native SDK for flareapp.io",
5
5
  "homepage": "https://flareapp.io",
6
6
  "bugs": {
@@ -49,7 +49,7 @@
49
49
  "release": "release-it"
50
50
  },
51
51
  "dependencies": {
52
- "@flareapp/core": "2.11.0"
52
+ "@flareapp/core": "2.12.0"
53
53
  },
54
54
  "peerDependencies": {
55
55
  "@flareapp/react": "^2.5.0",