posthog-node 5.0.0 → 5.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 +4 -0
- package/lib/edge/index.cjs +34 -146
- package/lib/edge/index.cjs.map +1 -1
- package/lib/edge/index.mjs +34 -146
- package/lib/edge/index.mjs.map +1 -1
- package/lib/index.d.ts +14 -14
- package/lib/node/index.cjs +34 -146
- package/lib/node/index.cjs.map +1 -1
- package/lib/node/index.mjs +34 -146
- package/lib/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -79,11 +79,11 @@ declare enum PostHogPersistedProperty {
|
|
|
79
79
|
InstalledAppBuild = "installed_app_build",
|
|
80
80
|
InstalledAppVersion = "installed_app_version",
|
|
81
81
|
SessionReplay = "session_replay",
|
|
82
|
-
DecideEndpointWasHit = "decide_endpoint_was_hit",
|
|
83
82
|
SurveyLastSeenDate = "survey_last_seen_date",
|
|
84
83
|
SurveysSeen = "surveys_seen",
|
|
85
84
|
Surveys = "surveys",
|
|
86
|
-
RemoteConfig = "remote_config"
|
|
85
|
+
RemoteConfig = "remote_config",
|
|
86
|
+
FlagsEndpointWasHit = "flags_endpoint_was_hit"
|
|
87
87
|
}
|
|
88
88
|
type PostHogFetchOptions = {
|
|
89
89
|
method: 'GET' | 'POST' | 'PUT' | 'PATCH';
|
|
@@ -132,7 +132,7 @@ type PostHogRemoteConfig = {
|
|
|
132
132
|
hasFeatureFlags?: boolean;
|
|
133
133
|
};
|
|
134
134
|
type FeatureFlagValue = string | boolean;
|
|
135
|
-
type
|
|
135
|
+
type PostHogFlagsResponse = Omit<PostHogRemoteConfig, 'surveys' | 'hasFeatureFlags'> & {
|
|
136
136
|
featureFlags: {
|
|
137
137
|
[key: string]: FeatureFlagValue;
|
|
138
138
|
};
|
|
@@ -178,13 +178,13 @@ type PartialWithRequired<T, K extends keyof T> = {
|
|
|
178
178
|
[P in Exclude<keyof T, K>]?: T[P];
|
|
179
179
|
};
|
|
180
180
|
/**
|
|
181
|
-
* These are the fields we care about from
|
|
181
|
+
* These are the fields we care about from PostHogFlagsResponse for feature flags.
|
|
182
182
|
*/
|
|
183
|
-
type PostHogFeatureFlagDetails = PartialWithRequired<
|
|
183
|
+
type PostHogFeatureFlagDetails = PartialWithRequired<PostHogFlagsResponse, 'flags' | 'featureFlags' | 'featureFlagPayloads' | 'requestId'>;
|
|
184
184
|
/**
|
|
185
185
|
* Models legacy flags and payloads return type for many public methods.
|
|
186
186
|
*/
|
|
187
|
-
type PostHogFlagsAndPayloadsResponse = Partial<Pick<
|
|
187
|
+
type PostHogFlagsAndPayloadsResponse = Partial<Pick<PostHogFlagsResponse, 'featureFlags' | 'featureFlagPayloads'>>;
|
|
188
188
|
type JsonType = string | number | boolean | null | {
|
|
189
189
|
[key: string]: JsonType;
|
|
190
190
|
} | Array<JsonType> | JsonType[];
|
|
@@ -494,7 +494,7 @@ declare abstract class PostHogCoreStateless {
|
|
|
494
494
|
/***
|
|
495
495
|
*** FEATURE FLAGS
|
|
496
496
|
***/
|
|
497
|
-
protected
|
|
497
|
+
protected getFlags(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, extraPayload?: Record<string, any>): Promise<PostHogFlagsResponse | undefined>;
|
|
498
498
|
protected getFeatureFlagStateless(key: string, distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean): Promise<{
|
|
499
499
|
response: FeatureFlagValue | undefined;
|
|
500
500
|
requestId: string | undefined;
|
|
@@ -504,16 +504,16 @@ declare abstract class PostHogCoreStateless {
|
|
|
504
504
|
requestId: string | undefined;
|
|
505
505
|
} | undefined>;
|
|
506
506
|
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>;
|
|
507
|
-
protected getFeatureFlagPayloadsStateless(distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean, flagKeysToEvaluate?: string[]): Promise<
|
|
507
|
+
protected getFeatureFlagPayloadsStateless(distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean, flagKeysToEvaluate?: string[]): Promise<PostHogFlagsResponse['featureFlagPayloads'] | undefined>;
|
|
508
508
|
protected getFeatureFlagsStateless(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean, flagKeysToEvaluate?: string[]): Promise<{
|
|
509
|
-
flags:
|
|
510
|
-
payloads:
|
|
511
|
-
requestId:
|
|
509
|
+
flags: PostHogFlagsResponse['featureFlags'] | undefined;
|
|
510
|
+
payloads: PostHogFlagsResponse['featureFlagPayloads'] | undefined;
|
|
511
|
+
requestId: PostHogFlagsResponse['requestId'] | undefined;
|
|
512
512
|
}>;
|
|
513
513
|
protected getFeatureFlagsAndPayloadsStateless(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean, flagKeysToEvaluate?: string[]): Promise<{
|
|
514
|
-
flags:
|
|
515
|
-
payloads:
|
|
516
|
-
requestId:
|
|
514
|
+
flags: PostHogFlagsResponse['featureFlags'] | undefined;
|
|
515
|
+
payloads: PostHogFlagsResponse['featureFlagPayloads'] | undefined;
|
|
516
|
+
requestId: PostHogFlagsResponse['requestId'] | undefined;
|
|
517
517
|
}>;
|
|
518
518
|
protected getFeatureFlagDetailsStateless(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean, flagKeysToEvaluate?: string[]): Promise<PostHogFeatureFlagDetails | undefined>;
|
|
519
519
|
/***
|
package/lib/node/index.cjs
CHANGED
|
@@ -1340,7 +1340,7 @@ function snipLine(line, colno) {
|
|
|
1340
1340
|
return newLine;
|
|
1341
1341
|
}
|
|
1342
1342
|
|
|
1343
|
-
var version = "5.
|
|
1343
|
+
var version = "5.1.0";
|
|
1344
1344
|
|
|
1345
1345
|
var PostHogPersistedProperty;
|
|
1346
1346
|
(function (PostHogPersistedProperty) {
|
|
@@ -1364,11 +1364,11 @@ var PostHogPersistedProperty;
|
|
|
1364
1364
|
PostHogPersistedProperty["InstalledAppBuild"] = "installed_app_build";
|
|
1365
1365
|
PostHogPersistedProperty["InstalledAppVersion"] = "installed_app_version";
|
|
1366
1366
|
PostHogPersistedProperty["SessionReplay"] = "session_replay";
|
|
1367
|
-
PostHogPersistedProperty["DecideEndpointWasHit"] = "decide_endpoint_was_hit";
|
|
1368
1367
|
PostHogPersistedProperty["SurveyLastSeenDate"] = "survey_last_seen_date";
|
|
1369
1368
|
PostHogPersistedProperty["SurveysSeen"] = "surveys_seen";
|
|
1370
1369
|
PostHogPersistedProperty["Surveys"] = "surveys";
|
|
1371
1370
|
PostHogPersistedProperty["RemoteConfig"] = "remote_config";
|
|
1371
|
+
PostHogPersistedProperty["FlagsEndpointWasHit"] = "flags_endpoint_was_hit";
|
|
1372
1372
|
})(PostHogPersistedProperty || (PostHogPersistedProperty = {}));
|
|
1373
1373
|
// Any key prefixed with `attr__` can be added
|
|
1374
1374
|
var Compression;
|
|
@@ -1436,27 +1436,27 @@ var ActionStepStringMatching;
|
|
|
1436
1436
|
ActionStepStringMatching["Regex"] = "regex";
|
|
1437
1437
|
})(ActionStepStringMatching || (ActionStepStringMatching = {}));
|
|
1438
1438
|
|
|
1439
|
-
const
|
|
1440
|
-
if ('flags' in
|
|
1441
|
-
// Convert
|
|
1442
|
-
const featureFlags = getFlagValuesFromFlags(
|
|
1443
|
-
const featureFlagPayloads = getPayloadsFromFlags(
|
|
1439
|
+
const normalizeFlagsResponse = (flagsResponse) => {
|
|
1440
|
+
if ('flags' in flagsResponse) {
|
|
1441
|
+
// Convert v2 format to v1 format
|
|
1442
|
+
const featureFlags = getFlagValuesFromFlags(flagsResponse.flags);
|
|
1443
|
+
const featureFlagPayloads = getPayloadsFromFlags(flagsResponse.flags);
|
|
1444
1444
|
return {
|
|
1445
|
-
...
|
|
1445
|
+
...flagsResponse,
|
|
1446
1446
|
featureFlags,
|
|
1447
1447
|
featureFlagPayloads,
|
|
1448
1448
|
};
|
|
1449
1449
|
}
|
|
1450
1450
|
else {
|
|
1451
|
-
// Convert
|
|
1452
|
-
const featureFlags =
|
|
1453
|
-
const featureFlagPayloads = Object.fromEntries(Object.entries(
|
|
1451
|
+
// Convert v1 format to v2 format
|
|
1452
|
+
const featureFlags = flagsResponse.featureFlags ?? {};
|
|
1453
|
+
const featureFlagPayloads = Object.fromEntries(Object.entries(flagsResponse.featureFlagPayloads || {}).map(([k, v]) => [k, parsePayload(v)]));
|
|
1454
1454
|
const flags = Object.fromEntries(Object.entries(featureFlags).map(([key, value]) => [
|
|
1455
1455
|
key,
|
|
1456
1456
|
getFlagDetailFromFlagAndPayload(key, value, featureFlagPayloads[key]),
|
|
1457
1457
|
]));
|
|
1458
1458
|
return {
|
|
1459
|
-
...
|
|
1459
|
+
...flagsResponse,
|
|
1460
1460
|
featureFlags,
|
|
1461
1461
|
featureFlagPayloads,
|
|
1462
1462
|
flags,
|
|
@@ -1519,90 +1519,6 @@ const parsePayload = (response) => {
|
|
|
1519
1519
|
}
|
|
1520
1520
|
};
|
|
1521
1521
|
|
|
1522
|
-
// Rollout constants
|
|
1523
|
-
const NEW_FLAGS_ROLLOUT_PERCENTAGE = 1;
|
|
1524
|
-
// The fnv1a hashes of the tokens that are explicitly excluded from the rollout
|
|
1525
|
-
// see https://github.com/PostHog/posthog-js-lite/blob/main/posthog-core/src/utils.ts#L84
|
|
1526
|
-
// are hashed API tokens from our top 10 for each category supported by this SDK.
|
|
1527
|
-
const NEW_FLAGS_EXCLUDED_HASHES = new Set([
|
|
1528
|
-
// Node
|
|
1529
|
-
'61be3dd8',
|
|
1530
|
-
'96f6df5f',
|
|
1531
|
-
'8cfdba9b',
|
|
1532
|
-
'bf027177',
|
|
1533
|
-
'e59430a8',
|
|
1534
|
-
'7fa5500b',
|
|
1535
|
-
'569798e9',
|
|
1536
|
-
'04809ff7',
|
|
1537
|
-
'0ebc61a5',
|
|
1538
|
-
'32de7f98',
|
|
1539
|
-
'3beeb69a',
|
|
1540
|
-
'12d34ad9',
|
|
1541
|
-
'733853ec',
|
|
1542
|
-
'0645bb64',
|
|
1543
|
-
'5dcbee21',
|
|
1544
|
-
'b1f95fa3',
|
|
1545
|
-
'2189e408',
|
|
1546
|
-
'82b460c2',
|
|
1547
|
-
'3a8cc979',
|
|
1548
|
-
'29ef8843',
|
|
1549
|
-
'2cdbf767',
|
|
1550
|
-
'38084b54',
|
|
1551
|
-
// React Native
|
|
1552
|
-
'50f9f8de',
|
|
1553
|
-
'41d0df91',
|
|
1554
|
-
'5c236689',
|
|
1555
|
-
'c11aedd3',
|
|
1556
|
-
'ada46672',
|
|
1557
|
-
'f4331ee1',
|
|
1558
|
-
'42fed62a',
|
|
1559
|
-
'c957462c',
|
|
1560
|
-
'd62f705a',
|
|
1561
|
-
// Web (lots of teams per org, hence lots of API tokens)
|
|
1562
|
-
'e0162666',
|
|
1563
|
-
'01b3e5cf',
|
|
1564
|
-
'441cef7f',
|
|
1565
|
-
'bb9cafee',
|
|
1566
|
-
'8f348eb0',
|
|
1567
|
-
'b2553f3a',
|
|
1568
|
-
'97469d7d',
|
|
1569
|
-
'39f21a76',
|
|
1570
|
-
'03706dcc',
|
|
1571
|
-
'27d50569',
|
|
1572
|
-
'307584a7',
|
|
1573
|
-
'6433e92e',
|
|
1574
|
-
'150c7fbb',
|
|
1575
|
-
'49f57f22',
|
|
1576
|
-
'3772f65b',
|
|
1577
|
-
'01eb8256',
|
|
1578
|
-
'3c9e9234',
|
|
1579
|
-
'f853c7f7',
|
|
1580
|
-
'c0ac4b67',
|
|
1581
|
-
'cd609d40',
|
|
1582
|
-
'10ca9b1a',
|
|
1583
|
-
'8a87f11b',
|
|
1584
|
-
'8e8e5216',
|
|
1585
|
-
'1f6b63b3',
|
|
1586
|
-
'db7943dd',
|
|
1587
|
-
'79b7164c',
|
|
1588
|
-
'07f78e33',
|
|
1589
|
-
'2d21b6fd',
|
|
1590
|
-
'952db5ee',
|
|
1591
|
-
'a7d3b43f',
|
|
1592
|
-
'1924dd9c',
|
|
1593
|
-
'84e1b8f6',
|
|
1594
|
-
'dff631b6',
|
|
1595
|
-
'c5aa8a79',
|
|
1596
|
-
'fa133a95',
|
|
1597
|
-
'498a4508',
|
|
1598
|
-
'24748755',
|
|
1599
|
-
'98f3d658',
|
|
1600
|
-
'21bbda67',
|
|
1601
|
-
'7dbfed69',
|
|
1602
|
-
'be3ec24c',
|
|
1603
|
-
'fc80b8e2',
|
|
1604
|
-
'75cc0998',
|
|
1605
|
-
]);
|
|
1606
1522
|
const STRING_FORMAT = 'utf8';
|
|
1607
1523
|
function assert(truthyValue, message) {
|
|
1608
1524
|
if (!truthyValue || typeof truthyValue !== 'string' || isEmpty(truthyValue)) {
|
|
@@ -1649,30 +1565,6 @@ function safeSetTimeout(fn, timeout) {
|
|
|
1649
1565
|
t?.unref && t?.unref();
|
|
1650
1566
|
return t;
|
|
1651
1567
|
}
|
|
1652
|
-
// FNV-1a hash function
|
|
1653
|
-
// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
|
|
1654
|
-
// I know, I know, I'm rolling my own hash function, but I didn't want to take on
|
|
1655
|
-
// a crypto dependency and this is just temporary anyway
|
|
1656
|
-
function fnv1a(str) {
|
|
1657
|
-
let hash = 0x811c9dc5; // FNV offset basis
|
|
1658
|
-
for (let i = 0; i < str.length; i++) {
|
|
1659
|
-
hash ^= str.charCodeAt(i);
|
|
1660
|
-
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
|
1661
|
-
}
|
|
1662
|
-
// Convert to hex string, padding to 8 chars
|
|
1663
|
-
return (hash >>> 0).toString(16).padStart(8, '0');
|
|
1664
|
-
}
|
|
1665
|
-
function isTokenInRollout(token, percentage = 0, excludedHashes) {
|
|
1666
|
-
const tokenHash = fnv1a(token);
|
|
1667
|
-
// Check excluded hashes (we're explicitly including these tokens from the rollout)
|
|
1668
|
-
if (excludedHashes?.has(tokenHash)) {
|
|
1669
|
-
return false;
|
|
1670
|
-
}
|
|
1671
|
-
// Convert hash to int and divide by max value to get number between 0-1
|
|
1672
|
-
const hashInt = parseInt(tokenHash, 16);
|
|
1673
|
-
const hashFloat = hashInt / 0xffffffff;
|
|
1674
|
-
return hashFloat < percentage;
|
|
1675
|
-
}
|
|
1676
1568
|
function allSettled(promises) {
|
|
1677
1569
|
return Promise.all(promises.map((p) => (p ?? Promise.resolve()).then((value) => ({ status: 'fulfilled', value }), (reason) => ({ status: 'rejected', reason }))));
|
|
1678
1570
|
}
|
|
@@ -1997,13 +1889,9 @@ class PostHogCoreStateless {
|
|
|
1997
1889
|
/***
|
|
1998
1890
|
*** FEATURE FLAGS
|
|
1999
1891
|
***/
|
|
2000
|
-
async
|
|
1892
|
+
async getFlags(distinctId, groups = {}, personProperties = {}, groupProperties = {}, extraPayload = {}) {
|
|
2001
1893
|
await this._initPromise;
|
|
2002
|
-
|
|
2003
|
-
// This is a temporary measure to ensure that we can still use the old flags API
|
|
2004
|
-
// while we migrate to the new flags API
|
|
2005
|
-
const useFlags = isTokenInRollout(this.apiKey, NEW_FLAGS_ROLLOUT_PERCENTAGE, NEW_FLAGS_EXCLUDED_HASHES);
|
|
2006
|
-
const url = useFlags ? `${this.host}/flags/?v=2` : `${this.host}/decide/?v=4`;
|
|
1894
|
+
const url = `${this.host}/flags/?v=2&config=true`;
|
|
2007
1895
|
const fetchOptions = {
|
|
2008
1896
|
method: 'POST',
|
|
2009
1897
|
headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/json' },
|
|
@@ -2016,11 +1904,11 @@ class PostHogCoreStateless {
|
|
|
2016
1904
|
...extraPayload,
|
|
2017
1905
|
}),
|
|
2018
1906
|
};
|
|
2019
|
-
this.logMsgIfDebug(() => console.log('PostHog Debug', '
|
|
2020
|
-
// Don't retry /
|
|
1907
|
+
this.logMsgIfDebug(() => console.log('PostHog Debug', 'Flags URL', url));
|
|
1908
|
+
// Don't retry /flags API calls
|
|
2021
1909
|
return this.fetchWithRetry(url, fetchOptions, { retryCount: 0 }, this.featureFlagsRequestTimeoutMs)
|
|
2022
1910
|
.then((response) => response.json())
|
|
2023
|
-
.then((response) =>
|
|
1911
|
+
.then((response) => normalizeFlagsResponse(response))
|
|
2024
1912
|
.catch((error) => {
|
|
2025
1913
|
this._events.emit('error', error);
|
|
2026
1914
|
return undefined;
|
|
@@ -2049,15 +1937,15 @@ class PostHogCoreStateless {
|
|
|
2049
1937
|
}
|
|
2050
1938
|
async getFeatureFlagDetailStateless(key, distinctId, groups = {}, personProperties = {}, groupProperties = {}, disableGeoip) {
|
|
2051
1939
|
await this._initPromise;
|
|
2052
|
-
const
|
|
2053
|
-
if (
|
|
1940
|
+
const flagsResponse = await this.getFeatureFlagDetailsStateless(distinctId, groups, personProperties, groupProperties, disableGeoip, [key]);
|
|
1941
|
+
if (flagsResponse === undefined) {
|
|
2054
1942
|
return undefined;
|
|
2055
1943
|
}
|
|
2056
|
-
const featureFlags =
|
|
1944
|
+
const featureFlags = flagsResponse.flags;
|
|
2057
1945
|
const flagDetail = featureFlags[key];
|
|
2058
1946
|
return {
|
|
2059
1947
|
response: flagDetail,
|
|
2060
|
-
requestId:
|
|
1948
|
+
requestId: flagsResponse.requestId,
|
|
2061
1949
|
};
|
|
2062
1950
|
}
|
|
2063
1951
|
async getFeatureFlagPayloadStateless(key, distinctId, groups = {}, personProperties = {}, groupProperties = {}, disableGeoip) {
|
|
@@ -2107,26 +1995,26 @@ class PostHogCoreStateless {
|
|
|
2107
1995
|
if (flagKeysToEvaluate) {
|
|
2108
1996
|
extraPayload['flag_keys_to_evaluate'] = flagKeysToEvaluate;
|
|
2109
1997
|
}
|
|
2110
|
-
const
|
|
2111
|
-
if (
|
|
1998
|
+
const flagsResponse = await this.getFlags(distinctId, groups, personProperties, groupProperties, extraPayload);
|
|
1999
|
+
if (flagsResponse === undefined) {
|
|
2112
2000
|
// We probably errored out, so return undefined
|
|
2113
2001
|
return undefined;
|
|
2114
2002
|
}
|
|
2115
|
-
// if there's an error on the
|
|
2116
|
-
if (
|
|
2003
|
+
// if there's an error on the flagsResponse, log a console error, but don't throw an error
|
|
2004
|
+
if (flagsResponse.errorsWhileComputingFlags) {
|
|
2117
2005
|
console.error('[FEATURE FLAGS] Error while computing feature flags, some flags may be missing or incorrect. Learn more at https://posthog.com/docs/feature-flags/best-practices');
|
|
2118
2006
|
}
|
|
2119
2007
|
// Add check for quota limitation on feature flags
|
|
2120
|
-
if (
|
|
2008
|
+
if (flagsResponse.quotaLimited?.includes(QuotaLimitedFeature.FeatureFlags)) {
|
|
2121
2009
|
console.warn('[FEATURE FLAGS] Feature flags quota limit exceeded - feature flags unavailable. Learn more about billing limits at https://posthog.com/docs/billing/limits-alerts');
|
|
2122
2010
|
return {
|
|
2123
2011
|
flags: {},
|
|
2124
2012
|
featureFlags: {},
|
|
2125
2013
|
featureFlagPayloads: {},
|
|
2126
|
-
requestId:
|
|
2014
|
+
requestId: flagsResponse?.requestId,
|
|
2127
2015
|
};
|
|
2128
2016
|
}
|
|
2129
|
-
return
|
|
2017
|
+
return flagsResponse;
|
|
2130
2018
|
}
|
|
2131
2019
|
/***
|
|
2132
2020
|
*** SURVEYS
|
|
@@ -2730,7 +2618,7 @@ class FeatureFlagsPoller {
|
|
|
2730
2618
|
await this.loadFeatureFlags();
|
|
2731
2619
|
const response = {};
|
|
2732
2620
|
const payloads = {};
|
|
2733
|
-
let
|
|
2621
|
+
let fallbackToFlags = this.featureFlags.length == 0;
|
|
2734
2622
|
await Promise.all(this.featureFlags.map(async flag => {
|
|
2735
2623
|
try {
|
|
2736
2624
|
const matchValue = await this.computeFlagLocally(flag, distinctId, groups, personProperties, groupProperties);
|
|
@@ -2743,13 +2631,13 @@ class FeatureFlagsPoller {
|
|
|
2743
2631
|
if (e instanceof InconclusiveMatchError) ; else if (e instanceof Error) {
|
|
2744
2632
|
this.onError?.(new Error(`Error computing flag locally: ${flag.key}: ${e}`));
|
|
2745
2633
|
}
|
|
2746
|
-
|
|
2634
|
+
fallbackToFlags = true;
|
|
2747
2635
|
}
|
|
2748
2636
|
}));
|
|
2749
2637
|
return {
|
|
2750
2638
|
response,
|
|
2751
2639
|
payloads,
|
|
2752
|
-
|
|
2640
|
+
fallbackToFlags
|
|
2753
2641
|
};
|
|
2754
2642
|
}
|
|
2755
2643
|
async computeFlagLocally(flag, distinctId, groups = {}, personProperties = {}, groupProperties = {}) {
|
|
@@ -3714,13 +3602,13 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
3714
3602
|
const localEvaluationResult = await this.featureFlagsPoller?.getAllFlagsAndPayloads(distinctId, groups, personProperties, groupProperties);
|
|
3715
3603
|
let featureFlags = {};
|
|
3716
3604
|
let featureFlagPayloads = {};
|
|
3717
|
-
let
|
|
3605
|
+
let fallbackToFlags = true;
|
|
3718
3606
|
if (localEvaluationResult) {
|
|
3719
3607
|
featureFlags = localEvaluationResult.response;
|
|
3720
3608
|
featureFlagPayloads = localEvaluationResult.payloads;
|
|
3721
|
-
|
|
3609
|
+
fallbackToFlags = localEvaluationResult.fallbackToFlags;
|
|
3722
3610
|
}
|
|
3723
|
-
if (
|
|
3611
|
+
if (fallbackToFlags && !onlyEvaluateLocally) {
|
|
3724
3612
|
const remoteEvaluationResult = await super.getFeatureFlagsAndPayloadsStateless(distinctId, groups, personProperties, groupProperties, disableGeoip);
|
|
3725
3613
|
featureFlags = {
|
|
3726
3614
|
...featureFlags,
|