Skip to content

refactor(flags): Unify method to compute flag value and payload#2196

Merged
haacked merged 3 commits intomainfrom
haacked/compute-locally-refactoring
Aug 6, 2025
Merged

refactor(flags): Unify method to compute flag value and payload#2196
haacked merged 3 commits intomainfrom
haacked/compute-locally-refactoring

Conversation

@haacked
Copy link
Contributor

@haacked haacked commented Aug 6, 2025

This refactors both compute*Locally methods into a single one.

Problem

Two separate methods for what is essentially the same operation is going to cause headaches down the line.

For example, while working on local evaluation support for flag dependencies, I ended up having two code paths for dependency evaluation. First to evaluate the flag value in a dependency-aware manner. Then I had to evaluate flag payloads. This was confusing and brittle.

Changes

  • Wrote a new computeFlagAndPayloadLocally method that computes the flag value and payload
    • This method accepts an optional provided matchValue and skips flag value evaluation if provided and uses that value to get the payload.
  • Update client.ts to use the new method.
  • Removed computeFeatureFlagPayloadLocally and computeFlagLocally.

Release info Sub-libraries affected

Libraries affected

  • All of them
  • posthog-js (web)
  • posthog-js-lite (web lite)
  • posthog-node
  • posthog-react-native
  • @posthog/react
  • @posthog/ai
  • @posthog/nextjs-config

Checklist

  • Tests for new code
  • Accounted for the impact of any changes across different platforms
  • Accounted for backwards compatibility of any changes (no breaking changes!)
  • Took care not to unnecessarily increase the bundle size

If releasing new changes

This change doesn't need to be released right away.

  • Ran pnpm changeset to generate a changeset file
  • Added the "release" label to the PR to indicate we're publishing new versions for the affected packages

@vercel
Copy link

vercel bot commented Aug 6, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
posthog-js ✅ Ready (Inspect) Visit Preview Aug 6, 2025 8:38pm

@haacked haacked requested a review from a team August 6, 2025 17:56
@dmarticus dmarticus moved this to In Review in Feature Flags Aug 6, 2025
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile Summary

This PR refactors the feature flags system in posthog-node by consolidating two separate methods (computeFlagLocally and computeFeatureFlagPayloadLocally) into a unified computeFlagAndPayloadLocally method. The refactoring addresses a fundamental design issue where maintaining separate code paths for flag value evaluation and payload retrieval was creating maintenance overhead and potential inconsistencies.

The new unified method accepts an optional matchValue parameter, allowing it to skip flag evaluation when a value is already known (useful for dependency-aware flag evaluation) while still computing the correct payload. Two new private helper methods were extracted: computeFlagValueLocally handles the core flag evaluation logic, and getFeatureFlagPayload manages payload retrieval with improved JSON parsing capabilities.

In client.ts, the getFeatureFlagPayload method was updated to use the new unified approach, including proper flag loading with await this.featureFlagsPoller?.loadFeatureFlags() and flag existence validation before computation. This change prepares the codebase for more sophisticated flag evaluation patterns like dependency chains while following the DRY principle and reducing cognitive load for developers working with the feature flags system.

Confidence score: 4/5

  • This PR is safe to merge with minimal risk as it's a well-structured refactoring that maintains backward compatibility
  • Score reflects solid code organization and clear separation of concerns, with only minor code quality issues identified
  • Pay close attention to the duplicate default value assignment in client.ts lines 461-463 and the stray comment marker on line 450

2 files reviewed, 1 comment

Edit Code Review Bot Settings | Greptile

@github-actions
Copy link
Contributor

github-actions bot commented Aug 6, 2025

@github-actions
Copy link
Contributor

github-actions bot commented Aug 6, 2025

Size Change: +4.52 kB (+0.1%)

Total Size: 4.74 MB

