@featbit/js-client-sdk 3.0.13 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +301 -301
- package/dist/esm/FbClientCore.d.ts +6 -5
- package/dist/esm/FbClientCore.d.ts.map +1 -1
- package/dist/esm/FbClientCore.js +27 -4
- package/dist/esm/FbClientCore.js.map +1 -1
- package/dist/esm/IFbClientCore.d.ts +8 -7
- package/dist/esm/IFbClientCore.d.ts.map +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.d.ts.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/version.js.map +1 -1
- package/dist/umd/featbit-js-client-sdk-4.0.0.js +2 -0
- package/dist/umd/featbit-js-client-sdk-4.0.0.js.map +1 -0
- package/dist/umd/featbit-js-client-sdk.js +1 -1
- package/dist/umd/featbit-js-client-sdk.js.map +1 -1
- package/package.json +46 -46
- package/src/Configuration.ts +232 -232
- package/src/Context.ts +61 -61
- package/src/FbClientBuilder.ts +167 -167
- package/src/FbClientCore.ts +428 -405
- package/src/IContextProperty.ts +3 -3
- package/src/IDataKind.ts +11 -11
- package/src/IFbClient.ts +29 -29
- package/src/IFbClientCore.ts +291 -290
- package/src/IVersionedData.ts +18 -18
- package/src/bootstrap/IBootstrapProvider.ts +4 -4
- package/src/bootstrap/JsonBootstrapProvider.ts +34 -34
- package/src/bootstrap/NullBootstrapProvider.ts +20 -20
- package/src/bootstrap/index.ts +2 -2
- package/src/constants.ts +1 -1
- package/src/data-sources/DataSourceUpdates.ts +116 -116
- package/src/data-sources/createStreamListeners.ts +67 -67
- package/src/data-sources/index.ts +1 -1
- package/src/data-sync/DataSyncMode.ts +3 -3
- package/src/data-sync/IDataSynchronizer.ts +15 -15
- package/src/data-sync/IRequestor.ts +10 -10
- package/src/data-sync/NullDataSynchronizer.ts +14 -14
- package/src/data-sync/PollingDataSynchronizer.ts +125 -125
- package/src/data-sync/Requestor.ts +61 -61
- package/src/data-sync/WebSocketDataSynchronizer.ts +77 -77
- package/src/data-sync/index.ts +8 -8
- package/src/data-sync/types.ts +19 -19
- package/src/data-sync/utils.ts +31 -31
- package/src/errors.ts +47 -47
- package/src/evaluation/EvalResult.ts +35 -35
- package/src/evaluation/Evaluator.ts +26 -26
- package/src/evaluation/IEvalDetail.ts +23 -23
- package/src/evaluation/ReasonKinds.ts +9 -9
- package/src/evaluation/data/IFlag.ts +29 -29
- package/src/evaluation/index.ts +4 -4
- package/src/events/DefaultEventProcessor.ts +83 -83
- package/src/events/DefaultEventQueue.ts +49 -49
- package/src/events/DefaultEventSender.ts +73 -73
- package/src/events/DefaultEventSerializer.ts +11 -11
- package/src/events/EventDispatcher.ts +127 -127
- package/src/events/EventSerializer.ts +4 -4
- package/src/events/IEventProcessor.ts +8 -8
- package/src/events/IEventQueue.ts +16 -16
- package/src/events/IEventSender.ts +13 -13
- package/src/events/NullEventProcessor.ts +15 -15
- package/src/events/event.ts +129 -129
- package/src/events/index.ts +11 -11
- package/src/index.ts +21 -21
- package/src/integrations/TestLogger.ts +24 -24
- package/src/integrations/index.ts +1 -1
- package/src/integrations/test_data/FlagBuilder.ts +59 -59
- package/src/integrations/test_data/TestData.ts +57 -57
- package/src/integrations/test_data/TestDataSynchronizer.ts +49 -49
- package/src/integrations/test_data/index.ts +4 -4
- package/src/logging/BasicLogger.ts +108 -108
- package/src/logging/IBasicLoggerOptions.ts +46 -46
- package/src/logging/ILogger.ts +49 -49
- package/src/logging/LogLevel.ts +8 -8
- package/src/logging/SafeLogger.ts +69 -69
- package/src/logging/format.ts +154 -154
- package/src/logging/index.ts +5 -5
- package/src/options/ClientContext.ts +39 -39
- package/src/options/IClientContext.ts +53 -53
- package/src/options/IOptions.ts +123 -123
- package/src/options/IUser.ts +6 -6
- package/src/options/IValidatedOptions.ts +29 -29
- package/src/options/OptionMessages.ts +35 -35
- package/src/options/UserBuilder.ts +35 -35
- package/src/options/Validators.ts +300 -300
- package/src/options/index.ts +7 -7
- package/src/platform/IInfo.ts +102 -102
- package/src/platform/IPlatform.ts +20 -20
- package/src/platform/IStore.ts +112 -112
- package/src/platform/IWebSocket.ts +22 -22
- package/src/platform/browser/BrowserInfo.ts +24 -24
- package/src/platform/browser/BrowserPlatform.ts +19 -19
- package/src/platform/browser/BrowserRequests.ts +6 -6
- package/src/platform/browser/BrowserWebSocket.ts +147 -147
- package/src/platform/browser/FbClient.ts +65 -65
- package/src/platform/browser/LocalStorageStore.ts +59 -59
- package/src/platform/index.ts +11 -11
- package/src/platform/requests.ts +76 -76
- package/src/store/BaseStore.ts +125 -125
- package/src/store/DataKinds.ts +6 -6
- package/src/store/IDataSourceUpdates.ts +68 -68
- package/src/store/InMemoryStore.ts +36 -36
- package/src/store/index.ts +5 -5
- package/src/store/serialization.ts +52 -52
- package/src/store/store.ts +37 -37
- package/src/utils/Emits.ts +75 -75
- package/src/utils/EventEmitter.ts +128 -128
- package/src/utils/IEventEmitter.ts +14 -14
- package/src/utils/Regex.ts +21 -21
- package/src/utils/ValueConverters.ts +55 -55
- package/src/utils/canonicalizeUri.ts +3 -3
- package/src/utils/debounce.ts +33 -33
- package/src/utils/http.ts +40 -40
- package/src/utils/index.ts +5 -5
- package/src/utils/isNullOrUndefined.ts +2 -2
- package/src/utils/serializeUser.ts +27 -27
- package/src/utils/sleep.ts +5 -5
- package/src/version.ts +1 -1
- package/dist/umd/featbit-js-client-sdk-3.0.13.js +0 -2
- package/dist/umd/featbit-js-client-sdk-3.0.13.js.map +0 -1
package/src/platform/requests.ts
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
// These are not full specifications of the interface, but instead subsets
|
|
2
|
-
// based on the functionality needed by the SDK. Exposure of the full standard
|
|
3
|
-
// would require much more per platform implementation for platforms that do not
|
|
4
|
-
// natively support fetch.
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Interface for headers that are part of a fetch response.
|
|
8
|
-
*/
|
|
9
|
-
export interface IHeaders {
|
|
10
|
-
/**
|
|
11
|
-
* Get a header by name.
|
|
12
|
-
*
|
|
13
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Headers/get
|
|
14
|
-
*
|
|
15
|
-
* @param name The name of the header to get.
|
|
16
|
-
*/
|
|
17
|
-
get(name: string): string | null;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Returns an iterator allowing iteration of all the keys contained
|
|
21
|
-
* in this object.
|
|
22
|
-
*
|
|
23
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Headers/keys
|
|
24
|
-
*
|
|
25
|
-
*/
|
|
26
|
-
keys(): Iterable<string>;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Returns an iterator allowing iteration of all the values contained
|
|
30
|
-
* in this object.
|
|
31
|
-
*
|
|
32
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Headers/values
|
|
33
|
-
*/
|
|
34
|
-
values(): Iterable<string>;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Returns an iterator allowing iteration of all the key-value pairs in
|
|
38
|
-
* the object.
|
|
39
|
-
*
|
|
40
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Headers/entries
|
|
41
|
-
*/
|
|
42
|
-
entries(): Iterable<[string, string]>;
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Returns true if the header is present.
|
|
46
|
-
* @param name The name of the header to check.
|
|
47
|
-
*/
|
|
48
|
-
has(name: string): boolean;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Interface for fetch responses.
|
|
53
|
-
*/
|
|
54
|
-
export interface IResponse {
|
|
55
|
-
status: number;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Read the response and provide it as a string.
|
|
59
|
-
*/
|
|
60
|
-
text(): Promise<string>;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Read the response and provide it as decoded json.
|
|
64
|
-
*/
|
|
65
|
-
json(): Promise<any>;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export interface IRequestOptions {
|
|
69
|
-
headers?: Record<string, string>;
|
|
70
|
-
method?: string;
|
|
71
|
-
body?: string;
|
|
72
|
-
timeout?: number;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export interface IRequests {
|
|
76
|
-
fetch(url: string, options?: IRequestOptions): Promise<IResponse>;
|
|
1
|
+
// These are not full specifications of the interface, but instead subsets
|
|
2
|
+
// based on the functionality needed by the SDK. Exposure of the full standard
|
|
3
|
+
// would require much more per platform implementation for platforms that do not
|
|
4
|
+
// natively support fetch.
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Interface for headers that are part of a fetch response.
|
|
8
|
+
*/
|
|
9
|
+
export interface IHeaders {
|
|
10
|
+
/**
|
|
11
|
+
* Get a header by name.
|
|
12
|
+
*
|
|
13
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Headers/get
|
|
14
|
+
*
|
|
15
|
+
* @param name The name of the header to get.
|
|
16
|
+
*/
|
|
17
|
+
get(name: string): string | null;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Returns an iterator allowing iteration of all the keys contained
|
|
21
|
+
* in this object.
|
|
22
|
+
*
|
|
23
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Headers/keys
|
|
24
|
+
*
|
|
25
|
+
*/
|
|
26
|
+
keys(): Iterable<string>;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Returns an iterator allowing iteration of all the values contained
|
|
30
|
+
* in this object.
|
|
31
|
+
*
|
|
32
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Headers/values
|
|
33
|
+
*/
|
|
34
|
+
values(): Iterable<string>;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Returns an iterator allowing iteration of all the key-value pairs in
|
|
38
|
+
* the object.
|
|
39
|
+
*
|
|
40
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Headers/entries
|
|
41
|
+
*/
|
|
42
|
+
entries(): Iterable<[string, string]>;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Returns true if the header is present.
|
|
46
|
+
* @param name The name of the header to check.
|
|
47
|
+
*/
|
|
48
|
+
has(name: string): boolean;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Interface for fetch responses.
|
|
53
|
+
*/
|
|
54
|
+
export interface IResponse {
|
|
55
|
+
status: number;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Read the response and provide it as a string.
|
|
59
|
+
*/
|
|
60
|
+
text(): Promise<string>;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Read the response and provide it as decoded json.
|
|
64
|
+
*/
|
|
65
|
+
json(): Promise<any>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface IRequestOptions {
|
|
69
|
+
headers?: Record<string, string>;
|
|
70
|
+
method?: string;
|
|
71
|
+
body?: string;
|
|
72
|
+
timeout?: number;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface IRequests {
|
|
76
|
+
fetch(url: string, options?: IRequestOptions): Promise<IResponse>;
|
|
77
77
|
}
|
package/src/store/BaseStore.ts
CHANGED
|
@@ -1,126 +1,126 @@
|
|
|
1
|
-
import { IStore } from "../platform";
|
|
2
|
-
import { IKeyedStoreItem, IStoreDataStorage, IStoreItem, IStoreKindData } from "./store";
|
|
3
|
-
import { IUser } from "../options";
|
|
4
|
-
import { IDataKind } from "../IDataKind";
|
|
5
|
-
|
|
6
|
-
export class BaseStore implements IStore {
|
|
7
|
-
protected store: IStoreDataStorage = {} as IStoreDataStorage;
|
|
8
|
-
|
|
9
|
-
protected initCalled = false;
|
|
10
|
-
|
|
11
|
-
protected _user: IUser = {} as IUser;
|
|
12
|
-
|
|
13
|
-
constructor() {
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async identify(user: IUser) {
|
|
17
|
-
this._user = {...user};
|
|
18
|
-
|
|
19
|
-
await this.saveUser();
|
|
20
|
-
await this.loadStoreFromStorage();
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
get user(): IUser {
|
|
24
|
-
return this._user;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
protected async addItem(kind: IDataKind, key: string, item: IStoreItem) {
|
|
28
|
-
let items = this.store[kind.namespace];
|
|
29
|
-
if (!items) {
|
|
30
|
-
items = {};
|
|
31
|
-
this.store[kind.namespace] = items;
|
|
32
|
-
}
|
|
33
|
-
if (Object.hasOwnProperty.call(items, key)) {
|
|
34
|
-
const old = items[key];
|
|
35
|
-
// we use <= here, the reason is that when a segment is changed, the upstream service would push the flag
|
|
36
|
-
// to client SDK with flag timestamp (version) instead of segment timestamp, so to ensure that the new flag value
|
|
37
|
-
// is saved, we need to use <=
|
|
38
|
-
if (!old || old.version <= item.version) {
|
|
39
|
-
items[key] = item;
|
|
40
|
-
}
|
|
41
|
-
} else {
|
|
42
|
-
items[key] = item;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (item.version > this.store.version) {
|
|
46
|
-
this.store.version = item.version;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
await this.dumpStoreToStorage();
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
get(kind: IDataKind, key: string): IStoreItem | null {
|
|
53
|
-
const items = this.store[kind.namespace];
|
|
54
|
-
if (items) {
|
|
55
|
-
if (Object.prototype.hasOwnProperty.call(items, key)) {
|
|
56
|
-
const item = items[key];
|
|
57
|
-
if (item) {
|
|
58
|
-
return item;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
all(kind: IDataKind): [IStoreKindData, number] {
|
|
66
|
-
const result: IStoreKindData = {};
|
|
67
|
-
const items = this.store[kind.namespace] ?? {};
|
|
68
|
-
Object.entries(items).forEach(([key, item]) => {
|
|
69
|
-
if (item) {
|
|
70
|
-
result[key] = <IStoreItem>item;
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
return [result, this.store.version];
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async init(allData: IStoreDataStorage) {
|
|
78
|
-
this.store = allData as IStoreDataStorage;
|
|
79
|
-
|
|
80
|
-
Object.keys(allData).map(namespace => {
|
|
81
|
-
Object.entries(allData[namespace]).forEach(([_, item]) => {
|
|
82
|
-
const ele = item as IStoreItem;
|
|
83
|
-
if (ele.version > this.store.version) {
|
|
84
|
-
this.store.version = ele.version;
|
|
85
|
-
}
|
|
86
|
-
})
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
await this.dumpStoreToStorage();
|
|
90
|
-
this.initCalled = true;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
async upsert(kind: IDataKind, data: IKeyedStoreItem) {
|
|
94
|
-
await this.addItem(kind, data.key, data);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
initialized(): boolean {
|
|
98
|
-
return this.initCalled;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/* eslint-disable class-methods-use-this */
|
|
102
|
-
close(): void {
|
|
103
|
-
// For the LocalStorage store this is a no-op.
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
get version(): number {
|
|
107
|
-
return this.store.version;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// This getter needs to be overridden in the child class
|
|
111
|
-
get description(): string {
|
|
112
|
-
return '';
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// This method needs to be overridden in the child class
|
|
116
|
-
protected async saveUser(): Promise<void> {
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// This method needs to be overridden in the child class
|
|
120
|
-
protected async loadStoreFromStorage(): Promise<void> {
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// This method needs to be overridden in the child class
|
|
124
|
-
protected async dumpStoreToStorage(): Promise<void> {
|
|
125
|
-
}
|
|
1
|
+
import { IStore } from "../platform";
|
|
2
|
+
import { IKeyedStoreItem, IStoreDataStorage, IStoreItem, IStoreKindData } from "./store";
|
|
3
|
+
import { IUser } from "../options";
|
|
4
|
+
import { IDataKind } from "../IDataKind";
|
|
5
|
+
|
|
6
|
+
export class BaseStore implements IStore {
|
|
7
|
+
protected store: IStoreDataStorage = {} as IStoreDataStorage;
|
|
8
|
+
|
|
9
|
+
protected initCalled = false;
|
|
10
|
+
|
|
11
|
+
protected _user: IUser = {} as IUser;
|
|
12
|
+
|
|
13
|
+
constructor() {
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async identify(user: IUser) {
|
|
17
|
+
this._user = {...user};
|
|
18
|
+
|
|
19
|
+
await this.saveUser();
|
|
20
|
+
await this.loadStoreFromStorage();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
get user(): IUser {
|
|
24
|
+
return this._user;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
protected async addItem(kind: IDataKind, key: string, item: IStoreItem) {
|
|
28
|
+
let items = this.store[kind.namespace];
|
|
29
|
+
if (!items) {
|
|
30
|
+
items = {};
|
|
31
|
+
this.store[kind.namespace] = items;
|
|
32
|
+
}
|
|
33
|
+
if (Object.hasOwnProperty.call(items, key)) {
|
|
34
|
+
const old = items[key];
|
|
35
|
+
// we use <= here, the reason is that when a segment is changed, the upstream service would push the flag
|
|
36
|
+
// to client SDK with flag timestamp (version) instead of segment timestamp, so to ensure that the new flag value
|
|
37
|
+
// is saved, we need to use <=
|
|
38
|
+
if (!old || old.version <= item.version) {
|
|
39
|
+
items[key] = item;
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
items[key] = item;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (item.version > this.store.version) {
|
|
46
|
+
this.store.version = item.version;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
await this.dumpStoreToStorage();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
get(kind: IDataKind, key: string): IStoreItem | null {
|
|
53
|
+
const items = this.store[kind.namespace];
|
|
54
|
+
if (items) {
|
|
55
|
+
if (Object.prototype.hasOwnProperty.call(items, key)) {
|
|
56
|
+
const item = items[key];
|
|
57
|
+
if (item) {
|
|
58
|
+
return item;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
all(kind: IDataKind): [IStoreKindData, number] {
|
|
66
|
+
const result: IStoreKindData = {};
|
|
67
|
+
const items = this.store[kind.namespace] ?? {};
|
|
68
|
+
Object.entries(items).forEach(([key, item]) => {
|
|
69
|
+
if (item) {
|
|
70
|
+
result[key] = <IStoreItem>item;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return [result, this.store.version];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async init(allData: IStoreDataStorage) {
|
|
78
|
+
this.store = allData as IStoreDataStorage;
|
|
79
|
+
|
|
80
|
+
Object.keys(allData).map(namespace => {
|
|
81
|
+
Object.entries(allData[namespace]).forEach(([_, item]) => {
|
|
82
|
+
const ele = item as IStoreItem;
|
|
83
|
+
if (ele.version > this.store.version) {
|
|
84
|
+
this.store.version = ele.version;
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
await this.dumpStoreToStorage();
|
|
90
|
+
this.initCalled = true;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async upsert(kind: IDataKind, data: IKeyedStoreItem) {
|
|
94
|
+
await this.addItem(kind, data.key, data);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
initialized(): boolean {
|
|
98
|
+
return this.initCalled;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* eslint-disable class-methods-use-this */
|
|
102
|
+
close(): void {
|
|
103
|
+
// For the LocalStorage store this is a no-op.
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
get version(): number {
|
|
107
|
+
return this.store.version;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// This getter needs to be overridden in the child class
|
|
111
|
+
get description(): string {
|
|
112
|
+
return '';
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// This method needs to be overridden in the child class
|
|
116
|
+
protected async saveUser(): Promise<void> {
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// This method needs to be overridden in the child class
|
|
120
|
+
protected async loadStoreFromStorage(): Promise<void> {
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// This method needs to be overridden in the child class
|
|
124
|
+
protected async dumpStoreToStorage(): Promise<void> {
|
|
125
|
+
}
|
|
126
126
|
}
|
package/src/store/DataKinds.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { IDataKind } from "../IDataKind";
|
|
2
|
-
|
|
3
|
-
export default class DataKinds {
|
|
4
|
-
static readonly Flags: IDataKind = {
|
|
5
|
-
namespace: 'flags'
|
|
6
|
-
};
|
|
1
|
+
import { IDataKind } from "../IDataKind";
|
|
2
|
+
|
|
3
|
+
export default class DataKinds {
|
|
4
|
+
static readonly Flags: IDataKind = {
|
|
5
|
+
namespace: 'flags'
|
|
6
|
+
};
|
|
7
7
|
}
|
|
@@ -1,68 +1,68 @@
|
|
|
1
|
-
import { IDataKind } from "../IDataKind";
|
|
2
|
-
import { IStoreDataStorage, IKeyedStoreItem } from "./store";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Interface that a data source implementation will use to push data into the SDK.
|
|
6
|
-
*
|
|
7
|
-
* The data source interacts with this object, rather than manipulating the data store directly, so
|
|
8
|
-
* that the SDK can perform any other necessary operations that must happen when data is updated.
|
|
9
|
-
*/
|
|
10
|
-
export interface IDataSourceUpdates {
|
|
11
|
-
/**
|
|
12
|
-
* Completely overwrites the current contents of the data store with a set of items for each
|
|
13
|
-
* collection.
|
|
14
|
-
*
|
|
15
|
-
* @param userKeyId
|
|
16
|
-
* The key ID of the user whose data is being updated.
|
|
17
|
-
*
|
|
18
|
-
* @param allData
|
|
19
|
-
* An object in which each key is the "namespace" of a collection (e.g. `"features"`) and
|
|
20
|
-
* the value is an object that maps keys to entities. The actual type of this parameter is
|
|
21
|
-
* `interfaces.FullDataSet<VersionedData>`.
|
|
22
|
-
*
|
|
23
|
-
* @param callback
|
|
24
|
-
* Will be called when the store has been initialized.
|
|
25
|
-
*/
|
|
26
|
-
init(userKeyId: string, allData: IStoreDataStorage, callback?: () => void): Promise<void>;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Compare old and new data, check if any update exists
|
|
30
|
-
* If update exists, send onUpdate events
|
|
31
|
-
*
|
|
32
|
-
* @param oldData
|
|
33
|
-
* An object in which each key is the "namespace" of a collection (e.g. `"features"`) and
|
|
34
|
-
* the value is an object that maps keys to entities. The actual type of this parameter is
|
|
35
|
-
* `interfaces.FullDataSet<VersionedData>`.
|
|
36
|
-
*
|
|
37
|
-
* @param newData
|
|
38
|
-
* An object in which each key is the "namespace" of a collection (e.g. `"features"`) and
|
|
39
|
-
* the value is an object that maps keys to entities. The actual type of this parameter is
|
|
40
|
-
* `interfaces.FullDataSet<VersionedData>`.
|
|
41
|
-
*
|
|
42
|
-
* @param callback
|
|
43
|
-
* Will be called when the store has been initialized.
|
|
44
|
-
*/
|
|
45
|
-
checkUpdates(oldData: IStoreDataStorage, newData: IStoreDataStorage, callback?: () => void): void;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Updates or inserts an item in the specified collection. For updates, the object will only be
|
|
49
|
-
* updated if the existing version is less than the new version.
|
|
50
|
-
*
|
|
51
|
-
* @param userKeyId
|
|
52
|
-
* The key ID of the user whose data is being updated.
|
|
53
|
-
*
|
|
54
|
-
* @param kind
|
|
55
|
-
* The type of data to be accessed. The actual type of this parameter is
|
|
56
|
-
* {@link IDataKind}.
|
|
57
|
-
*
|
|
58
|
-
* @param data
|
|
59
|
-
* The contents of the entity, as an object that can be converted to JSON. The store
|
|
60
|
-
* should check the `version` property of this object, and should *not* overwrite any
|
|
61
|
-
* existing data if the existing `version` is greater than or equal to that value.
|
|
62
|
-
* The actual type of this parameter is {@link IKeyedStoreItem}.
|
|
63
|
-
*
|
|
64
|
-
* @param callback
|
|
65
|
-
* Will be called after the upsert operation is complete.
|
|
66
|
-
*/
|
|
67
|
-
upsert(userKeyId: string, kind: IDataKind, data: IKeyedStoreItem, callback: () => void): Promise<void>;
|
|
68
|
-
}
|
|
1
|
+
import { IDataKind } from "../IDataKind";
|
|
2
|
+
import { IStoreDataStorage, IKeyedStoreItem } from "./store";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Interface that a data source implementation will use to push data into the SDK.
|
|
6
|
+
*
|
|
7
|
+
* The data source interacts with this object, rather than manipulating the data store directly, so
|
|
8
|
+
* that the SDK can perform any other necessary operations that must happen when data is updated.
|
|
9
|
+
*/
|
|
10
|
+
export interface IDataSourceUpdates {
|
|
11
|
+
/**
|
|
12
|
+
* Completely overwrites the current contents of the data store with a set of items for each
|
|
13
|
+
* collection.
|
|
14
|
+
*
|
|
15
|
+
* @param userKeyId
|
|
16
|
+
* The key ID of the user whose data is being updated.
|
|
17
|
+
*
|
|
18
|
+
* @param allData
|
|
19
|
+
* An object in which each key is the "namespace" of a collection (e.g. `"features"`) and
|
|
20
|
+
* the value is an object that maps keys to entities. The actual type of this parameter is
|
|
21
|
+
* `interfaces.FullDataSet<VersionedData>`.
|
|
22
|
+
*
|
|
23
|
+
* @param callback
|
|
24
|
+
* Will be called when the store has been initialized.
|
|
25
|
+
*/
|
|
26
|
+
init(userKeyId: string, allData: IStoreDataStorage, callback?: () => void): Promise<void>;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Compare old and new data, check if any update exists
|
|
30
|
+
* If update exists, send onUpdate events
|
|
31
|
+
*
|
|
32
|
+
* @param oldData
|
|
33
|
+
* An object in which each key is the "namespace" of a collection (e.g. `"features"`) and
|
|
34
|
+
* the value is an object that maps keys to entities. The actual type of this parameter is
|
|
35
|
+
* `interfaces.FullDataSet<VersionedData>`.
|
|
36
|
+
*
|
|
37
|
+
* @param newData
|
|
38
|
+
* An object in which each key is the "namespace" of a collection (e.g. `"features"`) and
|
|
39
|
+
* the value is an object that maps keys to entities. The actual type of this parameter is
|
|
40
|
+
* `interfaces.FullDataSet<VersionedData>`.
|
|
41
|
+
*
|
|
42
|
+
* @param callback
|
|
43
|
+
* Will be called when the store has been initialized.
|
|
44
|
+
*/
|
|
45
|
+
checkUpdates(oldData: IStoreDataStorage, newData: IStoreDataStorage, callback?: () => void): void;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Updates or inserts an item in the specified collection. For updates, the object will only be
|
|
49
|
+
* updated if the existing version is less than the new version.
|
|
50
|
+
*
|
|
51
|
+
* @param userKeyId
|
|
52
|
+
* The key ID of the user whose data is being updated.
|
|
53
|
+
*
|
|
54
|
+
* @param kind
|
|
55
|
+
* The type of data to be accessed. The actual type of this parameter is
|
|
56
|
+
* {@link IDataKind}.
|
|
57
|
+
*
|
|
58
|
+
* @param data
|
|
59
|
+
* The contents of the entity, as an object that can be converted to JSON. The store
|
|
60
|
+
* should check the `version` property of this object, and should *not* overwrite any
|
|
61
|
+
* existing data if the existing `version` is greater than or equal to that value.
|
|
62
|
+
* The actual type of this parameter is {@link IKeyedStoreItem}.
|
|
63
|
+
*
|
|
64
|
+
* @param callback
|
|
65
|
+
* Will be called after the upsert operation is complete.
|
|
66
|
+
*/
|
|
67
|
+
upsert(userKeyId: string, kind: IDataKind, data: IKeyedStoreItem, callback: () => void): Promise<void>;
|
|
68
|
+
}
|
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
import {
|
|
2
|
-
StoreStorageKey,
|
|
3
|
-
IStoreDataStorage
|
|
4
|
-
} from "./store";
|
|
5
|
-
import { BaseStore } from "./BaseStore";
|
|
6
|
-
|
|
7
|
-
export default class InMemoryStore extends BaseStore {
|
|
8
|
-
private allStores: { [DataStoreStorageKey: string]: IStoreDataStorage } = {};
|
|
9
|
-
|
|
10
|
-
constructor() {
|
|
11
|
-
super();
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/* eslint-disable class-methods-use-this */
|
|
15
|
-
close(): void {
|
|
16
|
-
// For the LocalStorage store this is a no-op.
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
get description(): string {
|
|
20
|
-
return 'in-memory-store'
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
protected async saveUser(): Promise<void> {
|
|
24
|
-
// For in-memory store, this is a no-op.
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
protected override async dumpStoreToStorage() {
|
|
28
|
-
const storageKey = `${StoreStorageKey}-${this._user.keyId}`;
|
|
29
|
-
this.allStores[storageKey] = {...this.store};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
protected override async loadStoreFromStorage() {
|
|
33
|
-
const storageKey = `${StoreStorageKey}-${this._user.keyId}`;
|
|
34
|
-
|
|
35
|
-
this.store = this.allStores[storageKey] ?? { flags: {}, version: 0 };
|
|
36
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
StoreStorageKey,
|
|
3
|
+
IStoreDataStorage
|
|
4
|
+
} from "./store";
|
|
5
|
+
import { BaseStore } from "./BaseStore";
|
|
6
|
+
|
|
7
|
+
export default class InMemoryStore extends BaseStore {
|
|
8
|
+
private allStores: { [DataStoreStorageKey: string]: IStoreDataStorage } = {};
|
|
9
|
+
|
|
10
|
+
constructor() {
|
|
11
|
+
super();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/* eslint-disable class-methods-use-this */
|
|
15
|
+
close(): void {
|
|
16
|
+
// For the LocalStorage store this is a no-op.
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
get description(): string {
|
|
20
|
+
return 'in-memory-store'
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
protected async saveUser(): Promise<void> {
|
|
24
|
+
// For in-memory store, this is a no-op.
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
protected override async dumpStoreToStorage() {
|
|
28
|
+
const storageKey = `${StoreStorageKey}-${this._user.keyId}`;
|
|
29
|
+
this.allStores[storageKey] = {...this.store};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
protected override async loadStoreFromStorage() {
|
|
33
|
+
const storageKey = `${StoreStorageKey}-${this._user.keyId}`;
|
|
34
|
+
|
|
35
|
+
this.store = this.allStores[storageKey] ?? { flags: {}, version: 0 };
|
|
36
|
+
}
|
|
37
37
|
}
|
package/src/store/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export * from './DataKinds';
|
|
2
|
-
export * from './IDataSourceUpdates';
|
|
3
|
-
export * from './InMemoryStore';
|
|
4
|
-
export * from './serialization';
|
|
5
|
-
export * from './store';
|
|
1
|
+
export * from './DataKinds';
|
|
2
|
+
export * from './IDataSourceUpdates';
|
|
3
|
+
export * from './InMemoryStore';
|
|
4
|
+
export * from './serialization';
|
|
5
|
+
export * from './store';
|
|
6
6
|
export * from './BaseStore';
|