@cross-deck/web 0.10.0 → 1.0.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/CHANGELOG.md +104 -0
- package/dist/crossdeck.umd.min.js +2 -1
- package/dist/crossdeck.umd.min.js.map +1 -1
- package/dist/error-codes.json +1 -1
- package/dist/index.cjs +680 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +213 -2
- package/dist/index.d.ts +213 -2
- package/dist/index.mjs +680 -5
- package/dist/index.mjs.map +1 -1
- package/dist/react.cjs +680 -5
- package/dist/react.cjs.map +1 -1
- package/dist/react.mjs +680 -5
- package/dist/react.mjs.map +1 -1
- package/dist/vue.cjs +680 -5
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.mjs +680 -5
- package/dist/vue.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -182,6 +182,17 @@ interface AutoTrackOptions {
|
|
|
182
182
|
* (DataDog, Sentry Performance) and don't want duplicates.
|
|
183
183
|
*/
|
|
184
184
|
webVitals: boolean;
|
|
185
|
+
/**
|
|
186
|
+
* Error capture (v1.0.0+) — installs window.onerror +
|
|
187
|
+
* window.onunhandledrejection listeners, wraps fetch + XHR to catch
|
|
188
|
+
* 5xx + network failures, ships each captured error as a Crossdeck
|
|
189
|
+
* event (kind: error.unhandled / error.unhandledrejection /
|
|
190
|
+
* error.handled / error.http / error.message). Errors gate on
|
|
191
|
+
* `consent.errors`. Rate-limited per-fingerprint so a runaway loop
|
|
192
|
+
* can't flood the queue; browser-extension noise filtered by
|
|
193
|
+
* default. Default true in browsers, no-op everywhere else.
|
|
194
|
+
*/
|
|
195
|
+
errors: boolean;
|
|
185
196
|
}
|
|
186
197
|
/** Minimal interface for any pluggable key-value persistence. */
|
|
187
198
|
interface KeyValueStorage {
|
|
@@ -368,6 +379,149 @@ interface ConsentState {
|
|
|
368
379
|
errors: boolean;
|
|
369
380
|
}
|
|
370
381
|
|
|
382
|
+
/**
|
|
383
|
+
* Breadcrumb ring buffer — context attached to every error report.
|
|
384
|
+
*
|
|
385
|
+
* Sentry / Datadog / Bugsnag all ship the same idea: keep a rolling
|
|
386
|
+
* record of the last N "things the user did" (page views, clicks,
|
|
387
|
+
* custom events, network calls, console logs). When an error fires,
|
|
388
|
+
* attach the buffer so the engineer reading the error can see exactly
|
|
389
|
+
* how the user got into the broken state. The single most powerful
|
|
390
|
+
* debugging signal in error monitoring — without breadcrumbs, errors
|
|
391
|
+
* are stack traces with no story.
|
|
392
|
+
*
|
|
393
|
+
* Implementation: a circular buffer with a fixed cap. Old entries are
|
|
394
|
+
* evicted as new ones arrive. The default cap (50) is enough to cover
|
|
395
|
+
* ~5 minutes of typical user activity without ballooning the error
|
|
396
|
+
* payload — Sentry uses 100 by default but the SDK is more aggressive
|
|
397
|
+
* about size since we ship breadcrumbs over the wire with every error,
|
|
398
|
+
* not as a separate batch.
|
|
399
|
+
*
|
|
400
|
+
* Privacy: breadcrumbs auto-emit from the same auto-tracking sources
|
|
401
|
+
* as analytics events (page.viewed, element.clicked). Those already
|
|
402
|
+
* skip password fields, form inputs, and cd-noTrack subtrees. Custom
|
|
403
|
+
* crumbs added via Crossdeck.addBreadcrumb() pass through the same
|
|
404
|
+
* property sanitiser as track() events.
|
|
405
|
+
*/
|
|
406
|
+
type BreadcrumbCategory = "navigation" | "ui.click" | "ui.input" | "http" | "console" | "custom" | "info";
|
|
407
|
+
type BreadcrumbLevel = "debug" | "info" | "warning" | "error";
|
|
408
|
+
interface Breadcrumb {
|
|
409
|
+
/** epoch ms */
|
|
410
|
+
timestamp: number;
|
|
411
|
+
category: BreadcrumbCategory;
|
|
412
|
+
level?: BreadcrumbLevel;
|
|
413
|
+
/** Short human-readable description. */
|
|
414
|
+
message?: string;
|
|
415
|
+
/** Arbitrary key/value context for the crumb. */
|
|
416
|
+
data?: Record<string, unknown>;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Stack-trace parser — normalises Chrome / Firefox / Safari / Edge
|
|
421
|
+
* stack strings into a common frame shape.
|
|
422
|
+
*
|
|
423
|
+
* Why hand-rolled, not stack-trace-js or error-stack-parser libraries:
|
|
424
|
+
* those weigh 5–15 KB after minification and we'd be pulling in their
|
|
425
|
+
* full feature matrix just for the parser. The patterns below cover
|
|
426
|
+
* the four shapes any modern browser emits, totalling ~80 lines.
|
|
427
|
+
*
|
|
428
|
+
* The output frame shape mirrors what Sentry's `mechanism: { type:
|
|
429
|
+
* 'generic' }` events ship, so future source-map symbolication on the
|
|
430
|
+
* Crossdeck backend has a stable input to work against.
|
|
431
|
+
*
|
|
432
|
+
* Defensive: never throws. An unparseable line becomes a `raw` frame
|
|
433
|
+
* with just the literal text. Engineers reading errors still get the
|
|
434
|
+
* raw stack as fallback.
|
|
435
|
+
*/
|
|
436
|
+
interface StackFrame {
|
|
437
|
+
/** Function name, or "?" if anonymous / unparseable. */
|
|
438
|
+
function: string;
|
|
439
|
+
/** Source file URL the frame ran in. Empty when unknown. */
|
|
440
|
+
filename: string;
|
|
441
|
+
/** 1-indexed line number, or 0 when unknown. */
|
|
442
|
+
lineno: number;
|
|
443
|
+
/** 1-indexed column number, or 0 when unknown. */
|
|
444
|
+
colno: number;
|
|
445
|
+
/**
|
|
446
|
+
* True when the frame is in the app's own code (best-effort:
|
|
447
|
+
* detected by URL not starting with chrome-extension://, etc.).
|
|
448
|
+
* Helps the dashboard's "your code vs library code" view.
|
|
449
|
+
*/
|
|
450
|
+
in_app: boolean;
|
|
451
|
+
/** Raw line from the stack string for debugging when parse fails. */
|
|
452
|
+
raw: string;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Error capture — the third Crossdeck USP.
|
|
457
|
+
*
|
|
458
|
+
* Catches every error source the browser can hand us and ships them as
|
|
459
|
+
* Crossdeck events. The pipeline reuses the analytics queue:
|
|
460
|
+
* - Same durable persistence (errors survive crashes / hard closes)
|
|
461
|
+
* - Same exponential backoff (a flapping server doesn't flood
|
|
462
|
+
* errors past the rate limit)
|
|
463
|
+
* - Same Idempotency-Key (duplicate batches dedup server-side)
|
|
464
|
+
* - Same consent gate (consent.errors)
|
|
465
|
+
* - Same PII scrub on properties before they leave
|
|
466
|
+
*
|
|
467
|
+
* Error sources captured (each toggleable):
|
|
468
|
+
* 1. window.onerror — uncaught synchronous errors
|
|
469
|
+
* 2. window.onunhandledrejection — unhandled promise rejections
|
|
470
|
+
* 3. fetch() wrap — HTTP errors the app code didn't catch
|
|
471
|
+
* 4. XMLHttpRequest wrap — same, for legacy XHR consumers
|
|
472
|
+
* 5. Crossdeck.captureError(err) — manual API for try/catch blocks
|
|
473
|
+
* 6. Crossdeck.captureMessage(msg) — non-error events you want to
|
|
474
|
+
* surface as issues (e.g. "we hit the soft-deprecated path")
|
|
475
|
+
*
|
|
476
|
+
* Defensive design rules:
|
|
477
|
+
* - The error handler must NEVER throw — if our own code crashes
|
|
478
|
+
* while reporting an error, we'd take down the host app's error
|
|
479
|
+
* handler too. Every callback is wrapped in try/swallow.
|
|
480
|
+
* - Recursion guard: a `_reporting` flag prevents the SDK from
|
|
481
|
+
* reporting its own errors recursively forever.
|
|
482
|
+
* - Rate limited per-fingerprint: max N reports per second to defend
|
|
483
|
+
* against runaway loops (e.g. an error in setInterval).
|
|
484
|
+
* - Browser-extension noise is filtered by default — those errors
|
|
485
|
+
* aren't the developer's fault and would otherwise drown the
|
|
486
|
+
* signal.
|
|
487
|
+
*/
|
|
488
|
+
|
|
489
|
+
type ErrorLevel = "error" | "warning" | "info";
|
|
490
|
+
interface CapturedError {
|
|
491
|
+
/** When the error fired (epoch ms). */
|
|
492
|
+
timestamp: number;
|
|
493
|
+
/** error.unhandled, error.unhandledrejection, error.handled, error.message, error.http */
|
|
494
|
+
kind: "error.unhandled" | "error.unhandledrejection" | "error.handled" | "error.message" | "error.http";
|
|
495
|
+
level: ErrorLevel;
|
|
496
|
+
message: string;
|
|
497
|
+
/** The error class name when we have it (TypeError, ReferenceError, etc.) */
|
|
498
|
+
errorType: string | null;
|
|
499
|
+
/** Parsed stack frames, empty when unavailable. */
|
|
500
|
+
frames: StackFrame[];
|
|
501
|
+
/** Raw stack string for fallback display. */
|
|
502
|
+
rawStack: string | null;
|
|
503
|
+
/** Origin URL when available (window.onerror's `source` arg). */
|
|
504
|
+
filename: string | null;
|
|
505
|
+
lineno: number | null;
|
|
506
|
+
colno: number | null;
|
|
507
|
+
/** djb2 hash of message + top frames — group identical errors. */
|
|
508
|
+
fingerprint: string;
|
|
509
|
+
/** Snapshot of the breadcrumb buffer at the moment the error fired. */
|
|
510
|
+
breadcrumbs: Breadcrumb[];
|
|
511
|
+
/** Free-form context attached via Crossdeck.setContext(). */
|
|
512
|
+
context: Record<string, unknown>;
|
|
513
|
+
/** Free-form tags attached via Crossdeck.setTag(). */
|
|
514
|
+
tags: Record<string, string>;
|
|
515
|
+
/** "TypeError: x is not a function" → "TypeError" + "x is not a function". */
|
|
516
|
+
/** Whether the error happened during a fetch / XHR. */
|
|
517
|
+
http?: {
|
|
518
|
+
url: string;
|
|
519
|
+
method: string;
|
|
520
|
+
status: number;
|
|
521
|
+
statusText?: string;
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
|
|
371
525
|
/**
|
|
372
526
|
* Public API surface for @cross-deck/web.
|
|
373
527
|
*
|
|
@@ -491,6 +645,63 @@ declare class CrossdeckClient {
|
|
|
491
645
|
consent(state: Partial<ConsentState>): ConsentState;
|
|
492
646
|
/** Snapshot of the current consent state. */
|
|
493
647
|
consentStatus(): ConsentState;
|
|
648
|
+
/**
|
|
649
|
+
* Manually capture an error from a try/catch block.
|
|
650
|
+
*
|
|
651
|
+
* try { …risky… } catch (err) {
|
|
652
|
+
* Crossdeck.captureError(err, { context: { plan: "pro" } });
|
|
653
|
+
* }
|
|
654
|
+
*
|
|
655
|
+
* The error is shipped through the same event queue as analytics
|
|
656
|
+
* (durable, retried, rate-limited per fingerprint). Sends are gated
|
|
657
|
+
* by `consent.errors`. Returns silently — never throws, even if the
|
|
658
|
+
* SDK isn't initialised yet.
|
|
659
|
+
*/
|
|
660
|
+
captureError(error: unknown, options?: {
|
|
661
|
+
context?: Record<string, unknown>;
|
|
662
|
+
tags?: Record<string, string>;
|
|
663
|
+
level?: ErrorLevel;
|
|
664
|
+
}): void;
|
|
665
|
+
/**
|
|
666
|
+
* Capture a non-error event you want to surface as an issue
|
|
667
|
+
* ("deprecated path hit", "we entered the slow code path"). Sentry
|
|
668
|
+
* captureMessage pattern. Returns silently if not initialised.
|
|
669
|
+
*/
|
|
670
|
+
captureMessage(message: string, level?: ErrorLevel): void;
|
|
671
|
+
/**
|
|
672
|
+
* Attach a tag to every subsequent error report. Tags are key/value
|
|
673
|
+
* strings (Sentry pattern): `setTag("flow", "checkout")` → every
|
|
674
|
+
* error from this point on carries `tags.flow === "checkout"`.
|
|
675
|
+
*/
|
|
676
|
+
setTag(key: string, value: string): void;
|
|
677
|
+
/** Bulk-set tags. Merges with existing tags. */
|
|
678
|
+
setTags(tags: Record<string, string>): void;
|
|
679
|
+
/**
|
|
680
|
+
* Attach a structured context blob to every subsequent error report.
|
|
681
|
+
* Unlike tags (flat key/value), context is a named bag of arbitrary
|
|
682
|
+
* data: `setContext("cart", { items: 3, total: 42.99 })`.
|
|
683
|
+
*/
|
|
684
|
+
setContext(name: string, data: Record<string, unknown>): void;
|
|
685
|
+
/**
|
|
686
|
+
* Add a custom breadcrumb to the rolling buffer. Useful for marking
|
|
687
|
+
* domain-meaningful moments ("user opened paywall") that aren't
|
|
688
|
+
* already auto-captured. The buffer caps at 50 entries; old ones
|
|
689
|
+
* evict.
|
|
690
|
+
*/
|
|
691
|
+
addBreadcrumb(crumb: Breadcrumb): void;
|
|
692
|
+
/**
|
|
693
|
+
* Install a pre-send hook for errors. Return null to drop, or a
|
|
694
|
+
* modified CapturedError to scrub / rewrite. Sentry's beforeSend
|
|
695
|
+
* pattern — the only way to redact app-specific PII (auth tokens
|
|
696
|
+
* in URLs, etc.) before the report leaves the browser.
|
|
697
|
+
*/
|
|
698
|
+
setErrorBeforeSend(hook: ((err: CapturedError) => CapturedError | null) | null): void;
|
|
699
|
+
/**
|
|
700
|
+
* Internal: turn a CapturedError into a Crossdeck event and enqueue
|
|
701
|
+
* it. Goes through the same queue / persistence / consent / scrub
|
|
702
|
+
* pipeline as analytics events.
|
|
703
|
+
*/
|
|
704
|
+
private reportError;
|
|
494
705
|
/**
|
|
495
706
|
* GDPR/CCPA "right to be forgotten" — calls the backend's
|
|
496
707
|
* /v1/identity/forget endpoint to schedule a server-side deletion of
|
|
@@ -744,7 +955,7 @@ declare class MemoryStorage implements KeyValueStorage {
|
|
|
744
955
|
* fetch shim, no transitive deps.
|
|
745
956
|
*/
|
|
746
957
|
declare const SDK_NAME = "@cross-deck/web";
|
|
747
|
-
declare const SDK_VERSION = "0.
|
|
958
|
+
declare const SDK_VERSION = "1.0.0";
|
|
748
959
|
declare const DEFAULT_BASE_URL = "https://api.cross-deck.com/v1";
|
|
749
960
|
|
|
750
961
|
/**
|
|
@@ -817,4 +1028,4 @@ interface DeviceInfo {
|
|
|
817
1028
|
appVersion?: string;
|
|
818
1029
|
}
|
|
819
1030
|
|
|
820
|
-
export { type AliasResult, type AuditRail, type AutoTrackOptions, CROSSDECK_ERROR_CODES, type ConsentState, Crossdeck, CrossdeckClient, CrossdeckError, type CrossdeckErrorPayload, type CrossdeckErrorType, type CrossdeckOptions, DEFAULT_BASE_URL, type DeviceInfo, type Diagnostics, type EntitlementsListResponse, type Environment, type ErrorCodeEntry, type EventProperties, type GroupTraits, type HeartbeatResponse, type IdentifyOptions, type KeyValueStorage, MemoryStorage, type Platform, type PublicEntitlement, type PurchaseResult, SDK_NAME, SDK_VERSION, getErrorCode };
|
|
1031
|
+
export { type AliasResult, type AuditRail, type AutoTrackOptions, type Breadcrumb, type BreadcrumbCategory, type BreadcrumbLevel, CROSSDECK_ERROR_CODES, type CapturedError, type ConsentState, Crossdeck, CrossdeckClient, CrossdeckError, type CrossdeckErrorPayload, type CrossdeckErrorType, type CrossdeckOptions, DEFAULT_BASE_URL, type DeviceInfo, type Diagnostics, type EntitlementsListResponse, type Environment, type ErrorCodeEntry, type ErrorLevel, type EventProperties, type GroupTraits, type HeartbeatResponse, type IdentifyOptions, type KeyValueStorage, MemoryStorage, type Platform, type PublicEntitlement, type PurchaseResult, SDK_NAME, SDK_VERSION, type StackFrame, getErrorCode };
|
package/dist/index.d.ts
CHANGED
|
@@ -182,6 +182,17 @@ interface AutoTrackOptions {
|
|
|
182
182
|
* (DataDog, Sentry Performance) and don't want duplicates.
|
|
183
183
|
*/
|
|
184
184
|
webVitals: boolean;
|
|
185
|
+
/**
|
|
186
|
+
* Error capture (v1.0.0+) — installs window.onerror +
|
|
187
|
+
* window.onunhandledrejection listeners, wraps fetch + XHR to catch
|
|
188
|
+
* 5xx + network failures, ships each captured error as a Crossdeck
|
|
189
|
+
* event (kind: error.unhandled / error.unhandledrejection /
|
|
190
|
+
* error.handled / error.http / error.message). Errors gate on
|
|
191
|
+
* `consent.errors`. Rate-limited per-fingerprint so a runaway loop
|
|
192
|
+
* can't flood the queue; browser-extension noise filtered by
|
|
193
|
+
* default. Default true in browsers, no-op everywhere else.
|
|
194
|
+
*/
|
|
195
|
+
errors: boolean;
|
|
185
196
|
}
|
|
186
197
|
/** Minimal interface for any pluggable key-value persistence. */
|
|
187
198
|
interface KeyValueStorage {
|
|
@@ -368,6 +379,149 @@ interface ConsentState {
|
|
|
368
379
|
errors: boolean;
|
|
369
380
|
}
|
|
370
381
|
|
|
382
|
+
/**
|
|
383
|
+
* Breadcrumb ring buffer — context attached to every error report.
|
|
384
|
+
*
|
|
385
|
+
* Sentry / Datadog / Bugsnag all ship the same idea: keep a rolling
|
|
386
|
+
* record of the last N "things the user did" (page views, clicks,
|
|
387
|
+
* custom events, network calls, console logs). When an error fires,
|
|
388
|
+
* attach the buffer so the engineer reading the error can see exactly
|
|
389
|
+
* how the user got into the broken state. The single most powerful
|
|
390
|
+
* debugging signal in error monitoring — without breadcrumbs, errors
|
|
391
|
+
* are stack traces with no story.
|
|
392
|
+
*
|
|
393
|
+
* Implementation: a circular buffer with a fixed cap. Old entries are
|
|
394
|
+
* evicted as new ones arrive. The default cap (50) is enough to cover
|
|
395
|
+
* ~5 minutes of typical user activity without ballooning the error
|
|
396
|
+
* payload — Sentry uses 100 by default but the SDK is more aggressive
|
|
397
|
+
* about size since we ship breadcrumbs over the wire with every error,
|
|
398
|
+
* not as a separate batch.
|
|
399
|
+
*
|
|
400
|
+
* Privacy: breadcrumbs auto-emit from the same auto-tracking sources
|
|
401
|
+
* as analytics events (page.viewed, element.clicked). Those already
|
|
402
|
+
* skip password fields, form inputs, and cd-noTrack subtrees. Custom
|
|
403
|
+
* crumbs added via Crossdeck.addBreadcrumb() pass through the same
|
|
404
|
+
* property sanitiser as track() events.
|
|
405
|
+
*/
|
|
406
|
+
type BreadcrumbCategory = "navigation" | "ui.click" | "ui.input" | "http" | "console" | "custom" | "info";
|
|
407
|
+
type BreadcrumbLevel = "debug" | "info" | "warning" | "error";
|
|
408
|
+
interface Breadcrumb {
|
|
409
|
+
/** epoch ms */
|
|
410
|
+
timestamp: number;
|
|
411
|
+
category: BreadcrumbCategory;
|
|
412
|
+
level?: BreadcrumbLevel;
|
|
413
|
+
/** Short human-readable description. */
|
|
414
|
+
message?: string;
|
|
415
|
+
/** Arbitrary key/value context for the crumb. */
|
|
416
|
+
data?: Record<string, unknown>;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Stack-trace parser — normalises Chrome / Firefox / Safari / Edge
|
|
421
|
+
* stack strings into a common frame shape.
|
|
422
|
+
*
|
|
423
|
+
* Why hand-rolled, not stack-trace-js or error-stack-parser libraries:
|
|
424
|
+
* those weigh 5–15 KB after minification and we'd be pulling in their
|
|
425
|
+
* full feature matrix just for the parser. The patterns below cover
|
|
426
|
+
* the four shapes any modern browser emits, totalling ~80 lines.
|
|
427
|
+
*
|
|
428
|
+
* The output frame shape mirrors what Sentry's `mechanism: { type:
|
|
429
|
+
* 'generic' }` events ship, so future source-map symbolication on the
|
|
430
|
+
* Crossdeck backend has a stable input to work against.
|
|
431
|
+
*
|
|
432
|
+
* Defensive: never throws. An unparseable line becomes a `raw` frame
|
|
433
|
+
* with just the literal text. Engineers reading errors still get the
|
|
434
|
+
* raw stack as fallback.
|
|
435
|
+
*/
|
|
436
|
+
interface StackFrame {
|
|
437
|
+
/** Function name, or "?" if anonymous / unparseable. */
|
|
438
|
+
function: string;
|
|
439
|
+
/** Source file URL the frame ran in. Empty when unknown. */
|
|
440
|
+
filename: string;
|
|
441
|
+
/** 1-indexed line number, or 0 when unknown. */
|
|
442
|
+
lineno: number;
|
|
443
|
+
/** 1-indexed column number, or 0 when unknown. */
|
|
444
|
+
colno: number;
|
|
445
|
+
/**
|
|
446
|
+
* True when the frame is in the app's own code (best-effort:
|
|
447
|
+
* detected by URL not starting with chrome-extension://, etc.).
|
|
448
|
+
* Helps the dashboard's "your code vs library code" view.
|
|
449
|
+
*/
|
|
450
|
+
in_app: boolean;
|
|
451
|
+
/** Raw line from the stack string for debugging when parse fails. */
|
|
452
|
+
raw: string;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Error capture — the third Crossdeck USP.
|
|
457
|
+
*
|
|
458
|
+
* Catches every error source the browser can hand us and ships them as
|
|
459
|
+
* Crossdeck events. The pipeline reuses the analytics queue:
|
|
460
|
+
* - Same durable persistence (errors survive crashes / hard closes)
|
|
461
|
+
* - Same exponential backoff (a flapping server doesn't flood
|
|
462
|
+
* errors past the rate limit)
|
|
463
|
+
* - Same Idempotency-Key (duplicate batches dedup server-side)
|
|
464
|
+
* - Same consent gate (consent.errors)
|
|
465
|
+
* - Same PII scrub on properties before they leave
|
|
466
|
+
*
|
|
467
|
+
* Error sources captured (each toggleable):
|
|
468
|
+
* 1. window.onerror — uncaught synchronous errors
|
|
469
|
+
* 2. window.onunhandledrejection — unhandled promise rejections
|
|
470
|
+
* 3. fetch() wrap — HTTP errors the app code didn't catch
|
|
471
|
+
* 4. XMLHttpRequest wrap — same, for legacy XHR consumers
|
|
472
|
+
* 5. Crossdeck.captureError(err) — manual API for try/catch blocks
|
|
473
|
+
* 6. Crossdeck.captureMessage(msg) — non-error events you want to
|
|
474
|
+
* surface as issues (e.g. "we hit the soft-deprecated path")
|
|
475
|
+
*
|
|
476
|
+
* Defensive design rules:
|
|
477
|
+
* - The error handler must NEVER throw — if our own code crashes
|
|
478
|
+
* while reporting an error, we'd take down the host app's error
|
|
479
|
+
* handler too. Every callback is wrapped in try/swallow.
|
|
480
|
+
* - Recursion guard: a `_reporting` flag prevents the SDK from
|
|
481
|
+
* reporting its own errors recursively forever.
|
|
482
|
+
* - Rate limited per-fingerprint: max N reports per second to defend
|
|
483
|
+
* against runaway loops (e.g. an error in setInterval).
|
|
484
|
+
* - Browser-extension noise is filtered by default — those errors
|
|
485
|
+
* aren't the developer's fault and would otherwise drown the
|
|
486
|
+
* signal.
|
|
487
|
+
*/
|
|
488
|
+
|
|
489
|
+
type ErrorLevel = "error" | "warning" | "info";
|
|
490
|
+
interface CapturedError {
|
|
491
|
+
/** When the error fired (epoch ms). */
|
|
492
|
+
timestamp: number;
|
|
493
|
+
/** error.unhandled, error.unhandledrejection, error.handled, error.message, error.http */
|
|
494
|
+
kind: "error.unhandled" | "error.unhandledrejection" | "error.handled" | "error.message" | "error.http";
|
|
495
|
+
level: ErrorLevel;
|
|
496
|
+
message: string;
|
|
497
|
+
/** The error class name when we have it (TypeError, ReferenceError, etc.) */
|
|
498
|
+
errorType: string | null;
|
|
499
|
+
/** Parsed stack frames, empty when unavailable. */
|
|
500
|
+
frames: StackFrame[];
|
|
501
|
+
/** Raw stack string for fallback display. */
|
|
502
|
+
rawStack: string | null;
|
|
503
|
+
/** Origin URL when available (window.onerror's `source` arg). */
|
|
504
|
+
filename: string | null;
|
|
505
|
+
lineno: number | null;
|
|
506
|
+
colno: number | null;
|
|
507
|
+
/** djb2 hash of message + top frames — group identical errors. */
|
|
508
|
+
fingerprint: string;
|
|
509
|
+
/** Snapshot of the breadcrumb buffer at the moment the error fired. */
|
|
510
|
+
breadcrumbs: Breadcrumb[];
|
|
511
|
+
/** Free-form context attached via Crossdeck.setContext(). */
|
|
512
|
+
context: Record<string, unknown>;
|
|
513
|
+
/** Free-form tags attached via Crossdeck.setTag(). */
|
|
514
|
+
tags: Record<string, string>;
|
|
515
|
+
/** "TypeError: x is not a function" → "TypeError" + "x is not a function". */
|
|
516
|
+
/** Whether the error happened during a fetch / XHR. */
|
|
517
|
+
http?: {
|
|
518
|
+
url: string;
|
|
519
|
+
method: string;
|
|
520
|
+
status: number;
|
|
521
|
+
statusText?: string;
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
|
|
371
525
|
/**
|
|
372
526
|
* Public API surface for @cross-deck/web.
|
|
373
527
|
*
|
|
@@ -491,6 +645,63 @@ declare class CrossdeckClient {
|
|
|
491
645
|
consent(state: Partial<ConsentState>): ConsentState;
|
|
492
646
|
/** Snapshot of the current consent state. */
|
|
493
647
|
consentStatus(): ConsentState;
|
|
648
|
+
/**
|
|
649
|
+
* Manually capture an error from a try/catch block.
|
|
650
|
+
*
|
|
651
|
+
* try { …risky… } catch (err) {
|
|
652
|
+
* Crossdeck.captureError(err, { context: { plan: "pro" } });
|
|
653
|
+
* }
|
|
654
|
+
*
|
|
655
|
+
* The error is shipped through the same event queue as analytics
|
|
656
|
+
* (durable, retried, rate-limited per fingerprint). Sends are gated
|
|
657
|
+
* by `consent.errors`. Returns silently — never throws, even if the
|
|
658
|
+
* SDK isn't initialised yet.
|
|
659
|
+
*/
|
|
660
|
+
captureError(error: unknown, options?: {
|
|
661
|
+
context?: Record<string, unknown>;
|
|
662
|
+
tags?: Record<string, string>;
|
|
663
|
+
level?: ErrorLevel;
|
|
664
|
+
}): void;
|
|
665
|
+
/**
|
|
666
|
+
* Capture a non-error event you want to surface as an issue
|
|
667
|
+
* ("deprecated path hit", "we entered the slow code path"). Sentry
|
|
668
|
+
* captureMessage pattern. Returns silently if not initialised.
|
|
669
|
+
*/
|
|
670
|
+
captureMessage(message: string, level?: ErrorLevel): void;
|
|
671
|
+
/**
|
|
672
|
+
* Attach a tag to every subsequent error report. Tags are key/value
|
|
673
|
+
* strings (Sentry pattern): `setTag("flow", "checkout")` → every
|
|
674
|
+
* error from this point on carries `tags.flow === "checkout"`.
|
|
675
|
+
*/
|
|
676
|
+
setTag(key: string, value: string): void;
|
|
677
|
+
/** Bulk-set tags. Merges with existing tags. */
|
|
678
|
+
setTags(tags: Record<string, string>): void;
|
|
679
|
+
/**
|
|
680
|
+
* Attach a structured context blob to every subsequent error report.
|
|
681
|
+
* Unlike tags (flat key/value), context is a named bag of arbitrary
|
|
682
|
+
* data: `setContext("cart", { items: 3, total: 42.99 })`.
|
|
683
|
+
*/
|
|
684
|
+
setContext(name: string, data: Record<string, unknown>): void;
|
|
685
|
+
/**
|
|
686
|
+
* Add a custom breadcrumb to the rolling buffer. Useful for marking
|
|
687
|
+
* domain-meaningful moments ("user opened paywall") that aren't
|
|
688
|
+
* already auto-captured. The buffer caps at 50 entries; old ones
|
|
689
|
+
* evict.
|
|
690
|
+
*/
|
|
691
|
+
addBreadcrumb(crumb: Breadcrumb): void;
|
|
692
|
+
/**
|
|
693
|
+
* Install a pre-send hook for errors. Return null to drop, or a
|
|
694
|
+
* modified CapturedError to scrub / rewrite. Sentry's beforeSend
|
|
695
|
+
* pattern — the only way to redact app-specific PII (auth tokens
|
|
696
|
+
* in URLs, etc.) before the report leaves the browser.
|
|
697
|
+
*/
|
|
698
|
+
setErrorBeforeSend(hook: ((err: CapturedError) => CapturedError | null) | null): void;
|
|
699
|
+
/**
|
|
700
|
+
* Internal: turn a CapturedError into a Crossdeck event and enqueue
|
|
701
|
+
* it. Goes through the same queue / persistence / consent / scrub
|
|
702
|
+
* pipeline as analytics events.
|
|
703
|
+
*/
|
|
704
|
+
private reportError;
|
|
494
705
|
/**
|
|
495
706
|
* GDPR/CCPA "right to be forgotten" — calls the backend's
|
|
496
707
|
* /v1/identity/forget endpoint to schedule a server-side deletion of
|
|
@@ -744,7 +955,7 @@ declare class MemoryStorage implements KeyValueStorage {
|
|
|
744
955
|
* fetch shim, no transitive deps.
|
|
745
956
|
*/
|
|
746
957
|
declare const SDK_NAME = "@cross-deck/web";
|
|
747
|
-
declare const SDK_VERSION = "0.
|
|
958
|
+
declare const SDK_VERSION = "1.0.0";
|
|
748
959
|
declare const DEFAULT_BASE_URL = "https://api.cross-deck.com/v1";
|
|
749
960
|
|
|
750
961
|
/**
|
|
@@ -817,4 +1028,4 @@ interface DeviceInfo {
|
|
|
817
1028
|
appVersion?: string;
|
|
818
1029
|
}
|
|
819
1030
|
|
|
820
|
-
export { type AliasResult, type AuditRail, type AutoTrackOptions, CROSSDECK_ERROR_CODES, type ConsentState, Crossdeck, CrossdeckClient, CrossdeckError, type CrossdeckErrorPayload, type CrossdeckErrorType, type CrossdeckOptions, DEFAULT_BASE_URL, type DeviceInfo, type Diagnostics, type EntitlementsListResponse, type Environment, type ErrorCodeEntry, type EventProperties, type GroupTraits, type HeartbeatResponse, type IdentifyOptions, type KeyValueStorage, MemoryStorage, type Platform, type PublicEntitlement, type PurchaseResult, SDK_NAME, SDK_VERSION, getErrorCode };
|
|
1031
|
+
export { type AliasResult, type AuditRail, type AutoTrackOptions, type Breadcrumb, type BreadcrumbCategory, type BreadcrumbLevel, CROSSDECK_ERROR_CODES, type CapturedError, type ConsentState, Crossdeck, CrossdeckClient, CrossdeckError, type CrossdeckErrorPayload, type CrossdeckErrorType, type CrossdeckOptions, DEFAULT_BASE_URL, type DeviceInfo, type Diagnostics, type EntitlementsListResponse, type Environment, type ErrorCodeEntry, type ErrorLevel, type EventProperties, type GroupTraits, type HeartbeatResponse, type IdentifyOptions, type KeyValueStorage, MemoryStorage, type Platform, type PublicEntitlement, type PurchaseResult, SDK_NAME, SDK_VERSION, type StackFrame, getErrorCode };
|