Skip to content

Commit

Permalink
fix: check if window is available before using on web env (#256)
Browse files Browse the repository at this point in the history
  • Loading branch information
marandaneto authored Jan 17, 2025
1 parent b2a20c4 commit 70d810b
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 19 deletions.
2 changes: 2 additions & 0 deletions posthog-core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,5 @@ export type PostHogFlagsAndPayloadsResponse = {
}

export type JsonType = string | number | boolean | null | { [key: string]: JsonType } | Array<JsonType>

export type FetchLike = (url: string, options: PostHogFetchOptions) => Promise<PostHogFetchResponse>
6 changes: 6 additions & 0 deletions posthog-core/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { FetchLike } from './types'

export function assert(truthyValue: any, message: string): void {
if (!truthyValue) {
throw new Error(message)
Expand Down Expand Up @@ -58,3 +60,7 @@ export function safeSetTimeout(fn: () => void, timeout: number): any {
export const isPromise = (obj: any): obj is Promise<any> => {
return obj && typeof obj.then === 'function'
}

export function getFetch(): FetchLike | undefined {
return typeof fetch !== 'undefined' ? fetch : typeof global.fetch !== 'undefined' ? global.fetch : undefined
}
10 changes: 3 additions & 7 deletions posthog-node/src/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,10 @@
* See https://github.com/PostHog/posthog-js-lite/issues/127 for more info
*/

import { PostHogFetchOptions, PostHogFetchResponse } from 'posthog-core/src'
import { FetchLike, PostHogFetchOptions, PostHogFetchResponse } from 'posthog-core/src'
import { getFetch } from 'posthog-core/src/utils'

type FetchLike = (url: string, options: PostHogFetchOptions) => Promise<PostHogFetchResponse>

let _fetch: FetchLike | undefined =
// eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
// @ts-ignore
typeof fetch !== 'undefined' ? fetch : typeof global.fetch !== 'undefined' ? global.fetch : undefined
let _fetch: FetchLike | undefined = getFetch()

if (!_fetch) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
Expand Down
6 changes: 6 additions & 0 deletions posthog-web/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Next

# 3.2.1 - 2025-01-17

## Fixed

1. fix: check if window and fetch are available before using on web env

# 3.2.0 - 2024-12-12

## Changed
Expand Down
2 changes: 1 addition & 1 deletion posthog-web/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "posthog-js-lite",
"version": "3.2.0",
"version": "3.2.1",
"main": "lib/index.cjs.js",
"module": "lib/index.esm.js",
"types": "lib/index.d.ts",
Expand Down
15 changes: 10 additions & 5 deletions posthog-web/src/context.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { utils } from '../../posthog-core'
import { version } from '../package.json'

export function getContext(window: Window): any {
export function getContext(window: Window | undefined): any {
let context = {}
if (window.navigator) {
if (window?.navigator) {
const userAgent = window.navigator.userAgent
const osValue = os(window)
context = {
...context,
$os: os(window),
...(osValue !== undefined && { $os: osValue }),
$browser: browser(userAgent, window.navigator.vendor, !!(window as any).opera),
$referrer: window.document.referrer,
$referring_domain: referringDomain(window.document.referrer),
Expand All @@ -21,6 +22,7 @@ export function getContext(window: Window): any {
$screen_dpr: window.devicePixelRatio,
}
}

context = {
...context,
$lib: 'js',
Expand Down Expand Up @@ -114,7 +116,10 @@ function browserVersion(userAgent: string, vendor: string, opera: boolean): numb
return parseFloat(matches[matches.length - 2])
}

function os(window: Window): string {
function os(window: Window | undefined): string | undefined {
if (!window?.navigator) {
return undefined
}
const a = window.navigator.userAgent
if (/Windows/i.test(a)) {
if (/Phone/.test(a) || /WPDesktop/.test(a)) {
Expand All @@ -134,7 +139,7 @@ function os(window: Window): string {
} else if (/CrOS/.test(a)) {
return 'Chrome OS'
} else {
return ''
return undefined
}
}

Expand Down
19 changes: 16 additions & 3 deletions posthog-web/src/posthog-web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { getContext } from './context'
import { PostHogStorage, getStorage } from './storage'
import { version } from '../package.json'
import { PostHogOptions } from './types'
import { getFetch } from 'posthog-core/src/utils'

export class PostHog extends PostHogCore {
private _storage: PostHogStorage
Expand All @@ -19,14 +20,19 @@ export class PostHog extends PostHogCore {

// posthog-js stores options in one object on
this._storageKey = options?.persistence_name ? `ph_${options.persistence_name}` : `ph_${apiKey}_posthog`
this._storage = getStorage(options?.persistence || 'localStorage', window)

this._storage = getStorage(options?.persistence || 'localStorage', this.getWindow())
this.setupBootstrap(options)

if (options?.preloadFeatureFlags !== false) {
this.reloadFeatureFlags()
}
}

private getWindow(): Window | undefined {
return typeof window !== 'undefined' ? window : undefined
}

getPersistedProperty<T>(key: PostHogPersistedProperty): T | undefined {
if (!this._storageCache) {
this._storageCache = JSON.parse(this._storage.getItem(this._storageKey) || '{}') || {}
Expand All @@ -50,7 +56,14 @@ export class PostHog extends PostHogCore {
}

fetch(url: string, options: PostHogFetchOptions): Promise<PostHogFetchResponse> {
return window.fetch(url, options)
const fetchFn = getFetch()

if (!fetchFn) {
// error will be handled by the caller (fetchWithRetry)
return Promise.reject(new Error('Fetch API is not available in this environment.'))
}

return fetchFn(url, options)
}

getLibraryId(): string {
Expand All @@ -68,7 +81,7 @@ export class PostHog extends PostHogCore {
getCommonEventProperties(): any {
return {
...super.getCommonEventProperties(),
...getContext(window),
...getContext(this.getWindow()),
}
}
}
3 changes: 0 additions & 3 deletions posthog-web/src/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,6 @@ const createStorageLike = (store: any): PostHogStorage => {
}

const checkStoreIsSupported = (storage: PostHogStorage, key = '__mplssupport__'): boolean => {
if (!window) {
return false
}
try {
const val = 'xyz'
storage.setItem(key, val)
Expand Down

0 comments on commit 70d810b

Please sign in to comment.