posthog-node 5.4.0 → 5.5.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.
package/lib/index.d.ts CHANGED
@@ -588,10 +588,15 @@ interface IdentifyMessage {
588
588
  properties?: Record<string | number, any>;
589
589
  disableGeoip?: boolean;
590
590
  }
591
+ interface SendFeatureFlagsOptions {
592
+ onlyEvaluateLocally?: boolean;
593
+ personProperties?: Record<string, any>;
594
+ groupProperties?: Record<string, Record<string, any>>;
595
+ }
591
596
  interface EventMessage extends IdentifyMessage {
592
597
  event: string;
593
598
  groups?: Record<string, string | number>;
594
- sendFeatureFlags?: boolean;
599
+ sendFeatureFlags?: boolean | SendFeatureFlagsOptions;
595
600
  timestamp?: Date;
596
601
  uuid?: string;
597
602
  }
@@ -967,4 +972,4 @@ declare class PostHog extends PostHogBackendClient {
967
972
  getLibraryId(): string;
968
973
  }
969
974
 
970
- export { EventMessage, FeatureFlagCondition, FlagProperty, GroupIdentifyMessage, IPostHog, IdentifyMessage, PostHog, PostHogFeatureFlag, PostHogOptions, PostHogSentryIntegration, PropertyGroup, SentryIntegrationOptions, createEventProcessor, sentryIntegration, setupExpressErrorHandler };
975
+ export { EventMessage, FeatureFlagCondition, FlagProperty, GroupIdentifyMessage, IPostHog, IdentifyMessage, PostHog, PostHogFeatureFlag, PostHogOptions, PostHogSentryIntegration, PropertyGroup, SendFeatureFlagsOptions, SentryIntegrationOptions, createEventProcessor, sentryIntegration, setupExpressErrorHandler };
@@ -1342,7 +1342,7 @@ function snipLine(line, colno) {
1342
1342
  return newLine;
1343
1343
  }
1344
1344
 
1345
- var version = "5.4.0";
1345
+ var version = "5.5.1";
1346
1346
 
1347
1347
  var PostHogPersistedProperty;
