@launchdarkly/js-sdk-common 2.17.0 → 2.19.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 (74) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/AttributeReference.d.ts +1 -0
  3. package/dist/cjs/AttributeReference.d.ts.map +1 -1
  4. package/dist/cjs/Context.d.ts +9 -0
  5. package/dist/cjs/Context.d.ts.map +1 -1
  6. package/dist/cjs/api/platform/Requests.d.ts +1 -0
  7. package/dist/cjs/api/platform/Requests.d.ts.map +1 -1
  8. package/dist/cjs/api/subsystem/DataSystem/CallbackHandler.d.ts.map +1 -1
  9. package/dist/cjs/api/subsystem/DataSystem/DataSource.d.ts +18 -2
  10. package/dist/cjs/api/subsystem/DataSystem/DataSource.d.ts.map +1 -1
  11. package/dist/cjs/datasource/CompositeDataSource.d.ts +7 -2
  12. package/dist/cjs/datasource/CompositeDataSource.d.ts.map +1 -1
  13. package/dist/cjs/datasource/errors.d.ts +9 -0
  14. package/dist/cjs/datasource/errors.d.ts.map +1 -1
  15. package/dist/cjs/datasource/index.d.ts +2 -2
  16. package/dist/cjs/datasource/index.d.ts.map +1 -1
  17. package/dist/cjs/index.cjs +201 -47
  18. package/dist/cjs/index.cjs.map +1 -1
  19. package/dist/cjs/index.d.ts +2 -2
  20. package/dist/cjs/index.d.ts.map +1 -1
  21. package/dist/cjs/internal/events/EventProcessor.d.ts +1 -1
  22. package/dist/cjs/internal/events/EventProcessor.d.ts.map +1 -1
  23. package/dist/cjs/internal/events/LDEventSummarizer.d.ts +32 -0
  24. package/dist/cjs/internal/events/LDEventSummarizer.d.ts.map +1 -0
  25. package/dist/cjs/internal/events/MultiEventSummarizer.d.ts +13 -0
  26. package/dist/cjs/internal/events/MultiEventSummarizer.d.ts.map +1 -0
  27. package/dist/cjs/internal/fdv2/payloadProcessor.d.ts.map +1 -1
  28. package/dist/cjs/internal/fdv2/proto.d.ts +1 -1
  29. package/dist/cjs/internal/fdv2/proto.d.ts.map +1 -1
  30. package/dist/cjs/internal/index.d.ts +1 -0
  31. package/dist/cjs/internal/index.d.ts.map +1 -1
  32. package/dist/cjs/internal/json/canonicalize.d.ts +10 -0
  33. package/dist/cjs/internal/json/canonicalize.d.ts.map +1 -0
  34. package/dist/cjs/internal/json/index.d.ts +2 -0
  35. package/dist/cjs/internal/json/index.d.ts.map +1 -0
  36. package/dist/cjs/options/ServiceEndpoints.d.ts +2 -2
  37. package/dist/cjs/options/ServiceEndpoints.d.ts.map +1 -1
  38. package/dist/esm/AttributeReference.d.ts +1 -0
  39. package/dist/esm/AttributeReference.d.ts.map +1 -1
  40. package/dist/esm/Context.d.ts +9 -0
  41. package/dist/esm/Context.d.ts.map +1 -1
  42. package/dist/esm/api/platform/Requests.d.ts +1 -0
  43. package/dist/esm/api/platform/Requests.d.ts.map +1 -1
  44. package/dist/esm/api/subsystem/DataSystem/CallbackHandler.d.ts.map +1 -1
  45. package/dist/esm/api/subsystem/DataSystem/DataSource.d.ts +18 -2
  46. package/dist/esm/api/subsystem/DataSystem/DataSource.d.ts.map +1 -1
  47. package/dist/esm/datasource/CompositeDataSource.d.ts +7 -2
  48. package/dist/esm/datasource/CompositeDataSource.d.ts.map +1 -1
  49. package/dist/esm/datasource/errors.d.ts +9 -0
  50. package/dist/esm/datasource/errors.d.ts.map +1 -1
  51. package/dist/esm/datasource/index.d.ts +2 -2
  52. package/dist/esm/datasource/index.d.ts.map +1 -1
  53. package/dist/esm/index.d.ts +2 -2
  54. package/dist/esm/index.d.ts.map +1 -1
  55. package/dist/esm/index.mjs +201 -48
  56. package/dist/esm/index.mjs.map +1 -1
  57. package/dist/esm/internal/events/EventProcessor.d.ts +1 -1
  58. package/dist/esm/internal/events/EventProcessor.d.ts.map +1 -1
  59. package/dist/esm/internal/events/LDEventSummarizer.d.ts +32 -0
  60. package/dist/esm/internal/events/LDEventSummarizer.d.ts.map +1 -0
  61. package/dist/esm/internal/events/MultiEventSummarizer.d.ts +13 -0
  62. package/dist/esm/internal/events/MultiEventSummarizer.d.ts.map +1 -0
  63. package/dist/esm/internal/fdv2/payloadProcessor.d.ts.map +1 -1
  64. package/dist/esm/internal/fdv2/proto.d.ts +1 -1
  65. package/dist/esm/internal/fdv2/proto.d.ts.map +1 -1
  66. package/dist/esm/internal/index.d.ts +1 -0
  67. package/dist/esm/internal/index.d.ts.map +1 -1
  68. package/dist/esm/internal/json/canonicalize.d.ts +10 -0
  69. package/dist/esm/internal/json/canonicalize.d.ts.map +1 -0
  70. package/dist/esm/internal/json/index.d.ts +2 -0
  71. package/dist/esm/internal/json/index.d.ts.map +1 -0
  72. package/dist/esm/options/ServiceEndpoints.d.ts +2 -2
  73. package/dist/esm/options/ServiceEndpoints.d.ts.map +1 -1
  74. package/package.json +1 -1
