@salesforce/lds-runtime-aura 1.316.0 → 1.318.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.
@@ -22,7 +22,7 @@ import applyPredictionRequestLimit from '@salesforce/gate/lds.pdl.applyRequestLi
22
22
  import useExactMatchesPlusGate from '@salesforce/gate/lds.pdl.useExactMatchesPlus';
23
23
  import { GetApexWireAdapterFactory, registerPrefetcher as registerPrefetcher$1 } from 'force/ldsAdaptersApex';
24
24
  import { getRecordAvatarsAdapterFactory, getRecordAdapterFactory, coerceFieldIdArray, getRecordsAdapterFactory, getRecordActionsAdapterFactory, getObjectInfosAdapterFactory, coerceObjectIdArray, getObjectInfoAdapterFactory, coerceObjectId, getRelatedListsActionsAdapterFactory, getRelatedListInfoBatchAdapterFactory, getRelatedListInfoAdapterFactory, getRelatedListRecordsBatchAdapterFactory, getRelatedListRecordsAdapterFactory, getListInfoByNameAdapterFactory, getListInfosByObjectNameAdapterFactory, getListRecordsByNameAdapterFactory, getListObjectInfoAdapterFactory, instrument, configuration, InMemoryRecordRepresentationQueryEvaluator, UiApiNamespace, RecordRepresentationRepresentationType, registerPrefetcher } from 'force/ldsAdaptersUiapi';
25
- import { BaseCommand, convertFetchResponseToData } from 'force/luvioRuntime5';
25
+ import { getInstrumentation } from 'o11y/client';
26
26
  import { serviceBroker } from 'force/luvioServiceBroker5';
27
27
  import oneStoreEnabled from '@salesforce/gate/lds.oneStoreEnabled.ltng';
28
28
  import oneStoreUiapiEnabled from '@salesforce/gate/lds.oneStoreUiapiEnabled.ltng';
@@ -39,6 +39,20 @@ import useHttpInsteadAuraTransport from '@salesforce/gate/lds.useHttpInsteadAura
39
39
  import { ThirdPartyTracker } from 'instrumentation:beaconLib';
40
40
  import { getObjectInfo, getObjectInfos } from 'force/ldsAdaptersUiapiLex';
41
41
 
42
+ /**
43
+ * Copyright (c) 2022, Salesforce, Inc.,
44
+ * All rights reserved.
45
+ * For full license text, see the LICENSE.txt file
46
+ */
47
+
48
+ /**
49
+ * BaseCommand is an abstract implementation of SubscribableCommand. It adds the
50
+ * notions of typed configuration, request context, and a set of runtime services
51
+ * to the contract defined by Command/SubscribableCommand.
52
+ */
53
+ class BaseCommand {
54
+ }
55
+
42
56
  /**
43
57
  * Copyright (c) 2022, Salesforce, Inc.,
44
58
  * All rights reserved.
@@ -59,7 +73,7 @@ class NetworkCommand extends BaseCommand {
59
73
  return this.fetch();
60
74
  }
61
75
  }
62
- function buildNetworkCommandBaseClassService() {
76
+ function buildServiceDescriptor$a() {
63
77
  return {
64
78
  type: 'networkCommandBaseClass',
65
79
  version: '1.0',
@@ -176,7 +190,7 @@ function toError(x) {
176
190
  if (x instanceof Error) {
177
191
  return x;
178
192
  }
179
- return new Error(`${x}`);
193
+ return new Error(typeof x === 'string' ? x : JSON.stringify(x));
180
194
  }
181
195
 
182
196
  class Ok {
@@ -203,33 +217,6 @@ class Err {
203
217
  }
204
218
  const ok = (value) => new Ok(value);
205
219
  const err = (err) => new Err(err);
206
- // an error to indicate that the data inside a Result construct
207
- // is missing or incomplete
208
- class DataNotFoundError extends Error {
209
- constructor(message) {
210
- super(message);
211
- this.name = 'DataNotFoundError';
212
- }
213
- }
214
- class DataIncompleteError extends Error {
215
- constructor(message, partialData) {
216
- super(message);
217
- this.partialData = partialData;
218
- this.name = 'DataIncompleteError';
219
- }
220
- }
221
- function isDataNotFoundError(error) {
222
- return error instanceof DataNotFoundError || error.name === 'DataNotFoundError';
223
- }
224
- function isDataIncompleteError(error) {
225
- return error instanceof DataIncompleteError || error.name === 'DataIncompleteError';
226
- }
227
- function isCacheHitOrError(value) {
228
- if (value.isErr() && (isDataIncompleteError(value.error) || isDataNotFoundError(value.error))) {
229
- return false;
230
- }
231
- return true;
232
- }
233
220
 
234
221
  /**
235
222
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -256,8 +243,7 @@ function convertAuraResponseToData(responsePromise) {
256
243
  }
257
244
 
258
245
  /**
259
- * An implementation of BaseCommand that makes network requests but does not try to
260
- * use the store.
246
+ * An implementation of NetworkCommand that uses Aura as the transport mechanism
261
247
  */
