@launchdarkly/js-client-sdk-common 1.9.0 → 1.9.1-beta.2

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 (215) hide show
  1. package/dist/{DataManager.d.ts → cjs/DataManager.d.ts} +6 -5
  2. package/dist/cjs/DataManager.d.ts.map +1 -0
  3. package/dist/{HookRunner.d.ts → cjs/HookRunner.d.ts} +3 -3
  4. package/dist/{HookRunner.d.ts.map → cjs/HookRunner.d.ts.map} +1 -1
  5. package/dist/{LDClientImpl.d.ts → cjs/LDClientImpl.d.ts} +19 -17
  6. package/dist/cjs/LDClientImpl.d.ts.map +1 -0
  7. package/dist/{LDEmitter.d.ts → cjs/LDEmitter.d.ts} +4 -4
  8. package/dist/{LDEmitter.d.ts.map → cjs/LDEmitter.d.ts.map} +1 -1
  9. package/dist/{api → cjs/api}/LDClient.d.ts +1 -1
  10. package/dist/{api → cjs/api}/LDClient.d.ts.map +1 -1
  11. package/dist/cjs/api/LDInspection.d.ts +105 -0
  12. package/dist/cjs/api/LDInspection.d.ts.map +1 -0
  13. package/dist/{api → cjs/api}/LDOptions.d.ts +12 -2
  14. package/dist/cjs/api/LDOptions.d.ts.map +1 -0
  15. package/dist/{configuration → cjs/configuration}/Configuration.d.ts +4 -1
  16. package/dist/cjs/configuration/Configuration.d.ts.map +1 -0
  17. package/dist/{configuration → cjs/configuration}/validators.d.ts.map +1 -1
  18. package/dist/{context → cjs/context}/addAutoEnv.d.ts +2 -2
  19. package/dist/cjs/context/addAutoEnv.d.ts.map +1 -0
  20. package/dist/{context → cjs/context}/ensureKey.d.ts +1 -1
  21. package/dist/{context → cjs/context}/ensureKey.d.ts.map +1 -1
  22. package/dist/{streaming → cjs/datasource}/DataSourceConfig.d.ts +1 -0
  23. package/dist/cjs/datasource/DataSourceConfig.d.ts.map +1 -0
  24. package/dist/{datasource → cjs/datasource}/DataSourceEventHandler.d.ts +4 -4
  25. package/dist/{datasource → cjs/datasource}/DataSourceEventHandler.d.ts.map +1 -1
  26. package/dist/{datasource → cjs/datasource}/DataSourceStatusManager.d.ts +7 -7
  27. package/dist/cjs/datasource/DataSourceStatusManager.d.ts.map +1 -0
  28. package/dist/cjs/datasource/Requestor.d.ts +26 -0
  29. package/dist/cjs/datasource/Requestor.d.ts.map +1 -0
  30. package/dist/{evaluation → cjs/evaluation}/evaluationDetail.d.ts.map +1 -1
  31. package/dist/{flag-manager → cjs/flag-manager}/FlagManager.d.ts +4 -5
  32. package/dist/{flag-manager → cjs/flag-manager}/FlagManager.d.ts.map +1 -1
  33. package/dist/{flag-manager → cjs/flag-manager}/FlagPersistence.d.ts +13 -13
  34. package/dist/cjs/flag-manager/FlagPersistence.d.ts.map +1 -0
  35. package/dist/{flag-manager → cjs/flag-manager}/FlagStore.d.ts +1 -1
  36. package/dist/{flag-manager → cjs/flag-manager}/FlagStore.d.ts.map +1 -1
  37. package/dist/{flag-manager → cjs/flag-manager}/FlagUpdater.d.ts +6 -5
  38. package/dist/cjs/flag-manager/FlagUpdater.d.ts.map +1 -0
  39. package/dist/{index.cjs → cjs/index.cjs} +581 -374
  40. package/dist/cjs/index.cjs.map +1 -0
  41. package/dist/{index.d.ts → cjs/index.d.ts} +2 -2
  42. package/dist/cjs/index.d.ts.map +1 -0
  43. package/dist/cjs/inspection/InspectorManager.d.ts +41 -0
  44. package/dist/cjs/inspection/InspectorManager.d.ts.map +1 -0
  45. package/dist/cjs/inspection/createSafeInspector.d.ts +8 -0
  46. package/dist/cjs/inspection/createSafeInspector.d.ts.map +1 -0
  47. package/dist/cjs/inspection/getInspectorHook.d.ts +4 -0
  48. package/dist/cjs/inspection/getInspectorHook.d.ts.map +1 -0
  49. package/dist/cjs/inspection/messages.d.ts +3 -0
  50. package/dist/cjs/inspection/messages.d.ts.map +1 -0
  51. package/dist/cjs/package.json +1 -0
  52. package/dist/{polling → cjs/polling}/PollingProcessor.d.ts.map +1 -1
  53. package/dist/cjs/streaming/StreamingProcessor.d.ts +35 -0
  54. package/dist/cjs/streaming/StreamingProcessor.d.ts.map +1 -0
  55. package/dist/{streaming → cjs/streaming}/index.d.ts +1 -1
  56. package/dist/{streaming → cjs/streaming}/index.d.ts.map +1 -1
  57. package/dist/{types → cjs/types}/index.d.ts +1 -0
  58. package/dist/{types → cjs/types}/index.d.ts.map +1 -1
  59. package/dist/esm/DataManager.d.ts +65 -0
  60. package/dist/esm/DataManager.d.ts.map +1 -0
  61. package/dist/esm/HookRunner.d.ts +12 -0
  62. package/dist/esm/HookRunner.d.ts.map +1 -0
  63. package/dist/esm/LDClientImpl.d.ts +84 -0
  64. package/dist/esm/LDClientImpl.d.ts.map +1 -0
  65. package/dist/esm/LDEmitter.d.ts +32 -0
  66. package/dist/esm/LDEmitter.d.ts.map +1 -0
  67. package/dist/esm/api/ConnectionMode.d.ts +16 -0
  68. package/dist/esm/api/ConnectionMode.d.ts.map +1 -0
  69. package/dist/esm/api/LDClient.d.ts +315 -0
  70. package/dist/esm/api/LDClient.d.ts.map +1 -0
  71. package/dist/esm/api/LDEvaluationDetail.d.ts +26 -0
  72. package/dist/esm/api/LDEvaluationDetail.d.ts.map +1 -0
  73. package/dist/esm/api/LDIdentifyOptions.d.ts +23 -0
  74. package/dist/esm/api/LDIdentifyOptions.d.ts.map +1 -0
  75. package/dist/esm/api/LDInspection.d.ts +105 -0
  76. package/dist/esm/api/LDInspection.d.ts.map +1 -0
  77. package/dist/esm/api/LDOptions.d.ts +246 -0
  78. package/dist/esm/api/LDOptions.d.ts.map +1 -0
  79. package/dist/esm/api/index.d.ts +8 -0
  80. package/dist/esm/api/index.d.ts.map +1 -0
  81. package/dist/esm/api/integrations/Hooks.d.ts +133 -0
  82. package/dist/esm/api/integrations/Hooks.d.ts.map +1 -0
  83. package/dist/esm/api/integrations/index.d.ts +2 -0
  84. package/dist/esm/api/integrations/index.d.ts.map +1 -0
  85. package/dist/esm/configuration/Configuration.d.ts +86 -0
  86. package/dist/esm/configuration/Configuration.d.ts.map +1 -0
  87. package/dist/esm/configuration/index.d.ts +3 -0
  88. package/dist/esm/configuration/index.d.ts.map +1 -0
  89. package/dist/esm/configuration/validators.d.ts +5 -0
  90. package/dist/esm/configuration/validators.d.ts.map +1 -0
  91. package/dist/esm/context/addAutoEnv.d.ts +31 -0
  92. package/dist/esm/context/addAutoEnv.d.ts.map +1 -0
  93. package/dist/esm/context/ensureKey.d.ts +10 -0
  94. package/dist/esm/context/ensureKey.d.ts.map +1 -0
  95. package/dist/esm/crypto/digest.d.ts +3 -0
  96. package/dist/esm/crypto/digest.d.ts.map +1 -0
  97. package/dist/esm/datasource/DataSourceConfig.d.ts +25 -0
  98. package/dist/esm/datasource/DataSourceConfig.d.ts.map +1 -0
  99. package/dist/esm/datasource/DataSourceEventHandler.d.ts +16 -0
  100. package/dist/esm/datasource/DataSourceEventHandler.d.ts.map +1 -0
  101. package/dist/esm/datasource/DataSourceStatus.d.ts +39 -0
  102. package/dist/esm/datasource/DataSourceStatus.d.ts.map +1 -0
  103. package/dist/esm/datasource/DataSourceStatusErrorInfo.d.ts +8 -0
  104. package/dist/esm/datasource/DataSourceStatusErrorInfo.d.ts.map +1 -0
  105. package/dist/esm/datasource/DataSourceStatusManager.d.ts +40 -0
  106. package/dist/esm/datasource/DataSourceStatusManager.d.ts.map +1 -0
  107. package/dist/esm/datasource/Requestor.d.ts +26 -0
  108. package/dist/esm/datasource/Requestor.d.ts.map +1 -0
  109. package/dist/esm/diagnostics/createDiagnosticsInitConfig.d.ts +16 -0
  110. package/dist/esm/diagnostics/createDiagnosticsInitConfig.d.ts.map +1 -0
  111. package/dist/esm/diagnostics/createDiagnosticsManager.d.ts +5 -0
  112. package/dist/esm/diagnostics/createDiagnosticsManager.d.ts.map +1 -0
  113. package/dist/esm/evaluation/evaluationDetail.d.ts +5 -0
  114. package/dist/esm/evaluation/evaluationDetail.d.ts.map +1 -0
  115. package/dist/esm/events/EventFactory.d.ts +2 -0
  116. package/dist/esm/events/EventFactory.d.ts.map +1 -0
  117. package/dist/esm/events/createEventProcessor.d.ts +5 -0
  118. package/dist/esm/events/createEventProcessor.d.ts.map +1 -0
  119. package/dist/esm/flag-manager/ContextIndex.d.ts +39 -0
  120. package/dist/esm/flag-manager/ContextIndex.d.ts.map +1 -0
  121. package/dist/esm/flag-manager/FlagManager.d.ts +81 -0
  122. package/dist/esm/flag-manager/FlagManager.d.ts.map +1 -0
  123. package/dist/esm/flag-manager/FlagPersistence.d.ts +43 -0
  124. package/dist/esm/flag-manager/FlagPersistence.d.ts.map +1 -0
  125. package/dist/esm/flag-manager/FlagStore.d.ts +29 -0
  126. package/dist/esm/flag-manager/FlagStore.d.ts.map +1 -0
  127. package/dist/esm/flag-manager/FlagUpdater.d.ts +40 -0
  128. package/dist/esm/flag-manager/FlagUpdater.d.ts.map +1 -0
  129. package/dist/esm/flag-manager/ItemDescriptor.d.ts +10 -0
  130. package/dist/esm/flag-manager/ItemDescriptor.d.ts.map +1 -0
  131. package/dist/esm/flag-manager/calculateChangedKeys.d.ts +6 -0
  132. package/dist/esm/flag-manager/calculateChangedKeys.d.ts.map +1 -0
  133. package/dist/esm/index.d.ts +20 -0
  134. package/dist/esm/index.d.ts.map +1 -0
  135. package/dist/{index.mjs → esm/index.mjs} +582 -376
  136. package/dist/esm/index.mjs.map +1 -0
  137. package/dist/esm/inspection/InspectorManager.d.ts +41 -0
  138. package/dist/esm/inspection/InspectorManager.d.ts.map +1 -0
  139. package/dist/esm/inspection/createSafeInspector.d.ts +8 -0
  140. package/dist/esm/inspection/createSafeInspector.d.ts.map +1 -0
  141. package/dist/esm/inspection/getInspectorHook.d.ts +4 -0
  142. package/dist/esm/inspection/getInspectorHook.d.ts.map +1 -0
  143. package/dist/esm/inspection/messages.d.ts +3 -0
  144. package/dist/esm/inspection/messages.d.ts.map +1 -0
  145. package/dist/esm/package.json +1 -0
  146. package/dist/esm/polling/PollingProcessor.d.ts +3 -0
  147. package/dist/esm/polling/PollingProcessor.d.ts.map +1 -0
  148. package/dist/esm/storage/getOrGenerateKey.d.ts +11 -0
  149. package/dist/esm/storage/getOrGenerateKey.d.ts.map +1 -0
  150. package/dist/esm/storage/namespaceUtils.d.ts +20 -0
  151. package/dist/esm/storage/namespaceUtils.d.ts.map +1 -0
  152. package/dist/esm/streaming/StreamingProcessor.d.ts +35 -0
  153. package/dist/esm/streaming/StreamingProcessor.d.ts.map +1 -0
  154. package/dist/esm/streaming/index.d.ts +4 -0
  155. package/dist/esm/streaming/index.d.ts.map +1 -0
  156. package/dist/esm/types/index.d.ts +21 -0
  157. package/dist/esm/types/index.d.ts.map +1 -0
  158. package/package.json +16 -8
  159. package/dist/DataManager.d.ts.map +0 -1
  160. package/dist/LDClientImpl.d.ts.map +0 -1
  161. package/dist/api/LDOptions.d.ts.map +0 -1
  162. package/dist/configuration/Configuration.d.ts.map +0 -1
  163. package/dist/context/addAutoEnv.d.ts.map +0 -1
  164. package/dist/datasource/DataSourceStatusManager.d.ts.map +0 -1
  165. package/dist/flag-manager/FlagPersistence.d.ts.map +0 -1
  166. package/dist/flag-manager/FlagUpdater.d.ts.map +0 -1
  167. package/dist/index.cjs.map +0 -1
  168. package/dist/index.d.ts.map +0 -1
  169. package/dist/index.mjs.map +0 -1
  170. package/dist/polling/Requestor.d.ts +0 -21
  171. package/dist/polling/Requestor.d.ts.map +0 -1
  172. package/dist/streaming/DataSourceConfig.d.ts.map +0 -1
  173. package/dist/streaming/StreamingProcessor.d.ts +0 -33
  174. package/dist/streaming/StreamingProcessor.d.ts.map +0 -1
  175. /package/dist/{api → cjs/api}/ConnectionMode.d.ts +0 -0
  176. /package/dist/{api → cjs/api}/ConnectionMode.d.ts.map +0 -0
  177. /package/dist/{api → cjs/api}/LDEvaluationDetail.d.ts +0 -0
  178. /package/dist/{api → cjs/api}/LDEvaluationDetail.d.ts.map +0 -0
  179. /package/dist/{api → cjs/api}/LDIdentifyOptions.d.ts +0 -0
  180. /package/dist/{api → cjs/api}/LDIdentifyOptions.d.ts.map +0 -0
  181. /package/dist/{api → cjs/api}/index.d.ts +0 -0
  182. /package/dist/{api → cjs/api}/index.d.ts.map +0 -0
  183. /package/dist/{api → cjs/api}/integrations/Hooks.d.ts +0 -0
  184. /package/dist/{api → cjs/api}/integrations/Hooks.d.ts.map +0 -0
  185. /package/dist/{api → cjs/api}/integrations/index.d.ts +0 -0
  186. /package/dist/{api → cjs/api}/integrations/index.d.ts.map +0 -0
  187. /package/dist/{configuration → cjs/configuration}/index.d.ts +0 -0
  188. /package/dist/{configuration → cjs/configuration}/index.d.ts.map +0 -0
  189. /package/dist/{configuration → cjs/configuration}/validators.d.ts +0 -0
  190. /package/dist/{crypto → cjs/crypto}/digest.d.ts +0 -0
  191. /package/dist/{crypto → cjs/crypto}/digest.d.ts.map +0 -0
  192. /package/dist/{datasource → cjs/datasource}/DataSourceStatus.d.ts +0 -0
  193. /package/dist/{datasource → cjs/datasource}/DataSourceStatus.d.ts.map +0 -0
  194. /package/dist/{datasource → cjs/datasource}/DataSourceStatusErrorInfo.d.ts +0 -0
  195. /package/dist/{datasource → cjs/datasource}/DataSourceStatusErrorInfo.d.ts.map +0 -0
  196. /package/dist/{diagnostics → cjs/diagnostics}/createDiagnosticsInitConfig.d.ts +0 -0
  197. /package/dist/{diagnostics → cjs/diagnostics}/createDiagnosticsInitConfig.d.ts.map +0 -0
  198. /package/dist/{diagnostics → cjs/diagnostics}/createDiagnosticsManager.d.ts +0 -0
  199. /package/dist/{diagnostics → cjs/diagnostics}/createDiagnosticsManager.d.ts.map +0 -0
  200. /package/dist/{evaluation → cjs/evaluation}/evaluationDetail.d.ts +0 -0
  201. /package/dist/{events → cjs/events}/EventFactory.d.ts +0 -0
  202. /package/dist/{events → cjs/events}/EventFactory.d.ts.map +0 -0
  203. /package/dist/{events → cjs/events}/createEventProcessor.d.ts +0 -0
  204. /package/dist/{events → cjs/events}/createEventProcessor.d.ts.map +0 -0
  205. /package/dist/{flag-manager → cjs/flag-manager}/ContextIndex.d.ts +0 -0
  206. /package/dist/{flag-manager → cjs/flag-manager}/ContextIndex.d.ts.map +0 -0
  207. /package/dist/{flag-manager → cjs/flag-manager}/ItemDescriptor.d.ts +0 -0
  208. /package/dist/{flag-manager → cjs/flag-manager}/ItemDescriptor.d.ts.map +0 -0
  209. /package/dist/{flag-manager → cjs/flag-manager}/calculateChangedKeys.d.ts +0 -0
  210. /package/dist/{flag-manager → cjs/flag-manager}/calculateChangedKeys.d.ts.map +0 -0
  211. /package/dist/{polling → cjs/polling}/PollingProcessor.d.ts +0 -0
  212. /package/dist/{storage → cjs/storage}/getOrGenerateKey.d.ts +0 -0
  213. /package/dist/{storage → cjs/storage}/getOrGenerateKey.d.ts.map +0 -0
  214. /package/dist/{storage → cjs/storage}/namespaceUtils.d.ts +0 -0
  215. /package/dist/{storage → cjs/storage}/namespaceUtils.d.ts.map +0 -0
