@salesforce/lds-runtime-bridge 1.294.0 → 1.296.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,12 +14,9 @@
14
14
  import { setDefaultLuvio } from 'force/ldsEngine';
15
15
  import { setBypassDeepFreeze, StoreKeySet, serializeStructuredKey, StringKeyInMemoryStore, Reader, deepFreeze, emitAdapterEvent, InMemoryStore, Environment, Luvio } from 'force/luvioEngine';
16
16
  import { instrumentLuvio } from 'force/ldsInstrumentation';
17
- import { isStoreKeyRecordViewEntity, RECORD_ID_PREFIX, RECORD_FIELDS_KEY_JUNCTION, getRecordId18, extractRecordIdFromStoreKey, RECORD_VIEW_ENTITY_ID_PREFIX, keyBuilderRecord } from 'force/ldsAdaptersUiapi';
17
+ import { isStoreKeyRecordViewEntity, RECORD_ID_PREFIX, RECORD_FIELDS_KEY_JUNCTION, extractRecordIdFromStoreKey, RECORD_VIEW_ENTITY_ID_PREFIX, keyBuilderRecord } from 'native/ldsAdaptersUiapiMobile';
18
18
  import '@salesforce/gate/lds.idempotencyWriteDisabled';
19
19
  import '@salesforce/gate/lds.backdatingEnabled';
20
- import { Kind, buildSchema, isObjectType, defaultFieldResolver } from 'force/ldsGraphqlParser';
21
- import FIRST_DAY_OF_WEEK from '@salesforce/i18n/firstDayOfWeek';
22
- import excludeStaleRecordsGate from '@salesforce/gate/lds.graphqlEvalExcludeStaleRecords';
23
20
  import networkAdapter from 'force/ldsNetwork';
24
21
  import ldsEngineCreator from 'force/ldsEngineCreator';
25
22
 
@@ -45,7 +42,7 @@ const RedirectDurableSegment = 'REDIRECT_KEYS';
45
42
  const MessagingDurableSegment = 'MESSAGING';
46
43
  const MessageNotifyStoreUpdateAvailable = 'notifyStoreUpdateAvailable';
47
44
 
48
- const { keys: keys$3, create: create$3, assign: assign$3, freeze: freeze$1 } = Object;
45
+ const { keys: keys$2, create: create$2, assign: assign$2, freeze: freeze$1 } = Object;
49
46
 
50
47
  //Durable store error instrumentation key
51
48
  const DURABLE_STORE_ERROR = 'durable-store-error';
