@salesforce/lds-worker-api 1.229.0-dev1 → 1.229.0-dev3

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.
@@ -3847,7 +3847,7 @@
3847
3847
  }
3848
3848
  return resourceParams;
3849
3849
  }
3850
- // engine version: 0.145.2-6a13677c
3850
+ // engine version: 0.146.0-dev3-502c4337
3851
3851
 
3852
3852
  /**
3853
3853
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -3974,7 +3974,7 @@
3974
3974
  }
3975
3975
  callbacks.push(callback);
3976
3976
  }
3977
- // version: 1.229.0-dev1-f69d054a9
3977
+ // version: 1.229.0-dev3-175ac936b
3978
3978
 
3979
3979
  // TODO [TD-0081508]: once that TD is fulfilled we can probably change this file
3980
3980
  function instrumentAdapter$1(createFunction, _metadata) {
@@ -15435,7 +15435,7 @@
15435
15435
  }
15436
15436
  return superResult;
15437
15437
  }
15438
- // version: 1.229.0-dev1-f69d054a9
15438
+ // version: 1.229.0-dev3-175ac936b
15439
15439
 
15440
15440
  function unwrap(data) {
15441
15441
  // The lwc-luvio bindings import a function from lwc called "unwrap".
@@ -15536,14 +15536,15 @@
15536
15536
  return undefined;
15537
15537
  });
15538
15538
  }
15539
- const { isArray: isArray$8 } = Array;
15540
- const { stringify: stringify$9 } = JSON;
15541
15539
 
15542
15540
  function isPromise$1(value) {
15543
15541
  // check for Thenable due to test frameworks using custom Promise impls
15544
15542
  return value.then !== undefined;
15545
15543
  }
15546
15544
 
15545
+ const { isArray: isArray$8 } = Array;
15546
+ const { stringify: stringify$9 } = JSON;
15547
+
15547
15548
  /**
15548
15549
  * (Re)throws an error after adding a prefix to the message.
15549
15550
  *
@@ -16358,7 +16359,7 @@
16358
16359
  const { apiFamily, name } = metadata;
16359
16360
  return createGraphQLWireAdapterConstructor$1(adapter, `${apiFamily}.${name}`, luvio, astResolver);
16360
16361
  }
16361
- // version: 1.229.0-dev1-f69d054a9
16362
+ // version: 1.229.0-dev3-175ac936b
16362
16363
 
16363
16364
  /**
16364
16365
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -16457,7 +16458,7 @@
16457
16458
  TypeCheckShapes[TypeCheckShapes["Integer"] = 3] = "Integer";
16458
16459
  TypeCheckShapes[TypeCheckShapes["Unsupported"] = 4] = "Unsupported";
16459
16460
  })(TypeCheckShapes || (TypeCheckShapes = {}));
16460
- // engine version: 0.145.2-6a13677c
16461
+ // engine version: 0.146.0-dev3-502c4337
16461
16462
 
16462
16463
  const { keys: ObjectKeys$3, create: ObjectCreate$3 } = Object;
16463
16464
 
@@ -25044,18 +25045,28 @@
25044
25045
  * These are intermediate lookups to check if the record is in the L2 cache
25045
25046
  * @param {Luvio} luvio
25046
25047
  * @param {GetRecordLayoutTypeConfig} config
25047
- * @param {BuildCachedSnapshot<BuildSnapshotContext} cachedSnapshot
25048
+ * @param {BuildCachedSnapshot<BuildSnapshotContext>} cachedSnapshot
25048
25049
  */
