@salesforce/lds-worker-api 1.228.1 → 1.229.0-dev10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/sfdc/es/ldsWorkerApi.js +1 -1
- package/dist/standalone/es/lds-worker-api.js +626 -354
- package/dist/standalone/umd/lds-worker-api.js +626 -354
- package/package.json +10 -10
|
@@ -31,12 +31,15 @@
|
|
|
31
31
|
const { isArray: isArray$9 } = Array;
|
|
32
32
|
const { push: push$5, indexOf, slice: slice$2 } = Array.prototype;
|
|
33
33
|
const { parse: parse$a, stringify: stringify$a } = JSON;
|
|
34
|
+
const WeakSetCtor = WeakSet;
|
|
34
35
|
|
|
36
|
+
const deeplyFrozen = new WeakSetCtor();
|
|
35
37
|
function deepFreeze(value) {
|
|
36
|
-
// No need to freeze primitives
|
|
37
|
-
if (typeof value !== 'object' || value === null) {
|
|
38
|
+
// No need to freeze primitives or already frozen stuff
|
|
39
|
+
if (typeof value !== 'object' || value === null || deeplyFrozen.has(value)) {
|
|
38
40
|
return;
|
|
39
41
|
}
|
|
42
|
+
deeplyFrozen.add(value);
|
|
40
43
|
if (isArray$9(value)) {
|
|
41
44
|
for (let i = 0, len = value.length; i < len; i += 1) {
|
|
42
45
|
deepFreeze(value[i]);
|
|
@@ -1733,6 +1736,10 @@
|
|
|
1733
1736
|
}
|
|
1734
1737
|
}
|
|
1735
1738
|
markVisited(canonicalKey) {
|
|
1739
|
+
if (typeof canonicalKey === 'string') {
|
|
1740
|
+
this.fallbackStringKeyInMemoryStore.markVisited(canonicalKey);
|
|
1741
|
+
return;
|
|
1742
|
+
}
|
|
1736
1743
|
const { visitedIdsSet, reverseRedirectKeysMap } = this;
|
|
1737
1744
|
let redirectKey = canonicalKey;
|
|
1738
1745
|
// mark all redirects leading up to the canonical key as visited so
|
|
@@ -2044,7 +2051,7 @@
|
|
|
2044
2051
|
if (isStoreRecordError$1(linked)) {
|
|
2045
2052
|
return new GraphNodeError(this.store, linked);
|
|
2046
2053
|
}
|
|
2047
|
-
return new GraphNode(this.store, linked);
|
|
2054
|
+
return new GraphNode(this.store, linked, __ref);
|
|
2048
2055
|
}
|
|
2049
2056
|
linkData() {
|
|
2050
2057
|
return this.data.data;
|
|
@@ -2054,10 +2061,11 @@
|
|
|
2054
2061
|
}
|
|
2055
2062
|
}
|
|
2056
2063
|
class GraphNode {
|
|
2057
|
-
constructor(store, data) {
|
|
2064
|
+
constructor(store, data, storeKey) {
|
|
2058
2065
|
this.type = GraphNodeType$1.Node;
|
|
2059
2066
|
this.store = store;
|
|
2060
2067
|
this.data = data;
|
|
2068
|
+
this.storeKey = storeKey;
|
|
2061
2069
|
}
|
|
2062
2070
|
object(propertyName) {
|
|
2063
2071
|
const value = this.data[propertyName];
|
|
@@ -2067,7 +2075,8 @@
|
|
|
2067
2075
|
if (typeof value !== 'object' || value === null) {
|
|
2068
2076
|
throw new Error(`Cannot walk to path ${String(propertyName)}. "${String(propertyName)}" is a scalar: "${value}"`);
|
|
2069
2077
|
}
|
|
2070
|
-
|
|
2078
|
+
// We're walking to an object property on the current store record, pass the storeKey down.
|
|
2079
|
+
return new GraphNode(this.store, value, this.storeKey);
|
|
2071
2080
|
}
|
|
2072
2081
|
link(propertyName) {
|
|
2073
2082
|
const value = this.data[propertyName];
|
|
@@ -2097,6 +2106,8 @@
|
|
|
2097
2106
|
}
|
|
2098
2107
|
write(propertyName, value) {
|
|
2099
2108
|
this.data[propertyName] = value;
|
|
2109
|
+
const canonicalKey = this.store.getCanonicalRecordId(this.storeKey);
|
|
2110
|
+
this.store.markVisited(canonicalKey);
|
|
2100
2111
|
}
|
|
2101
2112
|
isUndefined(propertyName) {
|
|
2102
2113
|
return this.data[propertyName] === undefined;
|
|
@@ -2281,6 +2292,34 @@
|
|
|
2281
2292
|
const FRAGMENT_READ_RESULT_MISSING = {
|
|
2282
2293
|
state: FragmentReadResultState$1.Missing,
|
|
2283
2294
|
};
|
|
2295
|
+
function resolveLink$1(reader, storeLink, version) {
|
|
2296
|
+
const { StoreLinkStateValues } = reader;
|
|
2297
|
+
const linkState = reader.getLinkState(storeLink);
|
|
2298
|
+
switch (linkState.state) {
|
|
2299
|
+
case StoreLinkStateValues.RefNotPresent:
|
|
2300
|
+
case StoreLinkStateValues.NotPresent:
|
|
2301
|
+
case StoreLinkStateValues.Missing:
|
|
2302
|
+
reader.markMissingLink(storeLink.__ref);
|
|
2303
|
+
reader.markMissing();
|
|
2304
|
+
return;
|
|
2305
|
+
case StoreLinkStateValues.Pending:
|
|
2306
|
+
reader.markPending();
|
|
2307
|
+
return;
|
|
2308
|
+
case StoreLinkStateValues.Null:
|
|
2309
|
+
return;
|
|
2310
|
+
}
|
|
2311
|
+
const { key: __ref } = linkState;
|
|
2312
|
+
return reader.read({
|
|
2313
|
+
recordId: __ref,
|
|
2314
|
+
node: {
|
|
2315
|
+
kind: 'Fragment',
|
|
2316
|
+
private: [],
|
|
2317
|
+
opaque: true,
|
|
2318
|
+
version,
|
|
2319
|
+
},
|
|
2320
|
+
variables: {},
|
|
2321
|
+
});
|
|
2322
|
+
}
|
|
2284
2323
|
class Reader {
|
|
2285
2324
|
constructor(store, variables, refresh, baseSnapshot, ttlStrategy) {
|
|
2286
2325
|
this.store = store;
|
|
@@ -3231,9 +3270,9 @@
|
|
|
3231
3270
|
if (value === undefined) {
|
|
3232
3271
|
return null;
|
|
3233
3272
|
}
|
|
3234
|
-
return this.wrapNormalizedGraphNode(value, store);
|
|
3273
|
+
return this.wrapNormalizedGraphNode(value, key, store);
|
|
3235
3274
|
}
|
|
3236
|
-
wrapNormalizedGraphNode(normalized, storeOverride) {
|
|
3275
|
+
wrapNormalizedGraphNode(normalized, key, storeOverride) {
|
|
3237
3276
|
if (normalized === null) {
|
|
3238
3277
|
return null;
|
|
3239
3278
|
}
|
|
@@ -3241,7 +3280,7 @@
|
|
|
3241
3280
|
if (isStoreRecordError$1(normalized)) {
|
|
3242
3281
|
return new GraphNodeError(store, normalized);
|
|
3243
3282
|
}
|
|
3244
|
-
return new GraphNode(store, normalized);
|
|
3283
|
+
return new GraphNode(store, normalized, key);
|
|
3245
3284
|
}
|
|
3246
3285
|
withContext(adapter, options) {
|
|
3247
3286
|
const { contextId, onContextLoaded } = options;
|
|
@@ -3536,8 +3575,8 @@
|
|
|
3536
3575
|
getNode(key) {
|
|
3537
3576
|
return this.environment.getNode(key);
|
|
3538
3577
|
}
|
|
3539
|
-
wrapNormalizedGraphNode(normalized) {
|
|
3540
|
-
return this.environment.wrapNormalizedGraphNode(normalized);
|
|
3578
|
+
wrapNormalizedGraphNode(normalized, key) {
|
|
3579
|
+
return this.environment.wrapNormalizedGraphNode(normalized, key);
|
|
3541
3580
|
}
|
|
3542
3581
|
instrument(paramsBuilder) {
|
|
3543
3582
|
const { instrument } = this.options;
|
|
@@ -3847,7 +3886,7 @@
|
|
|
3847
3886
|
}
|
|
3848
3887
|
return resourceParams;
|
|
3849
3888
|
}
|
|
3850
|
-
// engine version: 0.
|
|
3889
|
+
// engine version: 0.146.0-dev5-a2ec6e3f
|
|
3851
3890
|
|
|
3852
3891
|
/**
|
|
3853
3892
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
@@ -3974,7 +4013,7 @@
|
|
|
3974
4013
|
}
|
|
3975
4014
|
callbacks.push(callback);
|
|
3976
4015
|
}
|
|
3977
|
-
// version: 1.
|
|
4016
|
+
// version: 1.229.0-dev10-bc9ef2513
|
|
3978
4017
|
|
|
3979
4018
|
// TODO [TD-0081508]: once that TD is fulfilled we can probably change this file
|
|
3980
4019
|
function instrumentAdapter$1(createFunction, _metadata) {
|
|
@@ -15435,7 +15474,7 @@
|
|
|
15435
15474
|
}
|
|
15436
15475
|
return superResult;
|
|
15437
15476
|
}
|
|
15438
|
-
// version: 1.
|
|
15477
|
+
// version: 1.229.0-dev10-bc9ef2513
|
|
15439
15478
|
|
|
15440
15479
|
function unwrap(data) {
|
|
15441
15480
|
// The lwc-luvio bindings import a function from lwc called "unwrap".
|
|
@@ -15536,14 +15575,15 @@
|
|
|
15536
15575
|
return undefined;
|
|
15537
15576
|
});
|
|
15538
15577
|
}
|
|
15539
|
-
const { isArray: isArray$8 } = Array;
|
|
15540
|
-
const { stringify: stringify$9 } = JSON;
|
|
15541
15578
|
|
|
15542
15579
|
function isPromise$1(value) {
|
|
15543
15580
|
// check for Thenable due to test frameworks using custom Promise impls
|
|
15544
15581
|
return value.then !== undefined;
|
|
15545
15582
|
}
|
|
15546
15583
|
|
|
15584
|
+
const { isArray: isArray$8 } = Array;
|
|
15585
|
+
const { stringify: stringify$9 } = JSON;
|
|
15586
|
+
|
|
15547
15587
|
/**
|
|
15548
15588
|
* (Re)throws an error after adding a prefix to the message.
|
|
15549
15589
|
*
|
|
@@ -16358,7 +16398,7 @@
|
|
|
16358
16398
|
const { apiFamily, name } = metadata;
|
|
16359
16399
|
return createGraphQLWireAdapterConstructor$1(adapter, `${apiFamily}.${name}`, luvio, astResolver);
|
|
16360
16400
|
}
|
|
16361
|
-
// version: 1.
|
|
16401
|
+
// version: 1.229.0-dev10-bc9ef2513
|
|
16362
16402
|
|
|
16363
16403
|
/**
|
|
16364
16404
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
@@ -16457,11 +16497,11 @@
|
|
|
16457
16497
|
TypeCheckShapes[TypeCheckShapes["Integer"] = 3] = "Integer";
|
|
16458
16498
|
TypeCheckShapes[TypeCheckShapes["Unsupported"] = 4] = "Unsupported";
|
|
16459
16499
|
})(TypeCheckShapes || (TypeCheckShapes = {}));
|
|
16460
|
-
// engine version: 0.
|
|
16500
|
+
// engine version: 0.146.0-dev5-a2ec6e3f
|
|
16461
16501
|
|
|
16462
16502
|
const { keys: ObjectKeys$3, create: ObjectCreate$3 } = Object;
|
|
16463
16503
|
|
|
16464
|
-
const { assign: assign$9, create: create$9, freeze: freeze$4, keys: keys$b } = Object;
|
|
16504
|
+
const { assign: assign$9, create: create$9, freeze: freeze$4, isFrozen: isFrozen$2, keys: keys$b } = Object;
|
|
16465
16505
|
|
|
16466
16506
|
ObjectCreate$3(null);
|
|
16467
16507
|
|
|
@@ -16831,7 +16871,7 @@
|
|
|
16831
16871
|
}
|
|
16832
16872
|
const keyPrefix$1 = 'UiApi';
|
|
16833
16873
|
|
|
16834
|
-
const { assign: assign$8, create: create$8, freeze: freeze$3, keys: keys$a } = Object;
|
|
16874
|
+
const { assign: assign$8, create: create$8, freeze: freeze$3, isFrozen: isFrozen$1, keys: keys$a } = Object;
|
|
16835
16875
|
const { hasOwnProperty: hasOwnProperty$1 } = Object.prototype;
|
|
16836
16876
|
const { split, endsWith } = String.prototype;
|
|
16837
16877
|
const { isArray: isArray$7 } = Array;
|
|
@@ -19800,7 +19840,7 @@
|
|
|
19800
19840
|
extractTrackedFieldsToTrie(spanningLink.data.__ref, spanning, next, config, spanningVisitedRecordIds, depth + 1);
|
|
19801
19841
|
// For a spanning record that is detected to be a circular reference, we add the field along with Id and Name.
|
|
19802
19842
|
// It's possible for spanning record lookup fields to sometimes be circular, and sometimes not - depending on the value of the lookup field.
|
|
19803
|
-
// For more information on scenarios that caused this fix:
|
|
19843
|
+
// For more information on scenarios that caused this fix: search "LDS Recursive Spanning Fields Problem" in Quip
|
|
19804
19844
|
if (keys$a(next.children).length === 0) {
|
|
19805
19845
|
addScalarFieldId(next);
|
|
19806
19846
|
addScalarFieldName(next);
|
|
@@ -19953,7 +19993,11 @@
|
|
|
19953
19993
|
}
|
|
19954
19994
|
const link = fieldValueRepresentation.link(fieldName);
|
|
19955
19995
|
const resolved = link.follow();
|
|
19956
|
-
if (isGraphNode(resolved) &&
|
|
19996
|
+
if (isGraphNode(resolved) &&
|
|
19997
|
+
resolved.isScalar('value') &&
|
|
19998
|
+
path.length > 0 &&
|
|
19999
|
+
// TODO [W-14082782]: temporary fix
|
|
20000
|
+
!isFrozen$1(link.data)) {
|
|
19957
20001
|
const linkState = link.linkData();
|
|
19958
20002
|
const fields = linkState === undefined ? [] : linkState.fields;
|
|
19959
20003
|
link.writeLinkData({
|
|
@@ -19981,22 +20025,12 @@
|
|
|
19981
20025
|
const fieldValueRepresentation = record.object('fields');
|
|
19982
20026
|
const fieldName = path.shift();
|
|
19983
20027
|
if (fieldValueRepresentation.isUndefined(fieldName) === true) {
|
|
19984
|
-
|
|
19985
|
-
// an undefined/non-present __ref if isMissing is present
|
|
19986
|
-
fieldValueRepresentation.write(fieldName, {
|
|
19987
|
-
__ref: undefined,
|
|
19988
|
-
isMissing: true,
|
|
19989
|
-
});
|
|
20028
|
+
writeMissingFieldToStore(fieldValueRepresentation, fieldName);
|
|
19990
20029
|
return;
|
|
19991
20030
|
}
|
|
19992
20031
|
const link = fieldValueRepresentation.link(fieldName);
|
|
19993
20032
|
if (link.isPending()) {
|
|
19994
|
-
|
|
19995
|
-
// an undefined/non-present __ref if isMissing is present
|
|
19996
|
-
fieldValueRepresentation.write(fieldName, {
|
|
19997
|
-
__ref: undefined,
|
|
19998
|
-
isMissing: true,
|
|
19999
|
-
});
|
|
20033
|
+
writeMissingFieldToStore(fieldValueRepresentation, fieldName);
|
|
20000
20034
|
}
|
|
20001
20035
|
else if (path.length > 0 && link.isMissing() === false) {
|
|
20002
20036
|
const fieldValue = link.follow();
|
|
@@ -20012,6 +20046,19 @@
|
|
|
20012
20046
|
}
|
|
20013
20047
|
}
|
|
20014
20048
|
}
|
|
20049
|
+
/**
|
|
20050
|
+
* Graph Node Directly modifies store entries, which is generally a non-starter.
|
|
20051
|
+
* Until we can refactor this mess, you need to use this function to safely mark the RecordRepresentation
|
|
20052
|
+
* as a seenId in the store when you perform this mutation.
|
|
20053
|
+
*/
|
|
20054
|
+
function writeMissingFieldToStore(field, fieldName) {
|
|
20055
|
+
// TODO [W-6900046]: remove cast, make RecordRepresentationNormalized['fields'] accept
|
|
20056
|
+
// an undefined/non-present __ref if isMissing is present
|
|
20057
|
+
field.write(fieldName, {
|
|
20058
|
+
__ref: undefined,
|
|
20059
|
+
isMissing: true,
|
|
20060
|
+
});
|
|
20061
|
+
}
|
|
20015
20062
|
/**
|
|
20016
20063
|
* Tells you if an objectApiName is supported by UI API or not.
|
|
20017
20064
|
* Note: Luvio does not currently support all the entities, the list is limited to UI API supported entities
|
|
@@ -20143,8 +20190,11 @@
|
|
|
20143
20190
|
return existing;
|
|
20144
20191
|
}
|
|
20145
20192
|
function mergeRecordConflict(luvio, incoming, existing, recordConflictMap) {
|
|
20146
|
-
const
|
|
20147
|
-
|
|
20193
|
+
const recordKey = keyBuilder$1U(luvio, {
|
|
20194
|
+
recordId: incoming.id,
|
|
20195
|
+
});
|
|
20196
|
+
const incomingNode = luvio.wrapNormalizedGraphNode(incoming, recordKey);
|
|
20197
|
+
const existingNode = luvio.wrapNormalizedGraphNode(existing, recordKey);
|
|
20148
20198
|
const incomingTrackedFieldsTrieRoot = {
|
|
20149
20199
|
name: incoming.apiName,
|
|
20150
20200
|
children: {},
|
|
@@ -20153,9 +20203,6 @@
|
|
|
20153
20203
|
name: existing.apiName,
|
|
20154
20204
|
children: {},
|
|
20155
20205
|
};
|
|
20156
|
-
const recordKey = keyBuilder$1U(luvio, {
|
|
20157
|
-
recordId: incoming.id,
|
|
20158
|
-
});
|
|
20159
20206
|
const trackedFieldsConfig = {
|
|
20160
20207
|
maxDepth: configurationForRestAdapters$1.getTrackedFieldDepthOnCacheMergeConflict(),
|
|
20161
20208
|
onlyFetchLeafNodeIdAndName: configurationForRestAdapters$1.getTrackedFieldLeafNodeIdAndNameOnly(),
|
|
@@ -20461,7 +20508,7 @@
|
|
|
20461
20508
|
const batchRequestWithSingleRequest = isSingleBatchRecordRequest(existingUrlParams) &&
|
|
20462
20509
|
isSingleRecordRequest(urlParams) &&
|
|
20463
20510
|
incomingUrlRecords[0] === existingUrlRecords[0];
|
|
20464
|
-
if (!batchRequestWithSingleRequest) {
|
|
20511
|
+
if (!batchRequestWithSingleRequest || isRestrictedPathCondition(existingPath, path)) {
|
|
20465
20512
|
return false;
|
|
20466
20513
|
}
|
|
20467
20514
|
}
|
|
@@ -20504,6 +20551,12 @@
|
|
|
20504
20551
|
function isSingleRecordRequest(urlParams) {
|
|
20505
20552
|
return hasOwnProperty$1.call(urlParams, 'recordId');
|
|
20506
20553
|
}
|
|
20554
|
+
function isRestrictedPathCondition(existingPath, path) {
|
|
20555
|
+
// should not dedupe getRecordUi and getRecord as both of their representation is different
|
|
20556
|
+
// records call cannot digest response of getRecordUi
|
|
20557
|
+
return ((existingPath.includes('/record-ui') && path.includes('/records')) ||
|
|
20558
|
+
(existingPath.includes('/records') && path.includes('/record-ui')));
|
|
20559
|
+
}
|
|
20507
20560
|
|
|
20508
20561
|
const createResourceRequest$12 = function getUiApiRecordsByRecordIdCreateResourceRequest(config) {
|
|
20509
20562
|
return {
|
|
@@ -24860,7 +24913,7 @@
|
|
|
24860
24913
|
// Temp fix until we can mimic the server behavior for non-layoutable entities.
|
|
24861
24914
|
let layoutMap = {};
|
|
24862
24915
|
if (hasOwnProperty$1.call(layouts, apiName)) {
|
|
24863
|
-
layoutMap = layouts[apiName][recordTypeId];
|
|
24916
|
+
layoutMap = layouts[apiName][recordTypeId] || {};
|
|
24864
24917
|
}
|
|
24865
24918
|
return {
|
|
24866
24919
|
layoutMap,
|
|
@@ -25038,18 +25091,28 @@
|
|
|
25038
25091
|
* These are intermediate lookups to check if the record is in the L2 cache
|
|
25039
25092
|
* @param {Luvio} luvio
|
|
25040
25093
|
* @param {GetRecordLayoutTypeConfig} config
|
|
25041
|
-
* @param {BuildCachedSnapshot<BuildSnapshotContext} cachedSnapshot
|
|
25094
|
+
* @param {BuildCachedSnapshot<BuildSnapshotContext>} cachedSnapshot
|
|
25042
25095
|
*/
|
|
25043
25096
|
function makeCacheOnlySnapshot(luvio, config, adapterContext, cachedSnapshot) {
|
|
25044
|
-
return luvio.applyCachePolicy(
|
|
25045
|
-
|
|
25046
|
-
|
|
25047
|
-
|
|
25048
|
-
},
|
|
25049
|
-
}, { config, luvio, adapterContext }, cachedSnapshot,
|
|
25050
|
-
// this won't be invoked since we're requesting only-if-cached
|
|
25097
|
+
return luvio.applyCachePolicy(
|
|
25098
|
+
// Pass empty context so environment will use its default cache-policy
|
|
25099
|
+
{}, { config, luvio, adapterContext }, cachedSnapshot,
|
|
25100
|
+
// disallow hitting the network by returning a gateway timeout
|
|
25051
25101
|
() => {
|
|
25052
|
-
|
|
25102
|
+
return new Promise((resolve) => {
|
|
25103
|
+
resolve({
|
|
25104
|
+
state: 'Error',
|
|
25105
|
+
data: undefined,
|
|
25106
|
+
error: {
|
|
25107
|
+
body: undefined,
|
|
25108
|
+
headers: {},
|
|
25109
|
+
ok: false,
|
|
25110
|
+
status: 504,
|
|
25111
|
+
statusText: 'Gateway Timeout',
|
|
25112
|
+
errorType: 'fetchResponse',
|
|
25113
|
+
},
|
|
25114
|
+
});
|
|
25115
|
+
});
|
|
25053
25116
|
});
|
|
25054
25117
|
}
|
|
25055
25118
|
/**
|
|
@@ -25260,7 +25323,7 @@
|
|
|
25260
25323
|
const responsePromises = [];
|
|
25261
25324
|
for (let i = 0, len = entries.length; i < len; i++) {
|
|
25262
25325
|
const { key, record } = entries[i];
|
|
25263
|
-
const node = luvio.wrapNormalizedGraphNode(record);
|
|
25326
|
+
const node = luvio.wrapNormalizedGraphNode(record, key);
|
|
25264
25327
|
const optionalFields = getTrackedFields(key, node, {
|
|
25265
25328
|
maxDepth: configurationForRestAdapters$1.getTrackedFieldDepthOnNotifyChange(),
|
|
25266
25329
|
onlyFetchLeafNodeIdAndName: configurationForRestAdapters$1.getTrackedFieldLeafNodeIdAndNameOnly(),
|
|
@@ -41158,7 +41221,16 @@
|
|
|
41158
41221
|
throttle(60, 60000, createLDSAdapter(luvio, 'notifyListInfoUpdateAvailable', notifyUpdateAvailableFactory$1));
|
|
41159
41222
|
throttle(60, 60000, createLDSAdapter(luvio, 'notifyQuickActionDefaultsUpdateAvailable', notifyUpdateAvailableFactory));
|
|
41160
41223
|
});
|
|
41161
|
-
// version: 1.
|
|
41224
|
+
// version: 1.229.0-dev10-abb060196
|
|
41225
|
+
|
|
41226
|
+
var ldsIdempotencyWriteDisabled = {
|
|
41227
|
+
isOpen: function (e) {
|
|
41228
|
+
return e.fallback;
|
|
41229
|
+
},
|
|
41230
|
+
hasError: function () {
|
|
41231
|
+
return !0;
|
|
41232
|
+
},
|
|
41233
|
+
};
|
|
41162
41234
|
|
|
41163
41235
|
var caseSensitiveUserId = '005B0000000GR4OIAW';
|
|
41164
41236
|
|
|
@@ -41789,6 +41861,9 @@
|
|
|
41789
41861
|
}
|
|
41790
41862
|
|
|
41791
41863
|
function isStoreEntryError(storeRecord) {
|
|
41864
|
+
if (!storeRecord || typeof storeRecord !== 'object') {
|
|
41865
|
+
return false;
|
|
41866
|
+
}
|
|
41792
41867
|
return storeRecord.__type === 'error';
|
|
41793
41868
|
}
|
|
41794
41869
|
|
|
@@ -42373,12 +42448,12 @@
|
|
|
42373
42448
|
}
|
|
42374
42449
|
return environment.getNode(key, ingestStagingStore);
|
|
42375
42450
|
};
|
|
42376
|
-
const wrapNormalizedGraphNode = function (normalized) {
|
|
42451
|
+
const wrapNormalizedGraphNode = function (normalized, key) {
|
|
42377
42452
|
validateNotDisposed();
|
|
42378
42453
|
if (ingestStagingStore === null) {
|
|
42379
42454
|
ingestStagingStore = buildIngestStagingStore(environment);
|
|
42380
42455
|
}
|
|
42381
|
-
return environment.wrapNormalizedGraphNode(normalized, ingestStagingStore);
|
|
42456
|
+
return environment.wrapNormalizedGraphNode(normalized, key, ingestStagingStore);
|
|
42382
42457
|
};
|
|
42383
42458
|
const rebuildSnapshot = function (snapshot, onRebuild) {
|
|
42384
42459
|
validateNotDisposed();
|
|
@@ -42692,6 +42767,72 @@
|
|
|
42692
42767
|
});
|
|
42693
42768
|
}
|
|
42694
42769
|
|
|
42770
|
+
/**
|
|
42771
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
42772
|
+
* All rights reserved.
|
|
42773
|
+
* For full license text, see the LICENSE.txt file
|
|
42774
|
+
*/
|
|
42775
|
+
|
|
42776
|
+
const API_NAMESPACE$1 = 'UiApi';
|
|
42777
|
+
const RECORD_REPRESENTATION_NAME$2 = 'RecordRepresentation';
|
|
42778
|
+
const RECORD_VIEW_ENTITY_REPRESENTATION_NAME$1 = 'RecordViewEntityRepresentation';
|
|
42779
|
+
const RECORD_ID_PREFIX$1 = `${API_NAMESPACE$1}::${RECORD_REPRESENTATION_NAME$2}:`;
|
|
42780
|
+
const RECORD_VIEW_ENTITY_ID_PREFIX$1 = `${API_NAMESPACE$1}::${RECORD_VIEW_ENTITY_REPRESENTATION_NAME$1}:Name:`;
|
|
42781
|
+
const RECORD_FIELDS_KEY_JUNCTION$1 = '__fields__';
|
|
42782
|
+
function isStoreKeyRecordId(key) {
|
|
42783
|
+
return key.indexOf(RECORD_ID_PREFIX$1) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION$1) === -1;
|
|
42784
|
+
}
|
|
42785
|
+
function isStoreKeyRecordViewEntity$1(key) {
|
|
42786
|
+
return (key.indexOf(RECORD_VIEW_ENTITY_ID_PREFIX$1) > -1 &&
|
|
42787
|
+
key.indexOf(RECORD_FIELDS_KEY_JUNCTION$1) === -1);
|
|
42788
|
+
}
|
|
42789
|
+
function isStoreKeyRecordField(key) {
|
|
42790
|
+
return key.indexOf(RECORD_ID_PREFIX$1) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION$1) > -1;
|
|
42791
|
+
}
|
|
42792
|
+
function extractRecordIdFromStoreKey$1(key) {
|
|
42793
|
+
if (key === undefined ||
|
|
42794
|
+
(key.indexOf(RECORD_ID_PREFIX$1) === -1 && key.indexOf(RECORD_VIEW_ENTITY_ID_PREFIX$1) === -1)) {
|
|
42795
|
+
return undefined;
|
|
42796
|
+
}
|
|
42797
|
+
const parts = key.split(':');
|
|
42798
|
+
return parts[parts.length - 1].split('_')[0];
|
|
42799
|
+
}
|
|
42800
|
+
function buildRecordFieldStoreKey(recordKey, fieldName) {
|
|
42801
|
+
return `${recordKey}${RECORD_FIELDS_KEY_JUNCTION$1}${fieldName}`;
|
|
42802
|
+
}
|
|
42803
|
+
function objectsDeepEqual(lhs, rhs) {
|
|
42804
|
+
if (lhs === rhs)
|
|
42805
|
+
return true;
|
|
42806
|
+
if (typeof lhs !== 'object' || typeof rhs !== 'object' || lhs === null || rhs === null)
|
|
42807
|
+
return false;
|
|
42808
|
+
const lhsKeys = Object.keys(lhs);
|
|
42809
|
+
const rhsKeys = Object.keys(rhs);
|
|
42810
|
+
if (lhsKeys.length !== rhsKeys.length)
|
|
42811
|
+
return false;
|
|
42812
|
+
for (let key of lhsKeys) {
|
|
42813
|
+
if (!rhsKeys.includes(key))
|
|
42814
|
+
return false;
|
|
42815
|
+
if (typeof lhs[key] === 'function' || typeof rhs[key] === 'function') {
|
|
42816
|
+
if (lhs[key].toString() !== rhs[key].toString())
|
|
42817
|
+
return false;
|
|
42818
|
+
}
|
|
42819
|
+
else {
|
|
42820
|
+
if (!objectsDeepEqual(lhs[key], rhs[key]))
|
|
42821
|
+
return false;
|
|
42822
|
+
}
|
|
42823
|
+
}
|
|
42824
|
+
return true;
|
|
42825
|
+
}
|
|
42826
|
+
|
|
42827
|
+
function isStoreRecordError(storeRecord) {
|
|
42828
|
+
return storeRecord.__type === 'error';
|
|
42829
|
+
}
|
|
42830
|
+
function isEntryDurableRecordRepresentation(entry, key) {
|
|
42831
|
+
// Either a DurableRecordRepresentation or StoreRecordError can live at a record key
|
|
42832
|
+
return ((isStoreKeyRecordId(key) || isStoreKeyRecordViewEntity$1(key)) &&
|
|
42833
|
+
entry.data.__type === undefined);
|
|
42834
|
+
}
|
|
42835
|
+
|
|
42695
42836
|
/**
|
|
42696
42837
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
42697
42838
|
* All rights reserved.
|
|
@@ -43951,6 +44092,7 @@
|
|
|
43951
44092
|
'Email',
|
|
43952
44093
|
'TextArea',
|
|
43953
44094
|
'Percent',
|
|
44095
|
+
'EncryptedString',
|
|
43954
44096
|
].includes(type);
|
|
43955
44097
|
}
|
|
43956
44098
|
|
|
@@ -45431,8 +45573,12 @@
|
|
|
45431
45573
|
// If there is no metadata for this query or it somehow lacks a timestamp
|
|
45432
45574
|
// skip setting the root timestamp
|
|
45433
45575
|
if (queryMetadata !== undefined && queryMetadata.ingestionTimestamp !== undefined) {
|
|
45434
|
-
|
|
45435
|
-
|
|
45576
|
+
const timestamp = Number(queryMetadata.ingestionTimestamp);
|
|
45577
|
+
if (!isNaN(timestamp)) {
|
|
45578
|
+
// adjust the timestamp to account for ingestion processing time
|
|
45579
|
+
// 30s is used because this is the default record TTL
|
|
45580
|
+
input.rootTimestamp = timestamp - 30000;
|
|
45581
|
+
}
|
|
45436
45582
|
}
|
|
45437
45583
|
}
|
|
45438
45584
|
return recordQuery(selection, alias, apiName, [], input);
|
|
@@ -45890,7 +46036,11 @@
|
|
|
45890
46036
|
try {
|
|
45891
46037
|
const { data, seenRecords } = await queryEvaluator(rootQuery, context, eventEmitter);
|
|
45892
46038
|
const rebuildWithStoreEval = ((originalSnapshot) => {
|
|
45893
|
-
return storeEval(config, originalSnapshot, observers, connectionKeyBuilder)
|
|
46039
|
+
return storeEval(config, originalSnapshot, observers, connectionKeyBuilder).then((rebuiltSnapshot) => {
|
|
46040
|
+
return objectsDeepEqual(originalSnapshot.data, rebuiltSnapshot.data)
|
|
46041
|
+
? originalSnapshot
|
|
46042
|
+
: rebuiltSnapshot;
|
|
46043
|
+
});
|
|
45894
46044
|
});
|
|
45895
46045
|
const recordId = generateUniqueRecordId$1();
|
|
45896
46046
|
// if the non-eval'ed snapshot was an error then we return a synthetic
|
|
@@ -46241,8 +46391,12 @@
|
|
|
46241
46391
|
|
|
46242
46392
|
const HTTP_HEADER_RETRY_AFTER = 'Retry-After';
|
|
46243
46393
|
const HTTP_HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key';
|
|
46394
|
+
const ERROR_CODE_IDEMPOTENCY_FEATURE_NOT_ENABLED = 'IDEMPOTENCY_FEATURE_NOT_ENABLED';
|
|
46395
|
+
const ERROR_CODE_IDEMPOTENCY_NOT_SUPPORTED = 'IDEMPOTENCY_NOT_SUPPORTED';
|
|
46244
46396
|
const ERROR_CODE_IDEMPOTENCY_KEY_USED_DIFFERENT_USER = 'IDEMPOTENCY_KEY_USED_DIFFERENT_USER';
|
|
46245
46397
|
const ERROR_CODE_IDEMPOTENCY_CONCURRENT_REQUEST = 'IDEMPOTENCY_CONCURRENT_REQUEST';
|
|
46398
|
+
const ERROR_CODE_IDEMPOTENCY_KEY_ALREADY_USED = 'IDEMPOTENCY_KEY_ALREADY_USED';
|
|
46399
|
+
const ERROR_CODE_IDEMPOTENCY_BACKEND_OPERATION_ERROR = 'IDEMPOTENCY_BACKEND_OPERATION_ERROR';
|
|
46246
46400
|
/**
|
|
46247
46401
|
* Get the retry after in milliseconds from the response headers, undefined if not specified.
|
|
46248
46402
|
* The header could have two different format.
|
|
@@ -46272,7 +46426,9 @@
|
|
|
46272
46426
|
const dispatchResourceRequest = async function (resourceRequest, _context) {
|
|
46273
46427
|
const resourceRequestCopy = clone$1(resourceRequest);
|
|
46274
46428
|
resourceRequestCopy.headers = resourceRequestCopy.headers || {};
|
|
46275
|
-
|
|
46429
|
+
if (handler.hasIdempotencySupport()) {
|
|
46430
|
+
resourceRequestCopy.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
|
|
46431
|
+
}
|
|
46276
46432
|
// enable return extra fields for record creation and record update http call
|
|
46277
46433
|
if (resourceRequest.basePath === '/ui-api/records' &&
|
|
46278
46434
|
(resourceRequest.method === 'post' || resourceRequest.method === 'patch')) {
|
|
@@ -47094,6 +47250,12 @@
|
|
|
47094
47250
|
// the luvio store redirect table, during which a new draft might be enqueued
|
|
47095
47251
|
// which would not see a necessary mapping.
|
|
47096
47252
|
this.ephemeralRedirects = {};
|
|
47253
|
+
// determined by Server setup.
|
|
47254
|
+
this.isIdempotencySupported = true;
|
|
47255
|
+
// idempotency write flag set by lds
|
|
47256
|
+
this.isLdsIdempotencyWriteDisabled = ldsIdempotencyWriteDisabled.isOpen({
|
|
47257
|
+
fallback: false,
|
|
47258
|
+
});
|
|
47097
47259
|
}
|
|
47098
47260
|
enqueue(data) {
|
|
47099
47261
|
return this.draftQueue.enqueue(this.handlerId, data);
|
|
@@ -47123,21 +47285,43 @@
|
|
|
47123
47285
|
retryDelayInMs = getRetryAfterInMs(response.headers);
|
|
47124
47286
|
shouldRetry = true;
|
|
47125
47287
|
break;
|
|
47126
|
-
case HttpStatusCode$1.ServerError:
|
|
47288
|
+
case HttpStatusCode$1.ServerError: {
|
|
47127
47289
|
shouldRetry = true;
|
|
47290
|
+
if (this.handleIdempotencyServerError(response.body, updatedAction, false, ERROR_CODE_IDEMPOTENCY_BACKEND_OPERATION_ERROR)) {
|
|
47291
|
+
this.isIdempotencySupported = false;
|
|
47292
|
+
retryDelayInMs = 0;
|
|
47293
|
+
actionDataChanged = true;
|
|
47294
|
+
}
|
|
47128
47295
|
break;
|
|
47296
|
+
}
|
|
47129
47297
|
case 409 /* IdempotentWriteSpecificHttpStatusCode.Conflict */: {
|
|
47130
|
-
|
|
47131
|
-
|
|
47132
|
-
|
|
47133
|
-
|
|
47298
|
+
if (this.isUiApiErrors(response.body)) {
|
|
47299
|
+
const errorCode = response.body[0].errorCode;
|
|
47300
|
+
if (this.handleIdempotencyServerError(response.body, updatedAction, true, ERROR_CODE_IDEMPOTENCY_KEY_USED_DIFFERENT_USER)) {
|
|
47301
|
+
retryDelayInMs = 0;
|
|
47302
|
+
actionDataChanged = true;
|
|
47303
|
+
}
|
|
47304
|
+
else if (errorCode === ERROR_CODE_IDEMPOTENCY_CONCURRENT_REQUEST) {
|
|
47305
|
+
retryDelayInMs = getRetryAfterInMs(response.headers);
|
|
47306
|
+
}
|
|
47307
|
+
shouldRetry = true;
|
|
47308
|
+
}
|
|
47309
|
+
break;
|
|
47310
|
+
}
|
|
47311
|
+
case HttpStatusCode$1.BadRequest: {
|
|
47312
|
+
if (this.handleIdempotencyServerError(response.body, updatedAction, false, ERROR_CODE_IDEMPOTENCY_FEATURE_NOT_ENABLED, ERROR_CODE_IDEMPOTENCY_NOT_SUPPORTED)) {
|
|
47134
47313
|
retryDelayInMs = 0;
|
|
47135
47314
|
actionDataChanged = true;
|
|
47315
|
+
shouldRetry = true;
|
|
47136
47316
|
}
|
|
47137
|
-
|
|
47138
|
-
|
|
47317
|
+
break;
|
|
47318
|
+
}
|
|
47319
|
+
case 422 /* IdempotentWriteSpecificHttpStatusCode.UnProcessableEntity */: {
|
|
47320
|
+
if (this.handleIdempotencyServerError(response.body, updatedAction, true, ERROR_CODE_IDEMPOTENCY_KEY_ALREADY_USED)) {
|
|
47321
|
+
retryDelayInMs = 0;
|
|
47322
|
+
actionDataChanged = true;
|
|
47323
|
+
shouldRetry = true;
|
|
47139
47324
|
}
|
|
47140
|
-
shouldRetry = true;
|
|
47141
47325
|
break;
|
|
47142
47326
|
}
|
|
47143
47327
|
}
|
|
@@ -47156,6 +47340,27 @@
|
|
|
47156
47340
|
return ProcessActionResult.NETWORK_ERROR;
|
|
47157
47341
|
}
|
|
47158
47342
|
}
|
|
47343
|
+
// true if response is an idempotency server error. updates or deletes idempotency key if the reponse is idempotency related error. Idempotency related error is in format of UiApiError array.
|
|
47344
|
+
handleIdempotencyServerError(responseBody, action, updateIdempotencyKey, ...targetErrorCodes) {
|
|
47345
|
+
if (this.isUiApiErrors(responseBody)) {
|
|
47346
|
+
const errorCode = responseBody[0].errorCode;
|
|
47347
|
+
if (targetErrorCodes.includes(errorCode)) {
|
|
47348
|
+
action.data.headers = action.data.headers || {};
|
|
47349
|
+
if (updateIdempotencyKey) {
|
|
47350
|
+
action.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
|
|
47351
|
+
}
|
|
47352
|
+
else {
|
|
47353
|
+
delete action.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY];
|
|
47354
|
+
}
|
|
47355
|
+
return true;
|
|
47356
|
+
}
|
|
47357
|
+
}
|
|
47358
|
+
return false;
|
|
47359
|
+
}
|
|
47360
|
+
// checks if the body is an array of UiApiError. Sometimes the body has `enhancedErrorType` field as an error indicator(one example is the field validation failure). In such case Action being processed updates to an Error Action.
|
|
47361
|
+
isUiApiErrors(body) {
|
|
47362
|
+
return body !== undefined && Array.isArray(body) && body.length > 0 && body[0].errorCode;
|
|
47363
|
+
}
|
|
47159
47364
|
async buildPendingAction(request, queue) {
|
|
47160
47365
|
const targetId = await this.getIdFromRequest(request);
|
|
47161
47366
|
if (targetId === undefined) {
|
|
@@ -47369,6 +47574,10 @@
|
|
|
47369
47574
|
...targetData,
|
|
47370
47575
|
body: this.mergeRequestBody(targetBody, sourceBody),
|
|
47371
47576
|
};
|
|
47577
|
+
// Updates Idempotency key if target has one
|
|
47578
|
+
if (targetData.headers && targetData.headers[HTTP_HEADER_IDEMPOTENCY_KEY]) {
|
|
47579
|
+
merged.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
|
|
47580
|
+
}
|
|
47372
47581
|
// overlay metadata
|
|
47373
47582
|
merged.metadata = { ...targetMetadata, ...sourceMetadata };
|
|
47374
47583
|
// put status back to pending to auto upload if queue is active and targed is at the head.
|
|
@@ -47405,6 +47614,9 @@
|
|
|
47405
47614
|
getDraftIdsFromAction(action) {
|
|
47406
47615
|
return [action.targetId];
|
|
47407
47616
|
}
|
|
47617
|
+
hasIdempotencySupport() {
|
|
47618
|
+
return this.isIdempotencySupported && !this.isLdsIdempotencyWriteDisabled;
|
|
47619
|
+
}
|
|
47408
47620
|
async ingestResponses(responses, action) {
|
|
47409
47621
|
const luvio = this.getLuvio();
|
|
47410
47622
|
await luvio.handleSuccessResponse(() => {
|
|
@@ -47836,49 +48048,6 @@
|
|
|
47836
48048
|
});
|
|
47837
48049
|
}
|
|
47838
48050
|
|
|
47839
|
-
/**
|
|
47840
|
-
* Copyright (c) 2022, Salesforce, Inc.,
|
|
47841
|
-
* All rights reserved.
|
|
47842
|
-
* For full license text, see the LICENSE.txt file
|
|
47843
|
-
*/
|
|
47844
|
-
|
|
47845
|
-
const API_NAMESPACE$1 = 'UiApi';
|
|
47846
|
-
const RECORD_REPRESENTATION_NAME$2 = 'RecordRepresentation';
|
|
47847
|
-
const RECORD_VIEW_ENTITY_REPRESENTATION_NAME$1 = 'RecordViewEntityRepresentation';
|
|
47848
|
-
const RECORD_ID_PREFIX$1 = `${API_NAMESPACE$1}::${RECORD_REPRESENTATION_NAME$2}:`;
|
|
47849
|
-
const RECORD_VIEW_ENTITY_ID_PREFIX$1 = `${API_NAMESPACE$1}::${RECORD_VIEW_ENTITY_REPRESENTATION_NAME$1}:Name:`;
|
|
47850
|
-
const RECORD_FIELDS_KEY_JUNCTION$1 = '__fields__';
|
|
47851
|
-
function isStoreKeyRecordId(key) {
|
|
47852
|
-
return key.indexOf(RECORD_ID_PREFIX$1) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION$1) === -1;
|
|
47853
|
-
}
|
|
47854
|
-
function isStoreKeyRecordViewEntity$1(key) {
|
|
47855
|
-
return (key.indexOf(RECORD_VIEW_ENTITY_ID_PREFIX$1) > -1 &&
|
|
47856
|
-
key.indexOf(RECORD_FIELDS_KEY_JUNCTION$1) === -1);
|
|
47857
|
-
}
|
|
47858
|
-
function isStoreKeyRecordField(key) {
|
|
47859
|
-
return key.indexOf(RECORD_ID_PREFIX$1) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION$1) > -1;
|
|
47860
|
-
}
|
|
47861
|
-
function extractRecordIdFromStoreKey$1(key) {
|
|
47862
|
-
if (key === undefined ||
|
|
47863
|
-
(key.indexOf(RECORD_ID_PREFIX$1) === -1 && key.indexOf(RECORD_VIEW_ENTITY_ID_PREFIX$1) === -1)) {
|
|
47864
|
-
return undefined;
|
|
47865
|
-
}
|
|
47866
|
-
const parts = key.split(':');
|
|
47867
|
-
return parts[parts.length - 1].split('_')[0];
|
|
47868
|
-
}
|
|
47869
|
-
function buildRecordFieldStoreKey(recordKey, fieldName) {
|
|
47870
|
-
return `${recordKey}${RECORD_FIELDS_KEY_JUNCTION$1}${fieldName}`;
|
|
47871
|
-
}
|
|
47872
|
-
|
|
47873
|
-
function isStoreRecordError(storeRecord) {
|
|
47874
|
-
return storeRecord.__type === 'error';
|
|
47875
|
-
}
|
|
47876
|
-
function isEntryDurableRecordRepresentation(entry, key) {
|
|
47877
|
-
// Either a DurableRecordRepresentation or StoreRecordError can live at a record key
|
|
47878
|
-
return ((isStoreKeyRecordId(key) || isStoreKeyRecordViewEntity$1(key)) &&
|
|
47879
|
-
entry.data.__type === undefined);
|
|
47880
|
-
}
|
|
47881
|
-
|
|
47882
48051
|
function serializeFieldArguments$1(argumentNodes, variables) {
|
|
47883
48052
|
const mutableArgumentNodes = Object.assign([], argumentNodes);
|
|
47884
48053
|
return `args__(${mutableArgumentNodes
|
|
@@ -49253,6 +49422,10 @@
|
|
|
49253
49422
|
return node.kind === 'OperationDefinition';
|
|
49254
49423
|
}
|
|
49255
49424
|
|
|
49425
|
+
const POLYMORPHIC_PARENT_RELATIONSHIP = 'polymorphicParentRelationship';
|
|
49426
|
+
const PARENT_RELATIONSHIP = 'parentRelationship';
|
|
49427
|
+
const CHILD_RELATIONSHIP = 'childRelationship';
|
|
49428
|
+
const RECORD_QUERY = 'recordQuery';
|
|
49256
49429
|
function requestsDraftsField(recordFieldNode) {
|
|
49257
49430
|
if (!recordFieldNode.selectionSet)
|
|
49258
49431
|
return false;
|
|
@@ -49268,18 +49441,41 @@
|
|
|
49268
49441
|
directive.arguments
|
|
49269
49442
|
.map((argument) => argument.value)
|
|
49270
49443
|
.filter(isStringValueNode)
|
|
49271
|
-
.some((categoryName) => categoryName.value ===
|
|
49444
|
+
.some((categoryName) => categoryName.value === RECORD_QUERY));
|
|
49272
49445
|
});
|
|
49273
49446
|
}
|
|
49274
49447
|
return false;
|
|
49275
49448
|
}
|
|
49276
|
-
// finds field with 'recordQuery' and 'childRelationship' directive
|
|
49277
|
-
function
|
|
49278
|
-
const
|
|
49279
|
-
return
|
|
49449
|
+
// finds connection field with 'recordQuery' and 'childRelationship' directive.
|
|
49450
|
+
function findNearestConnection(ancestors) {
|
|
49451
|
+
const connectionAncestor = findNearestAncesterPath(ancestors, true).node;
|
|
49452
|
+
return connectionAncestor === undefined ? undefined : connectionAncestor;
|
|
49453
|
+
}
|
|
49454
|
+
// convinient method to find nearest connection with its path
|
|
49455
|
+
function findNearestConnectionWithPath(ancestors) {
|
|
49456
|
+
const closestAncestorPath = findNearestAncesterPath(ancestors, true);
|
|
49457
|
+
let connection = undefined;
|
|
49458
|
+
let connectionPath = undefined;
|
|
49459
|
+
if (closestAncestorPath.parentIndex > 0) {
|
|
49460
|
+
const connectionAncestor = closestAncestorPath.node;
|
|
49461
|
+
const connectionAncestors = ancestors.slice(0, closestAncestorPath.parentIndex);
|
|
49462
|
+
connection =
|
|
49463
|
+
connectionAncestor === undefined ? undefined : connectionAncestor;
|
|
49464
|
+
if (connection !== undefined) {
|
|
49465
|
+
const ancesterPath = findAncesterPath(connectionAncestors);
|
|
49466
|
+
connectionPath =
|
|
49467
|
+
ancesterPath === ''
|
|
49468
|
+
? connection.name.value
|
|
49469
|
+
: `${ancesterPath}#${connection.name.value}`;
|
|
49470
|
+
}
|
|
49471
|
+
}
|
|
49472
|
+
return {
|
|
49473
|
+
connection,
|
|
49474
|
+
path: connectionPath,
|
|
49475
|
+
};
|
|
49280
49476
|
}
|
|
49281
|
-
// finds
|
|
49282
|
-
function findNearestAncesterPath(ancestors,
|
|
49477
|
+
// 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.
|
|
49478
|
+
function findNearestAncesterPath(ancestors, connectionOnly) {
|
|
49283
49479
|
let recordQueryPath = { node: undefined, parentIndex: -1 };
|
|
49284
49480
|
let relationship = '';
|
|
49285
49481
|
for (let i = ancestors.length - 1; i >= 0; i--) {
|
|
@@ -49293,9 +49489,11 @@
|
|
|
49293
49489
|
continue;
|
|
49294
49490
|
for (let arg of directive.arguments) {
|
|
49295
49491
|
if (arg.value &&
|
|
49296
|
-
(arg.value.value ===
|
|
49297
|
-
arg.value.value ===
|
|
49298
|
-
(!
|
|
49492
|
+
(arg.value.value === RECORD_QUERY ||
|
|
49493
|
+
arg.value.value === CHILD_RELATIONSHIP ||
|
|
49494
|
+
(!connectionOnly &&
|
|
49495
|
+
(arg.value.value === PARENT_RELATIONSHIP ||
|
|
49496
|
+
arg.value.value === POLYMORPHIC_PARENT_RELATIONSHIP)))) {
|
|
49299
49497
|
recordQueryPath = { node: node, parentIndex: i };
|
|
49300
49498
|
relationship = arg.value.value;
|
|
49301
49499
|
break;
|
|
@@ -49310,17 +49508,19 @@
|
|
|
49310
49508
|
//checks if nearest ancester could be an inline fragment
|
|
49311
49509
|
if (recordQueryPath.node !== undefined &&
|
|
49312
49510
|
recordQueryPath.node.selectionSet &&
|
|
49313
|
-
relationship ===
|
|
49314
|
-
//
|
|
49315
|
-
|
|
49316
|
-
|
|
49317
|
-
|
|
49318
|
-
if (
|
|
49511
|
+
(relationship === PARENT_RELATIONSHIP || relationship === POLYMORPHIC_PARENT_RELATIONSHIP)) {
|
|
49512
|
+
// InlineFragment is usually 3 steps aways from its FieldNode parent within ancester hierarchy if it exists. The below search
|
|
49513
|
+
// is applied to adapt to future AST structure change
|
|
49514
|
+
let parentIndex = recordQueryPath.parentIndex + 1;
|
|
49515
|
+
while (parentIndex < ancestors.length) {
|
|
49516
|
+
if (isInlineFragmentNode(ancestors[parentIndex])) {
|
|
49319
49517
|
recordQueryPath = {
|
|
49320
|
-
node: ancestors[
|
|
49321
|
-
parentIndex
|
|
49518
|
+
node: ancestors[parentIndex],
|
|
49519
|
+
parentIndex,
|
|
49322
49520
|
};
|
|
49521
|
+
break;
|
|
49323
49522
|
}
|
|
49523
|
+
parentIndex++;
|
|
49324
49524
|
}
|
|
49325
49525
|
}
|
|
49326
49526
|
return recordQueryPath;
|
|
@@ -49344,7 +49544,7 @@
|
|
|
49344
49544
|
? sectionPath
|
|
49345
49545
|
: sectionPath === ''
|
|
49346
49546
|
? path
|
|
49347
|
-
: `${sectionPath}
|
|
49547
|
+
: `${sectionPath}#${path}`;
|
|
49348
49548
|
}
|
|
49349
49549
|
}
|
|
49350
49550
|
boundaryIndex = parentIndex;
|
|
@@ -49402,9 +49602,9 @@
|
|
|
49402
49602
|
const relationships = args
|
|
49403
49603
|
.map((arg) => arg.value)
|
|
49404
49604
|
.filter(isStringValueNode)
|
|
49405
|
-
.filter((valueNode) => valueNode.value ===
|
|
49406
|
-
valueNode.value ===
|
|
49407
|
-
valueNode.value ===
|
|
49605
|
+
.filter((valueNode) => valueNode.value === CHILD_RELATIONSHIP ||
|
|
49606
|
+
valueNode.value === PARENT_RELATIONSHIP ||
|
|
49607
|
+
valueNode.value === POLYMORPHIC_PARENT_RELATIONSHIP)
|
|
49408
49608
|
.map((relationshipNode) => relationshipNode.value);
|
|
49409
49609
|
if (relationships.length > 0) {
|
|
49410
49610
|
return relationships[0];
|
|
@@ -49461,8 +49661,8 @@
|
|
|
49461
49661
|
*/
|
|
49462
49662
|
function isParentRelationship(node) {
|
|
49463
49663
|
return (node &&
|
|
49464
|
-
(isRelationship(node,
|
|
49465
|
-
isRelationship(node,
|
|
49664
|
+
(isRelationship(node, PARENT_RELATIONSHIP) ||
|
|
49665
|
+
isRelationship(node, POLYMORPHIC_PARENT_RELATIONSHIP)));
|
|
49466
49666
|
}
|
|
49467
49667
|
/*
|
|
49468
49668
|
checks if the InlineFragment spans
|
|
@@ -49768,6 +49968,26 @@
|
|
|
49768
49968
|
return values$1(objectInfo.fields).find((field) => field.apiName === fieldName ||
|
|
49769
49969
|
(field.dataType === 'Reference' && field.relationshipName === fieldName));
|
|
49770
49970
|
}
|
|
49971
|
+
async function readIngestionTimestampForKey(key, query) {
|
|
49972
|
+
let ingestionTimestamp = 0;
|
|
49973
|
+
const sql = `
|
|
49974
|
+
SELECT json_extract(metadata, '${JSON_EXTRACT_PATH_INGESTION_TIMESTAMP}')
|
|
49975
|
+
FROM lds_data
|
|
49976
|
+
WHERE key IS ?
|
|
49977
|
+
`;
|
|
49978
|
+
const results = await query(sql, [key]);
|
|
49979
|
+
const [timestamp] = results.rows.map((row) => row[0]);
|
|
49980
|
+
if (timestamp !== null) {
|
|
49981
|
+
const numericalTimestamp = Number(timestamp);
|
|
49982
|
+
if (isNaN(numericalTimestamp)) {
|
|
49983
|
+
return ingestionTimestamp;
|
|
49984
|
+
}
|
|
49985
|
+
// adjust the timestamp to account for ingestion processing time
|
|
49986
|
+
// 30s is used because this is the default record TTL
|
|
49987
|
+
ingestionTimestamp = numericalTimestamp - 30000;
|
|
49988
|
+
}
|
|
49989
|
+
return ingestionTimestamp;
|
|
49990
|
+
}
|
|
49771
49991
|
|
|
49772
49992
|
function findSpanningField(name) {
|
|
49773
49993
|
return (field) => {
|
|
@@ -50287,17 +50507,7 @@
|
|
|
50287
50507
|
const key = buildKeyStringForRecordQuery(operation,
|
|
50288
50508
|
// join varables passed from query to the argument variables given from the AST
|
|
50289
50509
|
{ ...variableValues, ...args }, info.fieldNodes[0].arguments, apiName);
|
|
50290
|
-
|
|
50291
|
-
SELECT json_extract(metadata, '${JSON_EXTRACT_PATH_INGESTION_TIMESTAMP}')
|
|
50292
|
-
FROM lds_data
|
|
50293
|
-
WHERE key IS ?
|
|
50294
|
-
`;
|
|
50295
|
-
const results = await query(sql, [key]);
|
|
50296
|
-
const [timestamp] = results.rows.map((row) => row[0]);
|
|
50297
|
-
if (timestamp !== null && typeof timestamp === 'number') {
|
|
50298
|
-
//go back 10 ms to adjust for margin of error when top level query is stored and when raml objects are stored
|
|
50299
|
-
ingestionTimestamp = timestamp - 10;
|
|
50300
|
-
}
|
|
50510
|
+
return readIngestionTimestampForKey(key, query);
|
|
50301
50511
|
}
|
|
50302
50512
|
return ingestionTimestamp;
|
|
50303
50513
|
}
|
|
@@ -50345,26 +50555,20 @@
|
|
|
50345
50555
|
let recordConnections = ``;
|
|
50346
50556
|
const polymorphicFieldTypeNames = new Set();
|
|
50347
50557
|
let typedScalars = new Set();
|
|
50558
|
+
let parentRelationshipFields = new Set();
|
|
50348
50559
|
for (const objectInfo of values$1(objectInfos)) {
|
|
50349
50560
|
const { apiName, childRelationships } = objectInfo;
|
|
50350
50561
|
let fields = ``;
|
|
50351
50562
|
typedScalars.add(`${apiName}_Filter`);
|
|
50352
50563
|
typedScalars.add(`${apiName}_OrderBy`);
|
|
50353
|
-
for (const childRelationship of childRelationships) {
|
|
50354
|
-
const { childObjectApiName } = childRelationship;
|
|
50355
|
-
// Only add the relationship if there is relevant objectinfos for it,
|
|
50356
|
-
// otherwise we'd be defining types we cannot satisfy and aren't referenced in
|
|
50357
|
-
// the query.
|
|
50358
|
-
if (objectInfos[childObjectApiName] !== undefined) {
|
|
50359
|
-
fields += `${childRelationship.relationshipName}(first: Int, where: ${childObjectApiName}_Filter, orderBy: ${childObjectApiName}_OrderBy, scope: SupportedScopes): ${childObjectApiName}Connection \n`;
|
|
50360
|
-
typedScalars.add(`${childObjectApiName}_Filter`);
|
|
50361
|
-
typedScalars.add(`${childObjectApiName}_OrderBy`);
|
|
50362
|
-
}
|
|
50363
|
-
}
|
|
50364
50564
|
for (const field of values$1(objectInfo.fields)) {
|
|
50365
50565
|
if (!fieldsStaticallyAdded.includes(field.apiName)) {
|
|
50366
50566
|
fields += `${field.apiName}: ${dataTypeToType(field.dataType, field.apiName)}\n`;
|
|
50367
50567
|
}
|
|
50568
|
+
//handles parent relationship
|
|
50569
|
+
if (field.relationshipName === null) {
|
|
50570
|
+
continue;
|
|
50571
|
+
}
|
|
50368
50572
|
// For spanning parent relationships with no union types
|
|
50369
50573
|
if (field.referenceToInfos.length === 1) {
|
|
50370
50574
|
const [relation] = field.referenceToInfos;
|
|
@@ -50372,11 +50576,13 @@
|
|
|
50372
50576
|
// otherwise we'd be defining types we cannot satisfy and aren't referenced in
|
|
50373
50577
|
// the query.
|
|
50374
50578
|
if (objectInfos[relation.apiName] !== undefined) {
|
|
50579
|
+
parentRelationshipFields.add(field.relationshipName);
|
|
50375
50580
|
fields += `${field.relationshipName}: ${relation.apiName}\n`;
|
|
50376
50581
|
}
|
|
50377
50582
|
// For polymorphic field, its type is 'Record' inteface. The concrete entity type name is saved for field resolving of next phase
|
|
50378
50583
|
}
|
|
50379
50584
|
else if (field.referenceToInfos.length > 1) {
|
|
50585
|
+
parentRelationshipFields.add(field.relationshipName);
|
|
50380
50586
|
fields += `${field.relationshipName}: Record\n`;
|
|
50381
50587
|
for (const relation of field.referenceToInfos) {
|
|
50382
50588
|
if (objectInfos[relation.apiName] !== undefined) {
|
|
@@ -50385,6 +50591,20 @@
|
|
|
50385
50591
|
}
|
|
50386
50592
|
}
|
|
50387
50593
|
}
|
|
50594
|
+
// handles child relationship
|
|
50595
|
+
for (const childRelationship of childRelationships) {
|
|
50596
|
+
const { childObjectApiName } = childRelationship;
|
|
50597
|
+
// Only add the relationship if there is relevant objectinfos for it,
|
|
50598
|
+
// otherwise we'd be defining types we cannot satisfy and aren't referenced in
|
|
50599
|
+
// the query.
|
|
50600
|
+
// If one field has both parent relationship and child relationship with the same name, the child relationship is ignored. This is how the server GQL has implemented as date of 08/07/2023
|
|
50601
|
+
if (objectInfos[childObjectApiName] !== undefined &&
|
|
50602
|
+
!parentRelationshipFields.has(childRelationship.relationshipName)) {
|
|
50603
|
+
fields += `${childRelationship.relationshipName}(first: Int, where: ${childObjectApiName}_Filter, orderBy: ${childObjectApiName}_OrderBy, scope: SupportedScopes): ${childObjectApiName}Connection \n`;
|
|
50604
|
+
typedScalars.add(`${childObjectApiName}_Filter`);
|
|
50605
|
+
typedScalars.add(`${childObjectApiName}_OrderBy`);
|
|
50606
|
+
}
|
|
50607
|
+
}
|
|
50388
50608
|
recordQueries += `${apiName}(first: Int, where: ${apiName}_Filter, orderBy: ${apiName}_OrderBy, scope: SupportedScopes): ${apiName}Connection\n`;
|
|
50389
50609
|
const isServiceAppointment = apiName === 'ServiceAppointment';
|
|
50390
50610
|
recordConnections += /* GraphQL */ `
|
|
@@ -50459,6 +50679,8 @@
|
|
|
50459
50679
|
return 'PercentValue';
|
|
50460
50680
|
case 'Int':
|
|
50461
50681
|
return 'IntValue';
|
|
50682
|
+
case 'EncryptedString':
|
|
50683
|
+
return 'EncryptedStringValue';
|
|
50462
50684
|
// ! do the rest of the custom types
|
|
50463
50685
|
default:
|
|
50464
50686
|
return 'String';
|
|
@@ -50544,7 +50766,7 @@
|
|
|
50544
50766
|
},
|
|
50545
50767
|
value: {
|
|
50546
50768
|
kind: Kind.STRING,
|
|
50547
|
-
value:
|
|
50769
|
+
value: PARENT_RELATIONSHIP,
|
|
50548
50770
|
block: false,
|
|
50549
50771
|
},
|
|
50550
50772
|
},
|
|
@@ -50558,8 +50780,8 @@
|
|
|
50558
50780
|
// example 2 'ServiceAppointment' -> ['Owner']; 'Owner' -> ['User', 'Group']
|
|
50559
50781
|
const objectNodeInfoTree = {};
|
|
50560
50782
|
// save the field path to apiName map
|
|
50561
|
-
// example 1: 'ServiceAppointment' -> ['ServiceAppointment']; '
|
|
50562
|
-
const
|
|
50783
|
+
// example 1: 'ServiceAppointment' -> ['ServiceAppointment']; 'ServiceAppointment#ccount' -> ['Account']; 'ServiceAppointment#Account#Owner' -> ['User']
|
|
50784
|
+
const pathToObjectApiNamesMap = {};
|
|
50563
50785
|
let startNodes = new Set();
|
|
50564
50786
|
let totalNodes = new Set();
|
|
50565
50787
|
let objectInfos = {};
|
|
@@ -50573,11 +50795,11 @@
|
|
|
50573
50795
|
visit(originalAST, {
|
|
50574
50796
|
Argument: {
|
|
50575
50797
|
enter(node, key, parent, path, ancestors) {
|
|
50576
|
-
const
|
|
50577
|
-
if (!
|
|
50798
|
+
const { connection: recordConnectionNode, path: ancesterPath } = findNearestConnectionWithPath(ancestors);
|
|
50799
|
+
if (!recordConnectionNode || !ancesterPath)
|
|
50578
50800
|
return;
|
|
50579
|
-
if (!objectNodeInfoTree[
|
|
50580
|
-
objectNodeInfoTree[
|
|
50801
|
+
if (!objectNodeInfoTree[ancesterPath]) {
|
|
50802
|
+
objectNodeInfoTree[ancesterPath] = [];
|
|
50581
50803
|
}
|
|
50582
50804
|
switch (node.name.value) {
|
|
50583
50805
|
case 'orderBy':
|
|
@@ -50585,12 +50807,12 @@
|
|
|
50585
50807
|
if (node.value.kind !== 'ObjectValue') {
|
|
50586
50808
|
return;
|
|
50587
50809
|
}
|
|
50588
|
-
totalNodes.add(
|
|
50810
|
+
totalNodes.add(ancesterPath);
|
|
50589
50811
|
// 'childRelationship' node is not taken as the startNode of the 'NodeInfoTree' graph. The field scanning will construct the graph which lead here.
|
|
50590
|
-
if (isRecordQuery(
|
|
50591
|
-
startNodes.add(
|
|
50812
|
+
if (isRecordQuery(recordConnectionNode)) {
|
|
50813
|
+
startNodes.add(recordConnectionNode.name.value);
|
|
50592
50814
|
}
|
|
50593
|
-
growObjectFieldTree(objectNodeInfoTree,
|
|
50815
|
+
growObjectFieldTree(objectNodeInfoTree, ancesterPath, node.value, totalNodes, startNodes);
|
|
50594
50816
|
break;
|
|
50595
50817
|
case 'scope':
|
|
50596
50818
|
if (!isScopeArgumentNodeWithType(node, 'ASSIGNEDTOME', variables)) {
|
|
@@ -50605,17 +50827,16 @@
|
|
|
50605
50827
|
name: 'ServiceResources',
|
|
50606
50828
|
});
|
|
50607
50829
|
}
|
|
50608
|
-
if (objectNodeInfoTree['ServiceResources'] === undefined) {
|
|
50609
|
-
objectNodeInfoTree['ServiceResources'] = [
|
|
50610
|
-
|
|
50611
|
-
|
|
50612
|
-
|
|
50613
|
-
|
|
50614
|
-
|
|
50615
|
-
});
|
|
50830
|
+
if (objectNodeInfoTree['ServiceAppointment#ServiceResources'] === undefined) {
|
|
50831
|
+
objectNodeInfoTree['ServiceAppointment#ServiceResources'] = [
|
|
50832
|
+
{
|
|
50833
|
+
relation: 'parent',
|
|
50834
|
+
name: 'ServiceResource',
|
|
50835
|
+
},
|
|
50836
|
+
];
|
|
50616
50837
|
}
|
|
50617
|
-
if (objectNodeInfoTree['ServiceResource'] === undefined) {
|
|
50618
|
-
objectNodeInfoTree['ServiceResource'] = [];
|
|
50838
|
+
if (objectNodeInfoTree['ServiceAppointment#ServiceResources#ServiceResource'] === undefined) {
|
|
50839
|
+
objectNodeInfoTree['ServiceAppointment#ServiceResources#ServiceResource'] = [];
|
|
50619
50840
|
}
|
|
50620
50841
|
break;
|
|
50621
50842
|
default:
|
|
@@ -50629,7 +50850,7 @@
|
|
|
50629
50850
|
return;
|
|
50630
50851
|
if (!node.selectionSet)
|
|
50631
50852
|
return;
|
|
50632
|
-
const recordQueryField =
|
|
50853
|
+
const recordQueryField = findNearestConnection(ancestors);
|
|
50633
50854
|
//only injects fields for 'recordQuery' field. ignores the 'childRelationship' field since it will be traversed as the child of the 'recordQuery'
|
|
50634
50855
|
if (isRecordQuery(recordQueryField) && recordQueryField) {
|
|
50635
50856
|
totalNodes.add(recordQueryField.name.value);
|
|
@@ -50640,21 +50861,21 @@
|
|
|
50640
50861
|
},
|
|
50641
50862
|
});
|
|
50642
50863
|
if (objectInfoService && startNodes.size > 0) {
|
|
50643
|
-
objectInfos = await resolveObjectInfos(objectNodeInfoTree,
|
|
50864
|
+
objectInfos = await resolveObjectInfos(objectNodeInfoTree, pathToObjectApiNamesMap, startNodes, objectInfoService);
|
|
50644
50865
|
}
|
|
50645
50866
|
// read pass; gather whats needed
|
|
50646
50867
|
visit(originalAST, {
|
|
50647
50868
|
Argument: {
|
|
50648
50869
|
leave(node, key, parent, path, ancestors) {
|
|
50649
|
-
const recordQueryField =
|
|
50870
|
+
const recordQueryField = findNearestConnection(ancestors);
|
|
50650
50871
|
if (!recordQueryField)
|
|
50651
50872
|
return;
|
|
50652
50873
|
const ancestorPath = findAncesterPath(ancestors);
|
|
50653
50874
|
if (!inlineFragmentSelections[ancestorPath]) {
|
|
50654
50875
|
inlineFragmentSelections[ancestorPath] = [];
|
|
50655
50876
|
}
|
|
50656
|
-
const recordQueryApiName =
|
|
50657
|
-
?
|
|
50877
|
+
const recordQueryApiName = pathToObjectApiNamesMap[ancestorPath]
|
|
50878
|
+
? pathToObjectApiNamesMap[ancestorPath][0]
|
|
50658
50879
|
: recordQueryField.name.value;
|
|
50659
50880
|
// The record node acts as the reference. The duplicated field in the record node is not injected
|
|
50660
50881
|
const recordReferenceNode = [recordQueryField]
|
|
@@ -50668,7 +50889,7 @@
|
|
|
50668
50889
|
case 'scope':
|
|
50669
50890
|
// Hanle 'MINE' field
|
|
50670
50891
|
if (isScopeArgumentNodeWithType(node, 'MINE', variables)) {
|
|
50671
|
-
if (isMineScopeAvailable(ancestorPath,
|
|
50892
|
+
if (isMineScopeAvailable(ancestorPath, pathToObjectApiNamesMap, objectInfos)) {
|
|
50672
50893
|
// 'typeConditon' is added when the 'InlineFragmentNode' is appended at the write pass
|
|
50673
50894
|
inlineFragmentSelections[ancestorPath].push(...mineFragmentSelections);
|
|
50674
50895
|
}
|
|
@@ -50694,7 +50915,7 @@
|
|
|
50694
50915
|
case 'where': {
|
|
50695
50916
|
inlineFragmentSelections[ancestorPath] = [
|
|
50696
50917
|
...inlineFragmentSelections[ancestorPath],
|
|
50697
|
-
...injectFilter(node, idState, ancestorPath, objectInfos,
|
|
50918
|
+
...injectFilter(node, idState, ancestorPath, false, objectInfos, pathToObjectApiNamesMap, draftFunctions, recordReferenceNode),
|
|
50698
50919
|
];
|
|
50699
50920
|
break;
|
|
50700
50921
|
}
|
|
@@ -50710,7 +50931,7 @@
|
|
|
50710
50931
|
if (!node.selectionSet)
|
|
50711
50932
|
return;
|
|
50712
50933
|
// it could be 'recordQuery' or 'childRelationship'
|
|
50713
|
-
const recordQueryField =
|
|
50934
|
+
const recordQueryField = findNearestConnection(ancestors);
|
|
50714
50935
|
if (!recordQueryField)
|
|
50715
50936
|
return;
|
|
50716
50937
|
const ancestorPath = findAncesterPath(ancestors);
|
|
@@ -50722,7 +50943,7 @@
|
|
|
50722
50943
|
spanningSelections.push(selection);
|
|
50723
50944
|
}
|
|
50724
50945
|
}
|
|
50725
|
-
const injectedFields = injectFields(spanningSelections, node, ancestors, objectInfos,
|
|
50946
|
+
const injectedFields = injectFields(spanningSelections, node, ancestorPath, ancestors, objectInfos, pathToObjectApiNamesMap);
|
|
50726
50947
|
const mergedInjectedFields = mergeSelectionNodes$1(inlineFragmentSelections[ancestorPath], injectedFields);
|
|
50727
50948
|
inlineFragmentSelections[ancestorPath] = mergedInjectedFields;
|
|
50728
50949
|
},
|
|
@@ -50735,7 +50956,7 @@
|
|
|
50735
50956
|
// removes 'ServicesResources' query field node if 'assignedtome' scope shows up
|
|
50736
50957
|
if (assignedtomeQueryFieldNode !== undefined &&
|
|
50737
50958
|
node.name.value === 'ServiceResources') {
|
|
50738
|
-
const serviceResourcesAncestor =
|
|
50959
|
+
const serviceResourcesAncestor = findNearestConnection(ancestors);
|
|
50739
50960
|
if (serviceResourcesAncestor === assignedtomeQueryFieldNode) {
|
|
50740
50961
|
return null;
|
|
50741
50962
|
}
|
|
@@ -50744,7 +50965,7 @@
|
|
|
50744
50965
|
return;
|
|
50745
50966
|
if (!node.selectionSet)
|
|
50746
50967
|
return;
|
|
50747
|
-
const recordQueryField =
|
|
50968
|
+
const recordQueryField = findNearestConnection(ancestors);
|
|
50748
50969
|
if (!recordQueryField)
|
|
50749
50970
|
return;
|
|
50750
50971
|
const ancestorPath = findAncesterPath(ancestors);
|
|
@@ -50753,8 +50974,8 @@
|
|
|
50753
50974
|
return;
|
|
50754
50975
|
//const recordQueryPath = findAncesterPath(ancestors);
|
|
50755
50976
|
// '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.
|
|
50756
|
-
const recordQueryApiName =
|
|
50757
|
-
?
|
|
50977
|
+
const recordQueryApiName = pathToObjectApiNamesMap[ancestorPath]
|
|
50978
|
+
? pathToObjectApiNamesMap[ancestorPath][0]
|
|
50758
50979
|
: recordQueryField.name.value;
|
|
50759
50980
|
const nodeWithFragments = {
|
|
50760
50981
|
...node,
|
|
@@ -50791,7 +51012,7 @@
|
|
|
50791
51012
|
if (node.name.value === 'where') {
|
|
50792
51013
|
const ancestorPath = findAncesterPath(ancestors);
|
|
50793
51014
|
if (idState.paths.includes(ancestorPath)) {
|
|
50794
|
-
const apiName =
|
|
51015
|
+
const apiName = pathToObjectApiNamesMap[ancestorPath][0];
|
|
50795
51016
|
const objectInfo = objectInfos[apiName];
|
|
50796
51017
|
const swappedIdFilter = swapIdField(node.value, objectInfo, false, idState, draftFunctions);
|
|
50797
51018
|
return {
|
|
@@ -50857,8 +51078,8 @@
|
|
|
50857
51078
|
};
|
|
50858
51079
|
}
|
|
50859
51080
|
}
|
|
50860
|
-
function isMineScopeAvailable(apiNamePath,
|
|
50861
|
-
const apiName =
|
|
51081
|
+
function isMineScopeAvailable(apiNamePath, pathToObjectApiNamesMap, objectInfos) {
|
|
51082
|
+
const apiName = pathToObjectApiNamesMap[apiNamePath];
|
|
50862
51083
|
if (!apiName)
|
|
50863
51084
|
return false;
|
|
50864
51085
|
const objectInfo = objectInfos[apiName[0]];
|
|
@@ -50947,15 +51168,16 @@
|
|
|
50947
51168
|
}
|
|
50948
51169
|
// example: 'Account'
|
|
50949
51170
|
const childNode = objectFieldNode.name.value;
|
|
51171
|
+
const childNodepath = `${parentNode}#${childNode}`;
|
|
50950
51172
|
if (!tree[parentNode].some((child) => child.name === childNode)) {
|
|
50951
51173
|
tree[parentNode].push({
|
|
50952
51174
|
relation: 'parent',
|
|
50953
51175
|
name: childNode,
|
|
50954
51176
|
});
|
|
50955
|
-
totalNodes.add(
|
|
51177
|
+
totalNodes.add(childNodepath);
|
|
50956
51178
|
}
|
|
50957
51179
|
// recursively go to deeper level of filter.
|
|
50958
|
-
growObjectFieldTree(tree,
|
|
51180
|
+
growObjectFieldTree(tree, childNodepath, objectFieldNode.value, totalNodes, startNodes);
|
|
50959
51181
|
}
|
|
50960
51182
|
}
|
|
50961
51183
|
}
|
|
@@ -50990,19 +51212,20 @@
|
|
|
50990
51212
|
}
|
|
50991
51213
|
if (!tree[parentSectionPath].some((field) => field.name === fieldName)) {
|
|
50992
51214
|
tree[parentSectionPath].push({
|
|
50993
|
-
relation: relationType ===
|
|
50994
|
-
relationType ===
|
|
51215
|
+
relation: relationType === PARENT_RELATIONSHIP ||
|
|
51216
|
+
relationType === POLYMORPHIC_PARENT_RELATIONSHIP
|
|
50995
51217
|
? 'parent'
|
|
50996
51218
|
: 'child',
|
|
50997
51219
|
name: fieldName,
|
|
50998
51220
|
});
|
|
50999
|
-
totalNodes.add(fieldName);
|
|
51221
|
+
totalNodes.add(`${parentSectionPath}#${fieldName}`);
|
|
51000
51222
|
}
|
|
51001
51223
|
if (entryNode.selectionSet && entryNode.selectionSet.selections) {
|
|
51002
51224
|
const childNodes = entryNode.selectionSet.selections.filter(isFieldOrInlineFragmentNode);
|
|
51003
51225
|
// recursively build the traversal tree
|
|
51004
51226
|
for (const child of childNodes) {
|
|
51005
|
-
|
|
51227
|
+
const path = `${parentSectionPath}#${fieldName}`;
|
|
51228
|
+
growFieldTree(tree, path, child, entryNode, totalNodes, startNodes);
|
|
51006
51229
|
}
|
|
51007
51230
|
}
|
|
51008
51231
|
}
|
|
@@ -51032,23 +51255,23 @@
|
|
|
51032
51255
|
}
|
|
51033
51256
|
if (!tree[parentSectionPath].some((field) => field.name === conditionName)) {
|
|
51034
51257
|
tree[parentSectionPath].push({
|
|
51035
|
-
relation: relationType ===
|
|
51036
|
-
relationType ===
|
|
51258
|
+
relation: relationType === PARENT_RELATIONSHIP ||
|
|
51259
|
+
relationType === POLYMORPHIC_PARENT_RELATIONSHIP
|
|
51037
51260
|
? 'parent'
|
|
51038
51261
|
: 'child',
|
|
51039
51262
|
name: conditionName,
|
|
51040
51263
|
});
|
|
51041
|
-
|
|
51264
|
+
const path = `${parentSectionPath}#${conditionName}`;
|
|
51265
|
+
totalNodes.add(path);
|
|
51042
51266
|
}
|
|
51043
51267
|
}
|
|
51044
51268
|
}
|
|
51045
51269
|
// dive deep immediately for 'InlineFragment'
|
|
51046
51270
|
const childNodes = entryNode.selectionSet.selections.filter(isFieldOrInlineFragmentNode);
|
|
51271
|
+
const path = `${parentSectionPath}${entryNode.typeCondition ? '#' + entryNode.typeCondition.name.value : ''}`;
|
|
51047
51272
|
// Navigates into InLineFragment
|
|
51048
51273
|
for (const child of childNodes) {
|
|
51049
|
-
growFieldTree(tree, entryNode
|
|
51050
|
-
? entryNode.typeCondition.name.value
|
|
51051
|
-
: parentSectionPath, child, entryNode, totalNodes, startNodes);
|
|
51274
|
+
growFieldTree(tree, path, child, entryNode, totalNodes, startNodes);
|
|
51052
51275
|
}
|
|
51053
51276
|
}
|
|
51054
51277
|
}
|
|
@@ -51060,7 +51283,7 @@
|
|
|
51060
51283
|
* @param startNodes start nodes of the tree. It can be used to fetch ObjectInfo immediately
|
|
51061
51284
|
* @param path
|
|
51062
51285
|
*/
|
|
51063
|
-
async function resolveObjectInfos(objectInfotree,
|
|
51286
|
+
async function resolveObjectInfos(objectInfotree, pathToObjectApiNamesMap, startNodes, objectInfoService) {
|
|
51064
51287
|
let objectInfos;
|
|
51065
51288
|
try {
|
|
51066
51289
|
objectInfos = await objectInfoService.getObjectInfos(Array.from(startNodes));
|
|
@@ -51074,9 +51297,9 @@
|
|
|
51074
51297
|
throw new Error(`Unable to resolve ObjectInfo(s) for ${Array.from(startNodes)}`);
|
|
51075
51298
|
}
|
|
51076
51299
|
for (const startNode of startNodes) {
|
|
51077
|
-
|
|
51300
|
+
pathToObjectApiNamesMap[startNode] = [startNode];
|
|
51078
51301
|
const children = objectInfotree[startNode];
|
|
51079
|
-
const subObjectInfoMap = await fetchObjectInfos(objectInfotree,
|
|
51302
|
+
const subObjectInfoMap = await fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, objectInfos, children, startNode, objectInfoService);
|
|
51080
51303
|
objectInfos = { ...objectInfos, ...subObjectInfoMap };
|
|
51081
51304
|
}
|
|
51082
51305
|
return objectInfos;
|
|
@@ -51084,15 +51307,15 @@
|
|
|
51084
51307
|
// example 1: 'parentPath': 'ServiceAppointment', 'nodesAtSameLevel': ['Account']
|
|
51085
51308
|
// example 2: 'parentPath': 'ServiceAppointment', 'nodesAtSameLevel': ['Owner'], this example has 2 apiName for the node 'Owner'
|
|
51086
51309
|
// example 3: 'parentPath': 'ServiceAppointment_Owner', 'nodesAtSameLevel': ['User', 'Group']
|
|
51087
|
-
async function fetchObjectInfos(objectInfotree,
|
|
51088
|
-
const objectInfoApiNames =
|
|
51310
|
+
async function fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, objectInfoMap, nodesAtSameLevel, parentPath, objectInfoService) {
|
|
51311
|
+
const objectInfoApiNames = pathToObjectApiNamesMap[parentPath];
|
|
51089
51312
|
if (!objectInfoApiNames) {
|
|
51090
51313
|
// eslint-disable-next-line
|
|
51091
51314
|
throw new Error(`Object Info does not exist for ${parentPath}`);
|
|
51092
51315
|
}
|
|
51093
51316
|
const validObjectInfoNodes = [];
|
|
51094
51317
|
let updatedObjectInfoMap = {};
|
|
51095
|
-
// InlineFragment and polymorphic field support fits into this scenario
|
|
51318
|
+
// InlineFragment and polymorphic field support fits into this scenario pathToObjectApiNamesMap Entry: 'ServiceAppointment#Owner' -> ['User', 'Group']; ServiceAppointment#Owner#User' -> ['User']
|
|
51096
51319
|
if (objectInfoApiNames.length > 0 &&
|
|
51097
51320
|
nodesAtSameLevel.length > 0 &&
|
|
51098
51321
|
objectInfoApiNames.includes(nodesAtSameLevel[0].name)) {
|
|
@@ -51104,8 +51327,8 @@
|
|
|
51104
51327
|
// eslint-disable-next-line
|
|
51105
51328
|
throw new Error(`Condition ${field.name} does not exists for ${parentPath}`);
|
|
51106
51329
|
}
|
|
51107
|
-
const path = `${parentPath}
|
|
51108
|
-
|
|
51330
|
+
const path = `${parentPath}#${field.name}`;
|
|
51331
|
+
pathToObjectApiNamesMap[path] = [field.name];
|
|
51109
51332
|
}
|
|
51110
51333
|
validObjectInfoNodes.push(...nodesAtSameLevel);
|
|
51111
51334
|
updatedObjectInfoMap = { ...objectInfoMap };
|
|
@@ -51120,7 +51343,7 @@
|
|
|
51120
51343
|
let apiNames = [];
|
|
51121
51344
|
for (const nodeInfo of nodesAtSameLevel) {
|
|
51122
51345
|
const field = nodeInfo.name;
|
|
51123
|
-
const path = `${parentPath}
|
|
51346
|
+
const path = `${parentPath}#${field}`;
|
|
51124
51347
|
// Handle 'parentRelationship'
|
|
51125
51348
|
if (nodeInfo.relation === 'parent') {
|
|
51126
51349
|
const relationshipId = referenceIdFieldForRelationship(field);
|
|
@@ -51138,21 +51361,21 @@
|
|
|
51138
51361
|
}
|
|
51139
51362
|
}
|
|
51140
51363
|
// This is a polymorphic field
|
|
51141
|
-
if (fieldDefinition.referenceToInfos.length > 1 && objectInfotree[
|
|
51364
|
+
if (fieldDefinition.referenceToInfos.length > 1 && objectInfotree[path]) {
|
|
51142
51365
|
// Fields needs to expand and heterogenous entity ObjectInfo needs to be fetched
|
|
51143
|
-
const referencedNodeInfos = objectInfotree[
|
|
51366
|
+
const referencedNodeInfos = objectInfotree[path];
|
|
51144
51367
|
const requestedApiNames = referencedNodeInfos.map((referenceNodeInfo) => referenceNodeInfo.name);
|
|
51145
51368
|
// 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.
|
|
51146
|
-
if (requestedApiNames.length > 0 && objectInfotree[
|
|
51369
|
+
if (requestedApiNames.length > 0 && objectInfotree[path]) {
|
|
51147
51370
|
fieldDefinition.referenceToInfos
|
|
51148
51371
|
.filter((referenceToInfo) => requestedApiNames.includes(referenceToInfo.apiName))
|
|
51149
51372
|
.forEach((ref) => {
|
|
51150
|
-
if (!
|
|
51151
|
-
|
|
51373
|
+
if (!pathToObjectApiNamesMap[path]) {
|
|
51374
|
+
pathToObjectApiNamesMap[path] = [];
|
|
51152
51375
|
}
|
|
51153
51376
|
// 'ServiceAppointment_Owner' ->['User', 'Group']
|
|
51154
|
-
if (!
|
|
51155
|
-
|
|
51377
|
+
if (!pathToObjectApiNamesMap[path].includes(ref.apiName)) {
|
|
51378
|
+
pathToObjectApiNamesMap[path].push(ref.apiName);
|
|
51156
51379
|
}
|
|
51157
51380
|
if (!apiNames.includes(ref.apiName)) {
|
|
51158
51381
|
apiNames.push(ref.apiName);
|
|
@@ -51162,11 +51385,11 @@
|
|
|
51162
51385
|
}
|
|
51163
51386
|
else if (fieldDefinition.referenceToInfos.length === 1) {
|
|
51164
51387
|
const ref = fieldDefinition.referenceToInfos[0];
|
|
51165
|
-
if (!
|
|
51166
|
-
|
|
51388
|
+
if (!pathToObjectApiNamesMap[path]) {
|
|
51389
|
+
pathToObjectApiNamesMap[path] = [];
|
|
51167
51390
|
}
|
|
51168
|
-
if (!
|
|
51169
|
-
|
|
51391
|
+
if (!pathToObjectApiNamesMap[path].includes(ref.apiName)) {
|
|
51392
|
+
pathToObjectApiNamesMap[path].push(ref.apiName);
|
|
51170
51393
|
}
|
|
51171
51394
|
if (!apiNames.includes(ref.apiName)) {
|
|
51172
51395
|
apiNames.push(ref.apiName);
|
|
@@ -51177,11 +51400,11 @@
|
|
|
51177
51400
|
// handles 'childRelationship'
|
|
51178
51401
|
const childRelationship = parentObjectInfo.childRelationships.find((childRelationship) => childRelationship.relationshipName === field);
|
|
51179
51402
|
if (childRelationship) {
|
|
51180
|
-
if (!
|
|
51181
|
-
|
|
51403
|
+
if (!pathToObjectApiNamesMap[path]) {
|
|
51404
|
+
pathToObjectApiNamesMap[path] = [];
|
|
51182
51405
|
}
|
|
51183
|
-
if (!
|
|
51184
|
-
|
|
51406
|
+
if (!pathToObjectApiNamesMap[path].includes(childRelationship.childObjectApiName)) {
|
|
51407
|
+
pathToObjectApiNamesMap[path].push(childRelationship.childObjectApiName);
|
|
51185
51408
|
}
|
|
51186
51409
|
if (!apiNames.includes(childRelationship.childObjectApiName)) {
|
|
51187
51410
|
apiNames.push(childRelationship.childObjectApiName);
|
|
@@ -51203,10 +51426,10 @@
|
|
|
51203
51426
|
}
|
|
51204
51427
|
for (const nodeInfo of validObjectInfoNodes) {
|
|
51205
51428
|
const field = nodeInfo.name;
|
|
51206
|
-
const
|
|
51207
|
-
const
|
|
51429
|
+
const path = `${parentPath}#${field}`;
|
|
51430
|
+
const subLevelFields = objectInfotree[path];
|
|
51208
51431
|
if (subLevelFields && subLevelFields.length > 0) {
|
|
51209
|
-
const subObjectInfos = await fetchObjectInfos(objectInfotree,
|
|
51432
|
+
const subObjectInfos = await fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, updatedObjectInfoMap, subLevelFields, path, objectInfoService);
|
|
51210
51433
|
updatedObjectInfoMap = { ...updatedObjectInfoMap, ...subObjectInfos };
|
|
51211
51434
|
}
|
|
51212
51435
|
}
|
|
@@ -51221,27 +51444,29 @@
|
|
|
51221
51444
|
* 'path' and 'queryNode' is 1 level above the 'filterNode'
|
|
51222
51445
|
* @param filterNode filter node which needs to be injected. For example, 'State' ObjectFieldNode within filter 'where: { State: { eq: "Nova Scotia" }}'
|
|
51223
51446
|
* @param idState ID state will be updated to determine if the ID fields in AST need to be swapped. The swapping happens later.
|
|
51224
|
-
* @param
|
|
51447
|
+
* @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
|
|
51448
|
+
* @param isParentPolymorphic true if parent points to a polymorphic field.
|
|
51225
51449
|
* @param queryNode referece FieldNode which provides the information if 'filterNode' exist in it nor not.
|
|
51226
51450
|
* @param objectInfos ObjectInfo map used in injection. If ObjectInfo misses or field does not exist in ObjectInfo, the error will be thrown
|
|
51227
|
-
* @param
|
|
51451
|
+
* @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'].
|
|
51228
51452
|
* @param draftFunctions functions for working with record ids that may be draft-created ids
|
|
51229
51453
|
* @returns an array of nodes with injected fields
|
|
51230
51454
|
*/
|
|
51231
|
-
function injectFilter(filterNode, idState,
|
|
51455
|
+
function injectFilter(filterNode, idState, parentPath, isParentPolymorphic, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode) {
|
|
51232
51456
|
const injectedSelections = [];
|
|
51457
|
+
let isPolymorphicField = false;
|
|
51233
51458
|
switch (filterNode.kind) {
|
|
51234
51459
|
case Kind.ARGUMENT:
|
|
51235
51460
|
if (filterNode.value.kind !== 'ObjectValue')
|
|
51236
51461
|
return [];
|
|
51237
51462
|
filterNode.value.fields.forEach((objectFieldNode) => {
|
|
51238
|
-
let subResults = injectFilter(objectFieldNode, idState,
|
|
51463
|
+
let subResults = injectFilter(objectFieldNode, idState, parentPath, isParentPolymorphic, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode);
|
|
51239
51464
|
for (const subResult of subResults) {
|
|
51240
51465
|
mergeOrAddToGroup(injectedSelections, subResult);
|
|
51241
51466
|
}
|
|
51242
51467
|
// multiple Ids might need to be swapped. remember their paths for faster write.
|
|
51243
51468
|
if (idState.swapNeeded) {
|
|
51244
|
-
idState.paths.push(
|
|
51469
|
+
idState.paths.push(parentPath);
|
|
51245
51470
|
}
|
|
51246
51471
|
});
|
|
51247
51472
|
return injectedSelections;
|
|
@@ -51250,7 +51475,7 @@
|
|
|
51250
51475
|
case Kind.LIST: {
|
|
51251
51476
|
filterNode.value.values.filter(isObjectValueNode).forEach((objectValueNode) => {
|
|
51252
51477
|
objectValueNode.fields.forEach((objectFieldNode) => {
|
|
51253
|
-
const subResults = injectFilter(objectFieldNode, idState,
|
|
51478
|
+
const subResults = injectFilter(objectFieldNode, idState, parentPath, isParentPolymorphic, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode);
|
|
51254
51479
|
for (const subResult of subResults) {
|
|
51255
51480
|
mergeOrAddToGroup(injectedSelections, subResult);
|
|
51256
51481
|
}
|
|
@@ -51261,7 +51486,7 @@
|
|
|
51261
51486
|
case Kind.OBJECT: {
|
|
51262
51487
|
if (filterNode.name.value === 'not') {
|
|
51263
51488
|
filterNode.value.fields.forEach((objectFieldNode) => {
|
|
51264
|
-
const subResults = injectFilter(objectFieldNode, idState,
|
|
51489
|
+
const subResults = injectFilter(objectFieldNode, idState, parentPath, isParentPolymorphic, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode);
|
|
51265
51490
|
for (const subResult of subResults) {
|
|
51266
51491
|
mergeOrAddToGroup(injectedSelections, subResult);
|
|
51267
51492
|
}
|
|
@@ -51271,15 +51496,15 @@
|
|
|
51271
51496
|
let apiNames = [];
|
|
51272
51497
|
let isScalarField = false;
|
|
51273
51498
|
//It is possible that this is a polymorphic field
|
|
51274
|
-
apiNames =
|
|
51275
|
-
// example: path: '
|
|
51499
|
+
apiNames = pathToObjectApiNamesMap[parentPath];
|
|
51500
|
+
// example: path: 'ServiceAppointment#LastModifiedDate'; filterNode: '{eq: {literal: LAST_WEEK}}'. queryNode: 'LastModifedDate { value}' FilterNode's parent has been verifed as a valid node
|
|
51276
51501
|
if (apiNames === undefined) {
|
|
51277
51502
|
isScalarField = true;
|
|
51278
51503
|
}
|
|
51279
51504
|
else {
|
|
51280
51505
|
if (apiNames.some((apiName) => objectInfos[apiName] === undefined)) {
|
|
51281
51506
|
// eslint-disable-next-line
|
|
51282
|
-
throw new Error(`ObjectInfo is missing for ${
|
|
51507
|
+
throw new Error(`ObjectInfo is missing for ${parentPath}`);
|
|
51283
51508
|
}
|
|
51284
51509
|
}
|
|
51285
51510
|
if (isScalarField) {
|
|
@@ -51301,29 +51526,19 @@
|
|
|
51301
51526
|
}
|
|
51302
51527
|
});
|
|
51303
51528
|
let isSpanning = false;
|
|
51529
|
+
// if true, current node is a polymorphic concrete type node. For example, field node `User` under `Owner`
|
|
51304
51530
|
let isInlineFragment = false;
|
|
51305
|
-
let isPolymorphicField = false;
|
|
51306
51531
|
let isTypeNameExisting = false;
|
|
51307
51532
|
let curPath;
|
|
51308
51533
|
let fieldName = filterNode.name.value;
|
|
51309
|
-
curPath = `${
|
|
51310
|
-
if (
|
|
51534
|
+
curPath = `${parentPath}#${fieldName}`;
|
|
51535
|
+
if (pathToObjectApiNamesMap[curPath] &&
|
|
51536
|
+
pathToObjectApiNamesMap[curPath].length > 0) {
|
|
51311
51537
|
isSpanning = true;
|
|
51312
|
-
|
|
51313
|
-
|
|
51314
|
-
|
|
51315
|
-
|
|
51316
|
-
isInlineFragment = true;
|
|
51317
|
-
}
|
|
51318
|
-
}
|
|
51319
|
-
// Checks if the current filter node is a polymorphic field. 'ServiceAppointment_Owner' --> ['User']; 'ServiceAppointment_Owner_User' --> ['User']
|
|
51320
|
-
const childApiName = objectInfoApiMap[curPath][0];
|
|
51321
|
-
const trialApiNames = objectInfoApiMap[`${curPath}_${childApiName}`];
|
|
51322
|
-
if (trialApiNames !== undefined &&
|
|
51323
|
-
trialApiNames.length === 1 &&
|
|
51324
|
-
trialApiNames[0] === childApiName) {
|
|
51325
|
-
isPolymorphicField = true;
|
|
51326
|
-
}
|
|
51538
|
+
isInlineFragment =
|
|
51539
|
+
isParentPolymorphic &&
|
|
51540
|
+
pathToObjectApiNamesMap[curPath].length === 1;
|
|
51541
|
+
isPolymorphicField = isPolymorphicFieldPath(curPath, pathToObjectApiNamesMap, objectInfos);
|
|
51327
51542
|
}
|
|
51328
51543
|
// 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]
|
|
51329
51544
|
if (isInlineFragment) {
|
|
@@ -51367,23 +51582,25 @@
|
|
|
51367
51582
|
throw new Error(`Field ${fieldName} does not exist in ${apiNames[0]}`);
|
|
51368
51583
|
}
|
|
51369
51584
|
}
|
|
51370
|
-
const objectInfoName =
|
|
51371
|
-
?
|
|
51372
|
-
:
|
|
51585
|
+
const objectInfoName = pathToObjectApiNamesMap[curPath] !== undefined
|
|
51586
|
+
? pathToObjectApiNamesMap[curPath][0]
|
|
51587
|
+
: pathToObjectApiNamesMap[parentPath][0];
|
|
51373
51588
|
const isIdField = isFieldAnIdField(filterNode.name.value, objectInfos[objectInfoName]);
|
|
51374
51589
|
if (!isIdField) {
|
|
51375
51590
|
let subSelectionNodes = [];
|
|
51376
51591
|
let subFieldsHasId = false;
|
|
51377
|
-
|
|
51378
|
-
|
|
51379
|
-
|
|
51380
|
-
|
|
51381
|
-
|
|
51382
|
-
|
|
51383
|
-
|
|
51384
|
-
|
|
51385
|
-
|
|
51386
|
-
|
|
51592
|
+
if (isSpanning) {
|
|
51593
|
+
filterNode.value.fields.forEach((subFieldNode) => {
|
|
51594
|
+
// Check if the filter field has the 'Id'
|
|
51595
|
+
if (isFieldAnIdField(subFieldNode.name.value, objectInfos[objectInfoName])) {
|
|
51596
|
+
subFieldsHasId = true;
|
|
51597
|
+
updateIDInfo(subFieldNode, idState, draftFunctions);
|
|
51598
|
+
}
|
|
51599
|
+
// try injecting the fields within predicate no matter it has relation or not.
|
|
51600
|
+
let subResults = injectFilter(subFieldNode, idState, curPath, isPolymorphicField, objectInfos, pathToObjectApiNamesMap, draftFunctions, existingFields ? existingFields[0] : undefined);
|
|
51601
|
+
subSelectionNodes = subSelectionNodes.concat(subResults);
|
|
51602
|
+
});
|
|
51603
|
+
}
|
|
51387
51604
|
if (!subFieldsHasId) {
|
|
51388
51605
|
// Check if the query field has the 'Id'
|
|
51389
51606
|
const existingIdsInQuery = existingFields &&
|
|
@@ -51412,6 +51629,7 @@
|
|
|
51412
51629
|
}
|
|
51413
51630
|
//Inject Conditions: 1. Same field does not exist 2. Same fields has different children. 3. Filter spanning field does not have Id. 4. InLineFragment does not have the '__typename' field
|
|
51414
51631
|
if (!existingFields ||
|
|
51632
|
+
existingFields.length === 0 ||
|
|
51415
51633
|
subSelectionNodes.length > 0 ||
|
|
51416
51634
|
(isSpanning && !subFieldsHasId) ||
|
|
51417
51635
|
(isInlineFragment && !isTypeNameExisting)) {
|
|
@@ -51542,6 +51760,44 @@
|
|
|
51542
51760
|
}
|
|
51543
51761
|
group.push(element);
|
|
51544
51762
|
}
|
|
51763
|
+
// checks if the path points to a polymorphic field. For example, for the below `pathToObjectApiNamesMap`
|
|
51764
|
+
// {
|
|
51765
|
+
// 'ServiceAppointment' -> ['ServiceAppointment']
|
|
51766
|
+
// 'ServiceAppointment#Owner' --> ['User'],
|
|
51767
|
+
// 'ServiceAppointment#Owner#User' --> ['User']
|
|
51768
|
+
// }
|
|
51769
|
+
// path `ServiceAppointment#Owner` points to a polymorphic field, but path `ServiceAppointment#Owner#User` does not.
|
|
51770
|
+
function isPolymorphicFieldPath(path, pathToObjectApiNamesMap, objectInfos) {
|
|
51771
|
+
const lastSegmentIndex = path.lastIndexOf('#');
|
|
51772
|
+
if (lastSegmentIndex < 0) {
|
|
51773
|
+
return false;
|
|
51774
|
+
}
|
|
51775
|
+
const lastSegment = path.slice(lastSegmentIndex + 1);
|
|
51776
|
+
const parentApiPath = path.slice(0, lastSegmentIndex);
|
|
51777
|
+
if (pathToObjectApiNamesMap[parentApiPath] === undefined) {
|
|
51778
|
+
return false;
|
|
51779
|
+
}
|
|
51780
|
+
const parentObjectApiNames = pathToObjectApiNamesMap[parentApiPath];
|
|
51781
|
+
// 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`.
|
|
51782
|
+
// 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.
|
|
51783
|
+
// Below are the entries in `pathToObjectApiNamesMap`
|
|
51784
|
+
// {
|
|
51785
|
+
// `ServiceAppointmen`t: [`ServiceAppointment`],
|
|
51786
|
+
// `ServiceAppointment#Owner`: [`User`, `Group`],
|
|
51787
|
+
// `ServiceAppointment#Owner#User`: [`User`],
|
|
51788
|
+
// `ServiceAppointment#Owner#Group`: [`Group`],
|
|
51789
|
+
// }
|
|
51790
|
+
if (parentObjectApiNames.length !== 1) {
|
|
51791
|
+
return false;
|
|
51792
|
+
}
|
|
51793
|
+
const parentObjectInfo = objectInfos[parentObjectApiNames[0]];
|
|
51794
|
+
const relationshipField = referenceIdFieldForRelationship(lastSegment);
|
|
51795
|
+
let fieldDefinition = parentObjectInfo.fields[relationshipField];
|
|
51796
|
+
if (fieldDefinition === undefined) {
|
|
51797
|
+
return false;
|
|
51798
|
+
}
|
|
51799
|
+
return fieldDefinition.polymorphicForeignKey;
|
|
51800
|
+
}
|
|
51545
51801
|
function isFieldAnIdField(fieldName, objectInfo) {
|
|
51546
51802
|
if (fieldName === 'Id')
|
|
51547
51803
|
return true;
|
|
@@ -51594,10 +51850,10 @@
|
|
|
51594
51850
|
* @param parentNode parent node of param 1
|
|
51595
51851
|
* @param ancestors ancester of param 1
|
|
51596
51852
|
* @param objectInfos ObjectInfo map used in injection. If ObjectInfo misses or field does not exist in ObjectInfo, the error will be thrown
|
|
51597
|
-
* @param
|
|
51853
|
+
* @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'].
|
|
51598
51854
|
* @return injected SelectionNodes used to construct the InlineFragment.
|
|
51599
51855
|
*/
|
|
51600
|
-
function injectFields(selections, parentNode, ancestors, objectInfos,
|
|
51856
|
+
function injectFields(selections, parentNode, parentPath, ancestors, objectInfos, pathToObjectApiNamesMap) {
|
|
51601
51857
|
/**
|
|
51602
51858
|
* 1 parentship can return 2 FieldNode which need to be flattened
|
|
51603
51859
|
* Concact: { ** Contact { ** ContactId {
|
|
@@ -51615,6 +51871,10 @@
|
|
|
51615
51871
|
if (!selection.selectionSet) {
|
|
51616
51872
|
return selection;
|
|
51617
51873
|
}
|
|
51874
|
+
const segment = isFieldNode(selection)
|
|
51875
|
+
? selection.name.value
|
|
51876
|
+
: selection.typeCondition.name.value;
|
|
51877
|
+
const curPath = `${parentPath}#${segment}`;
|
|
51618
51878
|
const spanningSubSelections = [];
|
|
51619
51879
|
for (const subSelection of selection.selectionSet.selections) {
|
|
51620
51880
|
if (isFieldSpanning(subSelection, selection)) {
|
|
@@ -51622,7 +51882,7 @@
|
|
|
51622
51882
|
}
|
|
51623
51883
|
}
|
|
51624
51884
|
// Handles multiple level field injection like 'ServiceAppointment' --> 'Account' --> 'Owner'
|
|
51625
|
-
const subInjectedSelections = injectFields(spanningSubSelections, selection, ancestors, objectInfos,
|
|
51885
|
+
const subInjectedSelections = injectFields(spanningSubSelections, selection, curPath, ancestors, objectInfos, pathToObjectApiNamesMap);
|
|
51626
51886
|
if (!selection.selectionSet) {
|
|
51627
51887
|
return selection;
|
|
51628
51888
|
}
|
|
@@ -51665,7 +51925,7 @@
|
|
|
51665
51925
|
}
|
|
51666
51926
|
}
|
|
51667
51927
|
// For polymorphic fields, the Id field is excluded.
|
|
51668
|
-
const excludeId =
|
|
51928
|
+
const excludeId = isPolymorphicFieldPath(curPath, pathToObjectApiNamesMap, objectInfos);
|
|
51669
51929
|
const idSelection = [];
|
|
51670
51930
|
if (!excludeId && !hasIdAlready) {
|
|
51671
51931
|
idSelection.push({
|
|
@@ -51676,8 +51936,8 @@
|
|
|
51676
51936
|
},
|
|
51677
51937
|
});
|
|
51678
51938
|
}
|
|
51679
|
-
// Inject '__typename' for
|
|
51680
|
-
// please reference 'removeSyntheticFields'.
|
|
51939
|
+
// 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
|
|
51940
|
+
// `typedCondition` of the InlineFragment in the query AST. It is used to match JSON response with AST node. For more detail, please reference 'removeSyntheticFields'.
|
|
51681
51941
|
if (isInlineFragmentNode(selection) &&
|
|
51682
51942
|
!selection.selectionSet.selections.find((selection) => isFieldNode(selection) && selection.name.value === '__typename')) {
|
|
51683
51943
|
idSelection.push({
|
|
@@ -51711,7 +51971,7 @@
|
|
|
51711
51971
|
if (isFieldNode(parentNode) && parentNode.selectionSet && parentNode.name.value === 'node') {
|
|
51712
51972
|
if (parentNode.selectionSet.selections
|
|
51713
51973
|
.filter(isFieldOrInlineFragmentNode)
|
|
51714
|
-
.some((selectionNode) => isRelationship(selectionNode,
|
|
51974
|
+
.some((selectionNode) => isRelationship(selectionNode, CHILD_RELATIONSHIP))) {
|
|
51715
51975
|
if (!parentNode.selectionSet.selections
|
|
51716
51976
|
.filter(isFieldNode)
|
|
51717
51977
|
.some((sibling) => sibling.name.value === 'Id')) {
|
|
@@ -51730,15 +51990,15 @@
|
|
|
51730
51990
|
if (parentInfo.parentIndex >= 0) {
|
|
51731
51991
|
// example node { TimeSheetEntries { edges { node { Id }}}}
|
|
51732
51992
|
const parent = parentInfo.node;
|
|
51733
|
-
if (isRelationship(parent,
|
|
51993
|
+
if (isRelationship(parent, CHILD_RELATIONSHIP)) {
|
|
51734
51994
|
const unVisitedAncestors = ancestors.slice(0, parentInfo.parentIndex);
|
|
51735
51995
|
// path : "TimeSheet"
|
|
51736
51996
|
const grandParentPath = findAncesterPath(unVisitedAncestors);
|
|
51737
|
-
if (
|
|
51738
|
-
|
|
51997
|
+
if (pathToObjectApiNamesMap &&
|
|
51998
|
+
pathToObjectApiNamesMap[grandParentPath] &&
|
|
51739
51999
|
objectInfos &&
|
|
51740
|
-
objectInfos[
|
|
51741
|
-
const grandParentObjectInfo = objectInfos[
|
|
52000
|
+
objectInfos[pathToObjectApiNamesMap[grandParentPath][0]]) {
|
|
52001
|
+
const grandParentObjectInfo = objectInfos[pathToObjectApiNamesMap[grandParentPath][0]];
|
|
51742
52002
|
// exmaple "TimeSheetEntries"
|
|
51743
52003
|
const parentFieldName = parent.name.value;
|
|
51744
52004
|
const targetRelationship = grandParentObjectInfo.childRelationships.find((childRelationship) => {
|
|
@@ -51859,7 +52119,7 @@
|
|
|
51859
52119
|
},
|
|
51860
52120
|
value: {
|
|
51861
52121
|
kind: 'StringValue',
|
|
51862
|
-
value:
|
|
52122
|
+
value: CHILD_RELATIONSHIP,
|
|
51863
52123
|
block: false,
|
|
51864
52124
|
},
|
|
51865
52125
|
},
|
|
@@ -51951,7 +52211,7 @@
|
|
|
51951
52211
|
},
|
|
51952
52212
|
value: {
|
|
51953
52213
|
kind: 'StringValue',
|
|
51954
|
-
value:
|
|
52214
|
+
value: PARENT_RELATIONSHIP,
|
|
51955
52215
|
block: false,
|
|
51956
52216
|
},
|
|
51957
52217
|
},
|
|
@@ -52088,7 +52348,9 @@
|
|
|
52088
52348
|
jsonOutput[fieldName] = null;
|
|
52089
52349
|
return;
|
|
52090
52350
|
}
|
|
52091
|
-
jsonOutput[fieldName]
|
|
52351
|
+
if (jsonOutput[fieldName] === undefined) {
|
|
52352
|
+
jsonOutput[fieldName] = {};
|
|
52353
|
+
}
|
|
52092
52354
|
createUserJsonOutput(selection, jsonInput[fieldName], jsonOutput[fieldName]);
|
|
52093
52355
|
}
|
|
52094
52356
|
else {
|
|
@@ -52820,34 +53082,42 @@
|
|
|
52820
53082
|
}
|
|
52821
53083
|
const { dataType, relationshipName, referenceToInfos } = fieldInfo;
|
|
52822
53084
|
const draftFieldValue = record.fields[draftField].value;
|
|
52823
|
-
if (dataType === 'Reference' && relationshipName !== null
|
|
52824
|
-
if (
|
|
52825
|
-
|
|
53085
|
+
if (dataType === 'Reference' && relationshipName !== null) {
|
|
53086
|
+
if (draftFieldValue === null) {
|
|
53087
|
+
recordFields[relationshipName] = {
|
|
53088
|
+
displayValue: null,
|
|
53089
|
+
value: null,
|
|
53090
|
+
};
|
|
52826
53091
|
}
|
|
52827
|
-
|
|
52828
|
-
|
|
52829
|
-
|
|
52830
|
-
displayValue: null,
|
|
52831
|
-
value: createLink$2(key),
|
|
52832
|
-
};
|
|
52833
|
-
// for custom objects, we select the 'Name' field
|
|
52834
|
-
// otherwise we check the object info for name fields.
|
|
52835
|
-
//if there are multiple we select 'Name' if it exists, otherwise the first one
|
|
52836
|
-
if (referencedRecord !== undefined && referenceToInfos.length > 0) {
|
|
52837
|
-
let nameField;
|
|
52838
|
-
const referenceToInfo = referenceToInfos[0];
|
|
52839
|
-
const nameFields = referenceToInfo.nameFields;
|
|
52840
|
-
if (nameFields.length !== 0) {
|
|
52841
|
-
nameField = nameFields.find((x) => x === 'Name');
|
|
52842
|
-
if (nameField === undefined) {
|
|
52843
|
-
nameField = nameFields[0];
|
|
52844
|
-
}
|
|
53092
|
+
else {
|
|
53093
|
+
if (typeof draftFieldValue !== 'string') {
|
|
53094
|
+
throw Error('reference field value is not a string');
|
|
52845
53095
|
}
|
|
52846
|
-
|
|
52847
|
-
|
|
52848
|
-
|
|
52849
|
-
|
|
52850
|
-
|
|
53096
|
+
const key = getRecordKeyForId(luvio, draftFieldValue);
|
|
53097
|
+
const referencedRecord = referencedRecords.get(key);
|
|
53098
|
+
recordFields[relationshipName] = {
|
|
53099
|
+
displayValue: null,
|
|
53100
|
+
value: createLink$2(key),
|
|
53101
|
+
};
|
|
53102
|
+
// for custom objects, we select the 'Name' field
|
|
53103
|
+
// otherwise we check the object info for name fields.
|
|
53104
|
+
//if there are multiple we select 'Name' if it exists, otherwise the first one
|
|
53105
|
+
if (referencedRecord !== undefined && referenceToInfos.length > 0) {
|
|
53106
|
+
let nameField;
|
|
53107
|
+
const referenceToInfo = referenceToInfos[0];
|
|
53108
|
+
const nameFields = referenceToInfo.nameFields;
|
|
53109
|
+
if (nameFields.length !== 0) {
|
|
53110
|
+
nameField = nameFields.find((x) => x === 'Name');
|
|
53111
|
+
if (nameField === undefined) {
|
|
53112
|
+
nameField = nameFields[0];
|
|
53113
|
+
}
|
|
53114
|
+
}
|
|
53115
|
+
if (nameField !== undefined) {
|
|
53116
|
+
const nameFieldRef = referencedRecord.fields[nameField];
|
|
53117
|
+
if (nameFieldRef) {
|
|
53118
|
+
recordFields[relationshipName].displayValue =
|
|
53119
|
+
(_a = nameFieldRef.displayValue) !== null && _a !== void 0 ? _a : nameFieldRef.value;
|
|
53120
|
+
}
|
|
52851
53121
|
}
|
|
52852
53122
|
}
|
|
52853
53123
|
}
|
|
@@ -53140,17 +53410,8 @@
|
|
|
53140
53410
|
};
|
|
53141
53411
|
for (const fieldName of keys$3(recordWithSpanningRefLinks.fields)) {
|
|
53142
53412
|
const fieldKey = buildRecordFieldStoreKey(key, fieldName);
|
|
53143
|
-
|
|
53144
|
-
|
|
53145
|
-
normalizedRecord.fields[fieldName] = { __ref: fieldKey };
|
|
53146
|
-
publishData(fieldKey, fieldData);
|
|
53147
|
-
}
|
|
53148
|
-
else if (recordWithSpanningRefLinks.fields[fieldName] &&
|
|
53149
|
-
recordWithSpanningRefLinks.fields[fieldName].value &&
|
|
53150
|
-
recordWithSpanningRefLinks.fields[fieldName].value.__ref !== undefined) {
|
|
53151
|
-
normalizedRecord.fields[fieldName] = { __ref: fieldKey };
|
|
53152
|
-
publishData(fieldKey, recordWithSpanningRefLinks.fields[fieldName]);
|
|
53153
|
-
}
|
|
53413
|
+
normalizedRecord.fields[fieldName] = { __ref: fieldKey };
|
|
53414
|
+
publishData(fieldKey, recordWithSpanningRefLinks.fields[fieldName]);
|
|
53154
53415
|
}
|
|
53155
53416
|
// publish the normalized record
|
|
53156
53417
|
publishData(key, normalizedRecord);
|
|
@@ -54049,6 +54310,9 @@
|
|
|
54049
54310
|
if (!rebuildResult.errors) {
|
|
54050
54311
|
rebuildResult = removeSyntheticFields(rebuildResult, config.query);
|
|
54051
54312
|
}
|
|
54313
|
+
if (objectsDeepEqual(rebuildResult, originalSnapshot.data)) {
|
|
54314
|
+
return originalSnapshot;
|
|
54315
|
+
}
|
|
54052
54316
|
// 'originalSnapshot' is the local eval snapshot subscribed. It is always in 'Fulfilled' state. This behavior would change once W-1273462(rebuild non-evaluated snapshot when the graphql local eval rebuild is triggered) is resolved.
|
|
54053
54317
|
return {
|
|
54054
54318
|
...originalSnapshot,
|
|
@@ -54067,7 +54331,7 @@
|
|
|
54067
54331
|
// Fulfilled snapshot (this only happens in this code path if
|
|
54068
54332
|
// the error is network error or 504), otherwise we spread over
|
|
54069
54333
|
// the non-eval'ed snapshot (which will be either Fulfilled or Stale)
|
|
54070
|
-
|
|
54334
|
+
const resultSnapshot = nonEvaluatedSnapshot.state === 'Error'
|
|
54071
54335
|
? createLocalEvalSnapshot(gqlResult, seenRecords, recordId, rebuildWithLocalEval)
|
|
54072
54336
|
: {
|
|
54073
54337
|
...nonEvaluatedSnapshot,
|
|
@@ -54076,6 +54340,22 @@
|
|
|
54076
54340
|
seenRecords,
|
|
54077
54341
|
rebuildWithLocalEval,
|
|
54078
54342
|
};
|
|
54343
|
+
const { refresh, state } = resultSnapshot;
|
|
54344
|
+
if (state !== 'Error' && refresh) {
|
|
54345
|
+
// after refreshing a graphql snapshot, we want to force a rebuild regardless
|
|
54346
|
+
// of if the call failed or not or if the data changed or not because we want
|
|
54347
|
+
// to make sure any potential new drafts are picked up
|
|
54348
|
+
resultSnapshot.refresh = {
|
|
54349
|
+
...refresh,
|
|
54350
|
+
resolve: (config) => {
|
|
54351
|
+
return refresh.resolve(config).finally(() => {
|
|
54352
|
+
luvio.storePublish(resultSnapshot.recordId, undefined);
|
|
54353
|
+
luvio.storeBroadcast();
|
|
54354
|
+
});
|
|
54355
|
+
},
|
|
54356
|
+
};
|
|
54357
|
+
}
|
|
54358
|
+
return resultSnapshot;
|
|
54079
54359
|
};
|
|
54080
54360
|
}
|
|
54081
54361
|
|
|
@@ -55129,7 +55409,10 @@
|
|
|
55129
55409
|
* @returns the merged record
|
|
55130
55410
|
*/
|
|
55131
55411
|
function mergeAggregateUiResponse(response, mergeFunc) {
|
|
55132
|
-
|
|
55412
|
+
if (response.ok === false) {
|
|
55413
|
+
return response;
|
|
55414
|
+
}
|
|
55415
|
+
const body = response.body;
|
|
55133
55416
|
try {
|
|
55134
55417
|
if (body === null ||
|
|
55135
55418
|
body === undefined ||
|
|
@@ -56960,6 +57243,9 @@
|
|
|
56960
57243
|
this.ldsRecordRefresher = config.ldsRecordRefresher;
|
|
56961
57244
|
this.networkWorkerPool = new AsyncWorkerPool(this.concurrency);
|
|
56962
57245
|
this.useBatchGQL = ldsPrimingGraphqlBatch.isOpen({ fallback: false });
|
|
57246
|
+
if (this.useBatchGQL) {
|
|
57247
|
+
this.batchSize = this.batchSize / DEFAULT_GQL_QUERY_BATCH_SIZE;
|
|
57248
|
+
}
|
|
56963
57249
|
this.conflictPool = new ConflictPool(config.store, this.objectInfoLoader);
|
|
56964
57250
|
}
|
|
56965
57251
|
// function that enqueues priming work
|
|
@@ -57816,7 +58102,7 @@
|
|
|
57816
58102
|
id: '@salesforce/lds-network-adapter',
|
|
57817
58103
|
instrument: instrument$1,
|
|
57818
58104
|
});
|
|
57819
|
-
// version: 1.
|
|
58105
|
+
// version: 1.229.0-dev10-bc9ef2513
|
|
57820
58106
|
|
|
57821
58107
|
const { create: create$2, keys: keys$2 } = Object;
|
|
57822
58108
|
const { stringify: stringify$1, parse: parse$1 } = JSON;
|
|
@@ -71140,7 +71426,7 @@
|
|
|
71140
71426
|
}
|
|
71141
71427
|
}
|
|
71142
71428
|
|
|
71143
|
-
const { assign, create: create$1, freeze: freeze$1, keys: keys$1 } = Object;
|
|
71429
|
+
const { assign, create: create$1, freeze: freeze$1, isFrozen, keys: keys$1 } = Object;
|
|
71144
71430
|
const { isArray: isArray$1 } = Array;
|
|
71145
71431
|
const { concat, filter, includes, push, reduce } = Array.prototype;
|
|
71146
71432
|
|
|
@@ -72579,6 +72865,7 @@
|
|
|
72579
72865
|
}
|
|
72580
72866
|
if (fieldData === null) {
|
|
72581
72867
|
reader.assignScalar(requestedFieldName, sink, fieldData);
|
|
72868
|
+
reader.exitPath();
|
|
72582
72869
|
return sink;
|
|
72583
72870
|
}
|
|
72584
72871
|
const fieldType = getFieldType(sel);
|
|
@@ -72604,17 +72891,8 @@
|
|
|
72604
72891
|
return sink;
|
|
72605
72892
|
}
|
|
72606
72893
|
function selectTypeLink(sel, fieldData, reader, key, sink, variables, fragments, version, selectFn, isCursorConnection) {
|
|
72607
|
-
const resolvedLink = reader
|
|
72608
|
-
|
|
72609
|
-
node: {
|
|
72610
|
-
kind: 'Fragment',
|
|
72611
|
-
private: [],
|
|
72612
|
-
opaque: true,
|
|
72613
|
-
version,
|
|
72614
|
-
},
|
|
72615
|
-
variables: {}
|
|
72616
|
-
});
|
|
72617
|
-
if (resolvedLink.data !== undefined) {
|
|
72894
|
+
const resolvedLink = resolveLink$1(reader, fieldData, version);
|
|
72895
|
+
if (resolvedLink && resolvedLink.data !== undefined) {
|
|
72618
72896
|
if (isCursorConnection) {
|
|
72619
72897
|
selectTypeLinkWithPagination(resolvedLink, sel, fieldData, reader, key, sink, variables, fragments, selectFn);
|
|
72620
72898
|
}
|
|
@@ -73190,19 +73468,11 @@
|
|
|
73190
73468
|
}
|
|
73191
73469
|
case 'PolymorphicParentRelationship':
|
|
73192
73470
|
case 'RecordRepresentation': {
|
|
73193
|
-
const spanningFieldLink = reader
|
|
73194
|
-
|
|
73195
|
-
|
|
73196
|
-
kind: 'Fragment',
|
|
73197
|
-
private: [],
|
|
73198
|
-
opaque: true,
|
|
73199
|
-
version: VERSION$f,
|
|
73200
|
-
},
|
|
73201
|
-
variables: {},
|
|
73202
|
-
});
|
|
73203
|
-
reader.markSeenId(fieldData.__ref);
|
|
73204
|
-
const resolvedSpanningFieldValue = spanningFieldLink.data;
|
|
73471
|
+
const spanningFieldLink = resolveLink$1(reader, fieldData, VERSION$f);
|
|
73472
|
+
const resolvedSpanningFieldValue = spanningFieldLink && spanningFieldLink.data;
|
|
73473
|
+
const fieldDataRef = fieldData.__ref;
|
|
73205
73474
|
if (resolvedSpanningFieldValue !== undefined) {
|
|
73475
|
+
reader.markSeenId(fieldDataRef);
|
|
73206
73476
|
const { value: spanningFieldResult } = resolvedSpanningFieldValue;
|
|
73207
73477
|
// Handle null values - graphql will return it at the field level, not return nested { value: null }
|
|
73208
73478
|
if (spanningFieldResult === null || typeof spanningFieldResult !== 'object') {
|
|
@@ -73226,7 +73496,9 @@
|
|
|
73226
73496
|
}
|
|
73227
73497
|
}
|
|
73228
73498
|
else {
|
|
73229
|
-
|
|
73499
|
+
if (fieldDataRef !== undefined) {
|
|
73500
|
+
reader.markMissingLink(fieldDataRef);
|
|
73501
|
+
}
|
|
73230
73502
|
reader.markMissing();
|
|
73231
73503
|
}
|
|
73232
73504
|
break;
|
|
@@ -76262,7 +76534,7 @@
|
|
|
76262
76534
|
configuration: { ...configurationForGraphQLAdapters },
|
|
76263
76535
|
instrument,
|
|
76264
76536
|
});
|
|
76265
|
-
// version: 1.
|
|
76537
|
+
// version: 1.229.0-dev10-abb060196
|
|
76266
76538
|
|
|
76267
76539
|
// On core the unstable adapters are re-exported with different names,
|
|
76268
76540
|
|
|
@@ -78509,7 +78781,7 @@
|
|
|
78509
78781
|
unstable_graphQL_imperative = createImperativeAdapter(luvio, createInstrumentedAdapter(ldsAdapter, adapterMetadata), adapterMetadata);
|
|
78510
78782
|
graphQLImperative = ldsAdapter;
|
|
78511
78783
|
});
|
|
78512
|
-
// version: 1.
|
|
78784
|
+
// version: 1.229.0-dev10-abb060196
|
|
78513
78785
|
|
|
78514
78786
|
var gqlApi = /*#__PURE__*/Object.freeze({
|
|
78515
78787
|
__proto__: null,
|
|
@@ -79240,4 +79512,4 @@
|
|
|
79240
79512
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
79241
79513
|
|
|
79242
79514
|
}));
|
|
79243
|
-
// version: 1.
|
|
79515
|
+
// version: 1.229.0-dev10-bc9ef2513
|