@splitsoftware/splitio-commons 3.1.1-rc.0 → 3.1.1-rc.10

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 (241) hide show
  1. package/CHANGES.txt +10 -1
  2. package/cjs/evaluator/condition/index.js +1 -1
  3. package/cjs/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.js +8 -5
  4. package/cjs/evaluator/index.js +69 -81
  5. package/cjs/listeners/browser.js +1 -2
  6. package/cjs/listeners/node.js +4 -4
  7. package/cjs/logger/constants.js +20 -15
  8. package/cjs/logger/messages/debug.js +6 -5
  9. package/cjs/logger/messages/error.js +3 -3
  10. package/cjs/logger/messages/info.js +4 -3
  11. package/cjs/logger/messages/warn.js +7 -6
  12. package/cjs/presets/serverSide.js +2 -2
  13. package/cjs/readiness/constants.js +4 -5
  14. package/cjs/readiness/readinessManager.js +23 -23
  15. package/cjs/readiness/sdkReadinessManager.js +17 -1
  16. package/cjs/sdkClient/client.js +34 -9
  17. package/cjs/sdkClient/clientInputValidation.js +17 -6
  18. package/cjs/sdkClient/sdkClient.js +60 -3
  19. package/cjs/sdkFactory/index.js +15 -11
  20. package/cjs/sdkManager/index.js +5 -5
  21. package/cjs/services/decorateHeaders.js +1 -2
  22. package/cjs/services/splitApi.js +1 -14
  23. package/cjs/services/splitHttpClient.js +5 -3
  24. package/cjs/storages/AbstractSplitsCacheAsync.js +51 -0
  25. package/cjs/storages/AbstractSplitsCacheSync.js +76 -0
  26. package/cjs/storages/KeyBuilder.js +6 -6
  27. package/cjs/storages/KeyBuilderCS.js +5 -5
  28. package/cjs/storages/KeyBuilderSS.js +2 -2
  29. package/cjs/storages/getRolloutPlan.js +3 -3
  30. package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +2 -1
  31. package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +10 -10
  32. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +194 -0
  33. package/cjs/storages/inLocalStorage/index.js +6 -6
  34. package/cjs/storages/inLocalStorage/validateCache.js +3 -3
  35. package/cjs/storages/inMemory/InMemoryStorage.js +4 -4
  36. package/cjs/storages/inMemory/InMemoryStorageCS.js +5 -5
  37. package/cjs/storages/inMemory/RBSegmentsCacheInMemory.js +5 -5
  38. package/cjs/storages/inMemory/SegmentsCacheInMemory.js +1 -1
  39. package/cjs/storages/inMemory/SplitsCacheInMemory.js +121 -0
  40. package/cjs/storages/inMemory/TelemetryCacheInMemory.js +5 -5
  41. package/cjs/storages/inRedis/RBSegmentsCacheInRedis.js +1 -1
  42. package/cjs/storages/inRedis/RedisAdapter.js +8 -5
  43. package/cjs/storages/inRedis/{DefinitionsCacheInRedis.js → SplitsCacheInRedis.js} +77 -77
  44. package/cjs/storages/inRedis/index.js +2 -2
  45. package/cjs/storages/pluggable/RBSegmentsCachePluggable.js +1 -1
  46. package/cjs/storages/pluggable/SplitsCachePluggable.js +212 -0
  47. package/cjs/storages/pluggable/index.js +2 -2
  48. package/cjs/storages/setRolloutPlan.js +4 -4
  49. package/cjs/storages/utils.js +0 -1
  50. package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +5 -5
  51. package/cjs/sync/polling/fetchers/splitChangesFetcher.js +15 -24
  52. package/cjs/sync/polling/pollingManagerCS.js +20 -20
  53. package/cjs/sync/polling/pollingManagerSS.js +15 -15
  54. package/cjs/sync/polling/syncTasks/segmentsSyncTask.js +3 -2
  55. package/cjs/sync/polling/syncTasks/splitsSyncTask.js +13 -0
  56. package/cjs/sync/polling/updaters/mySegmentsUpdater.js +3 -3
  57. package/cjs/sync/polling/updaters/segmentChangesUpdater.js +6 -6
  58. package/cjs/sync/polling/updaters/{definitionChangesUpdater.js → splitChangesUpdater.js} +68 -65
  59. package/cjs/sync/streaming/AuthClient/index.js +1 -1
  60. package/cjs/sync/streaming/SSEHandler/NotificationKeeper.js +1 -1
  61. package/cjs/sync/streaming/SSEHandler/index.js +1 -1
  62. package/cjs/sync/streaming/UpdateWorkers/{DefinitionsUpdateWorker.js → SplitsUpdateWorker.js} +19 -16
  63. package/cjs/sync/streaming/constants.js +3 -3
  64. package/cjs/sync/streaming/parseUtils.js +11 -11
  65. package/cjs/sync/streaming/pushManager.js +16 -16
  66. package/cjs/sync/submitters/eventsSubmitter.js +1 -1
  67. package/cjs/sync/submitters/impressionCountsSubmitter.js +1 -1
  68. package/cjs/sync/submitters/impressionsSubmitter.js +4 -5
  69. package/cjs/sync/submitters/telemetrySubmitter.js +4 -3
  70. package/cjs/sync/submitters/uniqueKeysSubmitter.js +1 -1
  71. package/cjs/sync/syncManagerOnline.js +7 -12
  72. package/cjs/utils/Backoff.js +0 -20
  73. package/cjs/utils/inputValidation/index.js +7 -7
  74. package/cjs/utils/inputValidation/isOperational.js +4 -4
  75. package/cjs/utils/inputValidation/{definition.js → split.js} +10 -10
  76. package/cjs/utils/inputValidation/{definitionExistence.js → splitExistence.js} +6 -6
  77. package/cjs/utils/inputValidation/splits.js +25 -0
  78. package/cjs/utils/labels/index.js +3 -3
  79. package/cjs/utils/settingsValidation/index.js +0 -2
  80. package/cjs/utils/settingsValidation/splitFilters.js +3 -3
  81. package/cjs/utils/settingsValidation/url.js +2 -6
  82. package/esm/evaluator/condition/index.js +1 -1
  83. package/esm/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.js +8 -5
  84. package/esm/evaluator/index.js +69 -80
  85. package/esm/listeners/browser.js +1 -2
  86. package/esm/listeners/node.js +4 -4
  87. package/esm/logger/constants.js +17 -12
  88. package/esm/logger/messages/debug.js +6 -5
  89. package/esm/logger/messages/error.js +3 -3
  90. package/esm/logger/messages/info.js +4 -3
  91. package/esm/logger/messages/warn.js +7 -6
  92. package/esm/presets/serverSide.js +2 -2
  93. package/esm/readiness/constants.js +3 -4
  94. package/esm/readiness/readinessManager.js +24 -24
  95. package/esm/readiness/sdkReadinessManager.js +18 -2
  96. package/esm/sdkClient/client.js +35 -9
  97. package/esm/sdkClient/clientInputValidation.js +19 -8
  98. package/esm/sdkClient/sdkClient.js +60 -3
  99. package/esm/sdkFactory/index.js +16 -12
  100. package/esm/sdkManager/index.js +6 -6
  101. package/esm/services/decorateHeaders.js +1 -2
  102. package/esm/services/splitApi.js +1 -14
  103. package/esm/services/splitHttpClient.js +5 -3
  104. package/esm/storages/AbstractSplitsCacheAsync.js +48 -0
  105. package/esm/storages/AbstractSplitsCacheSync.js +71 -0
  106. package/esm/storages/KeyBuilder.js +6 -6
  107. package/esm/storages/KeyBuilderCS.js +5 -5
  108. package/esm/storages/KeyBuilderSS.js +2 -2
  109. package/esm/storages/getRolloutPlan.js +3 -3
  110. package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +2 -1
  111. package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +7 -7
  112. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +191 -0
  113. package/esm/storages/inLocalStorage/index.js +6 -6
  114. package/esm/storages/inLocalStorage/validateCache.js +3 -3
  115. package/esm/storages/inMemory/InMemoryStorage.js +4 -4
  116. package/esm/storages/inMemory/InMemoryStorageCS.js +5 -5
  117. package/esm/storages/inMemory/RBSegmentsCacheInMemory.js +2 -2
  118. package/esm/storages/inMemory/SegmentsCacheInMemory.js +1 -1
  119. package/esm/storages/inMemory/SplitsCacheInMemory.js +118 -0
  120. package/esm/storages/inMemory/TelemetryCacheInMemory.js +5 -5
  121. package/esm/storages/inRedis/RBSegmentsCacheInRedis.js +1 -1
  122. package/esm/storages/inRedis/RedisAdapter.js +8 -5
  123. package/esm/storages/inRedis/{DefinitionsCacheInRedis.js → SplitsCacheInRedis.js} +76 -76
  124. package/esm/storages/inRedis/index.js +2 -2
  125. package/esm/storages/pluggable/RBSegmentsCachePluggable.js +1 -1
  126. package/esm/storages/pluggable/SplitsCachePluggable.js +209 -0
  127. package/esm/storages/pluggable/index.js +2 -2
  128. package/esm/storages/setRolloutPlan.js +4 -4
  129. package/esm/storages/utils.js +0 -1
  130. package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +6 -6
  131. package/esm/sync/polling/fetchers/splitChangesFetcher.js +16 -25
  132. package/esm/sync/polling/pollingManagerCS.js +17 -17
  133. package/esm/sync/polling/pollingManagerSS.js +15 -15
  134. package/esm/sync/polling/syncTasks/segmentsSyncTask.js +3 -2
  135. package/esm/sync/polling/syncTasks/splitsSyncTask.js +9 -0
  136. package/esm/sync/polling/updaters/mySegmentsUpdater.js +3 -3
  137. package/esm/sync/polling/updaters/segmentChangesUpdater.js +7 -7
  138. package/esm/sync/polling/updaters/{definitionChangesUpdater.js → splitChangesUpdater.js} +68 -65
  139. package/esm/sync/streaming/AuthClient/index.js +1 -1
  140. package/esm/sync/streaming/SSEHandler/NotificationKeeper.js +2 -2
  141. package/esm/sync/streaming/SSEHandler/index.js +2 -2
  142. package/esm/sync/streaming/UpdateWorkers/{DefinitionsUpdateWorker.js → SplitsUpdateWorker.js} +18 -15
  143. package/esm/sync/streaming/constants.js +2 -2
  144. package/esm/sync/streaming/parseUtils.js +9 -9
  145. package/esm/sync/streaming/pushManager.js +18 -18
  146. package/esm/sync/submitters/eventsSubmitter.js +1 -1
  147. package/esm/sync/submitters/impressionCountsSubmitter.js +1 -1
  148. package/esm/sync/submitters/impressionsSubmitter.js +4 -5
  149. package/esm/sync/submitters/telemetrySubmitter.js +4 -3
  150. package/esm/sync/submitters/uniqueKeysSubmitter.js +1 -1
  151. package/esm/sync/syncManagerOnline.js +6 -11
  152. package/esm/utils/Backoff.js +0 -20
  153. package/esm/utils/inputValidation/index.js +3 -3
  154. package/esm/utils/inputValidation/isOperational.js +4 -4
  155. package/esm/utils/inputValidation/{definition.js → split.js} +8 -8
  156. package/esm/utils/inputValidation/splitExistence.js +15 -0
  157. package/esm/utils/inputValidation/splits.js +21 -0
  158. package/esm/utils/labels/index.js +2 -2
  159. package/esm/utils/settingsValidation/index.js +0 -2
  160. package/esm/utils/settingsValidation/splitFilters.js +3 -3
  161. package/esm/utils/settingsValidation/url.js +2 -6
  162. package/package.json +6 -7
  163. package/src/dtos/types.ts +1 -1
  164. package/src/evaluator/Engine.ts +3 -3
  165. package/src/evaluator/condition/index.ts +2 -2
  166. package/src/evaluator/index.ts +27 -35
  167. package/src/evaluator/types.ts +2 -6
  168. package/src/presets/serverSide.ts +3 -3
  169. package/src/sdkClient/client.ts +22 -24
  170. package/src/sdkClient/sdkLifecycle.ts +3 -0
  171. package/src/services/authProvider.ts +41 -19
  172. package/src/services/secureSplitHttpClient.ts +10 -18
  173. package/src/services/serviceApi.ts +27 -24
  174. package/src/services/splitApi.ts +10 -9
  175. package/src/services/types.ts +5 -4
  176. package/src/storages/inRedis/RedisAdapter.ts +8 -5
  177. package/src/sync/polling/pollingManagerCS.ts +80 -78
  178. package/src/sync/polling/pollingManagerSS.ts +49 -45
  179. package/src/sync/polling/updaters/definitionChangesUpdater.ts +3 -3
  180. package/src/sync/polling/updaters/segmentChangesUpdater.ts +1 -1
  181. package/src/sync/streaming/AuthClient/index.ts +14 -15
  182. package/src/sync/streaming/AuthClient/types.ts +9 -13
  183. package/src/sync/streaming/SSEClient/index.ts +2 -2
  184. package/src/sync/streaming/SSEClient/types.ts +2 -2
  185. package/src/sync/streaming/SSEHandler/index.ts +2 -1
  186. package/src/sync/streaming/SSEHandler/types.ts +2 -2
  187. package/src/sync/streaming/constants.ts +1 -0
  188. package/src/sync/streaming/pushManager.ts +32 -42
  189. package/src/sync/streaming/types.ts +3 -2
  190. package/src/sync/submitters/impressionsSubmitter.ts +3 -3
  191. package/src/sync/submitters/types.ts +2 -2
  192. package/src/sync/syncManagerOnline.ts +2 -8
  193. package/src/utils/Backoff.ts +16 -4
  194. package/types/splitio.d.ts +5 -4
  195. package/cjs/platform/browser.js +0 -15
  196. package/cjs/platform/getEventSource/browser.js +0 -8
  197. package/cjs/platform/getEventSource/eventsource.js +0 -480
  198. package/cjs/platform/getEventSource/node.js +0 -26
  199. package/cjs/platform/getFetch/browser.js +0 -9
  200. package/cjs/platform/getFetch/node.js +0 -27
  201. package/cjs/platform/getOptions/node.js +0 -25
  202. package/cjs/platform/node.js +0 -17
  203. package/cjs/sdkClient/sdkLifecycle.js +0 -72
  204. package/cjs/sdkClient/trackMethod.js +0 -56
  205. package/cjs/services/authProvider.js +0 -67
  206. package/cjs/services/secureSplitHttpClient.js +0 -39
  207. package/cjs/services/serviceApi.js +0 -145
  208. package/cjs/storages/AbstractDefinitionsCacheAsync.js +0 -51
  209. package/cjs/storages/AbstractDefinitionsCacheSync.js +0 -76
  210. package/cjs/storages/inLocalStorage/DefinitionsCacheInLocal.js +0 -194
  211. package/cjs/storages/inMemory/DefinitionsCacheInMemory.js +0 -121
  212. package/cjs/storages/pluggable/DefinitionsCachePluggable.js +0 -212
  213. package/cjs/sync/polling/syncTasks/definitionsSyncTask.js +0 -13
  214. package/cjs/utils/EventEmitter.js +0 -391
  215. package/cjs/utils/filter/bloomFilter.js +0 -37
  216. package/cjs/utils/inputValidation/definitions.js +0 -25
  217. package/cjs/utils/inputValidation/target.js +0 -22
  218. package/esm/platform/browser.js +0 -12
  219. package/esm/platform/getEventSource/browser.js +0 -4
  220. package/esm/platform/getEventSource/eventsource.js +0 -480
  221. package/esm/platform/getEventSource/node.js +0 -20
  222. package/esm/platform/getFetch/browser.js +0 -5
  223. package/esm/platform/getFetch/node.js +0 -22
  224. package/esm/platform/getOptions/node.js +0 -20
  225. package/esm/platform/node.js +0 -14
  226. package/esm/sdkClient/sdkLifecycle.js +0 -68
  227. package/esm/sdkClient/trackMethod.js +0 -52
  228. package/esm/services/authProvider.js +0 -63
  229. package/esm/services/secureSplitHttpClient.js +0 -35
  230. package/esm/services/serviceApi.js +0 -141
  231. package/esm/storages/AbstractDefinitionsCacheAsync.js +0 -48
  232. package/esm/storages/AbstractDefinitionsCacheSync.js +0 -71
  233. package/esm/storages/inLocalStorage/DefinitionsCacheInLocal.js +0 -191
  234. package/esm/storages/inMemory/DefinitionsCacheInMemory.js +0 -118
  235. package/esm/storages/pluggable/DefinitionsCachePluggable.js +0 -209
  236. package/esm/sync/polling/syncTasks/definitionsSyncTask.js +0 -9
  237. package/esm/utils/EventEmitter.js +0 -387
  238. package/esm/utils/filter/bloomFilter.js +0 -33
  239. package/esm/utils/inputValidation/definitionExistence.js +0 -15
  240. package/esm/utils/inputValidation/definitions.js +0 -21
  241. package/esm/utils/inputValidation/target.js +0 -18
