@salesforce/lds-runtime-bridge 1.266.0-dev2 → 1.266.0-dev21

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.
@@ -12,7 +12,7 @@
12
12
  * *******************************************************************************************
13
13
  */
14
14
  import { setDefaultLuvio } from 'force/ldsEngine';
15
- import { StoreKeySet, serializeStructuredKey, StringKeyInMemoryStore, Reader, deepFreeze, emitAdapterEvent, InMemoryStore, Environment, Luvio } from 'force/luvioEngine';
15
+ import { setBypassDeepFreeze, StoreKeySet, serializeStructuredKey, StringKeyInMemoryStore, Reader, deepFreeze, emitAdapterEvent, InMemoryStore, Environment, Luvio } from 'force/luvioEngine';
16
16
  import { instrumentLuvio } from 'force/ldsInstrumentation';
17
17
  import { isStoreKeyRecordViewEntity, RECORD_ID_PREFIX, RECORD_FIELDS_KEY_JUNCTION, getRecordId18, extractRecordIdFromStoreKey, RECORD_VIEW_ENTITY_ID_PREFIX, keyBuilderRecord } from 'force/ldsAdaptersUiapi';
18
18
  import '@salesforce/gate/lds.idempotencyWriteDisabled';
@@ -529,7 +529,9 @@ function isUnfulfilledSnapshot(cachedSnapshotResult) {
529
529
  * @param durableStore A DurableStore implementation
530
530
  * @param instrumentation An instrumentation function implementation
531
531
  */
532
- function makeDurable(environment, { durableStore, instrumentation, useRevivingStore, enableDurableMetadataRefresh = false, }) {
532
+ function makeDurable(environment, { durableStore, instrumentation, useRevivingStore, enableDurableMetadataRefresh = false, disableDeepFreeze = false, }) {
533
+ // runtimes can choose to disable deepFreeze, e.g. headless mobile runtime
534
+ setBypassDeepFreeze(disableDeepFreeze);
533
535
  let stagingStore = null;
534
536
  const durableTTLStore = new DurableTTLStore(durableStore);
535
537
  const mergeKeysPromiseMap = new Map();
@@ -900,6 +902,10 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
900
902
  }
901
903
  return {};
902
904
  };
905
+ const getIngestStagingStore = function () {
906
+ validateNotDisposed();
907
+ return stagingStore === null || stagingStore === void 0 ? void 0 : stagingStore.fallbackStringKeyInMemoryStore;
908
+ };
903
909
  const handleSuccessResponse = async function (ingestAndBroadcastFunc, getResponseCacheKeysFunc) {
904
910
  validateNotDisposed();
905
911
  const cacheKeyMap = getResponseCacheKeysFunc();
@@ -1092,6 +1098,7 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
1092
1098
  applyCachePolicy: { value: applyCachePolicy },
1093
1099
  getIngestStagingStoreRecords: { value: getIngestStagingStoreRecords },
1094
1100
  getIngestStagingStoreMetadata: { value: getIngestStagingStoreMetadata },
1101
+ getIngestStagingStore: { value: getIngestStagingStore },
1095
1102
  handleSuccessResponse: { value: handleSuccessResponse },
1096
1103
  handleErrorResponse: { value: handleErrorResponse },
1097
1104
  getNotifyChangeStoreEntries: { value: getNotifyChangeStoreEntries },
@@ -2531,6 +2538,9 @@ function createSinglePredicate(val, operator, field, alias) {
2531
2538
  else if (field.apiName === 'weakEtag') {
2532
2539
  leftPath = '$.weakEtag';
2533
2540
  }
2541
+ else if (field.apiName === 'RecordTypeId') {
2542
+ leftPath = '$.recordTypeId';
2543
+ }
2534
2544
  return {
2535
2545
  alias,
2536
2546
  leftPath,
@@ -3006,6 +3016,20 @@ function findFieldInfo(objectInfo, fieldName) {
3006
3016
  return values$1(objectInfo.fields).find((field) => field.apiName === fieldName ||
3007
3017
  (field.dataType === 'Reference' && field.relationshipName === fieldName));
3008
3018
  }
3019
+ async function readIngestionTimestampForKey(key, query) {
3020
+ let ingestionTimestamp = 0;
3021
+ const sql = `SELECT json_extract(metadata, '${JSON_EXTRACT_PATH_INGESTION_TIMESTAMP}') FROM lds_data WHERE key IS ?`;
3022
+ const results = await query(sql, [key]);
3023
+ const [timestamp] = results.rows.map((row) => row[0]);
3024
+ if (timestamp !== null) {
3025
+ const numericalTimestamp = Number(timestamp);
3026
+ if (isNaN(numericalTimestamp)) {
3027
+ return ingestionTimestamp;
3028
+ }
3029
+ ingestionTimestamp = numericalTimestamp;
3030
+ }
3031
+ return ingestionTimestamp;
3032
+ }
3009
3033
 
3010
3034
  function findSpanningField(name) {
3011
3035
  return (field) => {
@@ -3330,6 +3354,12 @@ function addResolversToSchema(schema, polyFields) {
3330
3354
  break;
3331
3355
  case 'LastModifiedDate':
3332
3356
  field.resolve = ({ recordRepresentation: record }) => {
3357
+ // In UIAPI record reps, LastModifiedDate might be present as a field,
3358
+ // which will include both the value and displayValue
3359
+ if (record.fields['LastModifiedDate']) {
3360
+ return record.fields['LastModifiedDate'];
3361
+ }
3362
+ // If the field is not present, just return the value of the root property
3333
3363
  return record.lastModifiedDate
3334
3364
  ? { value: record.lastModifiedDate }
3335
3365
  : null;
@@ -3364,16 +3394,26 @@ function addResolversToSchema(schema, polyFields) {
3364
3394
  : null;
3365
3395
  };
3366
3396
  const { recordRepresentation: record, ingestionTimestamp } = obj;
3367
- const fieldName = field.name.endsWith('__r')
3368
- ? field.name.replace('__r', '__c')
3369
- : field.name;
3370
- const id = (record.fields[fieldName] && record.fields[fieldName].value) ||
3371
- (record.fields[`${fieldName}Id`] &&
3372
- record.fields[`${fieldName}Id`].value);
3373
- if (!id)
3397
+ let id = undefined;
3398
+ if (field.name === 'RecordType') {
3399
+ // RecordTypeId has special handling during ingest and is
3400
+ // not in record.fields, so check for it at the UIAPI root property location
3401
+ id = record.recordTypeId;
3402
+ }
3403
+ else if (field.name.endsWith('__r')) {
3404
+ // Custom relationships end in `__r` and the corresponding ID field should be `__c`
3405
+ let fieldName = field.name.replace('__r', '__c');
3406
+ id = record.fields[fieldName] && record.fields[fieldName].value;
3407
+ }
3408
+ else {
3409
+ // Standard relationships are just FieldNameId
3410
+ let fieldName = field.name + 'Id';
3411
+ id = record.fields[fieldName] && record.fields[fieldName].value;
3412
+ }
3413
+ if (!id || typeof id !== 'string') {
3414
+ // possibly field injection did not inject the necessary Id field
3415
+ // for the relationship, or we found a non-string value.
3374
3416
  return null;
3375
- if (id['__ref'] !== undefined) {
3376
- return fetchRecordOrNull(record.fields[`${field.name}Id`].value);
3377
3417
  }
3378
3418
  seenRecordIds.add(id);
3379
3419
  return fetchRecordOrNull(id);
@@ -3525,18 +3565,7 @@ async function fetchIngestionTimeStampFromDatabase(apiName, info, args, query) {
3525
3565
  const key = buildKeyStringForRecordQuery(operation,
3526
3566
  // join varables passed from query to the argument variables given from the AST
3527
3567
  { ...variableValues, ...args }, info.fieldNodes[0].arguments, apiName);
3528
- const sql = `
3529
- SELECT json_extract(metadata, '${JSON_EXTRACT_PATH_INGESTION_TIMESTAMP}')
3530
- FROM lds_data
3531
- WHERE key IS ?
3532
- `;
3533
- const results = await query(sql, [key]);
3534
- const [timestamp] = results.rows.map((row) => row[0]);
3535
- if (timestamp !== null && typeof timestamp === 'number') {
3536
- // adjust the timestamp to account for ingestion processing time
3537
- // 30s is used because this is the default record TTL
3538
- ingestionTimestamp = timestamp - 30000;
3539
- }
3568
+ return readIngestionTimestampForKey(key, query);
3540
3569
  }
3541
3570
  return ingestionTimestamp;
3542
3571
  }
@@ -3653,10 +3682,13 @@ function normalizeRecordFields(key, entry) {
3653
3682
  * Transforms a record for storage in the durable store. The transformation involves denormalizing
3654
3683
  * scalar fields and persisting link metadata to transform back into a normalized representation
3655
3684
  *
3685
+ * If the record contains pending fields this will return undefined as pending records do not get persisted
3686
+ * to the durable store. There should be a refresh operation outbound that will bring in the updated record.
3687
+ *
3656
3688
  * @param normalizedRecord Record containing normalized field links
3657
3689
  * @param recordStore a store containing referenced record fields
3658
3690
  */
3659
- function buildDurableRecordRepresentation(normalizedRecord, records, pendingEntries) {
3691
+ function buildDurableRecordRepresentation(normalizedRecord, records, pendingEntries, store) {
3660
3692
  const fields = normalizedRecord.fields;
3661
3693
  const filteredFields = {};
3662
3694
  const links = {};
@@ -3667,7 +3699,9 @@ function buildDurableRecordRepresentation(normalizedRecord, records, pendingEntr
3667
3699
  // pending fields get filtered out of the durable store
3668
3700
  const { pending } = field;
3669
3701
  if (pending === true) {
3670
- continue;
3702
+ // do not write records with pending fields to the durable store
3703
+ // there should be a refresh operation outbound that will bring in the updated record
3704
+ return undefined;
3671
3705
  }
3672
3706
  const { __ref } = field;
3673
3707
  if (__ref !== undefined) {
@@ -3683,6 +3717,19 @@ function buildDurableRecordRepresentation(normalizedRecord, records, pendingEntr
3683
3717
  if (ref !== undefined) {
3684
3718
  filteredFields[fieldName] = ref;
3685
3719
  }
3720
+ else {
3721
+ // if we have a store to read, try to find the field there too
3722
+ // The durable ingest staging store may pass through to L1, and
3723
+ // not all fields are necessarily published every time, so it is
3724
+ // important to check L1 and not just the fields being published,
3725
+ // otherwise we risk truncating the fields on the record.
3726
+ if (store) {
3727
+ ref = store.readEntry(__ref);
3728
+ if (ref !== undefined) {
3729
+ filteredFields[fieldName] = ref;
3730
+ }
3731
+ }
3732
+ }
3686
3733
  }
3687
3734
  // we want to preserve fields that are missing nodes
3688
3735
  if (filteredFields[fieldName] !== undefined || field.isMissing === true) {
@@ -3704,7 +3751,7 @@ function getDenormalizedKey(originalKey, recordId, luvio) {
3704
3751
  }
3705
3752
  return keyBuilderRecord(luvio, { recordId });
3706
3753
  }
3707
- function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecords, getStoreMetadata) {
3754
+ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecords, getStoreMetadata, getStore) {
3708
3755
  const getEntries = function (entries, segment) {
3709
3756
  // this HOF only inspects records in the default segment
3710
3757
  if (segment !== DefaultDurableSegment) {
@@ -3772,6 +3819,7 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
3772
3819
  const putRecordViews = {};
3773
3820
  const storeRecords = getStoreRecords !== undefined ? getStoreRecords() : {};
3774
3821
  const storeMetadata = getStoreMetadata !== undefined ? getStoreMetadata() : {};
3822
+ const store = getStore();
3775
3823
  for (let i = 0, len = keys$1.length; i < len; i++) {
3776
3824
  const key = keys$1[i];
3777
3825
  let value = entries[key];
@@ -3818,11 +3866,13 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
3818
3866
  metadataVersion: DURABLE_METADATA_VERSION,
3819
3867
  };
3820
3868
  }
3821
- const denormalizedRecord = buildDurableRecordRepresentation(record, storeRecords, recordEntries);
3822
- putEntries[recordKey] = {
3823
- data: denormalizedRecord,
3824
- metadata,
3825
- };
3869
+ const denormalizedRecord = buildDurableRecordRepresentation(record, storeRecords, recordEntries, store);
3870
+ if (denormalizedRecord !== undefined) {
3871
+ putEntries[recordKey] = {
3872
+ data: denormalizedRecord,
3873
+ metadata,
3874
+ };
3875
+ }
3826
3876
  }
3827
3877
  else {
3828
3878
  putEntries[key] = value;
@@ -3911,6 +3961,7 @@ new CachedGraphQLSchema();
3911
3961
  let luvio;
3912
3962
  let getIngestRecords;
3913
3963
  let getIngestMetadata;
3964
+ let getIngestStore;
3914
3965
  // LdsSqliteStore plugin helper
3915
3966
  function getNimbusDurableStore() {
3916
3967
  const resolvedPlugin = __nimbus.plugins.LdsSqliteStore;
@@ -3922,7 +3973,7 @@ function getNimbusDurableStore() {
3922
3973
  * See TD-0153300 for moving RecordDenormalizingDurableStore out of lds-drafts
3923
3974
  */
3924
3975
  function createRecordDenormingStore(luvio, durableStore) {
3925
- const recordDenormingStore = makeRecordDenormalizingDurableStore(luvio, durableStore, () => getIngestRecords(), () => getIngestMetadata());
3976
+ const recordDenormingStore = makeRecordDenormalizingDurableStore(luvio, durableStore, () => getIngestRecords(), () => getIngestMetadata(), () => getIngestStore());
3926
3977
  return recordDenormingStore;
3927
3978
  }
3928
3979
  function getRuntime() {
@@ -3938,6 +3989,7 @@ function getRuntime() {
3938
3989
  // Set ingest records/metadata properties from durable environment
3939
3990
  getIngestRecords = durableEnv.getIngestStagingStoreRecords;
3940
3991
  getIngestMetadata = durableEnv.getIngestStagingStoreMetadata;
3992
+ getIngestStore = durableEnv.getIngestStagingStore;
3941
3993
  // Return new luvio instance
3942
3994
  luvio = new Luvio(durableEnv, {
3943
3995
  instrument: instrumentLuvio,
@@ -3963,4 +4015,4 @@ function ldsRuntimeBridge() {
3963
4015
  }
3964
4016
 
3965
4017
  export { ldsRuntimeBridge as default };
3966
- // version: 1.266.0-dev2-7c2f3615f
4018
+ // version: 1.266.0-dev21-b2a247476
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/lds-runtime-bridge",
3
- "version": "1.266.0-dev2",
3
+ "version": "1.266.0-dev21",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "description": "LDS runtime for bridge.app.",
6
6
  "main": "dist/ldsRuntimeBridge.js",
@@ -34,17 +34,17 @@
34
34
  "release:corejar": "yarn build && ../core-build/scripts/core.js --name=lds-runtime-bridge"
35
35
  },
36
36
  "dependencies": {
37
- "@salesforce/lds-adapters-uiapi": "^1.266.0-dev2",
38
- "@salesforce/lds-instrumentation": "^1.266.0-dev2",
37
+ "@salesforce/lds-adapters-uiapi": "^1.266.0-dev21",
38
+ "@salesforce/lds-instrumentation": "^1.266.0-dev21",
39
39
  "@salesforce/user": "0.0.21",
40
40
  "o11y": "244.0.0"
41
41
  },
42
42
  "devDependencies": {
43
- "@salesforce/lds-drafts-adapters-uiapi": "^1.266.0-dev2",
44
- "@salesforce/lds-network-aura": "^1.266.0-dev2",
45
- "@salesforce/lds-runtime-aura": "^1.266.0-dev2",
46
- "@salesforce/lds-store-nimbus": "^1.266.0-dev2",
47
- "@salesforce/nimbus-plugin-lds": "^1.266.0-dev2",
43
+ "@salesforce/lds-drafts-adapters-uiapi": "^1.266.0-dev21",
44
+ "@salesforce/lds-network-aura": "^1.266.0-dev21",
45
+ "@salesforce/lds-runtime-aura": "^1.266.0-dev21",
46
+ "@salesforce/lds-store-nimbus": "^1.266.0-dev21",
47
+ "@salesforce/nimbus-plugin-lds": "^1.266.0-dev21",
48
48
  "babel-plugin-dynamic-import-node": "^2.3.3"
49
49
  },
50
50
  "luvioBundlesize": [