@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.
Files changed (120) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +301 -301
  3. package/dist/esm/FbClientCore.d.ts +6 -5
  4. package/dist/esm/FbClientCore.d.ts.map +1 -1
  5. package/dist/esm/FbClientCore.js +27 -4
  6. package/dist/esm/FbClientCore.js.map +1 -1
  7. package/dist/esm/IFbClientCore.d.ts +8 -7
  8. package/dist/esm/IFbClientCore.d.ts.map +1 -1
  9. package/dist/esm/version.d.ts +1 -1
  10. package/dist/esm/version.d.ts.map +1 -1
  11. package/dist/esm/version.js +1 -1
  12. package/dist/esm/version.js.map +1 -1
  13. package/dist/umd/featbit-js-client-sdk-4.0.0.js +2 -0
  14. package/dist/umd/featbit-js-client-sdk-4.0.0.js.map +1 -0
  15. package/dist/umd/featbit-js-client-sdk.js +1 -1
  16. package/dist/umd/featbit-js-client-sdk.js.map +1 -1
  17. package/package.json +46 -46
  18. package/src/Configuration.ts +232 -232
  19. package/src/Context.ts +61 -61
  20. package/src/FbClientBuilder.ts +167 -167
  21. package/src/FbClientCore.ts +428 -405
  22. package/src/IContextProperty.ts +3 -3
  23. package/src/IDataKind.ts +11 -11
  24. package/src/IFbClient.ts +29 -29
  25. package/src/IFbClientCore.ts +291 -290
  26. package/src/IVersionedData.ts +18 -18
  27. package/src/bootstrap/IBootstrapProvider.ts +4 -4
  28. package/src/bootstrap/JsonBootstrapProvider.ts +34 -34
  29. package/src/bootstrap/NullBootstrapProvider.ts +20 -20
  30. package/src/bootstrap/index.ts +2 -2
  31. package/src/constants.ts +1 -1
  32. package/src/data-sources/DataSourceUpdates.ts +116 -116
  33. package/src/data-sources/createStreamListeners.ts +67 -67
  34. package/src/data-sources/index.ts +1 -1
  35. package/src/data-sync/DataSyncMode.ts +3 -3
  36. package/src/data-sync/IDataSynchronizer.ts +15 -15
  37. package/src/data-sync/IRequestor.ts +10 -10
  38. package/src/data-sync/NullDataSynchronizer.ts +14 -14
  39. package/src/data-sync/PollingDataSynchronizer.ts +125 -125
  40. package/src/data-sync/Requestor.ts +61 -61
  41. package/src/data-sync/WebSocketDataSynchronizer.ts +77 -77
  42. package/src/data-sync/index.ts +8 -8
  43. package/src/data-sync/types.ts +19 -19
  44. package/src/data-sync/utils.ts +31 -31
  45. package/src/errors.ts +47 -47
  46. package/src/evaluation/EvalResult.ts +35 -35
  47. package/src/evaluation/Evaluator.ts +26 -26
  48. package/src/evaluation/IEvalDetail.ts +23 -23
  49. package/src/evaluation/ReasonKinds.ts +9 -9
  50. package/src/evaluation/data/IFlag.ts +29 -29
  51. package/src/evaluation/index.ts +4 -4
  52. package/src/events/DefaultEventProcessor.ts +83 -83
  53. package/src/events/DefaultEventQueue.ts +49 -49
  54. package/src/events/DefaultEventSender.ts +73 -73
  55. package/src/events/DefaultEventSerializer.ts +11 -11
  56. package/src/events/EventDispatcher.ts +127 -127
  57. package/src/events/EventSerializer.ts +4 -4
  58. package/src/events/IEventProcessor.ts +8 -8
  59. package/src/events/IEventQueue.ts +16 -16
  60. package/src/events/IEventSender.ts +13 -13
  61. package/src/events/NullEventProcessor.ts +15 -15
  62. package/src/events/event.ts +129 -129
  63. package/src/events/index.ts +11 -11
  64. package/src/index.ts +21 -21
  65. package/src/integrations/TestLogger.ts +24 -24
  66. package/src/integrations/index.ts +1 -1
  67. package/src/integrations/test_data/FlagBuilder.ts +59 -59
  68. package/src/integrations/test_data/TestData.ts +57 -57
  69. package/src/integrations/test_data/TestDataSynchronizer.ts +49 -49
  70. package/src/integrations/test_data/index.ts +4 -4
  71. package/src/logging/BasicLogger.ts +108 -108
  72. package/src/logging/IBasicLoggerOptions.ts +46 -46
  73. package/src/logging/ILogger.ts +49 -49
  74. package/src/logging/LogLevel.ts +8 -8
  75. package/src/logging/SafeLogger.ts +69 -69
  76. package/src/logging/format.ts +154 -154
  77. package/src/logging/index.ts +5 -5
  78. package/src/options/ClientContext.ts +39 -39
  79. package/src/options/IClientContext.ts +53 -53
  80. package/src/options/IOptions.ts +123 -123
  81. package/src/options/IUser.ts +6 -6
  82. package/src/options/IValidatedOptions.ts +29 -29
  83. package/src/options/OptionMessages.ts +35 -35
  84. package/src/options/UserBuilder.ts +35 -35
  85. package/src/options/Validators.ts +300 -300
  86. package/src/options/index.ts +7 -7
  87. package/src/platform/IInfo.ts +102 -102
  88. package/src/platform/IPlatform.ts +20 -20
  89. package/src/platform/IStore.ts +112 -112
  90. package/src/platform/IWebSocket.ts +22 -22
  91. package/src/platform/browser/BrowserInfo.ts +24 -24
  92. package/src/platform/browser/BrowserPlatform.ts +19 -19
  93. package/src/platform/browser/BrowserRequests.ts +6 -6
  94. package/src/platform/browser/BrowserWebSocket.ts +147 -147
  95. package/src/platform/browser/FbClient.ts +65 -65
  96. package/src/platform/browser/LocalStorageStore.ts +59 -59
  97. package/src/platform/index.ts +11 -11
  98. package/src/platform/requests.ts +76 -76
  99. package/src/store/BaseStore.ts +125 -125
  100. package/src/store/DataKinds.ts +6 -6
  101. package/src/store/IDataSourceUpdates.ts +68 -68
  102. package/src/store/InMemoryStore.ts +36 -36
  103. package/src/store/index.ts +5 -5
  104. package/src/store/serialization.ts +52 -52
  105. package/src/store/store.ts +37 -37
  106. package/src/utils/Emits.ts +75 -75
  107. package/src/utils/EventEmitter.ts +128 -128
  108. package/src/utils/IEventEmitter.ts +14 -14
  109. package/src/utils/Regex.ts +21 -21
  110. package/src/utils/ValueConverters.ts +55 -55
  111. package/src/utils/canonicalizeUri.ts +3 -3
  112. package/src/utils/debounce.ts +33 -33
  113. package/src/utils/http.ts +40 -40
  114. package/src/utils/index.ts +5 -5
  115. package/src/utils/isNullOrUndefined.ts +2 -2
  116. package/src/utils/serializeUser.ts +27 -27
  117. package/src/utils/sleep.ts +5 -5
  118. package/src/version.ts +1 -1
  119. package/dist/umd/featbit-js-client-sdk-3.0.13.js +0 -2
  120. package/dist/umd/featbit-js-client-sdk-3.0.13.js.map +0 -1