262
248
  class AuraNetworkCommand extends NetworkCommand {
263
249
  constructor(services) {
@@ -274,7 +260,8 @@ class AuraNetworkCommand extends NetworkCommand {
274
260
  return convertAuraResponseToData(this.services.auraNetwork(this.endpoint, this.auraParams, this.actionConfig));
275
261
  }
276
262
  }
277
- function buildAuraNetworkCommandBaseClassService() {
263
+
264
+ function buildServiceDescriptor$9() {
278
265
  return {
279
266
  type: 'auraNetworkCommandBaseClass',
280
267
  version: '1.0',
@@ -290,8 +277,7 @@ function buildAuraNetworkCommandBaseClassService() {
290
277
 
291
278
 
292
279
  /**
293
- * An implementation of BaseCommand that makes network requests but does not try to
294
- * use the store.
280
+ * An implementation of NetworkCommand that uses HTTP/fetch as the transport mechanism.
295
281
  */
296
282
  class FetchNetworkCommand extends NetworkCommand {
297
283
  constructor(services) {
@@ -299,10 +285,21 @@ class FetchNetworkCommand extends NetworkCommand {
299
285
  this.services = services;
300
286
  }
301
287
  fetch() {
302
- return convertFetchResponseToData(this.services.fetch(...this.fetchParams));
288
+ return this.convertFetchResponseToData(this.services.fetch(...this.fetchParams));
289
+ }
290
+ convertFetchResponseToData(response) {
291
+ return response.then((response) => {
292
+ if (response.ok) {
293
+ return response.json().then((json) => ok(json), (reason) => err(toError(reason)));
294
+ }
295
+ else {
296
+ return err(toError(response.statusText));
297
+ }
298
+ }, (reason) => err(toError(reason)));
303
299
  }
304
300
  }
305
- function buildFetchNetworkCommandBaseClassService() {
301
+
302
+ function buildServiceDescriptor$8() {
306
303
  return {
307
304
  type: 'fetchNetworkCommandBaseClass',
308
305
  version: '1.0',
@@ -339,7 +336,8 @@ class StreamingCommand extends BaseCommand {
339
336
  }, (reason) => err(toError(reason)));
340
337
  }
341
338
  }
342
- function buildStreamingCommandBaseClassService() {
339
+
340
+ function buildServiceDescriptor$7() {
343
341
  return {
344
342
  type: 'streamingCommandBaseClass',
345
343
  version: '1.0',
@@ -375,13 +373,6 @@ class SSECommand extends StreamingCommand {
375
373
  .pipeThrough(new SSEParsingStream()));
376
374
  }
377
375
  }
378
- function buildSSECommandBaseClassService() {
379
- return {
380
- type: 'SSECommandBaseClass',
381
- version: '1.0',
382
- service: SSECommand,
383
- };
384
- }
385
376
  const sseRegex = /^(?<field>[^:]*?)(: ?(?<value>.*?))?(?:\r\n?|\n)/;
386
377
  // +-------v------++--------v--------++-----v----+
387
378
  // | | |
@@ -462,6 +453,14 @@ class SSEParsingStream extends TransformStream {
462
453
  }
463
454
  }
464
455
 
456
+ function buildServiceDescriptor$6() {
457
+ return {
458
+ type: 'SSECommandBaseClass',
459
+ version: '1.0',
460
+ service: SSECommand,
461
+ };
462
+ }
463
+
465
464
  /**
466
465
  * Copyright (c) 2022, Salesforce, Inc.,
467
466
  * All rights reserved.
@@ -503,11 +502,12 @@ function buildInstrumentCommand(services) {
503
502
  };
504
503
  };
505
504
  }
506
- function buildInstrumentCommandServiceDescriptor(services) {
505
+
506
+ function buildServiceDescriptor$5(instrumentation) {
507
507
  return {
508
508
  type: 'instrumentCommand',
509
509
  version: '1.0',
510
- service: buildInstrumentCommand(services),
510
+ service: buildInstrumentCommand({ instrumentation }),
511
511
  };
512
512
  }
513
513
 
@@ -517,271 +517,251 @@ function buildInstrumentCommandServiceDescriptor(services) {
517
517
  * For full license text, see the LICENSE.txt file
518
518
  */
519
519
 
520
- /**
521
- * A collection of keys, in no particular order.
522
- */
523
- class KeySetImpl {
524
- constructor(initialKeys) {
525
- // TODO - probably better to use Set<Key>
526
- this.data = {};
527
- this.lengthInternal = 0;
528
- if (initialKeys) {
529
- initialKeys.forEach((key) => {
530
- this.add(key);
531
- });
532
- }
533
- }
534
- add(key) {
535
- this.data[key] = true;
536
- // TODO - need to account for adding a key that was already in the set
537
- this.lengthInternal++;
520
+
521
+ /* eslint-disable no-dupe-class-members */
522
+ class O11yOTelTraceAPI {
523
+ constructor(services) {
524
+ this.services = services;
538
525
  }
539
- contains(key) {
540
- return this.data[key] === true;
526
+ getTracer(name, _version, _options) {
527
+ const o11yInstrumentation = getInstrumentation(name);
528
+ return new O11yTracer(o11yInstrumentation, this.services.logger);
541
529
  }
542
- elements() {
543
- return Object.keys(this.data);
530
+ }
531
+ class O11yTracer {
532
+ constructor(o11yInstrumentation, logger) {
533
+ this.o11yInstrumentation = o11yInstrumentation;
534
+ this.logger = logger;
544
535
  }
545
- get length() {
546
- return this.lengthInternal;
536
+ startSpan(name, _options, context) {
537
+ const traceId = context === null || context === void 0 ? void 0 : context.getValue(Symbol.for('traceId'));
538
+ const spanId = context === null || context === void 0 ? void 0 : context.getValue(Symbol.for('spanId'));
539
+ const traceFlags = context === null || context === void 0 ? void 0 : context.getValue(Symbol.for('traceFlags'));
540
+ let spanContext = undefined;
541
+ if (traceId !== undefined && spanId !== undefined && traceFlags !== undefined) {
542
+ spanContext = {
543
+ traceId,
544
+ spanId,
545
+ traceFlags,
546
+ };
547
+ }
548
+ const activityOptions = spanContext === undefined
549
+ ? undefined
550
+ : {
551
+ instrumentationContext: {
552
+ rootId: spanContext.traceId,
553
+ isRootActivitySampled: spanContext.traceFlags === 1,
554
+ parentId: spanId,
555
+ },
556
+ };
557
+ const activity = this.o11yInstrumentation.startActivity(name, activityOptions);
558
+ return new O11ySpan(activity, this.logger);
547
559
  }
548
- overlaps(other) {
549
- const otherKeys = other.elements();
550
- for (let j = 0; j < otherKeys.length; ++j) {
551
- if (this.contains(otherKeys[j])) {
552
- return true;
560
+ startActiveSpan(name, options, context, fn) {
561
+ let opts;
562
+ let ctx;
563
+ let fun;
564
+ if (typeof options === 'function') {
565
+ fun = options;
566
+ }
567
+ else {
568
+ opts = options;
569
+ if (typeof context === 'function') {
570
+ fun = context;
571
+ }
572
+ else {
573
+ ctx = context;
574
+ fun = fn;
553
575
  }
554
576
  }
555
- return false;
577
+ const span = this.startSpan(name, opts, ctx);
578
+ return fun(span);
556
579
  }
557
- difference(other) {
558
- const value = new KeySetImpl();
559
- this.elements().forEach((key) => {
560
- if (!other.contains(key)) {
561
- value.add(key);
562
- }
563
- });
564
- return value;
580
+ }
581
+ class O11ySpan {
582
+ constructor(activity, logger) {
583
+ this.activity = activity;
584
+ this.logger = logger;
585
+ this._isRecording = true;
586
+ this.attributes = {};
565
587
  }
566
- isSubsetOf(other) {
567
- return this.difference(other).length === 0;
588
+ spanContext() {
589
+ return {
590
+ traceId: this.activity.getRootId(),
591
+ spanId: this.activity.getId(),
592
+ traceFlags: this.activity.getIsSampled() ? 1 : 0,
593
+ };
568
594
  }
569
- equals(other) {
570
- return this.length === other.length && this.elements().every((key) => other.contains(key));
595
+ setAttribute(key, value) {
596
+ this.attributes[key] = value;
597
+ return this;
571
598
  }
572
- toString() {
573
- return `<<${JSON.stringify(this.elements())}>>`;
599
+ setAttributes(attributes) {
600
+ this.attributes = { ...this.attributes, ...attributes };
601
+ return this;
574
602
  }
575
- }
576
-
577
- /**
578
- * A simple in-memory implementation of the Store interface.
579
- *
580
- * Exported for testing purposes only.
581
- */
582
- class InMemoryStore {
583
- constructor() {
584
- this.data = {};
603
+ addEvent(_name, _attributesOrStartTime, _startTime) {
604
+ this.logger.warn('O11ySpan does not support addEvents.');
605
+ return this;
585
606
  }
586
- // TODO - only intended for use in tests. We should refactor this into a subclass &
587
- // add to a test util library.
588
- clear() {
589
- this.data = {};
607
+ setStatus(_status) {
608
+ this.logger.warn('O11ySpan does not support setStatus.');
609
+ return this;
590
610
  }
591
- delete(key, _options) {
592
- delete this.data[key];
611
+ updateName(_name) {
612
+ this.logger.warn('O11ySpan does not support updateName.');
613
+ return this;
593
614
  }
594
- get(key, _options) {
595
- return this.data[key];
615
+ end(endTime) {
616
+ let endTimeInternal = endTime;
617
+ try {
618
+ if (typeof endTimeInternal !== 'number') {
619
+ this.logger.warn('O11ySpan does not support non number endTime override.');
620
+ endTimeInternal = undefined;
621
+ }
622
+ // TODO: Add support for stop schemas and data
623
+ this.activity.stop(undefined, undefined, endTimeInternal ? { perfStopOverride: endTimeInternal } : undefined);
624
+ }
625
+ finally {
626
+ this._isRecording = false;
627
+ }
628
+ return;
596
629
  }
597
- set(key, value, _options) {
598
- this.data[key] = value;
630
+ isRecording() {
631
+ return this._isRecording;
599
632
  }
600
- length() {
601
- return this.keys().length;
633
+ recordException(exception, _time) {
634
+ // TODO: Add support for exception schemas and data
635
+ this.activity.error(exception);
602
636
  }
603
- keys() {
604
- return new KeySetImpl(Object.keys(this.data));
637
+ }
638
+
639
+ class O11yOTelMetricsAPI {
640
+ constructor(services) {
641
+ this.services = services;
605
642
  }
606
- toKeySet(keys) {
607
- return new KeySetImpl(keys);
643
+ getMeter(name,
644
+ // TODO: Not sure what to do with these?
645
+ _version, __options) {
646
+ const o11yInstrumentation = getInstrumentation(name);
647
+ return new O11yMeter(o11yInstrumentation, this.services.logger);
608
648
  }
609
649
  }
610
- /**
611
- * Constructs an in-memory implementation of StoreService.
612
- *
613
- * @returns in-memory implementation of StoreService
614
- */
615
- function buildInMemoryStoreService() {
616
- return {
617
- type: 'store',
618
- version: '1.0',
619
- service: new InMemoryStore(),
620
- };
621
- }
622
- /**
623
- * A simple in-memory implementation of the MetadataRepository interface.
624
- *
625
- * Exported for testing purposes only.
626
- */
627
- class InMemoryMetadataRepository {
628
- constructor() {
629
- this.data = {};
650
+ class O11yMeter {
651
+ constructor(o11yInstrumentation, logger) {
652
+ this.o11yInstrumentation = o11yInstrumentation;
653
+ this.logger = logger;
630
654
  }
631
- // TODO - only intended for use in tests. We should refactor this into a subclass &
632
- // add to a test util library.
633
- clear() {
634
- this.data = {};
655
+ createHistogram(name, _options) {
656
+ return new O11yHistogram(name, this.o11yInstrumentation, this.logger);
635
657
  }
636
- delete(key, _options) {
637
- delete this.data[key];
658
+ createCounter(name, options) {
659
+ if (options) {
660
+ this.logger.warn('counter options not supported in O11y instrumentation');
661
+ }
662
+ return new O11yCounter(name, this.o11yInstrumentation, this.logger);
638
663
  }
639
- get(key, _options) {
640
- return this.data[key];
664
+ createUpDownCounter(_name, _options) {
665
+ return new O11yUpDownCounter(this.logger);
641
666
  }
642
- set(key, value, _options) {
643
- this.data[key] = value;
667
+ createObservableGauge(_name, _options) {
668
+ return new O11yObservableGuage(this.logger);
644
669
  }
645
- setPartial(key, value, _options) {
646
- const metadata = this.get(key);
647
- if (metadata === undefined) {
648
- throw new Error(`Metadata for key "${key}" not found`);
649
- }
650
- this.data[key] = { ...metadata, ...value };
670
+ createObservableCounter(_name, _options) {
671
+ return new O11yObservableCounter(this.logger);
651
672
  }
652
- expire(key, options) {
653
- const { expirationTime = Date.now() } = options || {};
654
- this.setPartial(key, { expirationTime });
673
+ createObservableUpDownCounter(_name, _options) {
674
+ return new O11yObservableUpDownCounter(this.logger);
675
+ }
676
+ addBatchObservableCallback(_callback, _observables) {
677
+ this.logger.warn('addBatchObservableCallback not supported yet');
678
+ }
679
+ removeBatchObservableCallback(_callback, _observables) {
680
+ this.logger.warn('removeBatchObservableCallback not supported yet');
655
681
  }
656
682
  }
657
- /**
658
- * Constructs an in-memory implementation of MetadataRepositoryService.
659
- *
660
- * @returns in-memory implementation of MetadataRepositoryService
661
- */
662
- function buildInMemoryMetadataRepositoryService() {
663
- return {
664
- type: 'metadataRepository',
665
- version: '1.0',
666
- service: new InMemoryMetadataRepository(),
667
- };
668
- }
669
-
670
- /**
671
- * A RecordableStore wraps another Store and is used to record which keys in the
672
- * other Store are read/written.
673
- */
674
- class RecordableStore {
675
- constructor(baseStore) {
676
- this.baseStore = baseStore;
677
- this.keysRead = new KeySetImpl();
678
- this.missingKeysRead = new KeySetImpl();
679
- this.keysUpdated = new KeySetImpl();
683
+ class O11yCounter {
684
+ constructor(name, o11yInstrumentation, logger) {
685
+ this.name = name;
686
+ this.o11yInstrumentation = o11yInstrumentation;
687
+ this.logger = logger;
680
688
  }
681
- delete(key, options) {
682
- this.keysUpdated.add(key);
683
- this.baseStore.delete(key, options);
689
+ add(value, _attributes, _context) {
690
+ if (value < 0) {
691
+ this.logger.warn(`Counter values must be non-negative. Got ${value}.`);
692
+ return;
693
+ }
694
+ this.o11yInstrumentation.incrementCounter(this.name, value);
684
695
  }
685
- get(key, options) {
686
- this.keysRead.add(key);
687
- const value = this.baseStore.get(key, options);
688
- if (value === undefined) {
689
- this.missingKeysRead.add(key);
696
+ }
697
+ class O11yHistogram {
698
+ constructor(name, o11yInstrumentation, logger) {
699
+ this.name = name;
700
+ this.o11yInstrumentation = o11yInstrumentation;
701
+ this.logger = logger;
702
+ }
703
+ record(value, _attributes, _context) {
704
+ if (value < 0) {
705
+ this.logger.warn(`Histogram values must be non-negative. Got ${value}.`);
706
+ return;
690
707
  }
691
- return value;
708
+ this.o11yInstrumentation.trackValue(this.name, value);
692
709
  }
693
- set(key, value, options) {
694
- this.keysUpdated.add(key);
695
- this.baseStore.set(key, value, options);
710
+ }
711
+ class O11yUpDownCounter {
712
+ constructor(logger) {
713
+ this.logger = logger;
696
714
  }
697
- length() {
698
- return this.baseStore.length();
715
+ add(_value, _attributes, _context) {
716
+ this.logger.warn('O11yUpDownCounter not supported yet.');
699
717
  }
700
- keys() {
701
- return this.baseStore.keys();
718
+ }
719
+ class O11yObservableCounter {
720
+ constructor(logger) {
721
+ this.logger = logger;
702
722
  }
703
- toKeySet(keys) {
704
- return this.baseStore.toKeySet(keys);
723
+ addCallback(_callback) {
724
+ this.logger.warn('O11yObservableCounter not supported yet. Defaulting to noop.');
725
+ }
726
+ removeCallback(_callback) {
727
+ this.logger.warn('O11yObservableCounter not supported yet. Defaulting to noop.');
705
728
  }
706
729
  }
707
-
708
- /**
709
- * A TTLFilteredStore wraps another Store and filters data from that Store
710
- * to entries whose metadata indicates that it has not yet expired.
711
- */
712
- class TTLFilteredStore {
713
- constructor(baseStore, metadataRepository, now = Date.now()) {
714
- this.baseStore = baseStore;
715
- this.metadataRepository = metadataRepository;
716
- this.now = now;
717
- }
718
- delete(key, options) {
719
- this.baseStore.delete(key, options);
720
- }
721
- get(key, options) {
722
- const metadata = this.metadataRepository.get(key);
723
- if (metadata && metadata.expirationTime <= this.now) {
724
- return undefined;
725
- }
726
- return this.baseStore.get(key, options);
730
+ class O11yObservableGuage {
731
+ constructor(logger) {
732
+ this.logger = logger;
727
733
  }
728
- set(key, value, options) {
729
- this.baseStore.set(key, value, options);
734
+ addCallback(_callback) {
735
+ this.logger.warn('O11yObservableGuage not supported yet. Defaulting to noop.');
730
736
  }
731
- length() {
732
- return this.keys().length;
737
+ removeCallback(_callback) {
738
+ this.logger.warn('O11yObservableGuage not supported yet. Defaulting to noop.');
733
739
  }
734
- keys() {
735
- return new KeySetImpl(this.baseStore
736
- .keys()
737
- .elements()
738
- .filter((key) => this.get(key) !== undefined));
740
+ }
741
+ class O11yObservableUpDownCounter {
742
+ constructor(logger) {
743
+ this.logger = logger;
739
744
  }
740
- toKeySet(keys) {
741
- return this.baseStore.toKeySet(keys);
745
+ addCallback(_callback) {
746
+ this.logger.warn('O11yObservableUpDownCounter not supported yet. Defaulting to noop.');
747
+ }
748
+ removeCallback(_callback) {
749
+ this.logger.warn('O11yObservableUpDownCounter not supported yet. Defaulting to noop.');
742
750
  }
743
751
  }
744
752
 
745
- /**
746
- * Copyright (c) 2022, Salesforce, Inc.,
747
- * All rights reserved.
748
- * For full license text, see the LICENSE.txt file
749
- */
750
-
751
-
752
- /**
753
- * Implementation of CacheInclusionPolicy that uses a single level, in memory,
754
- * synchronous L1 cache.
755
- */
756
- class InMemoryCacheInclusionPolicy {
757
- /**
758
- * Reads data out of a single level in memory store.
759
- */
760
- read(options) {
761
- const { l1, readFromL1 } = options;
762
- // l1 is all we've got
763
- const readResult = readFromL1(l1);
764
- return resolvedPromiseLike(readResult);
765
- }
766
- /**
767
- * Writes data to a single level in memory store.
768
- */
769
- write(options) {
770
- const { l1, writeToL1 } = options;
771
- writeToL1(l1);
772
- return resolvedPromiseLike(undefined);
753
+ class O11yInstrumentation {
754
+ constructor(services) {
755
+ this.services = services;
756
+ this.trace = new O11yOTelTraceAPI(this.services);
757
+ this.metrics = new O11yOTelMetricsAPI(this.services);
773
758
  }
774
759
  }
775
- /**
776
- * Constructs an in-memory-only CacheInclusionPolicy.
777
- *
778
- * @returns in-memory-only CacheInclusionPolicy
779
- */
780
- function buildInMemoryCacheInclusionPolicyService() {
760
+ function buildServiceDescriptor$4(logger) {
781
761
  return {
782
- service: new InMemoryCacheInclusionPolicy(),
783
- type: 'cacheInclusionPolicy',
762
+ type: 'instrumentation',
784
763
  version: '1.0',
764
+ service: new O11yInstrumentation({ logger }),
785
765
  };
786
766
  }
787
767
 
@@ -791,207 +771,106 @@ function buildInMemoryCacheInclusionPolicyService() {
791
771
  * For full license text, see the LICENSE.txt file
792
772
  */
793
773
 
794
-
795
- class CacheThenNetworkPolicy {
796
- constructor(services, validator) {
797
- this.services = services;
798
- this.validator = validator;
799
- this.policyName = 'cache-then-network';
800
- }
801
- run(options) {
802
- const { readFromCache: readFromCacheOriginal, readFromNetwork: readFromNetworkOriginal, writeToCache: writeToCacheOriginal, buildResult, } = options;
803
- // filter what data readFromCache is allowed to access from the store
804
- const now = Date.now();
805
- let ttlStore = new TTLFilteredStore(this.services.store, this.services.metadataRepository, now);
806
- const { readFromCache: readFromCacheDedupe, readFromNetwork: readFromNetworkDedupe, writeToCache: writeToCacheDedupe, } = this.services.requestDedupe.applyDedupe({
807
- readFromCache: (services) => this.readWithValidation(() => readFromCacheOriginal(services)),
808
- readFromNetwork: readFromNetworkOriginal,
809
- writeToCache: (services, networkResult) => this.writeWithValidation(() => writeToCacheOriginal(networkResult, services)),
810
- });
811
- return readFromCacheDedupe({ ...this.services, store: ttlStore }).then((value) => {
812
- if (isCacheHitOrError(value)) {
813
- return value;
814
- }
815
- // result not found in cache, try network
816
- return readFromNetworkDedupe()
817
- .then((value) => {
818
- return writeToCacheDedupe(this.services, value).then(() => value);
819
- })
820
- .then((value) => {
821
- const builtResult = buildResult(value, this.services);
822
- this.validator.validateBuildResult(builtResult);
823
- return builtResult;
824
- });
825
- });
826
- }
827
- readWithValidation(readFromCache) {
828
- const readResult = readFromCache();
829
- this.validator.validateReadResult(readResult);
830
- return readResult;
831
- }
832
- writeWithValidation(writeToCache) {
833
- const writeResult = writeToCache();
834
- this.validator.validateWriteResult(writeResult);
835
- return writeResult;
836
- }
837
- }
838
- function buildCacheThenNetworkPolicy(services, validator) {
839
- return new CacheThenNetworkPolicy(services, validator);
840
- }
841
-
842
774
  /**
843
- * Copyright (c) 2022, Salesforce, Inc.,
844
- * All rights reserved.
845
- * For full license text, see the LICENSE.txt file
775
+ * A collection of keys, in no particular order.
846
776
  */
847
-
848
- class NoopOTelTraceAPI {
849
- getTracer(_name, _version, _options) {
850
- return new NoopTracer();
851
- }
852
- }
853
- class NoopTracer {
854
- startSpan(_name, _options, _context) {
855
- return new NoopSpan();
856
- }
857
- startActiveSpan(name, options, context, fn) {
858
- let opts;
859
- let ctx;
860
- let fun;
861
- if (typeof options === 'function') {
862
- fun = options;
863
- }
864
- else {
865
- opts = options;
866
- if (typeof context === 'function') {
867
- fun = context;
868
- }
869
- else {
870
- ctx = context;
871
- fun = fn;
872
- }
873
- }
874
- const span = this.startSpan(name, opts, ctx);
875
- try {
876
- return fun(span);
877
- }
878
- finally {
879
- span.end();
777
+ class KeySetImpl {
778
+ constructor(initialKeys) {
779
+ // TODO - probably better to use Set<Key>
780
+ this.data = {};
781
+ this.lengthInternal = 0;
782
+ if (initialKeys) {
783
+ initialKeys.forEach((key) => {
784
+ this.add(key);
785
+ });
880
786
  }
881
787
  }
882
- }
883
- class NoopSpan {
884
- spanContext() {
885
- // TODO: I'll need to double check, but I think even if we provide a
886
- // noop implementation, there is still a requirement to pass along context
887
- return {
888
- spanId: 'noopSpanId',
889
- traceId: 'noopTraceId',
890
- traceFlags: 0,
891
- };
892
- }
893
- setAttribute(_key, _value) {
894
- return this;
895
- }
896
- setAttributes(_attributes) {
897
- return this;
898
- }
899
- addEvent(_name, _attributesOrStartTime, _startTime) {
900
- return this;
901
- }
902
- setStatus(_status) {
903
- return this;
904
- }
905
- updateName(_name) {
906
- return this;
907
- }
908
- end(_endTime) {
909
- return;
910
- }
911
- isRecording() {
912
- return false;
913
- }
914
- recordException(_exception, _time) {
915
- return;
916
- }
917
- }
918
-
919
- class NoopOTelMetricsAPI {
920
- getMeter(__name, _version, __options) {
921
- return new NoopMeter();
922
- }
923
- }
924
- class NoopMeter {
925
- createHistogram(_name, _options) {
926
- return new NoopHistogram();
788
+ add(key) {
789
+ this.data[key] = true;
790
+ // TODO - need to account for adding a key that was already in the set
791
+ this.lengthInternal++;
927
792
  }
928
- createCounter(_name, _options) {
929
- return new NoopCounter();
793
+ contains(key) {
794
+ return this.data[key] === true;
930
795
  }
931
- createUpDownCounter(_name, _options) {
932
- return new NoopUpDownCounter();
796
+ elements() {
797
+ return Object.keys(this.data);
933
798
  }
934
- createObservableGauge(_name, _options) {
935
- return new NoopObservableGuage();
799
+ get length() {
800
+ return this.lengthInternal;
936
801
  }
937
- createObservableCounter(_name, _options) {
938
- return new NoopObservableCounter();
802
+ overlaps(other) {
803
+ const otherKeys = other.elements();
804
+ for (let j = 0; j < otherKeys.length; ++j) {
805
+ if (this.contains(otherKeys[j])) {
806
+ return true;
807
+ }
808
+ }
809
+ return false;
939
810
  }
940
- createObservableUpDownCounter(_name, _options) {
941
- return new NoopObservableUpDownCounter();
811
+ difference(other) {
812
+ const value = new KeySetImpl();
813
+ this.elements().forEach((key) => {
814
+ if (!other.contains(key)) {
815
+ value.add(key);
816
+ }
817
+ });
818
+ return value;
942
819
  }
943
- addBatchObservableCallback(_callback, _observables) {
944
- return;
820
+ isSubsetOf(other) {
821
+ return this.difference(other).length === 0;
945
822
  }
946
- removeBatchObservableCallback(_callback, _observables) {
947
- return;
823
+ equals(other) {
824
+ return this.length === other.length && this.elements().every((key) => other.contains(key));
948
825
  }
949
- }
950
- class NoopCounter {
951
- add(_value, _attributes, _context) {
952
- return;
826
+ toString() {
827
+ return `<<${JSON.stringify(this.elements())}>>`;
953
828
  }
954
829
  }
955
- class NoopHistogram {
956
- record(_value, _attributes, _context) {
957
- return;
830
+
831
+ /**
832
+ * A simple in-memory implementation of the Store interface.
833
+ *
834
+ * Exported for testing purposes only.
835
+ */
836
+ class InMemoryStore {
837
+ constructor() {
838
+ this.data = {};
958
839
  }
959
- }
960
- class NoopUpDownCounter {
961
- add(_value, _attributes, _context) {
962
- return;
840
+ // TODO - only intended for use in tests. We should refactor this into a subclass &
841
+ // add to a test util library.
842
+ clear() {
843
+ this.data = {};
963
844
  }
964
- }
965
- class NoopObservableCounter {
966
- addCallback(_callback) {
967
- return;
845
+ delete(key, _options) {
846
+ delete this.data[key];
968
847
  }
969
- removeCallback(_callback) {
970
- return;
848
+ get(key, _options) {
849
+ return this.data[key];
971
850
  }
972
- }
973
- class NoopObservableGuage {
974
- addCallback(_callback) {
975
- return;
851
+ set(key, value, _options) {
852
+ this.data[key] = value;
976
853
  }
977
- removeCallback(_callback) {
978
- return;
854
+ length() {
855
+ return this.keys().length;
979
856
  }
980
- }
981
- class NoopObservableUpDownCounter {
982
- addCallback(_callback) {
983
- return;
857
+ keys() {
858
+ return new KeySetImpl(Object.keys(this.data));
984
859
  }
985
- removeCallback(_callback) {
986
- return;
860
+ toKeySet(keys) {
861
+ return new KeySetImpl(keys);
987
862
  }
988
863
  }
989
-
990
- /* eslint-disable no-dupe-class-members */
991
- function buildNoopInstrumentationService() {
864
+ /**
865
+ * Constructs an in-memory implementation of StoreService.
866
+ *
867
+ * @returns in-memory implementation of StoreService
868
+ */
869
+ function buildServiceDescriptor$3() {
992
870
  return {
993
- trace: new NoopOTelTraceAPI(),
994
- metrics: new NoopOTelMetricsAPI(),
871
+ type: 'store',
872
+ version: '1.0',
873
+ service: new InMemoryStore(),
995
874
  };
996
875
  }
997
876
 
@@ -1002,120 +881,92 @@ function buildNoopInstrumentationService() {
1002
881
  */
1003
882
 
1004
883
 
884
+ class DefaultCache {
885
+ constructor(services) {
886
+ this.services = services;
887
+ }
888
+ /**
889
+ * Returns the cache entry at the specified key; undefined if no
890
+ * such entry exists.
891
+ *
892
+ * @param key store key
893
+ */
894
+ get(key) {
895
+ return this.services.store.get(key);
896
+ }
897
+ /**
898
+ * Adds the specified key/value to the cache.
899
+ *
900
+ * @param key key at which to store value
901
+ * @param entry value to be stored
902
+ */
903
+ set(key, entry) {
904
+ if (entry.cacheControlMetadata.type === 'no-store') {
905
+ return;
906
+ }
907
+ return this.services.store.set(key, entry);
908
+ }
909
+ /**
910
+ * Removes the cache entry associated with the specified key.
911
+ *
912
+ * @param key key to be removed from the store
913
+ */
914
+ delete(key) {
915
+ this.services.store.delete(key);
916
+ }
917
+ length() {
918
+ return this.services.store.length();
919
+ }
920
+ keys() {
921
+ return this.services.store.keys();
922
+ }
923
+ toKeySet(keys) {
924
+ return this.services.store.toKeySet(keys);
925
+ }
926
+ }
927
+
1005
928
  /**
1006
- * Exported for testing purposes only
929
+ A utility class for recording actions made on a cache.
1007
930
  */
1008
- class KeyBasedRequestDedupe {
1009
- constructor() {
1010
- // TODO [W-12965475]: This class is a first pass at network deduplication. No consuming Commands should
1011
- // directly try to leverage this, as it will be refactored/removed in the future.
1012
- // This map tracks the mapping of the key set a given network request response is expected to contain
1013
- // to that network request's outstanding promise. Entries are added to this map when a request has
1014
- // a set of expected keys, and a new network request promise is created.
1015
- this.outstandingNetworkRequests = new Map();
1016
- // This map tracks the mapping of the keys a given read is waiting for to a resolve function that notifies the read
1017
- // that the keys it needs may now be present in the cache. This resolve function can be called when any network
1018
- // response is ingested, and the ingested keys contain the keys the read needs. This map is added to when
1019
- // we believe that an outstanding request may contain the keys needed to satisfy a read.
1020
- this.outstandingReads = new Map();
1021
- }
1022
- applyDedupe({ readFromCache, readFromNetwork, writeToCache, }) {
1023
- const closureVariables = { expectedNetworkKeys: undefined };
1024
- return {
1025
- readFromCache: this.buildDedupedReadFromCache(readFromCache, closureVariables),
1026
- readFromNetwork: this.buildDedupedReadFromNetwork(readFromNetwork, closureVariables),
1027
- writeToCache: this.buildDedupedWriteToCache(writeToCache),
1028
- };
931
+ class RecordableCache {
932
+ constructor(baseCache) {
933
+ this.baseCache = baseCache;
934
+ this.keysRead = new KeySetImpl();
935
+ this.missingKeysRead = new KeySetImpl();
936
+ this.keysUpdated = new KeySetImpl();
1029
937
  }
1030
- buildDedupedReadFromCache(readFromCache, closureVariables) {
1031
- const dedupedReadFromCache = (services) => {
1032
- const recordableStore = new RecordableStore(services.store);
1033
- return readFromCache({ ...services, store: recordableStore }).then((value) => {
1034
- const missingKeys = recordableStore.missingKeysRead;
1035
- // if cache result was final, or we got a cache miss even though
1036
- // we don't recognize anything as missing then we're done
1037
- if (isCacheHitOrError(value) || missingKeys.length === 0) {
1038
- return value;
1039
- }
1040
- // if we end up making a network request, we expect that it will return
1041
- // everything that was initially missing
1042
- if (!closureVariables.expectedNetworkKeys) {
1043
- closureVariables.expectedNetworkKeys = missingKeys;
1044
- }
1045
- // build a list of the Promises for all the outstanding network requests
1046
- // that are expected to return at least one of our missing keys
1047
- let unrequestedKeys = services.store.toKeySet(missingKeys.elements());
1048
- const matchingRequests = Array.from(this.outstandingNetworkRequests.entries()).reduce((matches, [outstandingRequestKeys, promise]) => {
1049
- if (outstandingRequestKeys.overlaps(missingKeys)) {
1050
- matches.push(promise);
1051
- unrequestedKeys = unrequestedKeys.difference(outstandingRequestKeys);
1052
- }
1053
- return matches;
1054
- }, []);
1055
- // if outstanding requests are not expected to return all the keys we need,
1056
- // return the cache read result
1057
- if (unrequestedKeys.length > 0) {
1058
- return value;
1059
- }
1060
- // Create a promise that can be resolved if any outstanding requests satisfy
1061
- // the missing keys
1062
- const otherResultMatchesPromise = new Promise((resolve) => {
1063
- this.outstandingReads.set(closureVariables.expectedNetworkKeys, resolve);
1064
- });
1065
- // wait for one of the matching network requests to come back, then retry
1066
- return Promise.race([otherResultMatchesPromise, ...matchingRequests])
1067
- .then(() => {
1068
- this.outstandingReads.delete(closureVariables.expectedNetworkKeys);
1069
- return dedupedReadFromCache(services);
1070
- })
1071
- .catch(() => {
1072
- this.outstandingReads.delete(closureVariables.expectedNetworkKeys);
1073
- return dedupedReadFromCache(services);
1074
- });
1075
- });
1076
- };
1077
- return dedupedReadFromCache;
938
+ delete(key) {
939
+ this.keysUpdated.add(key);
940
+ this.baseCache.delete(key);
1078
941
  }
1079
- buildDedupedReadFromNetwork(readFromNetwork, closureVariables) {
1080
- return () => {
1081
- if (closureVariables.expectedNetworkKeys === undefined ||
1082
- closureVariables.expectedNetworkKeys.length === 0) {
1083
- return readFromNetwork();
1084
- }
1085
- const deleteOutstandingRequest = () => this.outstandingNetworkRequests.delete(closureVariables.expectedNetworkKeys);
1086
- const networkPromise = readFromNetwork().then((value) => {
1087
- deleteOutstandingRequest();
1088
- return value;
1089
- }, (reason) => {
1090
- deleteOutstandingRequest();
1091
- return new Promise((_resolve, rejects) => {
1092
- rejects(reason);
1093
- });
1094
- });
1095
- this.outstandingNetworkRequests.set(closureVariables.expectedNetworkKeys, networkPromise);
1096
- return networkPromise;
1097
- };
942
+ get(key) {
943
+ this.keysRead.add(key);
944
+ const value = this.baseCache.get(key);
945
+ if (value === undefined) {
946
+ this.missingKeysRead.add(key);
947
+ }
948
+ return value;
1098
949
  }
1099
- buildDedupedWriteToCache(writeToCache) {
1100
- return (services, networkResult) => {
1101
- const recordableStore = new RecordableStore(services.store);
1102
- const result = writeToCache({ ...services, store: recordableStore }, networkResult);
1103
- return result.then(() => {
1104
- const updatedKeys = recordableStore.keysUpdated;
1105
- Array.from(this.outstandingReads.entries()).forEach(([outstandingReadKeys, resolve]) => {
1106
- if (outstandingReadKeys.isSubsetOf(updatedKeys)) {
1107
- resolve();
1108
- }
1109
- });
1110
- });
1111
- };
950
+ set(key, value) {
951
+ this.keysUpdated.add(key);
952
+ this.baseCache.set(key, value);
953
+ }
954
+ length() {
955
+ return this.baseCache.length();
956
+ }
957
+ keys() {
958
+ return this.baseCache.keys();
959
+ }
960
+ toKeySet(keys) {
961
+ return this.baseCache.toKeySet(keys);
1112
962
  }
1113
963
  }
1114
- function buildKeyBasedRequestDedupeService() {
964
+
965
+ function buildServiceDescriptor$2(store) {
1115
966
  return {
1116
- type: 'requestDedupe',
967
+ type: 'cache',
1117
968
  version: '1.0',
1118
- service: new KeyBasedRequestDedupe(),
969
+ service: new DefaultCache({ store }),
1119
970
  };
1120
971
  }
1121
972
 
@@ -1127,87 +978,148 @@ function buildKeyBasedRequestDedupeService() {
1127
978
 
1128
979
 
1129
980
  /**
1130
- * A simple implementation of KeyKeySubscriptionService.
981
+ * A utility class for adapting a cache to a TypeStore.
982
+ *
983
+ * This allows command code to write to a cache without having
984
+ * to know about cache control metadata.
1131
985
  */
1132
- class DefaultKeySubscriptionService {
1133
- constructor() {
1134
- this.nextId = 1;
1135
- this.subscriptions = [];
986
+ class CacheControlTypeStoreAdapter {
987
+ constructor(cache, cacheControlMetadata = undefined) {
988
+ this.cache = cache;
989
+ this.cacheControlMetadata = cacheControlMetadata;
1136
990
  }
1137
- subscribe(options) {
1138
- const subscriptionId = this.nextId++;
1139
- const { subscription, callback } = options;
1140
- this.subscriptions.push({ subscriptionId, keys: subscription, callback });
1141
- return () => {
1142
- this.subscriptions = this.subscriptions.filter((subscription) => subscription.subscriptionId !== subscriptionId);
1143
- };
991
+ get(key) {
992
+ return this.cache.get(key);
1144
993
  }
1145
- publish(keys, _options) {
1146
- const subscriptions = this.subscriptions.slice();
1147
- for (let i = 0; i < subscriptions.length; ++i) {
1148
- const { keys: subscriptionKeys, callback } = subscriptions[i];
1149
- if (keys.overlaps(subscriptionKeys)) {
1150
- callback();
1151
- }
994
+ set(key, value) {
995
+ if (this.cacheControlMetadata === undefined) {
996
+ throw new Error('Cache control metadata is undefined');
1152
997
  }
1153
- return resolvedPromiseLike(undefined);
998
+ return this.cache.set(key, {
999
+ ...value,
1000
+ cacheControlMetadata: this.cacheControlMetadata,
1001
+ });
1002
+ }
1003
+ delete(key) {
1004
+ return this.cache.delete(key);
1005
+ }
1006
+ length() {
1007
+ return this.cache.length();
1008
+ }
1009
+ keys() {
1010
+ return this.cache.keys();
1011
+ }
1012
+ toKeySet(keys) {
1013
+ return this.cache.toKeySet(keys);
1154
1014
  }
1155
1015
  }
1156
- /**
1157
- * Constructs a default KeySubscriptionService
1158
- *
1159
- * @returns default KeySubscriptionService
1160
- */
1161
- function buildDefaultKeySubscriptionService() {
1162
- return {
1163
- type: 'keySubscription',
1164
- version: '1.0',
1165
- service: new DefaultKeySubscriptionService(),
1166
- };
1016
+
1017
+ class CacheControlStrategy {
1018
+ constructor(services, config, buildRequestRunnerProxy) {
1019
+ this.services = services;
1020
+ this.config = config;
1021
+ this.recordableCache = new RecordableCache(this.services.cache);
1022
+ this.recordableMaxAgeTypeStore = new CacheControlTypeStoreAdapter(this.recordableCache);
1023
+ this.requestRunnerProxy = buildRequestRunnerProxy(this.recordableMaxAgeTypeStore);
1024
+ }
1025
+ isCacheHit(cacheReadValue) {
1026
+ const isCacheMiss = cacheReadValue.isErr() ||
1027
+ cacheReadValue.value === undefined ||
1028
+ this.areUsedCacheEntriesExpired();
1029
+ return !isCacheMiss;
1030
+ }
1031
+ get expiredChecks() {
1032
+ return [
1033
+ (cacheControlMetadata) => cacheControlMetadata.type === 'max-age' &&
1034
+ this.config.now > cacheControlMetadata.generatedTime + cacheControlMetadata.maxAge,
1035
+ (cacheControlMetadata) => cacheControlMetadata.type === 'no-cache' ||
1036
+ cacheControlMetadata.type === 'no-store',
1037
+ ];
1038
+ }
1039
+ areUsedCacheEntriesExpired() {
1040
+ return this.recordableCache.keysRead.elements().some((key) => {
1041
+ const entry = this.recordableCache.get(key);
1042
+ if (entry === undefined) {
1043
+ // Not sure how this would be possible, but we'll just say it's expired
1044
+ return true;
1045
+ }
1046
+ const { cacheControlMetadata } = entry;
1047
+ return this.expiredChecks.some((check) => check(cacheControlMetadata));
1048
+ });
1049
+ }
1050
+ }
1051
+
1052
+ class MaxAgeCacheControlStrategy extends CacheControlStrategy {
1053
+ execute() {
1054
+ return this.requestRunnerProxy.readFromCache().then((value) => {
1055
+ if (this.isCacheHit(value)) {
1056
+ return value;
1057
+ }
1058
+ return this.handleCacheMiss();
1059
+ });
1060
+ }
1061
+ handleCacheMiss() {
1062
+ let error;
1063
+ return this.requestRunnerProxy
1064
+ .requestFromNetwork()
1065
+ .then((value) => {
1066
+ if (value.isErr()) {
1067
+ error = value;
1068
+ return resolvedPromiseLike(null);
1069
+ }
1070
+ this.recordableMaxAgeTypeStore.cacheControlMetadata =
1071
+ value.value.cacheControlMetadata;
1072
+ return this.requestRunnerProxy.writeToCache(ok(value.value.networkResponse));
1073
+ })
1074
+ .then(() => {
1075
+ if (error) {
1076
+ return resolvedPromiseLike(null);
1077
+ }
1078
+ return this.requestRunnerProxy.readFromCache();
1079
+ })
1080
+ .then((value) => {
1081
+ if (value === null) {
1082
+ return error;
1083
+ }
1084
+ if (!this.isCacheHit(value)) {
1085
+ return err(new Error('Cache miss after fetching from network'));
1086
+ }
1087
+ return value;
1088
+ });
1089
+ }
1090
+ get expiredChecks() {
1091
+ return [
1092
+ ...super.expiredChecks,
1093
+ (cacheControlMetadata) => cacheControlMetadata.generatedTime + this.config.requestMaxAge < this.config.now,
1094
+ ];
1095
+ }
1167
1096
  }
1168
1097
 
1169
1098
  /**
1170
- * Copyright (c) 2022, Salesforce, Inc.,
1171
- * All rights reserved.
1172
- * For full license text, see the LICENSE.txt file
1099
+ * A class that allows the execution of requested cache control strategies,
1100
+ * while also enforcing the canonical cache control metadata.
1173
1101
  */
1174
-
1175
-
1176
- class DefaultTypeNotFoundError extends Error {
1177
- }
1178
- class DefaultTypeRegistry {
1179
- constructor() {
1180
- this.registry = {};
1181
- this.TypeNotFoundError = DefaultTypeNotFoundError;
1102
+ class CacheController {
1103
+ constructor(services) {
1104
+ this.services = services;
1182
1105
  }
1183
- register(type, _options) {
1184
- if (!this.registry[type.namespace]) {
1185
- this.registry[type.namespace] = {};
1186
- }
1187
- this.registry[type.namespace][type.typeName] = type;
1106
+ execute(config, buildRequestRunnerProxy) {
1107
+ const strategy = this.getCacheControlStrategy(config, buildRequestRunnerProxy);
1108
+ return strategy.execute();
1188
1109
  }
1189
- get(namespace, typeName, _options) {
1190
- const registryNamespace = this.registry[namespace];
1191
- if (!registryNamespace) {
1192
- throw new DefaultTypeNotFoundError(`namespace ${namespace} not found`);
1193
- }
1194
- const type = registryNamespace[typeName];
1195
- if (!type) {
1196
- throw new DefaultTypeNotFoundError(`type ${typeName} not found in namespace ${namespace}`);
1110
+ getCacheControlStrategy(config, buildRequestRunnerProxy) {
1111
+ if (config.type === 'max-age') {
1112
+ return new MaxAgeCacheControlStrategy(this.services, config, buildRequestRunnerProxy);
1197
1113
  }
1198
- return type;
1114
+ throw new Error(`Unknown cache control strategy ${config.type}`);
1199
1115
  }
1200
1116
  }
1201
- /**
1202
- * Constructs an in-memory implementation of StoreService.
1203
- *
1204
- * @returns in-memory implementation of StoreService
1205
- */
1206
- function buildDefaultTypeRegistryService() {
1117
+
1118
+ function buildServiceDescriptor$1(cache) {
1207
1119
  return {
1208
- type: 'typeRegistry',
1120
+ type: 'cacheControl',
1209
1121
  version: '1.0',
1210
- service: new DefaultTypeRegistry(),
1122
+ service: new CacheController({ cache }),
1211
1123
  };
1212
1124
  }
1213
1125
 
@@ -1217,7 +1129,7 @@ function buildDefaultTypeRegistryService() {
1217
1129
  * For full license text, see the LICENSE.txt file
1218
1130
  */
1219
1131
 
1220
- function e$1(e){this.message=e;}e$1.prototype=new Error,e$1.prototype.name="InvalidCharacterError";var r$1="undefined"!=typeof window&&window.atob&&window.atob.bind(window)||function(r){var t=String(r).replace(/=+$/,"");if(t.length%4==1)throw new e$1("'atob' failed: The string to be decoded is not correctly encoded.");for(var n,o,a=0,i=0,c="";o=t.charAt(i++);~o&&(n=a%4?64*n+o:o,a++%4)?c+=String.fromCharCode(255&n>>(-2*a&6)):0)o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(o);return c};function t$1(e){var t=e.replace(/-/g,"+").replace(/_/g,"/");switch(t.length%4){case 0:break;case 2:t+="==";break;case 3:t+="=";break;default:throw "Illegal base64url string!"}try{return function(e){return decodeURIComponent(r$1(e).replace(/(.)/g,(function(e,r){var t=r.charCodeAt(0).toString(16).toUpperCase();return t.length<2&&(t="0"+t),"%"+t})))}(t)}catch(e){return r$1(t)}}function n$1(e){this.message=e;}function o$1(e,r){if("string"!=typeof e)throw new n$1("Invalid token specified");var o=!0===(r=r||{}).header?0:1;try{return JSON.parse(t$1(e.split(".")[o]))}catch(e){throw new n$1("Invalid token specified: "+e.message)}}n$1.prototype=new Error,n$1.prototype.name="InvalidTokenError";
1132
+ function e$1(e){this.message=e;}e$1.prototype=new Error,e$1.prototype.name="InvalidCharacterError";var r="undefined"!=typeof window&&window.atob&&window.atob.bind(window)||function(r){var t=String(r).replace(/=+$/,"");if(t.length%4==1)throw new e$1("'atob' failed: The string to be decoded is not correctly encoded.");for(var n,o,a=0,i=0,c="";o=t.charAt(i++);~o&&(n=a%4?64*n+o:o,a++%4)?c+=String.fromCharCode(255&n>>(-2*a&6)):0)o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(o);return c};function t(e){var t=e.replace(/-/g,"+").replace(/_/g,"/");switch(t.length%4){case 0:break;case 2:t+="==";break;case 3:t+="=";break;default:throw "Illegal base64url string!"}try{return function(e){return decodeURIComponent(r(e).replace(/(.)/g,(function(e,r){var t=r.charCodeAt(0).toString(16).toUpperCase();return t.length<2&&(t="0"+t),"%"+t})))}(t)}catch(e){return r(t)}}function n$1(e){this.message=e;}function o(e,r){if("string"!=typeof e)throw new n$1("Invalid token specified");var o=!0===(r=r||{}).header?0:1;try{return JSON.parse(t(e.split(".")[o]))}catch(e){throw new n$1("Invalid token specified: "+e.message)}}n$1.prototype=new Error,n$1.prototype.name="InvalidTokenError";
1221
1133
 
1222
1134
  /**
1223
1135
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -1357,7 +1269,7 @@ if (process.env.NODE_ENV !== 'production') {
1357
1269
  * @returns An object of decoded JWT token information.
1358
1270
  */
1359
1271
  function computeDecodedInfo(token, defaultTokenTTLInSeconds, logger) {
1360
- const decodedInfo = o$1(token);
1272
+ const decodedInfo = o(token);
1361
1273
  if (decodedInfo.exp === undefined) {
1362
1274
  logger.warn(`"exp" claim is not present in the provided token.`);
1363
1275
  decodedInfo.exp = Date.now() / 1000 + defaultTokenTTLInSeconds;
@@ -1541,7 +1453,7 @@ class JwtManager {
1541
1453
  */
1542
1454
 
1543
1455
 
1544
- function buildFetchService(interceptors = { request: [] }) {
1456
+ function buildServiceDescriptor(interceptors = { request: [] }) {
1545
1457
  return {
1546
1458
  type: 'fetch',
1547
1459
  version: '1.0',
@@ -1712,10 +1624,10 @@ const composedNetworkAdapter$1 = {
1712
1624
  adapter: sfapNetworkAdapter,
1713
1625
  };
1714
1626
 
1715
- function e(e){this.message=e;}e.prototype=new Error,e.prototype.name="InvalidCharacterError";var r="undefined"!=typeof window&&window.atob&&window.atob.bind(window)||function(r){var t=String(r).replace(/=+$/,"");if(t.length%4==1)throw new e("'atob' failed: The string to be decoded is not correctly encoded.");for(var n,o,a=0,i=0,c="";o=t.charAt(i++);~o&&(n=a%4?64*n+o:o,a++%4)?c+=String.fromCharCode(255&n>>(-2*a&6)):0)o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(o);return c};function t(e){var t=e.replace(/-/g,"+").replace(/_/g,"/");switch(t.length%4){case 0:break;case 2:t+="==";break;case 3:t+="=";break;default:throw "Illegal base64url string!"}try{return function(e){return decodeURIComponent(r(e).replace(/(.)/g,(function(e,r){var t=r.charCodeAt(0).toString(16).toUpperCase();return t.length<2&&(t="0"+t),"%"+t})))}(t)}catch(e){return r(t)}}function n(e){this.message=e;}function o(e,r){if("string"!=typeof e)throw new n("Invalid token specified");var o=!0===(r=r||{}).header?0:1;try{return JSON.parse(t(e.split(".")[o]))}catch(e){throw new n("Invalid token specified: "+e.message)}}n.prototype=new Error,n.prototype.name="InvalidTokenError";
1627
+ function e(e){this.message=e;}e.prototype=new Error,e.prototype.name="InvalidCharacterError";"undefined"!=typeof window&&window.atob&&window.atob.bind(window)||function(r){var t=String(r).replace(/=+$/,"");if(t.length%4==1)throw new e("'atob' failed: The string to be decoded is not correctly encoded.");for(var n,o,a=0,i=0,c="";o=t.charAt(i++);~o&&(n=a%4?64*n+o:o,a++%4)?c+=String.fromCharCode(255&n>>(-2*a&6)):0)o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(o);return c};function n(e){this.message=e;}n.prototype=new Error,n.prototype.name="InvalidTokenError";
1716
1628
 
1717
1629
  const SFAP_BASE_URL = 'api.salesforce.com';
1718
- function buildJwtAuthorizedSfapFetchService(logger) {
1630
+ function buildJwtAuthorizedSfapFetchServiceDescriptor(logger) {
1719
1631
  const jwtRepository = new JwtRepository();
1720
1632
  const jwtManager = new JwtManager(jwtRepository, platformSfapJwtResolver);
1721
1633
  const jwtRequestModifier = ({ baseUri }, [resource, request]) => {
@@ -1737,52 +1649,16 @@ function buildJwtAuthorizedSfapFetchService(logger) {
1737
1649
  return [url, request];
1738
1650
  };
1739
1651
  const jwtRequestHeaderInterceptor = buildJwtRequestHeaderInterceptor(jwtManager, jwtRequestModifier);
1740
- const jwtAuthorizedFetchService = buildFetchService({ request: [jwtRequestHeaderInterceptor] });
1652
+ const jwtAuthorizedFetchService = buildServiceDescriptor({
1653
+ request: [jwtRequestHeaderInterceptor],
1654
+ });
1741
1655
  return {
1742
1656
  ...jwtAuthorizedFetchService,
1743
1657
  tags: { authenticationScopes: 'sfap_api' },
1744
1658
  };
1745
1659
  }
1746
- const lightningJwtResolver = {
1747
- getJwt() {
1748
- // JWT Manager should be updated to use promise like instead of promise to accomadate use cases like this
1749
- return resolvedPromiseLike(window.$A.clientService.getJwtAuthToken()).then((jwt) => {
1750
- const baseUri = o(jwt.jwt).iss;
1751
- return {
1752
- jwt: jwt.jwt,
1753
- extraInfo: { baseUri },
1754
- };
1755
- });
1756
- },
1757
- };
1758
- function buildJwtAuthorizedLightningFetchService() {
1759
- const jwtRepository = new JwtRepository();
1760
- const jwtManager = new JwtManager(jwtRepository, lightningJwtResolver);
1761
- const jwtRequestModifier = ({ baseUri }, [resource, request]) => {
1762
- if (typeof resource !== 'string' && !(resource instanceof URL)) {
1763
- // istanbul ignore else: this will not be tested in NODE_ENV = production for test coverage
1764
- if (process.env.NODE_ENV !== 'production') {
1765
- throw new Error('Lightning fetch service expects a string or URL resource');
1766
- }
1767
- return [resource, request];
1768
- }
1769
- const url = typeof resource === 'string'
1770
- ? new URL(resource, 'https://lightning.salesforce.com')
1771
- : new URL(resource.toString());
1772
- const overrideUrl = new URL(baseUri);
1773
- url.host = overrideUrl.host;
1774
- url.protocol = overrideUrl.protocol;
1775
- return [url, request];
1776
- };
1777
- const jwtRequestHeaderInterceptor = buildJwtRequestHeaderInterceptor(jwtManager, jwtRequestModifier);
1778
- const jwtAuthorizedFetchService = buildFetchService({ request: [jwtRequestHeaderInterceptor] });
1779
- return {
1780
- ...jwtAuthorizedFetchService,
1781
- tags: { authenticationScopes: 'lightning_api' },
1782
- };
1783
- }
1784
- function buildUnauthorizedFetchService() {
1785
- const fetchService = buildFetchService();
1660
+ function buildUnauthorizedFetchServiceDescriptor() {
1661
+ const fetchService = buildServiceDescriptor();
1786
1662
  return {
1787
1663
  ...fetchService,
1788
1664
  tags: { authenticationScopes: '' },
@@ -4249,7 +4125,7 @@ function getEnvironmentSetting(name) {
4249
4125
  }
4250
4126
  return undefined;
4251
4127
  }
4252
- // version: 1.316.0-4453f1e2b6
4128
+ // version: 1.318.0-46c39b8717
4253
4129
 
4254
4130
  const forceRecordTransactionsDisabled = getEnvironmentSetting(EnvironmentSettings.ForceRecordTransactionsDisabled);
4255
4131
  //TODO: Some duplication here that can be most likely moved to a util class
@@ -4901,58 +4777,22 @@ function initializeLDS() {
4901
4777
  }
4902
4778
  // Initializes OneStore in LEX
4903
4779
  function initializeOneStore() {
4904
- const validator = {
4905
- validateReadResult() { },
4906
- validateWriteResult() { },
4907
- validateBuildResult() { },
4908
- };
4909
- const keySubscriptionServiceDescriptor = buildDefaultKeySubscriptionService();
4910
- const metadataRepositoryServiceDescriptor = buildInMemoryMetadataRepositoryService();
4911
- const storeServiceDescriptor = buildInMemoryStoreService();
4912
- const requestDedupeServiceDescriptor = buildKeyBasedRequestDedupeService();
4913
- const cachePolicyServiceDescriptor = {
4914
- type: 'cachePolicy',
4915
- version: '1.0',
4916
- service: {
4917
- cachePolicies: [
4918
- buildCacheThenNetworkPolicy({
4919
- keySubscription: keySubscriptionServiceDescriptor.service,
4920
- metadataRepository: metadataRepositoryServiceDescriptor.service,
4921
- requestDedupe: requestDedupeServiceDescriptor.service,
4922
- store: storeServiceDescriptor.service,
4923
- }, validator),
4924
- ],
4925
- defaultCachePolicyName: 'cache-then-network',
4926
- },
4927
- };
4928
- // TODO [W-1234567]: Export descriptor builder for o11y and noop instrumentaiton
4929
- const instrumentationServiceDescriptor = {
4930
- type: 'instrumentation',
4931
- version: '1.0',
4932
- service: buildNoopInstrumentationService(),
4933
- };
4934
4780
  const loggerService = new ConsoleLogger$1('ERROR');
4781
+ const storeServiceDescriptor = buildServiceDescriptor$3();
4782
+ const cacheServiceDescriptor = buildServiceDescriptor$2(storeServiceDescriptor.service);
4783
+ const instrumentationServiceDescriptor = buildServiceDescriptor$4(loggerService);
4935
4784
  const services = [
4936
- buildUnauthorizedFetchService(),
4937
- buildJwtAuthorizedSfapFetchService(loggerService),
4938
- buildJwtAuthorizedLightningFetchService(),
4939
- keySubscriptionServiceDescriptor,
4940
- metadataRepositoryServiceDescriptor,
4941
- storeServiceDescriptor,
4942
- requestDedupeServiceDescriptor,
4943
- cachePolicyServiceDescriptor,
4944
- buildDefaultTypeRegistryService(),
4945
- buildAuraNetworkService(),
4946
- buildInMemoryCacheInclusionPolicyService(),
4947
- buildAuraNetworkCommandBaseClassService(),
4948
- buildFetchNetworkCommandBaseClassService(),
4949
- buildNetworkCommandBaseClassService(),
4950
- buildStreamingCommandBaseClassService(),
4951
- buildSSECommandBaseClassService(),
4952
4785
  instrumentationServiceDescriptor,
4953
- buildInstrumentCommandServiceDescriptor({
4954
- instrumentation: instrumentationServiceDescriptor.service,
4955
- }),
4786
+ buildUnauthorizedFetchServiceDescriptor(),
4787
+ buildJwtAuthorizedSfapFetchServiceDescriptor(loggerService),
4788
+ buildAuraNetworkService(),
4789
+ buildServiceDescriptor$5(instrumentationServiceDescriptor.service),
4790
+ buildServiceDescriptor$1(cacheServiceDescriptor.service),
4791
+ buildServiceDescriptor$9(),
4792
+ buildServiceDescriptor$8(),
4793
+ buildServiceDescriptor$a(),
4794
+ buildServiceDescriptor$7(),
4795
+ buildServiceDescriptor$6(),
4956
4796
  ];
4957
4797
  serviceBroker.publish(services);
4958
4798
  }
@@ -4981,4 +4821,4 @@ function ldsEngineCreator() {
4981
4821
  }
4982
4822
 
4983
4823
  export { LexRequestStrategy, buildPredictorForContext, ldsEngineCreator as default, initializeLDS, initializeOneStore, registerRequestStrategy, saveRequestAsPrediction, unregisterRequestStrategy, whenPredictionsReady };
4984
- // version: 1.316.0-fd56ed976d
4824
+ // version: 1.318.0-5cd8dfe184