Filename Size Change
packages/node/dist/edge/index.cjs 82.5 kB +1.13 kB (+1.39%)
packages/node/dist/edge/index.mjs 82.4 kB +1.13 kB (+1.39%)
packages/node/dist/node/index.cjs 97.3 kB +1.13 kB (+1.17%)
packages/node/dist/node/index.mjs 97.2 kB +1.13 kB (+1.18%)
ℹ️ View Unchanged
Filename Size
packages/ai/dist/anthropic/index.cjs 10.2 kB
packages/ai/dist/anthropic/index.mjs 10 kB
packages/ai/dist/gemini/index.cjs 10.3 kB
packages/ai/dist/gemini/index.mjs 10.1 kB
packages/ai/dist/index.cjs 89.5 kB
packages/ai/dist/index.mjs 88.8 kB
packages/ai/dist/langchain/index.cjs 35.3 kB
packages/ai/dist/langchain/index.mjs 34.8 kB
packages/ai/dist/openai/index.cjs 17.7 kB
packages/ai/dist/openai/index.mjs 17.5 kB
packages/ai/dist/vercel/index.cjs 16.2 kB
packages/ai/dist/vercel/index.mjs 16.2 kB
packages/browser/dist/all-external-dependencies.js 221 kB
packages/browser/dist/array.full.es5.js 309 kB
packages/browser/dist/array.full.js 373 kB
packages/browser/dist/array.full.no-external.js 390 kB
packages/browser/dist/array.js 172 kB
packages/browser/dist/array.no-external.js 187 kB
packages/browser/dist/crisp-chat-integration.js 1.97 kB
packages/browser/dist/customizations.full.js 15.9 kB
packages/browser/dist/dead-clicks-autocapture.js 12.6 kB
packages/browser/dist/exception-autocapture.js 9.55 kB
packages/browser/dist/external-scripts-loader.js 2.57 kB
packages/browser/dist/intercom-integration.js 2.02 kB
packages/browser/dist/main.js 173 kB
packages/browser/dist/module.full.js 373 kB
packages/browser/dist/module.full.no-external.js 390 kB
packages/browser/dist/module.js 173 kB
packages/browser/dist/module.no-external.js 188 kB
packages/browser/dist/posthog-recorder.js 207 kB
packages/browser/dist/recorder-v2.js 113 kB
packages/browser/dist/recorder.js 113 kB
packages/browser/dist/surveys-preview.js 70.8 kB
packages/browser/dist/surveys.js 79.2 kB
packages/browser/dist/tracing-headers.js 1.81 kB
packages/browser/dist/web-vitals.js 10.4 kB
packages/browser/react/dist/esm/index.js 14.7 kB
packages/browser/react/dist/umd/index.js 17.3 kB
packages/core/dist/eventemitter.js 1.78 kB
packages/core/dist/eventemitter.mjs 571 B
packages/core/dist/featureFlagUtils.js 7.56 kB
packages/core/dist/featureFlagUtils.mjs 5.34 kB
packages/core/dist/gzip.js 1.95 kB
packages/core/dist/gzip.mjs 650 B
packages/core/dist/index.js 71.7 kB
packages/core/dist/index.mjs 60.3 kB
packages/core/dist/testing/index.js 2.93 kB
packages/core/dist/testing/index.mjs 79 B
packages/core/dist/testing/PostHogCoreTestClient.js 3.5 kB
packages/core/dist/testing/PostHogCoreTestClient.mjs 2.11 kB
packages/core/dist/testing/test-utils.js 2.35 kB
packages/core/dist/testing/test-utils.mjs 783 B
packages/core/dist/types.js 7.67 kB
packages/core/dist/types.mjs 5.56 kB
packages/core/dist/utils.js 3.91 kB
packages/core/dist/utils.mjs 1.76 kB
packages/core/dist/vendor/uuidv7.js 8.57 kB
packages/core/dist/vendor/uuidv7.mjs 7 kB
packages/nextjs-config/dist/config.js 3.8 kB
packages/nextjs-config/dist/config.mjs 2.53 kB
packages/nextjs-config/dist/index.js 2.24 kB
packages/nextjs-config/dist/index.mjs 30 B
packages/nextjs-config/dist/utils.js 4.21 kB
packages/nextjs-config/dist/utils.mjs 2.29 kB
packages/nextjs-config/dist/utils.spec.js 723 B
packages/nextjs-config/dist/utils.spec.mjs 455 B
packages/nextjs-config/dist/webpack-plugin.js 4.41 kB
packages/nextjs-config/dist/webpack-plugin.mjs 2.66 kB
packages/react-native/dist/autocapture.js 4.68 kB
packages/react-native/dist/frameworks/wix-navigation.js 1.3 kB
packages/react-native/dist/hooks/useFeatureFlag.js 1.49 kB
packages/react-native/dist/hooks/useFeatureFlags.js 821 B
packages/react-native/dist/hooks/useNavigationTracker.js 2.46 kB
packages/react-native/dist/hooks/usePostHog.js 467 B
packages/react-native/dist/index.js 3.12 kB
packages/react-native/dist/native-deps.js 12.2 kB
packages/react-native/dist/optional/OptionalAsyncStorage.js 299 B
packages/react-native/dist/optional/OptionalExpoApplication.js 377 B
packages/react-native/dist/optional/OptionalExpoDevice.js 347 B
packages/react-native/dist/optional/OptionalExpoFileSystem.js 386 B
packages/react-native/dist/optional/OptionalExpoLocalization.js 383 B
packages/react-native/dist/optional/OptionalReactNativeDeviceInfo.js 415 B
packages/react-native/dist/optional/OptionalReactNativeLocalize.js 303 B
packages/react-native/dist/optional/OptionalReactNativeNavigation.js 415 B
packages/react-native/dist/optional/OptionalReactNativeNavigationWix.js 443 B
packages/react-native/dist/optional/OptionalReactNativeSafeArea.js 644 B
packages/react-native/dist/optional/OptionalSessionReplay.js 455 B
packages/react-native/dist/posthog-rn.js 28.7 kB
packages/react-native/dist/PostHogContext.js 329 B
packages/react-native/dist/PostHogProvider.js 4.77 kB
packages/react-native/dist/storage.js 3.39 kB
packages/react-native/dist/surveys/components/BottomSection.js 1.34 kB
packages/react-native/dist/surveys/components/Cancel.js 909 B
packages/react-native/dist/surveys/components/ConfirmationMessage.js 1.63 kB
packages/react-native/dist/surveys/components/QuestionHeader.js 1.11 kB
packages/react-native/dist/surveys/components/QuestionTypes.js 10.1 kB
packages/react-native/dist/surveys/components/SurveyModal.js 3.95 kB
packages/react-native/dist/surveys/components/Surveys.js 6.17 kB
packages/react-native/dist/surveys/getActiveMatchingSurveys.js 3.06 kB
packages/react-native/dist/surveys/icons.js 7.76 kB
packages/react-native/dist/surveys/index.js 600 B
packages/react-native/dist/surveys/PostHogSurveyProvider.js 5.61 kB
packages/react-native/dist/surveys/surveys-utils.js 5.59 kB
packages/react-native/dist/surveys/useActivatedSurveys.js 3.38 kB
packages/react-native/dist/surveys/useSurveyStorage.js 2.16 kB
packages/react-native/dist/types.js 70 B
packages/react-native/dist/version.js 129 B
packages/react/dist/esm/index.js 14.7 kB
packages/react/dist/umd/index.js 17.3 kB
packages/web/dist/index.cjs 13.8 kB
packages/web/dist/index.mjs 13.7 kB
tooling/rollup-utils/dist/index.js 1.17 kB

