@posthog/core
Advanced tools
| import { CoercingContext, ErrorTrackingCoercer, ExceptionLike } from '../types'; | ||
| export declare class PromiseRejectionEventCoercer implements ErrorTrackingCoercer<PromiseRejectionEvent> { | ||
| match(err: unknown): err is PromiseRejectionEvent; | ||
| coerce(err: PromiseRejectionEvent, ctx: CoercingContext): ExceptionLike | undefined; | ||
| type EventWithDetailReason = Event & { | ||
| detail: { | ||
| reason: unknown; | ||
| }; | ||
| }; | ||
| export declare class PromiseRejectionEventCoercer implements ErrorTrackingCoercer<PromiseRejectionEvent | EventWithDetailReason> { | ||
| match(err: unknown): err is PromiseRejectionEvent | EventWithDetailReason; | ||
| private isCustomEventWrappingRejection; | ||
| coerce(err: PromiseRejectionEvent | EventWithDetailReason, ctx: CoercingContext): ExceptionLike | undefined; | ||
| private getUnhandledRejectionReason; | ||
| } | ||
| export {}; | ||
| //# sourceMappingURL=promise-rejection-event.d.ts.map |
@@ -1,1 +0,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;AAG/E,qBAAa,4BAA6B,YAAW,oBAAoB,CAAC,qBAAqB,CAAC;IAC9F,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,qBAAqB;IAIjD,MAAM,CAAC,GAAG,EAAE,qBAAqB,EAAE,GAAG,EAAE,eAAe,GAAG,aAAa,GAAG,SAAS;IAcnF,OAAO,CAAC,2BAA2B;CA6BpC"} | ||
| {"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"} |
@@ -32,4 +32,13 @@ "use strict"; | ||
| match(err) { | ||
| return (0, index_js_namespaceObject.isBuiltin)(err, 'PromiseRejectionEvent'); | ||
| return (0, index_js_namespaceObject.isBuiltin)(err, 'PromiseRejectionEvent') || this.isCustomEventWrappingRejection(err); | ||
| } | ||
| isCustomEventWrappingRejection(err) { | ||
| if (!(0, index_js_namespaceObject.isEvent)(err)) return false; | ||
| try { | ||
| const detail = err.detail; | ||
| return null != detail && 'object' == typeof detail && 'reason' in detail; | ||
| } catch { | ||
| return false; | ||
| } | ||
| } | ||
| coerce(err, ctx) { | ||
@@ -46,6 +55,5 @@ const reason = this.getUnhandledRejectionReason(err); | ||
| getUnhandledRejectionReason(error) { | ||
| if ((0, index_js_namespaceObject.isPrimitive)(error)) return error; | ||
| try { | ||
| if ('reason' in error) return error.reason; | ||
| if ('detail' in error && 'reason' in error.detail) return error.detail.reason; | ||
| if ('detail' in error && null != error.detail && 'object' == typeof error.detail && 'reason' in error.detail) return error.detail.reason; | ||
| } catch {} | ||
@@ -52,0 +60,0 @@ return error; |
@@ -1,6 +0,15 @@ | ||
| import { isBuiltin, isPrimitive } from "../../utils/index.mjs"; | ||
| import { isBuiltin, isEvent, isPrimitive } from "../../utils/index.mjs"; | ||
| class PromiseRejectionEventCoercer { | ||
| match(err) { | ||
| return isBuiltin(err, 'PromiseRejectionEvent'); | ||
| return isBuiltin(err, 'PromiseRejectionEvent') || this.isCustomEventWrappingRejection(err); | ||
| } | ||
| isCustomEventWrappingRejection(err) { | ||
| if (!isEvent(err)) return false; | ||
| try { | ||
| const detail = err.detail; | ||
| return null != detail && 'object' == typeof detail && 'reason' in detail; | ||
| } catch { | ||
| return false; | ||
| } | ||
| } | ||
| coerce(err, ctx) { | ||
@@ -17,6 +26,5 @@ const reason = this.getUnhandledRejectionReason(err); | ||
| getUnhandledRejectionReason(error) { | ||
| if (isPrimitive(error)) return error; | ||
| try { | ||
| if ('reason' in error) return error.reason; | ||
| if ('detail' in error && 'reason' in error.detail) return error.detail.reason; | ||
| if ('detail' in error && null != error.detail && 'object' == typeof error.detail && 'reason' in error.detail) return error.detail.reason; | ||
| } catch {} | ||
@@ -23,0 +31,0 @@ return error; |
@@ -18,3 +18,9 @@ /** | ||
| export declare const detectDevice: (user_agent: string) => string; | ||
| export declare const detectDeviceType: (user_agent: string) => string; | ||
| export declare const detectDeviceType: (user_agent: string, options?: { | ||
| userAgentDataPlatform?: string; | ||
| maxTouchPoints?: number; | ||
| screenWidth?: number; | ||
| screenHeight?: number; | ||
| devicePixelRatio?: number; | ||
| }) => string; | ||
| //# sourceMappingURL=user-agent-utils.d.ts.map |
@@ -1,1 +0,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,GAAa,YAAY,MAAM,KAAG,MAmB9D,CAAA"} | ||
| {"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"} |
@@ -362,3 +362,3 @@ "use strict"; | ||
| }; | ||
| const detectDeviceType = function(user_agent) { | ||
| const detectDeviceType = function(user_agent, options) { | ||
| const device = detectDevice(user_agent); | ||
@@ -369,2 +369,7 @@ if (device === IPAD || device === ANDROID_TABLET || 'Kobo' === device || 'Kindle Fire' === device || device === GENERIC_TABLET) return TABLET; | ||
| if (device) return MOBILE; | ||
| if (options?.userAgentDataPlatform === 'Android' && (options?.maxTouchPoints ?? 0) > 0) { | ||
| const shortSide = Math.min(options?.screenWidth ?? 0, options?.screenHeight ?? 0); | ||
| const shortSideDp = shortSide / (options?.devicePixelRatio ?? 1); | ||
| return shortSideDp >= 600 ? TABLET : MOBILE; | ||
| } | ||
| return 'Desktop'; | ||
@@ -371,0 +376,0 @@ }; |
@@ -330,3 +330,3 @@ import { includes } from "./string-utils.mjs"; | ||
| }; | ||
| const detectDeviceType = function(user_agent) { | ||
| const detectDeviceType = function(user_agent, options) { | ||
| const device = detectDevice(user_agent); | ||
@@ -337,4 +337,9 @@ if (device === IPAD || device === ANDROID_TABLET || 'Kobo' === device || 'Kindle Fire' === device || device === GENERIC_TABLET) return TABLET; | ||
| if (device) return MOBILE; | ||
| if (options?.userAgentDataPlatform === 'Android' && (options?.maxTouchPoints ?? 0) > 0) { | ||
| const shortSide = Math.min(options?.screenWidth ?? 0, options?.screenHeight ?? 0); | ||
| const shortSideDp = shortSide / (options?.devicePixelRatio ?? 1); | ||
| return shortSideDp >= 600 ? TABLET : MOBILE; | ||
| } | ||
| return 'Desktop'; | ||
| }; | ||
| export { detectBrowser, detectBrowserVersion, detectDevice, detectDeviceType, detectOS }; |
+1
-1
| { | ||
| "name": "@posthog/core", | ||
| "version": "1.23.2", | ||
| "version": "1.23.3", | ||
| "license": "MIT", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -1,11 +0,27 @@ | ||
| import { isBuiltin, isPrimitive } from '@/utils' | ||
| import { isBuiltin, isEvent, isPrimitive } from '@/utils' | ||
| import { CoercingContext, ErrorTrackingCoercer, ExceptionLike } from '../types' | ||
| type EventWithDetailReason = Event & { detail: { reason: unknown } } | ||
| // Web only | ||
| export class PromiseRejectionEventCoercer implements ErrorTrackingCoercer<PromiseRejectionEvent> { | ||
| match(err: unknown): err is PromiseRejectionEvent { | ||
| return isBuiltin(err, 'PromiseRejectionEvent') | ||
| export class PromiseRejectionEventCoercer implements ErrorTrackingCoercer< | ||
| PromiseRejectionEvent | EventWithDetailReason | ||
| > { | ||
| match(err: unknown): err is PromiseRejectionEvent | EventWithDetailReason { | ||
| return isBuiltin(err, 'PromiseRejectionEvent') || this.isCustomEventWrappingRejection(err) | ||
| } | ||
| coerce(err: PromiseRejectionEvent, ctx: CoercingContext): ExceptionLike | undefined { | ||
| private isCustomEventWrappingRejection(err: unknown): err is EventWithDetailReason { | ||
| if (!isEvent(err)) { | ||
| return false | ||
| } | ||
| try { | ||
| const detail = (err as EventWithDetailReason).detail | ||
| return detail != null && typeof detail === 'object' && 'reason' in detail | ||
| } catch { | ||
| return false | ||
| } | ||
| } | ||
| coerce(err: PromiseRejectionEvent | EventWithDetailReason, ctx: CoercingContext): ExceptionLike | undefined { | ||
| const reason = this.getUnhandledRejectionReason(err) | ||
@@ -24,17 +40,10 @@ if (isPrimitive(reason)) { | ||
| private getUnhandledRejectionReason(error: unknown): unknown { | ||
| if (isPrimitive(error)) { | ||
| return error | ||
| } | ||
| // dig the object of the rejection out of known event types | ||
| private getUnhandledRejectionReason(error: PromiseRejectionEvent | EventWithDetailReason): unknown { | ||
| try { | ||
| type ErrorWithReason = { reason: unknown } | ||
| // PromiseRejectionEvents store the object of the rejection under 'reason' | ||
| // see https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent | ||
| if ('reason' in (error as ErrorWithReason)) { | ||
| return (error as ErrorWithReason).reason | ||
| if ('reason' in error) { | ||
| return error.reason | ||
| } | ||
| type CustomEventWithDetail = { detail: { reason: unknown } } | ||
| // something, somewhere, (likely a browser extension) effectively casts PromiseRejectionEvents | ||
@@ -45,4 +54,4 @@ // to CustomEvents, moving the `promise` and `reason` attributes of the PRE into | ||
| // https://github.com/getsentry/sentry-javascript/issues/2380 | ||
| if ('detail' in (error as CustomEventWithDetail) && 'reason' in (error as CustomEventWithDetail).detail) { | ||
| return (error as CustomEventWithDetail).detail.reason | ||
| if ('detail' in error && error.detail != null && typeof error.detail === 'object' && 'reason' in error.detail) { | ||
| return error.detail.reason | ||
| } | ||
@@ -49,0 +58,0 @@ } catch { |
@@ -1,2 +0,9 @@ | ||
| import { DOMExceptionCoercer, ErrorEventCoercer, ErrorCoercer, ObjectCoercer, StringCoercer } from './coercers' | ||
| import { | ||
| DOMExceptionCoercer, | ||
| ErrorEventCoercer, | ||
| ErrorCoercer, | ||
| ObjectCoercer, | ||
| StringCoercer, | ||
| EventCoercer, | ||
| } from './coercers' | ||
| import { PrimitiveCoercer } from './coercers/primitive-coercer' | ||
@@ -24,2 +31,3 @@ import { PromiseRejectionEventCoercer } from './coercers/promise-rejection-event' | ||
| new PromiseRejectionEventCoercer(), | ||
| new EventCoercer(), | ||
| new ObjectCoercer(), | ||
@@ -169,3 +177,3 @@ new StringCoercer(), | ||
| type: 'MouseEvent', | ||
| value: "'MouseEvent' captured as exception with keys: [object has no keys]", | ||
| value: 'MouseEvent captured as exception with keys: [object has no keys]', | ||
| stack: syntheticError.stack, | ||
@@ -204,3 +212,21 @@ synthetic: true, | ||
| }) | ||
| it('should extract the buried Error from a CustomEvent wrapping a PromiseRejectionEvent', () => { | ||
| const buriedError = new Error('Extension context invalidated.') | ||
| const customEvent = new CustomEvent('unhandledrejection', { | ||
| detail: { | ||
| reason: buriedError, | ||
| promise: Promise.resolve(), | ||
| }, | ||
| }) | ||
| const exception = coerceInput(customEvent) | ||
| expect(exception).toMatchObject({ | ||
| type: 'Error', | ||
| value: 'Extension context invalidated.', | ||
| stack: buriedError.stack, | ||
| }) | ||
| }) | ||
| }) | ||
| }) |
@@ -339,3 +339,12 @@ import { includes } from './string-utils' | ||
| export const detectDeviceType = function (user_agent: string): string { | ||
| export const detectDeviceType = function ( | ||
| user_agent: string, | ||
| options?: { | ||
| userAgentDataPlatform?: string | ||
| maxTouchPoints?: number | ||
| screenWidth?: number | ||
| screenHeight?: number | ||
| devicePixelRatio?: number | ||
| } | ||
| ): string { | ||
| const device = detectDevice(user_agent) | ||
@@ -356,5 +365,14 @@ if ( | ||
| return MOBILE | ||
| } else { | ||
| return 'Desktop' | ||
| } | ||
| // Chrome on Android tablets defaults to "request desktop site" mode, sending | ||
| // a desktop-like UA (e.g. "X11; Linux x86_64") indistinguishable from desktop Linux. | ||
| // The Client Hints API reports the true platform even when the UA lies. | ||
| if (options?.userAgentDataPlatform === 'Android' && (options?.maxTouchPoints ?? 0) > 0) { | ||
| const shortSide = Math.min(options?.screenWidth ?? 0, options?.screenHeight ?? 0) | ||
| const shortSideDp = shortSide / (options?.devicePixelRatio ?? 1) | ||
| return shortSideDp >= 600 ? TABLET : MOBILE | ||
| } | ||
| return 'Desktop' | ||
| } |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
776685
0.47%18266
0.47%