@fixback/expo 0.2.0 → 0.3.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 (58) hide show
  1. package/README.md +72 -8
  2. package/dist/FeedbackModal.d.ts +10 -2
  3. package/dist/FeedbackModal.js +84 -36
  4. package/dist/FeedbackModal.js.map +1 -0
  5. package/dist/FixbackProvider.d.ts +12 -0
  6. package/dist/FixbackProvider.js +46 -23
  7. package/dist/FixbackProvider.js.map +1 -0
  8. package/dist/adapters.js +73 -23
  9. package/dist/adapters.js.map +1 -0
  10. package/dist/breadcrumbs.d.ts +21 -222
  11. package/dist/breadcrumbs.js +45 -605
  12. package/dist/breadcrumbs.js.map +1 -0
  13. package/dist/client.d.ts +65 -67
  14. package/dist/client.js +288 -151
  15. package/dist/client.js.map +1 -0
  16. package/dist/connect.d.ts +60 -0
  17. package/dist/connect.js +63 -0
  18. package/dist/connect.js.map +1 -0
  19. package/dist/error-capture.d.ts +28 -78
  20. package/dist/error-capture.js +76 -294
  21. package/dist/error-capture.js.map +1 -0
  22. package/dist/http.d.ts +10 -25
  23. package/dist/http.js +15 -12
  24. package/dist/http.js.map +1 -0
  25. package/dist/identity.d.ts +11 -11
  26. package/dist/identity.js +23 -28
  27. package/dist/identity.js.map +1 -0
  28. package/dist/index.d.ts +6 -5
  29. package/dist/index.js +22 -5
  30. package/dist/index.js.map +1 -0
  31. package/dist/origin.d.ts +21 -0
  32. package/dist/origin.js +45 -0
  33. package/dist/origin.js.map +1 -0
  34. package/dist/package.json +3 -0
  35. package/dist/report.d.ts +28 -63
  36. package/dist/report.js +33 -25
  37. package/dist/report.js.map +1 -0
  38. package/dist/reporter-session-store.d.ts +27 -0
  39. package/dist/reporter-session-store.js +53 -0
  40. package/dist/reporter-session-store.js.map +1 -0
  41. package/dist/shake.d.ts +26 -0
  42. package/dist/shake.js +32 -7
  43. package/dist/shake.js.map +1 -0
  44. package/dist/submit.d.ts +21 -12
  45. package/dist/submit.js +24 -41
  46. package/dist/submit.js.map +1 -0
  47. package/dist/tokens.js +5 -1
  48. package/dist/tokens.js.map +1 -0
  49. package/dist/version.d.ts +1 -1
  50. package/dist/version.js +5 -1
  51. package/dist/version.js.map +1 -0
  52. package/package.json +14 -7
  53. package/dist/auto-report-backoff.d.ts +0 -42
  54. package/dist/auto-report-backoff.js +0 -67
  55. package/dist/boot.d.ts +0 -65
  56. package/dist/boot.js +0 -60
  57. package/dist/scrub.d.ts +0 -55
  58. package/dist/scrub.js +0 -184
package/dist/adapters.js CHANGED
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  /**
2
3
  * The real React Native / Expo adapters behind the client's injectable seams
3
4
  * (`FixbackAdapters`), plus the accelerometer wiring for the shake gesture.
@@ -7,20 +8,62 @@
7
8
  * defensive: a missing native module or a capture failure degrades that one
8
9
  * capability instead of throwing into the host app.
9
10
  */
10
- import AsyncStorage from "@react-native-async-storage/async-storage";
11
- import { Accelerometer } from "expo-sensors";
12
- import { AppState, Dimensions, Platform } from "react-native";
13
- import { captureScreen, releaseCapture } from "react-native-view-shot";
14
- import { globalConsole, globalXhr } from "./breadcrumbs";
15
- import { globalErrorUtils } from "./error-capture";
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ var __importDefault = (this && this.__importDefault) || function (mod) {
45
+ return (mod && mod.__esModule) ? mod : { "default": mod };
46
+ };
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.SHAKE_UPDATE_INTERVAL_MS = void 0;
49
+ exports.createNativeAdapters = createNativeAdapters;
50
+ exports.startShakeListener = startShakeListener;
51
+ const async_storage_1 = __importDefault(require("@react-native-async-storage/async-storage"));
52
+ const expo_sensors_1 = require("expo-sensors");
53
+ const SecureStore = __importStar(require("expo-secure-store"));
54
+ const expo_web_browser_1 = require("expo-web-browser");
55
+ const react_native_1 = require("react-native");
56
+ const react_native_view_shot_1 = require("react-native-view-shot");
57
+ const breadcrumbs_1 = require("./breadcrumbs");
58
+ const error_capture_1 = require("./error-capture");
16
59
  /** Read the device environment: window size + `<os> <version>`. */