@@ -1,148 +1,148 @@
1
- import { IWebSocket, IWebSocketConfig } from "../IWebSocket";
2
- import { Emits } from "../../utils/Emits";
3
- import { IEventEmitter } from "../../utils/IEventEmitter";
4
- import { EventEmitter } from "../../utils/EventEmitter";
5
- import { generateConnectionToken } from "../../data-sync/utils";
6
- import { StreamResponseEventType } from "../../data-sync/types";
7
- import { IUser } from "../../options/IUser";
8
-
9
- const socketConnectionIntervals = [1000, 3000, 5000, 7000, 11000, 13000, 30000, 60000];
10
-
11
- class BrowserWebSocket implements IWebSocket {
12
- emitter: IEventEmitter;
13
- private ws?: WebSocket;
14
- private retryCounter = 0;
15
- private closed: boolean = false;
16
-
17
- private _config: IWebSocketConfig = {} as IWebSocketConfig;
18
-
19
- constructor() {
20
- this.emitter = new EventEmitter();
21
- }
22
-
23
- identify(user: IUser) {
24
- this._config.user = user;
25
- this.doDataSync();
26
- }
27
-
28
- connect() {
29
- let that = this;
30
- const startTime = Date.now();
31
- const url = this._config.streamingUri.replace(/^http/, 'ws') + `?type=client&token=${ generateConnectionToken(this._config.sdkKey) }`;
32
- this.ws = new WebSocket(url);
33
-
34
- // Connection opened
35
- that.ws?.addEventListener('open', function (this: WebSocket, event) {
36
- // this is the websocket instance to which the current listener is binded to, it's different from that.socket
37
- that._config.logger.info(`WebSocket connection succeeded, connection time: ${ Date.now() - startTime } ms`);
38
- that.doDataSync();
39
- that.sendPingMessage();
40
- });
41
-
42
- // Connection closed
43
- that.ws?.addEventListener('close', function (event) {
44
- that._config.logger.warn('WebSocket closed');
45
- if (event.code === 4003) { // do not reconnect when 4003
46
- return;
47
- }
48
-
49
- that.reconnect();
50
- });
51
-
52
- // Connection error
53
- that.ws?.addEventListener('error', function (event) {
54
- // reconnect
55
- that._config.logger.debug('error');
56
- });
57
-
58
- // Listen for messages
59
- that.ws?.addEventListener('message', function (event) {
60
- const message = JSON.parse(event.data as string);
61
- if (message.messageType === 'data-sync') {
62
- if (message.data.userKeyId !== that._config.user.keyId) {
63
- // abort the message if message is not for the current user
64
- return;
65
- }
66
-
67
- switch (message.data.eventType) {
68
- case StreamResponseEventType.patch:
69
- that.emitter.emit('patch', message);
70
- break;
71
- case StreamResponseEventType.full:
72
- that.emitter.emit('put', message);
73
- break;
74
- }
75
- }
76
- });
77
- }
78
-
79
- close() {
80
- this.closed = true;
81
- this.ws?.close(4003, 'The client is closed by user');
82
- this.ws = undefined;
83
- }
84
-
85
- config(param: IWebSocketConfig) {
86
- if (param.emitter) {
87
- this.emitter = param.emitter;
88
- }
89
-
90
- this._config = {...param};
91
- }
92
-
93
- private sendPingMessage() {
94
- const payload = {
95
- messageType: 'ping',
96
- data: null
97
- };
98
-
99
- setTimeout(() => {
100
- try {
101
- if (this.ws?.readyState === WebSocket.OPEN) {
102
- this._config.logger.debug('sending ping')
103
- this.ws.send(JSON.stringify(payload));
104
- this.sendPingMessage();
105
- } else {
106
- this._config.logger.debug(`socket closed at ${ new Date() }`);
107
- }
108
- } catch (err) {
109
- this._config.logger.debug(err);
110
- }
111
- }, this._config.pingInterval);
112
- }
113
-
114
- private doDataSync() {
115
- const payload = {
116
- messageType: 'data-sync',
117
- data: {
118
- timestamp: this._config.getStoreTimestamp(),
119
- user: this._config.user
120
- }
121
- };
122
-
123
- try {
124
- if (this.ws?.readyState === WebSocket.OPEN) {
125
- this._config.logger.debug('requesting data');
126
- this.ws?.send(JSON.stringify(payload));
127
- } else {
128
- this._config.logger.error(`not requesting data because socket not open`);
129
- }
130
- } catch (err) {
131
- this._config.logger.debug(err);
132
- }
133
- }
134
-
135
- private reconnect() {
136
- if (!this.closed) {
137
- this.ws = undefined;
138
- const waitTime = socketConnectionIntervals[Math.min(this.retryCounter++, socketConnectionIntervals.length - 1)];
139
- this._config.logger.info(`The client will try to reconnect in ${ waitTime } milliseconds.`);
140
- setTimeout(() => {
141
- this._config.logger.info(`The client is trying to reconnect, flag evaluation results may be stale until reconnected, waited for: ${ waitTime } milliseconds`);
142
- this.connect();
143
- }, waitTime);
144
- }
145
- }
146
- }
147
-
1
+ import { IWebSocket, IWebSocketConfig } from "../IWebSocket";
2
+ import { Emits } from "../../utils/Emits";
3
+ import { IEventEmitter } from "../../utils/IEventEmitter";
4
+ import { EventEmitter } from "../../utils/EventEmitter";
5
+ import { generateConnectionToken } from "../../data-sync/utils";
6
+ import { StreamResponseEventType } from "../../data-sync/types";
7
+ import { IUser } from "../../options/IUser";
8
+
9
+ const socketConnectionIntervals = [1000, 3000, 5000, 7000, 11000, 13000, 30000, 60000];
10
+
11
+ class BrowserWebSocket implements IWebSocket {
12
+ emitter: IEventEmitter;
13
+ private ws?: WebSocket;
14
+ private retryCounter = 0;
15
+ private closed: boolean = false;
16
+
17
+ private _config: IWebSocketConfig = {} as IWebSocketConfig;
18
+
19
+ constructor() {
20
+ this.emitter = new EventEmitter();
21
+ }
22
+
23
+ identify(user: IUser) {
24
+ this._config.user = user;
25
+ this.doDataSync();
26
+ }
27
+
28
+ connect() {
29
+ let that = this;
30
+ const startTime = Date.now();
31
+ const url = this._config.streamingUri.replace(/^http/, 'ws') + `?type=client&token=${ generateConnectionToken(this._config.sdkKey) }`;
32
+ this.ws = new WebSocket(url);
33
+
34
+ // Connection opened
35
+ that.ws?.addEventListener('open', function (this: WebSocket, event) {
36
+ // this is the websocket instance to which the current listener is binded to, it's different from that.socket
37
+ that._config.logger.info(`WebSocket connection succeeded, connection time: ${ Date.now() - startTime } ms`);
38
+ that.doDataSync();
39
+ that.sendPingMessage();
40
+ });
41
+
42
+ // Connection closed
43
+ that.ws?.addEventListener('close', function (event) {
44
+ that._config.logger.warn('WebSocket closed');
45
+ if (event.code === 4003) { // do not reconnect when 4003
46
+ return;
47
+ }
48
+
49
+ that.reconnect();
50
+ });
51
+
52
+ // Connection error
53
+ that.ws?.addEventListener('error', function (event) {
54
+ // reconnect
55
+ that._config.logger.debug('error');
56
+ });
57
+
58
+ // Listen for messages
59
+ that.ws?.addEventListener('message', function (event) {
60
+ const message = JSON.parse(event.data as string);
61
+ if (message.messageType === 'data-sync') {
62
+ if (message.data.userKeyId !== that._config.user.keyId) {
63
+ // abort the message if message is not for the current user
64
+ return;
65
+ }
66
+
67
+ switch (message.data.eventType) {
68
+ case StreamResponseEventType.patch:
69
+ that.emitter.emit('patch', message);
70
+ break;
71
+ case StreamResponseEventType.full:
72
+ that.emitter.emit('put', message);
73
+ break;
74
+ }
75
+ }
76
+ });
77
+ }
78
+
79
+ close() {
80
+ this.closed = true;
81
+ this.ws?.close(4003, 'The client is closed by user');
82
+ this.ws = undefined;
83
+ }
84
+
85
+ config(param: IWebSocketConfig) {
86
+ if (param.emitter) {
87
+ this.emitter = param.emitter;
88
+ }
89
+
90
+ this._config = {...param};
91
+ }
92
+
93
+ private sendPingMessage() {
94
+ const payload = {
95
+ messageType: 'ping',
96
+ data: null
97
+ };
98
+
99
+ setTimeout(() => {
100
+ try {
101
+ if (this.ws?.readyState === WebSocket.OPEN) {
102
+ this._config.logger.debug('sending ping')
103
+ this.ws.send(JSON.stringify(payload));
104
+ this.sendPingMessage();
105
+ } else {
106
+ this._config.logger.debug(`socket closed at ${ new Date() }`);
107
+ }
108
+ } catch (err) {
109
+ this._config.logger.debug(err);
110
+ }
111
+ }, this._config.pingInterval);
112
+ }
113
+
114
+ private doDataSync() {
115
+ const payload = {
116
+ messageType: 'data-sync',
117
+ data: {
118
+ timestamp: this._config.getStoreTimestamp(),
119
+ user: this._config.user
120
+ }
121
+ };
122
+
123
+ try {
124
+ if (this.ws?.readyState === WebSocket.OPEN) {
125
+ this._config.logger.debug('requesting data');
126
+ this.ws?.send(JSON.stringify(payload));
127
+ } else {
128
+ this._config.logger.error(`not requesting data because socket not open`);
129
+ }
130
+ } catch (err) {
131
+ this._config.logger.debug(err);
132
+ }
133
+ }
134
+
135
+ private reconnect() {
136
+ if (!this.closed) {
137
+ this.ws = undefined;
138
+ const waitTime = socketConnectionIntervals[Math.min(this.retryCounter++, socketConnectionIntervals.length - 1)];
139
+ this._config.logger.info(`The client will try to reconnect in ${ waitTime } milliseconds.`);
140
+ setTimeout(() => {
141
+ this._config.logger.info(`The client is trying to reconnect, flag evaluation results may be stale until reconnected, waited for: ${ waitTime } milliseconds`);
142
+ this.connect();
143
+ }, waitTime);
144
+ }
145
+ }
146
+ }
147
+
148
148
  export default Emits(BrowserWebSocket);
