Skip to content

feat(node): add evaluateFlags() API for single-call flag evaluation#3476

Merged
dmarticus merged 8 commits into
mainfrom
posthog-code/node-evaluate-flags-api
May 1, 2026
Merged

feat(node): add evaluateFlags() API for single-call flag evaluation#3476
dmarticus merged 8 commits into
mainfrom
posthog-code/node-evaluate-flags-api

Conversation

@dmarticus

@dmarticus dmarticus commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Problem

Phase 1 + Phase 2 of the Server SDK Feature Flag Evaluations RFC for posthog-node. Companion to the Python SDK PR (PostHog/posthog-python#539).

Today every flag check fires its own /flags request, and capture({ sendFeatureFlags: true }) silently fires yet another on every captured event. The flag values on a captured event can diverge from the ones the code actually branched on when person/group properties differ between calls. sendFeatureFlags also attaches every evaluated flag to every event, which bloats properties on high-volume events.

Changes

New API (Phase 1)

posthog.evaluateFlags(distinctId, ...) returns a FeatureFlagEvaluations snapshot:

const flags = await posthog.evaluateFlags(distinctId, { personProperties: { plan: 'enterprise' } })
if (flags.isEnabled('new-dashboard')) {
  renderNewDashboard()
}
posthog.capture({ distinctId, event: 'page_viewed', flags })

A single /flags request powers both branching and event enrichment. isEnabled() and getFlag() fire $feature_flag_called events (deduped through the existing cache) with the full metadata — $feature_flag_id, $feature_flag_version, $feature_flag_reason, $feature_flag_request_id — so experiment exposure tracking keeps working.

Two layers of scoping

  • Network-level (flagKeys option): scopes the underlying /flags request itself.

    const flags = await posthog.evaluateFlags(distinctId, { flagKeys: ['new-dashboard', 'checkout-flow'] })
  • Event-level (filter helpers): narrow which flags get attached to a captured event without re-fetching.

    posthog.capture({ ..., flags: flags.onlyAccessed() })           // only flags the developer checked
    posthog.capture({ ..., flags: flags.only(['new-dashboard']) })  // specific keys

    onlyAccessed() honors its name — if nothing has been accessed, it returns an empty snapshot (no fallback to all flags). only([...]) warns and drops unknown keys; the warning is silenceable via the featureFlagsLogWarnings: false SDK option.

Slices are for capture, not branching

onlyAccessed() / only([...]) return filtered snapshots intended for capture(). Calling isEnabled() / getFlag() on a slice for a key that was filtered out is a no-op (no event fires) — the flag wasn't actually missing, it was excluded from the slice.

Granular $feature_flag_error reporting

Response-level errors (errors_while_computing_flags, quota_limited) are propagated into $feature_flag_called events from the snapshot. A missing flag during a quota-limited response now reports quota_limited,flag_missing instead of just flag_missing, matching the single-flag path's granularity.

Exception captures carry flag context

captureException() and captureExceptionImmediate() accept an optional flags argument so $exception events carry the same flag context as the rest of your request's events:

const flags = await posthog.evaluateFlags(distinctId)
try {
  riskyThing()
} catch (e) {
  posthog.captureException(e, distinctId, undefined, undefined, flags)
}

flags vs sendFeatureFlags precedence

When both are passed, flags always wins and we log a warning so the precedence isn't surprising:

[PostHog] Both flags and sendFeatureFlags were passed to capture(); using flags and ignoring sendFeatureFlags.

Deprecation warnings (Phase 2)

The legacy single-flag surface keeps working but now emits a deduped [PostHog] ... is deprecated console warning the first time it's used:

  • getFeatureFlag()
  • isFeatureEnabled()
  • getFeatureFlagPayload()
  • capture({ sendFeatureFlags }) (only when truthy)

isFeatureEnabled is restructured to call _getFeatureFlagResult directly instead of routing through getFeatureFlag, so a single user-level call emits exactly one warning instead of cascading two. The dedup is process-wide via emitDeprecationWarningOnce, matching Python's warnings.warn default-dedup behavior. Phase 3 (removal in next major) ships separately.

Local evaluation

Transparent. When the poller resolves a flag, the snapshot carries locally_evaluated: true and reason "Evaluated locally", matching what getFeatureFlag() emits today.

Backwards compatibility

No breaking changes. All existing call paths return the same values they did before — the only behavior changes are:

  1. The new deprecation console warnings (deduped per-process)
  2. onlyAccessed() no longer falls back to all flags when nothing was accessed (empty input → empty output)

Internals

_getFeatureFlagResult was refactored: the dedup + capture portion is extracted into _captureFlagCalledEventIfNeeded, which is shared between the single-flag path and the new FeatureFlagEvaluations object. Both paths now dedupe identically. evaluateFlags uses getFeatureFlagDetailsStateless (the rich-detail endpoint) rather than the bare values endpoint so the snapshot carries full per-flag metadata.

Tests

packages/node/src/__tests__/evaluate-flags.spec.ts — 32 tests covering remote evaluation, local evaluation, filtering helpers, capture integration, flagKeys round-trip, empty-distinctId safety, error-granularity propagation, deprecation warning emission (with no-cascade verification), and captureException/captureExceptionImmediate flag forwarding.

Full Node SDK suite: zero regressions on this branch (the same pre-existing failures from main remain). pnpm lint clean.


Created with PostHog Code

Introduce `posthog.evaluateFlags(distinctId, options)` returning a
`FeatureFlagEvaluations` snapshot. Branch on `isEnabled()` / `getFlag()`
and pass the snapshot to `capture()` via a new `flags` option so events
carry the exact values the code branched on, with no extra /flags
request per capture.

Filtering helpers `onlyAccessed()` and `only([keys])` let callers shrink
the flag set attached to events. A new `featureFlagsLogWarnings` option
toggles the associated user-facing warnings.

Existing `isFeatureEnabled` / `getFeatureFlag` / `sendFeatureFlags`
continue to work unchanged; `sendFeatureFlags` is marked deprecated in
JSDoc ahead of a future major-version removal.

Generated-By: PostHog Code
Task-Id: b8a45b11-b41c-4995-8622-acea525e7703
@vercel

vercel Bot commented Apr 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
posthog-example-next-app-router Ready Ready Preview May 1, 2026 8:46pm
posthog-js Ready Ready Preview May 1, 2026 8:46pm
posthog-nextjs-config Ready Ready Preview May 1, 2026 8:46pm

Request Review

@github-actions

github-actions Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Size Change: +28 kB (+0.4%)

Total Size: 7.11 MB

Filename Size Change
packages/node/dist/client.js 45.3 kB +8.55 kB (+23.26%) 🚨
packages/node/dist/client.mjs 43 kB +8.23 kB (+23.7%) 🚨
packages/node/dist/exports.js 4.78 kB +567 B (+13.45%) ⚠️
packages/node/dist/exports.mjs 300 B +97 B (+47.78%) 🚨
packages/node/dist/feature-flag-evaluations.js 5.97 kB +5.97 kB (new file) 🆕
packages/node/dist/feature-flag-evaluations.mjs 4.63 kB +4.63 kB (new file) 🆕
ℹ️ View Unchanged
Filename Size Change
packages/ai/dist/anthropic/index.cjs 21.3 kB 0 B
packages/ai/dist/anthropic/index.mjs 20.9 kB 0 B
packages/ai/dist/gemini/index.cjs 30.1 kB 0 B
packages/ai/dist/gemini/index.mjs 29.9 kB 0 B
packages/ai/dist/index.cjs 170 kB 0 B
packages/ai/dist/index.mjs 169 kB 0 B
packages/ai/dist/langchain/index.cjs 44.2 kB 0 B
packages/ai/dist/langchain/index.mjs 43.7 kB 0 B
packages/ai/dist/openai-agents/index.cjs 22.8 kB 0 B
packages/ai/dist/openai-agents/index.mjs 22.7 kB 0 B
packages/ai/dist/openai/index.cjs 47.9 kB 0 B
packages/ai/dist/openai/index.mjs 47.6 kB 0 B
packages/ai/dist/otel/index.cjs 4.97 kB 0 B
packages/ai/dist/otel/index.mjs 4.86 kB 0 B
packages/ai/dist/vercel/index.cjs 39.3 kB 0 B
packages/ai/dist/vercel/index.mjs 39.3 kB 0 B
packages/browser/dist/all-external-dependencies.js 272 kB 0 B
packages/browser/dist/array.full.es5.js 346 kB 0 B
packages/browser/dist/array.full.js 438 kB 0 B
packages/browser/dist/array.full.no-external.js 507 kB 0 B
packages/browser/dist/array.js 190 kB 0 B
packages/browser/dist/array.no-external.js 208 kB 0 B
packages/browser/dist/conversations.js 67.3 kB 0 B
packages/browser/dist/crisp-chat-integration.js 1.97 kB 0 B
packages/browser/dist/customizations.full.js 18 kB 0 B
packages/browser/dist/dead-clicks-autocapture.js 13.2 kB 0 B
packages/browser/dist/default-extensions.js 188 kB 0 B
packages/browser/dist/element-inference.js 5.69 kB 0 B
packages/browser/dist/exception-autocapture.js 11.8 kB 0 B
packages/browser/dist/extension-bundles.js 107 kB 0 B
packages/browser/dist/external-scripts-loader.js 3.13 kB 0 B
packages/browser/dist/intercom-integration.js 2.03 kB 0 B
packages/browser/dist/lazy-recorder.js 159 kB 0 B
packages/browser/dist/logs.js 38.5 kB 0 B
packages/browser/dist/main.js 195 kB 0 B
packages/browser/dist/module.full.js 441 kB 0 B
packages/browser/dist/module.full.no-external.js 510 kB 0 B
packages/browser/dist/module.js 194 kB 0 B
packages/browser/dist/module.no-external.js 212 kB 0 B
packages/browser/dist/module.slim.js 101 kB 0 B
packages/browser/dist/module.slim.no-external.js 106 kB 0 B
packages/browser/dist/posthog-recorder.js 145 kB 0 B
packages/browser/dist/product-tours-preview.js 76.5 kB 0 B
packages/browser/dist/product-tours.js 115 kB 0 B
packages/browser/dist/recorder-v2.js 112 kB 0 B
packages/browser/dist/recorder.js 112 kB 0 B
packages/browser/dist/surveys-preview.js 77.1 kB 0 B
packages/browser/dist/surveys.js 95.4 kB 0 B
packages/browser/dist/tracing-headers.js 1.74 kB 0 B
packages/browser/dist/web-vitals-with-attribution.js 11.8 kB 0 B
packages/browser/dist/web-vitals.js 6.39 kB 0 B
packages/browser/react/dist/esm/index.js 21.2 kB 0 B
packages/browser/react/dist/esm/slim/index.js 17.6 kB 0 B
packages/browser/react/dist/esm/surveys/index.js 4.68 kB 0 B
packages/browser/react/dist/umd/index.js 24.4 kB 0 B
packages/browser/react/dist/umd/slim/index.js 20.4 kB 0 B
packages/browser/react/dist/umd/surveys/index.js 5.45 kB 0 B
packages/convex/dist/client/index.js 7.96 kB 0 B
packages/convex/dist/component/_generated/api.js 712 B 0 B
packages/convex/dist/component/_generated/component.js 212 B 0 B
packages/convex/dist/component/_generated/dataModel.js 230 B 0 B
packages/convex/dist/component/_generated/server.js 3.71 kB 0 B
packages/convex/dist/component/convex.config.js 133 B 0 B
packages/convex/dist/component/lib.js 7.95 kB 0 B
packages/convex/dist/component/schema.js 113 B 0 B
packages/core/dist/error-tracking/chunk-ids.js 2.54 kB 0 B
packages/core/dist/error-tracking/chunk-ids.mjs 1.31 kB 0 B
packages/core/dist/error-tracking/coercers/dom-exception-coercer.js 2.3 kB 0 B
packages/core/dist/error-tracking/coercers/dom-exception-coercer.mjs 993 B 0 B
packages/core/dist/error-tracking/coercers/error-coercer.js 2.02 kB 0 B
packages/core/dist/error-tracking/coercers/error-coercer.mjs 794 B 0 B
packages/core/dist/error-tracking/coercers/error-event-coercer.js 1.76 kB 0 B
packages/core/dist/error-tracking/coercers/error-event-coercer.mjs 513 B 0 B
packages/core/dist/error-tracking/coercers/event-coercer.js 1.82 kB 0 B
packages/core/dist/error-tracking/coercers/event-coercer.mjs 548 B 0 B
packages/core/dist/error-tracking/coercers/index.js 6.79 kB 0 B
packages/core/dist/error-tracking/coercers/index.mjs 326 B 0 B
packages/core/dist/error-tracking/coercers/object-coercer.js 3.46 kB 0 B
packages/core/dist/error-tracking/coercers/object-coercer.mjs 2.07 kB 0 B
packages/core/dist/error-tracking/coercers/primitive-coercer.js 1.67 kB 0 B
packages/core/dist/error-tracking/coercers/primitive-coercer.mjs 419 B 0 B
packages/core/dist/error-tracking/coercers/promise-rejection-event.js 2.59 kB 0 B
packages/core/dist/error-tracking/coercers/promise-rejection-event.mjs 1.25 kB 0 B
packages/core/dist/error-tracking/coercers/string-coercer.js 2.01 kB 0 B
packages/core/dist/error-tracking/coercers/string-coercer.mjs 820 B 0 B
packages/core/dist/error-tracking/coercers/utils.js 2.06 kB 0 B
packages/core/dist/error-tracking/coercers/utils.mjs 716 B 0 B
packages/core/dist/error-tracking/error-properties-builder.js 5.56 kB 0 B
packages/core/dist/error-tracking/error-properties-builder.mjs 4.23 kB 0 B
packages/core/dist/error-tracking/exception-steps.js 6.87 kB 0 B
packages/core/dist/error-tracking/exception-steps.mjs 4.71 kB 0 B
packages/core/dist/error-tracking/index.js 4.74 kB 0 B
packages/core/dist/error-tracking/index.mjs 191 B 0 B
packages/core/dist/error-tracking/parsers/base.js 1.83 kB 0 B
packages/core/dist/error-tracking/parsers/base.mjs 464 B 0 B
packages/core/dist/error-tracking/parsers/chrome.js 2.73 kB 0 B
packages/core/dist/error-tracking/parsers/chrome.mjs 1.32 kB 0 B
packages/core/dist/error-tracking/parsers/gecko.js 2.47 kB 0 B
packages/core/dist/error-tracking/parsers/gecko.mjs 1.13 kB 0 B
packages/core/dist/error-tracking/parsers/index.js 4.75 kB 0 B
packages/core/dist/error-tracking/parsers/index.mjs 2.1 kB 0 B
packages/core/dist/error-tracking/parsers/node.js 3.94 kB 0 B
packages/core/dist/error-tracking/parsers/node.mjs 2.68 kB 0 B
packages/core/dist/error-tracking/parsers/opera.js 2.26 kB 0 B
packages/core/dist/error-tracking/parsers/opera.mjs 746 B 0 B
packages/core/dist/error-tracking/parsers/safari.js 1.88 kB 0 B
packages/core/dist/error-tracking/parsers/safari.mjs 574 B 0 B
packages/core/dist/error-tracking/parsers/winjs.js 1.72 kB 0 B
packages/core/dist/error-tracking/parsers/winjs.mjs 426 B 0 B
packages/core/dist/error-tracking/types.js 1.33 kB 0 B
packages/core/dist/error-tracking/types.mjs 131 B 0 B
packages/core/dist/error-tracking/utils.js 1.8 kB 0 B
packages/core/dist/error-tracking/utils.mjs 604 B 0 B
packages/core/dist/eventemitter.js 1.78 kB 0 B
packages/core/dist/eventemitter.mjs 571 B 0 B
packages/core/dist/featureFlagUtils.js 6.8 kB 0 B
packages/core/dist/featureFlagUtils.mjs 4.32 kB 0 B
packages/core/dist/gzip.js 2.74 kB 0 B
packages/core/dist/gzip.mjs 1.29 kB 0 B
packages/core/dist/index.js 11.3 kB 0 B
packages/core/dist/index.mjs 1.15 kB 0 B
packages/core/dist/logs/index.js 9.38 kB 0 B
packages/core/dist/logs/index.mjs 7.77 kB 0 B
packages/core/dist/logs/logs-utils.js 5.96 kB 0 B
packages/core/dist/logs/logs-utils.mjs 3.99 kB 0 B
packages/core/dist/logs/types.js 603 B 0 B
packages/core/dist/logs/types.mjs 0 B 0 B 🆕
packages/core/dist/posthog-core-stateless.js 33.1 kB 0 B
packages/core/dist/posthog-core-stateless.mjs 30.6 kB 0 B
packages/core/dist/posthog-core.js 41.9 kB 0 B
packages/core/dist/posthog-core.mjs 36.9 kB 0 B
packages/core/dist/surveys/events.js 4.21 kB 0 B
packages/core/dist/surveys/events.mjs 1.99 kB 0 B
packages/core/dist/surveys/index.js 4.57 kB 0 B
packages/core/dist/surveys/index.mjs 894 B 0 B
packages/core/dist/surveys/translations.js 9.42 kB 0 B
packages/core/dist/surveys/translations.mjs 7.03 kB 0 B
packages/core/dist/surveys/validation.js 3.06 kB 0 B
packages/core/dist/surveys/validation.mjs 1.51 kB 0 B
packages/core/dist/testing/index.js 2.93 kB 0 B
packages/core/dist/testing/index.mjs 79 B 0 B
packages/core/dist/testing/PostHogCoreTestClient.js 3.15 kB 0 B
packages/core/dist/testing/PostHogCoreTestClient.mjs 1.74 kB 0 B
packages/core/dist/testing/test-utils.js 2.83 kB 0 B
packages/core/dist/testing/test-utils.mjs 1.15 kB 0 B
packages/core/dist/tracing-headers.js 3.38 kB 0 B
packages/core/dist/tracing-headers.mjs 2.08 kB 0 B
packages/core/dist/types.js 9.62 kB 0 B
packages/core/dist/types.mjs 7.07 kB 0 B
packages/core/dist/utils/bot-detection.js 3.28 kB 0 B
packages/core/dist/utils/bot-detection.mjs 1.95 kB 0 B
packages/core/dist/utils/bucketed-rate-limiter.js 3 kB 0 B
packages/core/dist/utils/bucketed-rate-limiter.mjs 1.62 kB 0 B
packages/core/dist/utils/index.js 11.9 kB 0 B
packages/core/dist/utils/index.mjs 1.98 kB 0 B
packages/core/dist/utils/logger.js 2.58 kB 0 B
packages/core/dist/utils/logger.mjs 1.29 kB 0 B
packages/core/dist/utils/number-utils.js 3.32 kB 0 B
packages/core/dist/utils/number-utils.mjs 1.68 kB 0 B
packages/core/dist/utils/promise-queue.js 2 kB 0 B
packages/core/dist/utils/promise-queue.mjs 768 B 0 B
packages/core/dist/utils/string-utils.js 2.73 kB 0 B
packages/core/dist/utils/string-utils.mjs 1.09 kB 0 B
packages/core/dist/utils/type-utils.js 7.04 kB 0 B
packages/core/dist/utils/type-utils.mjs 3.11 kB 0 B
packages/core/dist/utils/user-agent-utils.js 15.2 kB 0 B
packages/core/dist/utils/user-agent-utils.mjs 12.2 kB 0 B
packages/core/dist/vendor/uuidv7.js 8.29 kB 0 B
packages/core/dist/vendor/uuidv7.mjs 6.72 kB 0 B
packages/next/dist/app/PostHogProvider.js 3.23 kB 0 B
packages/next/dist/client/ClientPostHogProvider.js 1.76 kB 0 B
packages/next/dist/client/hooks.js 172 B 0 B
packages/next/dist/client/PostHogPageView.js 1.7 kB 0 B
packages/next/dist/index.client.js 401 B 0 B
packages/next/dist/index.edge.js 447 B 0 B
packages/next/dist/index.js 444 B 0 B
packages/next/dist/index.react-server.js 420 B 0 B
packages/next/dist/middleware/postHogMiddleware.js 3.64 kB 0 B
packages/next/dist/pages.js 414 B 0 B
packages/next/dist/pages/getServerSidePostHog.js 1.93 kB 0 B
packages/next/dist/pages/PostHogPageView.js 1.2 kB 0 B
packages/next/dist/pages/PostHogProvider.js 1.51 kB 0 B
packages/next/dist/server/getPostHog.js 2.73 kB 0 B
packages/next/dist/server/nodeClientCache.js 1.31 kB 0 B
packages/next/dist/shared/config.js 2.06 kB 0 B
packages/next/dist/shared/constants.js 278 B 0 B
packages/next/dist/shared/cookie.js 4.49 kB 0 B
packages/next/dist/shared/identity.js 264 B 0 B
packages/next/dist/shared/tracing-headers.js 2.18 kB 0 B
packages/nextjs-config/dist/config.js 4.97 kB 0 B
packages/nextjs-config/dist/config.mjs 3.49 kB 0 B
packages/nextjs-config/dist/index.js 2.24 kB 0 B
packages/nextjs-config/dist/index.mjs 30 B 0 B
packages/nextjs-config/dist/utils.js 2.94 kB 0 B
packages/nextjs-config/dist/utils.mjs 826 B 0 B
packages/node/dist/entrypoints/index.edge.js 4.25 kB 0 B
packages/node/dist/entrypoints/index.edge.mjs 723 B 0 B
packages/node/dist/entrypoints/index.node.js 6.04 kB 0 B
packages/node/dist/entrypoints/index.node.mjs 1.22 kB 0 B
packages/node/dist/entrypoints/nestjs.js 2.31 kB 0 B
packages/node/dist/entrypoints/nestjs.mjs 42 B 0 B
packages/node/dist/experimental.js 603 B 0 B
packages/node/dist/experimental.mjs 0 B 0 B 🆕
packages/node/dist/extensions/context/context.js 2.13 kB 0 B
packages/node/dist/extensions/context/context.mjs 863 B 0 B
packages/node/dist/extensions/context/types.js 603 B 0 B
packages/node/dist/extensions/context/types.mjs 0 B 0 B 🆕
packages/node/dist/extensions/error-tracking/autocapture.js 2.66 kB 0 B
packages/node/dist/extensions/error-tracking/autocapture.mjs 1.24 kB 0 B
packages/node/dist/extensions/error-tracking/index.js 4.14 kB 0 B
packages/node/dist/extensions/error-tracking/index.mjs 2.87 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/context-lines.node.js 8.81 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/context-lines.node.mjs 7.15 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/module.node.js 2.78 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/module.node.mjs 1.45 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/relative-path.node.js 1.97 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/relative-path.node.mjs 624 B 0 B
packages/node/dist/extensions/express.js 4.56 kB 0 B
packages/node/dist/extensions/express.mjs 2.45 kB 0 B
packages/node/dist/extensions/feature-flags/cache.js 603 B 0 B
packages/node/dist/extensions/feature-flags/cache.mjs 0 B 0 B 🆕
packages/node/dist/extensions/feature-flags/crypto.js 1.57 kB 0 B
packages/node/dist/extensions/feature-flags/crypto.mjs 395 B 0 B
packages/node/dist/extensions/feature-flags/feature-flags.js 40.1 kB 0 B
packages/node/dist/extensions/feature-flags/feature-flags.mjs 38 kB 0 B
packages/node/dist/extensions/nestjs.js 5 kB 0 B
packages/node/dist/extensions/nestjs.mjs 2.9 kB 0 B
packages/node/dist/extensions/sentry-integration.js 4.66 kB 0 B
packages/node/dist/extensions/sentry-integration.mjs 3.17 kB 0 B
packages/node/dist/extensions/tracing-headers.js 3.31 kB 0 B
packages/node/dist/extensions/tracing-headers.mjs 1.53 kB 0 B
packages/node/dist/storage-memory.js 1.52 kB 0 B
packages/node/dist/storage-memory.mjs 297 B 0 B
packages/node/dist/types.js 1.43 kB 0 B
packages/node/dist/types.mjs 224 B 0 B
packages/node/dist/version.js 1.21 kB 0 B
packages/node/dist/version.mjs 46 B 0 B
packages/nuxt/dist/module.mjs 5.29 kB 0 B
packages/nuxt/dist/runtime/composables/useFeatureFlagEnabled.js 566 B 0 B
packages/nuxt/dist/runtime/composables/useFeatureFlagPayload.js 690 B 0 B
packages/nuxt/dist/runtime/composables/useFeatureFlagVariantKey.js 591 B 0 B
packages/nuxt/dist/runtime/composables/usePostHog.js 128 B 0 B
packages/nuxt/dist/runtime/nitro-plugin.js 1.08 kB 0 B
packages/nuxt/dist/runtime/vue-plugin.js 1.14 kB 0 B
packages/plugin-utils/dist/cli.js 3.14 kB 0 B
packages/plugin-utils/dist/cli.mjs 1.64 kB 0 B
packages/plugin-utils/dist/config.js 3.07 kB 0 B
packages/plugin-utils/dist/config.mjs 1.83 kB 0 B
packages/plugin-utils/dist/index.js 4.3 kB 0 B
packages/plugin-utils/dist/index.mjs 217 B 0 B
packages/plugin-utils/dist/spawn-local.js 2.17 kB 0 B
packages/plugin-utils/dist/spawn-local.mjs 918 B 0 B
packages/plugin-utils/dist/utils.js 3.27 kB 0 B
packages/plugin-utils/dist/utils.mjs 1.3 kB 0 B
packages/react-native/dist/autocapture.js 5.05 kB 0 B
packages/react-native/dist/error-tracking/index.js 7.24 kB 0 B
packages/react-native/dist/error-tracking/utils.js 2.58 kB 0 B
packages/react-native/dist/frameworks/wix-navigation.js 1.3 kB 0 B
packages/react-native/dist/hooks/useFeatureFlag.js 1.7 kB 0 B
packages/react-native/dist/hooks/useFeatureFlagResult.js 963 B 0 B
packages/react-native/dist/hooks/useFeatureFlags.js 921 B 0 B
packages/react-native/dist/hooks/useNavigationTracker.js 2.45 kB 0 B
packages/react-native/dist/hooks/usePostHog.js 544 B 0 B
packages/react-native/dist/hooks/utils.js 988 B 0 B
packages/react-native/dist/index.js 4.33 kB 0 B
packages/react-native/dist/logs-defaults.js 3.32 kB 0 B
packages/react-native/dist/native-deps.js 8.77 kB 0 B
packages/react-native/dist/optional/OptionalAsyncStorage.js 299 B 0 B
packages/react-native/dist/optional/OptionalExpoApplication.js 377 B 0 B
packages/react-native/dist/optional/OptionalExpoDevice.js 347 B 0 B
packages/react-native/dist/optional/OptionalExpoFileSystem.js 386 B 0 B
packages/react-native/dist/optional/OptionalExpoFileSystemLegacy.js 423 B 0 B
packages/react-native/dist/optional/OptionalExpoLocalization.js 383 B 0 B
packages/react-native/dist/optional/OptionalReactNativeDeviceInfo.js 415 B 0 B
packages/react-native/dist/optional/OptionalReactNativeLocalize.js 303 B 0 B
packages/react-native/dist/optional/OptionalReactNativeNavigation.js 415 B 0 B
packages/react-native/dist/optional/OptionalReactNativeNavigationWix.js 443 B 0 B
packages/react-native/dist/optional/OptionalReactNativeSafeArea.js 644 B 0 B
packages/react-native/dist/optional/OptionalReactNativeSvg.js 872 B 0 B
packages/react-native/dist/optional/OptionalSessionReplay.js 455 B 0 B
packages/react-native/dist/posthog-rn.js 45.6 kB 0 B
packages/react-native/dist/PostHogContext.js 329 B 0 B
packages/react-native/dist/PostHogErrorBoundary.js 3.19 kB 0 B
packages/react-native/dist/PostHogMaskView.js 1.68 kB 0 B
packages/react-native/dist/PostHogProvider.js 4.76 kB 0 B
packages/react-native/dist/storage.js 5.2 kB 0 B
packages/react-native/dist/surveys/components/BottomSection.js 1.46 kB 0 B
packages/react-native/dist/surveys/components/Cancel.js 909 B 0 B
packages/react-native/dist/surveys/components/ConfirmationMessage.js 1.65 kB 0 B
packages/react-native/dist/surveys/components/QuestionHeader.js 1.37 kB 0 B
packages/react-native/dist/surveys/components/QuestionTypes.js 13.3 kB 0 B
packages/react-native/dist/surveys/components/SurveyModal.js 5.47 kB 0 B
packages/react-native/dist/surveys/components/Surveys.js 6.58 kB 0 B
packages/react-native/dist/surveys/getActiveMatchingSurveys.js 2.64 kB 0 B
packages/react-native/dist/surveys/icons.js 9.97 kB 0 B
packages/react-native/dist/surveys/index.js 600 B 0 B
packages/react-native/dist/surveys/PostHogSurveyProvider.js 6.28 kB 0 B
packages/react-native/dist/surveys/survey-translations.js 942 B 0 B
packages/react-native/dist/surveys/surveys-utils.js 14.2 kB 0 B
packages/react-native/dist/surveys/useActivatedSurveys.js 3.67 kB 0 B
packages/react-native/dist/surveys/useSurveyStorage.js 2.16 kB 0 B
packages/react-native/dist/tooling/expoconfig.js 4.02 kB 0 B
packages/react-native/dist/tooling/metroconfig.js 2.32 kB 0 B
packages/react-native/dist/tooling/posthogMetroSerializer.js 4.86 kB 0 B
packages/react-native/dist/tooling/utils.js 4.05 kB 0 B
packages/react-native/dist/tooling/vendor/expo/expoconfig.js 70 B 0 B
packages/react-native/dist/tooling/vendor/metro/countLines.js 237 B 0 B
packages/react-native/dist/tooling/vendor/metro/utils.js 3.35 kB 0 B
packages/react-native/dist/types.js 70 B 0 B
packages/react-native/dist/utils.js 1.14 kB 0 B
packages/react-native/dist/version.js 130 B 0 B
packages/react/dist/esm/index.js 21.2 kB 0 B
packages/react/dist/esm/slim/index.js 17.6 kB 0 B
packages/react/dist/esm/surveys/index.js 4.68 kB 0 B
packages/react/dist/umd/index.js 24.4 kB 0 B
packages/react/dist/umd/slim/index.js 20.4 kB 0 B
packages/react/dist/umd/surveys/index.js 5.45 kB 0 B
packages/rollup-plugin/dist/index.js 2.11 kB 0 B
packages/types/dist/capture-log.js 603 B 0 B
packages/types/dist/capture-log.mjs 0 B 0 B 🆕
packages/types/dist/capture.js 603 B 0 B
packages/types/dist/capture.mjs 0 B 0 B 🆕
packages/types/dist/common.js 603 B 0 B
packages/types/dist/common.mjs 0 B 0 B 🆕
packages/types/dist/feature-flags.js 603 B 0 B
packages/types/dist/feature-flags.mjs 0 B 0 B 🆕
packages/types/dist/index.js 603 B 0 B
packages/types/dist/index.mjs 0 B 0 B 🆕
packages/types/dist/posthog-config.js 603 B 0 B
packages/types/dist/posthog-config.mjs 0 B 0 B 🆕
packages/types/dist/posthog.js 603 B 0 B
packages/types/dist/posthog.mjs 0 B 0 B 🆕
packages/types/dist/request.js 603 B 0 B
packages/types/dist/request.mjs 0 B 0 B 🆕
packages/types/dist/segment.js 603 B 0 B
packages/types/dist/segment.mjs 0 B 0 B 🆕
packages/types/dist/session-recording.js 603 B 0 B
packages/types/dist/session-recording.mjs 0 B 0 B 🆕
packages/types/dist/survey.js 603 B 0 B
packages/types/dist/survey.mjs 0 B 0 B 🆕
packages/types/dist/toolbar.js 603 B 0 B
packages/types/dist/toolbar.mjs 0 B 0 B 🆕
packages/types/dist/tree-shakeable.js 603 B 0 B
packages/types/dist/tree-shakeable.mjs 0 B 0 B 🆕
packages/web/dist/index.cjs 13.8 kB 0 B
packages/web/dist/index.mjs 13.7 kB 0 B
packages/webpack-plugin/dist/config.js 1.53 kB 0 B
packages/webpack-plugin/dist/config.mjs 543 B 0 B
packages/webpack-plugin/dist/index.js 5.38 kB 0 B
packages/webpack-plugin/dist/index.mjs 2.04 kB 0 B
tooling/changelog/dist/index.js 3.31 kB 0 B
tooling/rollup-utils/dist/index.js 1.17 kB 0 B

compressed-size-action

Allow callers to scope the underlying /flags request to a subset of
flags. The chained `flags.only([...])` filter still exists for
event-attachment scoping after evaluation; `flagKeys` reduces the
network payload itself.

Generated-By: PostHog Code
Task-Id: b8a45b11-b41c-4995-8622-acea525e7703
…examples

Generated-By: PostHog Code
Task-Id: b8a45b11-b41c-4995-8622-acea525e7703
…called events

- Plumb $feature_flag_definitions_loaded_at into the snapshot at
  construction so locally-evaluated flag access via the new API emits
  the same event schema as the existing single-flag path.
- Short-circuit $feature_flag_called emission when the snapshot has
  no resolvable distinctId, so the safety-fallback empty snapshot
  doesn't leak events with empty distinct_id values.
- Demote the shared dedup helper from public to protected; the only
  external caller is a closure with `this`-scoped access.
- Document the onlyAccessed() empty-fallback behavior and clarify that
  the local-evaluation flag definition has no version field.

Generated-By: PostHog Code
Task-Id: b8a45b11-b41c-4995-8622-acea525e7703
@greptile-apps

greptile-apps Bot commented Apr 27, 2026

Copy link
Copy Markdown
Contributor
Prompt To Fix All With AI
This is a comment left during a code review.
Path: packages/node/src/feature-flag-evaluations.ts
Line: 248-260

Comment:
**Filtered snapshot branching fires misleading `flag_missing` events**

When `_recordAccess` is called on a filtered clone (returned by `onlyAccessed()` or `only()`) for a key that was excluded from the filter but actually exists in the original snapshot, `this._flags[key]` is `undefined` here — triggering the `$feature_flag_error: 'flag_missing'` path even though the flag was fully evaluated. This pollutes the analytics stream with spurious error events.

The test at line 341 of `evaluate-flags.spec.ts` exercises exactly this path (`filtered.isEnabled('variant-flag')` on a clone that only holds `boolean-flag`) but doesn't assert on the resulting events, so the misleading capture goes undetected.

Filtered views are intended for `capture()`, not for further branching. Consider guarding this in one of two ways: either document it explicitly and add an assertion in the test, or short-circuit `_recordAccess` when the key is absent from `_flags` on a filtered clone (e.g. by tracking whether the instance is a slice).

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: packages/node/src/__tests__/evaluate-flags.spec.ts
Line: 100-113

Comment:
**Repeated PostHog initialisation violates OnceAndOnlyOnce**

The pattern

```ts
posthog = new PostHog('TEST_API_KEY', {
  host: 'http://example.com',
  ...posthogImmediateResolveOptions,
})
```

appears verbatim in eight tests inside the `remote evaluation` describe block. Similarly, the `captures: any[]` + `posthog.on('capture', …)` setup repeats in four of them. A shared `beforeEach` for the common case would remove the duplication and make per-test deviations (e.g. `featureFlagsLogWarnings: false`, `personalApiKey`) stand out clearly.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(node): close parity gaps on FeatureF..." | Re-trigger Greptile

Comment thread packages/node/src/feature-flag-evaluations.ts
Comment thread packages/node/src/__tests__/evaluate-flags.spec.ts Outdated
…tions slices

Address review feedback on PR #3476:

- Filtered snapshots from `only()` / `onlyAccessed()` no longer fire
  misleading `$feature_flag_called` events with `flag_missing` when
  branching on a key that was excluded from the slice. The slice tracks
  whether it's a filtered view via an `_isSlice` flag and short-circuits
  `_recordAccess` for absent keys. Document this behavior on the filter
  helpers' JSDoc — slices are intended for `capture()`, not branching.
  Add a regression test covering the path.

- Refactor `evaluate-flags.spec.ts` to extract a `setup(overrides)`
  helper used by all suites, replacing eight repeated `new PostHog(...)`
  blocks plus four duplicated capture-listener setups. Per-test
  deviations (`featureFlagsLogWarnings: false`, `personalApiKey: ...`)
  now stand out as explicit overrides.

Generated-By: PostHog Code
Task-Id: b8a45b11-b41c-4995-8622-acea525e7703
…ularity, captureException flags)