@@ -115,6 +115,9 @@ class AttributeReference {
115
115
  return (this.depth === other.depth &&
116
116
  this._components.every((value, index) => value === other.getComponent(index)));
117
117
  }
118
+ get components() {
119
+ return [...this._components];
120
+ }
118
121
  }
119
122
  /**
120
123
  * For use as invalid references when deserializing Flag/Segment data.
@@ -314,6 +317,41 @@ function isLegacyUser(context) {
314
317
  return !('kind' in context) || context.kind === null || context.kind === undefined;
315
318
  }
316
319
 
320
+ /**
321
+ * Given some object to serialize product a canonicalized JSON string.
322
+ * https://www.rfc-editor.org/rfc/rfc8785.html
323
+ *
324
+ * We do not support custom toJSON methods on objects. Objects should be limited to basic types.
325
+ *
326
+ * @param object The object to serialize.
327
+ */
328
+ function canonicalize(object, visited = []) {
329
+ // For JavaScript the default JSON serialization will produce canonicalized output for basic types.
330
+ if (object === null || typeof object !== 'object') {
331
+ return JSON.stringify(object);
332
+ }
333
+ if (visited.includes(object)) {
334
+ throw new Error('Cycle detected');
335
+ }
336
+ if (Array.isArray(object)) {
337
+ const values = object
338
+ .map((item) => canonicalize(item, [...visited, object]))
339
+ .map((item) => (item === undefined ? 'null' : item));
340
+ return `[${values.join(',')}]`;
341
+ }
342
+ const values = Object.keys(object)
343
+ .sort()
344
+ .map((key) => {
345
+ const value = canonicalize(object[key], [...visited, object]);
346
+ if (value !== undefined) {
347
+ return `${JSON.stringify(key)}:${value}`;
348
+ }
349
+ return undefined;
350
+ })
351
+ .filter((item) => item !== undefined);
352
+ return `{${values.join(',')}}`;
353
+ }
354
+
317
355
  // The general strategy for the context is to transform the passed in context
318
356
  // as little as possible. We do convert the legacy users to a single kind
319
357
  // context, but we do not translate all passed contexts into a rigid structure.
@@ -688,6 +726,28 @@ class Context {
688
726
  get legacy() {
689
727
  return this._wasLegacy;
690
728
  }
729
+ /**
730
+ * Get the serialized canonical JSON for this context. This is not filtered for use in events.
731
+ *
732
+ * This method will cache the result.
733
+ *
734
+ * @returns The serialized canonical JSON or undefined if it cannot be serialized.
735
+ */
736
+ canonicalUnfilteredJson() {
737
+ if (!this.valid) {
738
+ return undefined;
739
+ }
740
+ if (this._cachedCanonicalJson) {
741
+ return this._cachedCanonicalJson;
742
+ }
743
+ try {
744
+ this._cachedCanonicalJson = canonicalize(Context.toLDContext(this));
745
+ }
746
+ catch {
747
+ // Indicated by undefined being returned.
748
+ }
749
+ return this._cachedCanonicalJson;
750
+ }
691
751
  }