25049
25050
  function makeCacheOnlySnapshot(luvio, config, adapterContext, cachedSnapshot) {
25050
- return luvio.applyCachePolicy({
25051
- cachePolicy: {
25052
- // only looking in the cache so we can check for L2 data offline
25053
- type: 'only-if-cached',
25054
- },
25055
- }, { config, luvio, adapterContext }, cachedSnapshot,
25056
- // this won't be invoked since we're requesting only-if-cached
25051
+ return luvio.applyCachePolicy(
25052
+ // Pass empty context so environment will use its default cache-policy
25053
+ {}, { config, luvio, adapterContext }, cachedSnapshot,
25054
+ // disallow hitting the network by returning a gateway timeout
25057
25055
  () => {
25058
- throw Error('buildNetworkSnapshot should not be called for only-if-cached policy');
25056
+ return new Promise((resolve) => {
25057
+ resolve({
25058
+ state: 'Error',
25059
+ data: undefined,
25060
+ error: {
25061
+ body: undefined,
25062
+ headers: {},
25063
+ ok: false,
25064
+ status: 504,
25065
+ statusText: 'Gateway Timeout',
25066
+ errorType: 'fetchResponse',
25067
+ },
25068
+ });
25069
+ });
25059
25070
  });
25060
25071
  }
25061
25072
  /**
@@ -41164,7 +41175,7 @@
41164
41175
  throttle(60, 60000, createLDSAdapter(luvio, 'notifyListInfoUpdateAvailable', notifyUpdateAvailableFactory$1));
41165
41176
  throttle(60, 60000, createLDSAdapter(luvio, 'notifyQuickActionDefaultsUpdateAvailable', notifyUpdateAvailableFactory));
41166
41177
  });
41167
- // version: 1.229.0-dev1-5b6d3db67
41178
+ // version: 1.229.0-dev3-71194d134
41168
41179
 
41169
41180
  var caseSensitiveUserId = '005B0000000GR4OIAW';
41170
41181
 
@@ -41795,6 +41806,9 @@
41795
41806
  }
41796
41807
 
41797
41808
  function isStoreEntryError(storeRecord) {
41809
+ if (!storeRecord || typeof storeRecord !== 'object') {
41810
+ return false;
41811
+ }
41798
41812
  return storeRecord.__type === 'error';
41799
41813
  }
41800
41814
 
@@ -45503,8 +45517,8 @@
45503
45517
  // If there is no metadata for this query or it somehow lacks a timestamp
45504
45518
  // skip setting the root timestamp
45505
45519
  if (queryMetadata !== undefined && queryMetadata.ingestionTimestamp !== undefined) {
45506
- // subtract 10ms from timestamp to account for ingestion processing time
45507
- input.rootTimestamp = queryMetadata.ingestionTimestamp - 10;
45520
+ // subtract 1000ms from timestamp to account for ingestion processing time
45521
+ input.rootTimestamp = queryMetadata.ingestionTimestamp - 1000;
45508
45522
  }
45509
45523
  }
45510
45524
  return recordQuery(selection, alias, apiName, [], input);
@@ -49286,6 +49300,10 @@
49286
49300
  return node.kind === 'OperationDefinition';
49287
49301
  }
49288
49302
 
49303
+ const POLYMORPHIC_PARENT_RELATIONSHIP = 'polymorphicParentRelationship';
49304
+ const PARENT_RELATIONSHIP = 'parentRelationship';
49305
+ const CHILD_RELATIONSHIP = 'childRelationship';
49306
+ const RECORD_QUERY = 'recordQuery';
49289
49307
  function requestsDraftsField(recordFieldNode) {
49290
49308
  if (!recordFieldNode.selectionSet)
49291
49309
  return false;
@@ -49301,18 +49319,41 @@
49301
49319
  directive.arguments
49302
49320
  .map((argument) => argument.value)
49303
49321
  .filter(isStringValueNode)
49304
- .some((categoryName) => categoryName.value === 'recordQuery'));
49322
+ .some((categoryName) => categoryName.value === RECORD_QUERY));
49305
49323
  });
49306
49324
  }
49307
49325
  return false;
49308
49326
  }
49309
- // finds field with 'recordQuery' and 'childRelationship' directive
49310
- function findNearestRecordQuery(ancestors) {
49311
- const recordQueryAncester = findNearestAncesterPath(ancestors, true).node;
49312
- return recordQueryAncester === undefined ? undefined : recordQueryAncester;
49327
+ // finds connection field with 'recordQuery' and 'childRelationship' directive.
49328
+ function findNearestConnection(ancestors) {
49329
+ const connectionAncestor = findNearestAncesterPath(ancestors, true).node;
49330
+ return connectionAncestor === undefined ? undefined : connectionAncestor;
49331
+ }
49332
+ // convinient method to find nearest connection with its path
49333
+ function findNearestConnectionWithPath(ancestors) {
49334
+ const closestAncestorPath = findNearestAncesterPath(ancestors, true);
49335
+ let connection = undefined;
49336
+ let connectionPath = undefined;
49337
+ if (closestAncestorPath.parentIndex > 0) {
49338
+ const connectionAncestor = closestAncestorPath.node;
49339
+ const connectionAncestors = ancestors.slice(0, closestAncestorPath.parentIndex);
49340
+ connection =
49341
+ connectionAncestor === undefined ? undefined : connectionAncestor;
49342
+ if (connection !== undefined) {
49343
+ const ancesterPath = findAncesterPath(connectionAncestors);
49344
+ connectionPath =
49345
+ ancesterPath === ''
49346
+ ? connection.name.value
49347
+ : `${ancesterPath}#${connection.name.value}`;
49348
+ }
49349
+ }
49350
+ return {
49351
+ connection,
49352
+ path: connectionPath,
49353
+ };
49313
49354
  }
49314
- // finds cloeset ancester. If 'parentRelationship' is allowed, it could be 'InlineFragmentNode' since it inherits the 'parent' relationship. 'InlineFragmentNode' makes sure that only one 'apiName' returns when tree is traversed.
49315
- function findNearestAncesterPath(ancestors, recordQueryOnly) {
49355
+ // finds closest ancestor. If node with 'parentRelationship' is the ancester, the end result could be 'InlineFragmentNode' since it inherits the 'parent' relationship. 'InlineFragmentNode' makes sure that only one 'apiName' returns when tree is traversed.
49356
+ function findNearestAncesterPath(ancestors, connectionOnly) {
49316
49357
  let recordQueryPath = { node: undefined, parentIndex: -1 };
49317
49358
  let relationship = '';
49318
49359
  for (let i = ancestors.length - 1; i >= 0; i--) {
@@ -49326,9 +49367,11 @@
49326
49367
  continue;
49327
49368
  for (let arg of directive.arguments) {
49328
49369
  if (arg.value &&
49329
- (arg.value.value === 'recordQuery' ||
49330
- arg.value.value === 'childRelationship' ||
49331
- (!recordQueryOnly && arg.value.value === 'parentRelationship'))) {
49370
+ (arg.value.value === RECORD_QUERY ||
49371
+ arg.value.value === CHILD_RELATIONSHIP ||
49372
+ (!connectionOnly &&
49373
+ (arg.value.value === PARENT_RELATIONSHIP ||
49374
+ arg.value.value === POLYMORPHIC_PARENT_RELATIONSHIP)))) {
49332
49375
  recordQueryPath = { node: node, parentIndex: i };
49333
49376
  relationship = arg.value.value;
49334
49377
  break;
@@ -49343,17 +49386,19 @@
49343
49386
  //checks if nearest ancester could be an inline fragment
49344
49387
  if (recordQueryPath.node !== undefined &&
49345
49388
  recordQueryPath.node.selectionSet &&
49346
- relationship === 'parentRelationship') {
49347
- //
49348
- if (recordQueryPath.node.selectionSet.selections.every(isInlineFragmentNode)) {
49349
- //
49350
- const inlineFragmentLoc = recordQueryPath.parentIndex + 2;
49351
- if (inlineFragmentLoc < ancestors.length && ancestors[inlineFragmentLoc]) {
49389
+ (relationship === PARENT_RELATIONSHIP || relationship === POLYMORPHIC_PARENT_RELATIONSHIP)) {
49390
+ // InlineFragment is usually 3 steps aways from its FieldNode parent within ancester hierarchy if it exists. The below search
49391
+ // is applied to adapt to future AST structure change
49392
+ let parentIndex = recordQueryPath.parentIndex + 1;
49393
+ while (parentIndex < ancestors.length) {
49394
+ if (isInlineFragmentNode(ancestors[parentIndex])) {
49352
49395
  recordQueryPath = {
49353
- node: ancestors[inlineFragmentLoc],
49354
- parentIndex: inlineFragmentLoc,
49396
+ node: ancestors[parentIndex],
49397
+ parentIndex,
49355
49398
  };
49399
+ break;
49356
49400
  }
49401
+ parentIndex++;
49357
49402
  }
49358
49403
  }
49359
49404
  return recordQueryPath;
@@ -49377,7 +49422,7 @@
49377
49422
  ? sectionPath
49378
49423
  : sectionPath === ''
49379
49424
  ? path
49380
- : `${sectionPath}_${path}`;
49425
+ : `${sectionPath}#${path}`;
49381
49426
  }
49382
49427
  }
49383
49428
  boundaryIndex = parentIndex;
@@ -49435,9 +49480,9 @@
49435
49480
  const relationships = args
49436
49481
  .map((arg) => arg.value)
49437
49482
  .filter(isStringValueNode)
49438
- .filter((valueNode) => valueNode.value === 'childRelationship' ||
49439
- valueNode.value === 'parentRelationship' ||
49440
- valueNode.value === 'polymorphicParentRelationship')
49483
+ .filter((valueNode) => valueNode.value === CHILD_RELATIONSHIP ||
49484
+ valueNode.value === PARENT_RELATIONSHIP ||
49485
+ valueNode.value === POLYMORPHIC_PARENT_RELATIONSHIP)
49441
49486
  .map((relationshipNode) => relationshipNode.value);
49442
49487
  if (relationships.length > 0) {
49443
49488
  return relationships[0];
@@ -49494,8 +49539,8 @@
49494
49539
  */
49495
49540
  function isParentRelationship(node) {
49496
49541
  return (node &&
49497
- (isRelationship(node, 'parentRelationship') ||
49498
- isRelationship(node, 'polymorphicParentRelationship')));
49542
+ (isRelationship(node, PARENT_RELATIONSHIP) ||
49543
+ isRelationship(node, POLYMORPHIC_PARENT_RELATIONSHIP)));
49499
49544
  }
