@posthog/core 1.1.0 → 1.2.1
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/dist/error-tracking/chunk-ids.js +1 -1
- package/dist/error-tracking/chunk-ids.mjs +1 -1
- package/dist/error-tracking/coercers/error-event-coercer.js +4 -5
- package/dist/error-tracking/coercers/error-event-coercer.mjs +4 -5
- package/dist/error-tracking/coercers/event-coercer.js +1 -2
- package/dist/error-tracking/coercers/event-coercer.mjs +1 -2
- package/dist/error-tracking/coercers/object-coercer.js +1 -2
- package/dist/error-tracking/coercers/object-coercer.mjs +1 -2
- package/dist/error-tracking/coercers/primitive-coercer.js +1 -2
- package/dist/error-tracking/coercers/primitive-coercer.mjs +1 -2
- package/dist/error-tracking/coercers/promise-rejection-event.js +4 -5
- package/dist/error-tracking/coercers/promise-rejection-event.mjs +4 -5
- package/dist/error-tracking/coercers/string-coercer.js +3 -4
- package/dist/error-tracking/coercers/string-coercer.mjs +3 -4
- package/dist/error-tracking/coercers/utils.js +2 -4
- package/dist/error-tracking/coercers/utils.mjs +2 -4
- package/dist/error-tracking/error-properties-builder.d.ts +6 -6
- package/dist/error-tracking/error-properties-builder.d.ts.map +1 -1
- package/dist/error-tracking/error-properties-builder.js +17 -27
- package/dist/error-tracking/error-properties-builder.mjs +16 -26
- package/dist/error-tracking/parsers/index.js +2 -4
- package/dist/error-tracking/parsers/index.mjs +2 -4
- package/dist/error-tracking/parsers/node.js +3 -5
- package/dist/error-tracking/parsers/node.mjs +3 -5
- package/dist/error-tracking/utils.js +4 -4
- package/dist/error-tracking/utils.mjs +4 -4
- package/dist/eventemitter.js +4 -4
- package/dist/eventemitter.mjs +4 -4
- package/dist/featureFlagUtils.js +20 -45
- package/dist/featureFlagUtils.mjs +20 -45
- package/dist/gzip.js +1 -2
- package/dist/gzip.mjs +1 -2
- package/dist/index.d.ts +4 -366
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +54 -1225
- package/dist/index.mjs +5 -1190
- package/dist/posthog-core-stateless.d.ts +204 -0
- package/dist/posthog-core-stateless.d.ts.map +1 -0
- package/dist/posthog-core-stateless.js +675 -0
- package/dist/posthog-core-stateless.mjs +632 -0
- package/dist/posthog-core.d.ts +171 -0
- package/dist/posthog-core.d.ts.map +1 -0
- package/dist/posthog-core.js +554 -0
- package/dist/posthog-core.mjs +520 -0
- package/dist/testing/PostHogCoreTestClient.d.ts +2 -1
- package/dist/testing/PostHogCoreTestClient.d.ts.map +1 -1
- package/dist/testing/PostHogCoreTestClient.js +9 -11
- package/dist/testing/PostHogCoreTestClient.mjs +8 -10
- package/dist/testing/test-utils.js +1 -1
- package/dist/testing/test-utils.mjs +1 -1
- package/dist/utils/bucketed-rate-limiter.js +8 -12
- package/dist/utils/bucketed-rate-limiter.mjs +8 -12
- package/dist/utils/index.js +3 -3
- package/dist/utils/index.mjs +3 -3
- package/dist/utils/type-utils.js +1 -1
- package/dist/utils/type-utils.mjs +1 -1
- package/dist/vendor/uuidv7.js +12 -16
- package/dist/vendor/uuidv7.mjs +12 -16
- package/package.json +3 -2
- package/src/__tests__/featureFlagUtils.spec.ts +427 -0
- package/src/__tests__/gzip.spec.ts +69 -0
- package/src/__tests__/posthog.ai.spec.ts +110 -0
- package/src/__tests__/posthog.capture.spec.ts +91 -0
- package/src/__tests__/posthog.core.spec.ts +135 -0
- package/src/__tests__/posthog.debug.spec.ts +36 -0
- package/src/__tests__/posthog.enqueue.spec.ts +93 -0
- package/src/__tests__/posthog.featureflags.spec.ts +1106 -0
- package/src/__tests__/posthog.featureflags.v1.spec.ts +922 -0
- package/src/__tests__/posthog.flush.spec.ts +237 -0
- package/src/__tests__/posthog.gdpr.spec.ts +50 -0
- package/src/__tests__/posthog.groups.spec.ts +96 -0
- package/src/__tests__/posthog.identify.spec.ts +194 -0
- package/src/__tests__/posthog.init.spec.ts +110 -0
- package/src/__tests__/posthog.listeners.spec.ts +51 -0
- package/src/__tests__/posthog.register.spec.ts +47 -0
- package/src/__tests__/posthog.reset.spec.ts +76 -0
- package/src/__tests__/posthog.sessions.spec.ts +63 -0
- package/src/__tests__/posthog.setProperties.spec.ts +102 -0
- package/src/__tests__/posthog.shutdown.spec.ts +88 -0
- package/src/__tests__/utils.spec.ts +36 -0
- package/src/error-tracking/chunk-ids.ts +58 -0
- package/src/error-tracking/coercers/dom-exception-coercer.ts +38 -0
- package/src/error-tracking/coercers/error-coercer.ts +36 -0
- package/src/error-tracking/coercers/error-event-coercer.ts +24 -0
- package/src/error-tracking/coercers/event-coercer.ts +19 -0
- package/src/error-tracking/coercers/index.ts +8 -0
- package/src/error-tracking/coercers/object-coercer.ts +76 -0
- package/src/error-tracking/coercers/primitive-coercer.ts +19 -0
- package/src/error-tracking/coercers/promise-rejection-event.spec.ts +77 -0
- package/src/error-tracking/coercers/promise-rejection-event.ts +53 -0
- package/src/error-tracking/coercers/string-coercer.spec.ts +26 -0
- package/src/error-tracking/coercers/string-coercer.ts +31 -0
- package/src/error-tracking/coercers/utils.ts +33 -0
- package/src/error-tracking/error-properties-builder.coerce.spec.ts +202 -0
- package/src/error-tracking/error-properties-builder.parse.spec.ts +30 -0
- package/src/error-tracking/error-properties-builder.ts +167 -0
- package/src/error-tracking/index.ts +5 -0
- package/src/error-tracking/parsers/base.ts +29 -0
- package/src/error-tracking/parsers/chrome.ts +53 -0
- package/src/error-tracking/parsers/gecko.ts +38 -0
- package/src/error-tracking/parsers/index.ts +104 -0
- package/src/error-tracking/parsers/node.ts +111 -0
- package/src/error-tracking/parsers/opera.ts +18 -0
- package/src/error-tracking/parsers/react-native.ts +0 -0
- package/src/error-tracking/parsers/safari.ts +33 -0
- package/src/error-tracking/parsers/winjs.ts +12 -0
- package/src/error-tracking/types.ts +107 -0
- package/src/error-tracking/utils.ts +39 -0
- package/src/eventemitter.ts +27 -0
- package/src/featureFlagUtils.ts +192 -0
- package/src/gzip.ts +29 -0
- package/src/index.ts +8 -0
- package/src/posthog-core-stateless.ts +1226 -0
- package/src/posthog-core.ts +958 -0
- package/src/testing/PostHogCoreTestClient.ts +91 -0
- package/src/testing/index.ts +2 -0
- package/src/testing/test-utils.ts +47 -0
- package/src/types.ts +544 -0
- package/src/utils/bucketed-rate-limiter.spec.ts +33 -0
- package/src/utils/bucketed-rate-limiter.ts +85 -0
- package/src/utils/index.ts +98 -0
- package/src/utils/number-utils.spec.ts +89 -0
- package/src/utils/number-utils.ts +30 -0
- package/src/utils/promise-queue.spec.ts +55 -0
- package/src/utils/promise-queue.ts +30 -0
- package/src/utils/string-utils.ts +23 -0
- package/src/utils/type-utils.ts +134 -0
- package/src/vendor/uuidv7.ts +479 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { createTestClient, PostHogCoreTestClient, PostHogCoreTestClientMocks } from '@/testing'
|
|
2
|
+
|
|
3
|
+
describe('PostHog Core', () => {
|
|
4
|
+
let posthog: PostHogCoreTestClient
|
|
5
|
+
let mocks: PostHogCoreTestClientMocks
|
|
6
|
+
|
|
7
|
+
jest.useFakeTimers()
|
|
8
|
+
jest.setSystemTime(new Date('2022-01-01'))
|
|
9
|
+
|
|
10
|
+
const errorAPIResponse = Promise.resolve({
|
|
11
|
+
status: 400,
|
|
12
|
+
text: () => Promise.resolve('error'),
|
|
13
|
+
json: () =>
|
|
14
|
+
Promise.resolve({
|
|
15
|
+
status: 'error',
|
|
16
|
+
}),
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
describe('getFlags', () => {
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
;[posthog, mocks] = createTestClient('TEST_API_KEY', { flushAt: 1 })
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('should handle successful v1 response and return normalized response', async () => {
|
|
25
|
+
const mockV1Response = {
|
|
26
|
+
featureFlags: { 'test-flag': true },
|
|
27
|
+
featureFlagPayloads: { 'test-flag': { a: 'payload' } },
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const expectedResponse = {
|
|
31
|
+
...mockV1Response,
|
|
32
|
+
flags: {
|
|
33
|
+
'test-flag': {
|
|
34
|
+
key: 'test-flag',
|
|
35
|
+
enabled: true,
|
|
36
|
+
variant: undefined,
|
|
37
|
+
reason: undefined,
|
|
38
|
+
metadata: {
|
|
39
|
+
id: undefined,
|
|
40
|
+
version: undefined,
|
|
41
|
+
description: undefined,
|
|
42
|
+
payload: '{"a":"payload"}',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
mocks.fetch.mockImplementation((url) => {
|
|
49
|
+
if (url.includes('/flags/?v=2&config=true')) {
|
|
50
|
+
return Promise.resolve({
|
|
51
|
+
status: 200,
|
|
52
|
+
text: () => Promise.resolve('ok'),
|
|
53
|
+
json: () => Promise.resolve(mockV1Response),
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
return errorAPIResponse
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
const response = await posthog.getFlags('test-distinct-id')
|
|
60
|
+
expect(response).toEqual(expectedResponse)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('should handle successful v4 response and return normalized response', async () => {
|
|
64
|
+
const mockV4Response = {
|
|
65
|
+
flags: {
|
|
66
|
+
'test-flag': {
|
|
67
|
+
key: 'test-flag',
|
|
68
|
+
enabled: true,
|
|
69
|
+
variant: 'test-payload',
|
|
70
|
+
reason: {
|
|
71
|
+
code: 'matched_condition',
|
|
72
|
+
description: 'matched condition set 1',
|
|
73
|
+
condition_index: 0,
|
|
74
|
+
},
|
|
75
|
+
metadata: {
|
|
76
|
+
id: 1,
|
|
77
|
+
version: 1,
|
|
78
|
+
description: 'test-flag',
|
|
79
|
+
payload: '{"a":"payload"}',
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const expectedResponse = {
|
|
86
|
+
...mockV4Response,
|
|
87
|
+
featureFlags: { 'test-flag': 'test-payload' },
|
|
88
|
+
featureFlagPayloads: { 'test-flag': { a: 'payload' } },
|
|
89
|
+
}
|
|
90
|
+
mocks.fetch.mockImplementation((url) => {
|
|
91
|
+
if (url.includes('/flags/?v=2&config=true')) {
|
|
92
|
+
return Promise.resolve({
|
|
93
|
+
status: 200,
|
|
94
|
+
text: () => Promise.resolve('ok'),
|
|
95
|
+
json: () => Promise.resolve(mockV4Response),
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
return errorAPIResponse
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
const response = await posthog.getFlags('test-distinct-id')
|
|
102
|
+
expect(response).toEqual(expectedResponse)
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
it('should handle error response', async () => {
|
|
106
|
+
mocks.fetch.mockImplementation((url) => {
|
|
107
|
+
if (url.includes('/flags/?v=2&config=true')) {
|
|
108
|
+
return Promise.resolve({
|
|
109
|
+
status: 400,
|
|
110
|
+
text: () => Promise.resolve('error'),
|
|
111
|
+
json: () => Promise.resolve({ error: 'went wrong' }),
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
return errorAPIResponse
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
const response = await posthog.getFlags('test-distinct-id')
|
|
118
|
+
expect(response).toBeUndefined()
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
it('should handle network errors', async () => {
|
|
122
|
+
const emitSpy = jest.spyOn(posthog['_events'], 'emit')
|
|
123
|
+
mocks.fetch.mockImplementation((url) => {
|
|
124
|
+
if (url.includes('/flags/?v=2&config=true')) {
|
|
125
|
+
return Promise.reject(new Error('Network error'))
|
|
126
|
+
}
|
|
127
|
+
return errorAPIResponse
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
const response = await posthog.getFlags('test-distinct-id')
|
|
131
|
+
expect(response).toBeUndefined()
|
|
132
|
+
expect(emitSpy).toHaveBeenCalledWith('error', expect.any(Error))
|
|
133
|
+
})
|
|
134
|
+
})
|
|
135
|
+
})
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { createTestClient, PostHogCoreTestClient, PostHogCoreTestClientMocks } from '@/testing'
|
|
2
|
+
|
|
3
|
+
describe('PostHog Core', () => {
|
|
4
|
+
let posthog: PostHogCoreTestClient
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
6
|
+
let mocks: PostHogCoreTestClientMocks
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
;[posthog, mocks] = createTestClient('TEST_API_KEY', {})
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
describe('debug', () => {
|
|
13
|
+
it('should log emitted events when enabled', () => {
|
|
14
|
+
const spy = jest.spyOn(console, 'log')
|
|
15
|
+
|
|
16
|
+
posthog.capture('test-event1')
|
|
17
|
+
expect(spy).toHaveBeenCalledTimes(0)
|
|
18
|
+
|
|
19
|
+
posthog.debug()
|
|
20
|
+
posthog.capture('test-event1')
|
|
21
|
+
expect(spy).toHaveBeenCalledTimes(1)
|
|
22
|
+
expect(spy).toHaveBeenCalledWith(
|
|
23
|
+
'PostHog Debug',
|
|
24
|
+
'capture',
|
|
25
|
+
expect.objectContaining({
|
|
26
|
+
event: 'test-event1',
|
|
27
|
+
})
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
spy.mockReset()
|
|
31
|
+
posthog.debug(false)
|
|
32
|
+
posthog.capture('test-event1')
|
|
33
|
+
expect(spy).toHaveBeenCalledTimes(0)
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
})
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { PostHogPersistedProperty } from '@/types'
|
|
2
|
+
import { createTestClient, PostHogCoreTestClient, PostHogCoreTestClientMocks } from '@/testing'
|
|
3
|
+
|
|
4
|
+
describe('PostHog Core', () => {
|
|
5
|
+
let posthog: PostHogCoreTestClient
|
|
6
|
+
let mocks: PostHogCoreTestClientMocks
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
jest.setSystemTime(new Date('2022-01-01'))
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
function createSut(maxQueueSize: number = 1000, flushAt: number = 20): void {
|
|
13
|
+
;[posthog, mocks] = createTestClient('TEST_API_KEY', {
|
|
14
|
+
maxQueueSize: maxQueueSize,
|
|
15
|
+
flushAt: flushAt,
|
|
16
|
+
})
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe('enqueue', () => {
|
|
20
|
+
it('should add a message to the queue', () => {
|
|
21
|
+
createSut()
|
|
22
|
+
|
|
23
|
+
posthog.capture('type', {
|
|
24
|
+
foo: 'bar',
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
expect(posthog.getPersistedProperty(PostHogPersistedProperty.Queue)).toHaveLength(1)
|
|
28
|
+
|
|
29
|
+
const item = posthog.getPersistedProperty<any[]>(PostHogPersistedProperty.Queue)?.pop()
|
|
30
|
+
|
|
31
|
+
expect(item).toMatchObject({
|
|
32
|
+
message: {
|
|
33
|
+
library: 'posthog-core-tests',
|
|
34
|
+
library_version: '2.0.0-alpha',
|
|
35
|
+
type: 'capture',
|
|
36
|
+
properties: {
|
|
37
|
+
foo: 'bar',
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
expect(mocks.fetch).not.toHaveBeenCalled()
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('should delete oldest message if queue is full', () => {
|
|
46
|
+
createSut(2, 2)
|
|
47
|
+
|
|
48
|
+
posthog.capture('type1', {
|
|
49
|
+
foo: 'bar',
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
posthog.capture('type2', {
|
|
53
|
+
foo: 'bar',
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
posthog.capture('type3', {
|
|
57
|
+
foo: 'bar',
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
expect(posthog.getPersistedProperty(PostHogPersistedProperty.Queue)).toHaveLength(2)
|
|
61
|
+
|
|
62
|
+
let item = posthog.getPersistedProperty<any[]>(PostHogPersistedProperty.Queue)?.pop()
|
|
63
|
+
|
|
64
|
+
expect(item).toMatchObject({
|
|
65
|
+
message: {
|
|
66
|
+
library: 'posthog-core-tests',
|
|
67
|
+
library_version: '2.0.0-alpha',
|
|
68
|
+
type: 'capture',
|
|
69
|
+
properties: {
|
|
70
|
+
foo: 'bar',
|
|
71
|
+
},
|
|
72
|
+
event: 'type3',
|
|
73
|
+
},
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
item = posthog.getPersistedProperty<any[]>(PostHogPersistedProperty.Queue)?.pop()
|
|
77
|
+
|
|
78
|
+
expect(item).toMatchObject({
|
|
79
|
+
message: {
|
|
80
|
+
library: 'posthog-core-tests',
|
|
81
|
+
library_version: '2.0.0-alpha',
|
|
82
|
+
type: 'capture',
|
|
83
|
+
properties: {
|
|
84
|
+
foo: 'bar',
|
|
85
|
+
},
|
|
86
|
+
event: 'type2',
|
|
87
|
+
},
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
expect(mocks.fetch).not.toHaveBeenCalled()
|
|
91
|
+
})
|
|
92
|
+
})
|
|
93
|
+
})
|