You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@posthog/core

Package Overview
Dependencies
Maintainers
17
Versions
50
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@posthog/core - npm Package Compare versions

Comparing version
1.23.2
to
1.23.3
+10
-3
dist/error-tracking/coercers/promise-rejection-event.d.ts
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 };
{
"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'
}