Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

posthog-node

Package Overview
Dependencies
Maintainers
6
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

posthog-node - npm Package Compare versions

Comparing version 2.4.0 to 2.5.0

6

CHANGELOG.md

@@ -0,1 +1,5 @@

# 2.5.0 - 2023-02-15
1. Removes shared client from `posthog-node`, getting rid of some race condition bugs when capturing events.
2. Sets minimum version of node.js to 15
# 2.4.0 - 2023-02-02

@@ -5,3 +9,3 @@

# 2.3.0 - 2022-1-26
# 2.3.0 - 2023-1-26

@@ -8,0 +12,0 @@ 1. uses v3 decide endpoint

@@ -21,2 +21,16 @@ /// <reference types="node" />

};
declare enum PostHogPersistedProperty {
AnonymousId = "anonymous_id",
DistinctId = "distinct_id",
Props = "props",
FeatureFlags = "feature_flags",
FeatureFlagPayloads = "feature_flag_payloads",
OverrideFeatureFlags = "override_feature_flags",
Queue = "queue",
OptedOut = "opted_out",
SessionId = "session_id",
SessionLastTimestamp = "session_timestamp",
PersonProperties = "person_properties",
GroupProperties = "group_properties"
}
declare type PostHogFetchOptions = {

@@ -32,2 +46,5 @@ method: 'GET' | 'POST' | 'PUT' | 'PATCH';

};
declare type PosthogCaptureOptions = {
timestamp?: Date;
};
declare type PostHogFetchResponse = {

@@ -38,2 +55,5 @@ status: number;

};
declare type PostHogEventProperties = {
[key: string]: any;
};
declare type PostHogDecideResponse = {

@@ -66,2 +86,81 @@ config: {

interface RetriableOptions {
retryCount?: number;
retryDelay?: number;
retryCheck?: (err: any) => true;
}
declare class SimpleEventEmitter {
events: {
[key: string]: ((...args: any[]) => void)[];
};
constructor();
on(event: string, listener: (...args: any[]) => void): () => void;
emit(event: string, payload: any): void;
}
declare abstract class PostHogCoreStateless {
private apiKey;
host: string;
private flushAt;
private flushInterval;
private requestTimeout;
private captureMode;
private removeDebugCallback?;
private _optoutOverride;
protected _events: SimpleEventEmitter;
protected _flushTimer?: any;
protected _retryOptions: RetriableOptions;
abstract fetch(url: string, options: PostHogFetchOptions): Promise<PostHogFetchResponse>;
abstract getLibraryId(): string;
abstract getLibraryVersion(): string;
abstract getCustomUserAgent(): string | void;
abstract getPersistedProperty<T>(key: PostHogPersistedProperty): T | undefined;
abstract setPersistedProperty<T>(key: PostHogPersistedProperty, value: T | null): void;
constructor(apiKey: string, options?: PosthogCoreOptions);
protected getCommonEventProperties(): any;
get optedOut(): boolean;
optIn(): void;
optOut(): void;
on(event: string, cb: (...args: any[]) => void): () => void;
debug(enabled?: boolean): void;
private buildPayload;
/***
*** TRACKING
***/
protected identifyStateless(distinctId: string, properties?: PostHogEventProperties, options?: PosthogCaptureOptions): this;
protected captureStateless(distinctId: string, event: string, properties?: {
[key: string]: any;
}, options?: PosthogCaptureOptions): this;
protected aliasStateless(alias: string, distinctId: string, properties?: {
[key: string]: any;
}): this;
/***
*** GROUPS
***/
protected groupIdentifyStateless(groupType: string, groupKey: string | number, groupProperties?: PostHogEventProperties, options?: PosthogCaptureOptions, distinctId?: string, eventProperties?: PostHogEventProperties): this;
/***
*** FEATURE FLAGS
***/
protected getDecide(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, extraPayload?: Record<string, any>): Promise<PostHogDecideResponse | undefined>;
protected getFeatureFlagStateless(key: string, distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>): Promise<boolean | string | undefined>;
protected getFeatureFlagPayloadStateless(key: string, distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>): Promise<JsonType | undefined>;
protected getFeatureFlagPayloadsStateless(distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>): Promise<PostHogDecideResponse['featureFlagPayloads'] | undefined>;
protected _parsePayload(response: any): any;
protected getFeatureFlagsStateless(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>): Promise<PostHogDecideResponse['featureFlags'] | undefined>;
protected getFeatureFlagsAndPayloadsStateless(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>): Promise<{
flags: PostHogDecideResponse['featureFlags'] | undefined;
payloads: PostHogDecideResponse['featureFlagPayloads'] | undefined;
}>;
/***
*** QUEUEING AND FLUSHING
***/
protected enqueue(type: string, _message: any, options?: PosthogCaptureOptions): void;
flushAsync(): Promise<any>;
flush(callback?: (err?: any, data?: any) => void): void;
private fetchWithRetry;
shutdownAsync(): Promise<void>;
shutdown(): void;
}
interface IdentifyMessageV1 {

@@ -210,9 +309,15 @@ distinctId: string;

};
declare class PostHog implements PostHogNodeV1 {
private _sharedClient;
declare class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
private _memoryStorage;
private featureFlagsPoller?;
private maxCacheSize;
private options;
distinctIdHasSentFlagCalls: Record<string, string[]>;
constructor(apiKey: string, options?: PostHogOptions);
private reInit;
getPersistedProperty(key: PostHogPersistedProperty): any | undefined;
setPersistedProperty(key: PostHogPersistedProperty, value: any | null): void;
fetch(url: string, options: PostHogFetchOptions): Promise<PostHogFetchResponse>;
getLibraryId(): string;
getLibraryVersion(): string;
getCustomUserAgent(): string;
enable(): void;

@@ -261,8 +366,6 @@ disable(): void;

reloadFeatureFlags(): Promise<void>;
flush(): void;
shutdown(): void;
shutdownAsync(): Promise<void>;
debug(enabled?: boolean): void;
}
export { PostHog, PostHogOptions };

77

lib/posthog-core/src/index.d.ts

@@ -6,3 +6,3 @@ import { PostHogFetchOptions, PostHogFetchResponse, PostHogAutocaptureElement, PostHogDecideResponse, PosthogCoreOptions, PostHogEventProperties, PostHogPersistedProperty, PosthogCaptureOptions, JsonType } from './types';

import { SimpleEventEmitter } from './eventemitter';
export declare abstract class PostHogCore {
export declare abstract class PostHogCoreStateless {
private apiKey;

@@ -14,10 +14,7 @@ host: string;

private captureMode;
private sendFeatureFlagEvent;
private flagCallReported;
private removeDebugCallback?;
private _optoutOverride;
protected _events: SimpleEventEmitter;
protected _flushTimer?: any;
protected _decideResponsePromise?: Promise<PostHogDecideResponse>;
protected _retryOptions: RetriableOptions;
protected _sessionExpirationTimeSeconds: number;
abstract fetch(url: string, options: PostHogFetchOptions): Promise<PostHogFetchResponse>;

@@ -29,5 +26,53 @@ abstract getLibraryId(): string;

abstract setPersistedProperty<T>(key: PostHogPersistedProperty, value: T | null): void;
private _optoutOverride;
constructor(apiKey: string, options?: PosthogCoreOptions);
protected getCommonEventProperties(): any;
get optedOut(): boolean;
optIn(): void;
optOut(): void;
on(event: string, cb: (...args: any[]) => void): () => void;
debug(enabled?: boolean): void;
private buildPayload;
/***
*** TRACKING
***/
protected identifyStateless(distinctId: string, properties?: PostHogEventProperties, options?: PosthogCaptureOptions): this;
protected captureStateless(distinctId: string, event: string, properties?: {
[key: string]: any;
}, options?: PosthogCaptureOptions): this;
protected aliasStateless(alias: string, distinctId: string, properties?: {
[key: string]: any;
}): this;
/***
*** GROUPS
***/
protected groupIdentifyStateless(groupType: string, groupKey: string | number, groupProperties?: PostHogEventProperties, options?: PosthogCaptureOptions, distinctId?: string, eventProperties?: PostHogEventProperties): this;
/***
*** FEATURE FLAGS
***/
protected getDecide(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, extraPayload?: Record<string, any>): Promise<PostHogDecideResponse | undefined>;
protected getFeatureFlagStateless(key: string, distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>): Promise<boolean | string | undefined>;
protected getFeatureFlagPayloadStateless(key: string, distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>): Promise<JsonType | undefined>;
protected getFeatureFlagPayloadsStateless(distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>): Promise<PostHogDecideResponse['featureFlagPayloads'] | undefined>;
protected _parsePayload(response: any): any;
protected getFeatureFlagsStateless(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>): Promise<PostHogDecideResponse['featureFlags'] | undefined>;
protected getFeatureFlagsAndPayloadsStateless(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>): Promise<{
flags: PostHogDecideResponse['featureFlags'] | undefined;
payloads: PostHogDecideResponse['featureFlagPayloads'] | undefined;
}>;
/***
*** QUEUEING AND FLUSHING
***/
protected enqueue(type: string, _message: any, options?: PosthogCaptureOptions): void;
flushAsync(): Promise<any>;
flush(callback?: (err?: any, data?: any) => void): void;
private fetchWithRetry;
shutdownAsync(): Promise<void>;
shutdown(): void;
}
export declare abstract class PostHogCore extends PostHogCoreStateless {
private sendFeatureFlagEvent;
private flagCallReported;
protected _decideResponsePromise?: Promise<PostHogDecideResponse | undefined>;
protected _sessionExpirationTimeSeconds: number;
constructor(apiKey: string, options?: PosthogCoreOptions);
protected setupBootstrap(options?: Partial<PosthogCoreOptions>): void;

@@ -38,9 +83,6 @@ private get props();

private _props;
get optedOut(): boolean;
optIn(): void;
optOut(): void;
on(event: string, cb: (...args: any[]) => void): () => void;
reset(propertiesToKeep?: PostHogPersistedProperty[]): void;
debug(enabled?: boolean): void;
private buildPayload;
protected getCommonEventProperties(): any;
private enrichProperties;
getSessionId(): string | undefined;

@@ -90,3 +132,2 @@ resetSessionId(): void;

getFeatureFlagPayloads(): PostHogDecideResponse['featureFlagPayloads'] | undefined;
_parsePayload(response: any): any;
getFeatureFlags(): PostHogDecideResponse['featureFlags'] | undefined;

@@ -98,17 +139,9 @@ getFeatureFlagsAndPayloads(): {

isFeatureEnabled(key: string): boolean | undefined;
reloadFeatureFlagsAsync(sendAnonDistinctId?: boolean): Promise<PostHogDecideResponse['featureFlags']>;
reloadFeatureFlags(cb?: (err?: Error, flags?: PostHogDecideResponse['featureFlags']) => void): void;
reloadFeatureFlagsAsync(sendAnonDistinctId?: boolean): Promise<PostHogDecideResponse['featureFlags'] | undefined>;
onFeatureFlags(cb: (flags: PostHogDecideResponse['featureFlags']) => void): () => void;
onFeatureFlag(key: string, cb: (value: string | boolean) => void): () => void;
overrideFeatureFlag(flags: PostHogDecideResponse['featureFlags'] | null): void;
/***
*** QUEUEING AND FLUSHING
***/
private enqueue;
flushAsync(): Promise<any>;
flush(callback?: (err?: any, data?: any) => void): void;
private fetchWithRetry;
shutdownAsync(): Promise<void>;
shutdown(): void;
}
export * from './types';
export { LZString };

@@ -1,2 +0,2 @@

import { JsonType, PosthogCoreOptions, PostHogFetchOptions, PostHogFetchResponse, PosthogFlagsAndPayloadsResponse } from '../../posthog-core/src';
import { JsonType, PosthogCoreOptions, PostHogCoreStateless, PostHogFetchOptions, PostHogFetchResponse, PosthogFlagsAndPayloadsResponse, PostHogPersistedProperty } from '../../posthog-core/src';
import { EventMessageV1, GroupIdentifyMessage, IdentifyMessageV1, PostHogNodeV1 } from './types';

@@ -11,9 +11,15 @@ export declare type PostHogOptions = PosthogCoreOptions & {

};
export declare class PostHog implements PostHogNodeV1 {
private _sharedClient;
export declare class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
private _memoryStorage;
private featureFlagsPoller?;
private maxCacheSize;
private options;
distinctIdHasSentFlagCalls: Record<string, string[]>;
constructor(apiKey: string, options?: PostHogOptions);
private reInit;
getPersistedProperty(key: PostHogPersistedProperty): any | undefined;
setPersistedProperty(key: PostHogPersistedProperty, value: any | null): void;
fetch(url: string, options: PostHogFetchOptions): Promise<PostHogFetchResponse>;
getLibraryId(): string;
getLibraryVersion(): string;
getCustomUserAgent(): string;
enable(): void;

@@ -62,6 +68,4 @@ disable(): void;

reloadFeatureFlags(): Promise<void>;
flush(): void;
shutdown(): void;
shutdownAsync(): Promise<void>;
debug(enabled?: boolean): void;
}
{
"name": "posthog-node",
"version": "2.4.0",
"version": "2.5.0",
"description": "PostHog Node.js integration",

@@ -10,3 +10,3 @@ "repository": "PostHog/posthog-node",

"engines": {
"node": ">=14.17.0"
"node": ">=15.0.0"
},

@@ -13,0 +13,0 @@ "license": "MIT",

@@ -5,4 +5,4 @@ import { version } from '../package.json'

JsonType,
PostHogCore,
PosthogCoreOptions,
PostHogCoreStateless,
PostHogFetchOptions,

@@ -33,11 +33,33 @@ PostHogFetchResponse,

class PostHogClient extends PostHogCore {
// The actual exported Nodejs API.
export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
private _memoryStorage = new PostHogMemoryStorage()
constructor(apiKey: string, private options: PostHogOptions = {}) {
private featureFlagsPoller?: FeatureFlagsPoller
private maxCacheSize: number
private options: PostHogOptions
distinctIdHasSentFlagCalls: Record<string, string[]>
constructor(apiKey: string, options: PostHogOptions = {}) {
options.captureMode = options?.captureMode || 'json'
options.preloadFeatureFlags = false // Don't preload as this makes no sense without a distinctId
options.sendFeatureFlagEvent = false // Let `posthog-node` handle this on its own, since we're dealing with multiple distinctIDs
super(apiKey, options)
super(apiKey, options)
this.options = options
if (options.personalApiKey) {
this.featureFlagsPoller = new FeatureFlagsPoller({
pollingInterval:
typeof options.featureFlagsPollingInterval === 'number'
? options.featureFlagsPollingInterval
: THIRTY_SECONDS,
personalApiKey: options.personalApiKey,
projectApiKey: apiKey,
timeout: options.requestTimeout ?? 10000, // 10 seconds
host: this.host,
fetch: options.fetch,
})
}
this.distinctIdHasSentFlagCalls = {}
this.maxCacheSize = options.maxCacheSize || MAX_CACHE_SIZE
}

@@ -53,7 +75,2 @@

getSessionId(): string | undefined {
// Sessions don't make sense for Node
return undefined
}
fetch(url: string, options: PostHogFetchOptions): Promise<PostHogFetchResponse> {

@@ -72,61 +89,32 @@ return this.options.fetch ? this.options.fetch(url, options) : fetch(url, options)

}
}
// The actual exported Nodejs API.
export class PostHog implements PostHogNodeV1 {
private _sharedClient: PostHogClient
private featureFlagsPoller?: FeatureFlagsPoller
private maxCacheSize: number
distinctIdHasSentFlagCalls: Record<string, string[]>
constructor(apiKey: string, options: PostHogOptions = {}) {
this._sharedClient = new PostHogClient(apiKey, options)
if (options.personalApiKey) {
this.featureFlagsPoller = new FeatureFlagsPoller({
pollingInterval:
typeof options.featureFlagsPollingInterval === 'number'
? options.featureFlagsPollingInterval
: THIRTY_SECONDS,
personalApiKey: options.personalApiKey,
projectApiKey: apiKey,
timeout: options.requestTimeout ?? 10000, // 10 seconds
host: this._sharedClient.host,
fetch: options.fetch,
})
}
this.distinctIdHasSentFlagCalls = {}
this.maxCacheSize = options.maxCacheSize || MAX_CACHE_SIZE
}
private reInit(distinctId: string): void {
// Certain properties we want to persist. Queue is persisted always by default.
this._sharedClient.reset([PostHogPersistedProperty.OptedOut])
this._sharedClient.setPersistedProperty(PostHogPersistedProperty.DistinctId, distinctId)
}
enable(): void {
return this._sharedClient.optIn()
return super.optIn()
}
disable(): void {
return this._sharedClient.optOut()
return super.optOut()
}
capture({ distinctId, event, properties, groups, sendFeatureFlags, timestamp }: EventMessageV1): void {
this.reInit(distinctId)
if (groups) {
this._sharedClient.groups(groups)
const _capture = (props: EventMessageV1['properties']): void => {
super.captureStateless(distinctId, event, props, { timestamp })
}
const _capture = (): void => {
this._sharedClient.capture(event, properties, { timestamp })
}
if (sendFeatureFlags) {
this._sharedClient.reloadFeatureFlagsAsync(false).finally(() => {
_capture()
super.getFeatureFlagsStateless(distinctId, groups).then((flags) => {
const featureVariantProperties: Record<string, string | boolean> = {}
if (flags) {
for (const [feature, variant] of Object.entries(flags)) {
featureVariantProperties[`$feature/${feature}`] = variant
}
}
const flagProperties = {
$active_feature_flags: flags ? Object.keys(flags) : undefined,
...featureVariantProperties,
}
_capture({ ...properties, $groups: groups, ...flagProperties })
})
} else {
_capture()
_capture({ ...properties, $groups: groups })
}

@@ -136,9 +124,7 @@ }

identify({ distinctId, properties }: IdentifyMessageV1): void {
this.reInit(distinctId)
this._sharedClient.identify(distinctId, properties)
super.identifyStateless(distinctId, properties)
}
alias(data: { distinctId: string; alias: string }): void {
this.reInit(data.distinctId)
this._sharedClient.alias(data.alias)
super.aliasStateless(data.alias, data.distinctId)
}

@@ -179,16 +165,3 @@

if (!flagWasLocallyEvaluated && !onlyEvaluateLocally) {
this.reInit(distinctId)
if (groups != undefined) {
this._sharedClient.groups(groups)
}
if (personProperties) {
this._sharedClient.personProperties(personProperties)
}
if (groupProperties) {
this._sharedClient.groupProperties(groupProperties)
}
await this._sharedClient.reloadFeatureFlagsAsync(false)
response = this._sharedClient.getFeatureFlag(key)
response = await super.getFeatureFlagStateless(key, distinctId, groups, personProperties, groupProperties)
}

@@ -269,16 +242,3 @@

if (!payloadWasLocallyEvaluated && !onlyEvaluateLocally) {
this.reInit(distinctId)
if (groups != undefined) {
this._sharedClient.groups(groups)
}
if (personProperties) {
this._sharedClient.personProperties(personProperties)
}
if (groupProperties) {
this._sharedClient.groupProperties(groupProperties)
}
await this._sharedClient.reloadFeatureFlagsAsync(false)
response = this._sharedClient.getFeatureFlagPayload(key)
response = await super.getFeatureFlagPayloadStateless(key, distinctId, groups, personProperties, groupProperties)
}

@@ -358,16 +318,8 @@

if (fallbackToDecide && !onlyEvaluateLocally) {
this.reInit(distinctId)
if (groups) {
this._sharedClient.groups(groups)
}
if (personProperties) {
this._sharedClient.personProperties(personProperties)
}
if (groupProperties) {
this._sharedClient.groupProperties(groupProperties)
}
await this._sharedClient.reloadFeatureFlagsAsync(false)
const remoteEvaluationResult = this._sharedClient.getFeatureFlagsAndPayloads()
const remoteEvaluationResult = await super.getFeatureFlagsAndPayloadsStateless(
distinctId,
groups,
personProperties,
groupProperties
)
featureFlags = {

@@ -387,4 +339,3 @@ ...featureFlags,

groupIdentify({ groupType, groupKey, properties }: GroupIdentifyMessage): void {
this.reInit(`$${groupType}_${groupKey}`)
this._sharedClient.groupIdentify(groupType, groupKey, properties)
super.groupIdentifyStateless(groupType, groupKey, properties)
}

@@ -396,6 +347,2 @@

flush(): void {
this._sharedClient.flush()
}
shutdown(): void {

@@ -407,8 +354,4 @@ void this.shutdownAsync()

this.featureFlagsPoller?.stopPoller()
return this._sharedClient.shutdownAsync()
return super.shutdownAsync()
}
debug(enabled?: boolean): void {
return this._sharedClient.debug(enabled)
}
}

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc