@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.
Files changed (128) hide show
  1. package/dist/error-tracking/chunk-ids.js +1 -1
  2. package/dist/error-tracking/chunk-ids.mjs +1 -1
  3. package/dist/error-tracking/coercers/error-event-coercer.js +4 -5
  4. package/dist/error-tracking/coercers/error-event-coercer.mjs +4 -5
  5. package/dist/error-tracking/coercers/event-coercer.js +1 -2
  6. package/dist/error-tracking/coercers/event-coercer.mjs +1 -2
  7. package/dist/error-tracking/coercers/object-coercer.js +1 -2
  8. package/dist/error-tracking/coercers/object-coercer.mjs +1 -2
  9. package/dist/error-tracking/coercers/primitive-coercer.js +1 -2
  10. package/dist/error-tracking/coercers/primitive-coercer.mjs +1 -2
  11. package/dist/error-tracking/coercers/promise-rejection-event.js +4 -5
  12. package/dist/error-tracking/coercers/promise-rejection-event.mjs +4 -5
  13. package/dist/error-tracking/coercers/string-coercer.js +3 -4
  14. package/dist/error-tracking/coercers/string-coercer.mjs +3 -4
  15. package/dist/error-tracking/coercers/utils.js +2 -4
  16. package/dist/error-tracking/coercers/utils.mjs +2 -4
  17. package/dist/error-tracking/error-properties-builder.d.ts +6 -6
  18. package/dist/error-tracking/error-properties-builder.d.ts.map +1 -1
  19. package/dist/error-tracking/error-properties-builder.js +17 -27
  20. package/dist/error-tracking/error-properties-builder.mjs +16 -26
  21. package/dist/error-tracking/parsers/index.js +2 -4
  22. package/dist/error-tracking/parsers/index.mjs +2 -4
  23. package/dist/error-tracking/parsers/node.js +3 -5
  24. package/dist/error-tracking/parsers/node.mjs +3 -5
  25. package/dist/error-tracking/utils.js +4 -4
  26. package/dist/error-tracking/utils.mjs +4 -4
  27. package/dist/eventemitter.js +4 -4
  28. package/dist/eventemitter.mjs +4 -4
  29. package/dist/featureFlagUtils.js +20 -45
  30. package/dist/featureFlagUtils.mjs +20 -45
  31. package/dist/gzip.js +1 -2
  32. package/dist/gzip.mjs +1 -2
  33. package/dist/index.d.ts +4 -366
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +54 -1225
  36. package/dist/index.mjs +5 -1190
  37. package/dist/posthog-core-stateless.d.ts +204 -0
  38. package/dist/posthog-core-stateless.d.ts.map +1 -0
  39. package/dist/posthog-core-stateless.js +675 -0
  40. package/dist/posthog-core-stateless.mjs +632 -0
  41. package/dist/posthog-core.d.ts +171 -0
  42. package/dist/posthog-core.d.ts.map +1 -0
  43. package/dist/posthog-core.js +554 -0
  44. package/dist/posthog-core.mjs +520 -0
  45. package/dist/testing/PostHogCoreTestClient.d.ts +2 -1
  46. package/dist/testing/PostHogCoreTestClient.d.ts.map +1 -1
  47. package/dist/testing/PostHogCoreTestClient.js +9 -11
  48. package/dist/testing/PostHogCoreTestClient.mjs +8 -10
  49. package/dist/testing/test-utils.js +1 -1
  50. package/dist/testing/test-utils.mjs +1 -1
  51. package/dist/utils/bucketed-rate-limiter.js +8 -12
  52. package/dist/utils/bucketed-rate-limiter.mjs +8 -12
  53. package/dist/utils/index.js +3 -3
  54. package/dist/utils/index.mjs +3 -3
  55. package/dist/utils/type-utils.js +1 -1
  56. package/dist/utils/type-utils.mjs +1 -1
  57. package/dist/vendor/uuidv7.js +12 -16
  58. package/dist/vendor/uuidv7.mjs +12 -16
  59. package/package.json +3 -2
  60. package/src/__tests__/featureFlagUtils.spec.ts +427 -0
  61. package/src/__tests__/gzip.spec.ts +69 -0
  62. package/src/__tests__/posthog.ai.spec.ts +110 -0
  63. package/src/__tests__/posthog.capture.spec.ts +91 -0
  64. package/src/__tests__/posthog.core.spec.ts +135 -0
  65. package/src/__tests__/posthog.debug.spec.ts +36 -0
  66. package/src/__tests__/posthog.enqueue.spec.ts +93 -0
  67. package/src/__tests__/posthog.featureflags.spec.ts +1106 -0
  68. package/src/__tests__/posthog.featureflags.v1.spec.ts +922 -0
  69. package/src/__tests__/posthog.flush.spec.ts +237 -0
  70. package/src/__tests__/posthog.gdpr.spec.ts +50 -0
  71. package/src/__tests__/posthog.groups.spec.ts +96 -0
  72. package/src/__tests__/posthog.identify.spec.ts +194 -0
  73. package/src/__tests__/posthog.init.spec.ts +110 -0
  74. package/src/__tests__/posthog.listeners.spec.ts +51 -0
  75. package/src/__tests__/posthog.register.spec.ts +47 -0
  76. package/src/__tests__/posthog.reset.spec.ts +76 -0
  77. package/src/__tests__/posthog.sessions.spec.ts +63 -0
  78. package/src/__tests__/posthog.setProperties.spec.ts +102 -0
  79. package/src/__tests__/posthog.shutdown.spec.ts +88 -0
  80. package/src/__tests__/utils.spec.ts +36 -0
  81. package/src/error-tracking/chunk-ids.ts +58 -0
  82. package/src/error-tracking/coercers/dom-exception-coercer.ts +38 -0
  83. package/src/error-tracking/coercers/error-coercer.ts +36 -0
  84. package/src/error-tracking/coercers/error-event-coercer.ts +24 -0
  85. package/src/error-tracking/coercers/event-coercer.ts +19 -0
  86. package/src/error-tracking/coercers/index.ts +8 -0
  87. package/src/error-tracking/coercers/object-coercer.ts +76 -0
  88. package/src/error-tracking/coercers/primitive-coercer.ts +19 -0
  89. package/src/error-tracking/coercers/promise-rejection-event.spec.ts +77 -0
  90. package/src/error-tracking/coercers/promise-rejection-event.ts +53 -0
  91. package/src/error-tracking/coercers/string-coercer.spec.ts +26 -0
  92. package/src/error-tracking/coercers/string-coercer.ts +31 -0
  93. package/src/error-tracking/coercers/utils.ts +33 -0
  94. package/src/error-tracking/error-properties-builder.coerce.spec.ts +202 -0
  95. package/src/error-tracking/error-properties-builder.parse.spec.ts +30 -0
  96. package/src/error-tracking/error-properties-builder.ts +167 -0
  97. package/src/error-tracking/index.ts +5 -0
  98. package/src/error-tracking/parsers/base.ts +29 -0
  99. package/src/error-tracking/parsers/chrome.ts +53 -0
  100. package/src/error-tracking/parsers/gecko.ts +38 -0
  101. package/src/error-tracking/parsers/index.ts +104 -0
  102. package/src/error-tracking/parsers/node.ts +111 -0
  103. package/src/error-tracking/parsers/opera.ts +18 -0
  104. package/src/error-tracking/parsers/react-native.ts +0 -0
  105. package/src/error-tracking/parsers/safari.ts +33 -0
  106. package/src/error-tracking/parsers/winjs.ts +12 -0
  107. package/src/error-tracking/types.ts +107 -0
  108. package/src/error-tracking/utils.ts +39 -0
  109. package/src/eventemitter.ts +27 -0
  110. package/src/featureFlagUtils.ts +192 -0
  111. package/src/gzip.ts +29 -0
  112. package/src/index.ts +8 -0
  113. package/src/posthog-core-stateless.ts +1226 -0
  114. package/src/posthog-core.ts +958 -0
  115. package/src/testing/PostHogCoreTestClient.ts +91 -0
  116. package/src/testing/index.ts +2 -0
  117. package/src/testing/test-utils.ts +47 -0
  118. package/src/types.ts +544 -0
  119. package/src/utils/bucketed-rate-limiter.spec.ts +33 -0
  120. package/src/utils/bucketed-rate-limiter.ts +85 -0
  121. package/src/utils/index.ts +98 -0
  122. package/src/utils/number-utils.spec.ts +89 -0
  123. package/src/utils/number-utils.ts +30 -0
  124. package/src/utils/promise-queue.spec.ts +55 -0
  125. package/src/utils/promise-queue.ts +30 -0
  126. package/src/utils/string-utils.ts +23 -0
  127. package/src/utils/type-utils.ts +134 -0
  128. package/src/vendor/uuidv7.ts +479 -0