@@ -1,23 +1,19 @@
1
1
  import { IDecodedJWTToken } from '../../../utils/jwt/types';
2
2
 
3
- export type IJwtCredentialV2 = {
4
- pushEnabled: boolean
5
- token: string // empty string ("") when `"pushEnabled": false`
6
- decodedToken: IDecodedJWTToken
7
- channels: { [channel: string]: string[] }
8
- connDelay?: number
9
- }
10
-
11
- export type IJwtCredentialV3 = {
12
- token: string
3
+ export type IJwtCredential = {
4
+ token: string; // empty string ("") when `"pushEnabled": false`
13
5
  decodedToken: IDecodedJWTToken
14
6
  channels: { [channel: string]: string[] }
7
+ // /api/v2/auth fields
8
+ pushEnabled?: boolean | null;
9
+ connDelay?: number | null;
10
+ // /api/v3/auth fields
15
11
  config?: {
16
12
  streaming?: {
17
- delay?: number
18
- enabled?: boolean
13
+ delay?: number | null;
14
+ enabled?: boolean | null;
19
15
  } | null;
20
16
  } | null;
21
17
  }
22
18
 
23
- export type IAuthenticate = (userKeys?: string[]) => Promise<IJwtCredentialV2>
19
+ export type IFetchAuth = (userKeys?: string[]) => Promise<IJwtCredential>
@@ -5,7 +5,7 @@ import { ISettings } from '../../../types';
5
5
  import { checkIfServerSide } from '../../../utils/key';
6
6
  import { isString } from '../../../utils/lang';
7
7
  import { objectAssign } from '../../../utils/lang/objectAssign';
8
- import { IJwtCredentialV2 } from '../AuthClient/types';
8
+ import { IJwtCredential } from '../AuthClient/types';
9
9
  import { ISSEClient, ISseEventHandler } from './types';
10
10
 
11
11
  const ABLY_API_VERSION = '1.1';
@@ -66,7 +66,7 @@ export class SSEClient implements ISSEClient {
66
66
  /**
67
67
  * Open the connection with a given authToken
68
68
  */
69
- open(authToken: IJwtCredentialV2) {
69
+ open(authToken: IJwtCredential) {
70
70
  this.close(); // it closes connection if previously opened
71
71
 
72
72
  const channelsQueryParam = Object.keys(authToken.channels).map((channel) => {
@@ -1,4 +1,4 @@
1
- import { IJwtCredentialV2 } from '../AuthClient/types';
1
+ import { IJwtCredential } from '../AuthClient/types';
2
2
 
3
3
  export interface ISseEventHandler {
4
4
  handleError: (ev: Event) => any;
@@ -7,7 +7,7 @@ export interface ISseEventHandler {
7
7
  }
8
8
 
9
9
  export interface ISSEClient {
10
- open(authToken: IJwtCredentialV2): void,
10
+ open(authToken: IJwtCredential): void,
11
11
  close(): void,
12
12
  setEventHandler(handler: ISseEventHandler): void
13
13
  }
@@ -1,6 +1,6 @@
1
1
  import { errorParser, messageParser } from './NotificationParser';
2
2
  import { notificationKeeperFactory } from './NotificationKeeper';
3
- import { PUSH_RETRYABLE_ERROR, PUSH_NON_RETRYABLE_ERROR, OCCUPANCY, CONTROL, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE, RB_SEGMENT_UPDATE } from '../constants';
3
+ import { PUSH_RETRYABLE_ERROR, PUSH_NON_RETRYABLE_ERROR, OCCUPANCY, CONTROL, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, CONFIG_UPDATE, MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE, RB_SEGMENT_UPDATE } from '../constants';
4
4
  import { IPushEventEmitter } from '../types';
5
5
  import { ISseEventHandler } from '../SSEClient/types';
6
6
  import { INotificationError, INotificationMessage } from './types';
@@ -80,6 +80,7 @@ export function SSEHandlerFactory(log: ILogger, pushEmitter: IPushEventEmitter,
80
80
  switch (parsedData.type) {
81
81
  /* update events */
82
82
  case SPLIT_UPDATE:
83
+ case CONFIG_UPDATE:
83
84
  case SEGMENT_UPDATE:
84
85
  case MEMBERSHIPS_MS_UPDATE:
85
86
  case MEMBERSHIPS_LS_UPDATE:
@@ -1,5 +1,5 @@
1
1
  import { ControlType } from '../constants';
2
- import { SEGMENT_UPDATE, SPLIT_UPDATE, SPLIT_KILL, CONTROL, OCCUPANCY, MEMBERSHIPS_LS_UPDATE, MEMBERSHIPS_MS_UPDATE, RB_SEGMENT_UPDATE } from '../types';
2
+ import { SEGMENT_UPDATE, SPLIT_UPDATE, CONFIG_UPDATE, SPLIT_KILL, CONTROL, OCCUPANCY, MEMBERSHIPS_LS_UPDATE, MEMBERSHIPS_MS_UPDATE, RB_SEGMENT_UPDATE } from '../types';
3
3
 
4
4
  export enum Compression {
5
5
  None = 0,
@@ -42,7 +42,7 @@ export interface ISegmentUpdateData {
42
42
  }
43
43
 
44
44
  export interface ISplitUpdateData {
45
- type: SPLIT_UPDATE | RB_SEGMENT_UPDATE,
45
+ type: SPLIT_UPDATE | CONFIG_UPDATE | RB_SEGMENT_UPDATE,
46
46
  changeNumber: number,
47
47
  pcn?: number,
48
48
  d?: string,
@@ -30,6 +30,7 @@ export const MEMBERSHIPS_LS_UPDATE = 'MEMBERSHIPS_LS_UPDATE';
30
30
  export const SEGMENT_UPDATE = 'SEGMENT_UPDATE';
31
31
  export const SPLIT_KILL = 'SPLIT_KILL';
32
32
  export const SPLIT_UPDATE = 'SPLIT_UPDATE';
33
+ export const CONFIG_UPDATE = 'CONFIG_UPDATE';
33
34
  export const RB_SEGMENT_UPDATE = 'RB_SEGMENT_UPDATE';
34
35
 
35
36
  // Control-type push notifications, handled by NotificationKeeper
@@ -7,16 +7,15 @@ import { SSEHandlerFactory } from './SSEHandler';
7
7
  import { MySegmentsUpdateWorker } from './UpdateWorkers/MySegmentsUpdateWorker';
8
8
  import { SegmentsUpdateWorker } from './UpdateWorkers/SegmentsUpdateWorker';
9
9
  import { DefinitionsUpdateWorker } from './UpdateWorkers/DefinitionsUpdateWorker';
10
- import { authenticateFactory, hashUserKey } from './AuthClient';
11
10
  import { forOwn } from '../../utils/lang';
12
11
  import { SSEClient } from './SSEClient';
13
12
  import { checkIfServerSide, getMatching } from '../../utils/key';
14
- import { MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE, PUSH_NON_RETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, RB_SEGMENT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP, ControlType } from './constants';
13
+ import { MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE, PUSH_NON_RETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, CONFIG_UPDATE, RB_SEGMENT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP, ControlType } from './constants';
15
14
  import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT, STREAMING_PARSING_MEMBERSHIPS_UPDATE } from '../../logger/constants';
16
15
  import { IMembershipMSUpdateData, IMembershipLSUpdateData, KeyList, UpdateStrategy } from './SSEHandler/types';
17
16
  import { getDelay, isInBitmap, parseBitmap, parseCompressedData } from './parseUtils';
18
17
  import { Hash64, hash64 } from '../../utils/murmur3/murmur3_64';
19
- import { IJwtCredentialV2 } from './AuthClient/types';
18
+ import { IJwtCredential } from './AuthClient/types';
20
19
  import { TOKEN_REFRESH, AUTH_REJECTION } from '../../utils/constants';
21
20
  import { ISdkFactoryContextSync } from '../../sdkFactory/types';
22
21
 
@@ -45,7 +44,6 @@ export function pushManagerFactory(
45
44
  log.warn(STREAMING_FALLBACK, [e]);
46
45
  return;
47
46
  }
48
- const authenticate = authenticateFactory(serviceApi.fetchAuth);
49
47
 
50
48
  // init feedback loop
51
49
  const pushEmitter = new platform.EventEmitter() as IPushEventEmitter;
@@ -58,8 +56,6 @@ export function pushManagerFactory(
58
56
  // For server-side we pass the segmentsSyncTask, used by DefinitionsUpdateWorker to fetch new segments
59
57
  const definitionsUpdateWorker = DefinitionsUpdateWorker(log, storage, pollingManager.definitionsSyncTask, readiness.definitions, telemetryTracker);
60
58
 
61
- // [Only for client-side] map of hashes to user keys, to dispatch membership update events to the corresponding MySegmentsUpdateWorker
62
- const userKeyHashes: Record<string, string> = {};
63
59
  // [Only for client-side] map of user keys to their corresponding hash64 and MySegmentsUpdateWorkers.
64
60
  // Hash64 is used to process membership update events and dispatch actions to the corresponding MySegmentsUpdateWorker.
65
61
  const clients: Record<string, { hash64: Hash64, worker: ReturnType<typeof MySegmentsUpdateWorker> }> = {};
@@ -81,7 +77,7 @@ export function pushManagerFactory(
81
77
  let timeoutIdTokenRefresh: ReturnType<typeof setTimeout>;
82
78
  let timeoutIdSseOpen: ReturnType<typeof setTimeout>;
83
79
 
84
- function scheduleTokenRefreshAndSse(authData: IJwtCredentialV2) {
80
+ function scheduleTokenRefreshAndSse(authData: IJwtCredential) {
85
81
  // clear scheduled tasks if exist
86
82
  if (timeoutIdTokenRefresh) clearTimeout(timeoutIdTokenRefresh);
87
83
  if (timeoutIdSseOpen) clearTimeout(timeoutIdSseOpen);
@@ -113,41 +109,37 @@ export function pushManagerFactory(
113
109
  disconnected = false;
114
110
 
115
111
  const userKeys = userKey ? Object.keys(clients) : undefined;
116
- authenticate(userKeys).then(
117
- function (authData) {
118
- if (disconnected) return;
119
-
120
- // 'pushEnabled: false' is handled as a PUSH_NON_RETRYABLE_ERROR instead of PUSH_SUBSYSTEM_DOWN, in order to
121
- // close the sseClient in case the org has been bloqued while the instance was connected to streaming
122
- if (!authData.pushEnabled) {
123
- log.info(STREAMING_DISABLED);
124
- pushEmitter.emit(PUSH_NON_RETRYABLE_ERROR);
125
- return;
126
- }
127
-
128
- // [Only for client-side] don't open SSE connection if a new shared client was added, since it means that a new authentication is taking place
129
- if (userKeys && userKeys.length < Object.keys(clients).length) return;
112
+ serviceApi.fetchAuth(userKeys).then((authData) => {
113
+ if (disconnected) return;
130
114
 
131
- // Schedule SSE connection and refresh token
132
- scheduleTokenRefreshAndSse(authData);
115
+ // 'pushEnabled: false' is handled as a PUSH_NON_RETRYABLE_ERROR instead of PUSH_SUBSYSTEM_DOWN, in order to
116
+ // close the sseClient in case the org has been bloqued while the instance was connected to streaming
117
+ if (!authData.pushEnabled) {
118
+ log.info(STREAMING_DISABLED);
119
+ pushEmitter.emit(PUSH_NON_RETRYABLE_ERROR);
120
+ return;
133
121
  }
134
- ).catch(
135
- function (error) {
136
- if (disconnected) return;
137
122
 
138
- log.error(ERROR_STREAMING_AUTH, [error.message]);
123
+ // [Only for client-side] don't open SSE connection if a new shared client was added, since it means that a new authentication is taking place
124
+ if (userKeys && userKeys.length < Object.keys(clients).length) return;
139
125
 
140
- // Handle 4XX HTTP errors: 401 (invalid SDK Key) or 400 (using incorrect SDK Key, i.e., client-side SDK Key on server-side)
141
- if (error.statusCode >= 400 && error.statusCode < 500) {
142
- telemetryTracker.streamingEvent(AUTH_REJECTION);
143
- pushEmitter.emit(PUSH_NON_RETRYABLE_ERROR);
144
- return;
145
- }
126
+ // Schedule SSE connection and refresh token
127
+ scheduleTokenRefreshAndSse(authData);
128
+ }).catch((error) => {
129
+ if (disconnected) return;
146
130
 
147
- // Handle other HTTP and network errors as recoverable errors
148
- pushEmitter.emit(PUSH_RETRYABLE_ERROR);
131
+ log.error(ERROR_STREAMING_AUTH, [error.message]);
132
+
133
+ // Handle 4XX HTTP errors: 401 (invalid SDK Key) or 400 (using incorrect SDK Key, i.e., client-side SDK Key on server-side)
134
+ if (error.statusCode >= 400 && error.statusCode < 500) {
135
+ telemetryTracker.streamingEvent(AUTH_REJECTION);
136
+ pushEmitter.emit(PUSH_NON_RETRYABLE_ERROR);
137
+ return;
149
138
  }
150
- );
139
+
140
+ // Handle other HTTP and network errors as recoverable errors
141
+ pushEmitter.emit(PUSH_RETRYABLE_ERROR);
142
+ });
151
143
  }
152
144
 
153
145
  // close SSE connection and cancel scheduled tasks
@@ -218,8 +210,11 @@ export function pushManagerFactory(
218
210
 
219
211
  /** Functions related to synchronization (Queues and Workers in the spec) */
220
212
 
213
+ // Some notification types are specific to the Feature flags or Configs SDKs. Their handlers are
214
+ // registered unconditionally, since the SDK only subscribes to the channels of its own entities.
221
215
  pushEmitter.on(SPLIT_KILL, definitionsUpdateWorker.killDefinition);
222
216
  pushEmitter.on(SPLIT_UPDATE, definitionsUpdateWorker.put);
217
+ pushEmitter.on(CONFIG_UPDATE, definitionsUpdateWorker.put);
223
218
  pushEmitter.on(RB_SEGMENT_UPDATE, definitionsUpdateWorker.put);
224
219
 
225
220
  function handleMySegmentsUpdate(parsedData: IMembershipMSUpdateData | IMembershipLSUpdateData) {
@@ -324,10 +319,7 @@ export function pushManagerFactory(
324
319
 
325
320
  // [Only for client-side]
326
321
  add(userKey: string, mySegmentsSyncTask: IMySegmentsSyncTask) {
327
- const hash = hashUserKey(userKey);
328
-
329
- if (!userKeyHashes[hash]) {
330
- userKeyHashes[hash] = userKey;
322
+ if (!clients[userKey]) {
331
323
  clients[userKey] = {
332
324
  hash64: hash64(userKey),
333
325
  worker: MySegmentsUpdateWorker(log, storage, mySegmentsSyncTask, telemetryTracker)
@@ -349,8 +341,6 @@ export function pushManagerFactory(
349
341
  },
350
342
  // [Only for client-side]
351
343
  remove(userKey: string) {
352
- const hash = hashUserKey(userKey);
353
- delete userKeyHashes[hash];
354
344
  delete clients[userKey];
355
345
  }
356
346
  }
@@ -16,19 +16,20 @@ export type MEMBERSHIPS_LS_UPDATE = 'MEMBERSHIPS_LS_UPDATE';
16
16
  export type SEGMENT_UPDATE = 'SEGMENT_UPDATE';
17
17
  export type SPLIT_KILL = 'SPLIT_KILL';
18
18
  export type SPLIT_UPDATE = 'SPLIT_UPDATE';
19
+ export type CONFIG_UPDATE = 'CONFIG_UPDATE';
19
20
  export type RB_SEGMENT_UPDATE = 'RB_SEGMENT_UPDATE';
20
21
 
21
22
  // Control-type push notifications, handled by NotificationKeeper
22
23
  export type CONTROL = 'CONTROL';
23
24
  export type OCCUPANCY = 'OCCUPANCY';
24
25
 
25
- export type IPushEvent = PUSH_SUBSYSTEM_UP | PUSH_SUBSYSTEM_DOWN | PUSH_NON_RETRYABLE_ERROR | PUSH_RETRYABLE_ERROR | MEMBERSHIPS_MS_UPDATE | MEMBERSHIPS_LS_UPDATE | SEGMENT_UPDATE | SPLIT_UPDATE | SPLIT_KILL | RB_SEGMENT_UPDATE | ControlType.STREAMING_RESET
26
+ export type IPushEvent = PUSH_SUBSYSTEM_UP | PUSH_SUBSYSTEM_DOWN | PUSH_NON_RETRYABLE_ERROR | PUSH_RETRYABLE_ERROR | MEMBERSHIPS_MS_UPDATE | MEMBERSHIPS_LS_UPDATE | SEGMENT_UPDATE | SPLIT_UPDATE | CONFIG_UPDATE | SPLIT_KILL | RB_SEGMENT_UPDATE | ControlType.STREAMING_RESET
26
27
 
27
28
  type IParsedData<T extends IPushEvent> =
28
29
  T extends MEMBERSHIPS_MS_UPDATE ? IMembershipMSUpdateData :
29
30
  T extends MEMBERSHIPS_LS_UPDATE ? IMembershipLSUpdateData :
30
31
  T extends SEGMENT_UPDATE ? ISegmentUpdateData :
31
- T extends SPLIT_UPDATE | RB_SEGMENT_UPDATE ? ISplitUpdateData :
32
+ T extends SPLIT_UPDATE | CONFIG_UPDATE | RB_SEGMENT_UPDATE ? ISplitUpdateData :
32
33
  T extends SPLIT_KILL ? ISplitKillData : INotificationData;
33
34
 
34
35
  /**
@@ -1,14 +1,14 @@
1
1
  import { groupBy, forOwn } from '../../utils/lang';
2
2
  import SplitIO from '../../../types/splitio';
3
3
  import { submitterFactory } from './submitter';
4
- import { ImpressionsPayload } from './types';
4
+ import { EntityType, ImpressionsPayload } from './types';
5
5
  import { SUBMITTERS_PUSH_FULL_QUEUE } from '../../logger/constants';
6
6
  import { ISdkFactoryContextSync } from '../../sdkFactory/types';
7
7
 
8
8
  /**
9
9
  * Converts `impressions` data from cache into request payload.
10
10
  */
11
- export function fromImpressionsCollector(sendLabels: boolean, data: SplitIO.ImpressionDTO[]): ImpressionsPayload {
11
+ export function fromImpressionsCollector(sendLabels: boolean, data: (SplitIO.ImpressionDTO & { entityType?: EntityType })[]): ImpressionsPayload {
12
12
  let groupedByFeature = groupBy(data, 'feature');
13
13
  let dto: ImpressionsPayload = [];
14
14
 
@@ -25,7 +25,7 @@ export function fromImpressionsCollector(sendLabels: boolean, data: SplitIO.Impr
25
25
  b: entry.bucketingKey, // Bucketing Key
26
26
  pt: entry.pt, // Previous time
27
27
  properties: entry.properties, // Properties
28
- // @ts-expect-error - entityType is not yet public. @TODO: add to SplitIO.ImpressionDTO type
28
+ // @TODO: add entityType to public SplitIO.ImpressionDTO type
29
29
  et: entry.entityType, // Definition type
30
30
  };
31
31
  })
@@ -3,7 +3,7 @@ import { IMetadata } from '../../dtos/types';
3
3
  import SplitIO from '../../../types/splitio';
4
4
  import { ISyncTask } from '../types';
5
5
 
6
- type EntityType = 'config' | 'flag' | 'ai-config';
6
+ export type EntityType = 'config' | 'flag' | 'ai-config';
7
7
 
8
8
  type ImpressionPayload = {
9
9
  /** Matching Key */
@@ -15,7 +15,7 @@ type ImpressionPayload = {
15
15
  /** Timestamp */
16
16
  m: number;
17
17
  /** Change number */
18
- c: number;
18
+ c?: number;
19
19
  /** Rule label */
20
20
  r?: string;
21
21
  /** Previous time */
@@ -11,9 +11,6 @@ import { POLLING, STREAMING, SYNC_MODE_UPDATE } from '../utils/constants';
11
11
  import { ISdkFactoryContextSync } from '../sdkFactory/types';
12
12
  import { SDK_DEFINITIONS_CACHE_LOADED } from '../readiness/constants';
13
13
  import { usesSegmentsSync } from '../storages/AbstractDefinitionsCacheSync';
14
- import { splitChangesFetcherFactory } from './polling/fetchers/splitChangesFetcher';
15
- import { IDefinitionChangesFetcher, ISegmentChangesFetcher } from './polling/fetchers/types';
16
- import { segmentChangesFetcherFactory } from './polling/fetchers/segmentChangesFetcher';
17
14
 
18
15
  /**
19
16
  * Online SyncManager factory.
@@ -22,13 +19,10 @@ import { segmentChangesFetcherFactory } from './polling/fetchers/segmentChangesF
22
19
  * @param pollingManagerFactory - allows to specialize the SyncManager for server-side or client-side API by passing
23
20
  * `pollingManagerSSFactory` or `pollingManagerCSFactory` respectively.
24
21
  * @param pushManagerFactory - optional to build a SyncManager with or without streaming support
25
- * @param definitionChangesFetcherFactory - optional to replace the default split changes fetcher
26
22
  */
27
23
  export function syncManagerOnlineFactory(
28
- pollingManagerFactory?: (params: ISdkFactoryContextSync, definitionChangesFetcher: IDefinitionChangesFetcher, segmentChangesFetcher: ISegmentChangesFetcher) => IPollingManager,
24
+ pollingManagerFactory?: (params: ISdkFactoryContextSync) => IPollingManager,
29
25
  pushManagerFactory?: (params: ISdkFactoryContextSync, pollingManager: IPollingManager) => IPushManager | undefined,
30
- definitionFetcherFactory = splitChangesFetcherFactory,
31
- segmentFetcherFactory = (params: ISdkFactoryContextSync) => segmentChangesFetcherFactory(params.serviceApi.fetchSegmentChanges)
32
26
  ): (params: ISdkFactoryContextSync) => ISyncManagerCS {
33
27
 
34
28
  /**
@@ -39,7 +33,7 @@ export function syncManagerOnlineFactory(
39
33
  const { settings, settings: { log, streamingEnabled, sync: { enabled: syncEnabled } }, telemetryTracker, storage, readiness } = params;
40
34
 
41
35
  /** Polling Manager */
42
- const pollingManager = pollingManagerFactory && pollingManagerFactory(params, definitionFetcherFactory(params), segmentFetcherFactory(params));
36
+ const pollingManager = pollingManagerFactory && pollingManagerFactory(params);
43
37
 
44
38
  /** Push Manager */
45
39
  const pushManager = syncEnabled && streamingEnabled && pollingManager && pushManagerFactory ?
@@ -12,9 +12,11 @@ export class Backoff {
12
12
  attempts: number;
13
13
  cb: (...args: any[]) => any;
14
14
  timeoutID: ReturnType<typeof setTimeout> | undefined;
15
+ pending: { resolve: (value: any) => void, reject: (error: any) => void } | undefined;
15
16
 
16
17
  /**
17
- * Schedule function calls with exponential backoff
18
+ * Schedule function calls with exponential backoff.
19
+ * @param cb - The function to call. Must return a promise if used with `scheduleCallAsync`.
18
20
  */
19
21
  constructor(cb: (...args: any[]) => any, baseMillis?: number, maxMillis?: number) {
20
22
  this.baseMillis = Backoff.__TEST__BASE_MILLIS || baseMillis || Backoff.DEFAULT_BASE_MILLIS;
@@ -31,11 +33,12 @@ export class Backoff {
31
33
  let delayInMillis = Math.min(this.baseMillis * Math.pow(2, this.attempts), this.maxMillis);
32
34
 
33
35
  if (this.timeoutID) clearTimeout(this.timeoutID);
36
+ this.attempts++;
37
+
34
38
  this.timeoutID = setTimeout(() => {
35
39
  this.timeoutID = undefined;
36
40
  this.cb();
37
41
  }, delayInMillis);
38
- this.attempts++;
39
42
 
40
43
  return delayInMillis;
41
44
  }
@@ -51,22 +54,31 @@ export class Backoff {
51
54
  this.attempts++;
52
55
 
53
56
  return new Promise<T>((resolve, reject) => {
57
+ this.pending = { resolve, reject };
54
58
  this.timeoutID = setTimeout(() => {
55
59
  this.timeoutID = undefined;
60
+ this.pending = undefined;
56
61
  this.cb().then(resolve, reject);
57
62
  }, delayInMillis);
58
63
  });
59
64
  }
60
65
 
61
66
  /**
62
- * Reset the backoff attempts
67
+ * Reset the backoff attempts, canceling any scheduled `cb` call. If a `scheduleCallAsync` call is pending
68
+ * and the caller wants to settle it immediately instead of waiting for `cb` to be invoked, pass `settle`:
69
+ * `{ value }` to resolve, or `{ error }` to reject.
63
70
  */
64
- reset() {
71
+ reset<T>(settle?: { value: T } | { error: any }) {
65
72
  this.attempts = 0;
66
73
  if (this.timeoutID) {
67
74
  clearTimeout(this.timeoutID);
68
75
  this.timeoutID = undefined;
69
76
  }
77
+ if (settle && this.pending) {
78
+ if ('value' in settle) this.pending.resolve(settle.value);
79
+ else this.pending.reject(settle.error);
80
+ this.pending = undefined;
81
+ }
70
82
  }
71
83
 
72
84
  }
@@ -1,7 +1,7 @@
1
1
  // Type definitions for Split Software SDKs
2
2
  // Project: https://www.split.io/
3
3
 
4
- import type { RedisOptions } from 'ioredis';
4
+ import type { ConnectionOptions } from 'tls';
5
5
  import type { RequestOptions } from 'http';
6
6
 
7
7
  export as namespace SplitIO;
@@ -1031,9 +1031,10 @@ declare namespace SplitIO {
1031
1031
  */
1032
1032
  label: string;
1033
1033
  /**
1034
- * Version of the feature flag
1034
+ * Version of the feature flag.
1035
+ * Undefined if the feature flag was not found, for example, if the label is 'not ready', 'exception' or 'definition not found'.
1035
1036
  */
1036
- changeNumber: number;
1037
+ changeNumber?: number;
1037
1038
  /**
1038
1039
  * Previous time
1039
1040
  */
@@ -1714,7 +1715,7 @@ declare namespace SplitIO {
1714
1715
  *
1715
1716
  * @defaultValue `undefined`
1716
1717
  */
1717
- tls?: RedisOptions['tls'];
1718
+ tls?: ConnectionOptions;
1718
1719
  };
1719
1720
  /**
1720
1721
  * Optional prefix to prevent any kind of data collision between SDK versions.
@@ -1,15 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.platform = void 0;
4
- var EventEmitter_1 = require("../utils/EventEmitter");
5
- var browser_1 = require("../platform/getFetch/browser");
6
- var browser_2 = require("../platform/getEventSource/browser");
7
- var browser_3 = require("../listeners/browser");
8
- var browser_4 = require("../utils/timeTracker/now/browser");
9
- exports.platform = {
10
- getFetch: browser_1.getFetch,
11
- getEventSource: browser_2.getEventSource,
12
- EventEmitter: EventEmitter_1.EventEmitter,
13
- now: browser_4.now,
14
- SignalListener: browser_3.BrowserSignalListener
15
- };
@@ -1,8 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getEventSource = void 0;
4
- function getEventSource() {
5
- // eslint-disable-next-line no-undef -- Feature detection for EventSource
6
- return typeof EventSource === 'function' ? EventSource : undefined;
7
- }
8
- exports.getEventSource = getEventSource;