49500
49545
  /*
49501
49546
  checks if the InlineFragment spans
@@ -50328,8 +50373,8 @@
50328
50373
  const results = await query(sql, [key]);
50329
50374
  const [timestamp] = results.rows.map((row) => row[0]);
50330
50375
  if (timestamp !== null && typeof timestamp === 'number') {
50331
- //go back 10 ms to adjust for margin of error when top level query is stored and when raml objects are stored
50332
- ingestionTimestamp = timestamp - 10;
50376
+ //go back 1000 ms to adjust for margin of error when top level query is stored and when raml objects are stored
50377
+ ingestionTimestamp = timestamp - 1000;
50333
50378
  }
50334
50379
  }
50335
50380
  return ingestionTimestamp;
@@ -50378,26 +50423,20 @@
50378
50423
  let recordConnections = ``;
50379
50424
  const polymorphicFieldTypeNames = new Set();
50380
50425
  let typedScalars = new Set();
50426
+ let parentRelationshipFields = new Set();
50381
50427
  for (const objectInfo of values$1(objectInfos)) {
50382
50428
  const { apiName, childRelationships } = objectInfo;
50383
50429
  let fields = ``;
50384
50430
  typedScalars.add(`${apiName}_Filter`);
50385
50431
  typedScalars.add(`${apiName}_OrderBy`);
50386
- for (const childRelationship of childRelationships) {
50387
- const { childObjectApiName } = childRelationship;
50388
- // Only add the relationship if there is relevant objectinfos for it,
50389
- // otherwise we'd be defining types we cannot satisfy and aren't referenced in
50390
- // the query.
50391
- if (objectInfos[childObjectApiName] !== undefined) {
50392
- fields += `${childRelationship.relationshipName}(first: Int, where: ${childObjectApiName}_Filter, orderBy: ${childObjectApiName}_OrderBy, scope: SupportedScopes): ${childObjectApiName}Connection \n`;
50393
- typedScalars.add(`${childObjectApiName}_Filter`);
50394
- typedScalars.add(`${childObjectApiName}_OrderBy`);
50395
- }
50396
- }
50397
50432
  for (const field of values$1(objectInfo.fields)) {
50398
50433
  if (!fieldsStaticallyAdded.includes(field.apiName)) {
50399
50434
  fields += `${field.apiName}: ${dataTypeToType(field.dataType, field.apiName)}\n`;
50400
50435
  }
50436
+ //handles parent relationship
50437
+ if (field.relationshipName === null) {
50438
+ continue;
50439
+ }
50401
50440
  // For spanning parent relationships with no union types
50402
50441
  if (field.referenceToInfos.length === 1) {
50403
50442
  const [relation] = field.referenceToInfos;
@@ -50405,11 +50444,13 @@
50405
50444
  // otherwise we'd be defining types we cannot satisfy and aren't referenced in
50406
50445
  // the query.
50407
50446
  if (objectInfos[relation.apiName] !== undefined) {
50447
+ parentRelationshipFields.add(field.relationshipName);
50408
50448
  fields += `${field.relationshipName}: ${relation.apiName}\n`;
50409
50449
  }
50410
50450
  // For polymorphic field, its type is 'Record' inteface. The concrete entity type name is saved for field resolving of next phase
50411
50451
  }
50412
50452
  else if (field.referenceToInfos.length > 1) {
50453
+ parentRelationshipFields.add(field.relationshipName);
50413
50454
  fields += `${field.relationshipName}: Record\n`;
50414
50455
  for (const relation of field.referenceToInfos) {
50415
50456
  if (objectInfos[relation.apiName] !== undefined) {
@@ -50418,6 +50459,20 @@
50418
50459
  }
50419
50460
  }
50420
50461
  }
50462
+ // handles child relationship
50463
+ for (const childRelationship of childRelationships) {
50464
+ const { childObjectApiName } = childRelationship;
50465
+ // Only add the relationship if there is relevant objectinfos for it,
50466
+ // otherwise we'd be defining types we cannot satisfy and aren't referenced in
50467
+ // the query.
50468
+ // If one field has both parent relationship and child relationship with the same name, the child relationship is ignored. This is how the server GQL has implemented as date of 08/07/2023
50469
+ if (objectInfos[childObjectApiName] !== undefined &&
50470
+ !parentRelationshipFields.has(childRelationship.relationshipName)) {
50471
+ fields += `${childRelationship.relationshipName}(first: Int, where: ${childObjectApiName}_Filter, orderBy: ${childObjectApiName}_OrderBy, scope: SupportedScopes): ${childObjectApiName}Connection \n`;
50472
+ typedScalars.add(`${childObjectApiName}_Filter`);
50473
+ typedScalars.add(`${childObjectApiName}_OrderBy`);
50474
+ }
50475
+ }
50421
50476
  recordQueries += `${apiName}(first: Int, where: ${apiName}_Filter, orderBy: ${apiName}_OrderBy, scope: SupportedScopes): ${apiName}Connection\n`;
50422
50477
  const isServiceAppointment = apiName === 'ServiceAppointment';
50423
50478
  recordConnections += /* GraphQL */ `
@@ -50577,7 +50632,7 @@
50577
50632
  },
50578
50633
  value: {
50579
50634
  kind: Kind.STRING,
50580
- value: 'parentRelationship',
50635
+ value: PARENT_RELATIONSHIP,
50581
50636
  block: false,
50582
50637
  },
50583
50638
  },
@@ -50591,8 +50646,8 @@
50591
50646
  // example 2 'ServiceAppointment' -> ['Owner']; 'Owner' -> ['User', 'Group']
50592
50647
  const objectNodeInfoTree = {};
50593
50648
  // save the field path to apiName map
50594
- // example 1: 'ServiceAppointment' -> ['ServiceAppointment']; 'ServiceAppointment_Account' -> ['Account']; 'ServiceAppointment_Account_Owner' -> ['User']
50595
- const objectInfoApiMap = {};
50649
+ // example 1: 'ServiceAppointment' -> ['ServiceAppointment']; 'ServiceAppointment#ccount' -> ['Account']; 'ServiceAppointment#Account#Owner' -> ['User']
50650
+ const pathToObjectApiNamesMap = {};
50596
50651
  let startNodes = new Set();
50597
50652
  let totalNodes = new Set();
50598
50653
  let objectInfos = {};
@@ -50606,11 +50661,11 @@
50606
50661
  visit(originalAST, {
50607
50662
  Argument: {
50608
50663
  enter(node, key, parent, path, ancestors) {
50609
- const recordQueryNode = findNearestRecordQuery(ancestors);
50610
- if (!recordQueryNode)
50664
+ const { connection: recordConnectionNode, path: ancesterPath } = findNearestConnectionWithPath(ancestors);
50665
+ if (!recordConnectionNode || !ancesterPath)
50611
50666
  return;
50612
- if (!objectNodeInfoTree[recordQueryNode.name.value]) {
50613
- objectNodeInfoTree[recordQueryNode.name.value] = [];
50667
+ if (!objectNodeInfoTree[ancesterPath]) {
50668
+ objectNodeInfoTree[ancesterPath] = [];
50614
50669
  }
50615
50670
  switch (node.name.value) {
50616
50671
  case 'orderBy':
@@ -50618,12 +50673,12 @@
50618
50673
  if (node.value.kind !== 'ObjectValue') {
50619
50674
  return;
50620
50675
  }
50621
- totalNodes.add(recordQueryNode.name.value);
50676
+ totalNodes.add(ancesterPath);
50622
50677
  // 'childRelationship' node is not taken as the startNode of the 'NodeInfoTree' graph. The field scanning will construct the graph which lead here.
50623
- if (isRecordQuery(recordQueryNode)) {
50624
- startNodes.add(recordQueryNode.name.value);
50678
+ if (isRecordQuery(recordConnectionNode)) {
50679
+ startNodes.add(recordConnectionNode.name.value);
50625
50680
  }
50626
- growObjectFieldTree(objectNodeInfoTree, recordQueryNode.name.value, node.value, totalNodes, startNodes);
50681
+ growObjectFieldTree(objectNodeInfoTree, ancesterPath, node.value, totalNodes, startNodes);
50627
50682
  break;
50628
50683
  case 'scope':
50629
50684
  if (!isScopeArgumentNodeWithType(node, 'ASSIGNEDTOME', variables)) {
@@ -50638,17 +50693,16 @@
50638
50693
  name: 'ServiceResources',
50639
50694
  });
50640
50695
  }
50641
- if (objectNodeInfoTree['ServiceResources'] === undefined) {
50642
- objectNodeInfoTree['ServiceResources'] = [];
50643
- }
50644
- if (!objectNodeInfoTree['ServiceResources'].some((child) => child.name === 'ServiceResource')) {
50645
- objectNodeInfoTree['ServiceResources'].push({
50646
- relation: 'parent',
50647
- name: 'ServiceResource',
50648
- });
50696
+ if (objectNodeInfoTree['ServiceAppointment#ServiceResources'] === undefined) {
50697
+ objectNodeInfoTree['ServiceAppointment#ServiceResources'] = [
50698
+ {
50699
+ relation: 'parent',
50700
+ name: 'ServiceResource',
50701
+ },
50702
+ ];
50649
50703
  }
50650
- if (objectNodeInfoTree['ServiceResource'] === undefined) {
50651
- objectNodeInfoTree['ServiceResource'] = [];
50704
+ if (objectNodeInfoTree['ServiceAppointment#ServiceResources#ServiceResource'] === undefined) {
50705
+ objectNodeInfoTree['ServiceAppointment#ServiceResources#ServiceResource'] = [];
50652
50706
  }
50653
50707
  break;
50654
50708
  default:
@@ -50662,7 +50716,7 @@
50662
50716
  return;
50663
50717
  if (!node.selectionSet)
50664
50718
  return;
50665
- const recordQueryField = findNearestRecordQuery(ancestors);
50719
+ const recordQueryField = findNearestConnection(ancestors);
50666
50720
  //only injects fields for 'recordQuery' field. ignores the 'childRelationship' field since it will be traversed as the child of the 'recordQuery'
50667
50721
  if (isRecordQuery(recordQueryField) && recordQueryField) {
50668
50722
  totalNodes.add(recordQueryField.name.value);
@@ -50673,21 +50727,21 @@
50673
50727
  },
50674
50728
  });
50675
50729
  if (objectInfoService && startNodes.size > 0) {
50676
- objectInfos = await resolveObjectInfos(objectNodeInfoTree, objectInfoApiMap, startNodes, objectInfoService);
50730
+ objectInfos = await resolveObjectInfos(objectNodeInfoTree, pathToObjectApiNamesMap, startNodes, objectInfoService);
50677
50731
  }
50678
50732
  // read pass; gather whats needed
50679
50733
  visit(originalAST, {
50680
50734
  Argument: {
50681
50735
  leave(node, key, parent, path, ancestors) {
50682
- const recordQueryField = findNearestRecordQuery(ancestors);
50736
+ const recordQueryField = findNearestConnection(ancestors);
50683
50737
  if (!recordQueryField)
50684
50738
  return;
50685
50739
  const ancestorPath = findAncesterPath(ancestors);
50686
50740
  if (!inlineFragmentSelections[ancestorPath]) {
50687
50741
  inlineFragmentSelections[ancestorPath] = [];
50688
50742
  }
50689
- const recordQueryApiName = objectInfoApiMap[ancestorPath]
50690
- ? objectInfoApiMap[ancestorPath][0]
50743
+ const recordQueryApiName = pathToObjectApiNamesMap[ancestorPath]
50744
+ ? pathToObjectApiNamesMap[ancestorPath][0]
50691
50745
  : recordQueryField.name.value;
50692
50746
  // The record node acts as the reference. The duplicated field in the record node is not injected
50693
50747
  const recordReferenceNode = [recordQueryField]
@@ -50701,7 +50755,7 @@
50701
50755
  case 'scope':
50702
50756
  // Hanle 'MINE' field
50703
50757
  if (isScopeArgumentNodeWithType(node, 'MINE', variables)) {
50704
- if (isMineScopeAvailable(ancestorPath, objectInfoApiMap, objectInfos)) {
50758
+ if (isMineScopeAvailable(ancestorPath, pathToObjectApiNamesMap, objectInfos)) {
50705
50759
  // 'typeConditon' is added when the 'InlineFragmentNode' is appended at the write pass
50706
50760
  inlineFragmentSelections[ancestorPath].push(...mineFragmentSelections);
50707
50761
  }
@@ -50727,7 +50781,7 @@
50727
50781
  case 'where': {
50728
50782
  inlineFragmentSelections[ancestorPath] = [
50729
50783
  ...inlineFragmentSelections[ancestorPath],
50730
- ...injectFilter(node, idState, ancestorPath, objectInfos, objectInfoApiMap, draftFunctions, recordReferenceNode),
50784
+ ...injectFilter(node, idState, ancestorPath, false, objectInfos, pathToObjectApiNamesMap, draftFunctions, recordReferenceNode),
50731
50785
  ];
50732
50786
  break;
50733
50787
  }
@@ -50743,7 +50797,7 @@
50743
50797
  if (!node.selectionSet)
50744
50798
  return;
50745
50799
  // it could be 'recordQuery' or 'childRelationship'
50746
- const recordQueryField = findNearestRecordQuery(ancestors);
50800
+ const recordQueryField = findNearestConnection(ancestors);
50747
50801
  if (!recordQueryField)
50748
50802
  return;
50749
50803
  const ancestorPath = findAncesterPath(ancestors);
@@ -50755,7 +50809,7 @@
50755
50809
  spanningSelections.push(selection);
50756
50810
  }
50757
50811
  }
50758
- const injectedFields = injectFields(spanningSelections, node, ancestors, objectInfos, objectInfoApiMap);
50812
+ const injectedFields = injectFields(spanningSelections, node, ancestorPath, ancestors, objectInfos, pathToObjectApiNamesMap);
50759
50813
  const mergedInjectedFields = mergeSelectionNodes$1(inlineFragmentSelections[ancestorPath], injectedFields);
50760
50814
  inlineFragmentSelections[ancestorPath] = mergedInjectedFields;
50761
50815
  },
@@ -50768,7 +50822,7 @@
50768
50822
  // removes 'ServicesResources' query field node if 'assignedtome' scope shows up
50769
50823
  if (assignedtomeQueryFieldNode !== undefined &&
50770
50824
  node.name.value === 'ServiceResources') {
50771
- const serviceResourcesAncestor = findNearestRecordQuery(ancestors);
50825
+ const serviceResourcesAncestor = findNearestConnection(ancestors);
50772
50826
  if (serviceResourcesAncestor === assignedtomeQueryFieldNode) {
50773
50827
  return null;
50774
50828
  }
@@ -50777,7 +50831,7 @@
50777
50831
  return;
50778
50832
  if (!node.selectionSet)
50779
50833
  return;
50780
- const recordQueryField = findNearestRecordQuery(ancestors);
50834
+ const recordQueryField = findNearestConnection(ancestors);
50781
50835
  if (!recordQueryField)
50782
50836
  return;
50783
50837
  const ancestorPath = findAncesterPath(ancestors);
@@ -50786,8 +50840,8 @@
50786
50840
  return;
50787
50841
  //const recordQueryPath = findAncesterPath(ancestors);
50788
50842
  // '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.
50789
- const recordQueryApiName = objectInfoApiMap[ancestorPath]
50790
- ? objectInfoApiMap[ancestorPath][0]
50843
+ const recordQueryApiName = pathToObjectApiNamesMap[ancestorPath]
50844
+ ? pathToObjectApiNamesMap[ancestorPath][0]
50791
50845
  : recordQueryField.name.value;
50792
50846
  const nodeWithFragments = {
50793
50847
  ...node,
@@ -50824,7 +50878,7 @@
50824
50878
  if (node.name.value === 'where') {
50825
50879
  const ancestorPath = findAncesterPath(ancestors);
50826
50880
  if (idState.paths.includes(ancestorPath)) {
50827
- const apiName = objectInfoApiMap[ancestorPath][0];
50881
+ const apiName = pathToObjectApiNamesMap[ancestorPath][0];
50828
50882
  const objectInfo = objectInfos[apiName];
50829
50883
  const swappedIdFilter = swapIdField(node.value, objectInfo, false, idState, draftFunctions);
50830
50884
  return {
@@ -50890,8 +50944,8 @@
50890
50944
  };
50891
50945
  }
50892
50946
  }
50893
- function isMineScopeAvailable(apiNamePath, objectInfoApiMap, objectInfos) {
50894
- const apiName = objectInfoApiMap[apiNamePath];
50947
+ function isMineScopeAvailable(apiNamePath, pathToObjectApiNamesMap, objectInfos) {
50948
+ const apiName = pathToObjectApiNamesMap[apiNamePath];
50895
50949
  if (!apiName)
50896
50950
  return false;
50897
50951
  const objectInfo = objectInfos[apiName[0]];
@@ -50980,15 +51034,16 @@
50980
51034
  }
50981
51035
  // example: 'Account'
50982
51036
  const childNode = objectFieldNode.name.value;
51037
+ const childNodepath = `${parentNode}#${childNode}`;
50983
51038
  if (!tree[parentNode].some((child) => child.name === childNode)) {
50984
51039
  tree[parentNode].push({
50985
51040
  relation: 'parent',
50986
51041
  name: childNode,
50987
51042
  });
50988
- totalNodes.add(childNode);
51043
+ totalNodes.add(childNodepath);
50989
51044
  }
