@rpcbase/server 0.507.0 → 0.508.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/{handler-CedzJJg0.js → handler-BNrqh1Kb.js} +2 -2
- package/dist/{handler-CedzJJg0.js.map → handler-BNrqh1Kb.js.map} +1 -1
- package/dist/{handler-qCAUmVgd.js → handler-Bh3a6Br1.js} +2 -2
- package/dist/{handler-qCAUmVgd.js.map → handler-Bh3a6Br1.js.map} +1 -1
- package/dist/{handler-BwK8qxLn.js → handler-r-HYO3Oy.js} +2 -2
- package/dist/{handler-BwK8qxLn.js.map → handler-r-HYO3Oy.js.map} +1 -1
- package/dist/index.js +186 -82
- package/dist/index.js.map +1 -1
- package/dist/notifications.js +1 -1
- package/dist/rts/index.js +1 -1
- package/dist/{schemas-7qqi9OQy.js → schemas-Cjdjgehl.js} +4 -4
- package/dist/schemas-Cjdjgehl.js.map +1 -0
- package/dist/uploads.js +1 -1
- package/package.json +1 -1
- package/dist/schemas-7qqi9OQy.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -539,6 +539,8 @@ var types_PostHogPersistedProperty = /* @__PURE__ */ (function(PostHogPersistedP
|
|
|
539
539
|
PostHogPersistedProperty["AnonymousId"] = "anonymous_id";
|
|
540
540
|
PostHogPersistedProperty["DistinctId"] = "distinct_id";
|
|
541
541
|
PostHogPersistedProperty["Props"] = "props";
|
|
542
|
+
PostHogPersistedProperty["EnablePersonProcessing"] = "enable_person_processing";
|
|
543
|
+
PostHogPersistedProperty["PersonMode"] = "person_mode";
|
|
542
544
|
PostHogPersistedProperty["FeatureFlagDetails"] = "feature_flag_details";
|
|
543
545
|
PostHogPersistedProperty["FeatureFlags"] = "feature_flags";
|
|
544
546
|
PostHogPersistedProperty["FeatureFlagPayloads"] = "feature_flag_payloads";
|
|
@@ -573,7 +575,7 @@ const isObject = (x) => x === Object(x) && !isArray(x);
|
|
|
573
575
|
const isUndefined = (x) => void 0 === x;
|
|
574
576
|
const isString = (x) => "[object String]" == type_utils_toString.call(x);
|
|
575
577
|
const isEmptyString = (x) => isString(x) && 0 === x.trim().length;
|
|
576
|
-
const isNumber = (x) => "[object Number]" == type_utils_toString.call(x);
|
|
578
|
+
const isNumber = (x) => "[object Number]" == type_utils_toString.call(x) && x === x;
|
|
577
579
|
const isPlainError = (x) => x instanceof Error;
|
|
578
580
|
function isPrimitive(value) {
|
|
579
581
|
return null === value || "object" != typeof value;
|
|
@@ -855,10 +857,11 @@ class PostHogCoreStateless {
|
|
|
855
857
|
this.disableGeoip = options.disableGeoip ?? true;
|
|
856
858
|
this.disabled = options.disabled ?? false;
|
|
857
859
|
this.historicalMigration = options?.historicalMigration ?? false;
|
|
858
|
-
this.evaluationEnvironments = options?.evaluationEnvironments;
|
|
859
860
|
this._initPromise = Promise.resolve();
|
|
860
861
|
this._isInitialized = true;
|
|
861
862
|
this._logger = createLogger("[PostHog]", this.logMsgIfDebug.bind(this));
|
|
863
|
+
this.evaluationContexts = options?.evaluationContexts ?? options?.evaluationEnvironments;
|
|
864
|
+
if (options?.evaluationEnvironments && !options?.evaluationContexts) this._logger.warn("evaluationEnvironments is deprecated. Use evaluationContexts instead. This property will be removed in a future version.");
|
|
862
865
|
this.disableCompression = !isGzipSupported() || (options?.disableCompression ?? false);
|
|
863
866
|
}
|
|
864
867
|
logMsgIfDebug(fn) {
|
|
@@ -1033,7 +1036,7 @@ class PostHogCoreStateless {
|
|
|
1033
1036
|
group_properties: groupProperties,
|
|
1034
1037
|
...extraPayload
|
|
1035
1038
|
};
|
|
1036
|
-
if (this.
|
|
1039
|
+
if (this.evaluationContexts && this.evaluationContexts.length > 0) requestData.evaluation_contexts = this.evaluationContexts;
|
|
1037
1040
|
const fetchOptions = {
|
|
1038
1041
|
method: "POST",
|
|
1039
1042
|
headers: {
|
|
@@ -1045,10 +1048,35 @@ class PostHogCoreStateless {
|
|
|
1045
1048
|
this._logger.info("Flags URL", url);
|
|
1046
1049
|
return this.fetchWithRetry(url, fetchOptions, {
|
|
1047
1050
|
retryCount: 0
|
|
1048
|
-
}, this.featureFlagsRequestTimeoutMs).then((response) => response.json()).then((response) =>
|
|
1051
|
+
}, this.featureFlagsRequestTimeoutMs).then((response) => response.json()).then((response) => ({
|
|
1052
|
+
success: true,
|
|
1053
|
+
response: normalizeFlagsResponse(response)
|
|
1054
|
+
})).catch((error) => {
|
|
1049
1055
|
this._events.emit("error", error);
|
|
1056
|
+
return {
|
|
1057
|
+
success: false,
|
|
1058
|
+
error: this.categorizeRequestError(error)
|
|
1059
|
+
};
|
|
1050
1060
|
});
|
|
1051
1061
|
}
|
|
1062
|
+
categorizeRequestError(error) {
|
|
1063
|
+
if (error instanceof PostHogFetchHttpError) return {
|
|
1064
|
+
type: "api_error",
|
|
1065
|
+
statusCode: error.status
|
|
1066
|
+
};
|
|
1067
|
+
if (error instanceof PostHogFetchNetworkError) {
|
|
1068
|
+
const cause = error.error;
|
|
1069
|
+
if (cause instanceof Error && ("AbortError" === cause.name || "TimeoutError" === cause.name)) return {
|
|
1070
|
+
type: "timeout"
|
|
1071
|
+
};
|
|
1072
|
+
return {
|
|
1073
|
+
type: "connection_error"
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
return {
|
|
1077
|
+
type: "unknown_error"
|
|
1078
|
+
};
|
|
1079
|
+
}
|
|
1052
1080
|
async getFeatureFlagStateless(key, distinctId, groups = {}, personProperties = {}, groupProperties = {}, disableGeoip) {
|
|
1053
1081
|
await this._initPromise;
|
|
1054
1082
|
const flagDetailResponse = await this.getFeatureFlagDetailStateless(key, distinctId, groups, personProperties, groupProperties, disableGeoip);
|
|
@@ -1115,8 +1143,9 @@ class PostHogCoreStateless {
|
|
|
1115
1143
|
const extraPayload = {};
|
|
1116
1144
|
if (disableGeoip ?? this.disableGeoip) extraPayload["geoip_disable"] = true;
|
|
1117
1145
|
if (flagKeysToEvaluate) extraPayload["flag_keys_to_evaluate"] = flagKeysToEvaluate;
|
|
1118
|
-
const
|
|
1119
|
-
if (
|
|
1146
|
+
const result = await this.getFlags(distinctId, groups, personProperties, groupProperties, extraPayload);
|
|
1147
|
+
if (!result.success) return;
|
|
1148
|
+
const flagsResponse = result.response;
|
|
1120
1149
|
if (flagsResponse.errorsWhileComputingFlags) 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");
|
|
1121
1150
|
if (flagsResponse.quotaLimited?.includes("feature_flags")) {
|
|
1122
1151
|
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");
|
|
@@ -1183,10 +1212,17 @@ class PostHogCoreStateless {
|
|
|
1183
1212
|
this.setPersistedProperty(types_PostHogPersistedProperty.Props, this.props);
|
|
1184
1213
|
});
|
|
1185
1214
|
}
|
|
1215
|
+
processBeforeEnqueue(message) {
|
|
1216
|
+
return message;
|
|
1217
|
+
}
|
|
1218
|
+
async flushStorage() {
|
|
1219
|
+
}
|
|
1186
1220
|
enqueue(type, _message, options) {
|
|
1187
1221
|
this.wrap(() => {
|
|
1188
1222
|
if (this.optedOut) return void this._events.emit(type, "Library is disabled. Not sending event. To re-enable, call posthog.optIn()");
|
|
1189
|
-
|
|
1223
|
+
let message = this.prepareMessage(type, _message, options);
|
|
1224
|
+
message = this.processBeforeEnqueue(message);
|
|
1225
|
+
if (null === message) return;
|
|
1190
1226
|
const queue = this.getPersistedProperty(types_PostHogPersistedProperty.Queue) || [];
|
|
1191
1227
|
if (queue.length >= this.maxQueueSize) {
|
|
1192
1228
|
queue.shift();
|
|
@@ -1205,10 +1241,13 @@ class PostHogCoreStateless {
|
|
|
1205
1241
|
if (this.disabled) return void this._logger.warn("The client is disabled");
|
|
1206
1242
|
if (!this._isInitialized) await this._initPromise;
|
|
1207
1243
|
if (this.optedOut) return void this._events.emit(type, "Library is disabled. Not sending event. To re-enable, call posthog.optIn()");
|
|
1244
|
+
let message = this.prepareMessage(type, _message, options);
|
|
1245
|
+
message = this.processBeforeEnqueue(message);
|
|
1246
|
+
if (null === message) return;
|
|
1208
1247
|
const data = {
|
|
1209
1248
|
api_key: this.apiKey,
|
|
1210
1249
|
batch: [
|
|
1211
|
-
|
|
1250
|
+
message
|
|
1212
1251
|
],
|
|
1213
1252
|
sent_at: currentISOTime()
|
|
1214
1253
|
};
|
|
@@ -1293,11 +1332,12 @@ class PostHogCoreStateless {
|
|
|
1293
1332
|
while (queue.length > 0 && sentMessages.length < originalQueueLength) {
|
|
1294
1333
|
const batchItems = queue.slice(0, this.maxBatchSize);
|
|
1295
1334
|
const batchMessages = batchItems.map((item) => item.message);
|
|
1296
|
-
const persistQueueChange = () => {
|
|
1335
|
+
const persistQueueChange = async () => {
|
|
1297
1336
|
const refreshedQueue = this.getPersistedProperty(types_PostHogPersistedProperty.Queue) || [];
|
|
1298
1337
|
const newQueue = refreshedQueue.slice(batchItems.length);
|
|
1299
1338
|
this.setPersistedProperty(types_PostHogPersistedProperty.Queue, newQueue);
|
|
1300
1339
|
queue = newQueue;
|
|
1340
|
+
await this.flushStorage();
|
|
1301
1341
|
};
|
|
1302
1342
|
const data = {
|
|
1303
1343
|
api_key: this.apiKey,
|
|
@@ -1333,11 +1373,11 @@ class PostHogCoreStateless {
|
|
|
1333
1373
|
this._logger.warn(`Received 413 when sending batch of size ${batchMessages.length}, reducing batch size to ${this.maxBatchSize}`);
|
|
1334
1374
|
continue;
|
|
1335
1375
|
}
|
|
1336
|
-
if (!(err instanceof PostHogFetchNetworkError)) persistQueueChange();
|
|
1376
|
+
if (!(err instanceof PostHogFetchNetworkError)) await persistQueueChange();
|
|
1337
1377
|
this._events.emit("error", err);
|
|
1338
1378
|
throw err;
|
|
1339
1379
|
}
|
|
1340
|
-
persistQueueChange();
|
|
1380
|
+
await persistQueueChange();
|
|
1341
1381
|
sentMessages.push(...batchMessages);
|
|
1342
1382
|
}
|
|
1343
1383
|
this._events.emit("flush", sentMessages);
|
|
@@ -1462,7 +1502,7 @@ class ErrorPropertiesBuilder {
|
|
|
1462
1502
|
};
|
|
1463
1503
|
const coercingContext = this.buildCoercingContext(mechanism, hint, 0);
|
|
1464
1504
|
const exceptionWithCause = coercingContext.apply(input);
|
|
1465
|
-
const parsingContext = this.buildParsingContext();
|
|
1505
|
+
const parsingContext = this.buildParsingContext(hint);
|
|
1466
1506
|
const exceptionWithStack = this.parseStacktrace(exceptionWithCause, parsingContext);
|
|
1467
1507
|
const exceptionList = this.convertToExceptionList(exceptionWithStack, mechanism);
|
|
1468
1508
|
return {
|
|
@@ -1486,7 +1526,7 @@ class ErrorPropertiesBuilder {
|
|
|
1486
1526
|
let cause;
|
|
1487
1527
|
if (null != err.cause) cause = this.parseStacktrace(err.cause, ctx);
|
|
1488
1528
|
let stack;
|
|
1489
|
-
if ("" != err.stack && null != err.stack) stack = this.applyChunkIds(this.stackParser(err.stack, err.synthetic ?
|
|
1529
|
+
if ("" != err.stack && null != err.stack) stack = this.applyChunkIds(this.stackParser(err.stack, err.synthetic ? ctx.skipFirstLines : 0), ctx.chunkIdMap);
|
|
1490
1530
|
return {
|
|
1491
1531
|
...err,
|
|
1492
1532
|
cause,
|
|
@@ -1531,9 +1571,10 @@ class ErrorPropertiesBuilder {
|
|
|
1531
1571
|
}));
|
|
1532
1572
|
return exceptionList;
|
|
1533
1573
|
}
|
|
1534
|
-
buildParsingContext() {
|
|
1574
|
+
buildParsingContext(hint) {
|
|
1535
1575
|
const context = {
|
|
1536
|
-
chunkIdMap: getFilenameToChunkIdMap(this.stackParser)
|
|
1576
|
+
chunkIdMap: getFilenameToChunkIdMap(this.stackParser),
|
|
1577
|
+
skipFirstLines: hint.skipFirstLines ?? 1
|
|
1537
1578
|
};
|
|
1538
1579
|
return context;
|
|
1539
1580
|
}
|
|
@@ -2105,7 +2146,7 @@ class ErrorTracking {
|
|
|
2105
2146
|
this._rateLimiter.stop();
|
|
2106
2147
|
}
|
|
2107
2148
|
}
|
|
2108
|
-
const version = "5.
|
|
2149
|
+
const version = "5.24.11";
|
|
2109
2150
|
const FeatureFlagError = {
|
|
2110
2151
|
ERRORS_WHILE_COMPUTING: "errors_while_computing_flags",
|
|
2111
2152
|
FLAG_MISSING: "flag_missing",
|
|
@@ -2170,6 +2211,7 @@ class FeatureFlagsPoller {
|
|
|
2170
2211
|
this.customHeaders = customHeaders;
|
|
2171
2212
|
this.onLoad = options.onLoad;
|
|
2172
2213
|
this.cacheProvider = options.cacheProvider;
|
|
2214
|
+
this.strictLocalEvaluation = options.strictLocalEvaluation ?? false;
|
|
2173
2215
|
this.loadFeatureFlags();
|
|
2174
2216
|
}
|
|
2175
2217
|
debug(enabled = true) {
|
|
@@ -2365,6 +2407,11 @@ class FeatureFlagsPoller {
|
|
|
2365
2407
|
this.cohorts = flagData.cohorts;
|
|
2366
2408
|
this.loadedSuccessfullyOnce = true;
|
|
2367
2409
|
}
|
|
2410
|
+
warnAboutExperienceContinuityFlags(flags) {
|
|
2411
|
+
if (this.strictLocalEvaluation) return;
|
|
2412
|
+
const experienceContinuityFlags = flags.filter((f) => f.ensure_experience_continuity);
|
|
2413
|
+
if (experienceContinuityFlags.length > 0) console.warn(`[PostHog] You are using local evaluation but ${experienceContinuityFlags.length} flag(s) have experience continuity enabled: ${experienceContinuityFlags.map((f) => f.key).join(", ")}. Experience continuity is incompatible with local evaluation and will cause a server request on every flag evaluation, negating local evaluation cost savings. To avoid server requests and unexpected costs, either disable experience continuity on these flags in PostHog, use strictLocalEvaluation: true in client init, or pass onlyEvaluateLocally: true per flag call (flags that cannot be evaluated locally will return undefined).`);
|
|
2414
|
+
}
|
|
2368
2415
|
async loadFromCache(debugMessage) {
|
|
2369
2416
|
if (!this.cacheProvider) return false;
|
|
2370
2417
|
try {
|
|
@@ -2373,6 +2420,7 @@ class FeatureFlagsPoller {
|
|
|
2373
2420
|
this.updateFlagState(cached);
|
|
2374
2421
|
this.logMsgIfDebug(() => console.debug(`[FEATURE FLAGS] ${debugMessage} (${cached.flags.length} flags)`));
|
|
2375
2422
|
this.onLoad?.(this.featureFlags.length);
|
|
2423
|
+
this.warnAboutExperienceContinuityFlags(cached.flags);
|
|
2376
2424
|
return true;
|
|
2377
2425
|
}
|
|
2378
2426
|
return false;
|
|
@@ -2466,6 +2514,7 @@ class FeatureFlagsPoller {
|
|
|
2466
2514
|
this.onError?.(new Error(`Failed to store in cache: ${err}`));
|
|
2467
2515
|
}
|
|
2468
2516
|
this.onLoad?.(this.featureFlags.length);
|
|
2517
|
+
this.warnAboutExperienceContinuityFlags(flagData.flags);
|
|
2469
2518
|
break;
|
|
2470
2519
|
}
|
|
2471
2520
|
default:
|
|
@@ -2720,7 +2769,8 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
2720
2769
|
this._events.emit("localEvaluationFlagsLoaded", count);
|
|
2721
2770
|
},
|
|
2722
2771
|
customHeaders: this.getCustomHeaders(),
|
|
2723
|
-
cacheProvider: options.flagDefinitionCacheProvider
|
|
2772
|
+
cacheProvider: options.flagDefinitionCacheProvider,
|
|
2773
|
+
strictLocalEvaluation: options.strictLocalEvaluation
|
|
2724
2774
|
});
|
|
2725
2775
|
}
|
|
2726
2776
|
this.errorTracking = new ErrorTracking(this, options, this._logger);
|
|
@@ -2826,21 +2876,56 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
2826
2876
|
});
|
|
2827
2877
|
});
|
|
2828
2878
|
}
|
|
2829
|
-
async
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2879
|
+
async _getFeatureFlagResult(key, distinctId, options = {}, matchValue) {
|
|
2880
|
+
const sendFeatureFlagEvents = options.sendFeatureFlagEvents ?? true;
|
|
2881
|
+
if (void 0 !== this._flagOverrides && key in this._flagOverrides) {
|
|
2882
|
+
const overrideValue = this._flagOverrides[key];
|
|
2883
|
+
if (void 0 === overrideValue) return;
|
|
2884
|
+
const overridePayload = this._payloadOverrides?.[key];
|
|
2885
|
+
return {
|
|
2886
|
+
key,
|
|
2887
|
+
enabled: false !== overrideValue,
|
|
2888
|
+
variant: "string" == typeof overrideValue ? overrideValue : void 0,
|
|
2889
|
+
payload: overridePayload
|
|
2890
|
+
};
|
|
2891
|
+
}
|
|
2892
|
+
const { groups, disableGeoip } = options;
|
|
2893
|
+
let { onlyEvaluateLocally, personProperties, groupProperties } = options;
|
|
2833
2894
|
const adjustedProperties = this.addLocalPersonAndGroupProperties(distinctId, groups, personProperties, groupProperties);
|
|
2834
2895
|
personProperties = adjustedProperties.allPersonProperties;
|
|
2835
2896
|
groupProperties = adjustedProperties.allGroupProperties;
|
|
2836
|
-
if (void 0 == onlyEvaluateLocally) onlyEvaluateLocally = false;
|
|
2837
|
-
|
|
2838
|
-
let
|
|
2839
|
-
const flagWasLocallyEvaluated = void 0 !== response;
|
|
2897
|
+
if (void 0 == onlyEvaluateLocally) onlyEvaluateLocally = this.options.strictLocalEvaluation ?? false;
|
|
2898
|
+
let result;
|
|
2899
|
+
let flagWasLocallyEvaluated = false;
|
|
2840
2900
|
let requestId;
|
|
2841
2901
|
let evaluatedAt;
|
|
2842
|
-
let flagDetail;
|
|
2843
2902
|
let featureFlagError;
|
|
2903
|
+
let flagId;
|
|
2904
|
+
let flagVersion;
|
|
2905
|
+
let flagReason;
|
|
2906
|
+
const localEvaluationEnabled = void 0 !== this.featureFlagsPoller;
|
|
2907
|
+
if (localEvaluationEnabled) {
|
|
2908
|
+
await this.featureFlagsPoller?.loadFeatureFlags();
|
|
2909
|
+
const flag = this.featureFlagsPoller?.featureFlagsByKey[key];
|
|
2910
|
+
if (flag) try {
|
|
2911
|
+
const localResult = await this.featureFlagsPoller?.computeFlagAndPayloadLocally(flag, distinctId, groups, personProperties, groupProperties, matchValue);
|
|
2912
|
+
if (localResult) {
|
|
2913
|
+
flagWasLocallyEvaluated = true;
|
|
2914
|
+
const value = localResult.value;
|
|
2915
|
+
flagId = flag.id;
|
|
2916
|
+
flagReason = "Evaluated locally";
|
|
2917
|
+
result = {
|
|
2918
|
+
key,
|
|
2919
|
+
enabled: false !== value,
|
|
2920
|
+
variant: "string" == typeof value ? value : void 0,
|
|
2921
|
+
payload: localResult.payload ?? void 0
|
|
2922
|
+
};
|
|
2923
|
+
}
|
|
2924
|
+
} catch (e) {
|
|
2925
|
+
if (e instanceof RequiresServerEvaluation || e instanceof InconclusiveMatchError) this._logger?.info(`${e.name} when computing flag locally: ${key}: ${e.message}`);
|
|
2926
|
+
else throw e;
|
|
2927
|
+
}
|
|
2928
|
+
}
|
|
2844
2929
|
if (!flagWasLocallyEvaluated && !onlyEvaluateLocally) {
|
|
2845
2930
|
const flagsResponse = await super.getFeatureFlagDetailsStateless(distinctId, groups, personProperties, groupProperties, disableGeoip, [
|
|
2846
2931
|
key
|
|
@@ -2852,68 +2937,87 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
2852
2937
|
const errors = [];
|
|
2853
2938
|
if (flagsResponse.errorsWhileComputingFlags) errors.push(FeatureFlagError.ERRORS_WHILE_COMPUTING);
|
|
2854
2939
|
if (flagsResponse.quotaLimited?.includes("feature_flags")) errors.push(FeatureFlagError.QUOTA_LIMITED);
|
|
2855
|
-
flagDetail = flagsResponse.flags[key];
|
|
2940
|
+
const flagDetail = flagsResponse.flags[key];
|
|
2856
2941
|
if (void 0 === flagDetail) errors.push(FeatureFlagError.FLAG_MISSING);
|
|
2942
|
+
else {
|
|
2943
|
+
flagId = flagDetail.metadata?.id;
|
|
2944
|
+
flagVersion = flagDetail.metadata?.version;
|
|
2945
|
+
flagReason = flagDetail.reason?.description ?? flagDetail.reason?.code;
|
|
2946
|
+
let parsedPayload;
|
|
2947
|
+
if (flagDetail.metadata?.payload !== void 0) try {
|
|
2948
|
+
parsedPayload = JSON.parse(flagDetail.metadata.payload);
|
|
2949
|
+
} catch {
|
|
2950
|
+
parsedPayload = flagDetail.metadata.payload;
|
|
2951
|
+
}
|
|
2952
|
+
result = {
|
|
2953
|
+
key,
|
|
2954
|
+
enabled: flagDetail.enabled,
|
|
2955
|
+
variant: flagDetail.variant,
|
|
2956
|
+
payload: parsedPayload
|
|
2957
|
+
};
|
|
2958
|
+
}
|
|
2857
2959
|
if (errors.length > 0) featureFlagError = errors.join(",");
|
|
2858
|
-
response = getFeatureFlagValue(flagDetail);
|
|
2859
2960
|
}
|
|
2860
2961
|
}
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
if (
|
|
2865
|
-
|
|
2866
|
-
featureFlagReportedKey
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2962
|
+
if (sendFeatureFlagEvents) {
|
|
2963
|
+
const response = void 0 === result ? void 0 : false === result.enabled ? false : result.variant ?? true;
|
|
2964
|
+
const featureFlagReportedKey = `${key}_${response}`;
|
|
2965
|
+
if (!(distinctId in this.distinctIdHasSentFlagCalls) || !this.distinctIdHasSentFlagCalls[distinctId].includes(featureFlagReportedKey)) {
|
|
2966
|
+
if (Object.keys(this.distinctIdHasSentFlagCalls).length >= this.maxCacheSize) this.distinctIdHasSentFlagCalls = {};
|
|
2967
|
+
if (Array.isArray(this.distinctIdHasSentFlagCalls[distinctId])) this.distinctIdHasSentFlagCalls[distinctId].push(featureFlagReportedKey);
|
|
2968
|
+
else this.distinctIdHasSentFlagCalls[distinctId] = [
|
|
2969
|
+
featureFlagReportedKey
|
|
2970
|
+
];
|
|
2971
|
+
const properties = {
|
|
2972
|
+
$feature_flag: key,
|
|
2973
|
+
$feature_flag_response: response,
|
|
2974
|
+
$feature_flag_id: flagId,
|
|
2975
|
+
$feature_flag_version: flagVersion,
|
|
2976
|
+
$feature_flag_reason: flagReason,
|
|
2977
|
+
locally_evaluated: flagWasLocallyEvaluated,
|
|
2978
|
+
[`$feature/${key}`]: response,
|
|
2979
|
+
$feature_flag_request_id: requestId,
|
|
2980
|
+
$feature_flag_evaluated_at: evaluatedAt
|
|
2981
|
+
};
|
|
2982
|
+
if (featureFlagError) properties.$feature_flag_error = featureFlagError;
|
|
2983
|
+
this.capture({
|
|
2984
|
+
distinctId,
|
|
2985
|
+
event: "$feature_flag_called",
|
|
2986
|
+
properties,
|
|
2987
|
+
groups,
|
|
2988
|
+
disableGeoip
|
|
2989
|
+
});
|
|
2990
|
+
}
|
|
2887
2991
|
}
|
|
2888
|
-
|
|
2992
|
+
if (void 0 !== result && void 0 !== this._payloadOverrides && key in this._payloadOverrides) result = {
|
|
2993
|
+
...result,
|
|
2994
|
+
payload: this._payloadOverrides[key]
|
|
2995
|
+
};
|
|
2996
|
+
return result;
|
|
2997
|
+
}
|
|
2998
|
+
async getFeatureFlag(key, distinctId, options) {
|
|
2999
|
+
const result = await this._getFeatureFlagResult(key, distinctId, {
|
|
3000
|
+
...options,
|
|
3001
|
+
sendFeatureFlagEvents: options?.sendFeatureFlagEvents ?? this.options.sendFeatureFlagEvent ?? true
|
|
3002
|
+
});
|
|
3003
|
+
if (void 0 === result) return;
|
|
3004
|
+
if (false === result.enabled) return false;
|
|
3005
|
+
return result.variant ?? true;
|
|
2889
3006
|
}
|
|
2890
3007
|
async getFeatureFlagPayload(key, distinctId, matchValue, options) {
|
|
2891
3008
|
if (void 0 !== this._payloadOverrides && key in this._payloadOverrides) return this._payloadOverrides[key];
|
|
2892
|
-
const
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
if (result) {
|
|
2905
|
-
matchValue = result.value;
|
|
2906
|
-
response = result.payload;
|
|
2907
|
-
}
|
|
2908
|
-
} catch (e) {
|
|
2909
|
-
if (e instanceof RequiresServerEvaluation || e instanceof InconclusiveMatchError) this._logger?.info(`${e.name} when computing flag locally: ${flag.key}: ${e.message}`);
|
|
2910
|
-
else throw e;
|
|
2911
|
-
}
|
|
2912
|
-
}
|
|
2913
|
-
if (void 0 == onlyEvaluateLocally) onlyEvaluateLocally = false;
|
|
2914
|
-
const payloadWasLocallyEvaluated = void 0 !== response;
|
|
2915
|
-
if (!payloadWasLocallyEvaluated && !onlyEvaluateLocally) response = await super.getFeatureFlagPayloadStateless(key, distinctId, groups, personProperties, groupProperties, disableGeoip);
|
|
2916
|
-
return response;
|
|
3009
|
+
const result = await this._getFeatureFlagResult(key, distinctId, {
|
|
3010
|
+
...options,
|
|
3011
|
+
sendFeatureFlagEvents: false
|
|
3012
|
+
}, matchValue);
|
|
3013
|
+
if (void 0 === result) return;
|
|
3014
|
+
return result.payload ?? null;
|
|
3015
|
+
}
|
|
3016
|
+
async getFeatureFlagResult(key, distinctId, options) {
|
|
3017
|
+
return this._getFeatureFlagResult(key, distinctId, {
|
|
3018
|
+
...options,
|
|
3019
|
+
sendFeatureFlagEvents: options?.sendFeatureFlagEvents ?? this.options.sendFeatureFlagEvent ?? true
|
|
3020
|
+
});
|
|
2917
3021
|
}
|
|
2918
3022
|
async getRemoteConfigPayload(flagKey) {
|
|
2919
3023
|
if (!this.options.personalApiKey) throw new Error("Personal API key is required for remote config payload decryption");
|
|
@@ -2941,7 +3045,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
2941
3045
|
const adjustedProperties = this.addLocalPersonAndGroupProperties(distinctId, groups, personProperties, groupProperties);
|
|
2942
3046
|
personProperties = adjustedProperties.allPersonProperties;
|
|
2943
3047
|
groupProperties = adjustedProperties.allGroupProperties;
|
|
2944
|
-
if (void 0 == onlyEvaluateLocally) onlyEvaluateLocally = false;
|
|
3048
|
+
if (void 0 == onlyEvaluateLocally) onlyEvaluateLocally = this.options.strictLocalEvaluation ?? false;
|
|
2945
3049
|
const localEvaluationResult = await this.featureFlagsPoller?.getAllFlagsAndPayloads(distinctId, groups, personProperties, groupProperties, flagKeys);
|
|
2946
3050
|
let featureFlags = {};
|
|
2947
3051
|
let featureFlagPayloads = {};
|
|
@@ -3091,7 +3195,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
3091
3195
|
const finalPersonProperties = sendFeatureFlagsOptions?.personProperties || {};
|
|
3092
3196
|
const finalGroupProperties = sendFeatureFlagsOptions?.groupProperties || {};
|
|
3093
3197
|
const flagKeys = sendFeatureFlagsOptions?.flagKeys;
|
|
3094
|
-
const onlyEvaluateLocally = sendFeatureFlagsOptions?.onlyEvaluateLocally ?? false;
|
|
3198
|
+
const onlyEvaluateLocally = sendFeatureFlagsOptions?.onlyEvaluateLocally ?? this.options.strictLocalEvaluation ?? false;
|
|
3095
3199
|
if (onlyEvaluateLocally) if (!((this.featureFlagsPoller?.featureFlags?.length || 0) > 0)) return {};
|
|
3096
3200
|
else {
|
|
3097
3201
|
const groupsWithStringValues = {};
|