Skip to content

Commit 00380bb

Browse files
authored
Merge pull request #3 from nosnibor89/feat/svelte-sdk-refactor-is-on
[refactor] Update SvelteLDClient to use proxy for flag variations. Allows to track flag evaluations
2 parents 3bf80cb + 3690339 commit 00380bb

File tree

3 files changed

+46
-12
lines changed

3 files changed

+46
-12
lines changed

packages/sdk/svelte/__tests__/lib/client/SvelteLDClient.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const mockLDClient = {
1818
on: (e: string, cb: () => void) => mockLDEventEmitter.on(e, cb),
1919
off: vi.fn(),
2020
allFlags: vi.fn().mockReturnValue(rawFlags),
21-
variation: vi.fn(),
21+
variation: vi.fn((_, defaultValue) => defaultValue),
2222
identify: vi.fn(),
2323
};
2424

@@ -130,6 +130,9 @@ describe('launchDarkly', () => {
130130
const flagStore = ld.watch(booleanFlagKey);
131131
const flagStore2 = ld.watch(stringFlagKey);
132132

133+
// emit ready event to set initial flag values
134+
mockLDEventEmitter.emit('ready');
135+
133136
// 'test-flag' initial value is true according to `rawFlags`
134137
expect(get(flagStore)).toBe(true);
135138
// 'another-test-flag' intial value is 'flag-value' according to `rawFlags`

packages/sdk/svelte/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,11 @@
4444
},
4545
"peerDependencies": {
4646
"@launchdarkly/js-client-sdk": "workspace:^",
47-
"@launchdarkly/js-client-sdk-common": "^1.10.0",
4847
"@launchdarkly/node-server-sdk": "^9.4.6",
4948
"svelte": "^4.0.0"
5049
},
5150
"dependencies": {
5251
"@launchdarkly/js-client-sdk": "workspace:^",
53-
"@launchdarkly/js-client-sdk-common": "1.10.0",
5452
"esm-env": "^1.0.0"
5553
},
5654
"devDependencies": {

packages/sdk/svelte/src/lib/client/SvelteLDClient.ts

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,43 @@ function isClientInitialized(client: LDClient | undefined): asserts client is LD
2727
}
2828
}
2929

30+
/**
31+
* Creates a proxy for the given flags object that intercepts access to flag values.
32+
* When a flag value is accessed, it checks if the flag key exists in the target object.
33+
* If the flag key exists, it returns the variation of the flag from the client.
34+
* Otherwise, it returns the current value of the flag.
35+
*
36+
* @param client - The LaunchDarkly client instance used to get flag variations.
37+
* @param flags - The initial flags object to be proxied.
38+
* @returns A proxy object that intercepts access to flag values and returns the appropriate variation.
39+
*/
40+
function toFlagsProxy(client: LDClient, flags: LDFlags): LDFlags {
41+
return new Proxy(flags, {
42+
get(target, prop, receiver) {
43+
const currentValue = Reflect.get(target, prop, receiver);
44+
// only process flag keys and ignore symbols and native Object functions
45+
if (typeof prop === 'symbol') {
46+
return currentValue;
47+
}
48+
49+
// check if flag key exists
50+
const validFlagKey = Object.hasOwn(target, prop);
51+
52+
if (!validFlagKey) {
53+
return currentValue;
54+
}
55+
56+
return client.variation(prop, currentValue);
57+
},
58+
});
59+
}
60+
3061
/**
3162
* Creates a LaunchDarkly instance.
3263
* @returns {Object} The LaunchDarkly instance object.
3364
*/
3465
function createLD() {
35-
let jsSdk: LDClient | undefined;
66+
let coreLdClient: LDClient | undefined;
3667
const loading = writable(true);
3768
const flagsWritable = writable<LDFlags>({});
3869

@@ -43,15 +74,17 @@ function createLD() {
4374
*/
4475

4576
function LDInitialize(clientId: LDClientID) {
46-
jsSdk = initialize(clientId);
47-
jsSdk!.on('ready', () => {
77+
coreLdClient = initialize(clientId);
78+
coreLdClient!.on('ready', () => {
4879
loading.set(false);
49-
const allFlags = jsSdk!.allFlags();
80+
const rawFlags = coreLdClient!.allFlags();
81+
const allFlags = toFlagsProxy(coreLdClient, rawFlags);
5082
flagsWritable.set(allFlags);
5183
});
5284

53-
jsSdk!.on('change', () => {
54-
const allFlags = jsSdk!.allFlags();
85+
coreLdClient!.on('change', () => {
86+
const rawFlags = coreLdClient!.allFlags();
87+
const allFlags = toFlagsProxy(coreLdClient, rawFlags);
5588
flagsWritable.set(allFlags);
5689
});
5790

@@ -66,8 +99,8 @@ function createLD() {
6699
* @returns {Promise} A promise that resolves when the user is identified.
67100
*/
68101
async function identify(context: LDContext) {
69-
isClientInitialized(jsSdk);
70-
return jsSdk.identify(context);
102+
isClientInitialized(coreLdClient);
103+
return coreLdClient.identify(context);
71104
}
72105

73106
/**
@@ -84,7 +117,7 @@ function createLD() {
84117
* @returns {boolean} True if the flag is on, false otherwise.
85118
*/
86119
const isOn = (flagKey: string): boolean => {
87-
isClientInitialized(jsSdk);
120+
isClientInitialized(coreLdClient);
88121
const currentFlags = get(flagsWritable);
89122
return !!currentFlags[flagKey];
90123
};

0 commit comments

Comments
 (0)