posthog-node 3.0.0 → 3.1.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.
- package/CHANGELOG.md +11 -1
- package/lib/index.cjs.js +110 -31
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.esm.js +110 -31
- package/lib/index.esm.js.map +1 -1
- package/lib/posthog-core/src/utils.d.ts +1 -1
- package/package.json +1 -1
- package/src/feature-flags.ts +1 -1
- package/src/fetch.ts +4 -2
- package/test/feature-flags.spec.ts +41 -6
- package/test/posthog-node.spec.ts +17 -4
|
@@ -3,7 +3,7 @@ export declare function removeTrailingSlash(url: string): string;
|
|
|
3
3
|
export interface RetriableOptions {
|
|
4
4
|
retryCount?: number;
|
|
5
5
|
retryDelay?: number;
|
|
6
|
-
retryCheck?: (err: any) =>
|
|
6
|
+
retryCheck?: (err: any) => boolean;
|
|
7
7
|
}
|
|
8
8
|
export declare function retriable<T>(fn: () => Promise<T>, props?: RetriableOptions): Promise<T>;
|
|
9
9
|
export declare function generateUUID(globalThis?: any): string;
|
package/package.json
CHANGED
package/src/feature-flags.ts
CHANGED
package/src/fetch.ts
CHANGED
|
@@ -10,11 +10,13 @@ export const fetch = async (url: string, options: PostHogFetchOptions): Promise<
|
|
|
10
10
|
method: options.method.toLowerCase(),
|
|
11
11
|
data: options.body,
|
|
12
12
|
signal: options.signal,
|
|
13
|
+
// fetch only throws on network errors, not on HTTP errors
|
|
14
|
+
validateStatus: () => true,
|
|
13
15
|
})
|
|
14
16
|
|
|
15
17
|
return {
|
|
16
18
|
status: res.status,
|
|
17
|
-
text: () => res.data,
|
|
18
|
-
json: () => res.data,
|
|
19
|
+
text: async () => res.data,
|
|
20
|
+
json: async () => res.data,
|
|
19
21
|
}
|
|
20
22
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// import { PostHog } from '../'
|
|
1
|
+
// import { PostHog, PostHogOptions } from '../'
|
|
2
2
|
// Uncomment below line while developing to not compile code everytime
|
|
3
|
-
import { PostHog as PostHog } from '../src/posthog-node'
|
|
3
|
+
import { PostHog as PostHog, PostHogOptions } from '../src/posthog-node'
|
|
4
4
|
import { matchProperty, InconclusiveMatchError } from '../src/feature-flags'
|
|
5
5
|
jest.mock('../src/fetch')
|
|
6
6
|
import { fetch } from '../src/fetch'
|
|
@@ -9,6 +9,10 @@ jest.spyOn(global.console, 'debug').mockImplementation()
|
|
|
9
9
|
|
|
10
10
|
const mockedFetch = jest.mocked(fetch, true)
|
|
11
11
|
|
|
12
|
+
const posthogImmediateResolveOptions: PostHogOptions = {
|
|
13
|
+
fetchRetryCount: 0,
|
|
14
|
+
}
|
|
15
|
+
|
|
12
16
|
export const apiImplementation = ({
|
|
13
17
|
localFlags,
|
|
14
18
|
decideFlags,
|
|
@@ -105,6 +109,7 @@ describe('local evaluation', () => {
|
|
|
105
109
|
posthog = new PostHog('TEST_API_KEY', {
|
|
106
110
|
host: 'http://example.com',
|
|
107
111
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
112
|
+
...posthogImmediateResolveOptions,
|
|
108
113
|
})
|
|
109
114
|
|
|
110
115
|
expect(
|
|
@@ -151,6 +156,7 @@ describe('local evaluation', () => {
|
|
|
151
156
|
posthog = new PostHog('TEST_API_KEY', {
|
|
152
157
|
host: 'http://example.com',
|
|
153
158
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
159
|
+
...posthogImmediateResolveOptions,
|
|
154
160
|
})
|
|
155
161
|
|
|
156
162
|
// # groups not passed in, hence false
|
|
@@ -231,6 +237,7 @@ describe('local evaluation', () => {
|
|
|
231
237
|
posthog = new PostHog('TEST_API_KEY', {
|
|
232
238
|
host: 'http://example.com',
|
|
233
239
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
240
|
+
...posthogImmediateResolveOptions,
|
|
234
241
|
})
|
|
235
242
|
// # group_type_mappings not present, so fallback to `/decide`
|
|
236
243
|
expect(
|
|
@@ -304,6 +311,7 @@ describe('local evaluation', () => {
|
|
|
304
311
|
posthog = new PostHog('TEST_API_KEY', {
|
|
305
312
|
host: 'http://example.com',
|
|
306
313
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
314
|
+
...posthogImmediateResolveOptions,
|
|
307
315
|
})
|
|
308
316
|
|
|
309
317
|
expect(
|
|
@@ -426,6 +434,7 @@ describe('local evaluation', () => {
|
|
|
426
434
|
posthog = new PostHog('TEST_API_KEY', {
|
|
427
435
|
host: 'http://example.com',
|
|
428
436
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
437
|
+
...posthogImmediateResolveOptions,
|
|
429
438
|
})
|
|
430
439
|
|
|
431
440
|
// # beta-feature fallbacks to decide because property type is unknown
|
|
@@ -488,6 +497,7 @@ describe('local evaluation', () => {
|
|
|
488
497
|
posthog = new PostHog('TEST_API_KEY', {
|
|
489
498
|
host: 'http://example.com',
|
|
490
499
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
500
|
+
...posthogImmediateResolveOptions,
|
|
491
501
|
})
|
|
492
502
|
|
|
493
503
|
// # beta-feature should fallback to decide because property type is unknown
|
|
@@ -536,6 +546,7 @@ describe('local evaluation', () => {
|
|
|
536
546
|
posthog = new PostHog('TEST_API_KEY', {
|
|
537
547
|
host: 'http://example.com',
|
|
538
548
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
549
|
+
...posthogImmediateResolveOptions,
|
|
539
550
|
})
|
|
540
551
|
|
|
541
552
|
// # beta-feature resolves to False
|
|
@@ -576,12 +587,20 @@ describe('local evaluation', () => {
|
|
|
576
587
|
posthog = new PostHog('TEST_API_KEY', {
|
|
577
588
|
host: 'http://example.com',
|
|
578
589
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
590
|
+
...posthogImmediateResolveOptions,
|
|
591
|
+
})
|
|
592
|
+
|
|
593
|
+
let err: any = null
|
|
594
|
+
posthog.on('error', (e) => {
|
|
595
|
+
err = e
|
|
579
596
|
})
|
|
580
597
|
|
|
581
598
|
// # beta-feature2 falls back to decide, which on error returns undefined
|
|
582
599
|
expect(await posthog.getFeatureFlag('beta-feature2', 'some-distinct-id')).toEqual(undefined)
|
|
583
600
|
expect(await posthog.isFeatureEnabled('beta-feature2', 'some-distinct-id')).toEqual(undefined)
|
|
584
601
|
expect(mockedFetch).toHaveBeenCalledWith(...anyDecideCall)
|
|
602
|
+
await posthog.shutdownAsync()
|
|
603
|
+
expect(err).toHaveProperty('name', 'PostHogFetchHttpError')
|
|
585
604
|
})
|
|
586
605
|
|
|
587
606
|
it('experience continuity flags are not evaluated locally', async () => {
|
|
@@ -612,6 +631,7 @@ describe('local evaluation', () => {
|
|
|
612
631
|
posthog = new PostHog('TEST_API_KEY', {
|
|
613
632
|
host: 'http://example.com',
|
|
614
633
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
634
|
+
...posthogImmediateResolveOptions,
|
|
615
635
|
})
|
|
616
636
|
|
|
617
637
|
// # beta-feature2 falls back to decide, which on error returns default
|
|
@@ -680,6 +700,7 @@ describe('local evaluation', () => {
|
|
|
680
700
|
posthog = new PostHog('TEST_API_KEY', {
|
|
681
701
|
host: 'http://example.com',
|
|
682
702
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
703
|
+
...posthogImmediateResolveOptions,
|
|
683
704
|
})
|
|
684
705
|
|
|
685
706
|
// # beta-feature value overridden by /decide
|
|
@@ -763,6 +784,7 @@ describe('local evaluation', () => {
|
|
|
763
784
|
posthog = new PostHog('TEST_API_KEY', {
|
|
764
785
|
host: 'http://example.com',
|
|
765
786
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
787
|
+
...posthogImmediateResolveOptions,
|
|
766
788
|
})
|
|
767
789
|
|
|
768
790
|
// # beta-feature value overridden by /decide
|
|
@@ -835,6 +857,7 @@ describe('local evaluation', () => {
|
|
|
835
857
|
posthog = new PostHog('TEST_API_KEY', {
|
|
836
858
|
host: 'http://example.com',
|
|
837
859
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
860
|
+
...posthogImmediateResolveOptions,
|
|
838
861
|
})
|
|
839
862
|
|
|
840
863
|
// # beta-feature2 has no value
|
|
@@ -916,6 +939,7 @@ describe('local evaluation', () => {
|
|
|
916
939
|
posthog = new PostHog('TEST_API_KEY', {
|
|
917
940
|
host: 'http://example.com',
|
|
918
941
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
942
|
+
...posthogImmediateResolveOptions,
|
|
919
943
|
})
|
|
920
944
|
|
|
921
945
|
expect(
|
|
@@ -940,6 +964,7 @@ describe('local evaluation', () => {
|
|
|
940
964
|
posthog = new PostHog('TEST_API_KEY', {
|
|
941
965
|
host: 'http://example.com',
|
|
942
966
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
967
|
+
...posthogImmediateResolveOptions,
|
|
943
968
|
})
|
|
944
969
|
|
|
945
970
|
expect(await posthog.getAllFlags('distinct-id')).toEqual({
|
|
@@ -965,6 +990,7 @@ describe('local evaluation', () => {
|
|
|
965
990
|
posthog = new PostHog('TEST_API_KEY', {
|
|
966
991
|
host: 'http://example.com',
|
|
967
992
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
993
|
+
...posthogImmediateResolveOptions,
|
|
968
994
|
})
|
|
969
995
|
|
|
970
996
|
expect((await posthog.getAllFlagsAndPayloads('distinct-id')).featureFlagPayloads).toEqual({
|
|
@@ -1021,6 +1047,7 @@ describe('local evaluation', () => {
|
|
|
1021
1047
|
posthog = new PostHog('TEST_API_KEY', {
|
|
1022
1048
|
host: 'http://example.com',
|
|
1023
1049
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
1050
|
+
...posthogImmediateResolveOptions,
|
|
1024
1051
|
})
|
|
1025
1052
|
|
|
1026
1053
|
expect(await posthog.getAllFlags('distinct-id')).toEqual({ 'beta-feature': true, 'disabled-feature': false })
|
|
@@ -1079,6 +1106,7 @@ describe('local evaluation', () => {
|
|
|
1079
1106
|
posthog = new PostHog('TEST_API_KEY', {
|
|
1080
1107
|
host: 'http://example.com',
|
|
1081
1108
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
1109
|
+
...posthogImmediateResolveOptions,
|
|
1082
1110
|
})
|
|
1083
1111
|
|
|
1084
1112
|
expect((await posthog.getAllFlagsAndPayloads('distinct-id')).featureFlagPayloads).toEqual({ 'beta-feature': 'new' })
|
|
@@ -1131,6 +1159,7 @@ describe('local evaluation', () => {
|
|
|
1131
1159
|
posthog = new PostHog('TEST_API_KEY', {
|
|
1132
1160
|
host: 'http://example.com',
|
|
1133
1161
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
1162
|
+
...posthogImmediateResolveOptions,
|
|
1134
1163
|
})
|
|
1135
1164
|
|
|
1136
1165
|
expect(await posthog.getAllFlags('distinct-id')).toEqual({ 'beta-feature': true, 'disabled-feature': false })
|
|
@@ -1238,6 +1267,7 @@ describe('local evaluation', () => {
|
|
|
1238
1267
|
posthog = new PostHog('TEST_API_KEY', {
|
|
1239
1268
|
host: 'http://example.com',
|
|
1240
1269
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
1270
|
+
...posthogImmediateResolveOptions,
|
|
1241
1271
|
})
|
|
1242
1272
|
|
|
1243
1273
|
expect(
|
|
@@ -1319,6 +1349,7 @@ describe('local evaluation', () => {
|
|
|
1319
1349
|
posthog = new PostHog('TEST_API_KEY', {
|
|
1320
1350
|
host: 'http://example.com',
|
|
1321
1351
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
1352
|
+
...posthogImmediateResolveOptions,
|
|
1322
1353
|
})
|
|
1323
1354
|
|
|
1324
1355
|
expect(
|
|
@@ -1408,6 +1439,7 @@ describe('local evaluation', () => {
|
|
|
1408
1439
|
posthog = new PostHog('TEST_API_KEY', {
|
|
1409
1440
|
host: 'http://example.com',
|
|
1410
1441
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
1442
|
+
...posthogImmediateResolveOptions,
|
|
1411
1443
|
})
|
|
1412
1444
|
|
|
1413
1445
|
expect(
|
|
@@ -1489,6 +1521,7 @@ describe('local evaluation', () => {
|
|
|
1489
1521
|
posthog = new PostHog('TEST_API_KEY', {
|
|
1490
1522
|
host: 'http://example.com',
|
|
1491
1523
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
1524
|
+
...posthogImmediateResolveOptions,
|
|
1492
1525
|
})
|
|
1493
1526
|
|
|
1494
1527
|
expect(
|
|
@@ -1560,6 +1593,7 @@ describe('local evaluation', () => {
|
|
|
1560
1593
|
posthog = new PostHog('TEST_API_KEY', {
|
|
1561
1594
|
host: 'http://example.com',
|
|
1562
1595
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
1596
|
+
...posthogImmediateResolveOptions,
|
|
1563
1597
|
})
|
|
1564
1598
|
|
|
1565
1599
|
expect(
|
|
@@ -1632,6 +1666,7 @@ describe('local evaluation', () => {
|
|
|
1632
1666
|
posthog = new PostHog('TEST_API_KEY', {
|
|
1633
1667
|
host: 'http://example.com',
|
|
1634
1668
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
1669
|
+
...posthogImmediateResolveOptions,
|
|
1635
1670
|
})
|
|
1636
1671
|
|
|
1637
1672
|
expect(
|
|
@@ -1682,6 +1717,7 @@ describe('local evaluation', () => {
|
|
|
1682
1717
|
posthog = new PostHog('TEST_API_KEY', {
|
|
1683
1718
|
host: 'http://example.com',
|
|
1684
1719
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
1720
|
+
...posthogImmediateResolveOptions,
|
|
1685
1721
|
})
|
|
1686
1722
|
|
|
1687
1723
|
expect(
|
|
@@ -1762,6 +1798,7 @@ describe('local evaluation', () => {
|
|
|
1762
1798
|
posthog = new PostHog('TEST_API_KEY', {
|
|
1763
1799
|
host: 'http://example.com',
|
|
1764
1800
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
1801
|
+
...posthogImmediateResolveOptions,
|
|
1765
1802
|
})
|
|
1766
1803
|
|
|
1767
1804
|
expect(
|
|
@@ -1990,10 +2027,6 @@ describe('consistency tests', () => {
|
|
|
1990
2027
|
let posthog: PostHog
|
|
1991
2028
|
jest.useFakeTimers()
|
|
1992
2029
|
|
|
1993
|
-
afterEach(async () => {
|
|
1994
|
-
await posthog.shutdownAsync()
|
|
1995
|
-
})
|
|
1996
|
-
|
|
1997
2030
|
it('is consistent for simple flags', () => {
|
|
1998
2031
|
const flags = {
|
|
1999
2032
|
flags: [
|
|
@@ -2015,6 +2048,7 @@ describe('consistency tests', () => {
|
|
|
2015
2048
|
posthog = new PostHog('TEST_API_KEY', {
|
|
2016
2049
|
host: 'http://example.com',
|
|
2017
2050
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
2051
|
+
...posthogImmediateResolveOptions,
|
|
2018
2052
|
})
|
|
2019
2053
|
|
|
2020
2054
|
const results = [
|
|
@@ -3057,6 +3091,7 @@ describe('consistency tests', () => {
|
|
|
3057
3091
|
posthog = new PostHog('TEST_API_KEY', {
|
|
3058
3092
|
host: 'http://example.com',
|
|
3059
3093
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
3094
|
+
...posthogImmediateResolveOptions,
|
|
3060
3095
|
})
|
|
3061
3096
|
|
|
3062
3097
|
const results = [
|
|
@@ -28,6 +28,7 @@ describe('PostHog Node.js', () => {
|
|
|
28
28
|
beforeEach(() => {
|
|
29
29
|
posthog = new PostHog('TEST_API_KEY', {
|
|
30
30
|
host: 'http://example.com',
|
|
31
|
+
fetchRetryCount: 0,
|
|
31
32
|
})
|
|
32
33
|
|
|
33
34
|
mockedFetch.mockResolvedValue({
|
|
@@ -266,8 +267,7 @@ describe('PostHog Node.js', () => {
|
|
|
266
267
|
// a serverless posthog configuration
|
|
267
268
|
posthog = new PostHog('TEST_API_KEY', {
|
|
268
269
|
host: 'http://example.com',
|
|
269
|
-
|
|
270
|
-
flushInterval: 0,
|
|
270
|
+
fetchRetryCount: 0,
|
|
271
271
|
})
|
|
272
272
|
|
|
273
273
|
mockedFetch.mockImplementation(async () => {
|
|
@@ -290,6 +290,12 @@ describe('PostHog Node.js', () => {
|
|
|
290
290
|
})
|
|
291
291
|
|
|
292
292
|
it('should shutdown cleanly', async () => {
|
|
293
|
+
posthog = new PostHog('TEST_API_KEY', {
|
|
294
|
+
host: 'http://example.com',
|
|
295
|
+
fetchRetryCount: 0,
|
|
296
|
+
flushAt: 1,
|
|
297
|
+
})
|
|
298
|
+
|
|
293
299
|
const logSpy = jest.spyOn(global.console, 'log')
|
|
294
300
|
jest.useRealTimers()
|
|
295
301
|
// using debug mode to check console.log output
|
|
@@ -319,9 +325,10 @@ describe('PostHog Node.js', () => {
|
|
|
319
325
|
})
|
|
320
326
|
|
|
321
327
|
describe('groupIdentify', () => {
|
|
322
|
-
it('should identify group with unique id', () => {
|
|
328
|
+
it('should identify group with unique id', async () => {
|
|
323
329
|
posthog.groupIdentify({ groupType: 'posthog', groupKey: 'team-1', properties: { analytics: true } })
|
|
324
330
|
jest.runOnlyPendingTimers()
|
|
331
|
+
await posthog.flushAsync()
|
|
325
332
|
const batchEvents = getLastBatchEvents()
|
|
326
333
|
expect(batchEvents).toMatchObject([
|
|
327
334
|
{
|
|
@@ -338,7 +345,7 @@ describe('PostHog Node.js', () => {
|
|
|
338
345
|
])
|
|
339
346
|
})
|
|
340
347
|
|
|
341
|
-
it('should allow passing optional distinctID to identify group', () => {
|
|
348
|
+
it('should allow passing optional distinctID to identify group', async () => {
|
|
342
349
|
posthog.groupIdentify({
|
|
343
350
|
groupType: 'posthog',
|
|
344
351
|
groupKey: 'team-1',
|
|
@@ -346,6 +353,7 @@ describe('PostHog Node.js', () => {
|
|
|
346
353
|
distinctId: '123',
|
|
347
354
|
})
|
|
348
355
|
jest.runOnlyPendingTimers()
|
|
356
|
+
await posthog.flushAsync()
|
|
349
357
|
const batchEvents = getLastBatchEvents()
|
|
350
358
|
expect(batchEvents).toMatchObject([
|
|
351
359
|
{
|
|
@@ -383,6 +391,7 @@ describe('PostHog Node.js', () => {
|
|
|
383
391
|
|
|
384
392
|
posthog = new PostHog('TEST_API_KEY', {
|
|
385
393
|
host: 'http://example.com',
|
|
394
|
+
fetchRetryCount: 0,
|
|
386
395
|
})
|
|
387
396
|
})
|
|
388
397
|
|
|
@@ -413,6 +422,7 @@ describe('PostHog Node.js', () => {
|
|
|
413
422
|
posthog = new PostHog('TEST_API_KEY', {
|
|
414
423
|
host: 'http://example.com',
|
|
415
424
|
flushAt: 1,
|
|
425
|
+
fetchRetryCount: 0,
|
|
416
426
|
})
|
|
417
427
|
|
|
418
428
|
posthog.capture({
|
|
@@ -463,6 +473,7 @@ describe('PostHog Node.js', () => {
|
|
|
463
473
|
posthog = new PostHog('TEST_API_KEY', {
|
|
464
474
|
host: 'http://example.com',
|
|
465
475
|
flushAt: 1,
|
|
476
|
+
fetchRetryCount: 0,
|
|
466
477
|
})
|
|
467
478
|
|
|
468
479
|
posthog.capture({
|
|
@@ -523,6 +534,7 @@ describe('PostHog Node.js', () => {
|
|
|
523
534
|
host: 'http://example.com',
|
|
524
535
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
525
536
|
maxCacheSize: 10,
|
|
537
|
+
fetchRetryCount: 0,
|
|
526
538
|
})
|
|
527
539
|
|
|
528
540
|
expect(Object.keys(posthog.distinctIdHasSentFlagCalls).length).toEqual(0)
|
|
@@ -581,6 +593,7 @@ describe('PostHog Node.js', () => {
|
|
|
581
593
|
host: 'http://example.com',
|
|
582
594
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
583
595
|
maxCacheSize: 10,
|
|
596
|
+
fetchRetryCount: 0,
|
|
584
597
|
})
|
|
585
598
|
|
|
586
599
|
expect(
|