@splitsoftware/splitio-commons 0.1.1-canary.6 → 0.1.1-rc.18

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 (269) hide show
  1. package/cjs/evaluator/matchers/matcherTypes.js +4 -4
  2. package/cjs/evaluator/matchersTransform/index.js +11 -11
  3. package/cjs/evaluator/value/sanitize.js +6 -6
  4. package/cjs/listeners/browser.js +5 -2
  5. package/cjs/listeners/node.js +9 -2
  6. package/cjs/logger/constants.js +3 -1
  7. package/cjs/logger/messages/error.js +3 -2
  8. package/cjs/logger/messages/info.js +2 -2
  9. package/cjs/logger/messages/warn.js +2 -1
  10. package/cjs/readiness/readinessManager.js +10 -7
  11. package/cjs/sdkFactory/index.js +1 -1
  12. package/cjs/services/splitApi.js +9 -1
  13. package/cjs/services/splitHttpClient.js +5 -4
  14. package/cjs/storages/AbstractSplitsCacheSync.js +1 -1
  15. package/cjs/storages/inLocalStorage/index.js +5 -2
  16. package/cjs/storages/inMemory/InMemoryStorage.js +2 -0
  17. package/cjs/storages/inMemory/InMemoryStorageCS.js +2 -0
  18. package/cjs/storages/inRedis/SplitsCacheInRedis.js +6 -2
  19. package/cjs/storages/inRedis/index.js +5 -2
  20. package/cjs/storages/pluggable/SplitsCachePluggable.js +6 -2
  21. package/cjs/storages/pluggable/inMemoryWrapper.js +6 -7
  22. package/cjs/storages/pluggable/index.js +5 -2
  23. package/cjs/storages/pluggable/wrapperAdapter.js +0 -1
  24. package/cjs/sync/offline/splitsParser/splitsParserFromFile.js +92 -89
  25. package/cjs/sync/offline/splitsParser/splitsParserFromSettings.js +45 -42
  26. package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +14 -4
  27. package/cjs/sync/polling/fetchers/segmentChangesFetcher.js +0 -8
  28. package/cjs/sync/polling/updaters/mySegmentsUpdater.js +30 -10
  29. package/cjs/sync/polling/updaters/segmentChangesUpdater.js +2 -4
  30. package/cjs/sync/streaming/SSEClient/index.js +38 -20
  31. package/cjs/sync/streaming/SSEHandler/NotificationKeeper.js +7 -0
  32. package/cjs/sync/streaming/SSEHandler/NotificationParser.js +4 -1
  33. package/cjs/sync/streaming/SSEHandler/index.js +8 -9
  34. package/cjs/sync/streaming/SSEHandler/types.js +14 -0
  35. package/cjs/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +5 -5
  36. package/cjs/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.js +2 -1
  37. package/cjs/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +5 -3
  38. package/cjs/sync/streaming/constants.js +3 -1
  39. package/cjs/sync/streaming/mySegmentsV2utils.js +75 -0
  40. package/cjs/sync/streaming/pushManager.js +148 -40
  41. package/cjs/sync/submitters/metricsSyncTask.js +1 -1
  42. package/cjs/sync/submitters/submitterSyncTask.js +2 -2
  43. package/cjs/sync/syncManagerFromFile.js +15 -0
  44. package/cjs/sync/syncManagerFromObject.js +14 -0
  45. package/cjs/sync/syncManagerOffline.js +3 -3
  46. package/cjs/sync/syncManagerOnline.js +18 -5
  47. package/cjs/sync/syncTask.js +1 -1
  48. package/cjs/trackers/impressionObserver/ImpressionObserver.js +0 -2
  49. package/cjs/trackers/impressionObserver/buildKey.js +3 -9
  50. package/cjs/trackers/impressionObserver/impressionObserverCS.js +2 -2
  51. package/cjs/trackers/impressionObserver/impressionObserverSS.js +3 -3
  52. package/cjs/utils/constants/index.js +4 -1
  53. package/cjs/utils/decompress/index.js +427 -0
  54. package/cjs/utils/murmur3/{commons.js → common.js} +2 -6
  55. package/cjs/utils/murmur3/murmur3.js +11 -12
  56. package/cjs/utils/murmur3/murmur3_128.js +7 -142
  57. package/cjs/utils/murmur3/murmur3_128_x86.js +154 -0
  58. package/cjs/utils/murmur3/murmur3_64.js +36 -0
  59. package/cjs/utils/murmur3/utfx.js +100 -106
  60. package/cjs/utils/promise/wrapper.js +14 -11
  61. package/cjs/utils/settingsValidation/index.js +5 -2
  62. package/cjs/utils/settingsValidation/localhost/index.js +20 -0
  63. package/cjs/utils/settingsValidation/splitFilters.js +0 -1
  64. package/cjs/utils/settingsValidation/storage/storageCS.js +18 -8
  65. package/cjs/utils/settingsValidation/url.js +1 -1
  66. package/esm/evaluator/matchers/matcherTypes.js +2 -2
  67. package/esm/evaluator/matchersTransform/index.js +12 -12
  68. package/esm/evaluator/value/sanitize.js +7 -7
  69. package/esm/listeners/browser.js +5 -2
  70. package/esm/listeners/node.js +9 -2
  71. package/esm/logger/constants.js +2 -0
  72. package/esm/logger/messages/error.js +3 -2
  73. package/esm/logger/messages/info.js +2 -2
  74. package/esm/logger/messages/warn.js +2 -1
  75. package/esm/readiness/readinessManager.js +10 -7
  76. package/esm/sdkFactory/index.js +1 -1
  77. package/esm/services/splitApi.js +9 -1
  78. package/esm/services/splitHttpClient.js +5 -4
  79. package/esm/storages/AbstractSplitsCacheSync.js +1 -1
  80. package/esm/storages/inLocalStorage/index.js +5 -2
  81. package/esm/storages/inMemory/InMemoryStorage.js +2 -0
  82. package/esm/storages/inMemory/InMemoryStorageCS.js +2 -0
  83. package/esm/storages/inRedis/SplitsCacheInRedis.js +6 -2
  84. package/esm/storages/inRedis/index.js +5 -2
  85. package/esm/storages/pluggable/SplitsCachePluggable.js +6 -2
  86. package/esm/storages/pluggable/inMemoryWrapper.js +6 -7
  87. package/esm/storages/pluggable/index.js +5 -2
  88. package/esm/storages/pluggable/wrapperAdapter.js +0 -1
  89. package/esm/sync/offline/splitsParser/splitsParserFromFile.js +90 -88
  90. package/esm/sync/offline/splitsParser/splitsParserFromSettings.js +43 -41
  91. package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +15 -5
  92. package/esm/sync/polling/fetchers/segmentChangesFetcher.js +0 -8
  93. package/esm/sync/polling/updaters/mySegmentsUpdater.js +30 -10
  94. package/esm/sync/polling/updaters/segmentChangesUpdater.js +2 -4
  95. package/esm/sync/streaming/SSEClient/index.js +38 -20
  96. package/esm/sync/streaming/SSEHandler/NotificationKeeper.js +7 -0
  97. package/esm/sync/streaming/SSEHandler/NotificationParser.js +4 -1
  98. package/esm/sync/streaming/SSEHandler/index.js +9 -10
  99. package/esm/sync/streaming/SSEHandler/types.js +13 -1
  100. package/esm/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +5 -5
  101. package/esm/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.js +2 -1
  102. package/esm/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +5 -3
  103. package/esm/sync/streaming/constants.js +2 -0
  104. package/esm/sync/streaming/mySegmentsV2utils.js +69 -0
  105. package/esm/sync/streaming/pushManager.js +150 -42
  106. package/esm/sync/submitters/metricsSyncTask.js +1 -1
  107. package/esm/sync/submitters/submitterSyncTask.js +2 -2
  108. package/esm/sync/syncManagerFromFile.js +11 -0
  109. package/esm/sync/syncManagerFromObject.js +10 -0
  110. package/esm/sync/syncManagerOffline.js +3 -3
  111. package/esm/sync/syncManagerOnline.js +18 -5
  112. package/esm/sync/syncTask.js +1 -1
  113. package/esm/trackers/impressionObserver/ImpressionObserver.js +0 -2
  114. package/esm/trackers/impressionObserver/buildKey.js +2 -9
  115. package/esm/trackers/impressionObserver/impressionObserverCS.js +2 -2
  116. package/esm/trackers/impressionObserver/impressionObserverSS.js +3 -3
  117. package/esm/utils/constants/index.js +3 -0
  118. package/esm/utils/decompress/index.js +424 -0
  119. package/esm/utils/murmur3/{commons.js → common.js} +1 -4
  120. package/esm/utils/murmur3/murmur3.js +1 -2
  121. package/esm/utils/murmur3/murmur3_128.js +7 -142
  122. package/esm/utils/murmur3/murmur3_128_x86.js +150 -0
  123. package/esm/utils/murmur3/murmur3_64.js +32 -0
  124. package/esm/utils/murmur3/utfx.js +96 -106
  125. package/esm/utils/promise/wrapper.js +14 -11
  126. package/esm/utils/settingsValidation/index.js +5 -2
  127. package/esm/utils/settingsValidation/localhost/index.js +16 -0
  128. package/esm/utils/settingsValidation/splitFilters.js +0 -1
  129. package/esm/utils/settingsValidation/storage/storageCS.js +16 -7
  130. package/esm/utils/settingsValidation/url.js +1 -1
  131. package/package.json +5 -5
  132. package/src/evaluator/matchers/matcherTypes.ts +2 -2
  133. package/src/evaluator/matchersTransform/index.ts +12 -12
  134. package/src/evaluator/value/sanitize.ts +7 -7
  135. package/src/listeners/browser.ts +5 -2
  136. package/src/listeners/node.ts +14 -2
  137. package/src/logger/constants.ts +2 -0
  138. package/src/logger/messages/error.ts +3 -2
  139. package/src/logger/messages/info.ts +2 -2
  140. package/src/logger/messages/warn.ts +3 -1
  141. package/src/readiness/readinessManager.ts +9 -7
  142. package/src/sdkFactory/index.ts +1 -1
  143. package/src/sdkFactory/types.ts +4 -5
  144. package/src/services/splitApi.ts +12 -3
  145. package/src/services/splitHttpClient.ts +6 -5
  146. package/src/services/types.ts +7 -3
  147. package/src/storages/AbstractSplitsCacheSync.ts +1 -1
  148. package/src/storages/inLocalStorage/index.ts +8 -4
  149. package/src/storages/inMemory/InMemoryStorage.ts +3 -0
  150. package/src/storages/inMemory/InMemoryStorageCS.ts +3 -0
  151. package/src/storages/inRedis/SplitsCacheInRedis.ts +3 -1
  152. package/src/storages/inRedis/index.ts +8 -4
  153. package/src/storages/pluggable/SegmentsCachePluggable.ts +1 -1
  154. package/src/storages/pluggable/SplitsCachePluggable.ts +3 -1
  155. package/src/storages/pluggable/inMemoryWrapper.ts +6 -7
  156. package/src/storages/pluggable/index.ts +8 -4
  157. package/src/storages/pluggable/wrapperAdapter.ts +0 -1
  158. package/src/storages/types.ts +18 -15
  159. package/src/sync/offline/splitsParser/splitsParserFromFile.ts +110 -105
  160. package/src/sync/offline/splitsParser/splitsParserFromSettings.ts +45 -41
  161. package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +15 -5
  162. package/src/sync/polling/fetchers/segmentChangesFetcher.ts +0 -7
  163. package/src/sync/polling/types.ts +2 -1
  164. package/src/sync/polling/updaters/mySegmentsUpdater.ts +28 -10
  165. package/src/sync/polling/updaters/segmentChangesUpdater.ts +2 -3
  166. package/src/sync/streaming/AuthClient/types.ts +3 -0
  167. package/src/sync/streaming/SSEClient/index.ts +43 -23
  168. package/src/sync/streaming/SSEClient/types.ts +0 -1
  169. package/src/sync/streaming/SSEHandler/NotificationKeeper.ts +8 -0
  170. package/src/sync/streaming/SSEHandler/NotificationParser.ts +4 -2
  171. package/src/sync/streaming/SSEHandler/index.ts +11 -20
  172. package/src/sync/streaming/SSEHandler/types.ts +37 -3
  173. package/src/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.ts +7 -6
  174. package/src/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.ts +2 -1
  175. package/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts +4 -3
  176. package/src/sync/streaming/UpdateWorkers/types.ts +1 -1
  177. package/src/sync/streaming/constants.ts +2 -0
  178. package/src/sync/streaming/mySegmentsV2utils.ts +77 -0
  179. package/src/sync/streaming/pushManager.ts +145 -42
  180. package/src/sync/streaming/types.ts +14 -22
  181. package/src/sync/submitters/metricsSyncTask.ts +1 -1
  182. package/src/sync/submitters/submitterSyncTask.ts +2 -1
  183. package/src/sync/syncManagerFromFile.ts +13 -0
  184. package/src/sync/syncManagerFromObject.ts +12 -0
  185. package/src/sync/syncManagerOffline.ts +3 -3
  186. package/src/sync/syncManagerOnline.ts +19 -5
  187. package/src/sync/syncTask.ts +1 -1
  188. package/src/sync/types.ts +3 -1
  189. package/src/trackers/impressionObserver/ImpressionObserver.ts +4 -6
  190. package/src/trackers/impressionObserver/buildKey.ts +2 -16
  191. package/src/trackers/impressionObserver/impressionObserverCS.ts +2 -2
  192. package/src/trackers/impressionObserver/impressionObserverSS.ts +3 -3
  193. package/src/types.ts +16 -2
  194. package/src/utils/constants/index.ts +6 -1
  195. package/src/utils/decompress/index.ts +429 -0
  196. package/src/utils/lang/index.ts +1 -1
  197. package/src/utils/murmur3/{commons.ts → common.ts} +1 -5
  198. package/src/utils/murmur3/murmur3.ts +5 -5
  199. package/src/utils/murmur3/murmur3_128.ts +7 -180
  200. package/src/utils/murmur3/murmur3_128_x86.ts +188 -0
  201. package/src/utils/murmur3/murmur3_64.ts +36 -0
  202. package/src/utils/murmur3/utfx.ts +92 -110
  203. package/src/utils/promise/wrapper.ts +12 -9
  204. package/src/utils/settingsValidation/index.ts +8 -4
  205. package/src/utils/settingsValidation/localhost/index.ts +19 -0
  206. package/src/utils/settingsValidation/splitFilters.ts +0 -1
  207. package/src/utils/settingsValidation/storage/storageCS.ts +21 -8
  208. package/src/utils/settingsValidation/types.ts +2 -11
  209. package/src/utils/settingsValidation/url.ts +1 -1
  210. package/types/evaluator/matchers/matcherTypes.d.ts +2 -2
  211. package/types/listeners/browser.d.ts +3 -3
  212. package/types/listeners/node.d.ts +3 -2
  213. package/types/logger/constants.d.ts +2 -0
  214. package/types/sdkFactory/types.d.ts +4 -5
  215. package/types/services/types.d.ts +4 -0
  216. package/types/storages/inLocalStorage/index.d.ts +2 -2
  217. package/types/storages/inMemory/InMemoryStorage.d.ts +3 -0
  218. package/types/storages/inMemory/InMemoryStorageCS.d.ts +3 -0
  219. package/types/storages/inRedis/index.d.ts +2 -2
  220. package/types/storages/pluggable/index.d.ts +2 -2
  221. package/types/storages/types.d.ts +15 -15
  222. package/types/sync/offline/splitsParser/splitsParserFromFile.d.ts +2 -7
  223. package/types/sync/offline/splitsParser/splitsParserFromSettings.d.ts +1 -5
  224. package/types/sync/polling/types.d.ts +2 -1
  225. package/types/sync/streaming/AuthClient/indexV1.d.ts +12 -0
  226. package/types/sync/streaming/AuthClient/indexV2.d.ts +8 -0
  227. package/types/sync/streaming/AuthClient/types.d.ts +2 -0
  228. package/types/sync/streaming/SSEClient/index.d.ts +9 -12
  229. package/types/sync/streaming/SSEClient/types.d.ts +0 -1
  230. package/types/sync/streaming/SSEHandler/NotificationParser.d.ts +3 -2
  231. package/types/sync/streaming/SSEHandler/types.d.ts +30 -2
  232. package/types/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.d.ts +4 -3
  233. package/types/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.d.ts +2 -1
  234. package/types/sync/streaming/UpdateWorkers/SplitsUpdateWorker.d.ts +3 -2
  235. package/types/sync/streaming/UpdateWorkers/types.d.ts +1 -1
  236. package/types/sync/streaming/constants.d.ts +3 -1
  237. package/types/sync/streaming/mySegmentsV2utils.d.ts +27 -0
  238. package/types/sync/streaming/pushManagerNoUsers.d.ts +13 -0
  239. package/types/sync/streaming/types.d.ts +9 -5
  240. package/types/sync/submitters/submitterSyncTask.d.ts +1 -1
  241. package/types/sync/syncManagerFromFile.d.ts +2 -0
  242. package/types/sync/syncManagerFromObject.d.ts +2 -0
  243. package/types/sync/syncManagerOffline.d.ts +1 -1
  244. package/types/sync/syncTask.d.ts +1 -1
  245. package/types/sync/types.d.ts +2 -0
  246. package/types/trackers/impressionObserver/ImpressionObserver.d.ts +2 -2
  247. package/types/trackers/impressionObserver/buildKey.d.ts +1 -1
  248. package/types/trackers/impressionObserver/impressionObserverCS.d.ts +2 -2
  249. package/types/trackers/impressionObserver/impressionObserverSS.d.ts +2 -2
  250. package/types/types.d.ts +16 -2
  251. package/types/utils/constants/index.d.ts +5 -1
  252. package/types/utils/decompress/index.d.ts +16 -0
  253. package/types/utils/lang/index.d.ts +1 -1
  254. package/types/utils/murmur3/common.d.ts +12 -0
  255. package/types/utils/murmur3/murmur3.d.ts +2 -2
  256. package/types/utils/murmur3/murmur3_128.d.ts +5 -0
  257. package/types/utils/murmur3/murmur3_128_x86.d.ts +7 -0
  258. package/types/utils/murmur3/murmur3_64.d.ts +10 -0
  259. package/types/utils/murmur3/utfx.d.ts +24 -6
  260. package/types/utils/settingsValidation/index.d.ts +3 -2
  261. package/types/utils/settingsValidation/localhost/index.d.ts +9 -0
  262. package/types/utils/settingsValidation/storage/storageCS.d.ts +7 -1
  263. package/types/utils/settingsValidation/types.d.ts +2 -10
  264. package/cjs/sync/streaming/pushManagerCS.js +0 -178
  265. package/cjs/sync/streaming/pushManagerSS.js +0 -128
  266. package/esm/sync/streaming/pushManagerCS.js +0 -174
  267. package/esm/sync/streaming/pushManagerSS.js +0 -124
  268. package/src/sync/streaming/pushManagerCS.ts +0 -237
  269. package/src/sync/streaming/pushManagerSS.ts +0 -177
