@salesforce/lds-runtime-mobile 1.296.0 → 1.297.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.
Files changed (3) hide show
  1. package/dist/main.js +589 -579
  2. package/package.json +18 -17
  3. package/sfdc/main.js +589 -579
package/dist/main.js CHANGED
@@ -20,9 +20,10 @@ import { setupInstrumentation, instrumentAdapter as instrumentAdapter$1, instrum
20
20
  import { HttpStatusCode, setBypassDeepFreeze, StoreKeySet, serializeStructuredKey, StringKeyInMemoryStore, Reader, deepFreeze, emitAdapterEvent, createCustomAdapterEventEmitter, StoreKeyMap, isFileReference, Environment, Luvio, InMemoryStore } from '@luvio/engine';
21
21
  import excludeStaleRecordsGate from '@salesforce/gate/lds.graphqlEvalExcludeStaleRecords';
22
22
  import { parseAndVisit, Kind, buildSchema, isObjectType, defaultFieldResolver, visit, execute, parse as parse$7, extendSchema, isScalarType } from '@luvio/graphql-parser';
23
- import { RECORD_ID_PREFIX, RECORD_FIELDS_KEY_JUNCTION, isStoreKeyRecordViewEntity, RECORD_REPRESENTATION_NAME, extractRecordIdFromStoreKey, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, keyBuilderContentDocumentCompositeRepresentation, getResponseCacheKeysContentDocumentCompositeRepresentation, keyBuilderFromTypeContentDocumentCompositeRepresentation, ingestContentDocumentCompositeRepresentation, keyBuilderRecord, RECORD_VIEW_ENTITY_ID_PREFIX, getTypeCacheKeysRecord, keyBuilderFromTypeRecordRepresentation, ingestRecord, getRecordId18, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getRecordAdapterFactory, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, getObjectInfoDirectoryAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationTTL, RecordRepresentationVersion, getRecordsAdapterFactory } from '@salesforce/lds-adapters-uiapi-mobile';
23
+ import { RECORD_ID_PREFIX, RECORD_FIELDS_KEY_JUNCTION, RECORD_REPRESENTATION_NAME, extractRecordIdFromStoreKey, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, keyBuilderContentDocumentCompositeRepresentation, getResponseCacheKeysContentDocumentCompositeRepresentation, keyBuilderFromTypeContentDocumentCompositeRepresentation, ingestContentDocumentCompositeRepresentation, keyBuilderRecord, getTypeCacheKeysRecord, keyBuilderFromTypeRecordRepresentation, ingestRecord, getRecordId18, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getRecordAdapterFactory, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, getObjectInfoDirectoryAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationTTL, RecordRepresentationVersion, getRecordsAdapterFactory } from '@salesforce/lds-adapters-uiapi-mobile';
24
24
  import ldsIdempotencyWriteDisabled from '@salesforce/gate/lds.idempotencyWriteDisabled';
25
25
  import ldsBackdatingEnabled from '@salesforce/gate/lds.backdatingEnabled';
26
+ import { extractRecordIdFromStoreKey as extractRecordIdFromStoreKey$1, RECORD_VIEW_ENTITY_ID_PREFIX, isStoreKeyRecordViewEntity, keyBuilderRecord as keyBuilderRecord$1, RECORD_ID_PREFIX as RECORD_ID_PREFIX$1, RECORD_FIELDS_KEY_JUNCTION as RECORD_FIELDS_KEY_JUNCTION$1 } from '@salesforce/lds-adapters-uiapi';
26
27
  import FIRST_DAY_OF_WEEK from '@salesforce/i18n/firstDayOfWeek';
27
28
  import caseSensitiveUserId from '@salesforce/user/Id';
28
29
  import { idleDetector, getInstrumentation } from 'o11y/client';
@@ -53,7 +54,7 @@ import graphqlL2AdapterGate from '@salesforce/gate/lmr.graphqlL2Adapter';
53
54
  const { parse: parse$6, stringify: stringify$6 } = JSON;
54
55
  const { join: join$2, push: push$2, unshift } = Array.prototype;
55
56
  const { isArray: isArray$5 } = Array;
56
- const { entries: entries$5, keys: keys$8 } = Object;
57
+ const { entries: entries$6, keys: keys$9 } = Object;
57
58
 
58
59
  const UI_API_BASE_URI = '/services/data/v62.0/ui-api';
59
60
 
@@ -118,7 +119,7 @@ function isSpanningRecord$1(fieldValue) {
118
119
  function mergeRecordFields$1(first, second) {
119
120
  const { fields: targetFields } = first;
120
121
  const { fields: sourceFields } = second;
121
- const fieldNames = keys$8(sourceFields);
122
+ const fieldNames = keys$9(sourceFields);
122
123
  for (let i = 0, len = fieldNames.length; i < len; i += 1) {
123
124
  const fieldName = fieldNames[i];
124
125
  const sourceField = sourceFields[fieldName];
@@ -365,7 +366,7 @@ function getFulfillingRequest(inflightRequests, resourceRequest) {
365
366
  if (fulfill === undefined) {
366
367
  return null;
367
368
  }
368
- const handlersMap = entries$5(inflightRequests);
369
+ const handlersMap = entries$6(inflightRequests);
369
370
  for (let i = 0, len = handlersMap.length; i < len; i += 1) {
370
371
  const [transactionKey, handlers] = handlersMap[i];
371
372
  // check fulfillment against only the first handler ([0]) because it's equal or
@@ -535,7 +536,7 @@ const RedirectDurableSegment = 'REDIRECT_KEYS';
535
536
  const MessagingDurableSegment = 'MESSAGING';
536
537
  const MessageNotifyStoreUpdateAvailable = 'notifyStoreUpdateAvailable';
537
538
 
538
- const { keys: keys$7, create: create$6, assign: assign$6, freeze: freeze$1 } = Object;
539
+ const { keys: keys$8, create: create$7, assign: assign$7, freeze: freeze$2 } = Object;
539
540
 
540
541
  //Durable store error instrumentation key
541
542
  const DURABLE_STORE_ERROR = 'durable-store-error';
@@ -585,7 +586,7 @@ function publishDurableStoreEntries(durableRecords, put, publishMetadata) {
585
586
  if (durableRecords === undefined) {
586
587
  return { revivedKeys, hadUnexpectedShape };
587
588
  }
588
- const durableKeys = keys$7(durableRecords);
589
+ const durableKeys = keys$8(durableRecords);
589
590
  if (durableKeys.length === 0) {
590
591
  // no records to revive
591
592
  return { revivedKeys, hadUnexpectedShape };
@@ -770,7 +771,7 @@ class DurableTTLStore {
770
771
  overrides,
771
772
  };
772
773
  }
773
- const keys$1 = keys$7(entries);
774
+ const keys$1 = keys$8(entries);
774
775
  for (let i = 0, len = keys$1.length; i < len; i++) {
775
776
  const key = keys$1[i];
776
777
  const entry = entries[key];
@@ -792,14 +793,14 @@ class DurableTTLStore {
792
793
  }
793
794
 
794
795
  function flushInMemoryStoreValuesToDurableStore(store, durableStore, durableStoreErrorHandler, redirects, additionalDurableStoreOperations = [], enableDurableMetadataRefresh = false) {
795
- const durableRecords = create$6(null);
796
- const refreshedDurableRecords = create$6(null);
797
- const evictedRecords = create$6(null);
796
+ const durableRecords = create$7(null);
797
+ const refreshedDurableRecords = create$7(null);
798
+ const evictedRecords = create$7(null);
798
799
  const { visitedIds, refreshedIds } = store.fallbackStringKeyInMemoryStore;
799
800
  // TODO: W-8909393 Once metadata is stored in its own segment we need to
800
801
  // call setEntries for the visitedIds on default segment and call setEntries
801
802
  // on the metadata segment for the refreshedIds
802
- const keys$1 = keys$7({ ...visitedIds, ...refreshedIds });
803
+ const keys$1 = keys$8({ ...visitedIds, ...refreshedIds });
803
804
  for (let i = 0, len = keys$1.length; i < len; i += 1) {
804
805
  const key = keys$1[i];
805
806
  const canonicalKey = store.getCanonicalRecordId(key);
@@ -822,7 +823,7 @@ function flushInMemoryStoreValuesToDurableStore(store, durableStore, durableStor
822
823
  setRecordTo(entries, key, record, metadata);
823
824
  }
824
825
  const durableStoreOperations = additionalDurableStoreOperations;
825
- const recordKeys = keys$7(durableRecords);
826
+ const recordKeys = keys$8(durableRecords);
826
827
  if (recordKeys.length > 0) {
827
828
  // publishes with data
828
829
  durableStoreOperations.push({
@@ -831,7 +832,7 @@ function flushInMemoryStoreValuesToDurableStore(store, durableStore, durableStor
831
832
  segment: DefaultDurableSegment,
832
833
  });
833
834
  }
834
- const refreshKeys = keys$7(refreshedDurableRecords);
835
+ const refreshKeys = keys$8(refreshedDurableRecords);
835
836
  if (refreshKeys.length > 0) {
836
837
  // publishes with only metadata updates
837
838
  durableStoreOperations.push({
@@ -853,7 +854,7 @@ function flushInMemoryStoreValuesToDurableStore(store, durableStore, durableStor
853
854
  });
854
855
  });
855
856
  // evicts
856
- const evictedKeys = keys$7(evictedRecords);
857
+ const evictedKeys = keys$8(evictedRecords);
857
858
  if (evictedKeys.length > 0) {
858
859
  durableStoreOperations.push({
859
860
  type: 'evictEntries',
@@ -957,7 +958,7 @@ function buildRevivingStagingStore(upstreamStore) {
957
958
  // A reviving store is only "active" during a call to `environment.storeLookup`, and will
958
959
  // be used by the reader attempting to build an L1 snapshot. Immediately after the L1 rebuild
959
960
  // the reviving store becomes inactive other than receiving change notifications.
960
- return create$6(upstreamStore, {
961
+ return create$7(upstreamStore, {
961
962
  readEntry: { value: readEntry },
962
963
  markStale: { value: markStale },
963
964
  clearStale: { value: clearStale },
@@ -969,7 +970,7 @@ const AdapterContextSegment = 'ADAPTER-CONTEXT';
969
970
  const ADAPTER_CONTEXT_ID_SUFFIX = '__NAMED_CONTEXT';
970
971
  async function reviveOrCreateContext(adapterId, durableStore, durableStoreErrorHandler, contextStores, pendingContextStoreKeys, onContextLoaded) {
971
972
  // initialize empty context store
972
- contextStores[adapterId] = create$6(null);
973
+ contextStores[adapterId] = create$7(null);
973
974
  const context = {
974
975
  set(key, value) {
975
976
  contextStores[adapterId][key] = value;
@@ -1034,7 +1035,7 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
1034
1035
  const revivingStores = new Set();
1035
1036
  // redirects that need to be flushed to the durable store
1036
1037
  const pendingStoreRedirects = new Map();
1037
- const contextStores = create$6(null);
1038
+ const contextStores = create$7(null);
1038
1039
  let initializationPromise = new Promise((resolve) => {
1039
1040
  const finish = () => {
1040
1041
  resolve();
@@ -1111,7 +1112,7 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
1111
1112
  try {
1112
1113
  const entries = await durableStore.getEntries(adapterContextKeysFromDifferentInstance, AdapterContextSegment);
1113
1114
  if (entries !== undefined) {
1114
- const entryKeys = keys$7(entries);
1115
+ const entryKeys = keys$8(entries);
1115
1116
  for (let i = 0, len = entryKeys.length; i < len; i++) {
1116
1117
  const entryKey = entryKeys[i];
1117
1118
  const entry = entries[entryKey];
@@ -1146,7 +1147,7 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
1146
1147
  if (filteredKeys.length > 0) {
1147
1148
  const entries = await durableStore.getMetadata(filteredKeys, DefaultDurableSegment);
1148
1149
  if (entries !== undefined) {
1149
- const entryKeys = keys$7(entries);
1150
+ const entryKeys = keys$8(entries);
1150
1151
  for (let i = 0, len = entryKeys.length; i < len; i++) {
1151
1152
  const entryKey = entryKeys[i];
1152
1153
  const { metadata } = entries[entryKey];
@@ -1518,7 +1519,7 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
1518
1519
  validateNotDisposed();
1519
1520
  const entryKeys = keys$1.map(serializeStructuredKey);
1520
1521
  const entries = await durableStore.getEntries(entryKeys, DefaultDurableSegment);
1521
- if (entries === undefined || keys$7(entries).length === 0) {
1522
+ if (entries === undefined || keys$8(entries).length === 0) {
1522
1523
  return environment.notifyStoreUpdateAvailable(keys$1);
1523
1524
  }
1524
1525
  const now = Date.now();
@@ -1570,7 +1571,7 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
1570
1571
  type: 'stale-while-revalidate',
1571
1572
  staleDurationSeconds: Number.MAX_SAFE_INTEGER,
1572
1573
  });
1573
- return create$6(environment, {
1574
+ return create$7(environment, {
1574
1575
  publishStoreMetadata: { value: publishStoreMetadata },
1575
1576
  storeIngest: { value: storeIngest },
1576
1577
  storeIngestError: { value: storeIngestError },
@@ -1606,14 +1607,10 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
1606
1607
  * For full license text, see the LICENSE.txt file
1607
1608
  */
1608
1609
 
1609
-
1610
- function isStoreKeyRecordId(key) {
1611
- return key.indexOf(RECORD_ID_PREFIX) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION) === -1;
1612
- }
1613
1610
  function isStoreKeyRecordField(key) {
1614
1611
  return key.indexOf(RECORD_ID_PREFIX) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION) > -1;
1615
1612
  }
1616
- function buildRecordFieldStoreKey(recordKey, fieldName) {
1613
+ function buildRecordFieldStoreKey$1(recordKey, fieldName) {
1617
1614
  return `${recordKey}${RECORD_FIELDS_KEY_JUNCTION}${fieldName}`;
1618
1615
  }
1619
1616
  function objectsDeepEqual(lhs, rhs) {
@@ -1640,15 +1637,6 @@ function objectsDeepEqual(lhs, rhs) {
1640
1637
  return true;
1641
1638
  }
1642
1639
 
1643
- function isStoreRecordError(storeRecord) {
1644
- return storeRecord.__type === 'error';
1645
- }
1646
- function isEntryDurableRecordRepresentation(entry, key) {
1647
- // Either a DurableRecordRepresentation or StoreRecordError can live at a record key
1648
- return ((isStoreKeyRecordId(key) || isStoreKeyRecordViewEntity(key)) &&
1649
- entry.data.__type === undefined);
1650
- }
1651
-
1652
1640
  /**
1653
1641
  * Copyright (c) 2022, Salesforce, Inc.,
1654
1642
  * All rights reserved.
@@ -2034,7 +2022,7 @@ function isFailure(result) {
2034
2022
  function errors(result) {
2035
2023
  return result.error;
2036
2024
  }
2037
- function values$4(result) {
2025
+ function values$5(result) {
2038
2026
  return result.value;
2039
2027
  }
2040
2028
  function flattenResults(results) {
@@ -2042,7 +2030,7 @@ function flattenResults(results) {
2042
2030
  if (fails.length > 0) {
2043
2031
  return failure(fails);
2044
2032
  }
2045
- return success(results.filter(isSuccess).map(values$4));
2033
+ return success(results.filter(isSuccess).map(values$5));
2046
2034
  }
2047
2035
 
2048
2036
  function getFieldInfo(apiName, fieldName, infoMap) {
@@ -2861,7 +2849,7 @@ function compoundOperatorToSql(operator) {
2861
2849
  }
2862
2850
 
2863
2851
  const { isArray: isArray$4 } = Array;
2864
- const { keys: keys$6 } = Object;
2852
+ const { keys: keys$7 } = Object;
2865
2853
 
2866
2854
  function isListValueNode(node) {
2867
2855
  return node.kind === 'ListValue';
@@ -2929,7 +2917,7 @@ function fieldsToFilters(fieldValues, joinAlias, apiName, input, compoundOperato
2929
2917
  if (failures.length > 0) {
2930
2918
  return failure(failures);
2931
2919
  }
2932
- const containers = results.filter(isSuccess).map(values$4);
2920
+ const containers = results.filter(isSuccess).map(values$5);
2933
2921
  const predicates = [];
2934
2922
  containers.forEach((c) => {
2935
2923
  if (c.predicate !== undefined) {
@@ -3221,7 +3209,7 @@ function dateFunctions(operatorNode, extract, dataType) {
3221
3209
  if (fails.length > 0) {
3222
3210
  return failure(fails);
3223
3211
  }
3224
- const vals = results.filter(isSuccess).reduce(flatMap(values$4), []);
3212
+ const vals = results.filter(isSuccess).reduce(flatMap(values$5), []);
3225
3213
  return success(vals);
3226
3214
  }
3227
3215
  function isFilterFunction(name) {
@@ -3231,7 +3219,7 @@ function fieldOperators(operatorNode, dataType) {
3231
3219
  const results = Object.entries(operatorNode.fields)
3232
3220
  .filter(([key, _]) => isFilterFunction(key) === false)
3233
3221
  .map(([key, value]) => operatorWithValue(key, value, dataType));
3234
- const _values = results.filter(isSuccess).map(values$4);
3222
+ const _values = results.filter(isSuccess).map(values$5);
3235
3223
  const fails = results.filter(isFailure).reduce(flatMap(errors), []);
3236
3224
  if (fails.length > 0) {
3237
3225
  return failure(fails);
@@ -4152,7 +4140,7 @@ function selectionToQueryField(node, names, parentApiName, parentAlias, input, j
4152
4140
  }
4153
4141
  function recordFields(luvioSelections, names, parentApiName, parentAlias, input, joins) {
4154
4142
  const results = luvioSelections.map((selection) => selectionToQueryField(selection, names, parentApiName, parentAlias, input, joins));
4155
- const fields = results.filter(isSuccess).reduce(flatMap(values$4), []);
4143
+ const fields = results.filter(isSuccess).reduce(flatMap(values$5), []);
4156
4144
  const fails = results.filter(isFailure).reduce(flatMap(errors), []);
4157
4145
  if (fails.length > 0) {
4158
4146
  return failure(fails);
@@ -4400,7 +4388,7 @@ function rootRecordQuery(selection, input) {
4400
4388
  }
4401
4389
  function rootQuery(recordNodes, input) {
4402
4390
  const results = recordNodes.map((record) => rootRecordQuery(record, input));
4403
- const connections = results.filter(isSuccess).map(values$4);
4391
+ const connections = results.filter(isSuccess).map(values$5);
4404
4392
  const fails = results.filter(isFailure).reduce(flatMap(errors), []);
4405
4393
  if (fails.length > 0) {
4406
4394
  return failure(fails);
@@ -4496,7 +4484,7 @@ function generateVariableSubQuery(valueNode, name, type, variables) {
4496
4484
  switch (valueNode.kind) {
4497
4485
  case Kind.OBJECT: {
4498
4486
  // For example, `{ Id: { eq: $draftId } }` is a `ObjectValueNode`, which has field keys 'Id'
4499
- const resultQuery = keys$6(valueNode.fields)
4487
+ const resultQuery = keys$7(valueNode.fields)
4500
4488
  .map((key) => generateVariableSubQuery(valueNode.fields[key], key, type, variables))
4501
4489
  .filter((subquery) => subquery.length > 0)
4502
4490
  .join(',');
@@ -4572,7 +4560,7 @@ function swapArgumentWithVariableNodes(swapped, original) {
4572
4560
  }
4573
4561
  function swapValueNodeWithVariableNodes(original, swapped) {
4574
4562
  if (original.kind === Kind.OBJECT) {
4575
- for (const key of keys$6(original.fields)) {
4563
+ for (const key of keys$7(original.fields)) {
4576
4564
  if (isObjectValueNode$1(swapped) && swapped.fields[key]) {
4577
4565
  if (is(original.fields[key], 'Variable')) {
4578
4566
  original.fields[key] = swapped.fields[key];
@@ -5181,7 +5169,7 @@ function createDraftSynthesisErrorResponse(message = 'failed to synthesize draft
5181
5169
  return new DraftErrorFetchResponse(HttpStatusCode.BadRequest, error);
5182
5170
  }
5183
5171
 
5184
- const { keys: keys$5, create: create$5, assign: assign$5, values: values$3 } = Object;
5172
+ const { keys: keys$6, create: create$6, assign: assign$6, values: values$4 } = Object;
5185
5173
  const { stringify: stringify$5, parse: parse$5 } = JSON;
5186
5174
  const { isArray: isArray$3 } = Array;
5187
5175
 
@@ -5291,13 +5279,13 @@ function buildLuvioOverrideForDraftAdapters(luvio, handler, extractTargetIdFromC
5291
5279
  }
5292
5280
  softEvict(key);
5293
5281
  };
5294
- return create$5(luvio, {
5282
+ return create$6(luvio, {
5295
5283
  dispatchResourceRequest: { value: dispatchResourceRequest },
5296
5284
  publishStoreMetadata: { value: publishStoreMetadata },
5297
5285
  storeEvict: { value: storeEvict },
5298
5286
  });
5299
5287
  }
5300
- return create$5(luvio, {
5288
+ return create$6(luvio, {
5301
5289
  dispatchResourceRequest: { value: dispatchResourceRequest },
5302
5290
  publishStoreMetadata: { value: publishStoreMetadata },
5303
5291
  });
@@ -5331,7 +5319,7 @@ async function getDraftIdMappings(durableStore, mappingIds) {
5331
5319
  if (entries === undefined) {
5332
5320
  return mappings;
5333
5321
  }
5334
- const keys$1 = keys$5(entries);
5322
+ const keys$1 = keys$6(entries);
5335
5323
  for (const key of keys$1) {
5336
5324
  const entry = entries[key].data;
5337
5325
  if (isLegacyDraftIdMapping(key)) {
@@ -5349,7 +5337,7 @@ async function getDraftIdMappings(durableStore, mappingIds) {
5349
5337
  async function clearDraftIdSegment(durableStore) {
5350
5338
  const entries = await durableStore.getAllEntries(DRAFT_ID_MAPPINGS_SEGMENT);
5351
5339
  if (entries) {
5352
- const keys$1 = keys$5(entries);
5340
+ const keys$1 = keys$6(entries);
5353
5341
  if (keys$1.length > 0) {
5354
5342
  await durableStore.evictEntries(keys$1, DRAFT_ID_MAPPINGS_SEGMENT);
5355
5343
  }
@@ -5608,7 +5596,7 @@ class DurableDraftQueue {
5608
5596
  const queueOperations = handler.getQueueOperationsForCompletingDrafts(queue, action);
5609
5597
  // write the queue operations to the store prior to ingesting the result
5610
5598
  await this.draftStore.completeAction(queueOperations);
5611
- await handler.handleActionCompleted(action, queueOperations, values$3(this.handlers));
5599
+ await handler.handleActionCompleted(action, queueOperations, values$4(this.handlers));
5612
5600
  this.retryIntervalMilliseconds = 0;
5613
5601
  this.uploadingActionId = undefined;
5614
5602
  await this.notifyChangedListeners({
@@ -5760,7 +5748,7 @@ class DurableDraftQueue {
5760
5748
  return this.replaceOrMergeActions(targetActionId, sourceActionId, true);
5761
5749
  }
5762
5750
  async setMetadata(actionId, metadata) {
5763
- const keys$1 = keys$5(metadata);
5751
+ const keys$1 = keys$6(metadata);
5764
5752
  const compatibleKeys = keys$1.filter((key) => {
5765
5753
  const value = metadata[key];
5766
5754
  return typeof key === 'string' && typeof value === 'string';
@@ -5915,7 +5903,7 @@ class DurableDraftStore {
5915
5903
  const waitForOngoingSync = this.syncPromise || Promise.resolve();
5916
5904
  return waitForOngoingSync.then(() => {
5917
5905
  const { draftStore } = this;
5918
- const keys$1 = keys$5(draftStore);
5906
+ const keys$1 = keys$6(draftStore);
5919
5907
  const actionArray = [];
5920
5908
  for (let i = 0, len = keys$1.length; i < len; i++) {
5921
5909
  const key = keys$1[i];
@@ -5939,7 +5927,7 @@ class DurableDraftStore {
5939
5927
  deleteByTag(tag) {
5940
5928
  const deleteAction = () => {
5941
5929
  const { draftStore } = this;
5942
- const keys$1 = keys$5(draftStore);
5930
+ const keys$1 = keys$6(draftStore);
5943
5931
  const durableKeys = [];
5944
5932
  for (let i = 0, len = keys$1.length; i < len; i++) {
5945
5933
  const key = keys$1[i];
@@ -6029,7 +6017,7 @@ class DurableDraftStore {
6029
6017
  return this.runQueuedOperations();
6030
6018
  }
6031
6019
  const { draftStore } = this;
6032
- const keys$1 = keys$5(durableEntries);
6020
+ const keys$1 = keys$6(durableEntries);
6033
6021
  for (let i = 0, len = keys$1.length; i < len; i++) {
6034
6022
  const entry = durableEntries[keys$1[i]];
6035
6023
  const action = entry.data;
@@ -6917,7 +6905,7 @@ function makeEnvironmentDraftAware(luvio, env, durableStore, handlers, draftQueu
6917
6905
  decrementRefCount(key);
6918
6906
  };
6919
6907
  // note the makeEnvironmentUiApiRecordDraftAware will eventually go away once the adapters become draft aware
6920
- return create$5(env, {
6908
+ return create$6(env, {
6921
6909
  storePublish: { value: storePublish },
6922
6910
  handleSuccessResponse: { value: handleSuccessResponse },
6923
6911
  softEvict: { value: softEvict },
@@ -6931,7 +6919,7 @@ function makeEnvironmentDraftAware(luvio, env, durableStore, handlers, draftQueu
6931
6919
  */
6932
6920
 
6933
6921
 
6934
- const { keys: keys$4, values: values$2, create: create$4, assign: assign$4, freeze, entries: entries$4 } = Object;
6922
+ const { keys: keys$5, values: values$3, create: create$5, assign: assign$5, freeze: freeze$1, entries: entries$5 } = Object;
6935
6923
  const { stringify: stringify$4, parse: parse$4 } = JSON;
6936
6924
  const { shift } = Array.prototype;
6937
6925
  const { isArray: isArray$2, from: from$2 } = Array;
@@ -6998,7 +6986,7 @@ function getRecordKeyForId(luvio, recordId) {
6998
6986
  */
6999
6987
  function filterOutReferenceFieldsAndLinks(record) {
7000
6988
  const filteredFields = {};
7001
- const fieldNames = keys$4(record.fields);
6989
+ const fieldNames = keys$5(record.fields);
7002
6990
  for (const fieldName of fieldNames) {
7003
6991
  const field = record.fields[fieldName];
7004
6992
  if (isFieldLink(field) === false) {
@@ -7099,7 +7087,7 @@ function getRecordDraftEnvironment(luvio, env, { isDraftId, durableStore }) {
7099
7087
  const resolvedRequest = resolveResourceRequestIds(luvio, resourceRequest, canonicalKey);
7100
7088
  return env.dispatchResourceRequest(resolvedRequest, context, eventObservers);
7101
7089
  };
7102
- return create$4(env, {
7090
+ return create$5(env, {
7103
7091
  dispatchResourceRequest: { value: dispatchResourceRequest },
7104
7092
  });
7105
7093
  }
@@ -7277,7 +7265,7 @@ function getRecordsDraftEnvironment(luvio, env, { isDraftId }) {
7277
7265
  return applyDraftsToBatchResponse(resourceRequest, response, removedDraftIds);
7278
7266
  }));
7279
7267
  };
7280
- return create$4(env, {
7268
+ return create$5(env, {
7281
7269
  dispatchResourceRequest: { value: dispatchResourceRequest },
7282
7270
  });
7283
7271
  }
@@ -7287,7 +7275,7 @@ function makeEnvironmentUiApiRecordDraftAware(luvio, options, env) {
7287
7275
  const adapterSpecificEnvironments = synthesizers.reduce((environment, synthesizer) => {
7288
7276
  return synthesizer(luvio, environment, options);
7289
7277
  }, env);
7290
- return create$4(adapterSpecificEnvironments, {});
7278
+ return create$5(adapterSpecificEnvironments, {});
7291
7279
  }
7292
7280
 
7293
7281
  function clone(obj) {
@@ -7381,7 +7369,7 @@ function compoundNameFieldFromDraftUpdates(record, draftFields, apiName, objectI
7381
7369
  changedNameFields[fieldName] = fieldValue;
7382
7370
  }
7383
7371
  }
7384
- if (keys$4(changedNameFields).length > 0) {
7372
+ if (keys$5(changedNameFields).length > 0) {
7385
7373
  const newNameValue = filteredNameFields
7386
7374
  .map((key) => {
7387
7375
  if (changedNameFields[key] !== undefined) {
@@ -7464,7 +7452,7 @@ function recursivelyApplyDraftsToRecord(record, draftMetadata, recordOperations)
7464
7452
  const injectedCompoundNameField = compoundNameFieldFromDraftUpdates(record, draftOperationFields, apiName, objectInfos);
7465
7453
  // inject the compound Name field into the DraftOperation so on broadcast it doesnt try to
7466
7454
  // synthesize the Name field a second time when the durable store change notifier is triggered
7467
- if (keys$4(injectedCompoundNameField).length > 0 && draftActionType === 'update') {
7455
+ if (keys$5(injectedCompoundNameField).length > 0 && draftActionType === 'update') {
7468
7456
  draftOperation.fields['Name'] = injectedCompoundNameField['Name'];
7469
7457
  }
7470
7458
  const fields = { ...draftOperationFields, ...injectedCompoundNameField };
@@ -7475,7 +7463,7 @@ function recursivelyApplyDraftsToRecord(record, draftMetadata, recordOperations)
7475
7463
  LastModifiedDate: lastModifiedDate,
7476
7464
  };
7477
7465
  const draftFields = buildRecordFieldValueRepresentationsFromDraftFields(luvio, apiName, internalFields, objectInfos, referencedRecords, formatDisplayValue);
7478
- const fieldNames = keys$4(draftFields);
7466
+ const fieldNames = keys$5(draftFields);
7479
7467
  for (let i = 0, len = fieldNames.length; i < len; i++) {
7480
7468
  const fieldName = fieldNames[i];
7481
7469
  // don't apply server values to draft created records
@@ -7536,7 +7524,7 @@ function removeDrafts(record, luvio, objectInfo) {
7536
7524
  return undefined;
7537
7525
  }
7538
7526
  const updatedFields = {};
7539
- const fieldNames = keys$4(fields);
7527
+ const fieldNames = keys$5(fields);
7540
7528
  for (let i = 0, len = fieldNames.length; i < len; i++) {
7541
7529
  const fieldName = fieldNames[i];
7542
7530
  const field = fields[fieldName];
@@ -7583,7 +7571,7 @@ function removeDrafts(record, luvio, objectInfo) {
7583
7571
  * @param fields List of draft record fields
7584
7572
  */
7585
7573
  function buildRecordFieldValueRepresentationsFromDraftFields(luvio, apiName, fields, objectInfos, referencedRecords, formatDisplayValue) {
7586
- const fieldNames = keys$4(fields);
7574
+ const fieldNames = keys$5(fields);
7587
7575
  const recordFields = {};
7588
7576
  const objectInfo = objectInfos.get(apiName);
7589
7577
  for (let i = 0, len = fieldNames.length; i < len; i++) {
@@ -7651,7 +7639,7 @@ function buildSyntheticRecordRepresentation(luvio, createOperation, userId, obje
7651
7639
  draftFields[DEFAULT_FIELD_LAST_MODIFIED_DATE] = { value: timestampString, displayValue: null };
7652
7640
  draftFields[DEFAULT_FIELD_OWNER_ID] = { value: userId, displayValue: null };
7653
7641
  draftFields[DEFAULT_FIELD_ID] = { value: recordId, displayValue: null };
7654
- const allObjectFields = keys$4(objectInfo.fields);
7642
+ const allObjectFields = keys$5(objectInfo.fields);
7655
7643
  allObjectFields.forEach((fieldName) => {
7656
7644
  if (draftFields[fieldName] === undefined) {
7657
7645
  draftFields[fieldName] = { value: null, displayValue: null };
@@ -7792,7 +7780,7 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
7792
7780
  this.isDraftId = isDraftId;
7793
7781
  this.recordService = recordService;
7794
7782
  this.handlerId = LDS_ACTION_HANDLER_ID;
7795
- this.collectedFields = create$4(null);
7783
+ this.collectedFields = create$5(null);
7796
7784
  recordService.registerRecordHandler(this);
7797
7785
  }
7798
7786
  async buildPendingAction(request, queue) {
@@ -7854,7 +7842,7 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
7854
7842
  throw Error(`Could not generate draft. Object info is missing`);
7855
7843
  }
7856
7844
  const appendedFields = this.getBackdatingFields(objectInfo, resolvedRequest.method, pendingAction);
7857
- if (keys$4(appendedFields).length > 0) {
7845
+ if (keys$5(appendedFields).length > 0) {
7858
7846
  pendingAction.data.body = {
7859
7847
  ...pendingAction.data.body,
7860
7848
  fields: {
@@ -7868,7 +7856,7 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
7868
7856
  }
7869
7857
  getBackdatingFields(objectInfo, requestMethod, pendingAction) {
7870
7858
  const fields = {};
7871
- const actionFieldNames = keys$4(pendingAction.data.body.fields);
7859
+ const actionFieldNames = keys$5(pendingAction.data.body.fields);
7872
7860
  if (requestMethod === 'post') {
7873
7861
  // `CreateRecord` with `CreatedDate` field
7874
7862
  if (isBackdatingFieldEditable(objectInfo, DEFAULT_FIELD_CREATED_DATE$1, 'createable', actionFieldNames)) {
@@ -7914,7 +7902,7 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
7914
7902
  return;
7915
7903
  }
7916
7904
  const objectInfo = objectInfoMap[apiName];
7917
- const optionalFields = values$2(objectInfo.fields).map((field) => `${apiName}.${field.apiName}`);
7905
+ const optionalFields = values$3(objectInfo.fields).map((field) => `${apiName}.${field.apiName}`);
7918
7906
  await getAdapterData(this.getRecordAdapter, {
7919
7907
  recordId: referenceFieldInfo.id,
7920
7908
  optionalFields,
@@ -7933,7 +7921,7 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
7933
7921
  const referenceToInfos = fieldInfo.referenceToInfos;
7934
7922
  const apiNames = referenceToInfos.map((referenceToInfo) => referenceToInfo.apiName);
7935
7923
  const objectInfoMap = await this.objectInfoService.getObjectInfos(apiNames);
7936
- for (const objectInfo of values$2(objectInfoMap)) {
7924
+ for (const objectInfo of values$3(objectInfoMap)) {
7937
7925
  const { apiName, keyPrefix } = objectInfo;
7938
7926
  if (keyPrefix !== null && id.startsWith(keyPrefix)) {
7939
7927
  return apiName;
@@ -8061,17 +8049,17 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
8061
8049
  // otherwise we're a record
8062
8050
  if (draftMetadata === undefined) {
8063
8051
  // no drafts applied to this record, publish and be done
8064
- this.collectedFields = create$4(null);
8052
+ this.collectedFields = create$5(null);
8065
8053
  return publishData(key, data);
8066
8054
  }
8067
8055
  // create a denormalized record with the collected fields
8068
- const recordFieldNames = keys$4(data.fields);
8056
+ const recordFieldNames = keys$5(data.fields);
8069
8057
  const partialRecord = {
8070
8058
  ...data,
8071
8059
  fields: {},
8072
8060
  };
8073
8061
  for (const fieldName of recordFieldNames) {
8074
- const collectedField = this.collectedFields[buildRecordFieldStoreKey(key, fieldName)];
8062
+ const collectedField = this.collectedFields[buildRecordFieldStoreKey$1(key, fieldName)];
8075
8063
  if (collectedField !== undefined) {
8076
8064
  partialRecord.fields[fieldName] =
8077
8065
  collectedField;
@@ -8087,15 +8075,15 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
8087
8075
  lastModifiedDate: recordWithDrafts.lastModifiedDate,
8088
8076
  lastModifiedById: recordWithDrafts.lastModifiedById,
8089
8077
  };
8090
- for (const fieldName of keys$4(recordWithSpanningRefLinks.fields)) {
8091
- const fieldKey = buildRecordFieldStoreKey(key, fieldName);
8078
+ for (const fieldName of keys$5(recordWithSpanningRefLinks.fields)) {
8079
+ const fieldKey = buildRecordFieldStoreKey$1(key, fieldName);
8092
8080
  normalizedRecord.fields[fieldName] = { __ref: fieldKey };
8093
8081
  publishData(fieldKey, recordWithSpanningRefLinks.fields[fieldName]);
8094
8082
  }
8095
8083
  // publish the normalized record
8096
8084
  publishData(key, normalizedRecord);
8097
8085
  // we've published the record, now clear the collected fields
8098
- this.collectedFields = create$4(null);
8086
+ this.collectedFields = create$5(null);
8099
8087
  }
8100
8088
  updateMetadata(existingMetadata, incomingMetadata) {
8101
8089
  // ensure the the api name cannot be overwritten in the incoming metadata
@@ -8132,7 +8120,7 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
8132
8120
  let resolvedUrlParams = request.urlParams;
8133
8121
  if (request.method === 'post' || request.method === 'patch') {
8134
8122
  const bodyFields = resolvedBody.fields;
8135
- const fieldNames = keys$4(bodyFields);
8123
+ const fieldNames = keys$5(bodyFields);
8136
8124
  for (let i = 0, len = fieldNames.length; i < len; i++) {
8137
8125
  const fieldName = fieldNames[i];
8138
8126
  const fieldValue = bodyFields[fieldName];
@@ -8226,532 +8214,172 @@ function isBackdatingFieldEditable(objectInfo, backdatingFieldName, attributeNam
8226
8214
  !draftActionFieldNames.includes(backdatingFieldName));
8227
8215
  }
8228
8216
 
8229
- function createLink(key) {
8230
- return { __ref: key };
8231
- }
8232
8217
  /**
8233
- * Records are stored in the durable store with scalar fields denormalized. This function takes that denoramlized
8234
- * durable store record representation and normalizes it back out into the format the the luvio store expects it
8235
- * @param key Record store key
8236
- * @param entry Durable entry containing a denormalized record representation
8237
- * @returns a set of entries containing the normalized record and its normalized fields
8218
+ * This function takes an unknown error and normalizes it to an Error object
8238
8219
  */
8239
- function normalizeRecordFields(key, entry) {
8240
- const { data: record } = entry;
8241
- const { fields, links } = record;
8242
- const missingFieldLinks = keys$4(links);
8243
- const fieldNames = keys$4(fields);
8244
- const normalizedFields = {};
8245
- const returnEntries = {};
8246
- // restore fields
8247
- for (let i = 0, len = fieldNames.length; i < len; i++) {
8248
- const fieldName = fieldNames[i];
8249
- const field = fields[fieldName];
8250
- const fieldKey = buildRecordFieldStoreKey(key, fieldName);
8251
- returnEntries[fieldKey] = { data: field };
8252
- normalizedFields[fieldName] = createLink(fieldKey);
8220
+ function normalizeError$1(error) {
8221
+ if (typeof error === 'object' && error instanceof Error) {
8222
+ return error;
8253
8223
  }
8254
- // restore missing fields
8255
- for (let i = 0, len = missingFieldLinks.length; i < len; i++) {
8256
- const fieldName = missingFieldLinks[i];
8257
- const link = links[fieldName];
8258
- if (link.isMissing === true) {
8259
- normalizedFields[fieldName] = { ...link, __ref: undefined };
8260
- }
8224
+ else if (typeof error === 'string') {
8225
+ return new Error(error);
8261
8226
  }
8262
- returnEntries[key] = {
8263
- data: assign$4(record, { fields: normalizedFields }),
8264
- metadata: entry.metadata,
8265
- };
8266
- return returnEntries;
8227
+ return new Error(stringify$4(error));
8267
8228
  }
8229
+
8230
+ const PERFORM_QUICK_ACTION_ENDPOINT_REGEX = /^\/ui-api\/actions\/perform-quick-action\/.*$/;
8268
8231
  /**
8269
- * Transforms a record for storage in the durable store. The transformation involves denormalizing
8270
- * scalar fields and persisting link metadata to transform back into a normalized representation
8271
- *
8272
- * If the record contains pending fields this will return undefined as pending records do not get persisted
8273
- * to the durable store. There should be a refresh operation outbound that will bring in the updated record.
8274
- *
8275
- * @param normalizedRecord Record containing normalized field links
8276
- * @param recordStore a store containing referenced record fields
8232
+ * Checks if a provided resource request is a POST operation on the record
8233
+ * endpoint. If so, it returns true indicating that the request should be enqueued instead of
8234
+ * hitting the network.
8235
+ * @param request the resource request
8277
8236
  */
8278
- function buildDurableRecordRepresentation(normalizedRecord, records, pendingEntries, store) {
8279
- const fields = normalizedRecord.fields;
8280
- const filteredFields = {};
8281
- const links = {};
8282
- const fieldNames = keys$4(fields);
8283
- for (let i = 0, len = fieldNames.length; i < len; i++) {
8284
- const fieldName = fieldNames[i];
8285
- const field = fields[fieldName];
8286
- // pending fields get filtered out of the durable store
8287
- const { pending } = field;
8288
- if (pending === true) {
8289
- // do not write records with pending fields to the durable store
8290
- // there should be a refresh operation outbound that will bring in the updated record
8291
- return undefined;
8292
- }
8293
- const { __ref } = field;
8294
- if (__ref !== undefined) {
8295
- let ref = records[__ref];
8296
- if (pendingEntries !== undefined) {
8297
- // If the ref was part of the pending write that takes precedence
8298
- const pendingEntry = pendingEntries[__ref];
8299
- if (pendingEntry !== undefined) {
8300
- ref = pendingEntry.data;
8301
- }
8302
- }
8303
- // if field reference exists then add it to our filteredFields
8304
- if (ref !== undefined) {
8305
- filteredFields[fieldName] = ref;
8306
- }
8307
- else {
8308
- // if we have a store to read, try to find the field there too
8309
- // The durable ingest staging store may pass through to L1, and
8310
- // not all fields are necessarily published every time, so it is
8311
- // important to check L1 and not just the fields being published,
8312
- // otherwise we risk truncating the fields on the record.
8313
- if (store) {
8314
- ref = store.readEntry(__ref);
8315
- if (ref !== undefined) {
8316
- filteredFields[fieldName] = ref;
8317
- }
8318
- }
8319
- }
8237
+ function isRequestPerformQuickAction(request) {
8238
+ const { basePath, method } = request;
8239
+ return method === 'post' && PERFORM_QUICK_ACTION_ENDPOINT_REGEX.test(basePath);
8240
+ }
8241
+ function performQuickActionDraftEnvironment(luvio, env, handler) {
8242
+ const dispatchResourceRequest = async function (request, context, eventObservers) {
8243
+ if (isRequestPerformQuickAction(request) === false) {
8244
+ // only override requests to createRecord endpoint
8245
+ return env.dispatchResourceRequest(request, context, eventObservers);
8320
8246
  }
8321
- // we want to preserve fields that are missing nodes
8322
- if (field.isMissing === true) {
8323
- links[fieldName] = field;
8247
+ const { data } = await handler.enqueue(request).catch((err) => {
8248
+ throw createDraftSynthesisErrorResponse(normalizeError$1(err).message);
8249
+ });
8250
+ if (data === undefined) {
8251
+ return Promise.reject(createDraftSynthesisErrorResponse());
8324
8252
  }
8325
- }
8326
- return {
8327
- ...normalizedRecord,
8328
- fields: filteredFields,
8329
- links,
8253
+ return createOkResponse(data);
8330
8254
  };
8255
+ return create$5(env, {
8256
+ dispatchResourceRequest: { value: dispatchResourceRequest },
8257
+ });
8331
8258
  }
8332
- function getDenormalizedKey(originalKey, recordId, luvio) {
8333
- // this will likely need to be handled when moving to structured keys
8334
- // note record view entities dont have an associated keybuilder. They get ingested as records to a different key format
8335
- // see the override for how they are handled packages/lds-adapters-uiapi/src/raml-artifacts/types/RecordRepresentation/keyBuilderFromType.ts
8336
- if (originalKey.startsWith(RECORD_VIEW_ENTITY_ID_PREFIX)) {
8337
- return RECORD_VIEW_ENTITY_ID_PREFIX + recordId;
8259
+
8260
+ class UiApiDraftRecordService {
8261
+ constructor(draftQueue, getLuvio, durableStore, objectInfoAdapter, generateId, userId, formatDisplayValue) {
8262
+ this.recordEffectingHandlers = {};
8263
+ this.draftQueue = draftQueue;
8264
+ this.getLuvio = getLuvio;
8265
+ this.durableStore = durableStore;
8266
+ this.objectInfoAdapter = objectInfoAdapter;
8267
+ this.generateId = generateId;
8268
+ this.userId = userId;
8269
+ this.formatDisplayValue = formatDisplayValue;
8338
8270
  }
8339
- return keyBuilderRecord(luvio, { recordId });
8340
- }
8341
- function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecords, getStoreMetadata, getStore, sqlStore) {
8342
- const getEntries = function (entries, segment) {
8343
- // this HOF only inspects records in the default segment
8344
- if (segment !== DefaultDurableSegment) {
8345
- return durableStore.getEntries(entries, segment);
8346
- }
8347
- const { length: entriesLength } = entries;
8348
- if (entriesLength === 0) {
8349
- return Promise.resolve({});
8271
+ async queueToRecordOperations(
8272
+ // an action that is not yet in the queue, we want to test to ensure that
8273
+ // we can still get the metadata once its been added to the queue
8274
+ incomingAction) {
8275
+ const recordOperations = [];
8276
+ const queue = await this.draftQueue.getQueueActions();
8277
+ if (incomingAction !== undefined) {
8278
+ queue.push(incomingAction);
8350
8279
  }
8351
- // filter out record field keys
8352
- const filteredEntryIds = [];
8353
- // map of records to avoid requesting duplicate record keys when requesting both records and fields
8354
- const recordEntries = {};
8355
- const recordViewEntries = {};
8356
- for (let i = 0, len = entriesLength; i < len; i++) {
8357
- const id = entries[i];
8358
- const recordId = extractRecordIdFromStoreKey(id);
8359
- if (recordId !== undefined) {
8360
- if (id.startsWith(RECORD_VIEW_ENTITY_ID_PREFIX)) {
8361
- if (recordViewEntries[recordId] === undefined) {
8362
- const key = getDenormalizedKey(id, recordId, luvio);
8363
- recordViewEntries[recordId] = true;
8364
- filteredEntryIds.push(key);
8365
- }
8366
- }
8367
- else {
8368
- if (recordEntries[recordId] === undefined) {
8369
- const key = getDenormalizedKey(id, recordId, luvio);
8370
- recordEntries[recordId] = true;
8371
- filteredEntryIds.push(key);
8372
- }
8280
+ for (const action of queue) {
8281
+ const handler = this.recordEffectingHandlers[action.handler];
8282
+ if (handler !== undefined) {
8283
+ const operations = handler.draftActionToDraftOperation(action);
8284
+ if (operations !== undefined) {
8285
+ recordOperations.push(...operations);
8373
8286
  }
8374
8287
  }
8375
- else {
8376
- filteredEntryIds.push(id);
8377
- }
8378
8288
  }
8379
- // call base getEntries
8380
- return durableStore.getEntries(filteredEntryIds, segment).then((durableEntries) => {
8381
- if (durableEntries === undefined) {
8382
- return undefined;
8289
+ return recordOperations;
8290
+ }
8291
+ async getRecordDraftMetadata(recordId, incomingAction) {
8292
+ var _a;
8293
+ const recordOperations = (await this.queueToRecordOperations(incomingAction)).filter((x) => x.id === recordId);
8294
+ if (recordOperations.length === 0) {
8295
+ return undefined;
8296
+ }
8297
+ const objectInfoMap = new Map();
8298
+ const referenceMap = new Map();
8299
+ const referenceFields = [];
8300
+ const metadata = {
8301
+ luvio: this.getLuvio(),
8302
+ userId: this.userId,
8303
+ formatDisplayValue: this.formatDisplayValue,
8304
+ objectInfos: objectInfoMap,
8305
+ referencedRecords: referenceMap,
8306
+ recordOperations,
8307
+ };
8308
+ for (const operation of recordOperations) {
8309
+ if (operation.type === 'delete') {
8310
+ continue;
8383
8311
  }
8384
- const returnEntries = create$4(null);
8385
- const keys$1 = keys$4(durableEntries);
8386
- for (let i = 0, len = keys$1.length; i < len; i++) {
8387
- const key = keys$1[i];
8388
- const value = durableEntries[key];
8389
- if (value === undefined) {
8312
+ const apiName = operation.apiName;
8313
+ const objectInfo = (_a = objectInfoMap.get(apiName)) !== null && _a !== void 0 ? _a : (await getAdapterData(this.objectInfoAdapter, { objectApiName: apiName }));
8314
+ if (objectInfo === undefined) {
8315
+ return {
8316
+ ok: false,
8317
+ data: metadata,
8318
+ status: 'missing-object-info',
8319
+ };
8320
+ }
8321
+ objectInfoMap.set(apiName, objectInfo);
8322
+ const fields = keys$5(operation.fields);
8323
+ const unexpectedFields = [];
8324
+ for (const field of fields) {
8325
+ const fieldInfo = objectInfo.fields[field];
8326
+ if (fieldInfo === undefined) {
8327
+ unexpectedFields.push(field);
8390
8328
  continue;
8391
8329
  }
8392
- if (isEntryDurableRecordRepresentation(value, key)) {
8393
- assign$4(returnEntries, normalizeRecordFields(key, value));
8394
- }
8395
- else {
8396
- returnEntries[key] = value;
8397
- }
8398
- }
8399
- return returnEntries;
8400
- });
8401
- };
8402
- const denormalizeEntries = function (entries) {
8403
- let hasEntries = false;
8404
- let hasMetadata = false;
8405
- const putEntries = create$4(null);
8406
- const putMetadata = create$4(null);
8407
- const keys$1 = keys$4(entries);
8408
- const putRecords = {};
8409
- const putRecordViews = {};
8410
- const storeRecords = getStoreRecords !== undefined ? getStoreRecords() : {};
8411
- const storeMetadata = getStoreMetadata !== undefined ? getStoreMetadata() : {};
8412
- const store = getStore();
8413
- for (let i = 0, len = keys$1.length; i < len; i++) {
8414
- const key = keys$1[i];
8415
- let value = entries[key];
8416
- const recordId = extractRecordIdFromStoreKey(key);
8417
- // do not put normalized field values
8418
- if (recordId !== undefined) {
8419
- const isRecordView = key.startsWith(RECORD_VIEW_ENTITY_ID_PREFIX);
8420
- if (isRecordView) {
8421
- if (putRecordViews[recordId] === true) {
8422
- continue;
8423
- }
8424
- }
8425
- else {
8426
- if (putRecords[recordId] === true) {
8427
- continue;
8428
- }
8429
- }
8430
- const recordKey = getDenormalizedKey(key, recordId, luvio);
8431
- const recordEntries = entries;
8432
- const entry = recordEntries[recordKey];
8433
- let record = entry && entry.data;
8434
- if (record === undefined) {
8435
- record = storeRecords[recordKey];
8436
- if (record === undefined) {
8437
- // fields are being published without a record for them existing,
8438
- // fields cannot exist standalone in the durable store
8439
- continue;
8440
- }
8441
- }
8442
- if (isRecordView) {
8443
- putRecordViews[recordId] = true;
8444
- }
8445
- else {
8446
- putRecords[recordId] = true;
8447
- }
8448
- if (isStoreRecordError(record)) {
8449
- hasEntries = true;
8450
- putEntries[recordKey] = value;
8330
+ // relax the check for record type ids as they will
8331
+ // unlikely to be cached
8332
+ if (fieldInfo.dataType !== 'Reference' || field === 'RecordTypeId') {
8451
8333
  continue;
8452
8334
  }
8453
- let metadata = entry && entry.metadata;
8454
- if (metadata === undefined) {
8455
- metadata = {
8456
- ...storeMetadata[recordKey],
8457
- metadataVersion: DURABLE_METADATA_VERSION,
8458
- };
8459
- }
8460
- const denormalizedRecord = buildDurableRecordRepresentation(record, storeRecords, recordEntries, store);
8461
- if (denormalizedRecord !== undefined) {
8462
- hasEntries = true;
8463
- putEntries[recordKey] = {
8464
- data: denormalizedRecord,
8465
- metadata,
8466
- };
8467
- // if undefined then it is pending
8468
- // we should still update metadata on pending records
8469
- }
8470
- else {
8471
- hasMetadata = true;
8472
- metadata.expirationTimestamp = metadata.ingestionTimestamp;
8473
- putMetadata[recordKey] = {
8474
- metadata,
8475
- };
8335
+ const id = operation.fields[field];
8336
+ if (typeof id !== 'string') {
8337
+ continue;
8476
8338
  }
8477
- }
8478
- else {
8479
- hasEntries = true;
8480
- putEntries[key] = value;
8481
- }
8482
- }
8483
- return { putEntries, putMetadata, hasEntries, hasMetadata };
8484
- };
8485
- const setEntries = function (entries, segment) {
8486
- if (segment !== DefaultDurableSegment) {
8487
- return durableStore.setEntries(entries, segment);
8488
- }
8489
- const { putEntries, putMetadata, hasEntries, hasMetadata } = denormalizeEntries(entries);
8490
- const promises = [
8491
- hasEntries ? durableStore.setEntries(putEntries, segment) : undefined,
8492
- ];
8493
- if (sqlStore !== undefined && sqlStore.isBatchUpdateSupported()) {
8494
- promises.push(hasMetadata && sqlStore !== undefined
8495
- ? durableStore.setMetadata(putMetadata, segment)
8496
- : undefined);
8497
- }
8498
- return Promise.all(promises).then(() => { });
8499
- };
8500
- const batchOperations = function (operations) {
8501
- const operationsWithDenormedRecords = [];
8502
- for (let i = 0, len = operations.length; i < len; i++) {
8503
- const operation = operations[i];
8504
- if (operation.type === 'setMetadata') {
8505
- // if setMetadata also contains entry data then it needs to be denormalized.
8506
- const keys$1 = keys$4(operation.entries);
8507
- if (keys$1.length > 0) {
8508
- const firstKey = keys$1[0];
8509
- // casted to any to check if data exists
8510
- const firstEntry = operation.entries[firstKey];
8511
- // it is not possible for setMetadata to contain entries with both data and no data in the same operation.
8512
- // this is determined by the plugin supporting update batch calls before it gets to this HOF.
8513
- // so we only need to check one entry to confirm this for performance
8514
- if (firstEntry.data !== undefined) {
8515
- const { putEntries, putMetadata, hasMetadata } = denormalizeEntries(operation.entries);
8516
- operationsWithDenormedRecords.push({
8517
- ...operation,
8518
- entries: putEntries,
8519
- });
8520
- if (hasMetadata &&
8521
- sqlStore !== undefined &&
8522
- sqlStore.isBatchUpdateSupported() === true) {
8523
- operationsWithDenormedRecords.push({
8524
- ...operation,
8525
- entries: putMetadata,
8526
- type: 'setMetadata',
8527
- });
8528
- }
8339
+ const key = getRecordKeyForId(this.getLuvio(), id);
8340
+ if (referenceMap.has(key) === false &&
8341
+ !referenceFields.some((refInfo) => refInfo.id === id)) {
8342
+ const record = await this.durableStore.getDenormalizedRecord(key);
8343
+ if (record !== undefined) {
8344
+ referenceMap.set(key, record);
8529
8345
  }
8530
8346
  else {
8531
- operationsWithDenormedRecords.push(operation);
8347
+ referenceFields.push({
8348
+ id,
8349
+ field: fieldInfo,
8350
+ });
8532
8351
  }
8533
8352
  }
8534
- continue;
8535
- }
8536
- if (operation.segment !== DefaultDurableSegment || operation.type === 'evictEntries') {
8537
- operationsWithDenormedRecords.push(operation);
8538
- continue;
8539
8353
  }
8540
- const { putEntries, putMetadata, hasMetadata } = denormalizeEntries(operation.entries);
8541
- operationsWithDenormedRecords.push({
8542
- ...operation,
8543
- entries: putEntries,
8544
- });
8545
- if (hasMetadata &&
8546
- sqlStore !== undefined &&
8547
- sqlStore.isBatchUpdateSupported() === true) {
8548
- operationsWithDenormedRecords.push({
8549
- ...operation,
8550
- entries: putMetadata,
8551
- type: 'setMetadata',
8552
- });
8354
+ if (unexpectedFields.length > 0) {
8355
+ return {
8356
+ ok: false,
8357
+ status: 'unexpected-fields',
8358
+ fieldNames: unexpectedFields,
8359
+ data: metadata,
8360
+ };
8553
8361
  }
8554
8362
  }
8555
- return durableStore.batchOperations(operationsWithDenormedRecords);
8556
- };
8557
- /**
8558
- * Retrieves a denormalized record from the store
8559
- * NOTE: do no use this if you don't know what you're doing, this can still contain normalized record references
8560
- * @param recordKey record key
8561
- * @param durableStore the durable store
8562
- * @returns a DraftRecordRepresentation containing the requested fields
8563
- */
8564
- const getDenormalizedRecord = function (recordKey) {
8565
- return durableStore.getEntries([recordKey], DefaultDurableSegment).then((entries) => {
8566
- if (entries === undefined) {
8567
- return undefined;
8568
- }
8569
- const denormalizedEntry = entries[recordKey];
8570
- if (denormalizedEntry === undefined) {
8571
- return undefined;
8572
- }
8573
- // don't include link information
8574
- const denormalizedRecord = denormalizedEntry.data;
8575
- if (isStoreRecordError(denormalizedRecord)) {
8576
- return undefined;
8577
- }
8578
- return denormalizedRecord;
8579
- });
8580
- };
8581
- return create$4(durableStore, {
8582
- getEntries: { value: getEntries, writable: true },
8583
- setEntries: { value: setEntries, writable: true },
8584
- batchOperations: { value: batchOperations, writable: true },
8585
- getDenormalizedRecord: { value: getDenormalizedRecord, writable: true },
8586
- });
8587
- }
8588
-
8589
- /**
8590
- * This function takes an unknown error and normalizes it to an Error object
8591
- */
8592
- function normalizeError$1(error) {
8593
- if (typeof error === 'object' && error instanceof Error) {
8594
- return error;
8363
+ if (referenceFields.length > 0) {
8364
+ return {
8365
+ ok: true,
8366
+ data: metadata,
8367
+ status: 'missing-referenced-records',
8368
+ missingRecordReferences: referenceFields,
8369
+ };
8370
+ }
8371
+ return {
8372
+ ok: true,
8373
+ status: 'success',
8374
+ data: metadata,
8375
+ };
8595
8376
  }
8596
- else if (typeof error === 'string') {
8597
- return new Error(error);
8377
+ registerRecordHandler(recordHandler) {
8378
+ this.recordEffectingHandlers[recordHandler.handlerId] = recordHandler;
8598
8379
  }
8599
- return new Error(stringify$4(error));
8600
- }
8601
-
8602
- const PERFORM_QUICK_ACTION_ENDPOINT_REGEX = /^\/ui-api\/actions\/perform-quick-action\/.*$/;
8603
- /**
8604
- * Checks if a provided resource request is a POST operation on the record
8605
- * endpoint. If so, it returns true indicating that the request should be enqueued instead of
8606
- * hitting the network.
8607
- * @param request the resource request
8608
- */
8609
- function isRequestPerformQuickAction(request) {
8610
- const { basePath, method } = request;
8611
- return method === 'post' && PERFORM_QUICK_ACTION_ENDPOINT_REGEX.test(basePath);
8612
- }
8613
- function performQuickActionDraftEnvironment(luvio, env, handler) {
8614
- const dispatchResourceRequest = async function (request, context, eventObservers) {
8615
- if (isRequestPerformQuickAction(request) === false) {
8616
- // only override requests to createRecord endpoint
8617
- return env.dispatchResourceRequest(request, context, eventObservers);
8618
- }
8619
- const { data } = await handler.enqueue(request).catch((err) => {
8620
- throw createDraftSynthesisErrorResponse(normalizeError$1(err).message);
8621
- });
8622
- if (data === undefined) {
8623
- return Promise.reject(createDraftSynthesisErrorResponse());
8624
- }
8625
- return createOkResponse(data);
8626
- };
8627
- return create$4(env, {
8628
- dispatchResourceRequest: { value: dispatchResourceRequest },
8629
- });
8630
- }
8631
-
8632
- class UiApiDraftRecordService {
8633
- constructor(draftQueue, getLuvio, durableStore, objectInfoAdapter, generateId, userId, formatDisplayValue) {
8634
- this.recordEffectingHandlers = {};
8635
- this.draftQueue = draftQueue;
8636
- this.getLuvio = getLuvio;
8637
- this.durableStore = durableStore;
8638
- this.objectInfoAdapter = objectInfoAdapter;
8639
- this.generateId = generateId;
8640
- this.userId = userId;
8641
- this.formatDisplayValue = formatDisplayValue;
8642
- }
8643
- async queueToRecordOperations(
8644
- // an action that is not yet in the queue, we want to test to ensure that
8645
- // we can still get the metadata once its been added to the queue
8646
- incomingAction) {
8647
- const recordOperations = [];
8648
- const queue = await this.draftQueue.getQueueActions();
8649
- if (incomingAction !== undefined) {
8650
- queue.push(incomingAction);
8651
- }
8652
- for (const action of queue) {
8653
- const handler = this.recordEffectingHandlers[action.handler];
8654
- if (handler !== undefined) {
8655
- const operations = handler.draftActionToDraftOperation(action);
8656
- if (operations !== undefined) {
8657
- recordOperations.push(...operations);
8658
- }
8659
- }
8660
- }
8661
- return recordOperations;
8662
- }
8663
- async getRecordDraftMetadata(recordId, incomingAction) {
8664
- var _a;
8665
- const recordOperations = (await this.queueToRecordOperations(incomingAction)).filter((x) => x.id === recordId);
8666
- if (recordOperations.length === 0) {
8667
- return undefined;
8668
- }
8669
- const objectInfoMap = new Map();
8670
- const referenceMap = new Map();
8671
- const referenceFields = [];
8672
- const metadata = {
8673
- luvio: this.getLuvio(),
8674
- userId: this.userId,
8675
- formatDisplayValue: this.formatDisplayValue,
8676
- objectInfos: objectInfoMap,
8677
- referencedRecords: referenceMap,
8678
- recordOperations,
8679
- };
8680
- for (const operation of recordOperations) {
8681
- if (operation.type === 'delete') {
8682
- continue;
8683
- }
8684
- const apiName = operation.apiName;
8685
- const objectInfo = (_a = objectInfoMap.get(apiName)) !== null && _a !== void 0 ? _a : (await getAdapterData(this.objectInfoAdapter, { objectApiName: apiName }));
8686
- if (objectInfo === undefined) {
8687
- return {
8688
- ok: false,
8689
- data: metadata,
8690
- status: 'missing-object-info',
8691
- };
8692
- }
8693
- objectInfoMap.set(apiName, objectInfo);
8694
- const fields = keys$4(operation.fields);
8695
- const unexpectedFields = [];
8696
- for (const field of fields) {
8697
- const fieldInfo = objectInfo.fields[field];
8698
- if (fieldInfo === undefined) {
8699
- unexpectedFields.push(field);
8700
- continue;
8701
- }
8702
- // relax the check for record type ids as they will
8703
- // unlikely to be cached
8704
- if (fieldInfo.dataType !== 'Reference' || field === 'RecordTypeId') {
8705
- continue;
8706
- }
8707
- const id = operation.fields[field];
8708
- if (typeof id !== 'string') {
8709
- continue;
8710
- }
8711
- const key = getRecordKeyForId(this.getLuvio(), id);
8712
- if (referenceMap.has(key) === false &&
8713
- !referenceFields.some((refInfo) => refInfo.id === id)) {
8714
- const record = await this.durableStore.getDenormalizedRecord(key);
8715
- if (record !== undefined) {
8716
- referenceMap.set(key, record);
8717
- }
8718
- else {
8719
- referenceFields.push({
8720
- id,
8721
- field: fieldInfo,
8722
- });
8723
- }
8724
- }
8725
- }
8726
- if (unexpectedFields.length > 0) {
8727
- return {
8728
- ok: false,
8729
- status: 'unexpected-fields',
8730
- fieldNames: unexpectedFields,
8731
- data: metadata,
8732
- };
8733
- }
8734
- }
8735
- if (referenceFields.length > 0) {
8736
- return {
8737
- ok: true,
8738
- data: metadata,
8739
- status: 'missing-referenced-records',
8740
- missingRecordReferences: referenceFields,
8741
- };
8742
- }
8743
- return {
8744
- ok: true,
8745
- status: 'success',
8746
- data: metadata,
8747
- };
8748
- }
8749
- registerRecordHandler(recordHandler) {
8750
- this.recordEffectingHandlers[recordHandler.handlerId] = recordHandler;
8751
- }
8752
- async synthesizeId(apiName) {
8753
- const objectInfo = await getAdapterData(this.objectInfoAdapter, {
8754
- objectApiName: apiName,
8380
+ async synthesizeId(apiName) {
8381
+ const objectInfo = await getAdapterData(this.objectInfoAdapter, {
8382
+ objectApiName: apiName,
8755
8383
  });
8756
8384
  if (objectInfo === undefined || objectInfo.keyPrefix === null) {
8757
8385
  throw Error(`Could not find or fetch object info for ${apiName}`);
@@ -9015,7 +8643,7 @@ function createContentDocumentAndVersionDraftAdapterFactory(luvio, binaryStore,
9015
8643
  ...trimmedDownData.contentVersion,
9016
8644
  fields: cvFields,
9017
8645
  };
9018
- freeze(trimmedDownData);
8646
+ freeze$1(trimmedDownData);
9019
8647
  snapshot.data = trimmedDownData;
9020
8648
  }
9021
8649
  eventEmitter({ type: 'create-content-document-and-version-draft-finished' });
@@ -9029,14 +8657,13 @@ const CONTENT_DOCUMENT_LINK_API_NAME = 'ContentDocumentLink';
9029
8657
  const CONTENT_VERSION_API_NAME = 'ContentVersion';
9030
8658
  const LATEST_PUBLISHED_VERSION_ID_FIELD = 'LatestPublishedVersionId';
9031
8659
  class ContentDocumentCompositeRepresentationActionHandler extends AbstractResourceRequestActionHandler {
9032
- constructor(getLuvio, draftRecordService, draftQueue, networkAdapter, isDraftId, durableStore, binaryStore) {
8660
+ constructor(getLuvio, draftRecordService, draftQueue, networkAdapter, isDraftId, binaryStore) {
9033
8661
  super(draftQueue, networkAdapter, getLuvio);
9034
8662
  this.getLuvio = getLuvio;
9035
8663
  this.draftRecordService = draftRecordService;
9036
8664
  this.draftQueue = draftQueue;
9037
8665
  this.networkAdapter = networkAdapter;
9038
8666
  this.isDraftId = isDraftId;
9039
- this.durableStore = durableStore;
9040
8667
  this.binaryStore = binaryStore;
9041
8668
  this.binaryStoreUrlsToUpdate = new Map();
9042
8669
  this.handlerId = HANDLER_ID;
@@ -9448,6 +9075,389 @@ function deleteRecordDraftAdapterFactory(luvio, actionHandler) {
9448
9075
  };
9449
9076
  }
9450
9077
 
9078
+ /**
9079
+ * Copyright (c) 2022, Salesforce, Inc.,
9080
+ * All rights reserved.
9081
+ * For full license text, see the LICENSE.txt file
9082
+ */
9083
+
9084
+
9085
+ const { keys: keys$4, values: values$2, create: create$4, assign: assign$4, freeze, entries: entries$4 } = Object;
9086
+
9087
+ function buildRecordFieldStoreKey(recordKey, fieldName) {
9088
+ return `${recordKey}${RECORD_FIELDS_KEY_JUNCTION$1}${fieldName}`;
9089
+ }
9090
+ function isStoreKeyRecordId(key) {
9091
+ return key.indexOf(RECORD_ID_PREFIX$1) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION$1) === -1;
9092
+ }
9093
+ function createLink(key) {
9094
+ return { __ref: key };
9095
+ }
9096
+ function isStoreRecordError(storeRecord) {
9097
+ return storeRecord.__type === 'error';
9098
+ }
9099
+ function isEntryDurableRecordRepresentation(entry, key) {
9100
+ // Either a DurableRecordRepresentation or StoreRecordError can live at a record key
9101
+ return ((isStoreKeyRecordId(key) || isStoreKeyRecordViewEntity(key)) &&
9102
+ entry.data.__type === undefined);
9103
+ }
9104
+ /**
9105
+ * Records are stored in the durable store with scalar fields denormalized. This function takes that denoramlized
9106
+ * durable store record representation and normalizes it back out into the format the the luvio store expects it
9107
+ * @param key Record store key
9108
+ * @param entry Durable entry containing a denormalized record representation
9109
+ * @returns a set of entries containing the normalized record and its normalized fields
9110
+ */
9111
+ function normalizeRecordFields(key, entry) {
9112
+ const { data: record } = entry;
9113
+ const { fields, links } = record;
9114
+ const missingFieldLinks = keys$4(links);
9115
+ const fieldNames = keys$4(fields);
9116
+ const normalizedFields = {};
9117
+ const returnEntries = {};
9118
+ // restore fields
9119
+ for (let i = 0, len = fieldNames.length; i < len; i++) {
9120
+ const fieldName = fieldNames[i];
9121
+ const field = fields[fieldName];
9122
+ const fieldKey = buildRecordFieldStoreKey(key, fieldName);
9123
+ returnEntries[fieldKey] = { data: field };
9124
+ normalizedFields[fieldName] = createLink(fieldKey);
9125
+ }
9126
+ // restore missing fields
9127
+ for (let i = 0, len = missingFieldLinks.length; i < len; i++) {
9128
+ const fieldName = missingFieldLinks[i];
9129
+ const link = links[fieldName];
9130
+ if (link.isMissing === true) {
9131
+ normalizedFields[fieldName] = { ...link, __ref: undefined };
9132
+ }
9133
+ }
9134
+ returnEntries[key] = {
9135
+ data: assign$4(record, { fields: normalizedFields }),
9136
+ metadata: entry.metadata,
9137
+ };
9138
+ return returnEntries;
9139
+ }
9140
+ /**
9141
+ * Transforms a record for storage in the durable store. The transformation involves denormalizing
9142
+ * scalar fields and persisting link metadata to transform back into a normalized representation
9143
+ *
9144
+ * If the record contains pending fields this will return undefined as pending records do not get persisted
9145
+ * to the durable store. There should be a refresh operation outbound that will bring in the updated record.
9146
+ *
9147
+ * @param normalizedRecord Record containing normalized field links
9148
+ * @param recordStore a store containing referenced record fields
9149
+ */
9150
+ function buildDurableRecordRepresentation(normalizedRecord, records, pendingEntries, store) {
9151
+ const fields = normalizedRecord.fields;
9152
+ const filteredFields = {};
9153
+ const links = {};
9154
+ const fieldNames = keys$4(fields);
9155
+ for (let i = 0, len = fieldNames.length; i < len; i++) {
9156
+ const fieldName = fieldNames[i];
9157
+ const field = fields[fieldName];
9158
+ // pending fields get filtered out of the durable store
9159
+ const { pending } = field;
9160
+ if (pending === true) {
9161
+ // do not write records with pending fields to the durable store
9162
+ // there should be a refresh operation outbound that will bring in the updated record
9163
+ return undefined;
9164
+ }
9165
+ const { __ref } = field;
9166
+ if (__ref !== undefined) {
9167
+ let ref = records[__ref];
9168
+ if (pendingEntries !== undefined) {
9169
+ // If the ref was part of the pending write that takes precedence
9170
+ const pendingEntry = pendingEntries[__ref];
9171
+ if (pendingEntry !== undefined) {
9172
+ ref = pendingEntry.data;
9173
+ }
9174
+ }
9175
+ // if field reference exists then add it to our filteredFields
9176
+ if (ref !== undefined) {
9177
+ filteredFields[fieldName] = ref;
9178
+ }
9179
+ else {
9180
+ // if we have a store to read, try to find the field there too
9181
+ // The durable ingest staging store may pass through to L1, and
9182
+ // not all fields are necessarily published every time, so it is
9183
+ // important to check L1 and not just the fields being published,
9184
+ // otherwise we risk truncating the fields on the record.
9185
+ if (store) {
9186
+ ref = store.readEntry(__ref);
9187
+ if (ref !== undefined) {
9188
+ filteredFields[fieldName] = ref;
9189
+ }
9190
+ }
9191
+ }
9192
+ }
9193
+ // we want to preserve fields that are missing nodes
9194
+ if (field.isMissing === true) {
9195
+ links[fieldName] = field;
9196
+ }
9197
+ }
9198
+ return {
9199
+ ...normalizedRecord,
9200
+ fields: filteredFields,
9201
+ links,
9202
+ };
9203
+ }
9204
+ function getDenormalizedKey(originalKey, recordId, luvio) {
9205
+ // this will likely need to be handled when moving to structured keys
9206
+ // note record view entities dont have an associated keybuilder. They get ingested as records to a different key format
9207
+ // see the override for how they are handled packages/lds-adapters-uiapi/src/raml-artifacts/types/RecordRepresentation/keyBuilderFromType.ts
9208
+ if (originalKey.startsWith(RECORD_VIEW_ENTITY_ID_PREFIX)) {
9209
+ return RECORD_VIEW_ENTITY_ID_PREFIX + recordId;
9210
+ }
9211
+ return keyBuilderRecord$1(luvio, { recordId });
9212
+ }
9213
+ function makeRecordDenormalizingDurableStore(luvio, durableStore, getStoreRecords, getStoreMetadata, getStore, sqlStore) {
9214
+ const getEntries = function (entries, segment) {
9215
+ // this HOF only inspects records in the default segment
9216
+ if (segment !== DefaultDurableSegment) {
9217
+ return durableStore.getEntries(entries, segment);
9218
+ }
9219
+ const { length: entriesLength } = entries;
9220
+ if (entriesLength === 0) {
9221
+ return Promise.resolve({});
9222
+ }
9223
+ // filter out record field keys
9224
+ const filteredEntryIds = [];
9225
+ // map of records to avoid requesting duplicate record keys when requesting both records and fields
9226
+ const recordEntries = {};
9227
+ const recordViewEntries = {};
9228
+ for (let i = 0, len = entriesLength; i < len; i++) {
9229
+ const id = entries[i];
9230
+ const recordId = extractRecordIdFromStoreKey$1(id);
9231
+ if (recordId !== undefined) {
9232
+ if (id.startsWith(RECORD_VIEW_ENTITY_ID_PREFIX)) {
9233
+ if (recordViewEntries[recordId] === undefined) {
9234
+ const key = getDenormalizedKey(id, recordId, luvio);
9235
+ recordViewEntries[recordId] = true;
9236
+ filteredEntryIds.push(key);
9237
+ }
9238
+ }
9239
+ else {
9240
+ if (recordEntries[recordId] === undefined) {
9241
+ const key = getDenormalizedKey(id, recordId, luvio);
9242
+ recordEntries[recordId] = true;
9243
+ filteredEntryIds.push(key);
9244
+ }
9245
+ }
9246
+ }
9247
+ else {
9248
+ filteredEntryIds.push(id);
9249
+ }
9250
+ }
9251
+ // call base getEntries
9252
+ return durableStore.getEntries(filteredEntryIds, segment).then((durableEntries) => {
9253
+ if (durableEntries === undefined) {
9254
+ return undefined;
9255
+ }
9256
+ const returnEntries = create$4(null);
9257
+ const keys$1 = keys$4(durableEntries);
9258
+ for (let i = 0, len = keys$1.length; i < len; i++) {
9259
+ const key = keys$1[i];
9260
+ const value = durableEntries[key];
9261
+ if (value === undefined) {
9262
+ continue;
9263
+ }
9264
+ if (isEntryDurableRecordRepresentation(value, key)) {
9265
+ assign$4(returnEntries, normalizeRecordFields(key, value));
9266
+ }
9267
+ else {
9268
+ returnEntries[key] = value;
9269
+ }
9270
+ }
9271
+ return returnEntries;
9272
+ });
9273
+ };
9274
+ const denormalizeEntries = function (entries) {
9275
+ let hasEntries = false;
9276
+ let hasMetadata = false;
9277
+ const putEntries = create$4(null);
9278
+ const putMetadata = create$4(null);
9279
+ const keys$1 = keys$4(entries);
9280
+ const putRecords = {};
9281
+ const putRecordViews = {};
9282
+ const storeRecords = getStoreRecords !== undefined ? getStoreRecords() : {};
9283
+ const storeMetadata = getStoreMetadata !== undefined ? getStoreMetadata() : {};
9284
+ const store = getStore();
9285
+ for (let i = 0, len = keys$1.length; i < len; i++) {
9286
+ const key = keys$1[i];
9287
+ let value = entries[key];
9288
+ const recordId = extractRecordIdFromStoreKey$1(key);
9289
+ // do not put normalized field values
9290
+ if (recordId !== undefined) {
9291
+ const isRecordView = key.startsWith(RECORD_VIEW_ENTITY_ID_PREFIX);
9292
+ if (isRecordView) {
9293
+ if (putRecordViews[recordId] === true) {
9294
+ continue;
9295
+ }
9296
+ }
9297
+ else {
9298
+ if (putRecords[recordId] === true) {
9299
+ continue;
9300
+ }
9301
+ }
9302
+ const recordKey = getDenormalizedKey(key, recordId, luvio);
9303
+ const recordEntries = entries;
9304
+ const entry = recordEntries[recordKey];
9305
+ let record = entry && entry.data;
9306
+ if (record === undefined) {
9307
+ record = storeRecords[recordKey];
9308
+ if (record === undefined) {
9309
+ // fields are being published without a record for them existing,
9310
+ // fields cannot exist standalone in the durable store
9311
+ continue;
9312
+ }
9313
+ }
9314
+ if (isRecordView) {
9315
+ putRecordViews[recordId] = true;
9316
+ }
9317
+ else {
9318
+ putRecords[recordId] = true;
9319
+ }
9320
+ if (isStoreRecordError(record)) {
9321
+ hasEntries = true;
9322
+ putEntries[recordKey] = value;
9323
+ continue;
9324
+ }
9325
+ let metadata = entry && entry.metadata;
9326
+ if (metadata === undefined) {
9327
+ metadata = {
9328
+ ...storeMetadata[recordKey],
9329
+ metadataVersion: DURABLE_METADATA_VERSION,
9330
+ };
9331
+ }
9332
+ const denormalizedRecord = buildDurableRecordRepresentation(record, storeRecords, recordEntries, store);
9333
+ if (denormalizedRecord !== undefined) {
9334
+ hasEntries = true;
9335
+ putEntries[recordKey] = {
9336
+ data: denormalizedRecord,
9337
+ metadata,
9338
+ };
9339
+ // if undefined then it is pending
9340
+ // we should still update metadata on pending records
9341
+ }
9342
+ else {
9343
+ hasMetadata = true;
9344
+ metadata.expirationTimestamp = metadata.ingestionTimestamp;
9345
+ putMetadata[recordKey] = {
9346
+ metadata,
9347
+ };
9348
+ }
9349
+ }
9350
+ else {
9351
+ hasEntries = true;
9352
+ putEntries[key] = value;
9353
+ }
9354
+ }
9355
+ return { putEntries, putMetadata, hasEntries, hasMetadata };
9356
+ };
9357
+ const setEntries = function (entries, segment) {
9358
+ if (segment !== DefaultDurableSegment) {
9359
+ return durableStore.setEntries(entries, segment);
9360
+ }
9361
+ const { putEntries, putMetadata, hasEntries, hasMetadata } = denormalizeEntries(entries);
9362
+ const promises = [
9363
+ hasEntries ? durableStore.setEntries(putEntries, segment) : undefined,
9364
+ ];
9365
+ if (sqlStore !== undefined && sqlStore.isBatchUpdateSupported()) {
9366
+ promises.push(hasMetadata && sqlStore !== undefined
9367
+ ? durableStore.setMetadata(putMetadata, segment)
9368
+ : undefined);
9369
+ }
9370
+ return Promise.all(promises).then(() => { });
9371
+ };
9372
+ const batchOperations = function (operations) {
9373
+ const operationsWithDenormedRecords = [];
9374
+ for (let i = 0, len = operations.length; i < len; i++) {
9375
+ const operation = operations[i];
9376
+ if (operation.type === 'setMetadata') {
9377
+ // if setMetadata also contains entry data then it needs to be denormalized.
9378
+ const keys$1 = keys$4(operation.entries);
9379
+ if (keys$1.length > 0) {
9380
+ const firstKey = keys$1[0];
9381
+ // casted to any to check if data exists
9382
+ const firstEntry = operation.entries[firstKey];
9383
+ // it is not possible for setMetadata to contain entries with both data and no data in the same operation.
9384
+ // this is determined by the plugin supporting update batch calls before it gets to this HOF.
9385
+ // so we only need to check one entry to confirm this for performance
9386
+ if (firstEntry.data !== undefined) {
9387
+ const { putEntries, putMetadata, hasMetadata } = denormalizeEntries(operation.entries);
9388
+ operationsWithDenormedRecords.push({
9389
+ ...operation,
9390
+ entries: putEntries,
9391
+ });
9392
+ if (hasMetadata &&
9393
+ sqlStore !== undefined &&
9394
+ sqlStore.isBatchUpdateSupported() === true) {
9395
+ operationsWithDenormedRecords.push({
9396
+ ...operation,
9397
+ entries: putMetadata,
9398
+ type: 'setMetadata',
9399
+ });
9400
+ }
9401
+ }
9402
+ else {
9403
+ operationsWithDenormedRecords.push(operation);
9404
+ }
9405
+ }
9406
+ continue;
9407
+ }
9408
+ if (operation.segment !== DefaultDurableSegment || operation.type === 'evictEntries') {
9409
+ operationsWithDenormedRecords.push(operation);
9410
+ continue;
9411
+ }
9412
+ const { putEntries, putMetadata, hasMetadata } = denormalizeEntries(operation.entries);
9413
+ operationsWithDenormedRecords.push({
9414
+ ...operation,
9415
+ entries: putEntries,
9416
+ });
9417
+ if (hasMetadata &&
9418
+ sqlStore !== undefined &&
9419
+ sqlStore.isBatchUpdateSupported() === true) {
9420
+ operationsWithDenormedRecords.push({
9421
+ ...operation,
9422
+ entries: putMetadata,
9423
+ type: 'setMetadata',
9424
+ });
9425
+ }
9426
+ }
9427
+ return durableStore.batchOperations(operationsWithDenormedRecords);
9428
+ };
9429
+ /**
9430
+ * Retrieves a denormalized record from the store
9431
+ * NOTE: do no use this if you don't know what you're doing, this can still contain normalized record references
9432
+ * @param recordKey record key
9433
+ * @param durableStore the durable store
9434
+ * @returns a DraftRecordRepresentation containing the requested fields
9435
+ */
9436
+ const getDenormalizedRecord = function (recordKey) {
9437
+ return durableStore.getEntries([recordKey], DefaultDurableSegment).then((entries) => {
9438
+ if (entries === undefined) {
9439
+ return undefined;
9440
+ }
9441
+ const denormalizedEntry = entries[recordKey];
9442
+ if (denormalizedEntry === undefined) {
9443
+ return undefined;
9444
+ }
9445
+ // don't include link information
9446
+ const denormalizedRecord = denormalizedEntry.data;
9447
+ if (isStoreRecordError(denormalizedRecord)) {
9448
+ return undefined;
9449
+ }
9450
+ return denormalizedRecord;
9451
+ });
9452
+ };
9453
+ return create$4(durableStore, {
9454
+ getEntries: { value: getEntries, writable: true },
9455
+ setEntries: { value: setEntries, writable: true },
9456
+ batchOperations: { value: batchOperations, writable: true },
9457
+ getDenormalizedRecord: { value: getDenormalizedRecord, writable: true },
9458
+ });
9459
+ }
9460
+
9451
9461
  function serializeFieldArguments(argumentNodes, variables) {
9452
9462
  const mutableArgumentNodes = Object.assign([], argumentNodes);
9453
9463
  return `args__(${mutableArgumentNodes
@@ -18359,7 +18369,7 @@ function getRuntime() {
18359
18369
  const draftService = new UiApiDraftRecordService(lazyDraftQueue, () => lazyLuvio, recordDenormingStore, getObjectInfo, newRecordId, userId, formatDisplayValue);
18360
18370
  const uiApiRecordHandler = new UiApiActionHandler(() => lazyLuvio, lazyNetworkAdapter, recordDenormingStore, lazyDraftQueue, getRecord, lazyObjectInfoService, isGenerated, draftService);
18361
18371
  const quickActionHandler = new QuickActionExecutionRepresentationHandler(() => lazyLuvio, draftService, lazyDraftQueue, lazyNetworkAdapter, isGenerated);
18362
- const contentDocumentCompositeActionHandler = new ContentDocumentCompositeRepresentationActionHandler(() => lazyLuvio, draftService, lazyDraftQueue, lazyNetworkAdapter, isGenerated, recordDenormingStore, NimbusBinaryStore);
18372
+ const contentDocumentCompositeActionHandler = new ContentDocumentCompositeRepresentationActionHandler(() => lazyLuvio, draftService, lazyDraftQueue, lazyNetworkAdapter, isGenerated, NimbusBinaryStore);
18363
18373
  lazyDraftQueue.addHandler(uiApiRecordHandler);
18364
18374
  lazyDraftQueue.addHandler(quickActionHandler);
18365
18375
  lazyDraftQueue.addHandler(contentDocumentCompositeActionHandler);
@@ -18461,4 +18471,4 @@ register({
18461
18471
  });
18462
18472
 
18463
18473
  export { O11Y_NAMESPACE_LDS_MOBILE, getRuntime, registerReportObserver, reportGraphqlQueryParseError };
18464
- // version: 1.296.0-ad26368c0
18474
+ // version: 1.297.0-1fc775982