Skip to content

Commit 78d60c2

Browse files
committed
test(flags): preserve unknown rules fields
1 parent ab83f0f commit 78d60c2

4 files changed

Lines changed: 32 additions & 17 deletions

File tree

packages/core/src/flags/configuration/__tests__/rules.test.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,8 @@ describe('rules configuration', () => {
200200

201201
// TODO(FFL-2837): Replace this legacy JSON compatibility test with a
202202
// generated protobuf fixture after a flagging-core release contains
203-
// DataDog/openfeature-js-client#344 through `41dff20`.
203+
// DataDog/openfeature-js-client#344 through `41dff20`. Round-trip the
204+
// generated fixture and confirm that serialization preserves the unknown field.
204205
it('keeps supported known data when an unknown field is present', () => {
205206
const source = buildRulesConfiguration();
206207
(source.flags['dynamic-flag'] as typeof source.flags['dynamic-flag'] & {
@@ -227,7 +228,9 @@ describe('rules configuration', () => {
227228

228229
// TODO(FFL-2837): Replace this unsafe JSON number with an out-of-range
229230
// protobuf `int64` fixture after flagging-core contains PR #344 at or after
230-
// `41dff20`. The generated parser must preserve the source value as `bigint`.
231+
// `41dff20` plus the no-`BigInt` follow-up. The generated parser must preserve
232+
// the source value as `bigint` where supported. Run the same evaluation with
233+
// global `BigInt` unavailable and require `PARSE_ERROR`, not `GENERAL`.
231234
it('returns PARSE_ERROR instead of serving an unsafe integer', () => {
232235
const source = buildRulesConfiguration();
233236
const flag = source.flags['dynamic-flag'];

packages/core/src/flags/configuration/__tests__/wire.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,15 @@ describe('temporary rules configuration wire compatibility', () => {
165165
});
166166

167167
it('round-trips a legacy rules configuration', () => {
168+
const response = buildRulesConfiguration() as ReturnType<
169+
typeof buildRulesConfiguration
170+
> & {
171+
futureField?: { value: number };
172+
};
173+
response.futureField = { value: 7 };
168174
const original = {
169175
rulesBased: {
170-
response: buildRulesConfiguration(),
176+
response,
171177
fetchedAt: 123,
172178
etag: 'rules-etag'
173179
}

packages/core/src/flags/configuration/rules.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ import type { EvaluationContext, JsonValue, PrimitiveValue } from '../types';
1414

1515
// TODO(FFL-2837): Replace this legacy UFC v1 alias with
1616
// `NonNullable<FlagsConfiguration['rules']>['response']` after a flagging-core
17-
// release contains DataDog/openfeature-js-client#344 through `41dff20`. Keep the
18-
// `FlagsConfiguration` type import on the flagging-core package root. PR #344
19-
// preserves protobuf integers as `bigint`, and its evaluator reports unsafe
20-
// conversions as deterministic per-flag `PARSE_ERROR` results.
17+
// release contains DataDog/openfeature-js-client#344 through `41dff20`, restores
18+
// 32-byte SHA digest validation, and defines or fixes integer evaluation without
19+
// global `BigInt`. Keep the `FlagsConfiguration` type import on the flagging-core
20+
// package root. PR #344 preserves protobuf integers as `bigint`, and its evaluator
21+
// reports unsafe conversions as deterministic per-flag `PARSE_ERROR` results when
22+
// `BigInt` is available.
2123
type RulesConfigurationResponse = UniversalFlagConfigurationV1;
2224

2325
export type RulesValueType = 'boolean' | 'string' | 'number' | 'object';
@@ -128,7 +130,8 @@ const hasOwn = (value: object, key: PropertyKey): boolean =>
128130
Object.prototype.hasOwnProperty.call(value, key);
129131

130132
// TODO(FFL-2837): Delete this compatibility error store after a flagging-core
131-
// release contains DataDog/openfeature-js-client#344 through `41dff20`.
133+
// release contains DataDog/openfeature-js-client#344 through `41dff20` and fixes
134+
// or explicitly excludes integer and shard evaluation without global `BigInt`.
132135
// The generated protobuf evaluator validates the requested flag and the data
133136
// that evaluation reaches. It does not build this error map during parsing.
134137
// It returns deterministic `PARSE_ERROR` results, including for an integer that
@@ -462,10 +465,11 @@ export const prepareRulesConfiguration = (
462465
const clone = cloneValue(value);
463466

464467
// TODO(FFL-2837): Delete this legacy JSON clone and validator after a
465-
// flagging-core release contains upstream PR #344 through `41dff20`. That
468+
// flagging-core release contains upstream PR #344 through `41dff20` and the
469+
// no-`BigInt` integer contract is fixed or declared unsupported. That
466470
// implementation preserves protobuf integers as `bigint` and validates only
467-
// the requested flag data that evaluation reaches. It returns a deterministic
468-
// per-flag error when evaluation cannot produce a safe JavaScript number.
471+
// the requested flag data that evaluation reaches. With `BigInt`, it returns a
472+
// deterministic per-flag error when evaluation cannot produce a safe number.
469473
// Do not adapt this validator to the generated response type.
470474
const errorMessage = validateRulesConfigurationEnvelope(clone);
471475
if (errorMessage) {
@@ -557,7 +561,7 @@ export const flaggingCoreRulesEngine: RulesEngine = {
557561
// TODO(FFL-2837): Delete this compatibility check with the local error
558562
// store after the published PR #344 evaluator through `41dff20` validates
559563
// reached flag data and reports deterministic errors, including unsafe
560-
// integer conversions.
564+
// integer conversions with and without global `BigInt` when supported.
561565
const configurationError = errorsByConfiguration
562566
.get(request.configuration)
563567
?.get(request.flagKey);

packages/core/src/flags/configuration/wire.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import type {
2323

2424
// TODO(FFL-2837): Delete the pending `rulesBased` types, reader, and wrappers
2525
// after a flagging-core release contains DataDog/openfeature-js-client#344
26-
// through `41dff20`.
26+
// through `41dff20` plus the required SHA digest and no-`BigInt` follow-ups.
2727
// Import and re-export the wire functions and `FlagsConfigurationWire` type from
2828
// `@datadog/flagging-core/configuration`. Keep `FlagsConfiguration` and the rules
2929
// evaluator on the package root. Use `FlagsConfiguration.rules`. The distribution
@@ -81,8 +81,9 @@ export const configurationFromString = (source: string): FlagsConfiguration => {
8181
// generated Protobuf-ES message. Do not adapt this shim to decode a raw
8282
// service response or to add a base64 layer. Do not copy the strict base64
8383
// validator that PR #344 removed in favor of the Protobuf-ES decoder. The
84-
// published parser must also include PR #344's unknown-field tolerance and
85-
// lossless integer parsing through `41dff20`.
84+
// published parser must also include PR #344's unknown-field tolerance,
85+
// unknown-field serialization, and lossless integer parsing through
86+
// `41dff20`, plus the final no-`BigInt` runtime decision.
8687
const pendingRules = readPendingRulesWire(source);
8788
if (pendingRules) {
8889
try {
@@ -107,8 +108,9 @@ export const configurationToString = (
107108
const pendingConfiguration = configuration as PendingRulesConfiguration;
108109

109110
// TODO(FFL-2837): Delete this legacy serialization wrapper with the pending
110-
// types above after the dependency contains PR #344 through `41dff20`.
111-
// The upstream serializer encodes generated protobuf rules back to base64.
111+
// types above after the dependency contains PR #344 through `41dff20` and
112+
// its required follow-ups. The upstream serializer encodes generated protobuf
113+
// rules back to base64 and preserves unknown protobuf fields.
112114
// This temporary UFC v1 shim serializes its legacy JSON response instead.
113115
if (pendingConfiguration.rulesBased) {
114116
const serialized = JSON.parse(

0 commit comments

Comments
 (0)