Skip to content

Commit e223b48

Browse files
featu: [Add support for exporting the configuration[ (FF-2437) (#90)
* featu: [Add support for exporting the configuration[ (FF-2437) * rename getAll to entries * getFlagConfigurations * bump to 3.4.0
1 parent cf76588 commit e223b48

File tree

8 files changed

+46
-5
lines changed

8 files changed

+46
-5
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@eppo/js-client-sdk-common",
3-
"version": "3.3.3",
3+
"version": "3.4.0",
44
"description": "Eppo SDK for client-side JavaScript applications (base for both web and react native)",
55
"main": "dist/index.js",
66
"files": [

src/client/eppo-client.spec.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,12 @@ describe('EppoClient E2E test', () => {
354354
expect(assignment).toEqual('variation-a');
355355
});
356356

357+
it('exports flag configuration', () => {
358+
storage.setEntries({ [flagKey]: mockFlag });
359+
const client = new EppoClient(storage);
360+
expect(client.getFlagConfigurations()).toEqual({ [flagKey]: mockFlag });
361+
});
362+
357363
describe('assignment logging deduplication', () => {
358364
let client: EppoClient;
359365
let mockLogger: IAssignmentLogger;

src/client/eppo-client.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ export interface IEppoClient {
143143

144144
getFlagKeys(): string[];
145145

146+
getFlagConfigurations(): Record<string, Flag>;
147+
146148
isInitialized(): boolean;
147149
}
148150

@@ -503,6 +505,10 @@ export default class EppoClient implements IEppoClient {
503505
this.isGracefulFailureMode = gracefulFailureMode;
504506
}
505507

508+
public getFlagConfigurations(): Record<string, Flag> {
509+
return this.configurationStore.entries();
510+
}
511+
506512
private flushQueuedEvents() {
507513
const eventsToFlush = this.queuedEvents;
508514
this.queuedEvents = [];

src/configuration-store/configuration-store.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
export interface IConfigurationStore<T> {
2424
init(): Promise<void>;
2525
get(key: string): T | null;
26+
entries(): Record<string, T>;
2627
getKeys(): string[];
2728
isInitialized(): boolean;
2829
isExpired(): Promise<boolean>;
@@ -31,6 +32,7 @@ export interface IConfigurationStore<T> {
3132

3233
export interface ISyncStore<T> {
3334
get(key: string): T | null;
35+
entries(): Record<string, T>;
3436
getKeys(): string[];
3537
isInitialized(): boolean;
3638
setEntries(entries: Record<string, T>): void;
@@ -39,6 +41,6 @@ export interface ISyncStore<T> {
3941
export interface IAsyncStore<T> {
4042
isInitialized(): boolean;
4143
isExpired(): Promise<boolean>;
42-
getEntries(): Promise<Record<string, T>>;
44+
entries(): Promise<Record<string, T>>;
4345
setEntries(entries: Record<string, T>): Promise<void>;
4446
}

src/configuration-store/hybrid.store.spec.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ describe('HybridConfigurationStore', () => {
99
beforeEach(() => {
1010
syncStoreMock = {
1111
get: jest.fn(),
12+
entries: jest.fn(),
1213
getKeys: jest.fn(),
1314
isInitialized: jest.fn(),
1415
setEntries: jest.fn(),
1516
};
1617

1718
asyncStoreMock = {
18-
getEntries: jest.fn(),
19+
entries: jest.fn(),
1920
isInitialized: jest.fn(),
2021
isExpired: jest.fn(),
2122
setEntries: jest.fn(),
@@ -28,7 +29,7 @@ describe('HybridConfigurationStore', () => {
2829
it('should initialize the serving store with entries from the persistent store if the persistent store is initialized', async () => {
2930
const entries = { key1: 'value1', key2: 'value2' };
3031
(asyncStoreMock.isInitialized as jest.Mock).mockReturnValue(true);
31-
(asyncStoreMock.getEntries as jest.Mock).mockResolvedValue(entries);
32+
(asyncStoreMock.entries as jest.Mock).mockResolvedValue(entries);
3233

3334
await store.init();
3435

@@ -67,6 +68,14 @@ describe('HybridConfigurationStore', () => {
6768
});
6869
});
6970

71+
describe('entries', () => {
72+
it('should return all entries from the serving store', () => {
73+
const entries = { key1: 'value1', key2: 'value2' };
74+
(syncStoreMock.entries as jest.Mock).mockReturnValue(entries);
75+
expect(store.entries()).toEqual(entries);
76+
});
77+
});
78+
7079
describe('setEntries', () => {
7180
it('should set entries in both stores if the persistent store is present', async () => {
7281
const entries = { key1: 'value1', key2: 'value2' };

src/configuration-store/hybrid.store.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export class HybridConfigurationStore<T> implements IConfigurationStore<T> {
2929
);
3030
}
3131

32-
const entries = await this.persistentStore.getEntries();
32+
const entries = await this.persistentStore.entries();
3333
this.servingStore.setEntries(entries);
3434
}
3535

@@ -49,6 +49,10 @@ export class HybridConfigurationStore<T> implements IConfigurationStore<T> {
4949
return this.servingStore.get(key);
5050
}
5151

52+
public entries(): Record<string, T> {
53+
return this.servingStore.entries();
54+
}
55+
5256
public getKeys(): string[] {
5357
return this.servingStore.getKeys();
5458
}

src/configuration-store/memory.store.spec.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ describe('MemoryOnlyConfigurationStore', () => {
3636
expect(memoryStore.getKeys()).toEqual(['key1', 'key2', 'key3']);
3737
});
3838

39+
it('should return all entries', async () => {
40+
const entries = { key1: 'value1', key2: 'value2', key3: 'value3' };
41+
await memoryStore.setEntries(entries);
42+
expect(memoryStore.entries()).toEqual(entries);
43+
});
44+
3945
it('should overwrite existing entries', async () => {
4046
await memoryStore.setEntries({ toBeReplaced: 'old value', toBeRemoved: 'delete me' });
4147
expect(memoryStore.get('toBeReplaced')).toBe('old value');

src/configuration-store/memory.store.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ export class MemoryStore<T> implements ISyncStore<T> {
88
return this.store[key] ?? null;
99
}
1010

11+
entries(): Record<string, T> {
12+
return this.store;
13+
}
14+
1115
getKeys(): string[] {
1216
return Object.keys(this.store);
1317
}
@@ -35,6 +39,10 @@ export class MemoryOnlyConfigurationStore<T> implements IConfigurationStore<T> {
3539
return this.servingStore.get(key);
3640
}
3741

42+
entries(): Record<string, T> {
43+
return this.servingStore.entries();
44+
}
45+
3846
getKeys(): string[] {
3947
return this.servingStore.getKeys();
4048
}

0 commit comments

Comments
 (0)