@@ -0,0 +1,91 @@
1
+ import { PostHogCore } from '@/posthog-core'
2
+ import type {
3
+ JsonType,
4
+ PostHogCoreOptions,
5
+ PostHogFetchOptions,
6
+ PostHogFetchResponse,
7
+ PostHogFlagsResponse,
8
+ } from '@/types'
9
+
10
+ const version = '2.0.0-alpha'
11
+
12
+ export interface PostHogCoreTestClientMocks {
13
+ fetch: jest.Mock<Promise<PostHogFetchResponse>, [string, PostHogFetchOptions]>
14
+ storage: {
15
+ getItem: jest.Mock<any | undefined, [string]>
16
+ setItem: jest.Mock<void, [string, any | null]>
17
+ }
18
+ }
19
+
20
+ export class PostHogCoreTestClient extends PostHogCore {
21
+ public _cachedDistinctId?: string
22
+
23
+ constructor(
24
+ private mocks: PostHogCoreTestClientMocks,
25
+ apiKey: string,
26
+ options?: PostHogCoreOptions
27
+ ) {
28
+ super(apiKey, options)
29
+
30
+ this.setupBootstrap(options)
31
+ }
32
+
33
+ // Expose protected methods for testing
34
+ public getFlags(
35
+ distinctId: string,
36
+ groups: Record<string, string | number> = {},
37
+ personProperties: Record<string, string> = {},
38
+ groupProperties: Record<string, Record<string, string>> = {},
39
+ extraPayload: Record<string, any> = {}
40
+ ): Promise<PostHogFlagsResponse | undefined> {
41
+ return super.getFlags(distinctId, groups, personProperties, groupProperties, extraPayload)
42
+ }
43
+
44
+ getPersistedProperty<T>(key: string): T {
45
+ return this.mocks.storage.getItem(key)
46
+ }
47
+ setPersistedProperty<T>(key: string, value: T | null): void {
48
+ return this.mocks.storage.setItem(key, value)
49
+ }
50
+ fetch(url: string, options: PostHogFetchOptions): Promise<PostHogFetchResponse> {
51
+ return this.mocks.fetch(url, options)
52
+ }
53
+ getLibraryId(): string {
54
+ return 'posthog-core-tests'
55
+ }
56
+ getLibraryVersion(): string {
57
+ return version
58
+ }
59
+ getCustomUserAgent(): string {
60
+ return 'posthog-core-tests'
61
+ }
62
+ }
63
+
64
+ export const createTestClient = (
65
+ apiKey: string,
66
+ options?: PostHogCoreOptions,
67
+ setupMocks?: (mocks: PostHogCoreTestClientMocks) => void,
68
+ storageCache: { [key: string]: string | JsonType } = {}
69
+ ): [PostHogCoreTestClient, PostHogCoreTestClientMocks] => {
70
+ const mocks = {
71
+ fetch: jest.fn(),
72
+ storage: {
73
+ getItem: jest.fn((key) => storageCache[key]),
74
+ setItem: jest.fn((key, val) => {
75
+ storageCache[key] = val == null ? undefined : val
76
+ }),
77
+ },
78
+ }
79
+
80
+ mocks.fetch.mockImplementation(() =>
81
+ Promise.resolve({
82
+ status: 200,
83
+ text: () => Promise.resolve('ok'),
84
+ json: () => Promise.resolve({ status: 'ok' }),
85
+ })
86
+ )
87
+
88
+ setupMocks?.(mocks)
89
+
90
+ return [new PostHogCoreTestClient(mocks, apiKey, { disableCompression: true, ...options }), mocks]
91
+ }
@@ -0,0 +1,2 @@
1
+ export * from './PostHogCoreTestClient'
2
+ export * from './test-utils'
@@ -0,0 +1,47 @@
1
+ import { Logger } from '@/types'
2
+
3
+ export const wait = async (t: number): Promise<void> => {
4
+ await new Promise((r) => setTimeout(r, t))
5
+ }
6
+
7
+ export const waitForPromises = async (): Promise<void> => {
8
+ await new Promise((resolve) => {
9
+ // IMPORTANT: Only enable real timers for this promise - allows us to pass a short amount of ticks
10
+ // whilst keeping any timers made during other promises as fake timers
11
+ jest.useRealTimers()
12
+ setTimeout(resolve, 10)
13
+ jest.useFakeTimers()
14
+ })
15
+ }
16
+
17
+ export const parseBody = (mockCall: any): any => {
18
+ const options = mockCall[1]
19
+ expect(options.method).toBe('POST')
20
+ return JSON.parse(options.body || '')
21
+ }
22
+
23
+ export const createImperativePromise = <T>(): [Promise<T>, (value: T) => void] => {
24
+ let resolve: (value: T) => void
25
+ const promise = new Promise<T>((r) => {
26
+ resolve = r
27
+ })
28
+ return [promise, (val) => resolve?.(val)]
29
+ }
30
+
31
+ export const delay = (ms: number): Promise<void> => {
32
+ return new Promise((resolve) => {
33
+ setTimeout(resolve, ms)
34
+ })
35
+ }
36
+
37
+ export const createMockLogger = (): Logger => {
38
+ return {
39
+ _log: jest.fn(),
40
+ info: jest.fn(),
41
+ warn: jest.fn(),
42
+ error: jest.fn(),
43
+ critical: jest.fn(),
44
+ uninitializedWarning: jest.fn(),
45
+ createLogger: createMockLogger,
46
+ }
47
+ }
package/src/types.ts ADDED
@@ -0,0 +1,544 @@
1
+ export type PostHogCoreOptions = {
2
+ /** PostHog API host, usually 'https://us.i.posthog.com' or 'https://eu.i.posthog.com' */
3
+ host?: string
4
+ /** The number of events to queue before sending to PostHog (flushing) */
5
+ flushAt?: number
6
+ /** The interval in milliseconds between periodic flushes */
7
+ flushInterval?: number
8
+ /** The maximum number of queued messages to be flushed as part of a single batch (must be higher than `flushAt`) */
9
+ maxBatchSize?: number
10
+ /** The maximum number of cached messages either in memory or on the local storage.
11
+ * Defaults to 1000, (must be higher than `flushAt`)
12
+ */
13
+ maxQueueSize?: number
14
+ /** If set to true the SDK is essentially disabled (useful for local environments where you don't want to track anything) */
15
+ disabled?: boolean
16
+ /** If set to false the SDK will not track until the `optIn` function is called. */
17
+ defaultOptIn?: boolean
18
+ /** Whether to track that `getFeatureFlag` was called (used by Experiments) */
19
+ sendFeatureFlagEvent?: boolean
20
+ /** Whether to load feature flags when initialized or not */
21
+ preloadFeatureFlags?: boolean
22
+ /**
23
+ * Whether to load remote config when initialized or not
24
+ * Experimental support
25
+ * Default: false - Remote config is loaded by default
26
+ */
27
+ disableRemoteConfig?: boolean
28
+ /**
29
+ * Whether to load surveys when initialized or not
30
+ * Experimental support
31
+ * Default: false - Surveys are loaded by default, but requires the `PostHogSurveyProvider` to be used
32
+ */
33
+ disableSurveys?: boolean
34
+ /** Option to bootstrap the library with given distinctId and feature flags */
35
+ bootstrap?: {
36
+ distinctId?: string
37
+ isIdentifiedId?: boolean
38
+ featureFlags?: Record<string, FeatureFlagValue>
39
+ featureFlagPayloads?: Record<string, JsonType>
40
+ }
41
+ /** How many times we will retry HTTP requests. Defaults to 3. */
42
+ fetchRetryCount?: number
43
+ /** The delay between HTTP request retries, Defaults to 3 seconds. */
44
+ fetchRetryDelay?: number
45
+ /** Timeout in milliseconds for any calls. Defaults to 10 seconds. */
46
+ requestTimeout?: number
47
+ /** Timeout in milliseconds for feature flag calls. Defaults to 10 seconds for stateful clients, and 3 seconds for stateless. */
48
+ featureFlagsRequestTimeoutMs?: number
49
+ /** Timeout in milliseconds for remote config calls. Defaults to 3 seconds. */
50
+ remoteConfigRequestTimeoutMs?: number
51
+ /** For Session Analysis how long before we expire a session (defaults to 30 mins) */
52
+ sessionExpirationTimeSeconds?: number
53
+ /** Whether to disable GZIP compression */
54
+ disableCompression?: boolean
55
+ disableGeoip?: boolean
56
+ /** Special flag to indicate ingested data is for a historical migration. */
57
+ historicalMigration?: boolean
58
+ }
59
+
60
+ export enum PostHogPersistedProperty {
61
+ AnonymousId = 'anonymous_id',
62
+ DistinctId = 'distinct_id',
63
+ Props = 'props',
64
+ FeatureFlagDetails = 'feature_flag_details',
65
+ FeatureFlags = 'feature_flags',
66
+ FeatureFlagPayloads = 'feature_flag_payloads',
67
+ BootstrapFeatureFlagDetails = 'bootstrap_feature_flag_details',
68
+ BootstrapFeatureFlags = 'bootstrap_feature_flags',
69
+ BootstrapFeatureFlagPayloads = 'bootstrap_feature_flag_payloads',
70
+ OverrideFeatureFlags = 'override_feature_flags',
71
+ Queue = 'queue',
72
+ OptedOut = 'opted_out',
73
+ SessionId = 'session_id',
74
+ SessionStartTimestamp = 'session_start_timestamp',
75
+ SessionLastTimestamp = 'session_timestamp',
76
+ PersonProperties = 'person_properties',
77
+ GroupProperties = 'group_properties',
78
+ InstalledAppBuild = 'installed_app_build', // only used by posthog-react-native
79
+ InstalledAppVersion = 'installed_app_version', // only used by posthog-react-native
80
+ SessionReplay = 'session_replay', // only used by posthog-react-native
81
+ SurveyLastSeenDate = 'survey_last_seen_date', // only used by posthog-react-native
82
+ SurveysSeen = 'surveys_seen', // only used by posthog-react-native
83
+ Surveys = 'surveys', // only used by posthog-react-native
84
+ RemoteConfig = 'remote_config',
85
+ FlagsEndpointWasHit = 'flags_endpoint_was_hit', // only used by posthog-react-native
86
+ }
87
+
88
+ export type PostHogFetchOptions = {
89
+ method: 'GET' | 'POST' | 'PUT' | 'PATCH'
90
+ mode?: 'no-cors'
91
+ credentials?: 'omit'
92
+ headers: { [key: string]: string }
93
+ body?: string | Blob
94
+ signal?: AbortSignal
95
+ }
96
+
97
+ // Check out posthog-js for these additional options and try to keep them in sync
98
+ export type PostHogCaptureOptions = {
99
+ /** If provided overrides the auto-generated event ID */
100
+ uuid?: string
101
+ /** If provided overrides the auto-generated timestamp */
102
+ timestamp?: Date
103
+ disableGeoip?: boolean
104
+ }
105
+
106
+ export type PostHogFetchResponse = {
107
+ status: number
108
+ text: () => Promise<string>
109
+ json: () => Promise<any>
110
+ }
111
+
112
+ export type PostHogQueueItem = {
113
+ message: any
114
+ callback?: (err: any) => void
115
+ }
116
+
117
+ export type PostHogEventProperties = {
118
+ [key: string]: JsonType
119
+ }
120
+
121
+ export type PostHogGroupProperties = {
122
+ [type: string]: string | number
123
+ }
124
+
125
+ export type PostHogAutocaptureElement = {
126
+ $el_text?: string
127
+ tag_name: string
128
+ href?: string
129
+ nth_child?: number
130
+ nth_of_type?: number
131
+ order?: number
132
+ } & PostHogEventProperties
133
+ // Any key prefixed with `attr__` can be added
134
+
135
+ export enum Compression {
136
+ GZipJS = 'gzip-js',
137
+ Base64 = 'base64',
138
+ }
139
+
140
+ export type PostHogRemoteConfig = {
141
+ sessionRecording?:
142
+ | boolean
143
+ | {
144
+ [key: string]: JsonType
145
+ }
146
+
147
+ /**
148
+ * Supported compression algorithms
149
+ */
150
+ supportedCompression?: Compression[]
151
+
152
+ /**
153
+ * Whether surveys are enabled
154
+ */
155
+ surveys?: boolean | Survey[]
156
+
157
+ /**
158
+ * Indicates if the team has any flags enabled (if not we don't need to load them)
159
+ */
160
+ hasFeatureFlags?: boolean
161
+ }
162
+
163
+ export type FeatureFlagValue = string | boolean
164
+
165
+ export type PostHogFlagsResponse = Omit<PostHogRemoteConfig, 'surveys' | 'hasFeatureFlags'> & {
166
+ featureFlags: {
167
+ [key: string]: FeatureFlagValue
168
+ }
169
+ featureFlagPayloads: {
170
+ [key: string]: JsonType
171
+ }
172
+ flags: {
173
+ [key: string]: FeatureFlagDetail
174
+ }
175
+ errorsWhileComputingFlags: boolean
176
+ sessionRecording?:
177
+ | boolean
178
+ | {
179
+ [key: string]: JsonType
180
+ }
181
+ quotaLimited?: string[]
182
+ requestId?: string
183
+ }
184
+
185
+ export type PostHogFeatureFlagsResponse = PartialWithRequired<
186
+ PostHogFlagsResponse,
187
+ 'flags' | 'featureFlags' | 'featureFlagPayloads' | 'requestId'
188
+ >
189
+
190
+ /**
191
+ * Creates a type with all properties of T, but makes only K properties required while the rest remain optional.
192
+ *
193
+ * @template T - The base type containing all properties
194
+ * @template K - Union type of keys from T that should be required
195
+ *
196
+ * @example
197
+ * interface User {
198
+ * id: number;
199
+ * name: string;
200
+ * email?: string;
201
+ * age?: number;
202
+ * }
203
+ *
204
+ * // Makes 'id' and 'name' required, but 'email' and 'age' optional
205
+ * type RequiredUser = PartialWithRequired<User, 'id' | 'name'>;
206
+ *
207
+ * const user: RequiredUser = {
208
+ * id: 1, // Must be provided
209
+ * name: "John" // Must be provided
210
+ * // email and age are optional
211
+ * };
212
+ */
213
+ export type PartialWithRequired<T, K extends keyof T> = {
214
+ [P in K]: T[P] // Required fields
215
+ } & {
216
+ [P in Exclude<keyof T, K>]?: T[P] // Optional fields
217
+ }
218
+
219
+ /**
220
+ * These are the fields we care about from PostHogFlagsResponse for feature flags.
221
+ */
222
+ export type PostHogFeatureFlagDetails = PartialWithRequired<
223
+ PostHogFlagsResponse,
224
+ 'flags' | 'featureFlags' | 'featureFlagPayloads' | 'requestId'
225
+ >
226
+
227
+ /**
228
+ * Models the response from the v1 `/flags` endpoint.
229
+ */
230
+ export type PostHogV1FlagsResponse = Omit<PostHogFlagsResponse, 'flags'>
231
+
232
+ /**
233
+ * Models the response from the v2 `/flags` endpoint.
234
+ */
235
+ export type PostHogV2FlagsResponse = Omit<PostHogFlagsResponse, 'featureFlags' | 'featureFlagPayloads'>
236
+
237
+ /**
238
+ * The format of the flags object in persisted storage
239
+ *
240
+ * When we pull flags from persistence, we can normalize them to PostHogFeatureFlagDetails
241
+ * so that we can support v1 and v2 of the API.
242
+ */
243
+ export type PostHogFlagsStorageFormat = Pick<PostHogFeatureFlagDetails, 'flags'>
244
+
245
+ /**
246
+ * Models legacy flags and payloads return type for many public methods.
247
+ */
248
+ export type PostHogFlagsAndPayloadsResponse = Partial<
249
+ Pick<PostHogFlagsResponse, 'featureFlags' | 'featureFlagPayloads'>
250
+ >
251
+
252
+ export type JsonType = string | number | boolean | null | { [key: string]: JsonType } | Array<JsonType> | JsonType[]
253
+
254
+ export type FetchLike = (url: string, options: PostHogFetchOptions) => Promise<PostHogFetchResponse>
255
+
256
+ export type FeatureFlagDetail = {
257
+ key: string
258
+ enabled: boolean
259
+ variant: string | undefined
260
+ reason: EvaluationReason | undefined
261
+ metadata: FeatureFlagMetadata | undefined
262
+ }
263
+
264
+ export type FeatureFlagMetadata = {
265
+ id: number | undefined
266
+ version: number | undefined
267
+ description: string | undefined
268
+ // Payloads in the response are always JSON encoded as a string
269
+ payload: string | undefined
270
+ }
271
+
272
+ export type EvaluationReason = {
273
+ code: string | undefined
274
+ condition_index: number | undefined
275
+ description: string | undefined
276
+ }
277
+
278
+ // survey types
279
+ export type SurveyAppearance = {
280
+ // keep in sync with frontend/src/types.ts -> SurveyAppearance
281
+ backgroundColor?: string
282
+ submitButtonColor?: string
283
+ // deprecate submit button text eventually
284
+ submitButtonText?: string
285
+ submitButtonTextColor?: string
286
+ ratingButtonColor?: string
287
+ ratingButtonActiveColor?: string
288
+ autoDisappear?: boolean
289
+ displayThankYouMessage?: boolean
290
+ thankYouMessageHeader?: string
291
+ thankYouMessageDescription?: string
292
+ thankYouMessageDescriptionContentType?: SurveyQuestionDescriptionContentType
293
+ thankYouMessageCloseButtonText?: string
294
+ borderColor?: string
295
+ position?: SurveyPosition
296
+ placeholder?: string
297
+ shuffleQuestions?: boolean
298
+ surveyPopupDelaySeconds?: number
299
+ // widget options
300
+ widgetType?: SurveyWidgetType
301
+ widgetSelector?: string
302
+ widgetLabel?: string
303
+ widgetColor?: string
304
+ }
305
+
306
+ export enum SurveyPosition {
307
+ TopLeft = 'top_left',
308
+ TopCenter = 'top_center',
309
+ TopRight = 'top_right',
310
+ MiddleLeft = 'middle_left',
311
+ MiddleCenter = 'middle_center',
312
+ MiddleRight = 'middle_right',
313
+ Left = 'left',
314
+ Right = 'right',
315
+ Center = 'center',
316
+ }
317
+
318
+ export enum SurveyWidgetType {
319
+ Button = 'button',
320
+ Tab = 'tab',
321
+ Selector = 'selector',
322
+ }
323
+
324
+ export enum SurveyType {
325
+ Popover = 'popover',
326
+ API = 'api',
327
+ Widget = 'widget',
328
+ ExternalSurvey = 'external_survey',
329
+ }
330
+
331
+ export type SurveyQuestion = BasicSurveyQuestion | LinkSurveyQuestion | RatingSurveyQuestion | MultipleSurveyQuestion
332
+
333
+ export enum SurveyQuestionDescriptionContentType {
334
+ Html = 'html',
335
+ Text = 'text',
336
+ }
337
+
338
+ type SurveyQuestionBase = {
339
+ question: string
340
+ id?: string // TODO: use this for the question id
341
+ description?: string
342
+ descriptionContentType?: SurveyQuestionDescriptionContentType
343
+ optional?: boolean
344
+ buttonText?: string
345
+ originalQuestionIndex: number
346
+ branching?: NextQuestionBranching | EndBranching | ResponseBasedBranching | SpecificQuestionBranching
347
+ }
348
+
349
+ export type BasicSurveyQuestion = SurveyQuestionBase & {
350
+ type: SurveyQuestionType.Open
351
+ }
352
+
353
+ export type LinkSurveyQuestion = SurveyQuestionBase & {
354
+ type: SurveyQuestionType.Link
355
+ link?: string
356
+ }
357
+
358
+ export type RatingSurveyQuestion = SurveyQuestionBase & {
359
+ type: SurveyQuestionType.Rating
360
+ display: SurveyRatingDisplay
361
+ scale: 3 | 5 | 7 | 10
362
+ lowerBoundLabel: string
363
+ upperBoundLabel: string
364
+ }
365
+
366
+ export enum SurveyRatingDisplay {
367
+ Number = 'number',
368
+ Emoji = 'emoji',
369
+ }
370
+
371
+ export type MultipleSurveyQuestion = SurveyQuestionBase & {
372
+ type: SurveyQuestionType.SingleChoice | SurveyQuestionType.MultipleChoice
373
+ choices: string[]
374
+ hasOpenChoice?: boolean
375
+ shuffleOptions?: boolean
376
+ }
377
+
378
+ export enum SurveyQuestionType {
379
+ Open = 'open',
380
+ MultipleChoice = 'multiple_choice',
381
+ SingleChoice = 'single_choice',
382
+ Rating = 'rating',
383
+ Link = 'link',
384
+ }
385
+
386
+ export enum SurveyQuestionBranchingType {
387
+ NextQuestion = 'next_question',
388
+ End = 'end',
389
+ ResponseBased = 'response_based',
390
+ SpecificQuestion = 'specific_question',
391
+ }
392
+
393
+ export type NextQuestionBranching = {
394
+ type: SurveyQuestionBranchingType.NextQuestion
395
+ }
396
+
397
+ export type EndBranching = {
398
+ type: SurveyQuestionBranchingType.End
399
+ }
400
+
401
+ export type ResponseBasedBranching = {
402
+ type: SurveyQuestionBranchingType.ResponseBased
403
+ responseValues: Record<string, any>
404
+ }
405
+
406
+ export type SpecificQuestionBranching = {
407
+ type: SurveyQuestionBranchingType.SpecificQuestion
408
+ index: number
409
+ }
410
+
411
+ export type SurveyResponse = {
412
+ surveys: Survey[]
413
+ }
414
+
415
+ export type SurveyCallback = (surveys: Survey[]) => void
416
+
417
+ export enum SurveyMatchType {
418
+ Regex = 'regex',
419
+ NotRegex = 'not_regex',
420
+ Exact = 'exact',
421
+ IsNot = 'is_not',
422
+ Icontains = 'icontains',
423
+ NotIcontains = 'not_icontains',
424
+ }
425
+
426
+ export type SurveyElement = {
427
+ text?: string
428
+ $el_text?: string
429
+ tag_name?: string
430
+ href?: string
431
+ attr_id?: string
432
+ attr_class?: string[]
433
+ nth_child?: number
434
+ nth_of_type?: number
435
+ attributes?: Record<string, any>
436
+ event_id?: number
437
+ order?: number
438
+ group_id?: number
439
+ }
440
+ export type SurveyRenderReason = {
441
+ visible: boolean
442
+ disabledReason?: string
443
+ }
444
+
445
+ export type Survey = {
446
+ // Sync this with the backend's SurveyAPISerializer!
447
+ id: string
448
+ name: string
449
+ description?: string
450
+ type: SurveyType
451
+ feature_flag_keys?: {
452
+ key: string
453
+ value?: string
454
+ }[]
455
+ linked_flag_key?: string
456
+ targeting_flag_key?: string
457
+ internal_targeting_flag_key?: string
458
+ questions: SurveyQuestion[]
459
+ appearance?: SurveyAppearance
460
+ conditions?: {
461
+ url?: string
462
+ selector?: string
463
+ seenSurveyWaitPeriodInDays?: number
464
+ urlMatchType?: SurveyMatchType
465
+ events?: {
466
+ repeatedActivation?: boolean
467
+ values?: {
468
+ name: string
469
+ }[]
470
+ }
471
+ actions?: {
472
+ values: SurveyActionType[]
473
+ }
474
+ deviceTypes?: string[]
475
+ deviceTypesMatchType?: SurveyMatchType
476
+ linkedFlagVariant?: string
477
+ }
478
+ start_date?: string
479
+ end_date?: string
480
+ current_iteration?: number
481
+ current_iteration_start_date?: string
482
+ }
483
+
484
+ export type SurveyActionType = {
485
+ id: number
486
+ name?: string
487
+ steps?: ActionStepType[]
488
+ }
489
+
490
+ /** Sync with plugin-server/src/types.ts */
491
+ export enum ActionStepStringMatching {
492
+ Contains = 'contains',
493
+ Exact = 'exact',
494
+ Regex = 'regex',
495
+ }
496
+
497
+ export type ActionStepType = {
498
+ event?: string
499
+ selector?: string
500
+ text?: string
501
+ /** @default StringMatching.Exact */
502
+ text_matching?: ActionStepStringMatching
503
+ href?: string
504
+ /** @default ActionStepStringMatching.Exact */
505
+ href_matching?: ActionStepStringMatching
506
+ url?: string
507
+ /** @default StringMatching.Contains */
508
+ url_matching?: ActionStepStringMatching
509
+ }
510
+
511
+ export type Logger = {
512
+ _log: (level: 'log' | 'warn' | 'error', ...args: any[]) => void
513
+ info: (...args: any[]) => void
514
+ warn: (...args: any[]) => void
515
+ error: (...args: any[]) => void
516
+ critical: (...args: any[]) => void
517
+ uninitializedWarning: (methodName: string) => void
518
+ createLogger: (prefix: string) => Logger
519
+ }
520
+
521
+ export const knownUnsafeEditableEvent = [
522
+ '$snapshot',
523
+ '$pageview',
524
+ '$pageleave',
525
+ '$set',
526
+ 'survey dismissed',
527
+ 'survey sent',
528
+ 'survey shown',
529
+ '$identify',
530
+ '$groupidentify',
531
+ '$create_alias',
532
+ '$$client_ingestion_warning',
533
+ '$web_experiment_applied',
534
+ '$feature_enrollment_update',
535
+ '$feature_flag_called',
536
+ ] as const
537
+
538
+ /**
539
+ * These events can be processed by the `beforeCapture` function
540
+ * but can cause unexpected confusion in data.
541
+ *
542
+ * Some features of PostHog rely on receiving 100% of these events
543
+ */
544
+ export type KnownUnsafeEditableEvent = (typeof knownUnsafeEditableEvent)[number]