@featbit/js-client-sdk 3.0.11 → 3.0.13

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 (147) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +301 -301
  3. package/dist/esm/FbClientCore.d.ts.map +1 -1
  4. package/dist/esm/FbClientCore.js +1 -1
  5. package/dist/esm/FbClientCore.js.map +1 -1
  6. package/dist/esm/data-sources/DataSourceUpdates.d.ts +2 -2
  7. package/dist/esm/data-sources/DataSourceUpdates.d.ts.map +1 -1
  8. package/dist/esm/data-sources/DataSourceUpdates.js +55 -51
  9. package/dist/esm/data-sources/DataSourceUpdates.js.map +1 -1
  10. package/dist/esm/data-sources/createStreamListeners.d.ts +0 -9
  11. package/dist/esm/data-sources/createStreamListeners.d.ts.map +1 -1
  12. package/dist/esm/data-sources/createStreamListeners.js +10 -10
  13. package/dist/esm/data-sources/createStreamListeners.js.map +1 -1
  14. package/dist/esm/data-sync/IDataSynchronizer.d.ts +1 -1
  15. package/dist/esm/data-sync/IDataSynchronizer.d.ts.map +1 -1
  16. package/dist/esm/data-sync/NullDataSynchronizer.d.ts +1 -1
  17. package/dist/esm/data-sync/NullDataSynchronizer.d.ts.map +1 -1
  18. package/dist/esm/data-sync/NullDataSynchronizer.js +11 -0
  19. package/dist/esm/data-sync/NullDataSynchronizer.js.map +1 -1
  20. package/dist/esm/data-sync/PollingDataSynchronizer.d.ts +1 -1
  21. package/dist/esm/data-sync/PollingDataSynchronizer.d.ts.map +1 -1
  22. package/dist/esm/data-sync/PollingDataSynchronizer.js +42 -17
  23. package/dist/esm/data-sync/PollingDataSynchronizer.js.map +1 -1
  24. package/dist/esm/data-sync/WebSocketDataSynchronizer.d.ts +2 -1
  25. package/dist/esm/data-sync/WebSocketDataSynchronizer.d.ts.map +1 -1
  26. package/dist/esm/data-sync/WebSocketDataSynchronizer.js +20 -6
  27. package/dist/esm/data-sync/WebSocketDataSynchronizer.js.map +1 -1
  28. package/dist/esm/data-sync/types.d.ts +1 -1
  29. package/dist/esm/data-sync/types.d.ts.map +1 -1
  30. package/dist/esm/integrations/test_data/TestDataSynchronizer.d.ts +1 -1
  31. package/dist/esm/integrations/test_data/TestDataSynchronizer.d.ts.map +1 -1
  32. package/dist/esm/integrations/test_data/TestDataSynchronizer.js +3 -1
  33. package/dist/esm/integrations/test_data/TestDataSynchronizer.js.map +1 -1
  34. package/dist/esm/platform/browser/BrowserWebSocket.d.ts.map +1 -1
  35. package/dist/esm/platform/browser/BrowserWebSocket.js +4 -0
  36. package/dist/esm/platform/browser/BrowserWebSocket.js.map +1 -1
  37. package/dist/esm/store/IDataSourceUpdates.d.ts +2 -2
  38. package/dist/esm/store/IDataSourceUpdates.d.ts.map +1 -1
  39. package/dist/esm/version.d.ts +1 -1
  40. package/dist/esm/version.js +1 -1
  41. package/dist/umd/{featbit-js-client-sdk-3.0.11.js → featbit-js-client-sdk-3.0.13.js} +2 -2
  42. package/dist/umd/featbit-js-client-sdk-3.0.13.js.map +1 -0
  43. package/dist/umd/featbit-js-client-sdk.js +1 -1
  44. package/dist/umd/featbit-js-client-sdk.js.map +1 -1
  45. package/package.json +46 -46
  46. package/src/Configuration.ts +232 -232
  47. package/src/Context.ts +61 -61
  48. package/src/FbClientBuilder.ts +167 -167
  49. package/src/FbClientCore.ts +405 -401
  50. package/src/IContextProperty.ts +3 -3
  51. package/src/IDataKind.ts +11 -11
  52. package/src/IFbClient.ts +29 -29
  53. package/src/IFbClientCore.ts +290 -290
  54. package/src/IVersionedData.ts +18 -18
  55. package/src/bootstrap/IBootstrapProvider.ts +4 -4
  56. package/src/bootstrap/JsonBootstrapProvider.ts +34 -34
  57. package/src/bootstrap/NullBootstrapProvider.ts +20 -20
  58. package/src/bootstrap/index.ts +2 -2
  59. package/src/constants.ts +1 -1
  60. package/src/data-sources/DataSourceUpdates.ts +116 -116
  61. package/src/data-sources/createStreamListeners.ts +67 -66
  62. package/src/data-sources/index.ts +1 -1
  63. package/src/data-sync/DataSyncMode.ts +3 -3
  64. package/src/data-sync/IDataSynchronizer.ts +15 -15
  65. package/src/data-sync/IRequestor.ts +10 -10
  66. package/src/data-sync/NullDataSynchronizer.ts +14 -14
  67. package/src/data-sync/PollingDataSynchronizer.ts +125 -111
  68. package/src/data-sync/Requestor.ts +61 -61
  69. package/src/data-sync/WebSocketDataSynchronizer.ts +77 -73
  70. package/src/data-sync/index.ts +8 -8
  71. package/src/data-sync/types.ts +19 -19
  72. package/src/data-sync/utils.ts +31 -31
  73. package/src/errors.ts +47 -47
  74. package/src/evaluation/EvalResult.ts +35 -35
  75. package/src/evaluation/Evaluator.ts +26 -26
  76. package/src/evaluation/IEvalDetail.ts +23 -23
  77. package/src/evaluation/ReasonKinds.ts +9 -9
  78. package/src/evaluation/data/IFlag.ts +29 -29
  79. package/src/evaluation/index.ts +4 -4
  80. package/src/events/DefaultEventProcessor.ts +83 -83
  81. package/src/events/DefaultEventQueue.ts +49 -49
  82. package/src/events/DefaultEventSender.ts +73 -73
  83. package/src/events/DefaultEventSerializer.ts +11 -11
  84. package/src/events/EventDispatcher.ts +127 -127
  85. package/src/events/EventSerializer.ts +4 -4
  86. package/src/events/IEventProcessor.ts +8 -8
  87. package/src/events/IEventQueue.ts +16 -16
  88. package/src/events/IEventSender.ts +13 -13
  89. package/src/events/NullEventProcessor.ts +15 -15
  90. package/src/events/event.ts +129 -129
  91. package/src/events/index.ts +11 -11
  92. package/src/index.ts +21 -21
  93. package/src/integrations/TestLogger.ts +24 -24
  94. package/src/integrations/index.ts +1 -1
  95. package/src/integrations/test_data/FlagBuilder.ts +59 -59
  96. package/src/integrations/test_data/TestData.ts +57 -57
  97. package/src/integrations/test_data/TestDataSynchronizer.ts +49 -49
  98. package/src/integrations/test_data/index.ts +4 -4
  99. package/src/logging/BasicLogger.ts +108 -108
  100. package/src/logging/IBasicLoggerOptions.ts +46 -46
  101. package/src/logging/ILogger.ts +49 -49
  102. package/src/logging/LogLevel.ts +8 -8
  103. package/src/logging/SafeLogger.ts +69 -69
  104. package/src/logging/format.ts +154 -154
  105. package/src/logging/index.ts +5 -5
  106. package/src/options/ClientContext.ts +39 -39
  107. package/src/options/IClientContext.ts +53 -53
  108. package/src/options/IOptions.ts +123 -123
  109. package/src/options/IUser.ts +6 -6
  110. package/src/options/IValidatedOptions.ts +29 -29
  111. package/src/options/OptionMessages.ts +35 -35
  112. package/src/options/UserBuilder.ts +35 -35
  113. package/src/options/Validators.ts +300 -300
  114. package/src/options/index.ts +7 -7
  115. package/src/platform/IInfo.ts +102 -102
  116. package/src/platform/IPlatform.ts +20 -20
  117. package/src/platform/IStore.ts +112 -112
  118. package/src/platform/IWebSocket.ts +22 -22
  119. package/src/platform/browser/BrowserInfo.ts +24 -24
  120. package/src/platform/browser/BrowserPlatform.ts +19 -19
  121. package/src/platform/browser/BrowserRequests.ts +6 -6
  122. package/src/platform/browser/BrowserWebSocket.ts +147 -142
  123. package/src/platform/browser/FbClient.ts +65 -65
  124. package/src/platform/browser/LocalStorageStore.ts +59 -59
  125. package/src/platform/index.ts +11 -11
  126. package/src/platform/requests.ts +76 -76
  127. package/src/store/BaseStore.ts +125 -125
  128. package/src/store/DataKinds.ts +6 -6
  129. package/src/store/IDataSourceUpdates.ts +68 -68
  130. package/src/store/InMemoryStore.ts +36 -36
  131. package/src/store/index.ts +5 -5
  132. package/src/store/serialization.ts +52 -52
  133. package/src/store/store.ts +37 -37
  134. package/src/utils/Emits.ts +75 -75
  135. package/src/utils/EventEmitter.ts +128 -128
  136. package/src/utils/IEventEmitter.ts +14 -14
  137. package/src/utils/Regex.ts +21 -21
  138. package/src/utils/ValueConverters.ts +55 -55
  139. package/src/utils/canonicalizeUri.ts +3 -3
  140. package/src/utils/debounce.ts +33 -33
  141. package/src/utils/http.ts +40 -40
  142. package/src/utils/index.ts +5 -5
  143. package/src/utils/isNullOrUndefined.ts +2 -2
  144. package/src/utils/serializeUser.ts +27 -27
  145. package/src/utils/sleep.ts +5 -5
  146. package/src/version.ts +1 -1
  147. package/dist/umd/featbit-js-client-sdk-3.0.11.js.map +0 -1