692
752
  Context.UserKind = DEFAULT_KIND;
693
753
 
@@ -889,8 +949,6 @@ class CallbackHandler {
889
949
  if (this._disabled) {
890
950
  return;
891
951
  }
892
- // TODO: SDK-1044 track selector for future synchronizer to use
893
- // report data up
894
952
  this._dataCallback(basis, data);
895
953
  }
896
954
  async statusHandler(status, err) {
@@ -902,6 +960,11 @@ class CallbackHandler {
902
960
  }
903
961
 
904
962
  // TODO: refactor client-sdk to use this enum
963
+ /**
964
+ * @experimental
965
+ * This feature is not stable and not subject to any backwards compatibility guarantees or semantic
966
+ * versioning. It is not suitable for production usage.
967
+ */
905
968
  var DataSourceState;
906
969
  (function (DataSourceState) {
907
970
  // Positive confirmation of connection/data receipt
@@ -1002,6 +1065,43 @@ class DataSourceList {
1002
1065
  }
1003
1066
  }
1004
1067
 
1068
+ class LDFileDataSourceError extends Error {
1069
+ constructor(message) {
1070
+ super(message);
1071
+ this.name = 'LaunchDarklyFileDataSourceError';
1072
+ }
1073
+ }
1074
+ class LDPollingError extends Error {
1075
+ constructor(kind, message, status, recoverable = true) {
1076
+ super(message);
1077
+ this.kind = kind;
1078
+ this.status = status;
1079
+ this.name = 'LaunchDarklyPollingError';
1080
+ this.recoverable = recoverable;
1081
+ }
1082
+ }
1083
+ class LDStreamingError extends Error {
1084
+ constructor(kind, message, code, recoverable = true) {
1085
+ super(message);
1086
+ this.kind = kind;
1087
+ this.code = code;
1088
+ this.name = 'LaunchDarklyStreamingError';
1089
+ this.recoverable = recoverable;
1090
+ }
1091
+ }
1092
+ /**
1093
+ * This is a short term error and will be removed once FDv2 adoption is sufficient.
1094
+ */
1095
+ class LDFlagDeliveryFallbackError extends Error {
1096
+ constructor(kind, message, code) {
1097
+ super(message);
1098
+ this.kind = kind;
1099
+ this.code = code;
1100
+ this.name = 'LDFlagDeliveryFallbackError';
1101
+ this.recoverable = false;
1102
+ }
1103
+ }
1104
+
1005
1105
  const DEFAULT_FALLBACK_TIME_MS = 2 * 60 * 1000;
1006
1106
  const DEFAULT_RECOVERY_TIME_MS = 5 * 60 * 1000;
1007
1107
  /**
@@ -1012,8 +1112,12 @@ class CompositeDataSource {
1012
1112
  /**
1013
1113
  * @param initializers factories to create {@link DataSystemInitializer}s, in priority order.
1014
1114
  * @param synchronizers factories to create {@link DataSystemSynchronizer}s, in priority order.
1115
+ * @param fdv1Synchronizers factories to fallback to if we need to fallback to FDv1.
1116
+ * @param _logger for logging
1117
+ * @param _transitionConditions to control automated transition between datasources. Typically only used for testing.
1118
+ * @param _backoff to control delay between transitions. Typically only used for testing.
1015
1119
  */
1016
- constructor(initializers, synchronizers, _logger, _transitionConditions = {
1120
+ constructor(initializers, synchronizers, fdv1Synchronizers, _logger, _transitionConditions = {
1017
1121
  [DataSourceState.Valid]: {
1018
1122
  durationMS: DEFAULT_RECOVERY_TIME_MS,
1019
1123
  transition: 'recover',
@@ -1049,8 +1153,9 @@ class CompositeDataSource {
1049
1153
  this._initPhaseActive = initializers.length > 0; // init phase if we have initializers
1050
1154
  this._initFactories = new DataSourceList(false, initializers);
1051
1155
  this._syncFactories = new DataSourceList(true, synchronizers);
1156
+ this._fdv1Synchronizers = new DataSourceList(true, fdv1Synchronizers);
1052
1157
  }
1053
- async start(dataCallback, statusCallback) {
1158
+ async start(dataCallback, statusCallback, selectorGetter) {
1054
1159
  if (!this._stopped) {
1055
1160
  // don't allow multiple simultaneous runs
1056
1161
  this._logger?.info('CompositeDataSource already running. Ignoring call to start.');
@@ -1087,12 +1192,18 @@ class CompositeDataSource {
1087
1192
  // When we get a status update, we want to fallback if it is an error. We also want to schedule a transition for some
1088
1193
  // time in the future if this status remains for some duration (ex: Recover to primary synchronizer after the secondary
1089
1194
  // synchronizer has been Valid for some time). These scheduled transitions are configurable in the constructor.
1090
- this._logger?.debug(`CompositeDataSource received state ${state} from underlying data source.`);
1195
+ this._logger?.debug(`CompositeDataSource received state ${state} from underlying data source. Err is ${err}`);
1091
1196
  if (err || state === DataSourceState.Closed) {
1092
1197
  callbackHandler.disable();
1093
- if (err.recoverable === false) {
1198
+ if (err?.recoverable === false) {
1094
1199
  // don't use this datasource's factory again
1200
+ this._logger?.debug(`Culling data source due to err ${err}`);
1095
1201
  cullDSFactory?.();
1202
+ // this error indicates we should fallback to only using FDv1 synchronizers
1203
+ if (err instanceof LDFlagDeliveryFallbackError) {
1204
+ this._logger?.debug(`Falling back to FDv1`);
1205
+ this._syncFactories = this._fdv1Synchronizers;
1206
+ }
1096
1207
  }
1097
1208
  sanitizedStatusCallback(state, err);
1098
1209
  this._consumeCancelToken(cancelScheduledTransition);
@@ -1119,7 +1230,7 @@ class CompositeDataSource {
1119
1230
  }
1120
1231
  }
1121
1232
  });
1122
- currentDS.start((basis, data) => callbackHandler.dataHandler(basis, data), (status, err) => callbackHandler.statusHandler(status, err));
1233
+ currentDS.start((basis, data) => callbackHandler.dataHandler(basis, data), (status, err) => callbackHandler.statusHandler(status, err), selectorGetter);
1123
1234
  }
1124
1235
  else {
1125
1236
  // we don't have a data source to use!
@@ -1140,8 +1251,8 @@ class CompositeDataSource {
1140
1251
  // stop the underlying datasource before transitioning to next state
1141
1252
  currentDS?.stop();
1142
1253
  if (transitionRequest.err && transitionRequest.transition !== 'stop') {
1143
- // if the transition was due to an error, throttle the transition
1144
- const delay = this._backoff.fail();
1254
+ // if the transition was due to an error we're not in the initializer phase, throttle the transition. Fallback between initializers is not throttled.
1255
+ const delay = this._initPhaseActive ? 0 : this._backoff.fail();
1145
1256
  const { promise, cancel: cancelDelay } = this._cancellableDelay(delay);
1146
1257
  this._cancelTokens.push(cancelDelay);
1147
1258
  const delayedTransition = promise.then(() => {
@@ -1176,6 +1287,7 @@ class CompositeDataSource {
1176
1287
  this._initPhaseActive = this._initFactories.length() > 0; // init phase if we have initializers;
1177
1288
  this._initFactories.reset();
1178
1289
  this._syncFactories.reset();
1290
+ this._fdv1Synchronizers.reset();
1179
1291
  this._externalTransitionPromise = new Promise((tr) => {
1180
1292
  this._externalTransitionResolve = tr;
1181
1293
  });
@@ -1210,6 +1322,11 @@ class CompositeDataSource {
1210
1322
  break;
1211
1323
  case 'fallback':
1212
1324
  default:
1325
+ // if asked to fallback after using all init factories, switch to sync factories
1326
+ if (this._initPhaseActive && this._initFactories.pos() >= this._initFactories.length()) {
1327
+ this._initPhaseActive = false;
1328
+ this._syncFactories.reset();
1329
+ }
1213
1330
  if (this._initPhaseActive) {
1214
1331
  isPrimary = this._initFactories.pos() === 0;
1215
1332
  factory = this._initFactories.next();
@@ -1301,31 +1418,6 @@ var DataSourceErrorKind;
1301
1418
  DataSourceErrorKind["InvalidData"] = "INVALID_DATA";
1302
1419
  })(DataSourceErrorKind || (DataSourceErrorKind = {}));
1303
1420
 
1304
- class LDFileDataSourceError extends Error {
1305
- constructor(message) {
1306
- super(message);
1307
- this.name = 'LaunchDarklyFileDataSourceError';
1308
- }
1309
- }
1310
- class LDPollingError extends Error {
1311
- constructor(kind, message, status, recoverable = true) {
1312
- super(message);
1313
- this.kind = kind;
1314
- this.status = status;
1315
- this.name = 'LaunchDarklyPollingError';
1316
- this.recoverable = recoverable;
1317
- }
1318
- }
1319
- class LDStreamingError extends Error {
1320
- constructor(kind, message, code, recoverable = true) {
1321
- super(message);
1322
- this.kind = kind;
1323
- this.code = code;
1324
- this.name = 'LaunchDarklyStreamingError';
1325
- this.recoverable = recoverable;
1326
- }
1327
- }
1328
-
1329
1421
  /* eslint-disable import/prefer-default-export */
1330
1422
  /**
1331
1423
  * Enable / disable Auto environment attributes. When enabled, the SDK will automatically
@@ -1808,7 +1900,7 @@ class ServiceEndpoints {
1808
1900
  }
1809
1901
  // eslint-disable-next-line @typescript-eslint/naming-convention
1810
1902
  ServiceEndpoints.DEFAULT_EVENTS = 'https://events.launchdarkly.com';
1811
- function getWithParams(uri, parameters) {
1903
+ function getWithParams(uri, parameters = []) {
1812
1904
  if (parameters.length === 0) {
1813
1905
  return uri;
1814
1906
  }
@@ -1837,7 +1929,7 @@ function getStreamingUri(endpoints, path, parameters) {
1837
1929
  * @param path The path to the resource, devoid of any query parameters or hrefs.
1838
1930
  * @param parameters The query parameters. These query parameters must already have the appropriate encoding applied. This function WILL NOT apply it for you.
1839
1931
  */
1840
- function getPollingUri(endpoints, path, parameters) {
1932
+ function getPollingUri(endpoints, path, parameters = []) {
1841
1933
  const canonicalizedPath = canonicalizePath(path);
1842
1934
  const combinedParameters = [...parameters];
1843
1935
  if (endpoints.payloadFilterKey) {
@@ -1852,7 +1944,7 @@ function getPollingUri(endpoints, path, parameters) {
1852
1944
  * @param path The path to the resource, devoid of any query parameters or hrefs.
1853
1945
  * @param parameters The query parameters. These query parameters must already have the appropriate encoding applied. This function WILL NOT apply it for you.
1854
1946
  */
1855
- function getEventsUri(endpoints, path, parameters) {
1947
+ function getEventsUri(endpoints, path, parameters = []) {
1856
1948
  const canonicalizedPath = canonicalizePath(path);
1857
1949
  return getWithParams(`${endpoints.events}/${canonicalizedPath}`, parameters);
1858
1950
  }
@@ -2351,7 +2443,9 @@ function counterKey(event) {
2351
2443
  * @internal
2352
2444
  */
2353
2445
  class EventSummarizer {
2354
- constructor() {
2446
+ constructor(_singleContext = false, _contextFilter) {
2447
+ this._singleContext = _singleContext;
2448
+ this._contextFilter = _contextFilter;
2355
2449
  this._startDate = 0;
2356
2450
  this._endDate = 0;
2357
2451
  this._counters = {};
@@ -2359,6 +2453,9 @@ class EventSummarizer {
2359
2453
  }
2360
2454
  summarizeEvent(event) {
2361
2455
  if (isFeature(event) && !event.excludeFromSummaries) {
2456
+ if (!this._context) {
2457
+ this._context = event.context;
2458
+ }
2362
2459
  const countKey = counterKey(event);
2363
2460
  const counter = this._counters[countKey];
2364
2461
  let kinds = this._contextKinds[event.key];
@@ -2408,14 +2505,19 @@ class EventSummarizer {
2408
2505
  flagSummary.counters.push(counterOut);
2409
2506
  return acc;
2410
2507
  }, {});
2411
- return {
2508
+ const event = {
2412
2509
  startDate: this._startDate,
2413
2510
  endDate: this._endDate,
2414
2511
  features,
2415
2512
  kind: 'summary',
2513
+ context: this._context !== undefined && this._singleContext
2514
+ ? this._contextFilter?.filter(this._context)
2515
+ : undefined,
2416
2516
  };
2517
+ this._clearSummary();
2518
+ return event;
2417
2519
  }
2418
- clearSummary() {
2520
+ _clearSummary() {
2419
2521
  this._startDate = 0;
2420
2522
  this._endDate = 0;
2421
2523
  this._counters = {};
@@ -2430,6 +2532,38 @@ class LDInvalidSDKKeyError extends Error {
2430
2532
  }
2431
2533
  }
2432
2534
 
2535
+ class MultiEventSummarizer {
2536
+ constructor(_contextFilter, _logger) {
2537
+ this._contextFilter = _contextFilter;
2538
+ this._logger = _logger;
2539
+ this._summarizers = {};
2540
+ }
2541
+ summarizeEvent(event) {
2542
+ if (isFeature(event)) {
2543
+ const key = event.context.canonicalUnfilteredJson();
2544
+ if (!key) {
2545
+ if (event.context.valid) {
2546
+ // The context appeared valid, but it could not be hashed.
2547
+ // This is likely because of a cycle in the data.
2548
+ this._logger?.error('Unable to serialize context, likely the context contains a cycle.');
2549
+ }
2550
+ return;
2551
+ }
2552
+ let summarizer = this._summarizers[key];
2553
+ if (!summarizer) {
2554
+ this._summarizers[key] = new EventSummarizer(true, this._contextFilter);
2555
+ summarizer = this._summarizers[key];
2556
+ }
2557
+ summarizer.summarizeEvent(event);
2558
+ }
2559
+ }
2560
+ getSummaries() {
2561
+ const summarizersToFlush = this._summarizers;
2562
+ this._summarizers = {};
2563
+ return Object.values(summarizersToFlush).map((summarizer) => summarizer.getSummary());
2564
+ }
2565
+ }
2566
+
2433
2567
  /**
2434
2568
  * The contents of this file are for event sampling. They are not used for
2435
2569
  * any purpose requiring cryptographic security.
@@ -2450,12 +2584,14 @@ function shouldSample(ratio) {
2450
2584
  return Math.floor(Math.random() * truncated) === 0;
2451
2585
  }
2452
2586
 
2587
+ function isMultiEventSummarizer(summarizer) {
2588
+ return summarizer.getSummaries !== undefined;
2589
+ }
2453
2590
  class EventProcessor {
2454
- constructor(_config, clientContext, baseHeaders, _contextDeduplicator, _diagnosticsManager, start = true) {
2591
+ constructor(_config, clientContext, baseHeaders, _contextDeduplicator, _diagnosticsManager, start = true, summariesPerContext = false) {
2455
2592
  this._config = _config;
2456
2593
  this._contextDeduplicator = _contextDeduplicator;
2457
2594
  this._diagnosticsManager = _diagnosticsManager;
2458
- this._summarizer = new EventSummarizer();
2459
2595
  this._queue = [];
2460
2596
  this._lastKnownPastTime = 0;
2461
2597
  this._droppedEvents = 0;
@@ -2468,6 +2604,12 @@ class EventProcessor {
2468
2604
  this._logger = clientContext.basicConfiguration.logger;
2469
2605
  this._eventSender = new EventSender(clientContext, baseHeaders);
2470
2606
  this._contextFilter = new ContextFilter(_config.allAttributesPrivate, _config.privateAttributes.map((ref) => new AttributeReference(ref)));
2607
+ if (summariesPerContext) {
2608
+ this._summarizer = new MultiEventSummarizer(this._contextFilter, this._logger);
2609
+ }
2610
+ else {
2611
+ this._summarizer = new EventSummarizer();
2612
+ }
2471
2613
  if (start) {
2472
2614
  this.start();
2473
2615
  }
@@ -2519,10 +2661,19 @@ class EventProcessor {
2519
2661
  }
2520
2662
  const eventsToFlush = this._queue;
2521
2663
  this._queue = [];
2522
- const summary = this._summarizer.getSummary();
2523
- this._summarizer.clearSummary();
2524
- if (Object.keys(summary.features).length) {
2525
- eventsToFlush.push(summary);
2664
+ if (isMultiEventSummarizer(this._summarizer)) {
2665
+ const summaries = this._summarizer.getSummaries();
2666
+ summaries.forEach((summary) => {
2667
+ if (Object.keys(summary.features).length) {
2668
+ eventsToFlush.push(summary);
2669
+ }
2670
+ });
2671
+ }
2672
+ else {
2673
+ const summary = this._summarizer.getSummary();
2674
+ if (Object.keys(summary.features).length) {
2675
+ eventsToFlush.push(summary);
2676
+ }
2526
2677
  }
2527
2678
  if (!eventsToFlush.length) {
2528
2679
  return;
@@ -2833,7 +2984,7 @@ class PayloadProcessor {
2833
2984
  }
2834
2985
  // at the time of writing this, it was agreed upon that SDKs could assume exactly 1 element in this list. In the future, a negotiation of protocol version will be required to remove this assumption.
2835
2986
  const payload = data.payloads[0];
2836
- switch (payload?.code) {
2987
+ switch (payload?.intentCode) {
2837
2988
  case 'xfer-full':
2838
2989
  this._tempBasis = true;
2839
2990
  break;
@@ -2846,6 +2997,7 @@ class PayloadProcessor {
2846
2997
  break;
2847
2998
  default:
2848
2999
  // unrecognized intent code, return
3000
+ this._logger?.warn(`Unable to process intent code '${payload?.intentCode}'.`);
2849
3001
  return;
2850
3002
  }
2851
3003
  this._tempId = payload?.id;
@@ -3113,6 +3265,7 @@ var index = /*#__PURE__*/Object.freeze({
3113
3265
  NullEventProcessor: NullEventProcessor,
3114
3266
  PayloadProcessor: PayloadProcessor,
3115
3267
  PayloadStreamReader: PayloadStreamReader,
3268
+ canonicalize: canonicalize,
3116
3269
  initMetadataFromHeaders: initMetadataFromHeaders,
3117
3270
  isLegacyUser: isLegacyUser,
3118
3271
  isMultiKind: isMultiKind,
@@ -3123,5 +3276,5 @@ var index = /*#__PURE__*/Object.freeze({
3123
3276
  shouldSample: shouldSample
3124
3277
  });
3125
3278
 
3126
- export { ApplicationTags, AttributeReference, AutoEnvAttributes, BasicLogger, ClientContext, CompositeDataSource, Context, ContextFilter, DataSourceErrorKind, DateValidator, DefaultBackoff, FactoryOrInstance, Function, KindValidator, LDClientError, LDFileDataSourceError, LDPollingError, LDStreamingError, LDTimeoutError, LDUnexpectedResponseError, NullableBoolean, NumberWithMinimum, OptionMessages, SafeLogger, ServiceEndpoints, StringMatchingRegex, Type, TypeArray, TypeValidators, base64UrlEncode, cancelableTimedPromise, clone, createSafeLogger, debounce, deepCompact, defaultHeaders, fastDeepEqual, getEventsUri, getPollingUri, getStreamingUri, httpErrorMessage, index as internal, isHttpLocallyRecoverable, isHttpRecoverable, noop, secondsToMillis, shouldRetry, sleep, index$1 as subsystem, timedPromise };
3279
+ export { ApplicationTags, AttributeReference, AutoEnvAttributes, BasicLogger, ClientContext, CompositeDataSource, Context, ContextFilter, DataSourceErrorKind, DateValidator, DefaultBackoff, FactoryOrInstance, Function, KindValidator, LDClientError, LDFileDataSourceError, LDFlagDeliveryFallbackError, LDPollingError, LDStreamingError, LDTimeoutError, LDUnexpectedResponseError, NullableBoolean, NumberWithMinimum, OptionMessages, SafeLogger, ServiceEndpoints, StringMatchingRegex, Type, TypeArray, TypeValidators, base64UrlEncode, cancelableTimedPromise, clone, createSafeLogger, debounce, deepCompact, defaultHeaders, fastDeepEqual, getEventsUri, getPollingUri, getStreamingUri, httpErrorMessage, index as internal, isHttpLocallyRecoverable, isHttpRecoverable, noop, secondsToMillis, shouldRetry, sleep, index$1 as subsystem, timedPromise };
3127
3280
  //# sourceMappingURL=index.mjs.map