Mirrors fixes from PostHog/posthog-python#539:

- `onlyAccessed()` returns empty when nothing has been accessed (no
  fallback to all flags). The previous fallback contradicted the method
  name and surprised reviewers.
- Propagate response-level errors (`errors_while_computing_flags`,
  `quota_limited`) into `$feature_flag_called` events so each access
  carries the granular error code(s) the single-flag path emits.
- Make `flags` vs `sendFeatureFlags` precedence explicit on `capture()`:
  `flags` always wins, and we log a warning when both are passed.
- Phase 2 deprecation warnings: `getFeatureFlag`, `isFeatureEnabled`,
  `getFeatureFlagPayload`, and `capture({ sendFeatureFlags })` now log a
  deduped `[PostHog] ... is deprecated` console warning the first time
  they're used. `isFeatureEnabled` is restructured to call
  `_getFeatureFlagResult` directly so a single user-level call emits
  exactly one warning instead of cascading.
- `captureException` and `captureExceptionImmediate` accept an optional
  `flags` snapshot so `$exception` events carry the same flag context
  as the rest of the request's events.

Adds a process-wide dedup helper `emitDeprecationWarningOnce` matching
Python's `warnings.warn` default-dedup behavior.

Generated-By: PostHog Code
Task-Id: b8a45b11-b41c-4995-8622-acea525e7703
dmarticus added a commit to PostHog/posthog-dotnet that referenced this pull request May 1, 2026
)