50990
51045
  // recursively go to deeper level of filter.
50991
- growObjectFieldTree(tree, childNode, objectFieldNode.value, totalNodes, startNodes);
51046
+ growObjectFieldTree(tree, childNodepath, objectFieldNode.value, totalNodes, startNodes);
50992
51047
  }
50993
51048
  }
50994
51049
  }
@@ -51023,19 +51078,20 @@
51023
51078
  }
51024
51079
  if (!tree[parentSectionPath].some((field) => field.name === fieldName)) {
51025
51080
  tree[parentSectionPath].push({
51026
- relation: relationType === 'parentRelationship' ||
51027
- relationType === 'polymorphicParentRelationship'
51081
+ relation: relationType === PARENT_RELATIONSHIP ||
51082
+ relationType === POLYMORPHIC_PARENT_RELATIONSHIP
51028
51083
  ? 'parent'
51029
51084
  : 'child',
51030
51085
  name: fieldName,
51031
51086
  });
51032
- totalNodes.add(fieldName);
51087
+ totalNodes.add(`${parentSectionPath}#${fieldName}`);
51033
51088
  }
51034
51089
  if (entryNode.selectionSet && entryNode.selectionSet.selections) {
51035
51090
  const childNodes = entryNode.selectionSet.selections.filter(isFieldOrInlineFragmentNode);
51036
51091
  // recursively build the traversal tree
51037
51092
  for (const child of childNodes) {
51038
- growFieldTree(tree, fieldName, child, entryNode, totalNodes, startNodes);
51093
+ const path = `${parentSectionPath}#${fieldName}`;
51094
+ growFieldTree(tree, path, child, entryNode, totalNodes, startNodes);
51039
51095
  }
51040
51096
  }
