@posthog/core 1.33.0 → 1.35.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/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +54 -18
- package/dist/index.mjs +3 -3
- package/dist/logs/index.d.ts +14 -15
- package/dist/logs/index.d.ts.map +1 -1
- package/dist/logs/index.js +46 -18
- package/dist/logs/index.mjs +47 -19
- package/dist/logs/logs-utils.d.ts +16 -1
- package/dist/logs/logs-utils.d.ts.map +1 -1
- package/dist/logs/logs-utils.js +17 -0
- package/dist/logs/logs-utils.mjs +15 -1
- package/dist/logs/types.d.ts +23 -38
- package/dist/logs/types.d.ts.map +1 -1
- package/dist/posthog-core.d.ts +20 -0
- package/dist/posthog-core.d.ts.map +1 -1
- package/dist/posthog-core.js +79 -10
- package/dist/posthog-core.mjs +79 -10
- package/dist/types.d.ts +19 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +2 -1
- package/src/logs/index.spec.ts +259 -0
- package/src/logs/index.ts +108 -49
- package/src/logs/logs-utils.ts +30 -1
- package/src/logs/types.ts +32 -37
- package/src/posthog-core.ts +120 -13
- package/src/types.ts +19 -0
package/src/logs/logs-utils.ts
CHANGED
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
OtlpSeverityEntry,
|
|
10
10
|
OtlpSeverityText,
|
|
11
11
|
} from '@posthog/types'
|
|
12
|
-
import type { LogSdkContext } from './types'
|
|
12
|
+
import type { LogSdkContext, ResolvedPostHogLogsConfig } from './types'
|
|
13
13
|
import { isArray, isBoolean, isNull, isUndefined } from '../utils'
|
|
14
14
|
|
|
15
15
|
// ============================================================================
|
|
@@ -168,6 +168,35 @@ export function buildOtlpLogRecord(options: CaptureLogOptions, sdkContext: LogSd
|
|
|
168
168
|
// OTLP envelope construction
|
|
169
169
|
// ============================================================================
|
|
170
170
|
|
|
171
|
+
/**
|
|
172
|
+
* OTLP resource attributes for every batch, shared by the core flush path and
|
|
173
|
+
* SDK-specific paths that bypass it (e.g. the browser's synchronous sendBeacon
|
|
174
|
+
* drain). Having one builder keeps those paths from drifting.
|
|
175
|
+
*
|
|
176
|
+
* Layout: user `resourceAttributes` spread first, then SDK-controlled keys
|
|
177
|
+
* (`service.name`, `deployment.environment`, `service.version`,
|
|
178
|
+
* `telemetry.sdk.*`) layered on top so a stray user key can't clobber the
|
|
179
|
+
* ingestion-attribution keys. The dedicated `serviceName` / `environment` /
|
|
180
|
+
* `serviceVersion` config fields are the supported way to override the first
|
|
181
|
+
* three; each SDK resolves its own `service.name` default before this point, so
|
|
182
|
+
* the `unknown_service` fallback here only fires if a config slips through with
|
|
183
|
+
* an empty `serviceName`.
|
|
184
|
+
*/
|
|
185
|
+
export function buildResourceAttributes(
|
|
186
|
+
config: ResolvedPostHogLogsConfig,
|
|
187
|
+
scopeName: string,
|
|
188
|
+
scopeVersion: string
|
|
189
|
+
): Record<string, LogAttributeValue> {
|
|
190
|
+
return {
|
|
191
|
+
...config.resourceAttributes,
|
|
192
|
+
'service.name': config.serviceName || 'unknown_service',
|
|
193
|
+
...(config.environment && { 'deployment.environment': config.environment }),
|
|
194
|
+
...(config.serviceVersion && { 'service.version': config.serviceVersion }),
|
|
195
|
+
'telemetry.sdk.name': scopeName,
|
|
196
|
+
'telemetry.sdk.version': scopeVersion,
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
171
200
|
/**
|
|
172
201
|
* Wraps a list of records in the OTLP `resourceLogs` envelope.
|
|
173
202
|
*
|
package/src/logs/types.ts
CHANGED
|
@@ -11,6 +11,7 @@ export type {
|
|
|
11
11
|
OtlpKeyValue,
|
|
12
12
|
OtlpLogRecord,
|
|
13
13
|
OtlpLogsPayload,
|
|
14
|
+
BeforeSendLogFn,
|
|
14
15
|
} from '@posthog/types'
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -39,44 +40,34 @@ export interface LogSdkContext {
|
|
|
39
40
|
import type { Logger as CaptureLoggerType } from '@posthog/types'
|
|
40
41
|
export type CaptureLogger = CaptureLoggerType
|
|
41
42
|
|
|
42
|
-
import type {
|
|
43
|
+
import type {
|
|
44
|
+
LogAttributeValue,
|
|
45
|
+
CaptureLogOptions,
|
|
46
|
+
OtlpLogRecord,
|
|
47
|
+
OtlpLogsPayload,
|
|
48
|
+
BeforeSendLogFn,
|
|
49
|
+
} from '@posthog/types'
|
|
50
|
+
import type { PostHogPersistedProperty } from '../types'
|
|
51
|
+
import type { SendLogsBatchOutcome } from '../posthog-core-stateless'
|
|
43
52
|
|
|
44
53
|
export interface BufferedLogEntry {
|
|
45
54
|
record: OtlpLogRecord
|
|
46
55
|
}
|
|
47
56
|
|
|
48
57
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* Configure as a single fn or an array. Arrays form a left-to-right chain:
|
|
54
|
-
* each fn receives the previous fn's return value. A `null` from any link
|
|
55
|
-
* short-circuits the chain and drops the record.
|
|
56
|
-
*
|
|
57
|
-
* Runs *before* the rate cap so dropped records don't consume the
|
|
58
|
-
* per-interval budget. Throwing fns are logged and skipped — the chain
|
|
59
|
-
* continues with the previous return value, so a buggy filter degrades to a
|
|
60
|
-
* no-op rather than crashing `captureLog()`.
|
|
61
|
-
*
|
|
62
|
-
* @example Redact secrets from log bodies
|
|
63
|
-
* ```ts
|
|
64
|
-
* logs: {
|
|
65
|
-
* beforeSend: (record) => ({
|
|
66
|
-
* ...record,
|
|
67
|
-
* body: record.body.replace(/api_key=\S+/g, 'api_key=[REDACTED]'),
|
|
68
|
-
* }),
|
|
69
|
-
* }
|
|
70
|
-
* ```
|
|
71
|
-
*
|
|
72
|
-
* @example Drop noisy debug logs in production
|
|
73
|
-
* ```ts
|
|
74
|
-
* logs: {
|
|
75
|
-
* beforeSend: (record) => (record.level === 'debug' ? null : record),
|
|
76
|
-
* }
|
|
77
|
-
* ```
|
|
58
|
+
* The minimal host surface `PostHogLogs` depends on. `PostHogCoreStateless`
|
|
59
|
+
* satisfies it structurally (mobile/node); the browser supplies an adapter
|
|
60
|
+
* backed by its own persistence and request layer.
|
|
78
61
|
*/
|
|
79
|
-
export
|
|
62
|
+
export interface LogsHost {
|
|
63
|
+
readonly isDisabled: boolean
|
|
64
|
+
readonly optedOut: boolean
|
|
65
|
+
getPersistedProperty<T>(key: PostHogPersistedProperty): T | undefined
|
|
66
|
+
setPersistedProperty<T>(key: PostHogPersistedProperty, value: T | null): void
|
|
67
|
+
_sendLogsBatch(payload: OtlpLogsPayload): Promise<SendLogsBatchOutcome>
|
|
68
|
+
getLibraryId(): string
|
|
69
|
+
getLibraryVersion(): string
|
|
70
|
+
}
|
|
80
71
|
|
|
81
72
|
/**
|
|
82
73
|
* Configuration for the logs feature on `new PostHog(key, { logs: ... })`.
|
|
@@ -87,7 +78,7 @@ export interface PostHogLogsConfig {
|
|
|
87
78
|
/**
|
|
88
79
|
* Service name attached to every record as the OTLP `service.name`
|
|
89
80
|
* resource attribute. Used by the Logs UI for filtering / grouping.
|
|
90
|
-
*
|
|
81
|
+
* Defaults to `'unknown_service'` when unset.
|
|
91
82
|
*/
|
|
92
83
|
serviceName?: string
|
|
93
84
|
|
|
@@ -121,11 +112,11 @@ export interface PostHogLogsConfig {
|
|
|
121
112
|
flushIntervalMs?: number
|
|
122
113
|
|
|
123
114
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
115
|
+
* Number of buffered records that triggers an immediate flush. Records also
|
|
116
|
+
* flush on the periodic interval and on `shutdown()`. The queue can grow past
|
|
117
|
+
* this while an async flush is in flight (e.g. during a synchronous burst); a
|
|
118
|
+
* separate, larger memory backstop evicts the oldest only once the queue
|
|
119
|
+
* exceeds the per-interval rate cap. Default: 100.
|
|
129
120
|
*/
|
|
130
121
|
maxBufferSize?: number
|
|
131
122
|
|
|
@@ -182,6 +173,10 @@ export interface PostHogLogsConfig {
|
|
|
182
173
|
// Flat names internally — public API uses `rateCap: { maxLogs, windowMs }`.
|
|
183
174
|
export interface ResolvedPostHogLogsConfig extends Omit<PostHogLogsConfig, 'rateCap'> {
|
|
184
175
|
maxBufferSize: number
|
|
176
|
+
// Eviction cap: the queue drops the oldest record once it exceeds this. Separate
|
|
177
|
+
// from `maxBufferSize` (the flush trigger) so a burst is held, not evicted, while
|
|
178
|
+
// the async flush drains. Defaults to `maxBufferSize` when unset.
|
|
179
|
+
maxQueueSize?: number
|
|
185
180
|
flushIntervalMs: number
|
|
186
181
|
maxBatchRecordsPerPost: number
|
|
187
182
|
rateCapWindowMs: number
|
package/src/posthog-core.ts
CHANGED
|
@@ -53,6 +53,7 @@ interface PendingFlagsRequest extends FlagsAsyncOptions {
|
|
|
53
53
|
export abstract class PostHogCore extends PostHogCoreStateless {
|
|
54
54
|
// options
|
|
55
55
|
private sendFeatureFlagEvent: boolean
|
|
56
|
+
private disableRemoteFeatureFlags: boolean
|
|
56
57
|
private flagCallReported: { [key: string]: boolean } = {}
|
|
57
58
|
private _beforeSend?: BeforeSendFn | BeforeSendFn[]
|
|
58
59
|
|
|
@@ -82,6 +83,7 @@ export abstract class PostHogCore extends PostHogCoreStateless {
|
|
|
82
83
|
super(apiKey, { ...options, disableGeoip: disableGeoipOption, featureFlagsRequestTimeoutMs })
|
|
83
84
|
|
|
84
85
|
this.sendFeatureFlagEvent = options?.sendFeatureFlagEvent ?? true
|
|
86
|
+
this.disableRemoteFeatureFlags = options?.disableRemoteFeatureFlags ?? false
|
|
85
87
|
this._sessionExpirationTimeSeconds = options?.sessionExpirationTimeSeconds ?? 1800 // 30 minutes
|
|
86
88
|
this._personProfiles = options?.personProfiles ?? 'identified_only'
|
|
87
89
|
this._beforeSend = options?.before_send
|
|
@@ -178,7 +180,17 @@ export abstract class PostHogCore extends PostHogCoreStateless {
|
|
|
178
180
|
}
|
|
179
181
|
}
|
|
180
182
|
|
|
181
|
-
this.
|
|
183
|
+
if (this.disableRemoteFeatureFlags && !this.disabled) {
|
|
184
|
+
// No reload runs to emit the change, so emit the now-cleared flags directly
|
|
185
|
+
// (drives onFeatureFlags listeners, e.g. session replay re-arm). Callers re-push
|
|
186
|
+
// the new identity's flags via updateFlags(). Skip when the caller kept
|
|
187
|
+
// FeatureFlagDetails — those flags stay as-is, so there's nothing to emit.
|
|
188
|
+
if (!allPropertiesToKeep.includes(PostHogPersistedProperty.FeatureFlagDetails)) {
|
|
189
|
+
this.setKnownFeatureFlagDetails({ flags: {} })
|
|
190
|
+
}
|
|
191
|
+
} else {
|
|
192
|
+
this.reloadFeatureFlags()
|
|
193
|
+
}
|
|
182
194
|
})
|
|
183
195
|
}
|
|
184
196
|
|
|
@@ -585,6 +597,11 @@ export abstract class PostHogCore extends PostHogCoreStateless {
|
|
|
585
597
|
if (this.disabled) {
|
|
586
598
|
return undefined
|
|
587
599
|
}
|
|
600
|
+
// Config-fetching requests still go out (carrying disable_flags); only pure reloads no-op.
|
|
601
|
+
if (this.disableRemoteFeatureFlags && !fetchConfig) {
|
|
602
|
+
this._logger.info('Feature flags are disabled (disableRemoteFeatureFlags), skipping reload.')
|
|
603
|
+
return undefined
|
|
604
|
+
}
|
|
588
605
|
if (this._flagsResponsePromise) {
|
|
589
606
|
// Queue the reload request instead of dropping it
|
|
590
607
|
// This ensures that requests with $anon_distinct_id (from identify()) are not lost
|
|
@@ -696,11 +713,12 @@ export abstract class PostHogCore extends PostHogCoreStateless {
|
|
|
696
713
|
// we only dont load flags if the remote config has no feature flags
|
|
697
714
|
let willLoadFlags = false
|
|
698
715
|
if (response.hasFeatureFlags === false) {
|
|
699
|
-
|
|
700
|
-
|
|
716
|
+
if (!this.disableRemoteFeatureFlags) {
|
|
717
|
+
this.setKnownFeatureFlagDetails({ flags: {} })
|
|
718
|
+
}
|
|
701
719
|
|
|
702
720
|
this._logger.warn('Remote config has no feature flags, will not load feature flags.')
|
|
703
|
-
} else if (this.preloadFeatureFlags !== false) {
|
|
721
|
+
} else if (this.preloadFeatureFlags !== false && !this.disableRemoteFeatureFlags) {
|
|
704
722
|
willLoadFlags = true
|
|
705
723
|
this.flagsAsync({ sendAnonDistinctId: true, fetchConfig: true, triggerOnRemoteConfig: true })
|
|
706
724
|
}
|
|
@@ -746,6 +764,7 @@ export abstract class PostHogCore extends PostHogCoreStateless {
|
|
|
746
764
|
$anon_distinct_id: sendAnonDistinctId ? this.getAnonymousId() : undefined,
|
|
747
765
|
// Only set by the React Native SDK; omitted from JSON when DeviceId is not persisted
|
|
748
766
|
$device_id: deviceId ?? undefined,
|
|
767
|
+
...(this.disableRemoteFeatureFlags ? { disable_flags: true } : {}),
|
|
749
768
|
}
|
|
750
769
|
|
|
751
770
|
const result = await super.getFlags(
|
|
@@ -758,20 +777,24 @@ export abstract class PostHogCore extends PostHogCoreStateless {
|
|
|
758
777
|
)
|
|
759
778
|
|
|
760
779
|
if (!result.success) {
|
|
761
|
-
this.
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
780
|
+
if (!this.disableRemoteFeatureFlags) {
|
|
781
|
+
this.setKnownFeatureFlagDetails({
|
|
782
|
+
flags: this.getKnownFeatureFlagDetails()?.flags ?? {},
|
|
783
|
+
requestError: result.error,
|
|
784
|
+
})
|
|
785
|
+
}
|
|
765
786
|
return undefined
|
|
766
787
|
}
|
|
767
788
|
|
|
768
789
|
const res = result.response
|
|
769
790
|
|
|
770
791
|
if (res?.quotaLimited?.includes(QuotaLimitedFeature.FeatureFlags)) {
|
|
771
|
-
this.
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
792
|
+
if (!this.disableRemoteFeatureFlags) {
|
|
793
|
+
this.setKnownFeatureFlagDetails({
|
|
794
|
+
flags: this.getKnownFeatureFlagDetails()?.flags ?? {},
|
|
795
|
+
quotaLimited: res.quotaLimited,
|
|
796
|
+
})
|
|
797
|
+
}
|
|
775
798
|
this._logger.warn(
|
|
776
799
|
'[FEATURE FLAGS] Feature flags quota limit exceeded. Learn more about billing limits at https://posthog.com/docs/billing/limits-alerts'
|
|
777
800
|
)
|
|
@@ -779,6 +802,12 @@ export abstract class PostHogCore extends PostHogCoreStateless {
|
|
|
779
802
|
return res
|
|
780
803
|
}
|
|
781
804
|
if (res?.featureFlags) {
|
|
805
|
+
if (this.disableRemoteFeatureFlags) {
|
|
806
|
+
this.cacheSessionReplay('flags', res)
|
|
807
|
+
this.maybeNotifyRemoteConfig(triggerOnRemoteConfig, res)
|
|
808
|
+
return res
|
|
809
|
+
}
|
|
810
|
+
|
|
782
811
|
// clear flag call reported if we have new flags since they might have changed
|
|
783
812
|
if (this.sendFeatureFlagEvent) {
|
|
784
813
|
this.flagCallReported = {}
|
|
@@ -1052,7 +1081,8 @@ export abstract class PostHogCore extends PostHogCoreStateless {
|
|
|
1052
1081
|
|
|
1053
1082
|
details = details ?? { featureFlags: {}, featureFlagPayloads: {}, flags: {} }
|
|
1054
1083
|
|
|
1055
|
-
|
|
1084
|
+
// Copy before applying overrides so reads don't mutate the stored flags in place.
|
|
1085
|
+
const flags: Record<string, FeatureFlagDetail> = { ...(details.flags ?? {}) }
|
|
1056
1086
|
|
|
1057
1087
|
for (const key in overriddenFlags) {
|
|
1058
1088
|
if (!overriddenFlags[key]) {
|
|
@@ -1093,6 +1123,10 @@ export abstract class PostHogCore extends PostHogCoreStateless {
|
|
|
1093
1123
|
|
|
1094
1124
|
// Used when we want to trigger the reload but we don't care about the result
|
|
1095
1125
|
reloadFeatureFlags(options?: { cb?: (err?: Error, flags?: PostHogFlagsResponse['featureFlags']) => void }): void {
|
|
1126
|
+
if (this.disableRemoteFeatureFlags && !this.disabled) {
|
|
1127
|
+
this._initPromise.then(() => options?.cb?.(undefined, this.getFeatureFlags()))
|
|
1128
|
+
return
|
|
1129
|
+
}
|
|
1096
1130
|
this.flagsAsync({ sendAnonDistinctId: true })
|
|
1097
1131
|
.then((res) => {
|
|
1098
1132
|
options?.cb?.(undefined, res?.featureFlags)
|
|
@@ -1112,6 +1146,10 @@ export abstract class PostHogCore extends PostHogCoreStateless {
|
|
|
1112
1146
|
async reloadFeatureFlagsAsync(
|
|
1113
1147
|
sendAnonDistinctId?: boolean
|
|
1114
1148
|
): Promise<PostHogFlagsResponse['featureFlags'] | undefined> {
|
|
1149
|
+
if (this.disableRemoteFeatureFlags && !this.disabled) {
|
|
1150
|
+
await this._initPromise
|
|
1151
|
+
return this.getFeatureFlags()
|
|
1152
|
+
}
|
|
1115
1153
|
return (await this.flagsAsync({ sendAnonDistinctId: sendAnonDistinctId }))?.featureFlags
|
|
1116
1154
|
}
|
|
1117
1155
|
|
|
@@ -1142,6 +1180,75 @@ export abstract class PostHogCore extends PostHogCoreStateless {
|
|
|
1142
1180
|
})
|
|
1143
1181
|
}
|
|
1144
1182
|
|
|
1183
|
+
/**
|
|
1184
|
+
* Replaces (or merges into) the stored feature flags and payloads with locally supplied
|
|
1185
|
+
* values, exactly as if they had been returned by the flags endpoint: the values are
|
|
1186
|
+
* persisted, `getFeatureFlag()`/`getFeatureFlagPayload()` read them back, and
|
|
1187
|
+
* `onFeatureFlags` listeners fire. Makes no network request.
|
|
1188
|
+
*
|
|
1189
|
+
* Intended for apps that evaluate flags outside the SDK (e.g. server-side local
|
|
1190
|
+
* evaluation) and push the results in at runtime, typically together with the
|
|
1191
|
+
* `disableRemoteFeatureFlags` option so the SDK never fetches flags itself.
|
|
1192
|
+
*
|
|
1193
|
+
* The values are cleared by `reset()`, so push them again after an identity change.
|
|
1194
|
+
*
|
|
1195
|
+
* @param flags - Flag keys mapped to their values (boolean, or a variant string)
|
|
1196
|
+
* @param payloads - Optional flag keys mapped to their JSON payloads
|
|
1197
|
+
* @param options - Set `merge: true` to merge with the currently stored flags instead of replacing them
|
|
1198
|
+
*/
|
|
1199
|
+
updateFlags(
|
|
1200
|
+
flags: Record<string, FeatureFlagValue>,
|
|
1201
|
+
payloads?: Record<string, JsonType>,
|
|
1202
|
+
options?: { merge?: boolean }
|
|
1203
|
+
): void {
|
|
1204
|
+
this.wrap(() => {
|
|
1205
|
+
// Merge against the raw stored flags, not the override-applied view.
|
|
1206
|
+
const existingDetails = options?.merge ? this.getKnownFeatureFlagDetails()?.flags : undefined
|
|
1207
|
+
const existingFlags = existingDetails ? getFlagValuesFromFlags(existingDetails) : {}
|
|
1208
|
+
const existingPayloads: Record<string, JsonType> = {}
|
|
1209
|
+
for (const key in existingDetails) {
|
|
1210
|
+
const storedPayload = existingDetails[key].metadata?.payload
|
|
1211
|
+
if (storedPayload !== undefined) {
|
|
1212
|
+
existingPayloads[key] = parsePayload(storedPayload)
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
const finalFlags = { ...existingFlags, ...flags }
|
|
1216
|
+
const finalPayloads = { ...existingPayloads, ...(payloads ?? {}) }
|
|
1217
|
+
|
|
1218
|
+
// Built by hand, not via createFlagsResponseFromFlagsAndPayloads, which drops false flags.
|
|
1219
|
+
const flagDetails: Record<string, FeatureFlagDetail> = {}
|
|
1220
|
+
for (const [key, value] of Object.entries(finalFlags)) {
|
|
1221
|
+
const payload = finalPayloads[key]
|
|
1222
|
+
let serializedPayload: string | undefined
|
|
1223
|
+
if (payload !== undefined) {
|
|
1224
|
+
try {
|
|
1225
|
+
serializedPayload = JSON.stringify(payload)
|
|
1226
|
+
} catch (e) {
|
|
1227
|
+
this._logger.error(`updateFlags: could not serialize the payload for flag "${key}", dropping it.`, e)
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
flagDetails[key] = {
|
|
1231
|
+
key,
|
|
1232
|
+
enabled: getEnabledFromValue(value),
|
|
1233
|
+
variant: getVariantFromValue(value),
|
|
1234
|
+
reason: undefined,
|
|
1235
|
+
// Locally supplied flags have no server-side id/version
|
|
1236
|
+
metadata: {
|
|
1237
|
+
id: undefined,
|
|
1238
|
+
version: undefined,
|
|
1239
|
+
description: undefined,
|
|
1240
|
+
payload: serializedPayload,
|
|
1241
|
+
},
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
if (this.sendFeatureFlagEvent) {
|
|
1246
|
+
this.flagCallReported = {}
|
|
1247
|
+
}
|
|
1248
|
+
this.setKnownFeatureFlagDetails({ flags: flagDetails })
|
|
1249
|
+
})
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1145
1252
|
/**
|
|
1146
1253
|
* Capture a caught exception manually
|
|
1147
1254
|
*
|
package/src/types.ts
CHANGED
|
@@ -53,6 +53,25 @@ export type PostHogCoreOptions = {
|
|
|
53
53
|
* @default true
|
|
54
54
|
*/
|
|
55
55
|
preloadFeatureFlags?: boolean
|
|
56
|
+
/**
|
|
57
|
+
* Advanced: whether to disable fetching and evaluating feature flags from PostHog entirely.
|
|
58
|
+
*
|
|
59
|
+
* When set to true, `reloadFeatureFlags()` and the reloads triggered by `identify()`,
|
|
60
|
+
* `group()`, `setPersonPropertiesForFlags()` and `reset()` become no-ops, and any request
|
|
61
|
+
* to the flags endpoint that still goes out (e.g. to fetch remote config or surveys)
|
|
62
|
+
* carries `disable_flags: true` so the server skips flag evaluation. Flag values must be
|
|
63
|
+
* supplied via the `bootstrap` option or `updateFlags()` instead; `getFeatureFlag()` and
|
|
64
|
+
* related methods keep working against those values. Until `updateFlags()` runs, reads
|
|
65
|
+
* return their not-loaded defaults, so use `bootstrap` for any flags needed at startup.
|
|
66
|
+
* Equivalent to the web SDK's `advanced_disable_feature_flags`.
|
|
67
|
+
*
|
|
68
|
+
* Note: surveys gated on feature flags will not evaluate unless the survey targeting
|
|
69
|
+
* flags are also provided via `updateFlags()`. This option cannot be toggled at runtime.
|
|
70
|
+
* `posthog-node` inherits this option but does not implement it (no-op).
|
|
71
|
+
*
|
|
72
|
+
* @default false
|
|
73
|
+
*/
|
|
74
|
+
disableRemoteFeatureFlags?: boolean
|
|
56
75
|
/**
|
|
57
76
|
* Whether to load remote config when initialized or not
|
|
58
77
|
* Experimental support
|