* feat: add EvaluateFlagsAsync() API for single-call flag evaluation

Adds a new EvaluateFlagsAsync(distinctId, options) method on the client
that returns a FeatureFlagEvaluations snapshot. The snapshot powers
IsEnabled / GetFlag / GetFlagPayload calls, fires $feature_flag_called
lazily (deduped against the existing per-distinct-id cache), and can be
forwarded to a new Capture(..., flags: snapshot) overload to attach
$feature/<key> and $active_feature_flags to events without a second
/flags request. Mirrors PostHog/posthog-js#3476 and PostHog/posthog-python#539.

Also fixes a long-standing bug where the legacy single-flag path
hard-coded locally_evaluated=false on every $feature_flag_called event.
Locally-evaluated flags now correctly carry locally_evaluated=true,
$feature_flag_reason="Evaluated locally", and a new
$feature_flag_definitions_loaded_at timestamp surfaced via
LocalFeatureFlagsLoader.

The existing IsFeatureEnabledAsync / GetFeatureFlagAsync /
Capture(..., sendFeatureFlags, ...) APIs are unchanged in this PR; a
follow-up minor will mark them deprecated in favor of the snapshot API.

Generated-By: PostHog Code
Task-Id: 494d1c64-1b39-421a-9317-7ccd5992aa40

