posthog-node 2.6.0 → 3.0.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.
@@ -13,6 +13,7 @@ export declare abstract class PostHogCoreStateless {
13
13
  private removeDebugCallback?;
14
14
  private debugMode;
15
15
  private pendingPromises;
16
+ private disableGeoip;
16
17
  private _optoutOverride;
17
18
  protected _events: SimpleEventEmitter;
18
19
  protected _flushTimer?: any;
@@ -40,7 +41,7 @@ export declare abstract class PostHogCoreStateless {
40
41
  }, options?: PosthogCaptureOptions): this;
41
42
  protected aliasStateless(alias: string, distinctId: string, properties?: {
42
43
  [key: string]: any;
43
- }): this;
44
+ }, options?: PosthogCaptureOptions): this;
44
45
  /***
45
46
  *** GROUPS
46
47
  ***/
@@ -49,12 +50,12 @@ export declare abstract class PostHogCoreStateless {
49
50
  *** FEATURE FLAGS
50
51
  ***/
51
52
  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>;
52
- protected getFeatureFlagStateless(key: string, distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>): Promise<boolean | string | undefined>;
53
- protected getFeatureFlagPayloadStateless(key: string, distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>): Promise<JsonType | undefined>;
54
- protected getFeatureFlagPayloadsStateless(distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>): Promise<PostHogDecideResponse['featureFlagPayloads'] | undefined>;
53
+ protected getFeatureFlagStateless(key: string, distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean): Promise<boolean | string | undefined>;
54
+ protected getFeatureFlagPayloadStateless(key: string, distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean): Promise<JsonType | undefined>;
55
+ protected getFeatureFlagPayloadsStateless(distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean): Promise<PostHogDecideResponse['featureFlagPayloads'] | undefined>;
55
56
  protected _parsePayload(response: any): any;
56
- protected getFeatureFlagsStateless(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>): Promise<PostHogDecideResponse['featureFlags'] | undefined>;
57
- protected getFeatureFlagsAndPayloadsStateless(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>): Promise<{
57
+ protected getFeatureFlagsStateless(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean): Promise<PostHogDecideResponse['featureFlags'] | undefined>;
58
+ protected getFeatureFlagsAndPayloadsStateless(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean): Promise<{
58
59
  flags: PostHogDecideResponse['featureFlags'] | undefined;
59
60
  payloads: PostHogDecideResponse['featureFlagPayloads'] | undefined;
60
61
  }>;
@@ -17,6 +17,7 @@ export declare type PosthogCoreOptions = {
17
17
  requestTimeout?: number;
18
18
  sessionExpirationTimeSeconds?: number;
19
19
  captureMode?: 'json' | 'form';
20
+ disableGeoip?: boolean;
20
21
  };
21
22
  export declare enum PostHogPersistedProperty {
22
23
  AnonymousId = "anonymous_id",
@@ -44,6 +45,7 @@ export declare type PostHogFetchOptions = {
44
45
  };
45
46
  export declare type PosthogCaptureOptions = {
46
47
  timestamp?: Date;
48
+ disableGeoip?: boolean;
47
49
  };
48
50
  export declare type PostHogFetchResponse = {
49
51
  status: number;
@@ -24,11 +24,12 @@ export declare class PostHog extends PostHogCoreStateless implements PostHogNode
24
24
  enable(): void;
25
25
  disable(): void;
26
26
  debug(enabled?: boolean): void;
27
- capture({ distinctId, event, properties, groups, sendFeatureFlags, timestamp }: EventMessageV1): void;
28
- identify({ distinctId, properties }: IdentifyMessageV1): void;
27
+ capture({ distinctId, event, properties, groups, sendFeatureFlags, timestamp, disableGeoip }: EventMessageV1): void;
28
+ identify({ distinctId, properties, disableGeoip }: IdentifyMessageV1): void;
29
29
  alias(data: {
30
30
  distinctId: string;
31
31
  alias: string;
32
+ disableGeoip?: boolean;
32
33
  }): void;
33
34
  getFeatureFlag(key: string, distinctId: string, options?: {
34
35
  groups?: Record<string, string>;
@@ -36,6 +37,7 @@ export declare class PostHog extends PostHogCoreStateless implements PostHogNode
36
37
  groupProperties?: Record<string, Record<string, string>>;
37
38
  onlyEvaluateLocally?: boolean;
38
39
  sendFeatureFlagEvents?: boolean;
40
+ disableGeoip?: boolean;
39
41
  }): Promise<string | boolean | undefined>;
40
42
  getFeatureFlagPayload(key: string, distinctId: string, matchValue?: string | boolean, options?: {
41
43
  groups?: Record<string, string>;
@@ -43,6 +45,7 @@ export declare class PostHog extends PostHogCoreStateless implements PostHogNode
43
45
  groupProperties?: Record<string, Record<string, string>>;
44
46
  onlyEvaluateLocally?: boolean;
45
47
  sendFeatureFlagEvents?: boolean;
48
+ disableGeoip?: boolean;
46
49
  }): Promise<JsonType | undefined>;
47
50
  isFeatureEnabled(key: string, distinctId: string, options?: {
48
51
  groups?: Record<string, string>;
@@ -50,20 +53,23 @@ export declare class PostHog extends PostHogCoreStateless implements PostHogNode
50
53
  groupProperties?: Record<string, Record<string, string>>;
51
54
  onlyEvaluateLocally?: boolean;
52
55
  sendFeatureFlagEvents?: boolean;
56
+ disableGeoip?: boolean;
53
57
  }): Promise<boolean | undefined>;
54
58
  getAllFlags(distinctId: string, options?: {
55
59
  groups?: Record<string, string>;
56
60
  personProperties?: Record<string, string>;
57
61
  groupProperties?: Record<string, Record<string, string>>;
58
62
  onlyEvaluateLocally?: boolean;
63
+ disableGeoip?: boolean;
59
64
  }): Promise<Record<string, string | boolean>>;
60
65
  getAllFlagsAndPayloads(distinctId: string, options?: {
61
66
  groups?: Record<string, string>;
62
67
  personProperties?: Record<string, string>;
63
68
  groupProperties?: Record<string, Record<string, string>>;
64
69
  onlyEvaluateLocally?: boolean;
70
+ disableGeoip?: boolean;
65
71
  }): Promise<PosthogFlagsAndPayloadsResponse>;
66
- groupIdentify({ groupType, groupKey, properties, distinctId }: GroupIdentifyMessage): void;
72
+ groupIdentify({ groupType, groupKey, properties, distinctId, disableGeoip }: GroupIdentifyMessage): void;
67
73
  reloadFeatureFlags(): Promise<void>;
68
74
  shutdown(): void;
69
75
  shutdownAsync(): Promise<void>;
@@ -2,6 +2,7 @@ import { JsonType } from '../../posthog-core/src';
2
2
  export interface IdentifyMessageV1 {
3
3
  distinctId: string;
4
4
  properties?: Record<string | number, any>;
5
+ disableGeoip?: boolean;
5
6
  }
6
7
  export interface EventMessageV1 extends IdentifyMessageV1 {
7
8
  event: string;
@@ -14,6 +15,7 @@ export interface GroupIdentifyMessage {
14
15
  groupKey: string;
15
16
  properties?: Record<string | number, any>;
16
17
  distinctId?: string;
18
+ disableGeoip?: boolean;
17
19
  }
18
20
  export declare type PropertyGroup = {
19
21
  type: 'AND' | 'OR';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "posthog-node",
3
- "version": "2.6.0",
3
+ "version": "3.0.0",
4
4
  "description": "PostHog Node.js integration",
5
5
  "repository": "PostHog/posthog-node",
6
6
  "scripts": {
@@ -97,13 +97,13 @@ export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
97
97
  this.featureFlagsPoller?.debug(enabled)
98
98
  }
99
99
 
100
- capture({ distinctId, event, properties, groups, sendFeatureFlags, timestamp }: EventMessageV1): void {
100
+ capture({ distinctId, event, properties, groups, sendFeatureFlags, timestamp, disableGeoip }: EventMessageV1): void {
101
101
  const _capture = (props: EventMessageV1['properties']): void => {
102
- super.captureStateless(distinctId, event, props, { timestamp })
102
+ super.captureStateless(distinctId, event, props, { timestamp, disableGeoip })
103
103
  }
104
104
 
105
105
  if (sendFeatureFlags) {
106
- super.getFeatureFlagsStateless(distinctId, groups).then((flags) => {
106
+ super.getFeatureFlagsStateless(distinctId, groups, undefined, undefined, disableGeoip).then((flags) => {
107
107
  const featureVariantProperties: Record<string, string | boolean> = {}
108
108
  if (flags) {
109
109
  for (const [feature, variant] of Object.entries(flags)) {
@@ -124,17 +124,21 @@ export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
124
124
  }
125
125
  }
126
126
 
127
- identify({ distinctId, properties }: IdentifyMessageV1): void {
127
+ identify({ distinctId, properties, disableGeoip }: IdentifyMessageV1): void {
128
128
  // Catch properties passed as $set and move them to the top level
129
129
  const personProperties = properties?.$set || properties
130
130
 
131
- super.identifyStateless(distinctId, {
132
- $set: personProperties,
133
- })
131
+ super.identifyStateless(
132
+ distinctId,
133
+ {
134
+ $set: personProperties,
135
+ },
136
+ { disableGeoip }
137
+ )
134
138
  }
135
139
 
136
- alias(data: { distinctId: string; alias: string }): void {
137
- super.aliasStateless(data.alias, data.distinctId)
140
+ alias(data: { distinctId: string; alias: string; disableGeoip?: boolean }): void {
141
+ super.aliasStateless(data.alias, data.distinctId, undefined, { disableGeoip: data.disableGeoip })
138
142
  }
139
143
 
140
144
  async getFeatureFlag(
@@ -146,9 +150,10 @@ export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
146
150
  groupProperties?: Record<string, Record<string, string>>
147
151
  onlyEvaluateLocally?: boolean
148
152
  sendFeatureFlagEvents?: boolean
153
+ disableGeoip?: boolean
149
154
  }
150
155
  ): Promise<string | boolean | undefined> {
151
- const { groups, personProperties, groupProperties } = options || {}
156
+ const { groups, personProperties, groupProperties, disableGeoip } = options || {}
152
157
  let { onlyEvaluateLocally, sendFeatureFlagEvents } = options || {}
153
158
 
154
159
  // set defaults
@@ -170,7 +175,14 @@ export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
170
175
  const flagWasLocallyEvaluated = response !== undefined
171
176
 
172
177
  if (!flagWasLocallyEvaluated && !onlyEvaluateLocally) {
173
- response = await super.getFeatureFlagStateless(key, distinctId, groups, personProperties, groupProperties)
178
+ response = await super.getFeatureFlagStateless(
179
+ key,
180
+ distinctId,
181
+ groups,
182
+ personProperties,
183
+ groupProperties,
184
+ disableGeoip
185
+ )
174
186
  }
175
187
 
176
188
  const featureFlagReportedKey = `${key}_${response}`
@@ -197,6 +209,7 @@ export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
197
209
  locally_evaluated: flagWasLocallyEvaluated,
198
210
  },
199
211
  groups,
212
+ disableGeoip,
200
213
  })
201
214
  }
202
215
  return response
@@ -212,9 +225,10 @@ export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
212
225
  groupProperties?: Record<string, Record<string, string>>
213
226
  onlyEvaluateLocally?: boolean
214
227
  sendFeatureFlagEvents?: boolean
228
+ disableGeoip?: boolean
215
229
  }
216
230
  ): Promise<JsonType | undefined> {
217
- const { groups, personProperties, groupProperties } = options || {}
231
+ const { groups, personProperties, groupProperties, disableGeoip } = options || {}
218
232
  let { onlyEvaluateLocally, sendFeatureFlagEvents } = options || {}
219
233
  let response = undefined
220
234
 
@@ -246,7 +260,14 @@ export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
246
260
  const payloadWasLocallyEvaluated = response !== undefined
247
261
 
248
262
  if (!payloadWasLocallyEvaluated && !onlyEvaluateLocally) {
249
- response = await super.getFeatureFlagPayloadStateless(key, distinctId, groups, personProperties, groupProperties)
263
+ response = await super.getFeatureFlagPayloadStateless(
264
+ key,
265
+ distinctId,
266
+ groups,
267
+ personProperties,
268
+ groupProperties,
269
+ disableGeoip
270
+ )
250
271
  }
251
272
 
252
273
  try {
@@ -265,6 +286,7 @@ export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
265
286
  groupProperties?: Record<string, Record<string, string>>
266
287
  onlyEvaluateLocally?: boolean
267
288
  sendFeatureFlagEvents?: boolean
289
+ disableGeoip?: boolean
268
290
  }
269
291
  ): Promise<boolean | undefined> {
270
292
  const feat = await this.getFeatureFlag(key, distinctId, options)
@@ -281,6 +303,7 @@ export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
281
303
  personProperties?: Record<string, string>
282
304
  groupProperties?: Record<string, Record<string, string>>
283
305
  onlyEvaluateLocally?: boolean
306
+ disableGeoip?: boolean
284
307
  }
285
308
  ): Promise<Record<string, string | boolean>> {
286
309
  const response = await this.getAllFlagsAndPayloads(distinctId, options)
@@ -294,9 +317,10 @@ export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
294
317
  personProperties?: Record<string, string>
295
318
  groupProperties?: Record<string, Record<string, string>>
296
319
  onlyEvaluateLocally?: boolean
320
+ disableGeoip?: boolean
297
321
  }
298
322
  ): Promise<PosthogFlagsAndPayloadsResponse> {
299
- const { groups, personProperties, groupProperties } = options || {}
323
+ const { groups, personProperties, groupProperties, disableGeoip } = options || {}
300
324
  let { onlyEvaluateLocally } = options || {}
301
325
 
302
326
  // set defaults
@@ -325,7 +349,8 @@ export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
325
349
  distinctId,
326
350
  groups,
327
351
  personProperties,
328
- groupProperties
352
+ groupProperties,
353
+ disableGeoip
329
354
  )
330
355
  featureFlags = {
331
356
  ...featureFlags,
@@ -340,8 +365,8 @@ export class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
340
365
  return { featureFlags, featureFlagPayloads }
341
366
  }
342
367
 
343
- groupIdentify({ groupType, groupKey, properties, distinctId }: GroupIdentifyMessage): void {
344
- super.groupIdentifyStateless(groupType, groupKey, properties, undefined, distinctId)
368
+ groupIdentify({ groupType, groupKey, properties, distinctId, disableGeoip }: GroupIdentifyMessage): void {
369
+ super.groupIdentifyStateless(groupType, groupKey, properties, { disableGeoip }, distinctId)
345
370
  }
346
371
 
347
372
  async reloadFeatureFlags(): Promise<void> {
package/src/types.ts CHANGED
@@ -3,6 +3,7 @@ import { JsonType } from '../../posthog-core/src'
3
3
  export interface IdentifyMessageV1 {
4
4
  distinctId: string
5
5
  properties?: Record<string | number, any>
6
+ disableGeoip?: boolean
6
7
  }
7
8
 
8
9
  export interface EventMessageV1 extends IdentifyMessageV1 {
@@ -17,6 +18,7 @@ export interface GroupIdentifyMessage {
17
18
  groupKey: string // Unique identifier for the group
18
19
  properties?: Record<string | number, any>
19
20
  distinctId?: string // optional distinctId to associate message with a person
21
+ disableGeoip?: boolean
20
22
  }
21
23
 
22
24
  export type PropertyGroup = {
@@ -336,6 +336,7 @@ describe('local evaluation', () => {
336
336
  groups: {},
337
337
  person_properties: { region: 'USA', email: 'a@b.com' },
338
338
  group_properties: {},
339
+ geoip_disable: true,
339
340
  }),
340
341
  })
341
342
  )
@@ -354,6 +355,7 @@ describe('local evaluation', () => {
354
355
  groups: {},
355
356
  person_properties: { doesnt_matter: '1' },
356
357
  group_properties: {},
358
+ geoip_disable: true,
357
359
  }),
358
360
  })
359
361
  )
@@ -12,7 +12,8 @@ const mockedFetch = jest.mocked(fetch, true)
12
12
  const getLastBatchEvents = (): any[] | undefined => {
13
13
  expect(mockedFetch).toHaveBeenCalledWith('http://example.com/batch/', expect.objectContaining({ method: 'POST' }))
14
14
 
15
- const call = mockedFetch.mock.calls.find((x) => (x[0] as string).includes('/batch/'))
15
+ // reverse mock calls array to get the last call
16
+ const call = mockedFetch.mock.calls.reverse().find((x) => (x[0] as string).includes('/batch/'))
16
17
  if (!call) {
17
18
  return undefined
18
19
  }
@@ -51,14 +52,21 @@ describe('PostHog Node.js', () => {
51
52
 
52
53
  jest.runOnlyPendingTimers()
53
54
  const batchEvents = getLastBatchEvents()
54
- expect(batchEvents).toMatchObject([
55
+ expect(batchEvents).toEqual([
55
56
  {
56
57
  distinct_id: '123',
57
58
  event: 'test-event',
58
59
  properties: {
59
60
  $groups: { org: 123 },
60
61
  foo: 'bar',
62
+ $geoip_disable: true,
63
+ $lib: 'posthog-node',
64
+ $lib_version: '1.2.3',
61
65
  },
66
+ timestamp: expect.any(String),
67
+ type: 'capture',
68
+ library: 'posthog-node',
69
+ library_version: '1.2.3',
62
70
  },
63
71
  ])
64
72
  })
@@ -97,6 +105,7 @@ describe('PostHog Node.js', () => {
97
105
  properties: expect.objectContaining({
98
106
  $groups: { other_group: 'x' },
99
107
  foo: 'bar',
108
+ $geoip_disable: true,
100
109
  }),
101
110
  library: 'posthog-node',
102
111
  library_version: '1.2.3',
@@ -117,6 +126,7 @@ describe('PostHog Node.js', () => {
117
126
  $set: {
118
127
  foo: 'bar',
119
128
  },
129
+ $geoip_disable: true,
120
130
  },
121
131
  },
122
132
  ])
@@ -135,6 +145,7 @@ describe('PostHog Node.js', () => {
135
145
  $set: {
136
146
  foo: 'other',
137
147
  },
148
+ $geoip_disable: true,
138
149
  },
139
150
  },
140
151
  ])
@@ -152,6 +163,7 @@ describe('PostHog Node.js', () => {
152
163
  properties: {
153
164
  distinct_id: '123',
154
165
  alias: '1234',
166
+ $geoip_disable: true,
155
167
  },
156
168
  },
157
169
  ])
@@ -170,6 +182,83 @@ describe('PostHog Node.js', () => {
170
182
  },
171
183
  ])
172
184
  })
185
+
186
+ it('should respect disableGeoip setting if passed in', async () => {
187
+ expect(mockedFetch).toHaveBeenCalledTimes(0)
188
+ posthog.capture({
189
+ distinctId: '123',
190
+ event: 'test-event',
191
+ properties: { foo: 'bar' },
192
+ groups: { org: 123 },
193
+ disableGeoip: false,
194
+ })
195
+
196
+ jest.runOnlyPendingTimers()
197
+ const batchEvents = getLastBatchEvents()
198
+ expect(batchEvents?.[0].properties).toEqual({
199
+ $groups: { org: 123 },
200
+ foo: 'bar',
201
+ $lib: 'posthog-node',
202
+ $lib_version: '1.2.3',
203
+ })
204
+ })
205
+
206
+ it('should use default is set, and override on specific disableGeoip calls', async () => {
207
+ expect(mockedFetch).toHaveBeenCalledTimes(0)
208
+ const client = new PostHog('TEST_API_KEY', {
209
+ host: 'http://example.com',
210
+ disableGeoip: false,
211
+ })
212
+ client.debug()
213
+ client.capture({ distinctId: '123', event: 'test-event', properties: { foo: 'bar' }, groups: { org: 123 } })
214
+
215
+ jest.runOnlyPendingTimers()
216
+ let batchEvents = getLastBatchEvents()
217
+ expect(batchEvents?.[0].properties).toEqual({
218
+ $groups: { org: 123 },
219
+ foo: 'bar',
220
+ $lib: 'posthog-node',
221
+ $lib_version: '1.2.3',
222
+ })
223
+
224
+ client.capture({
225
+ distinctId: '123',
226
+ event: 'test-event',
227
+ properties: { foo: 'bar' },
228
+ groups: { org: 123 },
229
+ disableGeoip: true,
230
+ })
231
+
232
+ jest.runOnlyPendingTimers()
233
+ batchEvents = getLastBatchEvents()
234
+ console.warn(batchEvents)
235
+ expect(batchEvents?.[0].properties).toEqual({
236
+ $groups: { org: 123 },
237
+ foo: 'bar',
238
+ $lib: 'posthog-node',
239
+ $lib_version: '1.2.3',
240
+ $geoip_disable: true,
241
+ })
242
+
243
+ client.capture({
244
+ distinctId: '123',
245
+ event: 'test-event',
246
+ properties: { foo: 'bar' },
247
+ groups: { org: 123 },
248
+ disableGeoip: false,
249
+ })
250
+
251
+ jest.runOnlyPendingTimers()
252
+ batchEvents = getLastBatchEvents()
253
+ expect(batchEvents?.[0].properties).toEqual({
254
+ $groups: { org: 123 },
255
+ foo: 'bar',
256
+ $lib: 'posthog-node',
257
+ $lib_version: '1.2.3',
258
+ })
259
+
260
+ await client.shutdownAsync()
261
+ })
173
262
  })
