@allstak/react-native 0.1.3 → 0.3.1

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.d.mts CHANGED
@@ -1 +1,873 @@
1
- export { AllStak, ReactNativeInstallOptions, installReactNative } from '@allstak/js/react-native';
1
+ import * as React from 'react';
2
+
3
+ /**
4
+ * Minimal HTTP transport for React Native. Uses the global `fetch` (always
5
+ * present in RN >= 0.60) with a 3s timeout. Failed sends fall into a small
6
+ * in-memory ring buffer that we retry on the next successful flush.
7
+ *
8
+ * No window, no AbortController fallback shims — RN exposes both natively.
9
+ */
10
+ declare class HttpTransport {
11
+ private baseUrl;
12
+ private apiKey;
13
+ private buffer;
14
+ private flushing;
15
+ constructor(baseUrl: string, apiKey: string);
16
+ send(path: string, payload: unknown): Promise<void>;
17
+ private doFetch;
18
+ private flushBuffer;
19
+ getBufferSize(): number;
20
+ /**
21
+ * Wait for the in-flight retry-buffer to drain. Resolves `true` if the
22
+ * buffer empties within `timeoutMs` (default 2000ms), `false` otherwise.
23
+ * Useful before navigation away or during native crash drain.
24
+ */
25
+ flush(timeoutMs?: number): Promise<boolean>;
26
+ }
27
+
28
+ /**
29
+ * HTTP request batching + transport for the React Native SDK.
30
+ *
31
+ * Mirrors the wire shape used by `@allstak/js`'s HttpRequestModule so the
32
+ * existing backend ingest endpoint (`/ingest/v1/http-requests`) accepts
33
+ * events from this SDK without a schema change. Adds optional rich fields
34
+ * (headers, bodies, error string) — these ride alongside the existing
35
+ * required fields and are tolerated as additive metadata server-side.
36
+ *
37
+ * Batching:
38
+ * - flushes on a 5s timer OR when 20 events queue up
39
+ * - flushes immediately on `destroy()`
40
+ * - `getRecentFailed(n)` returns the last n failed requests (statusCode
41
+ * >= 400 OR error set), used by error-linking on the next captureException
42
+ */
43
+
44
+ /** What instrumentation hands to the module per request. */
45
+ interface HttpRequestEvent {
46
+ type: 'http_request';
47
+ method: string;
48
+ url: string;
49
+ statusCode?: number;
50
+ durationMs: number;
51
+ requestSize?: number;
52
+ responseSize?: number;
53
+ requestBody?: string;
54
+ responseBody?: string;
55
+ requestHeaders?: Record<string, string>;
56
+ responseHeaders?: Record<string, string>;
57
+ error?: string;
58
+ traceId?: string;
59
+ }
60
+ interface HttpRequestIngestItem {
61
+ type: 'http_request';
62
+ traceId: string;
63
+ direction: 'outbound';
64
+ method: string;
65
+ host: string;
66
+ path: string;
67
+ url: string;
68
+ statusCode: number;
69
+ durationMs: number;
70
+ requestSize?: number;
71
+ responseSize?: number;
72
+ requestBody?: string;
73
+ responseBody?: string;
74
+ requestHeaders?: Record<string, string>;
75
+ responseHeaders?: Record<string, string>;
76
+ error?: string;
77
+ environment?: string;
78
+ release?: string;
79
+ dist?: string;
80
+ platform?: string;
81
+ 'sdk.name'?: string;
82
+ 'sdk.version'?: string;
83
+ timestamp: string;
84
+ }
85
+ interface ModuleDefaults {
86
+ environment?: string;
87
+ release?: string;
88
+ dist?: string;
89
+ platform?: string;
90
+ sdkName?: string;
91
+ sdkVersion?: string;
92
+ }
93
+ declare class HttpRequestModule {
94
+ private transport;
95
+ private queue;
96
+ private recentFailed;
97
+ private flushTimer;
98
+ private destroyed;
99
+ private defaults;
100
+ constructor(transport: HttpTransport);
101
+ setDefaults(defaults: ModuleDefaults): void;
102
+ capture(ev: HttpRequestEvent): void;
103
+ /** Snapshot of the last failed requests for error-linking. Newest last. */
104
+ getRecentFailed(): ReadonlyArray<HttpRequestIngestItem>;
105
+ flush(): void;
106
+ destroy(): void;
107
+ /** @internal — for tests. */
108
+ getQueueSize(): number;
109
+ }
110
+
111
+ /**
112
+ * Per-call scoped context isolation.
113
+ *
114
+ * A `Scope` carries the same shape as the top-level config (user, tags,
115
+ * extras, contexts, fingerprint, level) but only applies inside the
116
+ * `withScope` callback that owns it. The client merges the active scope
117
+ * stack on top of the base config when building each event payload, so:
118
+ *
119
+ * - context set inside `withScope` does NOT leak out
120
+ * - nested scopes layer additively (later wins on key conflicts)
121
+ * - throwing or async work in the callback still pops the scope
122
+ *
123
+ * Use this on the server (SSR / RSC / API route handlers) to attach
124
+ * per-request user/tags without leaking that data into another request
125
+ * being processed concurrently.
126
+ */
127
+ type Severity = 'fatal' | 'error' | 'warning' | 'info' | 'debug';
128
+ declare class Scope {
129
+ user?: {
130
+ id?: string;
131
+ email?: string;
132
+ };
133
+ tags: Record<string, string>;
134
+ extras: Record<string, unknown>;
135
+ contexts: Record<string, Record<string, unknown>>;
136
+ fingerprint?: string[];
137
+ level?: Severity;
138
+ setUser(user: {
139
+ id?: string;
140
+ email?: string;
141
+ }): this;
142
+ setTag(key: string, value: string): this;
143
+ setTags(tags: Record<string, string>): this;
144
+ setExtra(key: string, value: unknown): this;
145
+ setExtras(extras: Record<string, unknown>): this;
146
+ setContext(name: string, ctx: Record<string, unknown> | null): this;
147
+ setLevel(level: Severity): this;
148
+ setFingerprint(fingerprint: string[] | null): this;
149
+ clear(): this;
150
+ }
151
+
152
+ /**
153
+ * Lightweight distributed tracing primitives.
154
+ *
155
+ * A `Span` represents a unit of work — `startSpan('http.client', { description: 'GET /api/users' })`
156
+ * returns a Span; call `span.finish()` when the work completes. Spans
157
+ * batch into the transport's `/ingest/v1/spans` channel and ship every 5s
158
+ * (or when 20 spans accumulate).
159
+ *
160
+ * Trace propagation: each span carries a `traceId` (UUID, generated lazily
161
+ * on first call to `getTraceId()`) and a `spanId`. Nested calls to
162
+ * `startSpan()` automatically inherit the active span as their parent.
163
+ *
164
+ * Sampling: `tracesSampleRate` (config) gates whether `startSpan` actually
165
+ * records anything — drops when `Math.random() >= rate`. The returned
166
+ * Span is a no-op shim in that case so call sites don't need to null-check.
167
+ */
168
+
169
+ interface SpanData {
170
+ traceId: string;
171
+ spanId: string;
172
+ parentSpanId: string;
173
+ operation: string;
174
+ description: string;
175
+ status: 'ok' | 'error' | 'timeout';
176
+ durationMs: number;
177
+ startTimeMillis: number;
178
+ endTimeMillis: number;
179
+ service: string;
180
+ environment: string;
181
+ tags: Record<string, string>;
182
+ data: string;
183
+ }
184
+ declare class Span {
185
+ private _traceId;
186
+ private _spanId;
187
+ private _parentSpanId;
188
+ private _operation;
189
+ private _description;
190
+ private _service;
191
+ private _environment;
192
+ private _tags;
193
+ private _onFinish;
194
+ private _finished;
195
+ private _startTimeMillis;
196
+ private _data;
197
+ constructor(_traceId: string, _spanId: string, _parentSpanId: string, _operation: string, _description: string, _service: string, _environment: string, _tags: Record<string, string>, _onFinish: (data: SpanData) => void);
198
+ setTag(key: string, value: string): this;
199
+ setData(data: string): this;
200
+ setDescription(description: string): this;
201
+ finish(status?: 'ok' | 'error' | 'timeout'): void;
202
+ get traceId(): string;
203
+ get spanId(): string;
204
+ get isFinished(): boolean;
205
+ }
206
+
207
+ /**
208
+ * React Native "replay surrogate" — a privacy-first view-state breadcrumb
209
+ * recorder for environments where binary screen capture isn't available
210
+ * (Expo Go, JS-only test runners, or apps that can't link a native module
211
+ * for legal/compliance reasons).
212
+ *
213
+ * **What it captures (chronological, opt-in via sampleRate):**
214
+ * - the active route name on every navigation event
215
+ * - AppState foreground/background transitions (already covered by
216
+ * installReactNative's AppState breadcrumb wiring — we reuse that)
217
+ * - explicit `recordScreenView(name, params)` calls from the host app
218
+ * (used by router integrations or manual checkpoints)
219
+ *
220
+ * **What it intentionally does NOT capture:**
221
+ * - any user input values (text fields, password inputs, search queries)
222
+ * - any rendered text content from the visible screen
223
+ * - screenshots of any kind
224
+ * - URL path parameters by default (only the route name + opt-in `safeParams`)
225
+ *
226
+ * Hard rule: by default `safeParams` is `[]` and route params are dropped.
227
+ * Callers must explicitly enumerate which param keys are safe to log.
228
+ */
229
+
230
+ interface ReplaySurrogateOptions {
231
+ enabled?: boolean;
232
+ /** Probability in [0, 1] per session that recording happens. Default 0 (opt-in). */
233
+ sampleRate?: number;
234
+ /**
235
+ * Whitelist of route-param keys that are safe to record alongside the
236
+ * route name. Anything not on this list is dropped. Default `[]`.
237
+ */
238
+ safeParams?: string[];
239
+ /** Max events buffered before forced flush. Default 200. */
240
+ maxBufferedEvents?: number;
241
+ }
242
+ interface SurrogateEvent {
243
+ ts: number;
244
+ k: 'screen' | 'appstate' | 'manual';
245
+ data: Record<string, unknown>;
246
+ }
247
+ declare class ReplaySurrogate {
248
+ private transport;
249
+ private buffer;
250
+ private flushTimer;
251
+ private opts;
252
+ private sessionId;
253
+ private active;
254
+ private destroyed;
255
+ constructor(transport: HttpTransport, sessionId: string, options?: ReplaySurrogateOptions);
256
+ /** Enable recording for this session if sample-rate roll passes. */
257
+ start(): boolean;
258
+ /** Record a screen view. Filters params through the safeParams allow-list. */
259
+ recordScreenView(routeName: string, params?: Record<string, unknown>): void;
260
+ /** Record an AppState transition (foreground/background/inactive). */
261
+ recordAppState(next: string): void;
262
+ /** Record a free-form, customer-validated checkpoint. */
263
+ recordManual(label: string, data?: Record<string, unknown>): void;
264
+ destroy(): void;
265
+ /** @internal — for tests. */
266
+ isActive(): boolean;
267
+ /** @internal — for tests. */
268
+ getBuffer(): ReadonlyArray<SurrogateEvent>;
269
+ private push;
270
+ private flush;
271
+ }
272
+
273
+ interface HttpTrackingOptions {
274
+ /** Capture request body. Default false. Truncated to maxBodyBytes. */
275
+ captureRequestBody?: boolean;
276
+ /** Capture response body. Default false. Truncated to maxBodyBytes. */
277
+ captureResponseBody?: boolean;
278
+ /**
279
+ * Capture request + response headers. Default false. Hard-redacted
280
+ * names are always stripped regardless of this flag.
281
+ */
282
+ captureHeaders?: boolean;
283
+ /** Additional header names to redact (case-insensitive). */
284
+ redactHeaders?: string[];
285
+ /** Additional query-param names to redact (case-insensitive). */
286
+ redactQueryParams?: string[];
287
+ /**
288
+ * Skip URLs matching any of these patterns. String = case-insensitive
289
+ * substring match; RegExp = `.test()` against the full URL.
290
+ */
291
+ ignoredUrls?: (string | RegExp)[];
292
+ /**
293
+ * If non-empty, only capture URLs matching at least one of these
294
+ * patterns. Takes precedence over ignoredUrls.
295
+ */
296
+ allowedUrls?: (string | RegExp)[];
297
+ /** Max bytes per captured body. Default 4096. */
298
+ maxBodyBytes?: number;
299
+ }
300
+
301
+ /**
302
+ * Per-console-method capture flags. Defaults are set to keep the
303
+ * dashboard signal-to-noise high: `warn` and `error` capture by default
304
+ * (most apps fire those at human-meaningful moments), `log` and `info`
305
+ * are OFF by default since typical apps log thousands of debug lines
306
+ * per session.
307
+ *
308
+ * Override per-method:
309
+ *
310
+ * <AllStakProvider captureConsole={{ log: true, info: true }} />
311
+ *
312
+ * Or to fully suppress:
313
+ *
314
+ * <AllStakProvider captureConsole={{ warn: false, error: false }} />
315
+ *
316
+ * Setting `autoConsoleBreadcrumbs={false}` on the provider/install is a
317
+ * higher-level kill switch — it skips wrapping any console method.
318
+ */
319
+ interface ConsoleCaptureOptions {
320
+ log?: boolean;
321
+ info?: boolean;
322
+ warn?: boolean;
323
+ error?: boolean;
324
+ }
325
+ /** @internal — for tests. Resets the wrap-once flag. */
326
+ declare function __resetConsoleInstrumentationFlagForTest(): void;
327
+
328
+ declare const INGEST_HOST = "https://api.allstak.sa";
329
+ declare const SDK_NAME = "allstak-react-native";
330
+ declare const SDK_VERSION = "0.3.1";
331
+
332
+ interface AllStakConfig {
333
+ /** Project API key (`ask_live_…`). Required. */
334
+ apiKey: string;
335
+ /** Optional ingest host override; defaults to {@link INGEST_HOST}. */
336
+ host?: string;
337
+ environment?: string;
338
+ release?: string;
339
+ user?: {
340
+ id?: string;
341
+ email?: string;
342
+ };
343
+ tags?: Record<string, string>;
344
+ /** Per-event extra data attached to every capture (override per call via context arg). */
345
+ extras?: Record<string, unknown>;
346
+ /** Named context bags (e.g. `app`, `device`). Each lives under `metadata['context.<name>']`. */
347
+ contexts?: Record<string, Record<string, unknown>>;
348
+ /**
349
+ * Default severity level for events that don't specify their own.
350
+ * Affects `captureException` (sets `payload.level`) and the default of
351
+ * `captureMessage`. Customer-set default severity, mirrors `setLevel`.
352
+ */
353
+ level?: 'fatal' | 'error' | 'warning' | 'info' | 'debug';
354
+ /**
355
+ * Custom grouping fingerprint applied to every event. The backend uses
356
+ * this in place of stack-based grouping. Customer-set grouping override —
357
+ * `setFingerprint`. Pass an empty array or `null` to clear.
358
+ */
359
+ fingerprint?: string[];
360
+ /** Probability in [0, 1] that any new span is recorded. Default 1. */
361
+ tracesSampleRate?: number;
362
+ /** Service name attached to every span (defaults to release if unset). */
363
+ service?: string;
364
+ /**
365
+ * Privacy-first view-state replay surrogate. **Off by default.** Enable
366
+ * with `replay: { sampleRate: 0.1, safeParams: ['screenId'] }`. Captures
367
+ * route names + AppState transitions + manual checkpoints — never inputs
368
+ * or rendered text. See `src/replay-surrogate.ts` for the privacy contract.
369
+ */
370
+ replay?: ReplaySurrogateOptions;
371
+ /**
372
+ * Auto-instrument outbound HTTP — wraps `fetch`, `XMLHttpRequest`, and
373
+ * (when present) `axios`. Default: false. Combine with `httpTracking`
374
+ * to control body/header capture and redaction. Idempotent.
375
+ */
376
+ enableHttpTracking?: boolean;
377
+ /**
378
+ * Privacy + capture controls for HTTP instrumentation. Bodies and
379
+ * headers are OFF by default; auth headers and sensitive query params
380
+ * are ALWAYS redacted.
381
+ */
382
+ httpTracking?: HttpTrackingOptions;
383
+ /**
384
+ * Per-console-method capture flags. Defaults: warn + error captured,
385
+ * log + info NOT captured (to avoid breadcrumb spam from typical app
386
+ * logging). Set `{ log: true, info: true }` to opt-in.
387
+ */
388
+ captureConsole?: ConsoleCaptureOptions;
389
+ maxBreadcrumbs?: number;
390
+ /**
391
+ * Probability in [0, 1] that any given error is sent. Default: 1 (no sampling).
392
+ * Applied per event before {@link beforeSend}.
393
+ */
394
+ sampleRate?: number;
395
+ /**
396
+ * Mutate or drop an event before it is sent. Return `null` (or a falsy
397
+ * value) to drop. Sync or async. Errors thrown inside the hook are caught
398
+ * — the event is sent as-is so a buggy hook can't black-hole telemetry.
399
+ */
400
+ beforeSend?: (event: ErrorIngestPayload) => ErrorIngestPayload | null | undefined | Promise<ErrorIngestPayload | null | undefined>;
401
+ /** SDK identity overrides (set automatically by installReactNative). */
402
+ sdkName?: string;
403
+ sdkVersion?: string;
404
+ platform?: string;
405
+ dist?: string;
406
+ commitSha?: string;
407
+ branch?: string;
408
+ }
409
+ interface Breadcrumb {
410
+ timestamp: string;
411
+ type: string;
412
+ message: string;
413
+ level: string;
414
+ data?: Record<string, unknown>;
415
+ }
416
+ interface PayloadFrame {
417
+ filename?: string;
418
+ absPath?: string;
419
+ function?: string;
420
+ lineno?: number;
421
+ colno?: number;
422
+ inApp?: boolean;
423
+ platform?: string;
424
+ }
425
+ interface ErrorIngestPayload {
426
+ exceptionClass: string;
427
+ message: string;
428
+ stackTrace?: string[];
429
+ frames?: PayloadFrame[];
430
+ platform?: string;
431
+ sdkName?: string;
432
+ sdkVersion?: string;
433
+ dist?: string;
434
+ level: string;
435
+ environment?: string;
436
+ release?: string;
437
+ sessionId?: string;
438
+ user?: {
439
+ id?: string;
440
+ email?: string;
441
+ };
442
+ metadata?: Record<string, unknown>;
443
+ breadcrumbs?: Breadcrumb[];
444
+ fingerprint?: string[];
445
+ }
446
+ declare class AllStakClient {
447
+ private transport;
448
+ private config;
449
+ private sessionId;
450
+ private breadcrumbs;
451
+ private maxBreadcrumbs;
452
+ private scopeStack;
453
+ private tracing;
454
+ private replay;
455
+ private httpRequests;
456
+ private _instrumentAxios;
457
+ constructor(config: AllStakConfig);
458
+ /** Access the replay surrogate (or null if not initialized / sampled out). */
459
+ getReplay(): ReplaySurrogate | null;
460
+ /** Manually instrument an axios instance. No-op when HTTP tracking is off. */
461
+ instrumentAxios<T = any>(axios: T): T;
462
+ /** Snapshot of recent failed HTTP requests for error-linking. */
463
+ getRecentFailedHttp(): readonly HttpRequestIngestItem[];
464
+ captureException(error: Error, context?: Record<string, unknown>): void;
465
+ /** Start a new span. Auto-parented to any currently-active span. */
466
+ startSpan(operation: string, options?: {
467
+ description?: string;
468
+ tags?: Record<string, string>;
469
+ }): Span;
470
+ /** Get (and lazily create) the active trace ID. */
471
+ getTraceId(): string;
472
+ /** Override the active trace ID, e.g. from an inbound request header. */
473
+ setTraceId(traceId: string): void;
474
+ /** ID of the currently-active span, or null. */
475
+ getCurrentSpanId(): string | null;
476
+ /** Reset the trace ID and the active span stack. */
477
+ resetTrace(): void;
478
+ captureMessage(message: string, level?: 'fatal' | 'error' | 'warning' | 'info', options?: {
479
+ as?: 'log' | 'error' | 'both';
480
+ }): void;
481
+ addBreadcrumb(type: string, message: string, level?: string, data?: Record<string, unknown>): void;
482
+ clearBreadcrumbs(): void;
483
+ setUser(user: {
484
+ id?: string;
485
+ email?: string;
486
+ }): void;
487
+ setTag(key: string, value: string): void;
488
+ /** Bulk-set tags. Merges with existing tags. */
489
+ setTags(tags: Record<string, string>): void;
490
+ /** Set a single extra value. */
491
+ setExtra(key: string, value: unknown): void;
492
+ /** Bulk-set extras. Merges with existing extras. */
493
+ setExtras(extras: Record<string, unknown>): void;
494
+ /**
495
+ * Attach a named context bag (e.g. `app`, `device`, `runtime`) — appears
496
+ * under `metadata['context.<name>']` on every subsequent event. Pass
497
+ * `null` to remove a previously-set context.
498
+ */
499
+ setContext(name: string, ctx: Record<string, unknown> | null): void;
500
+ /**
501
+ * Wait for the in-flight retry-buffer to drain. Resolves `true` if the
502
+ * buffer empties within `timeoutMs` (default 2000ms), `false` otherwise.
503
+ */
504
+ flush(timeoutMs?: number): Promise<boolean>;
505
+ /** Set the default severity level applied to subsequent captures. */
506
+ setLevel(level: 'fatal' | 'error' | 'warning' | 'info' | 'debug'): void;
507
+ /**
508
+ * Set a custom grouping fingerprint applied to subsequent events.
509
+ * Pass `null` or an empty array to clear and revert to default grouping.
510
+ */
511
+ setFingerprint(fingerprint: string[] | null): void;
512
+ setIdentity(identity: {
513
+ sdkName?: string;
514
+ sdkVersion?: string;
515
+ platform?: string;
516
+ dist?: string;
517
+ }): void;
518
+ getSessionId(): string;
519
+ getConfig(): AllStakConfig;
520
+ destroy(): void;
521
+ private sendLog;
522
+ private passesSampleRate;
523
+ /**
524
+ * Returns the effective config layer = base config + every scope on the
525
+ * stack. Inner code reads from this instead of `this.config` directly so
526
+ * scope-only overrides (set inside `withScope`) flow into the wire
527
+ * payload without leaking out of the callback.
528
+ */
529
+ private effective;
530
+ private buildMetadata;
531
+ /**
532
+ * Run `callback` with a fresh, temporary {@link Scope} that isolates
533
+ * any user/tag/extra/context/fingerprint/level it sets. The scope is
534
+ * popped automatically when the callback returns or throws — including
535
+ * for `Promise`-returning callbacks (the pop runs in `.finally`).
536
+ *
537
+ * Use this on the server to attach per-request context without leaking
538
+ * across concurrent requests.
539
+ */
540
+ withScope<T>(callback: (scope: Scope) => T): T;
541
+ /** Direct access to the topmost active scope, or null. @internal */
542
+ getCurrentScope(): Scope | null;
543
+ private sendThroughBeforeSend;
544
+ private releaseTags;
545
+ }
546
+ declare const AllStak: {
547
+ init(config: AllStakConfig): AllStakClient;
548
+ captureException(error: Error, context?: Record<string, unknown>): void;
549
+ captureMessage(message: string, level?: "fatal" | "error" | "warning" | "info", options?: {
550
+ as?: "log" | "error" | "both";
551
+ }): void;
552
+ addBreadcrumb(type: string, message: string, level?: string, data?: Record<string, unknown>): void;
553
+ clearBreadcrumbs(): void;
554
+ setUser(user: {
555
+ id?: string;
556
+ email?: string;
557
+ }): void;
558
+ setTag(key: string, value: string): void;
559
+ setTags(tags: Record<string, string>): void;
560
+ setExtra(key: string, value: unknown): void;
561
+ setExtras(extras: Record<string, unknown>): void;
562
+ setContext(name: string, ctx: Record<string, unknown> | null): void;
563
+ setLevel(level: "fatal" | "error" | "warning" | "info" | "debug"): void;
564
+ setFingerprint(fingerprint: string[] | null): void;
565
+ flush(timeoutMs?: number): Promise<boolean>;
566
+ setIdentity(identity: {
567
+ sdkName?: string;
568
+ sdkVersion?: string;
569
+ platform?: string;
570
+ dist?: string;
571
+ }): void;
572
+ /**
573
+ * Run `callback` with a fresh scoped context. Any user/tag/extra/context/
574
+ * fingerprint/level set on the passed `Scope` is visible only inside the
575
+ * callback (and any captures made within it). Pop is automatic, including
576
+ * for async callbacks and thrown errors.
577
+ */
578
+ withScope<T>(callback: (scope: Scope) => T): T;
579
+ startSpan(operation: string, options?: {
580
+ description?: string;
581
+ tags?: Record<string, string>;
582
+ }): Span;
583
+ getTraceId(): string;
584
+ setTraceId(traceId: string): void;
585
+ getCurrentSpanId(): string | null;
586
+ resetTrace(): void;
587
+ /** Access the privacy-first replay surrogate (or null if disabled / sampled out). */
588
+ getReplay(): ReplaySurrogate | null;
589
+ /** Manually instrument an axios instance. No-op when HTTP tracking is off. */
590
+ instrumentAxios<T = any>(axios: T): T;
591
+ getSessionId(): string;
592
+ getConfig(): AllStakConfig | null;
593
+ destroy(): void;
594
+ /** @internal — exposed for testing */
595
+ _getInstance(): AllStakClient | null;
596
+ };
597
+
598
+ /**
599
+ * React Native runtime integration — ErrorUtils, Hermes promise rejection
600
+ * tracking, Platform tags, AppState breadcrumbs, XHR network capture,
601
+ * fetch breadcrumbs, and console breadcrumbs.
602
+ *
603
+ * Extracted from index.ts so AllStakProvider can call it without circular
604
+ * imports.
605
+ */
606
+ interface ReactNativeInstallOptions {
607
+ /** Auto-capture unhandled JS exceptions via ErrorUtils. Default: true */
608
+ autoErrorHandler?: boolean;
609
+ /** Auto-capture unhandled promise rejections (Hermes). Default: true */
610
+ autoPromiseRejections?: boolean;
611
+ /** Auto-attach Platform.* info as tags. Default: true */
612
+ autoDeviceTags?: boolean;
613
+ /** Auto-emit breadcrumbs on AppState change. Default: true */
614
+ autoAppStateBreadcrumbs?: boolean;
615
+ /** Auto-instrument XHR (RN's fetch is XHR-based) for network breadcrumbs. Default: true */
616
+ autoNetworkCapture?: boolean;
617
+ /** Wrap `globalThis.fetch` to record HTTP breadcrumbs. Default: true */
618
+ autoFetchBreadcrumbs?: boolean;
619
+ /**
620
+ * Wrap `console.*` methods to record log breadcrumbs. Default: true.
621
+ * Per-method capture is controlled by `captureConsole` in AllStakConfig
622
+ * (warn + error default on, log + info default off).
623
+ */
624
+ autoConsoleBreadcrumbs?: boolean;
625
+ /**
626
+ * Auto-detect `@react-navigation/native` and patch `NavigationContainer`
627
+ * so route changes ship as breadcrumbs without the host app needing
628
+ * to call `instrumentReactNavigation(ref)`. Default: true. When the
629
+ * package is not installed, this silently no-ops.
630
+ */
631
+ autoNavigationBreadcrumbs?: boolean;
632
+ /**
633
+ * Emit a `[AllStak] Navigation auto-instrumentation enabled/not applied`
634
+ * console log so developers can confirm the wiring at startup. The
635
+ * provider sets this from its `debug` prop; defaults to false when
636
+ * called manually.
637
+ */
638
+ debugLogs?: boolean;
639
+ }
640
+ declare function installReactNative(options?: ReactNativeInstallOptions): void;
641
+
642
+ interface AllStakProviderProps extends ReactNativeInstallOptions {
643
+ children: React.ReactNode;
644
+ apiKey: string;
645
+ environment?: string;
646
+ release?: string;
647
+ host?: string;
648
+ user?: {
649
+ id?: string;
650
+ email?: string;
651
+ };
652
+ tags?: Record<string, string>;
653
+ debug?: boolean;
654
+ enableHttpTracking?: boolean;
655
+ httpTracking?: AllStakConfig['httpTracking'];
656
+ /**
657
+ * Per-console-method capture flags. Defaults: warn + error on, log +
658
+ * info off. Set `{ log: true, info: true }` to opt-in to verbose
659
+ * capture, or `{ warn: false, error: false }` to suppress.
660
+ */
661
+ captureConsole?: AllStakConfig['captureConsole'];
662
+ sampleRate?: number;
663
+ beforeSend?: AllStakConfig['beforeSend'];
664
+ replay?: AllStakConfig['replay'];
665
+ tracesSampleRate?: number;
666
+ service?: string;
667
+ dist?: string;
668
+ /**
669
+ * Tear down the SDK when the provider unmounts. Default `false`.
670
+ *
671
+ * Most apps mount `AllStakProvider` once at the root and never unmount
672
+ * it. Setting this to `true` risks disabling telemetry if the provider
673
+ * re-mounts (Fast Refresh in dev, route key changes, React 18 Strict
674
+ * Mode double-mount, etc.) — there is a brief window between unmount
675
+ * and remount where captures throw.
676
+ *
677
+ * Leave at the default unless you genuinely need to dispose the SDK
678
+ * (e.g. test harness, multi-tenant container that switches projects).
679
+ */
680
+ destroyOnUnmount?: boolean;
681
+ fallback?: React.ReactNode | ((props: {
682
+ error: Error;
683
+ resetError: () => void;
684
+ }) => React.ReactNode);
685
+ onError?: (error: Error, componentStack?: string) => void;
686
+ }
687
+ declare function AllStakProvider({ children, apiKey, environment, release, host, user, tags, debug, enableHttpTracking, httpTracking, captureConsole, sampleRate, beforeSend, replay, tracesSampleRate, service, dist, destroyOnUnmount, fallback, onError, autoErrorHandler, autoPromiseRejections, autoDeviceTags, autoAppStateBreadcrumbs, autoNetworkCapture, autoFetchBreadcrumbs, autoConsoleBreadcrumbs, autoNavigationBreadcrumbs, }: AllStakProviderProps): React.ReactElement;
688
+ declare function useAllStak(): {
689
+ captureException: (error: Error, ctx?: Record<string, unknown>) => void;
690
+ captureMessage: (msg: string, level?: "fatal" | "error" | "warning" | "info") => void;
691
+ setUser: (user: {
692
+ id?: string;
693
+ email?: string;
694
+ }) => void;
695
+ setTag: (key: string, value: string) => void;
696
+ addBreadcrumb: (type: string, message: string, level?: string, data?: Record<string, unknown>) => void;
697
+ };
698
+ /** @internal — for tests. Resets the module-level remount-guard. */
699
+ declare function __resetProviderInstanceForTest(): void;
700
+
701
+ /**
702
+ * React Native navigation breadcrumbs — two opt-in helpers:
703
+ *
704
+ * - instrumentReactNavigation(navigationRef): call once after the
705
+ * NavigationContainer is mounted. Subscribes to `state` events on the
706
+ * NavigationContainerRef and emits a breadcrumb whenever the active
707
+ * route name changes. Works with @react-navigation/native v6+ without
708
+ * adding it as a dependency (the ref shape is duck-typed).
709
+ *
710
+ * - instrumentNavigationFromLinking(): registers a Linking event
711
+ * listener so deep links also appear in breadcrumbs. Useful when the
712
+ * app uses Linking.openURL(...) instead of (or alongside) a router.
713
+ *
714
+ * Both helpers are idempotent and never throw if the underlying RN module
715
+ * isn't present (Expo Go, JS-only test runs).
716
+ */
717
+ type NavigationRef = {
718
+ getCurrentRoute?: () => {
719
+ name?: string;
720
+ } | undefined;
721
+ addListener?: (event: string, cb: () => void) => () => void;
722
+ };
723
+ interface ReactNavigationOptions {
724
+ /**
725
+ * Whitelist of route-param keys safe to record alongside the route name.
726
+ * Anything outside this list is dropped — params commonly carry user IDs,
727
+ * order numbers, etc. Default `[]`.
728
+ */
729
+ safeParams?: string[];
730
+ /**
731
+ * Also forward the screen view to the replay surrogate (if active).
732
+ * Default true — the surrogate itself decides whether it's recording.
733
+ */
734
+ forwardToReplay?: boolean;
735
+ }
736
+ /**
737
+ * Subscribe to a `@react-navigation/native` NavigationContainerRef and
738
+ * emit a navigation breadcrumb whenever the active route changes. Captures:
739
+ *
740
+ * - route name change (from -> to)
741
+ * - whitelisted route params (via `safeParams`)
742
+ * - state change → forwarded to replay surrogate when enabled
743
+ *
744
+ * Idempotent — installs once per ref. Returns an unsubscribe function.
745
+ */
746
+ declare function instrumentReactNavigation(navigationRef: NavigationRef, options?: ReactNavigationOptions): () => void;
747
+ /**
748
+ * Register a Linking listener so `openURL`/deep-link launches surface
749
+ * as breadcrumbs. No-op if `react-native` isn't available (test env).
750
+ */
751
+ declare function instrumentNavigationFromLinking(): void;
752
+ /**
753
+ * Best-effort automatic instrumentation of `@react-navigation/native`.
754
+ *
755
+ * **What it does:**
756
+ * - Tries `require('@react-navigation/native')`. If the package is not
757
+ * installed, returns `false` and is otherwise a no-op.
758
+ * - If found, monkey-patches the module's exported `NavigationContainer`
759
+ * with a wrapper that auto-creates an internal ref, forwards the
760
+ * user's `ref` prop, and on mount calls `instrumentReactNavigation`
761
+ * so route changes ship as breadcrumbs.
762
+ * - Idempotent: a flag on the module's exports object prevents double
763
+ * patching across hot-reload cycles or repeated `installReactNative`
764
+ * calls.
765
+ *
766
+ * **Why this works:**
767
+ * Babel's CommonJS interop preserves runtime property lookups for
768
+ * named imports — `import { NavigationContainer } from '@react-navigation/native'`
769
+ * compiles to `_rnav.NavigationContainer` accesses at use-site, so
770
+ * patching the module's exports object before the host app renders
771
+ * means user code transparently picks up our wrapper.
772
+ *
773
+ * **Why it might fail:**
774
+ * - `@react-navigation/native` not installed → returns false silently.
775
+ * - Module exports frozen or sealed (rare in CJS-style RN builds).
776
+ * - User imported `NavigationContainer` via a deep path that bypasses
777
+ * the index module.
778
+ * In any failure case the manual API (`instrumentReactNavigation(ref)`)
779
+ * is still available as a fallback.
780
+ */
781
+ declare function tryAutoInstrumentNavigation(): boolean;
782
+ /** @internal — for tests. Resets the auto-patch flag on the cached module. */
783
+ declare function __resetAutoNavigationFlagForTest(): void;
784
+
785
+ /**
786
+ * React Native architecture / runtime detection.
787
+ *
788
+ * **Status:** the JS-level check is implemented and tested. The native
789
+ * AllStak modules (Java + Obj-C) are written in legacy module style and
790
+ * are known to interoperate with the New Architecture (Fabric +
791
+ * TurboModules) via the RN interop layer. End-to-end integration on a
792
+ * real Fabric build has not yet been verified — see README §"New
793
+ * Architecture support" for current status.
794
+ *
795
+ * The two booleans returned here are read off well-known global flags
796
+ * that RN exposes to JS:
797
+ *
798
+ * - `globalThis.__turboModuleProxy` — present when TurboModules is
799
+ * enabled (New Architecture).
800
+ * - `globalThis.RN$Bridgeless` — present when bridgeless mode is on.
801
+ *
802
+ * If the host app surfaces this through `AllStak.setTag('rn.newArch', '1')`
803
+ * we can correlate New-Arch crashes specifically and prioritize a fix.
804
+ */
805
+ interface ArchitectureInfo {
806
+ /** True when TurboModules / New Architecture is detected at runtime. */
807
+ newArchitecture: boolean;
808
+ /** True when bridgeless mode is detected. */
809
+ bridgeless: boolean;
810
+ /** True when the JS engine is Hermes. */
811
+ hermes: boolean;
812
+ /** Free-form tag suitable for `AllStak.setTag('rn.architecture', ...)`. */
813
+ tag: 'new-arch' | 'old-arch' | 'unknown';
814
+ }
815
+ declare function detectArchitecture(): ArchitectureInfo;
816
+ /**
817
+ * Convenience: stamp `rn.architecture`, `rn.bridgeless`, and `rn.hermes`
818
+ * tags on the active AllStak singleton based on detection. Safe to call
819
+ * any time after `AllStak.init()` and before the first capture.
820
+ */
821
+ declare function applyArchitectureTags(setTag: (key: string, value: string) => void): ArchitectureInfo;
822
+
823
+ /**
824
+ * @allstak/react-native — standalone React Native SDK.
825
+ *
826
+ * Self-contained: depends only on `react-native` (peer) and the global
827
+ * `fetch`/`AbortController` that RN guarantees. Contains no `window`,
828
+ * `document`, `localStorage`, `sessionStorage`, or browser DOM event
829
+ * listeners.
830
+ *
831
+ * Recommended usage (one-liner):
832
+ *
833
+ * import { AllStakProvider } from '@allstak/react-native';
834
+ *
835
+ * export default function App() {
836
+ * return (
837
+ * <AllStakProvider apiKey="YOUR_API_KEY" environment="production">
838
+ * <AppRoot />
839
+ * </AllStakProvider>
840
+ * );
841
+ * }
842
+ *
843
+ * Advanced / manual usage:
844
+ *
845
+ * import { AllStak, installReactNative } from '@allstak/react-native';
846
+ * AllStak.init({ apiKey, environment, release });
847
+ * installReactNative();
848
+ *
849
+ * Native crash capture (Java/Kotlin on Android, Obj-C/Swift on iOS) lives
850
+ * under the `native/` directory in this package. See README.
851
+ */
852
+
853
+ declare function __setNativeModuleForTest(mod: any): void;
854
+ /**
855
+ * DEV-ONLY: deliberately trigger a native iOS or Android crash via the
856
+ * linked AllStak native module. This is intended for verifying the
857
+ * native-crash → drain → ingest pipeline during SDK development. It
858
+ * **terminates the app process** — never expose this in production UI.
859
+ *
860
+ * import { __devTriggerNativeCrash } from '@allstak/react-native';
861
+ * if (__DEV__) __devTriggerNativeCrash(); // app dies; relaunch drains
862
+ *
863
+ * No-op when the native module is not linked.
864
+ */
865
+ declare function __devTriggerNativeCrash(): Promise<void>;
866
+ /**
867
+ * Drain any native crash stashed by AllStakCrashHandler on the previous
868
+ * launch and ship it to /ingest/v1/errors. No-op when the native module
869
+ * is not linked (Expo Go, JS-only test runners, etc).
870
+ */
871
+ declare function drainPendingNativeCrashes(release?: string): Promise<void>;
872
+
873
+ export { AllStak, AllStakClient, type AllStakConfig, AllStakProvider, type AllStakProviderProps, type ArchitectureInfo, type Breadcrumb, type ConsoleCaptureOptions, type HttpRequestEvent, HttpRequestModule, type HttpTrackingOptions, INGEST_HOST, type ReactNativeInstallOptions, ReplaySurrogate, type ReplaySurrogateOptions, SDK_NAME, SDK_VERSION, Scope, __devTriggerNativeCrash, __resetAutoNavigationFlagForTest, __resetConsoleInstrumentationFlagForTest, __resetProviderInstanceForTest, __setNativeModuleForTest, applyArchitectureTags, detectArchitecture, drainPendingNativeCrashes, installReactNative, instrumentNavigationFromLinking, instrumentReactNavigation, tryAutoInstrumentNavigation, useAllStak };