@salesforce/lds-runtime-mobile 1.239.0 → 1.242.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/main.js +72 -85
  2. package/package.json +4 -4
  3. package/sfdc/main.js +72 -85
package/dist/main.js CHANGED
@@ -16,7 +16,7 @@ import { setupInstrumentation, instrumentAdapter as instrumentAdapter$1, instrum
16
16
  import { HttpStatusCode, StoreKeySet, serializeStructuredKey, StringKeyInMemoryStore, Reader, deepFreeze, emitAdapterEvent, createCustomAdapterEventEmitter, StoreKeyMap, isFileReference, Environment, Luvio, InMemoryStore } from '@luvio/engine';
17
17
  import excludeStaleRecordsGate from '@salesforce/gate/lds.graphqlEvalExcludeStaleRecords';
18
18
  import { parseAndVisit, Kind, visit, execute, buildSchema, isObjectType, defaultFieldResolver } from '@luvio/graphql-parser';
19
- import { getRecordId18, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, keyBuilderContentDocumentCompositeRepresentation, getResponseCacheKeysContentDocumentCompositeRepresentation, keyBuilderFromTypeContentDocumentCompositeRepresentation, ingestContentDocumentCompositeRepresentation, keyBuilderRecord, getTypeCacheKeysRecord, keyBuilderFromTypeRecordRepresentation, ingestRecord, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getRecordAdapterFactory, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationTTL, RecordRepresentationVersion, getRecordsAdapterFactory } from '@salesforce/lds-adapters-uiapi';
19
+ import { RECORD_ID_PREFIX, RECORD_FIELDS_KEY_JUNCTION, isStoreKeyRecordViewEntity, getRecordId18, RECORD_REPRESENTATION_NAME, extractRecordIdFromStoreKey, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, keyBuilderContentDocumentCompositeRepresentation, getResponseCacheKeysContentDocumentCompositeRepresentation, keyBuilderFromTypeContentDocumentCompositeRepresentation, ingestContentDocumentCompositeRepresentation, keyBuilderRecord, RECORD_VIEW_ENTITY_ID_PREFIX, getTypeCacheKeysRecord, keyBuilderFromTypeRecordRepresentation, ingestRecord, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getRecordAdapterFactory, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationTTL, RecordRepresentationVersion, getRecordsAdapterFactory } from '@salesforce/lds-adapters-uiapi';
20
20
  import caseSensitiveUserId from '@salesforce/user/Id';
21
21
  import { idleDetector, getInstrumentation } from 'o11y/client';
22
22
  import ldsUseShortUrlGate from '@salesforce/gate/lds.useShortUrl';
@@ -1578,30 +1578,13 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
1578
1578
  * For full license text, see the LICENSE.txt file
1579
1579
  */
1580
1580
 
1581
- const API_NAMESPACE = 'UiApi';
1582
- const RECORD_REPRESENTATION_NAME = 'RecordRepresentation';
1583
- const RECORD_VIEW_ENTITY_REPRESENTATION_NAME = 'RecordViewEntityRepresentation';
1584
- const RECORD_ID_PREFIX = `${API_NAMESPACE}::${RECORD_REPRESENTATION_NAME}:`;
1585
- const RECORD_VIEW_ENTITY_ID_PREFIX = `${API_NAMESPACE}::${RECORD_VIEW_ENTITY_REPRESENTATION_NAME}:Name:`;
1586
- const RECORD_FIELDS_KEY_JUNCTION = '__fields__';
1581
+
1587
1582
  function isStoreKeyRecordId(key) {
1588
1583
  return key.indexOf(RECORD_ID_PREFIX) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION) === -1;
1589
1584
  }
1590
- function isStoreKeyRecordViewEntity(key) {
1591
- return (key.indexOf(RECORD_VIEW_ENTITY_ID_PREFIX) > -1 &&
1592
- key.indexOf(RECORD_FIELDS_KEY_JUNCTION) === -1);
1593
- }
1594
1585
  function isStoreKeyRecordField(key) {
1595
1586
  return key.indexOf(RECORD_ID_PREFIX) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION) > -1;
1596
1587
  }
1597
- function extractRecordIdFromStoreKey(key) {
1598
- if (key === undefined ||
1599
- (key.indexOf(RECORD_ID_PREFIX) === -1 && key.indexOf(RECORD_VIEW_ENTITY_ID_PREFIX) === -1)) {
1600
- return undefined;
1601
- }
1602
- const parts = key.split(':');
1603
- return parts[parts.length - 1].split('_')[0];
1604
- }
1605
1588
  function buildRecordFieldStoreKey(recordKey, fieldName) {
1606
1589
  return `${recordKey}${RECORD_FIELDS_KEY_JUNCTION}${fieldName}`;
1607
1590
  }
@@ -9494,7 +9477,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
9494
9477
  const objectNodeInfoTree = {};
9495
9478
  // save the field path to apiName map
9496
9479
  // example 1: 'ServiceAppointment' -> ['ServiceAppointment']; 'ServiceAppointment_Account' -> ['Account']; 'ServiceAppointment_Account_Owner' -> ['User']
9497
- const objectInfoApiMap = {};
9480
+ const pathToObjectApiNamesMap = {};
9498
9481
  let startNodes = new Set();
9499
9482
  let totalNodes = new Set();
9500
9483
  let objectInfos = {};
@@ -9575,7 +9558,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
9575
9558
  },
9576
9559
  });
9577
9560
  if (objectInfoService && startNodes.size > 0) {
9578
- objectInfos = await resolveObjectInfos(objectNodeInfoTree, objectInfoApiMap, startNodes, objectInfoService);
9561
+ objectInfos = await resolveObjectInfos(objectNodeInfoTree, pathToObjectApiNamesMap, startNodes, objectInfoService);
9579
9562
  }
9580
9563
  // read pass; gather whats needed
