@salesforce/lds-runtime-mobile 1.244.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 +247 -130
- package/dist/types/priming/NimbusPrimingNetworkAdapter.d.ts +4 -1
- package/dist/types/priming/SqlitePrimingStore.d.ts +5 -0
- package/dist/types/runtime.d.ts +2 -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 +247 -130
- package/sfdc/types/priming/NimbusPrimingNetworkAdapter.d.ts +4 -1
- package/sfdc/types/priming/SqlitePrimingStore.d.ts +5 -0
- package/sfdc/types/runtime.d.ts +2 -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)) {
|
|
@@ -12481,30 +12484,36 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
|
|
|
12481
12484
|
const operationsWithDenormedRecords = [];
|
|
12482
12485
|
for (let i = 0, len = operations.length; i < len; i++) {
|
|
12483
12486
|
const operation = operations[i];
|
|
12484
|
-
if (
|
|
12485
|
-
|
|
12486
|
-
|
|
12487
|
-
if (
|
|
12488
|
-
|
|
12489
|
-
|
|
12490
|
-
|
|
12487
|
+
if (operation.type === 'setMetadata') {
|
|
12488
|
+
// if setMetadata also contains entry data then it needs to be denormalized.
|
|
12489
|
+
const keys$1 = keys$3(operation.entries);
|
|
12490
|
+
if (keys$1.length > 0) {
|
|
12491
|
+
const firstKey = keys$1[0];
|
|
12492
|
+
// casted to any to check if data exists
|
|
12493
|
+
const firstEntry = operation.entries[firstKey];
|
|
12494
|
+
// it is not possible for setMetadata to contain entries with both data and no data in the same operation.
|
|
12495
|
+
// this is determined by the plugin supporting update batch calls before it gets to this HOF.
|
|
12496
|
+
// so we only need to check one entry to confirm this for performance
|
|
12497
|
+
if (firstEntry.data !== undefined) {
|
|
12498
|
+
operationsWithDenormedRecords.push({
|
|
12499
|
+
...operation,
|
|
12500
|
+
entries: denormalizeEntries(operation.entries),
|
|
12501
|
+
});
|
|
12502
|
+
}
|
|
12503
|
+
else {
|
|
12504
|
+
operationsWithDenormedRecords.push(operation);
|
|
12505
|
+
}
|
|
12491
12506
|
}
|
|
12492
|
-
|
|
12493
|
-
...operation,
|
|
12494
|
-
entries: denormalizeEntries(operation.entries),
|
|
12495
|
-
});
|
|
12507
|
+
continue;
|
|
12496
12508
|
}
|
|
12497
|
-
|
|
12498
|
-
|
|
12499
|
-
|
|
12500
|
-
operationsWithDenormedRecords.push(operation);
|
|
12501
|
-
continue;
|
|
12502
|
-
}
|
|
12503
|
-
operationsWithDenormedRecords.push({
|
|
12504
|
-
...operation,
|
|
12505
|
-
entries: denormalizeEntries(operation.entries),
|
|
12506
|
-
});
|
|
12509
|
+
if (operation.segment !== DefaultDurableSegment || operation.type === 'evictEntries') {
|
|
12510
|
+
operationsWithDenormedRecords.push(operation);
|
|
12511
|
+
continue;
|
|
12507
12512
|
}
|
|
12513
|
+
operationsWithDenormedRecords.push({
|
|
12514
|
+
...operation,
|
|
12515
|
+
entries: denormalizeEntries(operation.entries),
|
|
12516
|
+
});
|
|
12508
12517
|
}
|
|
12509
12518
|
return durableStore.batchOperations(operationsWithDenormedRecords);
|
|
12510
12519
|
};
|
|
@@ -13073,7 +13082,7 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
|
|
|
13073
13082
|
// Fulfilled snapshot (this only happens in this code path if
|
|
13074
13083
|
// the error is network error or 504), otherwise we spread over
|
|
13075
13084
|
// the non-eval'ed snapshot (which will be either Fulfilled or Stale)
|
|
13076
|
-
|
|
13085
|
+
const resultSnapshot = nonEvaluatedSnapshot.state === 'Error'
|
|
13077
13086
|
? createLocalEvalSnapshot(gqlResult, seenRecords, recordId, rebuildWithLocalEval)
|
|
13078
13087
|
: {
|
|
13079
13088
|
...nonEvaluatedSnapshot,
|
|
@@ -13082,6 +13091,22 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
|
|
|
13082
13091
|
seenRecords,
|
|
13083
13092
|
rebuildWithLocalEval,
|
|
13084
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;
|
|
13085
13110
|
};
|
|
13086
13111
|
}
|
|
13087
13112
|
|
|
@@ -15023,6 +15048,7 @@ function buildInternalAdapters(store, networkAdapter, durableStore, ensureObject
|
|
|
15023
15048
|
const getRecord = getRecordAdapterFactory(luvio);
|
|
15024
15049
|
const getObjectInfo = getObjectInfoAdapterFactory(luvio);
|
|
15025
15050
|
const getObjectInfos = getObjectInfosAdapterFactory(luvio);
|
|
15051
|
+
const getObjectInfoDirectory = getObjectInfoDirectoryAdapterFactory(luvio);
|
|
15026
15052
|
return {
|
|
15027
15053
|
luvio,
|
|
15028
15054
|
durableEnvironment,
|
|
@@ -15030,37 +15056,37 @@ function buildInternalAdapters(store, networkAdapter, durableStore, ensureObject
|
|
|
15030
15056
|
getRecord,
|
|
15031
15057
|
getObjectInfo,
|
|
15032
15058
|
getObjectInfos,
|
|
15059
|
+
getObjectInfoDirectory,
|
|
15033
15060
|
},
|
|
15034
15061
|
};
|
|
15035
15062
|
}
|
|
15036
15063
|
|
|
15037
|
-
const OBJECT_INFO_PREFIX_SEGMENT = 'OBJECT_INFO_PREFIX_SEGMENT';
|
|
15038
15064
|
class ObjectInfoService {
|
|
15039
|
-
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;
|
|
15040
15070
|
this.apiNameForPrefix = async (prefix) => {
|
|
15041
|
-
|
|
15042
|
-
|
|
15043
|
-
if (entries === undefined) {
|
|
15044
|
-
throw missingError;
|
|
15071
|
+
if (this.keyPrefixToApiNameMemoryCache[prefix] !== undefined) {
|
|
15072
|
+
return this.keyPrefixToApiNameMemoryCache[prefix];
|
|
15045
15073
|
}
|
|
15046
|
-
|
|
15047
|
-
|
|
15048
|
-
|
|
15049
|
-
|
|
15050
|
-
return entry.data.apiName;
|
|
15051
|
-
}
|
|
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`);
|
|
15052
15078
|
}
|
|
15053
|
-
|
|
15079
|
+
return apiName;
|
|
15054
15080
|
};
|
|
15055
15081
|
this.ensureObjectInfoCached = async (apiName, entry) => {
|
|
15082
|
+
if (entry !== undefined) {
|
|
15083
|
+
const { keyPrefix, apiName } = entry;
|
|
15084
|
+
return this.updateObjectInfoMapping(keyPrefix, apiName);
|
|
15085
|
+
}
|
|
15056
15086
|
const exists = await this.isObjectInfoInDurableStore(apiName);
|
|
15057
15087
|
if (exists) {
|
|
15058
15088
|
return;
|
|
15059
15089
|
}
|
|
15060
|
-
if (entry !== undefined) {
|
|
15061
|
-
// Since ObjectInfo is provided, no need to fetch the snapshot
|
|
15062
|
-
return this.createObjectInfoMapping(apiName, entry);
|
|
15063
|
-
}
|
|
15064
15090
|
// ObjectInfo is not present in Durable store. Fetch
|
|
15065
15091
|
const snapshot = await this.getObjectInfoAdapter({
|
|
15066
15092
|
objectApiName: apiName,
|
|
@@ -15069,46 +15095,34 @@ class ObjectInfoService {
|
|
|
15069
15095
|
throw Error(`No snapshot found for apiName ${apiName}`);
|
|
15070
15096
|
}
|
|
15071
15097
|
if (snapshot.data !== null && snapshot.data !== undefined) {
|
|
15072
|
-
|
|
15098
|
+
const { keyPrefix, apiName } = snapshot.data;
|
|
15099
|
+
return this.updateObjectInfoMapping(keyPrefix, apiName);
|
|
15073
15100
|
}
|
|
15074
15101
|
};
|
|
15075
|
-
/**
|
|
15076
|
-
* Caches ObjectInfo(ApiName and KeyPrefix) in Durable Store
|
|
15077
|
-
*
|
|
15078
|
-
* @param apiName eg: 'Account'
|
|
15079
|
-
* @param objectInfo Object Info
|
|
15080
|
-
*
|
|
15081
|
-
* @returns Promise
|
|
15082
|
-
*/
|
|
15083
|
-
this.createObjectInfoMapping = (apiName, objectInfo) => {
|
|
15084
|
-
const { keyPrefix } = objectInfo;
|
|
15085
|
-
const entries = {
|
|
15086
|
-
[apiName]: {
|
|
15087
|
-
data: {
|
|
15088
|
-
apiName,
|
|
15089
|
-
keyPrefix,
|
|
15090
|
-
},
|
|
15091
|
-
},
|
|
15092
|
-
};
|
|
15093
|
-
this.objectInfoMemoryCache[apiName] = keyPrefix;
|
|
15094
|
-
return this.durableStore.setEntries(entries, OBJECT_INFO_PREFIX_SEGMENT);
|
|
15095
|
-
};
|
|
15096
15102
|
this.isObjectInfoInDurableStore = async (apiName) => {
|
|
15097
|
-
if (this.
|
|
15103
|
+
if (this.apiNameToKeyPrefixMemoryCache[apiName] !== undefined) {
|
|
15098
15104
|
return Promise.resolve(true);
|
|
15099
15105
|
}
|
|
15100
|
-
|
|
15101
|
-
|
|
15102
|
-
|
|
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);
|
|
15103
15115
|
}
|
|
15104
|
-
this.objectInfoMemoryCache[apiName] = entries[apiName].data.keyPrefix;
|
|
15105
|
-
return true;
|
|
15106
15116
|
};
|
|
15107
|
-
this.
|
|
15108
|
-
|
|
15109
|
-
|
|
15110
|
-
|
|
15111
|
-
|
|
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);
|
|
15112
15126
|
}
|
|
15113
15127
|
/**
|
|
15114
15128
|
* Size of return map not necessarily correlated with number of inputs. The
|
|
@@ -15128,10 +15142,20 @@ class ObjectInfoService {
|
|
|
15128
15142
|
for (const result of snapshot.data.results) {
|
|
15129
15143
|
if (result.statusCode === 200) {
|
|
15130
15144
|
objectInfos[result.result.apiName] = result.result;
|
|
15145
|
+
this.updateObjectInfoMapping(result.result.keyPrefix, result.result.apiName);
|
|
15131
15146
|
}
|
|
15132
15147
|
}
|
|
15133
15148
|
return objectInfos;
|
|
15134
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
|
+
}
|
|
15135
15159
|
}
|
|
15136
15160
|
|
|
15137
15161
|
function instrumentGraphQLEval(adapter) {
|
|
@@ -15475,6 +15499,7 @@ class NimbusSqliteStore {
|
|
|
15475
15499
|
...additionalTableMap,
|
|
15476
15500
|
[DefaultDurableSegment]: new LdsDataTable(plugin),
|
|
15477
15501
|
};
|
|
15502
|
+
this.supportsBatchUpdates = plugin.supportsBatchUpdates !== undefined;
|
|
15478
15503
|
}
|
|
15479
15504
|
isEvalSupported() {
|
|
15480
15505
|
return true;
|
|
@@ -15509,16 +15534,15 @@ class NimbusSqliteStore {
|
|
|
15509
15534
|
setMetadata(entries, segment) {
|
|
15510
15535
|
const table = this.getTable(segment);
|
|
15511
15536
|
let operation;
|
|
15512
|
-
if (this.
|
|
15513
|
-
|
|
15537
|
+
if (this.supportsBatchUpdates) {
|
|
15538
|
+
operation = table.metadataToUpdateOperations(entries, segment);
|
|
15539
|
+
}
|
|
15540
|
+
else {
|
|
15514
15541
|
operation = table.entriesToUpsertOperations(entries, segment);
|
|
15515
15542
|
// manually set the context type on the upsert so notifications do not notify rebuilds without
|
|
15516
15543
|
// plugin updates
|
|
15517
15544
|
operation.context.type = 'setMetadata';
|
|
15518
15545
|
}
|
|
15519
|
-
else {
|
|
15520
|
-
operation = table.metadataToUpdateOperations(entries, segment);
|
|
15521
|
-
}
|
|
15522
15546
|
return this.batchOperationAsPromise([operation]);
|
|
15523
15547
|
}
|
|
15524
15548
|
batchOperations(operations) {
|
|
@@ -15529,17 +15553,16 @@ class NimbusSqliteStore {
|
|
|
15529
15553
|
}
|
|
15530
15554
|
else if (cur.type === 'setMetadata') {
|
|
15531
15555
|
const table = this.getTable(cur.segment);
|
|
15532
|
-
if (this.
|
|
15533
|
-
|
|
15556
|
+
if (this.supportsBatchUpdates) {
|
|
15557
|
+
acc.push(table.metadataToUpdateOperations(cur.entries, cur.segment));
|
|
15558
|
+
}
|
|
15559
|
+
else {
|
|
15534
15560
|
const upsert = table.entriesToUpsertOperations(cur.entries, cur.segment);
|
|
15535
15561
|
// manually set the context type on the upsert so notifications do not notify rebuilds without
|
|
15536
15562
|
// plugin updates
|
|
15537
15563
|
upsert.context.type = 'setMetadata';
|
|
15538
15564
|
acc.push(upsert);
|
|
15539
15565
|
}
|
|
15540
|
-
else {
|
|
15541
|
-
acc.push(table.metadataToUpdateOperations(cur.entries, cur.segment));
|
|
15542
|
-
}
|
|
15543
15566
|
}
|
|
15544
15567
|
else {
|
|
15545
15568
|
acc.push(this.idsToDeleteOperation(cur.ids, cur.segment));
|
|
@@ -16715,17 +16738,34 @@ function instrumentPrimingSession(session) {
|
|
|
16715
16738
|
const apiVersion = `v60.0`;
|
|
16716
16739
|
const batchEndPointPath = `/services/data/${apiVersion}/graphql/batch`;
|
|
16717
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`;
|
|
16718
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
|
+
}
|
|
16719
16766
|
postBatchGraphQL(configs, abortController) {
|
|
16720
16767
|
return new Promise((resolve, reject) => {
|
|
16721
|
-
|
|
16722
|
-
const unregisterListener = () => {
|
|
16723
|
-
if (listener) {
|
|
16724
|
-
abortController.removeEventListener(listener);
|
|
16725
|
-
}
|
|
16726
|
-
};
|
|
16727
|
-
__nimbus.plugins.LdsNetworkAdapter
|
|
16728
|
-
.sendRequest({
|
|
16768
|
+
this.sendRequestWithAbort({
|
|
16729
16769
|
method: 'POST',
|
|
16730
16770
|
path: batchEndPointPath,
|
|
16731
16771
|
body: JSON.stringify({
|
|
@@ -16735,8 +16775,7 @@ class NimbusPrimingNetworkAdapter {
|
|
|
16735
16775
|
queryParams: {},
|
|
16736
16776
|
priority: 'background',
|
|
16737
16777
|
observabilityContext: {},
|
|
16738
|
-
}, (response) => {
|
|
16739
|
-
unregisterListener();
|
|
16778
|
+
}, abortController, (response) => {
|
|
16740
16779
|
const { body } = response;
|
|
16741
16780
|
if (body) {
|
|
16742
16781
|
const { results } = JSON.parse(body);
|
|
@@ -16752,27 +16791,13 @@ class NimbusPrimingNetworkAdapter {
|
|
|
16752
16791
|
reject(new Error(`No body returned from ${batchEndPointPath} endpoint`));
|
|
16753
16792
|
}
|
|
16754
16793
|
}, (error) => {
|
|
16755
|
-
unregisterListener();
|
|
16756
16794
|
reject(error);
|
|
16757
|
-
})
|
|
16758
|
-
.then((cancellationToken) => {
|
|
16759
|
-
listener = () => {
|
|
16760
|
-
__nimbus.plugins.LdsNetworkAdapter.cancelRequest(cancellationToken);
|
|
16761
|
-
};
|
|
16762
|
-
abortController.addEventListener(listener);
|
|
16763
16795
|
});
|
|
16764
16796
|
});
|
|
16765
16797
|
}
|
|
16766
16798
|
postGraphQL(query, variables, abortController) {
|
|
16767
16799
|
return new Promise((resolve, reject) => {
|
|
16768
|
-
|
|
16769
|
-
const unregisterListener = () => {
|
|
16770
|
-
if (listener) {
|
|
16771
|
-
abortController.removeEventListener(listener);
|
|
16772
|
-
}
|
|
16773
|
-
};
|
|
16774
|
-
__nimbus.plugins.LdsNetworkAdapter
|
|
16775
|
-
.sendRequest({
|
|
16800
|
+
this.sendRequestWithAbort({
|
|
16776
16801
|
method: 'POST',
|
|
16777
16802
|
path: endPointPath,
|
|
16778
16803
|
body: JSON.stringify({
|
|
@@ -16783,8 +16808,7 @@ class NimbusPrimingNetworkAdapter {
|
|
|
16783
16808
|
queryParams: {},
|
|
16784
16809
|
priority: 'background',
|
|
16785
16810
|
observabilityContext: {},
|
|
16786
|
-
}, (response) => {
|
|
16787
|
-
unregisterListener();
|
|
16811
|
+
}, abortController, (response) => {
|
|
16788
16812
|
const { body } = response;
|
|
16789
16813
|
if (body) {
|
|
16790
16814
|
resolve(JSON.parse(body));
|
|
@@ -16793,14 +16817,64 @@ class NimbusPrimingNetworkAdapter {
|
|
|
16793
16817
|
reject(new Error(`No body returned from ${endPointPath} endpoint`));
|
|
16794
16818
|
}
|
|
16795
16819
|
}, (error) => {
|
|
16796
|
-
unregisterListener();
|
|
16797
16820
|
reject(error);
|
|
16798
|
-
})
|
|
16799
|
-
|
|
16800
|
-
|
|
16801
|
-
|
|
16802
|
-
|
|
16803
|
-
|
|
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);
|
|
16804
16878
|
});
|
|
16805
16879
|
});
|
|
16806
16880
|
}
|
|
@@ -16809,6 +16883,10 @@ class NimbusPrimingNetworkAdapter {
|
|
|
16809
16883
|
// ref: https://gnome.pages.gitlab.gnome.org/tracker/docs/developer/limits.html?gi-language=c
|
|
16810
16884
|
const SQLITE_MAX_VARIABLE_NUMBER = 999;
|
|
16811
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}:`;
|
|
16812
16890
|
// We need to batch the records to avoid hitting the SQLITE_MAX_VARIABLE_NUMBER limit. Each record has 3 parameters
|
|
16813
16891
|
const BATCH_SIZE = Math.floor(SQLITE_MAX_VARIABLE_NUMBER / PARAMS_PER_RECORD);
|
|
16814
16892
|
class SqlitePrimingStore {
|
|
@@ -16873,6 +16951,44 @@ class SqlitePrimingStore {
|
|
|
16873
16951
|
};
|
|
16874
16952
|
}
|
|
16875
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
|
+
}
|
|
16876
16992
|
}
|
|
16877
16993
|
function batchArray(arr, batchSize = BATCH_SIZE) {
|
|
16878
16994
|
const batches = [];
|
|
@@ -16997,13 +17113,13 @@ function getRuntime() {
|
|
|
16997
17113
|
: {}, () => getIngestMetadataForInternalAdapters !== undefined
|
|
16998
17114
|
? getIngestMetadataForInternalAdapters()
|
|
16999
17115
|
: {});
|
|
17000
|
-
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));
|
|
17001
17117
|
lazyInternalLuvio = internalLuvio;
|
|
17002
17118
|
getIngestRecordsForInternalAdapters =
|
|
17003
17119
|
internalAdapterDurableEnvironment.getIngestStagingStoreRecords;
|
|
17004
17120
|
getIngestMetadataForInternalAdapters =
|
|
17005
17121
|
internalAdapterDurableEnvironment.getIngestStagingStoreRecords;
|
|
17006
|
-
lazyObjectInfoService = new ObjectInfoService(getObjectInfo, getObjectInfos,
|
|
17122
|
+
lazyObjectInfoService = new ObjectInfoService(getObjectInfo, getObjectInfos, getObjectInfoDirectory, lazyBaseDurableStore);
|
|
17007
17123
|
// creates a durable store that denormalizes scalar fields for records
|
|
17008
17124
|
let getIngestRecords;
|
|
17009
17125
|
let getIngestMetadata;
|
|
@@ -17098,6 +17214,7 @@ function getRuntime() {
|
|
|
17098
17214
|
getRecords: lazyGetRecords,
|
|
17099
17215
|
});
|
|
17100
17216
|
},
|
|
17217
|
+
nimbusSqliteStore: lazyBaseDurableStore,
|
|
17101
17218
|
};
|
|
17102
17219
|
}
|
|
17103
17220
|
|
|
@@ -17114,4 +17231,4 @@ register({
|
|
|
17114
17231
|
});
|
|
17115
17232
|
|
|
17116
17233
|
export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
|
|
17117
|
-
// 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
|
}
|
package/dist/types/runtime.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Luvio, Environment } from '@luvio/engine';
|
|
2
2
|
import { DraftManager } from '@salesforce/lds-drafts';
|
|
3
3
|
import type { DraftQueue } from '@salesforce/lds-drafts';
|
|
4
|
+
import type { NimbusSqliteStore } from '@salesforce/lds-store-nimbus';
|
|
4
5
|
import type { PrimingSession } from '@salesforce/lds-priming';
|
|
5
6
|
export interface Runtime {
|
|
6
7
|
luvio: Luvio;
|
|
@@ -12,6 +13,7 @@ export interface Runtime {
|
|
|
12
13
|
concurrency?: number;
|
|
13
14
|
batchSize?: number;
|
|
14
15
|
}) => PrimingSession;
|
|
16
|
+
nimbusSqliteStore: NimbusSqliteStore;
|
|
15
17
|
}
|
|
16
18
|
/**
|
|
17
19
|
* This returns the LDS on Mobile Runtime singleton object.
|