@salesforce/lds-runtime-aura 1.394.0 → 1.396.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.
@@ -340,7 +340,7 @@ let NetworkCommand$1 = class NetworkCommand extends BaseCommand {
340
340
  async afterRequestHooks(_options) {
341
341
  }
342
342
  };
343
- function buildServiceDescriptor$j() {
343
+ function buildServiceDescriptor$k() {
344
344
  return {
345
345
  type: "networkCommandBaseClass",
346
346
  version: "1.0",
@@ -442,7 +442,7 @@ class AuraNetworkCommand extends NetworkCommand$1 {
442
442
  return resolvedPromiseLike$3(err$1(toError("Aura/Fetch network services not found")));
443
443
  }
444
444
  }
445
- function buildServiceDescriptor$i() {
445
+ function buildServiceDescriptor$j() {
446
446
  return {
447
447
  type: "auraNetworkCommandBaseClass",
448
448
  version: "1.0",
@@ -614,6 +614,14 @@ class CacheControlRequestRunner {
614
614
  }
615
615
  }
616
616
  class CacheControlCommand extends BaseCommand {
617
+ /**
618
+ * Creates a new CacheControlCommand instance
619
+ *
620
+ * @param services - Required services including cache controller and optional pub/sub service
621
+ * @param services.cacheController - The cache controller service for managing cache operations
622
+ * @param services.pubSub - Optional pub/sub service for cache invalidation notifications
623
+ * @param services - Additional services specific to the implementation
624
+ */
617
625
  constructor(services) {
618
626
  super();
619
627
  this.services = services;
@@ -621,16 +629,31 @@ class CacheControlCommand extends BaseCommand {
621
629
  this.keysUpdated = void 0;
622
630
  this._isInternalExecution = false;
623
631
  this.lastResult = void 0;
624
- this.unsubscribeFromKeysImpl = () => void 0;
632
+ this.unsubscribers = [];
625
633
  this.subscriptions = [];
626
634
  this.instantiationTime = Date.now() / 1e3;
627
635
  }
628
636
  get isInternalExecution() {
629
637
  return this._isInternalExecution;
630
638
  }
639
+ /**
640
+ * Executes the cache control command with optional overrides
641
+ *
642
+ * This method orchestrates the cache control flow by:
643
+ * 1. Clearing any existing subscriptions
644
+ * 2. Merging configuration overrides with the base strategy config
645
+ * 3. Building a request runner for cache operations
646
+ * 4. Executing the cache controller with the request runner
647
+ * 5. Handling the result and setting up subscriptions if needed
648
+ *
649
+ * @param overrides - Optional execution overrides including timestamp and cache control config
650
+ * @param overrides.now - Override the current timestamp for cache control calculations
651
+ * @param overrides.cacheControlConfig - Override cache control strategy configuration
652
+ * @returns A subscribable result containing either the cached/network data or an error
653
+ */
631
654
  execute(overrides) {
632
655
  this.keysUpdated = void 0;
633
- this.unsubscribeFromKeys();
656
+ this.unsubscribe();
634
657
  const mergedCacheControlConfig = mergeCacheControlConfigs(
635
658
  this.cacheControlStrategyConfig,
636
659
  overrides
@@ -652,6 +675,17 @@ class CacheControlCommand extends BaseCommand {
652
675
  });
653
676
  });
654
677
  }
678
+ /**
679
+ * Handles the result from the cache controller and builds the appropriate subscribable result
680
+ *
681
+ * This method processes the cache controller execution result and determines the appropriate
682
+ * response based on network errors, cache errors, and available data. It handles graceful
683
+ * degradation scenarios where network data is available even when cache operations fail.
684
+ *
685
+ * @param result - The result from the cache controller execution
686
+ * @param requestRunner - The request runner containing network data and errors
687
+ * @returns A subscribable result with the appropriate data or error
688
+ */
655
689
  handleCacheControllerResult(result, requestRunner) {
656
690
  const { networkError, networkData, returnData } = requestRunner;
657
691
  return this.publishUpdatedKeys().then(() => {
@@ -687,11 +721,21 @@ class CacheControlCommand extends BaseCommand {
687
721
  );
688
722
  }
689
723
  if (this.subscriptions.length > 0) {
690
- this.subscribeToKeysUsed();
724
+ this.subscribe();
691
725
  }
692
726
  return returnData;
693
727
  });
694
728
  }
729
+ /**
730
+ * Builds a request runner that orchestrates cache read, network request, and cache write operations
731
+ *
732
+ * The request runner encapsulates the three main operations:
733
+ * 1. Reading from cache with subscription setup
734
+ * 2. Requesting data from the network
735
+ * 3. Writing network results to cache and recording keys
736
+ *
737
+ * @returns A configured request runner for the cache controller
738
+ */
695
739
  buildRequestRunner() {
696
740
  return new CacheControlRequestRunner(
697
741
  (cache) => this.buildResultWithSubscribe(cache),
@@ -699,6 +743,15 @@ class CacheControlCommand extends BaseCommand {
699
743
  (cache, networkResult) => this.writeToCacheAndRecordKeys(cache, networkResult)
700
744
  );
701
745
  }
746
+ /**
747
+ * Publishes cache update events for keys that were modified during the operation
748
+ *
749
+ * This method notifies other parts of the system about cache changes by publishing
750
+ * a 'cacheUpdate' event with the set of keys that were updated. This enables
751
+ * cache invalidation and reactive updates across the application.
752
+ *
753
+ * @returns A promise that resolves when the update event is published (or immediately if no pub/sub service)
754
+ */
702
755
  publishUpdatedKeys() {
703
756
  if (this.services.pubSub) {
704
757
  if (this.keysUpdated !== void 0 && this.keysUpdated.size > 0) {
@@ -713,11 +766,25 @@ class CacheControlCommand extends BaseCommand {
713
766
  get operationType() {
714
767
  return "query";
715
768
  }
716
- subscribeToKeysUsed() {
717
- this.unsubscribeFromKeys();
769
+ /**
770
+ * Subscribes to cache update and invalidation events for reactive updates
771
+ *
772
+ * This method sets up subscriptions to listen for changes that affect the data returned
773
+ * by this Command.
774
+ *
775
+ * By default, it subscribes to two types of events on the PubSub service:
776
+ * - 'cacheUpdate': Triggers a rebuild with the original instantiation time
777
+ * - 'cacheInvalidation': Triggers a full refresh without time constraints
778
+ *
779
+ * This method can be extended by subclasses to add additional subscriptions.
780
+ *
781
+ * Note: ALL subscriptions should push an unsubscribe function to the unsubscribers array,
782
+ * for the lifecycle to work correctly and avoid memory leaks.
783
+ */
784
+ subscribe() {
785
+ this.unsubscribe();
718
786
  const { pubSub } = this.services;
719
787
  if (!pubSub) {
720
- this.unsubscribeFromKeysImpl = () => void 0;
721
788
  return;
722
789
  }
723
790
  const rebuildUnsubscribe = pubSub.subscribe({
@@ -732,21 +799,58 @@ class CacheControlCommand extends BaseCommand {
732
799
  callback: () => this.rerun().then(() => void 0),
733
800
  keys: this.keysUsed
734
801
  });
735
- this.unsubscribeFromKeysImpl = () => {
736
- rebuildUnsubscribe();
737
- refreshUnsubscribe();
738
- };
739
- return;
802
+ this.unsubscribers.push(rebuildUnsubscribe, refreshUnsubscribe);
740
803
  }
741
- unsubscribeFromKeys() {
742
- this.unsubscribeFromKeysImpl();
804
+ /**
805
+ * Unsubscribes from all stored subscriptions
806
+ *
807
+ * This method calls all stored unsubscribe functions to clean up event listeners
808
+ * and prevent memory leaks. It should be called when the command is no longer
809
+ * needed and is also called before setting up new subscriptions.
810
+ */
811
+ unsubscribe() {
812
+ while (this.unsubscribers.length > 0) {
813
+ const unsubscriber = this.unsubscribers.pop();
814
+ unsubscriber == null ? void 0 : unsubscriber();
815
+ }
743
816
  }
744
- // TODO: This should likely be abstract in v2. For v1, provide default comparison logic.
817
+ /**
818
+ * Compares two result values for equality to determine if a cache update should trigger a rerun
819
+ *
820
+ * This method is used to prevent unnecessary reruns when the cached data hasn't actually changed.
821
+ * The default implementation uses deep equality comparison, but subclasses can override this
822
+ * to provide more efficient or domain-specific comparison logic.
823
+ *
824
+ * @param result1 - The first result to compare
825
+ * @param result2 - The second result to compare
826
+ * @returns True if the results are equal, false otherwise
827
+ *
828
+ * @todo This should likely be abstract in v2. For v1, provide default comparison logic.
829
+ */
745
830
  equals(result1, result2) {
746
831
  return deepEquals$1(result1, result2);
747
832
  }
833
+ /**
834
+ * Hook method called after a network request completes
835
+ *
836
+ * This method provides a point for subclasses to perform post-request operations
837
+ * such as logging, metrics collection, or cleanup. The default implementation
838
+ * is empty and can be overridden by subclasses as needed.
839
+ *
840
+ * @param _options - Request completion options
841
+ * @param _options.statusCode - HTTP status code from the network response
842
+ */
748
843
  async afterRequestHooks(_options) {
749
844
  }
845
+ /**
846
+ * Forces a refresh of the cached data by bypassing cache and fetching from network
847
+ *
848
+ * This method executes the command with a "no-cache" configuration, ensuring that
849
+ * fresh data is fetched from the network regardless of cache state. It's useful
850
+ * for scenarios where you need to ensure the most up-to-date data.
851
+ *
852
+ * @returns A refresh result indicating success or failure of the refresh operation
853
+ */
750
854
  refresh() {
751
855
  return this.rerun({ cacheControlConfig: { type: "no-cache" } }).then((result) => {
752
856
  if (result.isErr()) {
@@ -755,6 +859,17 @@ class CacheControlCommand extends BaseCommand {
755
859
  return ok$1(void 0);
756
860
  });
757
861
  }
862
+ /**
863
+ * Writes network result to cache and records the keys that were updated
864
+ *
865
+ * This method wraps the cache write operation with key tracking functionality.
866
+ * It uses a recordable cache wrapper to capture which keys are modified during
867
+ * the write operation, then updates the internal tracking of used and updated keys.
868
+ *
869
+ * @param cache - The cache instance to write to
870
+ * @param networkResult - The network result containing data to write to cache
871
+ * @returns A result indicating success or failure of the write operation
872
+ */
758
873
  writeToCacheAndRecordKeys(cache, networkResult) {
759
874
  const recordableCache = cache.record();
760
875
  return this.writeToCache(recordableCache, networkResult).then((result) => {
@@ -763,6 +878,16 @@ class CacheControlCommand extends BaseCommand {
763
878
  return ok$1(result);
764
879
  });
765
880
  }
881
+ /**
882
+ * Builds a subscribable result by reading from cache and setting up subscriptions
883
+ *
884
+ * This method reads data from the cache and wraps the result in a subscribable
885
+ * structure that allows consumers to subscribe to updates. It also tracks which
886
+ * cache keys were read for future invalidation purposes.
887
+ *
888
+ * @param cache - The readonly cache to read from
889
+ * @returns A subscribable result containing the cached data or error
890
+ */
766
891
  buildResultWithSubscribe(cache) {
767
892
  const recordableCache = cache.record();
768
893
  const result = this.readFromCache(recordableCache);
@@ -790,23 +915,35 @@ class CacheControlCommand extends BaseCommand {
790
915
  * the last known value. If a change is detected, the provided
791
916
  * callback is invoked.
792
917
  *
793
- * @param keysRead - keys of interest that were read during readFromCache
794
918
  * @returns an unsubscribe function to stop watching for updates
795
919
  */
796
920
  buildSubscribe() {
797
921
  return (consumerCallback) => {
798
922
  if (this.subscriptions.length === 0 && this.operationType === "query") {
799
- this.subscribeToKeysUsed();
923
+ this.subscribe();
800
924
  }
801
925
  this.subscriptions.push(consumerCallback);
802
926
  return () => {
803
927
  this.subscriptions = this.subscriptions.filter((cb) => cb !== consumerCallback);
804
928
  if (this.subscriptions.length === 0) {
805
- this.unsubscribeFromKeys();
929
+ this.unsubscribe();
806
930
  }
807
931
  };
808
932
  };
809
933
  }
934
+ /**
935
+ * Re-runs the command execution with optional overrides and notifies subscribers of changes
936
+ *
937
+ * This method is called internally when cache updates occur that affect the command's data.
938
+ * It executes the command with the provided overrides and compares the result with the
939
+ * last known result. If the data has changed, it notifies all subscribers with the new data.
940
+ *
941
+ * The method handles deduplication to prevent unnecessary notifications when the data
942
+ * hasn't actually changed, and properly manages the internal execution state.
943
+ *
944
+ * @param overrides - Optional execution overrides for the rerun
945
+ * @returns A promise that resolves to the execution result
946
+ */
810
947
  rerun(overrides) {
811
948
  this._isInternalExecution = true;
812
949
  return this.execute(overrides).then((result) => {
@@ -823,6 +960,15 @@ class CacheControlCommand extends BaseCommand {
823
960
  return result;
824
961
  });
825
962
  }
963
+ /**
964
+ * Invokes all registered consumer callbacks with the provided data
965
+ *
966
+ * This private method safely calls all registered subscriber callbacks with the
967
+ * provided result data. It includes error handling to prevent callback failures
968
+ * from affecting other callbacks or the overall system.
969
+ *
970
+ * @param data - The result data to send to all subscribers
971
+ */
826
972
  invokeConsumerCallbacks(data) {
827
973
  this.subscriptions.forEach((cb) => {
828
974
  try {
@@ -984,7 +1130,7 @@ class AuraResourceCacheControlCommand extends AuraCacheControlCommand$1 {
984
1130
  return `{"endpoint":${this.endpoint},"params":${stableJSONStringify$2(this.auraParams)}}`;
985
1131
  }
986
1132
  }
987
- function buildServiceDescriptor$h() {
1133
+ function buildServiceDescriptor$i() {
988
1134
  return {
989
1135
  type: "auraResourceCacheControlCommand",
990
1136
  version: "1.0",
@@ -1123,7 +1269,7 @@ class AuraNormalizedCacheControlCommand extends AuraCacheControlCommand {
1123
1269
  return resolvedPromiseLike$3(void 0);
1124
1270
  }
1125
1271
  }
1126
- function buildServiceDescriptor$g() {
1272
+ function buildServiceDescriptor$h() {
1127
1273
  return {
1128
1274
  type: "auraNormalizedCacheControlCommand",
1129
1275
  version: "1.0",
@@ -1212,7 +1358,7 @@ class HttpNormalizedCacheControlCommand extends HttpCacheControlCommand {
1212
1358
  return resolvedPromiseLike$3(void 0);
1213
1359
  }
1214
1360
  }
1215
- function buildServiceDescriptor$f() {
1361
+ function buildServiceDescriptor$g() {
1216
1362
  return {
1217
1363
  type: "httpNormalizedCacheControlCommand",
1218
1364
  version: "1.0",
@@ -1390,7 +1536,7 @@ _FetchNetworkCommand.availableDecorators = {
1390
1536
  abortable: createAbortableDecorator
1391
1537
  };
1392
1538
  let FetchNetworkCommand = _FetchNetworkCommand;
1393
- function buildServiceDescriptor$e() {
1539
+ function buildServiceDescriptor$f() {
1394
1540
  return {
1395
1541
  type: "fetchNetworkCommandBaseClass",
1396
1542
  version: "1.0",
@@ -1426,7 +1572,7 @@ class StreamingCommand extends BaseCommand {
1426
1572
  );
1427
1573
  }
1428
1574
  }
1429
- function buildServiceDescriptor$d() {
1575
+ function buildServiceDescriptor$e() {
1430
1576
  return {
1431
1577
  type: "streamingCommandBaseClass",
1432
1578
  version: "1.0",
@@ -1509,7 +1655,7 @@ class SSEParsingStream extends TransformStream {
1509
1655
  });
1510
1656
  }
1511
1657
  }
1512
- function buildServiceDescriptor$c() {
1658
+ function buildServiceDescriptor$d() {
1513
1659
  return {
1514
1660
  type: "SSECommandBaseClass",
1515
1661
  version: "1.0",
@@ -1555,7 +1701,7 @@ function buildInstrumentCommand(services) {
1555
1701
  };
1556
1702
  };
1557
1703
  }
1558
- function buildServiceDescriptor$b(instrumentation) {
1704
+ function buildServiceDescriptor$c(instrumentation) {
1559
1705
  return {
1560
1706
  type: "instrumentCommand",
1561
1707
  version: "1.0",
@@ -1825,7 +1971,7 @@ class O11yInstrumentation {
1825
1971
  this.metrics = new O11yOTelMetricsAPI(this.services);
1826
1972
  }
1827
1973
  }
1828
- function buildServiceDescriptor$a(logger) {
1974
+ function buildServiceDescriptor$b(logger) {
1829
1975
  return {
1830
1976
  type: "instrumentation",
1831
1977
  version: "1.0",
@@ -2078,7 +2224,7 @@ class DefaultCache {
2078
2224
  return new FixedTimeWritableCache(this, generatedTime);
2079
2225
  }
2080
2226
  }
2081
- function buildServiceDescriptor$9() {
2227
+ function buildServiceDescriptor$a() {
2082
2228
  return {
2083
2229
  type: "cache",
2084
2230
  version: "1.0",
@@ -2301,7 +2447,7 @@ class CacheController {
2301
2447
  yield* this.services.cacheInclusionPolicy.findAndModify(query, cacheUpdate);
2302
2448
  }
2303
2449
  }
2304
- function buildServiceDescriptor$8(cache, cacheInclusionPolicy, instrumentation) {
2450
+ function buildServiceDescriptor$9(cache, cacheInclusionPolicy, instrumentation) {
2305
2451
  return {
2306
2452
  type: "cacheController",
2307
2453
  version: "1.0",
@@ -2411,7 +2557,7 @@ class DefaultPubSubService {
2411
2557
  return matchingSubscriptions;
2412
2558
  }
2413
2559
  }
2414
- function buildServiceDescriptor$7() {
2560
+ function buildServiceDescriptor$8() {
2415
2561
  return {
2416
2562
  type: "pubSub",
2417
2563
  version: "1.0",
@@ -2474,7 +2620,7 @@ class NDJSONParsingStream extends TransformStream {
2474
2620
  });
2475
2621
  }
2476
2622
  }
2477
- function buildServiceDescriptor$6() {
2623
+ function buildServiceDescriptor$7() {
2478
2624
  return {
2479
2625
  type: "NDJSONCommandBaseClass",
2480
2626
  version: "1.0",
@@ -2515,7 +2661,7 @@ function buildServiceDescriptor$6() {
2515
2661
  * };
2516
2662
  * ```
2517
2663
  */
2518
- function buildServiceDescriptor$5(luvio) {
2664
+ function buildServiceDescriptor$6(luvio) {
2519
2665
  return {
2520
2666
  type: 'luvio',
2521
2667
  version: '1.0',
@@ -2524,7 +2670,7 @@ function buildServiceDescriptor$5(luvio) {
2524
2670
  },
2525
2671
  };
2526
2672
  }
2527
- // version: 1.394.0-db58817a4e
2673
+ // version: 1.396.0-216c6e4547
2528
2674
 
2529
2675
  /*!
2530
2676
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -2682,13 +2828,13 @@ class AuraGraphQLNormalizedCacheControlCommand extends AuraNormalizedCacheContro
2682
2828
  return this.runOriginalRequest();
2683
2829
  }
2684
2830
  if (this.subscriptions.length > 0) {
2685
- this.subscribeToKeysUsed();
2831
+ this.subscribe();
2686
2832
  }
2687
2833
  return returnData;
2688
2834
  });
2689
2835
  }
2690
2836
  }
2691
- function buildServiceDescriptor$4() {
2837
+ function buildServiceDescriptor$5() {
2692
2838
  return {
2693
2839
  type: "auraGraphQLNormalizedCacheControlCommand",
2694
2840
  version: "1.0",
@@ -2800,13 +2946,13 @@ class HttpGraphQLNormalizedCacheControlCommand extends HttpNormalizedCacheContro
2800
2946
  return this.runOriginalRequest();
2801
2947
  }
2802
2948
  if (this.subscriptions.length > 0) {
2803
- this.subscribeToKeysUsed();
2949
+ this.subscribe();
2804
2950
  }
2805
2951
  return returnData;
2806
2952
  });
2807
2953
  }
2808
2954
  }
2809
- function buildServiceDescriptor$3() {
2955
+ function buildServiceDescriptor$4() {
2810
2956
  return {
2811
2957
  type: "httpGraphQLNormalizedCacheControlCommand",
2812
2958
  version: "1.0",
@@ -2830,7 +2976,7 @@ class FeatureFlagsService {
2830
2976
  return this.flags.get(flagName) || defaultValue;
2831
2977
  }
2832
2978
  }
2833
- function buildServiceDescriptor$2() {
2979
+ function buildServiceDescriptor$3() {
2834
2980
  return {
2835
2981
  version: "1.0",
2836
2982
  service: new FeatureFlagsService(),
@@ -2852,7 +2998,7 @@ function buildServiceDescriptor$2() {
2852
2998
  * *******************************************************************************************
2853
2999
  */
2854
3000
  /* proxy-compat-disable */
2855
- function buildServiceDescriptor$1(notifyRecordUpdateAvailable, getNormalizedLuvioRecord) {
3001
+ function buildServiceDescriptor$2(notifyRecordUpdateAvailable, getNormalizedLuvioRecord) {
2856
3002
  return {
2857
3003
  type: 'luvioUiapiRecords',
2858
3004
  version: '1.0',
@@ -2862,7 +3008,57 @@ function buildServiceDescriptor$1(notifyRecordUpdateAvailable, getNormalizedLuvi
2862
3008
  },
2863
3009
  };
2864
3010
  }
2865
- // version: 1.394.0-db58817a4e
3011
+ // version: 1.396.0-216c6e4547
3012
+
3013
+ /*!
3014
+ * Copyright (c) 2022, Salesforce, Inc.,
3015
+ * All rights reserved.
3016
+ * For full license text, see the LICENSE.txt file
3017
+ */
3018
+ class RetryService {
3019
+ constructor(defaultRetryPolicy) {
3020
+ this.defaultRetryPolicy = defaultRetryPolicy;
3021
+ }
3022
+ applyRetry(operation, retryPolicyOverride) {
3023
+ return this.retry(operation, retryPolicyOverride || this.defaultRetryPolicy);
3024
+ }
3025
+ async retry(operation, policy) {
3026
+ const startTime = Date.now();
3027
+ let attempt = 0;
3028
+ let result = await operation();
3029
+ let context = {
3030
+ attempt,
3031
+ totalElapsedMs: Date.now() - startTime,
3032
+ lastResult: result
3033
+ };
3034
+ while (policy.shouldRetry(result, context)) {
3035
+ const delay = policy.calculateDelay(result, context);
3036
+ await this.delay(delay);
3037
+ attempt++;
3038
+ result = await operation();
3039
+ context = {
3040
+ attempt,
3041
+ totalElapsedMs: Date.now() - startTime,
3042
+ lastResult: result
3043
+ };
3044
+ }
3045
+ return result;
3046
+ }
3047
+ delay(ms) {
3048
+ return new Promise((resolve) => {
3049
+ setTimeout(resolve, ms);
3050
+ });
3051
+ }
3052
+ }
3053
+ class RetryPolicy {
3054
+ }
3055
+ function buildServiceDescriptor$1(defaultRetryPolicy) {
3056
+ return {
3057
+ version: "1.0",
3058
+ service: new RetryService(defaultRetryPolicy),
3059
+ type: "retry"
3060
+ };
3061
+ }
2866
3062
 
2867
3063
  /*!
2868
3064
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -3203,7 +3399,7 @@ class JwtManager {
3203
3399
  * All rights reserved.
3204
3400
  * For full license text, see the LICENSE.txt file
3205
3401
  */
3206
- function buildServiceDescriptor(interceptors = { request: [], response: [] }) {
3402
+ function buildServiceDescriptor(interceptors = { request: [], response: [] }, retryService) {
3207
3403
  return {
3208
3404
  type: "fetch",
3209
3405
  version: "1.0",
@@ -3213,7 +3409,12 @@ function buildServiceDescriptor(interceptors = { request: [], response: [] }) {
3213
3409
  (previousPromise, interceptor) => previousPromise.then(interceptor),
3214
3410
  resolvedPromiseLike$3(args)
3215
3411
  );
3216
- return pending.then((args2) => fetch(...args2)).then((response) => {
3412
+ return pending.then((args2) => {
3413
+ if (retryService) {
3414
+ return retryService.applyRetry(() => fetch(...args2));
3415
+ }
3416
+ return fetch(...args2);
3417
+ }).then((response) => {
3217
3418
  return responseInterceptors.reduce(
3218
3419
  (previousPromise, interceptor) => previousPromise.then(interceptor),
3219
3420
  resolvedPromiseLike$3(response)
@@ -6364,7 +6565,7 @@ function getEnvironmentSetting(name) {
6364
6565
  }
6365
6566
  return undefined;
6366
6567
  }
6367
- // version: 1.394.0-db58817a4e
6568
+ // version: 1.396.0-216c6e4547
6368
6569
 
6369
6570
  const forceRecordTransactionsDisabled = getEnvironmentSetting(EnvironmentSettings.ForceRecordTransactionsDisabled);
6370
6571
  //TODO: Some duplication here that can be most likely moved to a util class
@@ -7066,29 +7267,96 @@ function buildInMemoryCacheInclusionPolicyService(cache) {
7066
7267
  };
7067
7268
  }
7068
7269
 
7069
- function buildLexRuntimeDefaultFetchServiceDescriptor(logger) {
7270
+ function buildLexRuntimeDefaultFetchServiceDescriptor(logger, retryService) {
7070
7271
  const fetchService = buildServiceDescriptor({
7071
7272
  request: [],
7072
7273
  response: [
7073
7274
  buildLexRuntime5xxStatusResponseInterceptor(logger),
7074
7275
  buildLexRuntimeAuthExpirationRedirectResponseInterceptor(logger),
7075
7276
  ],
7076
- });
7277
+ }, retryService);
7077
7278
  return {
7078
7279
  ...fetchService,
7079
7280
  };
7080
7281
  }
7081
- function buildLexRuntimeAllow5xxFetchServiceDescriptor(logger) {
7282
+ function buildLexRuntimeAllow5xxFetchServiceDescriptor(logger, retryService) {
7082
7283
  const fetchService = buildServiceDescriptor({
7083
7284
  request: [],
7084
7285
  response: [buildLexRuntimeAuthExpirationRedirectResponseInterceptor(logger)],
7085
- });
7286
+ }, retryService);
7086
7287
  return {
7087
7288
  ...fetchService,
7088
7289
  tags: { interceptors: 'allow_500s' },
7089
7290
  };
7090
7291
  }
7091
7292
 
7293
+ const DEFAULT_CONFIG = {
7294
+ maxRetries: 3,
7295
+ maxTimeToRetry: 10000,
7296
+ baseDelay: 250,
7297
+ maxDelay: 5000,
7298
+ exponentialFactor: 2,
7299
+ jitterPercent: 0.5,
7300
+ };
7301
+ class Fetch429RetryPolicy extends RetryPolicy {
7302
+ constructor(config = DEFAULT_CONFIG) {
7303
+ super();
7304
+ this.config = config;
7305
+ }
7306
+ shouldRetry(result, context) {
7307
+ return (result.status === 429 &&
7308
+ context.attempt < this.config.maxRetries &&
7309
+ context.totalElapsedMs <= this.config.maxTimeToRetry);
7310
+ }
7311
+ calculateDelay(result, context) {
7312
+ let delay;
7313
+ // If retry-after header is present and valid, use it
7314
+ const retryAfterHeader = this.parseRetryAfterHeader(result);
7315
+ if (retryAfterHeader !== undefined) {
7316
+ delay = Math.min(retryAfterHeader, this.config.maxDelay);
7317
+ }
7318
+ else {
7319
+ // Exponential backoff
7320
+ delay = Math.min(this.config.baseDelay * Math.pow(this.config.exponentialFactor, context.attempt), this.config.maxDelay);
7321
+ }
7322
+ // Add jitter to prevent thundering herd
7323
+ const jitter = delay * this.config.jitterPercent * (Math.random() - 0.5);
7324
+ return Math.max(0, delay + jitter);
7325
+ }
7326
+ parseRetryAfterHeader(result) {
7327
+ if (!result.headers) {
7328
+ return undefined;
7329
+ }
7330
+ const value = result.headers.get('Retry-After');
7331
+ if (!value) {
7332
+ return undefined;
7333
+ }
7334
+ // The Retry-After header can be either a number of seconds or an HTTP-date (IMF-fixdate)
7335
+ // Retry-After: <delay-seconds>
7336
+ // Retry-After: <http-date>
7337
+ const trimmed = value.trim();
7338
+ // Strictly treat only all-digits as seconds
7339
+ if (/^\d+$/.test(trimmed)) {
7340
+ const seconds = Number(trimmed);
7341
+ if (Number.isFinite(seconds) && seconds >= 0) {
7342
+ return seconds * 1000; // Convert to milliseconds
7343
+ }
7344
+ return undefined;
7345
+ }
7346
+ // Strict RFC 7231 IMF-fixdate format (e.g., "Sun, 06 Nov 1994 08:49:37 GMT")
7347
+ const IMF_FIXDATE = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), \d{2} (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{4} \d{2}:\d{2}:\d{2} GMT$/;
7348
+ if (!IMF_FIXDATE.test(trimmed)) {
7349
+ return undefined;
7350
+ }
7351
+ // Use Date.parse to avoid any engine-specific fallbacks
7352
+ const millis = Date.parse(trimmed);
7353
+ if (Number.isFinite(millis)) {
7354
+ return Math.max(0, millis - Date.now());
7355
+ }
7356
+ return undefined;
7357
+ }
7358
+ }
7359
+
7092
7360
  // This code *should* be in lds-network-adapter, but when combined with the Aura
7093
7361
  // component test workaround in lds-default-luvio it creates a circular dependecy
7094
7362
  // between lds-default-luvio and lds-network-adapter. We do the register on behalf
@@ -7350,12 +7618,12 @@ function initializeLDS() {
7350
7618
  // Initializes OneStore in LEX
7351
7619
  function initializeOneStore(luvio) {
7352
7620
  const loggerService = new ConsoleLogger$1('ERROR');
7353
- const cacheServiceDescriptor = buildServiceDescriptor$9();
7354
- const instrumentationServiceDescriptor = buildServiceDescriptor$a(loggerService);
7621
+ const cacheServiceDescriptor = buildServiceDescriptor$a();
7622
+ const instrumentationServiceDescriptor = buildServiceDescriptor$b(loggerService);
7355
7623
  const inMemoryCacheInclusionPolicyServiceDescriptor = buildInMemoryCacheInclusionPolicyService(cacheServiceDescriptor.service);
7356
- const featureFlagsServiceDescriptor = buildServiceDescriptor$2();
7624
+ const featureFlagsServiceDescriptor = buildServiceDescriptor$3();
7357
7625
  const featureFlagsService = featureFlagsServiceDescriptor.service;
7358
- const luvioUiapiRecordsServiceDescriptor = buildServiceDescriptor$1((configs) => {
7626
+ const luvioUiapiRecordsServiceDescriptor = buildServiceDescriptor$2((configs) => {
7359
7627
  return notifyUpdateAvailableFactory(luvio)(configs);
7360
7628
  }, (recordId, reader) => {
7361
7629
  const recordKey = buildRecordRepKeyFromId(recordId);
@@ -7374,33 +7642,37 @@ function initializeOneStore(luvio) {
7374
7642
  reader.unMarkMissing();
7375
7643
  return linkedData.data;
7376
7644
  });
7645
+ const retryPolicy = new Fetch429RetryPolicy();
7646
+ const retryServiceDescriptor = buildServiceDescriptor$1(retryPolicy);
7647
+ const retryService = retryServiceDescriptor.service;
7377
7648
  // set flags based on gates
7378
7649
  featureFlagsService.set('useOneStoreGraphQL', useOneStoreGraphql.isOpen({ fallback: false }));
7379
7650
  const services = [
7380
7651
  instrumentationServiceDescriptor,
7652
+ buildLexRuntimeDefaultFetchServiceDescriptor(loggerService, retryService),
7381
7653
  buildUnauthorizedFetchServiceDescriptor(),
7382
7654
  buildJwtAuthorizedSfapFetchServiceDescriptor(loggerService),
7383
7655
  buildCopilotFetchServiceDescriptor(loggerService),
7384
7656
  buildAuraNetworkService(),
7385
- buildServiceDescriptor$b(instrumentationServiceDescriptor.service),
7386
- buildServiceDescriptor$8(cacheServiceDescriptor.service, inMemoryCacheInclusionPolicyServiceDescriptor.service, instrumentationServiceDescriptor.service),
7387
- buildServiceDescriptor$i(),
7388
- buildServiceDescriptor$6(),
7389
- buildServiceDescriptor$e(),
7657
+ buildServiceDescriptor$c(instrumentationServiceDescriptor.service),
7658
+ buildServiceDescriptor$9(cacheServiceDescriptor.service, inMemoryCacheInclusionPolicyServiceDescriptor.service, instrumentationServiceDescriptor.service),
7390
7659
  buildServiceDescriptor$j(),
7660
+ buildServiceDescriptor$7(),
7661
+ buildServiceDescriptor$f(),
7662
+ buildServiceDescriptor$k(),
7663
+ buildServiceDescriptor$e(),
7391
7664
  buildServiceDescriptor$d(),
7392
- buildServiceDescriptor$c(),
7665
+ buildServiceDescriptor$i(),
7393
7666
  buildServiceDescriptor$h(),
7394
7667
  buildServiceDescriptor$g(),
7395
- buildServiceDescriptor$f(),
7396
- buildServiceDescriptor$7(),
7397
- buildLexRuntimeDefaultFetchServiceDescriptor(loggerService),
7398
- buildLexRuntimeAllow5xxFetchServiceDescriptor(loggerService),
7399
- buildServiceDescriptor$5(luvio),
7668
+ buildServiceDescriptor$8(),
7669
+ buildLexRuntimeAllow5xxFetchServiceDescriptor(loggerService, retryService),
7670
+ buildServiceDescriptor$6(luvio),
7400
7671
  luvioUiapiRecordsServiceDescriptor,
7672
+ buildServiceDescriptor$5(),
7401
7673
  buildServiceDescriptor$4(),
7402
- buildServiceDescriptor$3(),
7403
7674
  featureFlagsServiceDescriptor,
7675
+ retryServiceDescriptor,
7404
7676
  ];
7405
7677
  setServices(services);
7406
7678
  }
@@ -7420,4 +7692,4 @@ function ldsEngineCreator() {
7420
7692
  }
7421
7693
 
7422
7694
  export { LexRequestStrategy, PdlRequestPriority, buildPredictorForContext, ldsEngineCreator as default, initializeLDS, initializeOneStore, notifyUpdateAvailableFactory, registerRequestStrategy, saveRequestAsPrediction, unregisterRequestStrategy, whenPredictionsReady };
7423
- // version: 1.394.0-9f5a21c62e
7695
+ // version: 1.396.0-08650966f4
@@ -1,4 +1,5 @@
1
1
  import { type LoggerService } from '@luvio/utils';
2
2
  import { type FetchServiceDescriptor } from '@luvio/service-fetch-network/v1';
3
- export declare function buildLexRuntimeDefaultFetchServiceDescriptor(logger: LoggerService): FetchServiceDescriptor;
4
- export declare function buildLexRuntimeAllow5xxFetchServiceDescriptor(logger: LoggerService): FetchServiceDescriptor;
3
+ import { RetryService } from '@luvio/service-retry/v1';
4
+ export declare function buildLexRuntimeDefaultFetchServiceDescriptor(logger: LoggerService, retryService?: RetryService<Response>): FetchServiceDescriptor;
5
+ export declare function buildLexRuntimeAllow5xxFetchServiceDescriptor(logger: LoggerService, retryService?: RetryService<Response>): FetchServiceDescriptor;
@@ -0,0 +1,17 @@
1
+ import { RetryPolicy, RetryContext } from '@luvio/service-retry/v1';
2
+ type Fetch429RetryPolicyConfig = {
3
+ maxRetries: number;
4
+ maxTimeToRetry: number;
5
+ baseDelay: number;
6
+ maxDelay: number;
7
+ exponentialFactor: number;
8
+ jitterPercent: number;
9
+ };
10
+ export declare class Fetch429RetryPolicy extends RetryPolicy<Response> {
11
+ private config;
12
+ constructor(config?: Fetch429RetryPolicyConfig);
13
+ shouldRetry(result: Response, context: RetryContext<Response>): boolean;
14
+ calculateDelay(result: Response, context: RetryContext<Response>): number;
15
+ parseRetryAfterHeader(result: Response): number | undefined;
16
+ }
17
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/lds-runtime-aura",
3
- "version": "1.394.0",
3
+ "version": "1.396.0",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "description": "LDS engine for Aura runtime",
6
6
  "main": "dist/ldsEngineCreator.js",
@@ -34,47 +34,47 @@
34
34
  "release:corejar": "yarn build && ../core-build/scripts/core.js --name=lds-runtime-aura"
35
35
  },
36
36
  "devDependencies": {
37
- "@luvio/service-provisioner": "5.64.2",
38
- "@luvio/tools-core": "5.64.2",
39
- "@salesforce/lds-adapters-apex": "^1.394.0",
40
- "@salesforce/lds-adapters-uiapi": "^1.394.0",
41
- "@salesforce/lds-ads-bridge": "^1.394.0",
42
- "@salesforce/lds-aura-storage": "^1.394.0",
43
- "@salesforce/lds-bindings": "^1.394.0",
44
- "@salesforce/lds-instrumentation": "^1.394.0",
45
- "@salesforce/lds-network-aura": "^1.394.0",
46
- "@salesforce/lds-network-fetch": "^1.394.0",
37
+ "@luvio/service-provisioner": "5.65.1",
38
+ "@luvio/tools-core": "5.65.1",
39
+ "@salesforce/lds-adapters-apex": "^1.396.0",
40
+ "@salesforce/lds-adapters-uiapi": "^1.396.0",
41
+ "@salesforce/lds-ads-bridge": "^1.396.0",
42
+ "@salesforce/lds-aura-storage": "^1.396.0",
43
+ "@salesforce/lds-bindings": "^1.396.0",
44
+ "@salesforce/lds-instrumentation": "^1.396.0",
45
+ "@salesforce/lds-network-aura": "^1.396.0",
46
+ "@salesforce/lds-network-fetch": "^1.396.0",
47
47
  "jwt-encode": "1.0.1"
48
48
  },
49
49
  "dependencies": {
50
- "@luvio/command-aura-graphql-normalized-cache-control": "5.64.2",
51
- "@luvio/command-aura-network": "5.64.2",
52
- "@luvio/command-aura-normalized-cache-control": "5.64.2",
53
- "@luvio/command-aura-resource-cache-control": "5.64.2",
54
- "@luvio/command-fetch-network": "5.64.2",
55
- "@luvio/command-http-graphql-normalized-cache-control": "5.64.2",
56
- "@luvio/command-http-normalized-cache-control": "5.64.2",
57
- "@luvio/command-ndjson": "5.64.2",
58
- "@luvio/command-network": "5.64.2",
59
- "@luvio/command-sse": "5.64.2",
60
- "@luvio/command-streaming": "5.64.2",
50
+ "@luvio/command-aura-graphql-normalized-cache-control": "5.65.1",
51
+ "@luvio/command-aura-network": "5.65.1",
52
+ "@luvio/command-aura-normalized-cache-control": "5.65.1",
53
+ "@luvio/command-aura-resource-cache-control": "5.65.1",
54
+ "@luvio/command-fetch-network": "5.65.1",
55
+ "@luvio/command-http-graphql-normalized-cache-control": "5.65.1",
56
+ "@luvio/command-http-normalized-cache-control": "5.65.1",
57
+ "@luvio/command-ndjson": "5.65.1",
58
+ "@luvio/command-network": "5.65.1",
59
+ "@luvio/command-sse": "5.65.1",
60
+ "@luvio/command-streaming": "5.65.1",
61
61
  "@luvio/network-adapter-composable": "0.158.7",
62
62
  "@luvio/network-adapter-fetch": "0.158.7",
63
- "@luvio/service-aura-network": "5.64.2",
64
- "@luvio/service-cache": "5.64.2",
65
- "@luvio/service-cache-control": "5.64.2",
66
- "@luvio/service-cache-inclusion-policy": "5.64.2",
67
- "@luvio/service-feature-flags": "5.64.2",
68
- "@luvio/service-fetch-network": "5.64.2",
69
- "@luvio/service-instrument-command": "5.64.2",
70
- "@luvio/service-pubsub": "5.64.2",
71
- "@luvio/service-store": "5.64.2",
72
- "@luvio/utils": "5.64.2",
63
+ "@luvio/service-aura-network": "5.65.1",
64
+ "@luvio/service-cache": "5.65.1",
65
+ "@luvio/service-cache-control": "5.65.1",
66
+ "@luvio/service-cache-inclusion-policy": "5.65.1",
67
+ "@luvio/service-feature-flags": "5.65.1",
68
+ "@luvio/service-fetch-network": "5.65.1",
69
+ "@luvio/service-instrument-command": "5.65.1",
70
+ "@luvio/service-pubsub": "5.65.1",
71
+ "@luvio/service-store": "5.65.1",
72
+ "@luvio/utils": "5.65.1",
73
73
  "@lwc/state": "^0.23.0",
74
- "@salesforce/lds-adapters-onestore-graphql": "^1.394.0",
75
- "@salesforce/lds-adapters-uiapi-lex": "^1.394.0",
76
- "@salesforce/lds-luvio-service": "^1.394.0",
77
- "@salesforce/lds-luvio-uiapi-records-service": "^1.394.0"
74
+ "@salesforce/lds-adapters-onestore-graphql": "^1.396.0",
75
+ "@salesforce/lds-adapters-uiapi-lex": "^1.396.0",
76
+ "@salesforce/lds-luvio-service": "^1.396.0",
77
+ "@salesforce/lds-luvio-uiapi-records-service": "^1.396.0"
78
78
  },
79
79
  "luvioBundlesize": [
80
80
  {