@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.
Files changed (62) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/cjs/DataManager.d.ts +2 -2
  3. package/dist/cjs/DataManager.d.ts.map +1 -1
  4. package/dist/cjs/LDClientImpl.d.ts +3 -3
  5. package/dist/cjs/LDClientImpl.d.ts.map +1 -1
  6. package/dist/cjs/api/LDClient.d.ts +3 -2
  7. package/dist/cjs/api/LDClient.d.ts.map +1 -1
  8. package/dist/cjs/api/LDContext.d.ts +64 -0
  9. package/dist/cjs/api/LDContext.d.ts.map +1 -0
  10. package/dist/cjs/api/LDEvaluationDetail.d.ts +2 -2
  11. package/dist/cjs/api/LDEvaluationDetail.d.ts.map +1 -1
  12. package/dist/cjs/api/index.d.ts +1 -0
  13. package/dist/cjs/api/index.d.ts.map +1 -1
  14. package/dist/cjs/context/ensureKey.d.ts +3 -2
  15. package/dist/cjs/context/ensureKey.d.ts.map +1 -1
  16. package/dist/cjs/datasource/DataSourceEventHandler.d.ts +4 -6
  17. package/dist/cjs/datasource/DataSourceEventHandler.d.ts.map +1 -1
  18. package/dist/cjs/datasource/DataSourceStatus.d.ts +64 -14
  19. package/dist/cjs/datasource/DataSourceStatus.d.ts.map +1 -1
  20. package/dist/cjs/datasource/DataSourceStatusManager.d.ts +6 -17
  21. package/dist/cjs/datasource/DataSourceStatusManager.d.ts.map +1 -1
  22. package/dist/cjs/datasource/Requestor.d.ts +2 -9
  23. package/dist/cjs/datasource/Requestor.d.ts.map +1 -1
  24. package/dist/cjs/flag-manager/bootstrap.d.ts +6 -0
  25. package/dist/cjs/flag-manager/bootstrap.d.ts.map +1 -0
  26. package/dist/cjs/index.cjs +157 -154
  27. package/dist/cjs/index.cjs.map +1 -1
  28. package/dist/cjs/index.d.ts +3 -2
  29. package/dist/cjs/index.d.ts.map +1 -1
  30. package/dist/cjs/streaming/StreamingProcessor.d.ts +1 -1
  31. package/dist/cjs/streaming/StreamingProcessor.d.ts.map +1 -1
  32. package/dist/esm/DataManager.d.ts +2 -2
  33. package/dist/esm/DataManager.d.ts.map +1 -1
  34. package/dist/esm/LDClientImpl.d.ts +3 -3
  35. package/dist/esm/LDClientImpl.d.ts.map +1 -1
  36. package/dist/esm/api/LDClient.d.ts +3 -2
  37. package/dist/esm/api/LDClient.d.ts.map +1 -1
  38. package/dist/esm/api/LDContext.d.ts +64 -0
  39. package/dist/esm/api/LDContext.d.ts.map +1 -0
  40. package/dist/esm/api/LDEvaluationDetail.d.ts +2 -2
  41. package/dist/esm/api/LDEvaluationDetail.d.ts.map +1 -1
  42. package/dist/esm/api/index.d.ts +1 -0
  43. package/dist/esm/api/index.d.ts.map +1 -1
  44. package/dist/esm/context/ensureKey.d.ts +3 -2
  45. package/dist/esm/context/ensureKey.d.ts.map +1 -1
  46. package/dist/esm/datasource/DataSourceEventHandler.d.ts +4 -6
  47. package/dist/esm/datasource/DataSourceEventHandler.d.ts.map +1 -1
  48. package/dist/esm/datasource/DataSourceStatus.d.ts +64 -14
  49. package/dist/esm/datasource/DataSourceStatus.d.ts.map +1 -1
  50. package/dist/esm/datasource/DataSourceStatusManager.d.ts +6 -17
  51. package/dist/esm/datasource/DataSourceStatusManager.d.ts.map +1 -1
  52. package/dist/esm/datasource/Requestor.d.ts +2 -9
  53. package/dist/esm/datasource/Requestor.d.ts.map +1 -1
  54. package/dist/esm/flag-manager/bootstrap.d.ts +6 -0
  55. package/dist/esm/flag-manager/bootstrap.d.ts.map +1 -0
  56. package/dist/esm/index.d.ts +3 -2
  57. package/dist/esm/index.d.ts.map +1 -1
  58. package/dist/esm/index.mjs +156 -154
  59. package/dist/esm/index.mjs.map +1 -1
  60. package/dist/esm/streaming/StreamingProcessor.d.ts +1 -1
  61. package/dist/esm/streaming/StreamingProcessor.d.ts.map +1 -1
  62. package/package.json +1 -1