1348
1348
  (function (PostHogPersistedProperty) {
@@ -2637,7 +2637,7 @@ class FeatureFlagsPoller {
2637
2637
  }
2638
2638
  } catch (e) {
2639
2639
  if (e instanceof InconclusiveMatchError) {
2640
- this.onError?.(new Error(`Unable to compute flag locally: ${flag.key} - ${e.message}`));
2640
+ this.logMsgIfDebug(() => console.debug(`InconclusiveMatchError when computing flag locally: ${flag.key}: ${e}`));
2641
2641
  } else if (e instanceof Error) {
2642
2642
  this.onError?.(new Error(`Error computing flag locally: ${flag.key}: ${e}`));
2643
2643
  }
@@ -2734,6 +2734,9 @@ class FeatureFlagsPoller {
2734
2734
  let matches = false;
2735
2735
  if (propertyType === 'cohort') {
2736
2736
  matches = matchCohort(prop, properties, this.cohorts, this.debugMode);
2737
+ } else if (propertyType === 'flag') {
2738
+ this.logMsgIfDebug(() => console.warn(`[FEATURE FLAGS] Flag dependency filters are not supported in local evaluation. ` + `Skipping condition for flag '${flag.key}' with dependency on flag '${prop.key || 'unknown'}'`));
2739
+ continue;
2737
2740
  } else {
2738
2741
  matches = matchProperty(prop, properties, warnFunction);
2739
2742
  }
@@ -3071,6 +3074,11 @@ function matchPropertyGroup(propertyGroup, propertyValues, cohortProperties, deb
3071
3074
  let matches;
3072
3075
  if (prop.type === 'cohort') {
3073
3076
  matches = matchCohort(prop, propertyValues, cohortProperties, debugMode);
3077
+ } else if (prop.type === 'flag') {
3078
+ if (debugMode) {
3079
+ console.warn(`[FEATURE FLAGS] Flag dependency filters are not supported in local evaluation. ` + `Skipping condition with dependency on flag '${prop.key || 'unknown'}'`);
3080
+ }
3081
+ continue;
3074
3082
  } else {
3075
3083
  matches = matchProperty(prop, propertyValues);
3076
3084
  }
@@ -3266,7 +3274,8 @@ class PostHogBackendClient extends PostHogCoreStateless {
3266
3274
  const capturePromise = Promise.resolve().then(async () => {
3267
3275
  if (sendFeatureFlags) {
3268
3276
  // If we are sending feature flags, we evaluate them locally if the user prefers it, otherwise we fall back to remote evaluation
3269
- return await this.getFeatureFlagsForEvent(distinctId, groups, properties, disableGeoip);
3277
+ const sendFeatureFlagsOptions = typeof sendFeatureFlags === 'object' ? sendFeatureFlags : undefined;
3278
+ return await this.getFeatureFlagsForEvent(distinctId, groups, disableGeoip, sendFeatureFlagsOptions);
3270
3279
  }
3271
3280
  if (event === '$feature_flag_called') {
3272
3281
  // 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.
@@ -3323,7 +3332,8 @@ class PostHogBackendClient extends PostHogCoreStateless {
3323
3332
  const capturePromise = Promise.resolve().then(async () => {
3324
3333
  if (sendFeatureFlags) {
3325
3334
  // If we are sending feature flags, we evaluate them locally if the user prefers it, otherwise we fall back to remote evaluation
3326
- return await this.getFeatureFlagsForEvent(distinctId, groups, properties, disableGeoip);
3335
+ const sendFeatureFlagsOptions = typeof sendFeatureFlags === 'object' ? sendFeatureFlags : undefined;
3336
+ return await this.getFeatureFlagsForEvent(distinctId, groups, disableGeoip, sendFeatureFlagsOptions);
3327
3337
  }
3328
3338
  if (event === '$feature_flag_called') {
3329
3339
  // 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.
@@ -3690,13 +3700,32 @@ class PostHogBackendClient extends PostHogCoreStateless {
3690
3700
  groupProperties
3691
3701
  };
3692
3702
  }
3693
- async getFeatureFlagsForEvent(distinctId, groups, eventProperties, disableGeoip) {
3694
- // Extract person and group properties from the event properties
3695
- const {
3696
- personProperties: cleanPersonProperties,
3697
- groupProperties: cleanGroupProperties
3698
- } = this.extractPropertiesFromEvent(eventProperties, groups);
3699
- // Prefer local evaluation if available
3703
+ async getFeatureFlagsForEvent(distinctId, groups, disableGeoip, sendFeatureFlagsOptions) {
3704
+ // Use properties directly from options if they exist
3705
+ const finalPersonProperties = sendFeatureFlagsOptions?.personProperties || {};
3706
+ const finalGroupProperties = sendFeatureFlagsOptions?.groupProperties || {};
3707
+ // Check if we should only evaluate locally
3708
+ const onlyEvaluateLocally = sendFeatureFlagsOptions?.onlyEvaluateLocally ?? false;
3709
+ // If onlyEvaluateLocally is true, only use local evaluation
3710
+ if (onlyEvaluateLocally) {
3711
+ if ((this.featureFlagsPoller?.featureFlags?.length || 0) > 0) {
3712
+ const groupsWithStringValues = {};
3713
+ for (const [key, value] of Object.entries(groups || {})) {
3714
+ groupsWithStringValues[key] = String(value);
3715
+ }
3716
+ return await this.getAllFlags(distinctId, {
3717
+ groups: groupsWithStringValues,
3718
+ personProperties: finalPersonProperties,
3719
+ groupProperties: finalGroupProperties,
3720
+ disableGeoip,
3721
+ onlyEvaluateLocally: true
3722
+ });
3723
+ } else {
3724
+ // If onlyEvaluateLocally is true but we don't have local flags, return empty
3725
+ return {};
3726
+ }
3727
+ }
3728
+ // 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)
3700
3729
  if ((this.featureFlagsPoller?.featureFlags?.length || 0) > 0) {
3701
3730
  const groupsWithStringValues = {};
3702
3731
  for (const [key, value] of Object.entries(groups || {})) {
@@ -3704,14 +3733,14 @@ class PostHogBackendClient extends PostHogCoreStateless {
3704
3733
  }
3705
3734
  return await this.getAllFlags(distinctId, {
3706
3735
  groups: groupsWithStringValues,
3707
- personProperties: cleanPersonProperties,
3708
- groupProperties: cleanGroupProperties,
3736
+ personProperties: finalPersonProperties,
3737
+ groupProperties: finalGroupProperties,
3709
3738
  disableGeoip,
3710
3739
  onlyEvaluateLocally: true
3711
3740
  });
3712
3741
  }
3713
- // Fall back to remote evaluation if local evaluation is not available/is not being used
3714
- return (await super.getFeatureFlagsStateless(distinctId, groups, cleanPersonProperties, cleanGroupProperties, disableGeoip)).flags;
3742
+ // Fall back to remote evaluation if local evaluation is not available
3743
+ return (await super.getFeatureFlagsStateless(distinctId, groups, finalPersonProperties, finalGroupProperties, disableGeoip)).flags;
3715
3744
  }
3716
3745
  addLocalPersonAndGroupProperties(distinctId, groups, personProperties, groupProperties) {
3717
3746
  const allPersonProperties = {