@salesforce/lds-runtime-mobile 1.241.0 → 1.242.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +181 -131
- package/package.json +6 -6
- package/sfdc/main.js +181 -131
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';
|
|
@@ -554,6 +554,9 @@ function handleDurableStoreRejection(instrument) {
|
|
|
554
554
|
}
|
|
555
555
|
|
|
556
556
|
function isStoreEntryError(storeRecord) {
|
|
557
|
+
if (!storeRecord || typeof storeRecord !== 'object') {
|
|
558
|
+
return false;
|
|
559
|
+
}
|
|
557
560
|
return storeRecord.__type === 'error';
|
|
558
561
|
}
|
|
559
562
|
|
|
@@ -1578,30 +1581,13 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
|
|
|
1578
1581
|
* For full license text, see the LICENSE.txt file
|
|
1579
1582
|
*/
|
|
1580
1583
|
|
|
1581
|
-
|
|
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__';
|
|
1584
|
+
|
|
1587
1585
|
function isStoreKeyRecordId(key) {
|
|
1588
1586
|
return key.indexOf(RECORD_ID_PREFIX) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION) === -1;
|
|
1589
1587
|
}
|
|
1590
|
-
function isStoreKeyRecordViewEntity(key) {
|
|
1591
|
-
return (key.indexOf(RECORD_VIEW_ENTITY_ID_PREFIX) > -1 &&
|
|
1592
|
-
key.indexOf(RECORD_FIELDS_KEY_JUNCTION) === -1);
|
|
1593
|
-
}
|
|
1594
1588
|
function isStoreKeyRecordField(key) {
|
|
1595
1589
|
return key.indexOf(RECORD_ID_PREFIX) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION) > -1;
|
|
1596
1590
|
}
|
|
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
1591
|
function buildRecordFieldStoreKey(recordKey, fieldName) {
|
|
1606
1592
|
return `${recordKey}${RECORD_FIELDS_KEY_JUNCTION}${fieldName}`;
|
|
1607
1593
|
}
|
|
@@ -8178,6 +8164,10 @@ function isOperationDefinitionNode(node) {
|
|
|
8178
8164
|
return node.kind === 'OperationDefinition';
|
|
8179
8165
|
}
|
|
8180
8166
|
|
|
8167
|
+
const POLYMORPHIC_PARENT_RELATIONSHIP = 'polymorphicParentRelationship';
|
|
8168
|
+
const PARENT_RELATIONSHIP = 'parentRelationship';
|
|
8169
|
+
const CHILD_RELATIONSHIP = 'childRelationship';
|
|
8170
|
+
const RECORD_QUERY = 'recordQuery';
|
|
8181
8171
|
function requestsDraftsField(recordFieldNode) {
|
|
8182
8172
|
if (!recordFieldNode.selectionSet)
|
|
8183
8173
|
return false;
|
|
@@ -8193,18 +8183,41 @@ function isRecordQuery(recordQueryField) {
|
|
|
8193
8183
|
directive.arguments
|
|
8194
8184
|
.map((argument) => argument.value)
|
|
8195
8185
|
.filter(isStringValueNode)
|
|
8196
|
-
.some((categoryName) => categoryName.value ===
|
|
8186
|
+
.some((categoryName) => categoryName.value === RECORD_QUERY));
|
|
8197
8187
|
});
|
|
8198
8188
|
}
|
|
8199
8189
|
return false;
|
|
8200
8190
|
}
|
|
8201
|
-
// finds field with 'recordQuery' and 'childRelationship' directive
|
|
8202
|
-
function
|
|
8203
|
-
const
|
|
8204
|
-
return
|
|
8191
|
+
// finds connection field with 'recordQuery' and 'childRelationship' directive.
|
|
8192
|
+
function findNearestConnection(ancestors) {
|
|
8193
|
+
const connectionAncestor = findNearestAncesterPath(ancestors, true).node;
|
|
8194
|
+
return connectionAncestor === undefined ? undefined : connectionAncestor;
|
|
8195
|
+
}
|
|
8196
|
+
// convinient method to find nearest connection with its path
|
|
8197
|
+
function findNearestConnectionWithPath(ancestors) {
|
|
8198
|
+
const closestAncestorPath = findNearestAncesterPath(ancestors, true);
|
|
8199
|
+
let connection = undefined;
|
|
8200
|
+
let connectionPath = undefined;
|
|
8201
|
+
if (closestAncestorPath.parentIndex > 0) {
|
|
8202
|
+
const connectionAncestor = closestAncestorPath.node;
|
|
8203
|
+
const connectionAncestors = ancestors.slice(0, closestAncestorPath.parentIndex);
|
|
8204
|
+
connection =
|
|
8205
|
+
connectionAncestor === undefined ? undefined : connectionAncestor;
|
|
8206
|
+
if (connection !== undefined) {
|
|
8207
|
+
const ancesterPath = findAncesterPath(connectionAncestors);
|
|
8208
|
+
connectionPath =
|
|
8209
|
+
ancesterPath === ''
|
|
8210
|
+
? connection.name.value
|
|
8211
|
+
: `${ancesterPath}#${connection.name.value}`;
|
|
8212
|
+
}
|
|
8213
|
+
}
|
|
8214
|
+
return {
|
|
8215
|
+
connection,
|
|
8216
|
+
path: connectionPath,
|
|
8217
|
+
};
|
|
8205
8218
|
}
|
|
8206
|
-
// finds
|
|
8207
|
-
function findNearestAncesterPath(ancestors,
|
|
8219
|
+
// 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.
|
|
8220
|
+
function findNearestAncesterPath(ancestors, connectionOnly) {
|
|
8208
8221
|
let recordQueryPath = { node: undefined, parentIndex: -1 };
|
|
8209
8222
|
let relationship = '';
|
|
8210
8223
|
for (let i = ancestors.length - 1; i >= 0; i--) {
|
|
@@ -8218,9 +8231,11 @@ function findNearestAncesterPath(ancestors, recordQueryOnly) {
|
|
|
8218
8231
|
continue;
|
|
8219
8232
|
for (let arg of directive.arguments) {
|
|
8220
8233
|
if (arg.value &&
|
|
8221
|
-
(arg.value.value ===
|
|
8222
|
-
arg.value.value ===
|
|
8223
|
-
(!
|
|
8234
|
+
(arg.value.value === RECORD_QUERY ||
|
|
8235
|
+
arg.value.value === CHILD_RELATIONSHIP ||
|
|
8236
|
+
(!connectionOnly &&
|
|
8237
|
+
(arg.value.value === PARENT_RELATIONSHIP ||
|
|
8238
|
+
arg.value.value === POLYMORPHIC_PARENT_RELATIONSHIP)))) {
|
|
8224
8239
|
recordQueryPath = { node: node, parentIndex: i };
|
|
8225
8240
|
relationship = arg.value.value;
|
|
8226
8241
|
break;
|
|
@@ -8235,17 +8250,19 @@ function findNearestAncesterPath(ancestors, recordQueryOnly) {
|
|
|
8235
8250
|
//checks if nearest ancester could be an inline fragment
|
|
8236
8251
|
if (recordQueryPath.node !== undefined &&
|
|
8237
8252
|
recordQueryPath.node.selectionSet &&
|
|
8238
|
-
relationship ===
|
|
8239
|
-
//
|
|
8240
|
-
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
if (
|
|
8253
|
+
(relationship === PARENT_RELATIONSHIP || relationship === POLYMORPHIC_PARENT_RELATIONSHIP)) {
|
|
8254
|
+
// InlineFragment is usually 3 steps aways from its FieldNode parent within ancester hierarchy if it exists. The below search
|
|
8255
|
+
// is applied to adapt to future AST structure change
|
|
8256
|
+
let parentIndex = recordQueryPath.parentIndex + 1;
|
|
8257
|
+
while (parentIndex < ancestors.length) {
|
|
8258
|
+
if (isInlineFragmentNode(ancestors[parentIndex])) {
|
|
8244
8259
|
recordQueryPath = {
|
|
8245
|
-
node: ancestors[
|
|
8246
|
-
parentIndex
|
|
8260
|
+
node: ancestors[parentIndex],
|
|
8261
|
+
parentIndex,
|
|
8247
8262
|
};
|
|
8263
|
+
break;
|
|
8248
8264
|
}
|
|
8265
|
+
parentIndex++;
|
|
8249
8266
|
}
|
|
8250
8267
|
}
|
|
8251
8268
|
return recordQueryPath;
|
|
@@ -8269,7 +8286,7 @@ function findAncesterPath(ancesters) {
|
|
|
8269
8286
|
? sectionPath
|
|
8270
8287
|
: sectionPath === ''
|
|
8271
8288
|
? path
|
|
8272
|
-
: `${sectionPath}
|
|
8289
|
+
: `${sectionPath}#${path}`;
|
|
8273
8290
|
}
|
|
8274
8291
|
}
|
|
8275
8292
|
boundaryIndex = parentIndex;
|
|
@@ -8327,9 +8344,9 @@ function getRelation(node) {
|
|
|
8327
8344
|
const relationships = args
|
|
8328
8345
|
.map((arg) => arg.value)
|
|
8329
8346
|
.filter(isStringValueNode)
|
|
8330
|
-
.filter((valueNode) => valueNode.value ===
|
|
8331
|
-
valueNode.value ===
|
|
8332
|
-
valueNode.value ===
|
|
8347
|
+
.filter((valueNode) => valueNode.value === CHILD_RELATIONSHIP ||
|
|
8348
|
+
valueNode.value === PARENT_RELATIONSHIP ||
|
|
8349
|
+
valueNode.value === POLYMORPHIC_PARENT_RELATIONSHIP)
|
|
8333
8350
|
.map((relationshipNode) => relationshipNode.value);
|
|
8334
8351
|
if (relationships.length > 0) {
|
|
8335
8352
|
return relationships[0];
|
|
@@ -8386,8 +8403,8 @@ function isFieldSpanning(node, parentNode) {
|
|
|
8386
8403
|
*/
|
|
8387
8404
|
function isParentRelationship(node) {
|
|
8388
8405
|
return (node &&
|
|
8389
|
-
(isRelationship(node,
|
|
8390
|
-
isRelationship(node,
|
|
8406
|
+
(isRelationship(node, PARENT_RELATIONSHIP) ||
|
|
8407
|
+
isRelationship(node, POLYMORPHIC_PARENT_RELATIONSHIP)));
|
|
8391
8408
|
}
|
|
8392
8409
|
/*
|
|
8393
8410
|
checks if the InlineFragment spans
|
|
@@ -9479,7 +9496,7 @@ const parentRelationshipDirective = {
|
|
|
9479
9496
|
},
|
|
9480
9497
|
value: {
|
|
9481
9498
|
kind: Kind.STRING,
|
|
9482
|
-
value:
|
|
9499
|
+
value: PARENT_RELATIONSHIP,
|
|
9483
9500
|
block: false,
|
|
9484
9501
|
},
|
|
9485
9502
|
},
|
|
@@ -9493,7 +9510,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
9493
9510
|
// example 2 'ServiceAppointment' -> ['Owner']; 'Owner' -> ['User', 'Group']
|
|
9494
9511
|
const objectNodeInfoTree = {};
|
|
9495
9512
|
// save the field path to apiName map
|
|
9496
|
-
// example 1: 'ServiceAppointment' -> ['ServiceAppointment']; '
|
|
9513
|
+
// example 1: 'ServiceAppointment' -> ['ServiceAppointment']; 'ServiceAppointment#ccount' -> ['Account']; 'ServiceAppointment#Account#Owner' -> ['User']
|
|
9497
9514
|
const pathToObjectApiNamesMap = {};
|
|
9498
9515
|
let startNodes = new Set();
|
|
9499
9516
|
let totalNodes = new Set();
|
|
@@ -9508,11 +9525,11 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
9508
9525
|
visit(originalAST, {
|
|
9509
9526
|
Argument: {
|
|
9510
9527
|
enter(node, key, parent, path, ancestors) {
|
|
9511
|
-
const
|
|
9512
|
-
if (!
|
|
9528
|
+
const { connection: recordConnectionNode, path: ancesterPath } = findNearestConnectionWithPath(ancestors);
|
|
9529
|
+
if (!recordConnectionNode || !ancesterPath)
|
|
9513
9530
|
return;
|
|
9514
|
-
if (!objectNodeInfoTree[
|
|
9515
|
-
objectNodeInfoTree[
|
|
9531
|
+
if (!objectNodeInfoTree[ancesterPath]) {
|
|
9532
|
+
objectNodeInfoTree[ancesterPath] = [];
|
|
9516
9533
|
}
|
|
9517
9534
|
switch (node.name.value) {
|
|
9518
9535
|
case 'orderBy':
|
|
@@ -9520,12 +9537,12 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
9520
9537
|
if (node.value.kind !== 'ObjectValue') {
|
|
9521
9538
|
return;
|
|
9522
9539
|
}
|
|
9523
|
-
totalNodes.add(
|
|
9540
|
+
totalNodes.add(ancesterPath);
|
|
9524
9541
|
// 'childRelationship' node is not taken as the startNode of the 'NodeInfoTree' graph. The field scanning will construct the graph which lead here.
|
|
9525
|
-
if (isRecordQuery(
|
|
9526
|
-
startNodes.add(
|
|
9542
|
+
if (isRecordQuery(recordConnectionNode)) {
|
|
9543
|
+
startNodes.add(recordConnectionNode.name.value);
|
|
9527
9544
|
}
|
|
9528
|
-
growObjectFieldTree(objectNodeInfoTree,
|
|
9545
|
+
growObjectFieldTree(objectNodeInfoTree, ancesterPath, node.value, totalNodes, startNodes);
|
|
9529
9546
|
break;
|
|
9530
9547
|
case 'scope':
|
|
9531
9548
|
if (!isScopeArgumentNodeWithType(node, 'ASSIGNEDTOME', variables)) {
|
|
@@ -9540,17 +9557,16 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
9540
9557
|
name: 'ServiceResources',
|
|
9541
9558
|
});
|
|
9542
9559
|
}
|
|
9543
|
-
if (objectNodeInfoTree['ServiceResources'] === undefined) {
|
|
9544
|
-
objectNodeInfoTree['ServiceResources'] = [
|
|
9545
|
-
|
|
9546
|
-
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
|
|
9550
|
-
});
|
|
9560
|
+
if (objectNodeInfoTree['ServiceAppointment#ServiceResources'] === undefined) {
|
|
9561
|
+
objectNodeInfoTree['ServiceAppointment#ServiceResources'] = [
|
|
9562
|
+
{
|
|
9563
|
+
relation: 'parent',
|
|
9564
|
+
name: 'ServiceResource',
|
|
9565
|
+
},
|
|
9566
|
+
];
|
|
9551
9567
|
}
|
|
9552
|
-
if (objectNodeInfoTree['ServiceResource'] === undefined) {
|
|
9553
|
-
objectNodeInfoTree['ServiceResource'] = [];
|
|
9568
|
+
if (objectNodeInfoTree['ServiceAppointment#ServiceResources#ServiceResource'] === undefined) {
|
|
9569
|
+
objectNodeInfoTree['ServiceAppointment#ServiceResources#ServiceResource'] = [];
|
|
9554
9570
|
}
|
|
9555
9571
|
break;
|
|
9556
9572
|
default:
|
|
@@ -9564,7 +9580,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
9564
9580
|
return;
|
|
9565
9581
|
if (!node.selectionSet)
|
|
9566
9582
|
return;
|
|
9567
|
-
const recordQueryField =
|
|
9583
|
+
const recordQueryField = findNearestConnection(ancestors);
|
|
9568
9584
|
//only injects fields for 'recordQuery' field. ignores the 'childRelationship' field since it will be traversed as the child of the 'recordQuery'
|
|
9569
9585
|
if (isRecordQuery(recordQueryField) && recordQueryField) {
|
|
9570
9586
|
totalNodes.add(recordQueryField.name.value);
|
|
@@ -9581,7 +9597,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
9581
9597
|
visit(originalAST, {
|
|
9582
9598
|
Argument: {
|
|
9583
9599
|
leave(node, key, parent, path, ancestors) {
|
|
9584
|
-
const recordQueryField =
|
|
9600
|
+
const recordQueryField = findNearestConnection(ancestors);
|
|
9585
9601
|
if (!recordQueryField)
|
|
9586
9602
|
return;
|
|
9587
9603
|
const ancestorPath = findAncesterPath(ancestors);
|
|
@@ -9629,7 +9645,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
9629
9645
|
case 'where': {
|
|
9630
9646
|
inlineFragmentSelections[ancestorPath] = [
|
|
9631
9647
|
...inlineFragmentSelections[ancestorPath],
|
|
9632
|
-
...injectFilter(node, idState, ancestorPath, objectInfos, pathToObjectApiNamesMap, draftFunctions, recordReferenceNode),
|
|
9648
|
+
...injectFilter(node, idState, ancestorPath, false, objectInfos, pathToObjectApiNamesMap, draftFunctions, recordReferenceNode),
|
|
9633
9649
|
];
|
|
9634
9650
|
break;
|
|
9635
9651
|
}
|
|
@@ -9645,7 +9661,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
9645
9661
|
if (!node.selectionSet)
|
|
9646
9662
|
return;
|
|
9647
9663
|
// it could be 'recordQuery' or 'childRelationship'
|
|
9648
|
-
const recordQueryField =
|
|
9664
|
+
const recordQueryField = findNearestConnection(ancestors);
|
|
9649
9665
|
if (!recordQueryField)
|
|
9650
9666
|
return;
|
|
9651
9667
|
const ancestorPath = findAncesterPath(ancestors);
|
|
@@ -9657,7 +9673,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
9657
9673
|
spanningSelections.push(selection);
|
|
9658
9674
|
}
|
|
9659
9675
|
}
|
|
9660
|
-
const injectedFields = injectFields(spanningSelections, node, ancestors, objectInfos, pathToObjectApiNamesMap);
|
|
9676
|
+
const injectedFields = injectFields(spanningSelections, node, ancestorPath, ancestors, objectInfos, pathToObjectApiNamesMap);
|
|
9661
9677
|
const mergedInjectedFields = mergeSelectionNodes(inlineFragmentSelections[ancestorPath], injectedFields);
|
|
9662
9678
|
inlineFragmentSelections[ancestorPath] = mergedInjectedFields;
|
|
9663
9679
|
},
|
|
@@ -9670,7 +9686,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
9670
9686
|
// removes 'ServicesResources' query field node if 'assignedtome' scope shows up
|
|
9671
9687
|
if (assignedtomeQueryFieldNode !== undefined &&
|
|
9672
9688
|
node.name.value === 'ServiceResources') {
|
|
9673
|
-
const serviceResourcesAncestor =
|
|
9689
|
+
const serviceResourcesAncestor = findNearestConnection(ancestors);
|
|
9674
9690
|
if (serviceResourcesAncestor === assignedtomeQueryFieldNode) {
|
|
9675
9691
|
return null;
|
|
9676
9692
|
}
|
|
@@ -9679,7 +9695,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
9679
9695
|
return;
|
|
9680
9696
|
if (!node.selectionSet)
|
|
9681
9697
|
return;
|
|
9682
|
-
const recordQueryField =
|
|
9698
|
+
const recordQueryField = findNearestConnection(ancestors);
|
|
9683
9699
|
if (!recordQueryField)
|
|
9684
9700
|
return;
|
|
9685
9701
|
const ancestorPath = findAncesterPath(ancestors);
|
|
@@ -9882,15 +9898,16 @@ function growObjectFieldTree(tree, parentNode, entryNode, totalNodes, startNodes
|
|
|
9882
9898
|
}
|
|
9883
9899
|
// example: 'Account'
|
|
9884
9900
|
const childNode = objectFieldNode.name.value;
|
|
9901
|
+
const childNodepath = `${parentNode}#${childNode}`;
|
|
9885
9902
|
if (!tree[parentNode].some((child) => child.name === childNode)) {
|
|
9886
9903
|
tree[parentNode].push({
|
|
9887
9904
|
relation: 'parent',
|
|
9888
9905
|
name: childNode,
|
|
9889
9906
|
});
|
|
9890
|
-
totalNodes.add(
|
|
9907
|
+
totalNodes.add(childNodepath);
|
|
9891
9908
|
}
|
|
9892
9909
|
// recursively go to deeper level of filter.
|
|
9893
|
-
growObjectFieldTree(tree,
|
|
9910
|
+
growObjectFieldTree(tree, childNodepath, objectFieldNode.value, totalNodes, startNodes);
|
|
9894
9911
|
}
|
|
9895
9912
|
}
|
|
9896
9913
|
}
|
|
@@ -9925,19 +9942,20 @@ function growFieldTree(tree, parentSectionPath, entryNode, parentNode, totalNode
|
|
|
9925
9942
|
}
|
|
9926
9943
|
if (!tree[parentSectionPath].some((field) => field.name === fieldName)) {
|
|
9927
9944
|
tree[parentSectionPath].push({
|
|
9928
|
-
relation: relationType ===
|
|
9929
|
-
relationType ===
|
|
9945
|
+
relation: relationType === PARENT_RELATIONSHIP ||
|
|
9946
|
+
relationType === POLYMORPHIC_PARENT_RELATIONSHIP
|
|
9930
9947
|
? 'parent'
|
|
9931
9948
|
: 'child',
|
|
9932
9949
|
name: fieldName,
|
|
9933
9950
|
});
|
|
9934
|
-
totalNodes.add(fieldName);
|
|
9951
|
+
totalNodes.add(`${parentSectionPath}#${fieldName}`);
|
|
9935
9952
|
}
|
|
9936
9953
|
if (entryNode.selectionSet && entryNode.selectionSet.selections) {
|
|
9937
9954
|
const childNodes = entryNode.selectionSet.selections.filter(isFieldOrInlineFragmentNode);
|
|
9938
9955
|
// recursively build the traversal tree
|
|
9939
9956
|
for (const child of childNodes) {
|
|
9940
|
-
|
|
9957
|
+
const path = `${parentSectionPath}#${fieldName}`;
|
|
9958
|
+
growFieldTree(tree, path, child, entryNode, totalNodes, startNodes);
|
|
9941
9959
|
}
|
|
9942
9960
|
}
|
|
9943
9961
|
}
|
|
@@ -9967,23 +9985,23 @@ function growFieldTree(tree, parentSectionPath, entryNode, parentNode, totalNode
|
|
|
9967
9985
|
}
|
|
9968
9986
|
if (!tree[parentSectionPath].some((field) => field.name === conditionName)) {
|
|
9969
9987
|
tree[parentSectionPath].push({
|
|
9970
|
-
relation: relationType ===
|
|
9971
|
-
relationType ===
|
|
9988
|
+
relation: relationType === PARENT_RELATIONSHIP ||
|
|
9989
|
+
relationType === POLYMORPHIC_PARENT_RELATIONSHIP
|
|
9972
9990
|
? 'parent'
|
|
9973
9991
|
: 'child',
|
|
9974
9992
|
name: conditionName,
|
|
9975
9993
|
});
|
|
9976
|
-
|
|
9994
|
+
const path = `${parentSectionPath}#${conditionName}`;
|
|
9995
|
+
totalNodes.add(path);
|
|
9977
9996
|
}
|
|
9978
9997
|
}
|
|
9979
9998
|
}
|
|
9980
9999
|
// dive deep immediately for 'InlineFragment'
|
|
9981
10000
|
const childNodes = entryNode.selectionSet.selections.filter(isFieldOrInlineFragmentNode);
|
|
10001
|
+
const path = `${parentSectionPath}${entryNode.typeCondition ? '#' + entryNode.typeCondition.name.value : ''}`;
|
|
9982
10002
|
// Navigates into InLineFragment
|
|
9983
10003
|
for (const child of childNodes) {
|
|
9984
|
-
growFieldTree(tree, entryNode
|
|
9985
|
-
? entryNode.typeCondition.name.value
|
|
9986
|
-
: parentSectionPath, child, entryNode, totalNodes, startNodes);
|
|
10004
|
+
growFieldTree(tree, path, child, entryNode, totalNodes, startNodes);
|
|
9987
10005
|
}
|
|
9988
10006
|
}
|
|
9989
10007
|
}
|
|
@@ -10027,7 +10045,7 @@ async function fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, objectI
|
|
|
10027
10045
|
}
|
|
10028
10046
|
const validObjectInfoNodes = [];
|
|
10029
10047
|
let updatedObjectInfoMap = {};
|
|
10030
|
-
// InlineFragment and polymorphic field support fits into this scenario pathToObjectApiNamesMap Entry: '
|
|
10048
|
+
// InlineFragment and polymorphic field support fits into this scenario pathToObjectApiNamesMap Entry: 'ServiceAppointment#Owner' -> ['User', 'Group']; ServiceAppointment#Owner#User' -> ['User']
|
|
10031
10049
|
if (objectInfoApiNames.length > 0 &&
|
|
10032
10050
|
nodesAtSameLevel.length > 0 &&
|
|
10033
10051
|
objectInfoApiNames.includes(nodesAtSameLevel[0].name)) {
|
|
@@ -10039,7 +10057,7 @@ async function fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, objectI
|
|
|
10039
10057
|
// eslint-disable-next-line
|
|
10040
10058
|
throw new Error(`Condition ${field.name} does not exists for ${parentPath}`);
|
|
10041
10059
|
}
|
|
10042
|
-
const path = `${parentPath}
|
|
10060
|
+
const path = `${parentPath}#${field.name}`;
|
|
10043
10061
|
pathToObjectApiNamesMap[path] = [field.name];
|
|
10044
10062
|
}
|
|
10045
10063
|
validObjectInfoNodes.push(...nodesAtSameLevel);
|
|
@@ -10055,7 +10073,7 @@ async function fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, objectI
|
|
|
10055
10073
|
let apiNames = [];
|
|
10056
10074
|
for (const nodeInfo of nodesAtSameLevel) {
|
|
10057
10075
|
const field = nodeInfo.name;
|
|
10058
|
-
const path = `${parentPath}
|
|
10076
|
+
const path = `${parentPath}#${field}`;
|
|
10059
10077
|
// Handle 'parentRelationship'
|
|
10060
10078
|
if (nodeInfo.relation === 'parent') {
|
|
10061
10079
|
const relationshipId = referenceIdFieldForRelationship(field);
|
|
@@ -10073,12 +10091,12 @@ async function fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, objectI
|
|
|
10073
10091
|
}
|
|
10074
10092
|
}
|
|
10075
10093
|
// This is a polymorphic field
|
|
10076
|
-
if (fieldDefinition.referenceToInfos.length > 1 && objectInfotree[
|
|
10094
|
+
if (fieldDefinition.referenceToInfos.length > 1 && objectInfotree[path]) {
|
|
10077
10095
|
// Fields needs to expand and heterogenous entity ObjectInfo needs to be fetched
|
|
10078
|
-
const referencedNodeInfos = objectInfotree[
|
|
10096
|
+
const referencedNodeInfos = objectInfotree[path];
|
|
10079
10097
|
const requestedApiNames = referencedNodeInfos.map((referenceNodeInfo) => referenceNodeInfo.name);
|
|
10080
10098
|
// 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.
|
|
10081
|
-
if (requestedApiNames.length > 0 && objectInfotree[
|
|
10099
|
+
if (requestedApiNames.length > 0 && objectInfotree[path]) {
|
|
10082
10100
|
fieldDefinition.referenceToInfos
|
|
10083
10101
|
.filter((referenceToInfo) => requestedApiNames.includes(referenceToInfo.apiName))
|
|
10084
10102
|
.forEach((ref) => {
|
|
@@ -10138,8 +10156,8 @@ async function fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, objectI
|
|
|
10138
10156
|
}
|
|
10139
10157
|
for (const nodeInfo of validObjectInfoNodes) {
|
|
10140
10158
|
const field = nodeInfo.name;
|
|
10141
|
-
const
|
|
10142
|
-
const
|
|
10159
|
+
const path = `${parentPath}#${field}`;
|
|
10160
|
+
const subLevelFields = objectInfotree[path];
|
|
10143
10161
|
if (subLevelFields && subLevelFields.length > 0) {
|
|
10144
10162
|
const subObjectInfos = await fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, updatedObjectInfoMap, subLevelFields, path, objectInfoService);
|
|
10145
10163
|
updatedObjectInfoMap = { ...updatedObjectInfoMap, ...subObjectInfos };
|
|
@@ -10156,27 +10174,29 @@ async function fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, objectI
|
|
|
10156
10174
|
* 'path' and 'queryNode' is 1 level above the 'filterNode'
|
|
10157
10175
|
* @param filterNode filter node which needs to be injected. For example, 'State' ObjectFieldNode within filter 'where: { State: { eq: "Nova Scotia" }}'
|
|
10158
10176
|
* @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
|
|
10177
|
+
* @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
|
|
10178
|
+
* @param isParentPolymorphic true if parent points to a polymorphic field.
|
|
10160
10179
|
* @param queryNode referece FieldNode which provides the information if 'filterNode' exist in it nor not.
|
|
10161
10180
|
* @param objectInfos ObjectInfo map used in injection. If ObjectInfo misses or field does not exist in ObjectInfo, the error will be thrown
|
|
10162
10181
|
* @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
10182
|
* @param draftFunctions functions for working with record ids that may be draft-created ids
|
|
10164
10183
|
* @returns an array of nodes with injected fields
|
|
10165
10184
|
*/
|
|
10166
|
-
function injectFilter(filterNode, idState,
|
|
10185
|
+
function injectFilter(filterNode, idState, parentPath, isParentPolymorphic, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode) {
|
|
10167
10186
|
const injectedSelections = [];
|
|
10187
|
+
let isPolymorphicField = false;
|
|
10168
10188
|
switch (filterNode.kind) {
|
|
10169
10189
|
case Kind.ARGUMENT:
|
|
10170
10190
|
if (filterNode.value.kind !== 'ObjectValue')
|
|
10171
10191
|
return [];
|
|
10172
10192
|
filterNode.value.fields.forEach((objectFieldNode) => {
|
|
10173
|
-
let subResults = injectFilter(objectFieldNode, idState,
|
|
10193
|
+
let subResults = injectFilter(objectFieldNode, idState, parentPath, isParentPolymorphic, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode);
|
|
10174
10194
|
for (const subResult of subResults) {
|
|
10175
10195
|
mergeOrAddToGroup(injectedSelections, subResult);
|
|
10176
10196
|
}
|
|
10177
10197
|
// multiple Ids might need to be swapped. remember their paths for faster write.
|
|
10178
10198
|
if (idState.swapNeeded) {
|
|
10179
|
-
idState.paths.push(
|
|
10199
|
+
idState.paths.push(parentPath);
|
|
10180
10200
|
}
|
|
10181
10201
|
});
|
|
10182
10202
|
return injectedSelections;
|
|
@@ -10185,7 +10205,7 @@ function injectFilter(filterNode, idState, path, objectInfos, pathToObjectApiNam
|
|
|
10185
10205
|
case Kind.LIST: {
|
|
10186
10206
|
filterNode.value.values.filter(isObjectValueNode).forEach((objectValueNode) => {
|
|
10187
10207
|
objectValueNode.fields.forEach((objectFieldNode) => {
|
|
10188
|
-
const subResults = injectFilter(objectFieldNode, idState,
|
|
10208
|
+
const subResults = injectFilter(objectFieldNode, idState, parentPath, isParentPolymorphic, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode);
|
|
10189
10209
|
for (const subResult of subResults) {
|
|
10190
10210
|
mergeOrAddToGroup(injectedSelections, subResult);
|
|
10191
10211
|
}
|
|
@@ -10196,7 +10216,7 @@ function injectFilter(filterNode, idState, path, objectInfos, pathToObjectApiNam
|
|
|
10196
10216
|
case Kind.OBJECT: {
|
|
10197
10217
|
if (filterNode.name.value === 'not') {
|
|
10198
10218
|
filterNode.value.fields.forEach((objectFieldNode) => {
|
|
10199
|
-
const subResults = injectFilter(objectFieldNode, idState,
|
|
10219
|
+
const subResults = injectFilter(objectFieldNode, idState, parentPath, isParentPolymorphic, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode);
|
|
10200
10220
|
for (const subResult of subResults) {
|
|
10201
10221
|
mergeOrAddToGroup(injectedSelections, subResult);
|
|
10202
10222
|
}
|
|
@@ -10206,15 +10226,15 @@ function injectFilter(filterNode, idState, path, objectInfos, pathToObjectApiNam
|
|
|
10206
10226
|
let apiNames = [];
|
|
10207
10227
|
let isScalarField = false;
|
|
10208
10228
|
//It is possible that this is a polymorphic field
|
|
10209
|
-
apiNames = pathToObjectApiNamesMap[
|
|
10210
|
-
// example: path: '
|
|
10229
|
+
apiNames = pathToObjectApiNamesMap[parentPath];
|
|
10230
|
+
// example: path: 'ServiceAppointment#LastModifiedDate'; filterNode: '{eq: {literal: LAST_WEEK}}'. queryNode: 'LastModifedDate { value}' FilterNode's parent has been verifed as a valid node
|
|
10211
10231
|
if (apiNames === undefined) {
|
|
10212
10232
|
isScalarField = true;
|
|
10213
10233
|
}
|
|
10214
10234
|
else {
|
|
10215
10235
|
if (apiNames.some((apiName) => objectInfos[apiName] === undefined)) {
|
|
10216
10236
|
// eslint-disable-next-line
|
|
10217
|
-
throw new Error(`ObjectInfo is missing for ${
|
|
10237
|
+
throw new Error(`ObjectInfo is missing for ${parentPath}`);
|
|
10218
10238
|
}
|
|
10219
10239
|
}
|
|
10220
10240
|
if (isScalarField) {
|
|
@@ -10238,21 +10258,17 @@ function injectFilter(filterNode, idState, path, objectInfos, pathToObjectApiNam
|
|
|
10238
10258
|
let isSpanning = false;
|
|
10239
10259
|
// if true, current node is a polymorphic concrete type node. For example, field node `User` under `Owner`
|
|
10240
10260
|
let isInlineFragment = false;
|
|
10241
|
-
let isPolymorphicField = false;
|
|
10242
10261
|
let isTypeNameExisting = false;
|
|
10243
10262
|
let curPath;
|
|
10244
10263
|
let fieldName = filterNode.name.value;
|
|
10245
|
-
curPath = `${
|
|
10264
|
+
curPath = `${parentPath}#${fieldName}`;
|
|
10246
10265
|
if (pathToObjectApiNamesMap[curPath] &&
|
|
10247
10266
|
pathToObjectApiNamesMap[curPath].length > 0) {
|
|
10248
10267
|
isSpanning = true;
|
|
10249
|
-
|
|
10250
|
-
|
|
10251
|
-
|
|
10252
|
-
|
|
10253
|
-
isInlineFragment = isPolymorphicFieldPath(path, pathToObjectApiNamesMap);
|
|
10254
|
-
}
|
|
10255
|
-
isPolymorphicField = isPolymorphicFieldPath(curPath, pathToObjectApiNamesMap);
|
|
10268
|
+
isInlineFragment =
|
|
10269
|
+
isParentPolymorphic &&
|
|
10270
|
+
pathToObjectApiNamesMap[curPath].length === 1;
|
|
10271
|
+
isPolymorphicField = isPolymorphicFieldPath(curPath, pathToObjectApiNamesMap, objectInfos);
|
|
10256
10272
|
}
|
|
10257
10273
|
// 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]
|
|
10258
10274
|
if (isInlineFragment) {
|
|
@@ -10298,7 +10314,7 @@ function injectFilter(filterNode, idState, path, objectInfos, pathToObjectApiNam
|
|
|
10298
10314
|
}
|
|
10299
10315
|
const objectInfoName = pathToObjectApiNamesMap[curPath] !== undefined
|
|
10300
10316
|
? pathToObjectApiNamesMap[curPath][0]
|
|
10301
|
-
: pathToObjectApiNamesMap[
|
|
10317
|
+
: pathToObjectApiNamesMap[parentPath][0];
|
|
10302
10318
|
const isIdField = isFieldAnIdField(filterNode.name.value, objectInfos[objectInfoName]);
|
|
10303
10319
|
if (!isIdField) {
|
|
10304
10320
|
let subSelectionNodes = [];
|
|
@@ -10310,7 +10326,7 @@ function injectFilter(filterNode, idState, path, objectInfos, pathToObjectApiNam
|
|
|
10310
10326
|
updateIDInfo(subFieldNode, idState, draftFunctions);
|
|
10311
10327
|
}
|
|
10312
10328
|
// try injecting the fields within predicate no matter it has relation or not.
|
|
10313
|
-
let subResults = injectFilter(subFieldNode, idState, curPath, objectInfos, pathToObjectApiNamesMap, draftFunctions, existingFields ? existingFields[0] : undefined);
|
|
10329
|
+
let subResults = injectFilter(subFieldNode, idState, curPath, isPolymorphicField, objectInfos, pathToObjectApiNamesMap, draftFunctions, existingFields ? existingFields[0] : undefined);
|
|
10314
10330
|
subSelectionNodes = subSelectionNodes.concat(subResults);
|
|
10315
10331
|
});
|
|
10316
10332
|
if (!subFieldsHasId) {
|
|
@@ -10471,15 +10487,43 @@ function mergeOrAddToGroup(group, element) {
|
|
|
10471
10487
|
}
|
|
10472
10488
|
group.push(element);
|
|
10473
10489
|
}
|
|
10474
|
-
// checks if the path points to a polymorphic field.
|
|
10475
|
-
//
|
|
10476
|
-
//
|
|
10477
|
-
|
|
10478
|
-
|
|
10479
|
-
|
|
10480
|
-
|
|
10481
|
-
|
|
10482
|
-
|
|
10490
|
+
// checks if the path points to a polymorphic field. For example, for the below `pathToObjectApiNamesMap`
|
|
10491
|
+
// {
|
|
10492
|
+
// 'ServiceAppointment' -> ['ServiceAppointment']
|
|
10493
|
+
// 'ServiceAppointment#Owner' --> ['User'],
|
|
10494
|
+
// 'ServiceAppointment#Owner#User' --> ['User']
|
|
10495
|
+
// }
|
|
10496
|
+
// path `ServiceAppointment#Owner` points to a polymorphic field, but path `ServiceAppointment#Owner#User` does not.
|
|
10497
|
+
function isPolymorphicFieldPath(path, pathToObjectApiNamesMap, objectInfos) {
|
|
10498
|
+
const lastSegmentIndex = path.lastIndexOf('#');
|
|
10499
|
+
if (lastSegmentIndex < 0) {
|
|
10500
|
+
return false;
|
|
10501
|
+
}
|
|
10502
|
+
const lastSegment = path.slice(lastSegmentIndex + 1);
|
|
10503
|
+
const parentApiPath = path.slice(0, lastSegmentIndex);
|
|
10504
|
+
if (pathToObjectApiNamesMap[parentApiPath] === undefined) {
|
|
10505
|
+
return false;
|
|
10506
|
+
}
|
|
10507
|
+
const parentObjectApiNames = pathToObjectApiNamesMap[parentApiPath];
|
|
10508
|
+
// 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`.
|
|
10509
|
+
// 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.
|
|
10510
|
+
// Below are the entries in `pathToObjectApiNamesMap`
|
|
10511
|
+
// {
|
|
10512
|
+
// `ServiceAppointmen`t: [`ServiceAppointment`],
|
|
10513
|
+
// `ServiceAppointment#Owner`: [`User`, `Group`],
|
|
10514
|
+
// `ServiceAppointment#Owner#User`: [`User`],
|
|
10515
|
+
// `ServiceAppointment#Owner#Group`: [`Group`],
|
|
10516
|
+
// }
|
|
10517
|
+
if (parentObjectApiNames.length !== 1) {
|
|
10518
|
+
return false;
|
|
10519
|
+
}
|
|
10520
|
+
const parentObjectInfo = objectInfos[parentObjectApiNames[0]];
|
|
10521
|
+
const relationshipField = referenceIdFieldForRelationship(lastSegment);
|
|
10522
|
+
let fieldDefinition = parentObjectInfo.fields[relationshipField];
|
|
10523
|
+
if (fieldDefinition === undefined) {
|
|
10524
|
+
return false;
|
|
10525
|
+
}
|
|
10526
|
+
return fieldDefinition.polymorphicForeignKey;
|
|
10483
10527
|
}
|
|
10484
10528
|
function isFieldAnIdField(fieldName, objectInfo) {
|
|
10485
10529
|
if (fieldName === 'Id')
|
|
@@ -10533,10 +10577,10 @@ function updateIDInfo(fieldNode, idState, draftFunctions) {
|
|
|
10533
10577
|
* @param parentNode parent node of param 1
|
|
10534
10578
|
* @param ancestors ancester of param 1
|
|
10535
10579
|
* @param objectInfos ObjectInfo map used in injection. If ObjectInfo misses or field does not exist in ObjectInfo, the error will be thrown
|
|
10536
|
-
* @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']; '
|
|
10580
|
+
* @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'].
|
|
10537
10581
|
* @return injected SelectionNodes used to construct the InlineFragment.
|
|
10538
10582
|
*/
|
|
10539
|
-
function injectFields(selections, parentNode, ancestors, objectInfos, pathToObjectApiNamesMap) {
|
|
10583
|
+
function injectFields(selections, parentNode, parentPath, ancestors, objectInfos, pathToObjectApiNamesMap) {
|
|
10540
10584
|
/**
|
|
10541
10585
|
* 1 parentship can return 2 FieldNode which need to be flattened
|
|
10542
10586
|
* Concact: { ** Contact { ** ContactId {
|
|
@@ -10554,6 +10598,10 @@ function injectFields(selections, parentNode, ancestors, objectInfos, pathToObje
|
|
|
10554
10598
|
if (!selection.selectionSet) {
|
|
10555
10599
|
return selection;
|
|
10556
10600
|
}
|
|
10601
|
+
const segment = isFieldNode(selection)
|
|
10602
|
+
? selection.name.value
|
|
10603
|
+
: selection.typeCondition.name.value;
|
|
10604
|
+
const curPath = `${parentPath}#${segment}`;
|
|
10557
10605
|
const spanningSubSelections = [];
|
|
10558
10606
|
for (const subSelection of selection.selectionSet.selections) {
|
|
10559
10607
|
if (isFieldSpanning(subSelection, selection)) {
|
|
@@ -10561,7 +10609,7 @@ function injectFields(selections, parentNode, ancestors, objectInfos, pathToObje
|
|
|
10561
10609
|
}
|
|
10562
10610
|
}
|
|
10563
10611
|
// Handles multiple level field injection like 'ServiceAppointment' --> 'Account' --> 'Owner'
|
|
10564
|
-
const subInjectedSelections = injectFields(spanningSubSelections, selection, ancestors, objectInfos, pathToObjectApiNamesMap);
|
|
10612
|
+
const subInjectedSelections = injectFields(spanningSubSelections, selection, curPath, ancestors, objectInfos, pathToObjectApiNamesMap);
|
|
10565
10613
|
if (!selection.selectionSet) {
|
|
10566
10614
|
return selection;
|
|
10567
10615
|
}
|
|
@@ -10604,7 +10652,7 @@ function injectFields(selections, parentNode, ancestors, objectInfos, pathToObje
|
|
|
10604
10652
|
}
|
|
10605
10653
|
}
|
|
10606
10654
|
// For polymorphic fields, the Id field is excluded.
|
|
10607
|
-
const excludeId =
|
|
10655
|
+
const excludeId = isPolymorphicFieldPath(curPath, pathToObjectApiNamesMap, objectInfos);
|
|
10608
10656
|
const idSelection = [];
|
|
10609
10657
|
if (!excludeId && !hasIdAlready) {
|
|
10610
10658
|
idSelection.push({
|
|
@@ -10615,8 +10663,8 @@ function injectFields(selections, parentNode, ancestors, objectInfos, pathToObje
|
|
|
10615
10663
|
},
|
|
10616
10664
|
});
|
|
10617
10665
|
}
|
|
10618
|
-
// Inject '__typename' for
|
|
10619
|
-
// please reference 'removeSyntheticFields'.
|
|
10666
|
+
// 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
|
|
10667
|
+
// `typedCondition` of the InlineFragment in the query AST. It is used to match JSON response with AST node. For more detail, please reference 'removeSyntheticFields'.
|
|
10620
10668
|
if (isInlineFragmentNode(selection) &&
|
|
10621
10669
|
!selection.selectionSet.selections.find((selection) => isFieldNode(selection) && selection.name.value === '__typename')) {
|
|
10622
10670
|
idSelection.push({
|
|
@@ -10650,7 +10698,7 @@ function injectFields(selections, parentNode, ancestors, objectInfos, pathToObje
|
|
|
10650
10698
|
if (isFieldNode(parentNode) && parentNode.selectionSet && parentNode.name.value === 'node') {
|
|
10651
10699
|
if (parentNode.selectionSet.selections
|
|
10652
10700
|
.filter(isFieldOrInlineFragmentNode)
|
|
10653
|
-
.some((selectionNode) => isRelationship(selectionNode,
|
|
10701
|
+
.some((selectionNode) => isRelationship(selectionNode, CHILD_RELATIONSHIP))) {
|
|
10654
10702
|
if (!parentNode.selectionSet.selections
|
|
10655
10703
|
.filter(isFieldNode)
|
|
10656
10704
|
.some((sibling) => sibling.name.value === 'Id')) {
|
|
@@ -10669,7 +10717,7 @@ function injectFields(selections, parentNode, ancestors, objectInfos, pathToObje
|
|
|
10669
10717
|
if (parentInfo.parentIndex >= 0) {
|
|
10670
10718
|
// example node { TimeSheetEntries { edges { node { Id }}}}
|
|
10671
10719
|
const parent = parentInfo.node;
|
|
10672
|
-
if (isRelationship(parent,
|
|
10720
|
+
if (isRelationship(parent, CHILD_RELATIONSHIP)) {
|
|
10673
10721
|
const unVisitedAncestors = ancestors.slice(0, parentInfo.parentIndex);
|
|
10674
10722
|
// path : "TimeSheet"
|
|
10675
10723
|
const grandParentPath = findAncesterPath(unVisitedAncestors);
|
|
@@ -10798,7 +10846,7 @@ const assignedToMeFragmentSelections = [
|
|
|
10798
10846
|
},
|
|
10799
10847
|
value: {
|
|
10800
10848
|
kind: 'StringValue',
|
|
10801
|
-
value:
|
|
10849
|
+
value: CHILD_RELATIONSHIP,
|
|
10802
10850
|
block: false,
|
|
10803
10851
|
},
|
|
10804
10852
|
},
|
|
@@ -10890,7 +10938,7 @@ const assignedToMeFragmentSelections = [
|
|
|
10890
10938
|
},
|
|
10891
10939
|
value: {
|
|
10892
10940
|
kind: 'StringValue',
|
|
10893
|
-
value:
|
|
10941
|
+
value: PARENT_RELATIONSHIP,
|
|
10894
10942
|
block: false,
|
|
10895
10943
|
},
|
|
10896
10944
|
},
|
|
@@ -11027,7 +11075,9 @@ function handleNonArrayJsonProperty(selection, fieldName, jsonInput, jsonOutput)
|
|
|
11027
11075
|
jsonOutput[fieldName] = null;
|
|
11028
11076
|
return;
|
|
11029
11077
|
}
|
|
11030
|
-
jsonOutput[fieldName]
|
|
11078
|
+
if (jsonOutput[fieldName] === undefined) {
|
|
11079
|
+
jsonOutput[fieldName] = {};
|
|
11080
|
+
}
|
|
11031
11081
|
createUserJsonOutput(selection, jsonInput[fieldName], jsonOutput[fieldName]);
|
|
11032
11082
|
}
|
|
11033
11083
|
else {
|
|
@@ -17063,4 +17113,4 @@ register({
|
|
|
17063
17113
|
});
|
|
17064
17114
|
|
|
17065
17115
|
export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
|
|
17066
|
-
// version: 1.
|
|
17116
|
+
// version: 1.242.1-58f8f4bb1
|