@salesforce/lds-worker-api 1.287.0-dev15 → 1.287.0-dev17

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.
@@ -1074,4 +1074,4 @@ if (process.env.NODE_ENV !== 'production') {
1074
1074
  }
1075
1075
 
1076
1076
  export { createPrimingSession, draftManager, draftQueue, evictCacheRecordsByIds, evictExpiredCacheEntries, executeAdapter, executeMutatingAdapter, getImperativeAdapterNames, invokeAdapter, invokeAdapterWithDraftToMerge, invokeAdapterWithDraftToReplace, invokeAdapterWithMetadata, nimbusDraftQueue, setMetadataTTL, setUiApiRecordTTL, stopEviction, subscribeToAdapter };
1077
- // version: 1.287.0-dev15-a292df40d2
1077
+ // version: 1.287.0-dev17-670374cbf3
@@ -835,14 +835,7 @@ class StringKeyInMemoryStore {
835
835
  // of the function, in case the reference changes (because of an unsubscribe)
836
836
  const { snapshotSubscriptions } = this;
837
837
  // read metadata for each key, and mark as expired
838
- const expirationTimestamp = Date.now();
839
- for (let i = 0, len = keys.length; i < len; i++) {
840
- const key = keys[i];
841
- const metadata = this.readMetadata(key);
842
- if (metadata !== undefined) {
843
- this.publishMetadata(key, { ...metadata, expirationTimestamp });
844
- }
845
- }
838
+ this.expirePossibleStaleRecords(keys);
846
839
  // Process snapshot subscriptions
847
840
  const pendingPromises = [];
848
841
  for (let i = 0, len = snapshotSubscriptions.length; i < len; i++) {
@@ -937,6 +930,16 @@ class StringKeyInMemoryStore {
937
930
  this.metadata[canonicalKey] = storeMetadata;
938
931
  }
939
932
  }
933
+ expirePossibleStaleRecords(keys) {
934
+ const expirationTimestamp = Date.now();
935
+ for (let i = 0, len = keys.length; i < len; i++) {
936
+ const key = keys[i];
937
+ const metadata = this.readMetadata(key);
938
+ if (metadata !== undefined) {
939
+ this.publishMetadata(key, { ...metadata, expirationTimestamp });
940
+ }
941
+ }
942
+ }
940
943
  setTTLOverride(namespace, representationName, ttl) {
941
944
  this.ttlOverrides[getTTLOverrideKey(namespace, representationName)] = ttl;
942
945
  }
@@ -1531,14 +1534,7 @@ class InMemoryStore {
1531
1534
  // of the function, in case the reference changes (because of an unsubscribe)
1532
1535
  const { snapshotSubscriptions } = this;
1533
1536
  // read metadata for each key, and mark as expired
1534
- const expirationTimestamp = Date.now();
1535
- for (let i = 0, len = keys.length; i < len; i++) {
1536
- const key = keys[i];
1537
- const metadata = this.readMetadata(key);
1538
- if (metadata !== undefined) {
1539
- this.publishMetadata(key, { ...metadata, expirationTimestamp });
1540
- }
1541
- }
1537
+ this.expirePossibleStaleRecords(keys);
1542
1538
  // Process snapshot subscriptions
1543
1539
  const pendingPromises = [];
1544
1540
  for (let i = 0, len = snapshotSubscriptions.length; i < len; i++) {
@@ -1661,6 +1657,19 @@ class InMemoryStore {
1661
1657
  this.metadataMap.set(canonicalKey, storeMetadata);
1662
1658
  }
1663
1659
  }
1660
+ expirePossibleStaleRecords(keys) {
1661
+ if (keys.length > 0 && typeof keys[0] === 'string') {
1662
+ return this.fallbackStringKeyInMemoryStore.expirePossibleStaleRecords(keys);
1663
+ }
1664
+ const expirationTimestamp = Date.now();
1665
+ for (let i = 0, len = keys.length; i < len; i++) {
1666
+ const key = keys[i];
1667
+ const metadata = this.readMetadata(key);
1668
+ if (metadata !== undefined) {
1669
+ this.publishMetadata(key, { ...metadata, expirationTimestamp });
1670
+ }
1671
+ }
1672
+ }
1664
1673
  setTTLOverride(namespace, representationName, ttl) {
1665
1674
  // Set the TTLs in both the stores
1666
1675
  this.fallbackStringKeyInMemoryStore.setTTLOverride(namespace, representationName, ttl);
@@ -3622,6 +3631,30 @@ class Environment {
3622
3631
  buildStructuredKey(namespace, representationName, idValues) {
3623
3632
  return this.store.buildStructuredKey(namespace, representationName, idValues);
3624
3633
  }
3634
+ /**
3635
+ * Take a list of keys and marks them as stale to be refreshed.
3636
+ * Then will be refreshed with the provided refresh function.
3637
+ * If no refresh and makeConfig functions are provided it will refresh
3638
+ * time that record is trying to be fetched
3639
+ *
3640
+ * Example: one record from graphql needs to be refreshed and not
3641
+ * the entire graphql query
3642
+ *
3643
+ * @param keys
3644
+ * @param makeConfig
3645
+ * @param refresh
3646
+ * @returns
3647
+ */
3648
+ expirePossibleStaleRecords(keys, config, refresh) {
3649
+ this.store.expirePossibleStaleRecords(keys);
3650
+ if (refresh !== undefined && config !== undefined) {
3651
+ return this.refreshPossibleStaleRecords(config, refresh);
3652
+ }
3653
+ return Promise.resolve();
3654
+ }
3655
+ refreshPossibleStaleRecords(config, refresh) {
3656
+ return Promise.resolve(refresh(config, { cachePolicy: { type: 'no-cache' } })).then(() => { });
3657
+ }
3625
3658
  }
3626
3659
 
3627
3660
  class Luvio {
@@ -3688,6 +3721,9 @@ class Luvio {
3688
3721
  storeCleanup() {
3689
3722
  this.environment.storeCleanup();
3690
3723
  }
3724
+ storeExpirePossibleStaleRecords(keys, config, refresh) {
3725
+ return this.environment.expirePossibleStaleRecords(keys, config, refresh);
3726
+ }
3691
3727
  createSnapshot(selector, refresh) {
3692
3728
  return this.environment.createSnapshot(selector, refresh);
3693
3729
  }
@@ -4076,7 +4112,7 @@ function createResourceParamsImpl(config, configMetadata) {
4076
4112
  }
4077
4113
  return resourceParams;
4078
4114
  }
4079
- // engine version: 0.154.17-dev2-5c176528
4115
+ // engine version: 0.154.17-dev3-133dce6d
4080
4116
 
4081
4117
  /**
4082
4118
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -4204,7 +4240,7 @@ function withDefaultLuvio(callback) {
4204
4240
  }
4205
4241
  callbacks.push(callback);
4206
4242
  }
4207
- // version: 1.287.0-dev15-a292df40d2
4243
+ // version: 1.287.0-dev17-670374cbf3
4208
4244
 
4209
4245
  // TODO [TD-0081508]: once that TD is fulfilled we can probably change this file
4210
4246
  function instrumentAdapter$1(createFunction, _metadata) {
@@ -15712,7 +15748,7 @@ function gql(literals, ...subs) {
15712
15748
  }
15713
15749
  return superResult;
15714
15750
  }
15715
- // version: 1.287.0-dev15-a292df40d2
15751
+ // version: 1.287.0-dev17-670374cbf3
15716
15752
 
15717
15753
  function unwrap(data) {
15718
15754
  // The lwc-luvio bindings import a function from lwc called "unwrap".
@@ -16641,7 +16677,7 @@ function createGraphQLWireAdapterConstructor(luvio, adapter, metadata, astResolv
16641
16677
  const { apiFamily, name } = metadata;
16642
16678
  return createGraphQLWireAdapterConstructor$1(adapter, `${apiFamily}.${name}`, luvio, astResolver);
16643
16679
  }
16644
- // version: 1.287.0-dev15-a292df40d2
16680
+ // version: 1.287.0-dev17-670374cbf3
16645
16681
 
16646
16682
  /**
16647
16683
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -16740,7 +16776,7 @@ var TypeCheckShapes;
16740
16776
  TypeCheckShapes[TypeCheckShapes["Integer"] = 3] = "Integer";
16741
16777
  TypeCheckShapes[TypeCheckShapes["Unsupported"] = 4] = "Unsupported";
16742
16778
  })(TypeCheckShapes || (TypeCheckShapes = {}));
16743
- // engine version: 0.154.17-dev2-5c176528
16779
+ // engine version: 0.154.17-dev3-133dce6d
16744
16780
 
16745
16781
  const { keys: ObjectKeys$3, create: ObjectCreate$3 } = Object;
16746
16782
 
@@ -44256,7 +44292,7 @@ withDefaultLuvio((luvio) => {
44256
44292
  throttle(60, 60000, setupNotifyAllListRecordUpdateAvailable(luvio));
44257
44293
  throttle(60, 60000, setupNotifyAllListInfoSummaryUpdateAvailable(luvio));
44258
44294
  });
44259
- // version: 1.287.0-dev15-4b3ad0d7fe
44295
+ // version: 1.287.0-dev17-71a1131fd3
44260
44296
 
44261
44297
  var ldsIdempotencyWriteDisabled = {
44262
44298
  isOpen: function (e) {
@@ -45949,6 +45985,32 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
45949
45985
  }, revivingStore).finally(() => {
45950
45986
  });
45951
45987
  };
45988
+ const expirePossibleStaleRecords = async function (keys$1, config, refresh) {
45989
+ validateNotDisposed();
45990
+ const metadataKeys = keys$1.map(serializeStructuredKey);
45991
+ const now = Date.now();
45992
+ const entries = await durableStore.getMetadata(metadataKeys, DefaultDurableSegment);
45993
+ if (entries === undefined || keys$7(entries).length === 0) {
45994
+ return environment.expirePossibleStaleRecords(keys$1);
45995
+ }
45996
+ let metaDataChanged = false;
45997
+ const metadataEntries = metadataKeys.reduce((accu, key) => {
45998
+ const metadataEntry = entries[key];
45999
+ if (metadataEntry.metadata !== undefined) {
46000
+ const metadata = { ...metadataEntry.metadata, expirationTimestamp: now };
46001
+ accu[key] = { metadata };
46002
+ metaDataChanged = true;
46003
+ }
46004
+ return accu;
46005
+ }, {});
46006
+ if (metaDataChanged) {
46007
+ await durableStore.setMetadata(metadataEntries, DefaultDurableSegment);
46008
+ }
46009
+ if (config !== undefined && refresh !== undefined) {
46010
+ return environment.refreshPossibleStaleRecords(config, refresh);
46011
+ }
46012
+ return Promise.resolve();
46013
+ };
45952
46014
  // set the default cache policy of the base environment
45953
46015
  environment.setDefaultCachePolicy({
45954
46016
  type: 'stale-while-revalidate',
@@ -45981,6 +46043,7 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
45981
46043
  handleErrorResponse: { value: handleErrorResponse },
45982
46044
  getNotifyChangeStoreEntries: { value: getNotifyChangeStoreEntries },
45983
46045
  notifyStoreUpdateAvailable: { value: notifyStoreUpdateAvailable },
46046
+ expirePossibleStaleRecords: { value: expirePossibleStaleRecords },
45984
46047
  });
45985
46048
  }
45986
46049
 
@@ -51599,6 +51662,7 @@ function createContext(store, objectInfos, eventEmitter, settings, snapshot, dra
51599
51662
  Record,
51600
51663
  snapshot,
51601
51664
  seenRecordIds: new Set(),
51665
+ possibleStaleRecordMap: new Map(),
51602
51666
  draftFunctions,
51603
51667
  };
51604
51668
  }
@@ -52210,7 +52274,6 @@ function isTodayStartOfWeek() {
52210
52274
 
52211
52275
  const JSON_EXTRACT_PATH_INGESTION_TIMESTAMP = '$.ingestionTimestamp';
52212
52276
  const JSON_EXTRACT_PATH_INGESTION_APINAME = '$.apiName';
52213
- const JSON_EXTRACT_PATH_DRAFTS = '$.drafts';
52214
52277
 
52215
52278
  const MultiPickListValueSeparator = ';';
52216
52279
  function filterToPredicates(where, recordType, alias, objectInfoMap, joins, draftFunctions) {
@@ -52740,18 +52803,11 @@ function buildQuery(config) {
52740
52803
  const joins = buildJoins(config);
52741
52804
  const predicates = buildPredicates(config);
52742
52805
  const orderBy = buildOrderBy(config);
52743
- const staleRecordsSql = excludeStaleRecordsGate.isOpen({ fallback: false })
52744
- ? `AND (
52745
- json_extract("${config.alias}".metadata, '${JSON_EXTRACT_PATH_INGESTION_TIMESTAMP}') >= ?
52746
- OR json_extract("${config.alias}".data, '${JSON_EXTRACT_PATH_DRAFTS}') IS NOT NULL
52747
- )`
52748
- : '';
52749
52806
  const sql = `
52750
- SELECT "${config.alias}".data
52807
+ SELECT "${config.alias}".data, "${config.alias}".metadata
52751
52808
  FROM lds_data "${config.alias}" ${joins.sql}
52752
52809
  WHERE "${config.alias}".key like 'UiApi::RecordRepresentation:%'
52753
52810
  AND json_extract("${config.alias}".data, '${JSON_EXTRACT_PATH_INGESTION_APINAME}') = '${config.alias}'
52754
- ${staleRecordsSql}
52755
52811
  ${predicates.sql}
52756
52812
  ${orderBy.sql}
52757
52813
  LIMIT ?
@@ -52762,7 +52818,6 @@ function buildQuery(config) {
52762
52818
  const bindings = [
52763
52819
  // bindings from predicates on joins
52764
52820
  ...joins.bindings,
52765
- ...(excludeStaleRecordsGate.isOpen({ fallback: false }) ? [config.ingestionTimestamp] : []),
52766
52821
  // where clause and parent scope bindings
52767
52822
  ...predicates.bindings,
52768
52823
  // limit binding
@@ -52788,33 +52843,19 @@ function buildJoins(config) {
52788
52843
  if (allJoins.length === 0)
52789
52844
  return { sql, bindings };
52790
52845
  sql = allJoins.reduce((joinAccumulator, join) => {
52791
- let timestampAdded = false;
52792
52846
  const joinConditions = join.conditions.reduce((conditionAccumulator, condition) => {
52793
52847
  let joined_sql;
52794
- const joinMetadataTimestamp = excludeStaleRecordsGate.isOpen({ fallback: false })
52795
- ? ` AND (json_extract("${join.alias}".metadata, '${JSON_EXTRACT_PATH_INGESTION_TIMESTAMP}') >= ? OR json_extract("${join.alias}".data, '${JSON_EXTRACT_PATH_DRAFTS}') IS NOT NULL)`
52796
- : '';
52797
52848
  // predicate on a value, use the newly joined table
52798
52849
  if ('type' in condition) {
52799
52850
  const { sql, binding } = predicateToSQL(condition, join.alias);
52800
- joined_sql = ` AND ${sql}${timestampAdded ? '' : joinMetadataTimestamp}`;
52851
+ joined_sql = ` AND ${sql}`;
52801
52852
  bindings.push(...binding);
52802
- if (excludeStaleRecordsGate.isOpen({ fallback: false }) &&
52803
- timestampAdded === false) {
52804
- bindings.push(config.ingestionTimestamp);
52805
- timestampAdded = true;
52806
- }
52807
52853
  }
52808
52854
  else {
52809
52855
  // predicate on a path
52810
52856
  const left = ` AND json_extract("${join.to}".data, '${condition.leftPath}')`;
52811
52857
  const right = `json_extract("${join.alias}".data, '${condition.rightPath}')`;
52812
- joined_sql = `${left} = ${right}${timestampAdded ? '' : joinMetadataTimestamp}`;
52813
- if (excludeStaleRecordsGate.isOpen({ fallback: false }) &&
52814
- timestampAdded === false) {
52815
- bindings.push(config.ingestionTimestamp);
52816
- timestampAdded = true;
52817
- }
52858
+ joined_sql = `${left} = ${right}`;
52818
52859
  }
52819
52860
  conditionAccumulator += joined_sql;
52820
52861
  return conditionAccumulator;
@@ -53759,8 +53800,7 @@ function addResolversToSchema(schema, polyFields) {
53759
53800
  for (const field of fields) {
53760
53801
  if (field.name === 'node') {
53761
53802
  field.resolve = function nodeResolver(obj, _args, { seenRecordIds }) {
53762
- const { record, ingestionTimestamp } = obj;
53763
- const recordRepresentation = parse$4(record);
53803
+ const { recordRepresentation, ingestionTimestamp } = obj;
53764
53804
  seenRecordIds.add(recordRepresentation.id);
53765
53805
  return { recordRepresentation, ingestionTimestamp };
53766
53806
  };
@@ -53974,16 +54014,30 @@ async function connectionEdgeResolver(obj, _args, context) {
53974
54014
  predicates,
53975
54015
  orderBy: orderByToPredicate(parentArgs.orderBy, alias, alias, context.objectInfos),
53976
54016
  limit: parentArgs.first,
53977
- ingestionTimestamp,
53978
54017
  };
53979
54018
  const { sql, bindings } = buildQuery(queryConfig);
53980
54019
  const results = await query(sql, bindings);
53981
54020
  //map each sql result with the ingestion timestamp to pass it down a level
53982
- return results.rows
53983
- .map((row) => row[0])
53984
- .map((record) => {
54021
+ return results.rows.map((row) => {
54022
+ const recordMetadataResult = {
54023
+ recordRepresentation: parse$4(row[0]),
54024
+ metadata: parse$4(row[1]),
54025
+ };
54026
+ const { recordRepresentation, metadata } = recordMetadataResult;
54027
+ context.seenRecordIds.add(recordRepresentation.id);
54028
+ if (metadata.ingestionTimestamp < ingestionTimestamp &&
54029
+ recordRepresentation.drafts === undefined) {
54030
+ if (context.possibleStaleRecordMap.has(recordRepresentation.apiName) === false) {
54031
+ context.possibleStaleRecordMap.set(recordRepresentation.apiName, []);
54032
+ }
54033
+ const ids = context.possibleStaleRecordMap.get(recordRepresentation.apiName);
54034
+ if (ids !== undefined) {
54035
+ ids.push(recordRepresentation.id);
54036
+ context.possibleStaleRecordMap.set(recordRepresentation.apiName, ids);
54037
+ }
54038
+ }
53985
54039
  return {
53986
- record,
54040
+ recordRepresentation,
53987
54041
  ingestionTimestamp,
53988
54042
  };
53989
54043
  });
@@ -54548,7 +54602,11 @@ async function evaluate(config, observers, settings, objectInfos, store, snapsho
54548
54602
  seenRecordIds.push(queryString);
54549
54603
  });
54550
54604
  }
54551
- return { result, seenRecordIds };
54605
+ return {
54606
+ result,
54607
+ seenRecordIds,
54608
+ possibleStaleRecordMap: contextValue.possibleStaleRecordMap,
54609
+ };
54552
54610
  }
54553
54611
  finally {
54554
54612
  eventEmitter({ type: 'graphql-eval-end' });
@@ -58182,6 +58240,60 @@ function hasGraphQlErrors(response) {
58182
58240
  response.errors.length > 0);
58183
58241
  }
58184
58242
 
58243
+ const MAX_ID_CHUNK_LENGTH = 100;
58244
+ /**
58245
+ * Adapter for limiting the number of record ids to a maximum of 100 and sending them
58246
+ * out in batches to the getRecords adapter
58247
+ *
58248
+ * @param luvio
58249
+ * @returns
58250
+ */
58251
+ function batchingGetRecordsAdapterFactory(luvio) {
58252
+ const getRecordsAdapter = getRecordsAdapterFactory(luvio);
58253
+ const batchGetRecords = (config, requestContext) => {
58254
+ const seenRecords = new StoreKeySet();
58255
+ const chunks = chunkConfig(config);
58256
+ const promises = chunks.map((conf) => {
58257
+ return getRecordsAdapter(conf, requestContext);
58258
+ });
58259
+ return Promise.all(promises).then((results) => {
58260
+ const data = results.reduce((accu, item) => {
58261
+ if (item !== null && item.data !== undefined) {
58262
+ accu.results = accu.results.concat(item.data.results);
58263
+ seenRecords.merge(item.seenRecords);
58264
+ }
58265
+ return accu;
58266
+ }, { results: [] });
58267
+ return {
58268
+ data: data,
58269
+ seenRecords,
58270
+ state: 'Fulfilled',
58271
+ };
58272
+ });
58273
+ };
58274
+ return batchGetRecords;
58275
+ }
58276
+ /**
58277
+ * Given a GetRecordsConfig it will chunk it into multiple configs with a maximum of 100
58278
+ * record ids per config.
58279
+ *
58280
+ * @param config
58281
+ * @returns
58282
+ */
58283
+ function chunkConfig(config) {
58284
+ const chunks = [];
58285
+ config.records.forEach((record) => {
58286
+ const { recordIds, fields } = record;
58287
+ for (let i = 0, len = recordIds.length; i < len; i += MAX_ID_CHUNK_LENGTH) {
58288
+ const chunk = recordIds.slice(i, i + MAX_ID_CHUNK_LENGTH);
58289
+ chunks.push({
58290
+ records: [{ recordIds: chunk, fields: fields !== undefined ? fields : [] }],
58291
+ });
58292
+ }
58293
+ });
58294
+ return chunks;
58295
+ }
58296
+
58185
58297
  function generateUniqueRecordId() {
58186
58298
  return `UiApi::GraphQLRepresentation:${Date.now() + Math.random().toFixed(5).split('.')[1]}`;
58187
58299
  }
@@ -58291,8 +58403,13 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
58291
58403
  : [];
58292
58404
  let gqlResult;
58293
58405
  let seenRecordIds;
58406
+ let possibleStaleRecordMap;
58294
58407
  try {
58295
- ({ result: gqlResult, seenRecordIds } = await evaluate({
58408
+ ({
58409
+ result: gqlResult,
58410
+ seenRecordIds,
58411
+ possibleStaleRecordMap,
58412
+ } = await evaluate({
58296
58413
  ...config,
58297
58414
  //need to create another copy of the ast for future writes
58298
58415
  query: parse$3(stringify$3(injectedAST)),
@@ -58322,13 +58439,18 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
58322
58439
  const seenRecords = createSeenRecords(seenRecordIds, nonEvaluatedSnapshot);
58323
58440
  const recordId = generateUniqueRecordId();
58324
58441
  const rebuildWithLocalEval = async (originalSnapshot) => {
58325
- let { result: rebuildResult, seenRecordIds } = await evaluate({
58442
+ let { result: rebuildResult, seenRecordIds, possibleStaleRecordMap, } = await evaluate({
58326
58443
  ...config,
58327
58444
  query: injectedAST,
58328
58445
  }, observers, { userId }, objectInfoNeeded, store, originalSnapshot, graphqlSchemaCache, draftFunctions);
58329
58446
  if (!rebuildResult.errors) {
58330
58447
  rebuildResult = removeSyntheticFields(rebuildResult, config.query);
58331
58448
  }
58449
+ let snapshotState = 'Fulfilled';
58450
+ if (possibleStaleRecordMap.size > 0) {
58451
+ initiateStaleRecordRefresh(luvio, possibleStaleRecordMap);
58452
+ snapshotState = 'Stale';
58453
+ }
58332
58454
  if (objectsDeepEqual(rebuildResult, originalSnapshot.data)) {
58333
58455
  return originalSnapshot;
58334
58456
  }
@@ -58337,6 +58459,7 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
58337
58459
  ...originalSnapshot,
58338
58460
  data: rebuildResult,
58339
58461
  recordId,
58462
+ state: snapshotState,
58340
58463
  seenRecords: createSeenRecords(seenRecordIds, nonEvaluatedSnapshot),
58341
58464
  rebuildWithLocalEval,
58342
58465
  };
@@ -58374,6 +58497,10 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
58374
58497
  },
58375
58498
  };
58376
58499
  }
58500
+ if (possibleStaleRecordMap.size > 0) {
58501
+ initiateStaleRecordRefresh(luvio, possibleStaleRecordMap);
58502
+ resultSnapshot.state = 'Stale';
58503
+ }
58377
58504
  return resultSnapshot;
58378
58505
  };
58379
58506
  }
@@ -58434,6 +58561,24 @@ function environmentAwareGraphQLBatchAdapterFactory(objectInfoService, luvio, is
58434
58561
  };
58435
58562
  };
58436
58563
  }
58564
+ function initiateStaleRecordRefresh(luvio, keyMap) {
58565
+ const staleRecordKeys = from$1(keyMap.values())
58566
+ .flat()
58567
+ .map((id) => `UiApi::RecordRepresentation:${id}`);
58568
+ luvio.storeExpirePossibleStaleRecords(staleRecordKeys, makeGetRecordsConfig(keyMap), batchingGetRecordsAdapterFactory(luvio));
58569
+ }
58570
+ function makeGetRecordsConfig(keyMap) {
58571
+ const records = [];
58572
+ keyMap.forEach((recordIds, apiName) => {
58573
+ records.push({
58574
+ recordIds,
58575
+ fields: [`${apiName}.Id`],
58576
+ });
58577
+ });
58578
+ return {
58579
+ records,
58580
+ };
58581
+ }
58437
58582
 
58438
58583
  const CONTENT_DOCUMENT_DRAFT_ID_KEY = 'CONTENT_DOCUMENT_DRAFT_ID';
58439
58584
  const CONTENT_VERSION_DRAFT_ID_KEY = 'CONTENT_VERSION_DRAFT_ID';
@@ -62595,7 +62740,7 @@ register$1({
62595
62740
  id: '@salesforce/lds-network-adapter',
62596
62741
  instrument: instrument$2,
62597
62742
  });
62598
- // version: 1.287.0-dev15-a292df40d2
62743
+ // version: 1.287.0-dev17-670374cbf3
62599
62744
 
62600
62745
  const { create: create$3, keys: keys$3 } = Object;
62601
62746
  const { stringify: stringify$1, parse: parse$1 } = JSON;
@@ -82659,7 +82804,7 @@ register$1({
82659
82804
  configuration: { ...configurationForGraphQLAdapters$1 },
82660
82805
  instrument: instrument$1,
82661
82806
  });
82662
- // version: 1.287.0-dev15-4b3ad0d7fe
82807
+ // version: 1.287.0-dev17-71a1131fd3
82663
82808
 
82664
82809
  // On core the unstable adapters are re-exported with different names,
82665
82810
  // we want to match them here.
@@ -84915,7 +85060,7 @@ withDefaultLuvio((luvio) => {
84915
85060
  unstable_graphQL_imperative = createImperativeAdapter(luvio, createInstrumentedAdapter(ldsAdapter, adapterMetadata), adapterMetadata);
84916
85061
  graphQLImperative = ldsAdapter;
84917
85062
  });
84918
- // version: 1.287.0-dev15-4b3ad0d7fe
85063
+ // version: 1.287.0-dev17-71a1131fd3
84919
85064
 
84920
85065
  var gqlApi = /*#__PURE__*/Object.freeze({
84921
85066
  __proto__: null,
@@ -85653,7 +85798,7 @@ const callbacks$1 = [];
85653
85798
  function register(r) {
85654
85799
  callbacks$1.forEach((callback) => callback(r));
85655
85800
  }
85656
- // version: 1.287.0-dev15-a292df40d2
85801
+ // version: 1.287.0-dev17-670374cbf3
85657
85802
 
85658
85803
  /**
85659
85804
  * Returns true if the value acts like a Promise, i.e. has a "then" function,
@@ -90615,4 +90760,4 @@ const { luvio } = getRuntime();
90615
90760
  setDefaultLuvio({ luvio });
90616
90761
 
90617
90762
  export { createPrimingSession, draftManager, draftQueue, evictCacheRecordsByIds, evictExpiredCacheEntries, executeAdapter, executeMutatingAdapter, getImperativeAdapterNames, invokeAdapter, invokeAdapterWithDraftToMerge, invokeAdapterWithDraftToReplace, invokeAdapterWithMetadata, nimbusDraftQueue, registerReportObserver, setMetadataTTL, setUiApiRecordTTL, stopEviction, subscribeToAdapter };
90618
- // version: 1.287.0-dev15-a292df40d2
90763
+ // version: 1.287.0-dev17-670374cbf3
@@ -841,14 +841,7 @@
841
841
  // of the function, in case the reference changes (because of an unsubscribe)
842
842
  const { snapshotSubscriptions } = this;
843
843
  // read metadata for each key, and mark as expired
844
- const expirationTimestamp = Date.now();
845
- for (let i = 0, len = keys.length; i < len; i++) {
846
- const key = keys[i];
847
- const metadata = this.readMetadata(key);
848
- if (metadata !== undefined) {
849
- this.publishMetadata(key, { ...metadata, expirationTimestamp });
850
- }
851
- }
844
+ this.expirePossibleStaleRecords(keys);
852
845
  // Process snapshot subscriptions
853
846
  const pendingPromises = [];
854
847
  for (let i = 0, len = snapshotSubscriptions.length; i < len; i++) {
@@ -943,6 +936,16 @@
943
936
  this.metadata[canonicalKey] = storeMetadata;
944
937
  }
945
938
  }
939
+ expirePossibleStaleRecords(keys) {
940
+ const expirationTimestamp = Date.now();
941
+ for (let i = 0, len = keys.length; i < len; i++) {
942
+ const key = keys[i];
943
+ const metadata = this.readMetadata(key);
944
+ if (metadata !== undefined) {
945
+ this.publishMetadata(key, { ...metadata, expirationTimestamp });
946
+ }
947
+ }
948
+ }
946
949
  setTTLOverride(namespace, representationName, ttl) {
947
950
  this.ttlOverrides[getTTLOverrideKey(namespace, representationName)] = ttl;
948
951
  }
@@ -1537,14 +1540,7 @@
1537
1540
  // of the function, in case the reference changes (because of an unsubscribe)
1538
1541
  const { snapshotSubscriptions } = this;
1539
1542
  // read metadata for each key, and mark as expired
1540
- const expirationTimestamp = Date.now();
1541
- for (let i = 0, len = keys.length; i < len; i++) {
1542
- const key = keys[i];
1543
- const metadata = this.readMetadata(key);
1544
- if (metadata !== undefined) {
1545
- this.publishMetadata(key, { ...metadata, expirationTimestamp });
1546
- }
1547
- }
1543
+ this.expirePossibleStaleRecords(keys);
1548
1544
  // Process snapshot subscriptions
1549
1545
  const pendingPromises = [];
1550
1546
  for (let i = 0, len = snapshotSubscriptions.length; i < len; i++) {
@@ -1667,6 +1663,19 @@
1667
1663
  this.metadataMap.set(canonicalKey, storeMetadata);
1668
1664
  }
1669
1665
  }
1666
+ expirePossibleStaleRecords(keys) {
1667
+ if (keys.length > 0 && typeof keys[0] === 'string') {
1668
+ return this.fallbackStringKeyInMemoryStore.expirePossibleStaleRecords(keys);
1669
+ }
1670
+ const expirationTimestamp = Date.now();
1671
+ for (let i = 0, len = keys.length; i < len; i++) {
1672
+ const key = keys[i];
1673
+ const metadata = this.readMetadata(key);
1674
+ if (metadata !== undefined) {
1675
+ this.publishMetadata(key, { ...metadata, expirationTimestamp });
1676
+ }
1677
+ }
1678
+ }
1670
1679
  setTTLOverride(namespace, representationName, ttl) {
1671
1680
  // Set the TTLs in both the stores
1672
1681
  this.fallbackStringKeyInMemoryStore.setTTLOverride(namespace, representationName, ttl);
@@ -3628,6 +3637,30 @@
3628
3637
  buildStructuredKey(namespace, representationName, idValues) {
3629
3638
  return this.store.buildStructuredKey(namespace, representationName, idValues);
3630
3639
  }
3640
+ /**
3641
+ * Take a list of keys and marks them as stale to be refreshed.
3642
+ * Then will be refreshed with the provided refresh function.
3643
+ * If no refresh and makeConfig functions are provided it will refresh
3644
+ * time that record is trying to be fetched
3645
+ *
3646
+ * Example: one record from graphql needs to be refreshed and not
3647
+ * the entire graphql query
3648
+ *
3649
+ * @param keys
3650
+ * @param makeConfig
3651
+ * @param refresh
3652
+ * @returns
3653
+ */
3654
+ expirePossibleStaleRecords(keys, config, refresh) {
3655
+ this.store.expirePossibleStaleRecords(keys);
3656
+ if (refresh !== undefined && config !== undefined) {
3657
+ return this.refreshPossibleStaleRecords(config, refresh);
3658
+ }
3659
+ return Promise.resolve();
3660
+ }
3661
+ refreshPossibleStaleRecords(config, refresh) {
3662
+ return Promise.resolve(refresh(config, { cachePolicy: { type: 'no-cache' } })).then(() => { });
3663
+ }
3631
3664
  }
3632
3665
 
3633
3666
  class Luvio {
@@ -3694,6 +3727,9 @@
3694
3727
  storeCleanup() {
3695
3728
  this.environment.storeCleanup();
3696
3729
  }
3730
+ storeExpirePossibleStaleRecords(keys, config, refresh) {
3731
+ return this.environment.expirePossibleStaleRecords(keys, config, refresh);
3732
+ }
3697
3733
  createSnapshot(selector, refresh) {
3698
3734
  return this.environment.createSnapshot(selector, refresh);
3699
3735
  }
@@ -4082,7 +4118,7 @@
4082
4118
  }
4083
4119
  return resourceParams;
4084
4120
  }
4085
- // engine version: 0.154.17-dev2-5c176528
4121
+ // engine version: 0.154.17-dev3-133dce6d
4086
4122
 
4087
4123
  /**
4088
4124
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -4210,7 +4246,7 @@
4210
4246
  }
4211
4247
  callbacks.push(callback);
4212
4248
  }
4213
- // version: 1.287.0-dev15-a292df40d2
4249
+ // version: 1.287.0-dev17-670374cbf3
4214
4250
 
4215
4251
  // TODO [TD-0081508]: once that TD is fulfilled we can probably change this file
4216
4252
  function instrumentAdapter$1(createFunction, _metadata) {
@@ -15718,7 +15754,7 @@
15718
15754
  }
15719
15755
  return superResult;
15720
15756
  }
15721
- // version: 1.287.0-dev15-a292df40d2
15757
+ // version: 1.287.0-dev17-670374cbf3
15722
15758
 
15723
15759
  function unwrap(data) {
15724
15760
  // The lwc-luvio bindings import a function from lwc called "unwrap".
@@ -16647,7 +16683,7 @@
16647
16683
  const { apiFamily, name } = metadata;
16648
16684
  return createGraphQLWireAdapterConstructor$1(adapter, `${apiFamily}.${name}`, luvio, astResolver);
16649
16685
  }
16650
- // version: 1.287.0-dev15-a292df40d2
16686
+ // version: 1.287.0-dev17-670374cbf3
16651
16687
 
16652
16688
  /**
16653
16689
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -16746,7 +16782,7 @@
16746
16782
  TypeCheckShapes[TypeCheckShapes["Integer"] = 3] = "Integer";
16747
16783
  TypeCheckShapes[TypeCheckShapes["Unsupported"] = 4] = "Unsupported";
16748
16784
  })(TypeCheckShapes || (TypeCheckShapes = {}));
16749
- // engine version: 0.154.17-dev2-5c176528
16785
+ // engine version: 0.154.17-dev3-133dce6d
16750
16786
 
16751
16787
  const { keys: ObjectKeys$3, create: ObjectCreate$3 } = Object;
16752
16788
 
@@ -44262,7 +44298,7 @@
44262
44298
  throttle(60, 60000, setupNotifyAllListRecordUpdateAvailable(luvio));
44263
44299
  throttle(60, 60000, setupNotifyAllListInfoSummaryUpdateAvailable(luvio));
44264
44300
  });
44265
- // version: 1.287.0-dev15-4b3ad0d7fe
44301
+ // version: 1.287.0-dev17-71a1131fd3
44266
44302
 
44267
44303
  var ldsIdempotencyWriteDisabled = {
44268
44304
  isOpen: function (e) {
@@ -45955,6 +45991,32 @@
45955
45991
  }, revivingStore).finally(() => {
45956
45992
  });
45957
45993
  };
45994
+ const expirePossibleStaleRecords = async function (keys$1, config, refresh) {
45995
+ validateNotDisposed();
45996
+ const metadataKeys = keys$1.map(serializeStructuredKey);
45997
+ const now = Date.now();
45998
+ const entries = await durableStore.getMetadata(metadataKeys, DefaultDurableSegment);
45999
+ if (entries === undefined || keys$7(entries).length === 0) {
46000
+ return environment.expirePossibleStaleRecords(keys$1);
46001
+ }
46002
+ let metaDataChanged = false;
46003
+ const metadataEntries = metadataKeys.reduce((accu, key) => {
46004
+ const metadataEntry = entries[key];
46005
+ if (metadataEntry.metadata !== undefined) {
46006
+ const metadata = { ...metadataEntry.metadata, expirationTimestamp: now };
46007
+ accu[key] = { metadata };
46008
+ metaDataChanged = true;
46009
+ }
46010
+ return accu;
46011
+ }, {});
46012
+ if (metaDataChanged) {
46013
+ await durableStore.setMetadata(metadataEntries, DefaultDurableSegment);
46014
+ }
46015
+ if (config !== undefined && refresh !== undefined) {
46016
+ return environment.refreshPossibleStaleRecords(config, refresh);
46017
+ }
46018
+ return Promise.resolve();
46019
+ };
45958
46020
  // set the default cache policy of the base environment
45959
46021
  environment.setDefaultCachePolicy({
45960
46022
  type: 'stale-while-revalidate',
@@ -45987,6 +46049,7 @@
45987
46049
  handleErrorResponse: { value: handleErrorResponse },
45988
46050
  getNotifyChangeStoreEntries: { value: getNotifyChangeStoreEntries },
45989
46051
  notifyStoreUpdateAvailable: { value: notifyStoreUpdateAvailable },
46052
+ expirePossibleStaleRecords: { value: expirePossibleStaleRecords },
45990
46053
  });
45991
46054
  }
45992
46055
 
@@ -51605,6 +51668,7 @@
51605
51668
  Record,
51606
51669
  snapshot,
51607
51670
  seenRecordIds: new Set(),
51671
+ possibleStaleRecordMap: new Map(),
51608
51672
  draftFunctions,
51609
51673
  };
51610
51674
  }
@@ -52216,7 +52280,6 @@
52216
52280
 
52217
52281
  const JSON_EXTRACT_PATH_INGESTION_TIMESTAMP = '$.ingestionTimestamp';
52218
52282
  const JSON_EXTRACT_PATH_INGESTION_APINAME = '$.apiName';
52219
- const JSON_EXTRACT_PATH_DRAFTS = '$.drafts';
52220
52283
 
52221
52284
  const MultiPickListValueSeparator = ';';
52222
52285
  function filterToPredicates(where, recordType, alias, objectInfoMap, joins, draftFunctions) {
@@ -52746,18 +52809,11 @@
52746
52809
  const joins = buildJoins(config);
52747
52810
  const predicates = buildPredicates(config);
52748
52811
  const orderBy = buildOrderBy(config);
52749
- const staleRecordsSql = excludeStaleRecordsGate.isOpen({ fallback: false })
52750
- ? `AND (
52751
- json_extract("${config.alias}".metadata, '${JSON_EXTRACT_PATH_INGESTION_TIMESTAMP}') >= ?
52752
- OR json_extract("${config.alias}".data, '${JSON_EXTRACT_PATH_DRAFTS}') IS NOT NULL
52753
- )`
52754
- : '';
52755
52812
  const sql = `
52756
- SELECT "${config.alias}".data
52813
+ SELECT "${config.alias}".data, "${config.alias}".metadata
52757
52814
  FROM lds_data "${config.alias}" ${joins.sql}
52758
52815
  WHERE "${config.alias}".key like 'UiApi::RecordRepresentation:%'
52759
52816
  AND json_extract("${config.alias}".data, '${JSON_EXTRACT_PATH_INGESTION_APINAME}') = '${config.alias}'
52760
- ${staleRecordsSql}
52761
52817
  ${predicates.sql}
52762
52818
  ${orderBy.sql}
52763
52819
  LIMIT ?
@@ -52768,7 +52824,6 @@
52768
52824
  const bindings = [
52769
52825
  // bindings from predicates on joins
52770
52826
  ...joins.bindings,
52771
- ...(excludeStaleRecordsGate.isOpen({ fallback: false }) ? [config.ingestionTimestamp] : []),
52772
52827
  // where clause and parent scope bindings
52773
52828
  ...predicates.bindings,
52774
52829
  // limit binding
@@ -52794,33 +52849,19 @@
52794
52849
  if (allJoins.length === 0)
52795
52850
  return { sql, bindings };
52796
52851
  sql = allJoins.reduce((joinAccumulator, join) => {
52797
- let timestampAdded = false;
52798
52852
  const joinConditions = join.conditions.reduce((conditionAccumulator, condition) => {
52799
52853
  let joined_sql;
52800
- const joinMetadataTimestamp = excludeStaleRecordsGate.isOpen({ fallback: false })
52801
- ? ` AND (json_extract("${join.alias}".metadata, '${JSON_EXTRACT_PATH_INGESTION_TIMESTAMP}') >= ? OR json_extract("${join.alias}".data, '${JSON_EXTRACT_PATH_DRAFTS}') IS NOT NULL)`
52802
- : '';
52803
52854
  // predicate on a value, use the newly joined table
52804
52855
  if ('type' in condition) {
52805
52856
  const { sql, binding } = predicateToSQL(condition, join.alias);
52806
- joined_sql = ` AND ${sql}${timestampAdded ? '' : joinMetadataTimestamp}`;
52857
+ joined_sql = ` AND ${sql}`;
52807
52858
  bindings.push(...binding);
52808
- if (excludeStaleRecordsGate.isOpen({ fallback: false }) &&
52809
- timestampAdded === false) {
52810
- bindings.push(config.ingestionTimestamp);
52811
- timestampAdded = true;
52812
- }
52813
52859
  }
52814
52860
  else {
52815
52861
  // predicate on a path
52816
52862
  const left = ` AND json_extract("${join.to}".data, '${condition.leftPath}')`;
52817
52863
  const right = `json_extract("${join.alias}".data, '${condition.rightPath}')`;
52818
- joined_sql = `${left} = ${right}${timestampAdded ? '' : joinMetadataTimestamp}`;
52819
- if (excludeStaleRecordsGate.isOpen({ fallback: false }) &&
52820
- timestampAdded === false) {
52821
- bindings.push(config.ingestionTimestamp);
52822
- timestampAdded = true;
52823
- }
52864
+ joined_sql = `${left} = ${right}`;
52824
52865
  }
52825
52866
  conditionAccumulator += joined_sql;
52826
52867
  return conditionAccumulator;
@@ -53765,8 +53806,7 @@
53765
53806
  for (const field of fields) {
53766
53807
  if (field.name === 'node') {
53767
53808
  field.resolve = function nodeResolver(obj, _args, { seenRecordIds }) {
53768
- const { record, ingestionTimestamp } = obj;
53769
- const recordRepresentation = parse$4(record);
53809
+ const { recordRepresentation, ingestionTimestamp } = obj;
53770
53810
  seenRecordIds.add(recordRepresentation.id);
53771
53811
  return { recordRepresentation, ingestionTimestamp };
53772
53812
  };
@@ -53980,16 +54020,30 @@
53980
54020
  predicates,
53981
54021
  orderBy: orderByToPredicate(parentArgs.orderBy, alias, alias, context.objectInfos),
53982
54022
  limit: parentArgs.first,
53983
- ingestionTimestamp,
53984
54023
  };
53985
54024
  const { sql, bindings } = buildQuery(queryConfig);
53986
54025
  const results = await query(sql, bindings);
53987
54026
  //map each sql result with the ingestion timestamp to pass it down a level
53988
- return results.rows
53989
- .map((row) => row[0])
53990
- .map((record) => {
54027
+ return results.rows.map((row) => {
54028
+ const recordMetadataResult = {
54029
+ recordRepresentation: parse$4(row[0]),
54030
+ metadata: parse$4(row[1]),
54031
+ };
54032
+ const { recordRepresentation, metadata } = recordMetadataResult;
54033
+ context.seenRecordIds.add(recordRepresentation.id);
54034
+ if (metadata.ingestionTimestamp < ingestionTimestamp &&
54035
+ recordRepresentation.drafts === undefined) {
54036
+ if (context.possibleStaleRecordMap.has(recordRepresentation.apiName) === false) {
54037
+ context.possibleStaleRecordMap.set(recordRepresentation.apiName, []);
54038
+ }
54039
+ const ids = context.possibleStaleRecordMap.get(recordRepresentation.apiName);
54040
+ if (ids !== undefined) {
54041
+ ids.push(recordRepresentation.id);
54042
+ context.possibleStaleRecordMap.set(recordRepresentation.apiName, ids);
54043
+ }
54044
+ }
53991
54045
  return {
53992
- record,
54046
+ recordRepresentation,
53993
54047
  ingestionTimestamp,
53994
54048
  };
53995
54049
  });
@@ -54554,7 +54608,11 @@
54554
54608
  seenRecordIds.push(queryString);
54555
54609
  });
54556
54610
  }
54557
- return { result, seenRecordIds };
54611
+ return {
54612
+ result,
54613
+ seenRecordIds,
54614
+ possibleStaleRecordMap: contextValue.possibleStaleRecordMap,
54615
+ };
54558
54616
  }
54559
54617
  finally {
54560
54618
  eventEmitter({ type: 'graphql-eval-end' });
@@ -58188,6 +58246,60 @@
58188
58246
  response.errors.length > 0);
58189
58247
  }
58190
58248
 
58249
+ const MAX_ID_CHUNK_LENGTH = 100;
58250
+ /**
58251
+ * Adapter for limiting the number of record ids to a maximum of 100 and sending them
58252
+ * out in batches to the getRecords adapter
58253
+ *
58254
+ * @param luvio
58255
+ * @returns
58256
+ */
58257
+ function batchingGetRecordsAdapterFactory(luvio) {
58258
+ const getRecordsAdapter = getRecordsAdapterFactory(luvio);
58259
+ const batchGetRecords = (config, requestContext) => {
58260
+ const seenRecords = new StoreKeySet();
58261
+ const chunks = chunkConfig(config);
58262
+ const promises = chunks.map((conf) => {
58263
+ return getRecordsAdapter(conf, requestContext);
58264
+ });
58265
+ return Promise.all(promises).then((results) => {
58266
+ const data = results.reduce((accu, item) => {
58267
+ if (item !== null && item.data !== undefined) {
58268
+ accu.results = accu.results.concat(item.data.results);
58269
+ seenRecords.merge(item.seenRecords);
58270
+ }
58271
+ return accu;
58272
+ }, { results: [] });
58273
+ return {
58274
+ data: data,
58275
+ seenRecords,
58276
+ state: 'Fulfilled',
58277
+ };
58278
+ });
58279
+ };
58280
+ return batchGetRecords;
58281
+ }
58282
+ /**
58283
+ * Given a GetRecordsConfig it will chunk it into multiple configs with a maximum of 100
58284
+ * record ids per config.
58285
+ *
58286
+ * @param config
58287
+ * @returns
58288
+ */
58289
+ function chunkConfig(config) {
58290
+ const chunks = [];
58291
+ config.records.forEach((record) => {
58292
+ const { recordIds, fields } = record;
58293
+ for (let i = 0, len = recordIds.length; i < len; i += MAX_ID_CHUNK_LENGTH) {
58294
+ const chunk = recordIds.slice(i, i + MAX_ID_CHUNK_LENGTH);
58295
+ chunks.push({
58296
+ records: [{ recordIds: chunk, fields: fields !== undefined ? fields : [] }],
58297
+ });
58298
+ }
58299
+ });
58300
+ return chunks;
58301
+ }
58302
+
58191
58303
  function generateUniqueRecordId() {
58192
58304
  return `UiApi::GraphQLRepresentation:${Date.now() + Math.random().toFixed(5).split('.')[1]}`;
58193
58305
  }
@@ -58297,8 +58409,13 @@
58297
58409
  : [];
58298
58410
  let gqlResult;
58299
58411
  let seenRecordIds;
58412
+ let possibleStaleRecordMap;
58300
58413
  try {
58301
- ({ result: gqlResult, seenRecordIds } = await evaluate({
58414
+ ({
58415
+ result: gqlResult,
58416
+ seenRecordIds,
58417
+ possibleStaleRecordMap,
58418
+ } = await evaluate({
58302
58419
  ...config,
58303
58420
  //need to create another copy of the ast for future writes
58304
58421
  query: parse$3(stringify$3(injectedAST)),
@@ -58328,13 +58445,18 @@
58328
58445
  const seenRecords = createSeenRecords(seenRecordIds, nonEvaluatedSnapshot);
58329
58446
  const recordId = generateUniqueRecordId();
58330
58447
  const rebuildWithLocalEval = async (originalSnapshot) => {
58331
- let { result: rebuildResult, seenRecordIds } = await evaluate({
58448
+ let { result: rebuildResult, seenRecordIds, possibleStaleRecordMap, } = await evaluate({
58332
58449
  ...config,
58333
58450
  query: injectedAST,
58334
58451
  }, observers, { userId }, objectInfoNeeded, store, originalSnapshot, graphqlSchemaCache, draftFunctions);
58335
58452
  if (!rebuildResult.errors) {
58336
58453
  rebuildResult = removeSyntheticFields(rebuildResult, config.query);
58337
58454
  }
58455
+ let snapshotState = 'Fulfilled';
58456
+ if (possibleStaleRecordMap.size > 0) {
58457
+ initiateStaleRecordRefresh(luvio, possibleStaleRecordMap);
58458
+ snapshotState = 'Stale';
58459
+ }
58338
58460
  if (objectsDeepEqual(rebuildResult, originalSnapshot.data)) {
58339
58461
  return originalSnapshot;
58340
58462
  }
@@ -58343,6 +58465,7 @@
58343
58465
  ...originalSnapshot,
58344
58466
  data: rebuildResult,
58345
58467
  recordId,
58468
+ state: snapshotState,
58346
58469
  seenRecords: createSeenRecords(seenRecordIds, nonEvaluatedSnapshot),
58347
58470
  rebuildWithLocalEval,
58348
58471
  };
@@ -58380,6 +58503,10 @@
58380
58503
  },
58381
58504
  };
58382
58505
  }
58506
+ if (possibleStaleRecordMap.size > 0) {
58507
+ initiateStaleRecordRefresh(luvio, possibleStaleRecordMap);
58508
+ resultSnapshot.state = 'Stale';
58509
+ }
58383
58510
  return resultSnapshot;
58384
58511
  };
58385
58512
  }
@@ -58440,6 +58567,24 @@
58440
58567
  };
58441
58568
  };
58442
58569
  }
58570
+ function initiateStaleRecordRefresh(luvio, keyMap) {
58571
+ const staleRecordKeys = from$1(keyMap.values())
58572
+ .flat()
58573
+ .map((id) => `UiApi::RecordRepresentation:${id}`);
58574
+ luvio.storeExpirePossibleStaleRecords(staleRecordKeys, makeGetRecordsConfig(keyMap), batchingGetRecordsAdapterFactory(luvio));
58575
+ }
58576
+ function makeGetRecordsConfig(keyMap) {
58577
+ const records = [];
58578
+ keyMap.forEach((recordIds, apiName) => {
58579
+ records.push({
58580
+ recordIds,
58581
+ fields: [`${apiName}.Id`],
58582
+ });
58583
+ });
58584
+ return {
58585
+ records,
58586
+ };
58587
+ }
58443
58588
 
58444
58589
  const CONTENT_DOCUMENT_DRAFT_ID_KEY = 'CONTENT_DOCUMENT_DRAFT_ID';
58445
58590
  const CONTENT_VERSION_DRAFT_ID_KEY = 'CONTENT_VERSION_DRAFT_ID';
@@ -62601,7 +62746,7 @@
62601
62746
  id: '@salesforce/lds-network-adapter',
62602
62747
  instrument: instrument$2,
62603
62748
  });
62604
- // version: 1.287.0-dev15-a292df40d2
62749
+ // version: 1.287.0-dev17-670374cbf3
62605
62750
 
62606
62751
  const { create: create$3, keys: keys$3 } = Object;
62607
62752
  const { stringify: stringify$1, parse: parse$1 } = JSON;
@@ -82665,7 +82810,7 @@
82665
82810
  configuration: { ...configurationForGraphQLAdapters$1 },
82666
82811
  instrument: instrument$1,
82667
82812
  });
82668
- // version: 1.287.0-dev15-4b3ad0d7fe
82813
+ // version: 1.287.0-dev17-71a1131fd3
82669
82814
 
82670
82815
  // On core the unstable adapters are re-exported with different names,
82671
82816
  // we want to match them here.
@@ -84921,7 +85066,7 @@
84921
85066
  unstable_graphQL_imperative = createImperativeAdapter(luvio, createInstrumentedAdapter(ldsAdapter, adapterMetadata), adapterMetadata);
84922
85067
  graphQLImperative = ldsAdapter;
84923
85068
  });
84924
- // version: 1.287.0-dev15-4b3ad0d7fe
85069
+ // version: 1.287.0-dev17-71a1131fd3
84925
85070
 
84926
85071
  var gqlApi = /*#__PURE__*/Object.freeze({
84927
85072
  __proto__: null,
@@ -85659,7 +85804,7 @@
85659
85804
  function register(r) {
85660
85805
  callbacks$1.forEach((callback) => callback(r));
85661
85806
  }
85662
- // version: 1.287.0-dev15-a292df40d2
85807
+ // version: 1.287.0-dev17-670374cbf3
85663
85808
 
85664
85809
  /**
85665
85810
  * Returns true if the value acts like a Promise, i.e. has a "then" function,
@@ -90640,4 +90785,4 @@
90640
90785
  exports.subscribeToAdapter = subscribeToAdapter;
90641
90786
 
90642
90787
  }));
90643
- // version: 1.287.0-dev15-a292df40d2
90788
+ // version: 1.287.0-dev17-670374cbf3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/lds-worker-api",
3
- "version": "1.287.0-dev15",
3
+ "version": "1.287.0-dev17",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "description": "",
6
6
  "main": "dist/standalone/es/lds-worker-api.js",
@@ -35,15 +35,15 @@
35
35
  },
36
36
  "devDependencies": {
37
37
  "@oat-sa/rollup-plugin-wildcard-external": "^1.0.0",
38
- "@salesforce/lds-adapters-graphql": "^1.287.0-dev15",
39
- "@salesforce/lds-adapters-uiapi": "^1.287.0-dev15",
40
- "@salesforce/lds-default-luvio": "^1.287.0-dev15",
41
- "@salesforce/lds-drafts": "^1.287.0-dev15",
42
- "@salesforce/lds-graphql-parser": "^1.287.0-dev15",
43
- "@salesforce/lds-luvio-engine": "^1.287.0-dev15",
44
- "@salesforce/lds-priming": "^1.287.0-dev15",
45
- "@salesforce/lds-runtime-mobile": "^1.287.0-dev15",
46
- "@salesforce/nimbus-plugin-lds": "^1.287.0-dev15",
38
+ "@salesforce/lds-adapters-graphql": "^1.287.0-dev17",
39
+ "@salesforce/lds-adapters-uiapi": "^1.287.0-dev17",
40
+ "@salesforce/lds-default-luvio": "^1.287.0-dev17",
41
+ "@salesforce/lds-drafts": "^1.287.0-dev17",
42
+ "@salesforce/lds-graphql-parser": "^1.287.0-dev17",
43
+ "@salesforce/lds-luvio-engine": "^1.287.0-dev17",
44
+ "@salesforce/lds-priming": "^1.287.0-dev17",
45
+ "@salesforce/lds-runtime-mobile": "^1.287.0-dev17",
46
+ "@salesforce/nimbus-plugin-lds": "^1.287.0-dev17",
47
47
  "ajv": "^8.11.0",
48
48
  "glob": "^7.1.5",
49
49
  "nimbus-types": "^2.0.0-alpha1",