174
263
 
175
264
  describe('shutdown', () => {
@@ -243,6 +332,7 @@ describe('PostHog Node.js', () => {
243
332
  $group_key: 'team-1',
244
333
  $group_set: { analytics: true },
245
334
  $lib: 'posthog-node',
335
+ $geoip_disable: true,
246
336
  },
247
337
  },
248
338
  ])
@@ -266,6 +356,7 @@ describe('PostHog Node.js', () => {
266
356
  $group_key: 'team-1',
267
357
  $group_set: { analytics: true },
268
358
  $lib: 'posthog-node',
359
+ $geoip_disable: true,
269
360
  },
270
361
  },
271
362
  ])
@@ -292,7 +383,6 @@ describe('PostHog Node.js', () => {
292
383
 
293
384
  posthog = new PostHog('TEST_API_KEY', {
294
385
  host: 'http://example.com',
295
- // flushAt: 1,
296
386
  })
297
387
  })
298
388
 
@@ -302,6 +392,10 @@ describe('PostHog Node.js', () => {
302
392
  'variant'
303
393
  )
304
394
  expect(mockedFetch).toHaveBeenCalledTimes(1)
395
+ expect(mockedFetch).toHaveBeenCalledWith(
396
+ 'http://example.com/decide/?v=3',
397
+ expect.objectContaining({ method: 'POST', body: expect.stringContaining('"geoip_disable":true') })
398
+ )
305
399
  })