@@ -1,66 +1,66 @@
1
- import { FbClientCore } from "../../FbClientCore";
2
- import { IOptions } from "../../options/IOptions";
3
- import { BasicLogger } from "../../logging/BasicLogger";
4
- import { EventEmitter } from "../../utils/EventEmitter";
5
- import { SafeLogger } from "../../logging/SafeLogger";
6
- import { Emits } from "../../utils/Emits";
7
- import { IEventEmitter } from "../../utils/IEventEmitter";
8
- import { BrowserPlatform } from "./BrowserPlatform";
9
- import LocalStorageStore from "./LocalStorageStore";
10
- import { IPlatform } from "../IPlatform";
11
-
12
- /**
13
- * @ignore
14
- */
15
- class FbClient extends FbClientCore {
16
- emitter: IEventEmitter;
17
-
18
- constructor(options: IOptions, platform: IPlatform | undefined = undefined) {
19
- const fallbackLogger = new BasicLogger({
20
- level: 'none',
21
- destination: console.log
22
- });
23
-
24
- const logger = options.logger ? new SafeLogger(options.logger, fallbackLogger) : fallbackLogger;
25
-
26
- const emitter = new EventEmitter(logger);
27
-
28
- let { store } = options;
29
- if (!store) {
30
- store = new LocalStorageStore(options);
31
- }
32
-
33
- super(
34
- {...options, logger, store },
35
- platform ?? new BrowserPlatform({...options, logger}),
36
- {
37
- onError: (err: Error) => {
38
- if (emitter.listenerCount('error')) {
39
- emitter.emit('error', err);
40
- }
41
- },
42
- onFailed: (err: Error) => {
43
- emitter.emit('failed', err);
44
- },
45
- onReady: () => {
46
- emitter.emit('ready');
47
- },
48
- onUpdate: (keys: string[]) => {
49
- emitter.emit('update', [keys]);
50
- keys.forEach((key) => emitter.emit(`update:${ key }`, key));
51
- },
52
- hasEventListeners: () =>
53
- emitter
54
- .eventNames()
55
- .some(
56
- (name) =>
57
- name === 'update' || (typeof name === 'string' && name.startsWith('update:')),
58
- ),
59
- },
60
- );
61
-
62
- this.emitter = emitter;
63
- }
64
- }
65
-
1
+ import { FbClientCore } from "../../FbClientCore";
2
+ import { IOptions } from "../../options/IOptions";
3
+ import { BasicLogger } from "../../logging/BasicLogger";
4
+ import { EventEmitter } from "../../utils/EventEmitter";
5
+ import { SafeLogger } from "../../logging/SafeLogger";
6
+ import { Emits } from "../../utils/Emits";
7
+ import { IEventEmitter } from "../../utils/IEventEmitter";
8
+ import { BrowserPlatform } from "./BrowserPlatform";
9
+ import LocalStorageStore from "./LocalStorageStore";
10
+ import { IPlatform } from "../IPlatform";
11
+
12
+ /**
13
+ * @ignore
14
+ */
15
+ class FbClient extends FbClientCore {
16
+ emitter: IEventEmitter;
17
+
18
+ constructor(options: IOptions, platform: IPlatform | undefined = undefined) {
19
+ const fallbackLogger = new BasicLogger({
20
+ level: 'none',
21
+ destination: console.log
22
+ });
23
+
24
+ const logger = options.logger ? new SafeLogger(options.logger, fallbackLogger) : fallbackLogger;
25
+
26
+ const emitter = new EventEmitter(logger);
27
+
28
+ let { store } = options;
29
+ if (!store) {
30
+ store = new LocalStorageStore(options);
31
+ }
32
+
33
+ super(
34
+ {...options, logger, store },
35
+ platform ?? new BrowserPlatform({...options, logger}),
36
+ {
37
+ onError: (err: Error) => {
38
+ if (emitter.listenerCount('error')) {
39
+ emitter.emit('error', err);
40
+ }
41
+ },
42
+ onFailed: (err: Error) => {
43
+ emitter.emit('failed', err);
44
+ },
45
+ onReady: () => {
46
+ emitter.emit('ready');
47
+ },
48
+ onUpdate: (keys: string[]) => {
49
+ emitter.emit('update', [keys]);
50
+ keys.forEach((key) => emitter.emit(`update:${ key }`, key));
51
+ },
52
+ hasEventListeners: () =>
53
+ emitter
54
+ .eventNames()
55
+ .some(
56
+ (name) =>
57
+ name === 'update' || (typeof name === 'string' && name.startsWith('update:')),
58
+ ),
59
+ },
60
+ );
61
+
62
+ this.emitter = emitter;
63
+ }
64
+ }
65
+
66
66
  export default Emits(FbClient);
