@launchdarkly/js-client-sdk-common 1.17.1 → 1.18.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 +15 -0
- package/dist/cjs/DataManager.d.ts +2 -2
- package/dist/cjs/DataManager.d.ts.map +1 -1
- package/dist/cjs/LDClientImpl.d.ts +3 -3
- package/dist/cjs/LDClientImpl.d.ts.map +1 -1
- package/dist/cjs/api/LDClient.d.ts +3 -2
- package/dist/cjs/api/LDClient.d.ts.map +1 -1
- package/dist/cjs/api/LDContext.d.ts +64 -0
- package/dist/cjs/api/LDContext.d.ts.map +1 -0
- package/dist/cjs/api/LDEvaluationDetail.d.ts +2 -2
- package/dist/cjs/api/LDEvaluationDetail.d.ts.map +1 -1
- package/dist/cjs/api/index.d.ts +1 -0
- package/dist/cjs/api/index.d.ts.map +1 -1
- package/dist/cjs/context/ensureKey.d.ts +3 -2
- package/dist/cjs/context/ensureKey.d.ts.map +1 -1
- package/dist/cjs/datasource/DataSourceEventHandler.d.ts +4 -6
- package/dist/cjs/datasource/DataSourceEventHandler.d.ts.map +1 -1
- package/dist/cjs/datasource/DataSourceStatus.d.ts +64 -14
- package/dist/cjs/datasource/DataSourceStatus.d.ts.map +1 -1
- package/dist/cjs/datasource/DataSourceStatusManager.d.ts +6 -17
- package/dist/cjs/datasource/DataSourceStatusManager.d.ts.map +1 -1
- package/dist/cjs/datasource/Requestor.d.ts +2 -9
- package/dist/cjs/datasource/Requestor.d.ts.map +1 -1
- package/dist/cjs/flag-manager/bootstrap.d.ts +6 -0
- package/dist/cjs/flag-manager/bootstrap.d.ts.map +1 -0
- package/dist/cjs/index.cjs +157 -154
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.ts +3 -2
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/streaming/StreamingProcessor.d.ts +1 -1
- package/dist/cjs/streaming/StreamingProcessor.d.ts.map +1 -1
- package/dist/esm/DataManager.d.ts +2 -2
- package/dist/esm/DataManager.d.ts.map +1 -1
- package/dist/esm/LDClientImpl.d.ts +3 -3
- package/dist/esm/LDClientImpl.d.ts.map +1 -1
- package/dist/esm/api/LDClient.d.ts +3 -2
- package/dist/esm/api/LDClient.d.ts.map +1 -1
- package/dist/esm/api/LDContext.d.ts +64 -0
- package/dist/esm/api/LDContext.d.ts.map +1 -0
- package/dist/esm/api/LDEvaluationDetail.d.ts +2 -2
- package/dist/esm/api/LDEvaluationDetail.d.ts.map +1 -1
- package/dist/esm/api/index.d.ts +1 -0
- package/dist/esm/api/index.d.ts.map +1 -1
- package/dist/esm/context/ensureKey.d.ts +3 -2
- package/dist/esm/context/ensureKey.d.ts.map +1 -1
- package/dist/esm/datasource/DataSourceEventHandler.d.ts +4 -6
- package/dist/esm/datasource/DataSourceEventHandler.d.ts.map +1 -1
- package/dist/esm/datasource/DataSourceStatus.d.ts +64 -14
- package/dist/esm/datasource/DataSourceStatus.d.ts.map +1 -1
- package/dist/esm/datasource/DataSourceStatusManager.d.ts +6 -17
- package/dist/esm/datasource/DataSourceStatusManager.d.ts.map +1 -1
- package/dist/esm/datasource/Requestor.d.ts +2 -9
- package/dist/esm/datasource/Requestor.d.ts.map +1 -1
- package/dist/esm/flag-manager/bootstrap.d.ts +6 -0
- package/dist/esm/flag-manager/bootstrap.d.ts.map +1 -0
- package/dist/esm/index.d.ts +3 -2
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.mjs +156 -154
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/streaming/StreamingProcessor.d.ts +1 -1
- package/dist/esm/streaming/StreamingProcessor.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -21,18 +21,17 @@ function _interopNamespaceDefault(e) {
|
|
|
21
21
|
|
|
22
22
|
var jsSdkCommon__namespace = /*#__PURE__*/_interopNamespaceDefault(jsSdkCommon);
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
24
|
+
// This is a temporary compat for react native. We should remove this once we
|
|
25
|
+
// major version react native SDK.
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
|
27
|
+
const DataSourceState = {
|
|
28
|
+
Initializing: 'INITIALIZING',
|
|
29
|
+
Valid: 'VALID',
|
|
30
|
+
Interrupted: 'INTERRUPTED',
|
|
31
|
+
SetOffline: 'SET_OFFLINE',
|
|
32
|
+
Closed: 'CLOSED',
|
|
33
|
+
};
|
|
34
34
|
|
|
35
|
-
// eslint-disable-next-line max-classes-per-file
|
|
36
35
|
function isOk(status) {
|
|
37
36
|
return status >= 200 && status <= 299;
|
|
38
37
|
}
|
|
@@ -43,38 +42,6 @@ class LDRequestError extends Error {
|
|
|
43
42
|
this.name = 'LaunchDarklyRequestError';
|
|
44
43
|
}
|
|
45
44
|
}
|
|
46
|
-
/**
|
|
47
|
-
* Note: The requestor is implemented independently from polling such that it can be used to
|
|
48
|
-
* make a one-off request.
|
|
49
|
-
*/
|
|
50
|
-
class Requestor {
|
|
51
|
-
constructor(_requests, _uri, _headers, _method, _body) {
|
|
52
|
-
this._requests = _requests;
|
|
53
|
-
this._uri = _uri;
|
|
54
|
-
this._headers = _headers;
|
|
55
|
-
this._method = _method;
|
|
56
|
-
this._body = _body;
|
|
57
|
-
}
|
|
58
|
-
async requestPayload() {
|
|
59
|
-
let status;
|
|
60
|
-
try {
|
|
61
|
-
const res = await this._requests.fetch(this._uri, {
|
|
62
|
-
method: this._method,
|
|
63
|
-
headers: this._headers,
|
|
64
|
-
body: this._body,
|
|
65
|
-
});
|
|
66
|
-
if (isOk(res.status)) {
|
|
67
|
-
return await res.text();
|
|
68
|
-
}
|
|
69
|
-
// Assigning so it can be thrown after the try/catch.
|
|
70
|
-
status = res.status;
|
|
71
|
-
}
|
|
72
|
-
catch (err) {
|
|
73
|
-
throw new LDRequestError(err?.message);
|
|
74
|
-
}
|
|
75
|
-
throw new LDRequestError(`Unexpected status code: ${status}`, status);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
45
|
function makeRequestor(plainContextString, serviceEndpoints, paths, requests, encoding, baseHeaders, baseQueryParams, withReasons, useReport, secureModeHash) {
|
|
79
46
|
let body;
|
|
80
47
|
let method = 'GET';
|
|
@@ -95,7 +62,27 @@ function makeRequestor(plainContextString, serviceEndpoints, paths, requests, en
|
|
|
95
62
|
parameters.push({ key: 'h', value: secureModeHash });
|
|
96
63
|
}
|
|
97
64
|
const uri = jsSdkCommon.getPollingUri(serviceEndpoints, path, parameters);
|
|
98
|
-
return
|
|
65
|
+
return {
|
|
66
|
+
async requestPayload() {
|
|
67
|
+
let status;
|
|
68
|
+
try {
|
|
69
|
+
const res = await requests.fetch(uri, {
|
|
70
|
+
method,
|
|
71
|
+
headers,
|
|
72
|
+
body,
|
|
73
|
+
});
|
|
74
|
+
if (isOk(res.status)) {
|
|
75
|
+
return await res.text();
|
|
76
|
+
}
|
|
77
|
+
// Assigning so it can be thrown after the try/catch.
|
|
78
|
+
status = res.status;
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
throw new LDRequestError(err?.message);
|
|
82
|
+
}
|
|
83
|
+
throw new LDRequestError(`Unexpected status code: ${status}`, status);
|
|
84
|
+
},
|
|
85
|
+
};
|
|
99
86
|
}
|
|
100
87
|
|
|
101
88
|
const duplicateExecutionError = new Error('Task has already been executed or shed. This is likely an implementation error. The task will not be executed again.');
|
|
@@ -657,7 +644,7 @@ function createSuccessEvaluationDetail(value, variationIndex, reason) {
|
|
|
657
644
|
const res = {
|
|
658
645
|
value,
|
|
659
646
|
variationIndex: variationIndex ?? null,
|
|
660
|
-
reason
|
|
647
|
+
...(reason !== undefined && { reason }),
|
|
661
648
|
};
|
|
662
649
|
return res;
|
|
663
650
|
}
|
|
@@ -1913,9 +1900,6 @@ class LDClientImpl {
|
|
|
1913
1900
|
else {
|
|
1914
1901
|
details[flagKey] = {
|
|
1915
1902
|
value: undefined,
|
|
1916
|
-
// For backwards compatibility purposes reason and variationIndex are null instead of
|
|
1917
|
-
// being undefined.
|
|
1918
|
-
reason: null,
|
|
1919
1903
|
variationIndex: null,
|
|
1920
1904
|
};
|
|
1921
1905
|
}
|
|
@@ -1952,117 +1936,135 @@ function safeRegisterDebugOverridePlugins(logger, debugOverride, plugins) {
|
|
|
1952
1936
|
});
|
|
1953
1937
|
}
|
|
1954
1938
|
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
}
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
}
|
|
1994
|
-
handleStreamingError(error) {
|
|
1995
|
-
this._statusManager.reportError(error.kind, error.message, error.code, error.recoverable);
|
|
1996
|
-
}
|
|
1997
|
-
handlePollingError(error) {
|
|
1998
|
-
this._statusManager.reportError(error.kind, error.message, error.status, error.recoverable);
|
|
1999
|
-
}
|
|
1939
|
+
function readFlagsFromBootstrap(logger, data) {
|
|
1940
|
+
// If the bootstrap data came from an older server-side SDK, we'll have just a map of keys to values.
|
|
1941
|
+
// Newer SDKs that have an allFlagsState method will provide an extra "$flagsState" key that contains
|
|
1942
|
+
// the rest of the metadata we want. We do it this way for backward compatibility with older JS SDKs.
|
|
1943
|
+
const keys = Object.keys(data);
|
|
1944
|
+
const metadataKey = '$flagsState';
|
|
1945
|
+
const validKey = '$valid';
|
|
1946
|
+
const metadata = data[metadataKey];
|
|
1947
|
+
if (!metadata && keys.length) {
|
|
1948
|
+
logger.warn('LaunchDarkly client was initialized with bootstrap data that did not include flag' +
|
|
1949
|
+
' metadata. Events may not be sent correctly.');
|
|
1950
|
+
}
|
|
1951
|
+
if (data[validKey] === false) {
|
|
1952
|
+
logger.warn('LaunchDarkly bootstrap data is not available because the back end could not read the flags.');
|
|
1953
|
+
}
|
|
1954
|
+
const ret = {};
|
|
1955
|
+
keys.forEach((key) => {
|
|
1956
|
+
if (key !== metadataKey && key !== validKey) {
|
|
1957
|
+
let flag;
|
|
1958
|
+
if (metadata && metadata[key]) {
|
|
1959
|
+
flag = {
|
|
1960
|
+
value: data[key],
|
|
1961
|
+
...metadata[key],
|
|
1962
|
+
};
|
|
1963
|
+
}
|
|
1964
|
+
else {
|
|
1965
|
+
flag = {
|
|
1966
|
+
value: data[key],
|
|
1967
|
+
version: 0,
|
|
1968
|
+
};
|
|
1969
|
+
}
|
|
1970
|
+
ret[key] = {
|
|
1971
|
+
version: flag.version,
|
|
1972
|
+
flag,
|
|
1973
|
+
};
|
|
1974
|
+
}
|
|
1975
|
+
});
|
|
1976
|
+
return ret;
|
|
2000
1977
|
}
|
|
2001
1978
|
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
1979
|
+
function createDataSourceEventHandler(flagManager, statusManager, logger) {
|
|
1980
|
+
return {
|
|
1981
|
+
async handlePut(context, flags) {
|
|
1982
|
+
logger.debug(`Got PUT: ${Object.keys(flags)}`);
|
|
1983
|
+
// mapping flags to item descriptors
|
|
1984
|
+
const descriptors = Object.entries(flags).reduce((acc, [key, flag]) => {
|
|
1985
|
+
acc[key] = { version: flag.version, flag };
|
|
1986
|
+
return acc;
|
|
1987
|
+
}, {});
|
|
1988
|
+
await flagManager.init(context, descriptors);
|
|
1989
|
+
statusManager.requestStateUpdate('VALID');
|
|
1990
|
+
},
|
|
1991
|
+
async handlePatch(context, patchFlag) {
|
|
1992
|
+
logger.debug(`Got PATCH ${JSON.stringify(patchFlag, null, 2)}`);
|
|
1993
|
+
flagManager.upsert(context, patchFlag.key, {
|
|
1994
|
+
version: patchFlag.version,
|
|
1995
|
+
flag: patchFlag,
|
|
1996
|
+
});
|
|
1997
|
+
},
|
|
1998
|
+
async handleDelete(context, deleteFlag) {
|
|
1999
|
+
logger.debug(`Got DELETE ${JSON.stringify(deleteFlag, null, 2)}`);
|
|
2000
|
+
flagManager.upsert(context, deleteFlag.key, {
|
|
2001
|
+
version: deleteFlag.version,
|
|
2002
|
+
flag: {
|
|
2003
|
+
...deleteFlag,
|
|
2004
|
+
deleted: true,
|
|
2005
|
+
// props below are set to sensible defaults. they are irrelevant
|
|
2006
|
+
// because this flag has been deleted.
|
|
2007
|
+
flagVersion: 0,
|
|
2008
|
+
value: undefined,
|
|
2009
|
+
variation: 0,
|
|
2010
|
+
trackEvents: false,
|
|
2011
|
+
},
|
|
2012
|
+
});
|
|
2013
|
+
},
|
|
2014
|
+
handleStreamingError(error) {
|
|
2015
|
+
statusManager.reportError(error.kind, error.message, error.code, error.recoverable);
|
|
2016
|
+
},
|
|
2017
|
+
handlePollingError(error) {
|
|
2018
|
+
statusManager.reportError(error.kind, error.message, error.status, error.recoverable);
|
|
2019
|
+
},
|
|
2020
|
+
};
|
|
2021
|
+
}
|
|
2022
|
+
|
|
2023
|
+
function createDataSourceStatusManager(emitter, timeStamper = () => Date.now()) {
|
|
2024
|
+
let state = 'CLOSED';
|
|
2025
|
+
let stateSinceMillis = timeStamper();
|
|
2026
|
+
let errorInfo;
|
|
2027
|
+
function getStatus() {
|
|
2013
2028
|
return {
|
|
2014
|
-
state
|
|
2015
|
-
stateSince:
|
|
2016
|
-
lastError:
|
|
2029
|
+
state,
|
|
2030
|
+
stateSince: stateSinceMillis,
|
|
2031
|
+
lastError: errorInfo,
|
|
2017
2032
|
};
|
|
2018
2033
|
}
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
* @param requestedState to track
|
|
2023
|
-
* @param isError to indicate that the state update is a result of an error occurring.
|
|
2024
|
-
*/
|
|
2025
|
-
_updateState(requestedState, isError = false) {
|
|
2026
|
-
const newState = requestedState === exports.DataSourceState.Interrupted && this._state === exports.DataSourceState.Initializing // don't go to interrupted from initializing (recoverable errors when initializing are not noteworthy)
|
|
2027
|
-
? exports.DataSourceState.Initializing
|
|
2034
|
+
function updateState(requestedState, isError = false) {
|
|
2035
|
+
const newState = requestedState === 'INTERRUPTED' && state === 'INITIALIZING' // don't go to interrupted from initializing (recoverable errors when initializing are not noteworthy)
|
|
2036
|
+
? 'INITIALIZING'
|
|
2028
2037
|
: requestedState;
|
|
2029
|
-
const changedState =
|
|
2038
|
+
const changedState = state !== newState;
|
|
2030
2039
|
if (changedState) {
|
|
2031
|
-
|
|
2032
|
-
|
|
2040
|
+
state = newState;
|
|
2041
|
+
stateSinceMillis = timeStamper();
|
|
2033
2042
|
}
|
|
2034
2043
|
if (changedState || isError) {
|
|
2035
|
-
|
|
2044
|
+
emitter.emit('dataSourceStatus', getStatus());
|
|
2036
2045
|
}
|
|
2037
2046
|
}
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
message,
|
|
2060
|
-
statusCode,
|
|
2061
|
-
time: this._timeStamper(),
|
|
2062
|
-
};
|
|
2063
|
-
this._errorInfo = errorInfo;
|
|
2064
|
-
this._updateState(recoverable ? exports.DataSourceState.Interrupted : exports.DataSourceState.Closed, true);
|
|
2065
|
-
}
|
|
2047
|
+
return {
|
|
2048
|
+
get status() {
|
|
2049
|
+
return getStatus();
|
|
2050
|
+
},
|
|
2051
|
+
requestStateUpdate(requestedState) {
|
|
2052
|
+
updateState(requestedState);
|
|
2053
|
+
},
|
|
2054
|
+
reportError(kind, message, statusCode, recoverable = false) {
|
|
2055
|
+
errorInfo = {
|
|
2056
|
+
kind,
|
|
2057
|
+
message,
|
|
2058
|
+
statusCode,
|
|
2059
|
+
time: timeStamper(),
|
|
2060
|
+
};
|
|
2061
|
+
updateState(recoverable ? 'INTERRUPTED' : 'CLOSED', true);
|
|
2062
|
+
},
|
|
2063
|
+
// TODO: SDK-702 - Implement network availability behaviors
|
|
2064
|
+
// setNetworkUnavailable() {
|
|
2065
|
+
// updateState(DataSourceState.NetworkUnavailable);
|
|
2066
|
+
// },
|
|
2067
|
+
};
|
|
2066
2068
|
}
|
|
2067
2069
|
|
|
2068
2070
|
function reportClosed(logger) {
|
|
@@ -2344,8 +2346,8 @@ class BaseDataManager {
|
|
|
2344
2346
|
this.diagnosticsManager = diagnosticsManager;
|
|
2345
2347
|
this.closed = false;
|
|
2346
2348
|
this.logger = config.logger;
|
|
2347
|
-
this.dataSourceStatusManager =
|
|
2348
|
-
this._dataSourceEventHandler =
|
|
2349
|
+
this.dataSourceStatusManager = createDataSourceStatusManager(emitter);
|
|
2350
|
+
this._dataSourceEventHandler = createDataSourceEventHandler(flagManager, this.dataSourceStatusManager, this.config.logger);
|
|
2349
2351
|
}
|
|
2350
2352
|
/**
|
|
2351
2353
|
* Set additional connection parameters for requests polling/streaming.
|
|
@@ -2408,16 +2410,16 @@ class BaseDataManager {
|
|
|
2408
2410
|
return {
|
|
2409
2411
|
start: () => {
|
|
2410
2412
|
// update status before starting processor to ensure potential errors are reported after initializing
|
|
2411
|
-
statusManager.requestStateUpdate(
|
|
2413
|
+
statusManager.requestStateUpdate('INITIALIZING');
|
|
2412
2414
|
processor.start();
|
|
2413
2415
|
},
|
|
2414
2416
|
stop: () => {
|
|
2415
2417
|
processor.stop();
|
|
2416
|
-
statusManager.requestStateUpdate(
|
|
2418
|
+
statusManager.requestStateUpdate('CLOSED');
|
|
2417
2419
|
},
|
|
2418
2420
|
close: () => {
|
|
2419
2421
|
processor.close();
|
|
2420
|
-
statusManager.requestStateUpdate(
|
|
2422
|
+
statusManager.requestStateUpdate('CLOSED');
|
|
2421
2423
|
},
|
|
2422
2424
|
};
|
|
2423
2425
|
}
|
|
@@ -2429,9 +2431,10 @@ class BaseDataManager {
|
|
|
2429
2431
|
|
|
2430
2432
|
exports.platform = jsSdkCommon__namespace;
|
|
2431
2433
|
exports.BaseDataManager = BaseDataManager;
|
|
2434
|
+
exports.DataSourceState = DataSourceState;
|
|
2432
2435
|
exports.LDClientImpl = LDClientImpl;
|
|
2433
|
-
exports.Requestor = Requestor;
|
|
2434
2436
|
exports.makeRequestor = makeRequestor;
|
|
2437
|
+
exports.readFlagsFromBootstrap = readFlagsFromBootstrap;
|
|
2435
2438
|
exports.safeRegisterDebugOverridePlugins = safeRegisterDebugOverridePlugins;
|
|
2436
2439
|
Object.keys(jsSdkCommon).forEach(function (k) {
|
|
2437
2440
|
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|