@salesforce/lds-adapters-uiapi 1.228.1 → 1.229.0-dev10

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 @@ declare const assign: {
12
12
  [idx: string]: object | U | null | undefined;
13
13
  }, U extends string | number | bigint | boolean | symbol>(o: T_1): Readonly<T_1>;
14
14
  <T_2>(o: T_2): Readonly<T_2>;
15
- }, keys: {
15
+ }, isFrozen: (o: any) => boolean, keys: {
16
16
  (o: object): string[];
17
17
  (o: {}): string[];
18
18
  };
@@ -39,4 +39,4 @@ declare const parse: (text: string, reviver?: ((this: any, key: string, value: a
39
39
  (value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string;
40
40
  (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string;
41
41
  };
42
- export { assign as ObjectAssign, create as ObjectCreate, freeze as ObjectFreeze, keys as ObjectKeys, hasOwnProperty as ObjectPrototypeHasOwnProperty, isArray as ArrayIsArray, concat as ArrayPrototypeConcat, filter as ArrayPrototypeFilter, includes as ArrayPrototypeIncludes, push as ArrayPrototypePush, reduce as ArrayPrototypeReduce, split as StringPrototypeSplit, endsWith as StringPrototypeEndsWith, parse as JSONParse, stringify as JSONStringify, };
42
+ export { assign as ObjectAssign, create as ObjectCreate, freeze as ObjectFreeze, isFrozen as ObjectIsFrozen, keys as ObjectKeys, hasOwnProperty as ObjectPrototypeHasOwnProperty, isArray as ArrayIsArray, concat as ArrayPrototypeConcat, filter as ArrayPrototypeFilter, includes as ArrayPrototypeIncludes, push as ArrayPrototypePush, reduce as ArrayPrototypeReduce, split as StringPrototypeSplit, endsWith as StringPrototypeEndsWith, parse as JSONParse, stringify as JSONStringify, };
@@ -1,4 +1,4 @@
1
- import type { ProxyGraphNode, GraphNode, Luvio, NormalizedKeyMetadata } from '@luvio/engine';
1
+ import type { ProxyGraphNode, GraphNode, NormalizedKeyMetadata, Luvio } from '@luvio/engine';
2
2
  import type { FieldValueRepresentation } from '../generated/types/FieldValueRepresentation';
3
3
  import type { RecordCreateDefaultRecordRepresentation } from '../generated/types/RecordCreateDefaultRecordRepresentation';
4
4
  import type { ObjectInfoRepresentation } from '../generated/types/ObjectInfoRepresentation';
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import { register } from '@salesforce/lds-default-luvio';
8
- import { serializeStructuredKey, ingestShape, coerceConfig as coerceConfig$1, typeCheckConfig as typeCheckConfig$13, createResourceParams as createResourceParams$Z, StoreKeyMap, StoreKeySet, deepFreeze, buildNetworkSnapshotCachePolicy as buildNetworkSnapshotCachePolicy$R, coerceAdapterRequestContext, Wildcard } from '@luvio/engine';
8
+ import { serializeStructuredKey, ingestShape, coerceConfig as coerceConfig$1, typeCheckConfig as typeCheckConfig$13, createResourceParams as createResourceParams$Z, StoreKeyMap, StoreKeySet, deepFreeze, buildNetworkSnapshotCachePolicy as buildNetworkSnapshotCachePolicy$R, resolveLink, coerceAdapterRequestContext, Wildcard } from '@luvio/engine';
9
9
  import { print, visit, parse as parse$1 } from '@luvio/graphql-parser';
10
10
  import { getRequestedFieldsForType, buildFieldState, createFragmentMap, mergeSelectionSets, serializeFieldArguments, deepMerge, buildQueryTypeStringKey, getOperationFromDocument } from '@luvio/graphql';
11
11
 
@@ -355,7 +355,7 @@ function buildAdapterValidationConfig(displayName, paramsMeta) {
355
355
  }
356
356
  const keyPrefix = 'UiApi';
357
357
 
358
- const { assign, create, freeze, keys } = Object;
358
+ const { assign, create, freeze, isFrozen, keys } = Object;
359
359
  const { hasOwnProperty } = Object.prototype;
360
360
  const { split, endsWith } = String.prototype;
361
361
  const { isArray } = Array;
@@ -4239,7 +4239,7 @@ function extractTrackedFieldsToTrie(recordId, node, root, config, visitedRecordI
4239
4239
  extractTrackedFieldsToTrie(spanningLink.data.__ref, spanning, next, config, spanningVisitedRecordIds, depth + 1);
4240
4240
  // For a spanning record that is detected to be a circular reference, we add the field along with Id and Name.
4241
4241
  // It's possible for spanning record lookup fields to sometimes be circular, and sometimes not - depending on the value of the lookup field.
4242
- // For more information on scenarios that caused this fix: https://salesforce.quip.com/OvzNAh3eNIWY
4242
+ // For more information on scenarios that caused this fix: search "LDS Recursive Spanning Fields Problem" in Quip
4243
4243
  if (keys(next.children).length === 0) {
4244
4244
  addScalarFieldId(next);
4245
4245
  addScalarFieldName(next);
@@ -4574,7 +4574,11 @@ function markNulledOutPath(record, path) {
4574
4574
  }
4575
4575
  const link = fieldValueRepresentation.link(fieldName);
4576
4576
  const resolved = link.follow();
4577
- if (isGraphNode(resolved) && resolved.isScalar('value') && path.length > 0) {
4577
+ if (isGraphNode(resolved) &&
4578
+ resolved.isScalar('value') &&
4579
+ path.length > 0 &&
4580
+ // TODO [W-14082782]: temporary fix
4581
+ !isFrozen(link.data)) {
4578
4582
  const linkState = link.linkData();
4579
4583
  const fields = linkState === undefined ? [] : linkState.fields;
4580
4584
  link.writeLinkData({
@@ -4602,22 +4606,12 @@ function _markMissingPath(record, path) {
4602
4606
  const fieldValueRepresentation = record.object('fields');
4603
4607
  const fieldName = path.shift();
4604
4608
  if (fieldValueRepresentation.isUndefined(fieldName) === true) {
4605
- // TODO [W-6900046]: remove cast, make RecordRepresentationNormalized['fields'] accept
4606
- // an undefined/non-present __ref if isMissing is present
4607
- fieldValueRepresentation.write(fieldName, {
4608
- __ref: undefined,
4609
- isMissing: true,
4610
- });
4609
+ writeMissingFieldToStore(fieldValueRepresentation, fieldName);
4611
4610
  return;
4612
4611
  }
4613
4612
  const link = fieldValueRepresentation.link(fieldName);
4614
4613
  if (link.isPending()) {
4615
- // TODO [W-6900046]: remove cast, make RecordRepresentationNormalized['fields'] accept
4616
- // an undefined/non-present __ref if isMissing is present
4617
- fieldValueRepresentation.write(fieldName, {
4618
- __ref: undefined,
4619
- isMissing: true,
4620
- });
4614
+ writeMissingFieldToStore(fieldValueRepresentation, fieldName);
4621
4615
  }
4622
4616
  else if (path.length > 0 && link.isMissing() === false) {
4623
4617
  const fieldValue = link.follow();
@@ -4633,6 +4627,19 @@ function _markMissingPath(record, path) {
4633
4627
  }
4634
4628
  }
4635
4629
  }
4630
+ /**
4631
+ * Graph Node Directly modifies store entries, which is generally a non-starter.
4632
+ * Until we can refactor this mess, you need to use this function to safely mark the RecordRepresentation
4633
+ * as a seenId in the store when you perform this mutation.
4634
+ */
4635
+ function writeMissingFieldToStore(field, fieldName) {
4636
+ // TODO [W-6900046]: remove cast, make RecordRepresentationNormalized['fields'] accept
4637
+ // an undefined/non-present __ref if isMissing is present
4638
+ field.write(fieldName, {
4639
+ __ref: undefined,
4640
+ isMissing: true,
4641
+ });
4642
+ }
4636
4643
  /**
4637
4644
  * Tells you if an objectApiName is supported by UI API or not.
4638
4645
  * Note: Luvio does not currently support all the entities, the list is limited to UI API supported entities
@@ -4764,8 +4771,11 @@ function mergeAndRefreshLowerVersionRecord(luvio, incoming, existing, incomingTr
4764
4771
  return existing;
4765
4772
  }
4766
4773
  function mergeRecordConflict(luvio, incoming, existing, recordConflictMap) {
4767
- const incomingNode = luvio.wrapNormalizedGraphNode(incoming);
4768
- const existingNode = luvio.wrapNormalizedGraphNode(existing);
4774
+ const recordKey = keyBuilder$35(luvio, {
4775
+ recordId: incoming.id,
4776
+ });
4777
+ const incomingNode = luvio.wrapNormalizedGraphNode(incoming, recordKey);
4778
+ const existingNode = luvio.wrapNormalizedGraphNode(existing, recordKey);
4769
4779
  const incomingTrackedFieldsTrieRoot = {
4770
4780
  name: incoming.apiName,
4771
4781
  children: {},
@@ -4774,9 +4784,6 @@ function mergeRecordConflict(luvio, incoming, existing, recordConflictMap) {
4774
4784
  name: existing.apiName,
4775
4785
  children: {},
4776
4786
  };
4777
- const recordKey = keyBuilder$35(luvio, {
4778
- recordId: incoming.id,
4779
- });
4780
4787
  const trackedFieldsConfig = {
4781
4788
  maxDepth: configurationForRestAdapters.getTrackedFieldDepthOnCacheMergeConflict(),
4782
4789
  onlyFetchLeafNodeIdAndName: configurationForRestAdapters.getTrackedFieldLeafNodeIdAndNameOnly(),
@@ -5099,7 +5106,7 @@ function fulfill(existing, incoming) {
5099
5106
  const batchRequestWithSingleRequest = isSingleBatchRecordRequest(existingUrlParams) &&
5100
5107
  isSingleRecordRequest(urlParams) &&
5101
5108
  incomingUrlRecords[0] === existingUrlRecords[0];
5102
- if (!batchRequestWithSingleRequest) {
5109
+ if (!batchRequestWithSingleRequest || isRestrictedPathCondition(existingPath, path)) {
5103
5110
  return false;
5104
5111
  }
5105
5112
  }
@@ -5142,6 +5149,12 @@ function isSingleBatchRecordRequest(urlParams) {
5142
5149
  function isSingleRecordRequest(urlParams) {
5143
5150
  return hasOwnProperty.call(urlParams, 'recordId');
5144
5151
  }
5152
+ function isRestrictedPathCondition(existingPath, path) {
5153
+ // should not dedupe getRecordUi and getRecord as both of their representation is different
5154
+ // records call cannot digest response of getRecordUi
5155
+ return ((existingPath.includes('/record-ui') && path.includes('/records')) ||
5156
+ (existingPath.includes('/records') && path.includes('/record-ui')));
5157
+ }
5145
5158
 
5146
5159
  const createResourceRequest$16 = function getUiApiRecordsByRecordIdCreateResourceRequest(config) {
5147
5160
  return {
@@ -11792,7 +11805,7 @@ function getLayoutMapAndObjectInfo(recordId, data) {
11792
11805
  // Temp fix until we can mimic the server behavior for non-layoutable entities.
11793
11806
  let layoutMap = {};
11794
11807
  if (hasOwnProperty.call(layouts, apiName)) {
11795
- layoutMap = layouts[apiName][recordTypeId];
11808
+ layoutMap = layouts[apiName][recordTypeId] || {};
11796
11809
  }
11797
11810
  return {
11798
11811
  layoutMap,
@@ -11974,18 +11987,28 @@ const buildLayoutModeCacheSnapshot = (apiName, recordTypeId, layoutType, mode) =
11974
11987
  * These are intermediate lookups to check if the record is in the L2 cache
11975
11988
  * @param {Luvio} luvio
11976
11989
  * @param {GetRecordLayoutTypeConfig} config
11977
- * @param {BuildCachedSnapshot<BuildSnapshotContext} cachedSnapshot
11990
+ * @param {BuildCachedSnapshot<BuildSnapshotContext>} cachedSnapshot
11978
11991
  */
11979
11992
  function makeCacheOnlySnapshot(luvio, config, adapterContext, cachedSnapshot) {
11980
- return luvio.applyCachePolicy({
11981
- cachePolicy: {
11982
- // only looking in the cache so we can check for L2 data offline
11983
- type: 'only-if-cached',
11984
- },
11985
- }, { config, luvio, adapterContext }, cachedSnapshot,
11986
- // this won't be invoked since we're requesting only-if-cached
11993
+ return luvio.applyCachePolicy(
11994
+ // Pass empty context so environment will use its default cache-policy
11995
+ {}, { config, luvio, adapterContext }, cachedSnapshot,
11996
+ // disallow hitting the network by returning a gateway timeout
11987
11997
  () => {
11988
- throw Error('buildNetworkSnapshot should not be called for only-if-cached policy');
11998
+ return new Promise((resolve) => {
11999
+ resolve({
12000
+ state: 'Error',
12001
+ data: undefined,
12002
+ error: {
12003
+ body: undefined,
12004
+ headers: {},
12005
+ ok: false,
12006
+ status: 504,
12007
+ statusText: 'Gateway Timeout',
12008
+ errorType: 'fetchResponse',
12009
+ },
12010
+ });
12011
+ });
11989
12012
  });
11990
12013
  }
11991
12014
  /**
@@ -12196,7 +12219,7 @@ const notifyChangeFactory = (luvio) => {
12196
12219
  const responsePromises = [];
12197
12220
  for (let i = 0, len = entries.length; i < len; i++) {
12198
12221
  const { key, record } = entries[i];
12199
- const node = luvio.wrapNormalizedGraphNode(record);
12222
+ const node = luvio.wrapNormalizedGraphNode(record, key);
12200
12223
  const optionalFields = getTrackedFields(key, node, {
12201
12224
  maxDepth: configurationForRestAdapters.getTrackedFieldDepthOnNotifyChange(),
12202
12225
  onlyFetchLeafNodeIdAndName: configurationForRestAdapters.getTrackedFieldLeafNodeIdAndNameOnly(),
@@ -43066,6 +43089,7 @@ function buildSelectionForField$7(source, reader, sel, variables, fragments, isC
43066
43089
  }
43067
43090
  if (fieldData === null) {
43068
43091
  reader.assignScalar(requestedFieldName, sink, fieldData);
43092
+ reader.exitPath();
43069
43093
  return sink;
43070
43094
  }
43071
43095
  const fieldType = getFieldType(sel);
@@ -43091,17 +43115,8 @@ function buildSelectionForField$7(source, reader, sel, variables, fragments, isC
43091
43115
  return sink;
43092
43116
  }
43093
43117
  function selectTypeLink(sel, fieldData, reader, key, sink, variables, fragments, version, selectFn, isCursorConnection) {
43094
- const resolvedLink = reader.read({
43095
- recordId: fieldData.__ref,
43096
- node: {
43097
- kind: 'Fragment',
43098
- private: [],
43099
- opaque: true,
43100
- version,
43101
- },
43102
- variables: {}
43103
- });
43104
- if (resolvedLink.data !== undefined) {
43118
+ const resolvedLink = resolveLink(reader, fieldData, version);
43119
+ if (resolvedLink && resolvedLink.data !== undefined) {
43105
43120
  if (isCursorConnection) {
43106
43121
  selectTypeLinkWithPagination(resolvedLink, sel, fieldData, reader, key, sink, variables, fragments, selectFn);
43107
43122
  }
@@ -43683,19 +43698,11 @@ function selectType$6(typename, sel, fieldData, reader, key, sink, variables, fr
43683
43698
  }
43684
43699
  case 'PolymorphicParentRelationship':
43685
43700
  case 'RecordRepresentation': {
43686
- const spanningFieldLink = reader.read({
43687
- recordId: fieldData.__ref,
43688
- node: {
43689
- kind: 'Fragment',
43690
- private: [],
43691
- opaque: true,
43692
- version: VERSION$2i,
43693
- },
43694
- variables: {},
43695
- });
43696
- reader.markSeenId(fieldData.__ref);
43697
- const resolvedSpanningFieldValue = spanningFieldLink.data;
43701
+ const spanningFieldLink = resolveLink(reader, fieldData, VERSION$2i);
43702
+ const resolvedSpanningFieldValue = spanningFieldLink && spanningFieldLink.data;
43703
+ const fieldDataRef = fieldData.__ref;
43698
43704
  if (resolvedSpanningFieldValue !== undefined) {
43705
+ reader.markSeenId(fieldDataRef);
43699
43706
  const { value: spanningFieldResult } = resolvedSpanningFieldValue;
43700
43707
  // Handle null values - graphql will return it at the field level, not return nested { value: null }
43701
43708
  if (spanningFieldResult === null || typeof spanningFieldResult !== 'object') {
@@ -43719,7 +43726,9 @@ function selectType$6(typename, sel, fieldData, reader, key, sink, variables, fr
43719
43726
  }
43720
43727
  }
43721
43728
  else {
43722
- reader.markMissingLink(fieldData.__ref);
43729
+ if (fieldDataRef !== undefined) {
43730
+ reader.markMissingLink(fieldDataRef);
43731
+ }
43723
43732
  reader.markMissing();
43724
43733
  }
43725
43734
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/lds-adapters-uiapi",
3
- "version": "1.228.1",
3
+ "version": "1.229.0-dev10",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "description": "Wire adapters for record related UI API endpoints",
6
6
  "main": "dist/es/es2018/uiapi-records-service.js",
@@ -68,15 +68,15 @@
68
68
  }
69
69
  },
70
70
  "dependencies": {
71
- "@salesforce/lds-bindings": "*",
72
- "@salesforce/lds-default-luvio": "*"
71
+ "@salesforce/lds-bindings": "1.229.0-dev10",
72
+ "@salesforce/lds-default-luvio": "1.229.0-dev10"
73
73
  },
74
74
  "devDependencies": {
75
75
  "@databases/sqlite": "^3.0.0",
76
- "@salesforce/lds-compiler-plugins": "*",
77
- "@salesforce/lds-jest": "*",
78
- "@salesforce/lds-store-binary": "*",
79
- "@salesforce/lds-uiapi-record-utils": "*"
76
+ "@salesforce/lds-compiler-plugins": "1.229.0-dev10",
77
+ "@salesforce/lds-jest": "1.229.0-dev10",
78
+ "@salesforce/lds-store-binary": "1.229.0-dev10",
79
+ "@salesforce/lds-uiapi-record-utils": "1.229.0-dev10"
80
80
  },
81
81
  "luvioBundlesize": [
82
82
  {
@@ -16,7 +16,7 @@ import { register, withDefaultLuvio } from 'force/ldsEngine';
16
16
  import { print, visit, parse, astResolver } from 'force/ldsGraphqlParser';
17
17
  import { createInstrumentedAdapter, createLDSAdapter, createGraphQLWireAdapterConstructor, createGraphQLImperativeAdapter } from 'force/ldsBindings';
18
18
  export { refresh as refreshGraphQL } from 'force/ldsBindings';
19
- import { serializeStructuredKey, deepFreeze, buildNetworkSnapshotCachePolicy as buildNetworkSnapshotCachePolicy$2, StoreKeyMap, createResourceParams as createResourceParams$2, StoreKeySet } from 'force/luvioEngine';
19
+ import { serializeStructuredKey, deepFreeze, resolveLink, buildNetworkSnapshotCachePolicy as buildNetworkSnapshotCachePolicy$2, StoreKeyMap, createResourceParams as createResourceParams$2, StoreKeySet } from 'force/luvioEngine';
20
20
  import { getRequestedFieldsForType, buildFieldState, createFragmentMap, mergeSelectionSets, serializeFieldArguments, deepMerge, buildQueryTypeStringKey, getOperationFromDocument } from 'force/luvioGraphql';
21
21
  import { createIngestRecordWithFields } from 'force/ldsAdaptersUiapi';
22
22
 
@@ -12954,7 +12954,7 @@ function getFieldType$6(field) {
12954
12954
  }
12955
12955
  }
12956
12956
 
12957
- const { assign, create, freeze, keys } = Object;
12957
+ const { assign, create, freeze, isFrozen, keys } = Object;
12958
12958
  const { isArray } = Array;
12959
12959
  const { concat, filter, includes, push, reduce } = Array.prototype;
12960
12960
 
@@ -14393,6 +14393,7 @@ function buildSelectionForField$7(source, reader, sel, variables, fragments, isC
14393
14393
  }
14394
14394
  if (fieldData === null) {
14395
14395
  reader.assignScalar(requestedFieldName, sink, fieldData);
14396
+ reader.exitPath();
14396
14397
  return sink;
14397
14398
  }
14398
14399
  const fieldType = getFieldType(sel);
@@ -14418,17 +14419,8 @@ function buildSelectionForField$7(source, reader, sel, variables, fragments, isC
14418
14419
  return sink;
14419
14420
  }
14420
14421
  function selectTypeLink(sel, fieldData, reader, key, sink, variables, fragments, version, selectFn, isCursorConnection) {
14421
- const resolvedLink = reader.read({
14422
- recordId: fieldData.__ref,
14423
- node: {
14424
- kind: 'Fragment',
14425
- private: [],
14426
- opaque: true,
14427
- version,
14428
- },
14429
- variables: {}
14430
- });
14431
- if (resolvedLink.data !== undefined) {
14422
+ const resolvedLink = resolveLink(reader, fieldData, version);
14423
+ if (resolvedLink && resolvedLink.data !== undefined) {
14432
14424
  if (isCursorConnection) {
14433
14425
  selectTypeLinkWithPagination(resolvedLink, sel, fieldData, reader, key, sink, variables, fragments, selectFn);
14434
14426
  }
@@ -15010,19 +15002,11 @@ function selectType$6(typename, sel, fieldData, reader, key, sink, variables, fr
15010
15002
  }
15011
15003
  case 'PolymorphicParentRelationship':
15012
15004
  case 'RecordRepresentation': {
15013
- const spanningFieldLink = reader.read({
15014
- recordId: fieldData.__ref,
15015
- node: {
15016
- kind: 'Fragment',
15017
- private: [],
15018
- opaque: true,
15019
- version: VERSION$f,
15020
- },
15021
- variables: {},
15022
- });
15023
- reader.markSeenId(fieldData.__ref);
15024
- const resolvedSpanningFieldValue = spanningFieldLink.data;
15005
+ const spanningFieldLink = resolveLink(reader, fieldData, VERSION$f);
15006
+ const resolvedSpanningFieldValue = spanningFieldLink && spanningFieldLink.data;
15007
+ const fieldDataRef = fieldData.__ref;
15025
15008
  if (resolvedSpanningFieldValue !== undefined) {
15009
+ reader.markSeenId(fieldDataRef);
15026
15010
  const { value: spanningFieldResult } = resolvedSpanningFieldValue;
15027
15011
  // Handle null values - graphql will return it at the field level, not return nested { value: null }
15028
15012
  if (spanningFieldResult === null || typeof spanningFieldResult !== 'object') {
@@ -15046,7 +15030,9 @@ function selectType$6(typename, sel, fieldData, reader, key, sink, variables, fr
15046
15030
  }
15047
15031
  }
15048
15032
  else {
15049
- reader.markMissingLink(fieldData.__ref);
15033
+ if (fieldDataRef !== undefined) {
15034
+ reader.markMissingLink(fieldDataRef);
15035
+ }
15050
15036
  reader.markMissing();
15051
15037
  }
15052
15038
  break;
@@ -18121,4 +18107,4 @@ register({
18121
18107
  });
18122
18108
 
18123
18109
  export { configurationForGraphQLAdapters as configuration, graphql, factory$1 as graphqlAdapterFactory, graphqlBatch, graphqlBatch_imperative, graphql_imperative };
18124
- // version: 1.228.1-0cb6f94f1
18110
+ // version: 1.229.0-dev10-abb060196
package/sfdc/index.js CHANGED
@@ -403,7 +403,7 @@ function buildAdapterValidationConfig(displayName, paramsMeta) {
403
403
  }
404
404
  const keyPrefix = 'UiApi';
405
405
 
406
- const { assign, create, freeze, keys } = Object;
406
+ const { assign, create, freeze, isFrozen, keys } = Object;
407
407
  const { hasOwnProperty } = Object.prototype;
408
408
  const { split, endsWith } = String.prototype;
409
409
  const { isArray } = Array;
@@ -4287,7 +4287,7 @@ function extractTrackedFieldsToTrie(recordId, node, root, config, visitedRecordI
4287
4287
  extractTrackedFieldsToTrie(spanningLink.data.__ref, spanning, next, config, spanningVisitedRecordIds, depth + 1);
4288
4288
  // For a spanning record that is detected to be a circular reference, we add the field along with Id and Name.
4289
4289
  // It's possible for spanning record lookup fields to sometimes be circular, and sometimes not - depending on the value of the lookup field.
4290
- // For more information on scenarios that caused this fix: https://salesforce.quip.com/OvzNAh3eNIWY
4290
+ // For more information on scenarios that caused this fix: search "LDS Recursive Spanning Fields Problem" in Quip
4291
4291
  if (keys(next.children).length === 0) {
4292
4292
  addScalarFieldId(next);
4293
4293
  addScalarFieldName(next);
@@ -4440,7 +4440,11 @@ function markNulledOutPath(record, path) {
4440
4440
  }
4441
4441
  const link = fieldValueRepresentation.link(fieldName);
4442
4442
  const resolved = link.follow();
4443
- if (isGraphNode(resolved) && resolved.isScalar('value') && path.length > 0) {
4443
+ if (isGraphNode(resolved) &&
4444
+ resolved.isScalar('value') &&
4445
+ path.length > 0 &&
4446
+ // TODO [W-14082782]: temporary fix
4447
+ !isFrozen(link.data)) {
4444
4448
  const linkState = link.linkData();
4445
4449
  const fields = linkState === undefined ? [] : linkState.fields;
4446
4450
  link.writeLinkData({
@@ -4468,22 +4472,12 @@ function _markMissingPath(record, path) {
4468
4472
  const fieldValueRepresentation = record.object('fields');
4469
4473
  const fieldName = path.shift();
4470
4474
  if (fieldValueRepresentation.isUndefined(fieldName) === true) {
4471
- // TODO [W-6900046]: remove cast, make RecordRepresentationNormalized['fields'] accept
4472
- // an undefined/non-present __ref if isMissing is present
4473
- fieldValueRepresentation.write(fieldName, {
4474
- __ref: undefined,
4475
- isMissing: true,
4476
- });
4475
+ writeMissingFieldToStore(fieldValueRepresentation, fieldName);
4477
4476
  return;
4478
4477
  }
4479
4478
  const link = fieldValueRepresentation.link(fieldName);
4480
4479
  if (link.isPending()) {
4481
- // TODO [W-6900046]: remove cast, make RecordRepresentationNormalized['fields'] accept
4482
- // an undefined/non-present __ref if isMissing is present
4483
- fieldValueRepresentation.write(fieldName, {
4484
- __ref: undefined,
4485
- isMissing: true,
4486
- });
4480
+ writeMissingFieldToStore(fieldValueRepresentation, fieldName);
4487
4481
  }
4488
4482
  else if (path.length > 0 && link.isMissing() === false) {
4489
4483
  const fieldValue = link.follow();
@@ -4499,6 +4493,19 @@ function _markMissingPath(record, path) {
4499
4493
  }
4500
4494
  }
4501
4495
  }
4496
+ /**
4497
+ * Graph Node Directly modifies store entries, which is generally a non-starter.
4498
+ * Until we can refactor this mess, you need to use this function to safely mark the RecordRepresentation
4499
+ * as a seenId in the store when you perform this mutation.
4500
+ */
4501
+ function writeMissingFieldToStore(field, fieldName) {
4502
+ // TODO [W-6900046]: remove cast, make RecordRepresentationNormalized['fields'] accept
4503
+ // an undefined/non-present __ref if isMissing is present
4504
+ field.write(fieldName, {
4505
+ __ref: undefined,
4506
+ isMissing: true,
4507
+ });
4508
+ }
4502
4509
  /**
4503
4510
  * Tells you if an objectApiName is supported by UI API or not.
4504
4511
  * Note: Luvio does not currently support all the entities, the list is limited to UI API supported entities
@@ -4630,8 +4637,11 @@ function mergeAndRefreshLowerVersionRecord(luvio, incoming, existing, incomingTr
4630
4637
  return existing;
4631
4638
  }
4632
4639
  function mergeRecordConflict(luvio, incoming, existing, recordConflictMap) {
4633
- const incomingNode = luvio.wrapNormalizedGraphNode(incoming);
4634
- const existingNode = luvio.wrapNormalizedGraphNode(existing);
4640
+ const recordKey = keyBuilder$1U(luvio, {
4641
+ recordId: incoming.id,
4642
+ });
4643
+ const incomingNode = luvio.wrapNormalizedGraphNode(incoming, recordKey);
4644
+ const existingNode = luvio.wrapNormalizedGraphNode(existing, recordKey);
4635
4645
  const incomingTrackedFieldsTrieRoot = {
4636
4646
  name: incoming.apiName,
4637
4647
  children: {},
@@ -4640,9 +4650,6 @@ function mergeRecordConflict(luvio, incoming, existing, recordConflictMap) {
4640
4650
  name: existing.apiName,
4641
4651
  children: {},
4642
4652
  };
4643
- const recordKey = keyBuilder$1U(luvio, {
4644
- recordId: incoming.id,
4645
- });
4646
4653
  const trackedFieldsConfig = {
4647
4654
  maxDepth: configurationForRestAdapters.getTrackedFieldDepthOnCacheMergeConflict(),
4648
4655
  onlyFetchLeafNodeIdAndName: configurationForRestAdapters.getTrackedFieldLeafNodeIdAndNameOnly(),
@@ -4965,7 +4972,7 @@ function fulfill(existing, incoming) {
4965
4972
  const batchRequestWithSingleRequest = isSingleBatchRecordRequest(existingUrlParams) &&
4966
4973
  isSingleRecordRequest(urlParams) &&
4967
4974
  incomingUrlRecords[0] === existingUrlRecords[0];
4968
- if (!batchRequestWithSingleRequest) {
4975
+ if (!batchRequestWithSingleRequest || isRestrictedPathCondition(existingPath, path)) {
4969
4976
  return false;
4970
4977
  }
4971
4978
  }
@@ -5008,6 +5015,12 @@ function isSingleBatchRecordRequest(urlParams) {
5008
5015
  function isSingleRecordRequest(urlParams) {
5009
5016
  return hasOwnProperty.call(urlParams, 'recordId');
5010
5017
  }
5018
+ function isRestrictedPathCondition(existingPath, path) {
5019
+ // should not dedupe getRecordUi and getRecord as both of their representation is different
5020
+ // records call cannot digest response of getRecordUi
5021
+ return ((existingPath.includes('/record-ui') && path.includes('/records')) ||
5022
+ (existingPath.includes('/records') && path.includes('/record-ui')));
5023
+ }
5011
5024
 
5012
5025
  const createResourceRequest$12 = function getUiApiRecordsByRecordIdCreateResourceRequest(config) {
5013
5026
  return {
@@ -11324,7 +11337,7 @@ function getLayoutMapAndObjectInfo(recordId, data) {
11324
11337
  // Temp fix until we can mimic the server behavior for non-layoutable entities.
11325
11338
  let layoutMap = {};
11326
11339
  if (hasOwnProperty.call(layouts, apiName)) {
11327
- layoutMap = layouts[apiName][recordTypeId];
11340
+ layoutMap = layouts[apiName][recordTypeId] || {};
11328
11341
  }
11329
11342
  return {
11330
11343
  layoutMap,
@@ -11506,18 +11519,28 @@ const buildLayoutModeCacheSnapshot = (apiName, recordTypeId, layoutType, mode) =
11506
11519
  * These are intermediate lookups to check if the record is in the L2 cache
11507
11520
  * @param {Luvio} luvio
11508
11521
  * @param {GetRecordLayoutTypeConfig} config
11509
- * @param {BuildCachedSnapshot<BuildSnapshotContext} cachedSnapshot
11522
+ * @param {BuildCachedSnapshot<BuildSnapshotContext>} cachedSnapshot
11510
11523
  */
11511
11524
  function makeCacheOnlySnapshot(luvio, config, adapterContext, cachedSnapshot) {
11512
- return luvio.applyCachePolicy({
11513
- cachePolicy: {
11514
- // only looking in the cache so we can check for L2 data offline
11515
- type: 'only-if-cached',
11516
- },
11517
- }, { config, luvio, adapterContext }, cachedSnapshot,
11518
- // this won't be invoked since we're requesting only-if-cached
11525
+ return luvio.applyCachePolicy(
11526
+ // Pass empty context so environment will use its default cache-policy
11527
+ {}, { config, luvio, adapterContext }, cachedSnapshot,
11528
+ // disallow hitting the network by returning a gateway timeout
11519
11529
  () => {
11520
- throw Error('buildNetworkSnapshot should not be called for only-if-cached policy');
11530
+ return new Promise((resolve) => {
11531
+ resolve({
11532
+ state: 'Error',
11533
+ data: undefined,
11534
+ error: {
11535
+ body: undefined,
11536
+ headers: {},
11537
+ ok: false,
11538
+ status: 504,
11539
+ statusText: 'Gateway Timeout',
11540
+ errorType: 'fetchResponse',
11541
+ },
11542
+ });
11543
+ });
11521
11544
  });
11522
11545
  }
11523
11546
  /**
@@ -11728,7 +11751,7 @@ const notifyChangeFactory = (luvio) => {
11728
11751
  const responsePromises = [];
11729
11752
  for (let i = 0, len = entries.length; i < len; i++) {
11730
11753
  const { key, record } = entries[i];
11731
- const node = luvio.wrapNormalizedGraphNode(record);
11754
+ const node = luvio.wrapNormalizedGraphNode(record, key);
11732
11755
  const optionalFields = getTrackedFields(key, node, {
11733
11756
  maxDepth: configurationForRestAdapters.getTrackedFieldDepthOnNotifyChange(),
11734
11757
  onlyFetchLeafNodeIdAndName: configurationForRestAdapters.getTrackedFieldLeafNodeIdAndNameOnly(),
@@ -32847,4 +32870,4 @@ withDefaultLuvio((luvio) => {
32847
32870
  });
32848
32871
 
32849
32872
  export { InMemoryRecordRepresentationQueryEvaluator, MRU, RepresentationType$J as ObjectInfoRepresentationType, RepresentationType$O as RecordRepresentationRepresentationType, TTL$w as RecordRepresentationTTL, RepresentationType$O as RecordRepresentationType, VERSION$17 as RecordRepresentationVersion, keyPrefix as UiApiNamespace, configurationForRestAdapters as configuration, createContentDocumentAndVersion, createContentVersion, createIngestRecordWithFields, createRecord, deleteRecord, getActionOverrides, getActionOverrides_imperative, getAllApps, getAllApps_imperative, getAppDetails, getAppDetails_imperative, getDuplicateConfiguration, getDuplicateConfiguration_imperative, getDuplicates, getDuplicates_imperative, getGlobalActions, getGlobalActions_imperative, getKeywordSearchResults, getKeywordSearchResults_imperative, getLayout, getLayoutUserState, getLayoutUserState_imperative, getLayout_imperative, getListInfoByName, getListInfoByName_imperative, getListInfosByName, getListInfosByName_imperative, getListObjectInfo, getListObjectInfo_imperative, getListRecordsByName, getListRecordsByName_imperative, getListUi, getListUi_imperative, getLookupActions, getLookupActions_imperative, getLookupMetadata, getLookupMetadata_imperative, getLookupRecords, getLookupRecords_imperative, getNavItems, getNavItems_imperative, getObjectCreateActions, getObjectCreateActions_imperative, getObjectInfo, getObjectInfoAdapterFactory, getObjectInfo_imperative, getObjectInfos, getObjectInfosAdapterFactory, getObjectInfos_imperative, getPicklistValues, getPicklistValuesByRecordType, getPicklistValuesByRecordType_imperative, getPicklistValues_imperative, getQuickActionDefaults, getQuickActionDefaults_imperative, getQuickActionLayout, getQuickActionLayout_imperative, getRecord, getRecordActions, getRecordActions_imperative, factory$e as getRecordAdapterFactory, getRecordAvatars, getRecordAvatars_imperative, getRecordCreateDefaults, getRecordCreateDefaults_imperative, getRecordEditActions, getRecordEditActions_imperative, getRecordId18, getRecordNotifyChange, getRecordTemplateClone, getRecordTemplateClone_imperative, getRecordTemplateCreate, getRecordTemplateCreate_imperative, getRecordUi, getRecordUi_imperative, getRecord_imperative, getRecords, getRecordsAdapterFactory, getRecords_imperative, getRelatedListActions, getRelatedListActions_imperative, getRelatedListCount, getRelatedListCount_imperative, getRelatedListInfo, getRelatedListInfoBatch, getRelatedListInfoBatch_imperative, getRelatedListInfo_imperative, getRelatedListPreferences, getRelatedListPreferencesBatch, getRelatedListPreferencesBatch_imperative, getRelatedListPreferences_imperative, getRelatedListRecordActions, getRelatedListRecordActions_imperative, getRelatedListRecords, getRelatedListRecordsBatch, getRelatedListRecordsBatch_imperative, getRelatedListRecords_imperative, getRelatedListsActions, getRelatedListsActions_imperative, getRelatedListsCount, getRelatedListsCount_imperative, getRelatedListsInfo, getRelatedListsInfo_imperative, getResponseCacheKeys as getResponseCacheKeysContentDocumentCompositeRepresentation, getSearchFilterMetadata, getSearchFilterMetadata_imperative, getSearchFilterOptions, getSearchFilterOptions_imperative, getSearchResults, getSearchResults_imperative, getTypeCacheKeys$Q as getTypeCacheKeysRecord, ingest as ingestContentDocumentCompositeRepresentation, ingest$C as ingestObjectInfo, ingest$y as ingestQuickActionExecutionRepresentation, ingest$H as ingestRecord, instrument, keyBuilder as keyBuilderContentDocumentCompositeRepresentation, keyBuilderFromType as keyBuilderFromTypeContentDocumentCompositeRepresentation, keyBuilderFromType$y as keyBuilderFromTypeRecordRepresentation, keyBuilder$1J as keyBuilderObjectInfo, keyBuilder$1D as keyBuilderQuickActionExecutionRepresentation, keyBuilder$1U as keyBuilderRecord, notifyListInfoUpdateAvailable, notifyListViewSummaryUpdateAvailable, notifyQuickActionDefaultsUpdateAvailable, notifyRecordUpdateAvailable, performQuickAction, performUpdateRecordQuickAction, refresh, updateLayoutUserState, updateListInfoByName, updateRecord, updateRecordAvatar, updateRelatedListInfo, updateRelatedListPreferences };
32850
- // version: 1.228.1-0cb6f94f1
32873
+ // version: 1.229.0-dev10-abb060196
@@ -95,11 +95,11 @@ var TypeCheckShapes;
95
95
  TypeCheckShapes[TypeCheckShapes["Integer"] = 3] = "Integer";
96
96
  TypeCheckShapes[TypeCheckShapes["Unsupported"] = 4] = "Unsupported";
97
97
  })(TypeCheckShapes || (TypeCheckShapes = {}));
98
- // engine version: 0.145.2-6a13677c
98
+ // engine version: 0.146.0-dev5-a2ec6e3f
99
99
 
100
100
  const { keys: ObjectKeys, create: ObjectCreate } = Object;
101
101
 
102
- const { assign, create, freeze, keys } = Object;
102
+ const { assign, create, freeze, isFrozen, keys } = Object;
103
103
 
104
104
  function isString(value) {
105
105
  return typeof value === 'string';