@salesforce/lds-runtime-mobile 1.233.0 → 1.235.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 +458 -156
- package/package.json +1 -1
- package/sfdc/main.js +458 -156
package/dist/main.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { withRegistration, register } from '@salesforce/lds-default-luvio';
|
|
15
15
|
import { setupInstrumentation, instrumentAdapter as instrumentAdapter$1, instrumentLuvio, setLdsAdaptersUiapiInstrumentation, setLdsNetworkAdapterInstrumentation } from '@salesforce/lds-instrumentation';
|
|
16
|
-
import { HttpStatusCode, StoreKeySet, serializeStructuredKey, Reader, deepFreeze, emitAdapterEvent, createCustomAdapterEventEmitter, StoreKeyMap, isFileReference, Environment, Luvio, InMemoryStore } from '@luvio/engine';
|
|
16
|
+
import { HttpStatusCode, StoreKeySet, serializeStructuredKey, StringKeyInMemoryStore, Reader, deepFreeze, emitAdapterEvent, createCustomAdapterEventEmitter, StoreKeyMap, isFileReference, Environment, Luvio, InMemoryStore } from '@luvio/engine';
|
|
17
17
|
import excludeStaleRecordsGate from '@salesforce/gate/lds.graphqlEvalExcludeStaleRecords';
|
|
18
18
|
import { parseAndVisit, Kind, visit, execute, buildSchema, isObjectType, defaultFieldResolver } from '@luvio/graphql-parser';
|
|
19
19
|
import { getRecordId18, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, keyBuilderContentDocumentCompositeRepresentation, getResponseCacheKeysContentDocumentCompositeRepresentation, keyBuilderFromTypeContentDocumentCompositeRepresentation, ingestContentDocumentCompositeRepresentation, keyBuilderRecord, getTypeCacheKeysRecord, keyBuilderFromTypeRecordRepresentation, ingestRecord, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getRecordAdapterFactory, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationTTL, RecordRepresentationVersion, getRecordsAdapterFactory } from '@salesforce/lds-adapters-uiapi';
|
|
@@ -33,6 +33,7 @@ import eagerEvalValidAt from '@salesforce/gate/lds.eagerEvalValidAt';
|
|
|
33
33
|
import eagerEvalStaleWhileRevalidate from '@salesforce/gate/lds.eagerEvalStaleWhileRevalidate';
|
|
34
34
|
import eagerEvalDefaultCachePolicy from '@salesforce/gate/lds.eagerEvalDefaultCachePolicy';
|
|
35
35
|
import ldsPrimingGraphqlBatch from '@salesforce/gate/lds.primingGraphqlBatch';
|
|
36
|
+
import ldsMetadataRefreshEnabled from '@salesforce/gate/lds.metadataRefreshEnabled';
|
|
36
37
|
|
|
37
38
|
/**
|
|
38
39
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
@@ -615,7 +616,7 @@ function publishDurableStoreEntries(durableRecords, put, publishMetadata) {
|
|
|
615
616
|
* will refresh the snapshot from network, and then run the results from network
|
|
616
617
|
* through L2 ingestion, returning the subsequent revived snapshot.
|
|
617
618
|
*/
|
|
618
|
-
function reviveSnapshot(baseEnvironment, durableStore, unavailableSnapshot, durableStoreErrorHandler, buildL1Snapshot, reviveMetrics = { l2Trips: [] }) {
|
|
619
|
+
function reviveSnapshot(baseEnvironment, durableStore, unavailableSnapshot, durableStoreErrorHandler, buildL1Snapshot, revivingStore, reviveMetrics = { l2Trips: [] }) {
|
|
619
620
|
const { recordId, select, missingLinks, seenRecords, state } = unavailableSnapshot;
|
|
620
621
|
// L2 can only revive Unfulfilled snapshots that have a selector since they have the
|
|
621
622
|
// info needed to revive (like missingLinks) and rebuild. Otherwise return L1 snapshot.
|
|
@@ -625,10 +626,21 @@ function reviveSnapshot(baseEnvironment, durableStore, unavailableSnapshot, dura
|
|
|
625
626
|
metrics: reviveMetrics,
|
|
626
627
|
});
|
|
627
628
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
629
|
+
const keysToReviveSet = new StoreKeySet();
|
|
630
|
+
if (revivingStore) {
|
|
631
|
+
// Any stale keys since the last l2 read should be cleared and fetched again
|
|
632
|
+
for (const staleKey of revivingStore.staleEntries) {
|
|
633
|
+
keysToReviveSet.add(staleKey);
|
|
634
|
+
}
|
|
635
|
+
revivingStore.clearStale();
|
|
636
|
+
}
|
|
637
|
+
else {
|
|
638
|
+
// when not using a reviving store:
|
|
639
|
+
// in case L1 store changes/deallocs a record while we are doing the async read
|
|
640
|
+
// we attempt to read all keys from L2 - so combine recordId with any seenRecords
|
|
641
|
+
keysToReviveSet.add(recordId);
|
|
642
|
+
keysToReviveSet.merge(seenRecords);
|
|
643
|
+
}
|
|
632
644
|
keysToReviveSet.merge(missingLinks);
|
|
633
645
|
const keysToRevive = keysToReviveSet.keysAsArray();
|
|
634
646
|
const canonicalKeys = keysToRevive.map((x) => serializeStructuredKey(baseEnvironment.storeGetCanonicalKey(x)));
|
|
@@ -678,7 +690,7 @@ function reviveSnapshot(baseEnvironment, durableStore, unavailableSnapshot, dura
|
|
|
678
690
|
for (let i = 0, len = newKeys.length; i < len; i++) {
|
|
679
691
|
const newSnapshotSeenKey = newKeys[i];
|
|
680
692
|
if (!alreadyRequestedOrRevivedSet.has(newSnapshotSeenKey)) {
|
|
681
|
-
return reviveSnapshot(baseEnvironment, durableStore, snapshot, durableStoreErrorHandler, buildL1Snapshot, reviveMetrics);
|
|
693
|
+
return reviveSnapshot(baseEnvironment, durableStore, snapshot, durableStoreErrorHandler, buildL1Snapshot, revivingStore, reviveMetrics);
|
|
682
694
|
}
|
|
683
695
|
}
|
|
684
696
|
}
|
|
@@ -767,8 +779,9 @@ class DurableTTLStore {
|
|
|
767
779
|
}
|
|
768
780
|
}
|
|
769
781
|
|
|
770
|
-
function flushInMemoryStoreValuesToDurableStore(store, durableStore, durableStoreErrorHandler, redirects, additionalDurableStoreOperations = []) {
|
|
782
|
+
function flushInMemoryStoreValuesToDurableStore(store, durableStore, durableStoreErrorHandler, redirects, additionalDurableStoreOperations = [], enableDurableMetadataRefresh = false) {
|
|
771
783
|
const durableRecords = create$6(null);
|
|
784
|
+
const refreshedDurableRecords = create$6(null);
|
|
772
785
|
const evictedRecords = create$6(null);
|
|
773
786
|
const { records, metadata: storeMetadata, visitedIds, refreshedIds, } = store.fallbackStringKeyInMemoryStore;
|
|
774
787
|
// TODO: W-8909393 Once metadata is stored in its own segment we need to
|
|
@@ -778,32 +791,36 @@ function flushInMemoryStoreValuesToDurableStore(store, durableStore, durableStor
|
|
|
778
791
|
for (let i = 0, len = keys$1.length; i < len; i += 1) {
|
|
779
792
|
const key = keys$1[i];
|
|
780
793
|
const record = records[key];
|
|
794
|
+
const wasVisited = visitedIds[key] !== undefined;
|
|
781
795
|
// this record has been evicted, evict from DS
|
|
782
|
-
if (record === undefined) {
|
|
796
|
+
if (wasVisited && record === undefined) {
|
|
783
797
|
evictedRecords[key] = true;
|
|
784
798
|
continue;
|
|
785
799
|
}
|
|
786
800
|
const metadata = storeMetadata[key];
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
durableRecords[key].metadata = {
|
|
792
|
-
...metadata,
|
|
793
|
-
metadataVersion: DURABLE_METADATA_VERSION,
|
|
794
|
-
};
|
|
795
|
-
}
|
|
801
|
+
const entries = wasVisited === true || enableDurableMetadataRefresh === false
|
|
802
|
+
? durableRecords
|
|
803
|
+
: refreshedDurableRecords;
|
|
804
|
+
setRecordTo(entries, key, record, metadata);
|
|
796
805
|
}
|
|
797
806
|
const durableStoreOperations = additionalDurableStoreOperations;
|
|
798
|
-
// publishes
|
|
799
807
|
const recordKeys = keys$7(durableRecords);
|
|
800
808
|
if (recordKeys.length > 0) {
|
|
809
|
+
// publishes with data
|
|
801
810
|
durableStoreOperations.push({
|
|
802
811
|
type: 'setEntries',
|
|
803
812
|
entries: durableRecords,
|
|
804
813
|
segment: DefaultDurableSegment,
|
|
805
814
|
});
|
|
806
815
|
}
|
|
816
|
+
if (keys$7(refreshedDurableRecords).length > 0) {
|
|
817
|
+
// publishes with only metadata updates
|
|
818
|
+
durableStoreOperations.push({
|
|
819
|
+
type: 'setMetadata',
|
|
820
|
+
entries: refreshedDurableRecords,
|
|
821
|
+
segment: DefaultDurableSegment,
|
|
822
|
+
});
|
|
823
|
+
}
|
|
807
824
|
// redirects
|
|
808
825
|
redirects.forEach((value, key) => {
|
|
809
826
|
durableStoreOperations.push({
|
|
@@ -830,6 +847,17 @@ function flushInMemoryStoreValuesToDurableStore(store, durableStore, durableStor
|
|
|
830
847
|
}
|
|
831
848
|
return Promise.resolve();
|
|
832
849
|
}
|
|
850
|
+
function setRecordTo(entries, key, record, metadata) {
|
|
851
|
+
entries[key] = {
|
|
852
|
+
data: record,
|
|
853
|
+
};
|
|
854
|
+
if (metadata !== undefined) {
|
|
855
|
+
entries[key].metadata = {
|
|
856
|
+
...metadata,
|
|
857
|
+
metadataVersion: DURABLE_METADATA_VERSION,
|
|
858
|
+
};
|
|
859
|
+
}
|
|
860
|
+
}
|
|
833
861
|
|
|
834
862
|
const DurableEnvironmentEventDiscriminator = 'durable';
|
|
835
863
|
function emitDurableEnvironmentAdapterEvent(eventData, observers) {
|
|
@@ -874,6 +902,50 @@ async function reviveRedirects(durableStore, env) {
|
|
|
874
902
|
}
|
|
875
903
|
}
|
|
876
904
|
|
|
905
|
+
function buildRevivingStagingStore(upstreamStore) {
|
|
906
|
+
const localStore = new StringKeyInMemoryStore();
|
|
907
|
+
const staleEntries = new Set();
|
|
908
|
+
function readEntry(key) {
|
|
909
|
+
if (typeof key !== 'string') {
|
|
910
|
+
return upstreamStore.readEntry(key);
|
|
911
|
+
}
|
|
912
|
+
let storeEntry = localStore.readEntry(key);
|
|
913
|
+
if (!storeEntry) {
|
|
914
|
+
// read from upstream store...
|
|
915
|
+
storeEntry = upstreamStore.readEntry(key);
|
|
916
|
+
// put it in our store to avoid it getting evicted prior to the next durable store read
|
|
917
|
+
localStore.put(key, storeEntry);
|
|
918
|
+
}
|
|
919
|
+
return storeEntry;
|
|
920
|
+
}
|
|
921
|
+
// Entries are marked stale by the durable store change listener. They are not
|
|
922
|
+
// immediately evicted so as to not result in a cache miss during a rebuild.
|
|
923
|
+
// The revive process will clear stale entries and read them from the durable store
|
|
924
|
+
// on the next revive loop.
|
|
925
|
+
function markStale(key) {
|
|
926
|
+
staleEntries.add(key);
|
|
927
|
+
}
|
|
928
|
+
// The revive loop clears stale entries right before reading from the durable store.
|
|
929
|
+
// Any stale entries will be revived to ensure they are present in L1 and match the
|
|
930
|
+
// latest data.
|
|
931
|
+
function clearStale() {
|
|
932
|
+
for (const key of staleEntries) {
|
|
933
|
+
localStore.dealloc(key);
|
|
934
|
+
}
|
|
935
|
+
staleEntries.clear();
|
|
936
|
+
}
|
|
937
|
+
// All functions other than `readEntry` pass through to the upstream store.
|
|
938
|
+
// A reviving store is only "active" during a call to `environment.storeLookup`, and will
|
|
939
|
+
// be used by the reader attempting to build an L1 snapshot. Immediately after the L1 rebuild
|
|
940
|
+
// the reviving store becomes inactive other than receiving change notifications.
|
|
941
|
+
return create$6(upstreamStore, {
|
|
942
|
+
readEntry: { value: readEntry },
|
|
943
|
+
markStale: { value: markStale },
|
|
944
|
+
clearStale: { value: clearStale },
|
|
945
|
+
staleEntries: { value: staleEntries },
|
|
946
|
+
});
|
|
947
|
+
}
|
|
948
|
+
|
|
877
949
|
const AdapterContextSegment = 'ADAPTER-CONTEXT';
|
|
878
950
|
const ADAPTER_CONTEXT_ID_SUFFIX = '__NAMED_CONTEXT';
|
|
879
951
|
async function reviveOrCreateContext(adapterId, durableStore, durableStoreErrorHandler, contextStores, pendingContextStoreKeys, onContextLoaded) {
|
|
@@ -929,14 +1001,16 @@ function isUnfulfilledSnapshot$1(cachedSnapshotResult) {
|
|
|
929
1001
|
* @param durableStore A DurableStore implementation
|
|
930
1002
|
* @param instrumentation An instrumentation function implementation
|
|
931
1003
|
*/
|
|
932
|
-
function makeDurable(environment, { durableStore, instrumentation }) {
|
|
933
|
-
let
|
|
1004
|
+
function makeDurable(environment, { durableStore, instrumentation, useRevivingStore, enableDurableMetadataRefresh = false, }) {
|
|
1005
|
+
let stagingStore = null;
|
|
934
1006
|
const durableTTLStore = new DurableTTLStore(durableStore);
|
|
935
1007
|
const mergeKeysPromiseMap = new Map();
|
|
936
1008
|
// When a context store is mutated we write it to L2, which causes DS on change
|
|
937
1009
|
// event. If this instance of makeDurable caused that L2 write we can ignore that
|
|
938
1010
|
// on change event. This Set helps us do that.
|
|
939
1011
|
const pendingContextStoreKeys = new Set();
|
|
1012
|
+
// Reviving stores are tracked so that they can be notified of durable store change notifications.
|
|
1013
|
+
const revivingStores = new Set();
|
|
940
1014
|
// redirects that need to be flushed to the durable store
|
|
941
1015
|
const pendingStoreRedirects = new Map();
|
|
942
1016
|
const contextStores = create$6(null);
|
|
@@ -962,6 +1036,7 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
962
1036
|
const defaultSegmentKeys = [];
|
|
963
1037
|
const adapterContextSegmentKeys = [];
|
|
964
1038
|
const redirectSegmentKeys = [];
|
|
1039
|
+
const metadataRefreshSegmentKeys = [];
|
|
965
1040
|
const messagingSegmentKeys = [];
|
|
966
1041
|
let shouldBroadcast = false;
|
|
967
1042
|
for (let i = 0, len = changes.length; i < len; i++) {
|
|
@@ -969,7 +1044,12 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
969
1044
|
// we only care about changes to the data which is stored in the default
|
|
970
1045
|
// segment or the adapter context
|
|
971
1046
|
if (change.segment === DefaultDurableSegment) {
|
|
972
|
-
|
|
1047
|
+
if (change.type === 'setMetadata') {
|
|
1048
|
+
metadataRefreshSegmentKeys.push(...change.ids);
|
|
1049
|
+
}
|
|
1050
|
+
else {
|
|
1051
|
+
defaultSegmentKeys.push(...change.ids);
|
|
1052
|
+
}
|
|
973
1053
|
}
|
|
974
1054
|
else if (change.segment === AdapterContextSegment) {
|
|
975
1055
|
adapterContextSegmentKeys.push(...change.ids);
|
|
@@ -1033,9 +1113,26 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
1033
1113
|
// and go through an entire broadcast/revive cycle for unchanged data
|
|
1034
1114
|
// call base environment storeEvict so this evict is not tracked for durable deletion
|
|
1035
1115
|
environment.storeEvict(key);
|
|
1116
|
+
for (const revivingStore of revivingStores) {
|
|
1117
|
+
revivingStore.markStale(key);
|
|
1118
|
+
}
|
|
1036
1119
|
}
|
|
1037
1120
|
shouldBroadcast = true;
|
|
1038
1121
|
}
|
|
1122
|
+
// process metadata only refreshes
|
|
1123
|
+
if (metadataRefreshSegmentKeys.length > 0) {
|
|
1124
|
+
const entries = await durableStore.getMetadata(metadataRefreshSegmentKeys, DefaultDurableSegment);
|
|
1125
|
+
if (entries !== undefined) {
|
|
1126
|
+
const entryKeys = keys$7(entries);
|
|
1127
|
+
for (let i = 0, len = entryKeys.length; i < len; i++) {
|
|
1128
|
+
const entryKey = entryKeys[i];
|
|
1129
|
+
const { metadata } = entries[entryKey];
|
|
1130
|
+
if (metadata !== undefined) {
|
|
1131
|
+
environment.putStoreMetadata(entryKey, metadata, false);
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1039
1136
|
if (shouldBroadcast) {
|
|
1040
1137
|
await environment.storeBroadcast(rebuildSnapshot, environment.snapshotAvailable);
|
|
1041
1138
|
}
|
|
@@ -1061,10 +1158,10 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
1061
1158
|
};
|
|
1062
1159
|
const storePublish = function (key, data) {
|
|
1063
1160
|
validateNotDisposed();
|
|
1064
|
-
if (
|
|
1065
|
-
|
|
1161
|
+
if (stagingStore === null) {
|
|
1162
|
+
stagingStore = buildIngestStagingStore(environment);
|
|
1066
1163
|
}
|
|
1067
|
-
|
|
1164
|
+
stagingStore.publish(key, data);
|
|
1068
1165
|
// remove record from main luvio L1 cache while we are on the synchronous path
|
|
1069
1166
|
// because we do not want some other code attempting to use the
|
|
1070
1167
|
// in-memory values before the durable store onChanged handler
|
|
@@ -1073,26 +1170,26 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
1073
1170
|
};
|
|
1074
1171
|
const publishStoreMetadata = function (recordId, storeMetadata) {
|
|
1075
1172
|
validateNotDisposed();
|
|
1076
|
-
if (
|
|
1077
|
-
|
|
1173
|
+
if (stagingStore === null) {
|
|
1174
|
+
stagingStore = buildIngestStagingStore(environment);
|
|
1078
1175
|
}
|
|
1079
|
-
|
|
1176
|
+
stagingStore.publishMetadata(recordId, storeMetadata);
|
|
1080
1177
|
};
|
|
1081
1178
|
const storeIngest = function (key, ingest, response, luvio) {
|
|
1082
1179
|
validateNotDisposed();
|
|
1083
1180
|
// we don't ingest to the luvio L1 store from network directly, we ingest to
|
|
1084
1181
|
// L2 and let DurableStore on change event revive keys into luvio L1 store
|
|
1085
|
-
if (
|
|
1086
|
-
|
|
1182
|
+
if (stagingStore === null) {
|
|
1183
|
+
stagingStore = buildIngestStagingStore(environment);
|
|
1087
1184
|
}
|
|
1088
|
-
environment.storeIngest(key, ingest, response, luvio,
|
|
1185
|
+
environment.storeIngest(key, ingest, response, luvio, stagingStore);
|
|
1089
1186
|
};
|
|
1090
1187
|
const storeIngestError = function (key, errorSnapshot, storeMetadataParams, _storeOverride) {
|
|
1091
1188
|
validateNotDisposed();
|
|
1092
|
-
if (
|
|
1093
|
-
|
|
1189
|
+
if (stagingStore === null) {
|
|
1190
|
+
stagingStore = buildIngestStagingStore(environment);
|
|
1094
1191
|
}
|
|
1095
|
-
environment.storeIngestError(key, errorSnapshot, storeMetadataParams,
|
|
1192
|
+
environment.storeIngestError(key, errorSnapshot, storeMetadataParams, stagingStore);
|
|
1096
1193
|
};
|
|
1097
1194
|
const storeBroadcast = function (_rebuildSnapshot, _snapshotDataAvailable) {
|
|
1098
1195
|
validateNotDisposed();
|
|
@@ -1103,19 +1200,19 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
1103
1200
|
};
|
|
1104
1201
|
const publishChangesToDurableStore = function (additionalDurableStoreOperations) {
|
|
1105
1202
|
validateNotDisposed();
|
|
1106
|
-
if (
|
|
1203
|
+
if (stagingStore === null) {
|
|
1107
1204
|
return Promise.resolve();
|
|
1108
1205
|
}
|
|
1109
|
-
const promise = flushInMemoryStoreValuesToDurableStore(
|
|
1206
|
+
const promise = flushInMemoryStoreValuesToDurableStore(stagingStore, durableStore, durableStoreErrorHandler, new Map(pendingStoreRedirects), additionalDurableStoreOperations, enableDurableMetadataRefresh);
|
|
1110
1207
|
pendingStoreRedirects.clear();
|
|
1111
|
-
|
|
1208
|
+
stagingStore = null;
|
|
1112
1209
|
return promise;
|
|
1113
1210
|
};
|
|
1114
1211
|
const storeLookup = function (sel, createSnapshot, refresh, ttlStrategy) {
|
|
1115
1212
|
validateNotDisposed();
|
|
1116
|
-
// if this lookup is right after an ingest there will be a staging store
|
|
1117
|
-
if (
|
|
1118
|
-
const reader = new Reader(
|
|
1213
|
+
// if this lookup is right after an ingest or during a revive there will be a staging store
|
|
1214
|
+
if (stagingStore !== null) {
|
|
1215
|
+
const reader = new Reader(stagingStore, sel.variables, refresh, undefined, ttlStrategy);
|
|
1119
1216
|
return reader.read(sel);
|
|
1120
1217
|
}
|
|
1121
1218
|
// otherwise this is from buildCachedSnapshot and we should use the luvio
|
|
@@ -1124,24 +1221,24 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
1124
1221
|
};
|
|
1125
1222
|
const storeEvict = function (key) {
|
|
1126
1223
|
validateNotDisposed();
|
|
1127
|
-
if (
|
|
1128
|
-
|
|
1224
|
+
if (stagingStore === null) {
|
|
1225
|
+
stagingStore = buildIngestStagingStore(environment);
|
|
1129
1226
|
}
|
|
1130
|
-
|
|
1227
|
+
stagingStore.evict(key);
|
|
1131
1228
|
};
|
|
1132
1229
|
const getNode = function (key) {
|
|
1133
1230
|
validateNotDisposed();
|
|
1134
|
-
if (
|
|
1135
|
-
|
|
1231
|
+
if (stagingStore === null) {
|
|
1232
|
+
stagingStore = buildIngestStagingStore(environment);
|
|
1136
1233
|
}
|
|
1137
|
-
return environment.getNode(key,
|
|
1234
|
+
return environment.getNode(key, stagingStore);
|
|
1138
1235
|
};
|
|
1139
1236
|
const wrapNormalizedGraphNode = function (normalized) {
|
|
1140
1237
|
validateNotDisposed();
|
|
1141
|
-
if (
|
|
1142
|
-
|
|
1238
|
+
if (stagingStore === null) {
|
|
1239
|
+
stagingStore = buildIngestStagingStore(environment);
|
|
1143
1240
|
}
|
|
1144
|
-
return environment.wrapNormalizedGraphNode(normalized,
|
|
1241
|
+
return environment.wrapNormalizedGraphNode(normalized, stagingStore);
|
|
1145
1242
|
};
|
|
1146
1243
|
const rebuildSnapshot = function (snapshot, onRebuild) {
|
|
1147
1244
|
validateNotDisposed();
|
|
@@ -1153,7 +1250,7 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
1153
1250
|
return;
|
|
1154
1251
|
}
|
|
1155
1252
|
// Do an L2 revive and emit to subscriber using the callback.
|
|
1156
|
-
|
|
1253
|
+
reviveSnapshotWrapper(rebuilt, () => {
|
|
1157
1254
|
// reviveSnapshot will revive into L1, and since "records" is a reference
|
|
1158
1255
|
// (and not a copy) to the L1 records we can use it for rebuild
|
|
1159
1256
|
let rebuiltSnap;
|
|
@@ -1194,10 +1291,10 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
1194
1291
|
// the next publishChangesToDurableStore. NOTE: we don't need to call
|
|
1195
1292
|
// redirect on the base environment store because staging store and base
|
|
1196
1293
|
// L1 store share the same redirect and reverseRedirectKeys
|
|
1197
|
-
if (
|
|
1198
|
-
|
|
1294
|
+
if (stagingStore === null) {
|
|
1295
|
+
stagingStore = buildIngestStagingStore(environment);
|
|
1199
1296
|
}
|
|
1200
|
-
|
|
1297
|
+
stagingStore.redirect(existingKey, canonicalKey);
|
|
1201
1298
|
};
|
|
1202
1299
|
const storeSetTTLOverride = function (namespace, representationName, ttl) {
|
|
1203
1300
|
validateNotDisposed();
|
|
@@ -1238,7 +1335,7 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
1238
1335
|
if (isUnfulfilledSnapshot$1(snapshot)) {
|
|
1239
1336
|
const start = Date.now();
|
|
1240
1337
|
emitDurableEnvironmentAdapterEvent({ type: 'l2-revive-start' }, adapterRequestContext.eventObservers);
|
|
1241
|
-
const revivedSnapshot =
|
|
1338
|
+
const revivedSnapshot = reviveSnapshotWrapper(snapshot, () => injectedStoreLookup(snapshot.select, snapshot.refresh)).then((result) => {
|
|
1242
1339
|
emitDurableEnvironmentAdapterEvent({
|
|
1243
1340
|
type: 'l2-revive-end',
|
|
1244
1341
|
snapshot: result.snapshot,
|
|
@@ -1263,15 +1360,15 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
1263
1360
|
};
|
|
1264
1361
|
const getIngestStagingStoreRecords = function () {
|
|
1265
1362
|
validateNotDisposed();
|
|
1266
|
-
if (
|
|
1267
|
-
return
|
|
1363
|
+
if (stagingStore !== null) {
|
|
1364
|
+
return stagingStore.fallbackStringKeyInMemoryStore.records;
|
|
1268
1365
|
}
|
|
1269
1366
|
return {};
|
|
1270
1367
|
};
|
|
1271
1368
|
const getIngestStagingStoreMetadata = function () {
|
|
1272
1369
|
validateNotDisposed();
|
|
1273
|
-
if (
|
|
1274
|
-
return
|
|
1370
|
+
if (stagingStore !== null) {
|
|
1371
|
+
return stagingStore.fallbackStringKeyInMemoryStore.metadata;
|
|
1275
1372
|
}
|
|
1276
1373
|
return {};
|
|
1277
1374
|
};
|
|
@@ -1310,22 +1407,20 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
1310
1407
|
}
|
|
1311
1408
|
await Promise.all(pendingPromises);
|
|
1312
1409
|
const entries = await durableStore.getEntries(keysToReviveAsArray, DefaultDurableSegment);
|
|
1313
|
-
|
|
1410
|
+
stagingStore = buildIngestStagingStore(environment);
|
|
1314
1411
|
publishDurableStoreEntries(entries, (key, record) => {
|
|
1315
1412
|
if (typeof key === 'string') {
|
|
1316
|
-
|
|
1317
|
-
record;
|
|
1413
|
+
stagingStore.fallbackStringKeyInMemoryStore.records[key] = record;
|
|
1318
1414
|
}
|
|
1319
1415
|
else {
|
|
1320
|
-
|
|
1416
|
+
stagingStore.recordsMap.set(key, record);
|
|
1321
1417
|
}
|
|
1322
1418
|
}, (key, metadata) => {
|
|
1323
1419
|
if (typeof key === 'string') {
|
|
1324
|
-
|
|
1325
|
-
metadata;
|
|
1420
|
+
stagingStore.fallbackStringKeyInMemoryStore.metadata[key] = metadata;
|
|
1326
1421
|
}
|
|
1327
1422
|
else {
|
|
1328
|
-
|
|
1423
|
+
stagingStore.metadataMap.set(key, metadata);
|
|
1329
1424
|
}
|
|
1330
1425
|
});
|
|
1331
1426
|
snapshotFromMemoryIngest = await ingestAndBroadcastFunc();
|
|
@@ -1354,7 +1449,7 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
1354
1449
|
// we aren't doing any merging so we don't have to synchronize, the
|
|
1355
1450
|
// underlying DurableStore implementation takes care of R/W sync
|
|
1356
1451
|
// so all we have to do is ingest then write to L2
|
|
1357
|
-
|
|
1452
|
+
stagingStore = buildIngestStagingStore(environment);
|
|
1358
1453
|
snapshotFromMemoryIngest = await ingestAndBroadcastFunc();
|
|
1359
1454
|
}
|
|
1360
1455
|
if (snapshotFromMemoryIngest === undefined) {
|
|
@@ -1365,12 +1460,12 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
1365
1460
|
}
|
|
1366
1461
|
// if snapshot from staging store lookup is unfulfilled then do an L2 lookup
|
|
1367
1462
|
const { select, refresh } = snapshotFromMemoryIngest;
|
|
1368
|
-
const result = await
|
|
1463
|
+
const result = await reviveSnapshotWrapper(snapshotFromMemoryIngest, () => environment.storeLookup(select, environment.createSnapshot, refresh));
|
|
1369
1464
|
return result.snapshot;
|
|
1370
1465
|
};
|
|
1371
1466
|
const handleErrorResponse = async function (ingestAndBroadcastFunc) {
|
|
1372
1467
|
validateNotDisposed();
|
|
1373
|
-
|
|
1468
|
+
stagingStore = buildIngestStagingStore(environment);
|
|
1374
1469
|
return ingestAndBroadcastFunc();
|
|
1375
1470
|
};
|
|
1376
1471
|
const getNotifyChangeStoreEntries = function (keys) {
|
|
@@ -1421,6 +1516,27 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
1421
1516
|
await durableStore.setEntries({ notifyStoreUpdateAvailable: { data: entryKeys } }, MessagingDurableSegment);
|
|
1422
1517
|
return Promise.resolve(undefined);
|
|
1423
1518
|
};
|
|
1519
|
+
const reviveSnapshotWrapper = function (unavailableSnapshot, buildL1Snapshot) {
|
|
1520
|
+
let revivingStore = undefined;
|
|
1521
|
+
if (useRevivingStore) {
|
|
1522
|
+
// NOTE: `store` is private, there doesn't seem to be a better,
|
|
1523
|
+
// cleaner way of accessing it from a derived environment.
|
|
1524
|
+
let baseStore = environment.store;
|
|
1525
|
+
// If we're rebuilding during an ingest, the existing staging store should be the base store.
|
|
1526
|
+
if (stagingStore) {
|
|
1527
|
+
baseStore = stagingStore;
|
|
1528
|
+
}
|
|
1529
|
+
let revivingStore = buildRevivingStagingStore(baseStore);
|
|
1530
|
+
revivingStores.add(revivingStore);
|
|
1531
|
+
}
|
|
1532
|
+
return reviveSnapshot(environment, durableStore, unavailableSnapshot, durableStoreErrorHandler, () => {
|
|
1533
|
+
const tempStore = stagingStore;
|
|
1534
|
+
const result = buildL1Snapshot();
|
|
1535
|
+
stagingStore = tempStore;
|
|
1536
|
+
return result;
|
|
1537
|
+
}, revivingStore).finally(() => {
|
|
1538
|
+
});
|
|
1539
|
+
};
|
|
1424
1540
|
// set the default cache policy of the base environment
|
|
1425
1541
|
environment.setDefaultCachePolicy({
|
|
1426
1542
|
type: 'stale-while-revalidate',
|
|
@@ -1455,6 +1571,72 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
1455
1571
|
});
|
|
1456
1572
|
}
|
|
1457
1573
|
|
|
1574
|
+
/**
|
|
1575
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
1576
|
+
* All rights reserved.
|
|
1577
|
+
* For full license text, see the LICENSE.txt file
|
|
1578
|
+
*/
|
|
1579
|
+
|
|
1580
|
+
const API_NAMESPACE = 'UiApi';
|
|
1581
|
+
const RECORD_REPRESENTATION_NAME = 'RecordRepresentation';
|
|
1582
|
+
const RECORD_VIEW_ENTITY_REPRESENTATION_NAME = 'RecordViewEntityRepresentation';
|
|
1583
|
+
const RECORD_ID_PREFIX = `${API_NAMESPACE}::${RECORD_REPRESENTATION_NAME}:`;
|
|
1584
|
+
const RECORD_VIEW_ENTITY_ID_PREFIX = `${API_NAMESPACE}::${RECORD_VIEW_ENTITY_REPRESENTATION_NAME}:Name:`;
|
|
1585
|
+
const RECORD_FIELDS_KEY_JUNCTION = '__fields__';
|
|
1586
|
+
function isStoreKeyRecordId(key) {
|
|
1587
|
+
return key.indexOf(RECORD_ID_PREFIX) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION) === -1;
|
|
1588
|
+
}
|
|
1589
|
+
function isStoreKeyRecordViewEntity(key) {
|
|
1590
|
+
return (key.indexOf(RECORD_VIEW_ENTITY_ID_PREFIX) > -1 &&
|
|
1591
|
+
key.indexOf(RECORD_FIELDS_KEY_JUNCTION) === -1);
|
|
1592
|
+
}
|
|
1593
|
+
function isStoreKeyRecordField(key) {
|
|
1594
|
+
return key.indexOf(RECORD_ID_PREFIX) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION) > -1;
|
|
1595
|
+
}
|
|
1596
|
+
function extractRecordIdFromStoreKey(key) {
|
|
1597
|
+
if (key === undefined ||
|
|
1598
|
+
(key.indexOf(RECORD_ID_PREFIX) === -1 && key.indexOf(RECORD_VIEW_ENTITY_ID_PREFIX) === -1)) {
|
|
1599
|
+
return undefined;
|
|
1600
|
+
}
|
|
1601
|
+
const parts = key.split(':');
|
|
1602
|
+
return parts[parts.length - 1].split('_')[0];
|
|
1603
|
+
}
|
|
1604
|
+
function buildRecordFieldStoreKey(recordKey, fieldName) {
|
|
1605
|
+
return `${recordKey}${RECORD_FIELDS_KEY_JUNCTION}${fieldName}`;
|
|
1606
|
+
}
|
|
1607
|
+
function objectsDeepEqual(lhs, rhs) {
|
|
1608
|
+
if (lhs === rhs)
|
|
1609
|
+
return true;
|
|
1610
|
+
if (typeof lhs !== 'object' || typeof rhs !== 'object' || lhs === null || rhs === null)
|
|
1611
|
+
return false;
|
|
1612
|
+
const lhsKeys = Object.keys(lhs);
|
|
1613
|
+
const rhsKeys = Object.keys(rhs);
|
|
1614
|
+
if (lhsKeys.length !== rhsKeys.length)
|
|
1615
|
+
return false;
|
|
1616
|
+
for (let key of lhsKeys) {
|
|
1617
|
+
if (!rhsKeys.includes(key))
|
|
1618
|
+
return false;
|
|
1619
|
+
if (typeof lhs[key] === 'function' || typeof rhs[key] === 'function') {
|
|
1620
|
+
if (lhs[key].toString() !== rhs[key].toString())
|
|
1621
|
+
return false;
|
|
1622
|
+
}
|
|
1623
|
+
else {
|
|
1624
|
+
if (!objectsDeepEqual(lhs[key], rhs[key]))
|
|
1625
|
+
return false;
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
return true;
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
function isStoreRecordError(storeRecord) {
|
|
1632
|
+
return storeRecord.__type === 'error';
|
|
1633
|
+
}
|
|
1634
|
+
function isEntryDurableRecordRepresentation(entry, key) {
|
|
1635
|
+
// Either a DurableRecordRepresentation or StoreRecordError can live at a record key
|
|
1636
|
+
return ((isStoreKeyRecordId(key) || isStoreKeyRecordViewEntity(key)) &&
|
|
1637
|
+
entry.data.__type === undefined);
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1458
1640
|
/**
|
|
1459
1641
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
1460
1642
|
* All rights reserved.
|
|
@@ -1839,7 +2021,7 @@ function isFailure(result) {
|
|
|
1839
2021
|
function errors(result) {
|
|
1840
2022
|
return result.error;
|
|
1841
2023
|
}
|
|
1842
|
-
function values$
|
|
2024
|
+
function values$4(result) {
|
|
1843
2025
|
return result.value;
|
|
1844
2026
|
}
|
|
1845
2027
|
function flattenResults(results) {
|
|
@@ -1847,7 +2029,7 @@ function flattenResults(results) {
|
|
|
1847
2029
|
if (fails.length > 0) {
|
|
1848
2030
|
return failure(fails);
|
|
1849
2031
|
}
|
|
1850
|
-
return success(results.filter(isSuccess).map(values$
|
|
2032
|
+
return success(results.filter(isSuccess).map(values$4));
|
|
1851
2033
|
}
|
|
1852
2034
|
|
|
1853
2035
|
function getFieldInfo(apiName, fieldName, infoMap) {
|
|
@@ -2733,7 +2915,7 @@ function fieldsToFilters(fieldValues, joinAlias, apiName, input, compoundOperato
|
|
|
2733
2915
|
if (failures.length > 0) {
|
|
2734
2916
|
return failure(failures);
|
|
2735
2917
|
}
|
|
2736
|
-
const containers = results.filter(isSuccess).map(values$
|
|
2918
|
+
const containers = results.filter(isSuccess).map(values$4);
|
|
2737
2919
|
const predicates = [];
|
|
2738
2920
|
containers.forEach((c) => {
|
|
2739
2921
|
if (c.predicate !== undefined) {
|
|
@@ -3025,7 +3207,7 @@ function dateFunctions(operatorNode, extract, dataType) {
|
|
|
3025
3207
|
if (fails.length > 0) {
|
|
3026
3208
|
return failure(fails);
|
|
3027
3209
|
}
|
|
3028
|
-
const vals = results.filter(isSuccess).reduce(flatMap(values$
|
|
3210
|
+
const vals = results.filter(isSuccess).reduce(flatMap(values$4), []);
|
|
3029
3211
|
return success(vals);
|
|
3030
3212
|
}
|
|
3031
3213
|
function isFilterFunction(name) {
|
|
@@ -3035,7 +3217,7 @@ function fieldOperators(operatorNode, dataType) {
|
|
|
3035
3217
|
const results = Object.entries(operatorNode.fields)
|
|
3036
3218
|
.filter(([key, _]) => isFilterFunction(key) === false)
|
|
3037
3219
|
.map(([key, value]) => operatorWithValue(key, value, dataType));
|
|
3038
|
-
const _values = results.filter(isSuccess).map(values$
|
|
3220
|
+
const _values = results.filter(isSuccess).map(values$4);
|
|
3039
3221
|
const fails = results.filter(isFailure).reduce(flatMap(errors), []);
|
|
3040
3222
|
if (fails.length > 0) {
|
|
3041
3223
|
return failure(fails);
|
|
@@ -3956,7 +4138,7 @@ function selectionToQueryField(node, names, parentApiName, parentAlias, input, j
|
|
|
3956
4138
|
}
|
|
3957
4139
|
function recordFields(luvioSelections, names, parentApiName, parentAlias, input, joins) {
|
|
3958
4140
|
const results = luvioSelections.map((selection) => selectionToQueryField(selection, names, parentApiName, parentAlias, input, joins));
|
|
3959
|
-
const fields = results.filter(isSuccess).reduce(flatMap(values$
|
|
4141
|
+
const fields = results.filter(isSuccess).reduce(flatMap(values$4), []);
|
|
3960
4142
|
const fails = results.filter(isFailure).reduce(flatMap(errors), []);
|
|
3961
4143
|
if (fails.length > 0) {
|
|
3962
4144
|
return failure(fails);
|
|
@@ -4202,7 +4384,7 @@ function rootRecordQuery(selection, input) {
|
|
|
4202
4384
|
}
|
|
4203
4385
|
function rootQuery(recordNodes, input) {
|
|
4204
4386
|
const results = recordNodes.map((record) => rootRecordQuery(record, input));
|
|
4205
|
-
const connections = results.filter(isSuccess).map(values$
|
|
4387
|
+
const connections = results.filter(isSuccess).map(values$4);
|
|
4206
4388
|
const fails = results.filter(isFailure).reduce(flatMap(errors), []);
|
|
4207
4389
|
if (fails.length > 0) {
|
|
4208
4390
|
return failure(fails);
|
|
@@ -4653,7 +4835,11 @@ function makeStoreEval(preconditioner, objectInfoService, userId, contextProvide
|
|
|
4653
4835
|
try {
|
|
4654
4836
|
const { data, seenRecords } = await queryEvaluator(rootQuery, context, eventEmitter);
|
|
4655
4837
|
const rebuildWithStoreEval = ((originalSnapshot) => {
|
|
4656
|
-
return storeEval(config, originalSnapshot, observers, connectionKeyBuilder)
|
|
4838
|
+
return storeEval(config, originalSnapshot, observers, connectionKeyBuilder).then((rebuiltSnapshot) => {
|
|
4839
|
+
return objectsDeepEqual(originalSnapshot.data, rebuiltSnapshot.data)
|
|
4840
|
+
? originalSnapshot
|
|
4841
|
+
: rebuiltSnapshot;
|
|
4842
|
+
});
|
|
4657
4843
|
});
|
|
4658
4844
|
const recordId = generateUniqueRecordId$1();
|
|
4659
4845
|
// if the non-eval'ed snapshot was an error then we return a synthetic
|
|
@@ -4956,7 +5142,7 @@ function createDraftSynthesisErrorResponse(message = 'failed to synthesize draft
|
|
|
4956
5142
|
return new DraftErrorFetchResponse(HttpStatusCode.BadRequest, error);
|
|
4957
5143
|
}
|
|
4958
5144
|
|
|
4959
|
-
const { keys: keys$5, create: create$5, assign: assign$5, values: values$
|
|
5145
|
+
const { keys: keys$5, create: create$5, assign: assign$5, values: values$3 } = Object;
|
|
4960
5146
|
const { stringify: stringify$5, parse: parse$5 } = JSON;
|
|
4961
5147
|
const { isArray: isArray$3 } = Array;
|
|
4962
5148
|
|
|
@@ -5391,7 +5577,7 @@ class DurableDraftQueue {
|
|
|
5391
5577
|
const queueOperations = handler.getQueueOperationsForCompletingDrafts(queue, action);
|
|
5392
5578
|
// write the queue operations to the store prior to ingesting the result
|
|
5393
5579
|
await this.draftStore.completeAction(queueOperations);
|
|
5394
|
-
await handler.handleActionCompleted(action, queueOperations, values$
|
|
5580
|
+
await handler.handleActionCompleted(action, queueOperations, values$3(this.handlers));
|
|
5395
5581
|
this.retryIntervalMilliseconds = 0;
|
|
5396
5582
|
this.uploadingActionId = undefined;
|
|
5397
5583
|
await this.notifyChangedListeners({
|
|
@@ -6613,49 +6799,6 @@ function makeEnvironmentDraftAware(luvio, env, durableStore, handlers, draftQueu
|
|
|
6613
6799
|
});
|
|
6614
6800
|
}
|
|
6615
6801
|
|
|
6616
|
-
/**
|
|
6617
|
-
* Copyright (c) 2022, Salesforce, Inc.,
|
|
6618
|
-
* All rights reserved.
|
|
6619
|
-
* For full license text, see the LICENSE.txt file
|
|
6620
|
-
*/
|
|
6621
|
-
|
|
6622
|
-
const API_NAMESPACE = 'UiApi';
|
|
6623
|
-
const RECORD_REPRESENTATION_NAME = 'RecordRepresentation';
|
|
6624
|
-
const RECORD_VIEW_ENTITY_REPRESENTATION_NAME = 'RecordViewEntityRepresentation';
|
|
6625
|
-
const RECORD_ID_PREFIX = `${API_NAMESPACE}::${RECORD_REPRESENTATION_NAME}:`;
|
|
6626
|
-
const RECORD_VIEW_ENTITY_ID_PREFIX = `${API_NAMESPACE}::${RECORD_VIEW_ENTITY_REPRESENTATION_NAME}:Name:`;
|
|
6627
|
-
const RECORD_FIELDS_KEY_JUNCTION = '__fields__';
|
|
6628
|
-
function isStoreKeyRecordId(key) {
|
|
6629
|
-
return key.indexOf(RECORD_ID_PREFIX) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION) === -1;
|
|
6630
|
-
}
|
|
6631
|
-
function isStoreKeyRecordViewEntity(key) {
|
|
6632
|
-
return (key.indexOf(RECORD_VIEW_ENTITY_ID_PREFIX) > -1 &&
|
|
6633
|
-
key.indexOf(RECORD_FIELDS_KEY_JUNCTION) === -1);
|
|
6634
|
-
}
|
|
6635
|
-
function isStoreKeyRecordField(key) {
|
|
6636
|
-
return key.indexOf(RECORD_ID_PREFIX) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION) > -1;
|
|
6637
|
-
}
|
|
6638
|
-
function extractRecordIdFromStoreKey(key) {
|
|
6639
|
-
if (key === undefined ||
|
|
6640
|
-
(key.indexOf(RECORD_ID_PREFIX) === -1 && key.indexOf(RECORD_VIEW_ENTITY_ID_PREFIX) === -1)) {
|
|
6641
|
-
return undefined;
|
|
6642
|
-
}
|
|
6643
|
-
const parts = key.split(':');
|
|
6644
|
-
return parts[parts.length - 1].split('_')[0];
|
|
6645
|
-
}
|
|
6646
|
-
function buildRecordFieldStoreKey(recordKey, fieldName) {
|
|
6647
|
-
return `${recordKey}${RECORD_FIELDS_KEY_JUNCTION}${fieldName}`;
|
|
6648
|
-
}
|
|
6649
|
-
|
|
6650
|
-
function isStoreRecordError(storeRecord) {
|
|
6651
|
-
return storeRecord.__type === 'error';
|
|
6652
|
-
}
|
|
6653
|
-
function isEntryDurableRecordRepresentation(entry, key) {
|
|
6654
|
-
// Either a DurableRecordRepresentation or StoreRecordError can live at a record key
|
|
6655
|
-
return ((isStoreKeyRecordId(key) || isStoreKeyRecordViewEntity(key)) &&
|
|
6656
|
-
entry.data.__type === undefined);
|
|
6657
|
-
}
|
|
6658
|
-
|
|
6659
6802
|
function serializeFieldArguments(argumentNodes, variables) {
|
|
6660
6803
|
const mutableArgumentNodes = Object.assign([], argumentNodes);
|
|
6661
6804
|
return `args__(${mutableArgumentNodes
|
|
@@ -6887,7 +7030,7 @@ function isArrayLike(x) {
|
|
|
6887
7030
|
(x.length === 0 || (x.length > 0 && Object.prototype.hasOwnProperty.call(x, x.length - 1))));
|
|
6888
7031
|
}
|
|
6889
7032
|
|
|
6890
|
-
const { create: create$4, keys: keys$4, values: values$
|
|
7033
|
+
const { create: create$4, keys: keys$4, values: values$2, entries: entries$3, assign: assign$4 } = Object;
|
|
6891
7034
|
const { stringify: stringify$4, parse: parse$4 } = JSON;
|
|
6892
7035
|
const { isArray: isArray$2 } = Array;
|
|
6893
7036
|
|
|
@@ -7220,7 +7363,7 @@ function dateTimePredicate(input, operator, field, alias) {
|
|
|
7220
7363
|
return predicate;
|
|
7221
7364
|
}
|
|
7222
7365
|
else if (literal !== undefined) {
|
|
7223
|
-
const isAvailableLiteral = values$
|
|
7366
|
+
const isAvailableLiteral = values$2(DateLiteral).includes(literal);
|
|
7224
7367
|
// eslint-disable-next-line @salesforce/lds/no-error-in-production
|
|
7225
7368
|
if (!isAvailableLiteral)
|
|
7226
7369
|
throw new Error(`${literal} is not a valid DateLiteral`);
|
|
@@ -7894,7 +8037,7 @@ function dedupeJoins(joins) {
|
|
|
7894
8037
|
for (const join of joins) {
|
|
7895
8038
|
deduped[join.alias + join.to] = join;
|
|
7896
8039
|
}
|
|
7897
|
-
return values$
|
|
8040
|
+
return values$2(deduped);
|
|
7898
8041
|
}
|
|
7899
8042
|
function buildJoins(config) {
|
|
7900
8043
|
let sql = '';
|
|
@@ -8542,7 +8685,7 @@ function flatten(previous, current) {
|
|
|
8542
8685
|
return previous.concat(current);
|
|
8543
8686
|
}
|
|
8544
8687
|
function findFieldInfo(objectInfo, fieldName) {
|
|
8545
|
-
return values$
|
|
8688
|
+
return values$2(objectInfo.fields).find((field) => field.apiName === fieldName ||
|
|
8546
8689
|
(field.dataType === 'Reference' && field.relationshipName === fieldName));
|
|
8547
8690
|
}
|
|
8548
8691
|
|
|
@@ -8562,10 +8705,10 @@ function orderByToPredicate(orderBy, recordType, alias, objectInfoMap, joins) {
|
|
|
8562
8705
|
for (let i = 0, len = keys$1.length; i < len; i++) {
|
|
8563
8706
|
const key = keys$1[i];
|
|
8564
8707
|
const parentFields = objectInfoMap[recordType].fields;
|
|
8565
|
-
const fieldInfo = values$
|
|
8708
|
+
const fieldInfo = values$2(parentFields).find(findSpanningField(key));
|
|
8566
8709
|
if (fieldInfo && fieldInfo.referenceToInfos.length > 0) {
|
|
8567
8710
|
const { apiName } = fieldInfo.referenceToInfos[0];
|
|
8568
|
-
const parentFieldInfo = values$
|
|
8711
|
+
const parentFieldInfo = values$2(objectInfoMap[recordType].fields).find(findSpanningField(fieldInfo.apiName));
|
|
8569
8712
|
if (parentFieldInfo !== undefined) {
|
|
8570
8713
|
const path = {
|
|
8571
8714
|
leftPath: `$.fields.${parentFieldInfo.apiName}.value`,
|
|
@@ -8707,7 +8850,7 @@ function addResolversToSchema(schema, polyFields) {
|
|
|
8707
8850
|
let baseRecord = undefined;
|
|
8708
8851
|
// Concrete types for Polymorphic field
|
|
8709
8852
|
const polyTypes = [];
|
|
8710
|
-
for (const type of values$
|
|
8853
|
+
for (const type of values$2(schema.getTypeMap())) {
|
|
8711
8854
|
if (type.name === 'Record') {
|
|
8712
8855
|
recordInterface = type;
|
|
8713
8856
|
}
|
|
@@ -8720,7 +8863,7 @@ function addResolversToSchema(schema, polyFields) {
|
|
|
8720
8863
|
if (polyFields.find((fieldTypeName) => fieldTypeName === type.name) !== undefined) {
|
|
8721
8864
|
polyTypes.push(type);
|
|
8722
8865
|
}
|
|
8723
|
-
const fields = values$
|
|
8866
|
+
const fields = values$2(type.getFields());
|
|
8724
8867
|
// initialize the fields of current type with default behavior
|
|
8725
8868
|
for (const field of fields) {
|
|
8726
8869
|
field.resolve = defaultFieldResolver;
|
|
@@ -9122,26 +9265,20 @@ function generateRecordQueries(objectInfos) {
|
|
|
9122
9265
|
let recordConnections = ``;
|
|
9123
9266
|
const polymorphicFieldTypeNames = new Set();
|
|
9124
9267
|
let typedScalars = new Set();
|
|
9125
|
-
|
|
9268
|
+
let parentRelationshipFields = new Set();
|
|
9269
|
+
for (const objectInfo of values$2(objectInfos)) {
|
|
9126
9270
|
const { apiName, childRelationships } = objectInfo;
|
|
9127
9271
|
let fields = ``;
|
|
9128
9272
|
typedScalars.add(`${apiName}_Filter`);
|
|
9129
9273
|
typedScalars.add(`${apiName}_OrderBy`);
|
|
9130
|
-
for (const
|
|
9131
|
-
const { childObjectApiName } = childRelationship;
|
|
9132
|
-
// Only add the relationship if there is relevant objectinfos for it,
|
|
9133
|
-
// otherwise we'd be defining types we cannot satisfy and aren't referenced in
|
|
9134
|
-
// the query.
|
|
9135
|
-
if (objectInfos[childObjectApiName] !== undefined) {
|
|
9136
|
-
fields += `${childRelationship.relationshipName}(first: Int, where: ${childObjectApiName}_Filter, orderBy: ${childObjectApiName}_OrderBy, scope: SupportedScopes): ${childObjectApiName}Connection \n`;
|
|
9137
|
-
typedScalars.add(`${childObjectApiName}_Filter`);
|
|
9138
|
-
typedScalars.add(`${childObjectApiName}_OrderBy`);
|
|
9139
|
-
}
|
|
9140
|
-
}
|
|
9141
|
-
for (const field of values$1(objectInfo.fields)) {
|
|
9274
|
+
for (const field of values$2(objectInfo.fields)) {
|
|
9142
9275
|
if (!fieldsStaticallyAdded.includes(field.apiName)) {
|
|
9143
9276
|
fields += `${field.apiName}: ${dataTypeToType(field.dataType, field.apiName)}\n`;
|
|
9144
9277
|
}
|
|
9278
|
+
//handles parent relationship
|
|
9279
|
+
if (field.relationshipName === null) {
|
|
9280
|
+
continue;
|
|
9281
|
+
}
|
|
9145
9282
|
// For spanning parent relationships with no union types
|
|
9146
9283
|
if (field.referenceToInfos.length === 1) {
|
|
9147
9284
|
const [relation] = field.referenceToInfos;
|
|
@@ -9149,11 +9286,13 @@ function generateRecordQueries(objectInfos) {
|
|
|
9149
9286
|
// otherwise we'd be defining types we cannot satisfy and aren't referenced in
|
|
9150
9287
|
// the query.
|
|
9151
9288
|
if (objectInfos[relation.apiName] !== undefined) {
|
|
9289
|
+
parentRelationshipFields.add(field.relationshipName);
|
|
9152
9290
|
fields += `${field.relationshipName}: ${relation.apiName}\n`;
|
|
9153
9291
|
}
|
|
9154
9292
|
// For polymorphic field, its type is 'Record' inteface. The concrete entity type name is saved for field resolving of next phase
|
|
9155
9293
|
}
|
|
9156
9294
|
else if (field.referenceToInfos.length > 1) {
|
|
9295
|
+
parentRelationshipFields.add(field.relationshipName);
|
|
9157
9296
|
fields += `${field.relationshipName}: Record\n`;
|
|
9158
9297
|
for (const relation of field.referenceToInfos) {
|
|
9159
9298
|
if (objectInfos[relation.apiName] !== undefined) {
|
|
@@ -9162,6 +9301,20 @@ function generateRecordQueries(objectInfos) {
|
|
|
9162
9301
|
}
|
|
9163
9302
|
}
|
|
9164
9303
|
}
|
|
9304
|
+
// handles child relationship
|
|
9305
|
+
for (const childRelationship of childRelationships) {
|
|
9306
|
+
const { childObjectApiName } = childRelationship;
|
|
9307
|
+
// Only add the relationship if there is relevant objectinfos for it,
|
|
9308
|
+
// otherwise we'd be defining types we cannot satisfy and aren't referenced in
|
|
9309
|
+
// the query.
|
|
9310
|
+
// If one field has both parent relationship and child relationship with the same name, the child relationship is ignored. This is how the server GQL has implemented as date of 08/07/2023
|
|
9311
|
+
if (objectInfos[childObjectApiName] !== undefined &&
|
|
9312
|
+
!parentRelationshipFields.has(childRelationship.relationshipName)) {
|
|
9313
|
+
fields += `${childRelationship.relationshipName}(first: Int, where: ${childObjectApiName}_Filter, orderBy: ${childObjectApiName}_OrderBy, scope: SupportedScopes): ${childObjectApiName}Connection \n`;
|
|
9314
|
+
typedScalars.add(`${childObjectApiName}_Filter`);
|
|
9315
|
+
typedScalars.add(`${childObjectApiName}_OrderBy`);
|
|
9316
|
+
}
|
|
9317
|
+
}
|
|
9165
9318
|
recordQueries += `${apiName}(first: Int, where: ${apiName}_Filter, orderBy: ${apiName}_OrderBy, scope: SupportedScopes): ${apiName}Connection\n`;
|
|
9166
9319
|
const isServiceAppointment = apiName === 'ServiceAppointment';
|
|
9167
9320
|
recordConnections += /* GraphQL */ `
|
|
@@ -9641,7 +9794,7 @@ function isMineScopeAvailable(apiNamePath, objectInfoApiMap, objectInfos) {
|
|
|
9641
9794
|
const objectInfo = objectInfos[apiName[0]];
|
|
9642
9795
|
if (!objectInfo)
|
|
9643
9796
|
return false;
|
|
9644
|
-
return values$
|
|
9797
|
+
return values$2(objectInfo.fields).some((fieldInfo) => {
|
|
9645
9798
|
return (fieldInfo.apiName === 'OwnerId' &&
|
|
9646
9799
|
fieldInfo.referenceToInfos.some((referenceToInfo) => {
|
|
9647
9800
|
return referenceToInfo.apiName === 'User';
|
|
@@ -10892,7 +11045,7 @@ function referenceIdFieldForRelationship(relationshipName) {
|
|
|
10892
11045
|
* For full license text, see the LICENSE.txt file
|
|
10893
11046
|
*/
|
|
10894
11047
|
|
|
10895
|
-
const { keys: keys$3, values, create: create$3, assign: assign$3, freeze } = Object;
|
|
11048
|
+
const { keys: keys$3, values: values$1, create: create$3, assign: assign$3, freeze } = Object;
|
|
10896
11049
|
const { stringify: stringify$3, parse: parse$3 } = JSON;
|
|
10897
11050
|
const { shift } = Array.prototype;
|
|
10898
11051
|
const { isArray: isArray$1 } = Array;
|
|
@@ -11742,7 +11895,7 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
|
|
|
11742
11895
|
return;
|
|
11743
11896
|
}
|
|
11744
11897
|
const objectInfo = objectInfoMap[apiName];
|
|
11745
|
-
const optionalFields = values(objectInfo.fields).map((field) => `${apiName}.${field.apiName}`);
|
|
11898
|
+
const optionalFields = values$1(objectInfo.fields).map((field) => `${apiName}.${field.apiName}`);
|
|
11746
11899
|
await getAdapterData(this.getRecordAdapter, {
|
|
11747
11900
|
recordId: referenceFieldInfo.id,
|
|
11748
11901
|
optionalFields,
|
|
@@ -11761,7 +11914,7 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
|
|
|
11761
11914
|
const referenceToInfos = fieldInfo.referenceToInfos;
|
|
11762
11915
|
const apiNames = referenceToInfos.map((referenceToInfo) => referenceToInfo.apiName);
|
|
11763
11916
|
const objectInfoMap = await this.objectInfoService.getObjectInfos(apiNames);
|
|
11764
|
-
for (const objectInfo of values(objectInfoMap)) {
|
|
11917
|
+
for (const objectInfo of values$1(objectInfoMap)) {
|
|
11765
11918
|
const { apiName, keyPrefix } = objectInfo;
|
|
11766
11919
|
if (keyPrefix !== null && id.startsWith(keyPrefix)) {
|
|
11767
11920
|
return apiName;
|
|
@@ -12271,14 +12424,30 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
|
|
|
12271
12424
|
const operationsWithDenormedRecords = [];
|
|
12272
12425
|
for (let i = 0, len = operations.length; i < len; i++) {
|
|
12273
12426
|
const operation = operations[i];
|
|
12274
|
-
if (
|
|
12275
|
-
|
|
12276
|
-
|
|
12427
|
+
if (durableStore.plugin !== undefined &&
|
|
12428
|
+
durableStore.plugin.supportsBatchUpdates !== undefined &&
|
|
12429
|
+
durableStore.plugin.supportsBatchUpdates() === true) {
|
|
12430
|
+
if (operation.segment !== DefaultDurableSegment ||
|
|
12431
|
+
operation.type !== 'setEntries') {
|
|
12432
|
+
operationsWithDenormedRecords.push(operation);
|
|
12433
|
+
continue;
|
|
12434
|
+
}
|
|
12435
|
+
operationsWithDenormedRecords.push({
|
|
12436
|
+
...operation,
|
|
12437
|
+
entries: denormalizeEntries(operation.entries),
|
|
12438
|
+
});
|
|
12439
|
+
}
|
|
12440
|
+
else {
|
|
12441
|
+
if (operation.segment !== DefaultDurableSegment ||
|
|
12442
|
+
operation.type === 'evictEntries') {
|
|
12443
|
+
operationsWithDenormedRecords.push(operation);
|
|
12444
|
+
continue;
|
|
12445
|
+
}
|
|
12446
|
+
operationsWithDenormedRecords.push({
|
|
12447
|
+
...operation,
|
|
12448
|
+
entries: denormalizeEntries(operation.entries),
|
|
12449
|
+
});
|
|
12277
12450
|
}
|
|
12278
|
-
operationsWithDenormedRecords.push({
|
|
12279
|
-
...operation,
|
|
12280
|
-
entries: denormalizeEntries(operation.entries),
|
|
12281
|
-
});
|
|
12282
12451
|
}
|
|
12283
12452
|
return durableStore.batchOperations(operationsWithDenormedRecords);
|
|
12284
12453
|
};
|
|
@@ -12826,6 +12995,9 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
|
|
|
12826
12995
|
if (!rebuildResult.errors) {
|
|
12827
12996
|
rebuildResult = removeSyntheticFields(rebuildResult, config.query);
|
|
12828
12997
|
}
|
|
12998
|
+
if (objectsDeepEqual(rebuildResult, originalSnapshot.data)) {
|
|
12999
|
+
return originalSnapshot;
|
|
13000
|
+
}
|
|
12829
13001
|
// 'originalSnapshot' is the local eval snapshot subscribed. It is always in 'Fulfilled' state. This behavior would change once W-1273462(rebuild non-evaluated snapshot when the graphql local eval rebuild is triggered) is resolved.
|
|
12830
13002
|
return {
|
|
12831
13003
|
...originalSnapshot,
|
|
@@ -14990,7 +15162,7 @@ function registerReportObserver(reportObserver) {
|
|
|
14990
15162
|
};
|
|
14991
15163
|
}
|
|
14992
15164
|
|
|
14993
|
-
const { keys, create, assign, entries } = Object;
|
|
15165
|
+
const { keys, create, assign, entries, values } = Object;
|
|
14994
15166
|
const { stringify, parse } = JSON;
|
|
14995
15167
|
|
|
14996
15168
|
function selectColumnsFromTableWhereKeyIn(columnNames, table, keyColumnName, whereIn) {
|
|
@@ -15024,6 +15196,22 @@ class LdsDataTable {
|
|
|
15024
15196
|
}, reject);
|
|
15025
15197
|
});
|
|
15026
15198
|
}
|
|
15199
|
+
getMetadataByKeys(keys) {
|
|
15200
|
+
const query = selectColumnsFromTableWhereKeyIn([COLUMN_NAME_KEY$2, COLUMN_NAME_METADATA$1], this.tableName, COLUMN_NAME_KEY$2, keys);
|
|
15201
|
+
return new Promise((resolve, reject) => {
|
|
15202
|
+
this.plugin.query(query, keys, (results) => {
|
|
15203
|
+
resolve(results.rows.reduce((entries, row) => {
|
|
15204
|
+
const [key, stringifiedMetadata] = row;
|
|
15205
|
+
if (stringifiedMetadata !== undefined) {
|
|
15206
|
+
entries[key] = {
|
|
15207
|
+
metadata: parse(stringifiedMetadata),
|
|
15208
|
+
};
|
|
15209
|
+
}
|
|
15210
|
+
return entries;
|
|
15211
|
+
}, {}));
|
|
15212
|
+
}, reject);
|
|
15213
|
+
});
|
|
15214
|
+
}
|
|
15027
15215
|
getAll() {
|
|
15028
15216
|
return new Promise((resolve, reject) => {
|
|
15029
15217
|
this.plugin.query(this.getAllQuery, [], (x) => {
|
|
@@ -15050,6 +15238,24 @@ class LdsDataTable {
|
|
|
15050
15238
|
}, []),
|
|
15051
15239
|
};
|
|
15052
15240
|
}
|
|
15241
|
+
metadataToUpdateOperations(entries, segment) {
|
|
15242
|
+
return {
|
|
15243
|
+
type: 'update',
|
|
15244
|
+
table: this.tableName,
|
|
15245
|
+
keyColumn: COLUMN_NAME_KEY$2,
|
|
15246
|
+
context: {
|
|
15247
|
+
segment,
|
|
15248
|
+
type: 'setMetadata',
|
|
15249
|
+
},
|
|
15250
|
+
columns: [COLUMN_NAME_METADATA$1],
|
|
15251
|
+
values: keys(entries).reduce((values, key) => {
|
|
15252
|
+
const { metadata } = entries[key];
|
|
15253
|
+
const row = [metadata ? stringify(metadata) : null];
|
|
15254
|
+
values[key] = row;
|
|
15255
|
+
return values;
|
|
15256
|
+
}, {}),
|
|
15257
|
+
};
|
|
15258
|
+
}
|
|
15053
15259
|
mapToDurableEntries(sqliteResult) {
|
|
15054
15260
|
return sqliteResult.rows.reduce((entries, row) => {
|
|
15055
15261
|
const [key, stringifiedData, stringifiedMetadata] = row;
|
|
@@ -15096,6 +15302,25 @@ class LdsInternalDataTable {
|
|
|
15096
15302
|
}, reject);
|
|
15097
15303
|
});
|
|
15098
15304
|
}
|
|
15305
|
+
getMetadataByKeys(keys, namespace) {
|
|
15306
|
+
if (namespace === undefined) {
|
|
15307
|
+
throw Error('LdsInternalDataTable requires namespace');
|
|
15308
|
+
}
|
|
15309
|
+
const query = selectColumnsFromTableWhereKeyInNamespaced([COLUMN_NAME_KEY$1, COLUMN_NAME_METADATA], this.tableName, COLUMN_NAME_KEY$1, keys, COLUMN_NAME_NAMESPACE);
|
|
15310
|
+
return new Promise((resolve, reject) => {
|
|
15311
|
+
this.plugin.query(query, [namespace].concat(keys), (results) => {
|
|
15312
|
+
resolve(results.rows.reduce((entries, row) => {
|
|
15313
|
+
const [key, stringifiedMetadata] = row;
|
|
15314
|
+
if (stringifiedMetadata !== undefined) {
|
|
15315
|
+
entries[key] = {
|
|
15316
|
+
metadata: parse(stringifiedMetadata),
|
|
15317
|
+
};
|
|
15318
|
+
}
|
|
15319
|
+
return entries;
|
|
15320
|
+
}, {}));
|
|
15321
|
+
}, reject);
|
|
15322
|
+
});
|
|
15323
|
+
}
|
|
15099
15324
|
getAll(namespace) {
|
|
15100
15325
|
return new Promise((resolve, reject) => {
|
|
15101
15326
|
this.plugin.query(this.getAllQuery, [namespace], (x) => {
|
|
@@ -15129,6 +15354,42 @@ class LdsInternalDataTable {
|
|
|
15129
15354
|
}, []),
|
|
15130
15355
|
};
|
|
15131
15356
|
}
|
|
15357
|
+
metadataToUpdateOperations(entries, segment) {
|
|
15358
|
+
return {
|
|
15359
|
+
type: 'update',
|
|
15360
|
+
table: this.tableName,
|
|
15361
|
+
keyColumn: COLUMN_NAME_KEY$1,
|
|
15362
|
+
context: {
|
|
15363
|
+
segment,
|
|
15364
|
+
type: 'setMetadata',
|
|
15365
|
+
},
|
|
15366
|
+
columns: [COLUMN_NAME_METADATA],
|
|
15367
|
+
values: keys(entries).reduce((values, key) => {
|
|
15368
|
+
const { metadata } = entries[key];
|
|
15369
|
+
const row = [metadata ? stringify(metadata) : null];
|
|
15370
|
+
values[key] = row;
|
|
15371
|
+
return values;
|
|
15372
|
+
}, {}),
|
|
15373
|
+
};
|
|
15374
|
+
}
|
|
15375
|
+
metadataToUpdateSQLQueries(entries, segment) {
|
|
15376
|
+
return keys(entries).reduce((accu, key) => {
|
|
15377
|
+
const { metadata } = entries[key];
|
|
15378
|
+
if (metadata !== undefined) {
|
|
15379
|
+
accu.push({
|
|
15380
|
+
sql: `UPDATE ${this.tableName} SET ${COLUMN_NAME_METADATA} = ? WHERE (${COLUMN_NAME_KEY$1} IS ? AND ${COLUMN_NAME_NAMESPACE} IS ?)`,
|
|
15381
|
+
params: [stringify(metadata), key, segment],
|
|
15382
|
+
change: {
|
|
15383
|
+
ids: [key],
|
|
15384
|
+
segment,
|
|
15385
|
+
type: 'setMetadata',
|
|
15386
|
+
isExternalChange: false,
|
|
15387
|
+
},
|
|
15388
|
+
});
|
|
15389
|
+
}
|
|
15390
|
+
return accu;
|
|
15391
|
+
}, []);
|
|
15392
|
+
}
|
|
15132
15393
|
mapToDurableEntries(sqliteResult) {
|
|
15133
15394
|
return sqliteResult.rows.reduce((entries, row) => {
|
|
15134
15395
|
const [key, stringifiedData, stringifiedMetadata] = row;
|
|
@@ -15165,9 +15426,16 @@ class NimbusSqliteStore {
|
|
|
15165
15426
|
});
|
|
15166
15427
|
});
|
|
15167
15428
|
}
|
|
15429
|
+
batchQuery(queries) {
|
|
15430
|
+
const promises = queries.map((q) => this.query(q.sql, q.params));
|
|
15431
|
+
return Promise.all(promises);
|
|
15432
|
+
}
|
|
15168
15433
|
async getEntries(entryIds, segment) {
|
|
15169
15434
|
return this.getTable(segment).getByKeys(entryIds, segment);
|
|
15170
15435
|
}
|
|
15436
|
+
async getMetadata(entryIds, segment) {
|
|
15437
|
+
return this.getTable(segment).getMetadataByKeys(entryIds, segment);
|
|
15438
|
+
}
|
|
15171
15439
|
getAllEntries(segment) {
|
|
15172
15440
|
return this.getTable(segment).getAll(segment);
|
|
15173
15441
|
}
|
|
@@ -15176,12 +15444,30 @@ class NimbusSqliteStore {
|
|
|
15176
15444
|
const upsertOperation = table.entriesToUpsertOperations(entries, segment);
|
|
15177
15445
|
return this.batchOperationAsPromise([upsertOperation]);
|
|
15178
15446
|
}
|
|
15447
|
+
setMetadata(entries, segment) {
|
|
15448
|
+
const table = this.getTable(segment);
|
|
15449
|
+
const operation = this.plugin.supportsBatchUpdates === undefined ||
|
|
15450
|
+
this.plugin.supportsBatchUpdates() === false
|
|
15451
|
+
? table.entriesToUpsertOperations(entries, segment)
|
|
15452
|
+
: table.metadataToUpdateOperations(entries, segment);
|
|
15453
|
+
return this.batchOperationAsPromise([operation]);
|
|
15454
|
+
}
|
|
15179
15455
|
batchOperations(operations) {
|
|
15180
15456
|
const sqliteOperations = operations.reduce((acc, cur) => {
|
|
15181
15457
|
if (cur.type === 'setEntries') {
|
|
15182
15458
|
const table = this.getTable(cur.segment);
|
|
15183
15459
|
acc.push(table.entriesToUpsertOperations(cur.entries, cur.segment));
|
|
15184
15460
|
}
|
|
15461
|
+
else if (cur.type === 'setMetadata') {
|
|
15462
|
+
const table = this.getTable(cur.segment);
|
|
15463
|
+
if (this.plugin.supportsBatchUpdates === undefined ||
|
|
15464
|
+
this.plugin.supportsBatchUpdates() === false) {
|
|
15465
|
+
acc.push(table.entriesToUpsertOperations(cur.entries, cur.segment));
|
|
15466
|
+
}
|
|
15467
|
+
else {
|
|
15468
|
+
acc.push(table.metadataToUpdateOperations(cur.entries, cur.segment));
|
|
15469
|
+
}
|
|
15470
|
+
}
|
|
15185
15471
|
else {
|
|
15186
15472
|
acc.push(this.idsToDeleteOperation(cur.ids, cur.segment));
|
|
15187
15473
|
}
|
|
@@ -15198,8 +15484,15 @@ class NimbusSqliteStore {
|
|
|
15198
15484
|
this.plugin
|
|
15199
15485
|
.registerOnChangedListener(async (changes) => {
|
|
15200
15486
|
const durableChanges = changes.map((c) => {
|
|
15487
|
+
let type = c.type === 'upsert' ? 'setEntries' : 'evictEntries';
|
|
15488
|
+
// if our context contains a type then set that as our main level type
|
|
15489
|
+
// allows us in the future of updates to specify the segment change happening
|
|
15490
|
+
// example being update call on metadata only or updating data
|
|
15491
|
+
if (c.type === 'update' && c.context.type !== undefined) {
|
|
15492
|
+
type = c.context.type;
|
|
15493
|
+
}
|
|
15201
15494
|
return {
|
|
15202
|
-
type
|
|
15495
|
+
type,
|
|
15203
15496
|
ids: c.keys,
|
|
15204
15497
|
isExternalChange: false,
|
|
15205
15498
|
segment: c.context.segment,
|
|
@@ -15266,6 +15559,10 @@ class AbstractKeyValueDataTable {
|
|
|
15266
15559
|
}, reject);
|
|
15267
15560
|
});
|
|
15268
15561
|
}
|
|
15562
|
+
getMetadataByKeys(_keys) {
|
|
15563
|
+
// eslint-disable-next-line @salesforce/lds/no-error-in-production
|
|
15564
|
+
throw new Error(`There is no metadata in the ${this.tableName} table.`);
|
|
15565
|
+
}
|
|
15269
15566
|
getAll() {
|
|
15270
15567
|
const getAllQuery = `SELECT ${this.columnNames.join(',')} FROM ${this.tableName}`;
|
|
15271
15568
|
return new Promise((resolve, reject) => {
|
|
@@ -15291,6 +15588,10 @@ class AbstractKeyValueDataTable {
|
|
|
15291
15588
|
}, []),
|
|
15292
15589
|
};
|
|
15293
15590
|
}
|
|
15591
|
+
metadataToUpdateOperations(_entries, _segment) {
|
|
15592
|
+
// eslint-disable-next-line @salesforce/lds/no-error-in-production
|
|
15593
|
+
throw new Error(`There is no metadata in the ${this.tableName} table.`);
|
|
15594
|
+
}
|
|
15294
15595
|
mapToDurableEntries(sqliteResult) {
|
|
15295
15596
|
return sqliteResult.rows.reduce((entries, row) => {
|
|
15296
15597
|
const [key, stringifiedData] = row;
|
|
@@ -16630,6 +16931,7 @@ function getRuntime() {
|
|
|
16630
16931
|
const gqlEnv = makeEnvironmentGraphqlAware(baseEnv);
|
|
16631
16932
|
const durableEnv = makeDurable(gqlEnv, {
|
|
16632
16933
|
durableStore: recordDenormingStore,
|
|
16934
|
+
enableDurableMetadataRefresh: ldsMetadataRefreshEnabled.isOpen({ fallback: false }),
|
|
16633
16935
|
});
|
|
16634
16936
|
getIngestRecords = durableEnv.getIngestStagingStoreRecords;
|
|
16635
16937
|
getIngestMetadata = durableEnv.getIngestStagingStoreMetadata;
|
|
@@ -16731,4 +17033,4 @@ register({
|
|
|
16731
17033
|
});
|
|
16732
17034
|
|
|
16733
17035
|
export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
|
|
16734
|
-
// version: 1.
|
|
17036
|
+
// version: 1.235.0-3790decf0
|