@@ -32,6 +32,72 @@ exports.DataSourceState = void 0;
32
32
  // NetworkUnavailable,
33
33
  })(exports.DataSourceState || (exports.DataSourceState = {}));
34
34
 
35
+ // eslint-disable-next-line max-classes-per-file
36
+ function isOk(status) {
37
+ return status >= 200 && status <= 299;
38
+ }
39
+ class LDRequestError extends Error {
40
+ constructor(message, status) {
41
+ super(message);
42
+ this.status = status;
43
+ this.name = 'LaunchDarklyRequestError';
44
+ }
45
+ }
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
+ function makeRequestor(plainContextString, serviceEndpoints, paths, requests, encoding, baseHeaders, baseQueryParams, withReasons, useReport, secureModeHash) {
79
+ let body;
80
+ let method = 'GET';
81
+ const headers = { ...baseHeaders };
82
+ if (useReport) {
83
+ method = 'REPORT';
84
+ headers['content-type'] = 'application/json';
85
+ body = plainContextString; // context is in body for REPORT
86
+ }
87
+ const path = useReport
88
+ ? paths.pathReport(encoding, plainContextString)
89
+ : paths.pathGet(encoding, plainContextString);
90
+ const parameters = [...(baseQueryParams ?? [])];
91
+ if (withReasons) {
92
+ parameters.push({ key: 'withReasons', value: 'true' });
93
+ }
94
+ if (secureModeHash) {
95
+ parameters.push({ key: 'h', value: secureModeHash });
96
+ }
97
+ const uri = jsSdkCommon.getPollingUri(serviceEndpoints, path, parameters);
98
+ return new Requestor(requests, uri, headers, method, body);
99
+ }
100
+
35
101
  // eslint-disable-next-line max-classes-per-file
