Skip to content

feat: expose original feature name on flags - #427

Open
matthewelwell wants to merge 1 commit into
mainfrom
feat/expose-feature-name
Open

matthewelwell wants to merge 1 commit into
mainfrom
feat/expose-feature-name

Conversation

@matthewelwell

Copy link
Copy Markdown
Contributor

Adds an optional name to each flag carrying the feature's original casing, so getAllFlags() can be re-keyed by real feature names rather than reading flags one at a time — additive, flag keys are unchanged.

const flagsByName = Object.fromEntries(
  Object.entries(flagsmith.getAllFlags()).map(([key, flag]) => [flag.name ?? key, flag])
)

🤖 Generated with Claude Code

Comment thread test/feature-name-casing.test.ts Outdated
Comment on lines +44 to +49
test('getAllFlags can be re-keyed by original feature name', async () => {
const { flagsmith } = await initWithMixedCaseFlags();
const flagsByName = byName(flagsmith.getAllFlags());
expect(Object.keys(flagsByName).sort()).toEqual(['MyFeatureFlag', 'another_flag']);
expect(flagsByName.MyFeatureFlag.value).toBe('on');
});

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.

This test is just a pointless duplication of the above test.

Suggested change
test('getAllFlags can be re-keyed by original feature name', async () => {
const { flagsmith } = await initWithMixedCaseFlags();
const flagsByName = byName(flagsmith.getAllFlags());
expect(Object.keys(flagsByName).sort()).toEqual(['MyFeatureFlag', 'another_flag']);
expect(flagsByName.MyFeatureFlag.value).toBe('on');
});

Comment thread test/feature-name-casing.test.ts Outdated
Comment on lines +58 to +65
test('falls back to the flag key when name is absent, as with defaultFlags', async () => {
const { flagsmith, initConfig } = getFlagsmith({
preventFetch: true,
defaultFlags: { my_default: { enabled: true, value: 1 } },
});
await flagsmith.init(initConfig);
expect(byName(flagsmith.getAllFlags()).my_default).toEqual({ enabled: true, value: 1 });
});

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.

As far as I can tell, this test is also pointless.

Suggested change
test('falls back to the flag key when name is absent, as with defaultFlags', async () => {
const { flagsmith, initConfig } = getFlagsmith({
preventFetch: true,
defaultFlags: { my_default: { enabled: true, value: 1 } },
});
await flagsmith.init(initConfig);
expect(byName(flagsmith.getAllFlags()).my_default).toEqual({ enabled: true, value: 1 });
});

Comment thread flagsmith-core.ts Outdated
Comment on lines +71 to +72
// Flags are stored lower-cased with spaces replaced, so that callers can look a flag
// up by any casing. The feature's original name is kept on the flag itself as `name`.

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.

Suggested change
// Flags are stored lower-cased with spaces replaced, so that callers can look a flag
// up by any casing. The feature's original name is kept on the flag itself as `name`.

@matthewelwell
matthewelwell force-pushed the feat/expose-feature-name branch from 67c6577 to 44ce0be Compare October 6, 2026 09:42
Flag keys in getAllFlags() are lower-cased with spaces replaced, and the
feature's original name was discarded at ingest, so consumers who want a
map keyed by their real feature names had no way to recover it.

Each flag now carries the feature's own name as `name`. This is purely
additive - flag keys are unchanged. `name` is absent on flags supplied
via defaultFlags and on flags restored from a cache written by an older
SDK, hence the `?? key` fallback in the documented snippet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@matthewelwell
matthewelwell force-pushed the feat/expose-feature-name branch from 44ce0be to fe8068b Compare October 6, 2026 09:42
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.

1 participant