51041
51097
  }
@@ -51065,23 +51121,23 @@
51065
51121
  }
51066
51122
  if (!tree[parentSectionPath].some((field) => field.name === conditionName)) {
51067
51123
  tree[parentSectionPath].push({
51068
- relation: relationType === 'parentRelationship' ||
51069
- relationType === 'polymorphicParentRelationship'
51124
+ relation: relationType === PARENT_RELATIONSHIP ||
51125
+ relationType === POLYMORPHIC_PARENT_RELATIONSHIP
51070
51126
  ? 'parent'
51071
51127
  : 'child',
51072
51128
  name: conditionName,
51073
51129
  });
51074
- totalNodes.add(conditionName);
51130
+ const path = `${parentSectionPath}#${conditionName}`;
51131
+ totalNodes.add(path);
51075
51132
  }
51076
51133
  }
51077
51134
  }
51078
51135
  // dive deep immediately for 'InlineFragment'
51079
51136
  const childNodes = entryNode.selectionSet.selections.filter(isFieldOrInlineFragmentNode);
51137
+ const path = `${parentSectionPath}${entryNode.typeCondition ? '#' + entryNode.typeCondition.name.value : ''}`;
51080
51138
  // Navigates into InLineFragment
51081
51139
  for (const child of childNodes) {
51082
- growFieldTree(tree, entryNode.typeCondition
51083
- ? entryNode.typeCondition.name.value
51084
- : parentSectionPath, child, entryNode, totalNodes, startNodes);
51140
+ growFieldTree(tree, path, child, entryNode, totalNodes, startNodes);
51085
51141
  }
51086
51142
  }
51087
51143
  }
@@ -51093,7 +51149,7 @@
51093
51149
  * @param startNodes start nodes of the tree. It can be used to fetch ObjectInfo immediately
51094
51150
  * @param path
51095
51151
  */
51096
- async function resolveObjectInfos(objectInfotree, objectInfoApiMap, startNodes, objectInfoService) {
51152
+ async function resolveObjectInfos(objectInfotree, pathToObjectApiNamesMap, startNodes, objectInfoService) {
51097
51153
  let objectInfos;
51098
51154
  try {
51099
51155
  objectInfos = await objectInfoService.getObjectInfos(Array.from(startNodes));
@@ -51107,9 +51163,9 @@
51107
51163
  throw new Error(`Unable to resolve ObjectInfo(s) for ${Array.from(startNodes)}`);
51108
51164
  }
51109
51165
  for (const startNode of startNodes) {
51110
- objectInfoApiMap[startNode] = [startNode];
51166
+ pathToObjectApiNamesMap[startNode] = [startNode];
51111
51167
  const children = objectInfotree[startNode];
51112
- const subObjectInfoMap = await fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfos, children, startNode, objectInfoService);
51168
+ const subObjectInfoMap = await fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, objectInfos, children, startNode, objectInfoService);
51113
51169
  objectInfos = { ...objectInfos, ...subObjectInfoMap };
51114
51170
  }
51115
51171
  return objectInfos;
@@ -51117,15 +51173,15 @@
51117
51173
  // example 1: 'parentPath': 'ServiceAppointment', 'nodesAtSameLevel': ['Account']
51118
51174
  // example 2: 'parentPath': 'ServiceAppointment', 'nodesAtSameLevel': ['Owner'], this example has 2 apiName for the node 'Owner'
51119
51175
  // example 3: 'parentPath': 'ServiceAppointment_Owner', 'nodesAtSameLevel': ['User', 'Group']
51120
- async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap, nodesAtSameLevel, parentPath, objectInfoService) {
51121
- const objectInfoApiNames = objectInfoApiMap[parentPath];
51176
+ async function fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, objectInfoMap, nodesAtSameLevel, parentPath, objectInfoService) {
51177
+ const objectInfoApiNames = pathToObjectApiNamesMap[parentPath];
51122
51178
  if (!objectInfoApiNames) {
51123
51179
  // eslint-disable-next-line
51124
51180
  throw new Error(`Object Info does not exist for ${parentPath}`);
51125
51181
  }
51126
51182
  const validObjectInfoNodes = [];
51127
51183
  let updatedObjectInfoMap = {};
51128
- // InlineFragment and polymorphic field support fits into this scenario ObjectInfoApiMap Entry: 'ServiceAppointment_Owner' -> ['User', 'Group']; ServiceAppointment_Owner_User' -> ['User']
51184
+ // InlineFragment and polymorphic field support fits into this scenario pathToObjectApiNamesMap Entry: 'ServiceAppointment#Owner' -> ['User', 'Group']; ServiceAppointment#Owner#User' -> ['User']
51129
51185
  if (objectInfoApiNames.length > 0 &&
51130
51186
  nodesAtSameLevel.length > 0 &&
51131
51187
  objectInfoApiNames.includes(nodesAtSameLevel[0].name)) {
@@ -51137,8 +51193,8 @@
51137
51193
  // eslint-disable-next-line
51138
51194
  throw new Error(`Condition ${field.name} does not exists for ${parentPath}`);
51139
51195
  }
51140
- const path = `${parentPath}_${field.name}`;
51141
- objectInfoApiMap[path] = [field.name];
51196
+ const path = `${parentPath}#${field.name}`;
51197
+ pathToObjectApiNamesMap[path] = [field.name];
51142
51198
  }
51143
51199
  validObjectInfoNodes.push(...nodesAtSameLevel);
51144
51200
  updatedObjectInfoMap = { ...objectInfoMap };
@@ -51153,7 +51209,7 @@
51153
51209
  let apiNames = [];
51154
51210
  for (const nodeInfo of nodesAtSameLevel) {
51155
51211
  const field = nodeInfo.name;
51156
- const path = `${parentPath}_${field}`;
51212
+ const path = `${parentPath}#${field}`;
51157
51213
  // Handle 'parentRelationship'
51158
51214
  if (nodeInfo.relation === 'parent') {
51159
51215
  const relationshipId = referenceIdFieldForRelationship(field);
@@ -51171,21 +51227,21 @@
51171
51227
  }
51172
51228
  }
51173
51229
  // This is a polymorphic field
