@allstak/react 0.1.3 → 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.
package/dist/index.d.ts CHANGED
@@ -1 +1,672 @@
1
- export { AllStak, AllStakErrorBoundary, AllStakErrorBoundaryProps, useAllStak, withAllStakProfiler } from '@allstak/js/react';
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 at process exit / before navigation away.
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
+ * Lightweight session-replay surrogate for the browser.
209
+ *
210
+ * **Status:** experimental. Captures DOM mutation events as a chronological
211
+ * log so a server-side replay viewer can reconstruct the visible page over
212
+ * time. Privacy-first defaults:
213
+ *
214
+ * - all `<input>`, `<textarea>`, `<select>` values are masked by default
215
+ * - elements with `data-allstak-mask` are entirely replaced with `***`
216
+ * - `[type="password"]` is always masked, even with masking off
217
+ * - `sampleRate` defaults to 0 — replay is OPT-IN per init
218
+ *
219
+ * NOT a drop-in replacement for full DOM-snapshot replay libraries — it
220
+ * does not record initial paint, window resizes, scroll positions, or
221
+ * canvas content. It records:
222
+ *
223
+ * 1. an initial sanitized DOM snapshot at start
224
+ * 2. mutations: childList add/remove + attributes (filtered)
225
+ * 3. user input events with values masked
226
+ * 4. a periodic flush of the buffered log to /ingest/v1/replay
227
+ *
228
+ * Because the wire format is a JSON event log (not a binary blob), payloads
229
+ * are larger than dedicated replay tools — appropriate for low-volume
230
+ * debugging, not for sampling 100% of production traffic.
231
+ */
232
+
233
+ type AddBreadcrumbFn$2 = (type: string, msg: string, level?: string, data?: Record<string, unknown>) => void;
234
+ interface ReplayOptions {
235
+ enabled?: boolean;
236
+ /** Probability per session that replay records. Default 0 (opt-in). */
237
+ sampleRate?: number;
238
+ /** Mask all text inputs / textareas / selects by default. Default true. */
239
+ maskAllInputs?: boolean;
240
+ /** Custom attribute name that flags an element to be masked. Default `data-allstak-mask`. */
241
+ maskAttribute?: string;
242
+ /** Max number of events buffered before forced flush. Default 200. */
243
+ maxBufferedEvents?: number;
244
+ }
245
+ interface ReplayEvent {
246
+ /** UNIX millis when the event was observed. */
247
+ ts: number;
248
+ /** event kind */
249
+ k: 'snap' | 'mut' | 'input' | 'nav';
250
+ /** Free-form JSON-friendly payload. */
251
+ data: Record<string, unknown>;
252
+ }
253
+ declare class ReplayRecorder {
254
+ private transport;
255
+ private addBreadcrumb;
256
+ private buffer;
257
+ private flushTimer;
258
+ private observer;
259
+ private inputListener;
260
+ private opts;
261
+ private sessionId;
262
+ private destroyed;
263
+ constructor(transport: HttpTransport, sessionId: string, addBreadcrumb: AddBreadcrumbFn$2, options?: ReplayOptions);
264
+ start(): void;
265
+ destroy(): void;
266
+ /** @internal — exposed for tests. */
267
+ getBuffer(): ReadonlyArray<ReplayEvent>;
268
+ private push;
269
+ private flush;
270
+ private snapshotBody;
271
+ private maskTree;
272
+ private maskInputValue;
273
+ private describeNode;
274
+ private describePath;
275
+ private safeAttribute;
276
+ }
277
+
278
+ interface HttpTrackingOptions {
279
+ /** Capture request body. Default false. Truncated to maxBodyBytes. */
280
+ captureRequestBody?: boolean;
281
+ /** Capture response body. Default false. Truncated to maxBodyBytes. */
282
+ captureResponseBody?: boolean;
283
+ /**
284
+ * Capture request + response headers. Default false. Hard-redacted
285
+ * names are always stripped regardless of this flag.
286
+ */
287
+ captureHeaders?: boolean;
288
+ /** Additional header names to redact (case-insensitive). */
289
+ redactHeaders?: string[];
290
+ /** Additional query-param names to redact (case-insensitive). */
291
+ redactQueryParams?: string[];
292
+ /**
293
+ * Skip URLs matching any of these patterns. String = case-insensitive
294
+ * substring match; RegExp = `.test()` against the full URL.
295
+ */
296
+ ignoredUrls?: (string | RegExp)[];
297
+ /**
298
+ * If non-empty, only capture URLs matching at least one of these
299
+ * patterns. Takes precedence over ignoredUrls.
300
+ */
301
+ allowedUrls?: (string | RegExp)[];
302
+ /** Max bytes per captured body. Default 4096. */
303
+ maxBodyBytes?: number;
304
+ }
305
+
306
+ declare const INGEST_HOST = "https://api.allstak.sa";
307
+ declare const SDK_NAME = "allstak-react";
308
+ declare const SDK_VERSION = "0.3.0";
309
+
310
+ interface AllStakConfig {
311
+ /** Project API key (`ask_live_…`). Required. */
312
+ apiKey: string;
313
+ /** Optional ingest host override; defaults to {@link INGEST_HOST}. */
314
+ host?: string;
315
+ environment?: string;
316
+ release?: string;
317
+ user?: {
318
+ id?: string;
319
+ email?: string;
320
+ };
321
+ tags?: Record<string, string>;
322
+ /** Per-event extra data attached to every capture (override per call via context arg). */
323
+ extras?: Record<string, unknown>;
324
+ /** Named context bags (e.g. `app`, `device`). Each lives under `metadata['context.<name>']`. */
325
+ contexts?: Record<string, Record<string, unknown>>;
326
+ /**
327
+ * Default severity level for events that don't specify their own.
328
+ * Customer-set default severity, mirrors `setLevel`.
329
+ */
330
+ level?: 'fatal' | 'error' | 'warning' | 'info' | 'debug';
331
+ /**
332
+ * Custom grouping fingerprint applied to every event. Customer-set grouping override —
333
+ * `setFingerprint`. Pass an empty array or `null` to clear.
334
+ */
335
+ fingerprint?: string[];
336
+ /** Probability in [0, 1] that any new span is recorded. Default 1. */
337
+ tracesSampleRate?: number;
338
+ /** Service name attached to every span (defaults to release if unset). */
339
+ service?: string;
340
+ maxBreadcrumbs?: number;
341
+ /** Auto-capture unhandled `error` and `unhandledrejection` on `window`. Default: true */
342
+ autoCaptureBrowserErrors?: boolean;
343
+ /** Wrap `globalThis.fetch` to record HTTP breadcrumbs. Default: true */
344
+ autoBreadcrumbsFetch?: boolean;
345
+ /** Wrap `console.warn` and `console.error` to record log breadcrumbs. Default: true */
346
+ autoBreadcrumbsConsole?: boolean;
347
+ /** Wrap `history.pushState`/`replaceState` and listen to `popstate` for SPA navigation breadcrumbs. Default: true */
348
+ autoBreadcrumbsNavigation?: boolean;
349
+ /**
350
+ * Experimental session-replay surrogate. **Off by default.** Enable with
351
+ * `replay: { sampleRate: 0.1 }`. Captures sanitized initial DOM snapshot +
352
+ * subsequent mutations + masked input events. See `src/replay.ts` for
353
+ * the full privacy contract.
354
+ */
355
+ replay?: ReplayOptions;
356
+ /**
357
+ * Auto-instrument outbound HTTP — wraps `fetch`, `XMLHttpRequest`, and
358
+ * (when present) `axios`. Default: false.
359
+ */
360
+ enableHttpTracking?: boolean;
361
+ /**
362
+ * Privacy + capture controls for HTTP instrumentation. Bodies and
363
+ * headers are OFF by default; auth headers and sensitive query params
364
+ * are ALWAYS redacted.
365
+ */
366
+ httpTracking?: HttpTrackingOptions;
367
+ /**
368
+ * Probability in [0, 1] that any given error is sent. Default: 1 (no sampling).
369
+ * Applied per event before {@link beforeSend}.
370
+ */
371
+ sampleRate?: number;
372
+ /**
373
+ * Mutate or drop an event before it is sent. Return `null` (or a falsy
374
+ * value) to drop. Sync or async. Errors thrown inside the hook are caught
375
+ * — the event is sent as-is so a buggy hook can't black-hole telemetry.
376
+ */
377
+ beforeSend?: (event: ErrorIngestPayload) => ErrorIngestPayload | null | undefined | Promise<ErrorIngestPayload | null | undefined>;
378
+ /** SDK identity overrides. */
379
+ sdkName?: string;
380
+ sdkVersion?: string;
381
+ platform?: string;
382
+ dist?: string;
383
+ commitSha?: string;
384
+ branch?: string;
385
+ }
386
+ interface Breadcrumb {
387
+ timestamp: string;
388
+ type: string;
389
+ message: string;
390
+ level: string;
391
+ data?: Record<string, unknown>;
392
+ }
393
+ interface PayloadFrame {
394
+ filename?: string;
395
+ absPath?: string;
396
+ function?: string;
397
+ lineno?: number;
398
+ colno?: number;
399
+ inApp?: boolean;
400
+ platform?: string;
401
+ debugId?: string;
402
+ }
403
+ interface ErrorIngestPayload {
404
+ exceptionClass: string;
405
+ message: string;
406
+ stackTrace?: string[];
407
+ frames?: PayloadFrame[];
408
+ platform?: string;
409
+ sdkName?: string;
410
+ sdkVersion?: string;
411
+ dist?: string;
412
+ level: string;
413
+ environment?: string;
414
+ release?: string;
415
+ sessionId?: string;
416
+ user?: {
417
+ id?: string;
418
+ email?: string;
419
+ };
420
+ metadata?: Record<string, unknown>;
421
+ breadcrumbs?: Breadcrumb[];
422
+ requestContext?: {
423
+ method?: string;
424
+ path?: string;
425
+ host?: string;
426
+ userAgent?: string;
427
+ };
428
+ fingerprint?: string[];
429
+ }
430
+ declare class AllStakClient {
431
+ private transport;
432
+ private config;
433
+ private sessionId;
434
+ private breadcrumbs;
435
+ private maxBreadcrumbs;
436
+ private scopeStack;
437
+ private tracing;
438
+ private replay;
439
+ private httpRequests;
440
+ private _instrumentAxios;
441
+ private onErrorHandler;
442
+ private onRejectionHandler;
443
+ constructor(config: AllStakConfig);
444
+ /** Manually instrument an axios instance. No-op when HTTP tracking is off. */
445
+ instrumentAxios<T = any>(axios: T): T;
446
+ /** Snapshot of recent failed HTTP requests for error-linking. */
447
+ getRecentFailedHttp(): readonly HttpRequestIngestItem[];
448
+ captureException(error: Error, context?: Record<string, unknown>): void;
449
+ /** Start a new span — auto-parented to any currently-active span. */
450
+ startSpan(operation: string, options?: {
451
+ description?: string;
452
+ tags?: Record<string, string>;
453
+ }): Span;
454
+ /** Get (and lazily create) the active trace ID. */
455
+ getTraceId(): string;
456
+ /** Override the active trace ID, e.g. from an inbound request header. */
457
+ setTraceId(traceId: string): void;
458
+ /** ID of the currently-active span, or null. */
459
+ getCurrentSpanId(): string | null;
460
+ /** Reset the trace ID and the active span stack. */
461
+ resetTrace(): void;
462
+ captureMessage(message: string, level?: 'fatal' | 'error' | 'warning' | 'info', options?: {
463
+ as?: 'log' | 'error' | 'both';
464
+ }): void;
465
+ addBreadcrumb(type: string, message: string, level?: string, data?: Record<string, unknown>): void;
466
+ clearBreadcrumbs(): void;
467
+ setUser(user: {
468
+ id?: string;
469
+ email?: string;
470
+ }): void;
471
+ setTag(key: string, value: string): void;
472
+ /** Bulk-set tags. Merges with existing tags. */
473
+ setTags(tags: Record<string, string>): void;
474
+ /** Set a single extra value. */
475
+ setExtra(key: string, value: unknown): void;
476
+ /** Bulk-set extras. Merges with existing extras. */
477
+ setExtras(extras: Record<string, unknown>): void;
478
+ /**
479
+ * Attach a named context bag (e.g. `app`, `device`, `runtime`) — appears
480
+ * under `metadata['context.<name>']` on every subsequent event. Pass
481
+ * `null` to remove a previously-set context.
482
+ */
483
+ setContext(name: string, ctx: Record<string, unknown> | null): void;
484
+ /**
485
+ * Wait for the in-flight retry-buffer to drain. Resolves `true` if the
486
+ * buffer empties within `timeoutMs` (default 2000ms), `false` otherwise.
487
+ */
488
+ flush(timeoutMs?: number): Promise<boolean>;
489
+ /** Set the default severity level applied to subsequent captures. */
490
+ setLevel(level: 'fatal' | 'error' | 'warning' | 'info' | 'debug'): void;
491
+ /**
492
+ * Set a custom grouping fingerprint applied to subsequent events.
493
+ * Pass `null` or an empty array to clear and revert to default grouping.
494
+ */
495
+ setFingerprint(fingerprint: string[] | null): void;
496
+ setIdentity(identity: {
497
+ sdkName?: string;
498
+ sdkVersion?: string;
499
+ platform?: string;
500
+ dist?: string;
501
+ }): void;
502
+ getSessionId(): string;
503
+ getConfig(): AllStakConfig;
504
+ destroy(): void;
505
+ private installBrowserHandlers;
506
+ private sendLog;
507
+ private passesSampleRate;
508
+ /**
509
+ * Returns the effective config layer = base config + every active scope.
510
+ * Scope-only overrides (set inside `withScope`) flow into the wire
511
+ * payload without leaking out of the callback.
512
+ */
513
+ private effective;
514
+ private buildMetadata;
515
+ /**
516
+ * Run `callback` with a fresh, temporary {@link Scope} that isolates
517
+ * any user/tag/extra/context/fingerprint/level it sets. The scope is
518
+ * popped automatically when the callback returns or throws — including
519
+ * for `Promise`-returning callbacks (the pop runs in `.finally`).
520
+ *
521
+ * Use this on the server (SSR / RSC / API route handlers) to attach
522
+ * per-request user/tags without leaking that data into another request
523
+ * being processed concurrently.
524
+ */
525
+ withScope<T>(callback: (scope: Scope) => T): T;
526
+ /** Direct access to the topmost active scope, or null. @internal */
527
+ getCurrentScope(): Scope | null;
528
+ private sendThroughBeforeSend;
529
+ private releaseTags;
530
+ }
531
+ declare const AllStak: {
532
+ init(config: AllStakConfig): AllStakClient;
533
+ captureException(error: Error, context?: Record<string, unknown>): void;
534
+ captureMessage(message: string, level?: "fatal" | "error" | "warning" | "info", options?: {
535
+ as?: "log" | "error" | "both";
536
+ }): void;
537
+ addBreadcrumb(type: string, message: string, level?: string, data?: Record<string, unknown>): void;
538
+ clearBreadcrumbs(): void;
539
+ setUser(user: {
540
+ id?: string;
541
+ email?: string;
542
+ }): void;
543
+ setTag(key: string, value: string): void;
544
+ setTags(tags: Record<string, string>): void;
545
+ setExtra(key: string, value: unknown): void;
546
+ setExtras(extras: Record<string, unknown>): void;
547
+ setContext(name: string, ctx: Record<string, unknown> | null): void;
548
+ setLevel(level: "fatal" | "error" | "warning" | "info" | "debug"): void;
549
+ setFingerprint(fingerprint: string[] | null): void;
550
+ flush(timeoutMs?: number): Promise<boolean>;
551
+ setIdentity(identity: {
552
+ sdkName?: string;
553
+ sdkVersion?: string;
554
+ platform?: string;
555
+ dist?: string;
556
+ }): void;
557
+ /**
558
+ * Run `callback` with a fresh, temporary {@link Scope}. Any user/tag/
559
+ * extra/context/fingerprint/level set on the scope is visible only inside
560
+ * the callback. Pop is automatic (sync, async, throwing).
561
+ */
562
+ withScope<T>(callback: (scope: Scope) => T): T;
563
+ startSpan(operation: string, options?: {
564
+ description?: string;
565
+ tags?: Record<string, string>;
566
+ }): Span;
567
+ getTraceId(): string;
568
+ setTraceId(traceId: string): void;
569
+ getCurrentSpanId(): string | null;
570
+ resetTrace(): void;
571
+ /** Manually instrument an axios instance. No-op when HTTP tracking is off. */
572
+ instrumentAxios<T = any>(axios: T): T;
573
+ getSessionId(): string;
574
+ getConfig(): AllStakConfig | null;
575
+ destroy(): void;
576
+ /** @internal */ _getInstance(): AllStakClient | null;
577
+ };
578
+
579
+ /**
580
+ * Browser navigation breadcrumbs — minimal fallback that doesn't depend on
581
+ * any specific router library. Wraps `history.pushState`/`replaceState` and
582
+ * listens to `popstate` so SPA navigation transitions appear in the
583
+ * breadcrumb feed regardless of which router (React Router, Next, Remix,
584
+ * none) the app uses.
585
+ *
586
+ * Idempotent — calling twice is safe (the wrappers tag themselves).
587
+ *
588
+ * For framework-specific instrumentation (React Router's `useNavigate`,
589
+ * Next's `router.events`), bind manually with `AllStak.addBreadcrumb`.
590
+ */
591
+ type AddBreadcrumbFn$1 = (type: string, msg: string, level?: string, data?: Record<string, unknown>) => void;
592
+ declare function instrumentBrowserNavigation(addBreadcrumb: AddBreadcrumbFn$1): void;
593
+ declare function instrumentReactRouter(location: {
594
+ pathname: string;
595
+ search?: string;
596
+ }, addBreadcrumb?: AddBreadcrumbFn$1): void;
597
+ declare function instrumentNextRouter(url: string, addBreadcrumb?: AddBreadcrumbFn$1): void;
598
+
599
+ /**
600
+ * Idempotent instrumentation of `globalThis.fetch` and `console.warn/error`
601
+ * to feed breadcrumbs into the AllStak client. Safe to call once at init.
602
+ *
603
+ * - `instrumentFetch`: wraps fetch and records a breadcrumb per request
604
+ * (success and failure). Skips requests targeting the SDK's own ingest
605
+ * host so the wrap never recurses. Preserves the original return type
606
+ * and rethrows fetch errors after the breadcrumb is recorded.
607
+ * - `instrumentConsole`: wraps `console.warn` and `console.error` to
608
+ * record `log`-type breadcrumbs at the corresponding level.
609
+ *
610
+ * Both patches use a flag on the wrapper function so a second call is a
611
+ * no-op — important because hot-module-reload in dev would otherwise
612
+ * stack patches and double-fire breadcrumbs.
613
+ */
614
+ type AddBreadcrumbFn = (type: string, msg: string, level?: string, data?: Record<string, unknown>) => void;
615
+ declare function instrumentFetch(addBreadcrumb: AddBreadcrumbFn, ownBaseUrl?: string): void;
616
+ declare function instrumentConsole(addBreadcrumb: AddBreadcrumbFn): void;
617
+
618
+ /**
619
+ * @allstak/react — standalone React SDK.
620
+ *
621
+ * Self-contained: no @allstak/js or @allstak-io/* dependencies. Ships its own
622
+ * AllStak client (init/capture/breadcrumbs/transport) plus React-specific
623
+ * helpers (ErrorBoundary, useAllStak hook, withAllStakProfiler HOC).
624
+ *
625
+ * Usage:
626
+ * AllStak.init({ apiKey, environment, release });
627
+ * <AllStakErrorBoundary>...</AllStakErrorBoundary>
628
+ * const { captureException } = useAllStak();
629
+ */
630
+
631
+ interface AllStakErrorBoundaryProps {
632
+ children: React.ReactNode;
633
+ fallback?: React.ReactNode | ((props: {
634
+ error: Error;
635
+ reset: () => void;
636
+ }) => React.ReactNode);
637
+ /** Extra tags attached only to errors captured by this boundary. */
638
+ tags?: Record<string, string>;
639
+ /** Called after the error has been captured. */
640
+ onError?: (error: Error, info: React.ErrorInfo) => void;
641
+ }
642
+ interface AllStakErrorBoundaryState {
643
+ error: Error | null;
644
+ }
645
+ declare class AllStakErrorBoundary extends React.Component<AllStakErrorBoundaryProps, AllStakErrorBoundaryState> {
646
+ state: AllStakErrorBoundaryState;
647
+ static getDerivedStateFromError(error: Error): AllStakErrorBoundaryState;
648
+ componentDidCatch(error: Error, info: React.ErrorInfo): void;
649
+ private reset;
650
+ render(): React.ReactNode;
651
+ }
652
+ /**
653
+ * Convenience hook — exposes the most common capture/context APIs with a
654
+ * stable identity so components don't have to import the namespace.
655
+ */
656
+ declare function useAllStak(): {
657
+ captureException: (error: Error, ctx?: Record<string, unknown>) => void;
658
+ captureMessage: (msg: string, level?: "fatal" | "error" | "warning" | "info") => void;
659
+ setUser: (user: {
660
+ id?: string;
661
+ email?: string;
662
+ }) => void;
663
+ setTag: (key: string, value: string) => void;
664
+ addBreadcrumb: (type: string, message: string, level?: string, data?: Record<string, unknown>) => void;
665
+ };
666
+ /**
667
+ * HOC: drops a navigation breadcrumb when a component mounts. Useful for
668
+ * marking screen boundaries without a router.
669
+ */
670
+ declare function withAllStakProfiler<P extends object>(Component: React.ComponentType<P>, name?: string): React.FC<P>;
671
+
672
+ export { AllStak, AllStakClient, type AllStakConfig, AllStakErrorBoundary, type AllStakErrorBoundaryProps, type Breadcrumb, type HttpRequestEvent, HttpRequestModule, type HttpTrackingOptions, INGEST_HOST, type ReplayOptions, ReplayRecorder, SDK_NAME, SDK_VERSION, Scope, instrumentBrowserNavigation, instrumentConsole, instrumentFetch, instrumentNextRouter, instrumentReactRouter, useAllStak, withAllStakProfiler };