@sourav732/error-tracker-js 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +228 -2
  2. package/dist/index.cjs +2 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.mjs +2 -0
  5. package/dist/index.mjs.map +1 -0
  6. package/dist/types/collectors/breadcrumbCollector.d.ts +45 -0
  7. package/dist/types/collectors/collector.d.ts +22 -0
  8. package/dist/types/collectors/cspCollector.d.ts +63 -0
  9. package/dist/types/collectors/errorCollector.d.ts +26 -0
  10. package/dist/types/collectors/httpErrorCollector.d.ts +34 -0
  11. package/dist/types/collectors/jsonResponseCollector.d.ts +24 -0
  12. package/dist/types/collectors/memoryCollector.d.ts +38 -0
  13. package/dist/types/collectors/networkInterceptor.d.ts +54 -0
  14. package/dist/types/collectors/performanceCollector.d.ts +50 -0
  15. package/dist/types/collectors/resourceCollector.d.ts +45 -0
  16. package/dist/types/collectors/responsivenessCollector.d.ts +45 -0
  17. package/dist/types/collectors/screenshotCollector.d.ts +52 -0
  18. package/dist/types/collectors/workerCollector.d.ts +22 -0
  19. package/dist/types/constants.d.ts +108 -0
  20. package/dist/types/core/circularBuffer.d.ts +15 -0
  21. package/dist/types/core/client.d.ts +71 -0
  22. package/dist/types/core/config.d.ts +28 -0
  23. package/dist/types/core/device.d.ts +23 -0
  24. package/dist/types/core/env.d.ts +21 -0
  25. package/dist/types/core/eventFilters.d.ts +32 -0
  26. package/dist/types/core/eventQueue.d.ts +60 -0
  27. package/dist/types/core/logger.d.ts +19 -0
  28. package/dist/types/core/payloadBuilder.d.ts +32 -0
  29. package/dist/types/core/reportedErrors.d.ts +18 -0
  30. package/dist/types/core/retryManager.d.ts +18 -0
  31. package/dist/types/core/safe.d.ts +10 -0
  32. package/dist/types/core/serialize.d.ts +13 -0
  33. package/dist/types/core/stackParser.d.ts +5 -0
  34. package/dist/types/index.d.ts +55 -0
  35. package/dist/types/transport/httpTransport.d.ts +24 -0
  36. package/dist/types/transport/offlineStore.d.ts +33 -0
  37. package/dist/types/types.d.ts +161 -0
  38. package/package.json +62 -4
