@splitsoftware/splitio-commons 2.7.2-rc.0 → 2.7.9-rc.1

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 (73) hide show
  1. package/CHANGES.txt +4 -2
  2. package/cjs/evaluator/fallbackTreatmentsCalculator/constants.js +8 -0
  3. package/cjs/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.js +47 -0
  4. package/cjs/evaluator/fallbackTreatmentsCalculator/index.js +48 -0
  5. package/cjs/logger/constants.js +2 -2
  6. package/cjs/logger/messages/info.js +1 -1
  7. package/cjs/logger/messages/warn.js +3 -3
  8. package/cjs/readiness/readinessManager.js +3 -5
  9. package/cjs/readiness/sdkReadinessManager.js +33 -0
  10. package/cjs/sdkClient/client.js +12 -5
  11. package/cjs/sdkClient/clientInputValidation.js +18 -7
  12. package/cjs/sdkClient/sdkClient.js +1 -1
  13. package/cjs/sdkFactory/index.js +3 -1
  14. package/cjs/sdkManager/index.js +3 -3
  15. package/cjs/sync/polling/syncTasks/segmentsSyncTask.js +1 -1
  16. package/cjs/sync/polling/updaters/segmentChangesUpdater.js +5 -16
  17. package/cjs/sync/polling/updaters/splitChangesUpdater.js +2 -2
  18. package/cjs/sync/streaming/SSEHandler/index.js +1 -1
  19. package/cjs/sync/submitters/telemetrySubmitter.js +3 -3
  20. package/cjs/trackers/telemetryTracker.js +6 -6
  21. package/cjs/utils/inputValidation/index.js +2 -1
  22. package/cjs/utils/inputValidation/isOperational.js +9 -4
  23. package/cjs/utils/inputValidation/splitExistence.js +3 -3
  24. package/cjs/utils/labels/index.js +3 -1
  25. package/esm/evaluator/fallbackTreatmentsCalculator/constants.js +5 -0
  26. package/esm/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.js +44 -0
  27. package/esm/evaluator/fallbackTreatmentsCalculator/index.js +45 -0
  28. package/esm/logger/constants.js +1 -1
  29. package/esm/logger/messages/info.js +1 -1
  30. package/esm/logger/messages/warn.js +3 -3
  31. package/esm/readiness/readinessManager.js +3 -5
  32. package/esm/readiness/sdkReadinessManager.js +33 -0
  33. package/esm/sdkClient/client.js +12 -5
  34. package/esm/sdkClient/clientInputValidation.js +20 -9
  35. package/esm/sdkClient/sdkClient.js +1 -1
  36. package/esm/sdkFactory/index.js +3 -1
  37. package/esm/sdkManager/index.js +4 -4
  38. package/esm/sync/polling/syncTasks/segmentsSyncTask.js +1 -1
  39. package/esm/sync/polling/updaters/segmentChangesUpdater.js +5 -16
  40. package/esm/sync/polling/updaters/splitChangesUpdater.js +2 -2
  41. package/esm/sync/streaming/SSEHandler/index.js +1 -1
  42. package/esm/sync/submitters/telemetrySubmitter.js +3 -3
  43. package/esm/trackers/telemetryTracker.js +6 -6
  44. package/esm/utils/inputValidation/index.js +1 -1
  45. package/esm/utils/inputValidation/isOperational.js +8 -4
  46. package/esm/utils/inputValidation/splitExistence.js +4 -4
  47. package/esm/utils/labels/index.js +2 -0
  48. package/package.json +1 -1
  49. package/src/evaluator/fallbackTreatmentsCalculator/constants.ts +4 -0
  50. package/src/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.ts +62 -0
  51. package/src/evaluator/fallbackTreatmentsCalculator/index.ts +57 -0
  52. package/src/logger/constants.ts +1 -1
  53. package/src/logger/messages/info.ts +1 -1
  54. package/src/logger/messages/warn.ts +3 -3
  55. package/src/readiness/readinessManager.ts +3 -4
  56. package/src/readiness/sdkReadinessManager.ts +30 -0
  57. package/src/sdkClient/client.ts +14 -5
  58. package/src/sdkClient/clientInputValidation.ts +24 -9
  59. package/src/sdkClient/sdkClient.ts +2 -1
  60. package/src/sdkFactory/index.ts +4 -1
  61. package/src/sdkFactory/types.ts +2 -0
  62. package/src/sdkManager/index.ts +4 -4
  63. package/src/sync/polling/syncTasks/segmentsSyncTask.ts +0 -2
  64. package/src/sync/polling/updaters/segmentChangesUpdater.ts +4 -17
  65. package/src/sync/polling/updaters/splitChangesUpdater.ts +5 -4
  66. package/src/sync/streaming/SSEHandler/index.ts +1 -1
  67. package/src/sync/submitters/telemetrySubmitter.ts +3 -3
  68. package/src/trackers/telemetryTracker.ts +6 -6
  69. package/src/utils/inputValidation/index.ts +1 -1
  70. package/src/utils/inputValidation/isOperational.ts +9 -4
  71. package/src/utils/inputValidation/splitExistence.ts +4 -4
  72. package/src/utils/labels/index.ts +3 -0
  73. package/types/splitio.d.ts +37 -6