* review: thread-safety, drop dead reason, parameterize tests, parse JSON

- FeatureFlagEvaluations._accessed: HashSet<string> -> ConcurrentDictionary<string, byte>
  so callers may share a snapshot across parallel branches without corrupting it.
- ToRecord: leave EvaluatedFlagRecord.Reason null for locally-evaluated flags;
  the "Evaluated locally" string is hardcoded inside BuildFeatureFlagCalledProperties
  and the host gates record.Reason with !LocallyEvaluated, so it was unread.
- Collapse IsEnabledReturnsFalseForUnknownKey + GetFlagReturnsNullForUnknownKey
  into a parameterized [Theory] over the accessor under test.
- Replace the brittle substring match on $active_feature_flags with a parsed,
  order-independent comparison; Dictionary iteration order isn't a guarantee.

Generated-By: PostHog Code
Task-Id: 494d1c64-1b39-421a-9317-7ccd5992aa40

* review: DIMs, dedup fast-path, perf, coverage gaps

Address PR feedback:

- IPostHogClient: add default interface implementations for the new Capture(flags:),
  CaptureException(flags:), and EvaluateFlagsAsync members so external implementers
  don't see a source break. Conditionally compiled — DIMs only on netstandard2.1+
  (the runtime requirement); netstandard2.0 keeps abstract members.