@@ -1,52 +1,52 @@
1
- import { IFlag } from "../evaluation/data/IFlag";
2
- import DataKinds from "./DataKinds";
3
- import { IVersionedData } from "../IVersionedData";
4
- import { IDataKind } from "../IDataKind";
5
-
6
- export interface Flags {
7
- flags: { [name: string]: IFlag };
8
- }
9
-
10
- type VersionedFlag = IVersionedData & IFlag;
11
-
12
- export interface IPatchData {
13
- data: VersionedFlag;
14
- kind: IDataKind;
15
- }
16
-
17
- /**
18
- * @internal
19
- */
20
- export function deserializeAll(flags: IFlag[]): Flags {
21
- const result = {
22
- [DataKinds.Flags.namespace]: {}
23
- };
24
-
25
- if (flags?.length) {
26
- result[DataKinds.Flags.namespace] = flags.reduce((acc: any, cur: any) => {
27
- acc[cur.id] = {...cur, version: cur.timestamp || 0, key: cur.id, variations: cur.variationOptions};
28
- return acc;
29
- }, {});
30
- }
31
-
32
- return result as any as Flags;
33
- }
34
-
35
- /**
36
- * @internal
37
- */
38
- export function deserializePatch(flags: IFlag[]): IPatchData[] {
39
- const result = [
40
- ...flags?.map(item => ({
41
- data: {
42
- ...item,
43
- version:item.timestamp,
44
- key: item.id,
45
- variations: item.variationOptions
46
- },
47
- kind: DataKinds.Flags
48
- })) || []
49
- ];
50
-
51
- return result as any as IPatchData[];
52
- }
1
+ import { IFlag } from "../evaluation/data/IFlag";
2
+ import DataKinds from "./DataKinds";
3
+ import { IVersionedData } from "../IVersionedData";
4
+ import { IDataKind } from "../IDataKind";
5
+
6
+ export interface Flags {
7
+ flags: { [name: string]: IFlag };
8
+ }
9
+
10
+ type VersionedFlag = IVersionedData & IFlag;
11
+
12
+ export interface IPatchData {
13
+ data: VersionedFlag;
14
+ kind: IDataKind;
15
+ }
16
+
17
+ /**
18
+ * @internal
19
+ */
20
+ export function deserializeAll(flags: IFlag[]): Flags {
21
+ const result = {
22
+ [DataKinds.Flags.namespace]: {}
23
+ };
24
+
25
+ if (flags?.length) {
26
+ result[DataKinds.Flags.namespace] = flags.reduce((acc: any, cur: any) => {
27
+ acc[cur.id] = {...cur, version: cur.timestamp || 0, key: cur.id, variations: cur.variationOptions};
28
+ return acc;
29
+ }, {});
30
+ }
31
+
32
+ return result as any as Flags;
33
+ }
34
+
35
+ /**
36
+ * @internal
37
+ */
38
+ export function deserializePatch(flags: IFlag[]): IPatchData[] {
39
+ const result = [
40
+ ...flags?.map(item => ({
41
+ data: {
42
+ ...item,
43
+ version:item.timestamp,
44
+ key: item.id,
45
+ variations: item.variationOptions
46
+ },
47
+ kind: DataKinds.Flags
48
+ })) || []
49
+ ];
50
+
51
+ return result as any as IPatchData[];
52
+ }
@@ -1,38 +1,38 @@
1
- export const StoreStorageKey = 'fb-datastore';
2
-
3
- export const CurrentUserStorageKey = 'fb-user';
4
-
5
- /**
6
- * Represents an item which can be stored in the feature store.
7
- */
8
- export interface IStoreItem {
9
- version: number;
10
-
11
- // The actual data associated with the item.
12
- [attribute: string]: any;
13
- }
14
-
15
- /**
16
- * When upserting an item it must contain a key.
17
- */
18
- export interface IKeyedStoreItem extends IStoreItem {
19
- key: string;
20
- }
21
-
22
- /**
23
- * Represents the storage for a single kind of data. e.g. 'flag' or 'segment'.
24
- */
25
- export interface IStoreKindData {
26
- [key: string]: IStoreItem;
27
- }
28
-
29
- /**
30
- * Represents the storage for the full data store.
31
- */
32
- export interface IStoreDataStorage {
33
- flags: IStoreKindData;
34
- version: number;
35
-
36
- // This attribute is to ingore the type check error
37
- [attribute: string]: any;
1
+ export const StoreStorageKey = 'fb-datastore';
2
+
3
+ export const CurrentUserStorageKey = 'fb-user';
4
+
5
+ /**
6
+ * Represents an item which can be stored in the feature store.
7
+ */
8
+ export interface IStoreItem {
9
+ version: number;
10
+
11
+ // The actual data associated with the item.
12
+ [attribute: string]: any;
13
+ }
14
+
15
+ /**
16
+ * When upserting an item it must contain a key.
17
+ */
18
+ export interface IKeyedStoreItem extends IStoreItem {
19
+ key: string;
20
+ }
21
+
22
+ /**
23
+ * Represents the storage for a single kind of data. e.g. 'flag' or 'segment'.
24
+ */
25
+ export interface IStoreKindData {
26
+ [key: string]: IStoreItem;
27
+ }
28
+
29
+ /**
30
+ * Represents the storage for the full data store.
31
+ */
32
+ export interface IStoreDataStorage {
33
+ flags: IStoreKindData;
34
+ version: number;
35
+
36
+ // This attribute is to ingore the type check error
37
+ [attribute: string]: any;
38
38
  }
@@ -1,76 +1,76 @@
1
- import { IEventEmitter } from "./IEventEmitter";
2
-
3
- export type EventableConstructor<T = {}> = new (...args: any[]) => T;
4
- export type Eventable = EventableConstructor<{ emitter: IEventEmitter }>;
5
-
6
- /**
7
- * Adds the implementation of an event emitter to something that contains
8
- * a field of `emitter` with type `EventEmitter`.
9
- * @param Base The class to derive the mixin from.
10
- * @returns A class extending the base with an event emitter.
11
- */
12
- export function Emits<TBase extends Eventable>(Base: TBase) {
13
- return class WithEvents extends Base implements IEventEmitter {
14
- on(eventName: string | symbol, listener: (...args: any[]) => void, context?: any): this {
15
- this.emitter.on(eventName, listener, context);
16
- return this;
17
- }
18
-
19
- addListener(eventName: string | symbol, listener: (...args: any[]) => void, context?: any): this {
20
- this.emitter.addListener(eventName, listener, context);
21
- return this;
22
- }
23
-
24
- once(eventName: string | symbol, listener: (...args: any[]) => void, context?: any): this {
25
- this.emitter.once(eventName, listener, context);
26
- return this;
27
- }
28
-
29
- removeListener(eventName: string | symbol, listener: (...args: any[]) => void, context?: any): this {
30
- this.emitter.removeListener(eventName, listener, context);
31
- return this;
32
- }
33
-
34
- off(eventName: string | symbol, listener: (...args: any) => void, context?: any): this {
35
- this.emitter.off(eventName, listener, context);
36
- return this;
37
- }
38
-
39
- removeAllListeners(event?: string | symbol): this {
40
- this.emitter.removeAllListeners(event);
41
- return this;
42
- }
43
-
44
- listeners(eventName: string | symbol): Function[] {
45
- return this.emitter.listeners(eventName);
46
- }
47
-
48
- emit(eventName: string | symbol, ...args: any[]): this {
49
- this.emitter.emit(eventName, args);
50
- return this;
51
- }
52
-
53
- listenerCount(eventName: string | symbol): number {
54
- return this.emitter.listenerCount(eventName);
55
- }
56
-
57
- prependListener(eventName: string | symbol, listener: (...args: any[]) => void, context?: any): this {
58
- this.emitter.prependListener(eventName, listener, context);
59
- return this;
60
- }
61
-
62
- prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void, context?: any): this {
63
- this.emitter.prependOnceListener(eventName, listener, context);
64
- return this;
65
- }
66
-
67
- eventNames(): (string | symbol)[] {
68
- return this.emitter.eventNames();
69
- }
70
-
71
- maybeReportError (error: any): this {
72
- this.emitter.maybeReportError(error);
73
- return this;
74
- }
75
- };
1
+ import { IEventEmitter } from "./IEventEmitter";
2
+
3
+ export type EventableConstructor<T = {}> = new (...args: any[]) => T;
4
+ export type Eventable = EventableConstructor<{ emitter: IEventEmitter }>;
5
+
6
+ /**
7
+ * Adds the implementation of an event emitter to something that contains
8
+ * a field of `emitter` with type `EventEmitter`.
9
+ * @param Base The class to derive the mixin from.
10
+ * @returns A class extending the base with an event emitter.
11
+ */
12
+ export function Emits<TBase extends Eventable>(Base: TBase) {
13
+ return class WithEvents extends Base implements IEventEmitter {
14
+ on(eventName: string | symbol, listener: (...args: any[]) => void, context?: any): this {
15
+ this.emitter.on(eventName, listener, context);
16
+ return this;
17
+ }
18
+
19
+ addListener(eventName: string | symbol, listener: (...args: any[]) => void, context?: any): this {
20
+ this.emitter.addListener(eventName, listener, context);
21
+ return this;
22
+ }
23
+
24
+ once(eventName: string | symbol, listener: (...args: any[]) => void, context?: any): this {
25
+ this.emitter.once(eventName, listener, context);
26
+ return this;
27
+ }
28
+
29
+ removeListener(eventName: string | symbol, listener: (...args: any[]) => void, context?: any): this {
30
+ this.emitter.removeListener(eventName, listener, context);
31
+ return this;
32
+ }
33
+
34
+ off(eventName: string | symbol, listener: (...args: any) => void, context?: any): this {
35
+ this.emitter.off(eventName, listener, context);
36
+ return this;
37
+ }
38
+
39
+ removeAllListeners(event?: string | symbol): this {
40
+ this.emitter.removeAllListeners(event);
41
+ return this;
42
+ }
43
+
44
+ listeners(eventName: string | symbol): Function[] {
45
+ return this.emitter.listeners(eventName);
46
+ }
47
+
48
+ emit(eventName: string | symbol, ...args: any[]): this {
49
+ this.emitter.emit(eventName, args);
50
+ return this;
51
+ }
52
+
53
+ listenerCount(eventName: string | symbol): number {
54
+ return this.emitter.listenerCount(eventName);
55
+ }
56
+
57
+ prependListener(eventName: string | symbol, listener: (...args: any[]) => void, context?: any): this {
58
+ this.emitter.prependListener(eventName, listener, context);
59
+ return this;
60
+ }
61
+
62
+ prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void, context?: any): this {
63
+ this.emitter.prependOnceListener(eventName, listener, context);
64
+ return this;
65
+ }
66
+
67
+ eventNames(): (string | symbol)[] {
68
+ return this.emitter.eventNames();
69
+ }
70
+
71
+ maybeReportError (error: any): this {
72
+ this.emitter.maybeReportError(error);
73
+ return this;
74
+ }
75
+ };
76
76
  }
