Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .changeset/multivariate-evaluation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
"@reflag/flag-evaluation": major
---

Introduce a v2-only compiled-variant evaluator:

- `newEvaluator(flag)` prepares a compiled flag once and returns a reusable context evaluator. Remove the v1 value-rule APIs and the one-shot `evaluateFlag` wrapper.
- Preserve arbitrary variant value types through `CompiledFlag<T>` and `EvaluationResult<T>` (default `any`). `resolved: true | false` distinguishes a selected value, including `undefined`, from failure. Successful results require the variant key and matched rule ID.
- Keep membership Sets and prepared percentage bounds private. `ANY_OF` / `NOT_ANY_OF` use cached Set lookups, including under groups and negations; percentage distributions use precomputed bounds and a simple scan.
- Evaluate rules sequentially with explicit fallthrough and source-version/rule/allocation diagnostics.
- Return structured `INVALID_COMPARISON` errors for invalid numeric/date comparisons instead of logging context values. Invalid conditions cannot match through negation.
- Retain the original hash function and threshold rollout filter for boolean cohort compatibility. The inclusive maximum distribution bucket selects the last nonzero allocation.

The runtime exports are `newEvaluator`, `flattenContext`, and `hashInt`. Removed APIs include `evaluateFlagRules`, `newFlagEvaluator`, `evaluateFlag`, the scalar `evaluate` helper, and the legacy `flattenJSON` / `unflattenJSON` helpers.
5 changes: 5 additions & 0 deletions .changeset/pin-legacy-node-evaluator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@reflag/node-sdk": patch
---

Keep the existing Node SDK on evaluator 1.1.1 through the `@reflag/flag-evaluation-v1` npm alias. This preserves its legacy protocol and prevents the evaluator's v2 workspace release from automatically upgrading its dependency before SDK migration.
52 changes: 52 additions & 0 deletions packages/flag-evaluation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Flag evaluation v2

Prepare a compiled flag once when its definition is loaded or refreshed, then
reuse the evaluator for each context:

```ts
import { newEvaluator } from "@reflag/flag-evaluation";

const evaluate = newEvaluator(compiledFlag);
const result = evaluate({ company: { id: "acme" }, user: { id: "alice" } });

// Diagnostics can accompany either a successful result or a failure.
if (result.errors.length) console.warn(result.errors);

if (result.resolved) {
// T, not T | undefined. An undefined variant value is still a success.
console.log(result.value);
// Required success metadata for diagnostics/exposure events.
console.log(result.variantKey, result.matchedRuleId);
} else {
// No variant was selected: use the SDK's fallback behavior.
}
```

`CompiledFlag<T = any>` and `EvaluationResult<T = any>` preserve the caller's
value type. Non-fatal diagnostics may also accompany a successful
default/fallthrough result.

Rebuild the evaluator when definitions change. Treat definitions and returned
values as immutable. Each evaluation has independent diagnostics.

## Migration from v1

V2 exports `newEvaluator(flag)`, `flattenContext`, and `hashInt`, plus their public
types. `newEvaluator` now accepts a compiled flag, not value rules. The returned
function accepts only context; the flag key is part of the definition.

V1's `evaluateFlagRules`, scalar `evaluate`, `flattenJSON`, `unflattenJSON`, and
value-rule types are removed. There is no v2 one-shot evaluation wrapper.
The hash and `rolloutPercentage` filter remain to preserve boolean cohorts.

## Performance checks

From the repository root:

```sh
yarn workspace @reflag/flag-evaluation exec vitest bench --run test/variants.bench.ts
```

Benchmarks exclude preparation and compare with published v1 across candidate
lists up to 100,000 and percentage distributions up to 50 allocations. Unit tests
assert cached Set usage, no repeated percentage reads, and stable hash cohorts.
4 changes: 3 additions & 1 deletion packages/flag-evaluation/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@reflag/flag-evaluation",
"version": "1.1.1",
"version": "2.0.0-next.0",
"license": "MIT",
"repository": {
"type": "git",
Expand All @@ -16,6 +16,7 @@
},
"scripts": {
"build": "tsc --project tsconfig.build.json",
"prepack": "yarn build",
"test": "vitest",
"test:ci": "vitest --reporter=default --reporter=junit --outputFile=junit.xml",
"lint": "oxlint .",
Expand All @@ -30,6 +31,7 @@
"js-sha256": "0.11.0"
},
"devDependencies": {
"@reflag/flag-evaluation-v1": "npm:@reflag/flag-evaluation@1.1.1",
"@reflag/tsconfig": "^0.0.2",
"@types/node": "^22.12.0",
"ts-node": "^10.9.2",
Expand Down
Loading
Loading