@salesforce/lds-runtime-mobile 1.245.0 → 1.246.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 +219 -109
- package/dist/types/priming/NimbusPrimingNetworkAdapter.d.ts +4 -1
- package/dist/types/priming/SqlitePrimingStore.d.ts +5 -0
- package/dist/types/utils/ObjectInfoService.d.ts +13 -18
- package/dist/types/utils/adapters.d.ts +2 -1
- package/package.json +1 -1
- package/sfdc/main.js +219 -109
- package/sfdc/types/priming/NimbusPrimingNetworkAdapter.d.ts +4 -1
- package/sfdc/types/priming/SqlitePrimingStore.d.ts +5 -0
- package/sfdc/types/utils/ObjectInfoService.d.ts +13 -18
- package/sfdc/types/utils/adapters.d.ts +2 -1
package/dist/main.js
CHANGED
|
@@ -16,7 +16,7 @@ import { setupInstrumentation, instrumentAdapter as instrumentAdapter$1, instrum
|
|
|
16
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
|
-
import { RECORD_ID_PREFIX, RECORD_FIELDS_KEY_JUNCTION, isStoreKeyRecordViewEntity, getRecordId18, RECORD_REPRESENTATION_NAME, extractRecordIdFromStoreKey, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, keyBuilderContentDocumentCompositeRepresentation, getResponseCacheKeysContentDocumentCompositeRepresentation, keyBuilderFromTypeContentDocumentCompositeRepresentation, ingestContentDocumentCompositeRepresentation, keyBuilderRecord, RECORD_VIEW_ENTITY_ID_PREFIX, getTypeCacheKeysRecord, keyBuilderFromTypeRecordRepresentation, ingestRecord, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getRecordAdapterFactory, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationTTL, RecordRepresentationVersion, getRecordsAdapterFactory } from '@salesforce/lds-adapters-uiapi';
|
|
19
|
+
import { RECORD_ID_PREFIX, RECORD_FIELDS_KEY_JUNCTION, isStoreKeyRecordViewEntity, getRecordId18, RECORD_REPRESENTATION_NAME, extractRecordIdFromStoreKey, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, keyBuilderContentDocumentCompositeRepresentation, getResponseCacheKeysContentDocumentCompositeRepresentation, keyBuilderFromTypeContentDocumentCompositeRepresentation, ingestContentDocumentCompositeRepresentation, keyBuilderRecord, RECORD_VIEW_ENTITY_ID_PREFIX, getTypeCacheKeysRecord, keyBuilderFromTypeRecordRepresentation, ingestRecord, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getRecordAdapterFactory, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, getObjectInfoDirectoryAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationTTL, RecordRepresentationVersion, keyBuilderObjectInfo, ObjectInfoDirectoryEntryRepresentationType, getRecordsAdapterFactory } from '@salesforce/lds-adapters-uiapi';
|
|
20
20
|
import caseSensitiveUserId from '@salesforce/user/Id';
|
|
21
21
|
import { idleDetector, getInstrumentation } from 'o11y/client';
|
|
22
22
|
import ldsUseShortUrlGate from '@salesforce/gate/lds.useShortUrl';
|
|
@@ -10316,16 +10316,18 @@ function injectFilter(filterNode, idState, parentPath, isParentPolymorphic, obje
|
|
|
10316
10316
|
if (!isIdField) {
|
|
10317
10317
|
let subSelectionNodes = [];
|
|
10318
10318
|
let subFieldsHasId = false;
|
|
10319
|
-
|
|
10320
|
-
|
|
10321
|
-
|
|
10322
|
-
|
|
10323
|
-
|
|
10324
|
-
|
|
10325
|
-
|
|
10326
|
-
|
|
10327
|
-
|
|
10328
|
-
|
|
10319
|
+
if (isSpanning) {
|
|
10320
|
+
filterNode.value.fields.forEach((subFieldNode) => {
|
|
10321
|
+
// Check if the filter field has the 'Id'
|
|
10322
|
+
if (isFieldAnIdField(subFieldNode.name.value, objectInfos[objectInfoName])) {
|
|
10323
|
+
subFieldsHasId = true;
|
|
10324
|
+
updateIDInfo(subFieldNode, idState, draftFunctions);
|
|
10325
|
+
}
|
|
10326
|
+
// try injecting the fields within predicate no matter it has relation or not.
|
|
10327
|
+
let subResults = injectFilter(subFieldNode, idState, curPath, isPolymorphicField, objectInfos, pathToObjectApiNamesMap, draftFunctions, existingFields ? existingFields[0] : undefined);
|
|
10328
|
+
subSelectionNodes = subSelectionNodes.concat(subResults);
|
|
10329
|
+
});
|
|
10330
|
+
}
|
|
10329
10331
|
if (!subFieldsHasId) {
|
|
10330
10332
|
// Check if the query field has the 'Id'
|
|
10331
10333
|
const existingIdsInQuery = existingFields &&
|
|
@@ -10354,6 +10356,7 @@ function injectFilter(filterNode, idState, parentPath, isParentPolymorphic, obje
|
|
|
10354
10356
|
}
|
|
10355
10357
|
//Inject Conditions: 1. Same field does not exist 2. Same fields has different children. 3. Filter spanning field does not have Id. 4. InLineFragment does not have the '__typename' field
|
|
10356
10358
|
if (!existingFields ||
|
|
10359
|
+
existingFields.length === 0 ||
|
|
10357
10360
|
subSelectionNodes.length > 0 ||
|
|
10358
10361
|
(isSpanning && !subFieldsHasId) ||
|
|
10359
10362
|
(isInlineFragment && !isTypeNameExisting)) {
|
|
@@ -13079,7 +13082,7 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
|
|
|
13079
13082
|
// Fulfilled snapshot (this only happens in this code path if
|
|
13080
13083
|
// the error is network error or 504), otherwise we spread over
|
|
13081
13084
|
// the non-eval'ed snapshot (which will be either Fulfilled or Stale)
|
|
13082
|
-
|
|
13085
|
+
const resultSnapshot = nonEvaluatedSnapshot.state === 'Error'
|
|
13083
13086
|
? createLocalEvalSnapshot(gqlResult, seenRecords, recordId, rebuildWithLocalEval)
|
|
13084
13087
|
: {
|
|
13085
13088
|
...nonEvaluatedSnapshot,
|
|
@@ -13088,6 +13091,22 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
|
|
|
13088
13091
|
seenRecords,
|
|
13089
13092
|
rebuildWithLocalEval,
|
|
13090
13093
|
};
|
|
13094
|
+
const { refresh, state } = resultSnapshot;
|
|
13095
|
+
if (state !== 'Error' && refresh) {
|
|
13096
|
+
// after refreshing a graphql snapshot, we want to force a rebuild regardless
|
|
13097
|
+
// of if the call failed or not or if the data changed or not because we want
|
|
13098
|
+
// to make sure any potential new drafts are picked up
|
|
13099
|
+
resultSnapshot.refresh = {
|
|
13100
|
+
...refresh,
|
|
13101
|
+
resolve: (config) => {
|
|
13102
|
+
return refresh.resolve(config).finally(() => {
|
|
13103
|
+
luvio.storePublish(resultSnapshot.recordId, undefined);
|
|
13104
|
+
luvio.storeBroadcast();
|
|
13105
|
+
});
|
|
13106
|
+
},
|
|
13107
|
+
};
|
|
13108
|
+
}
|
|
13109
|
+
return resultSnapshot;
|
|
13091
13110
|
};
|
|
13092
13111
|
}
|
|
13093
13112
|
|
|
@@ -15029,6 +15048,7 @@ function buildInternalAdapters(store, networkAdapter, durableStore, ensureObject
|
|
|
15029
15048
|
const getRecord = getRecordAdapterFactory(luvio);
|
|
15030
15049
|
const getObjectInfo = getObjectInfoAdapterFactory(luvio);
|
|
15031
15050
|
const getObjectInfos = getObjectInfosAdapterFactory(luvio);
|
|
15051
|
+
const getObjectInfoDirectory = getObjectInfoDirectoryAdapterFactory(luvio);
|
|
15032
15052
|
return {
|
|
15033
15053
|
luvio,
|
|
15034
15054
|
durableEnvironment,
|
|
@@ -15036,37 +15056,37 @@ function buildInternalAdapters(store, networkAdapter, durableStore, ensureObject
|
|
|
15036
15056
|
getRecord,
|
|
15037
15057
|
getObjectInfo,
|
|
15038
15058
|
getObjectInfos,
|
|
15059
|
+
getObjectInfoDirectory,
|
|
15039
15060
|
},
|
|
15040
15061
|
};
|
|
15041
15062
|
}
|
|
15042
15063
|
|
|
15043
|
-
const OBJECT_INFO_PREFIX_SEGMENT = 'OBJECT_INFO_PREFIX_SEGMENT';
|
|
15044
15064
|
class ObjectInfoService {
|
|
15045
|
-
constructor(getObjectInfoAdapter, getObjectInfosAdapter, durableStore) {
|
|
15065
|
+
constructor(getObjectInfoAdapter, getObjectInfosAdapter, getObjectInfoDirectoryAdapter, durableStore) {
|
|
15066
|
+
this.getObjectInfoAdapter = getObjectInfoAdapter;
|
|
15067
|
+
this.getObjectInfosAdapter = getObjectInfosAdapter;
|
|
15068
|
+
this.getObjectInfoDirectoryAdapter = getObjectInfoDirectoryAdapter;
|
|
15069
|
+
this.durableStore = durableStore;
|
|
15046
15070
|
this.apiNameForPrefix = async (prefix) => {
|
|
15047
|
-
|
|
15048
|
-
|
|
15049
|
-
if (entries === undefined) {
|
|
15050
|
-
throw missingError;
|
|
15071
|
+
if (this.keyPrefixToApiNameMemoryCache[prefix] !== undefined) {
|
|
15072
|
+
return this.keyPrefixToApiNameMemoryCache[prefix];
|
|
15051
15073
|
}
|
|
15052
|
-
|
|
15053
|
-
|
|
15054
|
-
|
|
15055
|
-
|
|
15056
|
-
return entry.data.apiName;
|
|
15057
|
-
}
|
|
15074
|
+
await this.loadObjectInfoMaps();
|
|
15075
|
+
const apiName = this.keyPrefixToApiNameMemoryCache[prefix];
|
|
15076
|
+
if (apiName === undefined) {
|
|
15077
|
+
throw Error(`ObjectInfo for ${prefix} prefix is not primed into the durable store`);
|
|
15058
15078
|
}
|
|
15059
|
-
|
|
15079
|
+
return apiName;
|
|
15060
15080
|
};
|
|
15061
15081
|
this.ensureObjectInfoCached = async (apiName, entry) => {
|
|
15082
|
+
if (entry !== undefined) {
|
|
15083
|
+
const { keyPrefix, apiName } = entry;
|
|
15084
|
+
return this.updateObjectInfoMapping(keyPrefix, apiName);
|
|
15085
|
+
}
|
|
15062
15086
|
const exists = await this.isObjectInfoInDurableStore(apiName);
|
|
15063
15087
|
if (exists) {
|
|
15064
15088
|
return;
|
|
15065
15089
|
}
|
|
15066
|
-
if (entry !== undefined) {
|
|
15067
|
-
// Since ObjectInfo is provided, no need to fetch the snapshot
|
|
15068
|
-
return this.createObjectInfoMapping(apiName, entry);
|
|
15069
|
-
}
|
|
15070
15090
|
// ObjectInfo is not present in Durable store. Fetch
|
|
15071
15091
|
const snapshot = await this.getObjectInfoAdapter({
|
|
15072
15092
|
objectApiName: apiName,
|
|
@@ -15075,46 +15095,34 @@ class ObjectInfoService {
|
|
|
15075
15095
|
throw Error(`No snapshot found for apiName ${apiName}`);
|
|
15076
15096
|
}
|
|
15077
15097
|
if (snapshot.data !== null && snapshot.data !== undefined) {
|
|
15078
|
-
|
|
15098
|
+
const { keyPrefix, apiName } = snapshot.data;
|
|
15099
|
+
return this.updateObjectInfoMapping(keyPrefix, apiName);
|
|
15079
15100
|
}
|
|
15080
15101
|
};
|
|
15081
|
-
/**
|
|
15082
|
-
* Caches ObjectInfo(ApiName and KeyPrefix) in Durable Store
|
|
15083
|
-
*
|
|
15084
|
-
* @param apiName eg: 'Account'
|
|
15085
|
-
* @param objectInfo Object Info
|
|
15086
|
-
*
|
|
15087
|
-
* @returns Promise
|
|
15088
|
-
*/
|
|
15089
|
-
this.createObjectInfoMapping = (apiName, objectInfo) => {
|
|
15090
|
-
const { keyPrefix } = objectInfo;
|
|
15091
|
-
const entries = {
|
|
15092
|
-
[apiName]: {
|
|
15093
|
-
data: {
|
|
15094
|
-
apiName,
|
|
15095
|
-
keyPrefix,
|
|
15096
|
-
},
|
|
15097
|
-
},
|
|
15098
|
-
};
|
|
15099
|
-
this.objectInfoMemoryCache[apiName] = keyPrefix;
|
|
15100
|
-
return this.durableStore.setEntries(entries, OBJECT_INFO_PREFIX_SEGMENT);
|
|
15101
|
-
};
|
|
15102
15102
|
this.isObjectInfoInDurableStore = async (apiName) => {
|
|
15103
|
-
if (this.
|
|
15103
|
+
if (this.apiNameToKeyPrefixMemoryCache[apiName] !== undefined) {
|
|
15104
15104
|
return Promise.resolve(true);
|
|
15105
15105
|
}
|
|
15106
|
-
|
|
15107
|
-
|
|
15108
|
-
|
|
15106
|
+
await this.loadObjectInfoMaps();
|
|
15107
|
+
return this.apiNameToKeyPrefixMemoryCache[apiName] !== undefined;
|
|
15108
|
+
};
|
|
15109
|
+
this.loadObjectInfoMaps = async () => {
|
|
15110
|
+
const rows = (await this.durableStore.query(`SELECT json_extract(data, '$.apiName') as ApiName, json_extract(data, '$.keyPrefix') as keyPrefix from lds_data where key like '%ObjectInfoRepresentation%'`, [])).rows;
|
|
15111
|
+
for (const row of rows) {
|
|
15112
|
+
const apiName = row[0];
|
|
15113
|
+
const keyPrefix = row[1];
|
|
15114
|
+
this.updateObjectInfoMapping(keyPrefix, apiName);
|
|
15109
15115
|
}
|
|
15110
|
-
this.objectInfoMemoryCache[apiName] = entries[apiName].data.keyPrefix;
|
|
15111
|
-
return true;
|
|
15112
15116
|
};
|
|
15113
|
-
this.
|
|
15114
|
-
|
|
15115
|
-
|
|
15116
|
-
|
|
15117
|
-
|
|
15117
|
+
this.updateObjectInfoMapping = (keyPrefix, apiName) => {
|
|
15118
|
+
this.apiNameToKeyPrefixMemoryCache[apiName] = keyPrefix;
|
|
15119
|
+
if (keyPrefix !== null) {
|
|
15120
|
+
this.keyPrefixToApiNameMemoryCache[keyPrefix] = apiName;
|
|
15121
|
+
}
|
|
15122
|
+
};
|
|
15123
|
+
// Local in-memory cache for apiName to key prefixes
|
|
15124
|
+
this.apiNameToKeyPrefixMemoryCache = create$1(null);
|
|
15125
|
+
this.keyPrefixToApiNameMemoryCache = create$1(null);
|
|
15118
15126
|
}
|
|
15119
15127
|
/**
|
|
15120
15128
|
* Size of return map not necessarily correlated with number of inputs. The
|
|
@@ -15134,10 +15142,20 @@ class ObjectInfoService {
|
|
|
15134
15142
|
for (const result of snapshot.data.results) {
|
|
15135
15143
|
if (result.statusCode === 200) {
|
|
15136
15144
|
objectInfos[result.result.apiName] = result.result;
|
|
15145
|
+
this.updateObjectInfoMapping(result.result.keyPrefix, result.result.apiName);
|
|
15137
15146
|
}
|
|
15138
15147
|
}
|
|
15139
15148
|
return objectInfos;
|
|
15140
15149
|
}
|
|
15150
|
+
async getObjectInfoDirectory() {
|
|
15151
|
+
const snapshot = await this.getObjectInfoDirectoryAdapter({});
|
|
15152
|
+
if (!snapshot ||
|
|
15153
|
+
!snapshot.data ||
|
|
15154
|
+
(snapshot.state !== 'Fulfilled' && snapshot.state !== 'Stale')) {
|
|
15155
|
+
return undefined;
|
|
15156
|
+
}
|
|
15157
|
+
return snapshot.data;
|
|
15158
|
+
}
|
|
15141
15159
|
}
|
|
15142
15160
|
|
|
15143
15161
|
function instrumentGraphQLEval(adapter) {
|
|
@@ -15481,6 +15499,7 @@ class NimbusSqliteStore {
|
|
|
15481
15499
|
...additionalTableMap,
|
|
15482
15500
|
[DefaultDurableSegment]: new LdsDataTable(plugin),
|
|
15483
15501
|
};
|
|
15502
|
+
this.supportsBatchUpdates = plugin.supportsBatchUpdates !== undefined;
|
|
15484
15503
|
}
|
|
15485
15504
|
isEvalSupported() {
|
|
15486
15505
|
return true;
|
|
@@ -15515,16 +15534,15 @@ class NimbusSqliteStore {
|
|
|
15515
15534
|
setMetadata(entries, segment) {
|
|
15516
15535
|
const table = this.getTable(segment);
|
|
15517
15536
|
let operation;
|
|
15518
|
-
if (this.
|
|
15519
|
-
|
|
15537
|
+
if (this.supportsBatchUpdates) {
|
|
15538
|
+
operation = table.metadataToUpdateOperations(entries, segment);
|
|
15539
|
+
}
|
|
15540
|
+
else {
|
|
15520
15541
|
operation = table.entriesToUpsertOperations(entries, segment);
|
|
15521
15542
|
// manually set the context type on the upsert so notifications do not notify rebuilds without
|
|
15522
15543
|
// plugin updates
|
|
15523
15544
|
operation.context.type = 'setMetadata';
|
|
15524
15545
|
}
|
|
15525
|
-
else {
|
|
15526
|
-
operation = table.metadataToUpdateOperations(entries, segment);
|
|
15527
|
-
}
|
|
15528
15546
|
return this.batchOperationAsPromise([operation]);
|
|
15529
15547
|
}
|
|
15530
15548
|
batchOperations(operations) {
|
|
@@ -15535,17 +15553,16 @@ class NimbusSqliteStore {
|
|
|
15535
15553
|
}
|
|
15536
15554
|
else if (cur.type === 'setMetadata') {
|
|
15537
15555
|
const table = this.getTable(cur.segment);
|
|
15538
|
-
if (this.
|
|
15539
|
-
|
|
15556
|
+
if (this.supportsBatchUpdates) {
|
|
15557
|
+
acc.push(table.metadataToUpdateOperations(cur.entries, cur.segment));
|
|
15558
|
+
}
|
|
15559
|
+
else {
|
|
15540
15560
|
const upsert = table.entriesToUpsertOperations(cur.entries, cur.segment);
|
|
15541
15561
|
// manually set the context type on the upsert so notifications do not notify rebuilds without
|
|
15542
15562
|
// plugin updates
|
|
15543
15563
|
upsert.context.type = 'setMetadata';
|
|
15544
15564
|
acc.push(upsert);
|
|
15545
15565
|
}
|
|
15546
|
-
else {
|
|
15547
|
-
acc.push(table.metadataToUpdateOperations(cur.entries, cur.segment));
|
|
15548
|
-
}
|
|
15549
15566
|
}
|
|
15550
15567
|
else {
|
|
15551
15568
|
acc.push(this.idsToDeleteOperation(cur.ids, cur.segment));
|
|
@@ -16721,17 +16738,34 @@ function instrumentPrimingSession(session) {
|
|
|
16721
16738
|
const apiVersion = `v60.0`;
|
|
16722
16739
|
const batchEndPointPath = `/services/data/${apiVersion}/graphql/batch`;
|
|
16723
16740
|
const endPointPath = `/services/data/${apiVersion}/graphql`;
|
|
16741
|
+
const batchObjectInfoEndpoint = `/services/data/${apiVersion}/ui-api/object-info/batch`;
|
|
16742
|
+
const objectInfoDirectoryEndpoint = `/services/data/${apiVersion}/ui-api/object-info`;
|
|
16724
16743
|
class NimbusPrimingNetworkAdapter {
|
|
16744
|
+
sendRequestWithAbort(request, abortController, onResponse, onError) {
|
|
16745
|
+
let listener;
|
|
16746
|
+
const unregisterListener = () => {
|
|
16747
|
+
if (listener) {
|
|
16748
|
+
abortController.removeEventListener(listener);
|
|
16749
|
+
}
|
|
16750
|
+
};
|
|
16751
|
+
return __nimbus.plugins.LdsNetworkAdapter
|
|
16752
|
+
.sendRequest(request, (response) => {
|
|
16753
|
+
unregisterListener();
|
|
16754
|
+
onResponse(response);
|
|
16755
|
+
}, (error) => {
|
|
16756
|
+
unregisterListener();
|
|
16757
|
+
onError(error);
|
|
16758
|
+
})
|
|
16759
|
+
.then((cancellationToken) => {
|
|
16760
|
+
listener = () => {
|
|
16761
|
+
__nimbus.plugins.LdsNetworkAdapter.cancelRequest(cancellationToken);
|
|
16762
|
+
};
|
|
16763
|
+
abortController.addEventListener(listener);
|
|
16764
|
+
});
|
|
16765
|
+
}
|
|
16725
16766
|
postBatchGraphQL(configs, abortController) {
|
|
16726
16767
|
return new Promise((resolve, reject) => {
|
|
16727
|
-
|
|
16728
|
-
const unregisterListener = () => {
|
|
16729
|
-
if (listener) {
|
|
16730
|
-
abortController.removeEventListener(listener);
|
|
16731
|
-
}
|
|
16732
|
-
};
|
|
16733
|
-
__nimbus.plugins.LdsNetworkAdapter
|
|
16734
|
-
.sendRequest({
|
|
16768
|
+
this.sendRequestWithAbort({
|
|
16735
16769
|
method: 'POST',
|
|
16736
16770
|
path: batchEndPointPath,
|
|
16737
16771
|
body: JSON.stringify({
|
|
@@ -16741,8 +16775,7 @@ class NimbusPrimingNetworkAdapter {
|
|
|
16741
16775
|
queryParams: {},
|
|
16742
16776
|
priority: 'background',
|
|
16743
16777
|
observabilityContext: {},
|
|
16744
|
-
}, (response) => {
|
|
16745
|
-
unregisterListener();
|
|
16778
|
+
}, abortController, (response) => {
|
|
16746
16779
|
const { body } = response;
|
|
16747
16780
|
if (body) {
|
|
16748
16781
|
const { results } = JSON.parse(body);
|
|
@@ -16758,27 +16791,13 @@ class NimbusPrimingNetworkAdapter {
|
|
|
16758
16791
|
reject(new Error(`No body returned from ${batchEndPointPath} endpoint`));
|
|
16759
16792
|
}
|
|
16760
16793
|
}, (error) => {
|
|
16761
|
-
unregisterListener();
|
|
16762
16794
|
reject(error);
|
|
16763
|
-
})
|
|
16764
|
-
.then((cancellationToken) => {
|
|
16765
|
-
listener = () => {
|
|
16766
|
-
__nimbus.plugins.LdsNetworkAdapter.cancelRequest(cancellationToken);
|
|
16767
|
-
};
|
|
16768
|
-
abortController.addEventListener(listener);
|
|
16769
16795
|
});
|
|
16770
16796
|
});
|
|
16771
16797
|
}
|
|
16772
16798
|
postGraphQL(query, variables, abortController) {
|
|
16773
16799
|
return new Promise((resolve, reject) => {
|
|
16774
|
-
|
|
16775
|
-
const unregisterListener = () => {
|
|
16776
|
-
if (listener) {
|
|
16777
|
-
abortController.removeEventListener(listener);
|
|
16778
|
-
}
|
|
16779
|
-
};
|
|
16780
|
-
__nimbus.plugins.LdsNetworkAdapter
|
|
16781
|
-
.sendRequest({
|
|
16800
|
+
this.sendRequestWithAbort({
|
|
16782
16801
|
method: 'POST',
|
|
16783
16802
|
path: endPointPath,
|
|
16784
16803
|
body: JSON.stringify({
|
|
@@ -16789,8 +16808,7 @@ class NimbusPrimingNetworkAdapter {
|
|
|
16789
16808
|
queryParams: {},
|
|
16790
16809
|
priority: 'background',
|
|
16791
16810
|
observabilityContext: {},
|
|
16792
|
-
}, (response) => {
|
|
16793
|
-
unregisterListener();
|
|
16811
|
+
}, abortController, (response) => {
|
|
16794
16812
|
const { body } = response;
|
|
16795
16813
|
if (body) {
|
|
16796
16814
|
resolve(JSON.parse(body));
|
|
@@ -16799,14 +16817,64 @@ class NimbusPrimingNetworkAdapter {
|
|
|
16799
16817
|
reject(new Error(`No body returned from ${endPointPath} endpoint`));
|
|
16800
16818
|
}
|
|
16801
16819
|
}, (error) => {
|
|
16802
|
-
unregisterListener();
|
|
16803
16820
|
reject(error);
|
|
16804
|
-
})
|
|
16805
|
-
|
|
16806
|
-
|
|
16807
|
-
|
|
16808
|
-
|
|
16809
|
-
|
|
16821
|
+
});
|
|
16822
|
+
});
|
|
16823
|
+
}
|
|
16824
|
+
getObjectInfoDirectory(abortController) {
|
|
16825
|
+
return new Promise((resolve, reject) => {
|
|
16826
|
+
this.sendRequestWithAbort({
|
|
16827
|
+
method: 'GET',
|
|
16828
|
+
path: objectInfoDirectoryEndpoint,
|
|
16829
|
+
body: null,
|
|
16830
|
+
headers: {},
|
|
16831
|
+
queryParams: {},
|
|
16832
|
+
priority: 'background',
|
|
16833
|
+
observabilityContext: {},
|
|
16834
|
+
}, abortController, (response) => {
|
|
16835
|
+
const { body } = response;
|
|
16836
|
+
if (body) {
|
|
16837
|
+
resolve(JSON.parse(body).objects);
|
|
16838
|
+
}
|
|
16839
|
+
else {
|
|
16840
|
+
reject(new Error(`No body returned from ${endPointPath} endpoint`));
|
|
16841
|
+
}
|
|
16842
|
+
}, (error) => {
|
|
16843
|
+
reject(error);
|
|
16844
|
+
});
|
|
16845
|
+
});
|
|
16846
|
+
}
|
|
16847
|
+
getObjectInfos(apiName, abortController) {
|
|
16848
|
+
return new Promise((resolve, reject) => {
|
|
16849
|
+
const map = new Map();
|
|
16850
|
+
if (apiName.length === 0) {
|
|
16851
|
+
resolve(map);
|
|
16852
|
+
}
|
|
16853
|
+
this.sendRequestWithAbort({
|
|
16854
|
+
method: 'GET',
|
|
16855
|
+
path: `${batchObjectInfoEndpoint}/${apiName.join(',')}`,
|
|
16856
|
+
body: null,
|
|
16857
|
+
headers: {},
|
|
16858
|
+
queryParams: {},
|
|
16859
|
+
priority: 'background',
|
|
16860
|
+
observabilityContext: {},
|
|
16861
|
+
}, abortController, (response) => {
|
|
16862
|
+
const { body } = response;
|
|
16863
|
+
if (body) {
|
|
16864
|
+
const results = JSON.parse(body).results;
|
|
16865
|
+
results.forEach((result) => {
|
|
16866
|
+
// only populate the map if the status code is 200, caller needs to check for missing keys
|
|
16867
|
+
if (result.statusCode === 200) {
|
|
16868
|
+
map.set(result.result.apiName, result.result);
|
|
16869
|
+
}
|
|
16870
|
+
});
|
|
16871
|
+
resolve(map);
|
|
16872
|
+
}
|
|
16873
|
+
else {
|
|
16874
|
+
reject(new Error(`No body returned from ${endPointPath} endpoint`));
|
|
16875
|
+
}
|
|
16876
|
+
}, (error) => {
|
|
16877
|
+
reject(error);
|
|
16810
16878
|
});
|
|
16811
16879
|
});
|
|
16812
16880
|
}
|
|
@@ -16815,6 +16883,10 @@ class NimbusPrimingNetworkAdapter {
|
|
|
16815
16883
|
// ref: https://gnome.pages.gitlab.gnome.org/tracker/docs/developer/limits.html?gi-language=c
|
|
16816
16884
|
const SQLITE_MAX_VARIABLE_NUMBER = 999;
|
|
16817
16885
|
const PARAMS_PER_RECORD = 3;
|
|
16886
|
+
/**
|
|
16887
|
+
* No key builder (or adapter) exists for the object info directory, we need to build the key manually
|
|
16888
|
+
*/
|
|
16889
|
+
const ObjectInfoDirectoryKey = `${UiApiNamespace}::${ObjectInfoDirectoryEntryRepresentationType}:`;
|
|
16818
16890
|
// We need to batch the records to avoid hitting the SQLITE_MAX_VARIABLE_NUMBER limit. Each record has 3 parameters
|
|
16819
16891
|
const BATCH_SIZE = Math.floor(SQLITE_MAX_VARIABLE_NUMBER / PARAMS_PER_RECORD);
|
|
16820
16892
|
class SqlitePrimingStore {
|
|
@@ -16879,6 +16951,44 @@ class SqlitePrimingStore {
|
|
|
16879
16951
|
};
|
|
16880
16952
|
}
|
|
16881
16953
|
}
|
|
16954
|
+
async readObjectInfoDirectory() {
|
|
16955
|
+
const sql = 'SELECT data FROM lds_data WHERE key = ?';
|
|
16956
|
+
const params = [ObjectInfoDirectoryKey];
|
|
16957
|
+
const result = await this.store.query(sql, params);
|
|
16958
|
+
if (result.rows.length === 1) {
|
|
16959
|
+
return JSON.parse(result.rows[0][0]);
|
|
16960
|
+
}
|
|
16961
|
+
return undefined;
|
|
16962
|
+
}
|
|
16963
|
+
async readObjectApiNames() {
|
|
16964
|
+
const sql = 'SELECT key FROM lds_data WHERE key like ?';
|
|
16965
|
+
const params = [`%${ObjectInfoRepresentationType}%`];
|
|
16966
|
+
const result = await this.store.query(sql, params);
|
|
16967
|
+
const apiNames = new Set();
|
|
16968
|
+
result.rows.forEach((row) => {
|
|
16969
|
+
const key = row[0];
|
|
16970
|
+
const parts = key.split(':');
|
|
16971
|
+
apiNames.add(parts[parts.length - 1]);
|
|
16972
|
+
});
|
|
16973
|
+
return apiNames;
|
|
16974
|
+
}
|
|
16975
|
+
writeObjectInfoDirectory(directory) {
|
|
16976
|
+
const sql = 'INSERT or IGNORE into lds_data (key, data) values (?, ?)';
|
|
16977
|
+
const params = [ObjectInfoDirectoryKey, JSON.stringify(directory)];
|
|
16978
|
+
return this.store.query(sql, params).then(() => { });
|
|
16979
|
+
}
|
|
16980
|
+
writeObjectInfos(objectInfos) {
|
|
16981
|
+
const sql = `INSERT or IGNORE into lds_data (key, data) values ${objectInfos
|
|
16982
|
+
.map(() => '(?, ?)')
|
|
16983
|
+
.join(',')};`;
|
|
16984
|
+
const params = [];
|
|
16985
|
+
objectInfos.forEach((objectInfo) => {
|
|
16986
|
+
const key = keyBuilderObjectInfo(this.getLuvio(), { apiName: objectInfo.apiName });
|
|
16987
|
+
params.push(key);
|
|
16988
|
+
params.push(JSON.stringify(objectInfo));
|
|
16989
|
+
});
|
|
16990
|
+
return this.store.query(sql, params).then(() => { });
|
|
16991
|
+
}
|
|
16882
16992
|
}
|
|
16883
16993
|
function batchArray(arr, batchSize = BATCH_SIZE) {
|
|
16884
16994
|
const batches = [];
|
|
@@ -17003,13 +17113,13 @@ function getRuntime() {
|
|
|
17003
17113
|
: {}, () => getIngestMetadataForInternalAdapters !== undefined
|
|
17004
17114
|
? getIngestMetadataForInternalAdapters()
|
|
17005
17115
|
: {});
|
|
17006
|
-
const { adapters: { getObjectInfo, getObjectInfos, getRecord }, durableEnvironment: internalAdapterDurableEnvironment, luvio: internalLuvio, } = buildInternalAdapters(internalAdapterStore, lazyNetworkAdapter, internalAdapterDurableStore, (apiName, objectInfo) => lazyObjectInfoService.ensureObjectInfoCached(apiName, objectInfo));
|
|
17116
|
+
const { adapters: { getObjectInfo, getObjectInfos, getRecord, getObjectInfoDirectory }, durableEnvironment: internalAdapterDurableEnvironment, luvio: internalLuvio, } = buildInternalAdapters(internalAdapterStore, lazyNetworkAdapter, internalAdapterDurableStore, (apiName, objectInfo) => lazyObjectInfoService.ensureObjectInfoCached(apiName, objectInfo));
|
|
17007
17117
|
lazyInternalLuvio = internalLuvio;
|
|
17008
17118
|
getIngestRecordsForInternalAdapters =
|
|
17009
17119
|
internalAdapterDurableEnvironment.getIngestStagingStoreRecords;
|
|
17010
17120
|
getIngestMetadataForInternalAdapters =
|
|
17011
17121
|
internalAdapterDurableEnvironment.getIngestStagingStoreRecords;
|
|
17012
|
-
lazyObjectInfoService = new ObjectInfoService(getObjectInfo, getObjectInfos,
|
|
17122
|
+
lazyObjectInfoService = new ObjectInfoService(getObjectInfo, getObjectInfos, getObjectInfoDirectory, lazyBaseDurableStore);
|
|
17013
17123
|
// creates a durable store that denormalizes scalar fields for records
|
|
17014
17124
|
let getIngestRecords;
|
|
17015
17125
|
let getIngestMetadata;
|
|
@@ -17121,4 +17231,4 @@ register({
|
|
|
17121
17231
|
});
|
|
17122
17232
|
|
|
17123
17233
|
export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
|
|
17124
|
-
// version: 1.
|
|
17234
|
+
// version: 1.246.0-8357100fc
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { PrimingNetworkAdapter } from '@salesforce/lds-priming';
|
|
2
|
-
import type { GraphQLRepresentation, GraphQLInputRepresentation } from '@salesforce/lds-adapters-uiapi';
|
|
2
|
+
import type { GraphQLRepresentation, GraphQLInputRepresentation, ObjectInfoRepresentation, ObjectInfoDirectoryRepresentation } from '@salesforce/lds-adapters-uiapi';
|
|
3
3
|
import type { LdsAbortController } from '@salesforce/lds-utils-adapters';
|
|
4
4
|
export declare class NimbusPrimingNetworkAdapter implements PrimingNetworkAdapter {
|
|
5
|
+
private sendRequestWithAbort;
|
|
5
6
|
postBatchGraphQL(configs: GraphQLInputRepresentation[], abortController: LdsAbortController): Promise<GraphQLRepresentation[]>;
|
|
6
7
|
postGraphQL(query: string, variables: Record<string, any>, abortController: LdsAbortController): Promise<GraphQLRepresentation>;
|
|
8
|
+
getObjectInfoDirectory(abortController: LdsAbortController): Promise<ObjectInfoDirectoryRepresentation>;
|
|
9
|
+
getObjectInfos(apiName: string[], abortController: LdsAbortController): Promise<Map<string, ObjectInfoRepresentation>>;
|
|
7
10
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PrimingStore, RecordWithMetadata, WriteResult } from '@salesforce/lds-priming';
|
|
2
2
|
import type { Luvio } from '@luvio/engine';
|
|
3
|
+
import type { ObjectInfoDirectoryRepresentation, ObjectInfoRepresentation } from '@salesforce/lds-adapters-uiapi';
|
|
3
4
|
import type { SqliteStore } from '@salesforce/lds-store-sql';
|
|
4
5
|
export declare class SqlitePrimingStore implements PrimingStore {
|
|
5
6
|
private readonly getLuvio;
|
|
@@ -8,4 +9,8 @@ export declare class SqlitePrimingStore implements PrimingStore {
|
|
|
8
9
|
readRecords(ids: string[]): Promise<RecordWithMetadata[]>;
|
|
9
10
|
writeRecords(records: RecordWithMetadata[], overwrite: boolean): Promise<WriteResult>;
|
|
10
11
|
private writeBatch;
|
|
12
|
+
readObjectInfoDirectory(): Promise<ObjectInfoDirectoryRepresentation | undefined>;
|
|
13
|
+
readObjectApiNames(): Promise<Set<string>>;
|
|
14
|
+
writeObjectInfoDirectory(directory: ObjectInfoDirectoryRepresentation): Promise<void>;
|
|
15
|
+
writeObjectInfos(objectInfos: ObjectInfoRepresentation[]): Promise<void>;
|
|
11
16
|
}
|
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
import type { Adapter } from '@luvio/engine';
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
export declare const OBJECT_INFO_PREFIX_SEGMENT = "OBJECT_INFO_PREFIX_SEGMENT";
|
|
5
|
-
export interface ObjectInfoIndex {
|
|
6
|
-
apiName: string;
|
|
7
|
-
keyPrefix: string | null;
|
|
8
|
-
}
|
|
2
|
+
import type { ObjectInfoRepresentation, SimplifiedBatchRepresentation, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, getObjectInfoDirectoryAdapterFactory, ObjectInfoDirectoryRepresentation } from '@salesforce/lds-adapters-uiapi';
|
|
3
|
+
import type { SqliteStore } from '@salesforce/lds-store-sql';
|
|
9
4
|
type ObjectInfoAdapterReturn = ReturnType<typeof getObjectInfoAdapterFactory>;
|
|
10
5
|
type ObjectInfosAdapterReturn = ReturnType<typeof getObjectInfosAdapterFactory>;
|
|
6
|
+
type ObjectInfoDirectoryAdapterReturn = ReturnType<typeof getObjectInfoDirectoryAdapterFactory>;
|
|
11
7
|
type ObjectInfoConfig = Parameters<ObjectInfoAdapterReturn>[0];
|
|
12
8
|
type ObjectInfosConfig = Parameters<ObjectInfosAdapterReturn>[0];
|
|
9
|
+
type ObjectInfoDirectoryConfig = Parameters<ObjectInfoDirectoryAdapterReturn>[0];
|
|
13
10
|
export type ObjectInfoMap = {
|
|
14
11
|
[apiName: string]: ObjectInfoRepresentation;
|
|
15
12
|
};
|
|
16
13
|
export declare class ObjectInfoService {
|
|
17
14
|
private getObjectInfoAdapter;
|
|
18
15
|
private getObjectInfosAdapter;
|
|
16
|
+
private getObjectInfoDirectoryAdapter;
|
|
19
17
|
private durableStore;
|
|
20
|
-
|
|
18
|
+
apiNameToKeyPrefixMemoryCache: {
|
|
21
19
|
[apiName: string]: string | null;
|
|
22
20
|
};
|
|
23
|
-
|
|
21
|
+
keyPrefixToApiNameMemoryCache: {
|
|
22
|
+
[keyPrefix: string]: string;
|
|
23
|
+
};
|
|
24
|
+
constructor(getObjectInfoAdapter: Adapter<ObjectInfoConfig, ObjectInfoRepresentation>, getObjectInfosAdapter: Adapter<ObjectInfosConfig, SimplifiedBatchRepresentation>, getObjectInfoDirectoryAdapter: Adapter<ObjectInfoDirectoryConfig, ObjectInfoDirectoryRepresentation>, durableStore: SqliteStore);
|
|
24
25
|
apiNameForPrefix: (prefix: string) => Promise<string>;
|
|
25
26
|
/**
|
|
26
27
|
* Size of return map not necessarily correlated with number of inputs. The
|
|
@@ -28,16 +29,10 @@ export declare class ObjectInfoService {
|
|
|
28
29
|
* from the adapter.
|
|
29
30
|
*/
|
|
30
31
|
getObjectInfos(apiNames: string[]): Promise<ObjectInfoMap>;
|
|
32
|
+
getObjectInfoDirectory(): Promise<ObjectInfoDirectoryRepresentation | undefined>;
|
|
31
33
|
ensureObjectInfoCached: (apiName: string, entry?: ObjectInfoRepresentation) => Promise<void>;
|
|
32
|
-
/**
|
|
33
|
-
* Caches ObjectInfo(ApiName and KeyPrefix) in Durable Store
|
|
34
|
-
*
|
|
35
|
-
* @param apiName eg: 'Account'
|
|
36
|
-
* @param objectInfo Object Info
|
|
37
|
-
*
|
|
38
|
-
* @returns Promise
|
|
39
|
-
*/
|
|
40
|
-
private createObjectInfoMapping;
|
|
41
34
|
private isObjectInfoInDurableStore;
|
|
35
|
+
private loadObjectInfoMaps;
|
|
36
|
+
private updateObjectInfoMapping;
|
|
42
37
|
}
|
|
43
38
|
export {};
|
|
@@ -13,6 +13,7 @@ export declare function buildInternalAdapters(store: InMemoryStore, networkAdapt
|
|
|
13
13
|
adapters: {
|
|
14
14
|
getRecord: import("@luvio/engine").Adapter<import("@salesforce/lds-adapters-uiapi").GetRecordConfig, import("@salesforce/lds-adapters-uiapi").RecordRepresentation>;
|
|
15
15
|
getObjectInfo: import("@luvio/engine").Adapter<import("@salesforce/lds-adapters-uiapi").GetObjectInfoConfig, import("@salesforce/lds-adapters-uiapi").ObjectInfoRepresentation>;
|
|
16
|
-
getObjectInfos: import("@luvio/engine").Adapter<import("@salesforce/lds-adapters-uiapi
|
|
16
|
+
getObjectInfos: import("@luvio/engine").Adapter<import("@salesforce/lds-adapters-uiapi").GetObjectInfosConfig, import("@salesforce/lds-adapters-uiapi").SimplifiedBatchRepresentation>;
|
|
17
|
+
getObjectInfoDirectory: import("@luvio/engine").Adapter<import("@salesforce/lds-adapters-uiapi").GetObjectInfoDirectoryConfig, import("@salesforce/lds-adapters-uiapi").ObjectInfoDirectoryRepresentation>;
|
|
17
18
|
};
|
|
18
19
|
};
|
package/package.json
CHANGED
package/sfdc/main.js
CHANGED
|
@@ -16,7 +16,7 @@ import { setupInstrumentation, instrumentAdapter as instrumentAdapter$1, instrum
|
|
|
16
16
|
import { HttpStatusCode, StoreKeySet, serializeStructuredKey, StringKeyInMemoryStore, Reader, deepFreeze, emitAdapterEvent, createCustomAdapterEventEmitter, StoreKeyMap, isFileReference, Environment, Luvio, InMemoryStore } from 'force/luvioEngine';
|
|
17
17
|
import excludeStaleRecordsGate from '@salesforce/gate/lds.graphqlEvalExcludeStaleRecords';
|
|
18
18
|
import { parseAndVisit, Kind, visit, execute, buildSchema, isObjectType, defaultFieldResolver } from 'force/ldsGraphqlParser';
|
|
19
|
-
import { RECORD_ID_PREFIX, RECORD_FIELDS_KEY_JUNCTION, isStoreKeyRecordViewEntity, getRecordId18, RECORD_REPRESENTATION_NAME, extractRecordIdFromStoreKey, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, keyBuilderContentDocumentCompositeRepresentation, getResponseCacheKeysContentDocumentCompositeRepresentation, keyBuilderFromTypeContentDocumentCompositeRepresentation, ingestContentDocumentCompositeRepresentation, keyBuilderRecord, RECORD_VIEW_ENTITY_ID_PREFIX, getTypeCacheKeysRecord, keyBuilderFromTypeRecordRepresentation, ingestRecord, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getRecordAdapterFactory, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationTTL, RecordRepresentationVersion, getRecordsAdapterFactory } from 'force/ldsAdaptersUiapi';
|
|
19
|
+
import { RECORD_ID_PREFIX, RECORD_FIELDS_KEY_JUNCTION, isStoreKeyRecordViewEntity, getRecordId18, RECORD_REPRESENTATION_NAME, extractRecordIdFromStoreKey, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, keyBuilderContentDocumentCompositeRepresentation, getResponseCacheKeysContentDocumentCompositeRepresentation, keyBuilderFromTypeContentDocumentCompositeRepresentation, ingestContentDocumentCompositeRepresentation, keyBuilderRecord, RECORD_VIEW_ENTITY_ID_PREFIX, getTypeCacheKeysRecord, keyBuilderFromTypeRecordRepresentation, ingestRecord, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getRecordAdapterFactory, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, getObjectInfoDirectoryAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationTTL, RecordRepresentationVersion, keyBuilderObjectInfo, ObjectInfoDirectoryEntryRepresentationType, getRecordsAdapterFactory } from 'force/ldsAdaptersUiapi';
|
|
20
20
|
import caseSensitiveUserId from '@salesforce/user/Id';
|
|
21
21
|
import { idleDetector, getInstrumentation } from 'o11y/client';
|
|
22
22
|
import ldsUseShortUrlGate from '@salesforce/gate/lds.useShortUrl';
|
|
@@ -10316,16 +10316,18 @@ function injectFilter(filterNode, idState, parentPath, isParentPolymorphic, obje
|
|
|
10316
10316
|
if (!isIdField) {
|
|
10317
10317
|
let subSelectionNodes = [];
|
|
10318
10318
|
let subFieldsHasId = false;
|
|
10319
|
-
|
|
10320
|
-
|
|
10321
|
-
|
|
10322
|
-
|
|
10323
|
-
|
|
10324
|
-
|
|
10325
|
-
|
|
10326
|
-
|
|
10327
|
-
|
|
10328
|
-
|
|
10319
|
+
if (isSpanning) {
|
|
10320
|
+
filterNode.value.fields.forEach((subFieldNode) => {
|
|
10321
|
+
// Check if the filter field has the 'Id'
|
|
10322
|
+
if (isFieldAnIdField(subFieldNode.name.value, objectInfos[objectInfoName])) {
|
|
10323
|
+
subFieldsHasId = true;
|
|
10324
|
+
updateIDInfo(subFieldNode, idState, draftFunctions);
|
|
10325
|
+
}
|
|
10326
|
+
// try injecting the fields within predicate no matter it has relation or not.
|
|
10327
|
+
let subResults = injectFilter(subFieldNode, idState, curPath, isPolymorphicField, objectInfos, pathToObjectApiNamesMap, draftFunctions, existingFields ? existingFields[0] : undefined);
|
|
10328
|
+
subSelectionNodes = subSelectionNodes.concat(subResults);
|
|
10329
|
+
});
|
|
10330
|
+
}
|
|
10329
10331
|
if (!subFieldsHasId) {
|
|
10330
10332
|
// Check if the query field has the 'Id'
|
|
10331
10333
|
const existingIdsInQuery = existingFields &&
|
|
@@ -10354,6 +10356,7 @@ function injectFilter(filterNode, idState, parentPath, isParentPolymorphic, obje
|
|
|
10354
10356
|
}
|
|
10355
10357
|
//Inject Conditions: 1. Same field does not exist 2. Same fields has different children. 3. Filter spanning field does not have Id. 4. InLineFragment does not have the '__typename' field
|
|
10356
10358
|
if (!existingFields ||
|
|
10359
|
+
existingFields.length === 0 ||
|
|
10357
10360
|
subSelectionNodes.length > 0 ||
|
|
10358
10361
|
(isSpanning && !subFieldsHasId) ||
|
|
10359
10362
|
(isInlineFragment && !isTypeNameExisting)) {
|
|
@@ -13079,7 +13082,7 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
|
|
|
13079
13082
|
// Fulfilled snapshot (this only happens in this code path if
|
|
13080
13083
|
// the error is network error or 504), otherwise we spread over
|
|
13081
13084
|
// the non-eval'ed snapshot (which will be either Fulfilled or Stale)
|
|
13082
|
-
|
|
13085
|
+
const resultSnapshot = nonEvaluatedSnapshot.state === 'Error'
|
|
13083
13086
|
? createLocalEvalSnapshot(gqlResult, seenRecords, recordId, rebuildWithLocalEval)
|
|
13084
13087
|
: {
|
|
13085
13088
|
...nonEvaluatedSnapshot,
|
|
@@ -13088,6 +13091,22 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
|
|
|
13088
13091
|
seenRecords,
|
|
13089
13092
|
rebuildWithLocalEval,
|
|
13090
13093
|
};
|
|
13094
|
+
const { refresh, state } = resultSnapshot;
|
|
13095
|
+
if (state !== 'Error' && refresh) {
|
|
13096
|
+
// after refreshing a graphql snapshot, we want to force a rebuild regardless
|
|
13097
|
+
// of if the call failed or not or if the data changed or not because we want
|
|
13098
|
+
// to make sure any potential new drafts are picked up
|
|
13099
|
+
resultSnapshot.refresh = {
|
|
13100
|
+
...refresh,
|
|
13101
|
+
resolve: (config) => {
|
|
13102
|
+
return refresh.resolve(config).finally(() => {
|
|
13103
|
+
luvio.storePublish(resultSnapshot.recordId, undefined);
|
|
13104
|
+
luvio.storeBroadcast();
|
|
13105
|
+
});
|
|
13106
|
+
},
|
|
13107
|
+
};
|
|
13108
|
+
}
|
|
13109
|
+
return resultSnapshot;
|
|
13091
13110
|
};
|
|
13092
13111
|
}
|
|
13093
13112
|
|
|
@@ -15029,6 +15048,7 @@ function buildInternalAdapters(store, networkAdapter, durableStore, ensureObject
|
|
|
15029
15048
|
const getRecord = getRecordAdapterFactory(luvio);
|
|
15030
15049
|
const getObjectInfo = getObjectInfoAdapterFactory(luvio);
|
|
15031
15050
|
const getObjectInfos = getObjectInfosAdapterFactory(luvio);
|
|
15051
|
+
const getObjectInfoDirectory = getObjectInfoDirectoryAdapterFactory(luvio);
|
|
15032
15052
|
return {
|
|
15033
15053
|
luvio,
|
|
15034
15054
|
durableEnvironment,
|
|
@@ -15036,37 +15056,37 @@ function buildInternalAdapters(store, networkAdapter, durableStore, ensureObject
|
|
|
15036
15056
|
getRecord,
|
|
15037
15057
|
getObjectInfo,
|
|
15038
15058
|
getObjectInfos,
|
|
15059
|
+
getObjectInfoDirectory,
|
|
15039
15060
|
},
|
|
15040
15061
|
};
|
|
15041
15062
|
}
|
|
15042
15063
|
|
|
15043
|
-
const OBJECT_INFO_PREFIX_SEGMENT = 'OBJECT_INFO_PREFIX_SEGMENT';
|
|
15044
15064
|
class ObjectInfoService {
|
|
15045
|
-
constructor(getObjectInfoAdapter, getObjectInfosAdapter, durableStore) {
|
|
15065
|
+
constructor(getObjectInfoAdapter, getObjectInfosAdapter, getObjectInfoDirectoryAdapter, durableStore) {
|
|
15066
|
+
this.getObjectInfoAdapter = getObjectInfoAdapter;
|
|
15067
|
+
this.getObjectInfosAdapter = getObjectInfosAdapter;
|
|
15068
|
+
this.getObjectInfoDirectoryAdapter = getObjectInfoDirectoryAdapter;
|
|
15069
|
+
this.durableStore = durableStore;
|
|
15046
15070
|
this.apiNameForPrefix = async (prefix) => {
|
|
15047
|
-
|
|
15048
|
-
|
|
15049
|
-
if (entries === undefined) {
|
|
15050
|
-
throw missingError;
|
|
15071
|
+
if (this.keyPrefixToApiNameMemoryCache[prefix] !== undefined) {
|
|
15072
|
+
return this.keyPrefixToApiNameMemoryCache[prefix];
|
|
15051
15073
|
}
|
|
15052
|
-
|
|
15053
|
-
|
|
15054
|
-
|
|
15055
|
-
|
|
15056
|
-
return entry.data.apiName;
|
|
15057
|
-
}
|
|
15074
|
+
await this.loadObjectInfoMaps();
|
|
15075
|
+
const apiName = this.keyPrefixToApiNameMemoryCache[prefix];
|
|
15076
|
+
if (apiName === undefined) {
|
|
15077
|
+
throw Error(`ObjectInfo for ${prefix} prefix is not primed into the durable store`);
|
|
15058
15078
|
}
|
|
15059
|
-
|
|
15079
|
+
return apiName;
|
|
15060
15080
|
};
|
|
15061
15081
|
this.ensureObjectInfoCached = async (apiName, entry) => {
|
|
15082
|
+
if (entry !== undefined) {
|
|
15083
|
+
const { keyPrefix, apiName } = entry;
|
|
15084
|
+
return this.updateObjectInfoMapping(keyPrefix, apiName);
|
|
15085
|
+
}
|
|
15062
15086
|
const exists = await this.isObjectInfoInDurableStore(apiName);
|
|
15063
15087
|
if (exists) {
|
|
15064
15088
|
return;
|
|
15065
15089
|
}
|
|
15066
|
-
if (entry !== undefined) {
|
|
15067
|
-
// Since ObjectInfo is provided, no need to fetch the snapshot
|
|
15068
|
-
return this.createObjectInfoMapping(apiName, entry);
|
|
15069
|
-
}
|
|
15070
15090
|
// ObjectInfo is not present in Durable store. Fetch
|
|
15071
15091
|
const snapshot = await this.getObjectInfoAdapter({
|
|
15072
15092
|
objectApiName: apiName,
|
|
@@ -15075,46 +15095,34 @@ class ObjectInfoService {
|
|
|
15075
15095
|
throw Error(`No snapshot found for apiName ${apiName}`);
|
|
15076
15096
|
}
|
|
15077
15097
|
if (snapshot.data !== null && snapshot.data !== undefined) {
|
|
15078
|
-
|
|
15098
|
+
const { keyPrefix, apiName } = snapshot.data;
|
|
15099
|
+
return this.updateObjectInfoMapping(keyPrefix, apiName);
|
|
15079
15100
|
}
|
|
15080
15101
|
};
|
|
15081
|
-
/**
|
|
15082
|
-
* Caches ObjectInfo(ApiName and KeyPrefix) in Durable Store
|
|
15083
|
-
*
|
|
15084
|
-
* @param apiName eg: 'Account'
|
|
15085
|
-
* @param objectInfo Object Info
|
|
15086
|
-
*
|
|
15087
|
-
* @returns Promise
|
|
15088
|
-
*/
|
|
15089
|
-
this.createObjectInfoMapping = (apiName, objectInfo) => {
|
|
15090
|
-
const { keyPrefix } = objectInfo;
|
|
15091
|
-
const entries = {
|
|
15092
|
-
[apiName]: {
|
|
15093
|
-
data: {
|
|
15094
|
-
apiName,
|
|
15095
|
-
keyPrefix,
|
|
15096
|
-
},
|
|
15097
|
-
},
|
|
15098
|
-
};
|
|
15099
|
-
this.objectInfoMemoryCache[apiName] = keyPrefix;
|
|
15100
|
-
return this.durableStore.setEntries(entries, OBJECT_INFO_PREFIX_SEGMENT);
|
|
15101
|
-
};
|
|
15102
15102
|
this.isObjectInfoInDurableStore = async (apiName) => {
|
|
15103
|
-
if (this.
|
|
15103
|
+
if (this.apiNameToKeyPrefixMemoryCache[apiName] !== undefined) {
|
|
15104
15104
|
return Promise.resolve(true);
|
|
15105
15105
|
}
|
|
15106
|
-
|
|
15107
|
-
|
|
15108
|
-
|
|
15106
|
+
await this.loadObjectInfoMaps();
|
|
15107
|
+
return this.apiNameToKeyPrefixMemoryCache[apiName] !== undefined;
|
|
15108
|
+
};
|
|
15109
|
+
this.loadObjectInfoMaps = async () => {
|
|
15110
|
+
const rows = (await this.durableStore.query(`SELECT json_extract(data, '$.apiName') as ApiName, json_extract(data, '$.keyPrefix') as keyPrefix from lds_data where key like '%ObjectInfoRepresentation%'`, [])).rows;
|
|
15111
|
+
for (const row of rows) {
|
|
15112
|
+
const apiName = row[0];
|
|
15113
|
+
const keyPrefix = row[1];
|
|
15114
|
+
this.updateObjectInfoMapping(keyPrefix, apiName);
|
|
15109
15115
|
}
|
|
15110
|
-
this.objectInfoMemoryCache[apiName] = entries[apiName].data.keyPrefix;
|
|
15111
|
-
return true;
|
|
15112
15116
|
};
|
|
15113
|
-
this.
|
|
15114
|
-
|
|
15115
|
-
|
|
15116
|
-
|
|
15117
|
-
|
|
15117
|
+
this.updateObjectInfoMapping = (keyPrefix, apiName) => {
|
|
15118
|
+
this.apiNameToKeyPrefixMemoryCache[apiName] = keyPrefix;
|
|
15119
|
+
if (keyPrefix !== null) {
|
|
15120
|
+
this.keyPrefixToApiNameMemoryCache[keyPrefix] = apiName;
|
|
15121
|
+
}
|
|
15122
|
+
};
|
|
15123
|
+
// Local in-memory cache for apiName to key prefixes
|
|
15124
|
+
this.apiNameToKeyPrefixMemoryCache = create$1(null);
|
|
15125
|
+
this.keyPrefixToApiNameMemoryCache = create$1(null);
|
|
15118
15126
|
}
|
|
15119
15127
|
/**
|
|
15120
15128
|
* Size of return map not necessarily correlated with number of inputs. The
|
|
@@ -15134,10 +15142,20 @@ class ObjectInfoService {
|
|
|
15134
15142
|
for (const result of snapshot.data.results) {
|
|
15135
15143
|
if (result.statusCode === 200) {
|
|
15136
15144
|
objectInfos[result.result.apiName] = result.result;
|
|
15145
|
+
this.updateObjectInfoMapping(result.result.keyPrefix, result.result.apiName);
|
|
15137
15146
|
}
|
|
15138
15147
|
}
|
|
15139
15148
|
return objectInfos;
|
|
15140
15149
|
}
|
|
15150
|
+
async getObjectInfoDirectory() {
|
|
15151
|
+
const snapshot = await this.getObjectInfoDirectoryAdapter({});
|
|
15152
|
+
if (!snapshot ||
|
|
15153
|
+
!snapshot.data ||
|
|
15154
|
+
(snapshot.state !== 'Fulfilled' && snapshot.state !== 'Stale')) {
|
|
15155
|
+
return undefined;
|
|
15156
|
+
}
|
|
15157
|
+
return snapshot.data;
|
|
15158
|
+
}
|
|
15141
15159
|
}
|
|
15142
15160
|
|
|
15143
15161
|
function instrumentGraphQLEval(adapter) {
|
|
@@ -15481,6 +15499,7 @@ class NimbusSqliteStore {
|
|
|
15481
15499
|
...additionalTableMap,
|
|
15482
15500
|
[DefaultDurableSegment]: new LdsDataTable(plugin),
|
|
15483
15501
|
};
|
|
15502
|
+
this.supportsBatchUpdates = plugin.supportsBatchUpdates !== undefined;
|
|
15484
15503
|
}
|
|
15485
15504
|
isEvalSupported() {
|
|
15486
15505
|
return true;
|
|
@@ -15515,16 +15534,15 @@ class NimbusSqliteStore {
|
|
|
15515
15534
|
setMetadata(entries, segment) {
|
|
15516
15535
|
const table = this.getTable(segment);
|
|
15517
15536
|
let operation;
|
|
15518
|
-
if (this.
|
|
15519
|
-
|
|
15537
|
+
if (this.supportsBatchUpdates) {
|
|
15538
|
+
operation = table.metadataToUpdateOperations(entries, segment);
|
|
15539
|
+
}
|
|
15540
|
+
else {
|
|
15520
15541
|
operation = table.entriesToUpsertOperations(entries, segment);
|
|
15521
15542
|
// manually set the context type on the upsert so notifications do not notify rebuilds without
|
|
15522
15543
|
// plugin updates
|
|
15523
15544
|
operation.context.type = 'setMetadata';
|
|
15524
15545
|
}
|
|
15525
|
-
else {
|
|
15526
|
-
operation = table.metadataToUpdateOperations(entries, segment);
|
|
15527
|
-
}
|
|
15528
15546
|
return this.batchOperationAsPromise([operation]);
|
|
15529
15547
|
}
|
|
15530
15548
|
batchOperations(operations) {
|
|
@@ -15535,17 +15553,16 @@ class NimbusSqliteStore {
|
|
|
15535
15553
|
}
|
|
15536
15554
|
else if (cur.type === 'setMetadata') {
|
|
15537
15555
|
const table = this.getTable(cur.segment);
|
|
15538
|
-
if (this.
|
|
15539
|
-
|
|
15556
|
+
if (this.supportsBatchUpdates) {
|
|
15557
|
+
acc.push(table.metadataToUpdateOperations(cur.entries, cur.segment));
|
|
15558
|
+
}
|
|
15559
|
+
else {
|
|
15540
15560
|
const upsert = table.entriesToUpsertOperations(cur.entries, cur.segment);
|
|
15541
15561
|
// manually set the context type on the upsert so notifications do not notify rebuilds without
|
|
15542
15562
|
// plugin updates
|
|
15543
15563
|
upsert.context.type = 'setMetadata';
|
|
15544
15564
|
acc.push(upsert);
|
|
15545
15565
|
}
|
|
15546
|
-
else {
|
|
15547
|
-
acc.push(table.metadataToUpdateOperations(cur.entries, cur.segment));
|
|
15548
|
-
}
|
|
15549
15566
|
}
|
|
15550
15567
|
else {
|
|
15551
15568
|
acc.push(this.idsToDeleteOperation(cur.ids, cur.segment));
|
|
@@ -16721,17 +16738,34 @@ function instrumentPrimingSession(session) {
|
|
|
16721
16738
|
const apiVersion = `v60.0`;
|
|
16722
16739
|
const batchEndPointPath = `/services/data/${apiVersion}/graphql/batch`;
|
|
16723
16740
|
const endPointPath = `/services/data/${apiVersion}/graphql`;
|
|
16741
|
+
const batchObjectInfoEndpoint = `/services/data/${apiVersion}/ui-api/object-info/batch`;
|
|
16742
|
+
const objectInfoDirectoryEndpoint = `/services/data/${apiVersion}/ui-api/object-info`;
|
|
16724
16743
|
class NimbusPrimingNetworkAdapter {
|
|
16744
|
+
sendRequestWithAbort(request, abortController, onResponse, onError) {
|
|
16745
|
+
let listener;
|
|
16746
|
+
const unregisterListener = () => {
|
|
16747
|
+
if (listener) {
|
|
16748
|
+
abortController.removeEventListener(listener);
|
|
16749
|
+
}
|
|
16750
|
+
};
|
|
16751
|
+
return __nimbus.plugins.LdsNetworkAdapter
|
|
16752
|
+
.sendRequest(request, (response) => {
|
|
16753
|
+
unregisterListener();
|
|
16754
|
+
onResponse(response);
|
|
16755
|
+
}, (error) => {
|
|
16756
|
+
unregisterListener();
|
|
16757
|
+
onError(error);
|
|
16758
|
+
})
|
|
16759
|
+
.then((cancellationToken) => {
|
|
16760
|
+
listener = () => {
|
|
16761
|
+
__nimbus.plugins.LdsNetworkAdapter.cancelRequest(cancellationToken);
|
|
16762
|
+
};
|
|
16763
|
+
abortController.addEventListener(listener);
|
|
16764
|
+
});
|
|
16765
|
+
}
|
|
16725
16766
|
postBatchGraphQL(configs, abortController) {
|
|
16726
16767
|
return new Promise((resolve, reject) => {
|
|
16727
|
-
|
|
16728
|
-
const unregisterListener = () => {
|
|
16729
|
-
if (listener) {
|
|
16730
|
-
abortController.removeEventListener(listener);
|
|
16731
|
-
}
|
|
16732
|
-
};
|
|
16733
|
-
__nimbus.plugins.LdsNetworkAdapter
|
|
16734
|
-
.sendRequest({
|
|
16768
|
+
this.sendRequestWithAbort({
|
|
16735
16769
|
method: 'POST',
|
|
16736
16770
|
path: batchEndPointPath,
|
|
16737
16771
|
body: JSON.stringify({
|
|
@@ -16741,8 +16775,7 @@ class NimbusPrimingNetworkAdapter {
|
|
|
16741
16775
|
queryParams: {},
|
|
16742
16776
|
priority: 'background',
|
|
16743
16777
|
observabilityContext: {},
|
|
16744
|
-
}, (response) => {
|
|
16745
|
-
unregisterListener();
|
|
16778
|
+
}, abortController, (response) => {
|
|
16746
16779
|
const { body } = response;
|
|
16747
16780
|
if (body) {
|
|
16748
16781
|
const { results } = JSON.parse(body);
|
|
@@ -16758,27 +16791,13 @@ class NimbusPrimingNetworkAdapter {
|
|
|
16758
16791
|
reject(new Error(`No body returned from ${batchEndPointPath} endpoint`));
|
|
16759
16792
|
}
|
|
16760
16793
|
}, (error) => {
|
|
16761
|
-
unregisterListener();
|
|
16762
16794
|
reject(error);
|
|
16763
|
-
})
|
|
16764
|
-
.then((cancellationToken) => {
|
|
16765
|
-
listener = () => {
|
|
16766
|
-
__nimbus.plugins.LdsNetworkAdapter.cancelRequest(cancellationToken);
|
|
16767
|
-
};
|
|
16768
|
-
abortController.addEventListener(listener);
|
|
16769
16795
|
});
|
|
16770
16796
|
});
|
|
16771
16797
|
}
|
|
16772
16798
|
postGraphQL(query, variables, abortController) {
|
|
16773
16799
|
return new Promise((resolve, reject) => {
|
|
16774
|
-
|
|
16775
|
-
const unregisterListener = () => {
|
|
16776
|
-
if (listener) {
|
|
16777
|
-
abortController.removeEventListener(listener);
|
|
16778
|
-
}
|
|
16779
|
-
};
|
|
16780
|
-
__nimbus.plugins.LdsNetworkAdapter
|
|
16781
|
-
.sendRequest({
|
|
16800
|
+
this.sendRequestWithAbort({
|
|
16782
16801
|
method: 'POST',
|
|
16783
16802
|
path: endPointPath,
|
|
16784
16803
|
body: JSON.stringify({
|
|
@@ -16789,8 +16808,7 @@ class NimbusPrimingNetworkAdapter {
|
|
|
16789
16808
|
queryParams: {},
|
|
16790
16809
|
priority: 'background',
|
|
16791
16810
|
observabilityContext: {},
|
|
16792
|
-
}, (response) => {
|
|
16793
|
-
unregisterListener();
|
|
16811
|
+
}, abortController, (response) => {
|
|
16794
16812
|
const { body } = response;
|
|
16795
16813
|
if (body) {
|
|
16796
16814
|
resolve(JSON.parse(body));
|
|
@@ -16799,14 +16817,64 @@ class NimbusPrimingNetworkAdapter {
|
|
|
16799
16817
|
reject(new Error(`No body returned from ${endPointPath} endpoint`));
|
|
16800
16818
|
}
|
|
16801
16819
|
}, (error) => {
|
|
16802
|
-
unregisterListener();
|
|
16803
16820
|
reject(error);
|
|
16804
|
-
})
|
|
16805
|
-
|
|
16806
|
-
|
|
16807
|
-
|
|
16808
|
-
|
|
16809
|
-
|
|
16821
|
+
});
|
|
16822
|
+
});
|
|
16823
|
+
}
|
|
16824
|
+
getObjectInfoDirectory(abortController) {
|
|
16825
|
+
return new Promise((resolve, reject) => {
|
|
16826
|
+
this.sendRequestWithAbort({
|
|
16827
|
+
method: 'GET',
|
|
16828
|
+
path: objectInfoDirectoryEndpoint,
|
|
16829
|
+
body: null,
|
|
16830
|
+
headers: {},
|
|
16831
|
+
queryParams: {},
|
|
16832
|
+
priority: 'background',
|
|
16833
|
+
observabilityContext: {},
|
|
16834
|
+
}, abortController, (response) => {
|
|
16835
|
+
const { body } = response;
|
|
16836
|
+
if (body) {
|
|
16837
|
+
resolve(JSON.parse(body).objects);
|
|
16838
|
+
}
|
|
16839
|
+
else {
|
|
16840
|
+
reject(new Error(`No body returned from ${endPointPath} endpoint`));
|
|
16841
|
+
}
|
|
16842
|
+
}, (error) => {
|
|
16843
|
+
reject(error);
|
|
16844
|
+
});
|
|
16845
|
+
});
|
|
16846
|
+
}
|
|
16847
|
+
getObjectInfos(apiName, abortController) {
|
|
16848
|
+
return new Promise((resolve, reject) => {
|
|
16849
|
+
const map = new Map();
|
|
16850
|
+
if (apiName.length === 0) {
|
|
16851
|
+
resolve(map);
|
|
16852
|
+
}
|
|
16853
|
+
this.sendRequestWithAbort({
|
|
16854
|
+
method: 'GET',
|
|
16855
|
+
path: `${batchObjectInfoEndpoint}/${apiName.join(',')}`,
|
|
16856
|
+
body: null,
|
|
16857
|
+
headers: {},
|
|
16858
|
+
queryParams: {},
|
|
16859
|
+
priority: 'background',
|
|
16860
|
+
observabilityContext: {},
|
|
16861
|
+
}, abortController, (response) => {
|
|
16862
|
+
const { body } = response;
|
|
16863
|
+
if (body) {
|
|
16864
|
+
const results = JSON.parse(body).results;
|
|
16865
|
+
results.forEach((result) => {
|
|
16866
|
+
// only populate the map if the status code is 200, caller needs to check for missing keys
|
|
16867
|
+
if (result.statusCode === 200) {
|
|
16868
|
+
map.set(result.result.apiName, result.result);
|
|
16869
|
+
}
|
|
16870
|
+
});
|
|
16871
|
+
resolve(map);
|
|
16872
|
+
}
|
|
16873
|
+
else {
|
|
16874
|
+
reject(new Error(`No body returned from ${endPointPath} endpoint`));
|
|
16875
|
+
}
|
|
16876
|
+
}, (error) => {
|
|
16877
|
+
reject(error);
|
|
16810
16878
|
});
|
|
16811
16879
|
});
|
|
16812
16880
|
}
|
|
@@ -16815,6 +16883,10 @@ class NimbusPrimingNetworkAdapter {
|
|
|
16815
16883
|
// ref: https://gnome.pages.gitlab.gnome.org/tracker/docs/developer/limits.html?gi-language=c
|
|
16816
16884
|
const SQLITE_MAX_VARIABLE_NUMBER = 999;
|
|
16817
16885
|
const PARAMS_PER_RECORD = 3;
|
|
16886
|
+
/**
|
|
16887
|
+
* No key builder (or adapter) exists for the object info directory, we need to build the key manually
|
|
16888
|
+
*/
|
|
16889
|
+
const ObjectInfoDirectoryKey = `${UiApiNamespace}::${ObjectInfoDirectoryEntryRepresentationType}:`;
|
|
16818
16890
|
// We need to batch the records to avoid hitting the SQLITE_MAX_VARIABLE_NUMBER limit. Each record has 3 parameters
|
|
16819
16891
|
const BATCH_SIZE = Math.floor(SQLITE_MAX_VARIABLE_NUMBER / PARAMS_PER_RECORD);
|
|
16820
16892
|
class SqlitePrimingStore {
|
|
@@ -16879,6 +16951,44 @@ class SqlitePrimingStore {
|
|
|
16879
16951
|
};
|
|
16880
16952
|
}
|
|
16881
16953
|
}
|
|
16954
|
+
async readObjectInfoDirectory() {
|
|
16955
|
+
const sql = 'SELECT data FROM lds_data WHERE key = ?';
|
|
16956
|
+
const params = [ObjectInfoDirectoryKey];
|
|
16957
|
+
const result = await this.store.query(sql, params);
|
|
16958
|
+
if (result.rows.length === 1) {
|
|
16959
|
+
return JSON.parse(result.rows[0][0]);
|
|
16960
|
+
}
|
|
16961
|
+
return undefined;
|
|
16962
|
+
}
|
|
16963
|
+
async readObjectApiNames() {
|
|
16964
|
+
const sql = 'SELECT key FROM lds_data WHERE key like ?';
|
|
16965
|
+
const params = [`%${ObjectInfoRepresentationType}%`];
|
|
16966
|
+
const result = await this.store.query(sql, params);
|
|
16967
|
+
const apiNames = new Set();
|
|
16968
|
+
result.rows.forEach((row) => {
|
|
16969
|
+
const key = row[0];
|
|
16970
|
+
const parts = key.split(':');
|
|
16971
|
+
apiNames.add(parts[parts.length - 1]);
|
|
16972
|
+
});
|
|
16973
|
+
return apiNames;
|
|
16974
|
+
}
|
|
16975
|
+
writeObjectInfoDirectory(directory) {
|
|
16976
|
+
const sql = 'INSERT or IGNORE into lds_data (key, data) values (?, ?)';
|
|
16977
|
+
const params = [ObjectInfoDirectoryKey, JSON.stringify(directory)];
|
|
16978
|
+
return this.store.query(sql, params).then(() => { });
|
|
16979
|
+
}
|
|
16980
|
+
writeObjectInfos(objectInfos) {
|
|
16981
|
+
const sql = `INSERT or IGNORE into lds_data (key, data) values ${objectInfos
|
|
16982
|
+
.map(() => '(?, ?)')
|
|
16983
|
+
.join(',')};`;
|
|
16984
|
+
const params = [];
|
|
16985
|
+
objectInfos.forEach((objectInfo) => {
|
|
16986
|
+
const key = keyBuilderObjectInfo(this.getLuvio(), { apiName: objectInfo.apiName });
|
|
16987
|
+
params.push(key);
|
|
16988
|
+
params.push(JSON.stringify(objectInfo));
|
|
16989
|
+
});
|
|
16990
|
+
return this.store.query(sql, params).then(() => { });
|
|
16991
|
+
}
|
|
16882
16992
|
}
|
|
16883
16993
|
function batchArray(arr, batchSize = BATCH_SIZE) {
|
|
16884
16994
|
const batches = [];
|
|
@@ -17003,13 +17113,13 @@ function getRuntime() {
|
|
|
17003
17113
|
: {}, () => getIngestMetadataForInternalAdapters !== undefined
|
|
17004
17114
|
? getIngestMetadataForInternalAdapters()
|
|
17005
17115
|
: {});
|
|
17006
|
-
const { adapters: { getObjectInfo, getObjectInfos, getRecord }, durableEnvironment: internalAdapterDurableEnvironment, luvio: internalLuvio, } = buildInternalAdapters(internalAdapterStore, lazyNetworkAdapter, internalAdapterDurableStore, (apiName, objectInfo) => lazyObjectInfoService.ensureObjectInfoCached(apiName, objectInfo));
|
|
17116
|
+
const { adapters: { getObjectInfo, getObjectInfos, getRecord, getObjectInfoDirectory }, durableEnvironment: internalAdapterDurableEnvironment, luvio: internalLuvio, } = buildInternalAdapters(internalAdapterStore, lazyNetworkAdapter, internalAdapterDurableStore, (apiName, objectInfo) => lazyObjectInfoService.ensureObjectInfoCached(apiName, objectInfo));
|
|
17007
17117
|
lazyInternalLuvio = internalLuvio;
|
|
17008
17118
|
getIngestRecordsForInternalAdapters =
|
|
17009
17119
|
internalAdapterDurableEnvironment.getIngestStagingStoreRecords;
|
|
17010
17120
|
getIngestMetadataForInternalAdapters =
|
|
17011
17121
|
internalAdapterDurableEnvironment.getIngestStagingStoreRecords;
|
|
17012
|
-
lazyObjectInfoService = new ObjectInfoService(getObjectInfo, getObjectInfos,
|
|
17122
|
+
lazyObjectInfoService = new ObjectInfoService(getObjectInfo, getObjectInfos, getObjectInfoDirectory, lazyBaseDurableStore);
|
|
17013
17123
|
// creates a durable store that denormalizes scalar fields for records
|
|
17014
17124
|
let getIngestRecords;
|
|
17015
17125
|
let getIngestMetadata;
|
|
@@ -17121,4 +17231,4 @@ register({
|
|
|
17121
17231
|
});
|
|
17122
17232
|
|
|
17123
17233
|
export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
|
|
17124
|
-
// version: 1.
|
|
17234
|
+
// version: 1.246.0-8357100fc
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { PrimingNetworkAdapter } from '@salesforce/lds-priming';
|
|
2
|
-
import type { GraphQLRepresentation, GraphQLInputRepresentation } from '@salesforce/lds-adapters-uiapi';
|
|
2
|
+
import type { GraphQLRepresentation, GraphQLInputRepresentation, ObjectInfoRepresentation, ObjectInfoDirectoryRepresentation } from '@salesforce/lds-adapters-uiapi';
|
|
3
3
|
import type { LdsAbortController } from '@salesforce/lds-utils-adapters';
|
|
4
4
|
export declare class NimbusPrimingNetworkAdapter implements PrimingNetworkAdapter {
|
|
5
|
+
private sendRequestWithAbort;
|
|
5
6
|
postBatchGraphQL(configs: GraphQLInputRepresentation[], abortController: LdsAbortController): Promise<GraphQLRepresentation[]>;
|
|
6
7
|
postGraphQL(query: string, variables: Record<string, any>, abortController: LdsAbortController): Promise<GraphQLRepresentation>;
|
|
8
|
+
getObjectInfoDirectory(abortController: LdsAbortController): Promise<ObjectInfoDirectoryRepresentation>;
|
|
9
|
+
getObjectInfos(apiName: string[], abortController: LdsAbortController): Promise<Map<string, ObjectInfoRepresentation>>;
|
|
7
10
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PrimingStore, RecordWithMetadata, WriteResult } from '@salesforce/lds-priming';
|
|
2
2
|
import type { Luvio } from '@luvio/engine';
|
|
3
|
+
import type { ObjectInfoDirectoryRepresentation, ObjectInfoRepresentation } from '@salesforce/lds-adapters-uiapi';
|
|
3
4
|
import type { SqliteStore } from '@salesforce/lds-store-sql';
|
|
4
5
|
export declare class SqlitePrimingStore implements PrimingStore {
|
|
5
6
|
private readonly getLuvio;
|
|
@@ -8,4 +9,8 @@ export declare class SqlitePrimingStore implements PrimingStore {
|
|
|
8
9
|
readRecords(ids: string[]): Promise<RecordWithMetadata[]>;
|
|
9
10
|
writeRecords(records: RecordWithMetadata[], overwrite: boolean): Promise<WriteResult>;
|
|
10
11
|
private writeBatch;
|
|
12
|
+
readObjectInfoDirectory(): Promise<ObjectInfoDirectoryRepresentation | undefined>;
|
|
13
|
+
readObjectApiNames(): Promise<Set<string>>;
|
|
14
|
+
writeObjectInfoDirectory(directory: ObjectInfoDirectoryRepresentation): Promise<void>;
|
|
15
|
+
writeObjectInfos(objectInfos: ObjectInfoRepresentation[]): Promise<void>;
|
|
11
16
|
}
|
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
import type { Adapter } from '@luvio/engine';
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
export declare const OBJECT_INFO_PREFIX_SEGMENT = "OBJECT_INFO_PREFIX_SEGMENT";
|
|
5
|
-
export interface ObjectInfoIndex {
|
|
6
|
-
apiName: string;
|
|
7
|
-
keyPrefix: string | null;
|
|
8
|
-
}
|
|
2
|
+
import type { ObjectInfoRepresentation, SimplifiedBatchRepresentation, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, getObjectInfoDirectoryAdapterFactory, ObjectInfoDirectoryRepresentation } from '@salesforce/lds-adapters-uiapi';
|
|
3
|
+
import type { SqliteStore } from '@salesforce/lds-store-sql';
|
|
9
4
|
type ObjectInfoAdapterReturn = ReturnType<typeof getObjectInfoAdapterFactory>;
|
|
10
5
|
type ObjectInfosAdapterReturn = ReturnType<typeof getObjectInfosAdapterFactory>;
|
|
6
|
+
type ObjectInfoDirectoryAdapterReturn = ReturnType<typeof getObjectInfoDirectoryAdapterFactory>;
|
|
11
7
|
type ObjectInfoConfig = Parameters<ObjectInfoAdapterReturn>[0];
|
|
12
8
|
type ObjectInfosConfig = Parameters<ObjectInfosAdapterReturn>[0];
|
|
9
|
+
type ObjectInfoDirectoryConfig = Parameters<ObjectInfoDirectoryAdapterReturn>[0];
|
|
13
10
|
export type ObjectInfoMap = {
|
|
14
11
|
[apiName: string]: ObjectInfoRepresentation;
|
|
15
12
|
};
|
|
16
13
|
export declare class ObjectInfoService {
|
|
17
14
|
private getObjectInfoAdapter;
|
|
18
15
|
private getObjectInfosAdapter;
|
|
16
|
+
private getObjectInfoDirectoryAdapter;
|
|
19
17
|
private durableStore;
|
|
20
|
-
|
|
18
|
+
apiNameToKeyPrefixMemoryCache: {
|
|
21
19
|
[apiName: string]: string | null;
|
|
22
20
|
};
|
|
23
|
-
|
|
21
|
+
keyPrefixToApiNameMemoryCache: {
|
|
22
|
+
[keyPrefix: string]: string;
|
|
23
|
+
};
|
|
24
|
+
constructor(getObjectInfoAdapter: Adapter<ObjectInfoConfig, ObjectInfoRepresentation>, getObjectInfosAdapter: Adapter<ObjectInfosConfig, SimplifiedBatchRepresentation>, getObjectInfoDirectoryAdapter: Adapter<ObjectInfoDirectoryConfig, ObjectInfoDirectoryRepresentation>, durableStore: SqliteStore);
|
|
24
25
|
apiNameForPrefix: (prefix: string) => Promise<string>;
|
|
25
26
|
/**
|
|
26
27
|
* Size of return map not necessarily correlated with number of inputs. The
|
|
@@ -28,16 +29,10 @@ export declare class ObjectInfoService {
|
|
|
28
29
|
* from the adapter.
|
|
29
30
|
*/
|
|
30
31
|
getObjectInfos(apiNames: string[]): Promise<ObjectInfoMap>;
|
|
32
|
+
getObjectInfoDirectory(): Promise<ObjectInfoDirectoryRepresentation | undefined>;
|
|
31
33
|
ensureObjectInfoCached: (apiName: string, entry?: ObjectInfoRepresentation) => Promise<void>;
|
|
32
|
-
/**
|
|
33
|
-
* Caches ObjectInfo(ApiName and KeyPrefix) in Durable Store
|
|
34
|
-
*
|
|
35
|
-
* @param apiName eg: 'Account'
|
|
36
|
-
* @param objectInfo Object Info
|
|
37
|
-
*
|
|
38
|
-
* @returns Promise
|
|
39
|
-
*/
|
|
40
|
-
private createObjectInfoMapping;
|
|
41
34
|
private isObjectInfoInDurableStore;
|
|
35
|
+
private loadObjectInfoMaps;
|
|
36
|
+
private updateObjectInfoMapping;
|
|
42
37
|
}
|
|
43
38
|
export {};
|
|
@@ -13,6 +13,7 @@ export declare function buildInternalAdapters(store: InMemoryStore, networkAdapt
|
|
|
13
13
|
adapters: {
|
|
14
14
|
getRecord: import("@luvio/engine").Adapter<import("@salesforce/lds-adapters-uiapi").GetRecordConfig, import("@salesforce/lds-adapters-uiapi").RecordRepresentation>;
|
|
15
15
|
getObjectInfo: import("@luvio/engine").Adapter<import("@salesforce/lds-adapters-uiapi").GetObjectInfoConfig, import("@salesforce/lds-adapters-uiapi").ObjectInfoRepresentation>;
|
|
16
|
-
getObjectInfos: import("@luvio/engine").Adapter<import("@salesforce/lds-adapters-uiapi
|
|
16
|
+
getObjectInfos: import("@luvio/engine").Adapter<import("@salesforce/lds-adapters-uiapi").GetObjectInfosConfig, import("@salesforce/lds-adapters-uiapi").SimplifiedBatchRepresentation>;
|
|
17
|
+
getObjectInfoDirectory: import("@luvio/engine").Adapter<import("@salesforce/lds-adapters-uiapi").GetObjectInfoDirectoryConfig, import("@salesforce/lds-adapters-uiapi").ObjectInfoDirectoryRepresentation>;
|
|
17
18
|
};
|
|
18
19
|
};
|