@posthog/core 1.23.1 → 1.23.3
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/error-tracking/coercers/promise-rejection-event.d.ts +10 -3
- package/dist/error-tracking/coercers/promise-rejection-event.d.ts.map +1 -1
- package/dist/error-tracking/coercers/promise-rejection-event.js +11 -3
- package/dist/error-tracking/coercers/promise-rejection-event.mjs +12 -4
- package/dist/posthog-core-stateless.d.ts +3 -0
- package/dist/posthog-core-stateless.d.ts.map +1 -1
- package/dist/utils/number-utils.d.ts +29 -1
- package/dist/utils/number-utils.d.ts.map +1 -1
- package/dist/utils/number-utils.js +34 -2
- package/dist/utils/number-utils.mjs +24 -1
- package/dist/utils/user-agent-utils.d.ts +7 -1
- package/dist/utils/user-agent-utils.d.ts.map +1 -1
- package/dist/utils/user-agent-utils.js +6 -1
- package/dist/utils/user-agent-utils.mjs +6 -1
- package/package.json +1 -1
- package/src/error-tracking/coercers/promise-rejection-event.ts +26 -17
- package/src/error-tracking/error-properties-builder.coerce.spec.ts +28 -2
- package/src/posthog-core-stateless.ts +3 -0
- package/src/utils/number-utils.spec.ts +64 -1
- package/src/utils/number-utils.ts +68 -1
- package/src/utils/user-agent-utils.ts +21 -3
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { CoercingContext, ErrorTrackingCoercer, ExceptionLike } from '../types';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
type EventWithDetailReason = Event & {
|
|
3
|
+
detail: {
|
|
4
|
+
reason: unknown;
|
|
5
|
+
};
|
|
6
|
+
};
|
|
7
|
+
export declare class PromiseRejectionEventCoercer implements ErrorTrackingCoercer<PromiseRejectionEvent | EventWithDetailReason> {
|
|
8
|
+
match(err: unknown): err is PromiseRejectionEvent | EventWithDetailReason;
|
|
9
|
+
private isCustomEventWrappingRejection;
|
|
10
|
+
coerce(err: PromiseRejectionEvent | EventWithDetailReason, ctx: CoercingContext): ExceptionLike | undefined;
|
|
5
11
|
private getUnhandledRejectionReason;
|
|
6
12
|
}
|
|
13
|
+
export {};
|
|
7
14
|
//# sourceMappingURL=promise-rejection-event.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promise-rejection-event.d.ts","sourceRoot":"","sources":["../../../src/error-tracking/coercers/promise-rejection-event.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"promise-rejection-event.d.ts","sourceRoot":"","sources":["../../../src/error-tracking/coercers/promise-rejection-event.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAE/E,KAAK,qBAAqB,GAAG,KAAK,GAAG;IAAE,MAAM,EAAE;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,CAAA;AAGpE,qBAAa,4BAA6B,YAAW,oBAAoB,CACvE,qBAAqB,GAAG,qBAAqB,CAC9C;IACC,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,qBAAqB,GAAG,qBAAqB;IAIzE,OAAO,CAAC,8BAA8B;IAYtC,MAAM,CAAC,GAAG,EAAE,qBAAqB,GAAG,qBAAqB,EAAE,GAAG,EAAE,eAAe,GAAG,aAAa,GAAG,SAAS;IAc3G,OAAO,CAAC,2BAA2B;CAsBpC"}
|
|
@@ -29,7 +29,16 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
29
29
|
const index_js_namespaceObject = require("../../utils/index.js");
|
|
30
30
|
class PromiseRejectionEventCoercer {
|
|
31
31
|
match(err) {
|
|
32
|
-
return (0, index_js_namespaceObject.isBuiltin)(err, 'PromiseRejectionEvent');
|
|
32
|
+
return (0, index_js_namespaceObject.isBuiltin)(err, 'PromiseRejectionEvent') || this.isCustomEventWrappingRejection(err);
|
|
33
|
+
}
|
|
34
|
+
isCustomEventWrappingRejection(err) {
|
|
35
|
+
if (!(0, index_js_namespaceObject.isEvent)(err)) return false;
|
|
36
|
+
try {
|
|
37
|
+
const detail = err.detail;
|
|
38
|
+
return null != detail && 'object' == typeof detail && 'reason' in detail;
|
|
39
|
+
} catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
33
42
|
}
|
|
34
43
|
coerce(err, ctx) {
|
|
35
44
|
const reason = this.getUnhandledRejectionReason(err);
|
|
@@ -42,10 +51,9 @@ class PromiseRejectionEventCoercer {
|
|
|
42
51
|
return ctx.apply(reason);
|
|
43
52
|
}
|
|
44
53
|
getUnhandledRejectionReason(error) {
|
|
45
|
-
if ((0, index_js_namespaceObject.isPrimitive)(error)) return error;
|
|
46
54
|
try {
|
|
47
55
|
if ('reason' in error) return error.reason;
|
|
48
|
-
if ('detail' in error && 'reason' in error.detail) return error.detail.reason;
|
|
56
|
+
if ('detail' in error && null != error.detail && 'object' == typeof error.detail && 'reason' in error.detail) return error.detail.reason;
|
|
49
57
|
} catch {}
|
|
50
58
|
return error;
|
|
51
59
|
}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
import { isBuiltin, isPrimitive } from "../../utils/index.mjs";
|
|
1
|
+
import { isBuiltin, isEvent, isPrimitive } from "../../utils/index.mjs";
|
|
2
2
|
class PromiseRejectionEventCoercer {
|
|
3
3
|
match(err) {
|
|
4
|
-
return isBuiltin(err, 'PromiseRejectionEvent');
|
|
4
|
+
return isBuiltin(err, 'PromiseRejectionEvent') || this.isCustomEventWrappingRejection(err);
|
|
5
|
+
}
|
|
6
|
+
isCustomEventWrappingRejection(err) {
|
|
7
|
+
if (!isEvent(err)) return false;
|
|
8
|
+
try {
|
|
9
|
+
const detail = err.detail;
|
|
10
|
+
return null != detail && 'object' == typeof detail && 'reason' in detail;
|
|
11
|
+
} catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
5
14
|
}
|
|
6
15
|
coerce(err, ctx) {
|
|
7
16
|
const reason = this.getUnhandledRejectionReason(err);
|
|
@@ -14,10 +23,9 @@ class PromiseRejectionEventCoercer {
|
|
|
14
23
|
return ctx.apply(reason);
|
|
15
24
|
}
|
|
16
25
|
getUnhandledRejectionReason(error) {
|
|
17
|
-
if (isPrimitive(error)) return error;
|
|
18
26
|
try {
|
|
19
27
|
if ('reason' in error) return error.reason;
|
|
20
|
-
if ('detail' in error && 'reason' in error.detail) return error.detail.reason;
|
|
28
|
+
if ('detail' in error && null != error.detail && 'object' == typeof error.detail && 'reason' in error.detail) return error.detail.reason;
|
|
21
29
|
} catch {}
|
|
22
30
|
return error;
|
|
23
31
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"posthog-core-stateless.d.ts","sourceRoot":"","sources":["../src/posthog-core-stateless.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"posthog-core-stateless.d.ts","sourceRoot":"","sources":["../src/posthog-core-stateless.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Logger } from '../types';
|
|
1
|
+
import { JsonType, Logger } from '../types';
|
|
2
2
|
/**
|
|
3
3
|
* Clamps a value to a range.
|
|
4
4
|
* @param value the value to clamp
|
|
@@ -8,4 +8,32 @@ import { Logger } from '../types';
|
|
|
8
8
|
* @param fallbackValue if provided then returns this value if the value is not a valid number
|
|
9
9
|
*/
|
|
10
10
|
export declare function clampToRange(value: unknown, min: number, max: number, logger: Logger, fallbackValue?: number): number;
|
|
11
|
+
/**
|
|
12
|
+
* Reads a boolean value from a remote config field.
|
|
13
|
+
*
|
|
14
|
+
* Remote config fields follow a pattern: they are either a boolean (false = disabled),
|
|
15
|
+
* an object with specific keys, or absent/undefined.
|
|
16
|
+
*
|
|
17
|
+
* @param field The remote config field (e.g., `response.errorTracking`, `response.capturePerformance`)
|
|
18
|
+
* @param key The key to read from the object form (e.g., `'autocaptureExceptions'`, `'network_timing'`)
|
|
19
|
+
* @param defaultValue Value to return when the field is absent/undefined (defaults to `true` — don't block locally enabled capture)
|
|
20
|
+
*/
|
|
21
|
+
export declare function getRemoteConfigBool(field: boolean | {
|
|
22
|
+
[key: string]: JsonType;
|
|
23
|
+
} | undefined, key: string, defaultValue?: boolean): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Reads a numeric value from a remote config object field.
|
|
26
|
+
*
|
|
27
|
+
* Remote config values may be either numbers or numeric strings.
|
|
28
|
+
*
|
|
29
|
+
* @param field The remote config field (e.g. `response.sessionRecording`)
|
|
30
|
+
* @param key The key to read (e.g. `'sampleRate'`)
|
|
31
|
+
*/
|
|
32
|
+
export declare function getRemoteConfigNumber(field: boolean | {
|
|
33
|
+
[key: string]: JsonType;
|
|
34
|
+
} | undefined, key: string): number | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Checks whether a value is a valid session replay sample rate in the inclusive range [0, 1].
|
|
37
|
+
*/
|
|
38
|
+
export declare function isValidSampleRate(value: unknown): value is number;
|
|
11
39
|
//# sourceMappingURL=number-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-utils.d.ts","sourceRoot":"","sources":["../../src/utils/number-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"number-utils.d.ts","sourceRoot":"","sources":["../../src/utils/number-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAG3C;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAkBrH;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,OAAO,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAA;CAAE,GAAG,SAAS,EACxD,GAAG,EAAE,MAAM,EACX,YAAY,GAAE,OAAc,GAC3B,OAAO,CAYT;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAA;CAAE,GAAG,SAAS,EACxD,GAAG,EAAE,MAAM,GACV,MAAM,GAAG,SAAS,CAmBpB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEjE"}
|
|
@@ -24,7 +24,10 @@ var __webpack_require__ = {};
|
|
|
24
24
|
var __webpack_exports__ = {};
|
|
25
25
|
__webpack_require__.r(__webpack_exports__);
|
|
26
26
|
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
-
|
|
27
|
+
getRemoteConfigBool: ()=>getRemoteConfigBool,
|
|
28
|
+
clampToRange: ()=>clampToRange,
|
|
29
|
+
getRemoteConfigNumber: ()=>getRemoteConfigNumber,
|
|
30
|
+
isValidSampleRate: ()=>isValidSampleRate
|
|
28
31
|
});
|
|
29
32
|
const external_type_utils_js_namespaceObject = require("./type-utils.js");
|
|
30
33
|
function clampToRange(value, min, max, logger, fallbackValue) {
|
|
@@ -43,9 +46,38 @@ function clampToRange(value, min, max, logger, fallbackValue) {
|
|
|
43
46
|
logger.warn(' must be a number. using max or fallback. max: ' + max + ', fallback: ' + fallbackValue);
|
|
44
47
|
return clampToRange(fallbackValue || max, min, max, logger);
|
|
45
48
|
}
|
|
49
|
+
function getRemoteConfigBool(field, key, defaultValue = true) {
|
|
50
|
+
if (null == field) return defaultValue;
|
|
51
|
+
if ('boolean' == typeof field) return field;
|
|
52
|
+
if ('object' == typeof field) {
|
|
53
|
+
const value = field[key];
|
|
54
|
+
return 'boolean' == typeof value ? value : defaultValue;
|
|
55
|
+
}
|
|
56
|
+
return defaultValue;
|
|
57
|
+
}
|
|
58
|
+
function getRemoteConfigNumber(field, key) {
|
|
59
|
+
if (null == field || 'object' != typeof field) return;
|
|
60
|
+
const value = field[key];
|
|
61
|
+
if ('number' == typeof value && Number.isFinite(value)) return value;
|
|
62
|
+
if ('string' == typeof value) {
|
|
63
|
+
const trimmed = value.trim();
|
|
64
|
+
if ('' === trimmed) return;
|
|
65
|
+
const parsed = Number(trimmed);
|
|
66
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function isValidSampleRate(value) {
|
|
70
|
+
return 'number' == typeof value && Number.isFinite(value) && value >= 0 && value <= 1;
|
|
71
|
+
}
|
|
46
72
|
exports.clampToRange = __webpack_exports__.clampToRange;
|
|
73
|
+
exports.getRemoteConfigBool = __webpack_exports__.getRemoteConfigBool;
|
|
74
|
+
exports.getRemoteConfigNumber = __webpack_exports__.getRemoteConfigNumber;
|
|
75
|
+
exports.isValidSampleRate = __webpack_exports__.isValidSampleRate;
|
|
47
76
|
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
48
|
-
"clampToRange"
|
|
77
|
+
"clampToRange",
|
|
78
|
+
"getRemoteConfigBool",
|
|
79
|
+
"getRemoteConfigNumber",
|
|
80
|
+
"isValidSampleRate"
|
|
49
81
|
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
|
|
50
82
|
Object.defineProperty(exports, '__esModule', {
|
|
51
83
|
value: true
|
|
@@ -15,4 +15,27 @@ function clampToRange(value, min, max, logger, fallbackValue) {
|
|
|
15
15
|
logger.warn(' must be a number. using max or fallback. max: ' + max + ', fallback: ' + fallbackValue);
|
|
16
16
|
return clampToRange(fallbackValue || max, min, max, logger);
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
function getRemoteConfigBool(field, key, defaultValue = true) {
|
|
19
|
+
if (null == field) return defaultValue;
|
|
20
|
+
if ('boolean' == typeof field) return field;
|
|
21
|
+
if ('object' == typeof field) {
|
|
22
|
+
const value = field[key];
|
|
23
|
+
return 'boolean' == typeof value ? value : defaultValue;
|
|
24
|
+
}
|
|
25
|
+
return defaultValue;
|
|
26
|
+
}
|
|
27
|
+
function getRemoteConfigNumber(field, key) {
|
|
28
|
+
if (null == field || 'object' != typeof field) return;
|
|
29
|
+
const value = field[key];
|
|
30
|
+
if ('number' == typeof value && Number.isFinite(value)) return value;
|
|
31
|
+
if ('string' == typeof value) {
|
|
32
|
+
const trimmed = value.trim();
|
|
33
|
+
if ('' === trimmed) return;
|
|
34
|
+
const parsed = Number(trimmed);
|
|
35
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function isValidSampleRate(value) {
|
|
39
|
+
return 'number' == typeof value && Number.isFinite(value) && value >= 0 && value <= 1;
|
|
40
|
+
}
|
|
41
|
+
export { clampToRange, getRemoteConfigBool, getRemoteConfigNumber, isValidSampleRate };
|
|
@@ -15,5 +15,11 @@ export declare const detectBrowser: (user_agent: string, vendor: string | undefi
|
|
|
15
15
|
export declare const detectBrowserVersion: (userAgent: string, vendor: string | undefined) => number | null;
|
|
16
16
|
export declare const detectOS: (user_agent: string) => [string, string];
|
|
17
17
|
export declare const detectDevice: (user_agent: string) => string;
|
|
18
|
-
export declare const detectDeviceType: (user_agent: string
|
|
18
|
+
export declare const detectDeviceType: (user_agent: string, options?: {
|
|
19
|
+
userAgentDataPlatform?: string;
|
|
20
|
+
maxTouchPoints?: number;
|
|
21
|
+
screenWidth?: number;
|
|
22
|
+
screenHeight?: number;
|
|
23
|
+
devicePixelRatio?: number;
|
|
24
|
+
}) => string;
|
|
19
25
|
//# sourceMappingURL=user-agent-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-agent-utils.d.ts","sourceRoot":"","sources":["../../src/utils/user-agent-utils.ts"],"names":[],"mappings":"AAqFA;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAa,YAAY,MAAM,EAAE,QAAQ,MAAM,GAAG,SAAS,KAAG,MA4CvF,CAAA;AAsBD;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,GAAa,WAAW,MAAM,EAAE,QAAQ,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,IAetG,CAAA;AA0FD,eAAO,MAAM,QAAQ,GAAa,YAAY,MAAM,KAAG,CAAC,MAAM,EAAE,MAAM,CAUrE,CAAA;AAED,eAAO,MAAM,YAAY,GAAa,YAAY,MAAM,KAAG,MAuD1D,CAAA;AAED,eAAO,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"user-agent-utils.d.ts","sourceRoot":"","sources":["../../src/utils/user-agent-utils.ts"],"names":[],"mappings":"AAqFA;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAa,YAAY,MAAM,EAAE,QAAQ,MAAM,GAAG,SAAS,KAAG,MA4CvF,CAAA;AAsBD;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,GAAa,WAAW,MAAM,EAAE,QAAQ,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,IAetG,CAAA;AA0FD,eAAO,MAAM,QAAQ,GAAa,YAAY,MAAM,KAAG,CAAC,MAAM,EAAE,MAAM,CAUrE,CAAA;AAED,eAAO,MAAM,YAAY,GAAa,YAAY,MAAM,KAAG,MAuD1D,CAAA;AAED,eAAO,MAAM,gBAAgB,GAC3B,YAAY,MAAM,EAClB,UAAU;IACR,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B,KACA,MA4BF,CAAA"}
|
|
@@ -359,12 +359,17 @@ const detectDevice = function(user_agent) {
|
|
|
359
359
|
else if (new RegExp(TABLET, 'i').test(user_agent) && !new RegExp(TABLET + ' pc', 'i').test(user_agent)) return GENERIC_TABLET;
|
|
360
360
|
else return '';
|
|
361
361
|
};
|
|
362
|
-
const detectDeviceType = function(user_agent) {
|
|
362
|
+
const detectDeviceType = function(user_agent, options) {
|
|
363
363
|
const device = detectDevice(user_agent);
|
|
364
364
|
if (device === IPAD || device === ANDROID_TABLET || 'Kobo' === device || 'Kindle Fire' === device || device === GENERIC_TABLET) return TABLET;
|
|
365
365
|
if (device === NINTENDO || device === XBOX || device === PLAYSTATION || device === OUYA) return 'Console';
|
|
366
366
|
if (device === APPLE_WATCH) return 'Wearable';
|
|
367
367
|
if (device) return MOBILE;
|
|
368
|
+
if (options?.userAgentDataPlatform === 'Android' && (options?.maxTouchPoints ?? 0) > 0) {
|
|
369
|
+
const shortSide = Math.min(options?.screenWidth ?? 0, options?.screenHeight ?? 0);
|
|
370
|
+
const shortSideDp = shortSide / (options?.devicePixelRatio ?? 1);
|
|
371
|
+
return shortSideDp >= 600 ? TABLET : MOBILE;
|
|
372
|
+
}
|
|
368
373
|
return 'Desktop';
|
|
369
374
|
};
|
|
370
375
|
exports.detectBrowser = __webpack_exports__.detectBrowser;
|
|
@@ -327,12 +327,17 @@ const detectDevice = function(user_agent) {
|
|
|
327
327
|
else if (new RegExp(TABLET, 'i').test(user_agent) && !new RegExp(TABLET + ' pc', 'i').test(user_agent)) return GENERIC_TABLET;
|
|
328
328
|
else return '';
|
|
329
329
|
};
|
|
330
|
-
const detectDeviceType = function(user_agent) {
|
|
330
|
+
const detectDeviceType = function(user_agent, options) {
|
|
331
331
|
const device = detectDevice(user_agent);
|
|
332
332
|
if (device === IPAD || device === ANDROID_TABLET || 'Kobo' === device || 'Kindle Fire' === device || device === GENERIC_TABLET) return TABLET;
|
|
333
333
|
if (device === NINTENDO || device === XBOX || device === PLAYSTATION || device === OUYA) return 'Console';
|
|
334
334
|
if (device === APPLE_WATCH) return 'Wearable';
|
|
335
335
|
if (device) return MOBILE;
|
|
336
|
+
if (options?.userAgentDataPlatform === 'Android' && (options?.maxTouchPoints ?? 0) > 0) {
|
|
337
|
+
const shortSide = Math.min(options?.screenWidth ?? 0, options?.screenHeight ?? 0);
|
|
338
|
+
const shortSideDp = shortSide / (options?.devicePixelRatio ?? 1);
|
|
339
|
+
return shortSideDp >= 600 ? TABLET : MOBILE;
|
|
340
|
+
}
|
|
336
341
|
return 'Desktop';
|
|
337
342
|
};
|
|
338
343
|
export { detectBrowser, detectBrowserVersion, detectDevice, detectDeviceType, detectOS };
|
package/package.json
CHANGED
|
@@ -1,13 +1,29 @@
|
|
|
1
|
-
import { isBuiltin, isPrimitive } from '@/utils'
|
|
1
|
+
import { isBuiltin, isEvent, isPrimitive } from '@/utils'
|
|
2
2
|
import { CoercingContext, ErrorTrackingCoercer, ExceptionLike } from '../types'
|
|
3
3
|
|
|
4
|
+
type EventWithDetailReason = Event & { detail: { reason: unknown } }
|
|
5
|
+
|
|
4
6
|
// Web only
|
|
5
|
-
export class PromiseRejectionEventCoercer implements ErrorTrackingCoercer<
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
export class PromiseRejectionEventCoercer implements ErrorTrackingCoercer<
|
|
8
|
+
PromiseRejectionEvent | EventWithDetailReason
|
|
9
|
+
> {
|
|
10
|
+
match(err: unknown): err is PromiseRejectionEvent | EventWithDetailReason {
|
|
11
|
+
return isBuiltin(err, 'PromiseRejectionEvent') || this.isCustomEventWrappingRejection(err)
|
|
8
12
|
}
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
private isCustomEventWrappingRejection(err: unknown): err is EventWithDetailReason {
|
|
15
|
+
if (!isEvent(err)) {
|
|
16
|
+
return false
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
const detail = (err as EventWithDetailReason).detail
|
|
20
|
+
return detail != null && typeof detail === 'object' && 'reason' in detail
|
|
21
|
+
} catch {
|
|
22
|
+
return false
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
coerce(err: PromiseRejectionEvent | EventWithDetailReason, ctx: CoercingContext): ExceptionLike | undefined {
|
|
11
27
|
const reason = this.getUnhandledRejectionReason(err)
|
|
12
28
|
if (isPrimitive(reason)) {
|
|
13
29
|
return {
|
|
@@ -21,28 +37,21 @@ export class PromiseRejectionEventCoercer implements ErrorTrackingCoercer<Promis
|
|
|
21
37
|
}
|
|
22
38
|
}
|
|
23
39
|
|
|
24
|
-
private getUnhandledRejectionReason(error:
|
|
25
|
-
if (isPrimitive(error)) {
|
|
26
|
-
return error
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// dig the object of the rejection out of known event types
|
|
40
|
+
private getUnhandledRejectionReason(error: PromiseRejectionEvent | EventWithDetailReason): unknown {
|
|
30
41
|
try {
|
|
31
|
-
type ErrorWithReason = { reason: unknown }
|
|
32
42
|
// PromiseRejectionEvents store the object of the rejection under 'reason'
|
|
33
43
|
// see https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent
|
|
34
|
-
if ('reason' in
|
|
35
|
-
return
|
|
44
|
+
if ('reason' in error) {
|
|
45
|
+
return error.reason
|
|
36
46
|
}
|
|
37
47
|
|
|
38
|
-
type CustomEventWithDetail = { detail: { reason: unknown } }
|
|
39
48
|
// something, somewhere, (likely a browser extension) effectively casts PromiseRejectionEvents
|
|
40
49
|
// to CustomEvents, moving the `promise` and `reason` attributes of the PRE into
|
|
41
50
|
// the CustomEvent's `detail` attribute, since they're not part of CustomEvent's spec
|
|
42
51
|
// see https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent and
|
|
43
52
|
// https://github.com/getsentry/sentry-javascript/issues/2380
|
|
44
|
-
if ('detail' in
|
|
45
|
-
return
|
|
53
|
+
if ('detail' in error && error.detail != null && typeof error.detail === 'object' && 'reason' in error.detail) {
|
|
54
|
+
return error.detail.reason
|
|
46
55
|
}
|
|
47
56
|
} catch {
|
|
48
57
|
// no-empty
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
DOMExceptionCoercer,
|
|
3
|
+
ErrorEventCoercer,
|
|
4
|
+
ErrorCoercer,
|
|
5
|
+
ObjectCoercer,
|
|
6
|
+
StringCoercer,
|
|
7
|
+
EventCoercer,
|
|
8
|
+
} from './coercers'
|
|
2
9
|
import { PrimitiveCoercer } from './coercers/primitive-coercer'
|
|
3
10
|
import { PromiseRejectionEventCoercer } from './coercers/promise-rejection-event'
|
|
4
11
|
import { ErrorPropertiesBuilder } from './error-properties-builder'
|
|
@@ -21,6 +28,7 @@ describe('ErrorPropertiesBuilder', () => {
|
|
|
21
28
|
new ErrorEventCoercer(),
|
|
22
29
|
new ErrorCoercer(),
|
|
23
30
|
new PromiseRejectionEventCoercer(),
|
|
31
|
+
new EventCoercer(),
|
|
24
32
|
new ObjectCoercer(),
|
|
25
33
|
new StringCoercer(),
|
|
26
34
|
new PrimitiveCoercer(),
|
|
@@ -165,7 +173,7 @@ describe('ErrorPropertiesBuilder', () => {
|
|
|
165
173
|
const exception = coerceInput(event, syntheticError)
|
|
166
174
|
expect(exception).toMatchObject({
|
|
167
175
|
type: 'MouseEvent',
|
|
168
|
-
value:
|
|
176
|
+
value: 'MouseEvent captured as exception with keys: [object has no keys]',
|
|
169
177
|
stack: syntheticError.stack,
|
|
170
178
|
synthetic: true,
|
|
171
179
|
})
|
|
@@ -199,5 +207,23 @@ describe('ErrorPropertiesBuilder', () => {
|
|
|
199
207
|
synthetic: false,
|
|
200
208
|
})
|
|
201
209
|
})
|
|
210
|
+
|
|
211
|
+
it('should extract the buried Error from a CustomEvent wrapping a PromiseRejectionEvent', () => {
|
|
212
|
+
const buriedError = new Error('Extension context invalidated.')
|
|
213
|
+
const customEvent = new CustomEvent('unhandledrejection', {
|
|
214
|
+
detail: {
|
|
215
|
+
reason: buriedError,
|
|
216
|
+
promise: Promise.resolve(),
|
|
217
|
+
},
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
const exception = coerceInput(customEvent)
|
|
221
|
+
|
|
222
|
+
expect(exception).toMatchObject({
|
|
223
|
+
type: 'Error',
|
|
224
|
+
value: 'Extension context invalidated.',
|
|
225
|
+
stack: buriedError.stack,
|
|
226
|
+
})
|
|
227
|
+
})
|
|
202
228
|
})
|
|
203
229
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createMockLogger } from '@/testing'
|
|
2
|
-
import { clampToRange } from './number-utils'
|
|
2
|
+
import { clampToRange, getRemoteConfigBool, getRemoteConfigNumber, isValidSampleRate } from './number-utils'
|
|
3
3
|
|
|
4
4
|
describe('number-utils', () => {
|
|
5
5
|
const mockLogger = createMockLogger()
|
|
@@ -86,4 +86,67 @@ describe('number-utils', () => {
|
|
|
86
86
|
expect(mockLogger.warn).toHaveBeenCalledWith('min cannot be greater than max.')
|
|
87
87
|
})
|
|
88
88
|
})
|
|
89
|
+
|
|
90
|
+
describe('getRemoteConfigBool', () => {
|
|
91
|
+
it('returns default value when field is undefined or null', () => {
|
|
92
|
+
expect(getRemoteConfigBool(undefined, 'key')).toBe(true)
|
|
93
|
+
expect(getRemoteConfigBool(undefined, 'key', false)).toBe(false)
|
|
94
|
+
expect(getRemoteConfigBool(null as any, 'key')).toBe(true)
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
it('returns the boolean directly when field is boolean', () => {
|
|
98
|
+
expect(getRemoteConfigBool(true, 'key')).toBe(true)
|
|
99
|
+
expect(getRemoteConfigBool(false, 'key')).toBe(false)
|
|
100
|
+
expect(getRemoteConfigBool(false, 'key', true)).toBe(false)
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
it('returns the key value when field is an object with a boolean key', () => {
|
|
104
|
+
expect(getRemoteConfigBool({ autocaptureExceptions: true }, 'autocaptureExceptions')).toBe(true)
|
|
105
|
+
expect(getRemoteConfigBool({ autocaptureExceptions: false }, 'autocaptureExceptions')).toBe(false)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('returns default value when key is missing or non-boolean', () => {
|
|
109
|
+
expect(getRemoteConfigBool({ otherKey: 'value' }, 'autocaptureExceptions')).toBe(true)
|
|
110
|
+
expect(getRemoteConfigBool({ otherKey: 'value' }, 'autocaptureExceptions', false)).toBe(false)
|
|
111
|
+
expect(getRemoteConfigBool({ autocaptureExceptions: 'yes' }, 'autocaptureExceptions')).toBe(true)
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
it('returns default true for empty object', () => {
|
|
115
|
+
expect(getRemoteConfigBool({}, 'key')).toBe(true)
|
|
116
|
+
})
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
describe('getRemoteConfigNumber', () => {
|
|
120
|
+
it('returns undefined for missing/invalid fields', () => {
|
|
121
|
+
expect(getRemoteConfigNumber(undefined, 'sampleRate')).toBeUndefined()
|
|
122
|
+
expect(getRemoteConfigNumber(false, 'sampleRate')).toBeUndefined()
|
|
123
|
+
expect(getRemoteConfigNumber({}, 'sampleRate')).toBeUndefined()
|
|
124
|
+
expect(getRemoteConfigNumber({ sampleRate: 'abc' }, 'sampleRate')).toBeUndefined()
|
|
125
|
+
expect(getRemoteConfigNumber({ sampleRate: '' }, 'sampleRate')).toBeUndefined()
|
|
126
|
+
expect(getRemoteConfigNumber({ sampleRate: ' ' }, 'sampleRate')).toBeUndefined()
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it('returns numeric value from number', () => {
|
|
130
|
+
expect(getRemoteConfigNumber({ sampleRate: 0.5 }, 'sampleRate')).toBe(0.5)
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
it('returns numeric value from numeric string', () => {
|
|
134
|
+
expect(getRemoteConfigNumber({ sampleRate: '0.5' }, 'sampleRate')).toBe(0.5)
|
|
135
|
+
})
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
describe('isValidSampleRate', () => {
|
|
139
|
+
it('returns true only for finite values in [0, 1]', () => {
|
|
140
|
+
expect(isValidSampleRate(0)).toBe(true)
|
|
141
|
+
expect(isValidSampleRate(0.5)).toBe(true)
|
|
142
|
+
expect(isValidSampleRate(1)).toBe(true)
|
|
143
|
+
|
|
144
|
+
expect(isValidSampleRate(-0.1)).toBe(false)
|
|
145
|
+
expect(isValidSampleRate(1.1)).toBe(false)
|
|
146
|
+
expect(isValidSampleRate(Number.POSITIVE_INFINITY)).toBe(false)
|
|
147
|
+
expect(isValidSampleRate(Number.NaN)).toBe(false)
|
|
148
|
+
expect(isValidSampleRate('0.5')).toBe(false)
|
|
149
|
+
expect(isValidSampleRate(null)).toBe(false)
|
|
150
|
+
})
|
|
151
|
+
})
|
|
89
152
|
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Logger } from '../types'
|
|
1
|
+
import { JsonType, Logger } from '../types'
|
|
2
2
|
import { isNumber } from './type-utils'
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -28,3 +28,70 @@ export function clampToRange(value: unknown, min: number, max: number, logger: L
|
|
|
28
28
|
return value
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Reads a boolean value from a remote config field.
|
|
34
|
+
*
|
|
35
|
+
* Remote config fields follow a pattern: they are either a boolean (false = disabled),
|
|
36
|
+
* an object with specific keys, or absent/undefined.
|
|
37
|
+
*
|
|
38
|
+
* @param field The remote config field (e.g., `response.errorTracking`, `response.capturePerformance`)
|
|
39
|
+
* @param key The key to read from the object form (e.g., `'autocaptureExceptions'`, `'network_timing'`)
|
|
40
|
+
* @param defaultValue Value to return when the field is absent/undefined (defaults to `true` — don't block locally enabled capture)
|
|
41
|
+
*/
|
|
42
|
+
export function getRemoteConfigBool(
|
|
43
|
+
field: boolean | { [key: string]: JsonType } | undefined,
|
|
44
|
+
key: string,
|
|
45
|
+
defaultValue: boolean = true
|
|
46
|
+
): boolean {
|
|
47
|
+
if (field == null) {
|
|
48
|
+
return defaultValue
|
|
49
|
+
}
|
|
50
|
+
if (typeof field === 'boolean') {
|
|
51
|
+
return field
|
|
52
|
+
}
|
|
53
|
+
if (typeof field === 'object') {
|
|
54
|
+
const value = field[key]
|
|
55
|
+
return typeof value === 'boolean' ? value : defaultValue
|
|
56
|
+
}
|
|
57
|
+
return defaultValue
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Reads a numeric value from a remote config object field.
|
|
62
|
+
*
|
|
63
|
+
* Remote config values may be either numbers or numeric strings.
|
|
64
|
+
*
|
|
65
|
+
* @param field The remote config field (e.g. `response.sessionRecording`)
|
|
66
|
+
* @param key The key to read (e.g. `'sampleRate'`)
|
|
67
|
+
*/
|
|
68
|
+
export function getRemoteConfigNumber(
|
|
69
|
+
field: boolean | { [key: string]: JsonType } | undefined,
|
|
70
|
+
key: string
|
|
71
|
+
): number | undefined {
|
|
72
|
+
if (field == null || typeof field !== 'object') {
|
|
73
|
+
return undefined
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const value = field[key]
|
|
77
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
78
|
+
return value
|
|
79
|
+
}
|
|
80
|
+
if (typeof value === 'string') {
|
|
81
|
+
const trimmed = value.trim()
|
|
82
|
+
if (trimmed === '') {
|
|
83
|
+
return undefined
|
|
84
|
+
}
|
|
85
|
+
const parsed = Number(trimmed)
|
|
86
|
+
return Number.isFinite(parsed) ? parsed : undefined
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return undefined
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Checks whether a value is a valid session replay sample rate in the inclusive range [0, 1].
|
|
94
|
+
*/
|
|
95
|
+
export function isValidSampleRate(value: unknown): value is number {
|
|
96
|
+
return typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= 1
|
|
97
|
+
}
|
|
@@ -336,7 +336,16 @@ export const detectDevice = function (user_agent: string): string {
|
|
|
336
336
|
}
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
-
export const detectDeviceType = function (
|
|
339
|
+
export const detectDeviceType = function (
|
|
340
|
+
user_agent: string,
|
|
341
|
+
options?: {
|
|
342
|
+
userAgentDataPlatform?: string
|
|
343
|
+
maxTouchPoints?: number
|
|
344
|
+
screenWidth?: number
|
|
345
|
+
screenHeight?: number
|
|
346
|
+
devicePixelRatio?: number
|
|
347
|
+
}
|
|
348
|
+
): string {
|
|
340
349
|
const device = detectDevice(user_agent)
|
|
341
350
|
if (
|
|
342
351
|
device === IPAD ||
|
|
@@ -352,7 +361,16 @@ export const detectDeviceType = function (user_agent: string): string {
|
|
|
352
361
|
return 'Wearable'
|
|
353
362
|
} else if (device) {
|
|
354
363
|
return MOBILE
|
|
355
|
-
} else {
|
|
356
|
-
return 'Desktop'
|
|
357
364
|
}
|
|
365
|
+
|
|
366
|
+
// Chrome on Android tablets defaults to "request desktop site" mode, sending
|
|
367
|
+
// a desktop-like UA (e.g. "X11; Linux x86_64") indistinguishable from desktop Linux.
|
|
368
|
+
// The Client Hints API reports the true platform even when the UA lies.
|
|
369
|
+
if (options?.userAgentDataPlatform === 'Android' && (options?.maxTouchPoints ?? 0) > 0) {
|
|
370
|
+
const shortSide = Math.min(options?.screenWidth ?? 0, options?.screenHeight ?? 0)
|
|
371
|
+
const shortSideDp = shortSide / (options?.devicePixelRatio ?? 1)
|
|
372
|
+
return shortSideDp >= 600 ? TABLET : MOBILE
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return 'Desktop'
|
|
358
376
|
}
|