@@ -1,129 +1,129 @@
1
- import { ILogger } from "../logging/ILogger";
2
- import { IEventEmitter } from "./IEventEmitter";
3
-
4
- interface Events {
5
- [key: string | symbol]: {
6
- handler: (...args: any[]) => void;
7
- context: any;
8
- }[];
9
- }
10
-
11
- export class EventEmitter implements IEventEmitter {
12
- private events: Events = {};
13
-
14
- constructor(private logger?: ILogger) {}
15
-
16
- private listeningTo (event: string) {
17
- return !!this.events[event];
18
- }
19
-
20
- on (event: string | symbol, handler: (...args: any[]) => void, context?: any): this {
21
- this.events[event] = this.events[event] || [];
22
- this.events[event] = this.events[event].concat({
23
- handler: handler,
24
- context: context,
25
- });
26
-
27
- return this;
28
- }
29
-
30
- addListener (event: string | symbol, handler: (...args: any[]) => void, context?: any): this {
31
- return this.on(event, handler, context);
32
- }
33
-
34
- once (event: string | symbol, handler: (...args: any[]) => void, context?: any): this {
35
- const onceHandler = (...args: any[]) => {
36
- this.off(event, onceHandler, context);
37
- handler.apply(context, args);
38
- };
39
- return this.on(event, onceHandler, context);
40
- }
41
-
42
- off (event: string | symbol, handler: (...args: any[]) => void, context?: any): this {
43
- if (!this.events[event]) {
44
- return this;
45
- }
46
- for (let i = 0; i < this.events[event].length; i++) {
47
- if (this.events[event][i].handler === handler && this.events[event][i].context === context) {
48
- this.events[event] = this.events[event].slice(0, i).concat(this.events[event].slice(i + 1));
49
- }
50
- }
51
-
52
- return this;
53
- }
54
-
55
- removeListener (event: string | symbol, handler: (...args: any[]) => void, context?: any): this {
56
- return this.off(event, handler, context);
57
- }
58
-
59
- removeAllListeners (event?: string | symbol): this {
60
- if (event) {
61
- delete this.events[event];
62
- } else {
63
- this.events = {};
64
- }
65
-
66
- return this;
67
- }
68
-
69
- listeners (event: string | symbol): Function[] {
70
- return this.events[event] ? this.events[event].map((event) => event.handler) : [];
71
- }
72
-
73
- emit (event: string | symbol, ...args: any[]): this {
74
- if (!this.events[event]) {
75
- return this;
76
- }
77
- // Copy the list of handlers before iterating, in case any handler adds or removes another handler.
78
- // Any such changes should not affect what we do here-- we want to notify every handler that existed
79
- // at the moment that the event was fired.
80
- const copiedHandlers = [...this.events[event]];
81
- for (let i = 0; i < copiedHandlers.length; i++) {
82
- copiedHandlers[i].handler.apply(copiedHandlers[i].context, Array.prototype.slice.call(arguments, 1));
83
- }
84
-
85
- return this;
86
- }
87
-
88
- listenerCount (event: string | symbol): number {
89
- return this.events[event] ? this.events[event].length : 0;
90
- }
91
-
92
- prependListener (event: string | symbol, handler: (...args: any[]) => void, context?: any): this {
93
- this.events[event] = this.events[event] || [];
94
- this.events[event] = [
95
- {
96
- handler: handler,
97
- context: context,
98
- },
99
- ...this.events[event]
100
- ];
101
-
102
- return this;
103
- }
104
-
105
- prependOnceListener (event: string | symbol, handler: (...args: any[]) => void, context?: any): this {
106
- const onceHandler = (...args: any[]) => {
107
- this.off(event, onceHandler, context);
108
- handler.apply(context, args);
109
- };
110
- return this.prependListener(event, onceHandler, context);
111
- }
112
-
113
- eventNames (): (string | symbol)[] {
114
- return Object.keys(this.events);
115
- }
116
-
117
- maybeReportError (error: any): this {
118
- if (!error) {
119
- return this;
120
- }
121
- if (this.listeningTo('error')) {
122
- this.emit('error', error);
123
- } else {
124
- this.logger?.error(error);
125
- }
126
-
127
- return this;
128
- }
1
+ import { ILogger } from "../logging/ILogger";
2
+ import { IEventEmitter } from "./IEventEmitter";
3
+
4
+ interface Events {
5
+ [key: string | symbol]: {
6
+ handler: (...args: any[]) => void;
7
+ context: any;
8
+ }[];
9
+ }
10
+
11
+ export class EventEmitter implements IEventEmitter {
12
+ private events: Events = {};
13
+
14
+ constructor(private logger?: ILogger) {}
15
+
16
+ private listeningTo (event: string) {
17
+ return !!this.events[event];
18
+ }
19
+
20
+ on (event: string | symbol, handler: (...args: any[]) => void, context?: any): this {
21
+ this.events[event] = this.events[event] || [];
22
+ this.events[event] = this.events[event].concat({
23
+ handler: handler,
24
+ context: context,
25
+ });
26
+
27
+ return this;
28
+ }
29
+
30
+ addListener (event: string | symbol, handler: (...args: any[]) => void, context?: any): this {
31
+ return this.on(event, handler, context);
32
+ }
33
+
34
+ once (event: string | symbol, handler: (...args: any[]) => void, context?: any): this {
35
+ const onceHandler = (...args: any[]) => {
36
+ this.off(event, onceHandler, context);
37
+ handler.apply(context, args);
38
+ };
39
+ return this.on(event, onceHandler, context);
40
+ }
41
+
42
+ off (event: string | symbol, handler: (...args: any[]) => void, context?: any): this {
43
+ if (!this.events[event]) {
44
+ return this;
45
+ }
46
+ for (let i = 0; i < this.events[event].length; i++) {
47
+ if (this.events[event][i].handler === handler && this.events[event][i].context === context) {
48
+ this.events[event] = this.events[event].slice(0, i).concat(this.events[event].slice(i + 1));
49
+ }
50
+ }
51
+
52
+ return this;
53
+ }
54
+
55
+ removeListener (event: string | symbol, handler: (...args: any[]) => void, context?: any): this {
56
+ return this.off(event, handler, context);
57
+ }
58
+
59
+ removeAllListeners (event?: string | symbol): this {
60
+ if (event) {
61
+ delete this.events[event];
62
+ } else {
63
+ this.events = {};
64
+ }
65
+
66
+ return this;
67
+ }
68
+
69
+ listeners (event: string | symbol): Function[] {
70
+ return this.events[event] ? this.events[event].map((event) => event.handler) : [];
71
+ }
72
+
73
+ emit (event: string | symbol, ...args: any[]): this {
74
+ if (!this.events[event]) {
75
+ return this;
76
+ }
77
+ // Copy the list of handlers before iterating, in case any handler adds or removes another handler.
78
+ // Any such changes should not affect what we do here-- we want to notify every handler that existed
79
+ // at the moment that the event was fired.
80
+ const copiedHandlers = [...this.events[event]];
81
+ for (let i = 0; i < copiedHandlers.length; i++) {
82
+ copiedHandlers[i].handler.apply(copiedHandlers[i].context, Array.prototype.slice.call(arguments, 1));
83
+ }
84
+
85
+ return this;
86
+ }
87
+
88
+ listenerCount (event: string | symbol): number {
89
+ return this.events[event] ? this.events[event].length : 0;
90
+ }
91
+
92
+ prependListener (event: string | symbol, handler: (...args: any[]) => void, context?: any): this {
93
+ this.events[event] = this.events[event] || [];
94
+ this.events[event] = [
95
+ {
96
+ handler: handler,
97
+ context: context,
98
+ },
99
+ ...this.events[event]
100
+ ];
101
+
102
+ return this;
103
+ }
104
+
105
+ prependOnceListener (event: string | symbol, handler: (...args: any[]) => void, context?: any): this {
106
+ const onceHandler = (...args: any[]) => {
107
+ this.off(event, onceHandler, context);
108
+ handler.apply(context, args);
109
+ };
110
+ return this.prependListener(event, onceHandler, context);
111
+ }
112
+
113
+ eventNames (): (string | symbol)[] {
114
+ return Object.keys(this.events);
115
+ }
116
+
117
+ maybeReportError (error: any): this {
118
+ if (!error) {
119
+ return this;
120
+ }
121
+ if (this.listeningTo('error')) {
122
+ this.emit('error', error);
123
+ } else {
124
+ this.logger?.error(error);
125
+ }
126
+
127
+ return this;
128
+ }
129
129
  }
@@ -1,15 +1,15 @@
1
- export interface IEventEmitter {
2
- on(event: string | symbol, handler: (...args: any[]) => void, context?: any): this;
3
- addListener(event: string | symbol, handler: (...args: any[]) => void, context?: any): this;
4
- once(event: string | symbol, handler: (...args: any[]) => void, context?: any): this;
5
- off(event: string | symbol, handler: (...args: any[]) => void, context?: any): this;
6
- removeListener(event: string | symbol, handler: (...args: any[]) => void, context?: any): this;
7
- removeAllListeners(event?: string | symbol): this;
8
- listeners(event: string | symbol): Function[];
9
- emit(event: string | symbol, ...args: any[]): this;
10
- listenerCount(event: string | symbol): number;
11
- prependListener(event: string | symbol, handler: (...args: any[]) => void, context?: any): this;
12
- prependOnceListener(event: string | symbol, handler: (...args: any[]) => void, context?: any): this;
13
- eventNames(): (string | symbol)[];
14
- maybeReportError(error: any): this;
1
+ export interface IEventEmitter {
2
+ on(event: string | symbol, handler: (...args: any[]) => void, context?: any): this;
3
+ addListener(event: string | symbol, handler: (...args: any[]) => void, context?: any): this;
4
+ once(event: string | symbol, handler: (...args: any[]) => void, context?: any): this;
5
+ off(event: string | symbol, handler: (...args: any[]) => void, context?: any): this;
6
+ removeListener(event: string | symbol, handler: (...args: any[]) => void, context?: any): this;
7
+ removeAllListeners(event?: string | symbol): this;
8
+ listeners(event: string | symbol): Function[];
9
+ emit(event: string | symbol, ...args: any[]): this;
10
+ listenerCount(event: string | symbol): number;
11
+ prependListener(event: string | symbol, handler: (...args: any[]) => void, context?: any): this;
12
+ prependOnceListener(event: string | symbol, handler: (...args: any[]) => void, context?: any): this;
13
+ eventNames(): (string | symbol)[];
14
+ maybeReportError(error: any): this;
15
15
  }
@@ -1,22 +1,22 @@
1
- import { isNullOrUndefined } from "./isNullOrUndefined";
2
-
3
- export class Regex {
4
- private static patternWithFlags = /\/(.*)\/([a-z]*)/i;
5
- private static whiteSpaceRegex = /\s/g;
6
-
7
- static fromString(patternString: string): RegExp {
8
- let flags = '';
9
- const match = patternString.match(Regex.patternWithFlags);
10
-
11
- if (match) {
12
- patternString = match[1]; // Update the pattern string
13
- flags = match[2]; // Update the flags
14
- }
15
-
16
- return new RegExp(patternString, flags);
17
- }
18
-
19
- static isNullOrWhiteSpace(str: string) {
20
- return isNullOrUndefined(str) || !str.replace(Regex.whiteSpaceRegex, '').length;
21
- }
1
+ import { isNullOrUndefined } from "./isNullOrUndefined";
2
+
3
+ export class Regex {
4
+ private static patternWithFlags = /\/(.*)\/([a-z]*)/i;
5
+ private static whiteSpaceRegex = /\s/g;
6
+
7
+ static fromString(patternString: string): RegExp {
8
+ let flags = '';
9
+ const match = patternString.match(Regex.patternWithFlags);
10
+
11
+ if (match) {
12
+ patternString = match[1]; // Update the pattern string
13
+ flags = match[2]; // Update the flags
14
+ }
15
+
16
+ return new RegExp(patternString, flags);
17
+ }
18
+
19
+ static isNullOrWhiteSpace(str: string) {
20
+ return isNullOrUndefined(str) || !str.replace(Regex.whiteSpaceRegex, '').length;
21
+ }
22
22
  }