- FeatureFlagEvaluations.RecordAccess: early-return on repeat access, dropping
  per-call dedup-cache lookups + property allocation when a key has already been
  seen by this snapshot. Cross-snapshot dedup still flows through the MemoryCache.
- AddFeatureFlagsToCapturedEvent (snapshot path): single-pass enumeration over
  Records, skip the LINQ Where/Select/ToArray for $active_feature_flags.
- FeatureFlagEvaluations._records: tighten field type to Dictionary so Keys is a
  clean expression-bodied getter (no IReadOnlyDictionary cast).
- FeatureFlagEvaluations.Only(...): lazy missing-keys list — no allocation when
  every requested key is present.
- EvaluationsHost: drop the redundant id/version/reason copy block — the values
  it would write are already populated by BuildFeatureFlagCalledProperties via
  the FeatureFlagWithMetadata pattern match.
- EvaluatedFlagRecord: remove the now-unused Id/Version/Reason fields. The
  property dict is built from record.Flag (typed as FeatureFlagWithMetadata when
  present) rather than from duplicated record-level state.
- EvaluateFlagsAsync: local-pass quota_limited preserves locally-evaluated
  records and surfaces FeatureFlagError.QuotaLimited (matches remote-pass
  behavior); previously it discarded local results entirely. Add a comment on
  the local-wins merge clarifying the divergence from GetAllFeatureFlagsAsync.
