Skip to content

feat(node-sdk): adopt collection values and Boolean-first reads - #790

Open
roncohen wants to merge 15 commits into
mainfrom
feature/node-sdk-v2
Open

roncohen wants to merge 15 commits into
mainfrom
feature/node-sdk-v2

Conversation

@roncohen

@roncohen roncohen commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Breaking Node SDK v2, using #744's complete-collection evaluator. #744 has merged; this PR now targets main. Companion server protocol/check ingestion: https://github.com/reflagcom/web/pull/3660.

reflag.getFlag(context, "release"); // boolean, implicit false
reflag.getFlag(context, "settings", { model: "Swift" }); // { model: string }
reflag.bindClient(context).getFlag("release");
  • Consume and atomically prepare complete protocol-v2 { flags, segments } snapshots. Evaluate only requested roots/dependencies, without dependency-result caching.
  • Return direct values with Boolean-first reads and positional defaults, preserving valid falsy values. Runtime non-null defaults enforce top-level JSON categories, not nested selected-value schemas. Explicit null accepts arbitrary/nullable JSON.
  • Register requested-root checks immediately with buffered, identity-aware delivery. Dependencies, diagnostic reads and bootstrap serialization do not emit extra checks.
  • Persist isolated v2 fallback snapshots, retain known-good state and serialize live saves. Preserve synchronization modes, context binding, ordinary usage tracking and post-evaluation overrides.
  • Keep the existing OpenFeature provider and React bootstrap demo explicitly pinned to published Node SDK v1 until their separate migrations. Node has no Suspense behavior or reserved payload fields.

Registered-default follow-up

  • 3cc369b checks non-null defaults against their registered key's value schema for root, bound, local and remote singular getters. Named-interface and readonly defaults work without dictionary index signatures.
  • Bare/explicit-undefined reads still return Boolean. Explicit null still requests arbitrary JSON. Singular results still infer and widen from the supplied default rather than switching to the registered schema. Runtime JSON validation/copying and top-level category checking are unchanged; registration does not add nested selected-value validation.
  • Add augmented/unaugmented compiler regressions, preserve generic forwarding, and keep arbitrary-JSON registrations opaque to avoid recursive-instantiation failures.
  • 595758d declares the readonly mapper and existing log-level constant intentionally private in package-scoped TypeDoc configuration, without adding public exports or disabling export validation globally. It also makes the existing docs anchor-processing condition POSIX-shell compatible.
  • feat: adopt v2 flag values in Browser, React and Vue SDKs #791 inherits these exact Node commits; there is no second Node implementation. CLI 2 generation remains a separate, uncommitted follow-up.

Breaking changes

  • Remove flag wrappers: .value, .isEnabled, .config, and flag .track(). Client tracking remains separate.
  • Bare singular reads are Boolean with implicit false; supply positional defaults for other types. Batch APIs retain raw JSON/undefined records.
  • Remote signature: getFlagRemote(key, defaultValue, userId?, companyId?, context?). Use undefined for a Boolean read with explicit IDs.
  • V1 fallback/browser bootstrap formats and legacy CLI wrapper declarations are incompatible with v2.

Verification for this follow-up

  • Clean detached Node checkout: 219 runtime tests, both compiler-contract programs, immutable install and Node/evaluator builds passed.
  • Final Node commit: documentation build passed after building its Browser/React/Vue dependencies.
  • Clean feat: adopt v2 flag values in Browser, React and Vue SDKs #791 checkout containing the inherited Node commits: 466 tests across Node, Browser, React, Vue and the v1-isolated OpenFeature providers; all SDK compiler programs and both Next.js example typechecks passed.
  • The separate CLI-v2 generator successfully compiled Node/React/Vue consumers against those actual built SDK declarations, including expected failures for invalid defaults and wrapper access. That generator is not included in this PR.
  • Scoped lint/format, whitespace checks and normal commit hooks passed. Full Management-generator workspace build and browser E2E were not rerun for this typing delta.

Integration and release boundaries

  • Both SDK PRs still conflict with current main; main/evaluator reconciliation remains outstanding. This update does not claim merge readiness or green remote CI.
  • Pre-existing matched-rule patches and the machine-specific LAN demo remain untouched and uncommitted outside this PR.
  • No main merge, package publication, deployment or saved-snapshot rebuild is included. Compatible server readers/check ingestion, approved snapshot rebuilds, packed-artifact acceptance and final release CI remain gates. The evaluator's stable 2.0.0 release is already published and must not be republished from the old prerelease plan.

Copilot AI balanced review requested due to automatic review settings November 4, 2026 08:18

Copilot AI 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.

🟡 Changes recommended

Valid fractional allocations are rejected, potentially blocking all flag refreshes, while bound clients lose context synchronization and can drop company associations from events.

3 open issues
What changed in this PR

Migrates the Node SDK to the collection evaluator introduced in #744, adding a breaking v2 direct-value API while keeping existing OpenFeature and React bootstrap consumers on published v1.

