@launchdarkly/js-client-sdk-common 1.20.0 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/dist/cjs/LDClientImpl.d.ts.map +1 -1
- package/dist/cjs/api/LDOptions.d.ts +8 -0
- package/dist/cjs/api/LDOptions.d.ts.map +1 -1
- package/dist/cjs/api/datasource/DataSourceEntry.d.ts +45 -0
- package/dist/cjs/api/datasource/DataSourceEntry.d.ts.map +1 -0
- package/dist/cjs/api/datasource/FDv2ConnectionMode.d.ts +30 -0
- package/dist/cjs/api/datasource/FDv2ConnectionMode.d.ts.map +1 -0
- package/dist/cjs/api/datasource/LDClientDataSystemOptions.d.ts +75 -0
- package/dist/cjs/api/datasource/LDClientDataSystemOptions.d.ts.map +1 -0
- package/dist/cjs/api/datasource/ModeDefinition.d.ts +21 -0
- package/dist/cjs/api/datasource/ModeDefinition.d.ts.map +1 -0
- package/dist/cjs/api/datasource/ModeResolution.d.ts +75 -0
- package/dist/cjs/api/datasource/ModeResolution.d.ts.map +1 -0
- package/dist/cjs/api/datasource/index.d.ts +6 -0
- package/dist/cjs/api/datasource/index.d.ts.map +1 -0
- package/dist/cjs/api/index.d.ts +1 -0
- package/dist/cjs/api/index.d.ts.map +1 -1
- package/dist/cjs/configuration/Configuration.d.ts +6 -1
- package/dist/cjs/configuration/Configuration.d.ts.map +1 -1
- package/dist/cjs/configuration/validateOptions.d.ts +95 -0
- package/dist/cjs/configuration/validateOptions.d.ts.map +1 -0
- package/dist/cjs/configuration/validators.d.ts +5 -2
- package/dist/cjs/configuration/validators.d.ts.map +1 -1
- package/dist/cjs/datasource/ConnectionModeConfig.d.ts +19 -0
- package/dist/cjs/datasource/ConnectionModeConfig.d.ts.map +1 -0
- package/dist/cjs/datasource/LDClientDataSystemOptions.d.ts +20 -0
- package/dist/cjs/datasource/LDClientDataSystemOptions.d.ts.map +1 -0
- package/dist/cjs/datasource/ModeResolver.d.ts +30 -0
- package/dist/cjs/datasource/ModeResolver.d.ts.map +1 -0
- package/dist/cjs/datasource/StateDebounceManager.d.ts +92 -0
- package/dist/cjs/datasource/StateDebounceManager.d.ts.map +1 -0
- package/dist/cjs/datasource/fdv2/AsyncQueue.d.ts +2 -0
- package/dist/cjs/datasource/fdv2/AsyncQueue.d.ts.map +1 -0
- package/dist/cjs/datasource/fdv2/CacheInitializer.d.ts +17 -0
- package/dist/cjs/datasource/fdv2/CacheInitializer.d.ts.map +1 -0
- package/dist/cjs/datasource/fdv2/Conditions.d.ts +73 -0
- package/dist/cjs/datasource/fdv2/Conditions.d.ts.map +1 -0
- package/dist/cjs/datasource/fdv2/FDv1PollingSynchronizer.d.ts +2 -0
- package/dist/cjs/datasource/fdv2/FDv1PollingSynchronizer.d.ts.map +1 -0
- package/dist/cjs/datasource/fdv2/FDv2DataSource.d.ts +52 -0
- package/dist/cjs/datasource/fdv2/FDv2DataSource.d.ts.map +1 -0
- package/dist/cjs/datasource/fdv2/FDv2Requestor.d.ts +45 -0
- package/dist/cjs/datasource/fdv2/FDv2Requestor.d.ts.map +1 -0
- package/dist/cjs/datasource/fdv2/FDv2SourceResult.d.ts +84 -0
- package/dist/cjs/datasource/fdv2/FDv2SourceResult.d.ts.map +1 -0
- package/dist/cjs/datasource/fdv2/Initializer.d.ts +40 -0
- package/dist/cjs/datasource/fdv2/Initializer.d.ts.map +1 -0
- package/dist/cjs/datasource/fdv2/PollingBase.d.ts +2 -0
- package/dist/cjs/datasource/fdv2/PollingBase.d.ts.map +1 -0
- package/dist/cjs/datasource/fdv2/PollingInitializer.d.ts +2 -0
- package/dist/cjs/datasource/fdv2/PollingInitializer.d.ts.map +1 -0
- package/dist/cjs/datasource/fdv2/PollingSynchronizer.d.ts +2 -0
- package/dist/cjs/datasource/fdv2/PollingSynchronizer.d.ts.map +1 -0
- package/dist/cjs/datasource/fdv2/SourceManager.d.ts +88 -0
- package/dist/cjs/datasource/fdv2/SourceManager.d.ts.map +1 -0
- package/dist/cjs/datasource/fdv2/StreamingFDv2Base.d.ts +11 -0
- package/dist/cjs/datasource/fdv2/StreamingFDv2Base.d.ts.map +1 -0
- package/dist/cjs/datasource/fdv2/StreamingInitializerFDv2.d.ts +2 -0
- package/dist/cjs/datasource/fdv2/StreamingInitializerFDv2.d.ts.map +1 -0
- package/dist/cjs/datasource/fdv2/StreamingSynchronizerFDv2.d.ts +2 -0
- package/dist/cjs/datasource/fdv2/StreamingSynchronizerFDv2.d.ts.map +1 -0
- package/dist/cjs/datasource/fdv2/Synchronizer.d.ts +49 -0
- package/dist/cjs/datasource/fdv2/Synchronizer.d.ts.map +1 -0
- package/dist/cjs/datasource/fdv2/calculatePollDelay.d.ts +2 -0
- package/dist/cjs/datasource/fdv2/calculatePollDelay.d.ts.map +1 -0
- package/dist/cjs/datasource/fdv2/index.d.ts +20 -0
- package/dist/cjs/datasource/fdv2/index.d.ts.map +1 -0
- package/dist/cjs/datasource/flagEvalMapper.d.ts +3 -3
- package/dist/cjs/flag-manager/FlagManager.d.ts +2 -1
- package/dist/cjs/flag-manager/FlagManager.d.ts.map +1 -1
- package/dist/cjs/flag-manager/FlagPersistence.d.ts +8 -1
- package/dist/cjs/flag-manager/FlagPersistence.d.ts.map +1 -1
- package/dist/cjs/index.cjs +411 -100
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.ts +5 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/storage/freshness.d.ts +27 -0
- package/dist/cjs/storage/freshness.d.ts.map +1 -0
- package/dist/cjs/storage/loadCachedFlags.d.ts +25 -0
- package/dist/cjs/storage/loadCachedFlags.d.ts.map +1 -0
- package/dist/esm/LDClientImpl.d.ts.map +1 -1
- package/dist/esm/api/LDOptions.d.ts +8 -0
- package/dist/esm/api/LDOptions.d.ts.map +1 -1
- package/dist/esm/api/datasource/DataSourceEntry.d.ts +45 -0
- package/dist/esm/api/datasource/DataSourceEntry.d.ts.map +1 -0
- package/dist/esm/api/datasource/FDv2ConnectionMode.d.ts +30 -0
- package/dist/esm/api/datasource/FDv2ConnectionMode.d.ts.map +1 -0
- package/dist/esm/api/datasource/LDClientDataSystemOptions.d.ts +75 -0
- package/dist/esm/api/datasource/LDClientDataSystemOptions.d.ts.map +1 -0
- package/dist/esm/api/datasource/ModeDefinition.d.ts +21 -0
- package/dist/esm/api/datasource/ModeDefinition.d.ts.map +1 -0
- package/dist/esm/api/datasource/ModeResolution.d.ts +75 -0
- package/dist/esm/api/datasource/ModeResolution.d.ts.map +1 -0
- package/dist/esm/api/datasource/index.d.ts +6 -0
- package/dist/esm/api/datasource/index.d.ts.map +1 -0
- package/dist/esm/api/index.d.ts +1 -0
- package/dist/esm/api/index.d.ts.map +1 -1
- package/dist/esm/configuration/Configuration.d.ts +6 -1
- package/dist/esm/configuration/Configuration.d.ts.map +1 -1
- package/dist/esm/configuration/validateOptions.d.ts +95 -0
- package/dist/esm/configuration/validateOptions.d.ts.map +1 -0
- package/dist/esm/configuration/validators.d.ts +5 -2
- package/dist/esm/configuration/validators.d.ts.map +1 -1
- package/dist/esm/datasource/ConnectionModeConfig.d.ts +19 -0
- package/dist/esm/datasource/ConnectionModeConfig.d.ts.map +1 -0
- package/dist/esm/datasource/LDClientDataSystemOptions.d.ts +20 -0
- package/dist/esm/datasource/LDClientDataSystemOptions.d.ts.map +1 -0
- package/dist/esm/datasource/ModeResolver.d.ts +30 -0
- package/dist/esm/datasource/ModeResolver.d.ts.map +1 -0
- package/dist/esm/datasource/StateDebounceManager.d.ts +92 -0
- package/dist/esm/datasource/StateDebounceManager.d.ts.map +1 -0
- package/dist/esm/datasource/fdv2/AsyncQueue.d.ts +2 -0
- package/dist/esm/datasource/fdv2/AsyncQueue.d.ts.map +1 -0
- package/dist/esm/datasource/fdv2/CacheInitializer.d.ts +17 -0
- package/dist/esm/datasource/fdv2/CacheInitializer.d.ts.map +1 -0
- package/dist/esm/datasource/fdv2/Conditions.d.ts +73 -0
- package/dist/esm/datasource/fdv2/Conditions.d.ts.map +1 -0
- package/dist/esm/datasource/fdv2/FDv1PollingSynchronizer.d.ts +2 -0
- package/dist/esm/datasource/fdv2/FDv1PollingSynchronizer.d.ts.map +1 -0
- package/dist/esm/datasource/fdv2/FDv2DataSource.d.ts +52 -0
- package/dist/esm/datasource/fdv2/FDv2DataSource.d.ts.map +1 -0
- package/dist/esm/datasource/fdv2/FDv2Requestor.d.ts +45 -0
- package/dist/esm/datasource/fdv2/FDv2Requestor.d.ts.map +1 -0
- package/dist/esm/datasource/fdv2/FDv2SourceResult.d.ts +84 -0
- package/dist/esm/datasource/fdv2/FDv2SourceResult.d.ts.map +1 -0
- package/dist/esm/datasource/fdv2/Initializer.d.ts +40 -0
- package/dist/esm/datasource/fdv2/Initializer.d.ts.map +1 -0
- package/dist/esm/datasource/fdv2/PollingBase.d.ts +2 -0
- package/dist/esm/datasource/fdv2/PollingBase.d.ts.map +1 -0
- package/dist/esm/datasource/fdv2/PollingInitializer.d.ts +2 -0
- package/dist/esm/datasource/fdv2/PollingInitializer.d.ts.map +1 -0
- package/dist/esm/datasource/fdv2/PollingSynchronizer.d.ts +2 -0
- package/dist/esm/datasource/fdv2/PollingSynchronizer.d.ts.map +1 -0
- package/dist/esm/datasource/fdv2/SourceManager.d.ts +88 -0
- package/dist/esm/datasource/fdv2/SourceManager.d.ts.map +1 -0
- package/dist/esm/datasource/fdv2/StreamingFDv2Base.d.ts +11 -0
- package/dist/esm/datasource/fdv2/StreamingFDv2Base.d.ts.map +1 -0
- package/dist/esm/datasource/fdv2/StreamingInitializerFDv2.d.ts +2 -0
- package/dist/esm/datasource/fdv2/StreamingInitializerFDv2.d.ts.map +1 -0
- package/dist/esm/datasource/fdv2/StreamingSynchronizerFDv2.d.ts +2 -0
- package/dist/esm/datasource/fdv2/StreamingSynchronizerFDv2.d.ts.map +1 -0
- package/dist/esm/datasource/fdv2/Synchronizer.d.ts +49 -0
- package/dist/esm/datasource/fdv2/Synchronizer.d.ts.map +1 -0
- package/dist/esm/datasource/fdv2/calculatePollDelay.d.ts +2 -0
- package/dist/esm/datasource/fdv2/calculatePollDelay.d.ts.map +1 -0
- package/dist/esm/datasource/fdv2/index.d.ts +20 -0
- package/dist/esm/datasource/fdv2/index.d.ts.map +1 -0
- package/dist/esm/datasource/flagEvalMapper.d.ts +3 -3
- package/dist/esm/flag-manager/FlagManager.d.ts +2 -1
- package/dist/esm/flag-manager/FlagManager.d.ts.map +1 -1
- package/dist/esm/flag-manager/FlagPersistence.d.ts +8 -1
- package/dist/esm/flag-manager/FlagPersistence.d.ts.map +1 -1
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.mjs +404 -102
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/storage/freshness.d.ts +27 -0
- package/dist/esm/storage/freshness.d.ts.map +1 -0
- package/dist/esm/storage/loadCachedFlags.d.ts +25 -0
- package/dist/esm/storage/loadCachedFlags.d.ts.map +1 -0
- package/package.json +2 -2
package/dist/esm/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getPollingUri, TypeValidators,
|
|
1
|
+
import { getPollingUri, isNullish, TypeValidators, OptionMessages, NumberWithMinimum, createSafeLogger, ServiceEndpoints, ApplicationTags, SafeLogger, internal, deepCompact, clone, secondsToMillis, ClientContext, fastDeepEqual, defaultHeaders, Context, LDTimeoutError, AutoEnvAttributes, cancelableTimedPromise, LDClientError, base64UrlEncode, isHttpRecoverable, httpErrorMessage, LDPollingError, DataSourceErrorKind, getStreamingUri, shouldRetry, LDStreamingError } from '@launchdarkly/js-sdk-common';
|
|
2
2
|
export * from '@launchdarkly/js-sdk-common';
|
|
3
3
|
import * as jsSdkCommon from '@launchdarkly/js-sdk-common';
|
|
4
4
|
export { jsSdkCommon as platform };
|
|
@@ -204,34 +204,208 @@ function createAsyncTaskQueue(logger) {
|
|
|
204
204
|
};
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
207
|
+
function isCompoundValidator(v) {
|
|
208
|
+
return 'validate' in v;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Validates an options object against a map of validators and defaults.
|
|
212
|
+
*
|
|
213
|
+
* If `input` is null, undefined, or not an object the defaults are returned
|
|
214
|
+
* (with a warning for non-nullish non-objects).
|
|
215
|
+
*
|
|
216
|
+
* Supports special validator types created by:
|
|
217
|
+
* - {@link validatorOf}: recursively validates nested objects
|
|
218
|
+
* - {@link arrayOf}: validates arrays with per-item validation
|
|
219
|
+
* - {@link anyOf}: accepts the first matching validator from a list
|
|
220
|
+
* - {@link recordOf}: validates objects with dynamic keys
|
|
221
|
+
*/
|
|
222
|
+
function validateOptions(input, validatorMap, defaults, logger, prefix) {
|
|
223
|
+
const result = { ...defaults };
|
|
224
|
+
if (isNullish(input)) {
|
|
225
|
+
return result;
|
|
226
|
+
}
|
|
227
|
+
if (!TypeValidators.Object.is(input)) {
|
|
228
|
+
logger?.warn(OptionMessages.wrongOptionType(prefix ?? 'config', 'object', typeof input));
|
|
229
|
+
return result;
|
|
230
|
+
}
|
|
231
|
+
Object.entries(input).forEach(([key, value]) => {
|
|
232
|
+
const validator = validatorMap[key];
|
|
233
|
+
const name = prefix ? `${prefix}.${key}` : key;
|
|
234
|
+
if (!validator) {
|
|
235
|
+
logger?.warn(OptionMessages.unknownOption(name));
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
if (isNullish(value)) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if (isCompoundValidator(validator)) {
|
|
242
|
+
const validated = validator.validate(value, name, logger, defaults[key]);
|
|
243
|
+
if (validated !== undefined) {
|
|
244
|
+
result[key] = validated.value;
|
|
245
|
+
}
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
if (validator.is(value)) {
|
|
249
|
+
result[key] = value;
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
// Validation failed — apply correction or fall back to default.
|
|
253
|
+
const validatorType = validator.getType();
|
|
254
|
+
if (validatorType === 'boolean') {
|
|
255
|
+
logger?.warn(OptionMessages.wrongOptionTypeBoolean(name, typeof value));
|
|
256
|
+
result[key] = !!value;
|
|
257
|
+
}
|
|
258
|
+
else if (validatorType === 'boolean | undefined | null') {
|
|
259
|
+
logger?.warn(OptionMessages.wrongOptionTypeBoolean(name, typeof value));
|
|
260
|
+
if (typeof value !== 'boolean' && typeof value !== 'undefined' && value !== null) {
|
|
261
|
+
result[key] = !!value;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
else if (validator instanceof NumberWithMinimum && TypeValidators.Number.is(value)) {
|
|
265
|
+
logger?.warn(OptionMessages.optionBelowMinimum(name, value, validator.min));
|
|
266
|
+
result[key] = validator.min;
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
logger?.warn(OptionMessages.wrongOptionType(name, validatorType, typeof value));
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
return result;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Creates a validator for nested objects. When used in a validator map,
|
|
276
|
+
* `validateOptions` will recursively validate the nested object's properties.
|
|
277
|
+
* Defaults for nested fields are passed through from the parent.
|
|
278
|
+
*/
|
|
279
|
+
function validatorOf(validators, builtInDefaults) {
|
|
280
|
+
return {
|
|
281
|
+
is: (u) => TypeValidators.Object.is(u),
|
|
282
|
+
getType: () => 'object',
|
|
283
|
+
validate(value, name, logger, defaults) {
|
|
284
|
+
if (!TypeValidators.Object.is(value)) {
|
|
285
|
+
logger?.warn(OptionMessages.wrongOptionType(name, 'object', typeof value));
|
|
286
|
+
return undefined;
|
|
287
|
+
}
|
|
288
|
+
const nestedDefaults = builtInDefaults ??
|
|
289
|
+
(TypeValidators.Object.is(defaults) ? defaults : {});
|
|
290
|
+
const nested = validateOptions(value, validators, nestedDefaults, logger, name);
|
|
291
|
+
return Object.keys(nested).length > 0 ? { value: nested } : undefined;
|
|
292
|
+
},
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Creates a validator that tries each provided validator in order and uses the
|
|
297
|
+
* first one whose `is()` check passes. For compound validators the value is
|
|
298
|
+
* processed through `validate()`; for simple validators the value is accepted
|
|
299
|
+
* as-is. If no validator matches, a warning is logged and the default is
|
|
300
|
+
* preserved.
|
|
301
|
+
*
|
|
302
|
+
* @example
|
|
303
|
+
* ```ts
|
|
304
|
+
* // Accepts either a boolean or a nested object with specific fields:
|
|
305
|
+
* anyOf(TypeValidators.Boolean, validatorOf({ lifecycle: TypeValidators.Boolean }))
|
|
306
|
+
* ```
|
|
307
|
+
*/
|
|
308
|
+
function anyOf(...validators) {
|
|
309
|
+
return {
|
|
310
|
+
is: (u) => validators.some((v) => v.is(u)),
|
|
311
|
+
getType: () => validators.map((v) => v.getType()).join(' | '),
|
|
312
|
+
validate(value, name, logger, defaults) {
|
|
313
|
+
const match = validators.find((v) => v.is(value));
|
|
314
|
+
if (match) {
|
|
315
|
+
return isCompoundValidator(match)
|
|
316
|
+
? match.validate(value, name, logger, defaults)
|
|
317
|
+
: { value };
|
|
318
|
+
}
|
|
319
|
+
logger?.warn(OptionMessages.wrongOptionType(name, this.getType(), typeof value));
|
|
320
|
+
return undefined;
|
|
321
|
+
},
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const dataSourceTypeValidator = TypeValidators.oneOf('cache', 'polling', 'streaming');
|
|
326
|
+
const connectionModeValidator = TypeValidators.oneOf('streaming', 'polling', 'offline', 'one-shot', 'background');
|
|
327
|
+
const endpointValidators = {
|
|
328
|
+
pollingBaseUri: TypeValidators.String,
|
|
329
|
+
streamingBaseUri: TypeValidators.String,
|
|
330
|
+
};
|
|
331
|
+
({
|
|
332
|
+
type: dataSourceTypeValidator,
|
|
223
333
|
pollInterval: TypeValidators.numberWithMin(30),
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
334
|
+
endpoints: validatorOf(endpointValidators),
|
|
335
|
+
});
|
|
336
|
+
({
|
|
337
|
+
type: dataSourceTypeValidator,
|
|
338
|
+
initialReconnectDelay: TypeValidators.numberWithMin(1),
|
|
339
|
+
endpoints: validatorOf(endpointValidators),
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
const modeSwitchingValidators = {
|
|
343
|
+
lifecycle: TypeValidators.Boolean,
|
|
344
|
+
network: TypeValidators.Boolean,
|
|
345
|
+
};
|
|
346
|
+
const dataSystemValidators = {
|
|
347
|
+
initialConnectionMode: connectionModeValidator,
|
|
348
|
+
backgroundConnectionMode: connectionModeValidator,
|
|
349
|
+
automaticModeSwitching: anyOf(TypeValidators.Boolean, validatorOf(modeSwitchingValidators)),
|
|
350
|
+
};
|
|
351
|
+
/**
|
|
352
|
+
* Default FDv2 data system configuration for browser SDKs.
|
|
353
|
+
*/
|
|
354
|
+
const BROWSER_DATA_SYSTEM_DEFAULTS = {
|
|
355
|
+
initialConnectionMode: 'one-shot',
|
|
356
|
+
backgroundConnectionMode: undefined,
|
|
357
|
+
automaticModeSwitching: false,
|
|
358
|
+
};
|
|
359
|
+
/**
|
|
360
|
+
* Default FDv2 data system configuration for mobile (React Native) SDKs.
|
|
361
|
+
*/
|
|
362
|
+
const MOBILE_DATA_SYSTEM_DEFAULTS = {
|
|
363
|
+
initialConnectionMode: 'streaming',
|
|
364
|
+
backgroundConnectionMode: 'background',
|
|
365
|
+
automaticModeSwitching: true,
|
|
366
|
+
};
|
|
367
|
+
/**
|
|
368
|
+
* Default FDv2 data system configuration for desktop SDKs (Electron, etc.).
|
|
369
|
+
*/
|
|
370
|
+
const DESKTOP_DATA_SYSTEM_DEFAULTS = {
|
|
371
|
+
initialConnectionMode: 'streaming',
|
|
372
|
+
backgroundConnectionMode: undefined,
|
|
373
|
+
automaticModeSwitching: false,
|
|
233
374
|
};
|
|
234
375
|
|
|
376
|
+
function createValidators(options) {
|
|
377
|
+
return {
|
|
378
|
+
logger: TypeValidators.Object,
|
|
379
|
+
maxCachedContexts: TypeValidators.numberWithMin(0),
|
|
380
|
+
baseUri: TypeValidators.String,
|
|
381
|
+
streamUri: TypeValidators.String,
|
|
382
|
+
eventsUri: TypeValidators.String,
|
|
383
|
+
capacity: TypeValidators.numberWithMin(1),
|
|
384
|
+
diagnosticRecordingInterval: TypeValidators.numberWithMin(2),
|
|
385
|
+
flushInterval: TypeValidators.numberWithMin(2),
|
|
386
|
+
streamInitialReconnectDelay: TypeValidators.numberWithMin(0),
|
|
387
|
+
allAttributesPrivate: TypeValidators.Boolean,
|
|
388
|
+
debug: TypeValidators.Boolean,
|
|
389
|
+
diagnosticOptOut: TypeValidators.Boolean,
|
|
390
|
+
withReasons: TypeValidators.Boolean,
|
|
391
|
+
sendEvents: TypeValidators.Boolean,
|
|
392
|
+
pollInterval: TypeValidators.numberWithMin(30),
|
|
393
|
+
useReport: TypeValidators.Boolean,
|
|
394
|
+
privateAttributes: TypeValidators.StringArray,
|
|
395
|
+
disableCache: TypeValidators.Boolean,
|
|
396
|
+
applicationInfo: TypeValidators.Object,
|
|
397
|
+
wrapperName: TypeValidators.String,
|
|
398
|
+
wrapperVersion: TypeValidators.String,
|
|
399
|
+
payloadFilterKey: TypeValidators.stringMatchingRegex(/^[a-zA-Z0-9](\w|\.|-)*$/),
|
|
400
|
+
hooks: TypeValidators.createTypeArray('Hook[]', {}),
|
|
401
|
+
inspectors: TypeValidators.createTypeArray('LDInspection', {}),
|
|
402
|
+
cleanOldPersistentData: TypeValidators.Boolean,
|
|
403
|
+
dataSystem: options?.dataSystemDefaults
|
|
404
|
+
? validatorOf(dataSystemValidators, options.dataSystemDefaults)
|
|
405
|
+
: TypeValidators.Object,
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
|
|
235
409
|
const DEFAULT_POLLING_INTERVAL = 60 * 5;
|
|
236
410
|
const DEFAULT_POLLING = 'https://clientsdk.launchdarkly.com';
|
|
237
411
|
const DEFAULT_STREAM = 'https://clientstream.launchdarkly.com';
|
|
@@ -257,6 +431,7 @@ class ConfigurationImpl {
|
|
|
257
431
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
258
432
|
this.streamUri = DEFAULT_STREAM;
|
|
259
433
|
this.maxCachedContexts = 5;
|
|
434
|
+
this.disableCache = false;
|
|
260
435
|
this.capacity = 100;
|
|
261
436
|
this.diagnosticRecordingInterval = 900;
|
|
262
437
|
this.flushInterval = 30;
|
|
@@ -273,8 +448,15 @@ class ConfigurationImpl {
|
|
|
273
448
|
this.hooks = [];
|
|
274
449
|
this.inspectors = [];
|
|
275
450
|
this.logger = ensureSafeLogger(pristineOptions.logger);
|
|
276
|
-
const
|
|
277
|
-
|
|
451
|
+
const validators = createValidators({
|
|
452
|
+
dataSystemDefaults: internalOptions.dataSystemDefaults,
|
|
453
|
+
});
|
|
454
|
+
const validated = validateOptions(pristineOptions, validators, {}, this.logger);
|
|
455
|
+
Object.entries(validated).forEach(([k, v]) => {
|
|
456
|
+
if (k !== 'logger') {
|
|
457
|
+
this[k] = v;
|
|
458
|
+
}
|
|
459
|
+
});
|
|
278
460
|
this.serviceEndpoints = new ServiceEndpoints(this.streamUri, this.baseUri, this.eventsUri, internalOptions.analyticsEventPath, internalOptions.diagnosticEventPath, internalOptions.includeAuthorizationHeader, pristineOptions.payloadFilterKey);
|
|
279
461
|
this.useReport = pristineOptions.useReport ?? false;
|
|
280
462
|
this.tags = new ApplicationTags({ application: this.applicationInfo, logger: this.logger });
|
|
@@ -283,44 +465,6 @@ class ConfigurationImpl {
|
|
|
283
465
|
this.credentialType = internalOptions.credentialType;
|
|
284
466
|
this.getImplementationHooks = internalOptions.getImplementationHooks;
|
|
285
467
|
}
|
|
286
|
-
_validateTypesAndNames(pristineOptions) {
|
|
287
|
-
const errors = [];
|
|
288
|
-
Object.entries(pristineOptions).forEach(([k, v]) => {
|
|
289
|
-
const validator = validators[k];
|
|
290
|
-
if (validator) {
|
|
291
|
-
if (!validator.is(v)) {
|
|
292
|
-
const validatorType = validator.getType();
|
|
293
|
-
if (validatorType === 'boolean') {
|
|
294
|
-
errors.push(OptionMessages.wrongOptionTypeBoolean(k, typeof v));
|
|
295
|
-
this[k] = !!v;
|
|
296
|
-
}
|
|
297
|
-
else if (validatorType === 'boolean | undefined | null') {
|
|
298
|
-
errors.push(OptionMessages.wrongOptionTypeBoolean(k, typeof v));
|
|
299
|
-
if (typeof v !== 'boolean' && typeof v !== 'undefined' && v !== null) {
|
|
300
|
-
this[k] = !!v;
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
else if (validator instanceof NumberWithMinimum && TypeValidators.Number.is(v)) {
|
|
304
|
-
const { min } = validator;
|
|
305
|
-
errors.push(OptionMessages.optionBelowMinimum(k, v, min));
|
|
306
|
-
this[k] = min;
|
|
307
|
-
}
|
|
308
|
-
else {
|
|
309
|
-
errors.push(OptionMessages.wrongOptionType(k, validator.getType(), typeof v));
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
else if (k === 'logger') ;
|
|
313
|
-
else {
|
|
314
|
-
// if an option is explicitly null, coerce to undefined
|
|
315
|
-
this[k] = v ?? undefined;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
else {
|
|
319
|
-
errors.push(OptionMessages.unknownOption(k));
|
|
320
|
-
}
|
|
321
|
-
});
|
|
322
|
-
return errors;
|
|
323
|
-
}
|
|
324
468
|
}
|
|
325
469
|
|
|
326
470
|
async function digest(hasher, encoding) {
|
|
@@ -659,6 +803,71 @@ class EventFactory extends internal.EventFactoryBase {
|
|
|
659
803
|
}
|
|
660
804
|
}
|
|
661
805
|
|
|
806
|
+
/**
|
|
807
|
+
* Suffix appended to context storage keys to form the freshness storage key.
|
|
808
|
+
*/
|
|
809
|
+
const FRESHNESS_SUFFIX = '_freshness';
|
|
810
|
+
/**
|
|
811
|
+
* Computes a SHA-256 hash of the context's full canonical JSON.
|
|
812
|
+
* Returns `undefined` if the context cannot be serialized.
|
|
813
|
+
*/
|
|
814
|
+
async function hashContext(crypto, context) {
|
|
815
|
+
const json = context.canonicalUnfilteredJson();
|
|
816
|
+
if (!json) {
|
|
817
|
+
return undefined;
|
|
818
|
+
}
|
|
819
|
+
return digest(crypto.createHash('sha256').update(json), 'base64');
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
function isValidFlag(value) {
|
|
823
|
+
return value !== null && typeof value === 'object' && typeof value.version === 'number';
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* Loads cached flag data from storage for the given context.
|
|
827
|
+
*
|
|
828
|
+
* Checks the current storage key first, then falls back to the legacy
|
|
829
|
+
* canonical key location (pre-10.3.1). Does NOT perform migration — the
|
|
830
|
+
* caller is responsible for migrating data if {@link CachedFlagData.fromLegacyKey}
|
|
831
|
+
* is true.
|
|
832
|
+
*
|
|
833
|
+
* @returns The cached flag data, or `undefined` on cache miss or parse error.
|
|
834
|
+
*/
|
|
835
|
+
async function loadCachedFlags(storage, crypto, environmentNamespace, context, logger) {
|
|
836
|
+
const storageKey = await namespaceForContextData(crypto, environmentNamespace, context);
|
|
837
|
+
let flagsJson = await storage.get(storageKey);
|
|
838
|
+
let fromLegacyKey = false;
|
|
839
|
+
if (flagsJson === null || flagsJson === undefined) {
|
|
840
|
+
// Fallback: in version <10.3.1 flag data was stored under the canonical key.
|
|
841
|
+
flagsJson = await storage.get(context.canonicalKey);
|
|
842
|
+
if (flagsJson === null || flagsJson === undefined) {
|
|
843
|
+
return undefined;
|
|
844
|
+
}
|
|
845
|
+
fromLegacyKey = true;
|
|
846
|
+
}
|
|
847
|
+
try {
|
|
848
|
+
const parsed = JSON.parse(flagsJson);
|
|
849
|
+
if (parsed === null || typeof parsed !== 'object') {
|
|
850
|
+
logger?.warn('Cached flag data is not a valid object');
|
|
851
|
+
return undefined;
|
|
852
|
+
}
|
|
853
|
+
const entries = Object.entries(parsed);
|
|
854
|
+
const invalidKey = entries.find(([, value]) => !isValidFlag(value));
|
|
855
|
+
if (invalidKey) {
|
|
856
|
+
logger?.warn(`Discarding cached flags due to invalid entry: ${invalidKey[0]}`);
|
|
857
|
+
return undefined;
|
|
858
|
+
}
|
|
859
|
+
const flags = entries.reduce((acc, [key, value]) => {
|
|
860
|
+
acc[key] = value;
|
|
861
|
+
return acc;
|
|
862
|
+
}, {});
|
|
863
|
+
return { flags, storageKey, fromLegacyKey };
|
|
864
|
+
}
|
|
865
|
+
catch (e) {
|
|
866
|
+
logger?.warn(`Could not parse cached flag evaluations from persistent storage: ${e.message}`);
|
|
867
|
+
return undefined;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
|
|
662
871
|
/**
|
|
663
872
|
* An index for tracking the most recently used contexts by timestamp with the ability to
|
|
664
873
|
* update entry timestamps and prune out least used contexts above a max capacity provided.
|
|
@@ -724,12 +933,18 @@ class ContextIndex {
|
|
|
724
933
|
* This class handles persisting and loading flag values from a persistent
|
|
725
934
|
* store. It intercepts updates and forwards them to the flag updater and
|
|
726
935
|
* then persists changes after the updater has completed.
|
|
936
|
+
*
|
|
937
|
+
* Freshness metadata (timestamp + context attribute hash) is stored in a
|
|
938
|
+
* separate storage key (`{contextKey}_freshness`) alongside the flag data.
|
|
939
|
+
* Both keys are managed together — when a context is evicted, both the flag
|
|
940
|
+
* data and freshness record are cleared.
|
|
727
941
|
*/
|
|
728
942
|
class FlagPersistence {
|
|
729
|
-
constructor(_platform, _environmentNamespace, _maxCachedContexts, _flagStore, _flagUpdater, _logger, _timeStamper = () => Date.now()) {
|
|
943
|
+
constructor(_platform, _environmentNamespace, _maxCachedContexts, _disableCache, _flagStore, _flagUpdater, _logger, _timeStamper = () => Date.now()) {
|
|
730
944
|
this._platform = _platform;
|
|
731
945
|
this._environmentNamespace = _environmentNamespace;
|
|
732
946
|
this._maxCachedContexts = _maxCachedContexts;
|
|
947
|
+
this._disableCache = _disableCache;
|
|
733
948
|
this._flagStore = _flagStore;
|
|
734
949
|
this._flagUpdater = _flagUpdater;
|
|
735
950
|
this._logger = _logger;
|
|
@@ -761,35 +976,38 @@ class FlagPersistence {
|
|
|
761
976
|
* {@link FlagUpdater} this {@link FlagPersistence} was constructed with.
|
|
762
977
|
*/
|
|
763
978
|
async loadCached(context) {
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
if (flagsJson === null || flagsJson === undefined) {
|
|
767
|
-
// Fallback: in version <10.3.1 flag data was stored under the canonical key, check
|
|
768
|
-
// to see if data is present and migrate the data if present.
|
|
769
|
-
flagsJson = await this._platform.storage?.get(context.canonicalKey);
|
|
770
|
-
if (flagsJson === null || flagsJson === undefined) {
|
|
771
|
-
// return false indicating cache did not load if flag json is still absent
|
|
772
|
-
return false;
|
|
773
|
-
}
|
|
774
|
-
// migrate data from version <10.3.1 and cleanup data that was under canonical key
|
|
775
|
-
await this._platform.storage?.set(storageKey, flagsJson);
|
|
776
|
-
await this._platform.storage?.clear(context.canonicalKey);
|
|
979
|
+
if (this._disableCache || this._maxCachedContexts <= 0) {
|
|
980
|
+
return false;
|
|
777
981
|
}
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
// mapping flags to item descriptors
|
|
781
|
-
const descriptors = Object.entries(flags).reduce((acc, [key, flag]) => {
|
|
782
|
-
acc[key] = { version: flag.version, flag };
|
|
783
|
-
return acc;
|
|
784
|
-
}, {});
|
|
785
|
-
this._flagUpdater.initCached(context, descriptors);
|
|
786
|
-
this._logger.debug('Loaded cached flag evaluations from persistent storage');
|
|
787
|
-
return true;
|
|
982
|
+
if (!this._platform.storage) {
|
|
983
|
+
return false;
|
|
788
984
|
}
|
|
789
|
-
|
|
790
|
-
|
|
985
|
+
const cached = await loadCachedFlags(this._platform.storage, this._platform.crypto, this._environmentNamespace, context, this._logger);
|
|
986
|
+
if (!cached) {
|
|
791
987
|
return false;
|
|
792
988
|
}
|
|
989
|
+
// Migrate data from version <10.3.1 stored under the canonical key
|
|
990
|
+
if (cached.fromLegacyKey) {
|
|
991
|
+
await this._platform.storage.set(cached.storageKey, JSON.stringify(cached.flags));
|
|
992
|
+
await this._platform.storage.clear(context.canonicalKey);
|
|
993
|
+
}
|
|
994
|
+
// mapping flags to item descriptors
|
|
995
|
+
const descriptors = Object.entries(cached.flags).reduce((acc, [key, flag]) => {
|
|
996
|
+
acc[key] = { version: flag.version, flag };
|
|
997
|
+
return acc;
|
|
998
|
+
}, {});
|
|
999
|
+
this._flagUpdater.initCached(context, descriptors);
|
|
1000
|
+
this._logger.debug('Loaded cached flag evaluations from persistent storage');
|
|
1001
|
+
return true;
|
|
1002
|
+
}
|
|
1003
|
+
async _storeFreshness(contextStorageKey, context, timestamp) {
|
|
1004
|
+
const contextHash = await hashContext(this._platform.crypto, context);
|
|
1005
|
+
if (contextHash === undefined) {
|
|
1006
|
+
this._logger.error('Could not serialize context for freshness tracking');
|
|
1007
|
+
return;
|
|
1008
|
+
}
|
|
1009
|
+
const record = { timestamp, contextHash };
|
|
1010
|
+
await this._platform.storage?.set(`${contextStorageKey}${FRESHNESS_SUFFIX}`, JSON.stringify(record));
|
|
793
1011
|
}
|
|
794
1012
|
async _loadIndex() {
|
|
795
1013
|
if (this._contextIndex !== undefined) {
|
|
@@ -811,13 +1029,26 @@ class FlagPersistence {
|
|
|
811
1029
|
return this._contextIndex;
|
|
812
1030
|
}
|
|
813
1031
|
async _storeCache(context) {
|
|
1032
|
+
if (this._disableCache) {
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
1035
|
+
const now = this._timeStamper();
|
|
814
1036
|
const index = await this._loadIndex();
|
|
815
1037
|
const storageKey = await namespaceForContextData(this._platform.crypto, this._environmentNamespace, context);
|
|
816
|
-
|
|
1038
|
+
if (this._maxCachedContexts > 0) {
|
|
1039
|
+
index.notice(storageKey, now);
|
|
1040
|
+
}
|
|
817
1041
|
const pruned = index.prune(this._maxCachedContexts);
|
|
818
|
-
|
|
819
|
-
|
|
1042
|
+
// If maxCachedContexts <= 0, current context was never added, so always skip flag write
|
|
1043
|
+
const currentContextWasPruned = this._maxCachedContexts <= 0 || pruned.some((it) => it.id === storageKey);
|
|
1044
|
+
await Promise.all(pruned.flatMap((it) => [
|
|
1045
|
+
this._platform.storage?.clear(it.id),
|
|
1046
|
+
this._platform.storage?.clear(`${it.id}${FRESHNESS_SUFFIX}`),
|
|
1047
|
+
]));
|
|
820
1048
|
await this._platform.storage?.set(await this._indexKeyPromise, index.toJson());
|
|
1049
|
+
if (currentContextWasPruned) {
|
|
1050
|
+
return;
|
|
1051
|
+
}
|
|
821
1052
|
const allFlags = this._flagStore.getAll();
|
|
822
1053
|
// mapping item descriptors to flags
|
|
823
1054
|
const flags = Object.entries(allFlags).reduce((acc, [key, descriptor]) => {
|
|
@@ -827,8 +1058,15 @@ class FlagPersistence {
|
|
|
827
1058
|
return acc;
|
|
828
1059
|
}, {});
|
|
829
1060
|
const jsonAll = JSON.stringify(flags);
|
|
830
|
-
// store flag data
|
|
1061
|
+
// store flag data first, so freshness is never newer than the flags it describes
|
|
831
1062
|
await this._platform.storage?.set(storageKey, jsonAll);
|
|
1063
|
+
// store freshness — best-effort, must not block flag persistence
|
|
1064
|
+
try {
|
|
1065
|
+
await this._storeFreshness(storageKey, context, now);
|
|
1066
|
+
}
|
|
1067
|
+
catch (e) {
|
|
1068
|
+
this._logger.warn(`Failed to store freshness data: ${e.message}`);
|
|
1069
|
+
}
|
|
832
1070
|
}
|
|
833
1071
|
}
|
|
834
1072
|
|
|
@@ -944,17 +1182,18 @@ class DefaultFlagManager {
|
|
|
944
1182
|
* @param platform implementation of various platform provided functionality
|
|
945
1183
|
* @param sdkKey that will be used to distinguish different environments
|
|
946
1184
|
* @param maxCachedContexts that specifies the max number of contexts that will be cached in persistence
|
|
1185
|
+
* @param disableCache set to true to completely disable the persistent flag cache
|
|
947
1186
|
* @param logger used for logging various messages
|
|
948
1187
|
* @param timeStamper exists for testing purposes
|
|
949
1188
|
*/
|
|
950
|
-
constructor(platform, sdkKey, maxCachedContexts, logger, timeStamper = () => Date.now()) {
|
|
1189
|
+
constructor(platform, sdkKey, maxCachedContexts, disableCache, logger, timeStamper = () => Date.now()) {
|
|
951
1190
|
this._flagStore = createDefaultFlagStore();
|
|
952
1191
|
this._flagUpdater = createFlagUpdater(this._flagStore, logger);
|
|
953
|
-
this._flagPersistencePromise = this._initPersistence(platform, sdkKey, maxCachedContexts, logger, timeStamper);
|
|
1192
|
+
this._flagPersistencePromise = this._initPersistence(platform, sdkKey, maxCachedContexts, disableCache, logger, timeStamper);
|
|
954
1193
|
}
|
|
955
|
-
async _initPersistence(platform, sdkKey, maxCachedContexts, logger, timeStamper = () => Date.now()) {
|
|
1194
|
+
async _initPersistence(platform, sdkKey, maxCachedContexts, disableCache, logger, timeStamper = () => Date.now()) {
|
|
956
1195
|
const environmentNamespace = await namespaceForEnvironment(platform.crypto, sdkKey);
|
|
957
|
-
return new FlagPersistence(platform, environmentNamespace, maxCachedContexts, this._flagStore, this._flagUpdater, logger, timeStamper);
|
|
1196
|
+
return new FlagPersistence(platform, environmentNamespace, maxCachedContexts, disableCache, this._flagStore, this._flagUpdater, logger, timeStamper);
|
|
958
1197
|
}
|
|
959
1198
|
get(key) {
|
|
960
1199
|
if (this._overrides && Object.prototype.hasOwnProperty.call(this._overrides, key)) {
|
|
@@ -1430,7 +1669,7 @@ class LDClientImpl {
|
|
|
1430
1669
|
this._config = new ConfigurationImpl(options, internalOptions);
|
|
1431
1670
|
this.logger = this._config.logger;
|
|
1432
1671
|
this._baseHeaders = defaultHeaders(this.sdkKey, this.platform.info, this._config.tags, this._config.serviceEndpoints.includeAuthorizationHeader, this._config.userAgentHeaderName);
|
|
1433
|
-
this._flagManager = new DefaultFlagManager(this.platform, sdkKey, this._config.maxCachedContexts, this._config.logger);
|
|
1672
|
+
this._flagManager = new DefaultFlagManager(this.platform, sdkKey, this._config.maxCachedContexts, this._config.disableCache ?? false, this._config.logger);
|
|
1434
1673
|
this._diagnosticsManager = createDiagnosticsManager(sdkKey, this._config, platform);
|
|
1435
1674
|
this._eventProcessor = createEventProcessor(sdkKey, this._config, platform, this._baseHeaders, this._diagnosticsManager);
|
|
1436
1675
|
this.emitter = new LDEmitter();
|
|
@@ -2524,5 +2763,68 @@ class BaseDataManager {
|
|
|
2524
2763
|
}
|
|
2525
2764
|
}
|
|
2526
2765
|
|
|
2527
|
-
|
|
2766
|
+
function allConditionsMatch(conditions, input) {
|
|
2767
|
+
return Object.entries(conditions).every(([key, value]) => value === undefined || input[key] === value);
|
|
2768
|
+
}
|
|
2769
|
+
/**
|
|
2770
|
+
* Given a mode resolution table and the current input state, returns the
|
|
2771
|
+
* resolved FDv2 connection mode.
|
|
2772
|
+
*
|
|
2773
|
+
* Iterates entries in order. The first entry whose conditions all match the
|
|
2774
|
+
* input wins. If no entry matches (should not happen when the table ends with
|
|
2775
|
+
* a catch-all), falls back to `input.foregroundMode`.
|
|
2776
|
+
*/
|
|
2777
|
+
const CONFIGURED_MODE_MAP = {
|
|
2778
|
+
foreground: 'foregroundMode',
|
|
2779
|
+
background: 'backgroundMode',
|
|
2780
|
+
};
|
|
2781
|
+
function resolveConnectionMode(table, input) {
|
|
2782
|
+
const match = table.find((entry) => allConditionsMatch(entry.conditions, input));
|
|
2783
|
+
if (match) {
|
|
2784
|
+
const { mode } = match;
|
|
2785
|
+
if (typeof mode === 'object') {
|
|
2786
|
+
return input[CONFIGURED_MODE_MAP[mode.configured]];
|
|
2787
|
+
}
|
|
2788
|
+
return mode;
|
|
2789
|
+
}
|
|
2790
|
+
return input.foregroundMode;
|
|
2791
|
+
}
|
|
2792
|
+
/**
|
|
2793
|
+
* Mode resolution table for mobile platforms (React Native, etc.).
|
|
2794
|
+
*
|
|
2795
|
+
* - No network → offline.
|
|
2796
|
+
* - Background → configured background mode.
|
|
2797
|
+
* - Foreground → configured foreground mode.
|
|
2798
|
+
*/
|
|
2799
|
+
const MOBILE_TRANSITION_TABLE = [
|
|
2800
|
+
{ conditions: { networkAvailable: false }, mode: 'offline' },
|
|
2801
|
+
{ conditions: { lifecycle: 'background' }, mode: { configured: 'background' } },
|
|
2802
|
+
{ conditions: { lifecycle: 'foreground' }, mode: { configured: 'foreground' } },
|
|
2803
|
+
];
|
|
2804
|
+
/**
|
|
2805
|
+
* Mode resolution table for browser platforms.
|
|
2806
|
+
*
|
|
2807
|
+
* - No network → offline.
|
|
2808
|
+
* - Otherwise → configured foreground mode.
|
|
2809
|
+
*
|
|
2810
|
+
* Browser listener-driven streaming (auto-promotion to streaming when change
|
|
2811
|
+
* listeners are registered) is handled externally by the caller modifying
|
|
2812
|
+
* `foregroundMode` before consulting this table.
|
|
2813
|
+
*/
|
|
2814
|
+
const BROWSER_TRANSITION_TABLE = [
|
|
2815
|
+
{ conditions: { networkAvailable: false }, mode: 'offline' },
|
|
2816
|
+
{ conditions: {}, mode: { configured: 'foreground' } },
|
|
2817
|
+
];
|
|
2818
|
+
/**
|
|
2819
|
+
* Mode resolution table for desktop platforms (Electron, etc.).
|
|
2820
|
+
*
|
|
2821
|
+
* - No network → offline.
|
|
2822
|
+
* - Otherwise → configured foreground mode.
|
|
2823
|
+
*/
|
|
2824
|
+
const DESKTOP_TRANSITION_TABLE = [
|
|
2825
|
+
{ conditions: { networkAvailable: false }, mode: 'offline' },
|
|
2826
|
+
{ conditions: {}, mode: { configured: 'foreground' } },
|
|
2827
|
+
];
|
|
2828
|
+
|
|
2829
|
+
export { BROWSER_DATA_SYSTEM_DEFAULTS, BROWSER_TRANSITION_TABLE, BaseDataManager, DESKTOP_DATA_SYSTEM_DEFAULTS, DESKTOP_TRANSITION_TABLE, DataSourceState, LDClientImpl, MOBILE_DATA_SYSTEM_DEFAULTS, MOBILE_TRANSITION_TABLE, browserFdv1Endpoints, dataSystemValidators, fdv2Endpoints, makeRequestor, mobileFdv1Endpoints, readFlagsFromBootstrap, resolveConnectionMode, safeRegisterDebugOverridePlugins, validateOptions };
|
|
2528
2830
|
//# sourceMappingURL=index.mjs.map
|