- IPostHogClient.EvaluateFlagsAsync: <remarks> contrasting FlagKeysToEvaluate
  (request-body scoping) with FeatureFlagEvaluations.Only(...) (in-memory).
- IFeatureFlagEvaluationsHost.TryCaptureFeatureFlagCalledEventIfNeeded ->
  CaptureFeatureFlagCalled (no return value, no try semantics).

Tests added:
- MixedLocalAndRemoteEvaluationMergesRecordsAndTagsSourceCorrectly: pins the
  local-wins merge with locally_evaluated tagged correctly per source.
- UnknownKeyAccessAppendsFlagMissingErrorOnFeatureFlagCalled: pins the
  $feature_flag_error wiring through to the emitted event.
- CaptureExceptionAttachesFeatureFlagsFromSnapshot: pins the new
  CaptureException(flags:) overload so a CaptureExceptionCore wiring mistake
  would be caught.

Generated-By: PostHog Code
Task-Id: 494d1c64-1b39-421a-9317-7ccd5992aa40

* chore: deprecate single-flag and sendFeatureFlags APIs

Mark the four legacy paths replaced by EvaluateFlagsAsync + snapshot
[Obsolete(error: false)] so users see migration guidance the moment they
update the package:

- IPostHogClient.IsFeatureEnabledAsync / .GetFeatureFlagAsync
- IPostHogClient.Capture(..., bool sendFeatureFlags, ...)
- IPostHogClient.CaptureException(..., bool sendFeatureFlags, ...)

