@salesforce/lds-runtime-mobile 1.266.0-dev2 → 1.266.0-dev20
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 +133 -52
- package/package.json +16 -16
- package/sfdc/main.js +133 -52
package/dist/main.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { withRegistration, register } from '@salesforce/lds-default-luvio';
|
|
15
15
|
import { setupInstrumentation, instrumentAdapter as instrumentAdapter$1, instrumentLuvio, setLdsAdaptersUiapiInstrumentation, setLdsNetworkAdapterInstrumentation } from '@salesforce/lds-instrumentation';
|
|
16
|
-
import { HttpStatusCode, StoreKeySet, serializeStructuredKey, StringKeyInMemoryStore, Reader, deepFreeze, emitAdapterEvent, createCustomAdapterEventEmitter, StoreKeyMap, isFileReference, Environment, Luvio, InMemoryStore } from '@luvio/engine';
|
|
16
|
+
import { HttpStatusCode, setBypassDeepFreeze, 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, buildSchema, isObjectType, defaultFieldResolver, visit, execute, parse as parse$7, extendSchema, isScalarType } from '@luvio/graphql-parser';
|
|
19
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, getRecordsAdapterFactory } from '@salesforce/lds-adapters-uiapi';
|
|
@@ -1014,7 +1014,9 @@ function isUnfulfilledSnapshot$1(cachedSnapshotResult) {
|
|
|
1014
1014
|
* @param durableStore A DurableStore implementation
|
|
1015
1015
|
* @param instrumentation An instrumentation function implementation
|
|
1016
1016
|
*/
|
|
1017
|
-
function makeDurable(environment, { durableStore, instrumentation, useRevivingStore, enableDurableMetadataRefresh = false, }) {
|
|
1017
|
+
function makeDurable(environment, { durableStore, instrumentation, useRevivingStore, enableDurableMetadataRefresh = false, disableDeepFreeze = false, }) {
|
|
1018
|
+
// runtimes can choose to disable deepFreeze, e.g. headless mobile runtime
|
|
1019
|
+
setBypassDeepFreeze(disableDeepFreeze);
|
|
1018
1020
|
let stagingStore = null;
|
|
1019
1021
|
const durableTTLStore = new DurableTTLStore(durableStore);
|
|
1020
1022
|
const mergeKeysPromiseMap = new Map();
|
|
@@ -1385,6 +1387,10 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
|
|
|
1385
1387
|
}
|
|
1386
1388
|
return {};
|
|
1387
1389
|
};
|
|
1390
|
+
const getIngestStagingStore = function () {
|
|
1391
|
+
validateNotDisposed();
|
|
1392
|
+
return stagingStore === null || stagingStore === void 0 ? void 0 : stagingStore.fallbackStringKeyInMemoryStore;
|
|
1393
|
+
};
|
|
1388
1394
|
const handleSuccessResponse = async function (ingestAndBroadcastFunc, getResponseCacheKeysFunc) {
|
|
1389
1395
|
validateNotDisposed();
|
|
1390
1396
|
const cacheKeyMap = getResponseCacheKeysFunc();
|
|
@@ -1577,6 +1583,7 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
|
|
|
1577
1583
|
applyCachePolicy: { value: applyCachePolicy },
|
|
1578
1584
|
getIngestStagingStoreRecords: { value: getIngestStagingStoreRecords },
|
|
1579
1585
|
getIngestStagingStoreMetadata: { value: getIngestStagingStoreMetadata },
|
|
1586
|
+
getIngestStagingStore: { value: getIngestStagingStore },
|
|
1580
1587
|
handleSuccessResponse: { value: handleSuccessResponse },
|
|
1581
1588
|
handleErrorResponse: { value: handleErrorResponse },
|
|
1582
1589
|
getNotifyChangeStoreEntries: { value: getNotifyChangeStoreEntries },
|
|
@@ -4374,9 +4381,10 @@ function rootRecordQuery(selection, input) {
|
|
|
4374
4381
|
// If there is no metadata for this query or it somehow lacks a timestamp
|
|
4375
4382
|
// skip setting the root timestamp
|
|
4376
4383
|
if (queryMetadata !== undefined && queryMetadata.ingestionTimestamp !== undefined) {
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4384
|
+
const timestamp = Number(queryMetadata.ingestionTimestamp);
|
|
4385
|
+
if (!isNaN(timestamp)) {
|
|
4386
|
+
input.rootTimestamp = timestamp;
|
|
4387
|
+
}
|
|
4380
4388
|
}
|
|
4381
4389
|
}
|
|
4382
4390
|
return recordQuery(selection, alias, apiName, [], input);
|
|
@@ -5842,7 +5850,12 @@ class DurableDraftQueue {
|
|
|
5842
5850
|
}
|
|
5843
5851
|
finally {
|
|
5844
5852
|
this.replacingAction = undefined;
|
|
5845
|
-
|
|
5853
|
+
try {
|
|
5854
|
+
await this.startQueueSafe();
|
|
5855
|
+
}
|
|
5856
|
+
catch (_a) {
|
|
5857
|
+
// An error starting the queue should not bubble up from this method
|
|
5858
|
+
}
|
|
5846
5859
|
}
|
|
5847
5860
|
return updatedTarget;
|
|
5848
5861
|
});
|
|
@@ -8005,6 +8018,9 @@ function createSinglePredicate(val, operator, field, alias) {
|
|
|
8005
8018
|
else if (field.apiName === 'weakEtag') {
|
|
8006
8019
|
leftPath = '$.weakEtag';
|
|
8007
8020
|
}
|
|
8021
|
+
else if (field.apiName === 'RecordTypeId') {
|
|
8022
|
+
leftPath = '$.recordTypeId';
|
|
8023
|
+
}
|
|
8008
8024
|
return {
|
|
8009
8025
|
alias,
|
|
8010
8026
|
leftPath,
|
|
@@ -9041,6 +9057,20 @@ function findFieldInfo(objectInfo, fieldName) {
|
|
|
9041
9057
|
return values$2(objectInfo.fields).find((field) => field.apiName === fieldName ||
|
|
9042
9058
|
(field.dataType === 'Reference' && field.relationshipName === fieldName));
|
|
9043
9059
|
}
|
|
9060
|
+
async function readIngestionTimestampForKey(key, query) {
|
|
9061
|
+
let ingestionTimestamp = 0;
|
|
9062
|
+
const sql = `SELECT json_extract(metadata, '${JSON_EXTRACT_PATH_INGESTION_TIMESTAMP}') FROM lds_data WHERE key IS ?`;
|
|
9063
|
+
const results = await query(sql, [key]);
|
|
9064
|
+
const [timestamp] = results.rows.map((row) => row[0]);
|
|
9065
|
+
if (timestamp !== null) {
|
|
9066
|
+
const numericalTimestamp = Number(timestamp);
|
|
9067
|
+
if (isNaN(numericalTimestamp)) {
|
|
9068
|
+
return ingestionTimestamp;
|
|
9069
|
+
}
|
|
9070
|
+
ingestionTimestamp = numericalTimestamp;
|
|
9071
|
+
}
|
|
9072
|
+
return ingestionTimestamp;
|
|
9073
|
+
}
|
|
9044
9074
|
|
|
9045
9075
|
function findSpanningField(name) {
|
|
9046
9076
|
return (field) => {
|
|
@@ -9365,6 +9395,12 @@ function addResolversToSchema(schema, polyFields) {
|
|
|
9365
9395
|
break;
|
|
9366
9396
|
case 'LastModifiedDate':
|
|
9367
9397
|
field.resolve = ({ recordRepresentation: record }) => {
|
|
9398
|
+
// In UIAPI record reps, LastModifiedDate might be present as a field,
|
|
9399
|
+
// which will include both the value and displayValue
|
|
9400
|
+
if (record.fields['LastModifiedDate']) {
|
|
9401
|
+
return record.fields['LastModifiedDate'];
|
|
9402
|
+
}
|
|
9403
|
+
// If the field is not present, just return the value of the root property
|
|
9368
9404
|
return record.lastModifiedDate
|
|
9369
9405
|
? { value: record.lastModifiedDate }
|
|
9370
9406
|
: null;
|
|
@@ -9399,16 +9435,26 @@ function addResolversToSchema(schema, polyFields) {
|
|
|
9399
9435
|
: null;
|
|
9400
9436
|
};
|
|
9401
9437
|
const { recordRepresentation: record, ingestionTimestamp } = obj;
|
|
9402
|
-
|
|
9403
|
-
|
|
9404
|
-
|
|
9405
|
-
|
|
9406
|
-
|
|
9407
|
-
|
|
9408
|
-
if (
|
|
9438
|
+
let id = undefined;
|
|
9439
|
+
if (field.name === 'RecordType') {
|
|
9440
|
+
// RecordTypeId has special handling during ingest and is
|
|
9441
|
+
// not in record.fields, so check for it at the UIAPI root property location
|
|
9442
|
+
id = record.recordTypeId;
|
|
9443
|
+
}
|
|
9444
|
+
else if (field.name.endsWith('__r')) {
|
|
9445
|
+
// Custom relationships end in `__r` and the corresponding ID field should be `__c`
|
|
9446
|
+
let fieldName = field.name.replace('__r', '__c');
|
|
9447
|
+
id = record.fields[fieldName] && record.fields[fieldName].value;
|
|
9448
|
+
}
|
|
9449
|
+
else {
|
|
9450
|
+
// Standard relationships are just FieldNameId
|
|
9451
|
+
let fieldName = field.name + 'Id';
|
|
9452
|
+
id = record.fields[fieldName] && record.fields[fieldName].value;
|
|
9453
|
+
}
|
|
9454
|
+
if (!id || typeof id !== 'string') {
|
|
9455
|
+
// possibly field injection did not inject the necessary Id field
|
|
9456
|
+
// for the relationship, or we found a non-string value.
|
|
9409
9457
|
return null;
|
|
9410
|
-
if (id['__ref'] !== undefined) {
|
|
9411
|
-
return fetchRecordOrNull(record.fields[`${field.name}Id`].value);
|
|
9412
9458
|
}
|
|
9413
9459
|
seenRecordIds.add(id);
|
|
9414
9460
|
return fetchRecordOrNull(id);
|
|
@@ -9560,18 +9606,7 @@ async function fetchIngestionTimeStampFromDatabase(apiName, info, args, query) {
|
|
|
9560
9606
|
const key = buildKeyStringForRecordQuery(operation,
|
|
9561
9607
|
// join varables passed from query to the argument variables given from the AST
|
|
9562
9608
|
{ ...variableValues, ...args }, info.fieldNodes[0].arguments, apiName);
|
|
9563
|
-
|
|
9564
|
-
SELECT json_extract(metadata, '${JSON_EXTRACT_PATH_INGESTION_TIMESTAMP}')
|
|
9565
|
-
FROM lds_data
|
|
9566
|
-
WHERE key IS ?
|
|
9567
|
-
`;
|
|
9568
|
-
const results = await query(sql, [key]);
|
|
9569
|
-
const [timestamp] = results.rows.map((row) => row[0]);
|
|
9570
|
-
if (timestamp !== null && typeof timestamp === 'number') {
|
|
9571
|
-
// adjust the timestamp to account for ingestion processing time
|
|
9572
|
-
// 30s is used because this is the default record TTL
|
|
9573
|
-
ingestionTimestamp = timestamp - 30000;
|
|
9574
|
-
}
|
|
9609
|
+
return readIngestionTimestampForKey(key, query);
|
|
9575
9610
|
}
|
|
9576
9611
|
return ingestionTimestamp;
|
|
9577
9612
|
}
|
|
@@ -11638,7 +11673,7 @@ function createUserJsonOutput(selection, jsonInput, jsonOutput) {
|
|
|
11638
11673
|
function createjsonOutput(selections, jsonInput, jsonOutput) {
|
|
11639
11674
|
const keys$1 = keys$4(jsonInput);
|
|
11640
11675
|
selections.filter(isFieldNode).forEach((subSelection) => {
|
|
11641
|
-
const fieldName = subSelection.name.value;
|
|
11676
|
+
const fieldName = subSelection.alias ? subSelection.alias.value : subSelection.name.value;
|
|
11642
11677
|
if (keys$1.includes(fieldName)) {
|
|
11643
11678
|
if (isArray$2(jsonInput[fieldName])) {
|
|
11644
11679
|
jsonOutput[fieldName] = [];
|
|
@@ -12358,13 +12393,21 @@ function buildSyntheticRecordRepresentation(luvio, createOperation, userId, obje
|
|
|
12358
12393
|
draftFields[DEFAULT_FIELD_LAST_MODIFIED_DATE] = { value: timestampString, displayValue: null };
|
|
12359
12394
|
draftFields[DEFAULT_FIELD_OWNER_ID] = { value: userId, displayValue: null };
|
|
12360
12395
|
draftFields[DEFAULT_FIELD_ID] = { value: recordId, displayValue: null };
|
|
12361
|
-
|
|
12362
|
-
|
|
12363
|
-
|
|
12364
|
-
|
|
12365
|
-
|
|
12366
|
-
|
|
12367
|
-
|
|
12396
|
+
const allObjectFields = keys$3(objectInfo.fields);
|
|
12397
|
+
allObjectFields.forEach((fieldName) => {
|
|
12398
|
+
if (draftFields[fieldName] === undefined) {
|
|
12399
|
+
draftFields[fieldName] = { value: null, displayValue: null };
|
|
12400
|
+
}
|
|
12401
|
+
});
|
|
12402
|
+
// TODO [W-14915806]: lightning-record-form injects the `IsPersonAccount`
|
|
12403
|
+
// field for all `Account` and `PersonAccount` records. However, not all
|
|
12404
|
+
// orgs use person accounts, and if that field is not present in the object
|
|
12405
|
+
// info then it is not synthesized. We force it to be synthesized here to
|
|
12406
|
+
// ensure lightning-record-form will work correctly with draft-created
|
|
12407
|
+
// accounts.
|
|
12408
|
+
if ((apiName === 'Account' || apiName === 'PersonAccount') &&
|
|
12409
|
+
draftFields['IsPersonAccount'] === undefined) {
|
|
12410
|
+
draftFields['IsPersonAccount'] = { value: null, displayValue: null };
|
|
12368
12411
|
}
|
|
12369
12412
|
return {
|
|
12370
12413
|
id: recordId,
|
|
@@ -12951,10 +12994,13 @@ function normalizeRecordFields(key, entry) {
|
|
|
12951
12994
|
* Transforms a record for storage in the durable store. The transformation involves denormalizing
|
|
12952
12995
|
* scalar fields and persisting link metadata to transform back into a normalized representation
|
|
12953
12996
|
*
|
|
12997
|
+
* If the record contains pending fields this will return undefined as pending records do not get persisted
|
|
12998
|
+
* to the durable store. There should be a refresh operation outbound that will bring in the updated record.
|
|
12999
|
+
*
|
|
12954
13000
|
* @param normalizedRecord Record containing normalized field links
|
|
12955
13001
|
* @param recordStore a store containing referenced record fields
|
|
12956
13002
|
*/
|
|
12957
|
-
function buildDurableRecordRepresentation(normalizedRecord, records, pendingEntries) {
|
|
13003
|
+
function buildDurableRecordRepresentation(normalizedRecord, records, pendingEntries, store) {
|
|
12958
13004
|
const fields = normalizedRecord.fields;
|
|
12959
13005
|
const filteredFields = {};
|
|
12960
13006
|
const links = {};
|
|
@@ -12965,7 +13011,9 @@ function buildDurableRecordRepresentation(normalizedRecord, records, pendingEntr
|
|
|
12965
13011
|
// pending fields get filtered out of the durable store
|
|
12966
13012
|
const { pending } = field;
|
|
12967
13013
|
if (pending === true) {
|
|
12968
|
-
|
|
13014
|
+
// do not write records with pending fields to the durable store
|
|
13015
|
+
// there should be a refresh operation outbound that will bring in the updated record
|
|
13016
|
+
return undefined;
|
|
12969
13017
|
}
|
|
12970
13018
|
const { __ref } = field;
|
|
12971
13019
|
if (__ref !== undefined) {
|
|
@@ -12981,6 +13029,19 @@ function buildDurableRecordRepresentation(normalizedRecord, records, pendingEntr
|
|
|
12981
13029
|
if (ref !== undefined) {
|
|
12982
13030
|
filteredFields[fieldName] = ref;
|
|
12983
13031
|
}
|
|
13032
|
+
else {
|
|
13033
|
+
// if we have a store to read, try to find the field there too
|
|
13034
|
+
// The durable ingest staging store may pass through to L1, and
|
|
13035
|
+
// not all fields are necessarily published every time, so it is
|
|
13036
|
+
// important to check L1 and not just the fields being published,
|
|
13037
|
+
// otherwise we risk truncating the fields on the record.
|
|
13038
|
+
if (store) {
|
|
13039
|
+
ref = store.readEntry(__ref);
|
|
13040
|
+
if (ref !== undefined) {
|
|
13041
|
+
filteredFields[fieldName] = ref;
|
|
13042
|
+
}
|
|
13043
|
+
}
|
|
13044
|
+
}
|
|
12984
13045
|
}
|
|
12985
13046
|
// we want to preserve fields that are missing nodes
|
|
12986
13047
|
if (filteredFields[fieldName] !== undefined || field.isMissing === true) {
|
|
@@ -13002,7 +13063,7 @@ function getDenormalizedKey(originalKey, recordId, luvio) {
|
|
|
13002
13063
|
}
|
|
13003
13064
|
return keyBuilderRecord(luvio, { recordId });
|
|
13004
13065
|
}
|
|
13005
|
-
function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecords, getStoreMetadata) {
|
|
13066
|
+
function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecords, getStoreMetadata, getStore) {
|
|
13006
13067
|
const getEntries = function (entries, segment) {
|
|
13007
13068
|
// this HOF only inspects records in the default segment
|
|
13008
13069
|
if (segment !== DefaultDurableSegment) {
|
|
@@ -13070,6 +13131,7 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
|
|
|
13070
13131
|
const putRecordViews = {};
|
|
13071
13132
|
const storeRecords = getStoreRecords !== undefined ? getStoreRecords() : {};
|
|
13072
13133
|
const storeMetadata = getStoreMetadata !== undefined ? getStoreMetadata() : {};
|
|
13134
|
+
const store = getStore();
|
|
13073
13135
|
for (let i = 0, len = keys$1.length; i < len; i++) {
|
|
13074
13136
|
const key = keys$1[i];
|
|
13075
13137
|
let value = entries[key];
|
|
@@ -13116,11 +13178,13 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
|
|
|
13116
13178
|
metadataVersion: DURABLE_METADATA_VERSION,
|
|
13117
13179
|
};
|
|
13118
13180
|
}
|
|
13119
|
-
const denormalizedRecord = buildDurableRecordRepresentation(record, storeRecords, recordEntries);
|
|
13120
|
-
|
|
13121
|
-
|
|
13122
|
-
|
|
13123
|
-
|
|
13181
|
+
const denormalizedRecord = buildDurableRecordRepresentation(record, storeRecords, recordEntries, store);
|
|
13182
|
+
if (denormalizedRecord !== undefined) {
|
|
13183
|
+
putEntries[recordKey] = {
|
|
13184
|
+
data: denormalizedRecord,
|
|
13185
|
+
metadata,
|
|
13186
|
+
};
|
|
13187
|
+
}
|
|
13124
13188
|
}
|
|
13125
13189
|
else {
|
|
13126
13190
|
putEntries[key] = value;
|
|
@@ -15948,9 +16012,9 @@ function instrumentAdapter(adapter, metadata) {
|
|
|
15948
16012
|
}
|
|
15949
16013
|
}
|
|
15950
16014
|
return instrumentAdapter$1(instrumentedMobileAdapter, metadata, {
|
|
15951
|
-
trackL1Hits:
|
|
15952
|
-
trackL2Hits:
|
|
15953
|
-
trackCacheMisses:
|
|
16015
|
+
trackL1Hits: false,
|
|
16016
|
+
trackL2Hits: false,
|
|
16017
|
+
trackCacheMisses: false,
|
|
15954
16018
|
reportObserver: (report) => {
|
|
15955
16019
|
for (const observer of reportObservers) {
|
|
15956
16020
|
observer(report);
|
|
@@ -16757,6 +16821,7 @@ function findReferenceFieldForSpanningField(fieldName, objectInfo) {
|
|
|
16757
16821
|
function buildFieldUnionArray(existingRecord, incomingRecord, objectInfo) {
|
|
16758
16822
|
const allFields = Array.from(new Set([...Object.keys(existingRecord.fields), ...Object.keys(incomingRecord.fields)]));
|
|
16759
16823
|
const fieldUnion = [];
|
|
16824
|
+
let includesSpanningFields = false;
|
|
16760
16825
|
allFields.forEach((fieldName) => {
|
|
16761
16826
|
const objectInfoField = objectInfo.fields[fieldName];
|
|
16762
16827
|
if (objectInfoField === undefined) {
|
|
@@ -16764,13 +16829,14 @@ function buildFieldUnionArray(existingRecord, incomingRecord, objectInfo) {
|
|
|
16764
16829
|
const referenceField = findReferenceFieldForSpanningField(fieldName, objectInfo);
|
|
16765
16830
|
if (referenceField !== undefined) {
|
|
16766
16831
|
fieldUnion.push(`${fieldName}.Id`);
|
|
16832
|
+
includesSpanningFields = true;
|
|
16767
16833
|
}
|
|
16768
16834
|
}
|
|
16769
16835
|
else {
|
|
16770
16836
|
fieldUnion.push(fieldName);
|
|
16771
16837
|
}
|
|
16772
16838
|
});
|
|
16773
|
-
return fieldUnion;
|
|
16839
|
+
return { fields: fieldUnion, includesSpanningFields };
|
|
16774
16840
|
}
|
|
16775
16841
|
/**
|
|
16776
16842
|
* Merges (if possible) an incoming record from a priming session with an existing record in the durable store.
|
|
@@ -16802,7 +16868,7 @@ function mergeRecord(existingRecord, incomingRecord, objectInfo) {
|
|
|
16802
16868
|
ok: false,
|
|
16803
16869
|
code: 'conflict-drafts',
|
|
16804
16870
|
hasDraft: true,
|
|
16805
|
-
fieldUnion: buildFieldUnionArray(existingRecord, incomingRecord, objectInfo),
|
|
16871
|
+
fieldUnion: buildFieldUnionArray(existingRecord, incomingRecord, objectInfo).fields,
|
|
16806
16872
|
};
|
|
16807
16873
|
}
|
|
16808
16874
|
// Check if incoming record's Etag is equal to the existing one
|
|
@@ -16864,10 +16930,19 @@ function mergeRecord(existingRecord, incomingRecord, objectInfo) {
|
|
|
16864
16930
|
};
|
|
16865
16931
|
}
|
|
16866
16932
|
// If Etags do not match and the incoming record does not contain all fields, re-request the record
|
|
16933
|
+
const { fields, includesSpanningFields } = buildFieldUnionArray(existingRecord, incomingRecord, objectInfo);
|
|
16934
|
+
if (includesSpanningFields) {
|
|
16935
|
+
return {
|
|
16936
|
+
ok: false,
|
|
16937
|
+
code: 'conflict-spanning-record',
|
|
16938
|
+
fieldUnion: fields,
|
|
16939
|
+
hasDraft: false,
|
|
16940
|
+
};
|
|
16941
|
+
}
|
|
16867
16942
|
return {
|
|
16868
16943
|
ok: false,
|
|
16869
16944
|
code: 'conflict-missing-fields',
|
|
16870
|
-
fieldUnion:
|
|
16945
|
+
fieldUnion: fields,
|
|
16871
16946
|
hasDraft: false,
|
|
16872
16947
|
};
|
|
16873
16948
|
}
|
|
@@ -17793,30 +17868,36 @@ function getRuntime() {
|
|
|
17793
17868
|
const internalAdapterStore = new InMemoryStore();
|
|
17794
17869
|
let getIngestRecordsForInternalAdapters;
|
|
17795
17870
|
let getIngestMetadataForInternalAdapters;
|
|
17871
|
+
let getIngestStoreInternal;
|
|
17796
17872
|
const internalAdapterDurableStore = makeRecordDenormalizingDurableStore(lazyLuvio, lazyBaseDurableStore, () => getIngestRecordsForInternalAdapters !== undefined
|
|
17797
17873
|
? getIngestRecordsForInternalAdapters()
|
|
17798
17874
|
: {}, () => getIngestMetadataForInternalAdapters !== undefined
|
|
17799
17875
|
? getIngestMetadataForInternalAdapters()
|
|
17800
|
-
: {});
|
|
17876
|
+
: {}, () => (getIngestStoreInternal !== undefined ? getIngestStoreInternal() : undefined));
|
|
17801
17877
|
const { adapters: { getObjectInfo, getObjectInfos, getRecord, getObjectInfoDirectory }, durableEnvironment: internalAdapterDurableEnvironment, luvio: internalLuvio, } = buildInternalAdapters(internalAdapterStore, lazyNetworkAdapter, internalAdapterDurableStore, (apiName, objectInfo) => lazyObjectInfoService.ensureObjectInfoCached(apiName, objectInfo));
|
|
17802
17878
|
lazyInternalLuvio = internalLuvio;
|
|
17803
17879
|
getIngestRecordsForInternalAdapters =
|
|
17804
17880
|
internalAdapterDurableEnvironment.getIngestStagingStoreRecords;
|
|
17805
17881
|
getIngestMetadataForInternalAdapters =
|
|
17806
17882
|
internalAdapterDurableEnvironment.getIngestStagingStoreRecords;
|
|
17883
|
+
getIngestStoreInternal = internalAdapterDurableEnvironment.getIngestStagingStore;
|
|
17807
17884
|
lazyObjectInfoService = new ObjectInfoService(getObjectInfo, getObjectInfos, getObjectInfoDirectory, lazyBaseDurableStore);
|
|
17808
17885
|
// creates a durable store that denormalizes scalar fields for records
|
|
17809
17886
|
let getIngestRecords;
|
|
17810
17887
|
let getIngestMetadata;
|
|
17811
|
-
|
|
17888
|
+
let getIngestStore;
|
|
17889
|
+
const recordDenormingStore = makeRecordDenormalizingDurableStore(lazyLuvio, lazyBaseDurableStore, () => (getIngestRecords !== undefined ? getIngestRecords() : {}), () => (getIngestMetadata !== undefined ? getIngestMetadata() : {}), () => (getIngestStore !== undefined ? getIngestStore() : undefined));
|
|
17812
17890
|
const baseEnv = new Environment(store, lazyNetworkAdapter);
|
|
17813
17891
|
const gqlEnv = makeEnvironmentGraphqlAware(baseEnv);
|
|
17814
17892
|
const durableEnv = makeDurable(gqlEnv, {
|
|
17815
17893
|
durableStore: recordDenormingStore,
|
|
17816
17894
|
enableDurableMetadataRefresh: ldsMetadataRefreshEnabled.isOpen({ fallback: false }),
|
|
17895
|
+
// disable luvio deep freeze in headless environments
|
|
17896
|
+
disableDeepFreeze: typeof window === 'undefined',
|
|
17817
17897
|
});
|
|
17818
17898
|
getIngestRecords = durableEnv.getIngestStagingStoreRecords;
|
|
17819
17899
|
getIngestMetadata = durableEnv.getIngestStagingStoreMetadata;
|
|
17900
|
+
getIngestStore = durableEnv.getIngestStagingStore;
|
|
17820
17901
|
// draft queue
|
|
17821
17902
|
lazyDraftQueue = buildLdsDraftQueue(recordDenormingStore);
|
|
17822
17903
|
const draftService = new UiApiDraftRecordService(lazyDraftQueue, () => lazyLuvio, recordDenormingStore, getObjectInfo, newRecordId, userId, formatDisplayValue);
|
|
@@ -17916,4 +17997,4 @@ register({
|
|
|
17916
17997
|
});
|
|
17917
17998
|
|
|
17918
17999
|
export { O11Y_NAMESPACE_LDS_MOBILE, getRuntime, registerReportObserver, reportGraphqlQueryParseError };
|
|
17919
|
-
// version: 1.266.0-
|
|
18000
|
+
// version: 1.266.0-dev20-117d849b4
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/lds-runtime-mobile",
|
|
3
|
-
"version": "1.266.0-
|
|
3
|
+
"version": "1.266.0-dev20",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
5
5
|
"description": "LDS runtime for mobile/hybrid environments.",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -32,25 +32,25 @@
|
|
|
32
32
|
"release:corejar": "yarn build && ../core-build/scripts/core.js --name=lds-runtime-mobile"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@salesforce/lds-adapters-uiapi": "^1.266.0-
|
|
36
|
-
"@salesforce/lds-bindings": "^1.266.0-
|
|
37
|
-
"@salesforce/lds-instrumentation": "^1.266.0-
|
|
38
|
-
"@salesforce/lds-priming": "^1.266.0-
|
|
35
|
+
"@salesforce/lds-adapters-uiapi": "^1.266.0-dev20",
|
|
36
|
+
"@salesforce/lds-bindings": "^1.266.0-dev20",
|
|
37
|
+
"@salesforce/lds-instrumentation": "^1.266.0-dev20",
|
|
38
|
+
"@salesforce/lds-priming": "^1.266.0-dev20",
|
|
39
39
|
"@salesforce/user": "0.0.21",
|
|
40
40
|
"o11y": "244.0.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@salesforce/lds-adapters-graphql": "^1.266.0-
|
|
44
|
-
"@salesforce/lds-drafts": "^1.266.0-
|
|
45
|
-
"@salesforce/lds-drafts-adapters-uiapi": "^1.266.0-
|
|
46
|
-
"@salesforce/lds-graphql-eval": "^1.266.0-
|
|
47
|
-
"@salesforce/lds-network-adapter": "^1.266.0-
|
|
48
|
-
"@salesforce/lds-network-nimbus": "^1.266.0-
|
|
49
|
-
"@salesforce/lds-store-binary": "^1.266.0-
|
|
50
|
-
"@salesforce/lds-store-nimbus": "^1.266.0-
|
|
51
|
-
"@salesforce/lds-store-sql": "^1.266.0-
|
|
52
|
-
"@salesforce/lds-utils-adapters": "^1.266.0-
|
|
53
|
-
"@salesforce/nimbus-plugin-lds": "^1.266.0-
|
|
43
|
+
"@salesforce/lds-adapters-graphql": "^1.266.0-dev20",
|
|
44
|
+
"@salesforce/lds-drafts": "^1.266.0-dev20",
|
|
45
|
+
"@salesforce/lds-drafts-adapters-uiapi": "^1.266.0-dev20",
|
|
46
|
+
"@salesforce/lds-graphql-eval": "^1.266.0-dev20",
|
|
47
|
+
"@salesforce/lds-network-adapter": "^1.266.0-dev20",
|
|
48
|
+
"@salesforce/lds-network-nimbus": "^1.266.0-dev20",
|
|
49
|
+
"@salesforce/lds-store-binary": "^1.266.0-dev20",
|
|
50
|
+
"@salesforce/lds-store-nimbus": "^1.266.0-dev20",
|
|
51
|
+
"@salesforce/lds-store-sql": "^1.266.0-dev20",
|
|
52
|
+
"@salesforce/lds-utils-adapters": "^1.266.0-dev20",
|
|
53
|
+
"@salesforce/nimbus-plugin-lds": "^1.266.0-dev20",
|
|
54
54
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
|
55
55
|
"wait-for-expect": "^3.0.2"
|
|
56
56
|
},
|
package/sfdc/main.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { withRegistration, register } from 'native/ldsEngineMobile';
|
|
15
15
|
import { setupInstrumentation, instrumentAdapter as instrumentAdapter$1, instrumentLuvio, setLdsAdaptersUiapiInstrumentation, setLdsNetworkAdapterInstrumentation } from 'force/ldsInstrumentation';
|
|
16
|
-
import { HttpStatusCode, StoreKeySet, serializeStructuredKey, StringKeyInMemoryStore, Reader, deepFreeze, emitAdapterEvent, createCustomAdapterEventEmitter, StoreKeyMap, isFileReference, Environment, Luvio, InMemoryStore } from 'force/luvioEngine';
|
|
16
|
+
import { HttpStatusCode, setBypassDeepFreeze, 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, buildSchema, isObjectType, defaultFieldResolver, visit, execute, parse as parse$7, extendSchema, isScalarType } from 'force/ldsGraphqlParser';
|
|
19
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, getRecordsAdapterFactory } from 'force/ldsAdaptersUiapi';
|
|
@@ -1014,7 +1014,9 @@ function isUnfulfilledSnapshot$1(cachedSnapshotResult) {
|
|
|
1014
1014
|
* @param durableStore A DurableStore implementation
|
|
1015
1015
|
* @param instrumentation An instrumentation function implementation
|
|
1016
1016
|
*/
|
|
1017
|
-
function makeDurable(environment, { durableStore, instrumentation, useRevivingStore, enableDurableMetadataRefresh = false, }) {
|
|
1017
|
+
function makeDurable(environment, { durableStore, instrumentation, useRevivingStore, enableDurableMetadataRefresh = false, disableDeepFreeze = false, }) {
|
|
1018
|
+
// runtimes can choose to disable deepFreeze, e.g. headless mobile runtime
|
|
1019
|
+
setBypassDeepFreeze(disableDeepFreeze);
|
|
1018
1020
|
let stagingStore = null;
|
|
1019
1021
|
const durableTTLStore = new DurableTTLStore(durableStore);
|
|
1020
1022
|
const mergeKeysPromiseMap = new Map();
|
|
@@ -1385,6 +1387,10 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
|
|
|
1385
1387
|
}
|
|
1386
1388
|
return {};
|
|
1387
1389
|
};
|
|
1390
|
+
const getIngestStagingStore = function () {
|
|
1391
|
+
validateNotDisposed();
|
|
1392
|
+
return stagingStore === null || stagingStore === void 0 ? void 0 : stagingStore.fallbackStringKeyInMemoryStore;
|
|
1393
|
+
};
|
|
1388
1394
|
const handleSuccessResponse = async function (ingestAndBroadcastFunc, getResponseCacheKeysFunc) {
|
|
1389
1395
|
validateNotDisposed();
|
|
1390
1396
|
const cacheKeyMap = getResponseCacheKeysFunc();
|
|
@@ -1577,6 +1583,7 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
|
|
|
1577
1583
|
applyCachePolicy: { value: applyCachePolicy },
|
|
1578
1584
|
getIngestStagingStoreRecords: { value: getIngestStagingStoreRecords },
|
|
1579
1585
|
getIngestStagingStoreMetadata: { value: getIngestStagingStoreMetadata },
|
|
1586
|
+
getIngestStagingStore: { value: getIngestStagingStore },
|
|
1580
1587
|
handleSuccessResponse: { value: handleSuccessResponse },
|
|
1581
1588
|
handleErrorResponse: { value: handleErrorResponse },
|
|
1582
1589
|
getNotifyChangeStoreEntries: { value: getNotifyChangeStoreEntries },
|
|
@@ -4374,9 +4381,10 @@ function rootRecordQuery(selection, input) {
|
|
|
4374
4381
|
// If there is no metadata for this query or it somehow lacks a timestamp
|
|
4375
4382
|
// skip setting the root timestamp
|
|
4376
4383
|
if (queryMetadata !== undefined && queryMetadata.ingestionTimestamp !== undefined) {
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4384
|
+
const timestamp = Number(queryMetadata.ingestionTimestamp);
|
|
4385
|
+
if (!isNaN(timestamp)) {
|
|
4386
|
+
input.rootTimestamp = timestamp;
|
|
4387
|
+
}
|
|
4380
4388
|
}
|
|
4381
4389
|
}
|
|
4382
4390
|
return recordQuery(selection, alias, apiName, [], input);
|
|
@@ -5842,7 +5850,12 @@ class DurableDraftQueue {
|
|
|
5842
5850
|
}
|
|
5843
5851
|
finally {
|
|
5844
5852
|
this.replacingAction = undefined;
|
|
5845
|
-
|
|
5853
|
+
try {
|
|
5854
|
+
await this.startQueueSafe();
|
|
5855
|
+
}
|
|
5856
|
+
catch (_a) {
|
|
5857
|
+
// An error starting the queue should not bubble up from this method
|
|
5858
|
+
}
|
|
5846
5859
|
}
|
|
5847
5860
|
return updatedTarget;
|
|
5848
5861
|
});
|
|
@@ -8005,6 +8018,9 @@ function createSinglePredicate(val, operator, field, alias) {
|
|
|
8005
8018
|
else if (field.apiName === 'weakEtag') {
|
|
8006
8019
|
leftPath = '$.weakEtag';
|
|
8007
8020
|
}
|
|
8021
|
+
else if (field.apiName === 'RecordTypeId') {
|
|
8022
|
+
leftPath = '$.recordTypeId';
|
|
8023
|
+
}
|
|
8008
8024
|
return {
|
|
8009
8025
|
alias,
|
|
8010
8026
|
leftPath,
|
|
@@ -9041,6 +9057,20 @@ function findFieldInfo(objectInfo, fieldName) {
|
|
|
9041
9057
|
return values$2(objectInfo.fields).find((field) => field.apiName === fieldName ||
|
|
9042
9058
|
(field.dataType === 'Reference' && field.relationshipName === fieldName));
|
|
9043
9059
|
}
|
|
9060
|
+
async function readIngestionTimestampForKey(key, query) {
|
|
9061
|
+
let ingestionTimestamp = 0;
|
|
9062
|
+
const sql = `SELECT json_extract(metadata, '${JSON_EXTRACT_PATH_INGESTION_TIMESTAMP}') FROM lds_data WHERE key IS ?`;
|
|
9063
|
+
const results = await query(sql, [key]);
|
|
9064
|
+
const [timestamp] = results.rows.map((row) => row[0]);
|
|
9065
|
+
if (timestamp !== null) {
|
|
9066
|
+
const numericalTimestamp = Number(timestamp);
|
|
9067
|
+
if (isNaN(numericalTimestamp)) {
|
|
9068
|
+
return ingestionTimestamp;
|
|
9069
|
+
}
|
|
9070
|
+
ingestionTimestamp = numericalTimestamp;
|
|
9071
|
+
}
|
|
9072
|
+
return ingestionTimestamp;
|
|
9073
|
+
}
|
|
9044
9074
|
|
|
9045
9075
|
function findSpanningField(name) {
|
|
9046
9076
|
return (field) => {
|
|
@@ -9365,6 +9395,12 @@ function addResolversToSchema(schema, polyFields) {
|
|
|
9365
9395
|
break;
|
|
9366
9396
|
case 'LastModifiedDate':
|
|
9367
9397
|
field.resolve = ({ recordRepresentation: record }) => {
|
|
9398
|
+
// In UIAPI record reps, LastModifiedDate might be present as a field,
|
|
9399
|
+
// which will include both the value and displayValue
|
|
9400
|
+
if (record.fields['LastModifiedDate']) {
|
|
9401
|
+
return record.fields['LastModifiedDate'];
|
|
9402
|
+
}
|
|
9403
|
+
// If the field is not present, just return the value of the root property
|
|
9368
9404
|
return record.lastModifiedDate
|
|
9369
9405
|
? { value: record.lastModifiedDate }
|
|
9370
9406
|
: null;
|
|
@@ -9399,16 +9435,26 @@ function addResolversToSchema(schema, polyFields) {
|
|
|
9399
9435
|
: null;
|
|
9400
9436
|
};
|
|
9401
9437
|
const { recordRepresentation: record, ingestionTimestamp } = obj;
|
|
9402
|
-
|
|
9403
|
-
|
|
9404
|
-
|
|
9405
|
-
|
|
9406
|
-
|
|
9407
|
-
|
|
9408
|
-
if (
|
|
9438
|
+
let id = undefined;
|
|
9439
|
+
if (field.name === 'RecordType') {
|
|
9440
|
+
// RecordTypeId has special handling during ingest and is
|
|
9441
|
+
// not in record.fields, so check for it at the UIAPI root property location
|
|
9442
|
+
id = record.recordTypeId;
|
|
9443
|
+
}
|
|
9444
|
+
else if (field.name.endsWith('__r')) {
|
|
9445
|
+
// Custom relationships end in `__r` and the corresponding ID field should be `__c`
|
|
9446
|
+
let fieldName = field.name.replace('__r', '__c');
|
|
9447
|
+
id = record.fields[fieldName] && record.fields[fieldName].value;
|
|
9448
|
+
}
|
|
9449
|
+
else {
|
|
9450
|
+
// Standard relationships are just FieldNameId
|
|
9451
|
+
let fieldName = field.name + 'Id';
|
|
9452
|
+
id = record.fields[fieldName] && record.fields[fieldName].value;
|
|
9453
|
+
}
|
|
9454
|
+
if (!id || typeof id !== 'string') {
|
|
9455
|
+
// possibly field injection did not inject the necessary Id field
|
|
9456
|
+
// for the relationship, or we found a non-string value.
|
|
9409
9457
|
return null;
|
|
9410
|
-
if (id['__ref'] !== undefined) {
|
|
9411
|
-
return fetchRecordOrNull(record.fields[`${field.name}Id`].value);
|
|
9412
9458
|
}
|
|
9413
9459
|
seenRecordIds.add(id);
|
|
9414
9460
|
return fetchRecordOrNull(id);
|
|
@@ -9560,18 +9606,7 @@ async function fetchIngestionTimeStampFromDatabase(apiName, info, args, query) {
|
|
|
9560
9606
|
const key = buildKeyStringForRecordQuery(operation,
|
|
9561
9607
|
// join varables passed from query to the argument variables given from the AST
|
|
9562
9608
|
{ ...variableValues, ...args }, info.fieldNodes[0].arguments, apiName);
|
|
9563
|
-
|
|
9564
|
-
SELECT json_extract(metadata, '${JSON_EXTRACT_PATH_INGESTION_TIMESTAMP}')
|
|
9565
|
-
FROM lds_data
|
|
9566
|
-
WHERE key IS ?
|
|
9567
|
-
`;
|
|
9568
|
-
const results = await query(sql, [key]);
|
|
9569
|
-
const [timestamp] = results.rows.map((row) => row[0]);
|
|
9570
|
-
if (timestamp !== null && typeof timestamp === 'number') {
|
|
9571
|
-
// adjust the timestamp to account for ingestion processing time
|
|
9572
|
-
// 30s is used because this is the default record TTL
|
|
9573
|
-
ingestionTimestamp = timestamp - 30000;
|
|
9574
|
-
}
|
|
9609
|
+
return readIngestionTimestampForKey(key, query);
|
|
9575
9610
|
}
|
|
9576
9611
|
return ingestionTimestamp;
|
|
9577
9612
|
}
|
|
@@ -11638,7 +11673,7 @@ function createUserJsonOutput(selection, jsonInput, jsonOutput) {
|
|
|
11638
11673
|
function createjsonOutput(selections, jsonInput, jsonOutput) {
|
|
11639
11674
|
const keys$1 = keys$4(jsonInput);
|
|
11640
11675
|
selections.filter(isFieldNode).forEach((subSelection) => {
|
|
11641
|
-
const fieldName = subSelection.name.value;
|
|
11676
|
+
const fieldName = subSelection.alias ? subSelection.alias.value : subSelection.name.value;
|
|
11642
11677
|
if (keys$1.includes(fieldName)) {
|
|
11643
11678
|
if (isArray$2(jsonInput[fieldName])) {
|
|
11644
11679
|
jsonOutput[fieldName] = [];
|
|
@@ -12358,13 +12393,21 @@ function buildSyntheticRecordRepresentation(luvio, createOperation, userId, obje
|
|
|
12358
12393
|
draftFields[DEFAULT_FIELD_LAST_MODIFIED_DATE] = { value: timestampString, displayValue: null };
|
|
12359
12394
|
draftFields[DEFAULT_FIELD_OWNER_ID] = { value: userId, displayValue: null };
|
|
12360
12395
|
draftFields[DEFAULT_FIELD_ID] = { value: recordId, displayValue: null };
|
|
12361
|
-
|
|
12362
|
-
|
|
12363
|
-
|
|
12364
|
-
|
|
12365
|
-
|
|
12366
|
-
|
|
12367
|
-
|
|
12396
|
+
const allObjectFields = keys$3(objectInfo.fields);
|
|
12397
|
+
allObjectFields.forEach((fieldName) => {
|
|
12398
|
+
if (draftFields[fieldName] === undefined) {
|
|
12399
|
+
draftFields[fieldName] = { value: null, displayValue: null };
|
|
12400
|
+
}
|
|
12401
|
+
});
|
|
12402
|
+
// TODO [W-14915806]: lightning-record-form injects the `IsPersonAccount`
|
|
12403
|
+
// field for all `Account` and `PersonAccount` records. However, not all
|
|
12404
|
+
// orgs use person accounts, and if that field is not present in the object
|
|
12405
|
+
// info then it is not synthesized. We force it to be synthesized here to
|
|
12406
|
+
// ensure lightning-record-form will work correctly with draft-created
|
|
12407
|
+
// accounts.
|
|
12408
|
+
if ((apiName === 'Account' || apiName === 'PersonAccount') &&
|
|
12409
|
+
draftFields['IsPersonAccount'] === undefined) {
|
|
12410
|
+
draftFields['IsPersonAccount'] = { value: null, displayValue: null };
|
|
12368
12411
|
}
|
|
12369
12412
|
return {
|
|
12370
12413
|
id: recordId,
|
|
@@ -12951,10 +12994,13 @@ function normalizeRecordFields(key, entry) {
|
|
|
12951
12994
|
* Transforms a record for storage in the durable store. The transformation involves denormalizing
|
|
12952
12995
|
* scalar fields and persisting link metadata to transform back into a normalized representation
|
|
12953
12996
|
*
|
|
12997
|
+
* If the record contains pending fields this will return undefined as pending records do not get persisted
|
|
12998
|
+
* to the durable store. There should be a refresh operation outbound that will bring in the updated record.
|
|
12999
|
+
*
|
|
12954
13000
|
* @param normalizedRecord Record containing normalized field links
|
|
12955
13001
|
* @param recordStore a store containing referenced record fields
|
|
12956
13002
|
*/
|
|
12957
|
-
function buildDurableRecordRepresentation(normalizedRecord, records, pendingEntries) {
|
|
13003
|
+
function buildDurableRecordRepresentation(normalizedRecord, records, pendingEntries, store) {
|
|
12958
13004
|
const fields = normalizedRecord.fields;
|
|
12959
13005
|
const filteredFields = {};
|
|
12960
13006
|
const links = {};
|
|
@@ -12965,7 +13011,9 @@ function buildDurableRecordRepresentation(normalizedRecord, records, pendingEntr
|
|
|
12965
13011
|
// pending fields get filtered out of the durable store
|
|
12966
13012
|
const { pending } = field;
|
|
12967
13013
|
if (pending === true) {
|
|
12968
|
-
|
|
13014
|
+
// do not write records with pending fields to the durable store
|
|
13015
|
+
// there should be a refresh operation outbound that will bring in the updated record
|
|
13016
|
+
return undefined;
|
|
12969
13017
|
}
|
|
12970
13018
|
const { __ref } = field;
|
|
12971
13019
|
if (__ref !== undefined) {
|
|
@@ -12981,6 +13029,19 @@ function buildDurableRecordRepresentation(normalizedRecord, records, pendingEntr
|
|
|
12981
13029
|
if (ref !== undefined) {
|
|
12982
13030
|
filteredFields[fieldName] = ref;
|
|
12983
13031
|
}
|
|
13032
|
+
else {
|
|
13033
|
+
// if we have a store to read, try to find the field there too
|
|
13034
|
+
// The durable ingest staging store may pass through to L1, and
|
|
13035
|
+
// not all fields are necessarily published every time, so it is
|
|
13036
|
+
// important to check L1 and not just the fields being published,
|
|
13037
|
+
// otherwise we risk truncating the fields on the record.
|
|
13038
|
+
if (store) {
|
|
13039
|
+
ref = store.readEntry(__ref);
|
|
13040
|
+
if (ref !== undefined) {
|
|
13041
|
+
filteredFields[fieldName] = ref;
|
|
13042
|
+
}
|
|
13043
|
+
}
|
|
13044
|
+
}
|
|
12984
13045
|
}
|
|
12985
13046
|
// we want to preserve fields that are missing nodes
|
|
12986
13047
|
if (filteredFields[fieldName] !== undefined || field.isMissing === true) {
|
|
@@ -13002,7 +13063,7 @@ function getDenormalizedKey(originalKey, recordId, luvio) {
|
|
|
13002
13063
|
}
|
|
13003
13064
|
return keyBuilderRecord(luvio, { recordId });
|
|
13004
13065
|
}
|
|
13005
|
-
function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecords, getStoreMetadata) {
|
|
13066
|
+
function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecords, getStoreMetadata, getStore) {
|
|
13006
13067
|
const getEntries = function (entries, segment) {
|
|
13007
13068
|
// this HOF only inspects records in the default segment
|
|
13008
13069
|
if (segment !== DefaultDurableSegment) {
|
|
@@ -13070,6 +13131,7 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
|
|
|
13070
13131
|
const putRecordViews = {};
|
|
13071
13132
|
const storeRecords = getStoreRecords !== undefined ? getStoreRecords() : {};
|
|
13072
13133
|
const storeMetadata = getStoreMetadata !== undefined ? getStoreMetadata() : {};
|
|
13134
|
+
const store = getStore();
|
|
13073
13135
|
for (let i = 0, len = keys$1.length; i < len; i++) {
|
|
13074
13136
|
const key = keys$1[i];
|
|
13075
13137
|
let value = entries[key];
|
|
@@ -13116,11 +13178,13 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
|
|
|
13116
13178
|
metadataVersion: DURABLE_METADATA_VERSION,
|
|
13117
13179
|
};
|
|
13118
13180
|
}
|
|
13119
|
-
const denormalizedRecord = buildDurableRecordRepresentation(record, storeRecords, recordEntries);
|
|
13120
|
-
|
|
13121
|
-
|
|
13122
|
-
|
|
13123
|
-
|
|
13181
|
+
const denormalizedRecord = buildDurableRecordRepresentation(record, storeRecords, recordEntries, store);
|
|
13182
|
+
if (denormalizedRecord !== undefined) {
|
|
13183
|
+
putEntries[recordKey] = {
|
|
13184
|
+
data: denormalizedRecord,
|
|
13185
|
+
metadata,
|
|
13186
|
+
};
|
|
13187
|
+
}
|
|
13124
13188
|
}
|
|
13125
13189
|
else {
|
|
13126
13190
|
putEntries[key] = value;
|
|
@@ -15948,9 +16012,9 @@ function instrumentAdapter(adapter, metadata) {
|
|
|
15948
16012
|
}
|
|
15949
16013
|
}
|
|
15950
16014
|
return instrumentAdapter$1(instrumentedMobileAdapter, metadata, {
|
|
15951
|
-
trackL1Hits:
|
|
15952
|
-
trackL2Hits:
|
|
15953
|
-
trackCacheMisses:
|
|
16015
|
+
trackL1Hits: false,
|
|
16016
|
+
trackL2Hits: false,
|
|
16017
|
+
trackCacheMisses: false,
|
|
15954
16018
|
reportObserver: (report) => {
|
|
15955
16019
|
for (const observer of reportObservers) {
|
|
15956
16020
|
observer(report);
|
|
@@ -16757,6 +16821,7 @@ function findReferenceFieldForSpanningField(fieldName, objectInfo) {
|
|
|
16757
16821
|
function buildFieldUnionArray(existingRecord, incomingRecord, objectInfo) {
|
|
16758
16822
|
const allFields = Array.from(new Set([...Object.keys(existingRecord.fields), ...Object.keys(incomingRecord.fields)]));
|
|
16759
16823
|
const fieldUnion = [];
|
|
16824
|
+
let includesSpanningFields = false;
|
|
16760
16825
|
allFields.forEach((fieldName) => {
|
|
16761
16826
|
const objectInfoField = objectInfo.fields[fieldName];
|
|
16762
16827
|
if (objectInfoField === undefined) {
|
|
@@ -16764,13 +16829,14 @@ function buildFieldUnionArray(existingRecord, incomingRecord, objectInfo) {
|
|
|
16764
16829
|
const referenceField = findReferenceFieldForSpanningField(fieldName, objectInfo);
|
|
16765
16830
|
if (referenceField !== undefined) {
|
|
16766
16831
|
fieldUnion.push(`${fieldName}.Id`);
|
|
16832
|
+
includesSpanningFields = true;
|
|
16767
16833
|
}
|
|
16768
16834
|
}
|
|
16769
16835
|
else {
|
|
16770
16836
|
fieldUnion.push(fieldName);
|
|
16771
16837
|
}
|
|
16772
16838
|
});
|
|
16773
|
-
return fieldUnion;
|
|
16839
|
+
return { fields: fieldUnion, includesSpanningFields };
|
|
16774
16840
|
}
|
|
16775
16841
|
/**
|
|
16776
16842
|
* Merges (if possible) an incoming record from a priming session with an existing record in the durable store.
|
|
@@ -16802,7 +16868,7 @@ function mergeRecord(existingRecord, incomingRecord, objectInfo) {
|
|
|
16802
16868
|
ok: false,
|
|
16803
16869
|
code: 'conflict-drafts',
|
|
16804
16870
|
hasDraft: true,
|
|
16805
|
-
fieldUnion: buildFieldUnionArray(existingRecord, incomingRecord, objectInfo),
|
|
16871
|
+
fieldUnion: buildFieldUnionArray(existingRecord, incomingRecord, objectInfo).fields,
|
|
16806
16872
|
};
|
|
16807
16873
|
}
|
|
16808
16874
|
// Check if incoming record's Etag is equal to the existing one
|
|
@@ -16864,10 +16930,19 @@ function mergeRecord(existingRecord, incomingRecord, objectInfo) {
|
|
|
16864
16930
|
};
|
|
16865
16931
|
}
|
|
16866
16932
|
// If Etags do not match and the incoming record does not contain all fields, re-request the record
|
|
16933
|
+
const { fields, includesSpanningFields } = buildFieldUnionArray(existingRecord, incomingRecord, objectInfo);
|
|
16934
|
+
if (includesSpanningFields) {
|
|
16935
|
+
return {
|
|
16936
|
+
ok: false,
|
|
16937
|
+
code: 'conflict-spanning-record',
|
|
16938
|
+
fieldUnion: fields,
|
|
16939
|
+
hasDraft: false,
|
|
16940
|
+
};
|
|
16941
|
+
}
|
|
16867
16942
|
return {
|
|
16868
16943
|
ok: false,
|
|
16869
16944
|
code: 'conflict-missing-fields',
|
|
16870
|
-
fieldUnion:
|
|
16945
|
+
fieldUnion: fields,
|
|
16871
16946
|
hasDraft: false,
|
|
16872
16947
|
};
|
|
16873
16948
|
}
|
|
@@ -17793,30 +17868,36 @@ function getRuntime() {
|
|
|
17793
17868
|
const internalAdapterStore = new InMemoryStore();
|
|
17794
17869
|
let getIngestRecordsForInternalAdapters;
|
|
17795
17870
|
let getIngestMetadataForInternalAdapters;
|
|
17871
|
+
let getIngestStoreInternal;
|
|
17796
17872
|
const internalAdapterDurableStore = makeRecordDenormalizingDurableStore(lazyLuvio, lazyBaseDurableStore, () => getIngestRecordsForInternalAdapters !== undefined
|
|
17797
17873
|
? getIngestRecordsForInternalAdapters()
|
|
17798
17874
|
: {}, () => getIngestMetadataForInternalAdapters !== undefined
|
|
17799
17875
|
? getIngestMetadataForInternalAdapters()
|
|
17800
|
-
: {});
|
|
17876
|
+
: {}, () => (getIngestStoreInternal !== undefined ? getIngestStoreInternal() : undefined));
|
|
17801
17877
|
const { adapters: { getObjectInfo, getObjectInfos, getRecord, getObjectInfoDirectory }, durableEnvironment: internalAdapterDurableEnvironment, luvio: internalLuvio, } = buildInternalAdapters(internalAdapterStore, lazyNetworkAdapter, internalAdapterDurableStore, (apiName, objectInfo) => lazyObjectInfoService.ensureObjectInfoCached(apiName, objectInfo));
|
|
17802
17878
|
lazyInternalLuvio = internalLuvio;
|
|
17803
17879
|
getIngestRecordsForInternalAdapters =
|
|
17804
17880
|
internalAdapterDurableEnvironment.getIngestStagingStoreRecords;
|
|
17805
17881
|
getIngestMetadataForInternalAdapters =
|
|
17806
17882
|
internalAdapterDurableEnvironment.getIngestStagingStoreRecords;
|
|
17883
|
+
getIngestStoreInternal = internalAdapterDurableEnvironment.getIngestStagingStore;
|
|
17807
17884
|
lazyObjectInfoService = new ObjectInfoService(getObjectInfo, getObjectInfos, getObjectInfoDirectory, lazyBaseDurableStore);
|
|
17808
17885
|
// creates a durable store that denormalizes scalar fields for records
|
|
17809
17886
|
let getIngestRecords;
|
|
17810
17887
|
let getIngestMetadata;
|
|
17811
|
-
|
|
17888
|
+
let getIngestStore;
|
|
17889
|
+
const recordDenormingStore = makeRecordDenormalizingDurableStore(lazyLuvio, lazyBaseDurableStore, () => (getIngestRecords !== undefined ? getIngestRecords() : {}), () => (getIngestMetadata !== undefined ? getIngestMetadata() : {}), () => (getIngestStore !== undefined ? getIngestStore() : undefined));
|
|
17812
17890
|
const baseEnv = new Environment(store, lazyNetworkAdapter);
|
|
17813
17891
|
const gqlEnv = makeEnvironmentGraphqlAware(baseEnv);
|
|
17814
17892
|
const durableEnv = makeDurable(gqlEnv, {
|
|
17815
17893
|
durableStore: recordDenormingStore,
|
|
17816
17894
|
enableDurableMetadataRefresh: ldsMetadataRefreshEnabled.isOpen({ fallback: false }),
|
|
17895
|
+
// disable luvio deep freeze in headless environments
|
|
17896
|
+
disableDeepFreeze: typeof window === 'undefined',
|
|
17817
17897
|
});
|
|
17818
17898
|
getIngestRecords = durableEnv.getIngestStagingStoreRecords;
|
|
17819
17899
|
getIngestMetadata = durableEnv.getIngestStagingStoreMetadata;
|
|
17900
|
+
getIngestStore = durableEnv.getIngestStagingStore;
|
|
17820
17901
|
// draft queue
|
|
17821
17902
|
lazyDraftQueue = buildLdsDraftQueue(recordDenormingStore);
|
|
17822
17903
|
const draftService = new UiApiDraftRecordService(lazyDraftQueue, () => lazyLuvio, recordDenormingStore, getObjectInfo, newRecordId, userId, formatDisplayValue);
|
|
@@ -17916,4 +17997,4 @@ register({
|
|
|
17916
17997
|
});
|
|
17917
17998
|
|
|
17918
17999
|
export { O11Y_NAMESPACE_LDS_MOBILE, getRuntime, registerReportObserver, reportGraphqlQueryParseError };
|
|
17919
|
-
// version: 1.266.0-
|
|
18000
|
+
// version: 1.266.0-dev20-117d849b4
|