306
400
 
307
401
  it('should do isFeatureEnabled', async () => {
@@ -347,12 +441,57 @@ describe('PostHog Node.js', () => {
347
441
  '$feature/feature-variant': 'variant',
348
442
  $lib: 'posthog-node',
349
443
  $lib_version: '1.2.3',
444
+ $geoip_disable: true,
350
445
  }),
351
446
  })
352
447
  )
353
448
 
354
449
  // no calls to `/local_evaluation`
355
450
 
451
+ expect(mockedFetch).not.toHaveBeenCalledWith(...anyLocalEvalCall)
452
+ expect(mockedFetch).toHaveBeenCalledWith(
453
+ 'http://example.com/decide/?v=3',
454
+ expect.objectContaining({ method: 'POST', body: expect.stringContaining('"geoip_disable":true') })
455
+ )
456
+ })
457
+
458
+ it('captures feature flags with same geoip setting as capture', async () => {
459
+ mockedFetch.mockClear()
460
+ mockedFetch.mockClear()
461
+ expect(mockedFetch).toHaveBeenCalledTimes(0)
462
+
463
+ posthog = new PostHog('TEST_API_KEY', {
464
+ host: 'http://example.com',
465
+ flushAt: 1,
466
+ })
467
+
468
+ posthog.capture({
469
+ distinctId: 'distinct_id',
470
+ event: 'node test event',
471
+ sendFeatureFlags: true,
472
+ disableGeoip: false,
473
+ })
474
+
475
+ expect(mockedFetch).toHaveBeenCalledWith(
476
+ 'http://example.com/decide/?v=3',
477
+ expect.objectContaining({ method: 'POST', body: expect.not.stringContaining('geoip_disable') })
478
+ )
479
+
480
+ jest.runOnlyPendingTimers()
481
+
482
+ await waitForPromises()
483
+
484
+ expect(getLastBatchEvents()?.[0].properties).toEqual({
485
+ $active_feature_flags: ['feature-1', 'feature-2', 'feature-variant'],
486
+ '$feature/feature-1': true,
487
+ '$feature/feature-2': true,
488
+ '$feature/feature-variant': 'variant',
489
+ $lib: 'posthog-node',
490
+ $lib_version: '1.2.3',
491
+ })
492
+
493
+ // no calls to `/local_evaluation`
494
+
356
495
  expect(mockedFetch).not.toHaveBeenCalledWith(...anyLocalEvalCall)
357
496
  })
