@drakkar.software/sunglasses-core 0.12.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 +63 -4
- package/dist/index.d.ts +63 -4
- package/dist/index.js +76 -13
- package/dist/index.mjs +76 -13
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -533,8 +533,42 @@ interface ErrorEventProperties {
|
|
|
533
533
|
$error_handled: boolean;
|
|
534
534
|
/** Sentry-compatible severity level. Usually `'error'`. */
|
|
535
535
|
$error_level: string;
|
|
536
|
-
/**
|
|
536
|
+
/** Stringified stack trace (trimmed to `maxStackFrames`). On by default. */
|
|
537
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;
|
|
538
572
|
/** Allows adapter-specific extension properties (e.g. from `beforeCapture`). */
|
|
539
573
|
[key: string]: unknown;
|
|
540
574
|
}
|
|
@@ -676,7 +710,14 @@ declare class PiiSanitizer implements IMiddleware {
|
|
|
676
710
|
* - Recurse into nested objects and arrays
|
|
677
711
|
*/
|
|
678
712
|
private deepSanitizeValues;
|
|
679
|
-
|
|
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;
|
|
680
721
|
}
|
|
681
722
|
|
|
682
723
|
interface Logger {
|
|
@@ -1148,8 +1189,9 @@ interface CaptureExceptionOptions {
|
|
|
1148
1189
|
/** Sentry-compatible severity level. Default: `'error'`. */
|
|
1149
1190
|
level?: string;
|
|
1150
1191
|
/**
|
|
1151
|
-
* Include the stack trace in `$error_stack`. Default: `
|
|
1152
|
-
* 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.
|
|
1153
1195
|
*/
|
|
1154
1196
|
includeStack?: boolean;
|
|
1155
1197
|
/**
|
|
@@ -1192,6 +1234,23 @@ interface CaptureExceptionOptions {
|
|
|
1192
1234
|
* are dropped. Default: `1000`.
|
|
1193
1235
|
*/
|
|
1194
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;
|
|
1195
1254
|
}
|
|
1196
1255
|
/**
|
|
1197
1256
|
* Normalize any thrown value into a SunGlasses `$error` event and capture it
|
package/dist/index.d.ts
CHANGED
|
@@ -533,8 +533,42 @@ interface ErrorEventProperties {
|
|
|
533
533
|
$error_handled: boolean;
|
|
534
534
|
/** Sentry-compatible severity level. Usually `'error'`. */
|
|
535
535
|
$error_level: string;
|
|
536
|
-
/**
|
|
536
|
+
/** Stringified stack trace (trimmed to `maxStackFrames`). On by default. */
|
|
537
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;
|
|
538
572
|
/** Allows adapter-specific extension properties (e.g. from `beforeCapture`). */
|
|
539
573
|
[key: string]: unknown;
|
|
540
574
|
}
|
|
@@ -676,7 +710,14 @@ declare class PiiSanitizer implements IMiddleware {
|
|
|
676
710
|
* - Recurse into nested objects and arrays
|
|
677
711
|
*/
|
|
678
712
|
private deepSanitizeValues;
|
|
679
|
-
|
|
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;
|
|
680
721
|
}
|
|
681
722
|
|
|
682
723
|
interface Logger {
|
|
@@ -1148,8 +1189,9 @@ interface CaptureExceptionOptions {
|
|
|
1148
1189
|
/** Sentry-compatible severity level. Default: `'error'`. */
|
|
1149
1190
|
level?: string;
|
|
1150
1191
|
/**
|
|
1151
|
-
* Include the stack trace in `$error_stack`. Default: `
|
|
1152
|
-
* 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.
|
|
1153
1195
|
*/
|
|
1154
1196
|
includeStack?: boolean;
|
|
1155
1197
|
/**
|
|
@@ -1192,6 +1234,23 @@ interface CaptureExceptionOptions {
|
|
|
1192
1234
|
* are dropped. Default: `1000`.
|
|
1193
1235
|
*/
|
|
1194
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;
|
|
1195
1254
|
}
|
|
1196
1255
|
/**
|
|
1197
1256
|
* Normalize any thrown value into a SunGlasses `$error` event and capture it
|
package/dist/index.js
CHANGED
|
@@ -678,13 +678,13 @@ var BUILTIN_DENIED_KEYS = /* @__PURE__ */ new Set([
|
|
|
678
678
|
]);
|
|
679
679
|
var PII_PATTERNS = [
|
|
680
680
|
// Email (requires letter-only TLD)
|
|
681
|
-
/[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,
|
|
682
682
|
// Phone (US/international, various formats)
|
|
683
|
-
/(\+?1?\s?)?\(?\d{3}\)?[\s.\-]\d{3}[\s.\-]\d{4}
|
|
683
|
+
/(\+?1?\s?)?\(?\d{3}\)?[\s.\-]\d{3}[\s.\-]\d{4}/g,
|
|
684
684
|
// IPv4
|
|
685
|
-
/\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,
|
|
686
686
|
// Credit card (major formats: 16 digits with optional separators)
|
|
687
|
-
/\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b/
|
|
687
|
+
/\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b/g
|
|
688
688
|
];
|
|
689
689
|
var PiiSanitizer = class {
|
|
690
690
|
constructor(allowedProperties, deniedProperties) {
|
|
@@ -732,16 +732,25 @@ var PiiSanitizer = class {
|
|
|
732
732
|
}
|
|
733
733
|
return result;
|
|
734
734
|
}
|
|
735
|
-
if (typeof value === "string"
|
|
736
|
-
return
|
|
735
|
+
if (typeof value === "string") {
|
|
736
|
+
return this.maskPiiSubstrings(value);
|
|
737
737
|
}
|
|
738
738
|
return value;
|
|
739
739
|
}
|
|
740
|
-
|
|
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;
|
|
741
749
|
for (const pattern of PII_PATTERNS) {
|
|
742
|
-
|
|
750
|
+
pattern.lastIndex = 0;
|
|
751
|
+
result = result.replace(pattern, "[redacted]");
|
|
743
752
|
}
|
|
744
|
-
return
|
|
753
|
+
return result;
|
|
745
754
|
}
|
|
746
755
|
};
|
|
747
756
|
|
|
@@ -1614,6 +1623,47 @@ function extractStack(stack, maxFrames) {
|
|
|
1614
1623
|
}
|
|
1615
1624
|
return void 0;
|
|
1616
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
|
+
}
|
|
1617
1667
|
var dedupeStore = /* @__PURE__ */ new WeakMap();
|
|
1618
1668
|
function isDuplicate(client, fingerprint, windowMs) {
|
|
1619
1669
|
const now = Date.now();
|
|
@@ -1634,14 +1684,17 @@ function captureException(client, error, options = {}) {
|
|
|
1634
1684
|
const {
|
|
1635
1685
|
handled = true,
|
|
1636
1686
|
level = "error",
|
|
1637
|
-
includeStack =
|
|
1687
|
+
includeStack = true,
|
|
1638
1688
|
maxStackFrames = 5,
|
|
1639
1689
|
maxMessageLength = 200,
|
|
1640
1690
|
ignorePatterns = [],
|
|
1641
1691
|
properties,
|
|
1642
1692
|
beforeCapture,
|
|
1643
1693
|
dedupe = true,
|
|
1644
|
-
dedupeWindowMs = 1e3
|
|
1694
|
+
dedupeWindowMs = 1e3,
|
|
1695
|
+
componentStack,
|
|
1696
|
+
fatal,
|
|
1697
|
+
source
|
|
1645
1698
|
} = options;
|
|
1646
1699
|
const normalized = normalizeError(error);
|
|
1647
1700
|
const rawMessage = normalized.message;
|
|
@@ -1662,6 +1715,15 @@ function captureException(client, error, options = {}) {
|
|
|
1662
1715
|
const frames = extractStack(normalized.stack, maxStackFrames);
|
|
1663
1716
|
if (frames) props = { ...props, $error_stack: frames };
|
|
1664
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 };
|
|
1665
1727
|
if (beforeCapture) {
|
|
1666
1728
|
const transformed = beforeCapture(props);
|
|
1667
1729
|
if (!transformed) return;
|
|
@@ -1693,7 +1755,7 @@ function patchConsole(client, options = {}) {
|
|
|
1693
1755
|
levels = ["error"],
|
|
1694
1756
|
ignorePatterns = [],
|
|
1695
1757
|
maxMessageLength = 200,
|
|
1696
|
-
includeStack =
|
|
1758
|
+
includeStack = true,
|
|
1697
1759
|
properties
|
|
1698
1760
|
} = options;
|
|
1699
1761
|
const uniqueLevels = Array.from(new Set(levels));
|
|
@@ -1716,7 +1778,8 @@ function patchConsole(client, options = {}) {
|
|
|
1716
1778
|
level: LEVEL_TO_SEVERITY[level],
|
|
1717
1779
|
includeStack,
|
|
1718
1780
|
maxMessageLength,
|
|
1719
|
-
|
|
1781
|
+
source: "console",
|
|
1782
|
+
properties
|
|
1720
1783
|
});
|
|
1721
1784
|
} finally {
|
|
1722
1785
|
isCapturing = false;
|
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,6 +1576,47 @@ 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
|
+
}
|
|
1570
1620
|
var dedupeStore = /* @__PURE__ */ new WeakMap();
|
|
1571
1621
|
function isDuplicate(client, fingerprint, windowMs) {
|
|
1572
1622
|
const now = Date.now();
|
|
@@ -1587,14 +1637,17 @@ function captureException(client, error, options = {}) {
|
|
|
1587
1637
|
const {
|
|
1588
1638
|
handled = true,
|
|
1589
1639
|
level = "error",
|
|
1590
|
-
includeStack =
|
|
1640
|
+
includeStack = true,
|
|
1591
1641
|
maxStackFrames = 5,
|
|
1592
1642
|
maxMessageLength = 200,
|
|
1593
1643
|
ignorePatterns = [],
|
|
1594
1644
|
properties,
|
|
1595
1645
|
beforeCapture,
|
|
1596
1646
|
dedupe = true,
|
|
1597
|
-
dedupeWindowMs = 1e3
|
|
1647
|
+
dedupeWindowMs = 1e3,
|
|
1648
|
+
componentStack,
|
|
1649
|
+
fatal,
|
|
1650
|
+
source
|
|
1598
1651
|
} = options;
|
|
1599
1652
|
const normalized = normalizeError(error);
|
|
1600
1653
|
const rawMessage = normalized.message;
|
|
@@ -1615,6 +1668,15 @@ function captureException(client, error, options = {}) {
|
|
|
1615
1668
|
const frames = extractStack(normalized.stack, maxStackFrames);
|
|
1616
1669
|
if (frames) props = { ...props, $error_stack: frames };
|
|
1617
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 };
|
|
1618
1680
|
if (beforeCapture) {
|
|
1619
1681
|
const transformed = beforeCapture(props);
|
|
1620
1682
|
if (!transformed) return;
|
|
@@ -1646,7 +1708,7 @@ function patchConsole(client, options = {}) {
|
|
|
1646
1708
|
levels = ["error"],
|
|
1647
1709
|
ignorePatterns = [],
|
|
1648
1710
|
maxMessageLength = 200,
|
|
1649
|
-
includeStack =
|
|
1711
|
+
includeStack = true,
|
|
1650
1712
|
properties
|
|
1651
1713
|
} = options;
|
|
1652
1714
|
const uniqueLevels = Array.from(new Set(levels));
|
|
@@ -1669,7 +1731,8 @@ function patchConsole(client, options = {}) {
|
|
|
1669
1731
|
level: LEVEL_TO_SEVERITY[level],
|
|
1670
1732
|
includeStack,
|
|
1671
1733
|
maxMessageLength,
|
|
1672
|
-
|
|
1734
|
+
source: "console",
|
|
1735
|
+
properties
|
|
1673
1736
|
});
|
|
1674
1737
|
} finally {
|
|
1675
1738
|
isCapturing = false;
|