17
60
  function readEnvironment() {
18
61
  try {
19
- const { width, height } = Dimensions.get("window");
62
+ const { width, height } = react_native_1.Dimensions.get("window");
20
63
  return {
21
64
  windowWidth: width,
22
65
  windowHeight: height,
23
- os: `${Platform.OS} ${String(Platform.Version)}`,
66
+ os: `${react_native_1.Platform.OS} ${String(react_native_1.Platform.Version)}`,
24
67
  };
25
68
  }
26
69
  catch {
@@ -34,7 +77,7 @@ function readEnvironment() {
34
77
  */
35
78
  async function captureScreenshot() {
36
79
  try {
37
- const uri = await captureScreen({
80
+ const uri = await (0, react_native_view_shot_1.captureScreen)({
38
81
  format: "png",
39
82
  quality: 0.9,
40
83
  result: "tmpfile",
@@ -54,7 +97,7 @@ async function captureScreenshot() {
54
97
  */
55
98
  function releaseScreenshot(uri) {
56
99
  try {
57
- releaseCapture(uri);
100
+ (0, react_native_view_shot_1.releaseCapture)(uri);
58
101
  }
59
102
  catch {
60
103
  /* release is best-effort */
@@ -73,45 +116,51 @@ function devWarn(message) {
73
116
  }
74
117
  }
75
118
  /** Build the real adapter set `FixbackProvider` hands to the client. */
76
- export function createNativeAdapters() {
119
+ function createNativeAdapters() {
77
120
  return {
78
- storage: AsyncStorage,
121
+ storage: async_storage_1.default,
122
+ // The Reporter session token is a credential — persisted in the Keychain / Keystore
123
+ // via SecureStore, not AsyncStorage (ADR-0032).
124
+ secureStore: SecureStore,
125
+ // Connect opens the platform's connect page in an in-app auth session and returns
126
+ // via the app's declared `returnUrl` (ADR-0032).
127
+ openAuthSession: (url, returnUrl) => (0, expo_web_browser_1.openAuthSessionAsync)(url, returnUrl),
79
128
  environment: readEnvironment,
80
129
  captureScreenshot,
81
130
  releaseScreenshot,
82
- consoleObj: globalConsole() ?? null,
83
- xhr: globalXhr() ?? null,
84
- errorUtils: globalErrorUtils() ?? null,
85
- appState: AppState,
131
+ consoleObj: (0, breadcrumbs_1.globalConsole)() ?? null,
132
+ xhr: (0, breadcrumbs_1.globalXhr)() ?? null,
133
+ errorUtils: (0, error_capture_1.globalErrorUtils)() ?? null,
134
+ appState: react_native_1.AppState,
86
135
  warn: devWarn,
87
136
  };
88
137
  }
89
138
  /** How often the accelerometer reports while the gesture is armed. */
90
- export const SHAKE_UPDATE_INTERVAL_MS = 80;
139
+ exports.SHAKE_UPDATE_INTERVAL_MS = 80;
91
140
  /**
92
141
  * Feed accelerometer samples to a listener (the shake detector). Availability
93
142
  * is checked first (a simulator has no accelerometer); an unavailable or
94
143
  * missing sensor resolves to an inert subscription. `remove` also cancels a
95
144
  * subscription still waiting on the availability check.
96
145
  */
97
- export function startShakeListener(onSample, updateIntervalMs = SHAKE_UPDATE_INTERVAL_MS) {
146
+ function startShakeListener(onSample, updateIntervalMs = exports.SHAKE_UPDATE_INTERVAL_MS) {
98
147
  let removed = false;
99
148
  let subscription = null;
100
149
  void (async () => {
101
150
  try {
102
- const available = await Accelerometer.isAvailableAsync();
151
+ const available = await expo_sensors_1.Accelerometer.isAvailableAsync();
103
152
  if (!available || removed)
104
153
  return;
105
154
  // The update interval is global to the sensor, shared with the host
106
155
  // app's own listeners — only claim it when nobody else is listening, so
107
156
  // arming the gesture never degrades a host feature's sample rate.
108
- const listenerCount = typeof Accelerometer.getListenerCount === "function"
109
- ? Accelerometer.getListenerCount()
157
+ const listenerCount = typeof expo_sensors_1.Accelerometer.getListenerCount === "function"
158
+ ? expo_sensors_1.Accelerometer.getListenerCount()
110
159
  : 0;
111
160
  if (listenerCount === 0) {
112
- Accelerometer.setUpdateInterval(updateIntervalMs);
161
+ expo_sensors_1.Accelerometer.setUpdateInterval(updateIntervalMs);
113
162
  }
114
- subscription = Accelerometer.addListener(({ x, y, z }) => {
163
+ subscription = expo_sensors_1.Accelerometer.addListener(({ x, y, z }) => {
115
164
  try {
116
165
  onSample({ x, y, z, at: Date.now() });
117
166
  }
@@ -141,3 +190,4 @@ export function startShakeListener(onSample, updateIntervalMs = SHAKE_UPDATE_INT
141
190
  },
142
191
  };
143
192
  }
193
+ //# sourceMappingURL=adapters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapters.js","sourceRoot":"","sources":["../src/adapters.ts"],"names":[],"mappings":"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"}
@@ -1,229 +1,29 @@
1
1
  /**
2
- * The trace **breadcrumb ring buffer** and its React Native capture
3
- * instrumentation — a port of `packages/sdk/src/breadcrumbs.ts` kept
4
- * file-parallel on purpose (ADR-0021): the entry shapes, stream budgets, caps,
5
- * and eviction rules are the web SDK's exactly, so the server and dashboard
6
- * cannot tell a mobile trace from a web one.
2
+ * The Expo SDK's **React Native capture instrumentation** the runtime seams, and
3
+ * nothing else.
7
4
  *
8
- * Mobile mappings (spec 0004 §D): `console` wrapping is unchanged; network
9
- * capture patches `XMLHttpRequest` only React Native's `fetch` is a polyfill
10
- * over XHR, so wrapping both would double-record; navigation crumbs come from
11
- * the host app's `trackScreen` calls (there is no `history` to patch); the
12
- * masked `ui.*` streams have no mobile source yet and simply never occur.
5
+ * The trace buffer, the crumb builders, the caps and eviction rules, and the
6
+ * `console` wrapper are all shared with the browser SDK through
7
+ * `@fixback/sdk-core` (ADR-0028, replacing the file-parallel port ADR-0021
8
+ * described), so the server and dashboard cannot tell a mobile trace from a web one.
9
+ * What is left here is genuinely mobile: how to find React Native's globals, and
10
+ * the `XMLHttpRequest` patch.
13
11
  *
14
- * Everything private is kept out **at the source**: network crumbs carry method
15
- * + URL + status metadata only, **never** bodies; URLs are scrubbed as the
16
- * crumb is built. The `beforeSend` choke point (`scrub.ts`) is the final gate.
17
- * The SDK must never throw into the host app, so every instrumentation hook is
18
- * wrapped: a capture failure is swallowed and the original behaviour always runs.
19
- */
20
- /** Console-style severity a `console` crumb records. */
21
- export type BreadcrumbLevel = "log" | "info" | "warn" | "error" | "assert" | "debug";
22
- /**
23
- * The kind of activity a crumb records. The full web vocabulary is kept for
24
- * wire parity — on mobile only `console`, `navigation`, `xhr`, and `error`
25
- * are ever produced today.
26
- */
27
- export type BreadcrumbCategory = "console" | "navigation" | "fetch" | "xhr" | "beacon" | "ui.click" | "ui.input" | "error";
28
- /** Which API issued a captured network request. */
29
- export type NetworkApi = "fetch" | "xhr" | "beacon";
30
- /** A network request's failure classification. */
31
- export type NetworkOutcome = "ok" | "http-4xx" | "http-5xx" | "network-error" | "timeout" | "aborted" | "opaque-cors";
32
- /**
33
- * A crumb's structured detail. Deliberately narrow: there is **no** field for a
34
- * request/response body or an input value, so those can never be recorded.
35
- */
36
- export interface BreadcrumbData {
37
- readonly url?: string;
38
- readonly method?: string;
39
- readonly status?: number;
40
- /** A masked target for a `ui.*` crumb — unused on mobile, kept for parity. */
41
- readonly target?: string;
42
- readonly from?: string;
43
- readonly to?: string;
44
- readonly errorType?: string;
45
- }
46
- /** The type tag on a structured console argument. */
47
- export type ConsoleArgType = "string" | "number" | "bool" | "null" | "json" | "error";
48
- /** One structured console argument: a type tag plus a JSON-safe value. */
49
- export interface ConsoleArg {
50
- readonly t: ConsoleArgType;
51
- readonly v: unknown;
52
- }
53
- /** A `file:line` source location — where a console call was made. */
54
- export interface SourceLocation {
55
- readonly file: string;
56
- readonly line: number;
57
- }
58
- /**
59
- * One entry in a trace stream. Alongside its semantic fields every entry
60
- * carries a stable {@link id} and a high-res monotonic {@link mono} timestamp —
61
- * both stamped by the buffer on `add` — so entries from the three independent
62
- * streams order and cross-link exactly. `timestamp` stays epoch ms.
63
- */
64
- export interface Breadcrumb {
65
- readonly category: BreadcrumbCategory;
66
- readonly message?: string;
67
- readonly level?: BreadcrumbLevel;
68
- /** Epoch milliseconds when the crumb was recorded. */
69
- readonly timestamp: number;
70
- /** A stable id, unique within the buffer — assigned on `add` when not set. */
71
- readonly id?: string;
72
- /** A high-res monotonic timestamp — assigned on `add`. */
73
- readonly mono?: number;
74
- readonly data?: BreadcrumbData;
75
- /** For a `console` crumb: the call's structured, type-tagged arguments. */
76
- readonly args?: readonly ConsoleArg[];
77
- /** For a `console` crumb: the best-effort `file:line` the call was made from. */
78
- readonly source?: SourceLocation;
79
- /** For an auto-captured `error` crumb: ids of the entries preceding the throw. */
80
- readonly causedBy?: readonly string[];
81
- /** Network crumb metadata, lifted to the top level — never a body or header. */
82
- readonly api?: NetworkApi;
83
- readonly method?: string;
84
- readonly url?: string;
85
- readonly status?: number;
86
- readonly statusText?: string;
87
- readonly durationMs?: number;
88
- readonly reqSize?: number;
89
- readonly respSize?: number;
90
- readonly contentType?: string;
91
- readonly outcome?: NetworkOutcome;
92
- }
93
- /**
94
- * The three independent trace streams. Each is its own FIFO ring with its own
95
- * size budget, so a chatty stream can't evict another's lead-up.
96
- */
97
- export type TraceStream = "network" | "console" | "breadcrumbs";
98
- /** Per-stream ring budgets — the web SDK's numbers, unchanged. */
99
- export declare const DEFAULT_STREAM_BUDGETS: Readonly<Record<TraceStream, number>>;
100
- /** The shared age cap: entries older than this are pruned from every stream. */
101
- export declare const DEFAULT_MAX_AGE_MS: number;
102
- /** Console levels captured by default: **all** of them. */
103
- export declare const DEFAULT_CONSOLE_LEVELS: readonly BreadcrumbLevel[];
104
- /**
105
- * The console levels **pinned** against eviction: when the console stream
106
- * overflows, `warn`/`error`/`assert` are retained ahead of `log`/`info`/`debug`.
107
- */
108
- export declare const PINNED_CONSOLE_LEVELS: readonly BreadcrumbLevel[];
109
- /**
110
- * The console levels for which `source` (`file:line`) is captured — reading a
111
- * call site constructs a `new Error()` on every call, so only the levels that
112
- * matter for debugging pay that cost. Mirrors {@link PINNED_CONSOLE_LEVELS}.
113
- */
114
- export declare const SOURCE_CAPTURE_LEVELS: readonly BreadcrumbLevel[];
115
- /** Which stream a crumb's category belongs to. */
116
- export declare function streamOf(category: string): TraceStream;
117
- /** Filters or edits each crumb before it enters the buffer; `null` drops it. */
118
- export type BeforeBreadcrumb = (crumb: Breadcrumb) => Breadcrumb | null;
119
- /** Configuration for {@link createBreadcrumbBuffer}. All values are optional. */
120
- export interface BreadcrumbBufferConfig {
121
- /** Per-stream size budgets; any stream omitted falls back to the defaults. */
122
- readonly budgets?: Partial<Record<TraceStream, number>>;
123
- /** Shared age cap in ms; `0` (or non-positive) disables age pruning. */
124
- readonly maxAgeMs?: number;
125
- /** A per-crumb filter (mute a category, edit, or drop by returning `null`). */
126
- readonly beforeBreadcrumb?: BeforeBreadcrumb | null;
127
- /** Epoch clock source, injectable for tests. Defaults to `Date.now`. */
128
- readonly now?: () => number;
129
- /** High-res monotonic clock, injectable for tests. */
130
- readonly mono?: () => number;
131
- /** Stable id generator, injectable for tests. */
132
- readonly nextId?: () => string;
133
- }
134
- /** A live trace buffer. */
135
- export interface BreadcrumbBuffer {
136
- /** Record a crumb (subject to filtering, stamping, size, and age trimming). */
137
- add(crumb: Breadcrumb): void;
138
- /** The current crumbs, merged across streams and ordered in time. */
139
- snapshot(): Breadcrumb[];
140
- /** Drop every crumb. */
141
- clear(): void;
142
- }
143
- /**
144
- * Create the per-stream trace buffer: **three independent FIFO rings** —
145
- * `network`, `console`, `breadcrumbs` — each trimmed to its own budget so a
146
- * chatty stream never evicts another's lead-up, plus a shared age cap.
147
- * `snapshot` merges the three streams into one `mono`-ordered array for
148
- * transport — the wire keeps its single `trace` field.
149
- */
150
- export declare function createBreadcrumbBuffer(config?: BreadcrumbBufferConfig): BreadcrumbBuffer;
151
- /** Longest scrubbed URL kept on a crumb. */
152
- export declare const MAX_URL_LENGTH = 2048;
153
- /** Structured console argument caps, all applied at assembly. */
154
- export declare const MAX_ARG_DEPTH = 4;
155
- export declare const MAX_ARG_ITEMS = 100;
156
- export declare const MAX_ARG_STRING_LENGTH = 1024;
157
- export declare const MAX_CONSOLE_ARGS_BYTES = 4096;
158
- /** Classify one console argument into a type-tagged {@link ConsoleArg}. */
159
- export declare function toConsoleArg(value: unknown): ConsoleArg;
160
- /**
161
- * A `console` crumb from a captured call's level and arguments. The `message`
162
- * is the one-line preview; `args` preserves each argument as a structured,
163
- * type-tagged, size-capped value; `source` is the best-effort `file:line`.
164
- */
165
- export declare function consoleCrumb(level: BreadcrumbLevel, args: readonly unknown[], timestamp: number, source?: SourceLocation): Breadcrumb;
166
- /**
167
- * A `navigation` crumb; both sides are scrubbed and length-capped as the crumb
168
- * is built. On mobile this is fed by `trackScreen` (spec 0004 §D) — the values
169
- * are screen URLs derived from the configured origin.
170
- */
171
- export declare function navigationCrumb(from: string, to: string, timestamp: number): Breadcrumb;
172
- /** Classify an HTTP status into a {@link NetworkOutcome}. */
173
- export declare function outcomeFromStatus(status: number | undefined): NetworkOutcome;
174
- /**
175
- * The trivially-known byte size of a request body — a string's UTF-8 length, a
176
- * `Blob`'s `.size`, or an `ArrayBuffer`/typed-array `.byteLength`. Anything
177
- * that would require **reading** the body returns `undefined`.
178
- */
179
- export declare function trivialBodySize(body: unknown): number | undefined;
180
- /** Parse a `content-length` header into a non-negative byte count, or `undefined`. */
181
- export declare function parseContentLength(value: string | null | undefined): number | undefined;
182
- /** The media type from a `content-type` header (before any `;` parameters). */
183
- export declare function contentTypeOf(value: string | null | undefined): string | undefined;
184
- /** The rich metadata a network crumb records — never a body or header. */
185
- export interface NetworkCrumbInput {
186
- readonly api: NetworkApi;
187
- readonly method: string;
188
- /** The raw request URL — scrubbed as the crumb is built. */
189
- readonly url: string;
190
- readonly status?: number;
191
- readonly statusText?: string;
192
- readonly durationMs?: number;
193
- readonly reqSize?: number;
194
- readonly respSize?: number;
195
- readonly contentType?: string;
196
- readonly outcome: NetworkOutcome;
197
- }
198
- /**
199
- * A network crumb with the rich, metadata-only fields the Network tab renders.
200
- * The URL is scrubbed and length-capped at assembly. The shape has **no field
201
- * for a request/response body or an arbitrary header**.
202
- */
203
- export declare function networkCrumb(input: NetworkCrumbInput, timestamp: number): Breadcrumb;
204
- /** A thin `xhr` crumb from method + URL + status (outcome derived from the status). */
205
- export declare function xhrCrumb(method: string, url: string, status: number | undefined, timestamp: number): Breadcrumb;
206
- /**
207
- * An `error` crumb for the failing exception that ends the trace. When
208
- * `causedBy` is given (an auto-captured error), it rides on the crumb as the
209
- * causal pointer to the ids of the entries immediately preceding the throw.
12
+ * Mobile mappings (spec 0004 §D): network capture patches `XMLHttpRequest` **only**
13
+ * React Native's `fetch` is a polyfill over XHR, so wrapping both would
14
+ * double-record; navigation crumbs come from the host app's `trackScreen` calls
15
+ * (there is no `history` to patch); the masked `ui.*` streams have no mobile source
16
+ * yet and simply never occur.
17
+ *
18
+ * Everything private is kept out at the source: network crumbs carry method + URL +
19
+ * status metadata only, **never** bodies, and URLs are scrubbed as the crumb is
20
+ * built. The SDK must never throw into the host app, so every hook is wrapped: a
21
+ * capture failure is swallowed and the original behaviour always runs.
210
22
  */
211
- export declare function errorCrumb(error: unknown, timestamp: number, causedBy?: readonly string[]): Breadcrumb;
212
- /** Detaches an installed instrumentation, restoring the original behaviour. */
213
- export type Teardown = () => void;
214
- type AnyFn = (...args: unknown[]) => unknown;
215
- /** The `console` surface the wrapper patches — injectable for tests. */
216
- export type ConsoleLike = Partial<Record<BreadcrumbLevel, AnyFn>>;
23
+ import { type BreadcrumbBuffer, type BreadcrumbLevel, type ConsoleLike, type Teardown } from "@fixback/sdk-core";
24
+ export type { ConsoleLike, Teardown };
217
25
  /** React Native's global `console`, when present. */
218
26
  export declare function globalConsole(): ConsoleLike | undefined;
219
- /**
220
- * The best-effort `file:line` a console call was made from. Parses the frames
221
- * of a stack, skipping `skipFrames` leading (SDK-internal) frames so the
222
- * source points at the host code that called `console.*`.
223
- */
224
- export declare function sourceFromStack(stack: string | undefined, skipFrames?: number): SourceLocation | undefined;
225
- /** Wrap `console` methods so calls at the captured levels become crumbs. */
226
- export declare function instrumentConsole(buffer: BreadcrumbBuffer, consoleObj: ConsoleLike, levels: readonly BreadcrumbLevel[], now: () => number): Teardown;
227
27
  /** The XHR instance surface the network instrumentation touches. */
228
28
  export interface XhrInstance {
229
29
  status: number;
@@ -267,10 +67,9 @@ export interface InstrumentOptions {
267
67
  readonly captureNetwork?: boolean;
268
68
  }
269
69
  /**
270
- * Install the React Native capture hooks — the console wrapper and the XHR
70
+ * Install the React Native capture hooks — the shared console wrapper and the XHR
271
71
  * patch — and return a single teardown that removes them all. Each hook is
272
72
  * independent and defensive: a failure in one never blocks the other, and none
273
73
  * can throw into the host app. An off stream is never instrumented at all.
274
74
  */
275
75
  export declare function instrumentBreadcrumbs(buffer: BreadcrumbBuffer, options?: InstrumentOptions): Teardown;
276
- export {};