358
497
 
@@ -462,6 +601,7 @@ describe('PostHog Node.js', () => {
462
601
  $lib: 'posthog-node',
463
602
  $lib_version: '1.2.3',
464
603
  locally_evaluated: true,
604
+ $geoip_disable: true,
465
605
  }),
466
606
  })
467
607
  )
@@ -482,6 +622,7 @@ describe('PostHog Node.js', () => {
482
622
  await posthog.getFeatureFlag('beta-feature', 'some-distinct-id2', {
483
623
  groups: { x: 'y' },
484
624
  personProperties: { region: 'USA', name: 'Aloha' },
625
+ disableGeoip: false,
485
626
  })
486
627
  ).toEqual(true)
487
628
  jest.runOnlyPendingTimers()
@@ -491,16 +632,16 @@ describe('PostHog Node.js', () => {
491
632
  expect.objectContaining({
492
633
  distinct_id: 'some-distinct-id2',
493
634
  event: '$feature_flag_called',
494
- properties: expect.objectContaining({
495
- $feature_flag: 'beta-feature',
496
- $feature_flag_response: true,
497
- $lib: 'posthog-node',
498
- $lib_version: '1.2.3',
499
- locally_evaluated: true,
500
- $groups: { x: 'y' },
501
- }),
502
635
  })
503
636
  )
637
+ expect(getLastBatchEvents()?.[0].properties).toEqual({
638
+ $feature_flag: 'beta-feature',
639
+ $feature_flag_response: true,
640
+ $lib: 'posthog-node',
641
+ $lib_version: '1.2.3',
642
+ locally_evaluated: true,
643
+ $groups: { x: 'y' },
644
+ })
504
645
  mockedFetch.mockClear()
505
646
 
506
647
  // # called for different user, but send configuration is false, so should NOT call capture again
@@ -559,6 +700,10 @@ describe('PostHog Node.js', () => {
559
700
  posthog.getFeatureFlagPayload('feature-variant', '123', 'variant', { groups: { org: '123' } })
560
701
  ).resolves.toEqual(2)
561
702
  expect(mockedFetch).toHaveBeenCalledTimes(1)
703
+ expect(mockedFetch).toHaveBeenCalledWith(
704
+ 'http://example.com/decide/?v=3',
705
+ expect.objectContaining({ method: 'POST', body: expect.stringContaining('"geoip_disable":true') })
706
+ )
562
707
  })
563
708
 
564
709
  it('should do getFeatureFlagPayloads without matchValue', async () => {
@@ -568,5 +713,26 @@ describe('PostHog Node.js', () => {
568
713
  ).resolves.toEqual(2)
569
714
  expect(mockedFetch).toHaveBeenCalledTimes(1)
570
715
  })
716
+
717
+ it('should do getFeatureFlags with geoip disabled and enabled', async () => {
718
+ expect(mockedFetch).toHaveBeenCalledTimes(0)
719
+ await expect(
720
+ posthog.getFeatureFlagPayload('feature-variant', '123', 'variant', { groups: { org: '123' } })
721
+ ).resolves.toEqual(2)
722
+ expect(mockedFetch).toHaveBeenCalledTimes(1)
723
+ expect(mockedFetch).toHaveBeenCalledWith(
724
+ 'http://example.com/decide/?v=3',
725
+ expect.objectContaining({ method: 'POST', body: expect.stringContaining('"geoip_disable":true') })
726
+ )
727
+
728
+ mockedFetch.mockClear()
729
+
730
+ await expect(posthog.isFeatureEnabled('feature-variant', '123', { disableGeoip: false })).resolves.toEqual(true)
731
+ expect(mockedFetch).toHaveBeenCalledTimes(1)
732
+ expect(mockedFetch).toHaveBeenCalledWith(
733
+ 'http://example.com/decide/?v=3',
734
+ expect.objectContaining({ method: 'POST', body: expect.not.stringContaining('geoip_disable') })
735
+ )
736
+ })
571
737
  })
572
738
  })