Changes:

  • Introduces Boolean-first reads, positional defaults, and immediate, identity-aware check registration.
  • Validates complete flag/segment collections and persists isolated v2 fallback snapshots with ordered saves.
  • Updates documentation, type contracts, tests, and the Express example; pins unmigrated consumers to v1.
File Description
yarn.lock Resolves the v2 evaluator and published v1 SDK alias.
packages/​react-sdk/​dev/​nextjs-bootstrap-demo/​package.json Pins the demo to published Node SDK v1.
packages/​react-sdk/​dev/​nextjs-bootstrap-demo/​app/​client.ts Imports the v1 SDK alias.
packages/​openfeature-node-provider/​src/​index.ts Uses the v1 SDK alias.
packages/​openfeature-node-provider/​src/​index.test.ts Updates imports and mocks for the alias.
packages/​openfeature-node-provider/​package.json Pins the provider to published Node SDK v1.
packages/​node-sdk/​type-tests/​defaults.ts Tests default-based inference without declarations.
packages/​node-sdk/​type-tests/​augmented-defaults.ts Tests augmented keys and Boolean-first contracts.
packages/​node-sdk/​tsconfig.type-tests.json Isolates unaugmented type-contract checks.
packages/​node-sdk/​tsconfig.type-tests-augmented.json Isolates augmented type-contract checks.
packages/​node-sdk/​tsconfig.test.json Configures SDK and selected test typechecking.
packages/​node-sdk/​test/​flagsFallbackProvider.test.ts Covers v2 snapshots and storage namespaces.
packages/​node-sdk/​test/​flag-definitions.test.ts Tests collection validation and ownership.
packages/​node-sdk/​test/​fixtures.ts Adds shared v2 collection fixtures.
packages/​node-sdk/​test/​client-sync.test.ts Covers synchronization modes and option validation.
packages/​node-sdk/​src/​types.ts Defines direct values and v2 protocol contracts.
packages/​node-sdk/​src/​index.ts Updates public type exports.
packages/​node-sdk/​src/​flagsFallbackProvider.ts Adds v2 fallback envelopes and namespaces.
packages/​node-sdk/​src/​flags-cache.ts Stores complete collections and exposes an apply callback.
packages/​node-sdk/​src/​flag-definitions.ts Validates and prepares complete collections.
packages/​node-sdk/​src/​flag-defaults.ts Implements default validation and category matching.
packages/​node-sdk/​src/​config.ts Accepts direct JSON overrides.
packages/​node-sdk/​src/​client.ts Implements v2 reads, checks, bootstrap, and persistence.
packages/​node-sdk/​README.md Documents v2 usage and migration boundaries.
packages/​node-sdk/​package.json Sets the v2 prerelease and evaluator dependency.
packages/​node-sdk/​examples/​express/​reflag.ts Migrates declarations and overrides to direct values.
packages/​node-sdk/​examples/​express/​app.ts Uses direct reads and separate usage tracking.
packages/​flag-evaluation/​test/​release.test.ts Checks v2 adoption and v1 consumer isolation.
.changeset/​pin-legacy-node-evaluator.md Removes the superseded evaluator-pinning changeset.
.changeset/​node-sdk-collection-values.md Records breaking SDK changes and provider isolation.

Review effort: Balanced

Comment on lines +110 to +124
value.allocations.every(
(a: unknown) =>
isObject(a) &&
Number.isInteger(a.percentage) &&
a.percentage >= 0 &&
a.percentage <= 100 &&
isObject(a.destination) &&
(a.destination.type === "nextRule" ||
(a.destination.type === "variant" &&
isResult(a.destination, variants))),
) &&
value.allocations.reduce(
(sum: number, a: { percentage: number }) => sum + a.percentage,
0,
) === 100

checkContextWithTracking(this._options);
void this._client["syncContext"](this._options);
checkContext(options);
Comment on lines +946 to +947
companyId: this.company?.id,
...options,
Base automatically changed from feature/multivariate-evaluator-v2 to main November 4, 2026 18:40
Copilot AI balanced review requested due to automatic review settings November 5, 2026 14:44

Copilot AI 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.

🔵 Needs a closer look

Integer-only validation rejects valid three-decimal variant distributions, causing an entire live or fallback flag snapshot to be discarded and leaving flags stale or on caller defaults.

3 open issues
1 previously missed issue

In code that hasn't changed since last review

Low severity Correct Node SDK version guidance in migration guide

packages/​flag-evaluation/​README.md:101

The migration guide still says the Node SDK uses the published v1 evaluator, but this PR switches packages/node-sdk/package.json to the v2 workspace evaluator. This gives integrators the opposite compatibility guidance for the new collection protocol. Update this paragraph to distinguish Node SDK v2 from the OpenFeature provider and bootstrap demo, which remain isolated on published Node SDK v1.

Review effort: Balanced

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