posthog-node 4.13.0 → 4.15.0

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.
@@ -3,6 +3,7 @@ import { RetriableOptions } from './utils';
3
3
  import { LZString } from './lz-string';
4
4
  import { SimpleEventEmitter } from './eventemitter';
5
5
  export * as utils from './utils';
6
+ export declare function logFlushError(err: any): Promise<void>;
6
7
  export declare abstract class PostHogCoreStateless {
7
8
  readonly apiKey: string;
8
9
  readonly host: string;
@@ -52,12 +53,19 @@ export declare abstract class PostHogCoreStateless {
52
53
  *** TRACKING
53
54
  ***/
54
55
  protected identifyStateless(distinctId: string, properties?: PostHogEventProperties, options?: PostHogCaptureOptions): void;
56
+ protected identifyStatelessImmediate(distinctId: string, properties?: PostHogEventProperties, options?: PostHogCaptureOptions): Promise<void>;
55
57
  protected captureStateless(distinctId: string, event: string, properties?: {
56
58
  [key: string]: any;
57
59
  }, options?: PostHogCaptureOptions): void;
60
+ protected captureStatelessImmediate(distinctId: string, event: string, properties?: {
61
+ [key: string]: any;
62
+ }, options?: PostHogCaptureOptions): Promise<void>;
58
63
  protected aliasStateless(alias: string, distinctId: string, properties?: {
59
64
  [key: string]: any;
60
65
  }, options?: PostHogCaptureOptions): void;
66
+ protected aliasStatelessImmediate(alias: string, distinctId: string, properties?: {
67
+ [key: string]: any;
68
+ }, options?: PostHogCaptureOptions): Promise<void>;
61
69
  /***
62
70
  *** GROUPS
63
71
  ***/
@@ -92,10 +100,22 @@ export declare abstract class PostHogCoreStateless {
92
100
  *** SURVEYS
93
101
  ***/
94
102
  getSurveysStateless(): Promise<SurveyResponse['surveys']>;
103
+ /***
104
+ *** SUPER PROPERTIES
105
+ ***/
106
+ private _props;
107
+ protected get props(): PostHogEventProperties;
108
+ protected set props(val: PostHogEventProperties | undefined);
109
+ register(properties: {
110
+ [key: string]: any;
111
+ }): Promise<void>;
112
+ unregister(property: string): Promise<void>;
95
113
  /***
96
114
  *** QUEUEING AND FLUSHING
97
115
  ***/
98
116
  protected enqueue(type: string, _message: any, options?: PostHogCaptureOptions): void;
117
+ protected sendImmediate(type: string, _message: any, options?: PostHogCaptureOptions): Promise<void>;
118
+ private prepareMessage;
99
119
  private clearFlushTimer;
100
120
  /**
101
121
  * Helper for flushing the queue in the background
@@ -118,10 +138,7 @@ export declare abstract class PostHogCore extends PostHogCoreStateless {
118
138
  protected sessionProps: PostHogEventProperties;
119
139
  constructor(apiKey: string, options?: PostHogCoreOptions);
120
140
  protected setupBootstrap(options?: Partial<PostHogCoreOptions>): void;
121
- private get props();
122
- private set props(value);
123
141
  private clearProps;
124
- private _props;
125
142
  on(event: string, cb: (...args: any[]) => void): () => void;
126
143
  reset(propertiesToKeep?: PostHogPersistedProperty[]): void;
127
144
  protected getCommonEventProperties(): any;
@@ -139,10 +156,6 @@ export declare abstract class PostHogCore extends PostHogCoreStateless {
139
156
  * * @returns {string} The stored distinct ID. This may be an empty string if the client is not yet fully initialized.
140
157
  */
141
158
  getDistinctId(): string;
142
- unregister(property: string): Promise<void>;
143
- register(properties: {
144
- [key: string]: any;
145
- }): Promise<void>;
146
159
  registerForSession(properties: {
147
160
  [key: string]: any;
148
161
  }): void;
@@ -1,6 +1,7 @@
1
1
  import { FetchLike } from './types';
2
2
  export declare const NEW_FLAGS_ROLLOUT_PERCENTAGE = 1;
3
3
  export declare const NEW_FLAGS_EXCLUDED_HASHES: Set<string>;
4
+ export declare const STRING_FORMAT = "utf8";
4
5
  export declare function assert(truthyValue: any, message: string): void;
5
6
  export declare function removeTrailingSlash(url: string): string;
6
7
  export interface RetriableOptions {
@@ -32,12 +32,19 @@ export declare class PostHog extends PostHogCoreStateless implements PostHogNode
32
32
  disable(): Promise<void>;
33
33
  debug(enabled?: boolean): void;
34
34
  capture(props: EventMessage): void;
35
+ captureImmediate(props: EventMessage): Promise<void>;
35
36
  identify({ distinctId, properties, disableGeoip }: IdentifyMessage): void;
37
+ identifyImmediate({ distinctId, properties, disableGeoip }: IdentifyMessage): Promise<void>;
36
38
  alias(data: {
37
39
  distinctId: string;
38
40
  alias: string;
39
41
  disableGeoip?: boolean;
40
42
  }): void;
43
+ aliasImmediate(data: {
44
+ distinctId: string;
45
+ alias: string;
46
+ disableGeoip?: boolean;
47
+ }): Promise<void>;
41
48
  isLocalEvaluationReady(): boolean;
42
49
  waitForLocalEvaluationReady(timeoutMs?: number): Promise<boolean>;
43
50
  getFeatureFlag(key: string, distinctId: string, options?: {
@@ -70,6 +70,15 @@ export type PostHogNodeV1 = {
70
70
  * @param sendFeatureFlags OPTIONAL | Used with experiments. Determines whether to send feature flag values with the event.
71
71
  */
72
72
  capture({ distinctId, event, properties, groups, sendFeatureFlags }: EventMessage): void;
73
+ /**
74
+ * @description Capture an event immediately. Useful for edge environments where the usual queue-based sending is not preferable. Do not mix immediate and non-immediate calls.
75
+ * @param distinctId which uniquely identifies your user
76
+ * @param event We recommend using [verb] [noun], like movie played or movie updated to easily identify what your events mean later on.
77
+ * @param properties OPTIONAL | which can be a object with any information you'd like to add
78
+ * @param groups OPTIONAL | object of what groups are related to this event, example: { company: 'id:5' }. Can be used to analyze companies instead of users.
79
+ * @param sendFeatureFlags OPTIONAL | Used with experiments. Determines whether to send feature flag values with the event.
80
+ */
81
+ captureImmediate({ distinctId, event, properties, groups, sendFeatureFlags }: EventMessage): Promise<void>;
73
82
  /**
74
83
  * @description Identify lets you add metadata on your users so you can more easily identify who they are in PostHog,
75
84
  * and even do things like segment users by these properties.
@@ -78,6 +87,13 @@ export type PostHogNodeV1 = {
78
87
  * @param properties with a dict with any key: value pairs
79
88
  */
80
89
  identify({ distinctId, properties }: IdentifyMessage): void;
90
+ /**
91
+ * @description Identify lets you add metadata on your users so you can more easily identify who they are in PostHog.
92
+ * Useful for edge environments where the usual queue-based sending is not preferable. Do not mix immediate and non-immediate calls.
93
+ * @param distinctId which uniquely identifies your user
94
+ * @param properties with a dict with any key: value pairs
95
+ */
96
+ identifyImmediate({ distinctId, properties }: IdentifyMessage): Promise<void>;
81
97
  /**
82
98
  * @description To marry up whatever a user does before they sign up or log in with what they do after you need to make an alias call.
83
99
  * This will allow you to answer questions like "Which marketing channels leads to users churning after a month?"
@@ -93,6 +109,16 @@ export type PostHogNodeV1 = {
93
109
  distinctId: string;
94
110
  alias: string;
95
111
  }): void;
112
+ /**
113
+ * @description To marry up whatever a user does before they sign up or log in with what they do after you need to make an alias call.
114
+ * Useful for edge environments where the usual queue-based sending is not preferable. Do not mix immediate and non-immediate calls.
115
+ * @param distinctId the current unique id
116
+ * @param alias the unique ID of the user before
117
+ */
118
+ aliasImmediate(data: {
119
+ distinctId: string;
120
+ alias: string;
121
+ }): Promise<void>;
96
122
  /**
97
123
  * @description PostHog feature flags (https://posthog.com/docs/features/feature-flags)
98
124
  * allow you to safely deploy and roll back new features. Once you've created a feature flag in PostHog,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "posthog-node",
3
- "version": "4.13.0",
3
+ "version": "4.15.0",
4
4
  "description": "PostHog Node.js integration",
5
5
  "repository": {
6
6
  "type": "git",
@@ -199,6 +199,84 @@ export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
199
199
  this.addPendingPromise(capturePromise)
200
200
  }
201
201
 
202
+ async captureImmediate(props: EventMessage): Promise<void> {
203
+ if (typeof props === 'string') {
204
+ this.logMsgIfDebug(() =>
205
+ console.warn('Called capture() with a string as the first argument when an object was expected.')
206
+ )
207
+ }
208
+ const { distinctId, event, properties, groups, sendFeatureFlags, timestamp, disableGeoip, uuid }: EventMessage =
209
+ props
210
+
211
+ const _capture = (props: EventMessage['properties']): Promise<void> => {
212
+ return super.captureStatelessImmediate(distinctId, event, props, { timestamp, disableGeoip, uuid })
213
+ }
214
+
215
+ const _getFlags = async (
216
+ distinctId: EventMessage['distinctId'],
217
+ groups: EventMessage['groups'],
218
+ disableGeoip: EventMessage['disableGeoip']
219
+ ): Promise<PostHogDecideResponse['featureFlags'] | undefined> => {
220
+ return (await super.getFeatureFlagsStateless(distinctId, groups, undefined, undefined, disableGeoip)).flags
221
+ }
222
+
223
+ const capturePromise = Promise.resolve()
224
+ .then(async () => {
225
+ if (sendFeatureFlags) {
226
+ // If we are sending feature flags, we need to make sure we have the latest flags
227
+ // return await super.getFeatureFlagsStateless(distinctId, groups, undefined, undefined, disableGeoip)
228
+ return await _getFlags(distinctId, groups, disableGeoip)
229
+ }
230
+
231
+ if (event === '$feature_flag_called') {
232
+ // If we're capturing a $feature_flag_called event, we don't want to enrich the event with cached flags that may be out of date.
233
+ return {}
234
+ }
235
+
236
+ if ((this.featureFlagsPoller?.featureFlags?.length || 0) > 0) {
237
+ // Otherwise we may as well check for the flags locally and include them if they are already loaded
238
+ const groupsWithStringValues: Record<string, string> = {}
239
+ for (const [key, value] of Object.entries(groups || {})) {
240
+ groupsWithStringValues[key] = String(value)
241
+ }
242
+
243
+ return await this.getAllFlags(distinctId, {
244
+ groups: groupsWithStringValues,
245
+ disableGeoip,
246
+ onlyEvaluateLocally: true,
247
+ })
248
+ }
249
+ return {}
250
+ })
251
+ .then((flags) => {
252
+ // Derive the relevant flag properties to add
253
+ const additionalProperties: Record<string, any> = {}
254
+ if (flags) {
255
+ for (const [feature, variant] of Object.entries(flags)) {
256
+ additionalProperties[`$feature/${feature}`] = variant
257
+ }
258
+ }
259
+ const activeFlags = Object.keys(flags || {})
260
+ .filter((flag) => flags?.[flag] !== false)
261
+ .sort()
262
+ if (activeFlags.length > 0) {
263
+ additionalProperties['$active_feature_flags'] = activeFlags
264
+ }
265
+
266
+ return additionalProperties
267
+ })
268
+ .catch(() => {
269
+ // Something went wrong getting the flag info - we should capture the event anyways
270
+ return {}
271
+ })
272
+ .then((additionalProperties) => {
273
+ // No matter what - capture the event
274
+ _capture({ ...additionalProperties, ...properties, $groups: groups })
275
+ })
276
+
277
+ await capturePromise
278
+ }
279
+
202
280
  identify({ distinctId, properties, disableGeoip }: IdentifyMessage): void {
203
281
  // Catch properties passed as $set and move them to the top level
204
282
 
@@ -219,10 +297,32 @@ export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
219
297
  )
220
298
  }
221
299
 
300
+ async identifyImmediate({ distinctId, properties, disableGeoip }: IdentifyMessage): Promise<void> {
301
+ // promote $set and $set_once to top level
302
+ const userPropsOnce = properties?.$set_once
303
+ delete properties?.$set_once
304
+
305
+ // if no $set is provided we assume all properties are $set
306
+ const userProps = properties?.$set || properties
307
+
308
+ await super.identifyStatelessImmediate(
309
+ distinctId,
310
+ {
311
+ $set: userProps,
312
+ $set_once: userPropsOnce,
313
+ },
314
+ { disableGeoip }
315
+ )
316
+ }
317
+
222
318
  alias(data: { distinctId: string; alias: string; disableGeoip?: boolean }): void {
223
319
  super.aliasStateless(data.alias, data.distinctId, undefined, { disableGeoip: data.disableGeoip })
224
320
  }
225
321
 
322
+ async aliasImmediate(data: { distinctId: string; alias: string; disableGeoip?: boolean }): Promise<void> {
323
+ await super.aliasStatelessImmediate(data.alias, data.distinctId, undefined, { disableGeoip: data.disableGeoip })
324
+ }
325
+
226
326
  isLocalEvaluationReady(): boolean {
227
327
  return this.featureFlagsPoller?.isLocalEvaluationReady() ?? false
228
328
  }
package/src/types.ts CHANGED
@@ -79,6 +79,16 @@ export type PostHogNodeV1 = {
79
79
  */
80
80
  capture({ distinctId, event, properties, groups, sendFeatureFlags }: EventMessage): void
81
81
 
82
+ /**
83
+ * @description Capture an event immediately. Useful for edge environments where the usual queue-based sending is not preferable. Do not mix immediate and non-immediate calls.
84
+ * @param distinctId which uniquely identifies your user
85
+ * @param event We recommend using [verb] [noun], like movie played or movie updated to easily identify what your events mean later on.
86
+ * @param properties OPTIONAL | which can be a object with any information you'd like to add
87
+ * @param groups OPTIONAL | object of what groups are related to this event, example: { company: 'id:5' }. Can be used to analyze companies instead of users.
88
+ * @param sendFeatureFlags OPTIONAL | Used with experiments. Determines whether to send feature flag values with the event.
89
+ */
90
+ captureImmediate({ distinctId, event, properties, groups, sendFeatureFlags }: EventMessage): Promise<void>
91
+
82
92
  /**
83
93
  * @description Identify lets you add metadata on your users so you can more easily identify who they are in PostHog,
84
94
  * and even do things like segment users by these properties.
@@ -88,6 +98,14 @@ export type PostHogNodeV1 = {
88
98
  */
89
99
  identify({ distinctId, properties }: IdentifyMessage): void
90
100
 
101
+ /**
102
+ * @description Identify lets you add metadata on your users so you can more easily identify who they are in PostHog.
103
+ * Useful for edge environments where the usual queue-based sending is not preferable. Do not mix immediate and non-immediate calls.
104
+ * @param distinctId which uniquely identifies your user
105
+ * @param properties with a dict with any key: value pairs
106
+ */
107
+ identifyImmediate({ distinctId, properties }: IdentifyMessage): Promise<void>
108
+
91
109
  /**
92
110
  * @description To marry up whatever a user does before they sign up or log in with what they do after you need to make an alias call.
93
111
  * This will allow you to answer questions like "Which marketing channels leads to users churning after a month?"
@@ -101,6 +119,14 @@ export type PostHogNodeV1 = {
101
119
  */
102
120
  alias(data: { distinctId: string; alias: string }): void
103
121
 
122
+ /**
123
+ * @description To marry up whatever a user does before they sign up or log in with what they do after you need to make an alias call.
124
+ * Useful for edge environments where the usual queue-based sending is not preferable. Do not mix immediate and non-immediate calls.
125
+ * @param distinctId the current unique id
126
+ * @param alias the unique ID of the user before
127
+ */
128
+ aliasImmediate(data: { distinctId: string; alias: string }): Promise<void>
129
+
104
130
  /**
105
131
  * @description PostHog feature flags (https://posthog.com/docs/features/feature-flags)
106
132
  * allow you to safely deploy and roll back new features. Once you've created a feature flag in PostHog,