@@ -95,7 +92,7 @@ function publishDurableStoreEntries(durableRecords, put, publishMetadata) {
95
92
  if (durableRecords === undefined) {
96
93
  return { revivedKeys, hadUnexpectedShape };
97
94
  }
98
- const durableKeys = keys$3(durableRecords);
95
+ const durableKeys = keys$2(durableRecords);
99
96
  if (durableKeys.length === 0) {
100
97
  // no records to revive
101
98
  return { revivedKeys, hadUnexpectedShape };
@@ -280,7 +277,7 @@ class DurableTTLStore {
280
277
  overrides,
281
278
  };
282
279
  }
283
- const keys$1 = keys$3(entries);
280
+ const keys$1 = keys$2(entries);
284
281
  for (let i = 0, len = keys$1.length; i < len; i++) {
285
282
  const key = keys$1[i];
286
283
  const entry = entries[key];
@@ -302,14 +299,14 @@ class DurableTTLStore {
302
299
  }
303
300
 
304
301
  function flushInMemoryStoreValuesToDurableStore(store, durableStore, durableStoreErrorHandler, redirects, additionalDurableStoreOperations = [], enableDurableMetadataRefresh = false) {
305
- const durableRecords = create$3(null);
306
- const refreshedDurableRecords = create$3(null);
307
- const evictedRecords = create$3(null);
302
+ const durableRecords = create$2(null);
303
+ const refreshedDurableRecords = create$2(null);
304
+ const evictedRecords = create$2(null);
308
305
  const { visitedIds, refreshedIds } = store.fallbackStringKeyInMemoryStore;
309
306
  // TODO: W-8909393 Once metadata is stored in its own segment we need to
310
307
  // call setEntries for the visitedIds on default segment and call setEntries
311
308
  // on the metadata segment for the refreshedIds
312
- const keys$1 = keys$3({ ...visitedIds, ...refreshedIds });
309
+ const keys$1 = keys$2({ ...visitedIds, ...refreshedIds });
313
310
  for (let i = 0, len = keys$1.length; i < len; i += 1) {
314
311
  const key = keys$1[i];
315
312
  const canonicalKey = store.getCanonicalRecordId(key);
@@ -332,7 +329,7 @@ function flushInMemoryStoreValuesToDurableStore(store, durableStore, durableStor
332
329
  setRecordTo(entries, key, record, metadata);
333
330
  }
334
331
  const durableStoreOperations = additionalDurableStoreOperations;
335
- const recordKeys = keys$3(durableRecords);
332
+ const recordKeys = keys$2(durableRecords);
336
333
  if (recordKeys.length > 0) {
337
334
  // publishes with data
338
335
  durableStoreOperations.push({
@@ -341,7 +338,7 @@ function flushInMemoryStoreValuesToDurableStore(store, durableStore, durableStor
341
338
  segment: DefaultDurableSegment,
342
339
  });
343
340
  }
344
- const refreshKeys = keys$3(refreshedDurableRecords);
341
+ const refreshKeys = keys$2(refreshedDurableRecords);
345
342
  if (refreshKeys.length > 0) {
346
343
  // publishes with only metadata updates
347
344
  durableStoreOperations.push({
@@ -363,7 +360,7 @@ function flushInMemoryStoreValuesToDurableStore(store, durableStore, durableStor
363
360
  });
364
361
  });
365
362
  // evicts
366
- const evictedKeys = keys$3(evictedRecords);
363
+ const evictedKeys = keys$2(evictedRecords);
367
364
  if (evictedKeys.length > 0) {
368
365
  durableStoreOperations.push({
369
366
  type: 'evictEntries',
@@ -467,7 +464,7 @@ function buildRevivingStagingStore(upstreamStore) {
467
464
  // A reviving store is only "active" during a call to `environment.storeLookup`, and will
468
465
  // be used by the reader attempting to build an L1 snapshot. Immediately after the L1 rebuild
469
466
  // the reviving store becomes inactive other than receiving change notifications.
470
- return create$3(upstreamStore, {
467
+ return create$2(upstreamStore, {
471
468
  readEntry: { value: readEntry },
472
469
  markStale: { value: markStale },
473
470
  clearStale: { value: clearStale },
@@ -479,7 +476,7 @@ const AdapterContextSegment = 'ADAPTER-CONTEXT';
479
476
  const ADAPTER_CONTEXT_ID_SUFFIX = '__NAMED_CONTEXT';
480
477
  async function reviveOrCreateContext(adapterId, durableStore, durableStoreErrorHandler, contextStores, pendingContextStoreKeys, onContextLoaded) {
481
478
  // initialize empty context store
482
- contextStores[adapterId] = create$3(null);
479
+ contextStores[adapterId] = create$2(null);
483
480
  const context = {
484
481
  set(key, value) {
485
482
  contextStores[adapterId][key] = value;
@@ -544,7 +541,7 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
544
541
  const revivingStores = new Set();
545
542
  // redirects that need to be flushed to the durable store
546
543
  const pendingStoreRedirects = new Map();
547
- const contextStores = create$3(null);
544
+ const contextStores = create$2(null);
548
545
  let initializationPromise = new Promise((resolve) => {
549
546
  const finish = () => {
550
547
  resolve();
@@ -621,7 +618,7 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
621
618
  try {
622
619
  const entries = await durableStore.getEntries(adapterContextKeysFromDifferentInstance, AdapterContextSegment);
623
620
  if (entries !== undefined) {
624
- const entryKeys = keys$3(entries);
621
+ const entryKeys = keys$2(entries);
625
622
  for (let i = 0, len = entryKeys.length; i < len; i++) {
626
623
  const entryKey = entryKeys[i];
627
624
  const entry = entries[entryKey];
@@ -656,7 +653,7 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
656
653
  if (filteredKeys.length > 0) {
657
654
  const entries = await durableStore.getMetadata(filteredKeys, DefaultDurableSegment);
658
655
  if (entries !== undefined) {
659
- const entryKeys = keys$3(entries);
656
+ const entryKeys = keys$2(entries);
660
657
  for (let i = 0, len = entryKeys.length; i < len; i++) {
661
658
  const entryKey = entryKeys[i];
662
659
  const { metadata } = entries[entryKey];
@@ -1028,7 +1025,7 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
1028
1025
  validateNotDisposed();
1029
1026
  const entryKeys = keys$1.map(serializeStructuredKey);
1030
1027
  const entries = await durableStore.getEntries(entryKeys, DefaultDurableSegment);
1031
- if (entries === undefined || keys$3(entries).length === 0) {
1028
+ if (entries === undefined || keys$2(entries).length === 0) {
1032
1029
  return environment.notifyStoreUpdateAvailable(keys$1);
1033
1030
  }
1034
1031
  const now = Date.now();
@@ -1080,7 +1077,7 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
1080
1077
  type: 'stale-while-revalidate',
1081
1078
  staleDurationSeconds: Number.MAX_SAFE_INTEGER,
1082
1079
  });
1083
- return create$3(environment, {
1080
+ return create$2(environment, {
1084
1081
  publishStoreMetadata: { value: publishStoreMetadata },
1085
1082
  storeIngest: { value: storeIngest },
1086
1083
  storeIngestError: { value: storeIngestError },
@@ -1110,8 +1107,8 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
1110
1107
  });
1111
1108
  }
1112
1109
 
1113
- const { keys: keys$2, create: create$2, assign: assign$2, entries: entries$2, values: values$2 } = Object;
1114
- const { stringify: stringify$1, parse: parse$1 } = JSON;
1110
+ const { keys: keys$1, create: create$1, assign: assign$1, entries: entries$1, values: values$1 } = Object;
1111
+ const { stringify, parse } = JSON;
1115
1112
 
1116
1113
  function selectColumnsFromTableWhereKeyIn(columnNames, table, keyColumnName, whereIn) {
1117
1114
  const paramList = whereIn.map(() => '?').join(',');
@@ -1152,7 +1149,7 @@ class LdsDataTable {
1152
1149
  const [key, stringifiedMetadata] = row;
1153
1150
  if (stringifiedMetadata !== undefined) {
1154
1151
  entries[key] = {
1155
- metadata: parse$1(stringifiedMetadata),
1152
+ metadata: parse(stringifiedMetadata),
1156
1153
  };
1157
1154
  }
1158
1155
  return entries;
@@ -1177,10 +1174,10 @@ class LdsDataTable {
1177
1174
  },
1178
1175
  conflictColumns: this.conflictColumnNames,
1179
1176
  columns: this.columnNames,
1180
- rows: keys$2(entries).reduce((rows, key) => {
1177
+ rows: keys$1(entries).reduce((rows, key) => {
1181
1178
  const entry = entries[key];
1182
1179
  const { data, metadata } = entry;
1183
- const row = [key, stringify$1(data), metadata ? stringify$1(metadata) : null];
1180
+ const row = [key, stringify(data), metadata ? stringify(metadata) : null];
1184
1181
  rows.push(row);
1185
1182
  return rows;
1186
1183
  }, []),
@@ -1196,9 +1193,9 @@ class LdsDataTable {
1196
1193
  type: 'setMetadata',
1197
1194
  },
1198
1195
  columns: [COLUMN_NAME_METADATA$1],
1199
- values: keys$2(entries).reduce((values, key) => {
1196
+ values: keys$1(entries).reduce((values, key) => {
1200
1197
  const { metadata } = entries[key];
1201
- const row = [metadata ? stringify$1(metadata) : null];
1198
+ const row = [metadata ? stringify(metadata) : null];
1202
1199
  values[key] = row;
1203
1200
  return values;
1204
1201
  }, {}),
@@ -1208,10 +1205,10 @@ class LdsDataTable {
1208
1205
  return sqliteResult.rows.reduce((entries, row) => {
1209
1206
  const [key, stringifiedData, stringifiedMetadata] = row;
1210
1207
  const durableStoreEntry = {
1211
- data: parse$1(stringifiedData),
1208
+ data: parse(stringifiedData),
1212
1209
  };
1213
1210
  if (stringifiedMetadata !== null) {
1214
- durableStoreEntry.metadata = parse$1(stringifiedMetadata);
1211
+ durableStoreEntry.metadata = parse(stringifiedMetadata);
1215
1212
  }
1216
1213
  entries[key] = durableStoreEntry;
1217
1214
  return entries;
@@ -1261,7 +1258,7 @@ class LdsInternalDataTable {
1261
1258
  const [key, stringifiedMetadata] = row;
1262
1259
  if (stringifiedMetadata !== undefined) {
1263
1260
  entries[key] = {
1264
- metadata: parse$1(stringifiedMetadata),
1261
+ metadata: parse(stringifiedMetadata),
1265
1262
  };
1266
1263
  }
1267
1264
  return entries;
@@ -1286,12 +1283,12 @@ class LdsInternalDataTable {
1286
1283
  },
1287
1284
  conflictColumns: this.conflictColumnNames,
1288
1285
  columns: this.columnNames,
1289
- rows: keys$2(entries).reduce((rows, key) => {
1286
+ rows: keys$1(entries).reduce((rows, key) => {
1290
1287
  const entry = entries[key];
1291
1288
  const { data, metadata } = entry;
1292
- const row = [key, stringify$1(data)];
1289
+ const row = [key, stringify(data)];
1293
1290
  if (metadata) {
1294
- row.push(stringify$1(metadata));
1291
+ row.push(stringify(metadata));
1295
1292
  }
1296
1293
  else {
1297
1294
  row.push(null);
@@ -1312,21 +1309,21 @@ class LdsInternalDataTable {
1312
1309
  type: 'setMetadata',
1313
1310
  },
1314
1311
  columns: [COLUMN_NAME_METADATA],
1315
- values: keys$2(entries).reduce((values, key) => {
1312
+ values: keys$1(entries).reduce((values, key) => {
1316
1313
  const { metadata } = entries[key];
1317
- const row = [metadata ? stringify$1(metadata) : null];
1314
+ const row = [metadata ? stringify(metadata) : null];
1318
1315
  values[key] = row;
1319
1316
  return values;
1320
1317
  }, {}),
1321
1318
  };
1322
1319
  }
1323
1320
  metadataToUpdateSQLQueries(entries, segment) {
1324
- return keys$2(entries).reduce((accu, key) => {
1321
+ return keys$1(entries).reduce((accu, key) => {
1325
1322
  const { metadata } = entries[key];
1326
1323
  if (metadata !== undefined) {
1327
1324
  accu.push({
1328
1325
  sql: `UPDATE ${this.tableName} SET ${COLUMN_NAME_METADATA} = ? WHERE (${COLUMN_NAME_KEY$1} IS ? AND ${COLUMN_NAME_NAMESPACE} IS ?)`,
1329
- params: [stringify$1(metadata), key, segment],
1326
+ params: [stringify(metadata), key, segment],
1330
1327
  change: {
1331
1328
  ids: [key],
1332
1329
  segment,
@@ -1342,10 +1339,10 @@ class LdsInternalDataTable {
1342
1339
  return sqliteResult.rows.reduce((entries, row) => {
1343
1340
  const [key, stringifiedData, stringifiedMetadata] = row;
1344
1341
  const durableStoreEntry = {
1345
- data: parse$1(stringifiedData),
1342
+ data: parse(stringifiedData),
1346
1343
  };
1347
1344
  if (stringifiedMetadata !== null) {
1348
- durableStoreEntry.metadata = parse$1(stringifiedMetadata);
1345
+ durableStoreEntry.metadata = parse(stringifiedMetadata);
1349
1346
  }
1350
1347
  entries[key] = durableStoreEntry;
1351
1348
  return entries;
@@ -1392,7 +1389,7 @@ class NimbusSqliteStore {
1392
1389
  return this.getTable(segment).getAll(segment);
1393
1390
  }
1394
1391
  setEntries(entries, segment) {
1395
- if (keys$2(entries).length === 0) {
1392
+ if (keys$1(entries).length === 0) {
1396
1393
  return Promise.resolve();
1397
1394
  }
1398
1395
  const table = this.getTable(segment);
@@ -1400,7 +1397,7 @@ class NimbusSqliteStore {
1400
1397
  return this.batchOperationAsPromise([upsertOperation]);
1401
1398
  }
1402
1399
  setMetadata(entries, segment) {
1403
- if (keys$2(entries).length === 0) {
1400
+ if (keys$1(entries).length === 0) {
1404
1401
  return Promise.resolve();
1405
1402
  }
1406
1403
  const table = this.getTable(segment);
@@ -1419,13 +1416,13 @@ class NimbusSqliteStore {
1419
1416
  batchOperations(operations) {
1420
1417
  const sqliteOperations = operations.reduce((acc, cur) => {
1421
1418
  if (cur.type === 'setEntries') {
1422
- if (keys$2(cur.entries).length > 0) {
1419
+ if (keys$1(cur.entries).length > 0) {
1423
1420
  const table = this.getTable(cur.segment);
1424
1421
  acc.push(table.entriesToUpsertOperations(cur.entries, cur.segment));
1425
1422
  }
1426
1423
  }
1427
1424
  else if (cur.type === 'setMetadata') {
1428
- if (keys$2(cur.entries).length > 0) {
1425
+ if (keys$1(cur.entries).length > 0) {
1429
1426
  const table = this.getTable(cur.segment);
1430
1427
  if (this.supportsBatchUpdates) {
1431
1428
  acc.push(table.metadataToUpdateOperations(cur.entries, cur.segment));
@@ -1662,2151 +1659,6 @@ var DraftQueueOperationType;
1662
1659
  DraftQueueOperationType["QueueStopped"] = "stopped";
1663
1660
  })(DraftQueueOperationType || (DraftQueueOperationType = {}));
1664
1661
 
1665
- function serializeFieldArguments(argumentNodes, variables) {
1666
- const mutableArgumentNodes = Object.assign([], argumentNodes);
1667
- return `args__(${mutableArgumentNodes
1668
- .sort((a, b) => {
1669
- const aName = a.name.value.toUpperCase();
1670
- const bName = b.name.value.toUpperCase();
1671
- return aName < bName ? -1 : aName > bName ? 1 : 0;
1672
- })
1673
- .map((node) => serializeArgNode(node, variables))
1674
- .join('::')})`;
1675
- }
1676
- function serializeArgNode(argumentNode, variables) {
1677
- const argName = argumentNode.name.value;
1678
- return `${argName}:${serializeValueNode(argumentNode.value, variables)}`;
1679
- }
1680
- function serializeValueNode(valueNode, variables) {
1681
- switch (valueNode.kind) {
1682
- case 'BooleanValue':
1683
- return valueNode.value + '';
1684
- case 'IntValue':
1685
- case 'FloatValue':
1686
- case 'EnumValue':
1687
- case 'StringValue':
1688
- return valueNode.value;
1689
- case 'ListValue': {
1690
- const mutableValueNodeList = Object.assign([], valueNode.values);
1691
- return mutableValueNodeList
1692
- .sort((a, b) => {
1693
- const aVal = serializeValueNode(a, variables).toUpperCase();
1694
- const bVal = serializeValueNode(b, variables).toUpperCase();
1695
- return aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
1696
- })
1697
- .map((val, i) => `${serializeValueNode(val, variables)}[${i}]`)
1698
- .join(',');
1699
- }
1700
- case 'Variable': {
1701
- const variableValue = variables[valueNode.name.value];
1702
- return typeof variableValue === 'string'
1703
- ? variableValue
1704
- : JSON.stringify(variableValue);
1705
- }
1706
- case 'NullValue':
1707
- return 'null';
1708
- case 'ObjectValue': {
1709
- const mutableFieldNodeList = Object.assign([], valueNode.fields);
1710
- return mutableFieldNodeList
1711
- .sort((a, b) => {
1712
- const aName = a.name.value.toUpperCase();
1713
- const bName = b.name.value.toUpperCase();
1714
- return aName < bName ? -1 : aName > bName ? 1 : 0;
1715
- })
1716
- .map((field) => field.name.value + ':' + serializeValueNode(field.value, variables))
1717
- .join(',');
1718
- }
1719
- }
1720
- }
1721
-
1722
- function serializeOperationNode(operationNode, variables, fragmentMap) {
1723
- return `${serializeSelectionSet(operationNode.selectionSet, variables, fragmentMap)}`;
1724
- }
1725
- function serializeSelectionSet(selectionSetNode, variables, fragmentMap) {
1726
- return `${selectionSetNode.selections
1727
- .map((selection) => serializeSelectionNode(selection, variables, fragmentMap))
1728
- .join()}`;
1729
- }
1730
- /**
1731
- *
1732
- * @description This function takes a GraphQL SelectionNode from an AST and serializes it in a stable way, so we can
1733
- * use it for property names and Store keys.
1734
- * @param selectionNode
1735
- * @param variables
1736
- * @param fragmentMap
1737
- * @returns string
1738
- */
1739
- function serializeSelectionNode(selectionNode, variables, fragmentMap) {
1740
- switch (selectionNode.kind) {
1741
- case 'Field': {
1742
- const hasArguments = selectionNode.arguments !== undefined && selectionNode.arguments.length > 0;
1743
- const argumentSuffix = hasArguments
1744
- ? `__${serializeFieldArguments(selectionNode.arguments, variables)}`
1745
- : '';
1746
- return `${selectionNode.name.value}${argumentSuffix}`;
1747
- }
1748
- case 'FragmentSpread': {
1749
- const fragment = fragmentMap[selectionNode.name.value];
1750
- return fragment === undefined
1751
- ? selectionNode.name.value
1752
- : serializeSelectionSet(fragment.selectionSet, variables, fragmentMap);
1753
- }
1754
- case 'InlineFragment':
1755
- return serializeSelectionSet(selectionNode.selectionSet, variables, fragmentMap);
1756
- }
1757
- }
1758
- function buildQueryTypeStringKey(args) {
1759
- const { keyPrefix, schemaName, queryTypeName, operationNode, variables, fragmentMap } = args;
1760
- return `${keyPrefix}::${schemaName}::${queryTypeName}[${serializeOperationNode(operationNode, variables, fragmentMap)}]`;
1761
- }
1762
-
1763
- /**
1764
- * Copyright (c) 2022, Salesforce, Inc.,
1765
- * All rights reserved.
1766
- * For full license text, see the LICENSE.txt file
1767
- */
1768
-
1769
-
1770
- const { create: create$1, keys: keys$1, values: values$1, entries: entries$1, assign: assign$1 } = Object;
1771
- const { stringify, parse } = JSON;
1772
- const { isArray, from } = Array;
1773
-
1774
- function removeUndefined(array) {
1775
- return array.reduce((accu, item) => {
1776
- if (item !== undefined) {
1777
- accu.push(item);
1778
- }
1779
- return accu;
1780
- }, []);
1781
- }
1782
-
1783
- var DateLiteral;
1784
- (function (DateLiteral) {
1785
- DateLiteral["NEXT_YEAR"] = "NEXT_YEAR";
1786
- DateLiteral["LAST_WEEK"] = "LAST_WEEK";
1787
- DateLiteral["THIS_MONTH"] = "THIS_MONTH";
1788
- DateLiteral["THIS_QUARTER"] = "THIS_QUARTER";
1789
- DateLiteral["LAST_MONTH"] = "LAST_MONTH";
1790
- DateLiteral["LAST_90_DAYS"] = "LAST_90_DAYS";
1791
- DateLiteral["LAST_QUARTER"] = "LAST_QUARTER";
1792
- DateLiteral["THIS_YEAR"] = "THIS_YEAR";
1793
- DateLiteral["NEXT_QUARTER"] = "NEXT_QUARTER";
1794
- DateLiteral["NEXT_MONTH"] = "NEXT_MONTH";
1795
- DateLiteral["TOMORROW"] = "TOMORROW";
1796
- DateLiteral["TODAY"] = "TODAY";
1797
- DateLiteral["LAST_YEAR"] = "LAST_YEAR";
1798
- DateLiteral["NEXT_90_DAYS"] = "NEXT_90_DAYS";
1799
- DateLiteral["THIS_WEEK"] = "THIS_WEEK";
1800
- DateLiteral["YESTERDAY"] = "YESTERDAY";
1801
- DateLiteral["NEXT_WEEK"] = "NEXT_WEEK";
1802
- })(DateLiteral || (DateLiteral = {}));
1803
- // ranged adjusted to be between now and the end of the day,
1804
- // you cannot do a straight = comparison in SQL
1805
- const TODAY_RANGE = {
1806
- lowerBound: `date('now')`,
1807
- upperBound: `date('now', '+1 day', '-0.001 seconds')`,
1808
- };
1809
- // ranged adjusted to be between today +1 day and +2 days -.001 seconds to be the very end of tomorrows date
1810
- // you cannot do a straight = comparison in SQL
1811
- const TOMORROW_RANGE = {
1812
- lowerBound: `date('now', '+1 day')`,
1813
- upperBound: `date('now', '+2 day', '-0.001 seconds')`,
1814
- };
1815
- const YESTERDAY_RANGE = {
1816
- lowerBound: `date('now', '-1 day')`,
1817
- upperBound: `date('now', '-0.001 seconds')`,
1818
- };
1819
- const THIS_WEEK_RANGE = {
1820
- lowerBound: `date('now', 'weekday 0', '-7 days')`,
1821
- upperBound: `date('now', 'weekday 0', '-1 day')`,
1822
- };
1823
- const LAST_WEEK_RANGE = {
1824
- lowerBound: `date('now', 'weekday 0', '-14 days')`,
1825
- upperBound: `date('now', 'weekday 0', '-8 days')`,
1826
- };
1827
- const NEXT_WEEK_RANGE = {
1828
- lowerBound: `date('now', 'weekday 0')`,
1829
- upperBound: `date('now', 'weekday 0', '+6 days')`,
1830
- };
1831
- const THIS_MONTH_RANGE = {
1832
- lowerBound: `date('now', 'start of month')`,
1833
- upperBound: `date('now', 'start of month', '1 month', '0 day')`,
1834
- };
1835
- const LAST_MONTH_RANGE = {
1836
- lowerBound: `date('now', 'start of month', '-1 month')`,
1837
- upperBound: `date('now', 'start of month', '0 day')`,
1838
- };
1839
- const NEXT_MONTH_RANGE = {
1840
- lowerBound: `date('now', 'start of month', '+1 month')`,
1841
- // -1 day is the day before the end of the month
1842
- // this needs to be 0 day
1843
- upperBound: `date('now', 'start of month', '+2 month', '0 day')`,
1844
- };
1845
- const THIS_QUARTER_RANGE = () => {
1846
- return computeQuarterDateRange(DateLiteral.THIS_QUARTER);
1847
- };
1848
- const LAST_QUARTER_RANGE = () => {
1849
- return computeQuarterDateRange(DateLiteral.LAST_QUARTER);
1850
- };
1851
- const NEXT_QUARTER_RANGE = () => {
1852
- return computeQuarterDateRange(DateLiteral.NEXT_QUARTER);
1853
- };
1854
- const THIS_YEAR_RANGE = {
1855
- lowerBound: `date('now', 'start of year')`,
1856
- upperBound: `date('now', 'start of month', '1 year', '-1 day')`,
1857
- };
1858
- const LAST_YEAR_RANGE = {
1859
- lowerBound: `date('now', 'start of year', '-1 year')`,
1860
- upperBound: `date('now', 'start of year', '-1 day')`,
1861
- };
1862
- const NEXT_YEAR_RANGE = {
1863
- lowerBound: `date('now', 'start of year', '+1 year')`,
1864
- upperBound: `date('now', 'start of year', '+2 years', '-1 day')`,
1865
- };
1866
- const LAST_90_DAYS_RANGE = {
1867
- lowerBound: `date('now', '-90 days')`,
1868
- upperBound: `date('now')`,
1869
- };
1870
- const NEXT_90_DAYS_RANGE = {
1871
- lowerBound: `date('now', '+1 day')`,
1872
- upperBound: `date('now', '+90 days')`,
1873
- };
1874
- // querter start date in UTC
1875
- function quarterStart(date) {
1876
- let month = Math.floor(date.getUTCMonth() / 3) * 3 + 1;
1877
- const year = date.getUTCFullYear();
1878
- return month === 10 ? `${year}-${month}-01` : `${year}-0${month}-01`;
1879
- }
1880
- function computeQuarterDateRange(enumType) {
1881
- const curQuarterStart = quarterStart(new Date());
1882
- switch (enumType) {
1883
- case DateLiteral.LAST_QUARTER:
1884
- return {
1885
- lowerBound: `date('${curQuarterStart}', '-3 months')`,
1886
- // -1 days would set the day before the end of the quarter
1887
- // 0 days sets it to the end of the month
1888
- upperBound: `date('${curQuarterStart}', '0 days')`,
1889
- };
1890
- case DateLiteral.THIS_QUARTER:
1891
- return {
1892
- lowerBound: `date('${curQuarterStart}')`,
1893
- // -1 days would set the day before the end of the quarter
1894
- // 0 days sets it to the end of the month
1895
- upperBound: `date('${curQuarterStart}', '3 months', '0 days')`,
1896
- };
1897
- case DateLiteral.NEXT_QUARTER:
1898
- return {
1899
- lowerBound: `date('${curQuarterStart}', '+3 months')`,
1900
- // -1 days would set the day before the end of the quarter
1901
- // 0 days sets it to the end of the month
1902
- upperBound: `date('${curQuarterStart}', '+6 months', '0 days')`,
1903
- };
1904
- }
1905
- }
1906
- function dateLiteralRange(literal) {
1907
- switch (literal) {
1908
- case DateLiteral.NEXT_YEAR: {
1909
- return NEXT_YEAR_RANGE;
1910
- }
1911
- case DateLiteral.LAST_WEEK: {
1912
- return LAST_WEEK_RANGE;
1913
- }
1914
- case DateLiteral.THIS_MONTH: {
1915
- return THIS_MONTH_RANGE;
1916
- }
1917
- case DateLiteral.THIS_QUARTER: {
1918
- return THIS_QUARTER_RANGE();
1919
- }
1920
- case DateLiteral.LAST_MONTH: {
1921
- return LAST_MONTH_RANGE;
1922
- }
1923
- case DateLiteral.LAST_90_DAYS: {
1924
- return LAST_90_DAYS_RANGE;
1925
- }
1926
- case DateLiteral.LAST_QUARTER: {
1927
- return LAST_QUARTER_RANGE();
1928
- }
1929
- case DateLiteral.THIS_YEAR: {
1930
- return THIS_YEAR_RANGE;
1931
- }
1932
- case DateLiteral.NEXT_QUARTER: {
1933
- return NEXT_QUARTER_RANGE();
1934
- }
1935
- case DateLiteral.NEXT_MONTH: {
1936
- return NEXT_MONTH_RANGE;
1937
- }
1938
- case DateLiteral.TOMORROW: {
1939
- return TOMORROW_RANGE;
1940
- }
1941
- case DateLiteral.TODAY: {
1942
- return TODAY_RANGE;
1943
- }
1944
- case DateLiteral.LAST_YEAR: {
1945
- return LAST_YEAR_RANGE;
1946
- }
1947
- case DateLiteral.NEXT_90_DAYS: {
1948
- return NEXT_90_DAYS_RANGE;
1949
- }
1950
- case DateLiteral.THIS_WEEK: {
1951
- return THIS_WEEK_RANGE;
1952
- }
1953
- case DateLiteral.YESTERDAY: {
1954
- return YESTERDAY_RANGE;
1955
- }
1956
- case DateLiteral.NEXT_WEEK: {
1957
- return NEXT_WEEK_RANGE;
1958
- }
1959
- default: {
1960
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
1961
- throw new Error(`${literal} is currently not supported in graphql evaluation`);
1962
- }
1963
- }
1964
- }
1965
- function dateLiteral(literal, op, field, alias) {
1966
- let operator = op;
1967
- let value;
1968
- let bindings = [];
1969
- const { lowerBound, upperBound } = dateLiteralRange(literal);
1970
- switch (operator) {
1971
- case '=': {
1972
- operator = 'BETWEEN';
1973
- value = `${lowerBound} AND ${upperBound}`;
1974
- break;
1975
- }
1976
- case '!=': {
1977
- operator = 'NOT BETWEEN';
1978
- value = `${lowerBound} AND ${upperBound}`;
1979
- break;
1980
- }
1981
- case '<=':
1982
- case '>': {
1983
- value = upperBound;
1984
- break;
1985
- }
1986
- case '<':
1987
- case '>=': {
1988
- value = lowerBound;
1989
- break;
1990
- }
1991
- default: {
1992
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
1993
- throw new Error(`Operator ${operator} is not supported in Date Literals for graphql evaluation`);
1994
- }
1995
- }
1996
- return {
1997
- leftPath: `$.fields.${field.apiName}.value`,
1998
- operator,
1999
- value,
2000
- bindings,
2001
- type: PredicateType.single,
2002
- alias,
2003
- dataType: field.dataType,
2004
- isCaseSensitive: false,
2005
- };
2006
- }
2007
-
2008
- var DateRange;
2009
- (function (DateRange) {
2010
- DateRange["last_n_days"] = "last_n_days";
2011
- DateRange["next_n_days"] = "next_n_days";
2012
- DateRange["n_days_ago"] = "n_days_ago";
2013
- DateRange["last_n_weeks"] = "last_n_weeks";
2014
- DateRange["next_n_weeks"] = "next_n_weeks";
2015
- DateRange["n_weeks_ago"] = "n_weeks_ago";
2016
- DateRange["last_n_months"] = "last_n_months";
2017
- DateRange["next_n_months"] = "next_n_months";
2018
- DateRange["n_months_ago"] = "n_months_ago";
2019
- DateRange["last_n_quarters"] = "last_n_quarters";
2020
- DateRange["next_n_quarters"] = "next_n_quarters";
2021
- DateRange["n_quarters_ago"] = "n_quarters_ago";
2022
- DateRange["last_n_fiscal_quarters"] = "last_n_fiscal_quarters";
2023
- DateRange["next_n_fiscal_quarters"] = "next_n_fiscal_quarters";
2024
- DateRange["last_n_years"] = "last_n_years";
2025
- DateRange["next_n_years"] = "next_n_years";
2026
- DateRange["n_years_ago"] = "n_years_ago";
2027
- DateRange["last_n_fiscal_years"] = "last_n_fiscal_years";
2028
- DateRange["next_n_fiscal_years"] = "next_n_fiscal_years";
2029
- })(DateRange || (DateRange = {}));
2030
- function dateTimePredicate(input, operator, field, alias) {
2031
- const { value, literal, range } = input;
2032
- const predicate = {
2033
- leftPath: `$.fields.${field.apiName}.value`,
2034
- operator,
2035
- value,
2036
- alias,
2037
- dataType: field.dataType,
2038
- type: PredicateType.single,
2039
- isCaseSensitive: false,
2040
- };
2041
- if (value !== undefined) {
2042
- if (value === null) {
2043
- switch (predicate.operator) {
2044
- case '=':
2045
- predicate.operator = 'IS';
2046
- break;
2047
- case '!=':
2048
- predicate.operator = 'IS NOT';
2049
- break;
2050
- default:
2051
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
2052
- throw new Error(`Unsupported operator ${predicate.operator} with null value operand`);
2053
- }
2054
- predicate.value = 'NULL';
2055
- }
2056
- else {
2057
- const dateFn = field.dataType === 'Date' ? 'date' : 'datetime';
2058
- predicate.value = `${dateFn}(?)`;
2059
- predicate.bindings = [value];
2060
- }
2061
- return predicate;
2062
- }
2063
- else if (literal !== undefined) {
2064
- const isAvailableLiteral = values$1(DateLiteral).includes(literal);
2065
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
2066
- if (!isAvailableLiteral)
2067
- throw new Error(`${literal} is not a valid DateLiteral`);
2068
- return dateLiteral(literal, operator, field, alias);
2069
- }
2070
- else if (range !== undefined) {
2071
- return dateTimeRange(range, operator, field, alias);
2072
- }
2073
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
2074
- throw new Error(`Where filter ${stringify(input)} is not supported`);
2075
- }
2076
- function dateTimeRange(input, op, field, alias) {
2077
- const dateFunction = field.dataType === 'DateTime' ? 'datetime' : 'date';
2078
- const key = keys$1(input)[0];
2079
- let operator = op;
2080
- if (operator === '=')
2081
- operator = 'BETWEEN';
2082
- if (operator === '!=')
2083
- operator = 'NOT BETWEEN';
2084
- let value;
2085
- let bindings = [];
2086
- const { range, binding } = dateRangesFrom(key, input[key], dateFunction);
2087
- switch (operator) {
2088
- case '<':
2089
- case '>=':
2090
- value = range.lower;
2091
- bindings = [binding.lower];
2092
- break;
2093
- case '>':
2094
- case '<=':
2095
- value = range.upper;
2096
- bindings = [binding.upper];
2097
- break;
2098
- default:
2099
- value = `${range.lower} AND ${range.upper}`;
2100
- bindings = [binding.lower, binding.upper];
2101
- break;
2102
- }
2103
- return {
2104
- leftPath: `$.fields.${field.apiName}.value`,
2105
- operator,
2106
- value,
2107
- bindings,
2108
- type: PredicateType.single,
2109
- alias,
2110
- dataType: field.dataType,
2111
- };
2112
- }
2113
- // relative date ranges defined at https://help.salesforce.com/s/articleView?id=sf.filter_dates_relative.htm&type=5
2114
- function dateRangesFrom(dateRange, input, dateFunction) {
2115
- // use 'start of day' to ensure the timestamp is 00:00:00 for date time values
2116
- switch (dateRange) {
2117
- // next_n_days range starts at tomorrow through n days
2118
- case DateRange.next_n_days: {
2119
- return {
2120
- binding: {
2121
- upper: `${input} days`,
2122
- lower: '1 days',
2123
- },
2124
- range: {
2125
- upper: `${dateFunction}('now', 'start of day', ?)`,
2126
- lower: `${dateFunction}('now', 'start of day', ?)`,
2127
- },
2128
- };
2129
- }
2130
- // last_n_days starts -(n) days until today at the current second
2131
- case DateRange.last_n_days: {
2132
- return {
2133
- binding: {
2134
- upper: `0 days`,
2135
- lower: `-${input} days`,
2136
- },
2137
- range: {
2138
- upper: `${dateFunction}('now', ?)`,
2139
- lower: `${dateFunction}('now', 'start of day', ?)`,
2140
- },
2141
- };
2142
- }
2143
- // n_days_ago
2144
- // starts 12:00:00 am -(n) days from today
2145
- // ends 11:59:99 pm -(n) days from today
2146
- case DateRange.n_days_ago: {
2147
- return {
2148
- binding: {
2149
- upper: `${-input + 1} days`,
2150
- lower: `-${input} days`,
2151
- },
2152
- range: {
2153
- upper: `${dateFunction}('now', 'start of day', ?, '-1 seconds')`,
2154
- lower: `${dateFunction}('now', 'start of day', ?)`,
2155
- },
2156
- };
2157
- }
2158
- // next_n_weeks
2159
- // starts at 00:00:00 the first day of the week n weeks after the current week
2160
- // ends 23:59:59 of the last day of week before the current
2161
- case DateRange.next_n_weeks: {
2162
- const isStartOfWeek = isTodayStartOfWeek();
2163
- return {
2164
- binding: {
2165
- // weekday FIRST_DAY_OF_WEEK goes to the next weekday of FIRST_DAY_OF_WEEK if not that current day
2166
- // if that current day then it will be that day
2167
- // so for the upper bound if today is the start of the week we need to add 7 more days to the value to get next week as the start
2168
- upper: `${input * 7 + (isStartOfWeek ? 7 : 0)} days`,
2169
- //lower bound starts out 00:00:00 of next week
2170
- lower: `${isStartOfWeek ? 7 : 0} days`,
2171
- },
2172
- range: {
2173
- upper: `${dateFunction}('now', 'weekday ${FIRST_DAY_OF_WEEK}', 'start of day', ?, '-1 seconds')`,
2174
- lower: `${dateFunction}('now', 'weekday ${FIRST_DAY_OF_WEEK}', 'start of day', ?)`,
2175
- },
2176
- };
2177
- }
2178
- // last_n_weeks
2179
- // starts at 00:00:00 of day 0 n weeks before the current week
2180
- // ends 23:59:59 at last day of the week before the current week
2181
- case DateRange.last_n_weeks: {
2182
- const isStartOfWeek = isTodayStartOfWeek();
2183
- return {
2184
- binding: {
2185
- // ending on at 23:59:59 of the week before the current week
2186
- // -7 more days if today not start of week
2187
- upper: `${-(isStartOfWeek ? 0 : 7)} days`,
2188
- // starting on 00:00:00 of n * weeks before current week
2189
- // -7 more days if today not the start of the week because weekday FIRST_DAY_OF_WEEK puts us next week day 0
2190
- lower: `${-input * 7 - (isStartOfWeek ? 0 : 7)} days`,
2191
- },
2192
- range: {
2193
- upper: `${dateFunction}('now', 'weekday ${FIRST_DAY_OF_WEEK}', 'start of day', ?, '-1 seconds')`,
2194
- lower: `${dateFunction}('now', 'weekday ${FIRST_DAY_OF_WEEK}', 'start of day', ?)`,
2195
- },
2196
- };
2197
- }
2198
- // n_weeks_ago
2199
- // starts 00:00:00 on day 0 of n weeks before the current week
2200
- // ends 7 days after the start
2201
- case DateRange.n_weeks_ago: {
2202
- const isStartOfWeek = isTodayStartOfWeek();
2203
- return {
2204
- binding: {
2205
- // end of week n weeks before current week
2206
- // if today is start of the week then we need to -7 from the days given by n
2207
- // so add 7 to remove a week from -(n)
2208
- upper: `${-input * 7 + (isStartOfWeek ? 7 : 0)} days`,
2209
- // start of the week n weeks from the current week
2210
- // if today is the start of the week then -(n) will do to be the previous week, but
2211
- // if today is not the start of the week we need to go back 1 more week since weekday FIRST_DAY_OF_WEEK will put us next week
2212
- lower: `${-input * 7 - (isStartOfWeek ? 0 : 7)} days`,
2213
- },
2214
- range: {
2215
- upper: `${dateFunction}('now', 'weekday ${FIRST_DAY_OF_WEEK}', 'start of day', ?, '-1 seconds')`,
2216
- lower: `${dateFunction}('now', 'weekday ${FIRST_DAY_OF_WEEK}', 'start of day', ?)`,
2217
- },
2218
- };
2219
- }
2220
- // next_n_months
2221
- // starts the first day of the next month at 00:00:00 and
2222
- // ends end of the nth month 23:59:59
2223
- case DateRange.next_n_months: {
2224
- return {
2225
- binding: {
2226
- upper: `${input + 1} months`,
2227
- lower: `1 months`,
2228
- },
2229
- range: {
2230
- upper: `${dateFunction}('now', 'start of month', ?, '-1 seconds')`,
2231
- lower: `${dateFunction}('now', 'start of month', ?)`,
2232
- },
2233
- };
2234
- }
2235
- // last_n_months
2236
- // starts at 00:00:00 first day of n months before the current month and
2237
- // ends at 23:59:59 the last day of the month before the current month
2238
- case DateRange.last_n_months: {
2239
- return {
2240
- binding: {
2241
- upper: `0 months`,
2242
- lower: `${-input} months`,
2243
- },
2244
- range: {
2245
- upper: `${dateFunction}('now', 'start of month', ?, '-1 seconds')`,
2246
- lower: `${dateFunction}('now', 'start of month', ?)`,
2247
- },
2248
- };
2249
- }
2250
- // n_months_ago
2251
- // starts at the first day of the month 00:00:00 n months ago from now
2252
- // ends at 23:59:59 of n months ago
2253
- case DateRange.n_months_ago: {
2254
- return {
2255
- binding: {
2256
- // need to go 1 less month back then -1 seconds to get the end of it
2257
- upper: `${-input + 1} months`,
2258
- lower: `-${input} months`,
2259
- },
2260
- range: {
2261
- upper: `${dateFunction}('now', 'start of month', ?, '-1 seconds')`,
2262
- lower: `${dateFunction}('now', 'start of month', ?)`,
2263
- },
2264
- };
2265
- }
2266
- // next_n_years
2267
- // starts 00:00:00 Jan 1st the year after the current year
2268
- // ends Dec 31 23:59:59 of the nth year
2269
- case DateRange.next_n_years: {
2270
- return {
2271
- binding: {
2272
- upper: `+${input + 1} years`,
2273
- lower: `+1 year`,
2274
- },
2275
- range: {
2276
- upper: `${dateFunction}('now', 'start of year', ?, '-1 seconds')`,
2277
- lower: `${dateFunction}('now', 'start of year', ?)`,
2278
- },
2279
- };
2280
- }
2281
- // last_n_years starts
2282
- // starts 00:00:00 Jan 1 n+1 year ago and
2283
- // ends dec 31 23:59:59 of the year before the current
2284
- case DateRange.last_n_years: {
2285
- return {
2286
- binding: {
2287
- upper: `-1 seconds`,
2288
- lower: `-${input + 1} years`,
2289
- },
2290
- range: {
2291
- upper: `${dateFunction}('now', 'start of year', ?)`,
2292
- lower: `${dateFunction}('now', 'start of year', ?)`,
2293
- },
2294
- };
2295
- }
2296
- // n_years_ago
2297
- // starts 00:00:00 Jan 1 of n years before the current year and
2298
- // ends Dec 31 23:59:59 of that year
2299
- case DateRange.n_years_ago: {
2300
- return {
2301
- binding: {
2302
- upper: `-${input - 1} years`,
2303
- lower: `-${input} years`,
2304
- },
2305
- range: {
2306
- upper: `${dateFunction}('now', 'start of year', ?, '-1 seconds')`,
2307
- lower: `${dateFunction}('now', 'start of year', ?)`,
2308
- },
2309
- };
2310
- }
2311
- // next_n_quarters
2312
- // starts 00:00:00 first day of the quarter after the current quarter
2313
- // ends 23:59:59 of the last day of n quarters in the future
2314
- case DateRange.next_n_quarters: {
2315
- const currentQuarterString = quarterStart(new Date());
2316
- return {
2317
- binding: {
2318
- // add another quarter input to -1 seconds to get the end of the last day of the quarter
2319
- upper: `${(input + 1) * 3} months`,
2320
- lower: `3 months`,
2321
- },
2322
- range: {
2323
- upper: `${dateFunction}('${currentQuarterString}', 'start of day', ?, '-1 seconds')`,
2324
- lower: `${dateFunction}('${currentQuarterString}', 'start of day', ?)`,
2325
- },
2326
- };
2327
- }
2328
- // last_n_quarters
2329
- // starts 00:00:00 the first day of n quarters ago
2330
- // end 23:59:59 the last day of the quarter before the current quarter
2331
- case DateRange.last_n_quarters: {
2332
- const currentQuarterString = quarterStart(new Date());
2333
- return {
2334
- binding: {
2335
- upper: `-1 seconds`,
2336
- lower: `-${input * 3} months`,
2337
- },
2338
- range: {
2339
- upper: `${dateFunction}('${currentQuarterString}', 'start of day', ?)`,
2340
- lower: `${dateFunction}('${currentQuarterString}', 'start of day', ?)`,
2341
- },
2342
- };
2343
- }
2344
- // n_quarters_ago
2345
- // starts 00:00:00 first day of the quarter n quarters before the current
2346
- // ends 23:59:59 last day of the same quarter
2347
- case DateRange.n_quarters_ago: {
2348
- const currentQuarterString = quarterStart(new Date());
2349
- return {
2350
- binding: {
2351
- // minus 1 quarter to be able to -1 seconds to get the end of the nth quarter
2352
- upper: `-${(input - 1) * 3} months`,
2353
- lower: `-${input * 3} months`,
2354
- },
2355
- range: {
2356
- upper: `${dateFunction}('${currentQuarterString}', 'start of day', ?, '-1 seconds')`,
2357
- lower: `${dateFunction}('${currentQuarterString}', 'start of day', ?)`,
2358
- },
2359
- };
2360
- }
2361
- default:
2362
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
2363
- throw new Error(`DateRangeInput ${dateRange} is not supported in local evalutation`);
2364
- }
2365
- }
2366
- function isTodayStartOfWeek() {
2367
- return new Date().getDay() === FIRST_DAY_OF_WEEK;
2368
- }
2369
-
2370
- const JSON_EXTRACT_PATH_INGESTION_TIMESTAMP = '$.ingestionTimestamp';
2371
- const JSON_EXTRACT_PATH_INGESTION_APINAME = '$.apiName';
2372
- const JSON_EXTRACT_PATH_DRAFTS = '$.drafts';
2373
-
2374
- const MultiPickListValueSeparator = ';';
2375
- function filterToPredicates(where, recordType, alias, objectInfoMap, joins, draftFunctions) {
2376
- if (!where)
2377
- return [];
2378
- let predicates = [];
2379
- const fields = keys$1(where);
2380
- for (const field of fields) {
2381
- if (field === 'and' || field === 'or') {
2382
- predicates.push(processCompoundPredicate(field, where[field], recordType, alias, objectInfoMap, joins));
2383
- }
2384
- if (field === 'not') {
2385
- // get the predicates that are one level below the not field
2386
- const children = filterToPredicates(where[field], recordType, alias, objectInfoMap, joins);
2387
- // wrap a not predicate around all the child/children predicate
2388
- const notPredicates = children.map((predicate) => {
2389
- return {
2390
- type: PredicateType.not,
2391
- operator: 'not',
2392
- children: [predicate],
2393
- };
2394
- });
2395
- predicates = predicates.concat(notPredicates);
2396
- }
2397
- const fieldInfo = findFieldInfo(objectInfoMap[recordType], field);
2398
- if (!fieldInfo) {
2399
- continue;
2400
- }
2401
- // handles spanning field filter. For example, for 'OwnerId' field within 'Account' objectInfo, both 'OwnerId' and 'Owner' can be
2402
- // treated as reference type, while 'Owner' field spanns since it equals to 'relationshipName'
2403
- if (fieldInfo.dataType === 'Reference' && fieldInfo.relationshipName === field) {
2404
- const path = {
2405
- leftPath: `$.fields.${fieldInfo.apiName}.value`,
2406
- rightPath: `$.id`,
2407
- };
2408
- const childAlias = `${alias}_${field}`;
2409
- // Join can happen on polymorphic field too which has more than 1 `referenceToInfo`. If 'apiName' is undefined, it indicates a Join on polymorphic field.
2410
- const join = {
2411
- type: 'LEFT',
2412
- alias: childAlias,
2413
- to: alias,
2414
- conditions: [path],
2415
- apiName: fieldInfo.referenceToInfos.length === 1
2416
- ? fieldInfo.referenceToInfos[0].apiName
2417
- : undefined,
2418
- };
2419
- joins.push(join);
2420
- // 'RelationshipName' can be different from 'apiName'. For example, 'OwnerId' field
2421
- // in 'Account' has the 'Owner' as the 'RelationshipName', the api name in 'referenceToInfos' is 'User'
2422
- if (fieldInfo.referenceToInfos.length === 1) {
2423
- const childRecordType = fieldInfo.referenceToInfos[0].apiName;
2424
- predicates.push(...filterToPredicates(where[field], childRecordType, childAlias, objectInfoMap, joins));
2425
- }
2426
- else {
2427
- // @W-12618378 polymorphic query sometimes does not work as expected on server. The GQL on certain entities could fail.
2428
- const entityNames = keys$1(where[field]);
2429
- const polyPredicatesGroups = entityNames
2430
- .filter((entityName) => fieldInfo.referenceToInfos.some((referenceInfo) => referenceInfo.apiName === entityName))
2431
- .map((entityName) => {
2432
- return [
2433
- {
2434
- alias: childAlias,
2435
- leftPath: JSON_EXTRACT_PATH_INGESTION_APINAME,
2436
- operator: '=',
2437
- value: entityName,
2438
- dataType: 'String',
2439
- type: PredicateType.single,
2440
- isCaseSensitive: true,
2441
- },
2442
- ...filterToPredicates(where[field][entityName], entityName, childAlias, objectInfoMap, joins),
2443
- ];
2444
- });
2445
- if (polyPredicatesGroups.length === 1) {
2446
- predicates.push(...polyPredicatesGroups[0]);
2447
- }
2448
- else {
2449
- // if polymorphic field has more than 1 entity like `{Owner: { User: {...} Group: {...}}}`, precidates for each entity(`User` and `Group`) should have
2450
- // `and` operation. while at the base polymorphic field level (`Owner`), the group of compound predicates for each entity should have `or` operation.
2451
- const polyCompoundPredicates = polyPredicatesGroups.map((polyEntityPredicates) => transformCompoundPredicate('and', polyEntityPredicates));
2452
- predicates.push(transformCompoundPredicate('or', polyCompoundPredicates));
2453
- }
2454
- }
2455
- }
2456
- else {
2457
- //`field` match the filedInfo's apiName
2458
- for (const [op, value] of entries$1(where[field])) {
2459
- const operator = operatorToSql(op);
2460
- /**
2461
- Two types ID processing might be needed. Draft ID swapping is optional, which depends on DraftFunctions existence.
2462
- 1. Coercing is needed when query is executed against local db if field is Id field of entity or a reference to an entity. It is OK to use 15 char ID to query agaist server,
2463
- so there is no need to coerce the ID in injected AST which is used by luvio to do the network request when necessary.
2464
- 2. Draft ID swapping is needed when adapter rebuild is triggered. Draft ID swapping also happens in field injection phase when adapter call is invoked. The injected AST node has
2465
- the canonical ID and is passed to Luvio
2466
- */
2467
- const idProcessingNeeded = isIDValueField(fieldInfo);
2468
- const makePredicate = fieldInfo.dataType === 'MultiPicklist'
2469
- ? createMultiPicklistPredicate
2470
- : createSinglePredicate;
2471
- const predicate = makePredicate(idProcessingNeeded ? sanitizePredicateIDValue(value, draftFunctions) : value, operator, fieldInfo, alias);
2472
- // for the case where we have a not equals predicate that's value is not null
2473
- // we need to compound into an or statement to also inlcude the null values for that field
2474
- if (operator === '!=' && typeof value === 'string') {
2475
- // create a is null predicate
2476
- const isNullPredicate = createSinglePredicate(null, '=', fieldInfo, alias);
2477
- // compound the predicates into an or predicate
2478
- predicates.push(transformCompoundPredicate('or', [predicate, isNullPredicate]));
2479
- }
2480
- else {
2481
- predicates.push(predicate);
2482
- }
2483
- }
2484
- }
2485
- }
2486
- return predicates;
2487
- }
2488
- /**
2489
- *
2490
- * @param fieldInfo
2491
- * @returns true if field is of IDValue type
2492
- */
2493
- function isIDValueField(fieldInfo) {
2494
- return fieldInfo.apiName === 'Id' || fieldInfo.referenceToInfos.length > 0;
2495
- }
2496
- /**
2497
- * Coerces and swaps ID if it is a draft ID.
2498
- * @param value Predicate value which might be a string value like 'John' or a List like ['Acme', 'John']
2499
- * @param draftFunction optional. If undefined, draft ID swapping does not happen
2500
- * @returns sanitized previdicate value
2501
- */
2502
- function sanitizePredicateIDValue(value, draftFunction) {
2503
- if (isArray(value)) {
2504
- return value.map((singleValue) => sanitizePredicateIDValue(singleValue, draftFunction));
2505
- }
2506
- else if (typeof value === 'string' && value === '') {
2507
- return value;
2508
- }
2509
- else {
2510
- const coercedId = getRecordId18(value);
2511
- if (coercedId !== undefined) {
2512
- if (draftFunction !== undefined && draftFunction.isDraftId(coercedId)) {
2513
- return draftFunction.getCanonicalId(coercedId);
2514
- }
2515
- return coercedId;
2516
- }
2517
- return value;
2518
- }
2519
- }
2520
- function createMultiPicklistPredicate(value, operator, fieldInfo, alias) {
2521
- if (!value || (isArray(value) && value.length === 0)) {
2522
- // eslint-disable-next-line
2523
- throw new Error(`No value specified for MultiPickList filter`);
2524
- }
2525
- // generate single prodicate for = and !=
2526
- if (operator === '=' || operator === '!=') {
2527
- // The raw value could be ';;a; b;;', clean it up to 'a;b'
2528
- const welformatedValue = value
2529
- .toString()
2530
- .split(MultiPickListValueSeparator)
2531
- .map((v) => v.trim())
2532
- .filter((v) => v.length > 0)
2533
- .join(MultiPickListValueSeparator);
2534
- return createSinglePredicate(welformatedValue, operator, fieldInfo, alias);
2535
- }
2536
- // if we have more than 1 value in the array from an includes/excludes we must split the values into
2537
- // a compound OR predicate for includes, AND predicate for excludes. each predicate could a composite
2538
- // if the value in the array is ; separated. sample: ['a:b','c']
2539
- const valueArray = isArray(value) ? value : [value];
2540
- return {
2541
- type: PredicateType.compound,
2542
- operator: operator === 'LIKE' ? 'or' : 'and',
2543
- children: valueArray.map((v) => {
2544
- const splittedValue = v
2545
- .split(MultiPickListValueSeparator)
2546
- .map((v) => v.trim())
2547
- .filter((v) => v.length > 0);
2548
- if (splittedValue.length === 1) {
2549
- return createSinglePredicate(v, operator, fieldInfo, alias);
2550
- }
2551
- else {
2552
- return {
2553
- type: PredicateType.compound,
2554
- operator: operator === 'LIKE' ? 'and' : 'or',
2555
- children: splittedValue.map((vInner) => createSinglePredicate(vInner, operator, fieldInfo, alias)),
2556
- };
2557
- }
2558
- }),
2559
- };
2560
- }
2561
- function createSinglePredicate(val, operator, field, alias) {
2562
- let value = val;
2563
- if (field.dataType === 'MultiPicklist') {
2564
- value = multiPicklistToSql(operator, val);
2565
- }
2566
- else if (typeof value !== 'object' &&
2567
- !isArray(value) &&
2568
- typeof value !== 'number' &&
2569
- (typeof value !== 'string' || typeof value !== 'boolean')) {
2570
- value = value.toString();
2571
- }
2572
- else if (isDateTimeInput(value)) {
2573
- return dateTimePredicate(value, operator, field, alias);
2574
- }
2575
- let leftPath = `$.fields.${field.apiName}.value`;
2576
- if (field.apiName === 'Id') {
2577
- leftPath = '$.id';
2578
- }
2579
- else if (field.apiName === 'weakEtag') {
2580
- leftPath = '$.weakEtag';
2581
- }
2582
- else if (field.apiName === 'RecordTypeId') {
2583
- leftPath = '$.recordTypeId';
2584
- }
2585
- return {
2586
- alias,
2587
- leftPath,
2588
- operator,
2589
- value,
2590
- dataType: field.dataType,
2591
- type: PredicateType.single,
2592
- isCaseSensitive: isIDField(field),
2593
- };
2594
- }
2595
- function isIDField(field) {
2596
- return field.apiName === 'Id' || field.referenceToInfos.length > 0;
2597
- }
2598
- function multiPicklistToSql(operator, value) {
2599
- // Individual multipicklist terms that delimited by semicolon are stored server-side
2600
- // as lexically sorted strings and treated like logical ANDs. We can approximate this
2601
- // behavior in SQL with wildcarded `LIKE` SQL operators. Terms with no delimiter can
2602
- // be treated as string literals. Multiple terms are logically OR'd together to
2603
- // match the behavior described in SOQL documentation (https://sfdc.co/c9j0r)
2604
- // To make sure the match is safe for includes/excludes. the value is prefix and
2605
- // suffix with ';', like 'abc' to '%;abc;%'. raw value for eq and ne.
2606
- if (operator === 'LIKE' || operator === 'NOT LIKE') {
2607
- return `%${MultiPickListValueSeparator}${value}${MultiPickListValueSeparator}%`;
2608
- }
2609
- else {
2610
- return value;
2611
- }
2612
- }
2613
- // handles 'SinglePredicate' | 'CompoundPredicate'| 'NotPredicate' conversion to SQLite
2614
- function predicateToSQL(predicate, defaultAlias, isChildNotPredicate = false) {
2615
- if (isSinglePredicate(predicate)) {
2616
- return singlePredicateToSql(predicate, defaultAlias, isChildNotPredicate);
2617
- }
2618
- else if (isNotPredicate(predicate)) {
2619
- return notPredicateToSql(predicate, defaultAlias);
2620
- }
2621
- else {
2622
- return flattenSqlAndBindings(predicatesToSqls(predicate.children, defaultAlias, isChildNotPredicate), predicate.operator);
2623
- }
2624
- }
2625
- /**
2626
- * Takes an array of predicates turned to sql and flattens them into one statement string
2627
- * with combined bindings
2628
- * @param sqlAndBindings
2629
- * @param operator
2630
- * @returns
2631
- */
2632
- function flattenSqlAndBindings(sqlAndBindings, operator) {
2633
- const joiner = operator === undefined ? ' ' : ` ${operator} `.toUpperCase();
2634
- const sql = sqlAndBindings.map((sqlAndBinding) => sqlAndBinding.sql).join(joiner);
2635
- const binding = sqlAndBindings
2636
- .map((sqlAndBinding) => sqlAndBinding.binding)
2637
- .reduce(flatten, []);
2638
- return { sql, binding };
2639
- }
2640
- function inOrNotInValuesIncludeNull(predicate) {
2641
- const isInOrNin = predicate.operator === 'IN' || predicate.operator === 'NOT IN';
2642
- const nullValueExists = isArray(predicate.value)
2643
- ? predicate.value.some((v) => v === null)
2644
- : predicate.value === null;
2645
- return isInOrNin && nullValueExists;
2646
- }
2647
- /**
2648
- * Takes a single predicate and appends AND IS NOT NULL to the end of it.
2649
- * So when we wrap a NOT around the predicate it will include non-null values.
2650
- * @param predicate
2651
- * @param defaultAlias
2652
- * @returns
2653
- */
2654
- function singleNotPredicateToIncludeNulls(predicate, defaultAlias) {
2655
- // if we are checking a value of null then there is no need to append on and is not null
2656
- // also do not add to in/nin predicates
2657
- if (predicate.value === null || inOrNotInValuesIncludeNull(predicate)) {
2658
- return predicateToSQL(predicate, defaultAlias);
2659
- }
2660
- const { sql, binding } = predicateToSQL(predicate, defaultAlias);
2661
- const notNull = { ...predicate, operator: 'IS NOT', value: null };
2662
- const notNullSql = predicateToSQL(notNull, defaultAlias);
2663
- return {
2664
- sql: `${sql} AND ${notNullSql.sql}`,
2665
- binding: binding.concat(notNullSql.binding),
2666
- };
2667
- }
2668
- function notPredicateToSql(predicate, defaultAlias) {
2669
- const children = predicate.children.map((child) => {
2670
- if (isNotPredicate(child)) {
2671
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
2672
- throw new Error('A not predicate cannot be a child of a not query');
2673
- }
2674
- if (isSinglePredicate(child)) {
2675
- const { sql, binding } = singleNotPredicateToIncludeNulls(child, defaultAlias);
2676
- return { sql: `NOT ( ${sql} )`, binding };
2677
- }
2678
- else {
2679
- const compound = child.children.map((c) => {
2680
- if (isSinglePredicate(c)) {
2681
- const { sql, binding } = singleNotPredicateToIncludeNulls(c, defaultAlias);
2682
- return { sql: `( ${sql} )`, binding };
2683
- }
2684
- else {
2685
- return predicateToSQL(c, defaultAlias, true);
2686
- }
2687
- });
2688
- const { sql, binding } = flattenSqlAndBindings(compound, child.operator);
2689
- return { sql: `( NOT ( ${sql} ) )`, binding };
2690
- }
2691
- });
2692
- return flattenSqlAndBindings(children);
2693
- }
2694
- /**
2695
- * Used to build a SinglePredicate into a sql statement with bindings
2696
- * @param predicate
2697
- * @param defaultAlias
2698
- * @returns
2699
- */
2700
- function singlePredicateToSql(predicate, defaultAlias, isChildNotPredicate = false) {
2701
- //if a child of a not predicate than we need to include nulls
2702
- if (isChildNotPredicate) {
2703
- return singleNotPredicateToIncludeNulls(predicate, defaultAlias);
2704
- }
2705
- // handles different type of filter predicate like 'date', 'picklist', 'time', 'percent'
2706
- let { alias, leftPath, operator, value, dataType, isCaseSensitive } = predicate;
2707
- let binding = [];
2708
- let boundValue = extractPredicateValue(value, dataType);
2709
- // Handles boolean type field
2710
- if (dataType === 'Boolean') {
2711
- if (boundValue === null) {
2712
- if (operator === '=') {
2713
- operator = 'IS';
2714
- }
2715
- boundValue = 'NULL';
2716
- }
2717
- else if (boundValue === true) {
2718
- boundValue = 1;
2719
- }
2720
- else {
2721
- boundValue = 0;
2722
- }
2723
- }
2724
- if (boundValue === null) {
2725
- if (operator === '=') {
2726
- operator = 'IS';
2727
- }
2728
- else if (operator === '!=') {
2729
- operator = 'IS NOT';
2730
- }
2731
- }
2732
- alias = !alias ? defaultAlias : alias;
2733
- let sql;
2734
- if (predicate.bindings !== undefined) {
2735
- if (predicate.dataType !== undefined &&
2736
- (predicate.dataType === 'DateTime' || predicate.dataType === 'Date')) {
2737
- const dateFunction = predicate.dataType === 'DateTime' ? 'datetime' : 'date';
2738
- sql = `${dateFunction}(json_extract("${alias}".data, '${leftPath}')) ${operator} ${predicate.value}`;
2739
- }
2740
- else {
2741
- sql = `json_extract("${alias}".data, '${leftPath}') ${operator} ${predicate.value}`;
2742
- }
2743
- binding = binding.concat(predicate.bindings);
2744
- }
2745
- else {
2746
- if (operator === 'IN' || operator === 'NOT IN') {
2747
- const { sql: questionSql, binding: valueBinding, includesNull, } = handleExtractedPredicateValue(boundValue, true);
2748
- // If an explicit collating sequence is required on an IN operator it should be applied to the left operand,
2749
- // like this: "x COLLATE NOCASE IN (y,z, ...)".
2750
- const nullCheck = `json_extract("${alias}".data, '${leftPath}') ${operator === 'IN' ? 'IS' : 'IS NOT'} ?`;
2751
- sql = `json_extract("${alias}".data, '${leftPath}')${isCaseSensitive === true ? '' : ` COLLATE NOCASE`} ${operator} ${questionSql}`;
2752
- binding.push(...valueBinding);
2753
- if (includesNull) {
2754
- sql = `(${sql} OR ${nullCheck})`;
2755
- binding.push(null);
2756
- }
2757
- }
2758
- else {
2759
- const { sql: questionSql, binding: valueBinding } = handleExtractedPredicateValue(boundValue, false);
2760
- // SQLite is case sensitive by default, SOQL is case in-sensitive by default
2761
- // For pick list includes or excludeds, prefix and suffix the field value with ';' to guarantee the query accuracy.
2762
- if (dataType === 'MultiPicklist' && (operator === 'LIKE' || operator === 'NOT LIKE')) {
2763
- sql = `'${MultiPickListValueSeparator}' || json_extract("${alias}".data, '${leftPath}') || '${MultiPickListValueSeparator}' ${operator} ${questionSql} COLLATE NOCASE`;
2764
- }
2765
- else {
2766
- sql = `json_extract("${alias}".data, '${leftPath}') ${operator} ${questionSql}${isCaseSensitive === true ? '' : ` COLLATE NOCASE`}`;
2767
- }
2768
- binding.push(...valueBinding);
2769
- }
2770
- }
2771
- return { sql, binding };
2772
- }
2773
- // for one value, return { sql: '?', bindings:'xxx'}. for multiple value, return { sql: '(?, ?, ?)', binding: ['xxx','yyy','zzz'] }
2774
- function handleExtractedPredicateValue(boundValue, checkForNull) {
2775
- let questionSql = '?';
2776
- let binding = [];
2777
- let includesNull = false;
2778
- if (isArray(boundValue)) {
2779
- const removeNull = boundValue.filter((v) => v !== null);
2780
- includesNull = removeNull.length !== boundValue.length;
2781
- // construct (?, ?)
2782
- questionSql = `(${new Array(checkForNull ? removeNull.length : boundValue.length)
2783
- .fill('?')
2784
- .join(', ')})`;
2785
- binding = binding.concat(...(checkForNull ? removeNull : boundValue));
2786
- }
2787
- else {
2788
- binding = binding.concat(boundValue);
2789
- }
2790
- return { sql: questionSql, binding, includesNull };
2791
- }
2792
- function processCompoundPredicate(operator, filters, recordType, alias, objectInfoMap, joins) {
2793
- const predicates = filters
2794
- .map((filter) => filterToPredicates(filter, recordType, alias, objectInfoMap, joins))
2795
- .reduce(flatten);
2796
- return transformCompoundPredicate(operator, predicates);
2797
- }
2798
- function transformCompoundPredicate(operator, childPredicates) {
2799
- const diffCompoundPredicates = childPredicates
2800
- .filter(isCompoundPredicate)
2801
- .filter((compoundPredicate) => compoundPredicate.operator !== operator);
2802
- // flattens the child compound predicate if its operator is the same of its parent to improve the SQL efficiency.
2803
- const sameCompoundPredicates = childPredicates
2804
- .filter(isCompoundPredicate)
2805
- .filter((compoundPredicate) => compoundPredicate.operator === operator)
2806
- .map((pred) => pred.children)
2807
- .reduce(flatten, []);
2808
- const singlePredicates = childPredicates.filter((p) => isSinglePredicate(p) || isNotPredicate(p));
2809
- const children = [...diffCompoundPredicates, ...sameCompoundPredicates, ...singlePredicates];
2810
- if (children.length === 1) {
2811
- return children[0];
2812
- }
2813
- return {
2814
- type: PredicateType.compound,
2815
- operator,
2816
- children,
2817
- };
2818
- }
2819
- function predicatesToSqls(predicates, defaultAlias, isChildNotPredicate = false) {
2820
- // (a and (b or c)) is differnt from (a and b or c)
2821
- const wrapit = predicates.length >= 1 && predicates.some(isCompoundPredicate);
2822
- const sqlAndBindingsResult = [];
2823
- if (wrapit) {
2824
- const unwrappedSqlAndBindings = predicates
2825
- .filter(isSinglePredicate)
2826
- .map((predicate) => predicateToSQL(predicate, defaultAlias, isChildNotPredicate));
2827
- if (unwrappedSqlAndBindings && unwrappedSqlAndBindings.length) {
2828
- sqlAndBindingsResult.push(...unwrappedSqlAndBindings);
2829
- }
2830
- const wrappedSqlAndBindings = predicates
2831
- .filter(isCompoundPredicate)
2832
- .map((predicate) => predicateToSQL(predicate, defaultAlias, isChildNotPredicate))
2833
- .map(wrapSqlAndBindings);
2834
- sqlAndBindingsResult.push(...wrappedSqlAndBindings);
2835
- }
2836
- else {
2837
- const sqlAndBindings = predicates.map((predicate) => predicateToSQL(predicate, defaultAlias, isChildNotPredicate));
2838
- sqlAndBindingsResult.push(...sqlAndBindings);
2839
- }
2840
- return sqlAndBindingsResult;
2841
- }
2842
- function wrapSqlAndBindings(sqlAndBindings) {
2843
- return { sql: `(` + sqlAndBindings.sql + `)`, binding: sqlAndBindings.binding };
2844
- }
2845
- function operatorToSql(graphqlOperator) {
2846
- switch (graphqlOperator) {
2847
- case 'eq':
2848
- return '=';
2849
- case 'ne':
2850
- return '!=';
2851
- case 'gt':
2852
- return '>';
2853
- case 'gte':
2854
- return '>=';
2855
- case 'lt':
2856
- return '<';
2857
- case 'lte':
2858
- return '<=';
2859
- case 'in':
2860
- return 'IN';
2861
- case 'nin':
2862
- return 'NOT IN';
2863
- case 'like':
2864
- case 'includes':
2865
- return 'LIKE';
2866
- case 'excludes':
2867
- return 'NOT LIKE';
2868
- default:
2869
- // eslint-disable-next-line
2870
- throw new Error(`Unknown GraphQL operator: ${graphqlOperator}`);
2871
- }
2872
- }
2873
- function extractPredicateValue(value, dataType) {
2874
- if (dataType !== undefined && dataType === 'Boolean') {
2875
- if (typeof value === 'string') {
2876
- return value === 'true';
2877
- }
2878
- if (typeof value === 'boolean')
2879
- return value;
2880
- }
2881
- if (typeof value !== 'object') {
2882
- if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
2883
- return value;
2884
- }
2885
- else {
2886
- return value.toString();
2887
- }
2888
- }
2889
- return value;
2890
- }
2891
-
2892
- var PredicateType;
2893
- (function (PredicateType) {
2894
- PredicateType["compound"] = "compound";
2895
- PredicateType["single"] = "single";
2896
- PredicateType["not"] = "not";
2897
- })(PredicateType || (PredicateType = {}));
2898
- function buildQuery(config) {
2899
- const joins = buildJoins(config);
2900
- const predicates = buildPredicates(config);
2901
- const orderBy = buildOrderBy(config);
2902
- const staleRecordsSql = excludeStaleRecordsGate.isOpen({ fallback: false })
2903
- ? `AND (
2904
- json_extract("${config.alias}".metadata, '${JSON_EXTRACT_PATH_INGESTION_TIMESTAMP}') >= ?
2905
- OR json_extract("${config.alias}".data, '${JSON_EXTRACT_PATH_DRAFTS}') IS NOT NULL
2906
- )`
2907
- : '';
2908
- const sql = `
2909
- SELECT "${config.alias}".data
2910
- FROM lds_data "${config.alias}" ${joins.sql}
2911
- WHERE "${config.alias}".key like 'UiApi::RecordRepresentation:%'
2912
- AND json_extract("${config.alias}".data, '${JSON_EXTRACT_PATH_INGESTION_APINAME}') = '${config.alias}'
2913
- ${staleRecordsSql}
2914
- ${predicates.sql}
2915
- ${orderBy.sql}
2916
- LIMIT ?
2917
- OFFSET ?
2918
- `
2919
- .split('\n')
2920
- .map((line) => line.trim())
2921
- .join(' ');
2922
- const bindings = [
2923
- // bindings from predicates on joins
2924
- ...joins.bindings,
2925
- ...(excludeStaleRecordsGate.isOpen({ fallback: false }) ? [config.ingestionTimestamp] : []),
2926
- // where clause and parent scope bindings
2927
- ...predicates.bindings,
2928
- // limit binding
2929
- config.limit || 10,
2930
- config.offset || 0,
2931
- ];
2932
- return { sql: sql.trim(), bindings };
2933
- }
2934
- function dedupeJoins(joins) {
2935
- const deduped = {};
2936
- for (const join of joins) {
2937
- deduped[join.alias + join.to] = join;
2938
- }
2939
- return values$1(deduped);
2940
- }
2941
- function buildJoins(config) {
2942
- let sql = '';
2943
- const bindings = [];
2944
- const orderByJoins = config.orderBy !== undefined ? removeUndefined(config.orderBy.map((x) => x.joins)) : [];
2945
- const allJoins = dedupeJoins([
2946
- ...(config.joins || []),
2947
- ...(orderByJoins.reduce(flatten, []) || []),
2948
- ]);
2949
- if (allJoins.length === 0)
2950
- return { sql, bindings };
2951
- sql = allJoins.reduce((joinAccumulator, join) => {
2952
- let timestampAdded = false;
2953
- const joinConditions = join.conditions.reduce((conditionAccumulator, condition) => {
2954
- let joined_sql;
2955
- const joinMetadataTimestamp = excludeStaleRecordsGate.isOpen({ fallback: false })
2956
- ? ` AND (json_extract("${join.alias}".metadata, '${JSON_EXTRACT_PATH_INGESTION_TIMESTAMP}') >= ? OR json_extract("${join.alias}".data, '${JSON_EXTRACT_PATH_DRAFTS}') IS NOT NULL)`
2957
- : '';
2958
- // predicate on a value, use the newly joined table
2959
- if ('type' in condition) {
2960
- const { sql, binding } = predicateToSQL(condition, join.alias);
2961
- joined_sql = ` AND ${sql}${timestampAdded ? '' : joinMetadataTimestamp}`;
2962
- bindings.push(...binding);
2963
- if (excludeStaleRecordsGate.isOpen({ fallback: false }) &&
2964
- timestampAdded === false) {
2965
- bindings.push(config.ingestionTimestamp);
2966
- timestampAdded = true;
2967
- }
2968
- }
2969
- else {
2970
- // predicate on a path
2971
- const left = ` AND json_extract("${join.to}".data, '${condition.leftPath}')`;
2972
- const right = `json_extract("${join.alias}".data, '${condition.rightPath}')`;
2973
- joined_sql = `${left} = ${right}${timestampAdded ? '' : joinMetadataTimestamp}`;
2974
- if (excludeStaleRecordsGate.isOpen({ fallback: false }) &&
2975
- timestampAdded === false) {
2976
- bindings.push(config.ingestionTimestamp);
2977
- timestampAdded = true;
2978
- }
2979
- }
2980
- conditionAccumulator += joined_sql;
2981
- return conditionAccumulator;
2982
- }, '');
2983
- // 'joinConditions' has the prefix 'AND_' which needs to be removed.
2984
- const formattedJoinCondition = joinConditions.slice(4);
2985
- joinAccumulator += `
2986
- ${join.type} JOIN lds_data "${join.alias}"
2987
- ON "${join.alias}".key like 'UiApi::RecordRepresentation:%'
2988
- AND${formattedJoinCondition}
2989
- `;
2990
- return joinAccumulator;
2991
- }, '');
2992
- return { sql, bindings };
2993
- }
2994
- function buildPredicates(config) {
2995
- if (!config.predicates)
2996
- return { sql: '', bindings: [] };
2997
- const sqlAndBindingsResult = predicatesToSqls(config.predicates, config.alias);
2998
- let sql = sqlAndBindingsResult.map((sqlAndBinding) => sqlAndBinding.sql).join(` AND `);
2999
- if (sql && sql.length > 0) {
3000
- sql = `AND ` + sql;
3001
- }
3002
- const bindings = sqlAndBindingsResult
3003
- .map((sqlAndBinding) => sqlAndBinding.binding)
3004
- .reduce(flatten, []);
3005
- return { sql, bindings };
3006
- }
3007
- function buildOrderBy(config) {
3008
- let sql = '';
3009
- if (!config.orderBy)
3010
- return { sql };
3011
- const orderByStatements = config.orderBy.reduce((accumulator, orderBy) => {
3012
- const sortOrder = orderBy.order !== undefined ? `${orderBy.order}` : ``;
3013
- const sortNulls = orderBy.nulls !== undefined ? ` NULLS ${orderBy.nulls}` : ``;
3014
- const statement = `json_extract("${orderBy.alias}".data, '${orderBy.path}') ${sortOrder} ${sortNulls}`;
3015
- accumulator.push(statement);
3016
- return accumulator;
3017
- }, []);
3018
- sql = `
3019
- ${orderByStatements.length > 0 ? 'ORDER BY' : ''}
3020
- ${orderByStatements.join(', ')}
3021
- `;
3022
- return { sql };
3023
- }
3024
- function isCompoundPredicate(predicate) {
3025
- return predicate.type === PredicateType.compound;
3026
- }
3027
- function isSinglePredicate(predicate) {
3028
- return predicate.type === PredicateType.single;
3029
- }
3030
- function isNotPredicate(predicate) {
3031
- return predicate.type === PredicateType.not;
3032
- }
3033
- function isDateTimeInput(object) {
3034
- return (object !== undefined &&
3035
- object !== null &&
3036
- typeof object === 'object' &&
3037
- (object.value !== undefined || object.literal !== undefined || object.range !== undefined));
3038
- }
3039
- const PARENT_RELATIONSHIP = 'parentRelationship';
3040
- function depth(json, currentLevel = 0) {
3041
- if (typeof json !== 'object') {
3042
- return currentLevel;
3043
- }
3044
- const keys$1$1 = keys$1(json);
3045
- if (keys$1$1.length === 0)
3046
- return 0;
3047
- const depths = keys$1$1.map((key) => {
3048
- const value = json[key];
3049
- return depth(value, currentLevel + 1);
3050
- });
3051
- return Math.max(...depths);
3052
- }
3053
- function flatten(previous, current) {
3054
- return previous.concat(current);
3055
- }
3056
- function findFieldInfo(objectInfo, fieldName) {
3057
- return values$1(objectInfo.fields).find((field) => field.apiName === fieldName ||
3058
- (field.dataType === 'Reference' && field.relationshipName === fieldName));
3059
- }
3060
- async function readIngestionTimestampForKey(key, query) {
3061
- let ingestionTimestamp = 0;
3062
- const sql = `SELECT json_extract(metadata, '${JSON_EXTRACT_PATH_INGESTION_TIMESTAMP}') FROM lds_data WHERE key IS ?`;
3063
- const results = await query(sql, [key]);
3064
- const [timestamp] = results.rows.map((row) => row[0]);
3065
- if (timestamp !== null) {
3066
- const numericalTimestamp = Number(timestamp);
3067
- if (isNaN(numericalTimestamp)) {
3068
- return ingestionTimestamp;
3069
- }
3070
- ingestionTimestamp = numericalTimestamp;
3071
- }
3072
- return ingestionTimestamp;
3073
- }
3074
-
3075
- function findSpanningField(name) {
3076
- return (field) => {
3077
- return (field.apiName === name ||
3078
- (field.dataType === 'Reference' && field.relationshipName === name));
3079
- };
3080
- }
3081
- function orderByToPredicate(orderBy, recordType, alias, objectInfoMap, joins) {
3082
- let predicates = [];
3083
- if (!orderBy)
3084
- return predicates;
3085
- const isSpanning = depth(orderBy) > 2;
3086
- if (isSpanning) {
3087
- const keys$1$1 = keys$1(orderBy);
3088
- for (let i = 0, len = keys$1$1.length; i < len; i++) {
3089
- const key = keys$1$1[i];
3090
- const parentFields = objectInfoMap[recordType].fields;
3091
- const fieldInfo = values$1(parentFields).find(findSpanningField(key));
3092
- if (fieldInfo && fieldInfo.referenceToInfos.length > 0) {
3093
- const { apiName } = fieldInfo.referenceToInfos[0];
3094
- const parentFieldInfo = values$1(objectInfoMap[recordType].fields).find(findSpanningField(fieldInfo.apiName));
3095
- if (parentFieldInfo !== undefined) {
3096
- const path = {
3097
- leftPath: `$.fields.${parentFieldInfo.apiName}.value`,
3098
- rightPath: '$.id',
3099
- };
3100
- const childAlias = `${alias}_${fieldInfo.relationshipName}`;
3101
- const join = [
3102
- {
3103
- type: 'LEFT',
3104
- alias: childAlias,
3105
- to: alias,
3106
- conditions: [path],
3107
- apiName: apiName,
3108
- },
3109
- ];
3110
- let spanningPredicates = orderByToPredicate(orderBy[key], apiName, childAlias, objectInfoMap, joins ? joins.concat(join) : join);
3111
- predicates = predicates.concat(spanningPredicates);
3112
- }
3113
- }
3114
- }
3115
- }
3116
- else {
3117
- const keys$1$1 = keys$1(orderBy);
3118
- for (let i = 0, len = keys$1$1.length; i < len; i++) {
3119
- const key = keys$1$1[i];
3120
- if (!objectInfoMap[recordType])
3121
- continue;
3122
- const fieldInfo = objectInfoMap[recordType].fields[key];
3123
- if (fieldInfo === undefined)
3124
- continue;
3125
- const { order, nulls } = orderBy[key];
3126
- const predicate = {
3127
- path: pathForKey(key),
3128
- alias,
3129
- order,
3130
- nulls,
3131
- joins,
3132
- };
3133
- predicates.push(predicate);
3134
- }
3135
- }
3136
- return predicates;
3137
- }
3138
- function pathForKey(key) {
3139
- switch (key) {
3140
- case 'ApiName':
3141
- return JSON_EXTRACT_PATH_INGESTION_APINAME;
3142
- case 'WeakEtag':
3143
- return '$.weakEtag';
3144
- case 'Id':
3145
- return '$.id';
3146
- default:
3147
- return `$.fields.${key}.value`;
3148
- }
3149
- }
3150
-
3151
- function scopeToJoins(scope = '', settings) {
3152
- if (scope !== 'ASSIGNEDTOME')
3153
- return [];
3154
- return [
3155
- {
3156
- alias: 'ServiceAppointment_AssignedResource',
3157
- type: 'INNER',
3158
- to: 'ServiceAppointment',
3159
- conditions: [
3160
- {
3161
- type: PredicateType.single,
3162
- alias: 'ServiceAppointment_AssignedResource',
3163
- leftPath: JSON_EXTRACT_PATH_INGESTION_APINAME,
3164
- operator: '=',
3165
- value: 'AssignedResource',
3166
- dataType: 'String',
3167
- isCaseSensitive: true,
3168
- },
3169
- {
3170
- leftPath: '$.id',
3171
- rightPath: '$.fields.ServiceAppointmentId.value',
3172
- },
3173
- ],
3174
- apiName: 'AssignedResource',
3175
- },
3176
- {
3177
- alias: 'ServiceAppointment_AssignedResource_ServiceResource',
3178
- type: 'INNER',
3179
- to: 'ServiceAppointment_AssignedResource',
3180
- conditions: [
3181
- {
3182
- type: PredicateType.single,
3183
- alias: 'ServiceAppointment_AssignedResource_ServiceResource',
3184
- leftPath: JSON_EXTRACT_PATH_INGESTION_APINAME,
3185
- operator: '=',
3186
- value: 'ServiceResource',
3187
- dataType: 'String',
3188
- isCaseSensitive: true,
3189
- },
3190
- {
3191
- leftPath: '$.fields.ServiceResourceId.value',
3192
- rightPath: '$.id',
3193
- },
3194
- {
3195
- type: PredicateType.single,
3196
- alias: 'ServiceAppointment_AssignedResource_ServiceResource',
3197
- leftPath: '$.fields.RelatedRecordId.value',
3198
- operator: '=',
3199
- value: settings.userId,
3200
- dataType: 'String',
3201
- isCaseSensitive: true,
3202
- },
3203
- ],
3204
- apiName: 'ServiceResource',
3205
- },
3206
- ];
3207
- }
3208
- function scopeToPredicates(scope = '', settings) {
3209
- if (scope !== 'MINE')
3210
- return [];
3211
- return [
3212
- {
3213
- type: PredicateType.single,
3214
- leftPath: '$.fields.OwnerId.value',
3215
- operator: '=',
3216
- value: settings.userId,
3217
- },
3218
- ];
3219
- }
3220
-
3221
- // Code lifted from https://github.com/MaxArt2501/base64-js/blob/master/base64.js
3222
- // base64 character set, plus padding character (=)
3223
- const b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
3224
- const b64re = /^(?:[A-Za-z\d+/]{4})*?(?:[A-Za-z\d+/]{2}(?:==)?|[A-Za-z\d+/]{3}=?)?$/;
3225
- function btoaPolyfill(input) {
3226
- let bitmap, a, b, c;
3227
- let result = '', i = 0;
3228
- const rest = input.length % 3; // To determine the final padding
3229
- for (; i < input.length;) {
3230
- if ((a = input.charCodeAt(i++)) > 255 ||
3231
- (b = input.charCodeAt(i++)) > 255 ||
3232
- (c = input.charCodeAt(i++)) > 255) {
3233
- throw new TypeError('Failed base64ToAscii encoding: The string to be encoded contains characters outside of the Latin1 range. ' +
3234
- input);
3235
- }
3236
- bitmap = (a << 16) | (b << 8) | c;
3237
- result +=
3238
- b64.charAt((bitmap >> 18) & 63) +
3239
- b64.charAt((bitmap >> 12) & 63) +
3240
- b64.charAt((bitmap >> 6) & 63) +
3241
- b64.charAt(bitmap & 63);
3242
- }
3243
- // If there's need of padding, replace the last 'A's with equal signs
3244
- return rest ? result.slice(0, rest - 3) + '==='.substring(rest) : result;
3245
- }
3246
- function atobPolyfill(data) {
3247
- // atob can work with strings with whitespaces, even inside the encoded part,
3248
- // but only \t, \n, \f, \r and ' ', which can be stripped.
3249
- let string = String(data).replace(/[\t\n\f\r ]+/g, '');
3250
- if (!b64re.test(string))
3251
- throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.");
3252
- // Adding the padding if missing, for semplicity
3253
- string += '=='.slice(2 - (string.length & 3));
3254
- var bitmap, result = '', r1, r2, i = 0;
3255
- for (; i < string.length;) {
3256
- bitmap =
3257
- (b64.indexOf(string.charAt(i++)) << 18) |
3258
- (b64.indexOf(string.charAt(i++)) << 12) |
3259
- ((r1 = b64.indexOf(string.charAt(i++))) << 6) |
3260
- (r2 = b64.indexOf(string.charAt(i++)));
3261
- result +=
3262
- r1 === 64
3263
- ? String.fromCharCode((bitmap >> 16) & 255)
3264
- : r2 === 64
3265
- ? String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255)
3266
- : String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255, bitmap & 255);
3267
- }
3268
- return result;
3269
- }
3270
- const base64encode = typeof btoa === 'function' ? btoa : btoaPolyfill;
3271
- const base64decode = typeof atob === 'function' ? atob : atobPolyfill;
3272
-
3273
- function cursorResolver(source) {
3274
- return encodeV1Cursor(source.index);
3275
- }
3276
- function pageInfoResolver(source) {
3277
- if (source.length === 0) {
3278
- return {
3279
- startCursor: null,
3280
- endCursor: null,
3281
- };
3282
- }
3283
- let startIndex = source[0].index;
3284
- let endIndex = source[source.length - 1].index;
3285
- return {
3286
- startCursor: encodeV1Cursor(startIndex),
3287
- endCursor: encodeV1Cursor(endIndex),
3288
- };
3289
- }
3290
- function pageResultCountResolver(source) {
3291
- return source.length;
3292
- }
3293
- function encodeV1Cursor(index) {
3294
- return base64encode(`v1:${index}`);
3295
- }
3296
- const cursorRegex = /^v1:(?<index>\d+)$/;
3297
- function decodeV1Cursor(base64cursor) {
3298
- const cursor = base64decode(base64cursor);
3299
- if (!cursor) {
3300
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
3301
- throw new Error('Unable to parse cursor');
3302
- }
3303
- const found = cursor.match(cursorRegex);
3304
- if (!found || !found.groups) {
3305
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
3306
- throw new Error('Unable to parse cursor');
3307
- }
3308
- return Number(found.groups.index);
3309
- }
3310
-
3311
- /*
3312
- resolves connections...
3313
- */
3314
- async function connectionResolver(obj, args, context, info) {
3315
- let { recordRepresentation: parentRecord, ingestionTimestamp = 0 } = obj;
3316
- if (!parentRecord && excludeStaleRecordsGate.isOpen({ fallback: false })) {
3317
- // at our record query we fetch each ingestion time stamp and pass it down to each lower resolver to query against
3318
- ingestionTimestamp = await fetchIngestionTimeStampFromDatabase(info.fieldName, info, args, context.query);
3319
- }
3320
- const { query, objectInfos, draftFunctions } = context;
3321
- let joins = [];
3322
- let alias = info.fieldName;
3323
- let childRelationshipFieldName = undefined;
3324
- if (parentRecord) {
3325
- context.seenRecordIds.add(parentRecord.id);
3326
- const parentApiName = parentRecord.apiName;
3327
- const parentObjectInfo = objectInfos[parentApiName];
3328
- const childRelationship = parentObjectInfo &&
3329
- parentObjectInfo.childRelationships.find((rel) => rel.relationshipName === info.fieldName);
3330
- // or emit/throw if we want to report it
3331
- if (!childRelationship)
3332
- return [];
3333
- alias = childRelationship.childObjectApiName;
3334
- childRelationshipFieldName = childRelationship.fieldName;
3335
- }
3336
- // Alias starts as entity's ApiName
3337
- const predicates = [
3338
- ...filterToPredicates(args.where, alias, alias, context.objectInfos, joins, draftFunctions),
3339
- ...scopeToPredicates(args.scope, context.settings),
3340
- ...childRelationshipToPredicates(childRelationshipFieldName, parentRecord ? parentRecord.id : undefined),
3341
- ];
3342
- const scopeJoins = scopeToJoins(args.scope, context.settings);
3343
- joins.push(...scopeJoins);
3344
- let offset = 0;
3345
- if (args.after) {
3346
- offset = decodeV1Cursor(args.after) + 1;
3347
- }
3348
- // Alias starts as entity's ApiName
3349
- const queryConfig = {
3350
- alias,
3351
- joins,
3352
- predicates,
3353
- orderBy: orderByToPredicate(args.orderBy, alias, alias, context.objectInfos),
3354
- limit: args.first,
3355
- offset: offset,
3356
- ingestionTimestamp,
3357
- };
3358
- const { sql, bindings } = buildQuery(queryConfig);
3359
- const results = await query(sql, bindings);
3360
- //map each sql result with the ingestion timestamp to pass it down a level
3361
- return results.rows
3362
- .map((row) => parse(row[0]))
3363
- .map((recordRepresentation, index) => {
3364
- context.seenRecordIds.add(recordRepresentation.id);
3365
- return {
3366
- recordRepresentation,
3367
- ingestionTimestamp,
3368
- index: index + offset,
3369
- };
3370
- });
3371
- }
3372
- /**
3373
- * Converts a childRelationship into a predicate
3374
- * @param childRelationshipFieldName Reference ID field name to its parent record. A defined `childRelationshipFieldName` string indicates that a child relationship exists
3375
- * and a relationship predicate needs to be put into place. For example, `ServiceAppointment` has a child relationship `ServiceResources`, whose entity name is `AssignedResource`.
3376
- * Once the parent `ServiceAppointment` record comes back, its child connection starts to resolve. Child `AssignedResource` record needs to reference to parent Id using field `ServiceAppointmentId`.
3377
- * @param parentId prarent record Id
3378
- * @returns predicate array consists at most 1 predicate
3379
- */
3380
- function childRelationshipToPredicates(childRelationshipFieldName, parentId) {
3381
- const predicates = [];
3382
- if (childRelationshipFieldName !== undefined && parentId !== undefined) {
3383
- predicates.push({
3384
- type: PredicateType.single,
3385
- leftPath: `$.fields.${childRelationshipFieldName}.value`,
3386
- operator: '=',
3387
- value: parentId,
3388
- });
3389
- }
3390
- return predicates;
3391
- }
3392
- /**
3393
- * fetches a query level ingestion time stamp from the L2 cache
3394
- * if no query has been seen then the timestamp is 0
3395
- * @param apiName
3396
- * @param info
3397
- * @param args
3398
- * @param query
3399
- * @returns
3400
- */
3401
- async function fetchIngestionTimeStampFromDatabase(apiName, info, args, query) {
3402
- const { operation, variableValues } = info;
3403
- // if we cannot find the query key in the database then default to 0 as we assume we have not seen the query
3404
- // and all the data is not stale
3405
- let ingestionTimestamp = 0;
3406
- if (info.fieldNodes.length > 0 && info.fieldNodes[0].arguments !== undefined) {
3407
- const key = buildKeyStringForRecordQuery(operation,
3408
- // join varables passed from query to the argument variables given from the AST
3409
- { ...variableValues, ...args }, info.fieldNodes[0].arguments, apiName);
3410
- return readIngestionTimestampForKey(key, query);
3411
- }
3412
- return ingestionTimestamp;
3413
- }
3414
- /**
3415
- * Builds the top level record query key based on AST data
3416
- * @param operation
3417
- * @param variables
3418
- * @param argumentNodes
3419
- * @param currentFieldName
3420
- * @returns
3421
- */
3422
- function buildKeyStringForRecordQuery(operation, variables, argumentNodes, currentFieldName) {
3423
- const queryKey = buildQueryTypeStringKey({
3424
- luvio: {},
3425
- keyPrefix: 'UiApi',
3426
- schemaName: 'uiapi',
3427
- queryTypeName: 'Query',
3428
- operationNode: operation,
3429
- variables,
3430
- fragmentMap: {},
3431
- });
3432
- const filteredArgumentNodes = assign$1([], argumentNodes).filter((node) => node.name.value !== 'first' && node.name.value !== 'after');
3433
- const argumentString = filteredArgumentNodes.length > 0
3434
- ? '__' + serializeFieldArguments(filteredArgumentNodes, variables)
3435
- : '';
3436
- return `${queryKey}__uiapi__query__${currentFieldName}${argumentString}`;
3437
- }
3438
-
3439
- function passThroughResolver(source) {
3440
- return source;
3441
- }
3442
-
3443
- /**
3444
- *
3445
- * @param schema GraphQL Schema generated from ObjectInfos
3446
- * @param polyFields The record types which support polymorphic fields. For example, 'Owner' has the 'Record' interface which is a polymorphic fields. The 'User' and 'Group' are the concrete types which support 'Owner' interface.
3447
- * @returns Updated schema
3448
- */
3449
- function addResolversToSchema(schema, polyFields) {
3450
- // Polymorphic field type is 'recordInterface'
3451
- let recordInterface = undefined;
3452
- let baseRecord = undefined;
3453
- // Concrete types for Polymorphic field
3454
- const polyTypes = [];
3455
- for (const type of values$1(schema.getTypeMap())) {
3456
- if (type.name === 'Record') {
3457
- recordInterface = type;
3458
- }
3459
- else if (type.name === 'RecordRepresentation') {
3460
- baseRecord = type;
3461
- }
3462
- if (!isObjectType(type))
3463
- continue;
3464
- // Finds entity record type which supports polymorphism.
3465
- if (polyFields.find((fieldTypeName) => fieldTypeName === type.name) !== undefined) {
3466
- polyTypes.push(type);
3467
- }
3468
- const fields = values$1(type.getFields());
3469
- // initialize the fields of current type with default behavior
3470
- for (const field of fields) {
3471
- field.resolve = defaultFieldResolver;
3472
- }
3473
- if (type.name === 'Query') {
3474
- for (const field of fields) {
3475
- field.resolve = passThroughResolver;
3476
- }
3477
- }
3478
- if (type.name === 'UIAPI') {
3479
- for (const field of fields) {
3480
- if (field.name === 'query') {
3481
- field.resolve = passThroughResolver;
3482
- }
3483
- else {
3484
- const fieldName = field.name;
3485
- field.resolve = (_obj, _args, { snapshot }) => {
3486
- if (!snapshot.data)
3487
- return null;
3488
- if (!snapshot.data.data)
3489
- return null;
3490
- return snapshot.data.data.uiapi[fieldName];
3491
- };
3492
- }
3493
- }
3494
- }
3495
- if (type.name === 'RecordQuery') {
3496
- // {
3497
- // uiapi {
3498
- // query { <-----------|
3499
- // Account |
3500
- // User |
3501
- // Opportunity |
3502
- // } <-----------------|
3503
- // }
3504
- // }
3505
- // Fields of the `RecordQuery` type are the record queries for the entity types
3506
- // supported for the org
3507
- for (const recordQuery of fields) {
3508
- recordQuery.resolve = connectionResolver;
3509
- }
3510
- }
3511
- if (type.name.endsWith('Connection')) {
3512
- // {
3513
- // uiapi {
3514
- // query {
3515
- // ServiceAppointment @category(name: "recordQuery") { <---|
3516
- // totalCount |
3517
- // edges { |
3518
- // node { |
3519
- // Id |
3520
- // } |
3521
- // } |
3522
- // } <----------------------------------------------------|
3523
- // }
3524
- // }
3525
- // }
3526
- for (const field of fields) {
3527
- switch (field.name) {
3528
- case 'edges':
3529
- field.resolve = passThroughResolver;
3530
- break;
3531
- case 'pageInfo':
3532
- field.resolve = pageInfoResolver;
3533
- break;
3534
- case 'pageResultCount':
3535
- field.resolve = pageResultCountResolver;
3536
- break;
3537
- default:
3538
- field.resolve = defaultFieldResolver;
3539
- }
3540
- }
3541
- }
3542
- if (type.name.endsWith('Edge')) {
3543
- // {
3544
- // uiapi {
3545
- // query {
3546
- // ServiceAppointment @category(name: "recordQuery") {
3547
- // edges { <--|
3548
- // node { |
3549
- // Id |
3550
- // } |
3551
- // } <--|
3552
- // }
3553
- // }
3554
- // }
3555
- // }
3556
- for (const field of fields) {
3557
- if (field.name === 'node') {
3558
- field.resolve = passThroughResolver;
3559
- }
3560
- else if (field.name === 'cursor') {
3561
- field.resolve = cursorResolver;
3562
- }
3563
- }
3564
- }
3565
- if (isRecordType(type)) {
3566
- // All the generic named GraphQL Objects that map to Record Queries ("Account", "ServiceAppointment")
3567
- // {
3568
- // uiapi {
3569
- // query {
3570
- // ServiceAppointment @category(name: "recordQuery") {
3571
- // edges {
3572
- // node { <--|
3573
- // Id |
3574
- // } <--|
3575
- // }
3576
- // }
3577
- // }
3578
- // }
3579
- // }
3580
- for (const field of fields) {
3581
- switch (field.name) {
3582
- case 'Id':
3583
- field.resolve = ({ recordRepresentation: record }) => record.id;
3584
- break;
3585
- case 'ApiName':
3586
- field.resolve = ({ recordRepresentation: record }) => record.apiName;
3587
- break;
3588
- case 'WeakEtag':
3589
- field.resolve = ({ recordRepresentation: record }) => record.weakEtag;
3590
- break;
3591
- case '_drafts':
3592
- field.resolve = ({ recordRepresentation: record, }) => {
3593
- return record.drafts ? record.drafts : null;
3594
- };
3595
- break;
3596
- case 'LastModifiedById':
3597
- field.resolve = ({ recordRepresentation: record }) => {
3598
- return record.lastModifiedById
3599
- ? { value: record.lastModifiedById }
3600
- : null;
3601
- };
3602
- break;
3603
- case 'LastModifiedDate':
3604
- field.resolve = ({ recordRepresentation: record }) => {
3605
- // In UIAPI record reps, LastModifiedDate might be present as a field,
3606
- // which will include both the value and displayValue
3607
- if (record.fields['LastModifiedDate']) {
3608
- return record.fields['LastModifiedDate'];
3609
- }
3610
- // If the field is not present, just return the value of the root property
3611
- return record.lastModifiedDate
3612
- ? { value: record.lastModifiedDate }
3613
- : null;
3614
- };
3615
- break;
3616
- case 'SystemModstamp':
3617
- field.resolve = ({ recordRepresentation: record }) => {
3618
- return record.systemModstamp ? { value: record.systemModstamp } : null;
3619
- };
3620
- break;
3621
- case 'RecordTypeId':
3622
- field.resolve = ({ recordRepresentation: record }) => {
3623
- return record.recordTypeId ? { value: record.recordTypeId } : null;
3624
- };
3625
- break;
3626
- case 'DisplayValue':
3627
- field.resolve = recordDisplayValueResolver;
3628
- break;
3629
- default: {
3630
- const recordFieldType = schema.getType(field.type.name);
3631
- // Both concrete record type and 'record' interface type(polymorphic field) uses 'RecordLoader' to resolve.
3632
- if ((isObjectType(recordFieldType) &&
3633
- recordFieldType
3634
- .getInterfaces()
3635
- .find((iface) => iface.name === 'Record')) ||
3636
- (recordFieldType && recordFieldType.name === 'Record')) {
3637
- field.resolve = async function relationResolver(obj, _args, { Record, seenRecordIds }) {
3638
- const fetchRecordOrNull = async (key) => {
3639
- const recordRepresentation = await Record.load(key);
3640
- return recordRepresentation !== null
3641
- ? {
3642
- recordRepresentation,
3643
- ingestionTimestamp,
3644
- }
3645
- : null;
3646
- };
3647
- const { recordRepresentation: record, ingestionTimestamp } = obj;
3648
- let id = undefined;
3649
- if (field.name === 'RecordType') {
3650
- // RecordTypeId has special handling during ingest and is
3651
- // not in record.fields, so check for it at the UIAPI root property location
3652
- id = record.recordTypeId;
3653
- }
3654
- else if (field.name.endsWith('__r')) {
3655
- // Custom relationships end in `__r` and the corresponding ID field should be `__c`
3656
- let fieldName = field.name.replace('__r', '__c');
3657
- id = record.fields[fieldName] && record.fields[fieldName].value;
3658
- }
3659
- else {
3660
- // Standard relationships are just FieldNameId
3661
- let fieldName = field.name + 'Id';
3662
- id = record.fields[fieldName] && record.fields[fieldName].value;
3663
- }
3664
- if (!id || typeof id !== 'string') {
3665
- // possibly field injection did not inject the necessary Id field
3666
- // for the relationship, or we found a non-string value.
3667
- return null;
3668
- }
3669
- seenRecordIds.add(id);
3670
- return fetchRecordOrNull(id);
3671
- };
3672
- }
3673
- else if (isObjectType(recordFieldType) &&
3674
- field.type.name.endsWith('Connection')) {
3675
- // spanning field to a connection
3676
- field.resolve = connectionResolver;
3677
- }
3678
- else {
3679
- field.resolve = function recordFieldResolver({ recordRepresentation: record, }) {
3680
- return record.fields[field.name] || null;
3681
- };
3682
- }
3683
- }
3684
- }
3685
- }
3686
- }
3687
- }
3688
- if (recordInterface !== undefined && baseRecord !== undefined) {
3689
- // Applys 'resolveType' of GraphQLInterfaceType to 'Record' interface. Since all the heterogenous types are named as 'apiName', the type with same name as the loaded record 'apiName' property is the type wanted.
3690
- // GraphQL executor would match InLineFragment' condition with type and keeps the deeper level field resolving going.
3691
- recordInterface.resolveType = function ({ recordRepresentation: value, }) {
3692
- const targetType = polyTypes.find((type) => type.name === value.apiName);
3693
- return targetType === undefined ? baseRecord : targetType;
3694
- };
3695
- }
3696
- return schema;
3697
- }
3698
- /**
3699
- * Resolver to fetch the DisplayValue of a graphql record.
3700
- * This is taking the main Name field for the record
3701
- * type and using it for the DisplayValue.
3702
- *
3703
- * This allows us to be more performant without needing to call
3704
- * another SQL lookup for the cached graphql object of the RAML record.
3705
- */
3706
- function recordDisplayValueResolver({ recordRepresentation },
3707
- // not used, but gets sent in the resolver
3708
- _, { objectInfos }) {
3709
- const { apiName } = recordRepresentation;
3710
- const objectInfo = objectInfos[apiName];
3711
- if (objectInfo !== undefined) {
3712
- const { nameFields, fields } = objectInfo;
3713
- let nameField;
3714
- // use the field Name if it exists or the first field name
3715
- if (nameFields.length !== 0) {
3716
- nameField = nameFields.find((x) => x === 'Name');
3717
- if (nameField === undefined) {
3718
- nameField = nameFields[0];
3719
- }
3720
- }
3721
- if (nameField !== undefined) {
3722
- nameField = fields[nameField].apiName;
3723
- const nameFieldRep = recordRepresentation.fields[nameField];
3724
- if (nameFieldRep !== undefined) {
3725
- return nameFieldRep.value;
3726
- }
3727
- }
3728
- }
3729
- return null;
3730
- }
3731
- function isRecordType(type) {
3732
- const interfaces = type.getInterfaces();
3733
- return Boolean(interfaces.find((iface) => iface.name === 'Record'));
3734
- }
3735
-
3736
- var uiapiSchemaString = "scalar String\nscalar DateTime\nscalar Currency\nscalar ID\nscalar Boolean\nscalar Longitude\nscalar Float\nscalar MultiPicklist\nscalar Base64\nscalar Url\nscalar PhoneNumber\nscalar Email\nscalar TextArea\nscalar Latitude\nscalar Picklist\nscalar RichTextArea\nscalar EncryptedString\nscalar Double\nscalar Long\nscalar JSON\nscalar Time\nscalar Int\nscalar Percent\nscalar LongTextArea\nscalar IdOrRef\nscalar Date\ntype PercentAggregate implements FieldValue {\n value: Percent\n displayValue: String\n avg: DoubleValue\n count: LongValue\n countDistinct: LongValue\n format: String\n max: PercentValue\n min: PercentValue\n sum: PercentValue\n}\n\ntype StringAggregate implements FieldValue {\n value: String\n displayValue: String\n count: LongValue\n countDistinct: LongValue\n grouping: IntValue\n label: String\n max: StringValue\n min: StringValue\n}\n\ntype Query {\n uiapi: UIAPI!\n setup: Setup__Setup!\n}\n\ninput EmailOperators {\n eq: Email\n ne: Email\n like: Email\n lt: Email\n gt: Email\n lte: Email\n gte: Email\n in: [Email]\n nin: [Email]\n}\n\ninput PolymorphicParentRelationshipRecordOrderBy @generic {\n RecordOrderBy: RecordOrderBy @fieldCategory\n}\n\ninput DoubleOperators {\n eq: Double\n ne: Double\n lt: Double\n gt: Double\n lte: Double\n gte: Double\n in: [Double]\n nin: [Double]\n}\n\ntype DateOnlyAggregation {\n value: Date\n format: String\n}\n\ntype RecordCreatePayload @generic {\n Record: RecordRepresentation\n}\n\ntype DateAggregate implements FieldValue {\n value: Date\n displayValue: String\n calendarMonth: DateFunctionAggregation\n calendarQuarter: DateFunctionAggregation\n calendarYear: DateFunctionAggregation\n count: LongValue\n countDistinct: LongValue\n dayInMonth: DateFunctionAggregation\n dayInWeek: DateFunctionAggregation\n dayInYear: DateFunctionAggregation\n fiscalMonth: DateFunctionAggregation\n fiscalQuarter: DateFunctionAggregation\n fiscalYear: DateFunctionAggregation\n format: String\n grouping: IntValue\n max: DateValue\n min: DateValue\n weekInMonth: DateFunctionAggregation\n weekInYear: DateFunctionAggregation\n}\n\ninput PolymorphicParentRelationshipGroupBy @generic {\n RecordGroupBy: RecordGroupBy @fieldCategory\n}\n\nenum GroupByFunction {\n DAY_IN_WEEK\n DAY_IN_MONTH\n DAY_IN_YEAR\n WEEK_IN_MONTH\n WEEK_IN_YEAR\n CALENDAR_MONTH\n CALENDAR_QUARTER\n CALENDAR_YEAR\n FISCAL_MONTH\n FISCAL_QUARTER\n FISCAL_YEAR\n DAY_ONLY\n HOUR_IN_DAY\n}\n\ntype RecordTypeInfo {\n available: Boolean!\n defaultRecordTypeMapping: Boolean!\n master: Boolean!\n name: String\n recordTypeId: ID\n}\n\ninput UIAPIMutationsInput {\n allOrNone: Boolean = true\n}\n\ntype BooleanValue implements FieldValue {\n value: Boolean\n displayValue: String\n}\n\ntype ReferenceToInfo {\n ApiName: String!\n nameFields: [String]!\n objectInfo: ObjectInfo\n}\n\ninterface FieldValue {\n displayValue: String\n}\n\ntype LongitudeValue implements FieldValue {\n value: Longitude\n displayValue: String\n}\n\ntype StringValue implements FieldValue {\n value: String\n displayValue: String\n label: String\n}\n\ntype IntValue implements FieldValue {\n value: Int\n displayValue: String\n format: String\n}\n\ntype UrlValue implements FieldValue {\n value: Url\n displayValue: String\n}\n\ninput IdOperators {\n eq: ID\n ne: ID\n lt: ID\n gt: ID\n lte: ID\n gte: ID\n in: [ID]\n nin: [ID]\n inq: JoinInput\n ninq: JoinInput\n}\n\ninput Setup__SetupOrderBy @generic {\n orderableField: OrderByClause @fieldCategory\n orderableGeolocationField: OrderByGeolocationClause @fieldCategory\n orderableParentRelationship: Setup__SetupOrderBy @fieldCategory\n orderablePolymorphicParentRelationship: Setup__SetupPolymorphicParentRelationshipRecordOrderBy @fieldCategory\n}\n\ntype LongAggregate implements FieldValue {\n value: Long\n displayValue: String\n avg: DoubleValue\n count: LongValue\n countDistinct: LongValue\n format: String\n grouping: IntValue\n max: LongValue\n min: LongValue\n sum: LongValue\n}\n\ntype PhoneNumberAggregate implements FieldValue {\n value: PhoneNumber\n displayValue: String\n count: LongValue\n countDistinct: LongValue\n grouping: IntValue\n max: PhoneNumberValue\n min: PhoneNumberValue\n}\n\ninput TimeOperators {\n eq: Time\n ne: Time\n lt: Time\n gt: Time\n lte: Time\n gte: Time\n in: [Time]\n nin: [Time]\n}\n\ntype PicklistValue implements FieldValue {\n value: Picklist\n displayValue: String\n label: String\n}\n\ntype CurrencyAggregate implements FieldValue {\n value: Currency\n displayValue: String\n avg: DoubleValue\n count: LongValue\n countDistinct: LongValue\n format: String\n max: CurrencyValue\n min: CurrencyValue\n sum: CurrencyValue\n}\n\ntype RelatedListInfo {\n childApiName: String!\n relatedListName: String!\n label: String!\n displayColumns: [ListColumn!]!\n orderedByInfo: [ListOrder!]!\n parentApiName: String!\n fieldApiName: String!\n}\n\ninput StringOperators {\n eq: String\n ne: String\n like: String\n lt: String\n gt: String\n lte: String\n gte: String\n in: [String]\n nin: [String]\n}\n\ntype UIAPI {\n query: RecordQuery!\n aggregate: RecordQueryAggregate!\n objectInfos(apiNames: [String], locale: String): [ObjectInfo]\n relatedListByName(parentApiName: String!, relatedListName: String!): RelatedListInfo\n}\n\ninput MultiPicklistOperators {\n eq: MultiPicklist\n ne: MultiPicklist\n includes: [MultiPicklist]\n excludes: [MultiPicklist]\n}\n\ntype DateTimeAggregate implements FieldValue {\n value: DateTime\n displayValue: String\n calendarMonth: DateFunctionAggregation\n calendarQuarter: DateFunctionAggregation\n calendarYear: DateFunctionAggregation\n count: LongValue\n countDistinct: LongValue\n dayInMonth: DateFunctionAggregation\n dayInWeek: DateFunctionAggregation\n dayInYear: DateFunctionAggregation\n dayOnly: DateOnlyAggregation\n fiscalMonth: DateFunctionAggregation\n fiscalQuarter: DateFunctionAggregation\n fiscalYear: DateFunctionAggregation\n format: String\n hourInDay: DateFunctionAggregation\n max: DateTimeValue\n min: DateTimeValue\n weekInMonth: DateFunctionAggregation\n weekInYear: DateFunctionAggregation\n}\n\ninput BooleanOperators {\n eq: Boolean\n ne: Boolean\n}\n\ntype EmailAggregate implements FieldValue {\n value: Email\n displayValue: String\n count: LongValue\n countDistinct: LongValue\n grouping: IntValue\n max: EmailValue\n min: EmailValue\n}\n\n#enum OrderByType {\n#}\n\ninput GroupByDateFunction {\n function: GroupByFunction\n}\n\ntype RichTextAreaValue implements FieldValue {\n value: RichTextArea\n displayValue: String\n}\n\ntype MultiPicklistValue implements FieldValue {\n value: MultiPicklist\n displayValue: String\n label: String\n}\n\ntype Setup__SetupEdge @generic {\n node: Setup__EntityRepresentation\n cursor: String!\n}\n\ninput DatePrimitiveOperators {\n eq: Date\n ne: Date\n lt: Date\n gt: Date\n lte: Date\n gte: Date\n in: [Date]\n nin: [Date]\n}\n\ntype TimeAggregate implements FieldValue {\n value: Time\n displayValue: String\n format: String\n hourInDay: DateFunctionAggregation\n}\n\ntype __Type {\n kind: __TypeKind!\n name: String\n description: String\n fields(includeDeprecated: Boolean = false): [__Field!]\n interfaces: [__Type!]\n possibleTypes: [__Type!]\n enumValues(includeDeprecated: Boolean = false): [__EnumValue!]\n inputFields: [__InputValue!]\n ofType: __Type\n}\n\ntype ListColumn {\n fieldApiName: String!\n label: String!\n lookupId: String\n sortable: Boolean\n}\n\ntype Setup__SetupQuery {\n recordQuery(first: Int, after: String, where: Setup__SetupFilter, orderBy: Setup__SetupOrderBy, scope: String, upperBound: Int): Setup__SetupConnection @fieldCategory\n}\n\ntype Setup__EntityRepresentation @generic {\n Id: ID!\n ApiName: String!\n IntValue: IntValue @fieldCategory\n StringValue: StringValue @fieldCategory\n BooleanValue: BooleanValue @fieldCategory\n IDValue: IDValue @fieldCategory\n DateTimeValue: DateTimeValue @fieldCategory\n TimeValue: TimeValue @fieldCategory\n DateValue: DateValue @fieldCategory\n TextAreaValue: TextAreaValue @fieldCategory\n LongTextAreaValue: LongTextAreaValue @fieldCategory\n RichTextAreaValue: RichTextAreaValue @fieldCategory\n PhoneNumberValue: PhoneNumberValue @fieldCategory\n EmailValue: EmailValue @fieldCategory\n UrlValue: UrlValue @fieldCategory\n EncryptedStringValue: EncryptedStringValue @fieldCategory\n CurrencyValue: CurrencyValue @fieldCategory\n LongitudeValue: LongitudeValue @fieldCategory\n LatitudeValue: LatitudeValue @fieldCategory\n PicklistValue: PicklistValue @fieldCategory\n MultiPicklistValue: MultiPicklistValue @fieldCategory\n LongValue: LongValue @fieldCategory\n DoubleValue: DoubleValue @fieldCategory\n PercentValue: PercentValue @fieldCategory\n Base64Value: Base64Value @fieldCategory\n JSONValue: JSONValue @fieldCategory\n parentRelationship: Setup__EntityRepresentation @fieldCategory\n polymorphicParentRelationship: Setup__SetupPolymorphicParentRelationship @fieldCategory\n childRelationship(first: Int, after: String, where: Setup__SetupFilter, orderBy: Setup__SetupOrderBy, upperBound: Int): Setup__SetupConnection @fieldCategory\n CompoundField: CompoundField @fieldCategory\n}\n\ntype LatitudeAggregate implements FieldValue {\n value: Latitude\n displayValue: String\n avg: DoubleValue\n count: LongValue\n countDistinct: LongValue\n max: LatitudeValue\n min: LatitudeValue\n sum: DoubleValue\n}\n\ninput CurrencyOperators {\n eq: Currency\n ne: Currency\n lt: Currency\n gt: Currency\n lte: Currency\n gte: Currency\n in: [Currency]\n nin: [Currency]\n}\n\ninput DistanceInput {\n latitude: Latitude!\n longitude: Longitude!\n}\n\nunion PolymorphicParentRelationship @generic = RecordRepresentation\n\nenum AggregateOrderByNumberFunction {\n AVG\n COUNT\n COUNT_DISTINCT\n MAX\n MIN\n SUM\n}\n\ntype LongTextAreaValue implements FieldValue {\n value: LongTextArea\n displayValue: String\n}\n\ntype LatitudeValue implements FieldValue {\n value: Latitude\n displayValue: String\n}\n\ninput OrderByClause {\n order: ResultOrder\n nulls: NullOrder\n}\n\ninput AggregateOrderBy @generic {\n orderableNumberField: AggregateOrderByNumberClause @fieldCategory\n orderableStringField: AggregateOrderByStringClause @fieldCategory\n orderableField: NoFunctionAggregateOrderByClause @fieldCategory\n orderableGeolocationField: OrderByGeolocationClause @fieldCategory\n orderableParentRelationship: AggregateOrderBy @fieldCategory\n orderablePolymorphicParentRelationship: PolymorphicParentRelationshipOrderBy @fieldCategory\n type: String = ORDER_BY\n}\n\ninput GroupByClause {\n group: Boolean\n}\n\ntype RecordAggregateConnection @generic {\n edges: [RecordAggregateEdge]\n pageInfo: PageInfo!\n totalCount: Int!\n}\n\ntype LongitudeAggregate implements FieldValue {\n value: Longitude\n displayValue: String\n avg: DoubleValue\n count: LongValue\n countDistinct: LongValue\n max: LongitudeValue\n min: LongitudeValue\n sum: DoubleValue\n}\n\ntype RecordEdge @generic {\n node: RecordRepresentation\n cursor: String!\n}\n\nunion Setup__SetupPolymorphicParentRelationship @generic = Setup__EntityRepresentation\n\ntype DateValue implements FieldValue {\n value: Date\n displayValue: String\n format: String\n}\n\ninput URLOperators {\n eq: Url\n ne: Url\n like: Url\n lt: Url\n gt: Url\n lte: Url\n gte: Url\n in: [Url]\n nin: [Url]\n}\n\ninput LongOperators {\n eq: Long\n ne: Long\n lt: Long\n gt: Long\n lte: Long\n gte: Long\n in: [Long]\n nin: [Long]\n}\n\nenum DataType {\n STRING\n TEXTAREA\n PHONE\n EMAIL\n URL\n ENCRYPTEDSTRING\n BOOLEAN\n CURRENCY\n INT\n LONG\n DOUBLE\n PERCENT\n DATETIME\n TIME\n DATE\n REFERENCE\n PICKLIST\n MULTIPICKLIST\n ADDRESS\n LOCATION\n BASE64\n COMPLEXVALUE\n COMBOBOX\n JSON\n JUNCTIONIDLIST\n ANYTYPE\n}\n\nenum NullOrder {\n FIRST\n LAST\n}\n\ntype PhoneNumberValue implements FieldValue {\n value: PhoneNumber\n displayValue: String\n}\n\n# Cannot have empty enum\n# enum RecordScope @generic {\n# }\n\ninput Setup__SetupFilter @generic {\n and: [Setup__SetupFilter]\n or: [Setup__SetupFilter]\n not: Setup__SetupFilter\n parentRelationshipRecordFilter: Setup__SetupFilter @fieldCategory\n polymorphicParentRelationshipRecordFilter: Setup__SetupPolymorphicParentRelationshipRecordFilter @fieldCategory\n IntegerOperator: IntegerOperators @fieldCategory\n LongOperator: LongOperators @fieldCategory\n StringOperator: StringOperators @fieldCategory\n DoubleOperator: DoubleOperators @fieldCategory\n PercentOperator: PercentOperators @fieldCategory\n LongitudeOperator: LongitudeOperators @fieldCategory\n LatitudeOperator: LatitudeOperators @fieldCategory\n EmailOperator: EmailOperators @fieldCategory\n TextAreaOperator: TextAreaOperators @fieldCategory\n LongTextAreaOperator: LongTextAreaOperators @fieldCategory\n URLOperator: URLOperators @fieldCategory\n PhoneNumberOperator: PhoneNumberOperators @fieldCategory\n BooleanOperator: BooleanOperators @fieldCategory\n Setup__IdOperator: Setup__IdOperators @fieldCategory\n CurrencyOperator: CurrencyOperators @fieldCategory\n TimeOperator: TimeOperators @fieldCategory\n DateOperator: DateOperators @fieldCategory\n DateTimeOperator: DateTimeOperators @fieldCategory\n PicklistOperator: PicklistOperators @fieldCategory\n MultiPicklistOperator: MultiPicklistOperators @fieldCategory\n GeolocationOperator: GeolocationOperators @fieldCategory\n}\n\ntype DoubleAggregate implements FieldValue {\n value: Double\n displayValue: String\n avg: DoubleValue\n count: LongValue\n countDistinct: LongValue\n format: String\n max: DoubleValue\n min: DoubleValue\n sum: DoubleValue\n}\n\ntype __Field {\n name: String!\n description: String\n args: [__InputValue!]!\n type: __Type!\n isDeprecated: Boolean!\n deprecationReason: String\n}\n\ninput DateOperators {\n eq: DateInput\n ne: DateInput\n lt: DateInput\n gt: DateInput\n lte: DateInput\n gte: DateInput\n in: [DateInput]\n nin: [DateInput]\n DAY_IN_WEEK: DateFunctionInput\n DAY_IN_MONTH: DateFunctionInput\n DAY_IN_YEAR: DateFunctionInput\n WEEK_IN_MONTH: DateFunctionInput\n WEEK_IN_YEAR: DateFunctionInput\n CALENDAR_MONTH: DateFunctionInput\n CALENDAR_QUARTER: DateFunctionInput\n CALENDAR_YEAR: DateFunctionInput\n FISCAL_MONTH: DateFunctionInput\n FISCAL_QUARTER: DateFunctionInput\n FISCAL_YEAR: DateFunctionInput\n}\n\ninput GeolocationInput {\n latitude: Latitude!\n longitude: Longitude!\n radius: Float!\n unit: Unit!\n}\n\ninput JoinInput {\n Record: RecordFilter @fieldCategory\n ApiName: String\n}\n\ninput TextAreaOperators {\n eq: TextArea\n ne: TextArea\n like: TextArea\n lt: TextArea\n gt: TextArea\n lte: TextArea\n gte: TextArea\n in: [TextArea]\n nin: [TextArea]\n}\n\ntype TextAreaValue implements FieldValue {\n value: TextArea\n displayValue: String\n}\n\ntype RecordUpdatePayload @generic {\n success: Boolean\n}\n\ninput PercentOperators {\n eq: Percent\n ne: Percent\n lt: Percent\n gt: Percent\n lte: Percent\n gte: Percent\n in: [Percent]\n nin: [Percent]\n}\n\ninput Setup__SetupPolymorphicParentRelationshipRecordOrderBy @generic {\n Setup__SetupOrderBy: Setup__SetupOrderBy @fieldCategory\n}\n\ntype DoubleValue implements FieldValue {\n value: Double\n displayValue: String\n format: String\n}\n\ntype IDAggregate implements FieldValue {\n value: ID\n displayValue: String\n count: LongValue\n countDistinct: LongValue\n grouping: IntValue\n max: IDValue\n min: IDValue\n}\n\ntype __InputValue {\n name: String!\n description: String\n type: __Type!\n defaultValue: String\n}\n\ntype RecordAggregateEdge @generic {\n node: RecordResult\n cursor: String!\n}\n\ntype __Directive {\n name: String\n description: String\n locations: [__DirectiveLocation!]\n args: [__InputValue!]!\n}\n\ninput RecordCreateInput @generic {\n record: RecordCreateRepresentation! @fieldCategory\n}\n\ntype ThemeInfo {\n color: String\n iconUrl: String\n}\n\ninput AggregateOrderByStringClause {\n function: AggregateOrderByStringFunction\n order: ResultsOrder\n nulls: NullsOrder\n}\n\ntype RecordDeletePayload {\n Id: ID\n}\n\ntype UrlAggregate implements FieldValue {\n value: Url\n displayValue: String\n count: LongValue\n countDistinct: LongValue\n grouping: IntValue\n max: UrlValue\n min: UrlValue\n}\n\nenum DateLiteral {\n LAST_YEAR\n LAST_WEEK\n THIS_QUARTER\n NEXT_FISCAL_YEAR\n LAST_QUARTER\n TOMORROW\n NEXT_FISCAL_QUARTER\n YESTERDAY\n NEXT_QUARTER\n THIS_FISCAL_QUARTER\n THIS_WEEK\n LAST_MONTH\n LAST_90_DAYS\n NEXT_90_DAYS\n THIS_FISCAL_YEAR\n NEXT_WEEK\n TODAY\n NEXT_YEAR\n NEXT_MONTH\n LAST_FISCAL_QUARTER\n THIS_MONTH\n LAST_FISCAL_YEAR\n THIS_YEAR\n}\n\ntype __EnumValue {\n name: String!\n description: String\n isDeprecated: Boolean!\n deprecationReason: String\n}\n\ntype RecordRepresentation implements Record @generic {\n Id: ID!\n ApiName: String!\n WeakEtag: Long!\n DisplayValue: String\n LastModifiedById: IDValue\n LastModifiedDate: DateTimeValue\n SystemModstamp: DateTimeValue\n RecordTypeId(fallback: Boolean): IDValue\n IntValue: IntValue @fieldCategory\n StringValue: StringValue @fieldCategory\n BooleanValue: BooleanValue @fieldCategory\n IDValue: IDValue @fieldCategory\n DateTimeValue: DateTimeValue @fieldCategory\n TimeValue: TimeValue @fieldCategory\n DateValue: DateValue @fieldCategory\n TextAreaValue: TextAreaValue @fieldCategory\n LongTextAreaValue: LongTextAreaValue @fieldCategory\n RichTextAreaValue: RichTextAreaValue @fieldCategory\n PhoneNumberValue: PhoneNumberValue @fieldCategory\n EmailValue: EmailValue @fieldCategory\n UrlValue: UrlValue @fieldCategory\n EncryptedStringValue: EncryptedStringValue @fieldCategory\n CurrencyValue: CurrencyValue @fieldCategory\n LongitudeValue: LongitudeValue @fieldCategory\n LatitudeValue: LatitudeValue @fieldCategory\n PicklistValue: PicklistValue @fieldCategory\n MultiPicklistValue: MultiPicklistValue @fieldCategory\n LongValue: LongValue @fieldCategory\n DoubleValue: DoubleValue @fieldCategory\n PercentValue: PercentValue @fieldCategory\n Base64Value: Base64Value @fieldCategory\n JSONValue: JSONValue @fieldCategory\n parentRelationship: RecordRepresentation @fieldCategory\n polymorphicParentRelationship: PolymorphicParentRelationship @fieldCategory\n childRelationship(first: Int, after: String, where: RecordFilter, orderBy: RecordOrderBy, upperBound: Int): RecordConnection @fieldCategory\n CompoundField: CompoundField @fieldCategory\n}\n\ntype IDValue implements FieldValue {\n value: ID\n displayValue: String\n}\n\nenum Unit {\n MI\n KM\n}\n\ninput PolymorphicParentRelationshipOrderBy @generic {\n AggregateOrderBy: AggregateOrderBy @fieldCategory\n}\n\ninput OrderByGeolocationClause {\n distance: DistanceInput\n order: ResultOrder\n nulls: NullOrder\n}\n\ninput Setup__IdOperators {\n eq: ID\n ne: ID\n lt: ID\n gt: ID\n lte: ID\n gte: ID\n in: [ID]\n nin: [ID]\n inq: Setup__JoinInput\n ninq: Setup__JoinInput\n}\n\nenum NullsOrder {\n FIRST\n LAST\n}\n\ntype TextAreaAggregate implements FieldValue {\n value: TextArea\n displayValue: String\n count: LongValue\n countDistinct: LongValue\n grouping: IntValue\n max: TextAreaValue\n min: TextAreaValue\n}\n\nenum GroupByType {\n GROUP_BY\n ROLLUP\n CUBE\n}\n\nenum ResultOrder {\n ASC\n DESC\n}\n\ninput RecordOrderBy @generic {\n orderableField: OrderByClause @fieldCategory\n orderableGeolocationField: OrderByGeolocationClause @fieldCategory\n orderableParentRelationship: RecordOrderBy @fieldCategory\n orderablePolymorphicParentRelationship: PolymorphicParentRelationshipRecordOrderBy @fieldCategory\n}\n\ninput Setup__JoinInput {\n Record: Setup__SetupFilter @fieldCategory\n ApiName: String\n}\n\ninput PicklistOperators {\n eq: Picklist\n ne: Picklist\n in: [Picklist]\n nin: [Picklist]\n like: Picklist\n lt: Picklist\n gt: Picklist\n lte: Picklist\n gte: Picklist\n}\n\nenum ResultsOrder {\n ASC\n DESC\n}\n\ninput RecordFilter @generic {\n and: [RecordFilter]\n or: [RecordFilter]\n not: RecordFilter\n parentRelationshipRecordFilter: RecordFilter @fieldCategory\n polymorphicParentRelationshipRecordFilter: PolymorphicParentRelationshipRecordFilter @fieldCategory\n IntegerOperator: IntegerOperators @fieldCategory\n LongOperator: LongOperators @fieldCategory\n StringOperator: StringOperators @fieldCategory\n DoubleOperator: DoubleOperators @fieldCategory\n PercentOperator: PercentOperators @fieldCategory\n LongitudeOperator: LongitudeOperators @fieldCategory\n LatitudeOperator: LatitudeOperators @fieldCategory\n EmailOperator: EmailOperators @fieldCategory\n TextAreaOperator: TextAreaOperators @fieldCategory\n LongTextAreaOperator: LongTextAreaOperators @fieldCategory\n URLOperator: URLOperators @fieldCategory\n PhoneNumberOperator: PhoneNumberOperators @fieldCategory\n BooleanOperator: BooleanOperators @fieldCategory\n IdOperator: IdOperators @fieldCategory\n CurrencyOperator: CurrencyOperators @fieldCategory\n TimeOperator: TimeOperators @fieldCategory\n DateOperator: DateOperators @fieldCategory\n DateTimeOperator: DateTimeOperators @fieldCategory\n PicklistOperator: PicklistOperators @fieldCategory\n MultiPicklistOperator: MultiPicklistOperators @fieldCategory\n GeolocationOperator: GeolocationOperators @fieldCategory\n}\n\ntype TimeValue implements FieldValue {\n value: Time\n displayValue: String\n format: String\n}\n\ninput GeolocationOperators {\n lt: GeolocationInput\n gt: GeolocationInput\n}\n\ntype PicklistAggregate implements FieldValue {\n value: Picklist\n displayValue: String\n count: LongValue\n countDistinct: LongValue\n grouping: IntValue\n label: String\n max: PicklistValue\n min: PicklistValue\n}\n\ninput LatitudeOperators {\n eq: Latitude\n ne: Latitude\n lt: Latitude\n gt: Latitude\n lte: Latitude\n gte: Latitude\n in: [Latitude]\n nin: [Latitude]\n}\n\ninput RecordUpdateRepresentation @generic {\n Int: Int @fieldCategory\n String: String @fieldCategory\n Boolean: Boolean @fieldCategory\n ID: IdOrRef @fieldCategory\n DateTime: DateTime @fieldCategory\n Time: Time @fieldCategory\n Date: Date @fieldCategory\n TextArea: TextArea @fieldCategory\n LongTextArea: LongTextArea @fieldCategory\n RichTextArea: RichTextArea @fieldCategory\n PhoneNumber: PhoneNumber @fieldCategory\n Email: Email @fieldCategory\n Url: Url @fieldCategory\n EncryptedString: EncryptedString @fieldCategory\n Currency: Currency @fieldCategory\n Longitude: Longitude @fieldCategory\n Latitude: Latitude @fieldCategory\n Picklist: Picklist @fieldCategory\n MultiPicklist: MultiPicklist @fieldCategory\n Long: Long @fieldCategory\n Double: Double @fieldCategory\n Percent: Percent @fieldCategory\n Base64: Base64 @fieldCategory\n JSON: JSON @fieldCategory\n}\n\ntype DateTimeValue implements FieldValue {\n value: DateTime\n displayValue: String\n format: String\n}\n\ninput RecordDeleteInput {\n Id: IdOrRef!\n}\n\nenum __DirectiveLocation {\n QUERY\n MUTATION\n FIELD\n FRAGMENT_DEFINITION\n FRAGMENT_SPREAD\n INLINE_FRAGMENT\n SCHEMA\n SCALAR\n OBJECT\n FIELD_DEFINITION\n ARGUMENT_DEFINITION\n INTERFACE\n UNION\n ENUM\n ENUM_VALUE\n INPUT_OBJECT\n INPUT_FIELD_DEFINITION\n}\n\ntype IntAggregate implements FieldValue {\n value: Int\n displayValue: String\n avg: DoubleValue\n count: LongValue\n countDistinct: LongValue\n format: String\n grouping: IntValue\n max: IntValue\n min: IntValue\n sum: LongValue\n}\n\ntype ListOrder {\n fieldApiName: String!\n sortDirection: ResultOrder\n}\n\ntype RecordAggregate @generic {\n ApiName: String!\n BooleanAggregate: BooleanAggregate @fieldCategory\n CurrencyAggregate: CurrencyAggregate @fieldCategory\n DateAggregate: DateAggregate @fieldCategory\n DoubleAggregate: DoubleAggregate @fieldCategory\n EmailAggregate: EmailAggregate @fieldCategory\n IDAggregate: IDAggregate @fieldCategory\n IntAggregate: IntAggregate @fieldCategory\n LatitudeAggregate: LatitudeAggregate @fieldCategory\n LongitudeAggregate: LongitudeAggregate @fieldCategory\n LongAggregate: LongAggregate @fieldCategory\n PercentAggregate: PercentAggregate @fieldCategory\n PhoneNumberAggregate: PhoneNumberAggregate @fieldCategory\n PicklistAggregate: PicklistAggregate @fieldCategory\n StringAggregate: StringAggregate @fieldCategory\n TextAreaAggregate: TextAreaAggregate @fieldCategory\n TimeAggregate: TimeAggregate @fieldCategory\n UrlAggregate: UrlAggregate @fieldCategory\n}\n\ntype JSONValue implements FieldValue {\n value: JSON\n displayValue: String\n}\n\ntype EmailValue implements FieldValue {\n value: Email\n displayValue: String\n}\n\ntype Setup__Setup {\n query: Setup__SetupQuery!\n}\n\nenum AggregateOrderByStringFunction {\n COUNT\n COUNT_DISTINCT\n MAX\n MIN\n}\n\ntype LongValue implements FieldValue {\n value: Long\n displayValue: String\n format: String\n}\n\ninput DateFunctionInput {\n value: LongOperators\n convertTimezoneValue: LongOperators\n}\n\n# Mutations aren't supported yet.\n#type Mutation {\n# uiapi(input: UIAPIMutationsInput): UIAPIMutations!\n#}\n\ntype DependentField {\n controllingField: String!\n dependentFields: [String]!\n}\n\ninput LongTextAreaOperators {\n eq: LongTextArea\n ne: LongTextArea\n like: LongTextArea\n lt: LongTextArea\n gt: LongTextArea\n lte: LongTextArea\n gte: LongTextArea\n in: [LongTextArea]\n nin: [LongTextArea]\n}\n\nenum __TypeKind {\n SCALAR\n OBJECT\n INTERFACE\n UNION\n ENUM\n INPUT_OBJECT\n LIST\n NON_NULL\n}\n\ntype Setup__SetupConnection @generic {\n edges: [Setup__SetupEdge]\n pageInfo: PageInfo!\n totalCount: Int!\n pageResultCount: Int!\n}\n\ntype PercentValue implements FieldValue {\n value: Percent\n displayValue: String\n format: String\n}\n\ninput DateTimeOperators {\n eq: DateTimeInput\n ne: DateTimeInput\n lt: DateTimeInput\n gt: DateTimeInput\n lte: DateTimeInput\n gte: DateTimeInput\n in: [DateTimeInput]\n nin: [DateTimeInput]\n DAY_IN_WEEK: DateFunctionInput\n DAY_IN_MONTH: DateFunctionInput\n DAY_IN_YEAR: DateFunctionInput\n WEEK_IN_MONTH: DateFunctionInput\n WEEK_IN_YEAR: DateFunctionInput\n CALENDAR_MONTH: DateFunctionInput\n CALENDAR_QUARTER: DateFunctionInput\n CALENDAR_YEAR: DateFunctionInput\n FISCAL_MONTH: DateFunctionInput\n FISCAL_QUARTER: DateFunctionInput\n FISCAL_YEAR: DateFunctionInput\n DAY_ONLY: DateTimeFunctionInput\n HOUR_IN_DAY: DateFunctionInput\n}\n\ninput NoFunctionAggregateOrderByClause {\n order: ResultsOrder\n nulls: NullsOrder\n}\n\ntype BooleanAggregate implements FieldValue {\n value: Boolean\n displayValue: String\n grouping: IntValue\n}\n\ntype RecordQueryAggregate {\n # RecordScope is replaced with String\n recordQueryAggregate(first: Int, after: String, where: RecordFilter, orderBy: AggregateOrderBy, scope: String, groupBy: RecordGroupBy, upperBound: Int): RecordAggregateConnection @fieldCategory\n}\n\ntype RecordConnection @generic {\n edges: [RecordEdge]\n pageInfo: PageInfo!\n totalCount: Int!\n pageResultCount: Int!\n}\n\ntype FilteredLookupInfo {\n controllingFields: [String]!\n dependent: Boolean!\n optionalFilter: Boolean!\n}\n\ninput PhoneNumberOperators {\n eq: PhoneNumber\n ne: PhoneNumber\n like: PhoneNumber\n lt: PhoneNumber\n gt: PhoneNumber\n lte: PhoneNumber\n gte: PhoneNumber\n in: [PhoneNumber]\n nin: [PhoneNumber]\n}\n\ntype ObjectInfo {\n ApiName: String!\n childRelationships: [ChildRelationship]!\n createable: Boolean!\n custom: Boolean!\n defaultRecordTypeId: ID\n deletable: Boolean!\n dependentFields: [DependentField]!\n feedEnabled: Boolean!\n fields: [Field]!\n keyPrefix: String\n label: String\n labelPlural: String\n layoutable: Boolean!\n mruEnabled: Boolean!\n nameFields: [String]!\n queryable: Boolean!\n recordTypeInfos: [RecordTypeInfo]!\n searchable: Boolean!\n themeInfo: ThemeInfo\n updateable: Boolean!\n locale: String\n}\n\ninput LongitudeOperators {\n eq: Longitude\n ne: Longitude\n lt: Longitude\n gt: Longitude\n lte: Longitude\n gte: Longitude\n in: [Longitude]\n nin: [Longitude]\n}\n\ninput RecordCreateRepresentation @generic {\n Int: Int @fieldCategory\n String: String @fieldCategory\n Boolean: Boolean @fieldCategory\n ID: IdOrRef @fieldCategory\n DateTime: DateTime @fieldCategory\n Time: Time @fieldCategory\n Date: Date @fieldCategory\n TextArea: TextArea @fieldCategory\n LongTextArea: LongTextArea @fieldCategory\n RichTextArea: RichTextArea @fieldCategory\n PhoneNumber: PhoneNumber @fieldCategory\n Email: Email @fieldCategory\n Url: Url @fieldCategory\n EncryptedString: EncryptedString @fieldCategory\n Currency: Currency @fieldCategory\n Longitude: Longitude @fieldCategory\n Latitude: Latitude @fieldCategory\n Picklist: Picklist @fieldCategory\n MultiPicklist: MultiPicklist @fieldCategory\n Long: Long @fieldCategory\n Double: Double @fieldCategory\n Percent: Percent @fieldCategory\n Base64: Base64 @fieldCategory\n JSON: JSON @fieldCategory\n}\n\ntype Field {\n ApiName: String!\n calculated: Boolean!\n compound: Boolean!\n compoundComponentName: String\n compoundFieldName: String\n controllerName: String\n controllingFields: [String]!\n createable: Boolean!\n custom: Boolean!\n dataType: DataType\n extraTypeInfo: FieldExtraTypeInfo\n filterable: Boolean!\n filteredLookupInfo: FilteredLookupInfo\n highScaleNumber: Boolean!\n htmlFormatted: Boolean!\n inlineHelpText: String\n label: String\n nameField: Boolean!\n polymorphicForeignKey: Boolean!\n precision: Int\n reference: Boolean!\n referenceTargetField: String\n referenceToInfos: [ReferenceToInfo]!\n relationshipName: String\n required: Boolean!\n scale: Int\n searchPrefilterable: Boolean\n sortable: Boolean!\n updateable: Boolean!\n}\n\nenum FieldExtraTypeInfo {\n IMAGE_URL\n EXTERNAL_LOOKUP\n INDIRECT_LOOKUP\n PERSONNAME\n SWITCHABLE_PERSONNAME\n PLAINTEXTAREA\n RICHTEXTAREA\n}\n\ntype RateLimit {\n cost: Long\n limit: Long\n remaining: Long\n resetAt: DateTime\n}\n\ninput DateRange {\n last_n_days: Int\n next_n_days: Int\n last_n_weeks: Int\n next_n_weeks: Int\n last_n_months: Int\n next_n_months: Int\n last_n_quarters: Int\n next_n_quarters: Int\n last_n_fiscal_quarters: Int\n next_n_fiscal_quarters: Int\n last_n_years: Int\n next_n_years: Int\n last_n_fiscal_years: Int\n next_n_fiscal_years: Int\n n_days_ago: Int\n n_weeks_ago: Int\n n_months_ago: Int\n n_quarters_ago: Int\n n_years_ago: Int\n n_fiscal_quarters_ago: Int\n n_fiscal_years_ago: Int\n}\n\ntype UIAPIMutations {\n recordCreate(input: RecordCreateInput!): RecordCreatePayload @fieldCategory\n recordDelete(input: RecordDeleteInput!): RecordDeletePayload @fieldCategory\n recordUpdate(input: RecordUpdateInput!): RecordUpdatePayload @fieldCategory\n}\n\ninput DateTimeFunctionInput {\n value: DatePrimitiveOperators\n convertTimezoneValue: DatePrimitiveOperators\n}\n\ntype Base64Value implements FieldValue {\n value: Base64\n displayValue: String\n}\n\ninput IntegerOperators {\n eq: Int\n ne: Int\n lt: Int\n gt: Int\n lte: Int\n gte: Int\n in: [Int]\n nin: [Int]\n}\n\ntype EncryptedStringValue implements FieldValue {\n value: EncryptedString\n displayValue: String\n}\n\ninterface Record {\n Id: ID!\n ApiName: String!\n WeakEtag: Long!\n DisplayValue: String\n LastModifiedById: IDValue\n LastModifiedDate: DateTimeValue\n SystemModstamp: DateTimeValue\n RecordTypeId(fallback: Boolean): IDValue\n}\n\ninput PolymorphicParentRelationshipRecordFilter @generic {\n RecordFilter: RecordFilter @fieldCategory\n}\n\ninput AggregateOrderByNumberClause {\n function: AggregateOrderByNumberFunction\n order: ResultsOrder\n nulls: NullsOrder\n}\n\ntype __Schema {\n types: [__Type!]!\n queryType: __Type!\n mutationType: __Type\n directives: [__Directive!]!\n subscriptionType: __Type\n}\n\ninput Setup__SetupPolymorphicParentRelationshipRecordFilter @generic {\n Setup__SetupFilter: Setup__SetupFilter @fieldCategory\n}\n\ntype CompoundField @generic {\n IntValue: IntValue @fieldCategory\n StringValue: StringValue @fieldCategory\n BooleanValue: BooleanValue @fieldCategory\n IDValue: IDValue @fieldCategory\n DateTimeValue: DateTimeValue @fieldCategory\n TimeValue: TimeValue @fieldCategory\n DateValue: DateValue @fieldCategory\n TextAreaValue: TextAreaValue @fieldCategory\n LongTextAreaValue: LongTextAreaValue @fieldCategory\n RichTextAreaValue: RichTextAreaValue @fieldCategory\n PhoneNumberValue: PhoneNumberValue @fieldCategory\n EmailValue: EmailValue @fieldCategory\n UrlValue: UrlValue @fieldCategory\n EncryptedStringValue: EncryptedStringValue @fieldCategory\n CurrencyValue: CurrencyValue @fieldCategory\n LongitudeValue: LongitudeValue @fieldCategory\n LatitudeValue: LatitudeValue @fieldCategory\n PicklistValue: PicklistValue @fieldCategory\n MultiPicklistValue: MultiPicklistValue @fieldCategory\n LongValue: LongValue @fieldCategory\n DoubleValue: DoubleValue @fieldCategory\n PercentValue: PercentValue @fieldCategory\n Base64Value: Base64Value @fieldCategory\n JSONValue: JSONValue @fieldCategory\n}\n\ninput RecordUpdateInput @generic {\n Id: IdOrRef!\n record: RecordUpdateRepresentation! @fieldCategory\n}\n\ninput DateTimeInput {\n value: DateTime\n literal: DateLiteral\n range: DateRange\n}\n\ntype ChildRelationship {\n childObjectApiName: String!\n fieldName: String\n junctionIdListNames: [String]!\n junctionReferenceTo: [String]!\n relationshipName: String\n objectInfo: ObjectInfo\n}\n\ntype RecordResult @generic {\n aggregate: RecordAggregate\n}\n\ntype PageInfo {\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n startCursor: String\n endCursor: String\n}\n\ntype CurrencyValue implements FieldValue {\n value: Currency\n displayValue: String\n format: String\n}\n\ninput DateInput {\n value: Date\n literal: DateLiteral\n range: DateRange\n}\n\ninput RecordGroupBy @generic {\n groupableField: GroupByClause @fieldCategory\n groupableDateField: GroupByDateFunction @fieldCategory\n groupableParentRelationship: RecordGroupBy @fieldCategory\n groupablePolymorphicParentRelationship: PolymorphicParentRelationshipGroupBy @fieldCategory\n type: GroupByType = GROUP_BY\n}\n\ntype DateFunctionAggregation {\n value: Long\n format: String\n}\n\ntype RecordQuery {\n # scope should be type RecordScope but that's empty enum.\n recordQuery(first: Int, after: String, where: RecordFilter, orderBy: RecordOrderBy, scope: String, upperBound: Int): RecordConnection @fieldCategory\n}\n\ndirective @generic on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT\ndirective @fieldCategory on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | ENUM_VALUE\ndirective @category(name: String!) on FIELD";
3737
-
3738
- // Define additional schema that is missing from uiapi that we use in local evaluation
3739
- const additionalSchemaDefinitions = /* GraphQL */ `
3740
- enum SupportedScopes {
3741
- ASSIGNEDTOME
3742
- MINE
3743
- }
3744
- `;
3745
- const baseTypeDefinitions = uiapiSchemaString + additionalSchemaDefinitions;
3746
- class CachedGraphQLSchema {
3747
- constructor() {
3748
- this._schema = buildBaseSchema();
3749
- this._polymorphicFieldTypeNames = [];
3750
- }
3751
- getSchema() {
3752
- return this._schema;
3753
- }
3754
- setSchema(value) {
3755
- this._schema = value;
3756
- }
3757
- getPolymorphicFieldTypeNames() {
3758
- return this._polymorphicFieldTypeNames;
3759
- }
3760
- setPolymorphicFieldTypeNames(value) {
3761
- this._polymorphicFieldTypeNames = value;
3762
- }
3763
- set(schema, polymorphicFieldTypeNames) {
3764
- this._schema = schema;
3765
- this._polymorphicFieldTypeNames = polymorphicFieldTypeNames;
3766
- }
3767
- }
3768
- /**
3769
- * Builds the base schema from uiapi graphql adapter with resolvers attached
3770
- * @returns GraphQLSchema
3771
- */
3772
- function buildBaseSchema() {
3773
- return addResolversToSchema(buildSchema(baseTypeDefinitions), []);
3774
- }
3775
-
3776
- ({
3777
- kind: Kind.DIRECTIVE,
3778
- name: {
3779
- kind: Kind.NAME,
3780
- value: 'category',
3781
- },
3782
- arguments: [
3783
- {
3784
- kind: Kind.ARGUMENT,
3785
- name: {
3786
- kind: Kind.NAME,
3787
- value: 'name',
3788
- },
3789
- value: {
3790
- kind: Kind.STRING,
3791
- value: PARENT_RELATIONSHIP,
3792
- block: false,
3793
- },
3794
- },
3795
- ],
3796
- });
3797
- ({
3798
- kind: Kind.SELECTION_SET,
3799
- selections: [
3800
- {
3801
- kind: Kind.FIELD,
3802
- name: {
3803
- kind: Kind.NAME,
3804
- value: 'value',
3805
- },
3806
- },
3807
- ],
3808
- });
3809
-
3810
1662
  /**
3811
1663
  * Copyright (c) 2022, Salesforce, Inc.,
3812
1664
  * All rights reserved.
@@ -4175,8 +2027,6 @@ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecord
4175
2027
  getDenormalizedRecord: { value: getDenormalizedRecord, writable: true },
4176
2028
  });
4177
2029
  }
4178
- // create the runtime cache for the graphql schema when the factory creates the adapter
4179
- new CachedGraphQLSchema();
4180
2030
 
4181
2031
  let luvio;
4182
2032
  let getIngestRecords;
@@ -4235,4 +2085,4 @@ function ldsRuntimeBridge() {
4235
2085
  }
4236
2086
 
4237
2087
  export { ldsRuntimeBridge as default };
4238
- // version: 1.294.0-06a44f23f
2088
+ // version: 1.296.0-ad26368c0