@@ -4,7 +4,6 @@ import { IReadinessManager } from '../../../readiness/types';
4
4
  import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants';
5
5
  import { ILogger } from '../../../logger/types';
6
6
  import { LOG_PREFIX_INSTANTIATION, LOG_PREFIX_SYNC_SEGMENTS } from '../../../logger/constants';
7
- import { timeout } from '../../../utils/promise/timeout';
8
7
 
9
8
  type ISegmentChangesUpdater = (fetchOnlyNew?: boolean, segmentName?: string, noCache?: boolean, till?: number) => Promise<boolean>
10
9
 
@@ -24,18 +23,11 @@ export function segmentChangesUpdaterFactory(
24
23
  segmentChangesFetcher: ISegmentChangesFetcher,
25
24
  segments: ISegmentsCacheBase,
26
25
  readiness?: IReadinessManager,
27
- requestTimeoutBeforeReady?: number,
28
- retriesOnFailureBeforeReady?: number,
29
26
  ): ISegmentChangesUpdater {
30
27
 
31
28
  let readyOnAlreadyExistentState = true;
32
29
 
33
- function _promiseDecorator<T>(promise: Promise<T>) {
34
- if (readyOnAlreadyExistentState && requestTimeoutBeforeReady) promise = timeout(requestTimeoutBeforeReady, promise);
35
- return promise;
36
- }
37
-
38
- function updateSegment(segmentName: string, noCache?: boolean, till?: number, fetchOnlyNew?: boolean, retries?: number): Promise<boolean> {
30
+ function updateSegment(segmentName: string, noCache?: boolean, till?: number, fetchOnlyNew?: boolean): Promise<boolean> {
39
31
  log.debug(`${LOG_PREFIX_SYNC_SEGMENTS}Processing segment ${segmentName}`);
40
32
  let sincePromise = Promise.resolve(segments.getChangeNumber(segmentName));
41
33
 
@@ -43,19 +35,13 @@ export function segmentChangesUpdaterFactory(
43
35
  // if fetchOnlyNew flag, avoid processing already fetched segments
44
36
  return fetchOnlyNew && since !== undefined ?
45
37
  false :
46
- segmentChangesFetcher(since || -1, segmentName, noCache, till, _promiseDecorator).then((changes) => {
38
+ segmentChangesFetcher(since || -1, segmentName, noCache, till).then((changes) => {
47
39
  return Promise.all(changes.map(x => {
48
40
  log.debug(`${LOG_PREFIX_SYNC_SEGMENTS}Processing ${segmentName} with till = ${x.till}. Added: ${x.added.length}. Removed: ${x.removed.length}`);
49
41
  return segments.update(segmentName, x.added, x.removed, x.till);
50
42
  })).then((updates) => {
51
43
  return updates.some(update => update);
52
44
  });
53
- }).catch(error => {
54
- if (retries) {
55
- log.warn(`${LOG_PREFIX_SYNC_SEGMENTS}Retrying fetch of segment ${segmentName} (attempt #${retries}). Reason: ${error}`);
56
- return updateSegment(segmentName, noCache, till, fetchOnlyNew, retries - 1);
57
- }
58
- throw error;
59
45
  });
60
46
  });
61
47
  }
@@ -77,7 +63,8 @@ export function segmentChangesUpdaterFactory(
77
63
  let segmentsPromise = Promise.resolve(segmentName ? [segmentName] : segments.getRegisteredSegments());
78
64
 
79
65
  return segmentsPromise.then(segmentNames => {
80
- const updaters = segmentNames.map(segmentName => updateSegment(segmentName, noCache, till, fetchOnlyNew, readyOnAlreadyExistentState ? retriesOnFailureBeforeReady : 0));
66
+ // Async fetchers
67
+ const updaters = segmentNames.map(segmentName => updateSegment(segmentName, noCache, till, fetchOnlyNew));
81
68
 
82
69
  return Promise.all(updaters).then(shouldUpdateFlags => {
83
70
  // if at least one segment fetch succeeded, mark segments ready
@@ -120,8 +120,8 @@ export function splitChangesUpdaterFactory(
120
120
  storage: Pick<IStorageBase, 'splits' | 'rbSegments' | 'segments' | 'save'>,
121
121
  splitFiltersValidation: ISplitFiltersValidation,
122
122
  splitsEventEmitter?: ISplitsEventEmitter,
123
- requestTimeoutBeforeReady = 0,
124
- retriesOnFailureBeforeReady = 0,
123
+ requestTimeoutBeforeReady: number = 0,
124
+ retriesOnFailureBeforeReady: number = 0,
125
125
  isClientSide?: boolean
126
126
  ): SplitChangesUpdater {
127
127
  const { splits, rbSegments, segments } = storage;
@@ -201,13 +201,14 @@ export function splitChangesUpdaterFactory(
201
201
  });
202
202
  })
203
203
  .catch(error => {
204
+ log.warn(SYNC_SPLITS_FETCH_FAILS, [error]);
205
+
204
206
  if (startingUp && retriesOnFailureBeforeReady > retry) {
205
207
  retry += 1;
206
- log.warn(SYNC_SPLITS_FETCH_RETRY, [retry, error]);
208
+ log.info(SYNC_SPLITS_FETCH_RETRY, [retry, error]);
207
209
  return _splitChangesUpdater(sinces, retry);
208
210
  } else {
209
211
  startingUp = false;
210
- log.warn(SYNC_SPLITS_FETCH_FAILS, [error]);
211
212
  }
212
213
  return false;
213
214
  });
@@ -25,7 +25,7 @@ export function SSEHandlerFactory(log: ILogger, pushEmitter: IPushEventEmitter,
25
25
  const code = error.parsedData.code;
26
26
  telemetryTracker.streamingEvent(ABLY_ERROR, code);
27
27
 
28
- // 401 errors due to invalid or expired token (e.g., if refresh token coudn't be executed)
28
+ // 401 errors due to invalid or expired token (e.g., if refresh token couldn't be executed)
29
29
  if (40140 <= code && code <= 40149) return true;
30
30
  // Others 4XX errors (e.g., bad request from the SDK)
31
31
  if (40000 <= code && code <= 49999) return false;
@@ -119,7 +119,7 @@ export function telemetrySubmitterFactory(params: ISdkFactoryContextSync) {
119
119
  if (!telemetry || !now) return; // No submitter created if telemetry cache is not defined
120
120
 
121
121
  const { settings, settings: { log, scheduler: { telemetryRefreshRate } }, splitApi, readiness, sdkReadinessManager } = params;
122
- const startTime = timer(now);
122
+ const stopTimer = timer(now);
123
123
 
124
124
  const submitter = firstPushWindowDecorator(
125
125
  submitterFactory(
@@ -131,12 +131,12 @@ export function telemetrySubmitterFactory(params: ISdkFactoryContextSync) {
131
131
  );
132
132
 
133
133
  readiness.gate.once(SDK_READY_FROM_CACHE, () => {
134
- telemetry.recordTimeUntilReadyFromCache(startTime());
134
+ telemetry.recordTimeUntilReadyFromCache(stopTimer());
135
135
  });
136
136
 
137
137
  sdkReadinessManager.incInternalReadyCbCount();
138
138
  readiness.gate.once(SDK_READY, () => {
139
- telemetry.recordTimeUntilReady(startTime());
139
+ telemetry.recordTimeUntilReady(stopTimer());
140
140
 
141
141
  // Post config data when the SDK is ready and if the telemetry submitter was started
142
142
  if (submitter.isRunning()) {
@@ -11,11 +11,11 @@ export function telemetryTrackerFactory(
11
11
  ): ITelemetryTracker {
12
12
 
13
13
  if (telemetryCache && now) {
14
- const startTime = timer(now);
14
+ const sessionTimer = timer(now);
15
15
 
16
16
  return {
17
17
  trackEval(method) {
18
- const evalTime = timer(now);
18
+ const evalTimer = timer(now);
19
19
 
20
20
  return (label) => {
21
21
  switch (label) {
@@ -25,20 +25,20 @@ export function telemetryTrackerFactory(
25
25
  case SDK_NOT_READY: // @ts-ignore ITelemetryCacheAsync doesn't implement the method
26
26
  if (telemetryCache.recordNonReadyUsage) telemetryCache.recordNonReadyUsage();
27
27
  }
28
- telemetryCache.recordLatency(method, evalTime());
28
+ telemetryCache.recordLatency(method, evalTimer());
29
29
  };
30
30
  },
31
31
  trackHttp(operation) {
32
- const httpTime = timer(now);
32
+ const httpTimer = timer(now);
33
33
 
34
34
  return (error) => {
35
- (telemetryCache as ITelemetryCacheSync).recordHttpLatency(operation, httpTime());
35
+ (telemetryCache as ITelemetryCacheSync).recordHttpLatency(operation, httpTimer());
36
36
  if (error && error.statusCode) (telemetryCache as ITelemetryCacheSync).recordHttpError(operation, error.statusCode);
37
37
  else (telemetryCache as ITelemetryCacheSync).recordSuccessfulSync(operation, Date.now());
38
38
  };
39
39
  },
40
40
  sessionLength() { // @ts-ignore ITelemetryCacheAsync doesn't implement the method
41
- if (telemetryCache.recordSessionLength) telemetryCache.recordSessionLength(startTime());
41
+ if (telemetryCache.recordSessionLength) telemetryCache.recordSessionLength(sessionTimer());
42
42
  },
43
43
  streamingEvent(e, d) {
44
44
  if (e === AUTH_REJECTION) {
@@ -7,7 +7,7 @@ export { validateKey } from './key';
7
7
  export { validateSplit } from './split';
8
8
  export { validateSplits } from './splits';
9
9
  export { validateTrafficType } from './trafficType';
10
- export { validateIfNotDestroyed, validateIfOperational } from './isOperational';
10
+ export { validateIfNotDestroyed, validateIfReadyFromCache, validateIfOperational } from './isOperational';
11
11
  export { validateSplitExistence } from './splitExistence';
12
12
  export { validateTrafficTypeExistence } from './trafficTypeExistence';
13
13
  export { validateEvaluationOptions } from './eventProperties';
@@ -1,4 +1,4 @@
1
- import { ERROR_CLIENT_DESTROYED, CLIENT_NOT_READY } from '../../logger/constants';
1
+ import { ERROR_CLIENT_DESTROYED, CLIENT_NOT_READY_FROM_CACHE } from '../../logger/constants';
2
2
  import { ILogger } from '../../logger/types';
3
3
  import { IReadinessManager } from '../../readiness/types';
4
4
 
@@ -9,9 +9,14 @@ export function validateIfNotDestroyed(log: ILogger, readinessManager: IReadines
9
9
  return false;
10
10
  }
11
11
 
12
- export function validateIfOperational(log: ILogger, readinessManager: IReadinessManager, method: string, featureFlagNameOrNames?: string | string[] | false) {
13
- if (readinessManager.isReady() || readinessManager.isReadyFromCache()) return true;
12
+ export function validateIfReadyFromCache(log: ILogger, readinessManager: IReadinessManager, method: string, featureFlagNameOrNames?: string | string[] | false) {
13
+ if (readinessManager.isReadyFromCache()) return true;
14
14
 
15
- log.warn(CLIENT_NOT_READY, [method, featureFlagNameOrNames ? ` for feature flag ${featureFlagNameOrNames.toString()}` : '']);
15
+ log.warn(CLIENT_NOT_READY_FROM_CACHE, [method, featureFlagNameOrNames ? ` for feature flag ${featureFlagNameOrNames.toString()}` : '']);
16
16
  return false;
17
17
  }
18
+
19
+ // Operational means that the SDK is ready to evaluate (not destroyed and ready from cache)
20
+ export function validateIfOperational(log: ILogger, readinessManager: IReadinessManager, method: string, featureFlagNameOrNames?: string | string[] | false) {
21
+ return validateIfNotDestroyed(log, readinessManager, method) && validateIfReadyFromCache(log, readinessManager, method, featureFlagNameOrNames);
22
+ }
@@ -1,15 +1,15 @@
1
- import { SPLIT_NOT_FOUND } from '../labels';
1
+ import { FALLBACK_SPLIT_NOT_FOUND, SPLIT_NOT_FOUND } from '../labels';
2
2
  import { IReadinessManager } from '../../readiness/types';
3
3
  import { ILogger } from '../../logger/types';
4
4
  import { WARN_NOT_EXISTENT_SPLIT } from '../../logger/constants';
5
5
 
6
6
  /**
7
7
  * This is defined here and in this format mostly because of the logger and the fact that it's considered a validation at product level.
8
- * But it's not going to run on the input validation layer. In any case, the most compeling reason to use it as we do is to avoid going to Redis and get a split twice.
8
+ * But it's not going to run on the input validation layer. In any case, the most compelling reason to use it as we do is to avoid going to Redis and get a split twice.
9
9
  */
10
10
  export function validateSplitExistence(log: ILogger, readinessManager: IReadinessManager, splitName: string, labelOrSplitObj: any, method: string): boolean {
11
- if (readinessManager.isReady()) { // Only if it's ready we validate this, otherwise it may just be that the SDK is not ready yet.
12
- if (labelOrSplitObj === SPLIT_NOT_FOUND || labelOrSplitObj == null) {
11
+ if (readinessManager.isReady()) { // Only if it's ready (synced with BE) we validate this, otherwise it may just be that the SDK is still syncing
12
+ if (labelOrSplitObj === SPLIT_NOT_FOUND || labelOrSplitObj === FALLBACK_SPLIT_NOT_FOUND || labelOrSplitObj == null) {
13
13
  log.warn(WARN_NOT_EXISTENT_SPLIT, [method, splitName]);
14
14
  return false;
15
15
  }
@@ -1,3 +1,5 @@
1
+ import { FALLBACK_PREFIX } from '../../evaluator/fallbackTreatmentsCalculator';
2
+
1
3
  export const SPLIT_KILLED = 'killed';
2
4
  export const NO_CONDITION_MATCH = 'default rule';
3
5
  export const SPLIT_NOT_FOUND = 'definition not found';
@@ -7,3 +9,4 @@ export const SPLIT_ARCHIVED = 'archived';
7
9
  export const NOT_IN_SPLIT = 'not in split';
8
10
  export const UNSUPPORTED_MATCHER_TYPE = 'targeting rule type unsupported by sdk';
9
11
  export const PREREQUISITES_NOT_MET = 'prerequisites not met';
12
+ export const FALLBACK_SPLIT_NOT_FOUND = FALLBACK_PREFIX + SPLIT_NOT_FOUND;
@@ -525,19 +525,19 @@ declare namespace SplitIO {
525
525
  */
526
526
  type EventConsts = {
527
527
  /**
528
- * The ready event.
528
+ * The ready event emitted once the SDK is ready to evaluate feature flags with cache synchronized with the backend.
529
529
  */
530
530
  SDK_READY: 'init::ready';
531
531
  /**
532
- * The ready event when fired with cached data.
532
+ * The ready event emitted once the SDK is ready to evaluate feature flags with cache that could be stale. Use SDK_READY if you want to be sure the cache is in sync with the backend.
533
533
  */
534
534
  SDK_READY_FROM_CACHE: 'init::cache-ready';
535
535
  /**
536
- * The timeout event.
536
+ * The timeout event emitted after `startup.readyTimeout` seconds if the SDK_READY event was not emitted.
537
537
  */
538
538
  SDK_READY_TIMED_OUT: 'init::timeout';
539
539
  /**
540
- * The update event.
540
+ * The update event emitted when the SDK cache is updated with new data from the backend.
541
541
  */
542
542
  SDK_UPDATE: 'state::update';
543
543
  };
@@ -618,6 +618,10 @@ declare namespace SplitIO {
618
618
  * User consent status if using in client-side. Undefined if using in server-side (Node.js).
619
619
  */
620
620
  readonly userConsent?: ConsentStatus;
621
+ /**
622
+ * Fallback treatments to be used when the SDK is not ready or the flag is not found.
623
+ */
624
+ readonly fallbackTreatments?: FallbackTreatmentConfiguration;
621
625
  }
622
626
  /**
623
627
  * Log levels.
@@ -700,7 +704,7 @@ declare namespace SplitIO {
700
704
  */
701
705
  Event: EventConsts;
702
706
  /**
703
- * Returns a promise that resolves once the SDK has finished loading (`SDK_READY` event emitted) or rejected if the SDK has timedout (`SDK_READY_TIMED_OUT` event emitted).
707
+ * Returns a promise that resolves when the SDK has finished initial synchronization with the backend (`SDK_READY` event emitted), or rejected if the SDK has timedout (`SDK_READY_TIMED_OUT` event emitted).
704
708
  * As it's meant to provide similar flexibility to the event approach, given that the SDK might be eventually ready after a timeout event, the `ready` method will return a resolved promise once the SDK is ready.
705
709
  *
706
710
  * Caveats: the method was designed to avoid an unhandled Promise rejection if the rejection case is not handled, so that `onRejected` handler is optional when using promises.
@@ -715,8 +719,26 @@ declare namespace SplitIO {
715
719
  * ```
716
720
  *
717
721
  * @returns A promise that resolves once the SDK is ready or rejects if the SDK has timedout.
722
+ * @deprecated Use `whenReady` instead.
718
723
  */
719
724
  ready(): Promise<void>;
725
+ /**
726
+ * Returns a promise that resolves when the SDK has finished initial synchronization with the backend (`SDK_READY` event emitted), or rejected if the SDK has timedout (`SDK_READY_TIMED_OUT` event emitted).
727
+ * As it's meant to provide similar flexibility than event listeners, given that the SDK might be ready after a timeout event, the `whenReady` method will return a resolved promise once the SDK is ready.
728
+ * You must handle the promise rejection to avoid an unhandled promise rejection error, or set the `startup.readyTimeout` configuration option to 0 to avoid the timeout and thus the rejection.
729
+ *
730
+ * @returns A promise that resolves once the SDK_READY event is emitted or rejects if the SDK has timedout.
731
+ */
732
+ whenReady(): Promise<void>;
733
+ /**
734
+ * Returns a promise that resolves when the SDK is ready for evaluations using cached data, which might not yet be synchronized with the backend (`SDK_READY_FROM_CACHE` event emitted), or rejected if the SDK has timedout (`SDK_READY_TIMED_OUT` event emitted).
735
+ * As it's meant to provide similar flexibility than event listeners, given that the SDK might be ready from cache after a timeout event, the `whenReadyFromCache` method will return a resolved promise once the SDK is ready from cache.
736
+ * You must handle the promise rejection to avoid an unhandled promise rejection error, or set the `startup.readyTimeout` configuration option to 0 to avoid the timeout and thus the rejection.
737
+ *
738
+ * @returns A promise that resolves once the SDK_READY_FROM_CACHE event is emitted or rejects if the SDK has timedout. The promise resolves with a boolean value that
739
+ * indicates whether the SDK_READY_FROM_CACHE event was emitted together with the SDK_READY event (i.e., the SDK is ready and synchronized with the backend) or not.
740
+ */
741
+ whenReadyFromCache(): Promise<boolean>;
720
742
  }
721
743
  /**
722
744
  * Common definitions between clients for different environments interface.
@@ -1225,6 +1247,15 @@ declare namespace SplitIO {
1225
1247
  * User consent status.
1226
1248
  */
1227
1249
  type ConsentStatus = 'GRANTED' | 'DECLINED' | 'UNKNOWN';
1250
+ /**
1251
+ * Fallback treatments to be used when the SDK is not ready or the flag is not found.
1252
+ */
1253
+ type FallbackTreatmentConfiguration = {
1254
+ global?: Treatment | TreatmentWithConfig,
1255
+ byFlag?: {
1256
+ [featureFlagName: string]: Treatment | TreatmentWithConfig
1257
+ }
1258
+ }
1228
1259
  /**
1229
1260
  * Logger. Its interface details are not part of the public API. It shouldn't be used directly.
1230
1261
  */
@@ -1650,7 +1681,7 @@ declare namespace SplitIO {
1650
1681
  * Wait for the SDK client to be ready before calling this method.
1651
1682
  *
1652
1683
  * ```js
1653
- * await factory.client().ready();
1684
+ * await factory.client().whenReady();
1654
1685
  * const rolloutPlan = factory.getRolloutPlan();
1655
1686
  * ```
1656
1687
  *