posthog-node 5.3.1 → 5.5.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 +52 -0
- package/lib/edge/index.cjs +79 -38
- package/lib/edge/index.cjs.map +1 -1
- package/lib/edge/index.mjs +79 -38
- package/lib/edge/index.mjs.map +1 -1
- package/lib/index.d.ts +9 -2
- package/lib/node/index.cjs +79 -38
- package/lib/node/index.cjs.map +1 -1
- package/lib/node/index.mjs +79 -38
- package/lib/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/lib/node/index.mjs
CHANGED
|
@@ -1320,7 +1320,7 @@ function snipLine(line, colno) {
|
|
|
1320
1320
|
return newLine;
|
|
1321
1321
|
}
|
|
1322
1322
|
|
|
1323
|
-
var version = "5.
|
|
1323
|
+
var version = "5.5.0";
|
|
1324
1324
|
|
|
1325
1325
|
var PostHogPersistedProperty;
|
|
1326
1326
|
(function (PostHogPersistedProperty) {
|
|
@@ -2614,7 +2614,9 @@ class FeatureFlagsPoller {
|
|
|
2614
2614
|
payloads[flag.key] = matchPayload;
|
|
2615
2615
|
}
|
|
2616
2616
|
} catch (e) {
|
|
2617
|
-
if (e instanceof InconclusiveMatchError)
|
|
2617
|
+
if (e instanceof InconclusiveMatchError) {
|
|
2618
|
+
this.onError?.(new Error(`Unable to compute flag locally: ${flag.key} - ${e.message}`));
|
|
2619
|
+
} else if (e instanceof Error) {
|
|
2618
2620
|
this.onError?.(new Error(`Error computing flag locally: ${flag.key}: ${e}`));
|
|
2619
2621
|
}
|
|
2620
2622
|
fallbackToFlags = true;
|
|
@@ -3238,32 +3240,17 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
3238
3240
|
uuid
|
|
3239
3241
|
});
|
|
3240
3242
|
};
|
|
3241
|
-
const _getFlags = async (distinctId, groups, disableGeoip) => {
|
|
3242
|
-
return (await super.getFeatureFlagsStateless(distinctId, groups, undefined, undefined, disableGeoip)).flags;
|
|
3243
|
-
};
|
|
3244
3243
|
// :TRICKY: If we flush, or need to shut down, to not lose events we want this promise to resolve before we flush
|
|
3245
3244
|
const capturePromise = Promise.resolve().then(async () => {
|
|
3246
3245
|
if (sendFeatureFlags) {
|
|
3247
|
-
// If we are sending feature flags, we
|
|
3248
|
-
|
|
3249
|
-
return await
|
|
3246
|
+
// If we are sending feature flags, we evaluate them locally if the user prefers it, otherwise we fall back to remote evaluation
|
|
3247
|
+
const sendFeatureFlagsOptions = typeof sendFeatureFlags === 'object' ? sendFeatureFlags : undefined;
|
|
3248
|
+
return await this.getFeatureFlagsForEvent(distinctId, groups, disableGeoip, sendFeatureFlagsOptions);
|
|
3250
3249
|
}
|
|
3251
3250
|
if (event === '$feature_flag_called') {
|
|
3252
3251
|
// If we're capturing a $feature_flag_called event, we don't want to enrich the event with cached flags that may be out of date.
|
|
3253
3252
|
return {};
|
|
3254
3253
|
}
|
|
3255
|
-
if ((this.featureFlagsPoller?.featureFlags?.length || 0) > 0) {
|
|
3256
|
-
// Otherwise we may as well check for the flags locally and include them if they are already loaded
|
|
3257
|
-
const groupsWithStringValues = {};
|
|
3258
|
-
for (const [key, value] of Object.entries(groups || {})) {
|
|
3259
|
-
groupsWithStringValues[key] = String(value);
|
|
3260
|
-
}
|
|
3261
|
-
return await this.getAllFlags(distinctId, {
|
|
3262
|
-
groups: groupsWithStringValues,
|
|
3263
|
-
disableGeoip,
|
|
3264
|
-
onlyEvaluateLocally: true
|
|
3265
|
-
});
|
|
3266
|
-
}
|
|
3267
3254
|
return {};
|
|
3268
3255
|
}).then(flags => {
|
|
3269
3256
|
// Derive the relevant flag properties to add
|
|
@@ -3312,31 +3299,16 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
3312
3299
|
uuid
|
|
3313
3300
|
});
|
|
3314
3301
|
};
|
|
3315
|
-
const _getFlags = async (distinctId, groups, disableGeoip) => {
|
|
3316
|
-
return (await super.getFeatureFlagsStateless(distinctId, groups, undefined, undefined, disableGeoip)).flags;
|
|
3317
|
-
};
|
|
3318
3302
|
const capturePromise = Promise.resolve().then(async () => {
|
|
3319
3303
|
if (sendFeatureFlags) {
|
|
3320
|
-
// If we are sending feature flags, we
|
|
3321
|
-
|
|
3322
|
-
return await
|
|
3304
|
+
// If we are sending feature flags, we evaluate them locally if the user prefers it, otherwise we fall back to remote evaluation
|
|
3305
|
+
const sendFeatureFlagsOptions = typeof sendFeatureFlags === 'object' ? sendFeatureFlags : undefined;
|
|
3306
|
+
return await this.getFeatureFlagsForEvent(distinctId, groups, disableGeoip, sendFeatureFlagsOptions);
|
|
3323
3307
|
}
|
|
3324
3308
|
if (event === '$feature_flag_called') {
|
|
3325
3309
|
// If we're capturing a $feature_flag_called event, we don't want to enrich the event with cached flags that may be out of date.
|
|
3326
3310
|
return {};
|
|
3327
3311
|
}
|
|
3328
|
-
if ((this.featureFlagsPoller?.featureFlags?.length || 0) > 0) {
|
|
3329
|
-
// Otherwise we may as well check for the flags locally and include them if they are already loaded
|
|
3330
|
-
const groupsWithStringValues = {};
|
|
3331
|
-
for (const [key, value] of Object.entries(groups || {})) {
|
|
3332
|
-
groupsWithStringValues[key] = String(value);
|
|
3333
|
-
}
|
|
3334
|
-
return await this.getAllFlags(distinctId, {
|
|
3335
|
-
groups: groupsWithStringValues,
|
|
3336
|
-
disableGeoip,
|
|
3337
|
-
onlyEvaluateLocally: true
|
|
3338
|
-
});
|
|
3339
|
-
}
|
|
3340
3312
|
return {};
|
|
3341
3313
|
}).then(flags => {
|
|
3342
3314
|
// Derive the relevant flag properties to add
|
|
@@ -3671,6 +3643,75 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
3671
3643
|
}
|
|
3672
3644
|
}
|
|
3673
3645
|
}
|
|
3646
|
+
extractPropertiesFromEvent(eventProperties, groups) {
|
|
3647
|
+
if (!eventProperties) {
|
|
3648
|
+
return {
|
|
3649
|
+
personProperties: {},
|
|
3650
|
+
groupProperties: {}
|
|
3651
|
+
};
|
|
3652
|
+
}
|
|
3653
|
+
const personProperties = {};
|
|
3654
|
+
const groupProperties = {};
|
|
3655
|
+
for (const [key, value] of Object.entries(eventProperties)) {
|
|
3656
|
+
// If the value is a plain object and the key exists in groups, treat it as group properties
|
|
3657
|
+
if (isPlainObject(value) && groups && key in groups) {
|
|
3658
|
+
const groupProps = {};
|
|
3659
|
+
for (const [groupKey, groupValue] of Object.entries(value)) {
|
|
3660
|
+
groupProps[String(groupKey)] = String(groupValue);
|
|
3661
|
+
}
|
|
3662
|
+
groupProperties[String(key)] = groupProps;
|
|
3663
|
+
} else {
|
|
3664
|
+
// Otherwise treat as person property
|
|
3665
|
+
personProperties[String(key)] = String(value);
|
|
3666
|
+
}
|
|
3667
|
+
}
|
|
3668
|
+
return {
|
|
3669
|
+
personProperties,
|
|
3670
|
+
groupProperties
|
|
3671
|
+
};
|
|
3672
|
+
}
|
|
3673
|
+
async getFeatureFlagsForEvent(distinctId, groups, disableGeoip, sendFeatureFlagsOptions) {
|
|
3674
|
+
// Use properties directly from options if they exist
|
|
3675
|
+
const finalPersonProperties = sendFeatureFlagsOptions?.personProperties || {};
|
|
3676
|
+
const finalGroupProperties = sendFeatureFlagsOptions?.groupProperties || {};
|
|
3677
|
+
// Check if we should only evaluate locally
|
|
3678
|
+
const onlyEvaluateLocally = sendFeatureFlagsOptions?.onlyEvaluateLocally ?? false;
|
|
3679
|
+
// If onlyEvaluateLocally is true, only use local evaluation
|
|
3680
|
+
if (onlyEvaluateLocally) {
|
|
3681
|
+
if ((this.featureFlagsPoller?.featureFlags?.length || 0) > 0) {
|
|
3682
|
+
const groupsWithStringValues = {};
|
|
3683
|
+
for (const [key, value] of Object.entries(groups || {})) {
|
|
3684
|
+
groupsWithStringValues[key] = String(value);
|
|
3685
|
+
}
|
|
3686
|
+
return await this.getAllFlags(distinctId, {
|
|
3687
|
+
groups: groupsWithStringValues,
|
|
3688
|
+
personProperties: finalPersonProperties,
|
|
3689
|
+
groupProperties: finalGroupProperties,
|
|
3690
|
+
disableGeoip,
|
|
3691
|
+
onlyEvaluateLocally: true
|
|
3692
|
+
});
|
|
3693
|
+
} else {
|
|
3694
|
+
// If onlyEvaluateLocally is true but we don't have local flags, return empty
|
|
3695
|
+
return {};
|
|
3696
|
+
}
|
|
3697
|
+
}
|
|
3698
|
+
// Prefer local evaluation if available (default behavior; I'd rather not penalize users who haven't updated to the new API but still want to use local evaluation)
|
|
3699
|
+
if ((this.featureFlagsPoller?.featureFlags?.length || 0) > 0) {
|
|
3700
|
+
const groupsWithStringValues = {};
|
|
3701
|
+
for (const [key, value] of Object.entries(groups || {})) {
|
|
3702
|
+
groupsWithStringValues[key] = String(value);
|
|
3703
|
+
}
|
|
3704
|
+
return await this.getAllFlags(distinctId, {
|
|
3705
|
+
groups: groupsWithStringValues,
|
|
3706
|
+
personProperties: finalPersonProperties,
|
|
3707
|
+
groupProperties: finalGroupProperties,
|
|
3708
|
+
disableGeoip,
|
|
3709
|
+
onlyEvaluateLocally: true
|
|
3710
|
+
});
|
|
3711
|
+
}
|
|
3712
|
+
// Fall back to remote evaluation if local evaluation is not available
|
|
3713
|
+
return (await super.getFeatureFlagsStateless(distinctId, groups, finalPersonProperties, finalGroupProperties, disableGeoip)).flags;
|
|
3714
|
+
}
|
|
3674
3715
|
addLocalPersonAndGroupProperties(distinctId, groups, personProperties, groupProperties) {
|
|
3675
3716
|
const allPersonProperties = {
|
|
3676
3717
|
distinct_id: distinctId,
|