Cascade [Obsolete] to wrapper extensions:

- FeatureFlagExtensions: 5 IsFeatureEnabledAsync + 5 GetFeatureFlagAsync overloads
- CaptureExtensions: bool-sendFeatureFlags overloads of Capture / CapturePageView /
  CaptureScreenView
- CaptureExceptionExtensions: bool-sendFeatureFlags overloads

Each extension delegates internally; suppress CS0618 inside the body so the
warning surfaces at the user call site, not at the SDK call into itself.

Internal call sites that always passed sendFeatureFlags: false migrate to the
new Capture(..., flags: null, ...) overload — no behavioral change, but stops
the SDK from internally calling its own deprecated path.

Tests and samples that intentionally exercise the deprecated surface get a
file-level #pragma warning disable CS0618. The new
FeatureFlagEvaluationsTests cross-path dedup test wraps a single
IsFeatureEnabledAsync call in a per-call pragma so the rest of the file still
catches accidental new uses.

PostHog.AI's OpenAI handler keeps the legacy Capture(..., sendFeatureFlags:
false, ...) call with a #pragma + TODO; its tests assert the legacy mock
shape and migrating them is its own change.

PostHog.AspNetCore's PostHogVariantFeatureManager suppresses with a #pragma +
TODO; the FeatureManager API is per-flag so a snapshot rewrite is non-trivial.

