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