@salesforce/lds-runtime-mobile 1.419.0 → 1.420.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.
- package/dist/main.js +257 -60
- package/package.json +16 -16
- package/sfdc/main.js +257 -60
package/dist/main.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { withRegistration, register } from '@salesforce/lds-default-luvio';
|
|
19
19
|
import { setupInstrumentation, instrumentAdapter as instrumentAdapter$1, instrumentLuvio, setLdsAdaptersUiapiInstrumentation, setLdsNetworkAdapterInstrumentation } from '@salesforce/lds-instrumentation';
|
|
20
|
-
import { HttpStatusCode as HttpStatusCode$1, setBypassDeepFreeze, StoreKeySet,
|
|
20
|
+
import { HttpStatusCode as HttpStatusCode$1, setBypassDeepFreeze, StoreKeySet, StringKeyInMemoryStore, Reader, serializeStructuredKey, deepFreeze as deepFreeze$1, emitAdapterEvent, ingestShape, coerceConfig as coerceConfig$1, typeCheckConfig as typeCheckConfig$h, createResourceParams as createResourceParams$h, StoreKeyMap, buildNetworkSnapshotCachePolicy as buildNetworkSnapshotCachePolicy$f, resolveLink, createCustomAdapterEventEmitter, isFileReference, Environment, Luvio, InMemoryStore } from '@luvio/engine';
|
|
21
21
|
import { isSupportedEntity, configuration, getObjectInfoAdapterFactory, RECORD_ID_PREFIX, RECORD_FIELDS_KEY_JUNCTION, isStoreKeyRecordViewEntity, extractRecordIdFromStoreKey, buildRecordRepKeyFromId, keyBuilderRecord, RecordRepresentationTTL, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, getRecordId18 as getRecordId18$1, getRecordsAdapterFactory as getRecordsAdapterFactory$1, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getObjectInfosAdapterFactory, getObjectInfoDirectoryAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationVersion } from '@salesforce/lds-adapters-uiapi';
|
|
22
22
|
import allowUpdatesForNonCachedRecords from '@salesforce/gate/lmr.allowUpdatesForNonCachedRecords';
|
|
23
23
|
import { getInstrumentation, idleDetector } from 'o11y/client';
|
|
@@ -541,7 +541,7 @@ const RedirectDurableSegment$1 = 'REDIRECT_KEYS';
|
|
|
541
541
|
const MessagingDurableSegment = 'MESSAGING';
|
|
542
542
|
const MessageNotifyStoreUpdateAvailable = 'notifyStoreUpdateAvailable';
|
|
543
543
|
|
|
544
|
-
const { keys: keys$5, create: create$5, assign: assign$4, freeze: freeze$2 } = Object;
|
|
544
|
+
const { keys: keys$5, create: create$5, assign: assign$4, freeze: freeze$2, isFrozen: isFrozen$1 } = Object;
|
|
545
545
|
|
|
546
546
|
//Durable store error instrumentation key
|
|
547
547
|
const DURABLE_STORE_ERROR = 'durable-store-error';
|
|
@@ -628,6 +628,74 @@ function publishDurableStoreEntries(durableRecords, put, publishMetadata) {
|
|
|
628
628
|
}
|
|
629
629
|
return { revivedKeys, hadUnexpectedShape };
|
|
630
630
|
}
|
|
631
|
+
/**
|
|
632
|
+
* Extracts field filtering configuration from the selection.
|
|
633
|
+
*/
|
|
634
|
+
function extractFieldFilteringConfig(select, recordId, baseEnvironment) {
|
|
635
|
+
const rootRecordKey = serializeStructuredKey(baseEnvironment.storeGetCanonicalKey(recordId));
|
|
636
|
+
let topLevelFields;
|
|
637
|
+
let nestedFieldRequirements;
|
|
638
|
+
if (select &&
|
|
639
|
+
select.node.kind === 'Fragment' &&
|
|
640
|
+
'selections' in select.node &&
|
|
641
|
+
select.node.selections) {
|
|
642
|
+
topLevelFields = extractRequestedFieldNames(select.node.selections);
|
|
643
|
+
nestedFieldRequirements = extractNestedFieldRequirements(select.node.selections);
|
|
644
|
+
}
|
|
645
|
+
// Merge all nested field requirements into a single set
|
|
646
|
+
let nestedFields;
|
|
647
|
+
if (nestedFieldRequirements && nestedFieldRequirements.size > 0) {
|
|
648
|
+
nestedFields = new Set();
|
|
649
|
+
for (const fieldSet of nestedFieldRequirements.values()) {
|
|
650
|
+
for (const field of fieldSet) {
|
|
651
|
+
nestedFields.add(field);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
return { rootRecordKey, topLevelFields, nestedFields };
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Categorizes keys into different fetch strategies based on filtering requirements.
|
|
659
|
+
*/
|
|
660
|
+
function categorizeKeysForL2Fetch(keysToRevive, config, baseEnvironment, shouldFilterFields) {
|
|
661
|
+
const unfilteredKeys = [];
|
|
662
|
+
const rootKeysWithTopLevelFields = [];
|
|
663
|
+
const nestedKeysWithNestedFields = [];
|
|
664
|
+
const canFilter = config.topLevelFields !== undefined && config.topLevelFields.size > 0;
|
|
665
|
+
for (let i = 0, len = keysToRevive.length; i < len; i += 1) {
|
|
666
|
+
const canonicalKey = serializeStructuredKey(baseEnvironment.storeGetCanonicalKey(keysToRevive[i]));
|
|
667
|
+
if (!shouldFilterFields(canonicalKey) || !canFilter) {
|
|
668
|
+
unfilteredKeys.push(canonicalKey);
|
|
669
|
+
continue;
|
|
670
|
+
}
|
|
671
|
+
const isRootRecord = canonicalKey === config.rootRecordKey;
|
|
672
|
+
if (isRootRecord) {
|
|
673
|
+
rootKeysWithTopLevelFields.push(canonicalKey);
|
|
674
|
+
}
|
|
675
|
+
else if (config.nestedFields !== undefined && config.nestedFields.size > 0) {
|
|
676
|
+
nestedKeysWithNestedFields.push(canonicalKey);
|
|
677
|
+
}
|
|
678
|
+
else {
|
|
679
|
+
unfilteredKeys.push(canonicalKey);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
return { unfilteredKeys, rootKeysWithTopLevelFields, nestedKeysWithNestedFields };
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Builds L2 fetch promises for different key categories.
|
|
686
|
+
*/
|
|
687
|
+
function buildL2FetchPromises(categorizedKeys, config, durableStore) {
|
|
688
|
+
const promises = [
|
|
689
|
+
durableStore.getEntries(categorizedKeys.unfilteredKeys, DefaultDurableSegment),
|
|
690
|
+
];
|
|
691
|
+
if (config.topLevelFields && categorizedKeys.rootKeysWithTopLevelFields.length > 0) {
|
|
692
|
+
promises.push(durableStore.getEntriesWithSpecificFields(categorizedKeys.rootKeysWithTopLevelFields, config.topLevelFields, DefaultDurableSegment));
|
|
693
|
+
}
|
|
694
|
+
if (config.nestedFields && categorizedKeys.nestedKeysWithNestedFields.length > 0) {
|
|
695
|
+
promises.push(durableStore.getEntriesWithSpecificFields(categorizedKeys.nestedKeysWithNestedFields, config.nestedFields, DefaultDurableSegment));
|
|
696
|
+
}
|
|
697
|
+
return promises;
|
|
698
|
+
}
|
|
631
699
|
/**
|
|
632
700
|
* This method returns a Promise to a snapshot that is revived from L2 cache. If
|
|
633
701
|
* L2 does not have the entries necessary to fulfill the snapshot then this method
|
|
@@ -663,53 +731,41 @@ function reviveSnapshot(baseEnvironment, durableStore, unavailableSnapshot, dura
|
|
|
663
731
|
const keysToRevive = keysToReviveSet.keysAsArray();
|
|
664
732
|
const start = Date.now();
|
|
665
733
|
const { l2Trips } = reviveMetrics;
|
|
666
|
-
// Extract
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
const
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
if (requestedFields !== undefined &&
|
|
677
|
-
requestedFields.size > 0 &&
|
|
678
|
-
shouldFilterFields(canonicalKey)) {
|
|
679
|
-
filteredCanonicalKeys.push(canonicalKey);
|
|
680
|
-
}
|
|
681
|
-
else {
|
|
682
|
-
canonicalKeys.push(canonicalKey);
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
const fetchPromises = [
|
|
686
|
-
durableStore.getEntries(canonicalKeys, DefaultDurableSegment),
|
|
687
|
-
];
|
|
688
|
-
if (requestedFields !== undefined &&
|
|
689
|
-
requestedFields.size > 0 &&
|
|
690
|
-
filteredCanonicalKeys.length > 0) {
|
|
691
|
-
fetchPromises.push(durableStore.getEntriesWithSpecificFields(filteredCanonicalKeys, requestedFields, DefaultDurableSegment));
|
|
692
|
-
}
|
|
693
|
-
return Promise.all(fetchPromises).then(([durableRecords, filteredDurableRecords]) => {
|
|
734
|
+
// Extract field filtering requirements from the selection
|
|
735
|
+
const fieldFilteringConfig = extractFieldFilteringConfig(select, recordId, baseEnvironment);
|
|
736
|
+
// Categorize keys by how they should be fetched from L2
|
|
737
|
+
const categorizedKeys = categorizeKeysForL2Fetch(keysToRevive, fieldFilteringConfig, baseEnvironment, shouldFilterFields);
|
|
738
|
+
// Build fetch promises for each category
|
|
739
|
+
const fetchPromises = buildL2FetchPromises(categorizedKeys, fieldFilteringConfig, durableStore);
|
|
740
|
+
return Promise.all(fetchPromises).then(([durableRecords, filteredDurableRecords, nestedFilteredDurableRecords]) => {
|
|
741
|
+
const totalKeysRequested = categorizedKeys.unfilteredKeys.length +
|
|
742
|
+
categorizedKeys.rootKeysWithTopLevelFields.length +
|
|
743
|
+
categorizedKeys.nestedKeysWithNestedFields.length;
|
|
694
744
|
l2Trips.push({
|
|
695
745
|
duration: Date.now() - start,
|
|
696
|
-
keysRequestedCount:
|
|
746
|
+
keysRequestedCount: totalKeysRequested,
|
|
697
747
|
});
|
|
698
|
-
// Process
|
|
748
|
+
// Process all three categories of records
|
|
699
749
|
const revivedKeys = new StoreKeySet();
|
|
700
750
|
let hadUnexpectedShape = false;
|
|
701
|
-
// Process normal records
|
|
751
|
+
// Process normal records (all fields)
|
|
702
752
|
if (durableRecords !== undefined) {
|
|
703
753
|
const normalResult = publishDurableStoreEntries(durableRecords, baseEnvironment.storePut.bind(baseEnvironment), baseEnvironment.publishStoreMetadata.bind(baseEnvironment));
|
|
704
754
|
revivedKeys.merge(normalResult.revivedKeys);
|
|
705
755
|
hadUnexpectedShape = hadUnexpectedShape || normalResult.hadUnexpectedShape;
|
|
706
756
|
}
|
|
707
|
-
// Process filtered records with merging
|
|
757
|
+
// Process filtered records (root with top-level fields) with merging
|
|
708
758
|
if (filteredDurableRecords !== undefined) {
|
|
709
759
|
const filteredResult = publishDurableStoreEntries(filteredDurableRecords, createMergeFilteredPut((key) => baseEnvironment.store.readEntry(key), baseEnvironment.storePut.bind(baseEnvironment)), baseEnvironment.publishStoreMetadata.bind(baseEnvironment));
|
|
710
760
|
revivedKeys.merge(filteredResult.revivedKeys);
|
|
711
761
|
hadUnexpectedShape = hadUnexpectedShape || filteredResult.hadUnexpectedShape;
|
|
712
762
|
}
|
|
763
|
+
// Process nested filtered records with merging
|
|
764
|
+
if (nestedFilteredDurableRecords !== undefined) {
|
|
765
|
+
const nestedFilteredResult = publishDurableStoreEntries(nestedFilteredDurableRecords, createMergeFilteredPut((key) => baseEnvironment.store.readEntry(key), baseEnvironment.storePut.bind(baseEnvironment)), baseEnvironment.publishStoreMetadata.bind(baseEnvironment));
|
|
766
|
+
revivedKeys.merge(nestedFilteredResult.revivedKeys);
|
|
767
|
+
hadUnexpectedShape = hadUnexpectedShape || nestedFilteredResult.hadUnexpectedShape;
|
|
768
|
+
}
|
|
713
769
|
// if the data coming back from DS had an unexpected shape then just
|
|
714
770
|
// return the L1 snapshot
|
|
715
771
|
if (hadUnexpectedShape === true) {
|
|
@@ -755,6 +811,54 @@ function reviveSnapshot(baseEnvironment, durableStore, unavailableSnapshot, dura
|
|
|
755
811
|
return { snapshot: unavailableSnapshot, metrics: reviveMetrics };
|
|
756
812
|
});
|
|
757
813
|
}
|
|
814
|
+
/**
|
|
815
|
+
* Filters out null fields from a fields object (null indicates field doesn't exist in L2).
|
|
816
|
+
* Returns a new object without null values, or the original if no filtering needed.
|
|
817
|
+
*/
|
|
818
|
+
function filterNullFields(fields) {
|
|
819
|
+
const keys$1 = keys$5(fields);
|
|
820
|
+
let hasNull = false;
|
|
821
|
+
// Check if any nulls exist before allocating new object
|
|
822
|
+
for (let i = 0, len = keys$1.length; i < len; i += 1) {
|
|
823
|
+
if (fields[keys$1[i]] === null) {
|
|
824
|
+
hasNull = true;
|
|
825
|
+
break;
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
if (!hasNull) {
|
|
829
|
+
return fields;
|
|
830
|
+
}
|
|
831
|
+
const cleaned = {};
|
|
832
|
+
for (let i = 0, len = keys$1.length; i < len; i += 1) {
|
|
833
|
+
const key = keys$1[i];
|
|
834
|
+
if (fields[key] !== null) {
|
|
835
|
+
cleaned[key] = fields[key];
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
return cleaned;
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Merges new fields into existing fields object, skipping null values.
|
|
842
|
+
* Creates a new object to avoid mutations.
|
|
843
|
+
*/
|
|
844
|
+
function mergeFieldsObjects(existing, incoming) {
|
|
845
|
+
const merged = { ...existing };
|
|
846
|
+
const keys$1 = keys$5(incoming);
|
|
847
|
+
for (let i = 0, len = keys$1.length; i < len; i += 1) {
|
|
848
|
+
const key = keys$1[i];
|
|
849
|
+
// Skip null values - they indicate the field doesn't exist in L2
|
|
850
|
+
if (incoming[key] !== null) {
|
|
851
|
+
merged[key] = incoming[key];
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
return merged;
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* Type guard to check if value is a non-null object.
|
|
858
|
+
*/
|
|
859
|
+
function isObject$1(value) {
|
|
860
|
+
return typeof value === 'object' && value !== null;
|
|
861
|
+
}
|
|
758
862
|
/**
|
|
759
863
|
* Creates a put function that merges filtered fields with existing L1 records instead of replacing them.
|
|
760
864
|
* This is used when reviving filtered fields from L2 to preserve existing data in L1.
|
|
@@ -762,28 +866,36 @@ function reviveSnapshot(baseEnvironment, durableStore, unavailableSnapshot, dura
|
|
|
762
866
|
function createMergeFilteredPut(readEntry, storePut) {
|
|
763
867
|
return (key, filteredData) => {
|
|
764
868
|
const existingRecord = readEntry(key);
|
|
765
|
-
if
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
const
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
869
|
+
// Merge with existing record if both are objects
|
|
870
|
+
if (isObject$1(existingRecord) && isObject$1(filteredData)) {
|
|
871
|
+
// Create target object (copy if frozen to avoid mutation errors)
|
|
872
|
+
const targetObj = isFrozen$1(existingRecord)
|
|
873
|
+
? { ...existingRecord }
|
|
874
|
+
: existingRecord;
|
|
875
|
+
const keys$1 = keys$5(filteredData);
|
|
876
|
+
for (let i = 0, len = keys$1.length; i < len; i += 1) {
|
|
877
|
+
const fieldKey = keys$1[i];
|
|
878
|
+
const incomingValue = filteredData[fieldKey];
|
|
879
|
+
// Special handling for 'fields' property to merge rather than replace
|
|
880
|
+
if (fieldKey === 'fields' &&
|
|
881
|
+
isObject$1(incomingValue) &&
|
|
882
|
+
isObject$1(targetObj[fieldKey])) {
|
|
883
|
+
targetObj[fieldKey] = mergeFieldsObjects(targetObj[fieldKey], incomingValue);
|
|
884
|
+
}
|
|
885
|
+
else {
|
|
886
|
+
targetObj[fieldKey] = incomingValue;
|
|
887
|
+
}
|
|
782
888
|
}
|
|
783
889
|
storePut(key, targetObj);
|
|
784
890
|
}
|
|
785
891
|
else {
|
|
786
|
-
// No existing record
|
|
892
|
+
// No existing record - clean null fields before storing
|
|
893
|
+
if (isObject$1(filteredData) && 'fields' in filteredData) {
|
|
894
|
+
const fields = filteredData.fields;
|
|
895
|
+
if (isObject$1(fields)) {
|
|
896
|
+
filteredData.fields = filterNullFields(fields);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
787
899
|
storePut(key, filteredData);
|
|
788
900
|
}
|
|
789
901
|
};
|
|
@@ -797,16 +909,101 @@ function extractRequestedFieldNames(selections) {
|
|
|
797
909
|
return undefined;
|
|
798
910
|
}
|
|
799
911
|
// Find the 'fields' ObjectSelection
|
|
800
|
-
|
|
801
|
-
|
|
912
|
+
let fieldsSelection;
|
|
913
|
+
for (let i = 0, len = selections.length; i < len; i += 1) {
|
|
914
|
+
const sel = selections[i];
|
|
915
|
+
if (sel.kind === 'Object' && sel.name === 'fields') {
|
|
916
|
+
fieldsSelection = sel;
|
|
917
|
+
break;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
if (!fieldsSelection ||
|
|
921
|
+
!fieldsSelection.selections ||
|
|
922
|
+
fieldsSelection.selections.length === 0) {
|
|
802
923
|
return undefined;
|
|
803
924
|
}
|
|
804
925
|
// Extract all field names from the fields selections
|
|
926
|
+
const fieldSelections = fieldsSelection.selections;
|
|
805
927
|
const fieldNames = new Set();
|
|
806
|
-
for (
|
|
807
|
-
fieldNames.add(
|
|
928
|
+
for (let i = 0, len = fieldSelections.length; i < len; i += 1) {
|
|
929
|
+
fieldNames.add(fieldSelections[i].name);
|
|
930
|
+
}
|
|
931
|
+
return fieldNames;
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
934
|
+
* Extracts nested field requirements for spanning fields.
|
|
935
|
+
* For spanning fields like Case.CreatedBy.Name, we need to extract what fields
|
|
936
|
+
* are requested from the nested record (User in this case).
|
|
937
|
+
* The structure is: fields { CreatedBy { value (Link with fragment) { fields { Name } } } }
|
|
938
|
+
*/
|
|
939
|
+
function extractNestedFieldRequirements(selections) {
|
|
940
|
+
if (!selections) {
|
|
941
|
+
return undefined;
|
|
942
|
+
}
|
|
943
|
+
// Find the 'fields' ObjectSelection
|
|
944
|
+
let fieldsSelection;
|
|
945
|
+
for (let i = 0, len = selections.length; i < len; i += 1) {
|
|
946
|
+
const sel = selections[i];
|
|
947
|
+
if (sel.kind === 'Object' && sel.name === 'fields') {
|
|
948
|
+
fieldsSelection = sel;
|
|
949
|
+
break;
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
if (!fieldsSelection || !fieldsSelection.selections) {
|
|
953
|
+
return undefined;
|
|
954
|
+
}
|
|
955
|
+
let nestedFieldsMap;
|
|
956
|
+
// Look for ObjectSelections within fields (these are spanning fields)
|
|
957
|
+
const fieldSelections = fieldsSelection.selections;
|
|
958
|
+
for (let i = 0, len = fieldSelections.length; i < len; i += 1) {
|
|
959
|
+
const fieldSel = fieldSelections[i];
|
|
960
|
+
if (fieldSel.kind !== 'Object') {
|
|
961
|
+
continue;
|
|
962
|
+
}
|
|
963
|
+
const objSel = fieldSel;
|
|
964
|
+
if (!objSel.selections) {
|
|
965
|
+
continue;
|
|
966
|
+
}
|
|
967
|
+
// Look for the 'value' Link selection
|
|
968
|
+
let valueLinkSelection;
|
|
969
|
+
for (let j = 0, jlen = objSel.selections.length; j < jlen; j += 1) {
|
|
970
|
+
const sel = objSel.selections[j];
|
|
971
|
+
if (sel.kind === 'Link' && sel.name === 'value') {
|
|
972
|
+
valueLinkSelection = sel;
|
|
973
|
+
break;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
if (!valueLinkSelection || !('fragment' in valueLinkSelection)) {
|
|
977
|
+
continue;
|
|
978
|
+
}
|
|
979
|
+
const fragment = valueLinkSelection.fragment;
|
|
980
|
+
if (!fragment || !fragment.selections) {
|
|
981
|
+
continue;
|
|
982
|
+
}
|
|
983
|
+
// Look for the 'fields' selection within the fragment
|
|
984
|
+
let nestedFieldsSelection;
|
|
985
|
+
for (let j = 0, jlen = fragment.selections.length; j < jlen; j += 1) {
|
|
986
|
+
const sel = fragment.selections[j];
|
|
987
|
+
if (sel.kind === 'Object' && sel.name === 'fields') {
|
|
988
|
+
nestedFieldsSelection = sel;
|
|
989
|
+
break;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
if (nestedFieldsSelection && nestedFieldsSelection.selections) {
|
|
993
|
+
const nestedFields = new Set();
|
|
994
|
+
for (const nestedFieldSel of nestedFieldsSelection.selections) {
|
|
995
|
+
nestedFields.add(nestedFieldSel.name);
|
|
996
|
+
}
|
|
997
|
+
if (nestedFields.size > 0) {
|
|
998
|
+
// Lazy initialize map only if we have nested fields
|
|
999
|
+
if (!nestedFieldsMap) {
|
|
1000
|
+
nestedFieldsMap = new Map();
|
|
1001
|
+
}
|
|
1002
|
+
nestedFieldsMap.set(fieldSel.name, nestedFields);
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
808
1005
|
}
|
|
809
|
-
return
|
|
1006
|
+
return nestedFieldsMap;
|
|
810
1007
|
}
|
|
811
1008
|
|
|
812
1009
|
const TTL_DURABLE_SEGMENT = 'TTL_DURABLE_SEGMENT';
|
|
@@ -58582,7 +58779,7 @@ function buildServiceDescriptor$b(luvio) {
|
|
|
58582
58779
|
},
|
|
58583
58780
|
};
|
|
58584
58781
|
}
|
|
58585
|
-
// version: 1.
|
|
58782
|
+
// version: 1.420.0-576a1ea316
|
|
58586
58783
|
|
|
58587
58784
|
/**
|
|
58588
58785
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
@@ -58608,7 +58805,7 @@ function buildServiceDescriptor$a(notifyRecordUpdateAvailable, getNormalizedLuvi
|
|
|
58608
58805
|
},
|
|
58609
58806
|
};
|
|
58610
58807
|
}
|
|
58611
|
-
// version: 1.
|
|
58808
|
+
// version: 1.420.0-576a1ea316
|
|
58612
58809
|
|
|
58613
58810
|
/*!
|
|
58614
58811
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
@@ -61260,4 +61457,4 @@ register({
|
|
|
61260
61457
|
});
|
|
61261
61458
|
|
|
61262
61459
|
export { O11Y_NAMESPACE_LDS_MOBILE, getRuntime, ingest$1o as ingestDenormalizedRecordRepresentation, initializeOneStore, registerReportObserver, reportGraphqlQueryParseError };
|
|
61263
|
-
// version: 1.
|
|
61460
|
+
// version: 1.420.0-fc658f6118
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/lds-runtime-mobile",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.420.0",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
5
5
|
"description": "LDS runtime for mobile/hybrid environments.",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
"@conduit-client/service-bindings-imperative": "3.14.0",
|
|
36
36
|
"@conduit-client/service-bindings-lwc": "3.14.0",
|
|
37
37
|
"@conduit-client/service-provisioner": "3.14.0",
|
|
38
|
-
"@salesforce/lds-adapters-uiapi": "^1.
|
|
39
|
-
"@salesforce/lds-bindings": "^1.
|
|
40
|
-
"@salesforce/lds-instrumentation": "^1.
|
|
41
|
-
"@salesforce/lds-luvio-service": "^1.
|
|
42
|
-
"@salesforce/lds-luvio-uiapi-records-service": "^1.
|
|
38
|
+
"@salesforce/lds-adapters-uiapi": "^1.420.0",
|
|
39
|
+
"@salesforce/lds-bindings": "^1.420.0",
|
|
40
|
+
"@salesforce/lds-instrumentation": "^1.420.0",
|
|
41
|
+
"@salesforce/lds-luvio-service": "^1.420.0",
|
|
42
|
+
"@salesforce/lds-luvio-uiapi-records-service": "^1.420.0",
|
|
43
43
|
"@salesforce/user": "0.0.21",
|
|
44
44
|
"o11y": "250.7.0",
|
|
45
45
|
"o11y_schema": "256.126.0"
|
|
@@ -60,16 +60,16 @@
|
|
|
60
60
|
"@conduit-client/service-pubsub": "3.14.0",
|
|
61
61
|
"@conduit-client/service-store": "3.14.0",
|
|
62
62
|
"@conduit-client/utils": "3.14.0",
|
|
63
|
-
"@salesforce/lds-adapters-graphql": "^1.
|
|
64
|
-
"@salesforce/lds-drafts": "^1.
|
|
65
|
-
"@salesforce/lds-durable-records": "^1.
|
|
66
|
-
"@salesforce/lds-network-adapter": "^1.
|
|
67
|
-
"@salesforce/lds-network-nimbus": "^1.
|
|
68
|
-
"@salesforce/lds-store-binary": "^1.
|
|
69
|
-
"@salesforce/lds-store-nimbus": "^1.
|
|
70
|
-
"@salesforce/lds-store-sql": "^1.
|
|
71
|
-
"@salesforce/lds-utils-adapters": "^1.
|
|
72
|
-
"@salesforce/nimbus-plugin-lds": "^1.
|
|
63
|
+
"@salesforce/lds-adapters-graphql": "^1.420.0",
|
|
64
|
+
"@salesforce/lds-drafts": "^1.420.0",
|
|
65
|
+
"@salesforce/lds-durable-records": "^1.420.0",
|
|
66
|
+
"@salesforce/lds-network-adapter": "^1.420.0",
|
|
67
|
+
"@salesforce/lds-network-nimbus": "^1.420.0",
|
|
68
|
+
"@salesforce/lds-store-binary": "^1.420.0",
|
|
69
|
+
"@salesforce/lds-store-nimbus": "^1.420.0",
|
|
70
|
+
"@salesforce/lds-store-sql": "^1.420.0",
|
|
71
|
+
"@salesforce/lds-utils-adapters": "^1.420.0",
|
|
72
|
+
"@salesforce/nimbus-plugin-lds": "^1.420.0",
|
|
73
73
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
|
74
74
|
"wait-for-expect": "^3.0.2"
|
|
75
75
|
},
|
package/sfdc/main.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { withRegistration, register } from 'force/ldsEngine';
|
|
19
19
|
import { setupInstrumentation, instrumentAdapter as instrumentAdapter$1, instrumentLuvio, setLdsAdaptersUiapiInstrumentation, setLdsNetworkAdapterInstrumentation } from 'force/ldsInstrumentation';
|
|
20
|
-
import { HttpStatusCode as HttpStatusCode$1, setBypassDeepFreeze, StoreKeySet,
|
|
20
|
+
import { HttpStatusCode as HttpStatusCode$1, setBypassDeepFreeze, StoreKeySet, StringKeyInMemoryStore, Reader, serializeStructuredKey, deepFreeze as deepFreeze$1, emitAdapterEvent, ingestShape, coerceConfig as coerceConfig$1, typeCheckConfig as typeCheckConfig$h, createResourceParams as createResourceParams$h, StoreKeyMap, buildNetworkSnapshotCachePolicy as buildNetworkSnapshotCachePolicy$f, resolveLink, createCustomAdapterEventEmitter, isFileReference, Environment, Luvio, InMemoryStore } from 'force/luvioEngine';
|
|
21
21
|
import { isSupportedEntity, configuration, getObjectInfoAdapterFactory, RECORD_ID_PREFIX, RECORD_FIELDS_KEY_JUNCTION, isStoreKeyRecordViewEntity, extractRecordIdFromStoreKey, buildRecordRepKeyFromId, keyBuilderRecord, RecordRepresentationTTL, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, getRecordId18 as getRecordId18$1, getRecordsAdapterFactory as getRecordsAdapterFactory$1, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getObjectInfosAdapterFactory, getObjectInfoDirectoryAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationVersion } from 'force/ldsAdaptersUiapi';
|
|
22
22
|
import allowUpdatesForNonCachedRecords from '@salesforce/gate/lmr.allowUpdatesForNonCachedRecords';
|
|
23
23
|
import { getInstrumentation, idleDetector } from 'o11y/client';
|
|
@@ -541,7 +541,7 @@ const RedirectDurableSegment$1 = 'REDIRECT_KEYS';
|
|
|
541
541
|
const MessagingDurableSegment = 'MESSAGING';
|
|
542
542
|
const MessageNotifyStoreUpdateAvailable = 'notifyStoreUpdateAvailable';
|
|
543
543
|
|
|
544
|
-
const { keys: keys$5, create: create$5, assign: assign$4, freeze: freeze$2 } = Object;
|
|
544
|
+
const { keys: keys$5, create: create$5, assign: assign$4, freeze: freeze$2, isFrozen: isFrozen$1 } = Object;
|
|
545
545
|
|
|
546
546
|
//Durable store error instrumentation key
|
|
547
547
|
const DURABLE_STORE_ERROR = 'durable-store-error';
|
|
@@ -628,6 +628,74 @@ function publishDurableStoreEntries(durableRecords, put, publishMetadata) {
|
|
|
628
628
|
}
|
|
629
629
|
return { revivedKeys, hadUnexpectedShape };
|
|
630
630
|
}
|
|
631
|
+
/**
|
|
632
|
+
* Extracts field filtering configuration from the selection.
|
|
633
|
+
*/
|
|
634
|
+
function extractFieldFilteringConfig(select, recordId, baseEnvironment) {
|
|
635
|
+
const rootRecordKey = serializeStructuredKey(baseEnvironment.storeGetCanonicalKey(recordId));
|
|
636
|
+
let topLevelFields;
|
|
637
|
+
let nestedFieldRequirements;
|
|
638
|
+
if (select &&
|
|
639
|
+
select.node.kind === 'Fragment' &&
|
|
640
|
+
'selections' in select.node &&
|
|
641
|
+
select.node.selections) {
|
|
642
|
+
topLevelFields = extractRequestedFieldNames(select.node.selections);
|
|
643
|
+
nestedFieldRequirements = extractNestedFieldRequirements(select.node.selections);
|
|
644
|
+
}
|
|
645
|
+
// Merge all nested field requirements into a single set
|
|
646
|
+
let nestedFields;
|
|
647
|
+
if (nestedFieldRequirements && nestedFieldRequirements.size > 0) {
|
|
648
|
+
nestedFields = new Set();
|
|
649
|
+
for (const fieldSet of nestedFieldRequirements.values()) {
|
|
650
|
+
for (const field of fieldSet) {
|
|
651
|
+
nestedFields.add(field);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
return { rootRecordKey, topLevelFields, nestedFields };
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Categorizes keys into different fetch strategies based on filtering requirements.
|
|
659
|
+
*/
|
|
660
|
+
function categorizeKeysForL2Fetch(keysToRevive, config, baseEnvironment, shouldFilterFields) {
|
|
661
|
+
const unfilteredKeys = [];
|
|
662
|
+
const rootKeysWithTopLevelFields = [];
|
|
663
|
+
const nestedKeysWithNestedFields = [];
|
|
664
|
+
const canFilter = config.topLevelFields !== undefined && config.topLevelFields.size > 0;
|
|
665
|
+
for (let i = 0, len = keysToRevive.length; i < len; i += 1) {
|
|
666
|
+
const canonicalKey = serializeStructuredKey(baseEnvironment.storeGetCanonicalKey(keysToRevive[i]));
|
|
667
|
+
if (!shouldFilterFields(canonicalKey) || !canFilter) {
|
|
668
|
+
unfilteredKeys.push(canonicalKey);
|
|
669
|
+
continue;
|
|
670
|
+
}
|
|
671
|
+
const isRootRecord = canonicalKey === config.rootRecordKey;
|
|
672
|
+
if (isRootRecord) {
|
|
673
|
+
rootKeysWithTopLevelFields.push(canonicalKey);
|
|
674
|
+
}
|
|
675
|
+
else if (config.nestedFields !== undefined && config.nestedFields.size > 0) {
|
|
676
|
+
nestedKeysWithNestedFields.push(canonicalKey);
|
|
677
|
+
}
|
|
678
|
+
else {
|
|
679
|
+
unfilteredKeys.push(canonicalKey);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
return { unfilteredKeys, rootKeysWithTopLevelFields, nestedKeysWithNestedFields };
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Builds L2 fetch promises for different key categories.
|
|
686
|
+
*/
|
|
687
|
+
function buildL2FetchPromises(categorizedKeys, config, durableStore) {
|
|
688
|
+
const promises = [
|
|
689
|
+
durableStore.getEntries(categorizedKeys.unfilteredKeys, DefaultDurableSegment),
|
|
690
|
+
];
|
|
691
|
+
if (config.topLevelFields && categorizedKeys.rootKeysWithTopLevelFields.length > 0) {
|
|
692
|
+
promises.push(durableStore.getEntriesWithSpecificFields(categorizedKeys.rootKeysWithTopLevelFields, config.topLevelFields, DefaultDurableSegment));
|
|
693
|
+
}
|
|
694
|
+
if (config.nestedFields && categorizedKeys.nestedKeysWithNestedFields.length > 0) {
|
|
695
|
+
promises.push(durableStore.getEntriesWithSpecificFields(categorizedKeys.nestedKeysWithNestedFields, config.nestedFields, DefaultDurableSegment));
|
|
696
|
+
}
|
|
697
|
+
return promises;
|
|
698
|
+
}
|
|
631
699
|
/**
|
|
632
700
|
* This method returns a Promise to a snapshot that is revived from L2 cache. If
|
|
633
701
|
* L2 does not have the entries necessary to fulfill the snapshot then this method
|
|
@@ -663,53 +731,41 @@ function reviveSnapshot(baseEnvironment, durableStore, unavailableSnapshot, dura
|
|
|
663
731
|
const keysToRevive = keysToReviveSet.keysAsArray();
|
|
664
732
|
const start = Date.now();
|
|
665
733
|
const { l2Trips } = reviveMetrics;
|
|
666
|
-
// Extract
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
const
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
if (requestedFields !== undefined &&
|
|
677
|
-
requestedFields.size > 0 &&
|
|
678
|
-
shouldFilterFields(canonicalKey)) {
|
|
679
|
-
filteredCanonicalKeys.push(canonicalKey);
|
|
680
|
-
}
|
|
681
|
-
else {
|
|
682
|
-
canonicalKeys.push(canonicalKey);
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
const fetchPromises = [
|
|
686
|
-
durableStore.getEntries(canonicalKeys, DefaultDurableSegment),
|
|
687
|
-
];
|
|
688
|
-
if (requestedFields !== undefined &&
|
|
689
|
-
requestedFields.size > 0 &&
|
|
690
|
-
filteredCanonicalKeys.length > 0) {
|
|
691
|
-
fetchPromises.push(durableStore.getEntriesWithSpecificFields(filteredCanonicalKeys, requestedFields, DefaultDurableSegment));
|
|
692
|
-
}
|
|
693
|
-
return Promise.all(fetchPromises).then(([durableRecords, filteredDurableRecords]) => {
|
|
734
|
+
// Extract field filtering requirements from the selection
|
|
735
|
+
const fieldFilteringConfig = extractFieldFilteringConfig(select, recordId, baseEnvironment);
|
|
736
|
+
// Categorize keys by how they should be fetched from L2
|
|
737
|
+
const categorizedKeys = categorizeKeysForL2Fetch(keysToRevive, fieldFilteringConfig, baseEnvironment, shouldFilterFields);
|
|
738
|
+
// Build fetch promises for each category
|
|
739
|
+
const fetchPromises = buildL2FetchPromises(categorizedKeys, fieldFilteringConfig, durableStore);
|
|
740
|
+
return Promise.all(fetchPromises).then(([durableRecords, filteredDurableRecords, nestedFilteredDurableRecords]) => {
|
|
741
|
+
const totalKeysRequested = categorizedKeys.unfilteredKeys.length +
|
|
742
|
+
categorizedKeys.rootKeysWithTopLevelFields.length +
|
|
743
|
+
categorizedKeys.nestedKeysWithNestedFields.length;
|
|
694
744
|
l2Trips.push({
|
|
695
745
|
duration: Date.now() - start,
|
|
696
|
-
keysRequestedCount:
|
|
746
|
+
keysRequestedCount: totalKeysRequested,
|
|
697
747
|
});
|
|
698
|
-
// Process
|
|
748
|
+
// Process all three categories of records
|
|
699
749
|
const revivedKeys = new StoreKeySet();
|
|
700
750
|
let hadUnexpectedShape = false;
|
|
701
|
-
// Process normal records
|
|
751
|
+
// Process normal records (all fields)
|
|
702
752
|
if (durableRecords !== undefined) {
|
|
703
753
|
const normalResult = publishDurableStoreEntries(durableRecords, baseEnvironment.storePut.bind(baseEnvironment), baseEnvironment.publishStoreMetadata.bind(baseEnvironment));
|
|
704
754
|
revivedKeys.merge(normalResult.revivedKeys);
|
|
705
755
|
hadUnexpectedShape = hadUnexpectedShape || normalResult.hadUnexpectedShape;
|
|
706
756
|
}
|
|
707
|
-
// Process filtered records with merging
|
|
757
|
+
// Process filtered records (root with top-level fields) with merging
|
|
708
758
|
if (filteredDurableRecords !== undefined) {
|
|
709
759
|
const filteredResult = publishDurableStoreEntries(filteredDurableRecords, createMergeFilteredPut((key) => baseEnvironment.store.readEntry(key), baseEnvironment.storePut.bind(baseEnvironment)), baseEnvironment.publishStoreMetadata.bind(baseEnvironment));
|
|
710
760
|
revivedKeys.merge(filteredResult.revivedKeys);
|
|
711
761
|
hadUnexpectedShape = hadUnexpectedShape || filteredResult.hadUnexpectedShape;
|
|
712
762
|
}
|
|
763
|
+
// Process nested filtered records with merging
|
|
764
|
+
if (nestedFilteredDurableRecords !== undefined) {
|
|
765
|
+
const nestedFilteredResult = publishDurableStoreEntries(nestedFilteredDurableRecords, createMergeFilteredPut((key) => baseEnvironment.store.readEntry(key), baseEnvironment.storePut.bind(baseEnvironment)), baseEnvironment.publishStoreMetadata.bind(baseEnvironment));
|
|
766
|
+
revivedKeys.merge(nestedFilteredResult.revivedKeys);
|
|
767
|
+
hadUnexpectedShape = hadUnexpectedShape || nestedFilteredResult.hadUnexpectedShape;
|
|
768
|
+
}
|
|
713
769
|
// if the data coming back from DS had an unexpected shape then just
|
|
714
770
|
// return the L1 snapshot
|
|
715
771
|
if (hadUnexpectedShape === true) {
|
|
@@ -755,6 +811,54 @@ function reviveSnapshot(baseEnvironment, durableStore, unavailableSnapshot, dura
|
|
|
755
811
|
return { snapshot: unavailableSnapshot, metrics: reviveMetrics };
|
|
756
812
|
});
|
|
757
813
|
}
|
|
814
|
+
/**
|
|
815
|
+
* Filters out null fields from a fields object (null indicates field doesn't exist in L2).
|
|
816
|
+
* Returns a new object without null values, or the original if no filtering needed.
|
|
817
|
+
*/
|
|
818
|
+
function filterNullFields(fields) {
|
|
819
|
+
const keys$1 = keys$5(fields);
|
|
820
|
+
let hasNull = false;
|
|
821
|
+
// Check if any nulls exist before allocating new object
|
|
822
|
+
for (let i = 0, len = keys$1.length; i < len; i += 1) {
|
|
823
|
+
if (fields[keys$1[i]] === null) {
|
|
824
|
+
hasNull = true;
|
|
825
|
+
break;
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
if (!hasNull) {
|
|
829
|
+
return fields;
|
|
830
|
+
}
|
|
831
|
+
const cleaned = {};
|
|
832
|
+
for (let i = 0, len = keys$1.length; i < len; i += 1) {
|
|
833
|
+
const key = keys$1[i];
|
|
834
|
+
if (fields[key] !== null) {
|
|
835
|
+
cleaned[key] = fields[key];
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
return cleaned;
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Merges new fields into existing fields object, skipping null values.
|
|
842
|
+
* Creates a new object to avoid mutations.
|
|
843
|
+
*/
|
|
844
|
+
function mergeFieldsObjects(existing, incoming) {
|
|
845
|
+
const merged = { ...existing };
|
|
846
|
+
const keys$1 = keys$5(incoming);
|
|
847
|
+
for (let i = 0, len = keys$1.length; i < len; i += 1) {
|
|
848
|
+
const key = keys$1[i];
|
|
849
|
+
// Skip null values - they indicate the field doesn't exist in L2
|
|
850
|
+
if (incoming[key] !== null) {
|
|
851
|
+
merged[key] = incoming[key];
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
return merged;
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* Type guard to check if value is a non-null object.
|
|
858
|
+
*/
|
|
859
|
+
function isObject$1(value) {
|
|
860
|
+
return typeof value === 'object' && value !== null;
|
|
861
|
+
}
|
|
758
862
|
/**
|
|
759
863
|
* Creates a put function that merges filtered fields with existing L1 records instead of replacing them.
|
|
760
864
|
* This is used when reviving filtered fields from L2 to preserve existing data in L1.
|
|
@@ -762,28 +866,36 @@ function reviveSnapshot(baseEnvironment, durableStore, unavailableSnapshot, dura
|
|
|
762
866
|
function createMergeFilteredPut(readEntry, storePut) {
|
|
763
867
|
return (key, filteredData) => {
|
|
764
868
|
const existingRecord = readEntry(key);
|
|
765
|
-
if
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
const
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
869
|
+
// Merge with existing record if both are objects
|
|
870
|
+
if (isObject$1(existingRecord) && isObject$1(filteredData)) {
|
|
871
|
+
// Create target object (copy if frozen to avoid mutation errors)
|
|
872
|
+
const targetObj = isFrozen$1(existingRecord)
|
|
873
|
+
? { ...existingRecord }
|
|
874
|
+
: existingRecord;
|
|
875
|
+
const keys$1 = keys$5(filteredData);
|
|
876
|
+
for (let i = 0, len = keys$1.length; i < len; i += 1) {
|
|
877
|
+
const fieldKey = keys$1[i];
|
|
878
|
+
const incomingValue = filteredData[fieldKey];
|
|
879
|
+
// Special handling for 'fields' property to merge rather than replace
|
|
880
|
+
if (fieldKey === 'fields' &&
|
|
881
|
+
isObject$1(incomingValue) &&
|
|
882
|
+
isObject$1(targetObj[fieldKey])) {
|
|
883
|
+
targetObj[fieldKey] = mergeFieldsObjects(targetObj[fieldKey], incomingValue);
|
|
884
|
+
}
|
|
885
|
+
else {
|
|
886
|
+
targetObj[fieldKey] = incomingValue;
|
|
887
|
+
}
|
|
782
888
|
}
|
|
783
889
|
storePut(key, targetObj);
|
|
784
890
|
}
|
|
785
891
|
else {
|
|
786
|
-
// No existing record
|
|
892
|
+
// No existing record - clean null fields before storing
|
|
893
|
+
if (isObject$1(filteredData) && 'fields' in filteredData) {
|
|
894
|
+
const fields = filteredData.fields;
|
|
895
|
+
if (isObject$1(fields)) {
|
|
896
|
+
filteredData.fields = filterNullFields(fields);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
787
899
|
storePut(key, filteredData);
|
|
788
900
|
}
|
|
789
901
|
};
|
|
@@ -797,16 +909,101 @@ function extractRequestedFieldNames(selections) {
|
|
|
797
909
|
return undefined;
|
|
798
910
|
}
|
|
799
911
|
// Find the 'fields' ObjectSelection
|
|
800
|
-
|
|
801
|
-
|
|
912
|
+
let fieldsSelection;
|
|
913
|
+
for (let i = 0, len = selections.length; i < len; i += 1) {
|
|
914
|
+
const sel = selections[i];
|
|
915
|
+
if (sel.kind === 'Object' && sel.name === 'fields') {
|
|
916
|
+
fieldsSelection = sel;
|
|
917
|
+
break;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
if (!fieldsSelection ||
|
|
921
|
+
!fieldsSelection.selections ||
|
|
922
|
+
fieldsSelection.selections.length === 0) {
|
|
802
923
|
return undefined;
|
|
803
924
|
}
|
|
804
925
|
// Extract all field names from the fields selections
|
|
926
|
+
const fieldSelections = fieldsSelection.selections;
|
|
805
927
|
const fieldNames = new Set();
|
|
806
|
-
for (
|
|
807
|
-
fieldNames.add(
|
|
928
|
+
for (let i = 0, len = fieldSelections.length; i < len; i += 1) {
|
|
929
|
+
fieldNames.add(fieldSelections[i].name);
|
|
930
|
+
}
|
|
931
|
+
return fieldNames;
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
934
|
+
* Extracts nested field requirements for spanning fields.
|
|
935
|
+
* For spanning fields like Case.CreatedBy.Name, we need to extract what fields
|
|
936
|
+
* are requested from the nested record (User in this case).
|
|
937
|
+
* The structure is: fields { CreatedBy { value (Link with fragment) { fields { Name } } } }
|
|
938
|
+
*/
|
|
939
|
+
function extractNestedFieldRequirements(selections) {
|
|
940
|
+
if (!selections) {
|
|
941
|
+
return undefined;
|
|
942
|
+
}
|
|
943
|
+
// Find the 'fields' ObjectSelection
|
|
944
|
+
let fieldsSelection;
|
|
945
|
+
for (let i = 0, len = selections.length; i < len; i += 1) {
|
|
946
|
+
const sel = selections[i];
|
|
947
|
+
if (sel.kind === 'Object' && sel.name === 'fields') {
|
|
948
|
+
fieldsSelection = sel;
|
|
949
|
+
break;
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
if (!fieldsSelection || !fieldsSelection.selections) {
|
|
953
|
+
return undefined;
|
|
954
|
+
}
|
|
955
|
+
let nestedFieldsMap;
|
|
956
|
+
// Look for ObjectSelections within fields (these are spanning fields)
|
|
957
|
+
const fieldSelections = fieldsSelection.selections;
|
|
958
|
+
for (let i = 0, len = fieldSelections.length; i < len; i += 1) {
|
|
959
|
+
const fieldSel = fieldSelections[i];
|
|
960
|
+
if (fieldSel.kind !== 'Object') {
|
|
961
|
+
continue;
|
|
962
|
+
}
|
|
963
|
+
const objSel = fieldSel;
|
|
964
|
+
if (!objSel.selections) {
|
|
965
|
+
continue;
|
|
966
|
+
}
|
|
967
|
+
// Look for the 'value' Link selection
|
|
968
|
+
let valueLinkSelection;
|
|
969
|
+
for (let j = 0, jlen = objSel.selections.length; j < jlen; j += 1) {
|
|
970
|
+
const sel = objSel.selections[j];
|
|
971
|
+
if (sel.kind === 'Link' && sel.name === 'value') {
|
|
972
|
+
valueLinkSelection = sel;
|
|
973
|
+
break;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
if (!valueLinkSelection || !('fragment' in valueLinkSelection)) {
|
|
977
|
+
continue;
|
|
978
|
+
}
|
|
979
|
+
const fragment = valueLinkSelection.fragment;
|
|
980
|
+
if (!fragment || !fragment.selections) {
|
|
981
|
+
continue;
|
|
982
|
+
}
|
|
983
|
+
// Look for the 'fields' selection within the fragment
|
|
984
|
+
let nestedFieldsSelection;
|
|
985
|
+
for (let j = 0, jlen = fragment.selections.length; j < jlen; j += 1) {
|
|
986
|
+
const sel = fragment.selections[j];
|
|
987
|
+
if (sel.kind === 'Object' && sel.name === 'fields') {
|
|
988
|
+
nestedFieldsSelection = sel;
|
|
989
|
+
break;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
if (nestedFieldsSelection && nestedFieldsSelection.selections) {
|
|
993
|
+
const nestedFields = new Set();
|
|
994
|
+
for (const nestedFieldSel of nestedFieldsSelection.selections) {
|
|
995
|
+
nestedFields.add(nestedFieldSel.name);
|
|
996
|
+
}
|
|
997
|
+
if (nestedFields.size > 0) {
|
|
998
|
+
// Lazy initialize map only if we have nested fields
|
|
999
|
+
if (!nestedFieldsMap) {
|
|
1000
|
+
nestedFieldsMap = new Map();
|
|
1001
|
+
}
|
|
1002
|
+
nestedFieldsMap.set(fieldSel.name, nestedFields);
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
808
1005
|
}
|
|
809
|
-
return
|
|
1006
|
+
return nestedFieldsMap;
|
|
810
1007
|
}
|
|
811
1008
|
|
|
812
1009
|
const TTL_DURABLE_SEGMENT = 'TTL_DURABLE_SEGMENT';
|
|
@@ -58582,7 +58779,7 @@ function buildServiceDescriptor$b(luvio) {
|
|
|
58582
58779
|
},
|
|
58583
58780
|
};
|
|
58584
58781
|
}
|
|
58585
|
-
// version: 1.
|
|
58782
|
+
// version: 1.420.0-576a1ea316
|
|
58586
58783
|
|
|
58587
58784
|
/**
|
|
58588
58785
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
@@ -58608,7 +58805,7 @@ function buildServiceDescriptor$a(notifyRecordUpdateAvailable, getNormalizedLuvi
|
|
|
58608
58805
|
},
|
|
58609
58806
|
};
|
|
58610
58807
|
}
|
|
58611
|
-
// version: 1.
|
|
58808
|
+
// version: 1.420.0-576a1ea316
|
|
58612
58809
|
|
|
58613
58810
|
/*!
|
|
58614
58811
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
@@ -61260,4 +61457,4 @@ register({
|
|
|
61260
61457
|
});
|
|
61261
61458
|
|
|
61262
61459
|
export { O11Y_NAMESPACE_LDS_MOBILE, getRuntime, ingest$1o as ingestDenormalizedRecordRepresentation, initializeOneStore, registerReportObserver, reportGraphqlQueryParseError };
|
|
61263
|
-
// version: 1.
|
|
61460
|
+
// version: 1.420.0-fc658f6118
|