All 781 unit tests, 26 AspNetCore tests, and 19 AI tests pass.

Generated-By: PostHog Code
Task-Id: 494d1c64-1b39-421a-9317-7ccd5992aa40

* review: fix CI, propagate cancellation, tighten Records, polish comments

- sdk_compliance_adapter Program.cs: switch the lone Capture(..., sendFeatureFlags: false, ...)
  call to the new flags: null overload so the Docker publish in the
  SDK-compliance CI job no longer hits CS0618 → exit 1.
- EvaluateFlagsAsync: exclude OperationCanceledException from the catch-all so
  cancellation propagates instead of being logged as UnknownError. Matches
  GetFeatureFlagAsync's filter.
- FeatureFlagEvaluations.Records: typed as IReadOnlyDictionary so the one
  consumer (PostHogClient.AddFeatureFlagsToCapturedEvent) can iterate but
  cannot mutate the snapshot's underlying state.
- Local-quota comment in EvaluateFlagsAsync: clarify that `records` is always
  empty when the catch fires (the throwing call is the first inside the try).
- Capture / CaptureException / DIM bodies: name every trailing argument
  (timestamp:, flags:) so non-trailing-named-argument call sites don't
  trip future IDE/bot warnings even though the C# 7.2+ rules accept them.
- FeatureFlagEvaluationsTests: drop the unused
  Microsoft.Extensions.Options using directive.

Generated-By: PostHog Code
Task-Id: 494d1c64-1b39-421a-9317-7ccd5992aa40

* chore: drop stray BOM after pragma in FeatureFlagExtensionsTests

Generated-By: PostHog Code

Task-Id: 494d1c64-1b39-421a-9317-7ccd5992aa40

* chore: revert manual version bump; release workflow handles it

RELEASING.md confirms the auto-release workflow bumps Directory.Build.props on merge based on the bump-* PR label, so leaving 2.6.0 in source would cause it to compound (e.g. to 2.7.0 after bump-minor). Restore to main's 2.5.0.

Generated-By: PostHog Code

Task-Id: 494d1c64-1b39-421a-9317-7ccd5992aa40

@dustinbyrne dustinbyrne left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nice

Comment on lines +237 to +249
/**
* @internal
*/
_getDistinctId(): string {
return this._distinctId
}

/**
* @internal
*/
_getGroups(): Record<string, string | number> | undefined {
return this._groups
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

unused public methods

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch — dropped both _getDistinctId() / _getGroups() in 67b3a02. Verified no callers across the repo before removing.

Comment on lines 1118 to 1124
* @param key - The feature flag key
* @param distinctId - The user's distinct ID
* @param matchValue - Optional match value to get payload for
* @param options - Optional configuration for flag evaluation
* @returns Promise that resolves to the flag payload or undefined
*/
async getFeatureFlagPayload(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We should JSDoc @deprecated these too

agent visibility and all

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 67b3a02 — added JSDoc @deprecated tags to getFeatureFlag, isFeatureEnabled, and getFeatureFlagPayload on both the PostHogBackendClient impl (client.ts) and the IPostHog interface (types.ts). The runtime console.warn we already had handles users running code; the JSDoc tag adds IDE strike-through + agent-tooling visibility so code agents reading the public surface see the deprecation immediately, before any call is even made.

…ated tags

Per dustin's feedback on PR #3476:

- Remove unused public `_getDistinctId()` / `_getGroups()` methods on
  `FeatureFlagEvaluations`. They had no callers (verified via grep
  across the repo) and don't need to ship as part of the public surface.
- Add JSDoc `@deprecated` tags to `getFeatureFlag`, `isFeatureEnabled`,
  and `getFeatureFlagPayload` on both the `PostHogBackendClient` impl
  (client.ts) and the `IPostHog` interface (types.ts). The runtime
  `console.warn` was already in place; the JSDoc tag adds IDE strike-
  through and agent-tooling visibility — code agents reading the public
  surface will see the deprecation immediately rather than waiting for
  a runtime call.

Generated-By: PostHog Code
Task-Id: b8a45b11-b41c-4995-8622-acea525e7703
@dmarticus dmarticus enabled auto-merge (squash) May 1, 2026 20:38
@dmarticus dmarticus merged commit f8bc02f into main May 1, 2026
46 checks passed
@dmarticus dmarticus deleted the posthog-code/node-evaluate-flags-api branch May 1, 2026 20:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants