Skip to content

Commit 60fafe1

Browse files
committed
refactor: add ConfigurationStore abstraction
1 parent f5080f6 commit 60fafe1

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

src/configuration-store/configuration-store.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,57 @@
1+
import { IConfiguration } from '../i-configuration';
12
import { Environment } from '../interfaces';
23

4+
/**
5+
* `ConfigurationStore` is a central piece of Eppo SDK and answers a
6+
* simple question: what configuration is currently active?
7+
*
8+
* @internal `ConfigurationStore` shall only be used inside Eppo SDKs.
9+
*/
10+
export class ConfigurationStore {
11+
private readonly listeners: Array<
12+
(configuration: IConfiguration | null) => void
13+
> = [];
14+
15+
// TODO: replace IConfiguration with a concrete `Configuration` type.
16+
public constructor(private configuration: IConfiguration | null = null) {}
17+
18+
public getConfiguration(): IConfiguration | null {
19+
return this.configuration;
20+
}
21+
22+
public setConfiguration(configuration: IConfiguration | null): void {
23+
this.configuration = configuration;
24+
this.notifyListeners();
25+
}
26+
27+
/**
28+
* Subscribe to configuration changes. The callback will be called
29+
* every time configuration is changed.
30+
*
31+
* Returns a function to unsubscribe from future updates.
32+
*/
33+
public onConfigurationChange(
34+
listener: (configuration: IConfiguration | null) => void
35+
): () => void {
36+
this.listeners.push(listener);
37+
38+
return () => {
39+
const idx = this.listeners.indexOf(listener);
40+
if (idx !== -1) {
41+
this.listeners.splice(idx, 1);
42+
}
43+
};
44+
}
45+
46+
private notifyListeners(): void {
47+
for (const listener of this.listeners) {
48+
try {
49+
listener(this.configuration);
50+
} catch {}
51+
}
52+
}
53+
}
54+
355
/**
456
* ConfigurationStore interface
557
*
@@ -21,6 +73,8 @@ import { Environment } from '../interfaces';
2173
*
2274
* The policy choices surrounding the use of one or more underlying storages are
2375
* implementation specific and handled upstream.
76+
*
77+
* @deprecated To be replaced with ConfigurationStore and PersistentStorage.
2478
*/
2579
export interface IConfigurationStore<T> {
2680
init(): Promise<void>;
@@ -41,6 +95,7 @@ export interface IConfigurationStore<T> {
4195
salt?: string;
4296
}
4397

98+
/** @deprecated To be replaced with ConfigurationStore and PersistentStorage. */
4499
export interface ISyncStore<T> {
45100
get(key: string): T | null;
46101
entries(): Record<string, T>;
@@ -49,6 +104,7 @@ export interface ISyncStore<T> {
49104
setEntries(entries: Record<string, T>): void;
50105
}
51106

107+
/** @deprecated To be replaced with ConfigurationStore and PersistentStorage. */
52108
export interface IAsyncStore<T> {
53109
isInitialized(): boolean;
54110
isExpired(): Promise<boolean>;

src/configuration-store/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { ConfigurationStore } from "./configuration-store";

0 commit comments

Comments
 (0)