@@ -0,0 +1,45 @@
1
+ import { Logger } from '../core/logger';
2
+ import { CapturedError, Collector, CollectorSink } from './collector';
3
+ import { NetworkInterceptor } from './networkInterceptor';
4
+ /**
5
+ * Turns a `console.error(...)` call into an error. If one of the arguments is
6
+ * an Error, its own type and stack are used. Returns null when that Error was
7
+ * already reported (frameworks often log errors they have just rethrown).
8
+ */
9
+ export declare function consoleErrorFromArgs(args: unknown[], callStack: string | undefined): CapturedError | null;
10
+ /** Returns true if `el` or an ancestor matches any selector. Invalid selectors are ignored. */
11
+ export declare function isMasked(el: Element, selectors: readonly string[]): boolean;
12
+ /** Short CSS path such as `form#checkout > div.actions > button.primary`. */
13
+ export declare function cssPath(el: Element): string;
14
+ /** Human-readable label for a clicked element, never exposing form values or masked text. */
15
+ export declare function describeElementText(el: Element, maskSelectors: readonly string[]): string;
16
+ /**
17
+ * Records clicks, navigations, page visibility changes, console warnings and
18
+ * errors, and network requests as breadcrumbs.
19
+ */
20
+ export declare class BreadcrumbCollector implements Collector {
21
+ private readonly sink;
22
+ private readonly network;
23
+ private readonly maskSelectors;
24
+ private readonly logger;
25
+ /** Also report `console.error` calls as error events (opt-in). */
26
+ private readonly captureConsoleErrors;
27
+ private installed;
28
+ private lastUrl;
29
+ private originalPushState;
30
+ private originalReplaceState;
31
+ private originalConsole;
32
+ private inConsoleHook;
33
+ private readonly handleClick;
34
+ private readonly handlePopState;
35
+ private readonly handleVisibility;
36
+ constructor(sink: CollectorSink, network: NetworkInterceptor, maskSelectors: readonly string[], logger: Logger,
37
+ /** Also report `console.error` calls as error events (opt-in). */
38
+ captureConsoleErrors?: boolean);
39
+ install(): void;
40
+ uninstall(): void;
41
+ private recordClick;
42
+ private recordNavigation;
43
+ private wrapHistory;
44
+ private wrapConsole;
45
+ }
@@ -0,0 +1,22 @@
1
+ import { BreadcrumbInput, ErrorPayload, JsonObject, StackFrame } from '../types';
2
+ /** Lifecycle shared by every collector. Both methods must be idempotent and never throw. */
3
+ export interface Collector {
4
+ install(): void;
5
+ uninstall(): void;
6
+ }
7
+ /** An error ready to be turned into an event. */
8
+ export interface CapturedError {
9
+ error: ErrorPayload;
10
+ stacktrace: StackFrame[];
11
+ /** Extra details attached as the event's `context` (e.g. CSP directive, request failure kind). */
12
+ context?: JsonObject | null;
13
+ }
14
+ /** Kinds of performance problems that produce their own `performance` event. */
15
+ export type PerformanceIssueKind = 'SlowPageLoad' | 'SlowApiCall' | 'MemoryLeakSuspected' | 'MainThreadBlocked' | 'LowFrameRate';
16
+ /** Callbacks collectors use to hand data to the client. */
17
+ export interface CollectorSink {
18
+ onError(captured: CapturedError): void;
19
+ onBreadcrumb(breadcrumb: BreadcrumbInput): void;
20
+ onPerformanceIssue(kind: PerformanceIssueKind, message: string): void;
21
+ onNavigation(): void;
22
+ }
@@ -0,0 +1,63 @@
1
+ import { Logger } from '../core/logger';
2
+ import { CapturedError, Collector, CollectorSink } from './collector';
3
+ /** The fields shared by `SecurityPolicyViolationEvent` and the Reporting API's CSP report body. */
4
+ export interface CspViolation {
5
+ blocked: string;
6
+ directive: string;
7
+ disposition: string | null;
8
+ sourceFile: string | null;
9
+ lineNumber: number | null;
10
+ columnNumber: number | null;
11
+ }
12
+ /** Reporting API `csp-violation` report body (not in every TypeScript DOM lib). */
13
+ interface CspReportBody {
14
+ blockedURL?: string | null;
15
+ effectiveDirective?: string;
16
+ disposition?: string;
17
+ sourceFile?: string | null;
18
+ lineNumber?: number | null;
19
+ columnNumber?: number | null;
20
+ }
21
+ interface ReportLike {
22
+ type: string;
23
+ body: unknown;
24
+ }
25
+ type ReportingObserverConstructor = new (callback: (reports: ReportLike[]) => void, options: {
26
+ types: string[];
27
+ buffered: boolean;
28
+ }) => {
29
+ observe(): void;
30
+ disconnect(): void;
31
+ };
32
+ export declare function violationFromEvent(event: SecurityPolicyViolationEvent): CspViolation;
33
+ export declare function violationFromReport(body: CspReportBody): CspViolation;
34
+ /** Builds the error for one Content-Security-Policy violation. */
35
+ export declare function cspError(violation: CspViolation): CapturedError;
36
+ /**
37
+ * Reports Content-Security-Policy violations (enforced and report-only),
38
+ * such as a blocked third-party script, an inline script without a nonce or
39
+ * a disallowed `eval`.
40
+ *
41
+ * Where the Reporting API exists (Chromium), a buffered `ReportingObserver`
42
+ * is used: it also delivers violations that happened while the page's HTML
43
+ * was still loading, before the SDK started. Other browsers fall back to the
44
+ * `securitypolicyviolation` event, which only sees violations after init.
45
+ */
46
+ export declare class CspCollector implements Collector {
47
+ private readonly sink;
48
+ private readonly logger;
49
+ private readonly reportingObserver;
50
+ private installed;
51
+ private observer;
52
+ private readonly handleEvent;
53
+ private readonly handleReports;
54
+ constructor(sink: CollectorSink, logger: Logger,
55
+ /**
56
+ * Scripts loaded by the SDK itself (the screenshot library). Violations
57
+ * they cause, e.g. drawing `data:` images under a strict `img-src`, are not the app's problem.
58
+ */
59
+ sdkScriptUrls?: readonly string[], reportingObserver?: ReportingObserverConstructor | null);
60
+ install(): void;
61
+ uninstall(): void;
62
+ }
63
+ export {};
@@ -0,0 +1,26 @@
1
+ import { Logger } from '../core/logger';
2
+ import { CapturedError, Collector, CollectorSink } from './collector';
3
+ /**
4
+ * Converts any thrown value into an error payload plus parsed stack trace.
5
+ * Used for global handlers and for `captureError()`.
6
+ */
7
+ export declare function captureFromThrown(thrown: unknown, handled: boolean, fallbackType?: string): CapturedError;
8
+ /**
9
+ * Captures uncaught exceptions, unhandled promise rejections and failed
10
+ * resource loads (scripts, images, stylesheets).
11
+ *
12
+ * A capture-phase `error` listener is used rather than assigning
13
+ * `window.onerror`: it receives the same ErrorEvent, cannot be overwritten by
14
+ * the host app reassigning `onerror`, and also sees resource load failures,
15
+ * which do not bubble to `onerror`.
16
+ */
17
+ export declare class ErrorCollector implements Collector {
18
+ private readonly sink;
19
+ private installed;
20
+ private readonly handleError;
21
+ private readonly handleRejection;
22
+ constructor(sink: CollectorSink, logger: Logger);
23
+ install(): void;
24
+ uninstall(): void;
25
+ private fromErrorEvent;
26
+ }
@@ -0,0 +1,34 @@
1
+ import { ApiCall } from '../types';
2
+ import { CapturedError, Collector, CollectorSink } from './collector';
3
+ import { NetworkInterceptor, RequestDetails } from './networkInterceptor';
4
+ /** Builds the error for a response with an error status, e.g. `GET /api/cart → 500`. */
5
+ export declare function httpErrorFromCall(call: ApiCall, details?: RequestDetails): CapturedError;
6
+ /** Builds the error for a request that never got a response. */
7
+ export declare function networkErrorFromCall(call: ApiCall, details: RequestDetails): CapturedError;
8
+ export interface HttpErrorOptions {
9
+ /** Report 4xx/5xx responses. */
10
+ httpErrors: boolean;
11
+ /** Report requests that got no response (except user aborts). */
12
+ networkErrors: boolean;
13
+ }
14
+ /**
15
+ * Turns failed fetch/XHR requests into `error` events:
16
+ * - `HttpError` for responses with a 4xx or 5xx status;
17
+ * - `NetworkError` for requests that never got a response (offline, timeout,
18
+ * connection refused, DNS/SSL failure, CORS). Requests the app cancelled
19
+ * itself are not errors and are skipped.
20
+ *
21
+ * Each event's stack trace points at the line of app code that made the request.
22
+ * The rejection value of a failed fetch is marked as reported, so if the app
23
+ * leaves that promise uncaught it is not reported a second time.
24
+ */
25
+ export declare class HttpErrorCollector implements Collector {
26
+ private readonly sink;
27
+ private readonly network;
28
+ private readonly options;
29
+ private installed;
30
+ constructor(sink: CollectorSink, network: NetworkInterceptor, options: HttpErrorOptions);
31
+ install(): void;
32
+ uninstall(): void;
33
+ private handle;
34
+ }
@@ -0,0 +1,24 @@
1
+ import { Logger } from '../core/logger';
2
+ import { CapturedError, Collector, CollectorSink } from './collector';
3
+ /** Builds the error for a response body that could not be parsed as JSON. */
4
+ export declare function invalidJsonError(url: string, status: number, cause: unknown, callStack: string | undefined): CapturedError;
5
+ /**
6
+ * Reports responses whose body is not valid JSON when the app calls
7
+ * `response.json()`, even if the app catches the resulting SyntaxError.
8
+ * A malformed body from an API is a bug on one side or the other, so it is
9
+ * worth knowing about either way.
10
+ *
11
+ * Only parse failures (SyntaxError) are reported; aborted or already-read
12
+ * bodies are left alone. The error object is marked as reported so an
13
+ * uncaught rejection of it is not reported a second time.
14
+ */
15
+ export declare class JsonResponseCollector implements Collector {
16
+ private readonly sink;
17
+ private readonly logger;
18
+ private readonly isSdkUrl;
19
+ private original;
20
+ private patched;
21
+ constructor(sink: CollectorSink, logger: Logger, isSdkUrl: (url: string) => boolean);
22
+ install(): void;
23
+ uninstall(): void;
24
+ }
@@ -0,0 +1,38 @@
1
+ import { Logger } from '../core/logger';
2
+ import { MemoryPayload } from '../types';
3
+ import { Collector, CollectorSink } from './collector';
4
+ /** One heap sample, in bytes. */
5
+ export interface MemoryReading {
6
+ usedBytes: number;
7
+ totalBytes: number;
8
+ }
9
+ /** Reads `performance.memory`, which only Chromium-based browsers provide. */
10
+ export declare function readChromeMemory(): MemoryReading | null;
11
+ /**
12
+ * True when the last N readings grow strictly and the newest is more than
13
+ * the growth threshold above the oldest of the N.
14
+ */
15
+ export declare function isLeakPattern(usedBytes: readonly number[], consecutive?: number, threshold?: number): boolean;
16
+ /**
17
+ * Polls JS heap usage every 30 s and flags a suspected leak when the heap
18
+ * grows by more than 20% across 3 consecutive readings with no navigation in
19
+ * between. Readings reset on every navigation.
20
+ */
21
+ export declare class MemoryCollector implements Collector {
22
+ private readonly sink;
23
+ private readonly read;
24
+ private readonly intervalMs;
25
+ private timer;
26
+ private readings;
27
+ private latest;
28
+ private leakSuspected;
29
+ private readonly poll;
30
+ constructor(sink: CollectorSink, logger: Logger, read?: () => MemoryReading | null, intervalMs?: number);
31
+ install(): void;
32
+ uninstall(): void;
33
+ /** Called on navigation: a new page means a new baseline. */
34
+ resetBaseline(): void;
35
+ /** Takes one reading; exposed for tests. */
36
+ sample(): void;
37
+ snapshot(): MemoryPayload;
38
+ }
@@ -0,0 +1,54 @@
1
+ import { Logger } from '../core/logger';
2
+ import { ApiCall, StackFrame } from '../types';
3
+ import { Collector } from './collector';
4
+ /**
5
+ * Why a request ended without a response.
6
+ * - `offline`: the browser reported no connectivity.
7
+ * - `timeout`: the request timed out (`AbortSignal.timeout()`, `xhr.timeout`).
8
+ * - `aborted`: the app cancelled it (`AbortController.abort()`, `xhr.abort()`).
9
+ * - `network`: anything else the browser hides behind one generic error:
10
+ * connection refused, DNS failure, TLS/SSL failure, CORS rejection.
11
+ */
12
+ export type NetworkFailure = 'offline' | 'timeout' | 'aborted' | 'network';
13
+ /** Extra information about a request, beyond the schema's `ApiCall` fields. */
14
+ export interface RequestDetails {
15
+ /** Set when no HTTP response was received; `null` when one was. */
16
+ failure: NetworkFailure | null;
17
+ /** The value fetch rejected with, when it rejected. */
18
+ error: unknown;
19
+ /** Where in the app the request was made (SDK frames removed). Parsed lazily. */
20
+ callSite(): StackFrame[];
21
+ }
22
+ export type NetworkListener = (call: ApiCall, details: RequestDetails) => void;
23
+ /** Classifies a fetch rejection. */
24
+ export declare function classifyFetchFailure(error: unknown): NetworkFailure;
25
+ /**
26
+ * Wraps `fetch` and `XMLHttpRequest` once and fans each completed request out
27
+ * to listeners (breadcrumbs, performance, HTTP/network errors). Requests to
28
+ * the SDK's own endpoint are ignored. Query strings are stripped from
29
+ * recorded URLs.
30
+ *
31
+ * The wrappers never alter request or response behaviour; listener failures
32
+ * are isolated from the host app's request.
33
+ */
34
+ export declare class NetworkInterceptor implements Collector {
35
+ private readonly logger;
36
+ private listeners;
37
+ private installed;
38
+ private originalFetch;
39
+ private patchedFetch;
40
+ private originalOpen;
41
+ private originalSend;
42
+ private patchedOpen;
43
+ private patchedSend;
44
+ private readonly ignoredUrl;
45
+ constructor(sdkEndpoint: string, logger: Logger);
46
+ subscribe(listener: NetworkListener): void;
47
+ /** True for the SDK's own ingestion endpoint, which must never be tracked. */
48
+ isSdkUrl(rawUrl: string): boolean;
49
+ install(): void;
50
+ uninstall(): void;
51
+ private emit;
52
+ private wrapFetch;
53
+ private wrapXhr;
54
+ }
@@ -0,0 +1,50 @@
1
+ import { Logger } from '../core/logger';
2
+ import { ApiCall, PerformancePayload } from '../types';
3
+ import { Collector, CollectorSink } from './collector';
4
+ import { NetworkInterceptor } from './networkInterceptor';
5
+ /** Raw page timings, already relative to navigation start. */
6
+ export interface PageTimings {
7
+ pageLoadMs: number | null;
8
+ ttfbMs: number | null;
9
+ }
10
+ /** Reads load time and TTFB from Navigation Timing Level 2, falling back to Level 1. */
11
+ export declare function readPageTimings(perf: Performance): PageTimings;
12
+ /** Tracks CLS using the web-vitals "session window" definition. */
13
+ export declare class ClsTracker {
14
+ private sessionValue;
15
+ private sessionStart;
16
+ private sessionLast;
17
+ private max;
18
+ private seen;
19
+ add(value: number, startTime: number, hadRecentInput: boolean): void;
20
+ value(): number | null;
21
+ }
22
+ /**
23
+ * Collects page-load metrics (load time, TTFB, FCP, LCP, CLS) and the duration
24
+ * of every fetch/XHR call. Reports a `performance` event when the page load
25
+ * exceeds 3 s or an API call exceeds 2 s.
26
+ */
27
+ export declare class PerformanceCollector implements Collector {
28
+ private readonly sink;
29
+ private readonly network;
30
+ private readonly logger;
31
+ private installed;
32
+ private metrics;
33
+ private readonly apiCalls;
34
+ private readonly slowApiCalls;
35
+ private readonly cls;
36
+ private observers;
37
+ private lcpFinal;
38
+ private readonly handleLoad;
39
+ private readonly finalizeLcp;
40
+ constructor(sink: CollectorSink, network: NetworkInterceptor, logger: Logger);
41
+ install(): void;
42
+ uninstall(): void;
43
+ /** Current metrics for inclusion in a payload. */
44
+ snapshot(): PerformancePayload;
45
+ /** Records a completed request; exposed so it can be unit-tested without patching fetch. */
46
+ recordApiCall(call: ApiCall): void;
47
+ /** Reads navigation timings; exposed for tests. */
48
+ measurePageLoad(): void;
49
+ private observe;
50
+ }
@@ -0,0 +1,45 @@
1
+ import { Logger } from '../core/logger';
2
+ import { CapturedError, Collector, CollectorSink } from './collector';
3
+ /** A resource timing entry. `responseStatus` is Chromium 109+, so it may be missing at runtime. */
4
+ type ResourceEntryWithStatus = PerformanceEntry & {
5
+ initiatorType: string;
6
+ responseEnd: number;
7
+ responseStatus?: number;
8
+ };
9
+ /** Builds the error for an element resource that failed before the SDK started. */
10
+ export declare function earlyElementResourceError(tag: string, url: string, status: number): CapturedError;
11
+ /** Builds the error for a stylesheet-initiated resource that came back with an error status. */
12
+ export declare function cssResourceError(url: string, status: number): CapturedError;
13
+ /** Builds the error for a web font that failed to load or decode. */
14
+ export declare function fontError(family: string): CapturedError;
15
+ /**
16
+ * Covers resource failures that never fire an element `error` event, so the
17
+ * error collector cannot see them:
18
+ * - **Web fonts** (`@font-face`, `new FontFace()`): via `document.fonts`
19
+ * `loadingerror`, in all modern browsers.
20
+ * - **CSS background images and `@import`ed files** with a 4xx/5xx status:
21
+ * via Resource Timing `responseStatus`.
22
+ * - **`<img>`, `<script>` and `<link>` failures from before the SDK started**
23
+ * (e.g. a broken image in the server-rendered HTML): read from the buffered
24
+ * Resource Timing entries at startup.
25
+ *
26
+ * Resource Timing status is Chromium 109+ only, and only for same-origin
27
+ * resources or ones served with `Timing-Allow-Origin`.
28
+ */
29
+ export declare class ResourceCollector implements Collector {
30
+ private readonly sink;
31
+ private readonly logger;
32
+ private observer;
33
+ private fonts;
34
+ /** performance.now() at install; element failures that finished earlier were missed by the error collector. */
35
+ private installedAt;
36
+ private earlyReported;
37
+ private readonly handleFontError;
38
+ constructor(sink: CollectorSink, logger: Logger);
39
+ install(): void;
40
+ uninstall(): void;
41
+ /** Handles one resource timing entry; exposed for tests. */
42
+ recordResource(entry: ResourceEntryWithStatus): void;
43
+ private observeCssResources;
44
+ }
45
+ export {};
@@ -0,0 +1,45 @@
1
+ import { Logger } from '../core/logger';
2
+ import { Collector, CollectorSink } from './collector';
3
+ export interface ResponsivenessDependencies {
4
+ now?: () => number;
5
+ requestFrame?: (callback: () => void) => void;
6
+ sampleIntervalMs?: number;
7
+ }
8
+ /**
9
+ * Watches main-thread responsiveness:
10
+ * - **Freezes:** uses the Long Tasks API (Chromium browsers only) and reports
11
+ * a `MainThreadBlocked` performance event when one task blocks the page for
12
+ * longer than 1 s. At most one report per 30 s.
13
+ * - **Frame rate:** 5 s after start and then every 30 s, while the page is
14
+ * visible, counts animation frames for 1 s. The latest value fills `performance.frame_rate_fps`, and a
15
+ * sample under 20 fps is reported as `LowFrameRate`.
16
+ *
17
+ * A page stuck in an infinite loop never finishes its task, so it cannot be
18
+ * reported from inside the page.
19
+ */
20
+ export declare class ResponsivenessCollector implements Collector {
21
+ private readonly sink;
22
+ private readonly logger;
23
+ private observer;
24
+ private timer;
25
+ private firstSampleTimer;
26
+ private sampling;
27
+ private fps;
28
+ private lastFreezeReport;
29
+ private lastLowFpsReport;
30
+ private readonly now;
31
+ private readonly requestFrame;
32
+ private readonly sampleIntervalMs;
33
+ private readonly runSample;
34
+ constructor(sink: CollectorSink, logger: Logger, deps?: ResponsivenessDependencies);
35
+ install(): void;
36
+ uninstall(): void;
37
+ /** Latest sampled frame rate, or null if none was measured yet. */
38
+ frameRate(): number | null;
39
+ /** Handles one long task; exposed for tests. */
40
+ recordLongTask(durationMs: number): void;
41
+ /** Counts frames for one sample window; exposed for tests. */
42
+ sampleFrameRate(): void;
43
+ private recordFrameRate;
44
+ private observeLongTasks;
45
+ }
@@ -0,0 +1,52 @@
1
+ import { Logger } from '../core/logger';
2
+ /** The subset of html2canvas options the SDK uses. */
3
+ export interface Html2CanvasOptions {
4
+ logging: boolean;
5
+ useCORS: boolean;
6
+ x: number;
7
+ y: number;
8
+ width: number;
9
+ height: number;
10
+ scale: number;
11
+ onclone: (clonedDocument: Document) => void;
12
+ }
13
+ export type Html2Canvas = (element: HTMLElement, options: Html2CanvasOptions) => Promise<HTMLCanvasElement>;
14
+ export interface ScreenshotOptions {
15
+ maskSelectors: readonly string[];
16
+ libraryUrl: string;
17
+ /** SRI hash for `libraryUrl`; empty string disables the integrity attribute. */
18
+ libraryIntegrity: string;
19
+ }
20
+ /** Returns every element matching any selector. Invalid selectors are skipped. */
21
+ export declare function findMaskedElements(root: ParentNode, selectors: readonly string[]): Element[];
22
+ /**
23
+ * Pre-render masking applied to html2canvas's cloned DOM: masked elements are
24
+ * painted solid black and form values are blanked, so their content never
25
+ * reaches the renderer. The live page is not touched.
26
+ */
27
+ export declare function maskClonedDocument(clone: Document, selectors: readonly string[]): void;
28
+ /**
29
+ * Post-render masking: draws an opaque rectangle over each masked element's
30
+ * on-screen bounds. Belt-and-braces with `maskClonedDocument`.
31
+ */
32
+ export declare function paintMasks(ctx: CanvasRenderingContext2D, elements: Element[], scale: number): void;
33
+ /**
34
+ * Captures the visible viewport as a JPEG data URL using html2canvas, which
35
+ * is loaded from a CDN on first use (it is never bundled with the SDK).
36
+ * Elements matching the mask selectors are blacked out.
37
+ *
38
+ * Screenshots are skipped when the page is hidden, when one was taken in the
39
+ * last 10 s, or when capture takes longer than 3 s.
40
+ */
41
+ export declare class ScreenshotCollector {
42
+ private readonly options;
43
+ private readonly logger;
44
+ private readonly clock;
45
+ private loader;
46
+ private lastCaptureAt;
47
+ constructor(options: ScreenshotOptions, logger: Logger, clock?: () => number);
48
+ /** Resolves to a data URL, or `null` if no screenshot could or should be taken. Never rejects. */
49
+ capture(): Promise<string | null>;
50
+ private render;
51
+ private loadLibrary;
52
+ }
@@ -0,0 +1,22 @@
1
+ import { Logger } from '../core/logger';
2
+ import { CapturedError, Collector, CollectorSink } from './collector';
3
+ /** Builds the error for an `error` event fired on a Worker object. */
4
+ export declare function workerErrorFromEvent(event: Event, workerUrl: string): CapturedError;
5
+ /**
6
+ * Reports uncaught errors inside dedicated Web Workers, and workers that fail
7
+ * to load. Errors inside a worker never reach the page's `window` error
8
+ * handler in every browser, so `window.Worker` is wrapped to attach an
9
+ * `error` listener to each worker the app creates. The returned object is the
10
+ * real Worker, so `instanceof Worker` and all behaviour are unchanged.
11
+ *
12
+ * Service Worker errors are not visible from the page and are not covered.
13
+ */
14
+ export declare class WorkerCollector implements Collector {
15
+ private readonly sink;
16
+ private readonly logger;
17
+ private original;
18
+ private patched;
19
+ constructor(sink: CollectorSink, logger: Logger);
20
+ install(): void;
21
+ uninstall(): void;
22
+ }
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Every tunable number and fixed string used by the SDK lives here.
3
+ * Nothing else in the codebase should contain a bare threshold, timeout or limit.
4
+ */
5
+ export declare const SDK_NAME = "error-tracker-js";
6
+ /** Must match package.json "version" (a test enforces this). */
7
+ export declare const SDK_VERSION = "0.2.0";
8
+ export declare const PLATFORM = "js";
9
+ export declare const DEFAULT_SAMPLE_RATE = 1;
10
+ export declare const DEFAULT_MAX_BREADCRUMBS = 30;
11
+ /** Hard ceiling so a misconfigured app cannot make every payload huge. */
12
+ export declare const MAX_BREADCRUMBS_LIMIT = 100;
13
+ export declare const DEFAULT_ENVIRONMENT = "production";
14
+ export declare const API_KEY_HEADER = "X-API-Key";
15
+ export declare const CONTENT_TYPE_JSON = "application/json";
16
+ export declare const BATCH_SIZE = 10;
17
+ /**
18
+ * Max serialized size of one request. Serverless hosts cap request bodies
19
+ * (Vercel: 4.5 MB); batches are split to stay well below that. A single event
20
+ * larger than this is still sent on its own.
21
+ */
22
+ export declare const MAX_BATCH_BYTES = 1000000;
23
+ /** How long to wait for more events before sending a partial batch. */
24
+ export declare const FLUSH_DELAY_MS = 2000;
25
+ /** Backoff before each retry; length of this array is the retry count. */
26
+ export declare const RETRY_DELAYS_MS: readonly number[];
27
+ export declare const REQUEST_TIMEOUT_MS = 30000;
28
+ /** In-memory queue cap; oldest events are dropped beyond this. */
29
+ export declare const MAX_QUEUE_SIZE = 100;
30
+ export declare const OFFLINE_STORAGE_KEY = "_et_queue";
31
+ /** Persisted queue cap; keeps localStorage usage bounded. */
32
+ export declare const MAX_PERSISTED_EVENTS = 50;
33
+ export declare const HTTP_STATUS_REQUEST_TIMEOUT = 408;
34
+ export declare const HTTP_STATUS_TOO_MANY_REQUESTS = 429;
35
+ export declare const HTTP_STATUS_SERVER_ERROR_MIN = 500;
36
+ export declare const HTTP_STATUS_OK_MIN = 200;
37
+ export declare const HTTP_STATUS_OK_MAX = 299;
38
+ /** Max events accepted per rolling window (error-storm protection). */
39
+ export declare const RATE_LIMIT_MAX_EVENTS = 100;
40
+ export declare const RATE_LIMIT_WINDOW_MS = 60000;
41
+ /** Identical events inside this window are dropped as duplicates. */
42
+ export declare const DEDUP_WINDOW_MS = 5000;
43
+ /** Number of distinct fingerprints remembered for dedup. */
44
+ export declare const DEDUP_MAX_ENTRIES = 200;
45
+ /** Calls made to the public API before init() are buffered up to this count. */
46
+ export declare const MAX_PRE_INIT_CALLS = 100;
47
+ /** How long a reported error's text signature suppresses a second copy of the same failure. */
48
+ export declare const REPORTED_SIGNATURE_TTL_MS = 2000;
49
+ /** After the rate limiter starts dropping, a summary event is sent this long after the first drop. */
50
+ export declare const DROPPED_EVENTS_REPORT_DELAY_MS = 10000;
51
+ export declare const MAX_STACK_FRAMES = 50;
52
+ export declare const MAX_SERIALIZE_DEPTH = 5;
53
+ export declare const MAX_SERIALIZE_KEYS = 50;
54
+ export declare const MAX_STRING_LENGTH = 1000;
55
+ export declare const MAX_MESSAGE_LENGTH = 2000;
56
+ export declare const UNKNOWN_FUNCTION = "<anonymous>";
57
+ export declare const MAX_CLICK_TEXT_LENGTH = 50;
58
+ export declare const MAX_CSS_PATH_DEPTH = 5;
59
+ export declare const MASKED_TEXT = "[masked]";
60
+ export declare const SLOW_PAGE_LOAD_MS = 3000;
61
+ export declare const SLOW_API_CALL_MS = 2000;
62
+ /** Responses at or above this status are reported as HttpError events. */
63
+ export declare const HTTP_ERROR_STATUS_MIN = 400;
64
+ /** Number of most recent API calls attached to every payload. */
65
+ export declare const MAX_API_CALLS_TRACKED = 20;
66
+ /** Delay after window `load` so loadEventEnd is populated. */
67
+ export declare const PAGE_LOAD_SETTLE_MS = 0;
68
+ /** CLS session window rules (per the web-vitals definition). */
69
+ export declare const CLS_SESSION_GAP_MS = 1000;
70
+ export declare const CLS_SESSION_MAX_MS = 5000;
71
+ /** A single main-thread task longer than this is reported as a page freeze. */
72
+ export declare const LONG_TASK_FREEZE_MS = 1000;
73
+ /** Minimum gap between two freeze reports, so a sluggish page cannot flood events. */
74
+ export declare const FREEZE_REPORT_INTERVAL_MS = 30000;
75
+ /** Delay before the first frame-rate sample, so page-load work doesn't skew it. */
76
+ export declare const FPS_FIRST_SAMPLE_DELAY_MS = 5000;
77
+ /** How often the frame rate is sampled while the page is visible. */
78
+ export declare const FPS_SAMPLE_INTERVAL_MS = 30000;
79
+ /** How long each frame-rate sample runs. */
80
+ export declare const FPS_SAMPLE_DURATION_MS = 1000;
81
+ /** Sampled frame rates below this are reported as LowFrameRate. Kept well under 30 fps because low-power modes cap at 30. */
82
+ export declare const LOW_FPS_THRESHOLD = 20;
83
+ export declare const MS_PER_SECOND = 1000;
84
+ export declare const MEMORY_POLL_INTERVAL_MS = 30000;
85
+ export declare const LEAK_CONSECUTIVE_READINGS = 3;
86
+ /** Growth ratio across the consecutive readings that flags a leak (20%). */
87
+ export declare const LEAK_GROWTH_THRESHOLD = 0.2;
88
+ export declare const BYTES_PER_MB: number;
89
+ export declare const DEFAULT_HTML2CANVAS_URL = "https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js";
90
+ /** Subresource-integrity hash of DEFAULT_HTML2CANVAS_URL. */
91
+ export declare const DEFAULT_HTML2CANVAS_INTEGRITY = "sha384-ZZ1pncU3bQe8y31yfZdMFdSpttDoPmOZg2wguVK9almUodir1PghgT0eY7Mrty8H";
92
+ export declare const SCREENSHOT_MIME_TYPE = "image/jpeg";
93
+ export declare const SCREENSHOT_QUALITY = 0.5;
94
+ /** Fallback quality used when the first encode is over the size budget. */
95
+ export declare const SCREENSHOT_FALLBACK_QUALITY = 0.3;
96
+ /** Max base64 length of a screenshot data URL (~750 KB). */
97
+ /** Max base64 length of a screenshot data URL (~370 KB of image; the backend refuses > 400 KB). */
98
+ export declare const MAX_SCREENSHOT_LENGTH = 500000;
99
+ /** Library load + render must finish within this or the event is sent without it. */
100
+ export declare const SCREENSHOT_TIMEOUT_MS = 3000;
101
+ /** At most one screenshot per interval to protect the host app's main thread. */
102
+ export declare const SCREENSHOT_MIN_INTERVAL_MS = 10000;
103
+ export declare const SCREENSHOT_MAX_SCALE = 1;
104
+ /** Screenshots are downscaled so they are at most this many pixels wide. */
105
+ export declare const SCREENSHOT_MAX_WIDTH = 1280;
106
+ export declare const MASK_COLOR = "#000000";
107
+ /** Always masked, in addition to config.maskSelectors. */
108
+ export declare const DEFAULT_MASK_SELECTORS: readonly string[];
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Fixed-capacity FIFO buffer. Once full, each push overwrites the oldest item.
3
+ */
4
+ export declare class CircularBuffer<T> {
5
+ private readonly capacity;
6
+ private readonly items;
7
+ private start;
8
+ private count;
9
+ constructor(capacity: number);
10
+ push(item: T): void;
11
+ /** Items from oldest to newest. */
12
+ toArray(): T[];
13
+ get size(): number;
14
+ clear(): void;
15
+ }