compressed-size-action

@github-project-automation github-project-automation bot moved this from In Review to Approved in Feature Flags Aug 6, 2025
@haacked haacked requested a review from Copilot August 6, 2025 19:49
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors the feature flag evaluation system in the Node.js package by consolidating two separate methods (computeFlagLocally and computeFeatureFlagPayloadLocally) into a single unified method that computes both flag values and payloads together.

  • Introduces a new computeFlagAndPayloadLocally method that handles both flag evaluation and payload computation
  • Updates client code to use the unified method for more consistent evaluation paths
  • Removes duplicate code paths that were previously causing confusion and maintenance issues

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
packages/node/src/extensions/feature-flags/feature-flags.ts Replaces separate flag and payload computation methods with unified approach, adds payload extraction logic
packages/node/src/client.ts Updates payload retrieval to use the new unified method instead of separate evaluation calls

Two separate methods for what is essentially the same operation is going to cause headaches down the line.

This refactors both `compute*Locally` methods into a single one.
@haacked haacked force-pushed the haacked/compute-locally-refactoring branch from 3e50a15 to 6ff7082 Compare August 6, 2025 19:50
Add explicit checks for null and undefined values in getFeatureFlagPayload
to prevent invalid payload lookups. This makes the logic more explicit
and matches the behavior of the original computeFeatureFlagPayloadLocally
method which only processed boolean and string values.
@haacked haacked merged commit da8458d into main Aug 6, 2025
26 checks passed
@haacked haacked deleted the haacked/compute-locally-refactoring branch August 6, 2025 20:47
@github-project-automation github-project-automation bot moved this from Approved to Done in Feature Flags Aug 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants