@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/esm/index.mjs
CHANGED
|
@@ -3,18 +3,17 @@ export * from '@launchdarkly/js-sdk-common';
|
|
|
3
3
|
import * as jsSdkCommon from '@launchdarkly/js-sdk-common';
|
|
4
4
|
export { jsSdkCommon as platform };
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
6
|
+
// This is a temporary compat for react native. We should remove this once we
|
|
7
|
+
// major version react native SDK.
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
|
9
|
+
const DataSourceState = {
|
|
10
|
+
Initializing: 'INITIALIZING',
|
|
11
|
+
Valid: 'VALID',
|
|
12
|
+
Interrupted: 'INTERRUPTED',
|
|
13
|
+
SetOffline: 'SET_OFFLINE',
|
|
14
|
+
Closed: 'CLOSED',
|
|
15
|
+
};
|
|
16
16
|
|
|
17
|
-
// eslint-disable-next-line max-classes-per-file
|
|
18
17
|
function isOk(status) {
|
|
19
18
|
return status >= 200 && status <= 299;
|
|
20
19
|
}
|
|
@@ -25,38 +24,6 @@ class LDRequestError extends Error {
|
|
|
25
24
|
this.name = 'LaunchDarklyRequestError';
|
|
26
25
|
}
|
|
27
26
|
}
|
|
28
|
-
/**
|
|
29
|
-
* Note: The requestor is implemented independently from polling such that it can be used to
|
|
30
|
-
* make a one-off request.
|
|
31
|
-
*/
|
|
32
|
-
class Requestor {
|
|
33
|
-
constructor(_requests, _uri, _headers, _method, _body) {
|
|
34
|
-
this._requests = _requests;
|
|
35
|
-
this._uri = _uri;
|
|
36
|
-
this._headers = _headers;
|
|
37
|
-
this._method = _method;
|
|
38
|
-
this._body = _body;
|
|
39
|
-
}
|
|
40
|
-
async requestPayload() {
|
|
41
|
-
let status;
|
|
42
|
-
try {
|
|
43
|
-
const res = await this._requests.fetch(this._uri, {
|
|
44
|
-
method: this._method,
|
|
45
|
-
headers: this._headers,
|
|
46
|
-
body: this._body,
|
|
47
|
-
});
|
|
48
|
-
if (isOk(res.status)) {
|
|
49
|
-
return await res.text();
|
|
50
|
-
}
|
|
51
|
-
// Assigning so it can be thrown after the try/catch.
|
|
52
|
-
status = res.status;
|
|
53
|
-
}
|
|
54
|
-
catch (err) {
|
|
55
|
-
throw new LDRequestError(err?.message);
|
|
56
|
-
}
|
|
57
|
-
throw new LDRequestError(`Unexpected status code: ${status}`, status);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
27
|
function makeRequestor(plainContextString, serviceEndpoints, paths, requests, encoding, baseHeaders, baseQueryParams, withReasons, useReport, secureModeHash) {
|
|
61
28
|
let body;
|
|
62
29
|
let method = 'GET';
|
|
@@ -77,7 +44,27 @@ function makeRequestor(plainContextString, serviceEndpoints, paths, requests, en
|
|
|
77
44
|
parameters.push({ key: 'h', value: secureModeHash });
|
|
78
45
|
}
|
|
79
46
|
const uri = getPollingUri(serviceEndpoints, path, parameters);
|
|
80
|
-
return
|
|
47
|
+
return {
|
|
48
|
+
async requestPayload() {
|
|
49
|
+
let status;
|
|
50
|
+
try {
|
|
51
|
+
const res = await requests.fetch(uri, {
|
|
52
|
+
method,
|
|
53
|
+
headers,
|
|
54
|
+
body,
|
|
55
|
+
});
|
|
56
|
+
if (isOk(res.status)) {
|
|
57
|
+
return await res.text();
|
|
58
|
+
}
|
|
59
|
+
// Assigning so it can be thrown after the try/catch.
|
|
60
|
+
status = res.status;
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
throw new LDRequestError(err?.message);
|
|
64
|
+
}
|
|
65
|
+
throw new LDRequestError(`Unexpected status code: ${status}`, status);
|
|
66
|
+
},
|
|
67
|
+
};
|
|
81
68
|
}
|
|
82
69
|
|
|
83
70
|
const duplicateExecutionError = new Error('Task has already been executed or shed. This is likely an implementation error. The task will not be executed again.');
|
|
@@ -639,7 +626,7 @@ function createSuccessEvaluationDetail(value, variationIndex, reason) {
|
|
|
639
626
|
const res = {
|
|
640
627
|
value,
|
|
641
628
|
variationIndex: variationIndex ?? null,
|
|
642
|
-
reason
|
|
629
|
+
...(reason !== undefined && { reason }),
|
|
643
630
|
};
|
|
644
631
|
return res;
|
|
645
632
|
}
|
|
@@ -1895,9 +1882,6 @@ class LDClientImpl {
|
|
|
1895
1882
|
else {
|
|
1896
1883
|
details[flagKey] = {
|
|
1897
1884
|
value: undefined,
|
|
1898
|
-
// For backwards compatibility purposes reason and variationIndex are null instead of
|
|
1899
|
-
// being undefined.
|
|
1900
|
-
reason: null,
|
|
1901
1885
|
variationIndex: null,
|
|
1902
1886
|
};
|
|
1903
1887
|
}
|
|
@@ -1934,117 +1918,135 @@ function safeRegisterDebugOverridePlugins(logger, debugOverride, plugins) {
|
|
|
1934
1918
|
});
|
|
1935
1919
|
}
|
|
1936
1920
|
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
}
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
}
|
|
1976
|
-
handleStreamingError(error) {
|
|
1977
|
-
this._statusManager.reportError(error.kind, error.message, error.code, error.recoverable);
|
|
1978
|
-
}
|
|
1979
|
-
handlePollingError(error) {
|
|
1980
|
-
this._statusManager.reportError(error.kind, error.message, error.status, error.recoverable);
|
|
1981
|
-
}
|
|
1921
|
+
function readFlagsFromBootstrap(logger, data) {
|
|
1922
|
+
// If the bootstrap data came from an older server-side SDK, we'll have just a map of keys to values.
|
|
1923
|
+
// Newer SDKs that have an allFlagsState method will provide an extra "$flagsState" key that contains
|
|
1924
|
+
// the rest of the metadata we want. We do it this way for backward compatibility with older JS SDKs.
|
|
1925
|
+
const keys = Object.keys(data);
|
|
1926
|
+
const metadataKey = '$flagsState';
|
|
1927
|
+
const validKey = '$valid';
|
|
1928
|
+
const metadata = data[metadataKey];
|
|
1929
|
+
if (!metadata && keys.length) {
|
|
1930
|
+
logger.warn('LaunchDarkly client was initialized with bootstrap data that did not include flag' +
|
|
1931
|
+
' metadata. Events may not be sent correctly.');
|
|
1932
|
+
}
|
|
1933
|
+
if (data[validKey] === false) {
|
|
1934
|
+
logger.warn('LaunchDarkly bootstrap data is not available because the back end could not read the flags.');
|
|
1935
|
+
}
|
|
1936
|
+
const ret = {};
|
|
1937
|
+
keys.forEach((key) => {
|
|
1938
|
+
if (key !== metadataKey && key !== validKey) {
|
|
1939
|
+
let flag;
|
|
1940
|
+
if (metadata && metadata[key]) {
|
|
1941
|
+
flag = {
|
|
1942
|
+
value: data[key],
|
|
1943
|
+
...metadata[key],
|
|
1944
|
+
};
|
|
1945
|
+
}
|
|
1946
|
+
else {
|
|
1947
|
+
flag = {
|
|
1948
|
+
value: data[key],
|
|
1949
|
+
version: 0,
|
|
1950
|
+
};
|
|
1951
|
+
}
|
|
1952
|
+
ret[key] = {
|
|
1953
|
+
version: flag.version,
|
|
1954
|
+
flag,
|
|
1955
|
+
};
|
|
1956
|
+
}
|
|
1957
|
+
});
|
|
1958
|
+
return ret;
|
|
1982
1959
|
}
|
|
1983
1960
|
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1961
|
+
function createDataSourceEventHandler(flagManager, statusManager, logger) {
|
|
1962
|
+
return {
|
|
1963
|
+
async handlePut(context, flags) {
|
|
1964
|
+
logger.debug(`Got PUT: ${Object.keys(flags)}`);
|
|
1965
|
+
// mapping flags to item descriptors
|
|
1966
|
+
const descriptors = Object.entries(flags).reduce((acc, [key, flag]) => {
|
|
1967
|
+
acc[key] = { version: flag.version, flag };
|
|
1968
|
+
return acc;
|
|
1969
|
+
}, {});
|
|
1970
|
+
await flagManager.init(context, descriptors);
|
|
1971
|
+
statusManager.requestStateUpdate('VALID');
|
|
1972
|
+
},
|
|
1973
|
+
async handlePatch(context, patchFlag) {
|
|
1974
|
+
logger.debug(`Got PATCH ${JSON.stringify(patchFlag, null, 2)}`);
|
|
1975
|
+
flagManager.upsert(context, patchFlag.key, {
|
|
1976
|
+
version: patchFlag.version,
|
|
1977
|
+
flag: patchFlag,
|
|
1978
|
+
});
|
|
1979
|
+
},
|
|
1980
|
+
async handleDelete(context, deleteFlag) {
|
|
1981
|
+
logger.debug(`Got DELETE ${JSON.stringify(deleteFlag, null, 2)}`);
|
|
1982
|
+
flagManager.upsert(context, deleteFlag.key, {
|
|
1983
|
+
version: deleteFlag.version,
|
|
1984
|
+
flag: {
|
|
1985
|
+
...deleteFlag,
|
|
1986
|
+
deleted: true,
|
|
1987
|
+
// props below are set to sensible defaults. they are irrelevant
|
|
1988
|
+
// because this flag has been deleted.
|
|
1989
|
+
flagVersion: 0,
|
|
1990
|
+
value: undefined,
|
|
1991
|
+
variation: 0,
|
|
1992
|
+
trackEvents: false,
|
|
1993
|
+
},
|
|
1994
|
+
});
|
|
1995
|
+
},
|
|
1996
|
+
handleStreamingError(error) {
|
|
1997
|
+
statusManager.reportError(error.kind, error.message, error.code, error.recoverable);
|
|
1998
|
+
},
|
|
1999
|
+
handlePollingError(error) {
|
|
2000
|
+
statusManager.reportError(error.kind, error.message, error.status, error.recoverable);
|
|
2001
|
+
},
|
|
2002
|
+
};
|
|
2003
|
+
}
|
|
2004
|
+
|
|
2005
|
+
function createDataSourceStatusManager(emitter, timeStamper = () => Date.now()) {
|
|
2006
|
+
let state = 'CLOSED';
|
|
2007
|
+
let stateSinceMillis = timeStamper();
|
|
2008
|
+
let errorInfo;
|
|
2009
|
+
function getStatus() {
|
|
1995
2010
|
return {
|
|
1996
|
-
state
|
|
1997
|
-
stateSince:
|
|
1998
|
-
lastError:
|
|
2011
|
+
state,
|
|
2012
|
+
stateSince: stateSinceMillis,
|
|
2013
|
+
lastError: errorInfo,
|
|
1999
2014
|
};
|
|
2000
2015
|
}
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
* @param requestedState to track
|
|
2005
|
-
* @param isError to indicate that the state update is a result of an error occurring.
|
|
2006
|
-
*/
|
|
2007
|
-
_updateState(requestedState, isError = false) {
|
|
2008
|
-
const newState = requestedState === DataSourceState.Interrupted && this._state === DataSourceState.Initializing // don't go to interrupted from initializing (recoverable errors when initializing are not noteworthy)
|
|
2009
|
-
? DataSourceState.Initializing
|
|
2016
|
+
function updateState(requestedState, isError = false) {
|
|
2017
|
+
const newState = requestedState === 'INTERRUPTED' && state === 'INITIALIZING' // don't go to interrupted from initializing (recoverable errors when initializing are not noteworthy)
|
|
2018
|
+
? 'INITIALIZING'
|
|
2010
2019
|
: requestedState;
|
|
2011
|
-
const changedState =
|
|
2020
|
+
const changedState = state !== newState;
|
|
2012
2021
|
if (changedState) {
|
|
2013
|
-
|
|
2014
|
-
|
|
2022
|
+
state = newState;
|
|
2023
|
+
stateSinceMillis = timeStamper();
|
|
2015
2024
|
}
|
|
2016
2025
|
if (changedState || isError) {
|
|
2017
|
-
|
|
2026
|
+
emitter.emit('dataSourceStatus', getStatus());
|
|
2018
2027
|
}
|
|
2019
2028
|
}
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
message,
|
|
2042
|
-
statusCode,
|
|
2043
|
-
time: this._timeStamper(),
|
|
2044
|
-
};
|
|
2045
|
-
this._errorInfo = errorInfo;
|
|
2046
|
-
this._updateState(recoverable ? DataSourceState.Interrupted : DataSourceState.Closed, true);
|
|
2047
|
-
}
|
|
2029
|
+
return {
|
|
2030
|
+
get status() {
|
|
2031
|
+
return getStatus();
|
|
2032
|
+
},
|
|
2033
|
+
requestStateUpdate(requestedState) {
|
|
2034
|
+
updateState(requestedState);
|
|
2035
|
+
},
|
|
2036
|
+
reportError(kind, message, statusCode, recoverable = false) {
|
|
2037
|
+
errorInfo = {
|
|
2038
|
+
kind,
|
|
2039
|
+
message,
|
|
2040
|
+
statusCode,
|
|
2041
|
+
time: timeStamper(),
|
|
2042
|
+
};
|
|
2043
|
+
updateState(recoverable ? 'INTERRUPTED' : 'CLOSED', true);
|
|
2044
|
+
},
|
|
2045
|
+
// TODO: SDK-702 - Implement network availability behaviors
|
|
2046
|
+
// setNetworkUnavailable() {
|
|
2047
|
+
// updateState(DataSourceState.NetworkUnavailable);
|
|
2048
|
+
// },
|
|
2049
|
+
};
|
|
2048
2050
|
}
|
|
2049
2051
|
|
|
2050
2052
|
function reportClosed(logger) {
|
|
@@ -2326,8 +2328,8 @@ class BaseDataManager {
|
|
|
2326
2328
|
this.diagnosticsManager = diagnosticsManager;
|
|
2327
2329
|
this.closed = false;
|
|
2328
2330
|
this.logger = config.logger;
|
|
2329
|
-
this.dataSourceStatusManager =
|
|
2330
|
-
this._dataSourceEventHandler =
|
|
2331
|
+
this.dataSourceStatusManager = createDataSourceStatusManager(emitter);
|
|
2332
|
+
this._dataSourceEventHandler = createDataSourceEventHandler(flagManager, this.dataSourceStatusManager, this.config.logger);
|
|
2331
2333
|
}
|
|
2332
2334
|
/**
|
|
2333
2335
|
* Set additional connection parameters for requests polling/streaming.
|
|
@@ -2390,16 +2392,16 @@ class BaseDataManager {
|
|
|
2390
2392
|
return {
|
|
2391
2393
|
start: () => {
|
|
2392
2394
|
// update status before starting processor to ensure potential errors are reported after initializing
|
|
2393
|
-
statusManager.requestStateUpdate(
|
|
2395
|
+
statusManager.requestStateUpdate('INITIALIZING');
|
|
2394
2396
|
processor.start();
|
|
2395
2397
|
},
|
|
2396
2398
|
stop: () => {
|
|
2397
2399
|
processor.stop();
|
|
2398
|
-
statusManager.requestStateUpdate(
|
|
2400
|
+
statusManager.requestStateUpdate('CLOSED');
|
|
2399
2401
|
},
|
|
2400
2402
|
close: () => {
|
|
2401
2403
|
processor.close();
|
|
2402
|
-
statusManager.requestStateUpdate(
|
|
2404
|
+
statusManager.requestStateUpdate('CLOSED');
|
|
2403
2405
|
},
|
|
2404
2406
|
};
|
|
2405
2407
|
}
|
|
@@ -2409,5 +2411,5 @@ class BaseDataManager {
|
|
|
2409
2411
|
}
|
|
2410
2412
|
}
|
|
2411
2413
|
|
|
2412
|
-
export { BaseDataManager, DataSourceState, LDClientImpl,
|
|
2414
|
+
export { BaseDataManager, DataSourceState, LDClientImpl, makeRequestor, readFlagsFromBootstrap, safeRegisterDebugOverridePlugins };
|
|
2413
2415
|
//# sourceMappingURL=index.mjs.map
|