@@ -8,7 +8,6 @@ export const METHODS_TO_PROMISE_WRAP: string[] = [
8
8
  'getAndSet',
9
9
  'del',
10
10
  'getKeysByPrefix',
11
- 'getByPrefix',
12
11
  'incr',
13
12
  'decr',
14
13
  'getMany',
@@ -57,15 +57,6 @@ export interface ICustomStorageWrapper {
57
57
  * The promise rejects if the operation fails.
58
58
  */
59
59
  getKeysByPrefix: (prefix: string) => Promise<string[]>
60
- /**
61
- * Returns all values which keys match the given prefix.
62
- *
63
- * @function getByPrefix
64
- * @param {string} prefix String prefix to match
65
- * @returns {Promise<string[]>} A promise that resolves with the list of values which keys match the given `prefix`.
66
- * The promise rejects if the operation fails.
67
- */
68
- getByPrefix: (prefix: string) => Promise<string[]>
69
60
  /**
70
61
  * Returns the values of all given `keys`.
71
62
  *
@@ -83,19 +74,19 @@ export interface ICustomStorageWrapper {
83
74
  *
84
75
  * @function incr
85
76
  * @param {string} key Key to increment
86
- * @returns {Promise<void>} A promise that resolves if the operation success. The promise rejects if the operation fails,
77
+ * @returns {Promise<number>} A promise that resolves with the value of key after the increment. The promise rejects if the operation fails,
87
78
  * for example, if there is a connection error or the key contains a string that can not be represented as integer.
88
79
  */
89
- incr: (key: string) => Promise<void | boolean>
80
+ incr: (key: string) => Promise<number>
90
81
  /**
91
82
  * Decrements in 1 the given `key` value or set it in -1 if the value doesn't exist.
92
83
  *
93
84
  * @function decr
94
85
  * @param {string} key Key to decrement
95
- * @returns {Promise<void>} A promise that resolves if the operation success. The promise rejects if the operation fails,
86
+ * @returns {Promise<number>} A promise that resolves with the value of key after the decrement. The promise rejects if the operation fails,
96
87
  * for example, if there is a connection error or the key contains a string that can not be represented as integer.
97
88
  */
98
- decr: (key: string) => Promise<void | boolean>
89
+ decr: (key: string) => Promise<number>
99
90
 
100
91
  /** Queue operations */
101
92
 
@@ -266,8 +257,8 @@ export interface ISegmentsCacheBase {
266
257
 
267
258
  // Same API for both variants: SegmentsCache and MySegmentsCache (client-side API)
268
259
  export interface ISegmentsCacheSync extends ISegmentsCacheBase {
269
- addToSegment(name: string, segmentKeys: string[]): boolean
270
- removeFromSegment(name: string, segmentKeys: string[]): boolean
260
+ addToSegment(name: string, segmentKeys?: string[]): boolean
261
+ removeFromSegment(name: string, segmentKeys?: string[]): boolean
271
262
  isInSegment(name: string, key?: string): boolean
272
263
  registerSegments(names: string[]): boolean
273
264
  getRegisteredSegments(): string[]
@@ -448,3 +439,15 @@ export interface IStorageFactoryParams {
448
439
  onReadyCb?: (error?: any) => void,
449
440
  metadata: IMetadata,
450
441
  }
442
+
443
+ export type StorageType = 'MEMORY' | 'LOCALSTORAGE' | 'REDIS' | 'CUSTOM';
444
+
445
+ export type IStorageSyncFactory = {
446
+ type: StorageType,
447
+ (params: IStorageFactoryParams): IStorageSync
448
+ }
449
+
450
+ export type IStorageAsyncFactory = {
451
+ type: StorageType,
452
+ (params: IStorageFactoryParams): IStorageAsync
453
+ }
@@ -7,8 +7,9 @@ import yaml from 'js-yaml';
7
7
  import { isString, endsWith, find, forOwn, uniq, } from '../../../utils/lang';
8
8
  import parseCondition, { IMockSplitEntry } from './parseCondition';
9
9
  import { ISplitPartial } from '../../../dtos/types';
10
- import { SplitIO } from '../../../types';
10
+ import { ISettings, SplitIO } from '../../../types';
11
11
  import { ILogger } from '../../../logger/types';
12
+ import { ISplitsParser } from './types';
12
13
 
13
14
  const logPrefix = 'sync:offline:splits-fetcher: ';
14
15
 
@@ -16,8 +17,6 @@ type IYamlSplitEntry = Record<string, IMockSplitEntry>
16
17
 
17
18
  const DEFAULT_FILENAME = '.split';
18
19
 
19
- let previousMock = 'NO_MOCK_LOADED';
20
-
21
20
  function configFilesPath(configFilePath?: SplitIO.MockedFeaturesFilePath): SplitIO.MockedFeaturesFilePath {
22
21
  if (configFilePath === DEFAULT_FILENAME || !isString(configFilePath)) {
23
22
  let root = process.env.HOME;
@@ -39,96 +38,6 @@ function configFilesPath(configFilePath?: SplitIO.MockedFeaturesFilePath): Split
39
38
  return configFilePath as SplitIO.MockedFeaturesFilePath;
40
39
  }
41
40
 
42
- // Parse `.split` configuration file and return a map of "Split Objects"
43
- function readSplitConfigFile(log: ILogger, filePath: SplitIO.MockedFeaturesFilePath): false | Record<string, ISplitPartial> {
44
- const SPLIT_POSITION = 0;
45
- const TREATMENT_POSITION = 1;
46
- let data;
47
-
48
- try {
49
- data = fs.readFileSync(filePath, 'utf-8');
50
- } catch (e) {
51
- log.error(e.message);
52
-
53
- return {};
54
- }
55
-
56
- if (data === previousMock) return false;
57
- previousMock = data;
58
-
59
- const splitObjects = data.split(/\r?\n/).reduce((accum, line, index) => {
60
- let tuple: string | string[] = line.trim();
61
-
62
- if (tuple === '' || tuple.charAt(0) === '#') {
63
- log.debug(logPrefix + `Ignoring empty line or comment at #${index}`);
64
- } else {
65
- tuple = tuple.split(/\s+/);
66
-
67
- if (tuple.length !== 2) {
68
- log.debug(logPrefix + `Ignoring line since it does not have exactly two columns #${index}`);
69
- } else {
70
- const splitName = tuple[SPLIT_POSITION];
71
- const condition = parseCondition({ treatment: tuple[TREATMENT_POSITION] });
72
- accum[splitName] = { conditions: [condition], configurations: {}, trafficTypeName: 'localhost' };
73
- }
74
- }
75
-
76
- return accum;
77
- }, {} as Record<string, ISplitPartial>);
78
-
79
- return splitObjects;
80
- }
81
-
82
- // Parse `.yml` or `.yaml` configuration files and return a map of "Split Objects"
83
- function readYAMLConfigFile(log: ILogger, filePath: SplitIO.MockedFeaturesFilePath): false | Record<string, ISplitPartial> {
84
- let data = '';
85
- let yamldoc = null;
86
-
87
- try {
88
- data = fs.readFileSync(filePath, 'utf8');
89
-
90
- if (data === previousMock) return false;
91
- previousMock = data;
92
-
93
- yamldoc = yaml.safeLoad(data);
94
- } catch (e) {
95
- log.error(e);
96
-
97
- return {};
98
- }
99
-
100
- // Each entry will be mapped to a condition, but we'll also keep the configurations map.
101
- const mocksData = (yamldoc as IYamlSplitEntry[]).reduce((accum, splitEntry) => {
102
- const splitName = Object.keys(splitEntry)[0];
103
-
104
- if (!splitName || !isString(splitEntry[splitName].treatment))
105
- log.error(logPrefix + 'Ignoring entry on YAML since the format is incorrect.');
106
-
107
- const mockData = splitEntry[splitName];
108
-
109
- // "Template" for each split accumulated data
110
- if (!accum[splitName]) {
111
- accum[splitName] = {
112
- configurations: {}, conditions: [], treatments: [], trafficTypeName: 'localhost'
113
- };
114
- }
115
-
116
- // Assign the config if there is one on the mock
117
- if (mockData.config) accum[splitName].configurations[mockData.treatment] = mockData.config;
118
- // Parse the condition from the entry.
119
- const condition = parseCondition(mockData);
120
- accum[splitName].conditions[condition.conditionType === 'ROLLOUT' ? 'push' : 'unshift'](condition);
121
- // Also keep track of the treatments, will be useful for manager functionality.
122
- accum[splitName].treatments.push(mockData.treatment);
123
-
124
- return accum;
125
- }, {} as Record<string, Required<ISplitPartial> & { treatments: string[] }>);
126
-
127
- arrangeConditions(mocksData);
128
-
129
- return mocksData;
130
- }
131
-
132
41
  // This function is not pure nor meant to be. Here we apply modifications to cover
133
42
  // for behaviour that's ensured by the BE.
134
43
  function arrangeConditions(mocksData: Record<string, Required<ISplitPartial> & { treatments: string[] }>) {
@@ -160,18 +69,114 @@ function arrangeConditions(mocksData: Record<string, Required<ISplitPartial> & {
160
69
  });
161
70
  }
162
71
 
163
- // Load the content of a configuration file into an Object
164
- export default function splitsParserFromFile({ features, log }: { features?: SplitIO.MockedFeaturesFilePath, log: ILogger }): false | Record<string, ISplitPartial> {
165
- const filePath = configFilesPath(features);
166
- let mockData: false | Record<string, ISplitPartial>;
167
-
168
- // If we have a filePath, it means the extension is correct, choose the parser.
169
- if (endsWith(filePath, '.split')) {
170
- log.warn(logPrefix + '.split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.');
171
- mockData = readSplitConfigFile(log, filePath);
172
- } else {
173
- mockData = readYAMLConfigFile(log, filePath);
72
+ export function splitsParserFromFileFactory(): ISplitsParser {
73
+
74
+ let previousMock = 'NO_MOCK_LOADED';
75
+
76
+ // Parse `.split` configuration file and return a map of "Split Objects"
77
+ function readSplitConfigFile(log: ILogger, filePath: SplitIO.MockedFeaturesFilePath): false | Record<string, ISplitPartial> {
78
+ const SPLIT_POSITION = 0;
79
+ const TREATMENT_POSITION = 1;
80
+ let data;
81
+
82
+ try {
83
+ data = fs.readFileSync(filePath, 'utf-8');
84
+ } catch (e) {
85
+ log.error(e.message);
86
+
87
+ return {};
88
+ }
89
+
90
+ if (data === previousMock) return false;
91
+ previousMock = data;
92
+
93
+ const splitObjects = data.split(/\r?\n/).reduce((accum, line, index) => {
94
+ let tuple: string | string[] = line.trim();
95
+
96
+ if (tuple === '' || tuple.charAt(0) === '#') {
97
+ log.debug(logPrefix + `Ignoring empty line or comment at #${index}`);
98
+ } else {
99
+ tuple = tuple.split(/\s+/);
100
+
101
+ if (tuple.length !== 2) {
102
+ log.debug(logPrefix + `Ignoring line since it does not have exactly two columns #${index}`);
103
+ } else {
104
+ const splitName = tuple[SPLIT_POSITION];
105
+ const condition = parseCondition({ treatment: tuple[TREATMENT_POSITION] });
106
+ accum[splitName] = { conditions: [condition], configurations: {}, trafficTypeName: 'localhost' };
107
+ }
108
+ }
109
+
110
+ return accum;
111
+ }, {} as Record<string, ISplitPartial>);
112
+
113
+ return splitObjects;
114
+ }
115
+
116
+ // Parse `.yml` or `.yaml` configuration files and return a map of "Split Objects"
117
+ function readYAMLConfigFile(log: ILogger, filePath: SplitIO.MockedFeaturesFilePath): false | Record<string, ISplitPartial> {
118
+ let data = '';
119
+ let yamldoc = null;
120
+
121
+ try {
122
+ data = fs.readFileSync(filePath, 'utf8');
123
+
124
+ if (data === previousMock) return false;
125
+ previousMock = data;
126
+
127
+ yamldoc = yaml.safeLoad(data);
128
+ } catch (e) {
129
+ log.error(e);
130
+
131
+ return {};
132
+ }
133
+
134
+ // Each entry will be mapped to a condition, but we'll also keep the configurations map.
135
+ const mocksData = (yamldoc as IYamlSplitEntry[]).reduce((accum, splitEntry) => {
136
+ const splitName = Object.keys(splitEntry)[0];
137
+
138
+ if (!splitName || !isString(splitEntry[splitName].treatment))
139
+ log.error(logPrefix + 'Ignoring entry on YAML since the format is incorrect.');
140
+
141
+ const mockData = splitEntry[splitName];
142
+
143
+ // "Template" for each split accumulated data
144
+ if (!accum[splitName]) {
145
+ accum[splitName] = {
146
+ configurations: {}, conditions: [], treatments: [], trafficTypeName: 'localhost'
147
+ };
148
+ }
149
+
150
+ // Assign the config if there is one on the mock
151
+ if (mockData.config) accum[splitName].configurations[mockData.treatment] = mockData.config;
152
+ // Parse the condition from the entry.
153
+ const condition = parseCondition(mockData);
154
+ accum[splitName].conditions[condition.conditionType === 'ROLLOUT' ? 'push' : 'unshift'](condition);
155
+ // Also keep track of the treatments, will be useful for manager functionality.
156
+ accum[splitName].treatments.push(mockData.treatment);
157
+
158
+ return accum;
159
+ }, {} as Record<string, Required<ISplitPartial> & { treatments: string[] }>);
160
+
161
+ arrangeConditions(mocksData);
162
+
163
+ return mocksData;
174
164
  }
175
165
 
176
- return mockData;
166
+ // Load the content of a configuration file into an Object
167
+ return function splitsParserFromFile({ features, log }: ISettings): false | Record<string, ISplitPartial> {
168
+ const filePath = configFilesPath(features as string);
169
+ let mockData: false | Record<string, ISplitPartial>;
170
+
171
+ // If we have a filePath, it means the extension is correct, choose the parser.
172
+ if (endsWith(filePath, '.split')) {
173
+ log.warn(logPrefix + '.split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.');
174
+ mockData = readSplitConfigFile(log, filePath);
175
+ } else {
176
+ mockData = readYAMLConfigFile(log, filePath);
177
+ }
178
+
179
+ return mockData;
180
+ };
181
+
177
182
  }
@@ -3,8 +3,6 @@ import { ISettings, SplitIO } from '../../../types';
3
3
  import { isObject, forOwn } from '../../../utils/lang';
4
4
  import parseCondition from './parseCondition';
5
5
 
6
- let previousMock: SplitIO.MockedFeaturesMap = { 'emptyMock': '1' };
7
-
8
6
  function hasTreatmentChanged(prev: string | SplitIO.TreatmentWithConfig, curr: string | SplitIO.TreatmentWithConfig) {
9
7
  if (typeof prev !== typeof curr) return true;
10
8
 
@@ -15,54 +13,60 @@ function hasTreatmentChanged(prev: string | SplitIO.TreatmentWithConfig, curr: s
15
13
  }
16
14
  }
17
15
 
18
- function mockUpdated(currentData: SplitIO.MockedFeaturesMap) {
19
- const names = Object.keys(currentData);
16
+ export function splitsParserFromSettingsFactory() {
20
17
 
21
- // Different amount of items
22
- if (names.length !== Object.keys(previousMock).length) {
23
- previousMock = currentData;
24
- return true;
25
- }
18
+ let previousMock: SplitIO.MockedFeaturesMap = { 'emptyMock': '1' };
26
19
 
27
- return names.some(name => {
28
- const newSplit = !previousMock[name];
29
- const newTreatment = hasTreatmentChanged(previousMock[name], currentData[name]);
30
- const changed = newSplit || newTreatment;
20
+ function mockUpdated(currentData: SplitIO.MockedFeaturesMap) {
21
+ const names = Object.keys(currentData);
31
22
 
32
- if (changed) previousMock = currentData;
23
+ // Different amount of items
24
+ if (names.length !== Object.keys(previousMock).length) {
25
+ previousMock = currentData;
26
+ return true;
27
+ }
33
28
 
34
- return changed;
35
- });
36
- }
29
+ return names.some(name => {
30
+ const newSplit = !previousMock[name];
31
+ const newTreatment = hasTreatmentChanged(previousMock[name], currentData[name]);
32
+ const changed = newSplit || newTreatment;
37
33
 
38
- /**
39
- *
40
- * @param features validated object with mocked features mapping.
41
- */
42
- export default function splitsParserFromSettings(settings: ISettings): false | Record<string, ISplitPartial> {
43
- const features = settings.features as SplitIO.MockedFeaturesMap || {};
34
+ if (changed) previousMock = currentData;
44
35
 
45
- if (!mockUpdated(features)) return false;
36
+ return changed;
37
+ });
38
+ }
46
39
 
47
- const splitObjects: Record<string, ISplitPartial> = {};
40
+ /**
41
+ *
42
+ * @param settings validated object with mocked features mapping.
43
+ */
44
+ return function splitsParserFromSettings(settings: ISettings): false | Record<string, ISplitPartial> {
45
+ const features = settings.features as SplitIO.MockedFeaturesMap || {};
48
46
 
49
- forOwn(features, (data, splitName) => {
50
- let treatment = data;
51
- let config = null;
47
+ if (!mockUpdated(features)) return false;
52
48
 
53
- if (isObject(data)) {
54
- treatment = (data as SplitIO.TreatmentWithConfig).treatment;
55
- config = (data as SplitIO.TreatmentWithConfig).config || config;
56
- }
57
- const configurations: Record<string, string> = {};
58
- if (config !== null) configurations[treatment as string] = config;
49
+ const splitObjects: Record<string, ISplitPartial> = {};
50
+
51
+ forOwn(features, (data, splitName) => {
52
+ let treatment = data;
53
+ let config = null;
54
+
55
+ if (isObject(data)) {
56
+ treatment = (data as SplitIO.TreatmentWithConfig).treatment;
57
+ config = (data as SplitIO.TreatmentWithConfig).config || config;
58
+ }
59
+ const configurations: Record<string, string> = {};
60
+ if (config !== null) configurations[treatment as string] = config;
61
+
62
+ splitObjects[splitName] = {
63
+ trafficTypeName: 'localhost',
64
+ conditions: [parseCondition({ treatment: treatment as string })],
65
+ configurations
66
+ };
67
+ });
59
68
 
60
- splitObjects[splitName] = {
61
- trafficTypeName: 'localhost',
62
- conditions: [parseCondition({ treatment: treatment as string })],
63
- configurations
64
- };
65
- });
69
+ return splitObjects;
70
+ };
66
71
 
67
- return splitObjects;
68
72
  }
@@ -7,7 +7,7 @@ import syncTaskFactory from '../../syncTask';
7
7
  import { ISyncTask } from '../../types';
8
8
  import { ISettings } from '../../../types';
9
9
  import { CONTROL } from '../../../utils/constants';
10
- import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants';
10
+ import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED, SDK_SPLITS_CACHE_LOADED } from '../../../readiness/constants';
11
11
  import { SYNC_OFFLINE_DATA, ERROR_SYNC_OFFLINE_LOADING } from '../../../logger/constants';
12
12
 
13
13
  /**
@@ -20,7 +20,8 @@ export function fromObjectUpdaterFactory(
20
20
  settings: ISettings,
21
21
  ): () => Promise<boolean> {
22
22
 
23
- const log = settings.log;
23
+ const log = settings.log, splitsCache = storage.splits;
24
+ let startingUp = true;
24
25
 
25
26
  return function objectUpdater() {
26
27
  const splits: [string, string][] = [];
@@ -53,11 +54,20 @@ export function fromObjectUpdaterFactory(
53
54
  });
54
55
 
55
56
  return Promise.all([
56
- storage.splits.clear(),
57
- storage.splits.addSplits(splits)
57
+ splitsCache.clear(), // required to sync removed splits from mock
58
+ splitsCache.addSplits(splits)
58
59
  ]).then(() => {
59
60
  readiness.splits.emit(SDK_SPLITS_ARRIVED);
60
- readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
61
+
62
+ if (startingUp) {
63
+ startingUp = false;
64
+ Promise.resolve(splitsCache.checkCache()).then(cacheReady => {
65
+ // Emits SDK_READY_FROM_CACHE
66
+ if (cacheReady) readiness.splits.emit(SDK_SPLITS_CACHE_LOADED);
67
+ // Emits SDK_READY
68
+ readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
69
+ });
70
+ }
61
71
  return true;
62
72
  });
63
73
  } else {
@@ -14,13 +14,6 @@ function greedyFetch(fetchSegmentChanges: IFetchSegmentChanges, since: number, s
14
14
  return [flatMe[0], ...flatMe[1]];
15
15
  });
16
16
  }
17
- })
18
- .catch(err => {
19
- // If the operation is forbidden it may be due to permissions, don't recover and propagate the error.
20
- if (err.statusCode === 403) throw err;
21
- // if something goes wrong with the request to the server, we are going to
22
- // stop requesting information till the next round of downloading
23
- return [];
24
17
  });
25
18
  }
26
19
 
@@ -2,11 +2,12 @@ import { IReadinessManager } from '../../readiness/types';
2
2
  import { ISplitApi } from '../../services/types';
3
3
  import { IStorageSync } from '../../storages/types';
4
4
  import { ISettings } from '../../types';
5
+ import { SegmentsData } from '../streaming/SSEHandler/types';
5
6
  import { ITask, ISyncTask } from '../types';
6
7
 
7
8
  export interface ISplitsSyncTask extends ISyncTask<[noCache?: boolean], boolean> { }
8
9
 
9
- export interface ISegmentsSyncTask extends ISyncTask<[segmentNames?: string[], noCache?: boolean, fetchOnlyNew?: boolean], boolean> { }
10
+ export interface ISegmentsSyncTask extends ISyncTask<[segmentNames?: SegmentsData, noCache?: boolean, fetchOnlyNew?: boolean], boolean> { }
10
11
 
11
12
  export interface IPollingManager extends ITask {
12
13
  syncAll(): Promise<any>
@@ -5,6 +5,7 @@ import timeout from '../../../utils/promise/timeout';
5
5
  import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants';
6
6
  import { ILogger } from '../../../logger/types';
7
7
  import { SYNC_MYSEGMENTS_FETCH_RETRY } from '../../../logger/constants';
8
+ import { SegmentsData } from '../../streaming/SSEHandler/types';
8
9
 
9
10
  type IMySegmentsUpdater = (segmentList?: string[], noCache?: boolean) => Promise<boolean>
10
11
 
@@ -38,9 +39,23 @@ export function mySegmentsUpdaterFactory(
38
39
  }
39
40
 
40
41
  // @TODO if allowing custom storages, handle async execution
41
- function updateSegments(segments: string[]) {
42
- // Update the list of segment names available
43
- const shouldNotifyUpdate = mySegmentsCache.resetSegments(segments);
42
+ function updateSegments(segmentsData: SegmentsData) {
43
+
44
+ let shouldNotifyUpdate;
45
+ if (Array.isArray(segmentsData)) {
46
+ // Update the list of segment names available
47
+ shouldNotifyUpdate = mySegmentsCache.resetSegments(segmentsData);
48
+ } else {
49
+ // Add/Delete the segment
50
+ const { name, add } = segmentsData;
51
+ if (mySegmentsCache.isInSegment(name) !== add) {
52
+ shouldNotifyUpdate = true;
53
+ if (add) mySegmentsCache.addToSegment(name);
54
+ else mySegmentsCache.removeFromSegment(name);
55
+ } else {
56
+ shouldNotifyUpdate = false;
57
+ }
58
+ }
44
59
 
45
60
  // Notify update if required
46
61
  if (splitsCache.usesSegments() && (shouldNotifyUpdate || readyOnAlreadyExistentState)) {
@@ -49,10 +64,10 @@ export function mySegmentsUpdaterFactory(
49
64
  }
50
65
  }
51
66
 
52
- function _mySegmentsUpdater(retry: number, segmentList?: string[], noCache?: boolean): Promise<boolean> {
53
- const updaterPromise: Promise<boolean> = segmentList ?
54
- // If segmentList is provided, there is no need to fetch mySegments
55
- new Promise((res) => { updateSegments(segmentList); res(true); }) :
67
+ function _mySegmentsUpdater(retry: number, segmentsData?: SegmentsData, noCache?: boolean): Promise<boolean> {
68
+ const updaterPromise: Promise<boolean> = segmentsData ?
69
+ // If segmentsData is provided, there is no need to fetch mySegments
70
+ new Promise((res) => { updateSegments(segmentsData); res(true); }) :
56
71
  // If not provided, fetch mySegments
57
72
  mySegmentsFetcher(noCache, _promiseDecorator).then(segments => {
58
73
  // Only when we have downloaded segments completely, we should not keep retrying anymore
@@ -79,11 +94,14 @@ export function mySegmentsUpdaterFactory(
79
94
  * MySegments updater returns a promise that resolves with a `false` boolean value if it fails to fetch mySegments or synchronize them with the storage.
80
95
  * Returned promise will not be rejected.
81
96
  *
82
- * @param {string[] | undefined} segmentList list of mySegments names to sync in the storage. If the list is `undefined`, it fetches them before syncing in the storage.
97
+ * @param {SegmentsData | undefined} segmentsData it can be:
98
+ * (1) the list of mySegments names to sync in the storage,
99
+ * (2) an object with a segment name and action (true: add, or false: delete) to update the storage,
100
+ * (3) or `undefined`, for which the updater will fetch mySegments in order to sync the storage.
83
101
  * @param {boolean | undefined} noCache true to revalidate data to fetch
84
102
  */
85
- return function mySegmentsUpdater(segmentList?: string[], noCache?: boolean) {
86
- return _mySegmentsUpdater(0, segmentList, noCache);
103
+ return function mySegmentsUpdater(segmentsData?: SegmentsData, noCache?: boolean) {
104
+ return _mySegmentsUpdater(0, segmentsData, noCache);
87
105
  };
88
106
 
89
107
  }
@@ -94,14 +94,13 @@ export function segmentChangesUpdaterFactory(
94
94
  readyOnAlreadyExistentState = false;
95
95
  if (readiness) readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
96
96
  }
97
- // if at least one segment fetch fails, return false to indicate that there was some error (e.g., invalid json, HTTP error, etc)
98
- if (shouldUpdateFlags.indexOf(-1) !== -1) return false;
99
97
  return true;
100
98
  });
101
99
  })
102
100
  // Handles rejected promises at `segmentChangesFetcher`, `segments.getRegisteredSegments` and other segment storage operations.
103
101
  .catch(error => {
104
- if (error.statusCode === 403) {
102
+ if (error && error.statusCode === 403) {
103
+ // If the operation is forbidden, it may be due to permissions. Destroy the SDK instance.
105
104
  // @TODO although factory status is destroyed, synchronization is not stopped
106
105
  if (readiness) readiness.destroy();
107
106
  log.error(`${LOG_PREFIX_INSTANTIATION}: you passed a client-side type authorizationKey, please grab an Api Key from the Split web console that is of type Server-side.`);
@@ -5,6 +5,7 @@ export interface IAuthTokenPushEnabled {
5
5
  token: string
6
6
  decodedToken: IDecodedJWTToken
7
7
  channels: { [channel: string]: string[] }
8
+ connDelay?: number
8
9
  }
9
10
 
10
11
  export interface IAuthTokenPushDisabled {
@@ -15,3 +16,5 @@ export interface IAuthTokenPushDisabled {
15
16
  export type IAuthToken = IAuthTokenPushDisabled | IAuthTokenPushEnabled
16
17
 
17
18
  export type IAuthenticate = (userKeys?: string[]) => Promise<IAuthToken>
19
+
20
+ export type IAuthenticateV2 = (isClientSide?: boolean) => Promise<IAuthToken>