9581
9564
  visit(originalAST, {
@@ -9588,8 +9571,8 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
9588
9571
  if (!inlineFragmentSelections[ancestorPath]) {
9589
9572
  inlineFragmentSelections[ancestorPath] = [];
9590
9573
  }
9591
- const recordQueryApiName = objectInfoApiMap[ancestorPath]
9592
- ? objectInfoApiMap[ancestorPath][0]
9574
+ const recordQueryApiName = pathToObjectApiNamesMap[ancestorPath]
9575
+ ? pathToObjectApiNamesMap[ancestorPath][0]
9593
9576
  : recordQueryField.name.value;
9594
9577
  // The record node acts as the reference. The duplicated field in the record node is not injected
9595
9578
  const recordReferenceNode = [recordQueryField]
@@ -9603,7 +9586,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
9603
9586
  case 'scope':
9604
9587
  // Hanle 'MINE' field
9605
9588
  if (isScopeArgumentNodeWithType(node, 'MINE', variables)) {
9606
- if (isMineScopeAvailable(ancestorPath, objectInfoApiMap, objectInfos)) {
9589
+ if (isMineScopeAvailable(ancestorPath, pathToObjectApiNamesMap, objectInfos)) {
9607
9590
  // 'typeConditon' is added when the 'InlineFragmentNode' is appended at the write pass
9608
9591
  inlineFragmentSelections[ancestorPath].push(...mineFragmentSelections);
9609
9592
  }
@@ -9629,7 +9612,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
9629
9612
  case 'where': {
9630
9613
  inlineFragmentSelections[ancestorPath] = [
9631
9614
  ...inlineFragmentSelections[ancestorPath],
9632
- ...injectFilter(node, idState, ancestorPath, objectInfos, objectInfoApiMap, draftFunctions, recordReferenceNode),
9615
+ ...injectFilter(node, idState, ancestorPath, objectInfos, pathToObjectApiNamesMap, draftFunctions, recordReferenceNode),
9633
9616
  ];
9634
9617
  break;
9635
9618
  }
@@ -9657,7 +9640,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
9657
9640
  spanningSelections.push(selection);
9658
9641
  }
9659
9642
  }
9660
- const injectedFields = injectFields(spanningSelections, node, ancestors, objectInfos, objectInfoApiMap);
9643
+ const injectedFields = injectFields(spanningSelections, node, ancestors, objectInfos, pathToObjectApiNamesMap);
9661
9644
  const mergedInjectedFields = mergeSelectionNodes(inlineFragmentSelections[ancestorPath], injectedFields);
9662
9645
  inlineFragmentSelections[ancestorPath] = mergedInjectedFields;
9663
9646
  },
@@ -9688,8 +9671,8 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
9688
9671
  return;
9689
9672
  //const recordQueryPath = findAncesterPath(ancestors);
9690
9673
  // 'apiName' has to be at index 0 since 'node' record type could only be of 'recordQuery' or 'childRelationship'. They can not have the 'InlineFragmentNode' as its children.
9691
- const recordQueryApiName = objectInfoApiMap[ancestorPath]
9692
- ? objectInfoApiMap[ancestorPath][0]
9674
+ const recordQueryApiName = pathToObjectApiNamesMap[ancestorPath]
9675
+ ? pathToObjectApiNamesMap[ancestorPath][0]
9693
9676
  : recordQueryField.name.value;
9694
9677
  const nodeWithFragments = {
9695
9678
  ...node,
@@ -9726,7 +9709,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
9726
9709
  if (node.name.value === 'where') {
9727
9710
  const ancestorPath = findAncesterPath(ancestors);
9728
9711
  if (idState.paths.includes(ancestorPath)) {
9729
- const apiName = objectInfoApiMap[ancestorPath][0];
9712
+ const apiName = pathToObjectApiNamesMap[ancestorPath][0];
9730
9713
  const objectInfo = objectInfos[apiName];
9731
9714
  const swappedIdFilter = swapIdField(node.value, objectInfo, false, idState, draftFunctions);
9732
9715
  return {
@@ -9792,8 +9775,8 @@ function swapIdField(filterFields, objectInfo, swapped, idState, draftFunctions)
9792
9775
  };
9793
9776
  }
9794
9777
  }
9795
- function isMineScopeAvailable(apiNamePath, objectInfoApiMap, objectInfos) {
9796
- const apiName = objectInfoApiMap[apiNamePath];
9778
+ function isMineScopeAvailable(apiNamePath, pathToObjectApiNamesMap, objectInfos) {
9779
+ const apiName = pathToObjectApiNamesMap[apiNamePath];
9797
9780
  if (!apiName)
9798
9781
  return false;
9799
9782
  const objectInfo = objectInfos[apiName[0]];
@@ -9995,7 +9978,7 @@ function growFieldTree(tree, parentSectionPath, entryNode, parentNode, totalNode
9995
9978
  * @param startNodes start nodes of the tree. It can be used to fetch ObjectInfo immediately
9996
9979
  * @param path
9997
9980
  */
9998
- async function resolveObjectInfos(objectInfotree, objectInfoApiMap, startNodes, objectInfoService) {
9981
+ async function resolveObjectInfos(objectInfotree, pathToObjectApiNamesMap, startNodes, objectInfoService) {
9999
9982
  let objectInfos;
10000
9983
  try {
10001
9984
  objectInfos = await objectInfoService.getObjectInfos(Array.from(startNodes));
@@ -10009,9 +9992,9 @@ async function resolveObjectInfos(objectInfotree, objectInfoApiMap, startNodes,
10009
9992
  throw new Error(`Unable to resolve ObjectInfo(s) for ${Array.from(startNodes)}`);
10010
9993
  }
10011
9994
  for (const startNode of startNodes) {
10012
- objectInfoApiMap[startNode] = [startNode];
9995
+ pathToObjectApiNamesMap[startNode] = [startNode];
10013
9996
  const children = objectInfotree[startNode];
10014
- const subObjectInfoMap = await fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfos, children, startNode, objectInfoService);
9997
+ const subObjectInfoMap = await fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, objectInfos, children, startNode, objectInfoService);
10015
9998
  objectInfos = { ...objectInfos, ...subObjectInfoMap };
10016
9999
  }
10017
10000
  return objectInfos;
@@ -10019,15 +10002,15 @@ async function resolveObjectInfos(objectInfotree, objectInfoApiMap, startNodes,
10019
10002
  // example 1: 'parentPath': 'ServiceAppointment', 'nodesAtSameLevel': ['Account']
10020
10003
  // example 2: 'parentPath': 'ServiceAppointment', 'nodesAtSameLevel': ['Owner'], this example has 2 apiName for the node 'Owner'
10021
10004
  // example 3: 'parentPath': 'ServiceAppointment_Owner', 'nodesAtSameLevel': ['User', 'Group']
10022
- async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap, nodesAtSameLevel, parentPath, objectInfoService) {
10023
- const objectInfoApiNames = objectInfoApiMap[parentPath];
10005
+ async function fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, objectInfoMap, nodesAtSameLevel, parentPath, objectInfoService) {
10006
+ const objectInfoApiNames = pathToObjectApiNamesMap[parentPath];
10024
10007
  if (!objectInfoApiNames) {
10025
10008
  // eslint-disable-next-line
10026
10009
  throw new Error(`Object Info does not exist for ${parentPath}`);
10027
10010
  }
10028
10011
  const validObjectInfoNodes = [];
10029
10012
  let updatedObjectInfoMap = {};
10030
- // InlineFragment and polymorphic field support fits into this scenario ObjectInfoApiMap Entry: 'ServiceAppointment_Owner' -> ['User', 'Group']; ServiceAppointment_Owner_User' -> ['User']
10013
+ // InlineFragment and polymorphic field support fits into this scenario pathToObjectApiNamesMap Entry: 'ServiceAppointment_Owner' -> ['User', 'Group']; ServiceAppointment_Owner_User' -> ['User']
10031
10014
  if (objectInfoApiNames.length > 0 &&
10032
10015
  nodesAtSameLevel.length > 0 &&
10033
10016
  objectInfoApiNames.includes(nodesAtSameLevel[0].name)) {
@@ -10040,7 +10023,7 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
10040
10023
  throw new Error(`Condition ${field.name} does not exists for ${parentPath}`);
10041
10024
  }
10042
10025
  const path = `${parentPath}_${field.name}`;
10043
- objectInfoApiMap[path] = [field.name];
10026
+ pathToObjectApiNamesMap[path] = [field.name];
10044
10027
  }
10045
10028
  validObjectInfoNodes.push(...nodesAtSameLevel);
10046
10029
  updatedObjectInfoMap = { ...objectInfoMap };
@@ -10082,12 +10065,12 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
10082
10065
  fieldDefinition.referenceToInfos
10083
10066
  .filter((referenceToInfo) => requestedApiNames.includes(referenceToInfo.apiName))
10084
10067
  .forEach((ref) => {
10085
- if (!objectInfoApiMap[path]) {
10086
- objectInfoApiMap[path] = [];
10068
+ if (!pathToObjectApiNamesMap[path]) {
10069
+ pathToObjectApiNamesMap[path] = [];
10087
10070
  }
10088
10071
  // 'ServiceAppointment_Owner' ->['User', 'Group']
10089
- if (!objectInfoApiMap[path].includes(ref.apiName)) {
10090
- objectInfoApiMap[path].push(ref.apiName);
10072
+ if (!pathToObjectApiNamesMap[path].includes(ref.apiName)) {
10073
+ pathToObjectApiNamesMap[path].push(ref.apiName);
10091
10074
  }
10092
10075
  if (!apiNames.includes(ref.apiName)) {
10093
10076
  apiNames.push(ref.apiName);
@@ -10097,11 +10080,11 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
10097
10080
  }
10098
10081
  else if (fieldDefinition.referenceToInfos.length === 1) {
10099
10082
  const ref = fieldDefinition.referenceToInfos[0];
10100
- if (!objectInfoApiMap[path]) {
10101
- objectInfoApiMap[path] = [];
10083
+ if (!pathToObjectApiNamesMap[path]) {
10084
+ pathToObjectApiNamesMap[path] = [];
10102
10085
  }
10103
- if (!objectInfoApiMap[path].includes(ref.apiName)) {
10104
- objectInfoApiMap[path].push(ref.apiName);
10086
+ if (!pathToObjectApiNamesMap[path].includes(ref.apiName)) {
10087
+ pathToObjectApiNamesMap[path].push(ref.apiName);
10105
10088
  }
10106
10089
  if (!apiNames.includes(ref.apiName)) {
10107
10090
  apiNames.push(ref.apiName);
@@ -10112,11 +10095,11 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
10112
10095
  // handles 'childRelationship'
10113
10096
  const childRelationship = parentObjectInfo.childRelationships.find((childRelationship) => childRelationship.relationshipName === field);
10114
10097
  if (childRelationship) {
10115
- if (!objectInfoApiMap[path]) {
10116
- objectInfoApiMap[path] = [];
10098
+ if (!pathToObjectApiNamesMap[path]) {
10099
+ pathToObjectApiNamesMap[path] = [];
10117
10100
  }
10118
- if (!objectInfoApiMap[path].includes(childRelationship.childObjectApiName)) {
10119
- objectInfoApiMap[path].push(childRelationship.childObjectApiName);
10101
+ if (!pathToObjectApiNamesMap[path].includes(childRelationship.childObjectApiName)) {
10102
+ pathToObjectApiNamesMap[path].push(childRelationship.childObjectApiName);
10120
10103
  }
10121
10104
  if (!apiNames.includes(childRelationship.childObjectApiName)) {
10122
10105
  apiNames.push(childRelationship.childObjectApiName);
@@ -10141,7 +10124,7 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
10141
10124
  const subLevelFields = objectInfotree[field];
10142
10125
  const path = `${parentPath}_${field}`;
10143
10126
  if (subLevelFields && subLevelFields.length > 0) {
10144
- const subObjectInfos = await fetchObjectInfos(objectInfotree, objectInfoApiMap, updatedObjectInfoMap, subLevelFields, path, objectInfoService);
10127
+ const subObjectInfos = await fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, updatedObjectInfoMap, subLevelFields, path, objectInfoService);
10145
10128
  updatedObjectInfoMap = { ...updatedObjectInfoMap, ...subObjectInfos };
10146
10129
  }
10147
10130
  }
@@ -10156,21 +10139,21 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
10156
10139
  * 'path' and 'queryNode' is 1 level above the 'filterNode'
10157
10140
  * @param filterNode filter node which needs to be injected. For example, 'State' ObjectFieldNode within filter 'where: { State: { eq: "Nova Scotia" }}'
10158
10141
  * @param idState ID state will be updated to determine if the ID fields in AST need to be swapped. The swapping happens later.
10159
- * @param path path to the current filterNode's parent. For example, path could be 'ServiceApointment' when filterNode is 'State'. If the path does not exist in 'objectInfoApiMap', parent node is not an field of relationship or recordQuery
10142
+ * @param path path to the current filterNode's parent. For example, path could be 'ServiceApointment' when filterNode is 'State'. If the path does not exist in 'pathToObjectApiNamesMap', parent node is not an field of relationship or recordQuery
10160
10143
  * @param queryNode referece FieldNode which provides the information if 'filterNode' exist in it nor not.
10161
10144
  * @param objectInfos ObjectInfo map used in injection. If ObjectInfo misses or field does not exist in ObjectInfo, the error will be thrown
10162
- * @param objectInfoApiMap map used to locate the ObjectInfo. The key is path to a field, value is the ObjectInfo's apiName array. In the case of polymorphic fields, the apiName array have 2 or more elements. For example, 'ServiceAppointment' -> ['ServiceAppointment']; 'ServiceAppointment_Account' -> ['Account'], 'ServiceAppointment_Owner' -> ['User', 'Group'].
10145
+ * @param pathToObjectApiNamesMap map used to locate the ObjectInfo. The key is path to a field, value is the ObjectInfo's apiName array. In the case of polymorphic fields, the apiName array have 2 or more elements. For example, 'ServiceAppointment' -> ['ServiceAppointment']; 'ServiceAppointment_Account' -> ['Account'], 'ServiceAppointment_Owner' -> ['User', 'Group'].
10163
10146
  * @param draftFunctions functions for working with record ids that may be draft-created ids
10164
10147
  * @returns an array of nodes with injected fields
10165
10148
  */
10166
- function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap, draftFunctions, queryNode) {
10149
+ function injectFilter(filterNode, idState, path, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode) {
10167
10150
  const injectedSelections = [];
10168
10151
  switch (filterNode.kind) {
10169
10152
  case Kind.ARGUMENT:
10170
10153
  if (filterNode.value.kind !== 'ObjectValue')
10171
10154
  return [];
10172
10155
  filterNode.value.fields.forEach((objectFieldNode) => {
10173
- let subResults = injectFilter(objectFieldNode, idState, path, objectInfos, objectInfoApiMap, draftFunctions, queryNode);
10156
+ let subResults = injectFilter(objectFieldNode, idState, path, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode);
10174
10157
  for (const subResult of subResults) {
10175
10158
  mergeOrAddToGroup(injectedSelections, subResult);
10176
10159
  }
@@ -10185,7 +10168,7 @@ function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap,
10185
10168
  case Kind.LIST: {
10186
10169
  filterNode.value.values.filter(isObjectValueNode).forEach((objectValueNode) => {
10187
10170
  objectValueNode.fields.forEach((objectFieldNode) => {
10188
- const subResults = injectFilter(objectFieldNode, idState, path, objectInfos, objectInfoApiMap, draftFunctions, queryNode);
10171
+ const subResults = injectFilter(objectFieldNode, idState, path, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode);
10189
10172
  for (const subResult of subResults) {
10190
10173
  mergeOrAddToGroup(injectedSelections, subResult);
10191
10174
  }
@@ -10196,7 +10179,7 @@ function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap,
10196
10179
  case Kind.OBJECT: {
10197
10180
  if (filterNode.name.value === 'not') {
10198
10181
  filterNode.value.fields.forEach((objectFieldNode) => {
10199
- const subResults = injectFilter(objectFieldNode, idState, path, objectInfos, objectInfoApiMap, draftFunctions, queryNode);
10182
+ const subResults = injectFilter(objectFieldNode, idState, path, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode);
10200
10183
  for (const subResult of subResults) {
10201
10184
  mergeOrAddToGroup(injectedSelections, subResult);
10202
10185
  }
@@ -10206,7 +10189,7 @@ function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap,
10206
10189
  let apiNames = [];
10207
10190
  let isScalarField = false;
10208
10191
  //It is possible that this is a polymorphic field
10209
- apiNames = objectInfoApiMap[path];
10192
+ apiNames = pathToObjectApiNamesMap[path];
10210
10193
  // example: path: 'ServiceAppointment_LastModifiedDate'; filterNode: '{eq: {literal: LAST_WEEK}}'. queryNode: 'LastModifedDate { value}' FilterNode's parent has been verifed as a valid node
10211
10194
  if (apiNames === undefined) {
10212
10195
  isScalarField = true;
@@ -10236,29 +10219,23 @@ function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap,
10236
10219
  }
10237
10220
  });
10238
10221
  let isSpanning = false;
10222
+ // if true, current node is a polymorphic concrete type node. For example, field node `User` under `Owner`
10239
10223
  let isInlineFragment = false;
10240
10224
  let isPolymorphicField = false;
10241
10225
  let isTypeNameExisting = false;
10242
10226
  let curPath;
10243
10227
  let fieldName = filterNode.name.value;
10244
10228
  curPath = `${path}_${fieldName}`;
10245
- if (objectInfoApiMap[curPath] && objectInfoApiMap[curPath].length > 0) {
10229
+ if (pathToObjectApiNamesMap[curPath] &&
10230
+ pathToObjectApiNamesMap[curPath].length > 0) {
10246
10231
  isSpanning = true;
10247
- if (objectInfoApiMap[curPath].length === 1) {
10248
- if (objectInfoApiMap[path] &&
10249
- objectInfoApiMap[path].length >= 1 &&
10250
- objectInfoApiMap[path].includes(objectInfoApiMap[curPath][0])) {
10251
- isInlineFragment = true;
10252
- }
10253
- }
10254
- // Checks if the current filter node is a polymorphic field. 'ServiceAppointment_Owner' --> ['User']; 'ServiceAppointment_Owner_User' --> ['User']
10255
- const childApiName = objectInfoApiMap[curPath][0];
10256
- const trialApiNames = objectInfoApiMap[`${curPath}_${childApiName}`];
10257
- if (trialApiNames !== undefined &&
10258
- trialApiNames.length === 1 &&
10259
- trialApiNames[0] === childApiName) {
10260
- isPolymorphicField = true;
10232
+ if (pathToObjectApiNamesMap[curPath].length === 1 &&
10233
+ pathToObjectApiNamesMap[path] &&
10234
+ pathToObjectApiNamesMap[path].length >= 1 &&
10235
+ pathToObjectApiNamesMap[path].includes(pathToObjectApiNamesMap[curPath][0])) {
10236
+ isInlineFragment = isPolymorphicFieldPath(path, pathToObjectApiNamesMap);
10261
10237
  }
10238
+ isPolymorphicField = isPolymorphicFieldPath(curPath, pathToObjectApiNamesMap);
10262
10239
  }
10263
10240
  // When filter node is at InLineFragment Level(a concrete entity of polymorphic field), query node is one level up. For example, ObjectFieldNode is ...{User:{...}}, queryNode is Owner:[User]
10264
10241
  if (isInlineFragment) {
@@ -10302,9 +10279,9 @@ function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap,
10302
10279
  throw new Error(`Field ${fieldName} does not exist in ${apiNames[0]}`);
10303
10280
  }
10304
10281
  }
10305
- const objectInfoName = objectInfoApiMap[curPath] !== undefined
10306
- ? objectInfoApiMap[curPath][0]
10307
- : objectInfoApiMap[path][0];
10282
+ const objectInfoName = pathToObjectApiNamesMap[curPath] !== undefined
10283
+ ? pathToObjectApiNamesMap[curPath][0]
10284
+ : pathToObjectApiNamesMap[path][0];
10308
10285
  const isIdField = isFieldAnIdField(filterNode.name.value, objectInfos[objectInfoName]);
10309
10286
  if (!isIdField) {
10310
10287
  let subSelectionNodes = [];
@@ -10316,7 +10293,7 @@ function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap,
10316
10293
  updateIDInfo(subFieldNode, idState, draftFunctions);
10317
10294
  }
10318
10295
  // try injecting the fields within predicate no matter it has relation or not.
10319
- let subResults = injectFilter(subFieldNode, idState, curPath, objectInfos, objectInfoApiMap, draftFunctions, existingFields ? existingFields[0] : undefined);
10296
+ let subResults = injectFilter(subFieldNode, idState, curPath, objectInfos, pathToObjectApiNamesMap, draftFunctions, existingFields ? existingFields[0] : undefined);
10320
10297
  subSelectionNodes = subSelectionNodes.concat(subResults);
10321
10298
  });
10322
10299
  if (!subFieldsHasId) {
@@ -10477,6 +10454,16 @@ function mergeOrAddToGroup(group, element) {
10477
10454
  }
10478
10455
  group.push(element);
10479
10456
  }
10457
+ // checks if the path points to a polymorphic field. If path points to a polymorphic field, its entry within `pathToObjectApiNamesMap` has the format {"Path" : ["elem1", "elem2"]}.
10458
+ // There must be also two entries pointing to concrete polymorphic field path. The two entries are like {"Path_elem1" : ["elem1"]} and {"Path_elem2" : ["elem2"]}
10459
+ // For example ServiceAppointment_Owner' --> ['User', 'Group']; 'ServiceAppointment_Owner_User' --> ['User'], 'ServiceAppointment_Owner_Group' --> ['Group']
10460
+ function isPolymorphicFieldPath(path, pathToObjectApiNamesMap) {
10461
+ const apiName = pathToObjectApiNamesMap[path][0];
10462
+ const apiNamesAtChildPath = pathToObjectApiNamesMap[`${path}_${apiName}`];
10463
+ return (apiNamesAtChildPath !== undefined &&
10464
+ apiNamesAtChildPath.length === 1 &&
10465
+ apiNamesAtChildPath[0] === apiName);
10466
+ }
10480
10467
  function isFieldAnIdField(fieldName, objectInfo) {
10481
10468
  if (fieldName === 'Id')
10482
10469
  return true;
@@ -10529,10 +10516,10 @@ function updateIDInfo(fieldNode, idState, draftFunctions) {
10529
10516
  * @param parentNode parent node of param 1
10530
10517
  * @param ancestors ancester of param 1
10531
10518
  * @param objectInfos ObjectInfo map used in injection. If ObjectInfo misses or field does not exist in ObjectInfo, the error will be thrown
10532
- * @param objectInfoApiMap map used to locate the ObjectInfo. The key is path to a field, value is the ObjectInfo's apiName array. In the case of polymorphic fields, the apiName array have 2 or more elements. For example, 'ServiceAppointment' -> ['ServiceAppointment']; 'ServiceAppointment_Account' -> ['Account'], 'ServiceAppointment_Owner' -> ['User', 'Group'].
10519
+ * @param pathToObjectApiNamesMap map used to locate the ObjectInfo. The key is path to a field, value is the ObjectInfo's apiName array. In the case of polymorphic fields, the apiName array have 2 or more elements. For example, 'ServiceAppointment' -> ['ServiceAppointment']; 'ServiceAppointment_Account' -> ['Account'], 'ServiceAppointment_Owner' -> ['User', 'Group'].
10533
10520
  * @return injected SelectionNodes used to construct the InlineFragment.
10534
10521
  */
10535
- function injectFields(selections, parentNode, ancestors, objectInfos, objectInfoApiMap) {
10522
+ function injectFields(selections, parentNode, ancestors, objectInfos, pathToObjectApiNamesMap) {
10536
10523
  /**
10537
10524
  * 1 parentship can return 2 FieldNode which need to be flattened
10538
10525
  * Concact: { ** Contact { ** ContactId {
@@ -10557,7 +10544,7 @@ function injectFields(selections, parentNode, ancestors, objectInfos, objectInfo
10557
10544
  }
10558
10545
  }
10559
10546
  // Handles multiple level field injection like 'ServiceAppointment' --> 'Account' --> 'Owner'
10560
- const subInjectedSelections = injectFields(spanningSubSelections, selection, ancestors, objectInfos, objectInfoApiMap);
10547
+ const subInjectedSelections = injectFields(spanningSubSelections, selection, ancestors, objectInfos, pathToObjectApiNamesMap);
10561
10548
  if (!selection.selectionSet) {
10562
10549
  return selection;
10563
10550
  }
@@ -10669,11 +10656,11 @@ function injectFields(selections, parentNode, ancestors, objectInfos, objectInfo
10669
10656
  const unVisitedAncestors = ancestors.slice(0, parentInfo.parentIndex);
10670
10657
  // path : "TimeSheet"
10671
10658
  const grandParentPath = findAncesterPath(unVisitedAncestors);
10672
- if (objectInfoApiMap &&
10673
- objectInfoApiMap[grandParentPath] &&
10659
+ if (pathToObjectApiNamesMap &&
10660
+ pathToObjectApiNamesMap[grandParentPath] &&
10674
10661
  objectInfos &&
10675
- objectInfos[objectInfoApiMap[grandParentPath][0]]) {
10676
- const grandParentObjectInfo = objectInfos[objectInfoApiMap[grandParentPath][0]];
10662
+ objectInfos[pathToObjectApiNamesMap[grandParentPath][0]]) {
10663
+ const grandParentObjectInfo = objectInfos[pathToObjectApiNamesMap[grandParentPath][0]];
10677
10664
  // exmaple "TimeSheetEntries"
10678
10665
  const parentFieldName = parent.name.value;
10679
10666
  const targetRelationship = grandParentObjectInfo.childRelationships.find((childRelationship) => {
@@ -17059,4 +17046,4 @@ register({
17059
17046
  });
17060
17047
 
17061
17048
  export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
17062
- // version: 1.239.0-6c531185a
17049
+ // version: 1.242.0-57237c3b6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/lds-runtime-mobile",
3
- "version": "1.239.0",
3
+ "version": "1.242.0",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "description": "LDS runtime for mobile/hybrid environments.",
6
6
  "main": "dist/main.js",
@@ -87,9 +87,9 @@
87
87
  "targets": {
88
88
  "build": {
89
89
  "outputs": [
90
- "packages/lds-runtime-mobile/dist",
91
- "packages/lds-runtime-mobile/sfdc",
92
- "packages/lds-runtime-mobile/src/__tests__/fixtures"
90
+ "{projectRoot}/dist",
91
+ "{projectRoot}/sfdc",
92
+ "{projectRoot}/src/__tests__/fixtures"
93
93
  ]
94
94
  }
95
95
  }
package/sfdc/main.js CHANGED
@@ -16,7 +16,7 @@ import { setupInstrumentation, instrumentAdapter as instrumentAdapter$1, instrum
16
16
  import { HttpStatusCode, StoreKeySet, serializeStructuredKey, StringKeyInMemoryStore, Reader, deepFreeze, emitAdapterEvent, createCustomAdapterEventEmitter, StoreKeyMap, isFileReference, Environment, Luvio, InMemoryStore } from 'force/luvioEngine';
17
17
  import excludeStaleRecordsGate from '@salesforce/gate/lds.graphqlEvalExcludeStaleRecords';
18
18
  import { parseAndVisit, Kind, visit, execute, buildSchema, isObjectType, defaultFieldResolver } from 'force/ldsGraphqlParser';
19
- import { getRecordId18, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, keyBuilderContentDocumentCompositeRepresentation, getResponseCacheKeysContentDocumentCompositeRepresentation, keyBuilderFromTypeContentDocumentCompositeRepresentation, ingestContentDocumentCompositeRepresentation, keyBuilderRecord, getTypeCacheKeysRecord, keyBuilderFromTypeRecordRepresentation, ingestRecord, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getRecordAdapterFactory, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationTTL, RecordRepresentationVersion, getRecordsAdapterFactory } from 'force/ldsAdaptersUiapi';
19
+ import { RECORD_ID_PREFIX, RECORD_FIELDS_KEY_JUNCTION, isStoreKeyRecordViewEntity, getRecordId18, RECORD_REPRESENTATION_NAME, extractRecordIdFromStoreKey, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, keyBuilderContentDocumentCompositeRepresentation, getResponseCacheKeysContentDocumentCompositeRepresentation, keyBuilderFromTypeContentDocumentCompositeRepresentation, ingestContentDocumentCompositeRepresentation, keyBuilderRecord, RECORD_VIEW_ENTITY_ID_PREFIX, getTypeCacheKeysRecord, keyBuilderFromTypeRecordRepresentation, ingestRecord, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getRecordAdapterFactory, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationTTL, RecordRepresentationVersion, getRecordsAdapterFactory } from 'force/ldsAdaptersUiapi';
20
20
  import caseSensitiveUserId from '@salesforce/user/Id';
21
21
  import { idleDetector, getInstrumentation } from 'o11y/client';
22
22
  import ldsUseShortUrlGate from '@salesforce/gate/lds.useShortUrl';
@@ -1578,30 +1578,13 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
1578
1578
  * For full license text, see the LICENSE.txt file
1579
1579
  */
1580
1580
 
1581
- const API_NAMESPACE = 'UiApi';
1582
- const RECORD_REPRESENTATION_NAME = 'RecordRepresentation';
1583
- const RECORD_VIEW_ENTITY_REPRESENTATION_NAME = 'RecordViewEntityRepresentation';
1584
- const RECORD_ID_PREFIX = `${API_NAMESPACE}::${RECORD_REPRESENTATION_NAME}:`;
1585
- const RECORD_VIEW_ENTITY_ID_PREFIX = `${API_NAMESPACE}::${RECORD_VIEW_ENTITY_REPRESENTATION_NAME}:Name:`;
1586
- const RECORD_FIELDS_KEY_JUNCTION = '__fields__';
1581
+
1587
1582
  function isStoreKeyRecordId(key) {
1588
1583
  return key.indexOf(RECORD_ID_PREFIX) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION) === -1;
1589
1584
  }
1590
- function isStoreKeyRecordViewEntity(key) {
1591
- return (key.indexOf(RECORD_VIEW_ENTITY_ID_PREFIX) > -1 &&
1592
- key.indexOf(RECORD_FIELDS_KEY_JUNCTION) === -1);
1593
- }
1594
1585
  function isStoreKeyRecordField(key) {
1595
1586
  return key.indexOf(RECORD_ID_PREFIX) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION) > -1;
1596
1587
  }
1597
- function extractRecordIdFromStoreKey(key) {
1598
- if (key === undefined ||
1599
- (key.indexOf(RECORD_ID_PREFIX) === -1 && key.indexOf(RECORD_VIEW_ENTITY_ID_PREFIX) === -1)) {
1600
- return undefined;
1601
- }
1602
- const parts = key.split(':');
1603
- return parts[parts.length - 1].split('_')[0];
1604
- }
1605
1588
  function buildRecordFieldStoreKey(recordKey, fieldName) {
1606
1589
  return `${recordKey}${RECORD_FIELDS_KEY_JUNCTION}${fieldName}`;
1607
1590
  }
@@ -9494,7 +9477,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
9494
9477
  const objectNodeInfoTree = {};
9495
9478
  // save the field path to apiName map
9496
9479
  // example 1: 'ServiceAppointment' -> ['ServiceAppointment']; 'ServiceAppointment_Account' -> ['Account']; 'ServiceAppointment_Account_Owner' -> ['User']
9497
- const objectInfoApiMap = {};
9480
+ const pathToObjectApiNamesMap = {};
9498
9481
  let startNodes = new Set();
9499
9482
  let totalNodes = new Set();
9500
9483
  let objectInfos = {};
@@ -9575,7 +9558,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
9575
9558
  },
9576
9559
  });
9577
9560
  if (objectInfoService && startNodes.size > 0) {
9578
- objectInfos = await resolveObjectInfos(objectNodeInfoTree, objectInfoApiMap, startNodes, objectInfoService);
9561
+ objectInfos = await resolveObjectInfos(objectNodeInfoTree, pathToObjectApiNamesMap, startNodes, objectInfoService);
9579
9562
  }
9580
9563
  // read pass; gather whats needed
9581
9564
  visit(originalAST, {
@@ -9588,8 +9571,8 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
9588
9571
  if (!inlineFragmentSelections[ancestorPath]) {
9589
9572
  inlineFragmentSelections[ancestorPath] = [];
9590
9573
  }
9591
- const recordQueryApiName = objectInfoApiMap[ancestorPath]
9592
- ? objectInfoApiMap[ancestorPath][0]
9574
+ const recordQueryApiName = pathToObjectApiNamesMap[ancestorPath]
9575
+ ? pathToObjectApiNamesMap[ancestorPath][0]
9593
9576
  : recordQueryField.name.value;
9594
9577
  // The record node acts as the reference. The duplicated field in the record node is not injected
9595
9578
  const recordReferenceNode = [recordQueryField]
@@ -9603,7 +9586,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
9603
9586
  case 'scope':
9604
9587
  // Hanle 'MINE' field
9605
9588
  if (isScopeArgumentNodeWithType(node, 'MINE', variables)) {
9606
- if (isMineScopeAvailable(ancestorPath, objectInfoApiMap, objectInfos)) {
9589
+ if (isMineScopeAvailable(ancestorPath, pathToObjectApiNamesMap, objectInfos)) {
9607
9590
  // 'typeConditon' is added when the 'InlineFragmentNode' is appended at the write pass
9608
9591
  inlineFragmentSelections[ancestorPath].push(...mineFragmentSelections);
9609
9592
  }
@@ -9629,7 +9612,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
9629
9612
  case 'where': {
9630
9613
  inlineFragmentSelections[ancestorPath] = [
9631
9614
  ...inlineFragmentSelections[ancestorPath],
9632
- ...injectFilter(node, idState, ancestorPath, objectInfos, objectInfoApiMap, draftFunctions, recordReferenceNode),
9615
+ ...injectFilter(node, idState, ancestorPath, objectInfos, pathToObjectApiNamesMap, draftFunctions, recordReferenceNode),
9633
9616
  ];
9634
9617
  break;
9635
9618
  }
@@ -9657,7 +9640,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
9657
9640
  spanningSelections.push(selection);
9658
9641
  }
9659
9642
  }
9660
- const injectedFields = injectFields(spanningSelections, node, ancestors, objectInfos, objectInfoApiMap);
9643
+ const injectedFields = injectFields(spanningSelections, node, ancestors, objectInfos, pathToObjectApiNamesMap);
9661
9644
  const mergedInjectedFields = mergeSelectionNodes(inlineFragmentSelections[ancestorPath], injectedFields);
9662
9645
  inlineFragmentSelections[ancestorPath] = mergedInjectedFields;
9663
9646
  },
@@ -9688,8 +9671,8 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
9688
9671
  return;
9689
9672
  //const recordQueryPath = findAncesterPath(ancestors);
9690
9673
  // 'apiName' has to be at index 0 since 'node' record type could only be of 'recordQuery' or 'childRelationship'. They can not have the 'InlineFragmentNode' as its children.
9691
- const recordQueryApiName = objectInfoApiMap[ancestorPath]
9692
- ? objectInfoApiMap[ancestorPath][0]
9674
+ const recordQueryApiName = pathToObjectApiNamesMap[ancestorPath]
9675
+ ? pathToObjectApiNamesMap[ancestorPath][0]
9693
9676
  : recordQueryField.name.value;
9694
9677
  const nodeWithFragments = {
9695
9678
  ...node,
@@ -9726,7 +9709,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
9726
9709
  if (node.name.value === 'where') {
9727
9710
  const ancestorPath = findAncesterPath(ancestors);
9728
9711
  if (idState.paths.includes(ancestorPath)) {
9729
- const apiName = objectInfoApiMap[ancestorPath][0];
9712
+ const apiName = pathToObjectApiNamesMap[ancestorPath][0];
9730
9713
  const objectInfo = objectInfos[apiName];
9731
9714
  const swappedIdFilter = swapIdField(node.value, objectInfo, false, idState, draftFunctions);
9732
9715
  return {
@@ -9792,8 +9775,8 @@ function swapIdField(filterFields, objectInfo, swapped, idState, draftFunctions)
9792
9775
  };
9793
9776
  }
9794
9777
  }
9795
- function isMineScopeAvailable(apiNamePath, objectInfoApiMap, objectInfos) {
9796
- const apiName = objectInfoApiMap[apiNamePath];
9778
+ function isMineScopeAvailable(apiNamePath, pathToObjectApiNamesMap, objectInfos) {
9779
+ const apiName = pathToObjectApiNamesMap[apiNamePath];
9797
9780
  if (!apiName)
9798
9781
  return false;
9799
9782
  const objectInfo = objectInfos[apiName[0]];
@@ -9995,7 +9978,7 @@ function growFieldTree(tree, parentSectionPath, entryNode, parentNode, totalNode
9995
9978
  * @param startNodes start nodes of the tree. It can be used to fetch ObjectInfo immediately
9996
9979
  * @param path
9997
9980
  */
9998
- async function resolveObjectInfos(objectInfotree, objectInfoApiMap, startNodes, objectInfoService) {
9981
+ async function resolveObjectInfos(objectInfotree, pathToObjectApiNamesMap, startNodes, objectInfoService) {
9999
9982
  let objectInfos;
10000
9983
  try {
10001
9984
  objectInfos = await objectInfoService.getObjectInfos(Array.from(startNodes));
@@ -10009,9 +9992,9 @@ async function resolveObjectInfos(objectInfotree, objectInfoApiMap, startNodes,
10009
9992
  throw new Error(`Unable to resolve ObjectInfo(s) for ${Array.from(startNodes)}`);
10010
9993
  }
10011
9994
  for (const startNode of startNodes) {
10012
- objectInfoApiMap[startNode] = [startNode];
9995
+ pathToObjectApiNamesMap[startNode] = [startNode];
10013
9996
  const children = objectInfotree[startNode];
10014
- const subObjectInfoMap = await fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfos, children, startNode, objectInfoService);
9997
+ const subObjectInfoMap = await fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, objectInfos, children, startNode, objectInfoService);
10015
9998
  objectInfos = { ...objectInfos, ...subObjectInfoMap };
10016
9999
  }
10017
10000
  return objectInfos;
@@ -10019,15 +10002,15 @@ async function resolveObjectInfos(objectInfotree, objectInfoApiMap, startNodes,
10019
10002
  // example 1: 'parentPath': 'ServiceAppointment', 'nodesAtSameLevel': ['Account']
10020
10003
  // example 2: 'parentPath': 'ServiceAppointment', 'nodesAtSameLevel': ['Owner'], this example has 2 apiName for the node 'Owner'
10021
10004
  // example 3: 'parentPath': 'ServiceAppointment_Owner', 'nodesAtSameLevel': ['User', 'Group']
10022
- async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap, nodesAtSameLevel, parentPath, objectInfoService) {
10023
- const objectInfoApiNames = objectInfoApiMap[parentPath];
10005
+ async function fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, objectInfoMap, nodesAtSameLevel, parentPath, objectInfoService) {
10006
+ const objectInfoApiNames = pathToObjectApiNamesMap[parentPath];
10024
10007
  if (!objectInfoApiNames) {
10025
10008
  // eslint-disable-next-line
10026
10009
  throw new Error(`Object Info does not exist for ${parentPath}`);
10027
10010
  }
10028
10011
  const validObjectInfoNodes = [];
10029
10012
  let updatedObjectInfoMap = {};
10030
- // InlineFragment and polymorphic field support fits into this scenario ObjectInfoApiMap Entry: 'ServiceAppointment_Owner' -> ['User', 'Group']; ServiceAppointment_Owner_User' -> ['User']
10013
+ // InlineFragment and polymorphic field support fits into this scenario pathToObjectApiNamesMap Entry: 'ServiceAppointment_Owner' -> ['User', 'Group']; ServiceAppointment_Owner_User' -> ['User']
10031
10014
  if (objectInfoApiNames.length > 0 &&
10032
10015
  nodesAtSameLevel.length > 0 &&
10033
10016
  objectInfoApiNames.includes(nodesAtSameLevel[0].name)) {
@@ -10040,7 +10023,7 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
10040
10023
  throw new Error(`Condition ${field.name} does not exists for ${parentPath}`);
10041
10024
  }
10042
10025
  const path = `${parentPath}_${field.name}`;
10043
- objectInfoApiMap[path] = [field.name];
10026
+ pathToObjectApiNamesMap[path] = [field.name];
10044
10027
  }
10045
10028
  validObjectInfoNodes.push(...nodesAtSameLevel);
10046
10029
  updatedObjectInfoMap = { ...objectInfoMap };
@@ -10082,12 +10065,12 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
10082
10065
  fieldDefinition.referenceToInfos
10083
10066
  .filter((referenceToInfo) => requestedApiNames.includes(referenceToInfo.apiName))
10084
10067
  .forEach((ref) => {
10085
- if (!objectInfoApiMap[path]) {
10086
- objectInfoApiMap[path] = [];
10068
+ if (!pathToObjectApiNamesMap[path]) {
10069
+ pathToObjectApiNamesMap[path] = [];
10087
10070
  }
10088
10071
  // 'ServiceAppointment_Owner' ->['User', 'Group']
10089
- if (!objectInfoApiMap[path].includes(ref.apiName)) {
10090
- objectInfoApiMap[path].push(ref.apiName);
10072
+ if (!pathToObjectApiNamesMap[path].includes(ref.apiName)) {
10073
+ pathToObjectApiNamesMap[path].push(ref.apiName);
10091
10074
  }
10092
10075
  if (!apiNames.includes(ref.apiName)) {
10093
10076
  apiNames.push(ref.apiName);
@@ -10097,11 +10080,11 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
10097
10080
  }
10098
10081
  else if (fieldDefinition.referenceToInfos.length === 1) {
10099
10082
  const ref = fieldDefinition.referenceToInfos[0];
10100
- if (!objectInfoApiMap[path]) {
10101
- objectInfoApiMap[path] = [];
10083
+ if (!pathToObjectApiNamesMap[path]) {
10084
+ pathToObjectApiNamesMap[path] = [];
10102
10085
  }
10103
- if (!objectInfoApiMap[path].includes(ref.apiName)) {
10104
- objectInfoApiMap[path].push(ref.apiName);
10086
+ if (!pathToObjectApiNamesMap[path].includes(ref.apiName)) {
10087
+ pathToObjectApiNamesMap[path].push(ref.apiName);
10105
10088
  }
10106
10089
  if (!apiNames.includes(ref.apiName)) {
10107
10090
  apiNames.push(ref.apiName);
@@ -10112,11 +10095,11 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
10112
10095
  // handles 'childRelationship'
10113
10096
  const childRelationship = parentObjectInfo.childRelationships.find((childRelationship) => childRelationship.relationshipName === field);
10114
10097
  if (childRelationship) {
10115
- if (!objectInfoApiMap[path]) {
10116
- objectInfoApiMap[path] = [];
10098
+ if (!pathToObjectApiNamesMap[path]) {
10099
+ pathToObjectApiNamesMap[path] = [];
10117
10100
  }
10118
- if (!objectInfoApiMap[path].includes(childRelationship.childObjectApiName)) {
10119
- objectInfoApiMap[path].push(childRelationship.childObjectApiName);
10101
+ if (!pathToObjectApiNamesMap[path].includes(childRelationship.childObjectApiName)) {
10102
+ pathToObjectApiNamesMap[path].push(childRelationship.childObjectApiName);
10120
10103
  }
10121
10104
  if (!apiNames.includes(childRelationship.childObjectApiName)) {
10122
10105
  apiNames.push(childRelationship.childObjectApiName);
@@ -10141,7 +10124,7 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
10141
10124
  const subLevelFields = objectInfotree[field];
10142
10125
  const path = `${parentPath}_${field}`;
10143
10126
  if (subLevelFields && subLevelFields.length > 0) {
10144
- const subObjectInfos = await fetchObjectInfos(objectInfotree, objectInfoApiMap, updatedObjectInfoMap, subLevelFields, path, objectInfoService);
10127
+ const subObjectInfos = await fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, updatedObjectInfoMap, subLevelFields, path, objectInfoService);
10145
10128
  updatedObjectInfoMap = { ...updatedObjectInfoMap, ...subObjectInfos };
10146
10129
  }
10147
10130
  }
@@ -10156,21 +10139,21 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
10156
10139
  * 'path' and 'queryNode' is 1 level above the 'filterNode'
10157
10140
  * @param filterNode filter node which needs to be injected. For example, 'State' ObjectFieldNode within filter 'where: { State: { eq: "Nova Scotia" }}'
10158
10141
  * @param idState ID state will be updated to determine if the ID fields in AST need to be swapped. The swapping happens later.
10159
- * @param path path to the current filterNode's parent. For example, path could be 'ServiceApointment' when filterNode is 'State'. If the path does not exist in 'objectInfoApiMap', parent node is not an field of relationship or recordQuery
10142
+ * @param path path to the current filterNode's parent. For example, path could be 'ServiceApointment' when filterNode is 'State'. If the path does not exist in 'pathToObjectApiNamesMap', parent node is not an field of relationship or recordQuery
10160
10143
  * @param queryNode referece FieldNode which provides the information if 'filterNode' exist in it nor not.
10161
10144
  * @param objectInfos ObjectInfo map used in injection. If ObjectInfo misses or field does not exist in ObjectInfo, the error will be thrown
10162
- * @param objectInfoApiMap map used to locate the ObjectInfo. The key is path to a field, value is the ObjectInfo's apiName array. In the case of polymorphic fields, the apiName array have 2 or more elements. For example, 'ServiceAppointment' -> ['ServiceAppointment']; 'ServiceAppointment_Account' -> ['Account'], 'ServiceAppointment_Owner' -> ['User', 'Group'].
10145
+ * @param pathToObjectApiNamesMap map used to locate the ObjectInfo. The key is path to a field, value is the ObjectInfo's apiName array. In the case of polymorphic fields, the apiName array have 2 or more elements. For example, 'ServiceAppointment' -> ['ServiceAppointment']; 'ServiceAppointment_Account' -> ['Account'], 'ServiceAppointment_Owner' -> ['User', 'Group'].
10163
10146
  * @param draftFunctions functions for working with record ids that may be draft-created ids
10164
10147
  * @returns an array of nodes with injected fields
10165
10148
  */
10166
- function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap, draftFunctions, queryNode) {
10149
+ function injectFilter(filterNode, idState, path, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode) {
10167
10150
  const injectedSelections = [];
10168
10151
  switch (filterNode.kind) {
10169
10152
  case Kind.ARGUMENT:
10170
10153
  if (filterNode.value.kind !== 'ObjectValue')
10171
10154
  return [];
10172
10155
  filterNode.value.fields.forEach((objectFieldNode) => {
10173
- let subResults = injectFilter(objectFieldNode, idState, path, objectInfos, objectInfoApiMap, draftFunctions, queryNode);
10156
+ let subResults = injectFilter(objectFieldNode, idState, path, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode);
10174
10157
  for (const subResult of subResults) {
10175
10158
  mergeOrAddToGroup(injectedSelections, subResult);
10176
10159
  }
@@ -10185,7 +10168,7 @@ function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap,
10185
10168
  case Kind.LIST: {
10186
10169
  filterNode.value.values.filter(isObjectValueNode).forEach((objectValueNode) => {
10187
10170
  objectValueNode.fields.forEach((objectFieldNode) => {
10188
- const subResults = injectFilter(objectFieldNode, idState, path, objectInfos, objectInfoApiMap, draftFunctions, queryNode);
10171
+ const subResults = injectFilter(objectFieldNode, idState, path, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode);
10189
10172
  for (const subResult of subResults) {
10190
10173
  mergeOrAddToGroup(injectedSelections, subResult);
10191
10174
  }
@@ -10196,7 +10179,7 @@ function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap,
10196
10179
  case Kind.OBJECT: {
10197
10180
  if (filterNode.name.value === 'not') {
10198
10181
  filterNode.value.fields.forEach((objectFieldNode) => {
10199
- const subResults = injectFilter(objectFieldNode, idState, path, objectInfos, objectInfoApiMap, draftFunctions, queryNode);
10182
+ const subResults = injectFilter(objectFieldNode, idState, path, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode);
10200
10183
  for (const subResult of subResults) {
10201
10184
  mergeOrAddToGroup(injectedSelections, subResult);
10202
10185
  }
@@ -10206,7 +10189,7 @@ function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap,
10206
10189
  let apiNames = [];
10207
10190
  let isScalarField = false;
10208
10191
  //It is possible that this is a polymorphic field
10209
- apiNames = objectInfoApiMap[path];
10192
+ apiNames = pathToObjectApiNamesMap[path];
10210
10193
  // example: path: 'ServiceAppointment_LastModifiedDate'; filterNode: '{eq: {literal: LAST_WEEK}}'. queryNode: 'LastModifedDate { value}' FilterNode's parent has been verifed as a valid node
10211
10194
  if (apiNames === undefined) {
10212
10195
  isScalarField = true;
@@ -10236,29 +10219,23 @@ function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap,
10236
10219
  }
10237
10220
  });
10238
10221
  let isSpanning = false;
10222
+ // if true, current node is a polymorphic concrete type node. For example, field node `User` under `Owner`
10239
10223
  let isInlineFragment = false;
10240
10224
  let isPolymorphicField = false;
10241
10225
  let isTypeNameExisting = false;
10242
10226
  let curPath;
10243
10227
  let fieldName = filterNode.name.value;
10244
10228
  curPath = `${path}_${fieldName}`;
10245
- if (objectInfoApiMap[curPath] && objectInfoApiMap[curPath].length > 0) {
10229
+ if (pathToObjectApiNamesMap[curPath] &&
10230
+ pathToObjectApiNamesMap[curPath].length > 0) {
10246
10231
  isSpanning = true;
10247
- if (objectInfoApiMap[curPath].length === 1) {
10248
- if (objectInfoApiMap[path] &&
10249
- objectInfoApiMap[path].length >= 1 &&
10250
- objectInfoApiMap[path].includes(objectInfoApiMap[curPath][0])) {
10251
- isInlineFragment = true;
10252
- }
10253
- }
10254
- // Checks if the current filter node is a polymorphic field. 'ServiceAppointment_Owner' --> ['User']; 'ServiceAppointment_Owner_User' --> ['User']
10255
- const childApiName = objectInfoApiMap[curPath][0];
10256
- const trialApiNames = objectInfoApiMap[`${curPath}_${childApiName}`];
10257
- if (trialApiNames !== undefined &&
10258
- trialApiNames.length === 1 &&
10259
- trialApiNames[0] === childApiName) {
10260
- isPolymorphicField = true;
10232
+ if (pathToObjectApiNamesMap[curPath].length === 1 &&
10233
+ pathToObjectApiNamesMap[path] &&
10234
+ pathToObjectApiNamesMap[path].length >= 1 &&
10235
+ pathToObjectApiNamesMap[path].includes(pathToObjectApiNamesMap[curPath][0])) {
10236
+ isInlineFragment = isPolymorphicFieldPath(path, pathToObjectApiNamesMap);
10261
10237
  }
10238
+ isPolymorphicField = isPolymorphicFieldPath(curPath, pathToObjectApiNamesMap);
10262
10239
  }
10263
10240
  // When filter node is at InLineFragment Level(a concrete entity of polymorphic field), query node is one level up. For example, ObjectFieldNode is ...{User:{...}}, queryNode is Owner:[User]
10264
10241
  if (isInlineFragment) {
@@ -10302,9 +10279,9 @@ function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap,
10302
10279
  throw new Error(`Field ${fieldName} does not exist in ${apiNames[0]}`);
10303
10280
  }
10304
10281
  }
10305
- const objectInfoName = objectInfoApiMap[curPath] !== undefined
10306
- ? objectInfoApiMap[curPath][0]
10307
- : objectInfoApiMap[path][0];
10282
+ const objectInfoName = pathToObjectApiNamesMap[curPath] !== undefined
10283
+ ? pathToObjectApiNamesMap[curPath][0]
10284
+ : pathToObjectApiNamesMap[path][0];
10308
10285
  const isIdField = isFieldAnIdField(filterNode.name.value, objectInfos[objectInfoName]);
10309
10286
  if (!isIdField) {
10310
10287
  let subSelectionNodes = [];
@@ -10316,7 +10293,7 @@ function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap,
10316
10293
  updateIDInfo(subFieldNode, idState, draftFunctions);
10317
10294
  }
10318
10295
  // try injecting the fields within predicate no matter it has relation or not.
10319
- let subResults = injectFilter(subFieldNode, idState, curPath, objectInfos, objectInfoApiMap, draftFunctions, existingFields ? existingFields[0] : undefined);
10296
+ let subResults = injectFilter(subFieldNode, idState, curPath, objectInfos, pathToObjectApiNamesMap, draftFunctions, existingFields ? existingFields[0] : undefined);
10320
10297
  subSelectionNodes = subSelectionNodes.concat(subResults);
10321
10298
  });
10322
10299
  if (!subFieldsHasId) {
@@ -10477,6 +10454,16 @@ function mergeOrAddToGroup(group, element) {
10477
10454
  }
10478
10455
  group.push(element);
10479
10456
  }
10457
+ // checks if the path points to a polymorphic field. If path points to a polymorphic field, its entry within `pathToObjectApiNamesMap` has the format {"Path" : ["elem1", "elem2"]}.
10458
+ // There must be also two entries pointing to concrete polymorphic field path. The two entries are like {"Path_elem1" : ["elem1"]} and {"Path_elem2" : ["elem2"]}
10459
+ // For example ServiceAppointment_Owner' --> ['User', 'Group']; 'ServiceAppointment_Owner_User' --> ['User'], 'ServiceAppointment_Owner_Group' --> ['Group']
10460
+ function isPolymorphicFieldPath(path, pathToObjectApiNamesMap) {
10461
+ const apiName = pathToObjectApiNamesMap[path][0];
10462
+ const apiNamesAtChildPath = pathToObjectApiNamesMap[`${path}_${apiName}`];
10463
+ return (apiNamesAtChildPath !== undefined &&
10464
+ apiNamesAtChildPath.length === 1 &&
10465
+ apiNamesAtChildPath[0] === apiName);
10466
+ }
10480
10467
  function isFieldAnIdField(fieldName, objectInfo) {
10481
10468
  if (fieldName === 'Id')
10482
10469
  return true;
@@ -10529,10 +10516,10 @@ function updateIDInfo(fieldNode, idState, draftFunctions) {
10529
10516
  * @param parentNode parent node of param 1
10530
10517
  * @param ancestors ancester of param 1
10531
10518
  * @param objectInfos ObjectInfo map used in injection. If ObjectInfo misses or field does not exist in ObjectInfo, the error will be thrown
10532
- * @param objectInfoApiMap map used to locate the ObjectInfo. The key is path to a field, value is the ObjectInfo's apiName array. In the case of polymorphic fields, the apiName array have 2 or more elements. For example, 'ServiceAppointment' -> ['ServiceAppointment']; 'ServiceAppointment_Account' -> ['Account'], 'ServiceAppointment_Owner' -> ['User', 'Group'].
10519
+ * @param pathToObjectApiNamesMap map used to locate the ObjectInfo. The key is path to a field, value is the ObjectInfo's apiName array. In the case of polymorphic fields, the apiName array have 2 or more elements. For example, 'ServiceAppointment' -> ['ServiceAppointment']; 'ServiceAppointment_Account' -> ['Account'], 'ServiceAppointment_Owner' -> ['User', 'Group'].
10533
10520
  * @return injected SelectionNodes used to construct the InlineFragment.
10534
10521
  */
10535
- function injectFields(selections, parentNode, ancestors, objectInfos, objectInfoApiMap) {
10522
+ function injectFields(selections, parentNode, ancestors, objectInfos, pathToObjectApiNamesMap) {
10536
10523
  /**
10537
10524
  * 1 parentship can return 2 FieldNode which need to be flattened
10538
10525
  * Concact: { ** Contact { ** ContactId {
@@ -10557,7 +10544,7 @@ function injectFields(selections, parentNode, ancestors, objectInfos, objectInfo
10557
10544
  }
10558
10545
  }
10559
10546
  // Handles multiple level field injection like 'ServiceAppointment' --> 'Account' --> 'Owner'
10560
- const subInjectedSelections = injectFields(spanningSubSelections, selection, ancestors, objectInfos, objectInfoApiMap);
10547
+ const subInjectedSelections = injectFields(spanningSubSelections, selection, ancestors, objectInfos, pathToObjectApiNamesMap);
10561
10548
  if (!selection.selectionSet) {
10562
10549
  return selection;
10563
10550
  }
@@ -10669,11 +10656,11 @@ function injectFields(selections, parentNode, ancestors, objectInfos, objectInfo
10669
10656
  const unVisitedAncestors = ancestors.slice(0, parentInfo.parentIndex);
10670
10657
  // path : "TimeSheet"
10671
10658
  const grandParentPath = findAncesterPath(unVisitedAncestors);
10672
- if (objectInfoApiMap &&
10673
- objectInfoApiMap[grandParentPath] &&
10659
+ if (pathToObjectApiNamesMap &&
10660
+ pathToObjectApiNamesMap[grandParentPath] &&
10674
10661
  objectInfos &&
10675
- objectInfos[objectInfoApiMap[grandParentPath][0]]) {
10676
- const grandParentObjectInfo = objectInfos[objectInfoApiMap[grandParentPath][0]];
10662
+ objectInfos[pathToObjectApiNamesMap[grandParentPath][0]]) {
10663
+ const grandParentObjectInfo = objectInfos[pathToObjectApiNamesMap[grandParentPath][0]];
10677
10664
  // exmaple "TimeSheetEntries"
10678
10665
  const parentFieldName = parent.name.value;
10679
10666
  const targetRelationship = grandParentObjectInfo.childRelationships.find((childRelationship) => {
@@ -17059,4 +17046,4 @@ register({
17059
17046
  });
17060
17047
 
17061
17048
  export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
17062
- // version: 1.239.0-6c531185a
17049
+ // version: 1.242.0-57237c3b6