51174
- if (fieldDefinition.referenceToInfos.length > 1 && objectInfotree[field]) {
51230
+ if (fieldDefinition.referenceToInfos.length > 1 && objectInfotree[path]) {
51175
51231
  // Fields needs to expand and heterogenous entity ObjectInfo needs to be fetched
51176
- const referencedNodeInfos = objectInfotree[field];
51232
+ const referencedNodeInfos = objectInfotree[path];
51177
51233
  const requestedApiNames = referencedNodeInfos.map((referenceNodeInfo) => referenceNodeInfo.name);
51178
51234
  // Fetches requested ObjectInfo only. Some entity's relation field could define more than 6 references. Only references show up in query need to be handled.
51179
- if (requestedApiNames.length > 0 && objectInfotree[field]) {
51235
+ if (requestedApiNames.length > 0 && objectInfotree[path]) {
51180
51236
  fieldDefinition.referenceToInfos
51181
51237
  .filter((referenceToInfo) => requestedApiNames.includes(referenceToInfo.apiName))
51182
51238
  .forEach((ref) => {
51183
- if (!objectInfoApiMap[path]) {
51184
- objectInfoApiMap[path] = [];
51239
+ if (!pathToObjectApiNamesMap[path]) {
51240
+ pathToObjectApiNamesMap[path] = [];
51185
51241
  }
51186
51242
  // 'ServiceAppointment_Owner' ->['User', 'Group']
51187
- if (!objectInfoApiMap[path].includes(ref.apiName)) {
51188
- objectInfoApiMap[path].push(ref.apiName);
51243
+ if (!pathToObjectApiNamesMap[path].includes(ref.apiName)) {
51244
+ pathToObjectApiNamesMap[path].push(ref.apiName);
51189
51245
  }
51190
51246
  if (!apiNames.includes(ref.apiName)) {
51191
51247
  apiNames.push(ref.apiName);
@@ -51195,11 +51251,11 @@
51195
51251
  }
51196
51252
  else if (fieldDefinition.referenceToInfos.length === 1) {
51197
51253
  const ref = fieldDefinition.referenceToInfos[0];
51198
- if (!objectInfoApiMap[path]) {
51199
- objectInfoApiMap[path] = [];
51254
+ if (!pathToObjectApiNamesMap[path]) {
51255
+ pathToObjectApiNamesMap[path] = [];
51200
51256
  }
51201
- if (!objectInfoApiMap[path].includes(ref.apiName)) {
51202
- objectInfoApiMap[path].push(ref.apiName);
51257
+ if (!pathToObjectApiNamesMap[path].includes(ref.apiName)) {
51258
+ pathToObjectApiNamesMap[path].push(ref.apiName);
51203
51259
  }
51204
51260
  if (!apiNames.includes(ref.apiName)) {
51205
51261
  apiNames.push(ref.apiName);
@@ -51210,11 +51266,11 @@
51210
51266
  // handles 'childRelationship'
51211
51267
  const childRelationship = parentObjectInfo.childRelationships.find((childRelationship) => childRelationship.relationshipName === field);
51212
51268
  if (childRelationship) {
51213
- if (!objectInfoApiMap[path]) {
51214
- objectInfoApiMap[path] = [];
51269
+ if (!pathToObjectApiNamesMap[path]) {
51270
+ pathToObjectApiNamesMap[path] = [];
51215
51271
  }
51216
- if (!objectInfoApiMap[path].includes(childRelationship.childObjectApiName)) {
51217
- objectInfoApiMap[path].push(childRelationship.childObjectApiName);
51272
+ if (!pathToObjectApiNamesMap[path].includes(childRelationship.childObjectApiName)) {
51273
+ pathToObjectApiNamesMap[path].push(childRelationship.childObjectApiName);
51218
51274
  }
51219
51275
  if (!apiNames.includes(childRelationship.childObjectApiName)) {
51220
51276
  apiNames.push(childRelationship.childObjectApiName);
@@ -51236,10 +51292,10 @@
51236
51292
  }
51237
51293
  for (const nodeInfo of validObjectInfoNodes) {
51238
51294
  const field = nodeInfo.name;
51239
- const subLevelFields = objectInfotree[field];
51240
- const path = `${parentPath}_${field}`;
51295
+ const path = `${parentPath}#${field}`;
51296
+ const subLevelFields = objectInfotree[path];
51241
51297
  if (subLevelFields && subLevelFields.length > 0) {
51242
- const subObjectInfos = await fetchObjectInfos(objectInfotree, objectInfoApiMap, updatedObjectInfoMap, subLevelFields, path, objectInfoService);
51298
+ const subObjectInfos = await fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, updatedObjectInfoMap, subLevelFields, path, objectInfoService);
51243
51299
  updatedObjectInfoMap = { ...updatedObjectInfoMap, ...subObjectInfos };
51244
51300
  }
51245
51301
  }
@@ -51254,27 +51310,29 @@
51254
51310
  * 'path' and 'queryNode' is 1 level above the 'filterNode'
51255
51311
  * @param filterNode filter node which needs to be injected. For example, 'State' ObjectFieldNode within filter 'where: { State: { eq: "Nova Scotia" }}'
51256
51312
  * @param idState ID state will be updated to determine if the ID fields in AST need to be swapped. The swapping happens later.
51257
- * @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
51313
+ * @param parentPath 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
51314
+ * @param isParentPolymorphic true if parent points to a polymorphic field.
51258
51315
  * @param queryNode referece FieldNode which provides the information if 'filterNode' exist in it nor not.
51259
51316
  * @param objectInfos ObjectInfo map used in injection. If ObjectInfo misses or field does not exist in ObjectInfo, the error will be thrown
51260
- * @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'].
51317
+ * @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'].
51261
51318
  * @param draftFunctions functions for working with record ids that may be draft-created ids
51262
51319
  * @returns an array of nodes with injected fields
51263
51320
  */
51264
- function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap, draftFunctions, queryNode) {
51321
+ function injectFilter(filterNode, idState, parentPath, isParentPolymorphic, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode) {
51265
51322
  const injectedSelections = [];
51323
+ let isPolymorphicField = false;
51266
51324
  switch (filterNode.kind) {
51267
51325
  case Kind.ARGUMENT:
51268
51326
  if (filterNode.value.kind !== 'ObjectValue')
51269
51327
  return [];
51270
51328
  filterNode.value.fields.forEach((objectFieldNode) => {
51271
- let subResults = injectFilter(objectFieldNode, idState, path, objectInfos, objectInfoApiMap, draftFunctions, queryNode);
51329
+ let subResults = injectFilter(objectFieldNode, idState, parentPath, isParentPolymorphic, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode);
51272
51330
  for (const subResult of subResults) {
51273
51331
  mergeOrAddToGroup(injectedSelections, subResult);
51274
51332
  }
51275
51333
  // multiple Ids might need to be swapped. remember their paths for faster write.
51276
51334
  if (idState.swapNeeded) {
51277
- idState.paths.push(path);
51335
+ idState.paths.push(parentPath);
51278
51336
  }
51279
51337
  });
51280
51338
  return injectedSelections;
@@ -51283,7 +51341,7 @@
51283
51341
  case Kind.LIST: {
51284
51342
  filterNode.value.values.filter(isObjectValueNode).forEach((objectValueNode) => {
51285
51343
  objectValueNode.fields.forEach((objectFieldNode) => {
51286
- const subResults = injectFilter(objectFieldNode, idState, path, objectInfos, objectInfoApiMap, draftFunctions, queryNode);
51344
+ const subResults = injectFilter(objectFieldNode, idState, parentPath, isParentPolymorphic, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode);
51287
51345
  for (const subResult of subResults) {
51288
51346
  mergeOrAddToGroup(injectedSelections, subResult);
51289
51347
  }
@@ -51294,7 +51352,7 @@
51294
51352
  case Kind.OBJECT: {
51295
51353
  if (filterNode.name.value === 'not') {
51296
51354
  filterNode.value.fields.forEach((objectFieldNode) => {
51297
- const subResults = injectFilter(objectFieldNode, idState, path, objectInfos, objectInfoApiMap, draftFunctions, queryNode);
51355
+ const subResults = injectFilter(objectFieldNode, idState, parentPath, isParentPolymorphic, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode);
51298
51356
  for (const subResult of subResults) {
51299
51357
  mergeOrAddToGroup(injectedSelections, subResult);
51300
51358
  }
@@ -51304,15 +51362,15 @@
51304
51362
  let apiNames = [];
51305
51363
  let isScalarField = false;
51306
51364
  //It is possible that this is a polymorphic field
51307
- apiNames = objectInfoApiMap[path];
51308
- // example: path: 'ServiceAppointment_LastModifiedDate'; filterNode: '{eq: {literal: LAST_WEEK}}'. queryNode: 'LastModifedDate { value}' FilterNode's parent has been verifed as a valid node
51365
+ apiNames = pathToObjectApiNamesMap[parentPath];
51366
+ // example: path: 'ServiceAppointment#LastModifiedDate'; filterNode: '{eq: {literal: LAST_WEEK}}'. queryNode: 'LastModifedDate { value}' FilterNode's parent has been verifed as a valid node
51309
51367
  if (apiNames === undefined) {
51310
51368
  isScalarField = true;
51311
51369
  }
51312
51370
  else {
51313
51371
  if (apiNames.some((apiName) => objectInfos[apiName] === undefined)) {
51314
51372
  // eslint-disable-next-line
51315
- throw new Error(`ObjectInfo is missing for ${path}`);
51373
+ throw new Error(`ObjectInfo is missing for ${parentPath}`);
51316
51374
  }
51317
51375
  }
51318
51376
  if (isScalarField) {
@@ -51334,29 +51392,19 @@
51334
51392
  }
51335
51393
  });
51336
51394
  let isSpanning = false;
51395
+ // if true, current node is a polymorphic concrete type node. For example, field node `User` under `Owner`
51337
51396
  let isInlineFragment = false;
51338
- let isPolymorphicField = false;
51339
51397
  let isTypeNameExisting = false;
51340
51398
  let curPath;
51341
51399
  let fieldName = filterNode.name.value;
51342
- curPath = `${path}_${fieldName}`;
51343
- if (objectInfoApiMap[curPath] && objectInfoApiMap[curPath].length > 0) {
51400
+ curPath = `${parentPath}#${fieldName}`;
51401
+ if (pathToObjectApiNamesMap[curPath] &&
51402
+ pathToObjectApiNamesMap[curPath].length > 0) {
51344
51403
  isSpanning = true;
51345
- if (objectInfoApiMap[curPath].length === 1) {
51346
- if (objectInfoApiMap[path] &&
51347
- objectInfoApiMap[path].length >= 1 &&
51348
- objectInfoApiMap[path].includes(objectInfoApiMap[curPath][0])) {
51349
- isInlineFragment = true;
51350
- }
51351
- }
51352
- // Checks if the current filter node is a polymorphic field. 'ServiceAppointment_Owner' --> ['User']; 'ServiceAppointment_Owner_User' --> ['User']
51353
- const childApiName = objectInfoApiMap[curPath][0];
51354
- const trialApiNames = objectInfoApiMap[`${curPath}_${childApiName}`];
51355
- if (trialApiNames !== undefined &&
51356
- trialApiNames.length === 1 &&
51357
- trialApiNames[0] === childApiName) {
51358
- isPolymorphicField = true;
51359
- }
51404
+ isInlineFragment =
51405
+ isParentPolymorphic &&
51406
+ pathToObjectApiNamesMap[curPath].length === 1;
51407
+ isPolymorphicField = isPolymorphicFieldPath(curPath, pathToObjectApiNamesMap, objectInfos);
51360
51408
  }
51361
51409
  // 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]
51362
51410
  if (isInlineFragment) {
@@ -51400,9 +51448,9 @@
51400
51448
  throw new Error(`Field ${fieldName} does not exist in ${apiNames[0]}`);
51401
51449
  }
51402
51450
  }
51403
- const objectInfoName = objectInfoApiMap[curPath] !== undefined
51404
- ? objectInfoApiMap[curPath][0]
51405
- : objectInfoApiMap[path][0];
51451
+ const objectInfoName = pathToObjectApiNamesMap[curPath] !== undefined
51452
+ ? pathToObjectApiNamesMap[curPath][0]
51453
+ : pathToObjectApiNamesMap[parentPath][0];
51406
51454
  const isIdField = isFieldAnIdField(filterNode.name.value, objectInfos[objectInfoName]);
51407
51455
  if (!isIdField) {
51408
51456
  let subSelectionNodes = [];
@@ -51414,7 +51462,7 @@
51414
51462
  updateIDInfo(subFieldNode, idState, draftFunctions);
51415
51463
  }
51416
51464
  // try injecting the fields within predicate no matter it has relation or not.
51417
- let subResults = injectFilter(subFieldNode, idState, curPath, objectInfos, objectInfoApiMap, draftFunctions, existingFields ? existingFields[0] : undefined);
51465
+ let subResults = injectFilter(subFieldNode, idState, curPath, isPolymorphicField, objectInfos, pathToObjectApiNamesMap, draftFunctions, existingFields ? existingFields[0] : undefined);
51418
51466
  subSelectionNodes = subSelectionNodes.concat(subResults);
51419
51467
  });
51420
51468
  if (!subFieldsHasId) {
@@ -51575,6 +51623,44 @@
51575
51623
  }
51576
51624
  group.push(element);
51577
51625
  }
51626
+ // checks if the path points to a polymorphic field. For example, for the below `pathToObjectApiNamesMap`
51627
+ // {
51628
+ // 'ServiceAppointment' -> ['ServiceAppointment']
51629
+ // 'ServiceAppointment#Owner' --> ['User'],
51630
+ // 'ServiceAppointment#Owner#User' --> ['User']
51631
+ // }
51632
+ // path `ServiceAppointment#Owner` points to a polymorphic field, but path `ServiceAppointment#Owner#User` does not.
51633
+ function isPolymorphicFieldPath(path, pathToObjectApiNamesMap, objectInfos) {
51634
+ const lastSegmentIndex = path.lastIndexOf('#');
51635
+ if (lastSegmentIndex < 0) {
51636
+ return false;
51637
+ }
51638
+ const lastSegment = path.slice(lastSegmentIndex + 1);
51639
+ const parentApiPath = path.slice(0, lastSegmentIndex);
51640
+ if (pathToObjectApiNamesMap[parentApiPath] === undefined) {
51641
+ return false;
51642
+ }
51643
+ const parentObjectApiNames = pathToObjectApiNamesMap[parentApiPath];
51644
+ // If the last segment is a Polymorphic field, its immediate parent is a concrete object entity, which has 1 objectApiName mapped to the parent path in `pathToObjectApiNamesMap`.
51645
+ // For example, we like to check if `ServiceAppointment#Owner` path is polymorphic. The last segment is `Owner` and its parent `ServiceAppointment` has one element (which is also `ServiceAppointment`) array as its value.
51646
+ // Below are the entries in `pathToObjectApiNamesMap`
51647
+ // {
51648
+ // `ServiceAppointmen`t: [`ServiceAppointment`],
51649
+ // `ServiceAppointment#Owner`: [`User`, `Group`],
51650
+ // `ServiceAppointment#Owner#User`: [`User`],
51651
+ // `ServiceAppointment#Owner#Group`: [`Group`],
51652
+ // }
51653
+ if (parentObjectApiNames.length !== 1) {
51654
+ return false;
51655
+ }
51656
+ const parentObjectInfo = objectInfos[parentObjectApiNames[0]];
51657
+ const relationshipField = referenceIdFieldForRelationship(lastSegment);
51658
+ let fieldDefinition = parentObjectInfo.fields[relationshipField];
51659
+ if (fieldDefinition === undefined) {
51660
+ return false;
51661
+ }
51662
+ return fieldDefinition.polymorphicForeignKey;
51663
+ }
51578
51664
  function isFieldAnIdField(fieldName, objectInfo) {
51579
51665
  if (fieldName === 'Id')
51580
51666
  return true;
@@ -51627,10 +51713,10 @@
51627
51713
  * @param parentNode parent node of param 1
51628
51714
  * @param ancestors ancester of param 1
51629
51715
  * @param objectInfos ObjectInfo map used in injection. If ObjectInfo misses or field does not exist in ObjectInfo, the error will be thrown
51630
- * @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'].
51716
+ * @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'].
51631
51717
  * @return injected SelectionNodes used to construct the InlineFragment.
51632
51718
  */
51633
- function injectFields(selections, parentNode, ancestors, objectInfos, objectInfoApiMap) {
51719
+ function injectFields(selections, parentNode, parentPath, ancestors, objectInfos, pathToObjectApiNamesMap) {
51634
51720
  /**
51635
51721
  * 1 parentship can return 2 FieldNode which need to be flattened
51636
51722
  * Concact: { ** Contact { ** ContactId {
@@ -51648,6 +51734,10 @@
51648
51734
  if (!selection.selectionSet) {
51649
51735
  return selection;
51650
51736
  }
51737
+ const segment = isFieldNode(selection)
51738
+ ? selection.name.value
51739
+ : selection.typeCondition.name.value;
51740
+ const curPath = `${parentPath}#${segment}`;
51651
51741
  const spanningSubSelections = [];
51652
51742
  for (const subSelection of selection.selectionSet.selections) {
51653
51743
  if (isFieldSpanning(subSelection, selection)) {
@@ -51655,7 +51745,7 @@
51655
51745
  }
51656
51746
  }
51657
51747
  // Handles multiple level field injection like 'ServiceAppointment' --> 'Account' --> 'Owner'
51658
- const subInjectedSelections = injectFields(spanningSubSelections, selection, ancestors, objectInfos, objectInfoApiMap);
51748
+ const subInjectedSelections = injectFields(spanningSubSelections, selection, curPath, ancestors, objectInfos, pathToObjectApiNamesMap);
51659
51749
  if (!selection.selectionSet) {
51660
51750
  return selection;
51661
51751
  }
@@ -51698,7 +51788,7 @@
51698
51788
  }
51699
51789
  }
51700
51790
  // For polymorphic fields, the Id field is excluded.
51701
- const excludeId = selection.selectionSet.selections.every(isInlineFragmentNode);
51791
+ const excludeId = isPolymorphicFieldPath(curPath, pathToObjectApiNamesMap, objectInfos);
51702
51792
  const idSelection = [];
51703
51793
  if (!excludeId && !hasIdAlready) {
51704
51794
  idSelection.push({
@@ -51709,8 +51799,8 @@
51709
51799
  },
51710
51800
  });
51711
51801
  }
51712
- // Inject '__typename' for polymorphic fields. '__typename' field acts as a reference to concrete type of a polymorphic field and is used to match JSON response with AST node. For more detail,
51713
- // please reference 'removeSyntheticFields'.
51802
+ // Inject '__typename' for InlineFragment. '__typename' field acts as a reference to concrete type of a polymorphic field or a standard field in the returned GQL response, which equals to
51803
+ // `typedCondition` of the InlineFragment in the query AST. It is used to match JSON response with AST node. For more detail, please reference 'removeSyntheticFields'.
51714
51804
  if (isInlineFragmentNode(selection) &&
51715
51805
  !selection.selectionSet.selections.find((selection) => isFieldNode(selection) && selection.name.value === '__typename')) {
51716
51806
  idSelection.push({
@@ -51744,7 +51834,7 @@
51744
51834
  if (isFieldNode(parentNode) && parentNode.selectionSet && parentNode.name.value === 'node') {
51745
51835
  if (parentNode.selectionSet.selections
51746
51836
  .filter(isFieldOrInlineFragmentNode)
51747
- .some((selectionNode) => isRelationship(selectionNode, 'childRelationship'))) {
51837
+ .some((selectionNode) => isRelationship(selectionNode, CHILD_RELATIONSHIP))) {
51748
51838
  if (!parentNode.selectionSet.selections
51749
51839
  .filter(isFieldNode)
51750
51840
  .some((sibling) => sibling.name.value === 'Id')) {
@@ -51763,15 +51853,15 @@
51763
51853
  if (parentInfo.parentIndex >= 0) {
51764
51854
  // example node { TimeSheetEntries { edges { node { Id }}}}
51765
51855
  const parent = parentInfo.node;
51766
- if (isRelationship(parent, 'childRelationship')) {
51856
+ if (isRelationship(parent, CHILD_RELATIONSHIP)) {
51767
51857
  const unVisitedAncestors = ancestors.slice(0, parentInfo.parentIndex);
51768
51858
  // path : "TimeSheet"
51769
51859
  const grandParentPath = findAncesterPath(unVisitedAncestors);
51770
- if (objectInfoApiMap &&
51771
- objectInfoApiMap[grandParentPath] &&
51860
+ if (pathToObjectApiNamesMap &&
51861
+ pathToObjectApiNamesMap[grandParentPath] &&
51772
51862
  objectInfos &&
51773
- objectInfos[objectInfoApiMap[grandParentPath][0]]) {
51774
- const grandParentObjectInfo = objectInfos[objectInfoApiMap[grandParentPath][0]];
51863
+ objectInfos[pathToObjectApiNamesMap[grandParentPath][0]]) {
51864
+ const grandParentObjectInfo = objectInfos[pathToObjectApiNamesMap[grandParentPath][0]];
51775
51865
  // exmaple "TimeSheetEntries"
51776
51866
  const parentFieldName = parent.name.value;
51777
51867
  const targetRelationship = grandParentObjectInfo.childRelationships.find((childRelationship) => {
@@ -51892,7 +51982,7 @@
51892
51982
  },
51893
51983
  value: {
51894
51984
  kind: 'StringValue',
51895
- value: 'childRelationship',
51985
+ value: CHILD_RELATIONSHIP,
51896
51986
  block: false,
51897
51987
  },
51898
51988
  },
@@ -51984,7 +52074,7 @@
51984
52074
  },
51985
52075
  value: {
51986
52076
  kind: 'StringValue',
51987
- value: 'parentRelationship',
52077
+ value: PARENT_RELATIONSHIP,
51988
52078
  block: false,
51989
52079
  },
51990
52080
  },
@@ -52121,7 +52211,9 @@
52121
52211
  jsonOutput[fieldName] = null;
52122
52212
  return;
52123
52213
  }
52124
- jsonOutput[fieldName] = {};
52214
+ if (jsonOutput[fieldName] === undefined) {
52215
+ jsonOutput[fieldName] = {};
52216
+ }
52125
52217
  createUserJsonOutput(selection, jsonInput[fieldName], jsonOutput[fieldName]);
52126
52218
  }
52127
52219
  else {
@@ -56996,6 +57088,9 @@
56996
57088
  this.ldsRecordRefresher = config.ldsRecordRefresher;
56997
57089
  this.networkWorkerPool = new AsyncWorkerPool(this.concurrency);
56998
57090
  this.useBatchGQL = ldsPrimingGraphqlBatch.isOpen({ fallback: false });
57091
+ if (this.useBatchGQL) {
57092
+ this.batchSize = this.batchSize / DEFAULT_GQL_QUERY_BATCH_SIZE;
57093
+ }
56999
57094
  this.conflictPool = new ConflictPool(config.store, this.objectInfoLoader);
57000
57095
  }
57001
57096
  // function that enqueues priming work
@@ -57852,7 +57947,7 @@
57852
57947
  id: '@salesforce/lds-network-adapter',
57853
57948
  instrument: instrument$1,
57854
57949
  });
57855
- // version: 1.229.0-dev1-f69d054a9
57950
+ // version: 1.229.0-dev3-175ac936b
57856
57951
 
57857
57952
  const { create: create$2, keys: keys$2 } = Object;
57858
57953
  const { stringify: stringify$1, parse: parse$1 } = JSON;
@@ -72615,6 +72710,7 @@
72615
72710
  }
72616
72711
  if (fieldData === null) {
72617
72712
  reader.assignScalar(requestedFieldName, sink, fieldData);
72713
+ reader.exitPath();
72618
72714
  return sink;
72619
72715
  }
72620
72716
  const fieldType = getFieldType(sel);
@@ -76298,7 +76394,7 @@
76298
76394
  configuration: { ...configurationForGraphQLAdapters },
76299
76395
  instrument,
76300
76396
  });
76301
- // version: 1.229.0-dev1-5b6d3db67
76397
+ // version: 1.229.0-dev3-71194d134
76302
76398
 
76303
76399
  // On core the unstable adapters are re-exported with different names,
76304
76400
 
@@ -78545,7 +78641,7 @@
78545
78641
  unstable_graphQL_imperative = createImperativeAdapter(luvio, createInstrumentedAdapter(ldsAdapter, adapterMetadata), adapterMetadata);
78546
78642
  graphQLImperative = ldsAdapter;
78547
78643
  });
78548
- // version: 1.229.0-dev1-5b6d3db67
78644
+ // version: 1.229.0-dev3-71194d134
78549
78645
 
78550
78646
  var gqlApi = /*#__PURE__*/Object.freeze({
78551
78647
  __proto__: null,
@@ -79276,4 +79372,4 @@
79276
79372
  Object.defineProperty(exports, '__esModule', { value: true });
79277
79373
 
79278
79374
  }));
79279
- // version: 1.229.0-dev1-f69d054a9
79375
+ // version: 1.229.0-dev3-175ac936b