@@ -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
- var DataSourceState;
7
- (function (DataSourceState) {
8
- DataSourceState["Initializing"] = "INITIALIZING";
9
- DataSourceState["Valid"] = "VALID";
10
- DataSourceState["Interrupted"] = "INTERRUPTED";
11
- DataSourceState["SetOffline"] = "SET_OFFLINE";
12
- DataSourceState["Closed"] = "CLOSED";
13
- // TODO: SDK-702 - Implement network availability behaviors
14
- // NetworkUnavailable,
15
- })(DataSourceState || (DataSourceState = {}));
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 new Requestor(requests, uri, headers, method, body);
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: reason ?? null,
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
- class DataSourceEventHandler {
1938
- constructor(_flagManager, _statusManager, _logger) {
1939
- this._flagManager = _flagManager;
1940
- this._statusManager = _statusManager;
1941
- this._logger = _logger;
1942
- }
1943
- async handlePut(context, flags) {
1944
- this._logger.debug(`Got PUT: ${Object.keys(flags)}`);
1945
- // mapping flags to item descriptors
1946
- const descriptors = Object.entries(flags).reduce((acc, [key, flag]) => {
1947
- acc[key] = { version: flag.version, flag };
1948
- return acc;
1949
- }, {});
1950
- await this._flagManager.init(context, descriptors);
1951
- this._statusManager.requestStateUpdate(DataSourceState.Valid);
1952
- }
1953
- async handlePatch(context, patchFlag) {
1954
- this._logger.debug(`Got PATCH ${JSON.stringify(patchFlag, null, 2)}`);
1955
- this._flagManager.upsert(context, patchFlag.key, {
1956
- version: patchFlag.version,
1957
- flag: patchFlag,
1958
- });
1959
- }
1960
- async handleDelete(context, deleteFlag) {
1961
- this._logger.debug(`Got DELETE ${JSON.stringify(deleteFlag, null, 2)}`);
1962
- this._flagManager.upsert(context, deleteFlag.key, {
1963
- version: deleteFlag.version,
1964
- flag: {
1965
- ...deleteFlag,
1966
- deleted: true,
1967
- // props below are set to sensible defaults. they are irrelevant
1968
- // because this flag has been deleted.
1969
- flagVersion: 0,
1970
- value: undefined,
1971
- variation: 0,
1972
- trackEvents: false,
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
- * Tracks the current data source status and emits updates when the status changes.
1986
- */
1987
- class DataSourceStatusManager {
1988
- constructor(_emitter, timeStamper = () => Date.now()) {
1989
- this._emitter = _emitter;
1990
- this._state = DataSourceState.Closed;
1991
- this._stateSinceMillis = timeStamper();
1992
- this._timeStamper = timeStamper;
1993
- }
1994
- get status() {
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: this._state,
1997
- stateSince: this._stateSinceMillis,
1998
- lastError: this._errorInfo,
2011
+ state,
2012
+ stateSince: stateSinceMillis,
2013
+ lastError: errorInfo,
1999
2014
  };
2000
2015
  }
2001
- /**
2002
- * Updates the state of the manager.
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 = this._state !== newState;
2020
+ const changedState = state !== newState;
2012
2021
  if (changedState) {
2013
- this._state = newState;
2014
- this._stateSinceMillis = this._timeStamper();
2022
+ state = newState;
2023
+ stateSinceMillis = timeStamper();
2015
2024
  }
2016
2025
  if (changedState || isError) {
2017
- this._emitter.emit('dataSourceStatus', this.status);
2026
+ emitter.emit('dataSourceStatus', getStatus());
2018
2027
  }
2019
2028
  }
2020
- /**
2021
- * Requests the manager move to the provided state. This request may be ignored
2022
- * if the current state cannot transition to the requested state.
2023
- * @param state that is requested
2024
- */
2025
- requestStateUpdate(state) {
2026
- this._updateState(state);
2027
- }
2028
- /**
2029
- * Reports a datasource error to this manager. Since the {@link DataSourceStatus} includes error
2030
- * information, it is possible that that a {@link DataSourceStatus} update is emitted with
2031
- * the same {@link DataSourceState}.
2032
- *
2033
- * @param kind of the error
2034
- * @param message for the error
2035
- * @param statusCode of the error if there was one
2036
- * @param recoverable to indicate that the error is anticipated to be recoverable
2037
- */
2038
- reportError(kind, message, statusCode, recoverable = false) {
2039
- const errorInfo = {
2040
- kind,
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 = new DataSourceStatusManager(emitter);
2330
- this._dataSourceEventHandler = new DataSourceEventHandler(flagManager, this.dataSourceStatusManager, this.config.logger);
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(DataSourceState.Initializing);
2395
+ statusManager.requestStateUpdate('INITIALIZING');
2394
2396
  processor.start();
2395
2397
  },
2396
2398
  stop: () => {
2397
2399
  processor.stop();
2398
- statusManager.requestStateUpdate(DataSourceState.Closed);
2400
+ statusManager.requestStateUpdate('CLOSED');
2399
2401
  },
2400
2402
  close: () => {
2401
2403
  processor.close();
2402
- statusManager.requestStateUpdate(DataSourceState.Closed);
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, Requestor, makeRequestor, safeRegisterDebugOverridePlugins };
2414
+ export { BaseDataManager, DataSourceState, LDClientImpl, makeRequestor, readFlagsFromBootstrap, safeRegisterDebugOverridePlugins };
2413
2415
  //# sourceMappingURL=index.mjs.map