@@ -1,60 +1,60 @@
1
- import {
2
- StoreStorageKey,
3
- IStoreDataStorage, CurrentUserStorageKey
4
- } from "../../store/store";
5
- import { IOptions } from "../../options/IOptions";
6
- import { BaseStore } from "../../store/BaseStore";
7
- import { ILogger } from "../../logging";
8
- import { serializeUser } from "../../utils/serializeUser";
9
-
10
- export default class LocalStorageStore extends BaseStore {
11
- private logger: ILogger;
12
-
13
- constructor(options: IOptions) {
14
- super();
15
-
16
- this.logger = options.logger!;
17
- }
18
-
19
- /* eslint-disable class-methods-use-this */
20
- close(): void {
21
- // For the LocalStorage store this is a no-op.
22
- }
23
-
24
- get description(): string {
25
- return 'local-storage-store'
26
- }
27
-
28
- // This method needs to be overridden in the child class
29
- protected async saveUser(): Promise<void> {
30
- localStorage.setItem(CurrentUserStorageKey, serializeUser(this._user));
31
- }
32
-
33
- protected override async dumpStoreToStorage() {
34
- const storageKey = `${StoreStorageKey}-${this._user.keyId}`;
35
- localStorage.setItem(storageKey, JSON.stringify(this.store));
36
- }
37
-
38
- protected override async loadStoreFromStorage() {
39
- const storageKey = `${StoreStorageKey}-${this._user.keyId}`;
40
- const dataStoreStr = localStorage.getItem(storageKey);
41
- let store: IStoreDataStorage | null = null;
42
-
43
- try {
44
- if (dataStoreStr && dataStoreStr.trim().length > 0) {
45
- store = JSON.parse(dataStoreStr);
46
- }
47
- } catch (err) {
48
- this.logger.error(`error while loading local data store: ${storageKey}`, err);
49
- }
50
-
51
- if (!!store) {
52
- this.store = store;
53
- } else {
54
- this.store = {
55
- flags: {},
56
- version: 0
57
- };
58
- }
59
- }
1
+ import {
2
+ StoreStorageKey,
3
+ IStoreDataStorage, CurrentUserStorageKey
4
+ } from "../../store/store";
5
+ import { IOptions } from "../../options/IOptions";
6
+ import { BaseStore } from "../../store/BaseStore";
7
+ import { ILogger } from "../../logging";
8
+ import { serializeUser } from "../../utils/serializeUser";
9
+
10
+ export default class LocalStorageStore extends BaseStore {
11
+ private logger: ILogger;
12
+
13
+ constructor(options: IOptions) {
14
+ super();
15
+
16
+ this.logger = options.logger!;
17
+ }
18
+
19
+ /* eslint-disable class-methods-use-this */
20
+ close(): void {
21
+ // For the LocalStorage store this is a no-op.
22
+ }
23
+
24
+ get description(): string {
25
+ return 'local-storage-store'
26
+ }
27
+
28
+ // This method needs to be overridden in the child class
29
+ protected async saveUser(): Promise<void> {
30
+ localStorage.setItem(CurrentUserStorageKey, serializeUser(this._user));
31
+ }
32
+
33
+ protected override async dumpStoreToStorage() {
34
+ const storageKey = `${StoreStorageKey}-${this._user.keyId}`;
35
+ localStorage.setItem(storageKey, JSON.stringify(this.store));
36
+ }
37
+
38
+ protected override async loadStoreFromStorage() {
39
+ const storageKey = `${StoreStorageKey}-${this._user.keyId}`;
40
+ const dataStoreStr = localStorage.getItem(storageKey);
41
+ let store: IStoreDataStorage | null = null;
42
+
43
+ try {
44
+ if (dataStoreStr && dataStoreStr.trim().length > 0) {
45
+ store = JSON.parse(dataStoreStr);
46
+ }
47
+ } catch (err) {
48
+ this.logger.error(`error while loading local data store: ${storageKey}`, err);
49
+ }
50
+
51
+ if (!!store) {
52
+ this.store = store;
53
+ } else {
54
+ this.store = {
55
+ flags: {},
56
+ version: 0
57
+ };
58
+ }
59
+ }
60
60
  }
@@ -1,12 +1,12 @@
1
- export * from './IInfo';
2
- export * from './IStore';
3
- export * from './IPlatform';
4
- export * from './IWebSocket';
5
- export * from './requests';
6
- export * from './browser/BrowserRequests';
7
-
8
- import BrowserWebSocket from './browser/BrowserWebSocket';
9
-
10
- export {
11
- BrowserWebSocket
1
+ export * from './IInfo';
2
+ export * from './IStore';
3
+ export * from './IPlatform';
4
+ export * from './IWebSocket';
5
+ export * from './requests';
6
+ export * from './browser/BrowserRequests';
7
+
8
+ import BrowserWebSocket from './browser/BrowserWebSocket';
9
+
10
+ export {
11
+ BrowserWebSocket
12
12
  };