Fix array-valued Node SDK context targeting - #710
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Local CONTAINS evaluation currently performs substring matching on JSON-stringified arrays, which can yield incorrect targeting matches and couples behavior to JSON encoding details.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR updates how array-valued context attributes are serialized across the Node SDK and local flag evaluation so that arrays remain at their original property path (as JSON strings) instead of being expanded into numeric subpaths (e.g., user.roles.0).
Changes:
- Update
flattenJSONto serialize arrays as JSON strings at their property path (including empty arrays). - Add/adjust tests to validate array context serialization and basic
CONTAINSbehavior for array context values. - Add a changeset to publish patch releases for
@reflag/flag-evaluationand@reflag/node-sdk.
File summaries
| File | Description |
|---|---|
| packages/node-sdk/test/client.test.ts | Adds coverage for CONTAINS with array context and remote-eval query stringification behavior. |
| packages/flag-evaluation/test/index.test.ts | Updates flattening tests to expect array stringification; adds an integration test for CONTAINS against stringified arrays. |
| packages/flag-evaluation/src/index.ts | Changes flattenJSON array handling to JSON.stringify rather than expanding numeric paths. |
| .changeset/stringify-array-context-values.md | Declares patch releases and documents the behavior change. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| } else if (typeof value !== "object") { | ||
| result[prop] = String(value); | ||
| } else if (Array.isArray(value)) { | ||
| if (value.length === 0) { | ||
| result[prop] = ""; | ||
| } | ||
|
|
||
| for (let i = 0; i < value.length; i++) { | ||
| recurse(value[i], prop ? prop + "." + i : "" + i); | ||
| } | ||
| result[prop] = JSON.stringify(value); | ||
| } else { |
|
Superseded by #711, which implements the canonical array semantics ( intersection, empty-array behavior, type-preserving evaluation flattening, and legacy-array compatibility) without changing . |
|
Superseded by #711, which implements the canonical array semantics ( |
Summary
CONTAINSrules work with array context values@reflag/flag-evaluationand@reflag/node-sdkExample
This replaces the previous
user.roles.0/user.roles.1expansion.Tests
cd packages/flag-evaluation && node node_modules/vitest/vitest.mjs run(146 passed)yarn workspace @reflag/node-sdk test --run(220 passed)yarn workspace @reflag/flag-evaluation buildyarn workspace @reflag/node-sdk build