Skip to content

Commit cff67b0

Browse files
authored
Merge pull request #184 from launchdarkly/release-3.0.3
prepare 3.0.3 release
2 parents f166517 + e10f457 commit cff67b0

File tree

3 files changed

+29
-20
lines changed

3 files changed

+29
-20
lines changed

src/getFlagsProxy.test.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,40 +26,39 @@ test('native Object functions should be ignored', () => {
2626

2727
test('camel cases keys', () => {
2828
const { flags } = getFlagsProxy(ldClient, rawFlags);
29-
3029
expect(flags).toEqual(camelizedFlags);
3130
});
3231

3332
test('does not camel cases keys', () => {
34-
const { flags } = getFlagsProxy(ldClient, rawFlags, { useCamelCaseFlagKeys: false });
35-
33+
const { flags } = getFlagsProxy(ldClient, rawFlags, { ...defaultReactOptions, useCamelCaseFlagKeys: false });
3634
expect(flags).toEqual(rawFlags);
3735
});
3836

39-
test('proxy calls ldClient.variation on flag read', () => {
37+
test('proxy calls ldClient.variation on flag read when camelCase true', () => {
4038
const { flags } = getFlagsProxy(ldClient, rawFlags);
41-
4239
expect(flags.fooBar).toBe('foobar');
40+
expect(ldClient.variation).toHaveBeenCalledWith('foo-bar', 'foobar');
41+
});
4342

43+
test('proxy calls ldClient.variation on flag read when camelCase false', () => {
44+
const { flags } = getFlagsProxy(ldClient, rawFlags, { ...defaultReactOptions, useCamelCaseFlagKeys: false });
45+
expect(flags.fooBar).toBeUndefined();
46+
expect(flags['foo-bar']).toEqual('foobar');
4447
expect(ldClient.variation).toHaveBeenCalledWith('foo-bar', 'foobar');
4548
});
4649

4750
test('returns flag key map', () => {
4851
const { flagKeyMap } = getFlagsProxy(ldClient, rawFlags);
49-
5052
expect(flagKeyMap).toEqual({ fooBar: 'foo-bar', bazQux: 'baz-qux' });
5153
});
5254

5355
test('filters to target flags', () => {
5456
const { flags } = getFlagsProxy(ldClient, rawFlags, defaultReactOptions, { 'foo-bar': 'mr-toot' });
55-
5657
expect(flags).toEqual({ fooBar: 'foobar' });
5758
});
5859

59-
test('does not use proxy if option is false', () => {
60-
const { flags } = getFlagsProxy(ldClient, rawFlags, { sendEventsOnFlagRead: false });
61-
62-
expect(flags['foo-bar']).toBe('foobar');
63-
60+
test('does not use proxy if sendEventsOnFlagRead is false', () => {
61+
const { flags } = getFlagsProxy(ldClient, rawFlags, { ...defaultReactOptions, sendEventsOnFlagRead: false });
62+
expect(flags.fooBar).toBe('foobar');
6463
expect(ldClient.variation).not.toHaveBeenCalled();
6564
});

src/getFlagsProxy.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@ export default function getFlagsProxy(
99
targetFlags?: LDFlagSet,
1010
): { flags: LDFlagSet; flagKeyMap: LDFlagKeyMap } {
1111
const filteredFlags = filterFlags(rawFlags, targetFlags);
12-
const [flags, flagKeyMap = {}] = reactOptions.useCamelCaseFlagKeys
13-
? getCamelizedKeysAndFlagMap(filteredFlags)
14-
: [filteredFlags];
12+
const { useCamelCaseFlagKeys = true } = reactOptions;
13+
const [flags, flagKeyMap = {}] = useCamelCaseFlagKeys ? getCamelizedKeysAndFlagMap(filteredFlags) : [filteredFlags];
1514

1615
return {
17-
flags: reactOptions.sendEventsOnFlagRead ? toFlagsProxy(ldClient, flags, flagKeyMap) : flags,
16+
flags: reactOptions.sendEventsOnFlagRead ? toFlagsProxy(ldClient, flags, flagKeyMap, useCamelCaseFlagKeys) : flags,
1817
flagKeyMap,
1918
};
2019
}
@@ -53,22 +52,33 @@ function hasFlag(flags: LDFlagSet, flagKey: string) {
5352
return Object.prototype.hasOwnProperty.call(flags, flagKey);
5453
}
5554

56-
function toFlagsProxy(ldClient: LDClient, flags: LDFlagSet, flagKeyMap: LDFlagKeyMap): LDFlagSet {
55+
function toFlagsProxy(
56+
ldClient: LDClient,
57+
flags: LDFlagSet,
58+
flagKeyMap: LDFlagKeyMap,
59+
useCamelCaseFlagKeys: boolean,
60+
): LDFlagSet {
5761
return new Proxy(flags, {
5862
// trap for reading a flag value using `LDClient#variation` to trigger an evaluation event
5963
get(target, prop, receiver) {
6064
const currentValue = Reflect.get(target, prop, receiver);
6165

66+
// check if flag key exists as camelCase or original case
67+
const validFlagKey =
68+
(useCamelCaseFlagKeys && hasFlag(flagKeyMap, prop as string)) || hasFlag(target, prop as string);
69+
6270
// only process flag keys and ignore symbols and native Object functions
63-
if (typeof prop === 'symbol' || !hasFlag(flagKeyMap, prop)) {
71+
if (typeof prop === 'symbol' || !validFlagKey) {
6472
return currentValue;
6573
}
6674

6775
if (currentValue === undefined) {
6876
return;
6977
}
7078

71-
return ldClient.variation(flagKeyMap[prop], currentValue);
79+
const pristineFlagKey = useCamelCaseFlagKeys ? flagKeyMap[prop] : prop;
80+
81+
return ldClient.variation(pristineFlagKey, currentValue);
7282
},
7383
});
7484
}

src/useLDClient.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import context from './context';
33

44
// tslint:disable:max-line-length
55
/**
6-
* `useLDClient` is a custom hook which returns the underlying [LaunchDarkly JavaScript SDK client object](https://launchdarkly.github.io/js-client-sdk/interfaces/_launchdarkly_js_client_sdk_.ldclient.html).
6+
* `useLDClient` is a custom hook which returns the underlying [LaunchDarkly JavaScript SDK client object](https://launchdarkly.github.io/js-client-sdk/interfaces/LDClient.html).
77
* Like the `useFlags` custom hook, `useLDClient` also uses the `useContext` primitive to access the LaunchDarkly
88
* context set up by `withLDProvider`. You will still need to use the `withLDProvider` HOC
99
* to initialise the react sdk to use this custom hook.

0 commit comments

Comments
 (0)