@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
|
@@ -25,12 +25,15 @@ const { hasOwnProperty: hasOwnProperty$3 } = Object.prototype;
|
|
|
25
25
|
const { isArray: isArray$9 } = Array;
|
|
26
26
|
const { push: push$5, indexOf, slice: slice$2 } = Array.prototype;
|
|
27
27
|
const { parse: parse$a, stringify: stringify$a } = JSON;
|
|
28
|
+
const WeakSetCtor = WeakSet;
|
|
28
29
|
|
|
30
|
+
const deeplyFrozen = new WeakSetCtor();
|
|
29
31
|
function deepFreeze(value) {
|
|
30
|
-
// No need to freeze primitives
|
|
31
|
-
if (typeof value !== 'object' || value === null) {
|
|
32
|
+
// No need to freeze primitives or already frozen stuff
|
|
33
|
+
if (typeof value !== 'object' || value === null || deeplyFrozen.has(value)) {
|
|
32
34
|
return;
|
|
33
35
|
}
|
|
36
|
+
deeplyFrozen.add(value);
|
|
34
37
|
if (isArray$9(value)) {
|
|
35
38
|
for (let i = 0, len = value.length; i < len; i += 1) {
|
|
36
39
|
deepFreeze(value[i]);
|
|
@@ -1727,6 +1730,10 @@ class InMemoryStore {
|
|
|
1727
1730
|
}
|
|
1728
1731
|
}
|
|
1729
1732
|
markVisited(canonicalKey) {
|
|
1733
|
+
if (typeof canonicalKey === 'string') {
|
|
1734
|
+
this.fallbackStringKeyInMemoryStore.markVisited(canonicalKey);
|
|
1735
|
+
return;
|
|
1736
|
+
}
|
|
1730
1737
|
const { visitedIdsSet, reverseRedirectKeysMap } = this;
|
|
1731
1738
|
let redirectKey = canonicalKey;
|
|
1732
1739
|
// mark all redirects leading up to the canonical key as visited so
|
|
@@ -2038,7 +2045,7 @@ class GraphLink {
|
|
|
2038
2045
|
if (isStoreRecordError$1(linked)) {
|
|
2039
2046
|
return new GraphNodeError(this.store, linked);
|
|
2040
2047
|
}
|
|
2041
|
-
return new GraphNode(this.store, linked);
|
|
2048
|
+
return new GraphNode(this.store, linked, __ref);
|
|
2042
2049
|
}
|
|
2043
2050
|
linkData() {
|
|
2044
2051
|
return this.data.data;
|
|
@@ -2048,10 +2055,11 @@ class GraphLink {
|
|
|
2048
2055
|
}
|
|
2049
2056
|
}
|
|
2050
2057
|
class GraphNode {
|
|
2051
|
-
constructor(store, data) {
|
|
2058
|
+
constructor(store, data, storeKey) {
|
|
2052
2059
|
this.type = GraphNodeType$1.Node;
|
|
2053
2060
|
this.store = store;
|
|
2054
2061
|
this.data = data;
|
|
2062
|
+
this.storeKey = storeKey;
|
|
2055
2063
|
}
|
|
2056
2064
|
object(propertyName) {
|
|
2057
2065
|
const value = this.data[propertyName];
|
|
@@ -2061,7 +2069,8 @@ class GraphNode {
|
|
|
2061
2069
|
if (typeof value !== 'object' || value === null) {
|
|
2062
2070
|
throw new Error(`Cannot walk to path ${String(propertyName)}. "${String(propertyName)}" is a scalar: "${value}"`);
|
|
2063
2071
|
}
|
|
2064
|
-
|
|
2072
|
+
// We're walking to an object property on the current store record, pass the storeKey down.
|
|
2073
|
+
return new GraphNode(this.store, value, this.storeKey);
|
|
2065
2074
|
}
|
|
2066
2075
|
link(propertyName) {
|
|
2067
2076
|
const value = this.data[propertyName];
|
|
@@ -2091,6 +2100,8 @@ class GraphNode {
|
|
|
2091
2100
|
}
|
|
2092
2101
|
write(propertyName, value) {
|
|
2093
2102
|
this.data[propertyName] = value;
|
|
2103
|
+
const canonicalKey = this.store.getCanonicalRecordId(this.storeKey);
|
|
2104
|
+
this.store.markVisited(canonicalKey);
|
|
2094
2105
|
}
|
|
2095
2106
|
isUndefined(propertyName) {
|
|
2096
2107
|
return this.data[propertyName] === undefined;
|
|
@@ -2275,6 +2286,34 @@ var FragmentReadResultState$1;
|
|
|
2275
2286
|
const FRAGMENT_READ_RESULT_MISSING = {
|
|
2276
2287
|
state: FragmentReadResultState$1.Missing,
|
|
2277
2288
|
};
|
|
2289
|
+
function resolveLink$1(reader, storeLink, version) {
|
|
2290
|
+
const { StoreLinkStateValues } = reader;
|
|
2291
|
+
const linkState = reader.getLinkState(storeLink);
|
|
2292
|
+
switch (linkState.state) {
|
|
2293
|
+
case StoreLinkStateValues.RefNotPresent:
|
|
2294
|
+
case StoreLinkStateValues.NotPresent:
|
|
2295
|
+
case StoreLinkStateValues.Missing:
|
|
2296
|
+
reader.markMissingLink(storeLink.__ref);
|
|
2297
|
+
reader.markMissing();
|
|
2298
|
+
return;
|
|
2299
|
+
case StoreLinkStateValues.Pending:
|
|
2300
|
+
reader.markPending();
|
|
2301
|
+
return;
|
|
2302
|
+
case StoreLinkStateValues.Null:
|
|
2303
|
+
return;
|
|
2304
|
+
}
|
|
2305
|
+
const { key: __ref } = linkState;
|
|
2306
|
+
return reader.read({
|
|
2307
|
+
recordId: __ref,
|
|
2308
|
+
node: {
|
|
2309
|
+
kind: 'Fragment',
|
|
2310
|
+
private: [],
|
|
2311
|
+
opaque: true,
|
|
2312
|
+
version,
|
|
2313
|
+
},
|
|
2314
|
+
variables: {},
|
|
2315
|
+
});
|
|
2316
|
+
}
|
|
2278
2317
|
class Reader {
|
|
2279
2318
|
constructor(store, variables, refresh, baseSnapshot, ttlStrategy) {
|
|
2280
2319
|
this.store = store;
|
|
@@ -3225,9 +3264,9 @@ class Environment {
|
|
|
3225
3264
|
if (value === undefined) {
|
|
3226
3265
|
return null;
|
|
3227
3266
|
}
|
|
3228
|
-
return this.wrapNormalizedGraphNode(value, store);
|
|
3267
|
+
return this.wrapNormalizedGraphNode(value, key, store);
|
|
3229
3268
|
}
|
|
3230
|
-
wrapNormalizedGraphNode(normalized, storeOverride) {
|
|
3269
|
+
wrapNormalizedGraphNode(normalized, key, storeOverride) {
|
|
3231
3270
|
if (normalized === null) {
|
|
3232
3271
|
return null;
|
|
3233
3272
|
}
|
|
@@ -3235,7 +3274,7 @@ class Environment {
|
|
|
3235
3274
|
if (isStoreRecordError$1(normalized)) {
|
|
3236
3275
|
return new GraphNodeError(store, normalized);
|
|
3237
3276
|
}
|
|
3238
|
-
return new GraphNode(store, normalized);
|
|
3277
|
+
return new GraphNode(store, normalized, key);
|
|
3239
3278
|
}
|
|
3240
3279
|
withContext(adapter, options) {
|
|
3241
3280
|
const { contextId, onContextLoaded } = options;
|
|
@@ -3530,8 +3569,8 @@ class Luvio {
|
|
|
3530
3569
|
getNode(key) {
|
|
3531
3570
|
return this.environment.getNode(key);
|
|
3532
3571
|
}
|
|
3533
|
-
wrapNormalizedGraphNode(normalized) {
|
|
3534
|
-
return this.environment.wrapNormalizedGraphNode(normalized);
|
|
3572
|
+
wrapNormalizedGraphNode(normalized, key) {
|
|
3573
|
+
return this.environment.wrapNormalizedGraphNode(normalized, key);
|
|
3535
3574
|
}
|
|
3536
3575
|
instrument(paramsBuilder) {
|
|
3537
3576
|
const { instrument } = this.options;
|
|
@@ -3841,7 +3880,7 @@ function createResourceParamsImpl(config, configMetadata) {
|
|
|
3841
3880
|
}
|
|
3842
3881
|
return resourceParams;
|
|
3843
3882
|
}
|
|
3844
|
-
// engine version: 0.
|
|
3883
|
+
// engine version: 0.146.0-dev5-a2ec6e3f
|
|
3845
3884
|
|
|
3846
3885
|
/**
|
|
3847
3886
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
@@ -3968,7 +4007,7 @@ function withDefaultLuvio(callback) {
|
|
|
3968
4007
|
}
|
|
3969
4008
|
callbacks.push(callback);
|
|
3970
4009
|
}
|
|
3971
|
-
// version: 1.
|
|
4010
|
+
// version: 1.229.0-dev10-bc9ef2513
|
|
3972
4011
|
|
|
3973
4012
|
// TODO [TD-0081508]: once that TD is fulfilled we can probably change this file
|
|
3974
4013
|
function instrumentAdapter$1(createFunction, _metadata) {
|
|
@@ -15429,7 +15468,7 @@ function gql(literals, ...subs) {
|
|
|
15429
15468
|
}
|
|
15430
15469
|
return superResult;
|
|
15431
15470
|
}
|
|
15432
|
-
// version: 1.
|
|
15471
|
+
// version: 1.229.0-dev10-bc9ef2513
|
|
15433
15472
|
|
|
15434
15473
|
function unwrap(data) {
|
|
15435
15474
|
// The lwc-luvio bindings import a function from lwc called "unwrap".
|
|
@@ -15530,14 +15569,15 @@ function refreshData(data, dataToTuple, luvio) {
|
|
|
15530
15569
|
return undefined;
|
|
15531
15570
|
});
|
|
15532
15571
|
}
|
|
15533
|
-
const { isArray: isArray$8 } = Array;
|
|
15534
|
-
const { stringify: stringify$9 } = JSON;
|
|
15535
15572
|
|
|
15536
15573
|
function isPromise$1(value) {
|
|
15537
15574
|
// check for Thenable due to test frameworks using custom Promise impls
|
|
15538
15575
|
return value.then !== undefined;
|
|
15539
15576
|
}
|
|
15540
15577
|
|
|
15578
|
+
const { isArray: isArray$8 } = Array;
|
|
15579
|
+
const { stringify: stringify$9 } = JSON;
|
|
15580
|
+
|
|
15541
15581
|
/**
|
|
15542
15582
|
* (Re)throws an error after adding a prefix to the message.
|
|
15543
15583
|
*
|
|
@@ -16352,7 +16392,7 @@ function createGraphQLWireAdapterConstructor(luvio, adapter, metadata, astResolv
|
|
|
16352
16392
|
const { apiFamily, name } = metadata;
|
|
16353
16393
|
return createGraphQLWireAdapterConstructor$1(adapter, `${apiFamily}.${name}`, luvio, astResolver);
|
|
16354
16394
|
}
|
|
16355
|
-
// version: 1.
|
|
16395
|
+
// version: 1.229.0-dev10-bc9ef2513
|
|
16356
16396
|
|
|
16357
16397
|
/**
|
|
16358
16398
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
@@ -16451,11 +16491,11 @@ var TypeCheckShapes;
|
|
|
16451
16491
|
TypeCheckShapes[TypeCheckShapes["Integer"] = 3] = "Integer";
|
|
16452
16492
|
TypeCheckShapes[TypeCheckShapes["Unsupported"] = 4] = "Unsupported";
|
|
16453
16493
|
})(TypeCheckShapes || (TypeCheckShapes = {}));
|
|
16454
|
-
// engine version: 0.
|
|
16494
|
+
// engine version: 0.146.0-dev5-a2ec6e3f
|
|
16455
16495
|
|
|
16456
16496
|
const { keys: ObjectKeys$3, create: ObjectCreate$3 } = Object;
|
|
16457
16497
|
|
|
16458
|
-
const { assign: assign$9, create: create$9, freeze: freeze$4, keys: keys$b } = Object;
|
|
16498
|
+
const { assign: assign$9, create: create$9, freeze: freeze$4, isFrozen: isFrozen$2, keys: keys$b } = Object;
|
|
16459
16499
|
|
|
16460
16500
|
ObjectCreate$3(null);
|
|
16461
16501
|
|
|
@@ -16825,7 +16865,7 @@ function buildAdapterValidationConfig$1(displayName, paramsMeta) {
|
|
|
16825
16865
|
}
|
|
16826
16866
|
const keyPrefix$1 = 'UiApi';
|
|
16827
16867
|
|
|
16828
|
-
const { assign: assign$8, create: create$8, freeze: freeze$3, keys: keys$a } = Object;
|
|
16868
|
+
const { assign: assign$8, create: create$8, freeze: freeze$3, isFrozen: isFrozen$1, keys: keys$a } = Object;
|
|
16829
16869
|
const { hasOwnProperty: hasOwnProperty$1 } = Object.prototype;
|
|
16830
16870
|
const { split, endsWith } = String.prototype;
|
|
16831
16871
|
const { isArray: isArray$7 } = Array;
|
|
@@ -19794,7 +19834,7 @@ function extractTrackedFieldsToTrie(recordId, node, root, config, visitedRecordI
|
|
|
19794
19834
|
extractTrackedFieldsToTrie(spanningLink.data.__ref, spanning, next, config, spanningVisitedRecordIds, depth + 1);
|
|
19795
19835
|
// For a spanning record that is detected to be a circular reference, we add the field along with Id and Name.
|
|
19796
19836
|
// It's possible for spanning record lookup fields to sometimes be circular, and sometimes not - depending on the value of the lookup field.
|
|
19797
|
-
// For more information on scenarios that caused this fix:
|
|
19837
|
+
// For more information on scenarios that caused this fix: search "LDS Recursive Spanning Fields Problem" in Quip
|
|
19798
19838
|
if (keys$a(next.children).length === 0) {
|
|
19799
19839
|
addScalarFieldId(next);
|
|
19800
19840
|
addScalarFieldName(next);
|
|
@@ -19947,7 +19987,11 @@ function markNulledOutPath(record, path) {
|
|
|
19947
19987
|
}
|
|
19948
19988
|
const link = fieldValueRepresentation.link(fieldName);
|
|
19949
19989
|
const resolved = link.follow();
|
|
19950
|
-
if (isGraphNode(resolved) &&
|
|
19990
|
+
if (isGraphNode(resolved) &&
|
|
19991
|
+
resolved.isScalar('value') &&
|
|
19992
|
+
path.length > 0 &&
|
|
19993
|
+
// TODO [W-14082782]: temporary fix
|
|
19994
|
+
!isFrozen$1(link.data)) {
|
|
19951
19995
|
const linkState = link.linkData();
|
|
19952
19996
|
const fields = linkState === undefined ? [] : linkState.fields;
|
|
19953
19997
|
link.writeLinkData({
|
|
@@ -19975,22 +20019,12 @@ function _markMissingPath(record, path) {
|
|
|
19975
20019
|
const fieldValueRepresentation = record.object('fields');
|
|
19976
20020
|
const fieldName = path.shift();
|
|
19977
20021
|
if (fieldValueRepresentation.isUndefined(fieldName) === true) {
|
|
19978
|
-
|
|
19979
|
-
// an undefined/non-present __ref if isMissing is present
|
|
19980
|
-
fieldValueRepresentation.write(fieldName, {
|
|
19981
|
-
__ref: undefined,
|
|
19982
|
-
isMissing: true,
|
|
19983
|
-
});
|
|
20022
|
+
writeMissingFieldToStore(fieldValueRepresentation, fieldName);
|
|
19984
20023
|
return;
|
|
19985
20024
|
}
|
|
19986
20025
|
const link = fieldValueRepresentation.link(fieldName);
|
|
19987
20026
|
if (link.isPending()) {
|
|
19988
|
-
|
|
19989
|
-
// an undefined/non-present __ref if isMissing is present
|
|
19990
|
-
fieldValueRepresentation.write(fieldName, {
|
|
19991
|
-
__ref: undefined,
|
|
19992
|
-
isMissing: true,
|
|
19993
|
-
});
|
|
20027
|
+
writeMissingFieldToStore(fieldValueRepresentation, fieldName);
|
|
19994
20028
|
}
|
|
19995
20029
|
else if (path.length > 0 && link.isMissing() === false) {
|
|
19996
20030
|
const fieldValue = link.follow();
|
|
@@ -20006,6 +20040,19 @@ function _markMissingPath(record, path) {
|
|
|
20006
20040
|
}
|
|
20007
20041
|
}
|
|
20008
20042
|
}
|
|
20043
|
+
/**
|
|
20044
|
+
* Graph Node Directly modifies store entries, which is generally a non-starter.
|
|
20045
|
+
* Until we can refactor this mess, you need to use this function to safely mark the RecordRepresentation
|
|
20046
|
+
* as a seenId in the store when you perform this mutation.
|
|
20047
|
+
*/
|
|
20048
|
+
function writeMissingFieldToStore(field, fieldName) {
|
|
20049
|
+
// TODO [W-6900046]: remove cast, make RecordRepresentationNormalized['fields'] accept
|
|
20050
|
+
// an undefined/non-present __ref if isMissing is present
|
|
20051
|
+
field.write(fieldName, {
|
|
20052
|
+
__ref: undefined,
|
|
20053
|
+
isMissing: true,
|
|
20054
|
+
});
|
|
20055
|
+
}
|
|
20009
20056
|
/**
|
|
20010
20057
|
* Tells you if an objectApiName is supported by UI API or not.
|
|
20011
20058
|
* Note: Luvio does not currently support all the entities, the list is limited to UI API supported entities
|
|
@@ -20137,8 +20184,11 @@ function mergeAndRefreshLowerVersionRecord(luvio, incoming, existing, incomingTr
|
|
|
20137
20184
|
return existing;
|
|
20138
20185
|
}
|
|
20139
20186
|
function mergeRecordConflict(luvio, incoming, existing, recordConflictMap) {
|
|
20140
|
-
const
|
|
20141
|
-
|
|
20187
|
+
const recordKey = keyBuilder$1U(luvio, {
|
|
20188
|
+
recordId: incoming.id,
|
|
20189
|
+
});
|
|
20190
|
+
const incomingNode = luvio.wrapNormalizedGraphNode(incoming, recordKey);
|
|
20191
|
+
const existingNode = luvio.wrapNormalizedGraphNode(existing, recordKey);
|
|
20142
20192
|
const incomingTrackedFieldsTrieRoot = {
|
|
20143
20193
|
name: incoming.apiName,
|
|
20144
20194
|
children: {},
|
|
@@ -20147,9 +20197,6 @@ function mergeRecordConflict(luvio, incoming, existing, recordConflictMap) {
|
|
|
20147
20197
|
name: existing.apiName,
|
|
20148
20198
|
children: {},
|
|
20149
20199
|
};
|
|
20150
|
-
const recordKey = keyBuilder$1U(luvio, {
|
|
20151
|
-
recordId: incoming.id,
|
|
20152
|
-
});
|
|
20153
20200
|
const trackedFieldsConfig = {
|
|
20154
20201
|
maxDepth: configurationForRestAdapters$1.getTrackedFieldDepthOnCacheMergeConflict(),
|
|
20155
20202
|
onlyFetchLeafNodeIdAndName: configurationForRestAdapters$1.getTrackedFieldLeafNodeIdAndNameOnly(),
|
|
@@ -20455,7 +20502,7 @@ function fulfill(existing, incoming) {
|
|
|
20455
20502
|
const batchRequestWithSingleRequest = isSingleBatchRecordRequest(existingUrlParams) &&
|
|
20456
20503
|
isSingleRecordRequest(urlParams) &&
|
|
20457
20504
|
incomingUrlRecords[0] === existingUrlRecords[0];
|
|
20458
|
-
if (!batchRequestWithSingleRequest) {
|
|
20505
|
+
if (!batchRequestWithSingleRequest || isRestrictedPathCondition(existingPath, path)) {
|
|
20459
20506
|
return false;
|
|
20460
20507
|
}
|
|
20461
20508
|
}
|
|
@@ -20498,6 +20545,12 @@ function isSingleBatchRecordRequest(urlParams) {
|
|
|
20498
20545
|
function isSingleRecordRequest(urlParams) {
|
|
20499
20546
|
return hasOwnProperty$1.call(urlParams, 'recordId');
|
|
20500
20547
|
}
|
|
20548
|
+
function isRestrictedPathCondition(existingPath, path) {
|
|
20549
|
+
// should not dedupe getRecordUi and getRecord as both of their representation is different
|
|
20550
|
+
// records call cannot digest response of getRecordUi
|
|
20551
|
+
return ((existingPath.includes('/record-ui') && path.includes('/records')) ||
|
|
20552
|
+
(existingPath.includes('/records') && path.includes('/record-ui')));
|
|
20553
|
+
}
|
|
20501
20554
|
|
|
20502
20555
|
const createResourceRequest$12 = function getUiApiRecordsByRecordIdCreateResourceRequest(config) {
|
|
20503
20556
|
return {
|
|
@@ -24854,7 +24907,7 @@ function getLayoutMapAndObjectInfo(recordId, data) {
|
|
|
24854
24907
|
// Temp fix until we can mimic the server behavior for non-layoutable entities.
|
|
24855
24908
|
let layoutMap = {};
|
|
24856
24909
|
if (hasOwnProperty$1.call(layouts, apiName)) {
|
|
24857
|
-
layoutMap = layouts[apiName][recordTypeId];
|
|
24910
|
+
layoutMap = layouts[apiName][recordTypeId] || {};
|
|
24858
24911
|
}
|
|
24859
24912
|
return {
|
|
24860
24913
|
layoutMap,
|
|
@@ -25032,18 +25085,28 @@ const buildLayoutModeCacheSnapshot = (apiName, recordTypeId, layoutType, mode) =
|
|
|
25032
25085
|
* These are intermediate lookups to check if the record is in the L2 cache
|
|
25033
25086
|
* @param {Luvio} luvio
|
|
25034
25087
|
* @param {GetRecordLayoutTypeConfig} config
|
|
25035
|
-
* @param {BuildCachedSnapshot<BuildSnapshotContext} cachedSnapshot
|
|
25088
|
+
* @param {BuildCachedSnapshot<BuildSnapshotContext>} cachedSnapshot
|
|
25036
25089
|
*/
|
|
25037
25090
|
function makeCacheOnlySnapshot(luvio, config, adapterContext, cachedSnapshot) {
|
|
25038
|
-
return luvio.applyCachePolicy(
|
|
25039
|
-
|
|
25040
|
-
|
|
25041
|
-
|
|
25042
|
-
},
|
|
25043
|
-
}, { config, luvio, adapterContext }, cachedSnapshot,
|
|
25044
|
-
// this won't be invoked since we're requesting only-if-cached
|
|
25091
|
+
return luvio.applyCachePolicy(
|
|
25092
|
+
// Pass empty context so environment will use its default cache-policy
|
|
25093
|
+
{}, { config, luvio, adapterContext }, cachedSnapshot,
|
|
25094
|
+
// disallow hitting the network by returning a gateway timeout
|
|
25045
25095
|
() => {
|
|
25046
|
-
|
|
25096
|
+
return new Promise((resolve) => {
|
|
25097
|
+
resolve({
|
|
25098
|
+
state: 'Error',
|
|
25099
|
+
data: undefined,
|
|
25100
|
+
error: {
|
|
25101
|
+
body: undefined,
|
|
25102
|
+
headers: {},
|
|
25103
|
+
ok: false,
|
|
25104
|
+
status: 504,
|
|
25105
|
+
statusText: 'Gateway Timeout',
|
|
25106
|
+
errorType: 'fetchResponse',
|
|
25107
|
+
},
|
|
25108
|
+
});
|
|
25109
|
+
});
|
|
25047
25110
|
});
|
|
25048
25111
|
}
|
|
25049
25112
|
/**
|
|
@@ -25254,7 +25317,7 @@ const notifyChangeFactory = (luvio) => {
|
|
|
25254
25317
|
const responsePromises = [];
|
|
25255
25318
|
for (let i = 0, len = entries.length; i < len; i++) {
|
|
25256
25319
|
const { key, record } = entries[i];
|
|
25257
|
-
const node = luvio.wrapNormalizedGraphNode(record);
|
|
25320
|
+
const node = luvio.wrapNormalizedGraphNode(record, key);
|
|
25258
25321
|
const optionalFields = getTrackedFields(key, node, {
|
|
25259
25322
|
maxDepth: configurationForRestAdapters$1.getTrackedFieldDepthOnNotifyChange(),
|
|
25260
25323
|
onlyFetchLeafNodeIdAndName: configurationForRestAdapters$1.getTrackedFieldLeafNodeIdAndNameOnly(),
|
|
@@ -41152,7 +41215,16 @@ withDefaultLuvio((luvio) => {
|
|
|
41152
41215
|
throttle(60, 60000, createLDSAdapter(luvio, 'notifyListInfoUpdateAvailable', notifyUpdateAvailableFactory$1));
|
|
41153
41216
|
throttle(60, 60000, createLDSAdapter(luvio, 'notifyQuickActionDefaultsUpdateAvailable', notifyUpdateAvailableFactory));
|
|
41154
41217
|
});
|
|
41155
|
-
// version: 1.
|
|
41218
|
+
// version: 1.229.0-dev10-abb060196
|
|
41219
|
+
|
|
41220
|
+
var ldsIdempotencyWriteDisabled = {
|
|
41221
|
+
isOpen: function (e) {
|
|
41222
|
+
return e.fallback;
|
|
41223
|
+
},
|
|
41224
|
+
hasError: function () {
|
|
41225
|
+
return !0;
|
|
41226
|
+
},
|
|
41227
|
+
};
|
|
41156
41228
|
|
|
41157
41229
|
var caseSensitiveUserId = '005B0000000GR4OIAW';
|
|
41158
41230
|
|
|
@@ -41783,6 +41855,9 @@ function handleDurableStoreRejection(instrument) {
|
|
|
41783
41855
|
}
|
|
41784
41856
|
|
|
41785
41857
|
function isStoreEntryError(storeRecord) {
|
|
41858
|
+
if (!storeRecord || typeof storeRecord !== 'object') {
|
|
41859
|
+
return false;
|
|
41860
|
+
}
|
|
41786
41861
|
return storeRecord.__type === 'error';
|
|
41787
41862
|
}
|
|
41788
41863
|
|
|
@@ -42367,12 +42442,12 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
42367
42442
|
}
|
|
42368
42443
|
return environment.getNode(key, ingestStagingStore);
|
|
42369
42444
|
};
|
|
42370
|
-
const wrapNormalizedGraphNode = function (normalized) {
|
|
42445
|
+
const wrapNormalizedGraphNode = function (normalized, key) {
|
|
42371
42446
|
validateNotDisposed();
|
|
42372
42447
|
if (ingestStagingStore === null) {
|
|
42373
42448
|
ingestStagingStore = buildIngestStagingStore(environment);
|
|
42374
42449
|
}
|
|
42375
|
-
return environment.wrapNormalizedGraphNode(normalized, ingestStagingStore);
|
|
42450
|
+
return environment.wrapNormalizedGraphNode(normalized, key, ingestStagingStore);
|
|
42376
42451
|
};
|
|
42377
42452
|
const rebuildSnapshot = function (snapshot, onRebuild) {
|
|
42378
42453
|
validateNotDisposed();
|
|
@@ -42686,6 +42761,72 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
42686
42761
|
});
|
|
42687
42762
|
}
|
|
42688
42763
|
|
|
42764
|
+
/**
|
|
42765
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
42766
|
+
* All rights reserved.
|
|
42767
|
+
* For full license text, see the LICENSE.txt file
|
|
42768
|
+
*/
|
|
42769
|
+
|
|
42770
|
+
const API_NAMESPACE$1 = 'UiApi';
|
|
42771
|
+
const RECORD_REPRESENTATION_NAME$2 = 'RecordRepresentation';
|
|
42772
|
+
const RECORD_VIEW_ENTITY_REPRESENTATION_NAME$1 = 'RecordViewEntityRepresentation';
|
|
42773
|
+
const RECORD_ID_PREFIX$1 = `${API_NAMESPACE$1}::${RECORD_REPRESENTATION_NAME$2}:`;
|
|
42774
|
+
const RECORD_VIEW_ENTITY_ID_PREFIX$1 = `${API_NAMESPACE$1}::${RECORD_VIEW_ENTITY_REPRESENTATION_NAME$1}:Name:`;
|
|
42775
|
+
const RECORD_FIELDS_KEY_JUNCTION$1 = '__fields__';
|
|
42776
|
+
function isStoreKeyRecordId(key) {
|
|
42777
|
+
return key.indexOf(RECORD_ID_PREFIX$1) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION$1) === -1;
|
|
42778
|
+
}
|
|
42779
|
+
function isStoreKeyRecordViewEntity$1(key) {
|
|
42780
|
+
return (key.indexOf(RECORD_VIEW_ENTITY_ID_PREFIX$1) > -1 &&
|
|
42781
|
+
key.indexOf(RECORD_FIELDS_KEY_JUNCTION$1) === -1);
|
|
42782
|
+
}
|
|
42783
|
+
function isStoreKeyRecordField(key) {
|
|
42784
|
+
return key.indexOf(RECORD_ID_PREFIX$1) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION$1) > -1;
|
|
42785
|
+
}
|
|
42786
|
+
function extractRecordIdFromStoreKey$1(key) {
|
|
42787
|
+
if (key === undefined ||
|
|
42788
|
+
(key.indexOf(RECORD_ID_PREFIX$1) === -1 && key.indexOf(RECORD_VIEW_ENTITY_ID_PREFIX$1) === -1)) {
|
|
42789
|
+
return undefined;
|
|
42790
|
+
}
|
|
42791
|
+
const parts = key.split(':');
|
|
42792
|
+
return parts[parts.length - 1].split('_')[0];
|
|
42793
|
+
}
|
|
42794
|
+
function buildRecordFieldStoreKey(recordKey, fieldName) {
|
|
42795
|
+
return `${recordKey}${RECORD_FIELDS_KEY_JUNCTION$1}${fieldName}`;
|
|
42796
|
+
}
|
|
42797
|
+
function objectsDeepEqual(lhs, rhs) {
|
|
42798
|
+
if (lhs === rhs)
|
|
42799
|
+
return true;
|
|
42800
|
+
if (typeof lhs !== 'object' || typeof rhs !== 'object' || lhs === null || rhs === null)
|
|
42801
|
+
return false;
|
|
42802
|
+
const lhsKeys = Object.keys(lhs);
|
|
42803
|
+
const rhsKeys = Object.keys(rhs);
|
|
42804
|
+
if (lhsKeys.length !== rhsKeys.length)
|
|
42805
|
+
return false;
|
|
42806
|
+
for (let key of lhsKeys) {
|
|
42807
|
+
if (!rhsKeys.includes(key))
|
|
42808
|
+
return false;
|
|
42809
|
+
if (typeof lhs[key] === 'function' || typeof rhs[key] === 'function') {
|
|
42810
|
+
if (lhs[key].toString() !== rhs[key].toString())
|
|
42811
|
+
return false;
|
|
42812
|
+
}
|
|
42813
|
+
else {
|
|
42814
|
+
if (!objectsDeepEqual(lhs[key], rhs[key]))
|
|
42815
|
+
return false;
|
|
42816
|
+
}
|
|
42817
|
+
}
|
|
42818
|
+
return true;
|
|
42819
|
+
}
|
|
42820
|
+
|
|
42821
|
+
function isStoreRecordError(storeRecord) {
|
|
42822
|
+
return storeRecord.__type === 'error';
|
|
42823
|
+
}
|
|
42824
|
+
function isEntryDurableRecordRepresentation(entry, key) {
|
|
42825
|
+
// Either a DurableRecordRepresentation or StoreRecordError can live at a record key
|
|
42826
|
+
return ((isStoreKeyRecordId(key) || isStoreKeyRecordViewEntity$1(key)) &&
|
|
42827
|
+
entry.data.__type === undefined);
|
|
42828
|
+
}
|
|
42829
|
+
|
|
42689
42830
|
/**
|
|
42690
42831
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
42691
42832
|
* All rights reserved.
|
|
@@ -43945,6 +44086,7 @@ function isScalarDataType(type) {
|
|
|
43945
44086
|
'Email',
|
|
43946
44087
|
'TextArea',
|
|
43947
44088
|
'Percent',
|
|
44089
|
+
'EncryptedString',
|
|
43948
44090
|
].includes(type);
|
|
43949
44091
|
}
|
|
43950
44092
|
|
|
@@ -45425,8 +45567,12 @@ function rootRecordQuery(selection, input) {
|
|
|
45425
45567
|
// If there is no metadata for this query or it somehow lacks a timestamp
|
|
45426
45568
|
// skip setting the root timestamp
|
|
45427
45569
|
if (queryMetadata !== undefined && queryMetadata.ingestionTimestamp !== undefined) {
|
|
45428
|
-
|
|
45429
|
-
|
|
45570
|
+
const timestamp = Number(queryMetadata.ingestionTimestamp);
|
|
45571
|
+
if (!isNaN(timestamp)) {
|
|
45572
|
+
// adjust the timestamp to account for ingestion processing time
|
|
45573
|
+
// 30s is used because this is the default record TTL
|
|
45574
|
+
input.rootTimestamp = timestamp - 30000;
|
|
45575
|
+
}
|
|
45430
45576
|
}
|
|
45431
45577
|
}
|
|
45432
45578
|
return recordQuery(selection, alias, apiName, [], input);
|
|
@@ -45884,7 +46030,11 @@ function makeStoreEval(preconditioner, objectInfoService, userId, contextProvide
|
|
|
45884
46030
|
try {
|
|
45885
46031
|
const { data, seenRecords } = await queryEvaluator(rootQuery, context, eventEmitter);
|
|
45886
46032
|
const rebuildWithStoreEval = ((originalSnapshot) => {
|
|
45887
|
-
return storeEval(config, originalSnapshot, observers, connectionKeyBuilder)
|
|
46033
|
+
return storeEval(config, originalSnapshot, observers, connectionKeyBuilder).then((rebuiltSnapshot) => {
|
|
46034
|
+
return objectsDeepEqual(originalSnapshot.data, rebuiltSnapshot.data)
|
|
46035
|
+
? originalSnapshot
|
|
46036
|
+
: rebuiltSnapshot;
|
|
46037
|
+
});
|
|
45888
46038
|
});
|
|
45889
46039
|
const recordId = generateUniqueRecordId$1();
|
|
45890
46040
|
// if the non-eval'ed snapshot was an error then we return a synthetic
|
|
@@ -46235,8 +46385,12 @@ function uuidv4() {
|
|
|
46235
46385
|
|
|
46236
46386
|
const HTTP_HEADER_RETRY_AFTER = 'Retry-After';
|
|
46237
46387
|
const HTTP_HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key';
|
|
46388
|
+
const ERROR_CODE_IDEMPOTENCY_FEATURE_NOT_ENABLED = 'IDEMPOTENCY_FEATURE_NOT_ENABLED';
|
|
46389
|
+
const ERROR_CODE_IDEMPOTENCY_NOT_SUPPORTED = 'IDEMPOTENCY_NOT_SUPPORTED';
|
|
46238
46390
|
const ERROR_CODE_IDEMPOTENCY_KEY_USED_DIFFERENT_USER = 'IDEMPOTENCY_KEY_USED_DIFFERENT_USER';
|
|
46239
46391
|
const ERROR_CODE_IDEMPOTENCY_CONCURRENT_REQUEST = 'IDEMPOTENCY_CONCURRENT_REQUEST';
|
|
46392
|
+
const ERROR_CODE_IDEMPOTENCY_KEY_ALREADY_USED = 'IDEMPOTENCY_KEY_ALREADY_USED';
|
|
46393
|
+
const ERROR_CODE_IDEMPOTENCY_BACKEND_OPERATION_ERROR = 'IDEMPOTENCY_BACKEND_OPERATION_ERROR';
|
|
46240
46394
|
/**
|
|
46241
46395
|
* Get the retry after in milliseconds from the response headers, undefined if not specified.
|
|
46242
46396
|
* The header could have two different format.
|
|
@@ -46266,7 +46420,9 @@ function buildLuvioOverrideForDraftAdapters(luvio, handler, extractTargetIdFromC
|
|
|
46266
46420
|
const dispatchResourceRequest = async function (resourceRequest, _context) {
|
|
46267
46421
|
const resourceRequestCopy = clone$1(resourceRequest);
|
|
46268
46422
|
resourceRequestCopy.headers = resourceRequestCopy.headers || {};
|
|
46269
|
-
|
|
46423
|
+
if (handler.hasIdempotencySupport()) {
|
|
46424
|
+
resourceRequestCopy.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
|
|
46425
|
+
}
|
|
46270
46426
|
// enable return extra fields for record creation and record update http call
|
|
46271
46427
|
if (resourceRequest.basePath === '/ui-api/records' &&
|
|
46272
46428
|
(resourceRequest.method === 'post' || resourceRequest.method === 'patch')) {
|
|
@@ -47088,6 +47244,12 @@ class AbstractResourceRequestActionHandler {
|
|
|
47088
47244
|
// the luvio store redirect table, during which a new draft might be enqueued
|
|
47089
47245
|
// which would not see a necessary mapping.
|
|
47090
47246
|
this.ephemeralRedirects = {};
|
|
47247
|
+
// determined by Server setup.
|
|
47248
|
+
this.isIdempotencySupported = true;
|
|
47249
|
+
// idempotency write flag set by lds
|
|
47250
|
+
this.isLdsIdempotencyWriteDisabled = ldsIdempotencyWriteDisabled.isOpen({
|
|
47251
|
+
fallback: false,
|
|
47252
|
+
});
|
|
47091
47253
|
}
|
|
47092
47254
|
enqueue(data) {
|
|
47093
47255
|
return this.draftQueue.enqueue(this.handlerId, data);
|
|
@@ -47117,21 +47279,43 @@ class AbstractResourceRequestActionHandler {
|
|
|
47117
47279
|
retryDelayInMs = getRetryAfterInMs(response.headers);
|
|
47118
47280
|
shouldRetry = true;
|
|
47119
47281
|
break;
|
|
47120
|
-
case HttpStatusCode$1.ServerError:
|
|
47282
|
+
case HttpStatusCode$1.ServerError: {
|
|
47121
47283
|
shouldRetry = true;
|
|
47284
|
+
if (this.handleIdempotencyServerError(response.body, updatedAction, false, ERROR_CODE_IDEMPOTENCY_BACKEND_OPERATION_ERROR)) {
|
|
47285
|
+
this.isIdempotencySupported = false;
|
|
47286
|
+
retryDelayInMs = 0;
|
|
47287
|
+
actionDataChanged = true;
|
|
47288
|
+
}
|
|
47122
47289
|
break;
|
|
47290
|
+
}
|
|
47123
47291
|
case 409 /* IdempotentWriteSpecificHttpStatusCode.Conflict */: {
|
|
47124
|
-
|
|
47125
|
-
|
|
47126
|
-
|
|
47127
|
-
|
|
47292
|
+
if (this.isUiApiErrors(response.body)) {
|
|
47293
|
+
const errorCode = response.body[0].errorCode;
|
|
47294
|
+
if (this.handleIdempotencyServerError(response.body, updatedAction, true, ERROR_CODE_IDEMPOTENCY_KEY_USED_DIFFERENT_USER)) {
|
|
47295
|
+
retryDelayInMs = 0;
|
|
47296
|
+
actionDataChanged = true;
|
|
47297
|
+
}
|
|
47298
|
+
else if (errorCode === ERROR_CODE_IDEMPOTENCY_CONCURRENT_REQUEST) {
|
|
47299
|
+
retryDelayInMs = getRetryAfterInMs(response.headers);
|
|
47300
|
+
}
|
|
47301
|
+
shouldRetry = true;
|
|
47302
|
+
}
|
|
47303
|
+
break;
|
|
47304
|
+
}
|
|
47305
|
+
case HttpStatusCode$1.BadRequest: {
|
|
47306
|
+
if (this.handleIdempotencyServerError(response.body, updatedAction, false, ERROR_CODE_IDEMPOTENCY_FEATURE_NOT_ENABLED, ERROR_CODE_IDEMPOTENCY_NOT_SUPPORTED)) {
|
|
47128
47307
|
retryDelayInMs = 0;
|
|
47129
47308
|
actionDataChanged = true;
|
|
47309
|
+
shouldRetry = true;
|
|
47130
47310
|
}
|
|
47131
|
-
|
|
47132
|
-
|
|
47311
|
+
break;
|
|
47312
|
+
}
|
|
47313
|
+
case 422 /* IdempotentWriteSpecificHttpStatusCode.UnProcessableEntity */: {
|
|
47314
|
+
if (this.handleIdempotencyServerError(response.body, updatedAction, true, ERROR_CODE_IDEMPOTENCY_KEY_ALREADY_USED)) {
|
|
47315
|
+
retryDelayInMs = 0;
|
|
47316
|
+
actionDataChanged = true;
|
|
47317
|
+
shouldRetry = true;
|
|
47133
47318
|
}
|
|
47134
|
-
shouldRetry = true;
|
|
47135
47319
|
break;
|
|
47136
47320
|
}
|
|
47137
47321
|
}
|
|
@@ -47150,6 +47334,27 @@ class AbstractResourceRequestActionHandler {
|
|
|
47150
47334
|
return ProcessActionResult.NETWORK_ERROR;
|
|
47151
47335
|
}
|
|
47152
47336
|
}
|
|
47337
|
+
// 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.
|
|
47338
|
+
handleIdempotencyServerError(responseBody, action, updateIdempotencyKey, ...targetErrorCodes) {
|
|
47339
|
+
if (this.isUiApiErrors(responseBody)) {
|
|
47340
|
+
const errorCode = responseBody[0].errorCode;
|
|
47341
|
+
if (targetErrorCodes.includes(errorCode)) {
|
|
47342
|
+
action.data.headers = action.data.headers || {};
|
|
47343
|
+
if (updateIdempotencyKey) {
|
|
47344
|
+
action.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
|
|
47345
|
+
}
|
|
47346
|
+
else {
|
|
47347
|
+
delete action.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY];
|
|
47348
|
+
}
|
|
47349
|
+
return true;
|
|
47350
|
+
}
|
|
47351
|
+
}
|
|
47352
|
+
return false;
|
|
47353
|
+
}
|
|
47354
|
+
// 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.
|
|
47355
|
+
isUiApiErrors(body) {
|
|
47356
|
+
return body !== undefined && Array.isArray(body) && body.length > 0 && body[0].errorCode;
|
|
47357
|
+
}
|
|
47153
47358
|
async buildPendingAction(request, queue) {
|
|
47154
47359
|
const targetId = await this.getIdFromRequest(request);
|
|
47155
47360
|
if (targetId === undefined) {
|
|
@@ -47363,6 +47568,10 @@ class AbstractResourceRequestActionHandler {
|
|
|
47363
47568
|
...targetData,
|
|
47364
47569
|
body: this.mergeRequestBody(targetBody, sourceBody),
|
|
47365
47570
|
};
|
|
47571
|
+
// Updates Idempotency key if target has one
|
|
47572
|
+
if (targetData.headers && targetData.headers[HTTP_HEADER_IDEMPOTENCY_KEY]) {
|
|
47573
|
+
merged.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
|
|
47574
|
+
}
|
|
47366
47575
|
// overlay metadata
|
|
47367
47576
|
merged.metadata = { ...targetMetadata, ...sourceMetadata };
|
|
47368
47577
|
// put status back to pending to auto upload if queue is active and targed is at the head.
|
|
@@ -47399,6 +47608,9 @@ class AbstractResourceRequestActionHandler {
|
|
|
47399
47608
|
getDraftIdsFromAction(action) {
|
|
47400
47609
|
return [action.targetId];
|
|
47401
47610
|
}
|
|
47611
|
+
hasIdempotencySupport() {
|
|
47612
|
+
return this.isIdempotencySupported && !this.isLdsIdempotencyWriteDisabled;
|
|
47613
|
+
}
|
|
47402
47614
|
async ingestResponses(responses, action) {
|
|
47403
47615
|
const luvio = this.getLuvio();
|
|
47404
47616
|
await luvio.handleSuccessResponse(() => {
|
|
@@ -47830,49 +48042,6 @@ function makeEnvironmentDraftAware(luvio, env, durableStore, handlers, draftQueu
|
|
|
47830
48042
|
});
|
|
47831
48043
|
}
|
|
47832
48044
|
|
|
47833
|
-
/**
|
|
47834
|
-
* Copyright (c) 2022, Salesforce, Inc.,
|
|
47835
|
-
* All rights reserved.
|
|
47836
|
-
* For full license text, see the LICENSE.txt file
|
|
47837
|
-
*/
|
|
47838
|
-
|
|
47839
|
-
const API_NAMESPACE$1 = 'UiApi';
|
|
47840
|
-
const RECORD_REPRESENTATION_NAME$2 = 'RecordRepresentation';
|
|
47841
|
-
const RECORD_VIEW_ENTITY_REPRESENTATION_NAME$1 = 'RecordViewEntityRepresentation';
|
|
47842
|
-
const RECORD_ID_PREFIX$1 = `${API_NAMESPACE$1}::${RECORD_REPRESENTATION_NAME$2}:`;
|
|
47843
|
-
const RECORD_VIEW_ENTITY_ID_PREFIX$1 = `${API_NAMESPACE$1}::${RECORD_VIEW_ENTITY_REPRESENTATION_NAME$1}:Name:`;
|
|
47844
|
-
const RECORD_FIELDS_KEY_JUNCTION$1 = '__fields__';
|
|
47845
|
-
function isStoreKeyRecordId(key) {
|
|
47846
|
-
return key.indexOf(RECORD_ID_PREFIX$1) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION$1) === -1;
|
|
47847
|
-
}
|
|
47848
|
-
function isStoreKeyRecordViewEntity$1(key) {
|
|
47849
|
-
return (key.indexOf(RECORD_VIEW_ENTITY_ID_PREFIX$1) > -1 &&
|
|
47850
|
-
key.indexOf(RECORD_FIELDS_KEY_JUNCTION$1) === -1);
|
|
47851
|
-
}
|
|
47852
|
-
function isStoreKeyRecordField(key) {
|
|
47853
|
-
return key.indexOf(RECORD_ID_PREFIX$1) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION$1) > -1;
|
|
47854
|
-
}
|
|
47855
|
-
function extractRecordIdFromStoreKey$1(key) {
|
|
47856
|
-
if (key === undefined ||
|
|
47857
|
-
(key.indexOf(RECORD_ID_PREFIX$1) === -1 && key.indexOf(RECORD_VIEW_ENTITY_ID_PREFIX$1) === -1)) {
|
|
47858
|
-
return undefined;
|
|
47859
|
-
}
|
|
47860
|
-
const parts = key.split(':');
|
|
47861
|
-
return parts[parts.length - 1].split('_')[0];
|
|
47862
|
-
}
|
|
47863
|
-
function buildRecordFieldStoreKey(recordKey, fieldName) {
|
|
47864
|
-
return `${recordKey}${RECORD_FIELDS_KEY_JUNCTION$1}${fieldName}`;
|
|
47865
|
-
}
|
|
47866
|
-
|
|
47867
|
-
function isStoreRecordError(storeRecord) {
|
|
47868
|
-
return storeRecord.__type === 'error';
|
|
47869
|
-
}
|
|
47870
|
-
function isEntryDurableRecordRepresentation(entry, key) {
|
|
47871
|
-
// Either a DurableRecordRepresentation or StoreRecordError can live at a record key
|
|
47872
|
-
return ((isStoreKeyRecordId(key) || isStoreKeyRecordViewEntity$1(key)) &&
|
|
47873
|
-
entry.data.__type === undefined);
|
|
47874
|
-
}
|
|
47875
|
-
|
|
47876
48045
|
function serializeFieldArguments$1(argumentNodes, variables) {
|
|
47877
48046
|
const mutableArgumentNodes = Object.assign([], argumentNodes);
|
|
47878
48047
|
return `args__(${mutableArgumentNodes
|
|
@@ -49247,6 +49416,10 @@ function isOperationDefinitionNode(node) {
|
|
|
49247
49416
|
return node.kind === 'OperationDefinition';
|
|
49248
49417
|
}
|
|
49249
49418
|
|
|
49419
|
+
const POLYMORPHIC_PARENT_RELATIONSHIP = 'polymorphicParentRelationship';
|
|
49420
|
+
const PARENT_RELATIONSHIP = 'parentRelationship';
|
|
49421
|
+
const CHILD_RELATIONSHIP = 'childRelationship';
|
|
49422
|
+
const RECORD_QUERY = 'recordQuery';
|
|
49250
49423
|
function requestsDraftsField(recordFieldNode) {
|
|
49251
49424
|
if (!recordFieldNode.selectionSet)
|
|
49252
49425
|
return false;
|
|
@@ -49262,18 +49435,41 @@ function isRecordQuery(recordQueryField) {
|
|
|
49262
49435
|
directive.arguments
|
|
49263
49436
|
.map((argument) => argument.value)
|
|
49264
49437
|
.filter(isStringValueNode)
|
|
49265
|
-
.some((categoryName) => categoryName.value ===
|
|
49438
|
+
.some((categoryName) => categoryName.value === RECORD_QUERY));
|
|
49266
49439
|
});
|
|
49267
49440
|
}
|
|
49268
49441
|
return false;
|
|
49269
49442
|
}
|
|
49270
|
-
// finds field with 'recordQuery' and 'childRelationship' directive
|
|
49271
|
-
function
|
|
49272
|
-
const
|
|
49273
|
-
return
|
|
49443
|
+
// finds connection field with 'recordQuery' and 'childRelationship' directive.
|
|
49444
|
+
function findNearestConnection(ancestors) {
|
|
49445
|
+
const connectionAncestor = findNearestAncesterPath(ancestors, true).node;
|
|
49446
|
+
return connectionAncestor === undefined ? undefined : connectionAncestor;
|
|
49447
|
+
}
|
|
49448
|
+
// convinient method to find nearest connection with its path
|
|
49449
|
+
function findNearestConnectionWithPath(ancestors) {
|
|
49450
|
+
const closestAncestorPath = findNearestAncesterPath(ancestors, true);
|
|
49451
|
+
let connection = undefined;
|
|
49452
|
+
let connectionPath = undefined;
|
|
49453
|
+
if (closestAncestorPath.parentIndex > 0) {
|
|
49454
|
+
const connectionAncestor = closestAncestorPath.node;
|
|
49455
|
+
const connectionAncestors = ancestors.slice(0, closestAncestorPath.parentIndex);
|
|
49456
|
+
connection =
|
|
49457
|
+
connectionAncestor === undefined ? undefined : connectionAncestor;
|
|
49458
|
+
if (connection !== undefined) {
|
|
49459
|
+
const ancesterPath = findAncesterPath(connectionAncestors);
|
|
49460
|
+
connectionPath =
|
|
49461
|
+
ancesterPath === ''
|
|
49462
|
+
? connection.name.value
|
|
49463
|
+
: `${ancesterPath}#${connection.name.value}`;
|
|
49464
|
+
}
|
|
49465
|
+
}
|
|
49466
|
+
return {
|
|
49467
|
+
connection,
|
|
49468
|
+
path: connectionPath,
|
|
49469
|
+
};
|
|
49274
49470
|
}
|
|
49275
|
-
// finds
|
|
49276
|
-
function findNearestAncesterPath(ancestors,
|
|
49471
|
+
// 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.
|
|
49472
|
+
function findNearestAncesterPath(ancestors, connectionOnly) {
|
|
49277
49473
|
let recordQueryPath = { node: undefined, parentIndex: -1 };
|
|
49278
49474
|
let relationship = '';
|
|
49279
49475
|
for (let i = ancestors.length - 1; i >= 0; i--) {
|
|
@@ -49287,9 +49483,11 @@ function findNearestAncesterPath(ancestors, recordQueryOnly) {
|
|
|
49287
49483
|
continue;
|
|
49288
49484
|
for (let arg of directive.arguments) {
|
|
49289
49485
|
if (arg.value &&
|
|
49290
|
-
(arg.value.value ===
|
|
49291
|
-
arg.value.value ===
|
|
49292
|
-
(!
|
|
49486
|
+
(arg.value.value === RECORD_QUERY ||
|
|
49487
|
+
arg.value.value === CHILD_RELATIONSHIP ||
|
|
49488
|
+
(!connectionOnly &&
|
|
49489
|
+
(arg.value.value === PARENT_RELATIONSHIP ||
|
|
49490
|
+
arg.value.value === POLYMORPHIC_PARENT_RELATIONSHIP)))) {
|
|
49293
49491
|
recordQueryPath = { node: node, parentIndex: i };
|
|
49294
49492
|
relationship = arg.value.value;
|
|
49295
49493
|
break;
|
|
@@ -49304,17 +49502,19 @@ function findNearestAncesterPath(ancestors, recordQueryOnly) {
|
|
|
49304
49502
|
//checks if nearest ancester could be an inline fragment
|
|
49305
49503
|
if (recordQueryPath.node !== undefined &&
|
|
49306
49504
|
recordQueryPath.node.selectionSet &&
|
|
49307
|
-
relationship ===
|
|
49308
|
-
//
|
|
49309
|
-
|
|
49310
|
-
|
|
49311
|
-
|
|
49312
|
-
if (
|
|
49505
|
+
(relationship === PARENT_RELATIONSHIP || relationship === POLYMORPHIC_PARENT_RELATIONSHIP)) {
|
|
49506
|
+
// InlineFragment is usually 3 steps aways from its FieldNode parent within ancester hierarchy if it exists. The below search
|
|
49507
|
+
// is applied to adapt to future AST structure change
|
|
49508
|
+
let parentIndex = recordQueryPath.parentIndex + 1;
|
|
49509
|
+
while (parentIndex < ancestors.length) {
|
|
49510
|
+
if (isInlineFragmentNode(ancestors[parentIndex])) {
|
|
49313
49511
|
recordQueryPath = {
|
|
49314
|
-
node: ancestors[
|
|
49315
|
-
parentIndex
|
|
49512
|
+
node: ancestors[parentIndex],
|
|
49513
|
+
parentIndex,
|
|
49316
49514
|
};
|
|
49515
|
+
break;
|
|
49317
49516
|
}
|
|
49517
|
+
parentIndex++;
|
|
49318
49518
|
}
|
|
49319
49519
|
}
|
|
49320
49520
|
return recordQueryPath;
|
|
@@ -49338,7 +49538,7 @@ function findAncesterPath(ancesters) {
|
|
|
49338
49538
|
? sectionPath
|
|
49339
49539
|
: sectionPath === ''
|
|
49340
49540
|
? path
|
|
49341
|
-
: `${sectionPath}
|
|
49541
|
+
: `${sectionPath}#${path}`;
|
|
49342
49542
|
}
|
|
49343
49543
|
}
|
|
49344
49544
|
boundaryIndex = parentIndex;
|
|
@@ -49396,9 +49596,9 @@ function getRelation(node) {
|
|
|
49396
49596
|
const relationships = args
|
|
49397
49597
|
.map((arg) => arg.value)
|
|
49398
49598
|
.filter(isStringValueNode)
|
|
49399
|
-
.filter((valueNode) => valueNode.value ===
|
|
49400
|
-
valueNode.value ===
|
|
49401
|
-
valueNode.value ===
|
|
49599
|
+
.filter((valueNode) => valueNode.value === CHILD_RELATIONSHIP ||
|
|
49600
|
+
valueNode.value === PARENT_RELATIONSHIP ||
|
|
49601
|
+
valueNode.value === POLYMORPHIC_PARENT_RELATIONSHIP)
|
|
49402
49602
|
.map((relationshipNode) => relationshipNode.value);
|
|
49403
49603
|
if (relationships.length > 0) {
|
|
49404
49604
|
return relationships[0];
|
|
@@ -49455,8 +49655,8 @@ function isFieldSpanning(node, parentNode) {
|
|
|
49455
49655
|
*/
|
|
49456
49656
|
function isParentRelationship(node) {
|
|
49457
49657
|
return (node &&
|
|
49458
|
-
(isRelationship(node,
|
|
49459
|
-
isRelationship(node,
|
|
49658
|
+
(isRelationship(node, PARENT_RELATIONSHIP) ||
|
|
49659
|
+
isRelationship(node, POLYMORPHIC_PARENT_RELATIONSHIP)));
|
|
49460
49660
|
}
|
|
49461
49661
|
/*
|
|
49462
49662
|
checks if the InlineFragment spans
|
|
@@ -49762,6 +49962,26 @@ function findFieldInfo(objectInfo, fieldName) {
|
|
|
49762
49962
|
return values$1(objectInfo.fields).find((field) => field.apiName === fieldName ||
|
|
49763
49963
|
(field.dataType === 'Reference' && field.relationshipName === fieldName));
|
|
49764
49964
|
}
|
|
49965
|
+
async function readIngestionTimestampForKey(key, query) {
|
|
49966
|
+
let ingestionTimestamp = 0;
|
|
49967
|
+
const sql = `
|
|
49968
|
+
SELECT json_extract(metadata, '${JSON_EXTRACT_PATH_INGESTION_TIMESTAMP}')
|
|
49969
|
+
FROM lds_data
|
|
49970
|
+
WHERE key IS ?
|
|
49971
|
+
`;
|
|
49972
|
+
const results = await query(sql, [key]);
|
|
49973
|
+
const [timestamp] = results.rows.map((row) => row[0]);
|
|
49974
|
+
if (timestamp !== null) {
|
|
49975
|
+
const numericalTimestamp = Number(timestamp);
|
|
49976
|
+
if (isNaN(numericalTimestamp)) {
|
|
49977
|
+
return ingestionTimestamp;
|
|
49978
|
+
}
|
|
49979
|
+
// adjust the timestamp to account for ingestion processing time
|
|
49980
|
+
// 30s is used because this is the default record TTL
|
|
49981
|
+
ingestionTimestamp = numericalTimestamp - 30000;
|
|
49982
|
+
}
|
|
49983
|
+
return ingestionTimestamp;
|
|
49984
|
+
}
|
|
49765
49985
|
|
|
49766
49986
|
function findSpanningField(name) {
|
|
49767
49987
|
return (field) => {
|
|
@@ -50281,17 +50501,7 @@ async function fetchIngestionTimeStampFromDatabase(apiName, info, args, query) {
|
|
|
50281
50501
|
const key = buildKeyStringForRecordQuery(operation,
|
|
50282
50502
|
// join varables passed from query to the argument variables given from the AST
|
|
50283
50503
|
{ ...variableValues, ...args }, info.fieldNodes[0].arguments, apiName);
|
|
50284
|
-
|
|
50285
|
-
SELECT json_extract(metadata, '${JSON_EXTRACT_PATH_INGESTION_TIMESTAMP}')
|
|
50286
|
-
FROM lds_data
|
|
50287
|
-
WHERE key IS ?
|
|
50288
|
-
`;
|
|
50289
|
-
const results = await query(sql, [key]);
|
|
50290
|
-
const [timestamp] = results.rows.map((row) => row[0]);
|
|
50291
|
-
if (timestamp !== null && typeof timestamp === 'number') {
|
|
50292
|
-
//go back 10 ms to adjust for margin of error when top level query is stored and when raml objects are stored
|
|
50293
|
-
ingestionTimestamp = timestamp - 10;
|
|
50294
|
-
}
|
|
50504
|
+
return readIngestionTimestampForKey(key, query);
|
|
50295
50505
|
}
|
|
50296
50506
|
return ingestionTimestamp;
|
|
50297
50507
|
}
|
|
@@ -50339,26 +50549,20 @@ function generateRecordQueries(objectInfos) {
|
|
|
50339
50549
|
let recordConnections = ``;
|
|
50340
50550
|
const polymorphicFieldTypeNames = new Set();
|
|
50341
50551
|
let typedScalars = new Set();
|
|
50552
|
+
let parentRelationshipFields = new Set();
|
|
50342
50553
|
for (const objectInfo of values$1(objectInfos)) {
|
|
50343
50554
|
const { apiName, childRelationships } = objectInfo;
|
|
50344
50555
|
let fields = ``;
|
|
50345
50556
|
typedScalars.add(`${apiName}_Filter`);
|
|
50346
50557
|
typedScalars.add(`${apiName}_OrderBy`);
|
|
50347
|
-
for (const childRelationship of childRelationships) {
|
|
50348
|
-
const { childObjectApiName } = childRelationship;
|
|
50349
|
-
// Only add the relationship if there is relevant objectinfos for it,
|
|
50350
|
-
// otherwise we'd be defining types we cannot satisfy and aren't referenced in
|
|
50351
|
-
// the query.
|
|
50352
|
-
if (objectInfos[childObjectApiName] !== undefined) {
|
|
50353
|
-
fields += `${childRelationship.relationshipName}(first: Int, where: ${childObjectApiName}_Filter, orderBy: ${childObjectApiName}_OrderBy, scope: SupportedScopes): ${childObjectApiName}Connection \n`;
|
|
50354
|
-
typedScalars.add(`${childObjectApiName}_Filter`);
|
|
50355
|
-
typedScalars.add(`${childObjectApiName}_OrderBy`);
|
|
50356
|
-
}
|
|
50357
|
-
}
|
|
50358
50558
|
for (const field of values$1(objectInfo.fields)) {
|
|
50359
50559
|
if (!fieldsStaticallyAdded.includes(field.apiName)) {
|
|
50360
50560
|
fields += `${field.apiName}: ${dataTypeToType(field.dataType, field.apiName)}\n`;
|
|
50361
50561
|
}
|
|
50562
|
+
//handles parent relationship
|
|
50563
|
+
if (field.relationshipName === null) {
|
|
50564
|
+
continue;
|
|
50565
|
+
}
|
|
50362
50566
|
// For spanning parent relationships with no union types
|
|
50363
50567
|
if (field.referenceToInfos.length === 1) {
|
|
50364
50568
|
const [relation] = field.referenceToInfos;
|
|
@@ -50366,11 +50570,13 @@ function generateRecordQueries(objectInfos) {
|
|
|
50366
50570
|
// otherwise we'd be defining types we cannot satisfy and aren't referenced in
|
|
50367
50571
|
// the query.
|
|
50368
50572
|
if (objectInfos[relation.apiName] !== undefined) {
|
|
50573
|
+
parentRelationshipFields.add(field.relationshipName);
|
|
50369
50574
|
fields += `${field.relationshipName}: ${relation.apiName}\n`;
|
|
50370
50575
|
}
|
|
50371
50576
|
// For polymorphic field, its type is 'Record' inteface. The concrete entity type name is saved for field resolving of next phase
|
|
50372
50577
|
}
|
|
50373
50578
|
else if (field.referenceToInfos.length > 1) {
|
|
50579
|
+
parentRelationshipFields.add(field.relationshipName);
|
|
50374
50580
|
fields += `${field.relationshipName}: Record\n`;
|
|
50375
50581
|
for (const relation of field.referenceToInfos) {
|
|
50376
50582
|
if (objectInfos[relation.apiName] !== undefined) {
|
|
@@ -50379,6 +50585,20 @@ function generateRecordQueries(objectInfos) {
|
|
|
50379
50585
|
}
|
|
50380
50586
|
}
|
|
50381
50587
|
}
|
|
50588
|
+
// handles child relationship
|
|
50589
|
+
for (const childRelationship of childRelationships) {
|
|
50590
|
+
const { childObjectApiName } = childRelationship;
|
|
50591
|
+
// Only add the relationship if there is relevant objectinfos for it,
|
|
50592
|
+
// otherwise we'd be defining types we cannot satisfy and aren't referenced in
|
|
50593
|
+
// the query.
|
|
50594
|
+
// 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
|
|
50595
|
+
if (objectInfos[childObjectApiName] !== undefined &&
|
|
50596
|
+
!parentRelationshipFields.has(childRelationship.relationshipName)) {
|
|
50597
|
+
fields += `${childRelationship.relationshipName}(first: Int, where: ${childObjectApiName}_Filter, orderBy: ${childObjectApiName}_OrderBy, scope: SupportedScopes): ${childObjectApiName}Connection \n`;
|
|
50598
|
+
typedScalars.add(`${childObjectApiName}_Filter`);
|
|
50599
|
+
typedScalars.add(`${childObjectApiName}_OrderBy`);
|
|
50600
|
+
}
|
|
50601
|
+
}
|
|
50382
50602
|
recordQueries += `${apiName}(first: Int, where: ${apiName}_Filter, orderBy: ${apiName}_OrderBy, scope: SupportedScopes): ${apiName}Connection\n`;
|
|
50383
50603
|
const isServiceAppointment = apiName === 'ServiceAppointment';
|
|
50384
50604
|
recordConnections += /* GraphQL */ `
|
|
@@ -50453,6 +50673,8 @@ function dataTypeToType(objectInfoDataType, apiName) {
|
|
|
50453
50673
|
return 'PercentValue';
|
|
50454
50674
|
case 'Int':
|
|
50455
50675
|
return 'IntValue';
|
|
50676
|
+
case 'EncryptedString':
|
|
50677
|
+
return 'EncryptedStringValue';
|
|
50456
50678
|
// ! do the rest of the custom types
|
|
50457
50679
|
default:
|
|
50458
50680
|
return 'String';
|
|
@@ -50538,7 +50760,7 @@ const parentRelationshipDirective = {
|
|
|
50538
50760
|
},
|
|
50539
50761
|
value: {
|
|
50540
50762
|
kind: Kind.STRING,
|
|
50541
|
-
value:
|
|
50763
|
+
value: PARENT_RELATIONSHIP,
|
|
50542
50764
|
block: false,
|
|
50543
50765
|
},
|
|
50544
50766
|
},
|
|
@@ -50552,8 +50774,8 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
50552
50774
|
// example 2 'ServiceAppointment' -> ['Owner']; 'Owner' -> ['User', 'Group']
|
|
50553
50775
|
const objectNodeInfoTree = {};
|
|
50554
50776
|
// save the field path to apiName map
|
|
50555
|
-
// example 1: 'ServiceAppointment' -> ['ServiceAppointment']; '
|
|
50556
|
-
const
|
|
50777
|
+
// example 1: 'ServiceAppointment' -> ['ServiceAppointment']; 'ServiceAppointment#ccount' -> ['Account']; 'ServiceAppointment#Account#Owner' -> ['User']
|
|
50778
|
+
const pathToObjectApiNamesMap = {};
|
|
50557
50779
|
let startNodes = new Set();
|
|
50558
50780
|
let totalNodes = new Set();
|
|
50559
50781
|
let objectInfos = {};
|
|
@@ -50567,11 +50789,11 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
50567
50789
|
visit(originalAST, {
|
|
50568
50790
|
Argument: {
|
|
50569
50791
|
enter(node, key, parent, path, ancestors) {
|
|
50570
|
-
const
|
|
50571
|
-
if (!
|
|
50792
|
+
const { connection: recordConnectionNode, path: ancesterPath } = findNearestConnectionWithPath(ancestors);
|
|
50793
|
+
if (!recordConnectionNode || !ancesterPath)
|
|
50572
50794
|
return;
|
|
50573
|
-
if (!objectNodeInfoTree[
|
|
50574
|
-
objectNodeInfoTree[
|
|
50795
|
+
if (!objectNodeInfoTree[ancesterPath]) {
|
|
50796
|
+
objectNodeInfoTree[ancesterPath] = [];
|
|
50575
50797
|
}
|
|
50576
50798
|
switch (node.name.value) {
|
|
50577
50799
|
case 'orderBy':
|
|
@@ -50579,12 +50801,12 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
50579
50801
|
if (node.value.kind !== 'ObjectValue') {
|
|
50580
50802
|
return;
|
|
50581
50803
|
}
|
|
50582
|
-
totalNodes.add(
|
|
50804
|
+
totalNodes.add(ancesterPath);
|
|
50583
50805
|
// 'childRelationship' node is not taken as the startNode of the 'NodeInfoTree' graph. The field scanning will construct the graph which lead here.
|
|
50584
|
-
if (isRecordQuery(
|
|
50585
|
-
startNodes.add(
|
|
50806
|
+
if (isRecordQuery(recordConnectionNode)) {
|
|
50807
|
+
startNodes.add(recordConnectionNode.name.value);
|
|
50586
50808
|
}
|
|
50587
|
-
growObjectFieldTree(objectNodeInfoTree,
|
|
50809
|
+
growObjectFieldTree(objectNodeInfoTree, ancesterPath, node.value, totalNodes, startNodes);
|
|
50588
50810
|
break;
|
|
50589
50811
|
case 'scope':
|
|
50590
50812
|
if (!isScopeArgumentNodeWithType(node, 'ASSIGNEDTOME', variables)) {
|
|
@@ -50599,17 +50821,16 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
50599
50821
|
name: 'ServiceResources',
|
|
50600
50822
|
});
|
|
50601
50823
|
}
|
|
50602
|
-
if (objectNodeInfoTree['ServiceResources'] === undefined) {
|
|
50603
|
-
objectNodeInfoTree['ServiceResources'] = [
|
|
50604
|
-
|
|
50605
|
-
|
|
50606
|
-
|
|
50607
|
-
|
|
50608
|
-
|
|
50609
|
-
});
|
|
50824
|
+
if (objectNodeInfoTree['ServiceAppointment#ServiceResources'] === undefined) {
|
|
50825
|
+
objectNodeInfoTree['ServiceAppointment#ServiceResources'] = [
|
|
50826
|
+
{
|
|
50827
|
+
relation: 'parent',
|
|
50828
|
+
name: 'ServiceResource',
|
|
50829
|
+
},
|
|
50830
|
+
];
|
|
50610
50831
|
}
|
|
50611
|
-
if (objectNodeInfoTree['ServiceResource'] === undefined) {
|
|
50612
|
-
objectNodeInfoTree['ServiceResource'] = [];
|
|
50832
|
+
if (objectNodeInfoTree['ServiceAppointment#ServiceResources#ServiceResource'] === undefined) {
|
|
50833
|
+
objectNodeInfoTree['ServiceAppointment#ServiceResources#ServiceResource'] = [];
|
|
50613
50834
|
}
|
|
50614
50835
|
break;
|
|
50615
50836
|
default:
|
|
@@ -50623,7 +50844,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
50623
50844
|
return;
|
|
50624
50845
|
if (!node.selectionSet)
|
|
50625
50846
|
return;
|
|
50626
|
-
const recordQueryField =
|
|
50847
|
+
const recordQueryField = findNearestConnection(ancestors);
|
|
50627
50848
|
//only injects fields for 'recordQuery' field. ignores the 'childRelationship' field since it will be traversed as the child of the 'recordQuery'
|
|
50628
50849
|
if (isRecordQuery(recordQueryField) && recordQueryField) {
|
|
50629
50850
|
totalNodes.add(recordQueryField.name.value);
|
|
@@ -50634,21 +50855,21 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
50634
50855
|
},
|
|
50635
50856
|
});
|
|
50636
50857
|
if (objectInfoService && startNodes.size > 0) {
|
|
50637
|
-
objectInfos = await resolveObjectInfos(objectNodeInfoTree,
|
|
50858
|
+
objectInfos = await resolveObjectInfos(objectNodeInfoTree, pathToObjectApiNamesMap, startNodes, objectInfoService);
|
|
50638
50859
|
}
|
|
50639
50860
|
// read pass; gather whats needed
|
|
50640
50861
|
visit(originalAST, {
|
|
50641
50862
|
Argument: {
|
|
50642
50863
|
leave(node, key, parent, path, ancestors) {
|
|
50643
|
-
const recordQueryField =
|
|
50864
|
+
const recordQueryField = findNearestConnection(ancestors);
|
|
50644
50865
|
if (!recordQueryField)
|
|
50645
50866
|
return;
|
|
50646
50867
|
const ancestorPath = findAncesterPath(ancestors);
|
|
50647
50868
|
if (!inlineFragmentSelections[ancestorPath]) {
|
|
50648
50869
|
inlineFragmentSelections[ancestorPath] = [];
|
|
50649
50870
|
}
|
|
50650
|
-
const recordQueryApiName =
|
|
50651
|
-
?
|
|
50871
|
+
const recordQueryApiName = pathToObjectApiNamesMap[ancestorPath]
|
|
50872
|
+
? pathToObjectApiNamesMap[ancestorPath][0]
|
|
50652
50873
|
: recordQueryField.name.value;
|
|
50653
50874
|
// The record node acts as the reference. The duplicated field in the record node is not injected
|
|
50654
50875
|
const recordReferenceNode = [recordQueryField]
|
|
@@ -50662,7 +50883,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
50662
50883
|
case 'scope':
|
|
50663
50884
|
// Hanle 'MINE' field
|
|
50664
50885
|
if (isScopeArgumentNodeWithType(node, 'MINE', variables)) {
|
|
50665
|
-
if (isMineScopeAvailable(ancestorPath,
|
|
50886
|
+
if (isMineScopeAvailable(ancestorPath, pathToObjectApiNamesMap, objectInfos)) {
|
|
50666
50887
|
// 'typeConditon' is added when the 'InlineFragmentNode' is appended at the write pass
|
|
50667
50888
|
inlineFragmentSelections[ancestorPath].push(...mineFragmentSelections);
|
|
50668
50889
|
}
|
|
@@ -50688,7 +50909,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
50688
50909
|
case 'where': {
|
|
50689
50910
|
inlineFragmentSelections[ancestorPath] = [
|
|
50690
50911
|
...inlineFragmentSelections[ancestorPath],
|
|
50691
|
-
...injectFilter(node, idState, ancestorPath, objectInfos,
|
|
50912
|
+
...injectFilter(node, idState, ancestorPath, false, objectInfos, pathToObjectApiNamesMap, draftFunctions, recordReferenceNode),
|
|
50692
50913
|
];
|
|
50693
50914
|
break;
|
|
50694
50915
|
}
|
|
@@ -50704,7 +50925,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
50704
50925
|
if (!node.selectionSet)
|
|
50705
50926
|
return;
|
|
50706
50927
|
// it could be 'recordQuery' or 'childRelationship'
|
|
50707
|
-
const recordQueryField =
|
|
50928
|
+
const recordQueryField = findNearestConnection(ancestors);
|
|
50708
50929
|
if (!recordQueryField)
|
|
50709
50930
|
return;
|
|
50710
50931
|
const ancestorPath = findAncesterPath(ancestors);
|
|
@@ -50716,7 +50937,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
50716
50937
|
spanningSelections.push(selection);
|
|
50717
50938
|
}
|
|
50718
50939
|
}
|
|
50719
|
-
const injectedFields = injectFields(spanningSelections, node, ancestors, objectInfos,
|
|
50940
|
+
const injectedFields = injectFields(spanningSelections, node, ancestorPath, ancestors, objectInfos, pathToObjectApiNamesMap);
|
|
50720
50941
|
const mergedInjectedFields = mergeSelectionNodes$1(inlineFragmentSelections[ancestorPath], injectedFields);
|
|
50721
50942
|
inlineFragmentSelections[ancestorPath] = mergedInjectedFields;
|
|
50722
50943
|
},
|
|
@@ -50729,7 +50950,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
50729
50950
|
// removes 'ServicesResources' query field node if 'assignedtome' scope shows up
|
|
50730
50951
|
if (assignedtomeQueryFieldNode !== undefined &&
|
|
50731
50952
|
node.name.value === 'ServiceResources') {
|
|
50732
|
-
const serviceResourcesAncestor =
|
|
50953
|
+
const serviceResourcesAncestor = findNearestConnection(ancestors);
|
|
50733
50954
|
if (serviceResourcesAncestor === assignedtomeQueryFieldNode) {
|
|
50734
50955
|
return null;
|
|
50735
50956
|
}
|
|
@@ -50738,7 +50959,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
50738
50959
|
return;
|
|
50739
50960
|
if (!node.selectionSet)
|
|
50740
50961
|
return;
|
|
50741
|
-
const recordQueryField =
|
|
50962
|
+
const recordQueryField = findNearestConnection(ancestors);
|
|
50742
50963
|
if (!recordQueryField)
|
|
50743
50964
|
return;
|
|
50744
50965
|
const ancestorPath = findAncesterPath(ancestors);
|
|
@@ -50747,8 +50968,8 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
50747
50968
|
return;
|
|
50748
50969
|
//const recordQueryPath = findAncesterPath(ancestors);
|
|
50749
50970
|
// '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.
|
|
50750
|
-
const recordQueryApiName =
|
|
50751
|
-
?
|
|
50971
|
+
const recordQueryApiName = pathToObjectApiNamesMap[ancestorPath]
|
|
50972
|
+
? pathToObjectApiNamesMap[ancestorPath][0]
|
|
50752
50973
|
: recordQueryField.name.value;
|
|
50753
50974
|
const nodeWithFragments = {
|
|
50754
50975
|
...node,
|
|
@@ -50785,7 +51006,7 @@ async function injectSyntheticFields(originalAST, objectInfoService, draftFuncti
|
|
|
50785
51006
|
if (node.name.value === 'where') {
|
|
50786
51007
|
const ancestorPath = findAncesterPath(ancestors);
|
|
50787
51008
|
if (idState.paths.includes(ancestorPath)) {
|
|
50788
|
-
const apiName =
|
|
51009
|
+
const apiName = pathToObjectApiNamesMap[ancestorPath][0];
|
|
50789
51010
|
const objectInfo = objectInfos[apiName];
|
|
50790
51011
|
const swappedIdFilter = swapIdField(node.value, objectInfo, false, idState, draftFunctions);
|
|
50791
51012
|
return {
|
|
@@ -50851,8 +51072,8 @@ function swapIdField(filterFields, objectInfo, swapped, idState, draftFunctions)
|
|
|
50851
51072
|
};
|
|
50852
51073
|
}
|
|
50853
51074
|
}
|
|
50854
|
-
function isMineScopeAvailable(apiNamePath,
|
|
50855
|
-
const apiName =
|
|
51075
|
+
function isMineScopeAvailable(apiNamePath, pathToObjectApiNamesMap, objectInfos) {
|
|
51076
|
+
const apiName = pathToObjectApiNamesMap[apiNamePath];
|
|
50856
51077
|
if (!apiName)
|
|
50857
51078
|
return false;
|
|
50858
51079
|
const objectInfo = objectInfos[apiName[0]];
|
|
@@ -50941,15 +51162,16 @@ function growObjectFieldTree(tree, parentNode, entryNode, totalNodes, startNodes
|
|
|
50941
51162
|
}
|
|
50942
51163
|
// example: 'Account'
|
|
50943
51164
|
const childNode = objectFieldNode.name.value;
|
|
51165
|
+
const childNodepath = `${parentNode}#${childNode}`;
|
|
50944
51166
|
if (!tree[parentNode].some((child) => child.name === childNode)) {
|
|
50945
51167
|
tree[parentNode].push({
|
|
50946
51168
|
relation: 'parent',
|
|
50947
51169
|
name: childNode,
|
|
50948
51170
|
});
|
|
50949
|
-
totalNodes.add(
|
|
51171
|
+
totalNodes.add(childNodepath);
|
|
50950
51172
|
}
|
|
50951
51173
|
// recursively go to deeper level of filter.
|
|
50952
|
-
growObjectFieldTree(tree,
|
|
51174
|
+
growObjectFieldTree(tree, childNodepath, objectFieldNode.value, totalNodes, startNodes);
|
|
50953
51175
|
}
|
|
50954
51176
|
}
|
|
50955
51177
|
}
|
|
@@ -50984,19 +51206,20 @@ function growFieldTree(tree, parentSectionPath, entryNode, parentNode, totalNode
|
|
|
50984
51206
|
}
|
|
50985
51207
|
if (!tree[parentSectionPath].some((field) => field.name === fieldName)) {
|
|
50986
51208
|
tree[parentSectionPath].push({
|
|
50987
|
-
relation: relationType ===
|
|
50988
|
-
relationType ===
|
|
51209
|
+
relation: relationType === PARENT_RELATIONSHIP ||
|
|
51210
|
+
relationType === POLYMORPHIC_PARENT_RELATIONSHIP
|
|
50989
51211
|
? 'parent'
|
|
50990
51212
|
: 'child',
|
|
50991
51213
|
name: fieldName,
|
|
50992
51214
|
});
|
|
50993
|
-
totalNodes.add(fieldName);
|
|
51215
|
+
totalNodes.add(`${parentSectionPath}#${fieldName}`);
|
|
50994
51216
|
}
|
|
50995
51217
|
if (entryNode.selectionSet && entryNode.selectionSet.selections) {
|
|
50996
51218
|
const childNodes = entryNode.selectionSet.selections.filter(isFieldOrInlineFragmentNode);
|
|
50997
51219
|
// recursively build the traversal tree
|
|
50998
51220
|
for (const child of childNodes) {
|
|
50999
|
-
|
|
51221
|
+
const path = `${parentSectionPath}#${fieldName}`;
|
|
51222
|
+
growFieldTree(tree, path, child, entryNode, totalNodes, startNodes);
|
|
51000
51223
|
}
|
|
51001
51224
|
}
|
|
51002
51225
|
}
|
|
@@ -51026,23 +51249,23 @@ function growFieldTree(tree, parentSectionPath, entryNode, parentNode, totalNode
|
|
|
51026
51249
|
}
|
|
51027
51250
|
if (!tree[parentSectionPath].some((field) => field.name === conditionName)) {
|
|
51028
51251
|
tree[parentSectionPath].push({
|
|
51029
|
-
relation: relationType ===
|
|
51030
|
-
relationType ===
|
|
51252
|
+
relation: relationType === PARENT_RELATIONSHIP ||
|
|
51253
|
+
relationType === POLYMORPHIC_PARENT_RELATIONSHIP
|
|
51031
51254
|
? 'parent'
|
|
51032
51255
|
: 'child',
|
|
51033
51256
|
name: conditionName,
|
|
51034
51257
|
});
|
|
51035
|
-
|
|
51258
|
+
const path = `${parentSectionPath}#${conditionName}`;
|
|
51259
|
+
totalNodes.add(path);
|
|
51036
51260
|
}
|
|
51037
51261
|
}
|
|
51038
51262
|
}
|
|
51039
51263
|
// dive deep immediately for 'InlineFragment'
|
|
51040
51264
|
const childNodes = entryNode.selectionSet.selections.filter(isFieldOrInlineFragmentNode);
|
|
51265
|
+
const path = `${parentSectionPath}${entryNode.typeCondition ? '#' + entryNode.typeCondition.name.value : ''}`;
|
|
51041
51266
|
// Navigates into InLineFragment
|
|
51042
51267
|
for (const child of childNodes) {
|
|
51043
|
-
growFieldTree(tree, entryNode
|
|
51044
|
-
? entryNode.typeCondition.name.value
|
|
51045
|
-
: parentSectionPath, child, entryNode, totalNodes, startNodes);
|
|
51268
|
+
growFieldTree(tree, path, child, entryNode, totalNodes, startNodes);
|
|
51046
51269
|
}
|
|
51047
51270
|
}
|
|
51048
51271
|
}
|
|
@@ -51054,7 +51277,7 @@ function growFieldTree(tree, parentSectionPath, entryNode, parentNode, totalNode
|
|
|
51054
51277
|
* @param startNodes start nodes of the tree. It can be used to fetch ObjectInfo immediately
|
|
51055
51278
|
* @param path
|
|
51056
51279
|
*/
|
|
51057
|
-
async function resolveObjectInfos(objectInfotree,
|
|
51280
|
+
async function resolveObjectInfos(objectInfotree, pathToObjectApiNamesMap, startNodes, objectInfoService) {
|
|
51058
51281
|
let objectInfos;
|
|
51059
51282
|
try {
|
|
51060
51283
|
objectInfos = await objectInfoService.getObjectInfos(Array.from(startNodes));
|
|
@@ -51068,9 +51291,9 @@ async function resolveObjectInfos(objectInfotree, objectInfoApiMap, startNodes,
|
|
|
51068
51291
|
throw new Error(`Unable to resolve ObjectInfo(s) for ${Array.from(startNodes)}`);
|
|
51069
51292
|
}
|
|
51070
51293
|
for (const startNode of startNodes) {
|
|
51071
|
-
|
|
51294
|
+
pathToObjectApiNamesMap[startNode] = [startNode];
|
|
51072
51295
|
const children = objectInfotree[startNode];
|
|
51073
|
-
const subObjectInfoMap = await fetchObjectInfos(objectInfotree,
|
|
51296
|
+
const subObjectInfoMap = await fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, objectInfos, children, startNode, objectInfoService);
|
|
51074
51297
|
objectInfos = { ...objectInfos, ...subObjectInfoMap };
|
|
51075
51298
|
}
|
|
51076
51299
|
return objectInfos;
|
|
@@ -51078,15 +51301,15 @@ async function resolveObjectInfos(objectInfotree, objectInfoApiMap, startNodes,
|
|
|
51078
51301
|
// example 1: 'parentPath': 'ServiceAppointment', 'nodesAtSameLevel': ['Account']
|
|
51079
51302
|
// example 2: 'parentPath': 'ServiceAppointment', 'nodesAtSameLevel': ['Owner'], this example has 2 apiName for the node 'Owner'
|
|
51080
51303
|
// example 3: 'parentPath': 'ServiceAppointment_Owner', 'nodesAtSameLevel': ['User', 'Group']
|
|
51081
|
-
async function fetchObjectInfos(objectInfotree,
|
|
51082
|
-
const objectInfoApiNames =
|
|
51304
|
+
async function fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, objectInfoMap, nodesAtSameLevel, parentPath, objectInfoService) {
|
|
51305
|
+
const objectInfoApiNames = pathToObjectApiNamesMap[parentPath];
|
|
51083
51306
|
if (!objectInfoApiNames) {
|
|
51084
51307
|
// eslint-disable-next-line
|
|
51085
51308
|
throw new Error(`Object Info does not exist for ${parentPath}`);
|
|
51086
51309
|
}
|
|
51087
51310
|
const validObjectInfoNodes = [];
|
|
51088
51311
|
let updatedObjectInfoMap = {};
|
|
51089
|
-
// InlineFragment and polymorphic field support fits into this scenario
|
|
51312
|
+
// InlineFragment and polymorphic field support fits into this scenario pathToObjectApiNamesMap Entry: 'ServiceAppointment#Owner' -> ['User', 'Group']; ServiceAppointment#Owner#User' -> ['User']
|
|
51090
51313
|
if (objectInfoApiNames.length > 0 &&
|
|
51091
51314
|
nodesAtSameLevel.length > 0 &&
|
|
51092
51315
|
objectInfoApiNames.includes(nodesAtSameLevel[0].name)) {
|
|
@@ -51098,8 +51321,8 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
|
|
|
51098
51321
|
// eslint-disable-next-line
|
|
51099
51322
|
throw new Error(`Condition ${field.name} does not exists for ${parentPath}`);
|
|
51100
51323
|
}
|
|
51101
|
-
const path = `${parentPath}
|
|
51102
|
-
|
|
51324
|
+
const path = `${parentPath}#${field.name}`;
|
|
51325
|
+
pathToObjectApiNamesMap[path] = [field.name];
|
|
51103
51326
|
}
|
|
51104
51327
|
validObjectInfoNodes.push(...nodesAtSameLevel);
|
|
51105
51328
|
updatedObjectInfoMap = { ...objectInfoMap };
|
|
@@ -51114,7 +51337,7 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
|
|
|
51114
51337
|
let apiNames = [];
|
|
51115
51338
|
for (const nodeInfo of nodesAtSameLevel) {
|
|
51116
51339
|
const field = nodeInfo.name;
|
|
51117
|
-
const path = `${parentPath}
|
|
51340
|
+
const path = `${parentPath}#${field}`;
|
|
51118
51341
|
// Handle 'parentRelationship'
|
|
51119
51342
|
if (nodeInfo.relation === 'parent') {
|
|
51120
51343
|
const relationshipId = referenceIdFieldForRelationship(field);
|
|
@@ -51132,21 +51355,21 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
|
|
|
51132
51355
|
}
|
|
51133
51356
|
}
|
|
51134
51357
|
// This is a polymorphic field
|
|
51135
|
-
if (fieldDefinition.referenceToInfos.length > 1 && objectInfotree[
|
|
51358
|
+
if (fieldDefinition.referenceToInfos.length > 1 && objectInfotree[path]) {
|
|
51136
51359
|
// Fields needs to expand and heterogenous entity ObjectInfo needs to be fetched
|
|
51137
|
-
const referencedNodeInfos = objectInfotree[
|
|
51360
|
+
const referencedNodeInfos = objectInfotree[path];
|
|
51138
51361
|
const requestedApiNames = referencedNodeInfos.map((referenceNodeInfo) => referenceNodeInfo.name);
|
|
51139
51362
|
// 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.
|
|
51140
|
-
if (requestedApiNames.length > 0 && objectInfotree[
|
|
51363
|
+
if (requestedApiNames.length > 0 && objectInfotree[path]) {
|
|
51141
51364
|
fieldDefinition.referenceToInfos
|
|
51142
51365
|
.filter((referenceToInfo) => requestedApiNames.includes(referenceToInfo.apiName))
|
|
51143
51366
|
.forEach((ref) => {
|
|
51144
|
-
if (!
|
|
51145
|
-
|
|
51367
|
+
if (!pathToObjectApiNamesMap[path]) {
|
|
51368
|
+
pathToObjectApiNamesMap[path] = [];
|
|
51146
51369
|
}
|
|
51147
51370
|
// 'ServiceAppointment_Owner' ->['User', 'Group']
|
|
51148
|
-
if (!
|
|
51149
|
-
|
|
51371
|
+
if (!pathToObjectApiNamesMap[path].includes(ref.apiName)) {
|
|
51372
|
+
pathToObjectApiNamesMap[path].push(ref.apiName);
|
|
51150
51373
|
}
|
|
51151
51374
|
if (!apiNames.includes(ref.apiName)) {
|
|
51152
51375
|
apiNames.push(ref.apiName);
|
|
@@ -51156,11 +51379,11 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
|
|
|
51156
51379
|
}
|
|
51157
51380
|
else if (fieldDefinition.referenceToInfos.length === 1) {
|
|
51158
51381
|
const ref = fieldDefinition.referenceToInfos[0];
|
|
51159
|
-
if (!
|
|
51160
|
-
|
|
51382
|
+
if (!pathToObjectApiNamesMap[path]) {
|
|
51383
|
+
pathToObjectApiNamesMap[path] = [];
|
|
51161
51384
|
}
|
|
51162
|
-
if (!
|
|
51163
|
-
|
|
51385
|
+
if (!pathToObjectApiNamesMap[path].includes(ref.apiName)) {
|
|
51386
|
+
pathToObjectApiNamesMap[path].push(ref.apiName);
|
|
51164
51387
|
}
|
|
51165
51388
|
if (!apiNames.includes(ref.apiName)) {
|
|
51166
51389
|
apiNames.push(ref.apiName);
|
|
@@ -51171,11 +51394,11 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
|
|
|
51171
51394
|
// handles 'childRelationship'
|
|
51172
51395
|
const childRelationship = parentObjectInfo.childRelationships.find((childRelationship) => childRelationship.relationshipName === field);
|
|
51173
51396
|
if (childRelationship) {
|
|
51174
|
-
if (!
|
|
51175
|
-
|
|
51397
|
+
if (!pathToObjectApiNamesMap[path]) {
|
|
51398
|
+
pathToObjectApiNamesMap[path] = [];
|
|
51176
51399
|
}
|
|
51177
|
-
if (!
|
|
51178
|
-
|
|
51400
|
+
if (!pathToObjectApiNamesMap[path].includes(childRelationship.childObjectApiName)) {
|
|
51401
|
+
pathToObjectApiNamesMap[path].push(childRelationship.childObjectApiName);
|
|
51179
51402
|
}
|
|
51180
51403
|
if (!apiNames.includes(childRelationship.childObjectApiName)) {
|
|
51181
51404
|
apiNames.push(childRelationship.childObjectApiName);
|
|
@@ -51197,10 +51420,10 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
|
|
|
51197
51420
|
}
|
|
51198
51421
|
for (const nodeInfo of validObjectInfoNodes) {
|
|
51199
51422
|
const field = nodeInfo.name;
|
|
51200
|
-
const
|
|
51201
|
-
const
|
|
51423
|
+
const path = `${parentPath}#${field}`;
|
|
51424
|
+
const subLevelFields = objectInfotree[path];
|
|
51202
51425
|
if (subLevelFields && subLevelFields.length > 0) {
|
|
51203
|
-
const subObjectInfos = await fetchObjectInfos(objectInfotree,
|
|
51426
|
+
const subObjectInfos = await fetchObjectInfos(objectInfotree, pathToObjectApiNamesMap, updatedObjectInfoMap, subLevelFields, path, objectInfoService);
|
|
51204
51427
|
updatedObjectInfoMap = { ...updatedObjectInfoMap, ...subObjectInfos };
|
|
51205
51428
|
}
|
|
51206
51429
|
}
|
|
@@ -51215,27 +51438,29 @@ async function fetchObjectInfos(objectInfotree, objectInfoApiMap, objectInfoMap,
|
|
|
51215
51438
|
* 'path' and 'queryNode' is 1 level above the 'filterNode'
|
|
51216
51439
|
* @param filterNode filter node which needs to be injected. For example, 'State' ObjectFieldNode within filter 'where: { State: { eq: "Nova Scotia" }}'
|
|
51217
51440
|
* @param idState ID state will be updated to determine if the ID fields in AST need to be swapped. The swapping happens later.
|
|
51218
|
-
* @param
|
|
51441
|
+
* @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
|
|
51442
|
+
* @param isParentPolymorphic true if parent points to a polymorphic field.
|
|
51219
51443
|
* @param queryNode referece FieldNode which provides the information if 'filterNode' exist in it nor not.
|
|
51220
51444
|
* @param objectInfos ObjectInfo map used in injection. If ObjectInfo misses or field does not exist in ObjectInfo, the error will be thrown
|
|
51221
|
-
* @param
|
|
51445
|
+
* @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'].
|
|
51222
51446
|
* @param draftFunctions functions for working with record ids that may be draft-created ids
|
|
51223
51447
|
* @returns an array of nodes with injected fields
|
|
51224
51448
|
*/
|
|
51225
|
-
function injectFilter(filterNode, idState,
|
|
51449
|
+
function injectFilter(filterNode, idState, parentPath, isParentPolymorphic, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode) {
|
|
51226
51450
|
const injectedSelections = [];
|
|
51451
|
+
let isPolymorphicField = false;
|
|
51227
51452
|
switch (filterNode.kind) {
|
|
51228
51453
|
case Kind.ARGUMENT:
|
|
51229
51454
|
if (filterNode.value.kind !== 'ObjectValue')
|
|
51230
51455
|
return [];
|
|
51231
51456
|
filterNode.value.fields.forEach((objectFieldNode) => {
|
|
51232
|
-
let subResults = injectFilter(objectFieldNode, idState,
|
|
51457
|
+
let subResults = injectFilter(objectFieldNode, idState, parentPath, isParentPolymorphic, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode);
|
|
51233
51458
|
for (const subResult of subResults) {
|
|
51234
51459
|
mergeOrAddToGroup(injectedSelections, subResult);
|
|
51235
51460
|
}
|
|
51236
51461
|
// multiple Ids might need to be swapped. remember their paths for faster write.
|
|
51237
51462
|
if (idState.swapNeeded) {
|
|
51238
|
-
idState.paths.push(
|
|
51463
|
+
idState.paths.push(parentPath);
|
|
51239
51464
|
}
|
|
51240
51465
|
});
|
|
51241
51466
|
return injectedSelections;
|
|
@@ -51244,7 +51469,7 @@ function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap,
|
|
|
51244
51469
|
case Kind.LIST: {
|
|
51245
51470
|
filterNode.value.values.filter(isObjectValueNode).forEach((objectValueNode) => {
|
|
51246
51471
|
objectValueNode.fields.forEach((objectFieldNode) => {
|
|
51247
|
-
const subResults = injectFilter(objectFieldNode, idState,
|
|
51472
|
+
const subResults = injectFilter(objectFieldNode, idState, parentPath, isParentPolymorphic, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode);
|
|
51248
51473
|
for (const subResult of subResults) {
|
|
51249
51474
|
mergeOrAddToGroup(injectedSelections, subResult);
|
|
51250
51475
|
}
|
|
@@ -51255,7 +51480,7 @@ function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap,
|
|
|
51255
51480
|
case Kind.OBJECT: {
|
|
51256
51481
|
if (filterNode.name.value === 'not') {
|
|
51257
51482
|
filterNode.value.fields.forEach((objectFieldNode) => {
|
|
51258
|
-
const subResults = injectFilter(objectFieldNode, idState,
|
|
51483
|
+
const subResults = injectFilter(objectFieldNode, idState, parentPath, isParentPolymorphic, objectInfos, pathToObjectApiNamesMap, draftFunctions, queryNode);
|
|
51259
51484
|
for (const subResult of subResults) {
|
|
51260
51485
|
mergeOrAddToGroup(injectedSelections, subResult);
|
|
51261
51486
|
}
|
|
@@ -51265,15 +51490,15 @@ function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap,
|
|
|
51265
51490
|
let apiNames = [];
|
|
51266
51491
|
let isScalarField = false;
|
|
51267
51492
|
//It is possible that this is a polymorphic field
|
|
51268
|
-
apiNames =
|
|
51269
|
-
// example: path: '
|
|
51493
|
+
apiNames = pathToObjectApiNamesMap[parentPath];
|
|
51494
|
+
// example: path: 'ServiceAppointment#LastModifiedDate'; filterNode: '{eq: {literal: LAST_WEEK}}'. queryNode: 'LastModifedDate { value}' FilterNode's parent has been verifed as a valid node
|
|
51270
51495
|
if (apiNames === undefined) {
|
|
51271
51496
|
isScalarField = true;
|
|
51272
51497
|
}
|
|
51273
51498
|
else {
|
|
51274
51499
|
if (apiNames.some((apiName) => objectInfos[apiName] === undefined)) {
|
|
51275
51500
|
// eslint-disable-next-line
|
|
51276
|
-
throw new Error(`ObjectInfo is missing for ${
|
|
51501
|
+
throw new Error(`ObjectInfo is missing for ${parentPath}`);
|
|
51277
51502
|
}
|
|
51278
51503
|
}
|
|
51279
51504
|
if (isScalarField) {
|
|
@@ -51295,29 +51520,19 @@ function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap,
|
|
|
51295
51520
|
}
|
|
51296
51521
|
});
|
|
51297
51522
|
let isSpanning = false;
|
|
51523
|
+
// if true, current node is a polymorphic concrete type node. For example, field node `User` under `Owner`
|
|
51298
51524
|
let isInlineFragment = false;
|
|
51299
|
-
let isPolymorphicField = false;
|
|
51300
51525
|
let isTypeNameExisting = false;
|
|
51301
51526
|
let curPath;
|
|
51302
51527
|
let fieldName = filterNode.name.value;
|
|
51303
|
-
curPath = `${
|
|
51304
|
-
if (
|
|
51528
|
+
curPath = `${parentPath}#${fieldName}`;
|
|
51529
|
+
if (pathToObjectApiNamesMap[curPath] &&
|
|
51530
|
+
pathToObjectApiNamesMap[curPath].length > 0) {
|
|
51305
51531
|
isSpanning = true;
|
|
51306
|
-
|
|
51307
|
-
|
|
51308
|
-
|
|
51309
|
-
|
|
51310
|
-
isInlineFragment = true;
|
|
51311
|
-
}
|
|
51312
|
-
}
|
|
51313
|
-
// Checks if the current filter node is a polymorphic field. 'ServiceAppointment_Owner' --> ['User']; 'ServiceAppointment_Owner_User' --> ['User']
|
|
51314
|
-
const childApiName = objectInfoApiMap[curPath][0];
|
|
51315
|
-
const trialApiNames = objectInfoApiMap[`${curPath}_${childApiName}`];
|
|
51316
|
-
if (trialApiNames !== undefined &&
|
|
51317
|
-
trialApiNames.length === 1 &&
|
|
51318
|
-
trialApiNames[0] === childApiName) {
|
|
51319
|
-
isPolymorphicField = true;
|
|
51320
|
-
}
|
|
51532
|
+
isInlineFragment =
|
|
51533
|
+
isParentPolymorphic &&
|
|
51534
|
+
pathToObjectApiNamesMap[curPath].length === 1;
|
|
51535
|
+
isPolymorphicField = isPolymorphicFieldPath(curPath, pathToObjectApiNamesMap, objectInfos);
|
|
51321
51536
|
}
|
|
51322
51537
|
// 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]
|
|
51323
51538
|
if (isInlineFragment) {
|
|
@@ -51361,23 +51576,25 @@ function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap,
|
|
|
51361
51576
|
throw new Error(`Field ${fieldName} does not exist in ${apiNames[0]}`);
|
|
51362
51577
|
}
|
|
51363
51578
|
}
|
|
51364
|
-
const objectInfoName =
|
|
51365
|
-
?
|
|
51366
|
-
:
|
|
51579
|
+
const objectInfoName = pathToObjectApiNamesMap[curPath] !== undefined
|
|
51580
|
+
? pathToObjectApiNamesMap[curPath][0]
|
|
51581
|
+
: pathToObjectApiNamesMap[parentPath][0];
|
|
51367
51582
|
const isIdField = isFieldAnIdField(filterNode.name.value, objectInfos[objectInfoName]);
|
|
51368
51583
|
if (!isIdField) {
|
|
51369
51584
|
let subSelectionNodes = [];
|
|
51370
51585
|
let subFieldsHasId = false;
|
|
51371
|
-
|
|
51372
|
-
|
|
51373
|
-
|
|
51374
|
-
|
|
51375
|
-
|
|
51376
|
-
|
|
51377
|
-
|
|
51378
|
-
|
|
51379
|
-
|
|
51380
|
-
|
|
51586
|
+
if (isSpanning) {
|
|
51587
|
+
filterNode.value.fields.forEach((subFieldNode) => {
|
|
51588
|
+
// Check if the filter field has the 'Id'
|
|
51589
|
+
if (isFieldAnIdField(subFieldNode.name.value, objectInfos[objectInfoName])) {
|
|
51590
|
+
subFieldsHasId = true;
|
|
51591
|
+
updateIDInfo(subFieldNode, idState, draftFunctions);
|
|
51592
|
+
}
|
|
51593
|
+
// try injecting the fields within predicate no matter it has relation or not.
|
|
51594
|
+
let subResults = injectFilter(subFieldNode, idState, curPath, isPolymorphicField, objectInfos, pathToObjectApiNamesMap, draftFunctions, existingFields ? existingFields[0] : undefined);
|
|
51595
|
+
subSelectionNodes = subSelectionNodes.concat(subResults);
|
|
51596
|
+
});
|
|
51597
|
+
}
|
|
51381
51598
|
if (!subFieldsHasId) {
|
|
51382
51599
|
// Check if the query field has the 'Id'
|
|
51383
51600
|
const existingIdsInQuery = existingFields &&
|
|
@@ -51406,6 +51623,7 @@ function injectFilter(filterNode, idState, path, objectInfos, objectInfoApiMap,
|
|
|
51406
51623
|
}
|
|
51407
51624
|
//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
|
|
51408
51625
|
if (!existingFields ||
|
|
51626
|
+
existingFields.length === 0 ||
|
|
51409
51627
|
subSelectionNodes.length > 0 ||
|
|
51410
51628
|
(isSpanning && !subFieldsHasId) ||
|
|
51411
51629
|
(isInlineFragment && !isTypeNameExisting)) {
|
|
@@ -51536,6 +51754,44 @@ function mergeOrAddToGroup(group, element) {
|
|
|
51536
51754
|
}
|
|
51537
51755
|
group.push(element);
|
|
51538
51756
|
}
|
|
51757
|
+
// checks if the path points to a polymorphic field. For example, for the below `pathToObjectApiNamesMap`
|
|
51758
|
+
// {
|
|
51759
|
+
// 'ServiceAppointment' -> ['ServiceAppointment']
|
|
51760
|
+
// 'ServiceAppointment#Owner' --> ['User'],
|
|
51761
|
+
// 'ServiceAppointment#Owner#User' --> ['User']
|
|
51762
|
+
// }
|
|
51763
|
+
// path `ServiceAppointment#Owner` points to a polymorphic field, but path `ServiceAppointment#Owner#User` does not.
|
|
51764
|
+
function isPolymorphicFieldPath(path, pathToObjectApiNamesMap, objectInfos) {
|
|
51765
|
+
const lastSegmentIndex = path.lastIndexOf('#');
|
|
51766
|
+
if (lastSegmentIndex < 0) {
|
|
51767
|
+
return false;
|
|
51768
|
+
}
|
|
51769
|
+
const lastSegment = path.slice(lastSegmentIndex + 1);
|
|
51770
|
+
const parentApiPath = path.slice(0, lastSegmentIndex);
|
|
51771
|
+
if (pathToObjectApiNamesMap[parentApiPath] === undefined) {
|
|
51772
|
+
return false;
|
|
51773
|
+
}
|
|
51774
|
+
const parentObjectApiNames = pathToObjectApiNamesMap[parentApiPath];
|
|
51775
|
+
// 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`.
|
|
51776
|
+
// 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.
|
|
51777
|
+
// Below are the entries in `pathToObjectApiNamesMap`
|
|
51778
|
+
// {
|
|
51779
|
+
// `ServiceAppointmen`t: [`ServiceAppointment`],
|
|
51780
|
+
// `ServiceAppointment#Owner`: [`User`, `Group`],
|
|
51781
|
+
// `ServiceAppointment#Owner#User`: [`User`],
|
|
51782
|
+
// `ServiceAppointment#Owner#Group`: [`Group`],
|
|
51783
|
+
// }
|
|
51784
|
+
if (parentObjectApiNames.length !== 1) {
|
|
51785
|
+
return false;
|
|
51786
|
+
}
|
|
51787
|
+
const parentObjectInfo = objectInfos[parentObjectApiNames[0]];
|
|
51788
|
+
const relationshipField = referenceIdFieldForRelationship(lastSegment);
|
|
51789
|
+
let fieldDefinition = parentObjectInfo.fields[relationshipField];
|
|
51790
|
+
if (fieldDefinition === undefined) {
|
|
51791
|
+
return false;
|
|
51792
|
+
}
|
|
51793
|
+
return fieldDefinition.polymorphicForeignKey;
|
|
51794
|
+
}
|
|
51539
51795
|
function isFieldAnIdField(fieldName, objectInfo) {
|
|
51540
51796
|
if (fieldName === 'Id')
|
|
51541
51797
|
return true;
|
|
@@ -51588,10 +51844,10 @@ function updateIDInfo(fieldNode, idState, draftFunctions) {
|
|
|
51588
51844
|
* @param parentNode parent node of param 1
|
|
51589
51845
|
* @param ancestors ancester of param 1
|
|
51590
51846
|
* @param objectInfos ObjectInfo map used in injection. If ObjectInfo misses or field does not exist in ObjectInfo, the error will be thrown
|
|
51591
|
-
* @param
|
|
51847
|
+
* @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'].
|
|
51592
51848
|
* @return injected SelectionNodes used to construct the InlineFragment.
|
|
51593
51849
|
*/
|
|
51594
|
-
function injectFields(selections, parentNode, ancestors, objectInfos,
|
|
51850
|
+
function injectFields(selections, parentNode, parentPath, ancestors, objectInfos, pathToObjectApiNamesMap) {
|
|
51595
51851
|
/**
|
|
51596
51852
|
* 1 parentship can return 2 FieldNode which need to be flattened
|
|
51597
51853
|
* Concact: { ** Contact { ** ContactId {
|
|
@@ -51609,6 +51865,10 @@ function injectFields(selections, parentNode, ancestors, objectInfos, objectInfo
|
|
|
51609
51865
|
if (!selection.selectionSet) {
|
|
51610
51866
|
return selection;
|
|
51611
51867
|
}
|
|
51868
|
+
const segment = isFieldNode(selection)
|
|
51869
|
+
? selection.name.value
|
|
51870
|
+
: selection.typeCondition.name.value;
|
|
51871
|
+
const curPath = `${parentPath}#${segment}`;
|
|
51612
51872
|
const spanningSubSelections = [];
|
|
51613
51873
|
for (const subSelection of selection.selectionSet.selections) {
|
|
51614
51874
|
if (isFieldSpanning(subSelection, selection)) {
|
|
@@ -51616,7 +51876,7 @@ function injectFields(selections, parentNode, ancestors, objectInfos, objectInfo
|
|
|
51616
51876
|
}
|
|
51617
51877
|
}
|
|
51618
51878
|
// Handles multiple level field injection like 'ServiceAppointment' --> 'Account' --> 'Owner'
|
|
51619
|
-
const subInjectedSelections = injectFields(spanningSubSelections, selection, ancestors, objectInfos,
|
|
51879
|
+
const subInjectedSelections = injectFields(spanningSubSelections, selection, curPath, ancestors, objectInfos, pathToObjectApiNamesMap);
|
|
51620
51880
|
if (!selection.selectionSet) {
|
|
51621
51881
|
return selection;
|
|
51622
51882
|
}
|
|
@@ -51659,7 +51919,7 @@ function injectFields(selections, parentNode, ancestors, objectInfos, objectInfo
|
|
|
51659
51919
|
}
|
|
51660
51920
|
}
|
|
51661
51921
|
// For polymorphic fields, the Id field is excluded.
|
|
51662
|
-
const excludeId =
|
|
51922
|
+
const excludeId = isPolymorphicFieldPath(curPath, pathToObjectApiNamesMap, objectInfos);
|
|
51663
51923
|
const idSelection = [];
|
|
51664
51924
|
if (!excludeId && !hasIdAlready) {
|
|
51665
51925
|
idSelection.push({
|
|
@@ -51670,8 +51930,8 @@ function injectFields(selections, parentNode, ancestors, objectInfos, objectInfo
|
|
|
51670
51930
|
},
|
|
51671
51931
|
});
|
|
51672
51932
|
}
|
|
51673
|
-
// Inject '__typename' for
|
|
51674
|
-
// please reference 'removeSyntheticFields'.
|
|
51933
|
+
// 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
|
|
51934
|
+
// `typedCondition` of the InlineFragment in the query AST. It is used to match JSON response with AST node. For more detail, please reference 'removeSyntheticFields'.
|
|
51675
51935
|
if (isInlineFragmentNode(selection) &&
|
|
51676
51936
|
!selection.selectionSet.selections.find((selection) => isFieldNode(selection) && selection.name.value === '__typename')) {
|
|
51677
51937
|
idSelection.push({
|
|
@@ -51705,7 +51965,7 @@ function injectFields(selections, parentNode, ancestors, objectInfos, objectInfo
|
|
|
51705
51965
|
if (isFieldNode(parentNode) && parentNode.selectionSet && parentNode.name.value === 'node') {
|
|
51706
51966
|
if (parentNode.selectionSet.selections
|
|
51707
51967
|
.filter(isFieldOrInlineFragmentNode)
|
|
51708
|
-
.some((selectionNode) => isRelationship(selectionNode,
|
|
51968
|
+
.some((selectionNode) => isRelationship(selectionNode, CHILD_RELATIONSHIP))) {
|
|
51709
51969
|
if (!parentNode.selectionSet.selections
|
|
51710
51970
|
.filter(isFieldNode)
|
|
51711
51971
|
.some((sibling) => sibling.name.value === 'Id')) {
|
|
@@ -51724,15 +51984,15 @@ function injectFields(selections, parentNode, ancestors, objectInfos, objectInfo
|
|
|
51724
51984
|
if (parentInfo.parentIndex >= 0) {
|
|
51725
51985
|
// example node { TimeSheetEntries { edges { node { Id }}}}
|
|
51726
51986
|
const parent = parentInfo.node;
|
|
51727
|
-
if (isRelationship(parent,
|
|
51987
|
+
if (isRelationship(parent, CHILD_RELATIONSHIP)) {
|
|
51728
51988
|
const unVisitedAncestors = ancestors.slice(0, parentInfo.parentIndex);
|
|
51729
51989
|
// path : "TimeSheet"
|
|
51730
51990
|
const grandParentPath = findAncesterPath(unVisitedAncestors);
|
|
51731
|
-
if (
|
|
51732
|
-
|
|
51991
|
+
if (pathToObjectApiNamesMap &&
|
|
51992
|
+
pathToObjectApiNamesMap[grandParentPath] &&
|
|
51733
51993
|
objectInfos &&
|
|
51734
|
-
objectInfos[
|
|
51735
|
-
const grandParentObjectInfo = objectInfos[
|
|
51994
|
+
objectInfos[pathToObjectApiNamesMap[grandParentPath][0]]) {
|
|
51995
|
+
const grandParentObjectInfo = objectInfos[pathToObjectApiNamesMap[grandParentPath][0]];
|
|
51736
51996
|
// exmaple "TimeSheetEntries"
|
|
51737
51997
|
const parentFieldName = parent.name.value;
|
|
51738
51998
|
const targetRelationship = grandParentObjectInfo.childRelationships.find((childRelationship) => {
|
|
@@ -51853,7 +52113,7 @@ const assignedToMeFragmentSelections = [
|
|
|
51853
52113
|
},
|
|
51854
52114
|
value: {
|
|
51855
52115
|
kind: 'StringValue',
|
|
51856
|
-
value:
|
|
52116
|
+
value: CHILD_RELATIONSHIP,
|
|
51857
52117
|
block: false,
|
|
51858
52118
|
},
|
|
51859
52119
|
},
|
|
@@ -51945,7 +52205,7 @@ const assignedToMeFragmentSelections = [
|
|
|
51945
52205
|
},
|
|
51946
52206
|
value: {
|
|
51947
52207
|
kind: 'StringValue',
|
|
51948
|
-
value:
|
|
52208
|
+
value: PARENT_RELATIONSHIP,
|
|
51949
52209
|
block: false,
|
|
51950
52210
|
},
|
|
51951
52211
|
},
|
|
@@ -52082,7 +52342,9 @@ function handleNonArrayJsonProperty(selection, fieldName, jsonInput, jsonOutput)
|
|
|
52082
52342
|
jsonOutput[fieldName] = null;
|
|
52083
52343
|
return;
|
|
52084
52344
|
}
|
|
52085
|
-
jsonOutput[fieldName]
|
|
52345
|
+
if (jsonOutput[fieldName] === undefined) {
|
|
52346
|
+
jsonOutput[fieldName] = {};
|
|
52347
|
+
}
|
|
52086
52348
|
createUserJsonOutput(selection, jsonInput[fieldName], jsonOutput[fieldName]);
|
|
52087
52349
|
}
|
|
52088
52350
|
else {
|
|
@@ -52814,34 +53076,42 @@ function applyReferenceLinksToDraft(record, draftMetadata) {
|
|
|
52814
53076
|
}
|
|
52815
53077
|
const { dataType, relationshipName, referenceToInfos } = fieldInfo;
|
|
52816
53078
|
const draftFieldValue = record.fields[draftField].value;
|
|
52817
|
-
if (dataType === 'Reference' && relationshipName !== null
|
|
52818
|
-
if (
|
|
52819
|
-
|
|
53079
|
+
if (dataType === 'Reference' && relationshipName !== null) {
|
|
53080
|
+
if (draftFieldValue === null) {
|
|
53081
|
+
recordFields[relationshipName] = {
|
|
53082
|
+
displayValue: null,
|
|
53083
|
+
value: null,
|
|
53084
|
+
};
|
|
52820
53085
|
}
|
|
52821
|
-
|
|
52822
|
-
|
|
52823
|
-
|
|
52824
|
-
displayValue: null,
|
|
52825
|
-
value: createLink$2(key),
|
|
52826
|
-
};
|
|
52827
|
-
// for custom objects, we select the 'Name' field
|
|
52828
|
-
// otherwise we check the object info for name fields.
|
|
52829
|
-
//if there are multiple we select 'Name' if it exists, otherwise the first one
|
|
52830
|
-
if (referencedRecord !== undefined && referenceToInfos.length > 0) {
|
|
52831
|
-
let nameField;
|
|
52832
|
-
const referenceToInfo = referenceToInfos[0];
|
|
52833
|
-
const nameFields = referenceToInfo.nameFields;
|
|
52834
|
-
if (nameFields.length !== 0) {
|
|
52835
|
-
nameField = nameFields.find((x) => x === 'Name');
|
|
52836
|
-
if (nameField === undefined) {
|
|
52837
|
-
nameField = nameFields[0];
|
|
52838
|
-
}
|
|
53086
|
+
else {
|
|
53087
|
+
if (typeof draftFieldValue !== 'string') {
|
|
53088
|
+
throw Error('reference field value is not a string');
|
|
52839
53089
|
}
|
|
52840
|
-
|
|
52841
|
-
|
|
52842
|
-
|
|
52843
|
-
|
|
52844
|
-
|
|
53090
|
+
const key = getRecordKeyForId(luvio, draftFieldValue);
|
|
53091
|
+
const referencedRecord = referencedRecords.get(key);
|
|
53092
|
+
recordFields[relationshipName] = {
|
|
53093
|
+
displayValue: null,
|
|
53094
|
+
value: createLink$2(key),
|
|
53095
|
+
};
|
|
53096
|
+
// for custom objects, we select the 'Name' field
|
|
53097
|
+
// otherwise we check the object info for name fields.
|
|
53098
|
+
//if there are multiple we select 'Name' if it exists, otherwise the first one
|
|
53099
|
+
if (referencedRecord !== undefined && referenceToInfos.length > 0) {
|
|
53100
|
+
let nameField;
|
|
53101
|
+
const referenceToInfo = referenceToInfos[0];
|
|
53102
|
+
const nameFields = referenceToInfo.nameFields;
|
|
53103
|
+
if (nameFields.length !== 0) {
|
|
53104
|
+
nameField = nameFields.find((x) => x === 'Name');
|
|
53105
|
+
if (nameField === undefined) {
|
|
53106
|
+
nameField = nameFields[0];
|
|
53107
|
+
}
|
|
53108
|
+
}
|
|
53109
|
+
if (nameField !== undefined) {
|
|
53110
|
+
const nameFieldRef = referencedRecord.fields[nameField];
|
|
53111
|
+
if (nameFieldRef) {
|
|
53112
|
+
recordFields[relationshipName].displayValue =
|
|
53113
|
+
(_a = nameFieldRef.displayValue) !== null && _a !== void 0 ? _a : nameFieldRef.value;
|
|
53114
|
+
}
|
|
52845
53115
|
}
|
|
52846
53116
|
}
|
|
52847
53117
|
}
|
|
@@ -53134,17 +53404,8 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
|
|
|
53134
53404
|
};
|
|
53135
53405
|
for (const fieldName of keys$3(recordWithSpanningRefLinks.fields)) {
|
|
53136
53406
|
const fieldKey = buildRecordFieldStoreKey(key, fieldName);
|
|
53137
|
-
|
|
53138
|
-
|
|
53139
|
-
normalizedRecord.fields[fieldName] = { __ref: fieldKey };
|
|
53140
|
-
publishData(fieldKey, fieldData);
|
|
53141
|
-
}
|
|
53142
|
-
else if (recordWithSpanningRefLinks.fields[fieldName] &&
|
|
53143
|
-
recordWithSpanningRefLinks.fields[fieldName].value &&
|
|
53144
|
-
recordWithSpanningRefLinks.fields[fieldName].value.__ref !== undefined) {
|
|
53145
|
-
normalizedRecord.fields[fieldName] = { __ref: fieldKey };
|
|
53146
|
-
publishData(fieldKey, recordWithSpanningRefLinks.fields[fieldName]);
|
|
53147
|
-
}
|
|
53407
|
+
normalizedRecord.fields[fieldName] = { __ref: fieldKey };
|
|
53408
|
+
publishData(fieldKey, recordWithSpanningRefLinks.fields[fieldName]);
|
|
53148
53409
|
}
|
|
53149
53410
|
// publish the normalized record
|
|
53150
53411
|
publishData(key, normalizedRecord);
|
|
@@ -54043,6 +54304,9 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
|
|
|
54043
54304
|
if (!rebuildResult.errors) {
|
|
54044
54305
|
rebuildResult = removeSyntheticFields(rebuildResult, config.query);
|
|
54045
54306
|
}
|
|
54307
|
+
if (objectsDeepEqual(rebuildResult, originalSnapshot.data)) {
|
|
54308
|
+
return originalSnapshot;
|
|
54309
|
+
}
|
|
54046
54310
|
// '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.
|
|
54047
54311
|
return {
|
|
54048
54312
|
...originalSnapshot,
|
|
@@ -54061,7 +54325,7 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
|
|
|
54061
54325
|
// Fulfilled snapshot (this only happens in this code path if
|
|
54062
54326
|
// the error is network error or 504), otherwise we spread over
|
|
54063
54327
|
// the non-eval'ed snapshot (which will be either Fulfilled or Stale)
|
|
54064
|
-
|
|
54328
|
+
const resultSnapshot = nonEvaluatedSnapshot.state === 'Error'
|
|
54065
54329
|
? createLocalEvalSnapshot(gqlResult, seenRecords, recordId, rebuildWithLocalEval)
|
|
54066
54330
|
: {
|
|
54067
54331
|
...nonEvaluatedSnapshot,
|
|
@@ -54070,6 +54334,22 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
|
|
|
54070
54334
|
seenRecords,
|
|
54071
54335
|
rebuildWithLocalEval,
|
|
54072
54336
|
};
|
|
54337
|
+
const { refresh, state } = resultSnapshot;
|
|
54338
|
+
if (state !== 'Error' && refresh) {
|
|
54339
|
+
// after refreshing a graphql snapshot, we want to force a rebuild regardless
|
|
54340
|
+
// of if the call failed or not or if the data changed or not because we want
|
|
54341
|
+
// to make sure any potential new drafts are picked up
|
|
54342
|
+
resultSnapshot.refresh = {
|
|
54343
|
+
...refresh,
|
|
54344
|
+
resolve: (config) => {
|
|
54345
|
+
return refresh.resolve(config).finally(() => {
|
|
54346
|
+
luvio.storePublish(resultSnapshot.recordId, undefined);
|
|
54347
|
+
luvio.storeBroadcast();
|
|
54348
|
+
});
|
|
54349
|
+
},
|
|
54350
|
+
};
|
|
54351
|
+
}
|
|
54352
|
+
return resultSnapshot;
|
|
54073
54353
|
};
|
|
54074
54354
|
}
|
|
54075
54355
|
|
|
@@ -55123,7 +55403,10 @@ function isErrorResponse(response) {
|
|
|
55123
55403
|
* @returns the merged record
|
|
55124
55404
|
*/
|
|
55125
55405
|
function mergeAggregateUiResponse(response, mergeFunc) {
|
|
55126
|
-
|
|
55406
|
+
if (response.ok === false) {
|
|
55407
|
+
return response;
|
|
55408
|
+
}
|
|
55409
|
+
const body = response.body;
|
|
55127
55410
|
try {
|
|
55128
55411
|
if (body === null ||
|
|
55129
55412
|
body === undefined ||
|
|
@@ -56954,6 +57237,9 @@ class PrimingSession extends EventEmitter {
|
|
|
56954
57237
|
this.ldsRecordRefresher = config.ldsRecordRefresher;
|
|
56955
57238
|
this.networkWorkerPool = new AsyncWorkerPool(this.concurrency);
|
|
56956
57239
|
this.useBatchGQL = ldsPrimingGraphqlBatch.isOpen({ fallback: false });
|
|
57240
|
+
if (this.useBatchGQL) {
|
|
57241
|
+
this.batchSize = this.batchSize / DEFAULT_GQL_QUERY_BATCH_SIZE;
|
|
57242
|
+
}
|
|
56957
57243
|
this.conflictPool = new ConflictPool(config.store, this.objectInfoLoader);
|
|
56958
57244
|
}
|
|
56959
57245
|
// function that enqueues priming work
|
|
@@ -57810,7 +58096,7 @@ register({
|
|
|
57810
58096
|
id: '@salesforce/lds-network-adapter',
|
|
57811
58097
|
instrument: instrument$1,
|
|
57812
58098
|
});
|
|
57813
|
-
// version: 1.
|
|
58099
|
+
// version: 1.229.0-dev10-bc9ef2513
|
|
57814
58100
|
|
|
57815
58101
|
const { create: create$2, keys: keys$2 } = Object;
|
|
57816
58102
|
const { stringify: stringify$1, parse: parse$1 } = JSON;
|
|
@@ -71134,7 +71420,7 @@ function getFieldType$6(field) {
|
|
|
71134
71420
|
}
|
|
71135
71421
|
}
|
|
71136
71422
|
|
|
71137
|
-
const { assign, create: create$1, freeze: freeze$1, keys: keys$1 } = Object;
|
|
71423
|
+
const { assign, create: create$1, freeze: freeze$1, isFrozen, keys: keys$1 } = Object;
|
|
71138
71424
|
const { isArray: isArray$1 } = Array;
|
|
71139
71425
|
const { concat, filter, includes, push, reduce } = Array.prototype;
|
|
71140
71426
|
|
|
@@ -72573,6 +72859,7 @@ function buildSelectionForField$7(source, reader, sel, variables, fragments, isC
|
|
|
72573
72859
|
}
|
|
72574
72860
|
if (fieldData === null) {
|
|
72575
72861
|
reader.assignScalar(requestedFieldName, sink, fieldData);
|
|
72862
|
+
reader.exitPath();
|
|
72576
72863
|
return sink;
|
|
72577
72864
|
}
|
|
72578
72865
|
const fieldType = getFieldType(sel);
|
|
@@ -72598,17 +72885,8 @@ function buildSelectionForField$7(source, reader, sel, variables, fragments, isC
|
|
|
72598
72885
|
return sink;
|
|
72599
72886
|
}
|
|
72600
72887
|
function selectTypeLink(sel, fieldData, reader, key, sink, variables, fragments, version, selectFn, isCursorConnection) {
|
|
72601
|
-
const resolvedLink = reader
|
|
72602
|
-
|
|
72603
|
-
node: {
|
|
72604
|
-
kind: 'Fragment',
|
|
72605
|
-
private: [],
|
|
72606
|
-
opaque: true,
|
|
72607
|
-
version,
|
|
72608
|
-
},
|
|
72609
|
-
variables: {}
|
|
72610
|
-
});
|
|
72611
|
-
if (resolvedLink.data !== undefined) {
|
|
72888
|
+
const resolvedLink = resolveLink$1(reader, fieldData, version);
|
|
72889
|
+
if (resolvedLink && resolvedLink.data !== undefined) {
|
|
72612
72890
|
if (isCursorConnection) {
|
|
72613
72891
|
selectTypeLinkWithPagination(resolvedLink, sel, fieldData, reader, key, sink, variables, fragments, selectFn);
|
|
72614
72892
|
}
|
|
@@ -73184,19 +73462,11 @@ function selectType$6(typename, sel, fieldData, reader, key, sink, variables, fr
|
|
|
73184
73462
|
}
|
|
73185
73463
|
case 'PolymorphicParentRelationship':
|
|
73186
73464
|
case 'RecordRepresentation': {
|
|
73187
|
-
const spanningFieldLink = reader
|
|
73188
|
-
|
|
73189
|
-
|
|
73190
|
-
kind: 'Fragment',
|
|
73191
|
-
private: [],
|
|
73192
|
-
opaque: true,
|
|
73193
|
-
version: VERSION$f,
|
|
73194
|
-
},
|
|
73195
|
-
variables: {},
|
|
73196
|
-
});
|
|
73197
|
-
reader.markSeenId(fieldData.__ref);
|
|
73198
|
-
const resolvedSpanningFieldValue = spanningFieldLink.data;
|
|
73465
|
+
const spanningFieldLink = resolveLink$1(reader, fieldData, VERSION$f);
|
|
73466
|
+
const resolvedSpanningFieldValue = spanningFieldLink && spanningFieldLink.data;
|
|
73467
|
+
const fieldDataRef = fieldData.__ref;
|
|
73199
73468
|
if (resolvedSpanningFieldValue !== undefined) {
|
|
73469
|
+
reader.markSeenId(fieldDataRef);
|
|
73200
73470
|
const { value: spanningFieldResult } = resolvedSpanningFieldValue;
|
|
73201
73471
|
// Handle null values - graphql will return it at the field level, not return nested { value: null }
|
|
73202
73472
|
if (spanningFieldResult === null || typeof spanningFieldResult !== 'object') {
|
|
@@ -73220,7 +73490,9 @@ function selectType$6(typename, sel, fieldData, reader, key, sink, variables, fr
|
|
|
73220
73490
|
}
|
|
73221
73491
|
}
|
|
73222
73492
|
else {
|
|
73223
|
-
|
|
73493
|
+
if (fieldDataRef !== undefined) {
|
|
73494
|
+
reader.markMissingLink(fieldDataRef);
|
|
73495
|
+
}
|
|
73224
73496
|
reader.markMissing();
|
|
73225
73497
|
}
|
|
73226
73498
|
break;
|
|
@@ -76256,7 +76528,7 @@ register({
|
|
|
76256
76528
|
configuration: { ...configurationForGraphQLAdapters },
|
|
76257
76529
|
instrument,
|
|
76258
76530
|
});
|
|
76259
|
-
// version: 1.
|
|
76531
|
+
// version: 1.229.0-dev10-abb060196
|
|
76260
76532
|
|
|
76261
76533
|
// On core the unstable adapters are re-exported with different names,
|
|
76262
76534
|
|
|
@@ -78503,7 +78775,7 @@ withDefaultLuvio((luvio) => {
|
|
|
78503
78775
|
unstable_graphQL_imperative = createImperativeAdapter(luvio, createInstrumentedAdapter(ldsAdapter, adapterMetadata), adapterMetadata);
|
|
78504
78776
|
graphQLImperative = ldsAdapter;
|
|
78505
78777
|
});
|
|
78506
|
-
// version: 1.
|
|
78778
|
+
// version: 1.229.0-dev10-abb060196
|
|
78507
78779
|
|
|
78508
78780
|
var gqlApi = /*#__PURE__*/Object.freeze({
|
|
78509
78781
|
__proto__: null,
|
|
@@ -79217,4 +79489,4 @@ const { luvio } = getRuntime();
|
|
|
79217
79489
|
setDefaultLuvio({ luvio });
|
|
79218
79490
|
|
|
79219
79491
|
export { createPrimingSession, draftManager, draftQueue, executeAdapter, executeMutatingAdapter, getImperativeAdapterNames, invokeAdapter, invokeAdapterWithDraftToReplace, invokeAdapterWithMetadata, nimbusDraftQueue, registerReportObserver, setMetadataTTL, setUiApiRecordTTL, subscribeToAdapter };
|
|
79220
|
-
// version: 1.
|
|
79492
|
+
// version: 1.229.0-dev10-bc9ef2513
|