@drakkar.software/sunglasses-core 0.11.0 → 0.13.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.mts +124 -10
- package/dist/index.d.ts +124 -10
- package/dist/index.js +122 -15
- package/dist/index.mjs +119 -14
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -523,9 +523,8 @@ interface ISunglassesTypedClient<T extends EventMap> extends ISunglassesClient {
|
|
|
523
523
|
capture<K extends keyof T & string>(eventName: K, ...args: T[K] extends undefined ? [properties?: Record<string, unknown>] : [properties: T[K]]): void;
|
|
524
524
|
}
|
|
525
525
|
/**
|
|
526
|
-
* Standard properties emitted by error-capturing
|
|
527
|
-
*
|
|
528
|
-
* `@drakkar.software/sunglasses-adapter-posthog`, and `SunglassesErrorBoundary`.
|
|
526
|
+
* Standard properties emitted by error-capturing code as `$error` events.
|
|
527
|
+
* Used by `captureException`, `SunglassesErrorBoundary`, and `autoCaptureErrors`.
|
|
529
528
|
*/
|
|
530
529
|
interface ErrorEventProperties {
|
|
531
530
|
$error_message: string;
|
|
@@ -534,8 +533,42 @@ interface ErrorEventProperties {
|
|
|
534
533
|
$error_handled: boolean;
|
|
535
534
|
/** Sentry-compatible severity level. Usually `'error'`. */
|
|
536
535
|
$error_level: string;
|
|
537
|
-
/**
|
|
536
|
+
/** Stringified stack trace (trimmed to `maxStackFrames`). On by default. */
|
|
538
537
|
$error_stack?: string;
|
|
538
|
+
/**
|
|
539
|
+
* React component stack from `errorInfo.componentStack` (boundaries only).
|
|
540
|
+
* Populated when the error is caught by a `SunglassesErrorBoundary` or
|
|
541
|
+
* `SunglassesGlobalErrorBoundary`.
|
|
542
|
+
*/
|
|
543
|
+
$error_component_stack?: string;
|
|
544
|
+
/**
|
|
545
|
+
* Serialized `error.cause` chain — each link formatted as `"Name: message"`,
|
|
546
|
+
* joined by `"\ncaused by: "`, depth-capped at 3 levels.
|
|
547
|
+
*/
|
|
548
|
+
$error_cause?: string;
|
|
549
|
+
/**
|
|
550
|
+
* Custom enumerable properties on the Error object beyond the standard
|
|
551
|
+
* `message / name / stack / cause` keys (e.g. `code`, `statusCode`).
|
|
552
|
+
* Scalar values only (string/number/boolean); nested objects are skipped.
|
|
553
|
+
*/
|
|
554
|
+
$error_extra?: Record<string, unknown>;
|
|
555
|
+
/**
|
|
556
|
+
* Whether the error was fatal (React Native `ErrorUtils` `isFatal` only).
|
|
557
|
+
* Absent on web.
|
|
558
|
+
*/
|
|
559
|
+
$error_fatal?: boolean;
|
|
560
|
+
/**
|
|
561
|
+
* Where the error was captured: `'boundary'` (error boundary / component
|
|
562
|
+
* `componentDidCatch`), `'global'` (platform global handler), `'rejection'`
|
|
563
|
+
* (unhandled promise), or `'console'` (console patching).
|
|
564
|
+
*/
|
|
565
|
+
$error_source?: string;
|
|
566
|
+
/** Source filename for web `window 'error'` events (`ErrorEvent.filename`). */
|
|
567
|
+
$error_filename?: string;
|
|
568
|
+
/** Source line number for web `window 'error'` events (`ErrorEvent.lineno`). */
|
|
569
|
+
$error_line?: number;
|
|
570
|
+
/** Source column number for web `window 'error'` events (`ErrorEvent.colno`). */
|
|
571
|
+
$error_column?: number;
|
|
539
572
|
/** Allows adapter-specific extension properties (e.g. from `beforeCapture`). */
|
|
540
573
|
[key: string]: unknown;
|
|
541
574
|
}
|
|
@@ -677,7 +710,14 @@ declare class PiiSanitizer implements IMiddleware {
|
|
|
677
710
|
* - Recurse into nested objects and arrays
|
|
678
711
|
*/
|
|
679
712
|
private deepSanitizeValues;
|
|
680
|
-
|
|
713
|
+
/**
|
|
714
|
+
* Replace every PII match in `value` with `'[redacted]'`, preserving the
|
|
715
|
+
* surrounding text. This is safer than whole-value redaction for stack traces
|
|
716
|
+
* and error messages that may contain PII alongside non-sensitive context.
|
|
717
|
+
*
|
|
718
|
+
* Each pattern must have the `g` (global) flag so all occurrences are replaced.
|
|
719
|
+
*/
|
|
720
|
+
private maskPiiSubstrings;
|
|
681
721
|
}
|
|
682
722
|
|
|
683
723
|
interface Logger {
|
|
@@ -1149,8 +1189,9 @@ interface CaptureExceptionOptions {
|
|
|
1149
1189
|
/** Sentry-compatible severity level. Default: `'error'`. */
|
|
1150
1190
|
level?: string;
|
|
1151
1191
|
/**
|
|
1152
|
-
* Include the stack trace in `$error_stack`. Default: `
|
|
1153
|
-
* Stack traces may expose internal file paths and function names
|
|
1192
|
+
* Include the stack trace in `$error_stack`. Default: `true`.
|
|
1193
|
+
* Stack traces may expose internal file paths and function names; set to
|
|
1194
|
+
* `false` to disable if your privacy policy requires it.
|
|
1154
1195
|
*/
|
|
1155
1196
|
includeStack?: boolean;
|
|
1156
1197
|
/**
|
|
@@ -1179,6 +1220,37 @@ interface CaptureExceptionOptions {
|
|
|
1179
1220
|
* object to capture, or `null` to skip capture entirely.
|
|
1180
1221
|
*/
|
|
1181
1222
|
beforeCapture?: (props: ErrorEventProperties) => Record<string, unknown> | null;
|
|
1223
|
+
/**
|
|
1224
|
+
* Drop errors with the same fingerprint (name + message + first stack frame)
|
|
1225
|
+
* captured within {@link dedupeWindowMs}. This collapses the common
|
|
1226
|
+
* double-capture cases — e.g. an error boundary plus `console.error` capture
|
|
1227
|
+
* reporting the same render error, or a global handler firing repeatedly for
|
|
1228
|
+
* the same throw. The fingerprint deliberately ignores the `handled` flag and
|
|
1229
|
+
* `$error_source`, so the first capture wins. Default: `true`.
|
|
1230
|
+
*/
|
|
1231
|
+
dedupe?: boolean;
|
|
1232
|
+
/**
|
|
1233
|
+
* Time window (ms) used by {@link dedupe}. Identical errors within this window
|
|
1234
|
+
* are dropped. Default: `1000`.
|
|
1235
|
+
*/
|
|
1236
|
+
dedupeWindowMs?: number;
|
|
1237
|
+
/**
|
|
1238
|
+
* React component stack from `errorInfo.componentStack`, set by error
|
|
1239
|
+
* boundaries. Emitted as `$error_component_stack`. Framework-set — takes
|
|
1240
|
+
* precedence over any value in `properties`.
|
|
1241
|
+
*/
|
|
1242
|
+
componentStack?: string;
|
|
1243
|
+
/**
|
|
1244
|
+
* Whether the error was fatal (React Native `ErrorUtils` `isFatal`).
|
|
1245
|
+
* Emitted as `$error_fatal`. Framework-set — takes precedence over `properties`.
|
|
1246
|
+
*/
|
|
1247
|
+
fatal?: boolean;
|
|
1248
|
+
/**
|
|
1249
|
+
* Origin of the capture: `'boundary'`, `'global'`, `'rejection'`, or
|
|
1250
|
+
* `'console'`. Emitted as `$error_source`. Framework-set — takes precedence
|
|
1251
|
+
* over any value in `properties`.
|
|
1252
|
+
*/
|
|
1253
|
+
source?: string;
|
|
1182
1254
|
}
|
|
1183
1255
|
/**
|
|
1184
1256
|
* Normalize any thrown value into a SunGlasses `$error` event and capture it
|
|
@@ -1230,10 +1302,15 @@ interface ConsoleCaptureOptions {
|
|
|
1230
1302
|
*/
|
|
1231
1303
|
interface AutoCaptureErrorsOptions extends CaptureExceptionOptions {
|
|
1232
1304
|
/**
|
|
1233
|
-
* Install the platform
|
|
1234
|
-
*
|
|
1305
|
+
* Install the platform uncaught-error handlers (web `window` `'error'`,
|
|
1306
|
+
* React Native `ErrorUtils`). Default: `true`.
|
|
1235
1307
|
*/
|
|
1236
1308
|
globalHandlers?: boolean;
|
|
1309
|
+
/**
|
|
1310
|
+
* Capture unhandled promise rejections (web `window` `'unhandledrejection'`,
|
|
1311
|
+
* React Native engine-specific rejection tracking). Default: `true`.
|
|
1312
|
+
*/
|
|
1313
|
+
unhandledRejections?: boolean;
|
|
1237
1314
|
/**
|
|
1238
1315
|
* Also capture console output as `$error` events. `true` captures
|
|
1239
1316
|
* `console.error`; pass {@link ConsoleCaptureOptions} to configure levels.
|
|
@@ -1268,6 +1345,43 @@ interface AutoCaptureErrorsOptions extends CaptureExceptionOptions {
|
|
|
1268
1345
|
*/
|
|
1269
1346
|
declare function patchConsole(client: ISunglassesClient, options?: ConsoleCaptureOptions): () => void;
|
|
1270
1347
|
|
|
1348
|
+
/**
|
|
1349
|
+
* Describes a global (non-render) error surfaced by a platform global handler.
|
|
1350
|
+
* Published by the providers' auto-capture handlers and consumed by
|
|
1351
|
+
* `SunglassesGlobalErrorBoundary` to decide whether to render its fallback UI.
|
|
1352
|
+
*
|
|
1353
|
+
* The raw `error` reference is forwarded only to in-process subscribers; nothing
|
|
1354
|
+
* is persisted, logged, or sent anywhere by the bus itself.
|
|
1355
|
+
*/
|
|
1356
|
+
interface GlobalErrorInfo {
|
|
1357
|
+
/** The thrown value (an `Error`, string, or arbitrary object). */
|
|
1358
|
+
error: unknown;
|
|
1359
|
+
/**
|
|
1360
|
+
* Whether the runtime considered the error fatal. Uncaught errors are fatal
|
|
1361
|
+
* unless the platform reports otherwise; unhandled promise rejections are
|
|
1362
|
+
* non-fatal.
|
|
1363
|
+
*/
|
|
1364
|
+
fatal: boolean;
|
|
1365
|
+
/** Whether the error came from an uncaught error or an unhandled rejection. */
|
|
1366
|
+
kind: 'error' | 'rejection';
|
|
1367
|
+
}
|
|
1368
|
+
/** A subscriber notified for every published {@link GlobalErrorInfo}. */
|
|
1369
|
+
type GlobalErrorListener = (info: GlobalErrorInfo) => void;
|
|
1370
|
+
/**
|
|
1371
|
+
* Publish a global error to all current subscribers. Subscriber errors are
|
|
1372
|
+
* swallowed so one faulty listener cannot break others or the caller.
|
|
1373
|
+
*
|
|
1374
|
+
* @param info - The global error descriptor.
|
|
1375
|
+
*/
|
|
1376
|
+
declare function publishGlobalError(info: GlobalErrorInfo): void;
|
|
1377
|
+
/**
|
|
1378
|
+
* Subscribe to global errors published via {@link publishGlobalError}.
|
|
1379
|
+
*
|
|
1380
|
+
* @param listener - Called for each published error.
|
|
1381
|
+
* @returns An unsubscribe function.
|
|
1382
|
+
*/
|
|
1383
|
+
declare function subscribeGlobalError(listener: GlobalErrorListener): () => void;
|
|
1384
|
+
|
|
1271
1385
|
/**
|
|
1272
1386
|
* A typed analytics stub that is safe to use before the SDK initialises.
|
|
1273
1387
|
*
|
|
@@ -1340,4 +1454,4 @@ declare function sha256Hex(input: string): Promise<string>;
|
|
|
1340
1454
|
*/
|
|
1341
1455
|
declare function nowISO(): string;
|
|
1342
1456
|
|
|
1343
|
-
export { type AppMetadata, type AppUpdateInfo, type AutoCaptureErrorsOptions, type CaptureExceptionOptions, type CleanupConfig, type ConsentHistoryEntry, ConsentManager, type ConsentState, type ConsentStatus, type ConsoleCaptureOptions, type ConsoleLevel, type ErrorEventProperties, type EventContext, type EventCountPeriod, EventCounter, type EventMap, EventQueue, type EventType, FrequencyMiddleware, type FrequencyMiddlewareOptions, type HttpAdapterConfig, type IAnalyticsAdapter, type IEventCounter, type IMiddleware, type IStorageAdapter, type ISunglassesClient, type ISunglassesTypedClient, IdentityManager, type IdentityState, LocalEventArchive, type Logger, type MiddlewareNext, MiddlewarePipeline, PiiSanitizer, SamplingMiddleware, type SamplingMiddlewareOptions, type ScreenTrackingOptions, SessionManager, type SessionState, type SunglassesConfig, SunglassesCore, type SunglassesEvent, TraitManager, type UserDataExport, asTyped, captureException, createLazyClient, createLogger, generateUUID, nowISO, patchConsole, sha256Hex };
|
|
1457
|
+
export { type AppMetadata, type AppUpdateInfo, type AutoCaptureErrorsOptions, type CaptureExceptionOptions, type CleanupConfig, type ConsentHistoryEntry, ConsentManager, type ConsentState, type ConsentStatus, type ConsoleCaptureOptions, type ConsoleLevel, type ErrorEventProperties, type EventContext, type EventCountPeriod, EventCounter, type EventMap, EventQueue, type EventType, FrequencyMiddleware, type FrequencyMiddlewareOptions, type GlobalErrorInfo, type GlobalErrorListener, type HttpAdapterConfig, type IAnalyticsAdapter, type IEventCounter, type IMiddleware, type IStorageAdapter, type ISunglassesClient, type ISunglassesTypedClient, IdentityManager, type IdentityState, LocalEventArchive, type Logger, type MiddlewareNext, MiddlewarePipeline, PiiSanitizer, SamplingMiddleware, type SamplingMiddlewareOptions, type ScreenTrackingOptions, SessionManager, type SessionState, type SunglassesConfig, SunglassesCore, type SunglassesEvent, TraitManager, type UserDataExport, asTyped, captureException, createLazyClient, createLogger, generateUUID, nowISO, patchConsole, publishGlobalError, sha256Hex, subscribeGlobalError };
|
package/dist/index.d.ts
CHANGED
|
@@ -523,9 +523,8 @@ interface ISunglassesTypedClient<T extends EventMap> extends ISunglassesClient {
|
|
|
523
523
|
capture<K extends keyof T & string>(eventName: K, ...args: T[K] extends undefined ? [properties?: Record<string, unknown>] : [properties: T[K]]): void;
|
|
524
524
|
}
|
|
525
525
|
/**
|
|
526
|
-
* Standard properties emitted by error-capturing
|
|
527
|
-
*
|
|
528
|
-
* `@drakkar.software/sunglasses-adapter-posthog`, and `SunglassesErrorBoundary`.
|
|
526
|
+
* Standard properties emitted by error-capturing code as `$error` events.
|
|
527
|
+
* Used by `captureException`, `SunglassesErrorBoundary`, and `autoCaptureErrors`.
|
|
529
528
|
*/
|
|
530
529
|
interface ErrorEventProperties {
|
|
531
530
|
$error_message: string;
|
|
@@ -534,8 +533,42 @@ interface ErrorEventProperties {
|
|
|
534
533
|
$error_handled: boolean;
|
|
535
534
|
/** Sentry-compatible severity level. Usually `'error'`. */
|
|
536
535
|
$error_level: string;
|
|
537
|
-
/**
|
|
536
|
+
/** Stringified stack trace (trimmed to `maxStackFrames`). On by default. */
|
|
538
537
|
$error_stack?: string;
|
|
538
|
+
/**
|
|
539
|
+
* React component stack from `errorInfo.componentStack` (boundaries only).
|
|
540
|
+
* Populated when the error is caught by a `SunglassesErrorBoundary` or
|
|
541
|
+
* `SunglassesGlobalErrorBoundary`.
|
|
542
|
+
*/
|
|
543
|
+
$error_component_stack?: string;
|
|
544
|
+
/**
|
|
545
|
+
* Serialized `error.cause` chain — each link formatted as `"Name: message"`,
|
|
546
|
+
* joined by `"\ncaused by: "`, depth-capped at 3 levels.
|
|
547
|
+
*/
|
|
548
|
+
$error_cause?: string;
|
|
549
|
+
/**
|
|
550
|
+
* Custom enumerable properties on the Error object beyond the standard
|
|
551
|
+
* `message / name / stack / cause` keys (e.g. `code`, `statusCode`).
|
|
552
|
+
* Scalar values only (string/number/boolean); nested objects are skipped.
|
|
553
|
+
*/
|
|
554
|
+
$error_extra?: Record<string, unknown>;
|
|
555
|
+
/**
|
|
556
|
+
* Whether the error was fatal (React Native `ErrorUtils` `isFatal` only).
|
|
557
|
+
* Absent on web.
|
|
558
|
+
*/
|
|
559
|
+
$error_fatal?: boolean;
|
|
560
|
+
/**
|
|
561
|
+
* Where the error was captured: `'boundary'` (error boundary / component
|
|
562
|
+
* `componentDidCatch`), `'global'` (platform global handler), `'rejection'`
|
|
563
|
+
* (unhandled promise), or `'console'` (console patching).
|
|
564
|
+
*/
|
|
565
|
+
$error_source?: string;
|
|
566
|
+
/** Source filename for web `window 'error'` events (`ErrorEvent.filename`). */
|
|
567
|
+
$error_filename?: string;
|
|
568
|
+
/** Source line number for web `window 'error'` events (`ErrorEvent.lineno`). */
|
|
569
|
+
$error_line?: number;
|
|
570
|
+
/** Source column number for web `window 'error'` events (`ErrorEvent.colno`). */
|
|
571
|
+
$error_column?: number;
|
|
539
572
|
/** Allows adapter-specific extension properties (e.g. from `beforeCapture`). */
|
|
540
573
|
[key: string]: unknown;
|
|
541
574
|
}
|
|
@@ -677,7 +710,14 @@ declare class PiiSanitizer implements IMiddleware {
|
|
|
677
710
|
* - Recurse into nested objects and arrays
|
|
678
711
|
*/
|
|
679
712
|
private deepSanitizeValues;
|
|
680
|
-
|
|
713
|
+
/**
|
|
714
|
+
* Replace every PII match in `value` with `'[redacted]'`, preserving the
|
|
715
|
+
* surrounding text. This is safer than whole-value redaction for stack traces
|
|
716
|
+
* and error messages that may contain PII alongside non-sensitive context.
|
|
717
|
+
*
|
|
718
|
+
* Each pattern must have the `g` (global) flag so all occurrences are replaced.
|
|
719
|
+
*/
|
|
720
|
+
private maskPiiSubstrings;
|
|
681
721
|
}
|
|
682
722
|
|
|
683
723
|
interface Logger {
|
|
@@ -1149,8 +1189,9 @@ interface CaptureExceptionOptions {
|
|
|
1149
1189
|
/** Sentry-compatible severity level. Default: `'error'`. */
|
|
1150
1190
|
level?: string;
|
|
1151
1191
|
/**
|
|
1152
|
-
* Include the stack trace in `$error_stack`. Default: `
|
|
1153
|
-
* Stack traces may expose internal file paths and function names
|
|
1192
|
+
* Include the stack trace in `$error_stack`. Default: `true`.
|
|
1193
|
+
* Stack traces may expose internal file paths and function names; set to
|
|
1194
|
+
* `false` to disable if your privacy policy requires it.
|
|
1154
1195
|
*/
|
|
1155
1196
|
includeStack?: boolean;
|
|
1156
1197
|
/**
|
|
@@ -1179,6 +1220,37 @@ interface CaptureExceptionOptions {
|
|
|
1179
1220
|
* object to capture, or `null` to skip capture entirely.
|
|
1180
1221
|
*/
|
|
1181
1222
|
beforeCapture?: (props: ErrorEventProperties) => Record<string, unknown> | null;
|
|
1223
|
+
/**
|
|
1224
|
+
* Drop errors with the same fingerprint (name + message + first stack frame)
|
|
1225
|
+
* captured within {@link dedupeWindowMs}. This collapses the common
|
|
1226
|
+
* double-capture cases — e.g. an error boundary plus `console.error` capture
|
|
1227
|
+
* reporting the same render error, or a global handler firing repeatedly for
|
|
1228
|
+
* the same throw. The fingerprint deliberately ignores the `handled` flag and
|
|
1229
|
+
* `$error_source`, so the first capture wins. Default: `true`.
|
|
1230
|
+
*/
|
|
1231
|
+
dedupe?: boolean;
|
|
1232
|
+
/**
|
|
1233
|
+
* Time window (ms) used by {@link dedupe}. Identical errors within this window
|
|
1234
|
+
* are dropped. Default: `1000`.
|
|
1235
|
+
*/
|
|
1236
|
+
dedupeWindowMs?: number;
|
|
1237
|
+
/**
|
|
1238
|
+
* React component stack from `errorInfo.componentStack`, set by error
|
|
1239
|
+
* boundaries. Emitted as `$error_component_stack`. Framework-set — takes
|
|
1240
|
+
* precedence over any value in `properties`.
|
|
1241
|
+
*/
|
|
1242
|
+
componentStack?: string;
|
|
1243
|
+
/**
|
|
1244
|
+
* Whether the error was fatal (React Native `ErrorUtils` `isFatal`).
|
|
1245
|
+
* Emitted as `$error_fatal`. Framework-set — takes precedence over `properties`.
|
|
1246
|
+
*/
|
|
1247
|
+
fatal?: boolean;
|
|
1248
|
+
/**
|
|
1249
|
+
* Origin of the capture: `'boundary'`, `'global'`, `'rejection'`, or
|
|
1250
|
+
* `'console'`. Emitted as `$error_source`. Framework-set — takes precedence
|
|
1251
|
+
* over any value in `properties`.
|
|
1252
|
+
*/
|
|
1253
|
+
source?: string;
|
|
1182
1254
|
}
|
|
1183
1255
|
/**
|
|
1184
1256
|
* Normalize any thrown value into a SunGlasses `$error` event and capture it
|
|
@@ -1230,10 +1302,15 @@ interface ConsoleCaptureOptions {
|
|
|
1230
1302
|
*/
|
|
1231
1303
|
interface AutoCaptureErrorsOptions extends CaptureExceptionOptions {
|
|
1232
1304
|
/**
|
|
1233
|
-
* Install the platform
|
|
1234
|
-
*
|
|
1305
|
+
* Install the platform uncaught-error handlers (web `window` `'error'`,
|
|
1306
|
+
* React Native `ErrorUtils`). Default: `true`.
|
|
1235
1307
|
*/
|
|
1236
1308
|
globalHandlers?: boolean;
|
|
1309
|
+
/**
|
|
1310
|
+
* Capture unhandled promise rejections (web `window` `'unhandledrejection'`,
|
|
1311
|
+
* React Native engine-specific rejection tracking). Default: `true`.
|
|
1312
|
+
*/
|
|
1313
|
+
unhandledRejections?: boolean;
|
|
1237
1314
|
/**
|
|
1238
1315
|
* Also capture console output as `$error` events. `true` captures
|
|
1239
1316
|
* `console.error`; pass {@link ConsoleCaptureOptions} to configure levels.
|
|
@@ -1268,6 +1345,43 @@ interface AutoCaptureErrorsOptions extends CaptureExceptionOptions {
|
|
|
1268
1345
|
*/
|
|
1269
1346
|
declare function patchConsole(client: ISunglassesClient, options?: ConsoleCaptureOptions): () => void;
|
|
1270
1347
|
|
|
1348
|
+
/**
|
|
1349
|
+
* Describes a global (non-render) error surfaced by a platform global handler.
|
|
1350
|
+
* Published by the providers' auto-capture handlers and consumed by
|
|
1351
|
+
* `SunglassesGlobalErrorBoundary` to decide whether to render its fallback UI.
|
|
1352
|
+
*
|
|
1353
|
+
* The raw `error` reference is forwarded only to in-process subscribers; nothing
|
|
1354
|
+
* is persisted, logged, or sent anywhere by the bus itself.
|
|
1355
|
+
*/
|
|
1356
|
+
interface GlobalErrorInfo {
|
|
1357
|
+
/** The thrown value (an `Error`, string, or arbitrary object). */
|
|
1358
|
+
error: unknown;
|
|
1359
|
+
/**
|
|
1360
|
+
* Whether the runtime considered the error fatal. Uncaught errors are fatal
|
|
1361
|
+
* unless the platform reports otherwise; unhandled promise rejections are
|
|
1362
|
+
* non-fatal.
|
|
1363
|
+
*/
|
|
1364
|
+
fatal: boolean;
|
|
1365
|
+
/** Whether the error came from an uncaught error or an unhandled rejection. */
|
|
1366
|
+
kind: 'error' | 'rejection';
|
|
1367
|
+
}
|
|
1368
|
+
/** A subscriber notified for every published {@link GlobalErrorInfo}. */
|
|
1369
|
+
type GlobalErrorListener = (info: GlobalErrorInfo) => void;
|
|
1370
|
+
/**
|
|
1371
|
+
* Publish a global error to all current subscribers. Subscriber errors are
|
|
1372
|
+
* swallowed so one faulty listener cannot break others or the caller.
|
|
1373
|
+
*
|
|
1374
|
+
* @param info - The global error descriptor.
|
|
1375
|
+
*/
|
|
1376
|
+
declare function publishGlobalError(info: GlobalErrorInfo): void;
|
|
1377
|
+
/**
|
|
1378
|
+
* Subscribe to global errors published via {@link publishGlobalError}.
|
|
1379
|
+
*
|
|
1380
|
+
* @param listener - Called for each published error.
|
|
1381
|
+
* @returns An unsubscribe function.
|
|
1382
|
+
*/
|
|
1383
|
+
declare function subscribeGlobalError(listener: GlobalErrorListener): () => void;
|
|
1384
|
+
|
|
1271
1385
|
/**
|
|
1272
1386
|
* A typed analytics stub that is safe to use before the SDK initialises.
|
|
1273
1387
|
*
|
|
@@ -1340,4 +1454,4 @@ declare function sha256Hex(input: string): Promise<string>;
|
|
|
1340
1454
|
*/
|
|
1341
1455
|
declare function nowISO(): string;
|
|
1342
1456
|
|
|
1343
|
-
export { type AppMetadata, type AppUpdateInfo, type AutoCaptureErrorsOptions, type CaptureExceptionOptions, type CleanupConfig, type ConsentHistoryEntry, ConsentManager, type ConsentState, type ConsentStatus, type ConsoleCaptureOptions, type ConsoleLevel, type ErrorEventProperties, type EventContext, type EventCountPeriod, EventCounter, type EventMap, EventQueue, type EventType, FrequencyMiddleware, type FrequencyMiddlewareOptions, type HttpAdapterConfig, type IAnalyticsAdapter, type IEventCounter, type IMiddleware, type IStorageAdapter, type ISunglassesClient, type ISunglassesTypedClient, IdentityManager, type IdentityState, LocalEventArchive, type Logger, type MiddlewareNext, MiddlewarePipeline, PiiSanitizer, SamplingMiddleware, type SamplingMiddlewareOptions, type ScreenTrackingOptions, SessionManager, type SessionState, type SunglassesConfig, SunglassesCore, type SunglassesEvent, TraitManager, type UserDataExport, asTyped, captureException, createLazyClient, createLogger, generateUUID, nowISO, patchConsole, sha256Hex };
|
|
1457
|
+
export { type AppMetadata, type AppUpdateInfo, type AutoCaptureErrorsOptions, type CaptureExceptionOptions, type CleanupConfig, type ConsentHistoryEntry, ConsentManager, type ConsentState, type ConsentStatus, type ConsoleCaptureOptions, type ConsoleLevel, type ErrorEventProperties, type EventContext, type EventCountPeriod, EventCounter, type EventMap, EventQueue, type EventType, FrequencyMiddleware, type FrequencyMiddlewareOptions, type GlobalErrorInfo, type GlobalErrorListener, type HttpAdapterConfig, type IAnalyticsAdapter, type IEventCounter, type IMiddleware, type IStorageAdapter, type ISunglassesClient, type ISunglassesTypedClient, IdentityManager, type IdentityState, LocalEventArchive, type Logger, type MiddlewareNext, MiddlewarePipeline, PiiSanitizer, SamplingMiddleware, type SamplingMiddlewareOptions, type ScreenTrackingOptions, SessionManager, type SessionState, type SunglassesConfig, SunglassesCore, type SunglassesEvent, TraitManager, type UserDataExport, asTyped, captureException, createLazyClient, createLogger, generateUUID, nowISO, patchConsole, publishGlobalError, sha256Hex, subscribeGlobalError };
|
package/dist/index.js
CHANGED
|
@@ -39,7 +39,9 @@ __export(index_exports, {
|
|
|
39
39
|
generateUUID: () => generateUUID,
|
|
40
40
|
nowISO: () => nowISO,
|
|
41
41
|
patchConsole: () => patchConsole,
|
|
42
|
-
|
|
42
|
+
publishGlobalError: () => publishGlobalError,
|
|
43
|
+
sha256Hex: () => sha256Hex,
|
|
44
|
+
subscribeGlobalError: () => subscribeGlobalError
|
|
43
45
|
});
|
|
44
46
|
module.exports = __toCommonJS(index_exports);
|
|
45
47
|
|
|
@@ -676,13 +678,13 @@ var BUILTIN_DENIED_KEYS = /* @__PURE__ */ new Set([
|
|
|
676
678
|
]);
|
|
677
679
|
var PII_PATTERNS = [
|
|
678
680
|
// Email (requires letter-only TLD)
|
|
679
|
-
/[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}
|
|
681
|
+
/[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}/g,
|
|
680
682
|
// Phone (US/international, various formats)
|
|
681
|
-
/(\+?1?\s?)?\(?\d{3}\)?[\s.\-]\d{3}[\s.\-]\d{4}
|
|
683
|
+
/(\+?1?\s?)?\(?\d{3}\)?[\s.\-]\d{3}[\s.\-]\d{4}/g,
|
|
682
684
|
// IPv4
|
|
683
|
-
/\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b
|
|
685
|
+
/\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/g,
|
|
684
686
|
// Credit card (major formats: 16 digits with optional separators)
|
|
685
|
-
/\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b/
|
|
687
|
+
/\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b/g
|
|
686
688
|
];
|
|
687
689
|
var PiiSanitizer = class {
|
|
688
690
|
constructor(allowedProperties, deniedProperties) {
|
|
@@ -730,16 +732,25 @@ var PiiSanitizer = class {
|
|
|
730
732
|
}
|
|
731
733
|
return result;
|
|
732
734
|
}
|
|
733
|
-
if (typeof value === "string"
|
|
734
|
-
return
|
|
735
|
+
if (typeof value === "string") {
|
|
736
|
+
return this.maskPiiSubstrings(value);
|
|
735
737
|
}
|
|
736
738
|
return value;
|
|
737
739
|
}
|
|
738
|
-
|
|
740
|
+
/**
|
|
741
|
+
* Replace every PII match in `value` with `'[redacted]'`, preserving the
|
|
742
|
+
* surrounding text. This is safer than whole-value redaction for stack traces
|
|
743
|
+
* and error messages that may contain PII alongside non-sensitive context.
|
|
744
|
+
*
|
|
745
|
+
* Each pattern must have the `g` (global) flag so all occurrences are replaced.
|
|
746
|
+
*/
|
|
747
|
+
maskPiiSubstrings(value) {
|
|
748
|
+
let result = value;
|
|
739
749
|
for (const pattern of PII_PATTERNS) {
|
|
740
|
-
|
|
750
|
+
pattern.lastIndex = 0;
|
|
751
|
+
result = result.replace(pattern, "[redacted]");
|
|
741
752
|
}
|
|
742
|
-
return
|
|
753
|
+
return result;
|
|
743
754
|
}
|
|
744
755
|
};
|
|
745
756
|
|
|
@@ -1612,20 +1623,87 @@ function extractStack(stack, maxFrames) {
|
|
|
1612
1623
|
}
|
|
1613
1624
|
return void 0;
|
|
1614
1625
|
}
|
|
1626
|
+
var STANDARD_ERROR_KEYS = /* @__PURE__ */ new Set(["message", "name", "stack", "cause"]);
|
|
1627
|
+
var MAX_EXTRA_PROPS = 20;
|
|
1628
|
+
function extractErrorExtras(error, maxMessageLength) {
|
|
1629
|
+
const extras = {};
|
|
1630
|
+
let count = 0;
|
|
1631
|
+
for (const key of Object.getOwnPropertyNames(error)) {
|
|
1632
|
+
if (STANDARD_ERROR_KEYS.has(key)) continue;
|
|
1633
|
+
if (count >= MAX_EXTRA_PROPS) break;
|
|
1634
|
+
const val = error[key];
|
|
1635
|
+
const t = typeof val;
|
|
1636
|
+
if (t === "string") {
|
|
1637
|
+
extras[key] = val.slice(0, maxMessageLength);
|
|
1638
|
+
count++;
|
|
1639
|
+
} else if (t === "number" || t === "boolean") {
|
|
1640
|
+
extras[key] = val;
|
|
1641
|
+
count++;
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
return count > 0 ? extras : void 0;
|
|
1645
|
+
}
|
|
1646
|
+
function serializeCauseChain(error, maxDepth, maxMessageLength) {
|
|
1647
|
+
if (!(error instanceof Error) || !("cause" in error)) return void 0;
|
|
1648
|
+
const parts = [];
|
|
1649
|
+
let current = error.cause;
|
|
1650
|
+
for (let depth = 0; depth < maxDepth && current != null; depth++) {
|
|
1651
|
+
if (current instanceof Error) {
|
|
1652
|
+
parts.push(`${current.name}: ${current.message.slice(0, maxMessageLength)}`);
|
|
1653
|
+
current = "cause" in current ? current.cause : void 0;
|
|
1654
|
+
} else if (typeof current === "string") {
|
|
1655
|
+
parts.push(current.slice(0, maxMessageLength));
|
|
1656
|
+
break;
|
|
1657
|
+
} else if (current && typeof current === "object" && "message" in current) {
|
|
1658
|
+
parts.push(String(current.message).slice(0, maxMessageLength));
|
|
1659
|
+
break;
|
|
1660
|
+
} else {
|
|
1661
|
+
parts.push(String(current).slice(0, maxMessageLength));
|
|
1662
|
+
break;
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
return parts.length > 0 ? parts.join("\ncaused by: ") : void 0;
|
|
1666
|
+
}
|
|
1667
|
+
var dedupeStore = /* @__PURE__ */ new WeakMap();
|
|
1668
|
+
function isDuplicate(client, fingerprint, windowMs) {
|
|
1669
|
+
const now = Date.now();
|
|
1670
|
+
let seen = dedupeStore.get(client);
|
|
1671
|
+
if (!seen) {
|
|
1672
|
+
seen = /* @__PURE__ */ new Map();
|
|
1673
|
+
dedupeStore.set(client, seen);
|
|
1674
|
+
}
|
|
1675
|
+
for (const [fp, ts] of seen) {
|
|
1676
|
+
if (now - ts > windowMs) seen.delete(fp);
|
|
1677
|
+
}
|
|
1678
|
+
const last = seen.get(fingerprint);
|
|
1679
|
+
if (last !== void 0 && now - last <= windowMs) return true;
|
|
1680
|
+
seen.set(fingerprint, now);
|
|
1681
|
+
return false;
|
|
1682
|
+
}
|
|
1615
1683
|
function captureException(client, error, options = {}) {
|
|
1616
1684
|
const {
|
|
1617
1685
|
handled = true,
|
|
1618
1686
|
level = "error",
|
|
1619
|
-
includeStack =
|
|
1687
|
+
includeStack = true,
|
|
1620
1688
|
maxStackFrames = 5,
|
|
1621
1689
|
maxMessageLength = 200,
|
|
1622
1690
|
ignorePatterns = [],
|
|
1623
1691
|
properties,
|
|
1624
|
-
beforeCapture
|
|
1692
|
+
beforeCapture,
|
|
1693
|
+
dedupe = true,
|
|
1694
|
+
dedupeWindowMs = 1e3,
|
|
1695
|
+
componentStack,
|
|
1696
|
+
fatal,
|
|
1697
|
+
source
|
|
1625
1698
|
} = options;
|
|
1626
1699
|
const normalized = normalizeError(error);
|
|
1627
1700
|
const rawMessage = normalized.message;
|
|
1628
1701
|
if (ignorePatterns.some((p) => p.test(rawMessage))) return;
|
|
1702
|
+
if (dedupe) {
|
|
1703
|
+
const firstFrame = extractStack(normalized.stack, 1) ?? "";
|
|
1704
|
+
const fingerprint = `${normalized.name}|${rawMessage}|${firstFrame}`;
|
|
1705
|
+
if (isDuplicate(client, fingerprint, dedupeWindowMs)) return;
|
|
1706
|
+
}
|
|
1629
1707
|
let props = {
|
|
1630
1708
|
...properties,
|
|
1631
1709
|
$error_message: rawMessage.slice(0, maxMessageLength),
|
|
@@ -1637,6 +1715,15 @@ function captureException(client, error, options = {}) {
|
|
|
1637
1715
|
const frames = extractStack(normalized.stack, maxStackFrames);
|
|
1638
1716
|
if (frames) props = { ...props, $error_stack: frames };
|
|
1639
1717
|
}
|
|
1718
|
+
const cause = serializeCauseChain(error, 3, maxMessageLength);
|
|
1719
|
+
if (cause) props = { ...props, $error_cause: cause };
|
|
1720
|
+
if (error instanceof Error) {
|
|
1721
|
+
const extra = extractErrorExtras(error, maxMessageLength);
|
|
1722
|
+
if (extra) props = { ...props, $error_extra: extra };
|
|
1723
|
+
}
|
|
1724
|
+
if (componentStack) props = { ...props, $error_component_stack: componentStack };
|
|
1725
|
+
if (fatal !== void 0) props = { ...props, $error_fatal: fatal };
|
|
1726
|
+
if (source) props = { ...props, $error_source: source };
|
|
1640
1727
|
if (beforeCapture) {
|
|
1641
1728
|
const transformed = beforeCapture(props);
|
|
1642
1729
|
if (!transformed) return;
|
|
@@ -1668,7 +1755,7 @@ function patchConsole(client, options = {}) {
|
|
|
1668
1755
|
levels = ["error"],
|
|
1669
1756
|
ignorePatterns = [],
|
|
1670
1757
|
maxMessageLength = 200,
|
|
1671
|
-
includeStack =
|
|
1758
|
+
includeStack = true,
|
|
1672
1759
|
properties
|
|
1673
1760
|
} = options;
|
|
1674
1761
|
const uniqueLevels = Array.from(new Set(levels));
|
|
@@ -1691,7 +1778,8 @@ function patchConsole(client, options = {}) {
|
|
|
1691
1778
|
level: LEVEL_TO_SEVERITY[level],
|
|
1692
1779
|
includeStack,
|
|
1693
1780
|
maxMessageLength,
|
|
1694
|
-
|
|
1781
|
+
source: "console",
|
|
1782
|
+
properties
|
|
1695
1783
|
});
|
|
1696
1784
|
} finally {
|
|
1697
1785
|
isCapturing = false;
|
|
@@ -1705,6 +1793,23 @@ function patchConsole(client, options = {}) {
|
|
|
1705
1793
|
};
|
|
1706
1794
|
}
|
|
1707
1795
|
|
|
1796
|
+
// src/errorBus.ts
|
|
1797
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
1798
|
+
function publishGlobalError(info) {
|
|
1799
|
+
for (const listener of listeners) {
|
|
1800
|
+
try {
|
|
1801
|
+
listener(info);
|
|
1802
|
+
} catch {
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
function subscribeGlobalError(listener) {
|
|
1807
|
+
listeners.add(listener);
|
|
1808
|
+
return () => {
|
|
1809
|
+
listeners.delete(listener);
|
|
1810
|
+
};
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1708
1813
|
// src/LazyClient.ts
|
|
1709
1814
|
function createLazyClient() {
|
|
1710
1815
|
let _inner = null;
|
|
@@ -1843,5 +1948,7 @@ function createLazyClient() {
|
|
|
1843
1948
|
generateUUID,
|
|
1844
1949
|
nowISO,
|
|
1845
1950
|
patchConsole,
|
|
1846
|
-
|
|
1951
|
+
publishGlobalError,
|
|
1952
|
+
sha256Hex,
|
|
1953
|
+
subscribeGlobalError
|
|
1847
1954
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -631,13 +631,13 @@ var BUILTIN_DENIED_KEYS = /* @__PURE__ */ new Set([
|
|
|
631
631
|
]);
|
|
632
632
|
var PII_PATTERNS = [
|
|
633
633
|
// Email (requires letter-only TLD)
|
|
634
|
-
/[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}
|
|
634
|
+
/[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}/g,
|
|
635
635
|
// Phone (US/international, various formats)
|
|
636
|
-
/(\+?1?\s?)?\(?\d{3}\)?[\s.\-]\d{3}[\s.\-]\d{4}
|
|
636
|
+
/(\+?1?\s?)?\(?\d{3}\)?[\s.\-]\d{3}[\s.\-]\d{4}/g,
|
|
637
637
|
// IPv4
|
|
638
|
-
/\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b
|
|
638
|
+
/\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/g,
|
|
639
639
|
// Credit card (major formats: 16 digits with optional separators)
|
|
640
|
-
/\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b/
|
|
640
|
+
/\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b/g
|
|
641
641
|
];
|
|
642
642
|
var PiiSanitizer = class {
|
|
643
643
|
constructor(allowedProperties, deniedProperties) {
|
|
@@ -685,16 +685,25 @@ var PiiSanitizer = class {
|
|
|
685
685
|
}
|
|
686
686
|
return result;
|
|
687
687
|
}
|
|
688
|
-
if (typeof value === "string"
|
|
689
|
-
return
|
|
688
|
+
if (typeof value === "string") {
|
|
689
|
+
return this.maskPiiSubstrings(value);
|
|
690
690
|
}
|
|
691
691
|
return value;
|
|
692
692
|
}
|
|
693
|
-
|
|
693
|
+
/**
|
|
694
|
+
* Replace every PII match in `value` with `'[redacted]'`, preserving the
|
|
695
|
+
* surrounding text. This is safer than whole-value redaction for stack traces
|
|
696
|
+
* and error messages that may contain PII alongside non-sensitive context.
|
|
697
|
+
*
|
|
698
|
+
* Each pattern must have the `g` (global) flag so all occurrences are replaced.
|
|
699
|
+
*/
|
|
700
|
+
maskPiiSubstrings(value) {
|
|
701
|
+
let result = value;
|
|
694
702
|
for (const pattern of PII_PATTERNS) {
|
|
695
|
-
|
|
703
|
+
pattern.lastIndex = 0;
|
|
704
|
+
result = result.replace(pattern, "[redacted]");
|
|
696
705
|
}
|
|
697
|
-
return
|
|
706
|
+
return result;
|
|
698
707
|
}
|
|
699
708
|
};
|
|
700
709
|
|
|
@@ -1567,20 +1576,87 @@ function extractStack(stack, maxFrames) {
|
|
|
1567
1576
|
}
|
|
1568
1577
|
return void 0;
|
|
1569
1578
|
}
|
|
1579
|
+
var STANDARD_ERROR_KEYS = /* @__PURE__ */ new Set(["message", "name", "stack", "cause"]);
|
|
1580
|
+
var MAX_EXTRA_PROPS = 20;
|
|
1581
|
+
function extractErrorExtras(error, maxMessageLength) {
|
|
1582
|
+
const extras = {};
|
|
1583
|
+
let count = 0;
|
|
1584
|
+
for (const key of Object.getOwnPropertyNames(error)) {
|
|
1585
|
+
if (STANDARD_ERROR_KEYS.has(key)) continue;
|
|
1586
|
+
if (count >= MAX_EXTRA_PROPS) break;
|
|
1587
|
+
const val = error[key];
|
|
1588
|
+
const t = typeof val;
|
|
1589
|
+
if (t === "string") {
|
|
1590
|
+
extras[key] = val.slice(0, maxMessageLength);
|
|
1591
|
+
count++;
|
|
1592
|
+
} else if (t === "number" || t === "boolean") {
|
|
1593
|
+
extras[key] = val;
|
|
1594
|
+
count++;
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
return count > 0 ? extras : void 0;
|
|
1598
|
+
}
|
|
1599
|
+
function serializeCauseChain(error, maxDepth, maxMessageLength) {
|
|
1600
|
+
if (!(error instanceof Error) || !("cause" in error)) return void 0;
|
|
1601
|
+
const parts = [];
|
|
1602
|
+
let current = error.cause;
|
|
1603
|
+
for (let depth = 0; depth < maxDepth && current != null; depth++) {
|
|
1604
|
+
if (current instanceof Error) {
|
|
1605
|
+
parts.push(`${current.name}: ${current.message.slice(0, maxMessageLength)}`);
|
|
1606
|
+
current = "cause" in current ? current.cause : void 0;
|
|
1607
|
+
} else if (typeof current === "string") {
|
|
1608
|
+
parts.push(current.slice(0, maxMessageLength));
|
|
1609
|
+
break;
|
|
1610
|
+
} else if (current && typeof current === "object" && "message" in current) {
|
|
1611
|
+
parts.push(String(current.message).slice(0, maxMessageLength));
|
|
1612
|
+
break;
|
|
1613
|
+
} else {
|
|
1614
|
+
parts.push(String(current).slice(0, maxMessageLength));
|
|
1615
|
+
break;
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
return parts.length > 0 ? parts.join("\ncaused by: ") : void 0;
|
|
1619
|
+
}
|
|
1620
|
+
var dedupeStore = /* @__PURE__ */ new WeakMap();
|
|
1621
|
+
function isDuplicate(client, fingerprint, windowMs) {
|
|
1622
|
+
const now = Date.now();
|
|
1623
|
+
let seen = dedupeStore.get(client);
|
|
1624
|
+
if (!seen) {
|
|
1625
|
+
seen = /* @__PURE__ */ new Map();
|
|
1626
|
+
dedupeStore.set(client, seen);
|
|
1627
|
+
}
|
|
1628
|
+
for (const [fp, ts] of seen) {
|
|
1629
|
+
if (now - ts > windowMs) seen.delete(fp);
|
|
1630
|
+
}
|
|
1631
|
+
const last = seen.get(fingerprint);
|
|
1632
|
+
if (last !== void 0 && now - last <= windowMs) return true;
|
|
1633
|
+
seen.set(fingerprint, now);
|
|
1634
|
+
return false;
|
|
1635
|
+
}
|
|
1570
1636
|
function captureException(client, error, options = {}) {
|
|
1571
1637
|
const {
|
|
1572
1638
|
handled = true,
|
|
1573
1639
|
level = "error",
|
|
1574
|
-
includeStack =
|
|
1640
|
+
includeStack = true,
|
|
1575
1641
|
maxStackFrames = 5,
|
|
1576
1642
|
maxMessageLength = 200,
|
|
1577
1643
|
ignorePatterns = [],
|
|
1578
1644
|
properties,
|
|
1579
|
-
beforeCapture
|
|
1645
|
+
beforeCapture,
|
|
1646
|
+
dedupe = true,
|
|
1647
|
+
dedupeWindowMs = 1e3,
|
|
1648
|
+
componentStack,
|
|
1649
|
+
fatal,
|
|
1650
|
+
source
|
|
1580
1651
|
} = options;
|
|
1581
1652
|
const normalized = normalizeError(error);
|
|
1582
1653
|
const rawMessage = normalized.message;
|
|
1583
1654
|
if (ignorePatterns.some((p) => p.test(rawMessage))) return;
|
|
1655
|
+
if (dedupe) {
|
|
1656
|
+
const firstFrame = extractStack(normalized.stack, 1) ?? "";
|
|
1657
|
+
const fingerprint = `${normalized.name}|${rawMessage}|${firstFrame}`;
|
|
1658
|
+
if (isDuplicate(client, fingerprint, dedupeWindowMs)) return;
|
|
1659
|
+
}
|
|
1584
1660
|
let props = {
|
|
1585
1661
|
...properties,
|
|
1586
1662
|
$error_message: rawMessage.slice(0, maxMessageLength),
|
|
@@ -1592,6 +1668,15 @@ function captureException(client, error, options = {}) {
|
|
|
1592
1668
|
const frames = extractStack(normalized.stack, maxStackFrames);
|
|
1593
1669
|
if (frames) props = { ...props, $error_stack: frames };
|
|
1594
1670
|
}
|
|
1671
|
+
const cause = serializeCauseChain(error, 3, maxMessageLength);
|
|
1672
|
+
if (cause) props = { ...props, $error_cause: cause };
|
|
1673
|
+
if (error instanceof Error) {
|
|
1674
|
+
const extra = extractErrorExtras(error, maxMessageLength);
|
|
1675
|
+
if (extra) props = { ...props, $error_extra: extra };
|
|
1676
|
+
}
|
|
1677
|
+
if (componentStack) props = { ...props, $error_component_stack: componentStack };
|
|
1678
|
+
if (fatal !== void 0) props = { ...props, $error_fatal: fatal };
|
|
1679
|
+
if (source) props = { ...props, $error_source: source };
|
|
1595
1680
|
if (beforeCapture) {
|
|
1596
1681
|
const transformed = beforeCapture(props);
|
|
1597
1682
|
if (!transformed) return;
|
|
@@ -1623,7 +1708,7 @@ function patchConsole(client, options = {}) {
|
|
|
1623
1708
|
levels = ["error"],
|
|
1624
1709
|
ignorePatterns = [],
|
|
1625
1710
|
maxMessageLength = 200,
|
|
1626
|
-
includeStack =
|
|
1711
|
+
includeStack = true,
|
|
1627
1712
|
properties
|
|
1628
1713
|
} = options;
|
|
1629
1714
|
const uniqueLevels = Array.from(new Set(levels));
|
|
@@ -1646,7 +1731,8 @@ function patchConsole(client, options = {}) {
|
|
|
1646
1731
|
level: LEVEL_TO_SEVERITY[level],
|
|
1647
1732
|
includeStack,
|
|
1648
1733
|
maxMessageLength,
|
|
1649
|
-
|
|
1734
|
+
source: "console",
|
|
1735
|
+
properties
|
|
1650
1736
|
});
|
|
1651
1737
|
} finally {
|
|
1652
1738
|
isCapturing = false;
|
|
@@ -1660,6 +1746,23 @@ function patchConsole(client, options = {}) {
|
|
|
1660
1746
|
};
|
|
1661
1747
|
}
|
|
1662
1748
|
|
|
1749
|
+
// src/errorBus.ts
|
|
1750
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
1751
|
+
function publishGlobalError(info) {
|
|
1752
|
+
for (const listener of listeners) {
|
|
1753
|
+
try {
|
|
1754
|
+
listener(info);
|
|
1755
|
+
} catch {
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
function subscribeGlobalError(listener) {
|
|
1760
|
+
listeners.add(listener);
|
|
1761
|
+
return () => {
|
|
1762
|
+
listeners.delete(listener);
|
|
1763
|
+
};
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1663
1766
|
// src/LazyClient.ts
|
|
1664
1767
|
function createLazyClient() {
|
|
1665
1768
|
let _inner = null;
|
|
@@ -1797,5 +1900,7 @@ export {
|
|
|
1797
1900
|
generateUUID,
|
|
1798
1901
|
nowISO,
|
|
1799
1902
|
patchConsole,
|
|
1800
|
-
|
|
1903
|
+
publishGlobalError,
|
|
1904
|
+
sha256Hex,
|
|
1905
|
+
subscribeGlobalError
|
|
1801
1906
|
};
|