36
102
  const validators = {
37
103
  logger: jsSdkCommon.TypeValidators.Object,
@@ -56,6 +122,7 @@ const validators = {
56
122
  wrapperVersion: jsSdkCommon.TypeValidators.String,
57
123
  payloadFilterKey: jsSdkCommon.TypeValidators.stringMatchingRegex(/^[a-zA-Z0-9](\w|\.|-)*$/),
58
124
  hooks: jsSdkCommon.TypeValidators.createTypeArray('Hook[]', {}),
125
+ inspectors: jsSdkCommon.TypeValidators.createTypeArray('LDInspection', {}),
59
126
  };
60
127
 
61
128
  const DEFAULT_POLLING_INTERVAL = 60 * 5;
@@ -71,8 +138,13 @@ function ensureSafeLogger(logger) {
71
138
  class ConfigurationImpl {
72
139
  constructor(pristineOptions = {}, internalOptions = {}) {
73
140
  this.logger = jsSdkCommon.createSafeLogger();
141
+ // Naming conventions is not followed for these lines because the config validation
142
+ // accesses members based on the keys of the options. (sdk-763)
143
+ // eslint-disable-next-line @typescript-eslint/naming-convention
74
144
  this.baseUri = DEFAULT_POLLING;
145
+ // eslint-disable-next-line @typescript-eslint/naming-convention
75
146
  this.eventsUri = jsSdkCommon.ServiceEndpoints.DEFAULT_EVENTS;
147
+ // eslint-disable-next-line @typescript-eslint/naming-convention
76
148
  this.streamUri = DEFAULT_STREAM;
77
149
  this.maxCachedContexts = 5;
78
150
  this.capacity = 100;
@@ -89,8 +161,9 @@ class ConfigurationImpl {
89
161
  this.privateAttributes = [];
90
162
  this.pollInterval = DEFAULT_POLLING_INTERVAL;
91
163
  this.hooks = [];
164
+ this.inspectors = [];
92
165
  this.logger = ensureSafeLogger(pristineOptions.logger);
93
- const errors = this.validateTypesAndNames(pristineOptions);
166
+ const errors = this._validateTypesAndNames(pristineOptions);
94
167
  errors.forEach((e) => this.logger.warn(e));
95
168
  this.serviceEndpoints = new jsSdkCommon.ServiceEndpoints(this.streamUri, this.baseUri, this.eventsUri, internalOptions.analyticsEventPath, internalOptions.diagnosticEventPath, internalOptions.includeAuthorizationHeader, pristineOptions.payloadFilterKey);
96
169
  this.useReport = pristineOptions.useReport ?? false;
@@ -98,7 +171,7 @@ class ConfigurationImpl {
98
171
  this.userAgentHeaderName = internalOptions.userAgentHeaderName ?? 'user-agent';
99
172
  this.trackEventModifier = internalOptions.trackEventModifier ?? ((event) => event);
100
173
  }
101
- validateTypesAndNames(pristineOptions) {
174
+ _validateTypesAndNames(pristineOptions) {
102
175
  const errors = [];
103
176
  Object.entries(pristineOptions).forEach(([k, v]) => {
104
177
  const validator = validators[k];
@@ -406,11 +479,12 @@ function createErrorEvaluationDetail(errorKind, def) {
406
479
  };
407
480
  }
408
481
  function createSuccessEvaluationDetail(value, variationIndex, reason) {
409
- return {
482
+ const res = {
410
483
  value,
411
484
  variationIndex: variationIndex ?? null,
412
485
  reason: reason ?? null,
413
486
  };
487
+ return res;
414
488
  }
415
489
 
416
490
  const createEventProcessor = (clientSideID, config, platform, baseHeaders, diagnosticsManager) => {
@@ -508,23 +582,23 @@ class ContextIndex {
508
582
  * then persists changes after the updater has completed.
509
583
  */
510
584
  class FlagPersistence {
511
- constructor(platform, environmentNamespace, maxCachedContexts, flagStore, flagUpdater, logger, timeStamper = () => Date.now()) {
512
- this.platform = platform;
513
- this.environmentNamespace = environmentNamespace;
514
- this.maxCachedContexts = maxCachedContexts;
515
- this.flagStore = flagStore;
516
- this.flagUpdater = flagUpdater;
517
- this.logger = logger;
518
- this.timeStamper = timeStamper;
519
- this.indexKeyPromise = namespaceForContextIndex(this.environmentNamespace);
585
+ constructor(_platform, _environmentNamespace, _maxCachedContexts, _flagStore, _flagUpdater, _logger, _timeStamper = () => Date.now()) {
586
+ this._platform = _platform;
587
+ this._environmentNamespace = _environmentNamespace;
588
+ this._maxCachedContexts = _maxCachedContexts;
589
+ this._flagStore = _flagStore;
590
+ this._flagUpdater = _flagUpdater;
591
+ this._logger = _logger;
592
+ this._timeStamper = _timeStamper;
593
+ this._indexKeyPromise = namespaceForContextIndex(this._environmentNamespace);
520
594
  }
521
595
  /**
522
596
  * Inits flag persistence for the provided context with the provided flags. This will result
523
597
  * in the underlying {@link FlagUpdater} switching its active context.
524
598
  */
525
599
  async init(context, newFlags) {
526
- this.flagUpdater.init(context, newFlags);
527
- await this.storeCache(context);
600
+ this._flagUpdater.init(context, newFlags);
601
+ await this._storeCache(context);
528
602
  }
529
603
  /**
530
604
  * Upserts a flag into the {@link FlagUpdater} and stores that to persistence if the upsert
@@ -532,8 +606,8 @@ class FlagPersistence {
532
606
  * the active context.
533
607
  */
534
608
  async upsert(context, key, item) {
535
- if (this.flagUpdater.upsert(context, key, item)) {
536
- await this.storeCache(context);
609
+ if (this._flagUpdater.upsert(context, key, item)) {
610
+ await this._storeCache(context);
537
611
  return true;
538
612
  }
539
613
  return false;
@@ -543,19 +617,19 @@ class FlagPersistence {
543
617
  * {@link FlagUpdater} this {@link FlagPersistence} was constructed with.
544
618
  */
545
619
  async loadCached(context) {
546
- const storageKey = await namespaceForContextData(this.platform.crypto, this.environmentNamespace, context);
547
- let flagsJson = await this.platform.storage?.get(storageKey);
620
+ const storageKey = await namespaceForContextData(this._platform.crypto, this._environmentNamespace, context);
621
+ let flagsJson = await this._platform.storage?.get(storageKey);
548
622
  if (flagsJson === null || flagsJson === undefined) {
549
623
  // Fallback: in version <10.3.1 flag data was stored under the canonical key, check
550
624
  // to see if data is present and migrate the data if present.
551
- flagsJson = await this.platform.storage?.get(context.canonicalKey);
625
+ flagsJson = await this._platform.storage?.get(context.canonicalKey);
552
626
  if (flagsJson === null || flagsJson === undefined) {
553
627
  // return false indicating cache did not load if flag json is still absent
554
628
  return false;
555
629
  }
556
630
  // migrate data from version <10.3.1 and cleanup data that was under canonical key
557
- await this.platform.storage?.set(storageKey, flagsJson);
558
- await this.platform.storage?.clear(context.canonicalKey);
631
+ await this._platform.storage?.set(storageKey, flagsJson);
632
+ await this._platform.storage?.clear(context.canonicalKey);
559
633
  }
560
634
  try {
561
635
  const flags = JSON.parse(flagsJson);
@@ -564,43 +638,43 @@ class FlagPersistence {
564
638
  acc[key] = { version: flag.version, flag };
565
639
  return acc;
566
640
  }, {});
567
- this.flagUpdater.initCached(context, descriptors);
568
- this.logger.debug('Loaded cached flag evaluations from persistent storage');
641
+ this._flagUpdater.initCached(context, descriptors);
642
+ this._logger.debug('Loaded cached flag evaluations from persistent storage');
569
643
  return true;
570
644
  }
571
645
  catch (e) {
572
- this.logger.warn(`Could not load cached flag evaluations from persistent storage: ${e.message}`);
646
+ this._logger.warn(`Could not load cached flag evaluations from persistent storage: ${e.message}`);
573
647
  return false;
574
648
  }
575
649
  }
576
- async loadIndex() {
577
- if (this.contextIndex !== undefined) {
578
- return this.contextIndex;
650
+ async _loadIndex() {
651
+ if (this._contextIndex !== undefined) {
652
+ return this._contextIndex;
579
653
  }
580
- const json = await this.platform.storage?.get(await this.indexKeyPromise);
654
+ const json = await this._platform.storage?.get(await this._indexKeyPromise);
581
655
  if (!json) {
582
- this.contextIndex = new ContextIndex();
583
- return this.contextIndex;
656
+ this._contextIndex = new ContextIndex();
657
+ return this._contextIndex;
584
658
  }
585
659
  try {
586
- this.contextIndex = ContextIndex.fromJson(json);
587
- this.logger.debug('Loaded context index from persistent storage');
660
+ this._contextIndex = ContextIndex.fromJson(json);
661
+ this._logger.debug('Loaded context index from persistent storage');
588
662
  }
589
663
  catch (e) {
590
- this.logger.warn(`Could not load index from persistent storage: ${e.message}`);
591
- this.contextIndex = new ContextIndex();
664
+ this._logger.warn(`Could not load index from persistent storage: ${e.message}`);
665
+ this._contextIndex = new ContextIndex();
592
666
  }
593
- return this.contextIndex;
594
- }
595
- async storeCache(context) {
596
- const index = await this.loadIndex();
597
- const storageKey = await namespaceForContextData(this.platform.crypto, this.environmentNamespace, context);
598
- index.notice(storageKey, this.timeStamper());
599
- const pruned = index.prune(this.maxCachedContexts);
600
- await Promise.all(pruned.map(async (it) => this.platform.storage?.clear(it.id)));
667
+ return this._contextIndex;
668
+ }
669
+ async _storeCache(context) {
670
+ const index = await this._loadIndex();
671
+ const storageKey = await namespaceForContextData(this._platform.crypto, this._environmentNamespace, context);
672
+ index.notice(storageKey, this._timeStamper());
673
+ const pruned = index.prune(this._maxCachedContexts);
674
+ await Promise.all(pruned.map(async (it) => this._platform.storage?.clear(it.id)));
601
675
  // store index
602
- await this.platform.storage?.set(await this.indexKeyPromise, index.toJson());
603
- const allFlags = this.flagStore.getAll();
676
+ await this._platform.storage?.set(await this._indexKeyPromise, index.toJson());
677
+ const allFlags = this._flagStore.getAll();
604
678
  // mapping item descriptors to flags
605
679
  const flags = Object.entries(allFlags).reduce((acc, [key, descriptor]) => {
606
680
  if (descriptor.flag !== null && descriptor.flag !== undefined) {
@@ -610,7 +684,7 @@ class FlagPersistence {
610
684
  }, {});
611
685
  const jsonAll = JSON.stringify(flags);
612
686
  // store flag data
613
- await this.platform.storage?.set(storageKey, jsonAll);
687
+ await this._platform.storage?.set(storageKey, jsonAll);
614
688
  }
615
689
  }
616
690
 
@@ -619,25 +693,25 @@ class FlagPersistence {
619
693
  */
620
694
  class DefaultFlagStore {
621
695
  constructor() {
622
- this.flags = {};
696
+ this._flags = {};
623
697
  }
624
698
  init(newFlags) {
625
- this.flags = Object.entries(newFlags).reduce((acc, [key, flag]) => {
699
+ this._flags = Object.entries(newFlags).reduce((acc, [key, flag]) => {
626
700
  acc[key] = flag;
627
701
  return acc;
628
702
  }, {});
629
703
  }
630
704
  insertOrUpdate(key, update) {
631
- this.flags[key] = update;
705
+ this._flags[key] = update;
632
706
  }
633
707
  get(key) {
634
- if (Object.prototype.hasOwnProperty.call(this.flags, key)) {
635
- return this.flags[key];
708
+ if (Object.prototype.hasOwnProperty.call(this._flags, key)) {
709
+ return this._flags[key];
636
710
  }
637
711
  return undefined;
638
712
  }
639
713
  getAll() {
640
- return this.flags;
714
+ return this._flags;
641
715
  }
642
716
  }
643
717
 
@@ -666,19 +740,19 @@ function calculateChangedKeys(existingObject, newObject) {
666
740
  */
667
741
  class FlagUpdater {
668
742
  constructor(flagStore, logger) {
669
- this.changeCallbacks = new Array();
670
- this.flagStore = flagStore;
671
- this.logger = logger;
743
+ this._changeCallbacks = new Array();
744
+ this._flagStore = flagStore;
745
+ this._logger = logger;
672
746
  }
673
747
  init(context, newFlags) {
674
- this.activeContextKey = context.canonicalKey;
675
- const oldFlags = this.flagStore.getAll();
676
- this.flagStore.init(newFlags);
748
+ this._activeContextKey = context.canonicalKey;
749
+ const oldFlags = this._flagStore.getAll();
750
+ this._flagStore.init(newFlags);
677
751
  const changed = calculateChangedKeys(oldFlags, newFlags);
678
752
  if (changed.length > 0) {
679
- this.changeCallbacks.forEach((callback) => {
753
+ this._changeCallbacks.forEach((callback) => {
680
754
  try {
681
- callback(context, changed);
755
+ callback(context, changed, 'init');
682
756
  }
683
757
  catch (err) {
684
758
  /* intentionally empty */
@@ -687,25 +761,25 @@ class FlagUpdater {
687
761
  }
688
762
  }
689
763
  initCached(context, newFlags) {
690
- if (this.activeContextKey === context.canonicalKey) {
764
+ if (this._activeContextKey === context.canonicalKey) {
691
765
  return;
692
766
  }
693
767
  this.init(context, newFlags);
694
768
  }
695
769
  upsert(context, key, item) {
696
- if (this.activeContextKey !== context.canonicalKey) {
697
- this.logger.warn('Received an update for an inactive context.');
770
+ if (this._activeContextKey !== context.canonicalKey) {
771
+ this._logger.warn('Received an update for an inactive context.');
698
772
  return false;
699
773
  }
700
- const currentValue = this.flagStore.get(key);
774
+ const currentValue = this._flagStore.get(key);
701
775
  if (currentValue !== undefined && currentValue.version >= item.version) {
702
776
  // this is an out of order update that can be ignored
703
777
  return false;
704
778
  }
705
- this.flagStore.insertOrUpdate(key, item);
706
- this.changeCallbacks.forEach((callback) => {
779
+ this._flagStore.insertOrUpdate(key, item);
780
+ this._changeCallbacks.forEach((callback) => {
707
781
  try {
708
- callback(context, [key]);
782
+ callback(context, [key], 'patch');
709
783
  }
710
784
  catch (err) {
711
785
  /* intentionally empty */
@@ -714,12 +788,12 @@ class FlagUpdater {
714
788
  return true;
715
789
  }
716
790
  on(callback) {
717
- this.changeCallbacks.push(callback);
791
+ this._changeCallbacks.push(callback);
718
792
  }
719
793
  off(callback) {
720
- const index = this.changeCallbacks.indexOf(callback);
794
+ const index = this._changeCallbacks.indexOf(callback);
721
795
  if (index > -1) {
722
- this.changeCallbacks.splice(index, 1);
796
+ this._changeCallbacks.splice(index, 1);
723
797
  }
724
798
  }
725
799
  }
@@ -733,40 +807,39 @@ class DefaultFlagManager {
733
807
  * @param timeStamper exists for testing purposes
734
808
  */
735
809
  constructor(platform, sdkKey, maxCachedContexts, logger, timeStamper = () => Date.now()) {
736
- this.timeStamper = timeStamper;
737
- this.flagStore = new DefaultFlagStore();
738
- this.flagUpdater = new FlagUpdater(this.flagStore, logger);
739
- this.flagPersistencePromise = this.initPersistence(platform, sdkKey, maxCachedContexts, logger, timeStamper);
810
+ this._flagStore = new DefaultFlagStore();
811
+ this._flagUpdater = new FlagUpdater(this._flagStore, logger);
812
+ this._flagPersistencePromise = this._initPersistence(platform, sdkKey, maxCachedContexts, logger, timeStamper);
740
813
  }
741
- async initPersistence(platform, sdkKey, maxCachedContexts, logger, timeStamper = () => Date.now()) {
814
+ async _initPersistence(platform, sdkKey, maxCachedContexts, logger, timeStamper = () => Date.now()) {
742
815
  const environmentNamespace = await namespaceForEnvironment(platform.crypto, sdkKey);
743
- return new FlagPersistence(platform, environmentNamespace, maxCachedContexts, this.flagStore, this.flagUpdater, logger, timeStamper);
816
+ return new FlagPersistence(platform, environmentNamespace, maxCachedContexts, this._flagStore, this._flagUpdater, logger, timeStamper);
744
817
  }
745
818
  get(key) {
746
- return this.flagStore.get(key);
819
+ return this._flagStore.get(key);
747
820
  }
748
821
  getAll() {
749
- return this.flagStore.getAll();
822
+ return this._flagStore.getAll();
750
823
  }
751
824
  setBootstrap(context, newFlags) {
752
825
  // Bypasses the persistence as we do not want to put these flags into any cache.
753
826
  // Generally speaking persistence likely *SHOULD* be disabled when using bootstrap.
754
- this.flagUpdater.init(context, newFlags);
827
+ this._flagUpdater.init(context, newFlags);
755
828
  }
756
829
  async init(context, newFlags) {
757
- return (await this.flagPersistencePromise).init(context, newFlags);
830
+ return (await this._flagPersistencePromise).init(context, newFlags);
758
831
  }
759
832
  async upsert(context, key, item) {
760
- return (await this.flagPersistencePromise).upsert(context, key, item);
833
+ return (await this._flagPersistencePromise).upsert(context, key, item);
761
834
  }
762
835
  async loadCached(context) {
763
- return (await this.flagPersistencePromise).loadCached(context);
836
+ return (await this._flagPersistencePromise).loadCached(context);
764
837
  }
765
838
  on(callback) {
766
- this.flagUpdater.on(callback);
839
+ this._flagUpdater.on(callback);
767
840
  }
768
841
  off(callback) {
769
- this.flagUpdater.off(callback);
842
+ this._flagUpdater.off(callback);
770
843
  }
771
844
  }
772
845
 
@@ -816,39 +889,186 @@ function executeAfterIdentify(logger, hooks, hookContext, updatedData, result) {
816
889
  }
817
890
  }
818
891
  class HookRunner {
819
- constructor(logger, initialHooks) {
820
- this.logger = logger;
821
- this.hooks = [];
822
- this.hooks.push(...initialHooks);
892
+ constructor(_logger, initialHooks) {
893
+ this._logger = _logger;
894
+ this._hooks = [];
895
+ this._hooks.push(...initialHooks);
823
896
  }
824
897
  withEvaluation(key, context, defaultValue, method) {
825
- if (this.hooks.length === 0) {
898
+ if (this._hooks.length === 0) {
826
899
  return method();
827
900
  }
828
- const hooks = [...this.hooks];
901
+ const hooks = [...this._hooks];
829
902
  const hookContext = {
830
903
  flagKey: key,
831
904
  context,
832
905
  defaultValue,
833
906
  };
834
- const hookData = executeBeforeEvaluation(this.logger, hooks, hookContext);
907
+ const hookData = executeBeforeEvaluation(this._logger, hooks, hookContext);
835
908
  const result = method();
836
- executeAfterEvaluation(this.logger, hooks, hookContext, hookData, result);
909
+ executeAfterEvaluation(this._logger, hooks, hookContext, hookData, result);
837
910
  return result;
838
911
  }
839
912
  identify(context, timeout) {
840
- const hooks = [...this.hooks];
913
+ const hooks = [...this._hooks];
841
914
  const hookContext = {
842
915
  context,
843
916
  timeout,
844
917
  };
845
- const hookData = executeBeforeIdentify(this.logger, hooks, hookContext);
918
+ const hookData = executeBeforeIdentify(this._logger, hooks, hookContext);
846
919
  return (result) => {
847
- executeAfterIdentify(this.logger, hooks, hookContext, hookData, result);
920
+ executeAfterIdentify(this._logger, hooks, hookContext, hookData, result);
848
921
  };
849
922
  }
850
923
  addHook(hook) {
851
- this.hooks.push(hook);
924
+ this._hooks.push(hook);
925
+ }
926
+ }
927
+
928
+ function getInspectorHook(inspectorManager) {
929
+ return {
930
+ getMetadata() {
931
+ return {
932
+ name: 'LaunchDarkly-Inspector-Adapter',
933
+ };
934
+ },
935
+ afterEvaluation: (hookContext, data, detail) => {
936
+ inspectorManager.onFlagUsed(hookContext.flagKey, detail, hookContext.context);
937
+ return data;
938
+ },
939
+ afterIdentify(hookContext, data, _result) {
940
+ inspectorManager.onIdentityChanged(hookContext.context);
941
+ return data;
942
+ },
943
+ };
944
+ }
945
+
946
+ function invalidInspector(type, name) {
947
+ return `an inspector: "${name}" of an invalid type (${type}) was configured`;
948
+ }
949
+ function inspectorMethodError(type, name) {
950
+ return `an inspector: "${name}" of type: "${type}" generated an exception`;
951
+ }
952
+
953
+ /**
954
+ * Wrap an inspector ensuring that calling its methods are safe.
955
+ * @param inspector Inspector to wrap.
956
+ */
957
+ function createSafeInspector(inspector, logger) {
958
+ let errorLogged = false;
959
+ const wrapper = {
960
+ method: (...args) => {
961
+ try {
962
+ // We are proxying arguments here to the underlying method. Typescript doesn't care
963
+ // for this as it cannot validate the parameters are correct, but we are also the caller
964
+ // in this case and will dispatch things with the correct arguments. The dispatch to this
965
+ // will itself happen with a type guard.
966
+ // @ts-ignore
967
+ inspector.method(...args);
968
+ }
969
+ catch {
970
+ // If something goes wrong in an inspector we want to log that something
971
+ // went wrong. We don't want to flood the logs, so we only log something
972
+ // the first time that something goes wrong.
973
+ // We do not include the exception in the log, because we do not know what
974
+ // kind of data it may contain.
975
+ if (!errorLogged) {
976
+ errorLogged = true;
977
+ logger.warn(inspectorMethodError(wrapper.type, wrapper.name));
978
+ }
979
+ // Prevent errors.
980
+ }
981
+ },
982
+ type: inspector.type,
983
+ name: inspector.name,
984
+ synchronous: inspector.synchronous,
985
+ };
986
+ return wrapper;
987
+ }
988
+
989
+ const FLAG_USED_TYPE = 'flag-used';
990
+ const FLAG_DETAILS_CHANGED_TYPE = 'flag-details-changed';
991
+ const FLAG_DETAIL_CHANGED_TYPE = 'flag-detail-changed';
992
+ const IDENTITY_CHANGED_TYPE = 'client-identity-changed';
993
+ const VALID__TYPES = [
994
+ FLAG_USED_TYPE,
995
+ FLAG_DETAILS_CHANGED_TYPE,
996
+ FLAG_DETAIL_CHANGED_TYPE,
997
+ IDENTITY_CHANGED_TYPE,
998
+ ];
999
+ function validateInspector(inspector, logger) {
1000
+ const valid = VALID__TYPES.includes(inspector.type) &&
1001
+ inspector.method &&
1002
+ typeof inspector.method === 'function';
1003
+ if (!valid) {
1004
+ logger.warn(invalidInspector(inspector.type, inspector.name));
1005
+ }
1006
+ return valid;
1007
+ }
1008
+ /**
1009
+ * Manages dispatching of inspection data to registered inspectors.
1010
+ */
1011
+ class InspectorManager {
1012
+ constructor(inspectors, logger) {
1013
+ this._safeInspectors = [];
1014
+ const validInspectors = inspectors.filter((inspector) => validateInspector(inspector, logger));
1015
+ this._safeInspectors = validInspectors.map((inspector) => createSafeInspector(inspector, logger));
1016
+ }
1017
+ hasInspectors() {
1018
+ return this._safeInspectors.length !== 0;
1019
+ }
1020
+ /**
1021
+ * Notify registered inspectors of a flag being used.
1022
+ *
1023
+ * @param flagKey The key for the flag.
1024
+ * @param detail The LDEvaluationDetail for the flag.
1025
+ * @param context The LDContext for the flag.
1026
+ */
1027
+ onFlagUsed(flagKey, detail, context) {
1028
+ this._safeInspectors.forEach((inspector) => {
1029
+ if (inspector.type === FLAG_USED_TYPE) {
1030
+ inspector.method(flagKey, detail, context);
1031
+ }
1032
+ });
1033
+ }
1034
+ /**
1035
+ * Notify registered inspectors that the flags have been replaced.
1036
+ *
1037
+ * @param flags The current flags as a Record<string, LDEvaluationDetail>.
1038
+ */
1039
+ onFlagsChanged(flags) {
1040
+ this._safeInspectors.forEach((inspector) => {
1041
+ if (inspector.type === FLAG_DETAILS_CHANGED_TYPE) {
1042
+ inspector.method(flags);
1043
+ }
1044
+ });
1045
+ }
1046
+ /**
1047
+ * Notify registered inspectors that a flag value has changed.
1048
+ *
1049
+ * @param flagKey The key for the flag that changed.
1050
+ * @param flag An `LDEvaluationDetail` for the flag.
1051
+ */
1052
+ onFlagChanged(flagKey, flag) {
1053
+ this._safeInspectors.forEach((inspector) => {
1054
+ if (inspector.type === FLAG_DETAIL_CHANGED_TYPE) {
1055
+ inspector.method(flagKey, flag);
1056
+ }
1057
+ });
1058
+ }
1059
+ /**
1060
+ * Notify the registered inspectors that the context identity has changed.
1061
+ *
1062
+ * The notification itself will be dispatched asynchronously.
1063
+ *
1064
+ * @param context The `LDContext` which is now identified.
1065
+ */
1066
+ onIdentityChanged(context) {
1067
+ this._safeInspectors.forEach((inspector) => {
1068
+ if (inspector.type === IDENTITY_CHANGED_TYPE) {
1069
+ inspector.method(context);
1070
+ }
1071
+ });
852
1072
  }
853
1073
  }
854
1074
 
@@ -859,16 +1079,16 @@ class HookRunner {
859
1079
  * a system to allow listeners which have counts independent of the primary listener counts.
860
1080
  */
861
1081
  class LDEmitter {
862
- constructor(logger) {
863
- this.logger = logger;
864
- this.listeners = new Map();
1082
+ constructor(_logger) {
1083
+ this._logger = _logger;
1084
+ this._listeners = new Map();
865
1085
  }
866
1086
  on(name, listener) {
867
- if (!this.listeners.has(name)) {
868
- this.listeners.set(name, [listener]);
1087
+ if (!this._listeners.has(name)) {
1088
+ this._listeners.set(name, [listener]);
869
1089
  }
870
1090
  else {
871
- this.listeners.get(name)?.push(listener);
1091
+ this._listeners.get(name)?.push(listener);
872
1092
  }
873
1093
  }
874
1094
  /**
@@ -878,7 +1098,7 @@ class LDEmitter {
878
1098
  * @param listener Optional. If unspecified, all listeners for the event will be removed.
879
1099
  */
880
1100
  off(name, listener) {
881
- const existingListeners = this.listeners.get(name);
1101
+ const existingListeners = this._listeners.get(name);
882
1102
  if (!existingListeners) {
883
1103
  return;
884
1104
  }
@@ -886,33 +1106,33 @@ class LDEmitter {
886
1106
  // remove from internal cache
887
1107
  const updated = existingListeners.filter((fn) => fn !== listener);
888
1108
  if (updated.length === 0) {
889
- this.listeners.delete(name);
1109
+ this._listeners.delete(name);
890
1110
  }
891
1111
  else {
892
- this.listeners.set(name, updated);
1112
+ this._listeners.set(name, updated);
893
1113
  }
894
1114
  return;
895
1115
  }
896
1116
  // listener was not specified, so remove them all for that event
897
- this.listeners.delete(name);
1117
+ this._listeners.delete(name);
898
1118
  }
899
- invokeListener(listener, name, ...detail) {
1119
+ _invokeListener(listener, name, ...detail) {
900
1120
  try {
901
1121
  listener(...detail);
902
1122
  }
903
1123
  catch (err) {
904
- this.logger?.error(`Encountered error invoking handler for "${name}", detail: "${err}"`);
1124
+ this._logger?.error(`Encountered error invoking handler for "${name}", detail: "${err}"`);
905
1125
  }
906
1126
  }
907
1127
  emit(name, ...detail) {
908
- const listeners = this.listeners.get(name);
909
- listeners?.forEach((listener) => this.invokeListener(listener, name, ...detail));
1128
+ const listeners = this._listeners.get(name);
1129
+ listeners?.forEach((listener) => this._invokeListener(listener, name, ...detail));
910
1130
  }
911
1131
  eventNames() {
912
- return [...this.listeners.keys()];
1132
+ return [...this._listeners.keys()];
913
1133
  }
914
1134
  listenerCount(name) {
915
- return this.listeners.get(name)?.length ?? 0;
1135
+ return this._listeners.get(name)?.length ?? 0;
916
1136
  }
917
1137
  }
918
1138
 
@@ -925,40 +1145,45 @@ class LDClientImpl {
925
1145
  this.sdkKey = sdkKey;
926
1146
  this.autoEnvAttributes = autoEnvAttributes;
927
1147
  this.platform = platform;
928
- this.identifyTimeout = 5;
929
- this.highTimeoutThreshold = 15;
930
- this.eventFactoryDefault = new EventFactory(false);
931
- this.eventFactoryWithReasons = new EventFactory(true);
932
- this.eventSendingEnabled = false;
1148
+ this._identifyTimeout = 5;
1149
+ this._highTimeoutThreshold = 15;
1150
+ this._eventFactoryDefault = new EventFactory(false);
1151
+ this._eventFactoryWithReasons = new EventFactory(true);
1152
+ this._eventSendingEnabled = false;
933
1153
  if (!sdkKey) {
934
1154
  throw new Error('You must configure the client with a client-side SDK key');
935
1155
  }
936
1156
  if (!platform.encoding) {
937
1157
  throw new Error('Platform must implement Encoding because btoa is required.');
938
1158
  }
939
- this.config = new ConfigurationImpl(options, internalOptions);
940
- this.logger = this.config.logger;
941
- this.baseHeaders = jsSdkCommon.defaultHeaders(this.sdkKey, this.platform.info, this.config.tags, this.config.serviceEndpoints.includeAuthorizationHeader, this.config.userAgentHeaderName);
942
- this.flagManager = new DefaultFlagManager(this.platform, sdkKey, this.config.maxCachedContexts, this.config.logger);
943
- this.diagnosticsManager = createDiagnosticsManager(sdkKey, this.config, platform);
944
- this.eventProcessor = createEventProcessor(sdkKey, this.config, platform, this.baseHeaders, this.diagnosticsManager);
1159
+ this._config = new ConfigurationImpl(options, internalOptions);
1160
+ this.logger = this._config.logger;
1161
+ this._baseHeaders = jsSdkCommon.defaultHeaders(this.sdkKey, this.platform.info, this._config.tags, this._config.serviceEndpoints.includeAuthorizationHeader, this._config.userAgentHeaderName);
1162
+ this._flagManager = new DefaultFlagManager(this.platform, sdkKey, this._config.maxCachedContexts, this._config.logger);
1163
+ this._diagnosticsManager = createDiagnosticsManager(sdkKey, this._config, platform);
1164
+ this._eventProcessor = createEventProcessor(sdkKey, this._config, platform, this._baseHeaders, this._diagnosticsManager);
945
1165
  this.emitter = new LDEmitter();
946
1166
  this.emitter.on('error', (c, err) => {
947
1167
  this.logger.error(`error: ${err}, context: ${JSON.stringify(c)}`);
948
1168
  });
949
- this.flagManager.on((context, flagKeys) => {
1169
+ this._flagManager.on((context, flagKeys, type) => {
1170
+ this._handleInspectionChanged(flagKeys, type);
950
1171
  const ldContext = jsSdkCommon.Context.toLDContext(context);
951
1172
  this.emitter.emit('change', ldContext, flagKeys);
952
1173
  flagKeys.forEach((it) => {
953
1174
  this.emitter.emit(`change:${it}`, ldContext);
954
1175
  });
955
1176
  });
956
- this.dataManager = dataManagerFactory(this.flagManager, this.config, this.baseHeaders, this.emitter, this.diagnosticsManager);
957
- this.hookRunner = new HookRunner(this.logger, this.config.hooks);
1177
+ this.dataManager = dataManagerFactory(this._flagManager, this._config, this._baseHeaders, this.emitter, this._diagnosticsManager);
1178
+ this._hookRunner = new HookRunner(this.logger, this._config.hooks);
1179
+ this._inspectorManager = new InspectorManager(this._config.inspectors, this.logger);
1180
+ if (this._inspectorManager.hasInspectors()) {
1181
+ this._hookRunner.addHook(getInspectorHook(this._inspectorManager));
1182
+ }
958
1183
  }
959
1184
  allFlags() {
960
1185
  // extracting all flag values
961
- const result = Object.entries(this.flagManager.getAll()).reduce((acc, [key, descriptor]) => {
1186
+ const result = Object.entries(this._flagManager.getAll()).reduce((acc, [key, descriptor]) => {
962
1187
  if (descriptor.flag !== null && descriptor.flag !== undefined && !descriptor.flag.deleted) {
963
1188
  acc[key] = descriptor.flag.value;
964
1189
  }
@@ -968,13 +1193,13 @@ class LDClientImpl {
968
1193
  }
969
1194
  async close() {
970
1195
  await this.flush();
971
- this.eventProcessor?.close();
972
- this.updateProcessor?.close();
1196
+ this._eventProcessor?.close();
1197
+ this._updateProcessor?.close();
973
1198
  this.logger.debug('Closed event processor and data source.');
974
1199
  }
975
1200
  async flush() {
976
1201
  try {
977
- await this.eventProcessor?.flush();
1202
+ await this._eventProcessor?.flush();
978
1203
  this.logger.debug('Successfully flushed event processor.');
979
1204
  }
980
1205
  catch (e) {
@@ -989,12 +1214,12 @@ class LDClientImpl {
989
1214
  // code. We are returned the unchecked context so that if a consumer identifies with an invalid context
990
1215
  // and then calls getContext, they get back the same context they provided, without any assertion about
991
1216
  // validity.
992
- return this.uncheckedContext ? jsSdkCommon.clone(this.uncheckedContext) : undefined;
1217
+ return this._uncheckedContext ? jsSdkCommon.clone(this._uncheckedContext) : undefined;
993
1218
  }
994
1219
  getInternalContext() {
995
- return this.checkedContext;
1220
+ return this._checkedContext;
996
1221
  }
997
- createIdentifyPromise(timeout) {
1222
+ _createIdentifyPromise(timeout) {
998
1223
  let res;
999
1224
  let rej;
1000
1225
  const slow = new Promise((resolve, reject) => {
@@ -1027,16 +1252,16 @@ class LDClientImpl {
1027
1252
  */
1028
1253
  async identify(pristineContext, identifyOptions) {
1029
1254
  if (identifyOptions?.timeout) {
1030
- this.identifyTimeout = identifyOptions.timeout;
1255
+ this._identifyTimeout = identifyOptions.timeout;
1031
1256
  }
1032
- if (this.identifyTimeout > this.highTimeoutThreshold) {
1257
+ if (this._identifyTimeout > this._highTimeoutThreshold) {
1033
1258
  this.logger.warn('The identify function was called with a timeout greater than ' +
1034
- `${this.highTimeoutThreshold} seconds. We recommend a timeout of less than ` +
1035
- `${this.highTimeoutThreshold} seconds.`);
1259
+ `${this._highTimeoutThreshold} seconds. We recommend a timeout of less than ` +
1260
+ `${this._highTimeoutThreshold} seconds.`);
1036
1261
  }
1037
1262
  let context = await ensureKey(pristineContext, this.platform);
1038
1263
  if (this.autoEnvAttributes === jsSdkCommon.AutoEnvAttributes.Enabled) {
1039
- context = await addAutoEnv(context, this.platform, this.config);
1264
+ context = await addAutoEnv(context, this.platform, this._config);
1040
1265
  }
1041
1266
  const checkedContext = jsSdkCommon.Context.fromLDContext(context);
1042
1267
  if (!checkedContext.valid) {
@@ -1044,12 +1269,12 @@ class LDClientImpl {
1044
1269
  this.emitter.emit('error', context, error);
1045
1270
  return Promise.reject(error);
1046
1271
  }
1047
- this.uncheckedContext = context;
1048
- this.checkedContext = checkedContext;
1049
- this.eventProcessor?.sendEvent(this.eventFactoryDefault.identifyEvent(this.checkedContext));
1050
- const { identifyPromise, identifyResolve, identifyReject } = this.createIdentifyPromise(this.identifyTimeout);
1051
- this.logger.debug(`Identifying ${JSON.stringify(this.checkedContext)}`);
1052
- const afterIdentify = this.hookRunner.identify(context, identifyOptions?.timeout);
1272
+ this._uncheckedContext = context;
1273
+ this._checkedContext = checkedContext;
1274
+ this._eventProcessor?.sendEvent(this._eventFactoryDefault.identifyEvent(this._checkedContext));
1275
+ const { identifyPromise, identifyResolve, identifyReject } = this._createIdentifyPromise(this._identifyTimeout);
1276
+ this.logger.debug(`Identifying ${JSON.stringify(this._checkedContext)}`);
1277
+ const afterIdentify = this._hookRunner.identify(context, identifyOptions?.timeout);
1053
1278
  await this.dataManager.identify(identifyResolve, identifyReject, checkedContext, identifyOptions);
1054
1279
  return identifyPromise.then((res) => {
1055
1280
  afterIdentify({ status: 'completed' });
@@ -1066,38 +1291,38 @@ class LDClientImpl {
1066
1291
  this.emitter.off(eventName, listener);
1067
1292
  }
1068
1293
  track(key, data, metricValue) {
1069
- if (!this.checkedContext || !this.checkedContext.valid) {
1070
- this.logger.warn(ClientMessages.missingContextKeyNoEvent);
1294
+ if (!this._checkedContext || !this._checkedContext.valid) {
1295
+ this.logger.warn(ClientMessages.MissingContextKeyNoEvent);
1071
1296
  return;
1072
1297
  }
1073
1298
  // 0 is valid, so do not truthy check the metric value
1074
1299
  if (metricValue !== undefined && !jsSdkCommon.TypeValidators.Number.is(metricValue)) {
1075
1300
  this.logger?.warn(ClientMessages.invalidMetricValue(typeof metricValue));
1076
1301
  }
1077
- this.eventProcessor?.sendEvent(this.config.trackEventModifier(this.eventFactoryDefault.customEvent(key, this.checkedContext, data, metricValue)));
1302
+ this._eventProcessor?.sendEvent(this._config.trackEventModifier(this._eventFactoryDefault.customEvent(key, this._checkedContext, data, metricValue)));
1078
1303
  }
1079
- variationInternal(flagKey, defaultValue, eventFactory, typeChecker) {
1080
- if (!this.uncheckedContext) {
1081
- this.logger.debug(ClientMessages.missingContextKeyNoEvent);
1304
+ _variationInternal(flagKey, defaultValue, eventFactory, typeChecker) {
1305
+ if (!this._uncheckedContext) {
1306
+ this.logger.debug(ClientMessages.MissingContextKeyNoEvent);
1082
1307
  return createErrorEvaluationDetail(ErrorKinds.UserNotSpecified, defaultValue);
1083
1308
  }
1084
- const evalContext = jsSdkCommon.Context.fromLDContext(this.uncheckedContext);
1085
- const foundItem = this.flagManager.get(flagKey);
1309
+ const evalContext = jsSdkCommon.Context.fromLDContext(this._uncheckedContext);
1310
+ const foundItem = this._flagManager.get(flagKey);
1086
1311
  if (foundItem === undefined || foundItem.flag.deleted) {
1087
1312
  const defVal = defaultValue ?? null;
1088
1313
  const error = new jsSdkCommon.LDClientError(`Unknown feature flag "${flagKey}"; returning default value ${defVal}.`);
1089
- this.emitter.emit('error', this.uncheckedContext, error);
1090
- this.eventProcessor?.sendEvent(this.eventFactoryDefault.unknownFlagEvent(flagKey, defVal, evalContext));
1314
+ this.emitter.emit('error', this._uncheckedContext, error);
1315
+ this._eventProcessor?.sendEvent(this._eventFactoryDefault.unknownFlagEvent(flagKey, defVal, evalContext));
1091
1316
  return createErrorEvaluationDetail(ErrorKinds.FlagNotFound, defaultValue);
1092
1317
  }
1093
- const { reason, value, variation } = foundItem.flag;
1318
+ const { reason, value, variation, prerequisites } = foundItem.flag;
1094
1319
  if (typeChecker) {
1095
1320
  const [matched, type] = typeChecker(value);
1096
1321
  if (!matched) {
1097
- this.eventProcessor?.sendEvent(eventFactory.evalEventClient(flagKey, defaultValue, // track default value on type errors
1322
+ this._eventProcessor?.sendEvent(eventFactory.evalEventClient(flagKey, defaultValue, // track default value on type errors
1098
1323
  defaultValue, foundItem.flag, evalContext, reason));
1099
1324
  const error = new jsSdkCommon.LDClientError(`Wrong type "${type}" for feature flag "${flagKey}"; returning default value`);
1100
- this.emitter.emit('error', this.uncheckedContext, error);
1325
+ this.emitter.emit('error', this._uncheckedContext, error);
1101
1326
  return createErrorEvaluationDetail(ErrorKinds.WrongType, defaultValue);
1102
1327
  }
1103
1328
  }
@@ -1106,21 +1331,24 @@ class LDClientImpl {
1106
1331
  this.logger.debug('Result value is null. Providing default value.');
1107
1332
  successDetail.value = defaultValue;
1108
1333
  }
1109
- this.eventProcessor?.sendEvent(eventFactory.evalEventClient(flagKey, value, defaultValue, foundItem.flag, evalContext, reason));
1334
+ prerequisites?.forEach((prereqKey) => {
1335
+ this._variationInternal(prereqKey, undefined, this._eventFactoryDefault);
1336
+ });
1337
+ this._eventProcessor?.sendEvent(eventFactory.evalEventClient(flagKey, value, defaultValue, foundItem.flag, evalContext, reason));
1110
1338
  return successDetail;
1111
1339
  }
1112
1340
  variation(flagKey, defaultValue) {
1113
- const { value } = this.hookRunner.withEvaluation(flagKey, this.uncheckedContext, defaultValue, () => this.variationInternal(flagKey, defaultValue, this.eventFactoryDefault));
1341
+ const { value } = this._hookRunner.withEvaluation(flagKey, this._uncheckedContext, defaultValue, () => this._variationInternal(flagKey, defaultValue, this._eventFactoryDefault));
1114
1342
  return value;
1115
1343
  }
1116
1344
  variationDetail(flagKey, defaultValue) {
1117
- return this.hookRunner.withEvaluation(flagKey, this.uncheckedContext, defaultValue, () => this.variationInternal(flagKey, defaultValue, this.eventFactoryWithReasons));
1345
+ return this._hookRunner.withEvaluation(flagKey, this._uncheckedContext, defaultValue, () => this._variationInternal(flagKey, defaultValue, this._eventFactoryWithReasons));
1118
1346
  }
1119
- typedEval(key, defaultValue, eventFactory, typeChecker) {
1120
- return this.hookRunner.withEvaluation(key, this.uncheckedContext, defaultValue, () => this.variationInternal(key, defaultValue, eventFactory, typeChecker));
1347
+ _typedEval(key, defaultValue, eventFactory, typeChecker) {
1348
+ return this._hookRunner.withEvaluation(key, this._uncheckedContext, defaultValue, () => this._variationInternal(key, defaultValue, eventFactory, typeChecker));
1121
1349
  }
1122
1350
  boolVariation(key, defaultValue) {
1123
- return this.typedEval(key, defaultValue, this.eventFactoryDefault, (value) => [
1351
+ return this._typedEval(key, defaultValue, this._eventFactoryDefault, (value) => [
1124
1352
  jsSdkCommon.TypeValidators.Boolean.is(value),
1125
1353
  jsSdkCommon.TypeValidators.Boolean.getType(),
1126
1354
  ]).value;
@@ -1129,31 +1357,31 @@ class LDClientImpl {
1129
1357
  return this.variation(key, defaultValue);
1130
1358
  }
1131
1359
  numberVariation(key, defaultValue) {
1132
- return this.typedEval(key, defaultValue, this.eventFactoryDefault, (value) => [
1360
+ return this._typedEval(key, defaultValue, this._eventFactoryDefault, (value) => [
1133
1361
  jsSdkCommon.TypeValidators.Number.is(value),
1134
1362
  jsSdkCommon.TypeValidators.Number.getType(),
1135
1363
  ]).value;
1136
1364
  }
1137
1365
  stringVariation(key, defaultValue) {
1138
- return this.typedEval(key, defaultValue, this.eventFactoryDefault, (value) => [
1366
+ return this._typedEval(key, defaultValue, this._eventFactoryDefault, (value) => [
1139
1367
  jsSdkCommon.TypeValidators.String.is(value),
1140
1368
  jsSdkCommon.TypeValidators.String.getType(),
1141
1369
  ]).value;
1142
1370
  }
1143
1371
  boolVariationDetail(key, defaultValue) {
1144
- return this.typedEval(key, defaultValue, this.eventFactoryWithReasons, (value) => [
1372
+ return this._typedEval(key, defaultValue, this._eventFactoryWithReasons, (value) => [
1145
1373
  jsSdkCommon.TypeValidators.Boolean.is(value),
1146
1374
  jsSdkCommon.TypeValidators.Boolean.getType(),
1147
1375
  ]);
1148
1376
  }
1149
1377
  numberVariationDetail(key, defaultValue) {
1150
- return this.typedEval(key, defaultValue, this.eventFactoryWithReasons, (value) => [
1378
+ return this._typedEval(key, defaultValue, this._eventFactoryWithReasons, (value) => [
1151
1379
  jsSdkCommon.TypeValidators.Number.is(value),
1152
1380
  jsSdkCommon.TypeValidators.Number.getType(),
1153
1381
  ]);
1154
1382
  }
1155
1383
  stringVariationDetail(key, defaultValue) {
1156
- return this.typedEval(key, defaultValue, this.eventFactoryWithReasons, (value) => [
1384
+ return this._typedEval(key, defaultValue, this._eventFactoryWithReasons, (value) => [
1157
1385
  jsSdkCommon.TypeValidators.String.is(value),
1158
1386
  jsSdkCommon.TypeValidators.String.getType(),
1159
1387
  ]);
@@ -1162,7 +1390,7 @@ class LDClientImpl {
1162
1390
  return this.variationDetail(key, defaultValue);
1163
1391
  }
1164
1392
  addHook(hook) {
1165
- this.hookRunner.addHook(hook);
1393
+ this._hookRunner.addHook(hook);
1166
1394
  }
1167
1395
  /**
1168
1396
  * Enable/Disable event sending.
@@ -1170,13 +1398,13 @@ class LDClientImpl {
1170
1398
  * @param flush True to flush while disabling. Useful to flush on certain state transitions.
1171
1399
  */
1172
1400
  setEventSendingEnabled(enabled, flush) {
1173
- if (this.eventSendingEnabled === enabled) {
1401
+ if (this._eventSendingEnabled === enabled) {
1174
1402
  return;
1175
1403
  }
1176
- this.eventSendingEnabled = enabled;
1404
+ this._eventSendingEnabled = enabled;
1177
1405
  if (enabled) {
1178
1406
  this.logger.debug('Starting event processor');
1179
- this.eventProcessor?.start();
1407
+ this._eventProcessor?.start();
1180
1408
  }
1181
1409
  else if (flush) {
1182
1410
  this.logger?.debug('Flushing event processor before disabling.');
@@ -1184,92 +1412,70 @@ class LDClientImpl {
1184
1412
  this.flush().then(() => {
1185
1413
  // While waiting for the flush event sending could be re-enabled, in which case
1186
1414
  // we do not want to close the event processor.
1187
- if (!this.eventSendingEnabled) {
1415
+ if (!this._eventSendingEnabled) {
1188
1416
  this.logger?.debug('Stopping event processor.');
1189
- this.eventProcessor?.close();
1417
+ this._eventProcessor?.close();
1190
1418
  }
1191
1419
  });
1192
1420
  }
1193
1421
  else {
1194
1422
  // Just disabled.
1195
1423
  this.logger?.debug('Stopping event processor.');
1196
- this.eventProcessor?.close();
1424
+ this._eventProcessor?.close();
1197
1425
  }
1198
1426
  }
1199
1427
  sendEvent(event) {
1200
- this.eventProcessor?.sendEvent(event);
1201
- }
1202
- }
1203
-
1204
- function isOk(status) {
1205
- return status >= 200 && status <= 299;
1206
- }
1207
- class LDRequestError extends Error {
1208
- constructor(message, status) {
1209
- super(message);
1210
- this.status = status;
1211
- this.name = 'LaunchDarklyRequestError';
1428
+ this._eventProcessor?.sendEvent(event);
1212
1429
  }
1213
- }
1214
- /**
1215
- * Note: The requestor is implemented independently from polling such that it can be used to
1216
- * make a one-off request.
1217
- */
1218
- class Requestor {
1219
- constructor(requests, uri, headers, method, body) {
1220
- this.requests = requests;
1221
- this.uri = uri;
1222
- this.headers = headers;
1223
- this.method = method;
1224
- this.body = body;
1225
- }
1226
- async requestPayload() {
1227
- let status;
1228
- try {
1229
- const res = await this.requests.fetch(this.uri, {
1230
- method: this.method,
1231
- headers: this.headers,
1232
- body: this.body,
1233
- });
1234
- if (isOk(res.status)) {
1235
- return await res.text();
1430
+ _handleInspectionChanged(flagKeys, type) {
1431
+ if (!this._inspectorManager.hasInspectors()) {
1432
+ return;
1433
+ }
1434
+ const details = {};
1435
+ flagKeys.forEach((flagKey) => {
1436
+ const item = this._flagManager.get(flagKey);
1437
+ if (item?.flag && !item.flag.deleted) {
1438
+ const { reason, value, variation } = item.flag;
1439
+ details[flagKey] = createSuccessEvaluationDetail(value, variation, reason);
1236
1440
  }
1237
- // Assigning so it can be thrown after the try/catch.
1238
- status = res.status;
1441
+ });
1442
+ if (type === 'init') {
1443
+ this._inspectorManager.onFlagsChanged(details);
1239
1444
  }
1240
- catch (err) {
1241
- throw new LDRequestError(err?.message);
1445
+ else if (type === 'patch') {
1446
+ Object.entries(details).forEach(([flagKey, detail]) => {
1447
+ this._inspectorManager.onFlagChanged(flagKey, detail);
1448
+ });
1242
1449
  }
1243
- throw new LDRequestError(`Unexpected status code: ${status}`, status);
1244
1450
  }
1245
1451
  }
1246
1452
 
1247
1453
  class DataSourceEventHandler {
1248
- constructor(flagManager, statusManager, logger) {
1249
- this.flagManager = flagManager;
1250
- this.statusManager = statusManager;
1251
- this.logger = logger;
1454
+ constructor(_flagManager, _statusManager, _logger) {
1455
+ this._flagManager = _flagManager;
1456
+ this._statusManager = _statusManager;
1457
+ this._logger = _logger;
1252
1458
  }
1253
1459
  async handlePut(context, flags) {
1254
- this.logger.debug(`Got PUT: ${Object.keys(flags)}`);
1460
+ this._logger.debug(`Got PUT: ${Object.keys(flags)}`);
1255
1461
  // mapping flags to item descriptors
1256
1462
  const descriptors = Object.entries(flags).reduce((acc, [key, flag]) => {
1257
1463
  acc[key] = { version: flag.version, flag };
1258
1464
  return acc;
1259
1465
  }, {});
1260
- await this.flagManager.init(context, descriptors);
1261
- this.statusManager.requestStateUpdate(exports.DataSourceState.Valid);
1466
+ await this._flagManager.init(context, descriptors);
1467
+ this._statusManager.requestStateUpdate(exports.DataSourceState.Valid);
1262
1468
  }
1263
1469
  async handlePatch(context, patchFlag) {
1264
- this.logger.debug(`Got PATCH ${JSON.stringify(patchFlag, null, 2)}`);
1265
- this.flagManager.upsert(context, patchFlag.key, {
1470
+ this._logger.debug(`Got PATCH ${JSON.stringify(patchFlag, null, 2)}`);
1471
+ this._flagManager.upsert(context, patchFlag.key, {
1266
1472
  version: patchFlag.version,
1267
1473
  flag: patchFlag,
1268
1474
  });
1269
1475
  }
1270
1476
  async handleDelete(context, deleteFlag) {
1271
- this.logger.debug(`Got DELETE ${JSON.stringify(deleteFlag, null, 2)}`);
1272
- this.flagManager.upsert(context, deleteFlag.key, {
1477
+ this._logger.debug(`Got DELETE ${JSON.stringify(deleteFlag, null, 2)}`);
1478
+ this._flagManager.upsert(context, deleteFlag.key, {
1273
1479
  version: deleteFlag.version,
1274
1480
  flag: {
1275
1481
  ...deleteFlag,
@@ -1284,10 +1490,10 @@ class DataSourceEventHandler {
1284
1490
  });
1285
1491
  }
1286
1492
  handleStreamingError(error) {
1287
- this.statusManager.reportError(error.kind, error.message, error.code, error.recoverable);
1493
+ this._statusManager.reportError(error.kind, error.message, error.code, error.recoverable);
1288
1494
  }
1289
1495
  handlePollingError(error) {
1290
- this.statusManager.reportError(error.kind, error.message, error.status, error.recoverable);
1496
+ this._statusManager.reportError(error.kind, error.message, error.status, error.recoverable);
1291
1497
  }
1292
1498
  }
1293
1499
 
@@ -1295,17 +1501,17 @@ class DataSourceEventHandler {
1295
1501
  * Tracks the current data source status and emits updates when the status changes.
1296
1502
  */
1297
1503
  class DataSourceStatusManager {
1298
- constructor(emitter, timeStamper = () => Date.now()) {
1299
- this.emitter = emitter;
1300
- this.state = exports.DataSourceState.Closed;
1301
- this.stateSinceMillis = timeStamper();
1302
- this.timeStamper = timeStamper;
1504
+ constructor(_emitter, timeStamper = () => Date.now()) {
1505
+ this._emitter = _emitter;
1506
+ this._state = exports.DataSourceState.Closed;
1507
+ this._stateSinceMillis = timeStamper();
1508
+ this._timeStamper = timeStamper;
1303
1509
  }
1304
1510
  get status() {
1305
1511
  return {
1306
- state: this.state,
1307
- stateSince: this.stateSinceMillis,
1308
- lastError: this.errorInfo,
1512
+ state: this._state,
1513
+ stateSince: this._stateSinceMillis,
1514
+ lastError: this._errorInfo,
1309
1515
  };
1310
1516
  }
1311
1517
  /**
@@ -1314,17 +1520,17 @@ class DataSourceStatusManager {
1314
1520
  * @param requestedState to track
1315
1521
  * @param isError to indicate that the state update is a result of an error occurring.
1316
1522
  */
1317
- updateState(requestedState, isError = false) {
1318
- 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)
1523
+ _updateState(requestedState, isError = false) {
1524
+ 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)
1319
1525
  ? exports.DataSourceState.Initializing
1320
1526
  : requestedState;
1321
- const changedState = this.state !== newState;
1527
+ const changedState = this._state !== newState;
1322
1528
  if (changedState) {
1323
- this.state = newState;
1324
- this.stateSinceMillis = this.timeStamper();
1529
+ this._state = newState;
1530
+ this._stateSinceMillis = this._timeStamper();
1325
1531
  }
1326
1532
  if (changedState || isError) {
1327
- this.emitter.emit('dataSourceStatus', this.status);
1533
+ this._emitter.emit('dataSourceStatus', this.status);
1328
1534
  }
1329
1535
  }
1330
1536
  /**
@@ -1333,7 +1539,7 @@ class DataSourceStatusManager {
1333
1539
  * @param state that is requested
1334
1540
  */
1335
1541
  requestStateUpdate(state) {
1336
- this.updateState(state);
1542
+ this._updateState(state);
1337
1543
  }
1338
1544
  /**
1339
1545
  * Reports a datasource error to this manager. Since the {@link DataSourceStatus} includes error
@@ -1350,10 +1556,10 @@ class DataSourceStatusManager {
1350
1556
  kind,
1351
1557
  message,
1352
1558
  statusCode,
1353
- time: this.timeStamper(),
1559
+ time: this._timeStamper(),
1354
1560
  };
1355
- this.errorInfo = errorInfo;
1356
- this.updateState(recoverable ? exports.DataSourceState.Interrupted : exports.DataSourceState.Closed, true);
1561
+ this._errorInfo = errorInfo;
1562
+ this._updateState(recoverable ? exports.DataSourceState.Interrupted : exports.DataSourceState.Closed, true);
1357
1563
  }
1358
1564
  }
1359
1565
 
@@ -1361,54 +1567,34 @@ class DataSourceStatusManager {
1361
1567
  * @internal
1362
1568
  */
1363
1569
  class PollingProcessor {
1364
- constructor(plainContextString, dataSourceConfig, requests, encoding, dataHandler, errorHandler, logger) {
1365
- this.plainContextString = plainContextString;
1366
- this.dataSourceConfig = dataSourceConfig;
1367
- this.dataHandler = dataHandler;
1368
- this.errorHandler = errorHandler;
1369
- this.logger = logger;
1370
- this.stopped = false;
1371
- const path = dataSourceConfig.useReport
1372
- ? dataSourceConfig.paths.pathReport(encoding, plainContextString)
1373
- : dataSourceConfig.paths.pathGet(encoding, plainContextString);
1374
- const parameters = [
1375
- ...(dataSourceConfig.queryParameters ?? []),
1376
- ];
1377
- if (this.dataSourceConfig.withReasons) {
1378
- parameters.push({ key: 'withReasons', value: 'true' });
1379
- }
1380
- const uri = jsSdkCommon.getPollingUri(dataSourceConfig.serviceEndpoints, path, parameters);
1381
- this.pollInterval = dataSourceConfig.pollInterval;
1382
- let method = 'GET';
1383
- const headers = { ...dataSourceConfig.baseHeaders };
1384
- let body;
1385
- if (dataSourceConfig.useReport) {
1386
- method = 'REPORT';
1387
- headers['content-type'] = 'application/json';
1388
- body = plainContextString; // context is in body for REPORT
1389
- }
1390
- this.requestor = new Requestor(requests, uri, headers, method, body);
1391
- }
1392
- async poll() {
1393
- if (this.stopped) {
1570
+ constructor(_requestor, _pollIntervalSeconds, _dataHandler, _errorHandler, _logger) {
1571
+ this._requestor = _requestor;
1572
+ this._pollIntervalSeconds = _pollIntervalSeconds;
1573
+ this._dataHandler = _dataHandler;
1574
+ this._errorHandler = _errorHandler;
1575
+ this._logger = _logger;
1576
+ this._stopped = false;
1577
+ }
1578
+ async _poll() {
1579
+ if (this._stopped) {
1394
1580
  return;
1395
1581
  }
1396
1582
  const reportJsonError = (data) => {
1397
- this.logger?.error('Polling received invalid data');
1398
- this.logger?.debug(`Invalid JSON follows: ${data}`);
1399
- this.errorHandler?.(new jsSdkCommon.LDPollingError(jsSdkCommon.DataSourceErrorKind.InvalidData, 'Malformed JSON data in polling response'));
1583
+ this._logger?.error('Polling received invalid data');
1584
+ this._logger?.debug(`Invalid JSON follows: ${data}`);
1585
+ this._errorHandler?.(new jsSdkCommon.LDPollingError(jsSdkCommon.DataSourceErrorKind.InvalidData, 'Malformed JSON data in polling response'));
1400
1586
  };
1401
- this.logger?.debug('Polling LaunchDarkly for feature flag updates');
1587
+ this._logger?.debug('Polling LaunchDarkly for feature flag updates');
1402
1588
  const startTime = Date.now();
1403
1589
  try {
1404
- const res = await this.requestor.requestPayload();
1590
+ const res = await this._requestor.requestPayload();
1405
1591
  try {
1406
1592
  const flags = JSON.parse(res);
1407
1593
  try {
1408
- this.dataHandler?.(flags);
1594
+ this._dataHandler?.(flags);
1409
1595
  }
1410
1596
  catch (err) {
1411
- this.logger?.error(`Exception from data handler: ${err}`);
1597
+ this._logger?.error(`Exception from data handler: ${err}`);
1412
1598
  }
1413
1599
  }
1414
1600
  catch {
@@ -1419,29 +1605,29 @@ class PollingProcessor {
1419
1605
  const requestError = err;
1420
1606
  if (requestError.status !== undefined) {
1421
1607
  if (!jsSdkCommon.isHttpRecoverable(requestError.status)) {
1422
- this.logger?.error(jsSdkCommon.httpErrorMessage(err, 'polling request'));
1423
- this.errorHandler?.(new jsSdkCommon.LDPollingError(jsSdkCommon.DataSourceErrorKind.ErrorResponse, requestError.message, requestError.status));
1608
+ this._logger?.error(jsSdkCommon.httpErrorMessage(err, 'polling request'));
1609
+ this._errorHandler?.(new jsSdkCommon.LDPollingError(jsSdkCommon.DataSourceErrorKind.ErrorResponse, requestError.message, requestError.status));
1424
1610
  return;
1425
1611
  }
1426
1612
  }
1427
- this.logger?.error(jsSdkCommon.httpErrorMessage(err, 'polling request', 'will retry'));
1613
+ this._logger?.error(jsSdkCommon.httpErrorMessage(err, 'polling request', 'will retry'));
1428
1614
  }
1429
1615
  const elapsed = Date.now() - startTime;
1430
- const sleepFor = Math.max(this.pollInterval * 1000 - elapsed, 0);
1431
- this.logger?.debug('Elapsed: %d ms, sleeping for %d ms', elapsed, sleepFor);
1432
- this.timeoutHandle = setTimeout(() => {
1433
- this.poll();
1616
+ const sleepFor = Math.max(this._pollIntervalSeconds * 1000 - elapsed, 0);
1617
+ this._logger?.debug('Elapsed: %d ms, sleeping for %d ms', elapsed, sleepFor);
1618
+ this._timeoutHandle = setTimeout(() => {
1619
+ this._poll();
1434
1620
  }, sleepFor);
1435
1621
  }
1436
1622
  start() {
1437
- this.poll();
1623
+ this._poll();
1438
1624
  }
1439
1625
  stop() {
1440
- if (this.timeoutHandle) {
1441
- clearTimeout(this.timeoutHandle);
1442
- this.timeoutHandle = undefined;
1626
+ if (this._timeoutHandle) {
1627
+ clearTimeout(this._timeoutHandle);
1628
+ this._timeoutHandle = undefined;
1443
1629
  }
1444
- this.stopped = true;
1630
+ this._stopped = true;
1445
1631
  }
1446
1632
  close() {
1447
1633
  this.stop();
@@ -1454,40 +1640,43 @@ const reportJsonError = (type, data, logger, errorHandler) => {
1454
1640
  errorHandler?.(new jsSdkCommon.LDStreamingError(jsSdkCommon.DataSourceErrorKind.InvalidData, 'Malformed JSON data in event stream'));
1455
1641
  };
1456
1642
  class StreamingProcessor {
1457
- constructor(plainContextString, dataSourceConfig, listeners, requests, encoding, diagnosticsManager, errorHandler, logger) {
1458
- this.plainContextString = plainContextString;
1459
- this.dataSourceConfig = dataSourceConfig;
1460
- this.listeners = listeners;
1461
- this.requests = requests;
1462
- this.diagnosticsManager = diagnosticsManager;
1463
- this.errorHandler = errorHandler;
1464
- this.logger = logger;
1465
- // TODO: SC-255969 Implement better REPORT fallback logic
1466
- if (dataSourceConfig.useReport && !requests.getEventSourceCapabilities().customMethod) {
1467
- logger?.error("Configuration option useReport is true, but platform's EventSource does not support custom HTTP methods. Streaming may not work.");
1468
- }
1469
- const path = dataSourceConfig.useReport
1470
- ? dataSourceConfig.paths.pathReport(encoding, plainContextString)
1471
- : dataSourceConfig.paths.pathGet(encoding, plainContextString);
1643
+ constructor(_plainContextString, _dataSourceConfig, _listeners, _requests, encoding, _pollingRequestor, _diagnosticsManager, _errorHandler, _logger) {
1644
+ this._plainContextString = _plainContextString;
1645
+ this._dataSourceConfig = _dataSourceConfig;
1646
+ this._listeners = _listeners;
1647
+ this._requests = _requests;
1648
+ this._pollingRequestor = _pollingRequestor;
1649
+ this._diagnosticsManager = _diagnosticsManager;
1650
+ this._errorHandler = _errorHandler;
1651
+ this._logger = _logger;
1652
+ let path;
1653
+ if (_dataSourceConfig.useReport && !_requests.getEventSourceCapabilities().customMethod) {
1654
+ path = _dataSourceConfig.paths.pathPing(encoding, _plainContextString);
1655
+ }
1656
+ else {
1657
+ path = _dataSourceConfig.useReport
1658
+ ? _dataSourceConfig.paths.pathReport(encoding, _plainContextString)
1659
+ : _dataSourceConfig.paths.pathGet(encoding, _plainContextString);
1660
+ }
1472
1661
  const parameters = [
1473
- ...(dataSourceConfig.queryParameters ?? []),
1662
+ ...(_dataSourceConfig.queryParameters ?? []),
1474
1663
  ];
1475
- if (this.dataSourceConfig.withReasons) {
1664
+ if (this._dataSourceConfig.withReasons) {
1476
1665
  parameters.push({ key: 'withReasons', value: 'true' });
1477
1666
  }
1478
- this.requests = requests;
1479
- this.headers = { ...dataSourceConfig.baseHeaders };
1480
- this.logger = logger;
1481
- this.streamUri = jsSdkCommon.getStreamingUri(dataSourceConfig.serviceEndpoints, path, parameters);
1667
+ this._requests = _requests;
1668
+ this._headers = { ..._dataSourceConfig.baseHeaders };
1669
+ this._logger = _logger;
1670
+ this._streamUri = jsSdkCommon.getStreamingUri(_dataSourceConfig.serviceEndpoints, path, parameters);
1482
1671
  }
1483
- logConnectionStarted() {
1484
- this.connectionAttemptStartTime = Date.now();
1672
+ _logConnectionStarted() {
1673
+ this._connectionAttemptStartTime = Date.now();
1485
1674
  }
1486
- logConnectionResult(success) {
1487
- if (this.connectionAttemptStartTime && this.diagnosticsManager) {
1488
- this.diagnosticsManager.recordStreamInit(this.connectionAttemptStartTime, !success, Date.now() - this.connectionAttemptStartTime);
1675
+ _logConnectionResult(success) {
1676
+ if (this._connectionAttemptStartTime && this._diagnosticsManager) {
1677
+ this._diagnosticsManager.recordStreamInit(this._connectionAttemptStartTime, !success, Date.now() - this._connectionAttemptStartTime);
1489
1678
  }
1490
- this.connectionAttemptStartTime = undefined;
1679
+ this._connectionAttemptStartTime = undefined;
1491
1680
  }
1492
1681
  /**
1493
1682
  * This is a wrapper around the passed errorHandler which adds additional
@@ -1498,75 +1687,101 @@ class StreamingProcessor {
1498
1687
  *
1499
1688
  * @private
1500
1689
  */
1501
- retryAndHandleError(err) {
1690
+ _retryAndHandleError(err) {
1502
1691
  if (!jsSdkCommon.shouldRetry(err)) {
1503
- this.logConnectionResult(false);
1504
- this.errorHandler?.(new jsSdkCommon.LDStreamingError(jsSdkCommon.DataSourceErrorKind.ErrorResponse, err.message, err.status, false));
1505
- this.logger?.error(jsSdkCommon.httpErrorMessage(err, 'streaming request'));
1692
+ this._logConnectionResult(false);
1693
+ this._errorHandler?.(new jsSdkCommon.LDStreamingError(jsSdkCommon.DataSourceErrorKind.ErrorResponse, err.message, err.status, false));
1694
+ this._logger?.error(jsSdkCommon.httpErrorMessage(err, 'streaming request'));
1506
1695
  return false;
1507
1696
  }
1508
- this.logger?.warn(jsSdkCommon.httpErrorMessage(err, 'streaming request', 'will retry'));
1509
- this.logConnectionResult(false);
1510
- this.logConnectionStarted();
1697
+ this._logger?.warn(jsSdkCommon.httpErrorMessage(err, 'streaming request', 'will retry'));
1698
+ this._logConnectionResult(false);
1699
+ this._logConnectionStarted();
1511
1700
  return true;
1512
1701
  }
1513
1702
  start() {
1514
- this.logConnectionStarted();
1703
+ this._logConnectionStarted();
1515
1704
  let methodAndBodyOverrides;
1516
- if (this.dataSourceConfig.useReport) {
1705
+ if (this._dataSourceConfig.useReport) {
1517
1706
  // REPORT will include a body, so content type is required.
1518
- this.headers['content-type'] = 'application/json';
1707
+ this._headers['content-type'] = 'application/json';
1519
1708
  // orverrides default method with REPORT and adds body.
1520
- methodAndBodyOverrides = { method: 'REPORT', body: this.plainContextString };
1709
+ methodAndBodyOverrides = { method: 'REPORT', body: this._plainContextString };
1521
1710
  }
1522
1711
  else {
1523
1712
  // no method or body override
1524
1713
  methodAndBodyOverrides = {};
1525
1714
  }
1526
1715
  // TLS is handled by the platform implementation.
1527
- const eventSource = this.requests.createEventSource(this.streamUri, {
1528
- headers: this.headers,
1716
+ const eventSource = this._requests.createEventSource(this._streamUri, {
1717
+ headers: this._headers,
1529
1718
  ...methodAndBodyOverrides,
1530
- errorFilter: (error) => this.retryAndHandleError(error),
1531
- initialRetryDelayMillis: this.dataSourceConfig.initialRetryDelayMillis,
1719
+ errorFilter: (error) => this._retryAndHandleError(error),
1720
+ initialRetryDelayMillis: this._dataSourceConfig.initialRetryDelayMillis,
1532
1721
  readTimeoutMillis: 5 * 60 * 1000,
1533
1722
  retryResetIntervalMillis: 60 * 1000,
1534
1723
  });
1535
- this.eventSource = eventSource;
1724
+ this._eventSource = eventSource;
1536
1725
  eventSource.onclose = () => {
1537
- this.logger?.info('Closed LaunchDarkly stream connection');
1726
+ this._logger?.info('Closed LaunchDarkly stream connection');
1538
1727
  };
1539
1728
  eventSource.onerror = () => {
1540
1729
  // The work is done by `errorFilter`.
1541
1730
  };
1542
1731
  eventSource.onopen = () => {
1543
- this.logger?.info('Opened LaunchDarkly stream connection');
1732
+ this._logger?.info('Opened LaunchDarkly stream connection');
1544
1733
  };
1545
1734
  eventSource.onretrying = (e) => {
1546
- this.logger?.info(`Will retry stream connection in ${e.delayMillis} milliseconds`);
1735
+ this._logger?.info(`Will retry stream connection in ${e.delayMillis} milliseconds`);
1547
1736
  };
1548
- this.listeners.forEach(({ deserializeData, processJson }, eventName) => {
1737
+ this._listeners.forEach(({ deserializeData, processJson }, eventName) => {
1549
1738
  eventSource.addEventListener(eventName, (event) => {
1550
- this.logger?.debug(`Received ${eventName} event`);
1739
+ this._logger?.debug(`Received ${eventName} event`);
1551
1740
  if (event?.data) {
1552
- this.logConnectionResult(true);
1741
+ this._logConnectionResult(true);
1553
1742
  const { data } = event;
1554
1743
  const dataJson = deserializeData(data);
1555
1744
  if (!dataJson) {
1556
- reportJsonError(eventName, data, this.logger, this.errorHandler);
1745
+ reportJsonError(eventName, data, this._logger, this._errorHandler);
1557
1746
  return;
1558
1747
  }
1559
1748
  processJson(dataJson);
1560
1749
  }
1561
1750
  else {
1562
- this.errorHandler?.(new jsSdkCommon.LDStreamingError(jsSdkCommon.DataSourceErrorKind.InvalidData, 'Unexpected payload from event stream'));
1751
+ this._errorHandler?.(new jsSdkCommon.LDStreamingError(jsSdkCommon.DataSourceErrorKind.InvalidData, 'Unexpected payload from event stream'));
1563
1752
  }
1564
1753
  });
1565
1754
  });
1755
+ // here we set up a listener that will poll when ping is received
1756
+ eventSource.addEventListener('ping', async () => {
1757
+ this._logger?.debug('Got PING, going to poll LaunchDarkly for feature flag updates');
1758
+ try {
1759
+ const res = await this._pollingRequestor.requestPayload();
1760
+ try {
1761
+ const payload = JSON.parse(res);
1762
+ try {
1763
+ // forward the payload on to the PUT listener
1764
+ this._listeners.get('put')?.processJson(payload);
1765
+ }
1766
+ catch (err) {
1767
+ this._logger?.error(`Exception from data handler: ${err}`);
1768
+ }
1769
+ }
1770
+ catch {
1771
+ this._logger?.error('Polling after ping received invalid data');
1772
+ this._logger?.debug(`Invalid JSON follows: ${res}`);
1773
+ this._errorHandler?.(new jsSdkCommon.LDPollingError(jsSdkCommon.DataSourceErrorKind.InvalidData, 'Malformed JSON data in ping polling response'));
1774
+ }
1775
+ }
1776
+ catch (err) {
1777
+ const requestError = err;
1778
+ this._errorHandler?.(new jsSdkCommon.LDPollingError(jsSdkCommon.DataSourceErrorKind.ErrorResponse, requestError.message, requestError.status));
1779
+ }
1780
+ });
1566
1781
  }
1567
1782
  stop() {
1568
- this.eventSource?.close();
1569
- this.eventSource = undefined;
1783
+ this._eventSource?.close();
1784
+ this._eventSource = undefined;
1570
1785
  }
1571
1786
  close() {
1572
1787
  this.stop();
@@ -1586,35 +1801,26 @@ class BaseDataManager {
1586
1801
  this.diagnosticsManager = diagnosticsManager;
1587
1802
  this.logger = config.logger;
1588
1803
  this.dataSourceStatusManager = new DataSourceStatusManager(emitter);
1589
- this.dataSourceEventHandler = new DataSourceEventHandler(flagManager, this.dataSourceStatusManager, this.config.logger);
1804
+ this._dataSourceEventHandler = new DataSourceEventHandler(flagManager, this.dataSourceStatusManager, this.config.logger);
1590
1805
  }
1591
1806
  /**
1592
1807
  * Set additional connection parameters for requests polling/streaming.
1593
1808
  */
1594
1809
  setConnectionParams(connectionParams) {
1595
- this.connectionParams = connectionParams;
1810
+ this._connectionParams = connectionParams;
1596
1811
  }
1597
- createPollingProcessor(context, checkedContext, identifyResolve, identifyReject) {
1598
- const processor = new PollingProcessor(JSON.stringify(context), {
1599
- credential: this.credential,
1600
- serviceEndpoints: this.config.serviceEndpoints,
1601
- paths: this.getPollingPaths(),
1602
- baseHeaders: this.baseHeaders,
1603
- pollInterval: this.config.pollInterval,
1604
- withReasons: this.config.withReasons,
1605
- useReport: this.config.useReport,
1606
- queryParameters: this.connectionParams?.queryParameters,
1607
- }, this.platform.requests, this.platform.encoding, async (flags) => {
1608
- await this.dataSourceEventHandler.handlePut(checkedContext, flags);
1812
+ createPollingProcessor(context, checkedContext, requestor, identifyResolve, identifyReject) {
1813
+ const processor = new PollingProcessor(requestor, this.config.pollInterval, async (flags) => {
1814
+ await this._dataSourceEventHandler.handlePut(checkedContext, flags);
1609
1815
  identifyResolve?.();
1610
1816
  }, (err) => {
1611
1817
  this.emitter.emit('error', context, err);
1612
- this.dataSourceEventHandler.handlePollingError(err);
1818
+ this._dataSourceEventHandler.handlePollingError(err);
1613
1819
  identifyReject?.(err);
1614
- });
1615
- this.updateProcessor = this.decorateProcessorWithStatusReporting(processor, this.dataSourceStatusManager);
1820
+ }, this.logger);
1821
+ this.updateProcessor = this._decorateProcessorWithStatusReporting(processor, this.dataSourceStatusManager);
1616
1822
  }
1617
- createStreamingProcessor(context, checkedContext, identifyResolve, identifyReject) {
1823
+ createStreamingProcessor(context, checkedContext, pollingRequestor, identifyResolve, identifyReject) {
1618
1824
  const processor = new StreamingProcessor(JSON.stringify(context), {
1619
1825
  credential: this.credential,
1620
1826
  serviceEndpoints: this.config.serviceEndpoints,
@@ -1623,38 +1829,38 @@ class BaseDataManager {
1623
1829
  initialRetryDelayMillis: this.config.streamInitialReconnectDelay * 1000,
1624
1830
  withReasons: this.config.withReasons,
1625
1831
  useReport: this.config.useReport,
1626
- queryParameters: this.connectionParams?.queryParameters,
1627
- }, this.createStreamListeners(checkedContext, identifyResolve), this.platform.requests, this.platform.encoding, this.diagnosticsManager, (e) => {
1832
+ queryParameters: this._connectionParams?.queryParameters,
1833
+ }, this.createStreamListeners(checkedContext, identifyResolve), this.platform.requests, this.platform.encoding, pollingRequestor, this.diagnosticsManager, (e) => {
1628
1834
  this.emitter.emit('error', context, e);
1629
- this.dataSourceEventHandler.handleStreamingError(e);
1835
+ this._dataSourceEventHandler.handleStreamingError(e);
1630
1836
  identifyReject?.(e);
1631
- });
1632
- this.updateProcessor = this.decorateProcessorWithStatusReporting(processor, this.dataSourceStatusManager);
1837
+ }, this.logger);
1838
+ this.updateProcessor = this._decorateProcessorWithStatusReporting(processor, this.dataSourceStatusManager);
1633
1839
  }
1634
1840
  createStreamListeners(context, identifyResolve) {
1635
1841
  const listeners = new Map();
1636
1842
  listeners.set('put', {
1637
1843
  deserializeData: JSON.parse,
1638
1844
  processJson: async (flags) => {
1639
- await this.dataSourceEventHandler.handlePut(context, flags);
1845
+ await this._dataSourceEventHandler.handlePut(context, flags);
1640
1846
  identifyResolve?.();
1641
1847
  },
1642
1848
  });
1643
1849
  listeners.set('patch', {
1644
1850
  deserializeData: JSON.parse,
1645
1851
  processJson: async (patchFlag) => {
1646
- this.dataSourceEventHandler.handlePatch(context, patchFlag);
1852
+ this._dataSourceEventHandler.handlePatch(context, patchFlag);
1647
1853
  },
1648
1854
  });
1649
1855
  listeners.set('delete', {
1650
1856
  deserializeData: JSON.parse,
1651
1857
  processJson: async (deleteFlag) => {
1652
- this.dataSourceEventHandler.handleDelete(context, deleteFlag);
1858
+ this._dataSourceEventHandler.handleDelete(context, deleteFlag);
1653
1859
  },
1654
1860
  });
1655
1861
  return listeners;
1656
1862
  }
1657
- decorateProcessorWithStatusReporting(processor, statusManager) {
1863
+ _decorateProcessorWithStatusReporting(processor, statusManager) {
1658
1864
  return {
1659
1865
  start: () => {
1660
1866
  // update status before starting processor to ensure potential errors are reported after initializing
@@ -1677,6 +1883,7 @@ exports.platform = jsSdkCommon__namespace;
1677
1883
  exports.BaseDataManager = BaseDataManager;
1678
1884
  exports.LDClientImpl = LDClientImpl;
1679
1885
  exports.Requestor = Requestor;
1886
+ exports.makeRequestor = makeRequestor;
1680
1887
  Object.keys(jsSdkCommon).forEach(function (k) {
1681
1888
  if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
1682
1889
  enumerable: true,