@salesforce/lds-runtime-mobile 1.124.4 → 1.124.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -4800,10 +4800,6 @@ function customActionHandler(executor, id, draftQueue) {
4800
4800
  });
4801
4801
  return queueOperations;
4802
4802
  };
4803
- const replaceAction = (actionId, _withActionId, _uploadingActionId, _actions) => {
4804
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
4805
- throw new Error(`${actionId} does not support action replacing. You can only delete ${actionId}`);
4806
- };
4807
4803
  const getRedirectMappings = (_action) => {
4808
4804
  return undefined;
4809
4805
  };
@@ -4815,7 +4811,9 @@ function customActionHandler(executor, id, draftQueue) {
4815
4811
  handleAction: handle,
4816
4812
  buildPendingAction,
4817
4813
  getQueueOperationsForCompletingDrafts: getQueueOperationsForCompletingDrafts,
4818
- handleReplaceAction: replaceAction,
4814
+ handleReplaceAction: () => {
4815
+ throw Error('replaceAction not supported for custom actions');
4816
+ },
4819
4817
  getRedirectMappings,
4820
4818
  handleActionRemoved: () => Promise.resolve(),
4821
4819
  handleActionCompleted: () => Promise.resolve(),
@@ -4882,13 +4880,13 @@ class DurableDraftQueue {
4882
4880
  this.userState = DraftQueueState.Started;
4883
4881
  if (this.state === DraftQueueState.Started) {
4884
4882
  // Do nothing if the queue state is already started
4885
- return Promise.resolve();
4883
+ return;
4886
4884
  }
4887
4885
  if (this.replacingAction !== undefined) {
4888
4886
  // If we're replacing an action do nothing
4889
4887
  // replace will restart the queue for us as long as the user
4890
4888
  // has last set the queue to be started
4891
- return Promise.resolve();
4889
+ return;
4892
4890
  }
4893
4891
  this.retryIntervalMilliseconds = 0;
4894
4892
  this.state = DraftQueueState.Started;
@@ -5128,92 +5126,11 @@ class DurableDraftQueue {
5128
5126
  await this.startQueue();
5129
5127
  }
5130
5128
  }
5131
- replaceAction(actionId, withActionId) {
5132
- // ids must be unique
5133
- if (actionId === withActionId) {
5134
- return Promise.reject('Swapped and swapping action ids cannot be the same');
5135
- }
5136
- // cannot have a replace action already in progress
5137
- if (this.replacingAction !== undefined) {
5138
- return Promise.reject('Cannot replace actions while a replace action is in progress');
5139
- }
5140
- this.stopQueueManually();
5141
- const replacing = this.getQueueActions().then(async (actions) => {
5142
- const first = actions.filter((action) => action.id === actionId)[0];
5143
- if (first === undefined) {
5144
- this.replacingAction = undefined;
5145
- await this.startQueueSafe();
5146
- return Promise.reject('No action to replace');
5147
- }
5148
- // put in a try/finally block so we don't leave this.replacingAction
5149
- // indefinitely set
5150
- let actionToReplace;
5151
- try {
5152
- const replaceResult = this.getHandler(first.handler).handleReplaceAction(actionId, withActionId, this.uploadingActionId, actions);
5153
- actionToReplace = replaceResult.actionToReplace;
5154
- // TODO [W-8873834]: Will add batching support to durable store
5155
- // we should use that here to remove and set both actions in one operation
5156
- await this.removeDraftAction(replaceResult.replacingAction.id);
5157
- await this.draftStore.writeAction(actionToReplace);
5158
- await this.notifyChangedListeners({
5159
- type: DraftQueueEventType.ActionUpdated,
5160
- action: actionToReplace,
5161
- });
5162
- }
5163
- finally {
5164
- this.replacingAction = undefined;
5165
- }
5166
- await this.startQueueSafe();
5167
- return actionToReplace;
5168
- });
5169
- this.replacingAction = replacing;
5170
- return replacing;
5129
+ replaceAction(targetActionId, sourceActionId) {
5130
+ return this.replaceOrMergeActions(targetActionId, sourceActionId, false);
5171
5131
  }
5172
5132
  mergeActions(targetActionId, sourceActionId) {
5173
- // ids must be unique
5174
- if (targetActionId === sourceActionId) {
5175
- return Promise.reject(new Error('targetActionId and sourceActionId cannot be the same.'));
5176
- }
5177
- // cannot have a replace action already in progress
5178
- if (this.replacingAction !== undefined) {
5179
- return Promise.reject(new Error('Cannot merge actions while a replace/merge action operation is in progress.'));
5180
- }
5181
- this.stopQueueManually();
5182
- const promise = this.getQueueActions().then(async (actions) => {
5183
- const target = actions.find((action) => action.id === targetActionId);
5184
- if (target === undefined) {
5185
- this.replacingAction = undefined;
5186
- await this.startQueueSafe();
5187
- throw Error('targetActionId not found in the draft queue.');
5188
- }
5189
- const source = actions.find((action) => action.id === sourceActionId);
5190
- if (source === undefined) {
5191
- this.replacingAction = undefined;
5192
- await this.startQueueSafe();
5193
- throw Error('sourceActionId not found in the draft queue.');
5194
- }
5195
- // put in a try/finally block so we don't leave this.replacingAction
5196
- // indefinitely set
5197
- let merged;
5198
- try {
5199
- merged = this.getHandler(target.handler).mergeActions(target, source);
5200
- // update the target
5201
- await this.draftStore.writeAction(merged);
5202
- await this.notifyChangedListeners({
5203
- type: DraftQueueEventType.ActionUpdated,
5204
- action: merged,
5205
- });
5206
- // remove the source from queue
5207
- await this.removeDraftAction(sourceActionId);
5208
- }
5209
- finally {
5210
- this.replacingAction = undefined;
5211
- }
5212
- await this.startQueueSafe();
5213
- return merged;
5214
- });
5215
- this.replacingAction = promise;
5216
- return promise;
5133
+ return this.replaceOrMergeActions(targetActionId, sourceActionId, true);
5217
5134
  }
5218
5135
  async setMetadata(actionId, metadata) {
5219
5136
  const keys$1 = keys$4(metadata);
@@ -5248,6 +5165,81 @@ class DurableDraftQueue {
5248
5165
  }
5249
5166
  }, this.retryIntervalMilliseconds);
5250
5167
  }
5168
+ async getActionsForReplaceOrMerge(targetActionId, sourceActionId) {
5169
+ const actions = await this.getQueueActions();
5170
+ const target = actions.find((action) => action.id === targetActionId);
5171
+ if (target === undefined) {
5172
+ this.replacingAction = undefined;
5173
+ await this.startQueueSafe();
5174
+ throw Error(`targetActionId ${targetActionId} not found in the draft queue.`);
5175
+ }
5176
+ const source = actions.find((action) => action.id === sourceActionId);
5177
+ if (source === undefined) {
5178
+ this.replacingAction = undefined;
5179
+ await this.startQueueSafe();
5180
+ throw Error(`sourceActionId ${sourceActionId} not found in the draft queue.`);
5181
+ }
5182
+ return { target, source };
5183
+ }
5184
+ assertReplaceOrMergePrerequisites(target, source) {
5185
+ // ensure actions are in a state to be replaced/merged
5186
+ const { targetId: targetCacheKey, tag: targetTag, status: targetStatus, version: targetVersion, } = target;
5187
+ const { targetId: sourceCacheKey, tag: sourceTag, status: sourceStatus, version: sourceVersion, } = source;
5188
+ if (targetCacheKey !== sourceCacheKey) {
5189
+ throw Error('Cannot replace/merge actions for different targetIds.');
5190
+ }
5191
+ if (targetTag !== sourceTag) {
5192
+ throw Error('Cannot replace/merge actions for different tags.');
5193
+ }
5194
+ if (targetStatus === DraftActionStatus.Completed ||
5195
+ targetStatus === DraftActionStatus.Uploading) {
5196
+ throw Error(`Cannot replace/merge actions when targetAction is in ${targetStatus} status.`);
5197
+ }
5198
+ if (sourceStatus !== DraftActionStatus.Pending) {
5199
+ throw Error(`Cannot replace/merge actions when sourceAction is in ${sourceStatus} status.`);
5200
+ }
5201
+ if (targetVersion !== sourceVersion) {
5202
+ throw Error('Cannot replace/merge actions with different versions.');
5203
+ }
5204
+ }
5205
+ async replaceOrMergeActions(targetActionId, sourceActionId, merge) {
5206
+ // ids must be unique
5207
+ if (targetActionId === sourceActionId) {
5208
+ throw Error('targetActionId and sourceActionId cannot be the same.');
5209
+ }
5210
+ // cannot have a replace action already in progress
5211
+ if (this.replacingAction !== undefined) {
5212
+ throw Error('Cannot replace/merge actions while a replace/merge action operation is in progress.');
5213
+ }
5214
+ this.stopQueueManually();
5215
+ const promise = this.getActionsForReplaceOrMerge(targetActionId, sourceActionId).then(async ({ target, source }) => {
5216
+ // put in a try/finally block so we don't leave this.replacingAction
5217
+ // indefinitely set
5218
+ let updatedTarget;
5219
+ try {
5220
+ this.assertReplaceOrMergePrerequisites(target, source);
5221
+ const handler = this.getHandler(target.handler);
5222
+ updatedTarget = merge
5223
+ ? handler.mergeActions(target, source)
5224
+ : handler.handleReplaceAction(target, source);
5225
+ // update the target
5226
+ await this.draftStore.writeAction(updatedTarget);
5227
+ await this.notifyChangedListeners({
5228
+ type: DraftQueueEventType.ActionUpdated,
5229
+ action: updatedTarget,
5230
+ });
5231
+ // remove the source from queue
5232
+ await this.removeDraftAction(sourceActionId);
5233
+ }
5234
+ finally {
5235
+ this.replacingAction = undefined;
5236
+ await this.startQueueSafe();
5237
+ }
5238
+ return updatedTarget;
5239
+ });
5240
+ this.replacingAction = promise;
5241
+ return promise;
5242
+ }
5251
5243
  }
5252
5244
 
5253
5245
  const DRAFT_ACTION_KEY_JUNCTION = '__DraftAction__';
@@ -5681,56 +5673,53 @@ class AbstractResourceRequestActionHandler {
5681
5673
  }
5682
5674
  await this.ingestResponses(recordsToIngest, action);
5683
5675
  }
5684
- handleReplaceAction(actionId, withActionId, uploadingActionId, actions) {
5685
- // get the action to replace
5686
- const actionToReplace = actions.filter((action) => action.id === actionId)[0];
5687
- // get the replacing action
5688
- const replacingAction = actions.filter((action) => action.id === withActionId)[0];
5689
- // reject if either action is undefined
5690
- if (actionToReplace === undefined || replacingAction === undefined) {
5691
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
5692
- throw new Error('One or both actions does not exist');
5693
- }
5694
- // reject if either action is uploading
5695
- if (actionToReplace.id === uploadingActionId || replacingAction.id === uploadingActionId) {
5696
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
5697
- throw new Error('Cannot replace an draft action that is uploading');
5698
- }
5699
- // reject if these two draft actions aren't acting on the same target
5700
- if (actionToReplace.tag !== replacingAction.tag) {
5701
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
5702
- throw new Error('Cannot swap actions targeting different targets');
5703
- }
5704
- // reject if the replacing action is not pending
5705
- if (replacingAction.status !== DraftActionStatus.Pending) {
5706
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
5707
- throw new Error('Cannot replace with a non-pending action');
5708
- }
5676
+ handleReplaceAction(targetAction, sourceAction) {
5709
5677
  //reject if the action to replace is a POST action
5710
- const pendingAction = actionToReplace;
5678
+ const pendingAction = targetAction;
5711
5679
  if (pendingAction.data.method === 'post') {
5712
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
5713
- throw new Error('Cannot replace a POST action');
5680
+ throw Error('Cannot replace a POST action');
5714
5681
  }
5715
- if (this.isActionOfType(actionToReplace) &&
5716
- this.isActionOfType(replacingAction)) {
5717
- const actionToReplaceCopy = {
5718
- ...actionToReplace,
5719
- status: DraftActionStatus.Pending,
5720
- };
5721
- actionToReplace.status = DraftActionStatus.Pending;
5722
- actionToReplace.data = replacingAction.data;
5723
- return {
5724
- original: actionToReplaceCopy,
5725
- actionToReplace: actionToReplace,
5726
- replacingAction: replacingAction,
5727
- };
5682
+ if (this.isActionOfType(targetAction) &&
5683
+ this.isActionOfType(sourceAction)) {
5684
+ targetAction.status = DraftActionStatus.Pending;
5685
+ targetAction.data = sourceAction.data;
5686
+ return targetAction;
5728
5687
  }
5729
5688
  else {
5730
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
5731
- throw new Error('Incompatible Action types to replace one another');
5689
+ throw Error('Incompatible Action types to replace one another');
5732
5690
  }
5733
5691
  }
5692
+ mergeActions(targetAction, sourceAction) {
5693
+ const { id: targetId, data: targetData, metadata: targetMetadata, timestamp: targetTimestamp, } = targetAction;
5694
+ const { method: targetMethod, body: targetBody } = targetData;
5695
+ const { data: sourceData, metadata: sourceMetadata } = sourceAction;
5696
+ const { method: sourceMethod, body: sourceBody } = sourceData;
5697
+ if (targetMethod.toLowerCase() === 'delete' || sourceMethod.toLowerCase() === 'delete') {
5698
+ throw Error('Cannot merge DELETE actions.');
5699
+ }
5700
+ if (targetMethod.toLowerCase() === 'patch' && sourceMethod.toLowerCase() === 'post') {
5701
+ // overlaying a POST over a PATCH is not supported
5702
+ throw Error('Cannot merge a POST action over top of a PATCH action.');
5703
+ }
5704
+ // overlay top-level properties, maintain target's timestamp and id
5705
+ const merged = {
5706
+ ...targetAction,
5707
+ ...sourceAction,
5708
+ timestamp: targetTimestamp,
5709
+ id: targetId,
5710
+ };
5711
+ // overlay data
5712
+ // NOTE: we stick to the target's ResourceRequest properties (except body
5713
+ // which is merged) because we don't want to overwrite a POST with a PATCH
5714
+ // (all other cases should be fine or wouldn't have passed pre-requisites)
5715
+ merged.data = {
5716
+ ...targetData,
5717
+ body: this.mergeRequestBody(targetBody, sourceBody),
5718
+ };
5719
+ // overlay metadata
5720
+ merged.metadata = { ...targetMetadata, ...sourceMetadata };
5721
+ return merged;
5722
+ }
5734
5723
  shouldDeleteActionByTagOnRemoval(action) {
5735
5724
  return action.data.method === 'post';
5736
5725
  }
@@ -11581,68 +11570,17 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
11581
11570
  synchronousIngest(response) {
11582
11571
  return this.recordService.synchronousIngestRecord(response);
11583
11572
  }
11584
- mergeActions(targetAction, sourceAction) {
11585
- // NOTE: a lot of the logic in this method could be hoisted to the
11586
- // AbstractResourceRequestActionHandler, and then some new abstract mergeBody()
11587
- // method could be called there and implemented here. As of right now there
11588
- // are no other concrete ResourceRequest handlers implementing mergeActions
11589
- // so to keep this simple we aren't hoisting the shared stuff yet.
11590
- const { id: targetId, targetId: targetCacheKey, tag: targetTag, status: targetStatus, data: targetData, metadata: targetMetadata, timestamp: targetTimestamp, version: targetVersion, } = targetAction;
11591
- const { method: targetMethod, body: targetBody } = targetData;
11592
- const { targetId: sourceCacheKey, tag: sourceTag, status: sourceStatus, data: sourceData, metadata: sourceMetadata, version: sourceVersion, } = sourceAction;
11593
- const { method: sourceMethod, body: sourceBody } = sourceData;
11594
- // pre-requisites
11595
- if (targetCacheKey !== sourceCacheKey) {
11596
- throw Error('Cannot merge actions for different targetIds.');
11597
- }
11598
- if (targetTag !== sourceTag) {
11599
- throw Error('Cannot merge actions for different tags.');
11600
- }
11601
- if (targetStatus === DraftActionStatus.Completed ||
11602
- targetStatus === DraftActionStatus.Uploading) {
11603
- throw Error(`Cannot merge actions when targetAction is in ${targetStatus} status.`);
11604
- }
11605
- if (sourceStatus === DraftActionStatus.Completed ||
11606
- sourceStatus === DraftActionStatus.Uploading) {
11607
- throw Error(`Cannot merge actions when sourceAction is in ${sourceStatus} status.`);
11608
- }
11609
- if (targetMethod.toLowerCase() === 'delete' || sourceMethod.toLowerCase() === 'delete') {
11610
- throw Error('Cannot merge DELETE actions.');
11611
- }
11612
- if (targetMethod.toLowerCase() === 'patch' && sourceMethod.toLowerCase() === 'post') {
11613
- // overlaying a POST over a PATCH is not supported
11614
- throw Error('Cannot merge a POST action over top of a PATCH action.');
11615
- }
11616
- if (targetVersion !== sourceVersion) {
11617
- throw Error('Cannot merge actions with different versions.');
11618
- }
11619
- // overlay top-level properties, maintain target's timestamp and id
11620
- const merged = {
11621
- ...targetAction,
11622
- ...sourceAction,
11623
- timestamp: targetTimestamp,
11624
- id: targetId,
11625
- };
11626
- // overlay data
11573
+ mergeRequestBody(targetBody, sourceBody) {
11627
11574
  // IMPORTANT: spread operator isn't deep clone so we have to individually
11628
11575
  // spread nested objects (just "fields" for RecordInputReps)
11629
- // NOTE: we stick to the target's ResourceRequest properties (except body
11630
- // which is merged) because we don't want to overwrite a POST with a PATCH
11631
- // (all other cases should be fine or wouldn't have passed pre-requisites)
11632
- merged.data = {
11633
- ...targetData,
11634
- body: {
11635
- ...targetBody,
11636
- ...sourceBody,
11637
- fields: {
11638
- ...targetBody.fields,
11639
- ...sourceBody.fields,
11640
- },
11576
+ return {
11577
+ ...targetBody,
11578
+ ...sourceBody,
11579
+ fields: {
11580
+ ...targetBody.fields,
11581
+ ...sourceBody.fields,
11641
11582
  },
11642
11583
  };
11643
- // overlay metadata
11644
- merged.metadata = { ...targetMetadata, ...sourceMetadata };
11645
- return merged;
11646
11584
  }
11647
11585
  }
11648
11586
  function isField(key, data) {
@@ -12157,7 +12095,7 @@ class QuickActionExecutionRepresentationHandler extends AbstractResourceRequestA
12157
12095
  });
12158
12096
  luvio.storeIngest(key, ingestQuickActionExecutionRepresentation, response);
12159
12097
  }
12160
- mergeActions(_targetAction, _sourceAction) {
12098
+ mergeRequestBody() {
12161
12099
  throw Error('mergeActions not supported for QuickActionExecutionRepresentationHandler');
12162
12100
  }
12163
12101
  }
@@ -12844,7 +12782,7 @@ class ContentDocumentCompositeRepresentationActionHandler extends AbstractResour
12844
12782
  this.binaryStoreUrlsToUpdate.set(fileReference.handle, versionDataUrl);
12845
12783
  }
12846
12784
  }
12847
- mergeActions(_targetAction, _sourceAction) {
12785
+ mergeRequestBody() {
12848
12786
  throw Error('mergeActions not supported for ContentDocumentCompositeRepresentationActionHandler');
12849
12787
  }
12850
12788
  async ingestResponses(responses, action) {
@@ -15669,4 +15607,4 @@ register({
15669
15607
  });
15670
15608
 
15671
15609
  export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
15672
- // version: 1.124.4-f07bfc14d
15610
+ // version: 1.124.5-f65e6d350
@@ -19,7 +19,7 @@ export declare class NimbusDraftQueue implements DraftQueue {
19
19
  removeDraftAction(_actionId: string): Promise<void>;
20
20
  startQueue(): Promise<void>;
21
21
  stopQueue(): Promise<void>;
22
- replaceAction(_actionId: string, _withActionId: string): Promise<DraftAction<unknown, unknown>>;
22
+ replaceAction<Data, Response>(_actionId: string, _withActionId: string): Promise<DraftAction<Data, Response>>;
23
23
  mergeActions<Data, Response>(_targetActionId: string, _sourceActionId: string): Promise<DraftAction<Data, Response>>;
24
24
  setMetadata(_actionId: string, _metadata: DraftActionMetadata): Promise<DraftAction<unknown, unknown>>;
25
25
  addHandler(_handler: ActionHandler<unknown, unknown, unknown>): Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/lds-runtime-mobile",
3
- "version": "1.124.4",
3
+ "version": "1.124.5",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "description": "LDS runtime for mobile/hybrid environments.",
6
6
  "main": "dist/main.js",
package/sfdc/main.js CHANGED
@@ -4800,10 +4800,6 @@ function customActionHandler(executor, id, draftQueue) {
4800
4800
  });
4801
4801
  return queueOperations;
4802
4802
  };
4803
- const replaceAction = (actionId, _withActionId, _uploadingActionId, _actions) => {
4804
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
4805
- throw new Error(`${actionId} does not support action replacing. You can only delete ${actionId}`);
4806
- };
4807
4803
  const getRedirectMappings = (_action) => {
4808
4804
  return undefined;
4809
4805
  };
@@ -4815,7 +4811,9 @@ function customActionHandler(executor, id, draftQueue) {
4815
4811
  handleAction: handle,
4816
4812
  buildPendingAction,
4817
4813
  getQueueOperationsForCompletingDrafts: getQueueOperationsForCompletingDrafts,
4818
- handleReplaceAction: replaceAction,
4814
+ handleReplaceAction: () => {
4815
+ throw Error('replaceAction not supported for custom actions');
4816
+ },
4819
4817
  getRedirectMappings,
4820
4818
  handleActionRemoved: () => Promise.resolve(),
4821
4819
  handleActionCompleted: () => Promise.resolve(),
@@ -4882,13 +4880,13 @@ class DurableDraftQueue {
4882
4880
  this.userState = DraftQueueState.Started;
4883
4881
  if (this.state === DraftQueueState.Started) {
4884
4882
  // Do nothing if the queue state is already started
4885
- return Promise.resolve();
4883
+ return;
4886
4884
  }
4887
4885
  if (this.replacingAction !== undefined) {
4888
4886
  // If we're replacing an action do nothing
4889
4887
  // replace will restart the queue for us as long as the user
4890
4888
  // has last set the queue to be started
4891
- return Promise.resolve();
4889
+ return;
4892
4890
  }
4893
4891
  this.retryIntervalMilliseconds = 0;
4894
4892
  this.state = DraftQueueState.Started;
@@ -5128,92 +5126,11 @@ class DurableDraftQueue {
5128
5126
  await this.startQueue();
5129
5127
  }
5130
5128
  }
5131
- replaceAction(actionId, withActionId) {
5132
- // ids must be unique
5133
- if (actionId === withActionId) {
5134
- return Promise.reject('Swapped and swapping action ids cannot be the same');
5135
- }
5136
- // cannot have a replace action already in progress
5137
- if (this.replacingAction !== undefined) {
5138
- return Promise.reject('Cannot replace actions while a replace action is in progress');
5139
- }
5140
- this.stopQueueManually();
5141
- const replacing = this.getQueueActions().then(async (actions) => {
5142
- const first = actions.filter((action) => action.id === actionId)[0];
5143
- if (first === undefined) {
5144
- this.replacingAction = undefined;
5145
- await this.startQueueSafe();
5146
- return Promise.reject('No action to replace');
5147
- }
5148
- // put in a try/finally block so we don't leave this.replacingAction
5149
- // indefinitely set
5150
- let actionToReplace;
5151
- try {
5152
- const replaceResult = this.getHandler(first.handler).handleReplaceAction(actionId, withActionId, this.uploadingActionId, actions);
5153
- actionToReplace = replaceResult.actionToReplace;
5154
- // TODO [W-8873834]: Will add batching support to durable store
5155
- // we should use that here to remove and set both actions in one operation
5156
- await this.removeDraftAction(replaceResult.replacingAction.id);
5157
- await this.draftStore.writeAction(actionToReplace);
5158
- await this.notifyChangedListeners({
5159
- type: DraftQueueEventType.ActionUpdated,
5160
- action: actionToReplace,
5161
- });
5162
- }
5163
- finally {
5164
- this.replacingAction = undefined;
5165
- }
5166
- await this.startQueueSafe();
5167
- return actionToReplace;
5168
- });
5169
- this.replacingAction = replacing;
5170
- return replacing;
5129
+ replaceAction(targetActionId, sourceActionId) {
5130
+ return this.replaceOrMergeActions(targetActionId, sourceActionId, false);
5171
5131
  }
5172
5132
  mergeActions(targetActionId, sourceActionId) {
5173
- // ids must be unique
5174
- if (targetActionId === sourceActionId) {
5175
- return Promise.reject(new Error('targetActionId and sourceActionId cannot be the same.'));
5176
- }
5177
- // cannot have a replace action already in progress
5178
- if (this.replacingAction !== undefined) {
5179
- return Promise.reject(new Error('Cannot merge actions while a replace/merge action operation is in progress.'));
5180
- }
5181
- this.stopQueueManually();
5182
- const promise = this.getQueueActions().then(async (actions) => {
5183
- const target = actions.find((action) => action.id === targetActionId);
5184
- if (target === undefined) {
5185
- this.replacingAction = undefined;
5186
- await this.startQueueSafe();
5187
- throw Error('targetActionId not found in the draft queue.');
5188
- }
5189
- const source = actions.find((action) => action.id === sourceActionId);
5190
- if (source === undefined) {
5191
- this.replacingAction = undefined;
5192
- await this.startQueueSafe();
5193
- throw Error('sourceActionId not found in the draft queue.');
5194
- }
5195
- // put in a try/finally block so we don't leave this.replacingAction
5196
- // indefinitely set
5197
- let merged;
5198
- try {
5199
- merged = this.getHandler(target.handler).mergeActions(target, source);
5200
- // update the target
5201
- await this.draftStore.writeAction(merged);
5202
- await this.notifyChangedListeners({
5203
- type: DraftQueueEventType.ActionUpdated,
5204
- action: merged,
5205
- });
5206
- // remove the source from queue
5207
- await this.removeDraftAction(sourceActionId);
5208
- }
5209
- finally {
5210
- this.replacingAction = undefined;
5211
- }
5212
- await this.startQueueSafe();
5213
- return merged;
5214
- });
5215
- this.replacingAction = promise;
5216
- return promise;
5133
+ return this.replaceOrMergeActions(targetActionId, sourceActionId, true);
5217
5134
  }
5218
5135
  async setMetadata(actionId, metadata) {
5219
5136
  const keys$1 = keys$4(metadata);
@@ -5248,6 +5165,81 @@ class DurableDraftQueue {
5248
5165
  }
5249
5166
  }, this.retryIntervalMilliseconds);
5250
5167
  }
5168
+ async getActionsForReplaceOrMerge(targetActionId, sourceActionId) {
5169
+ const actions = await this.getQueueActions();
5170
+ const target = actions.find((action) => action.id === targetActionId);
5171
+ if (target === undefined) {
5172
+ this.replacingAction = undefined;
5173
+ await this.startQueueSafe();
5174
+ throw Error(`targetActionId ${targetActionId} not found in the draft queue.`);
5175
+ }
5176
+ const source = actions.find((action) => action.id === sourceActionId);
5177
+ if (source === undefined) {
5178
+ this.replacingAction = undefined;
5179
+ await this.startQueueSafe();
5180
+ throw Error(`sourceActionId ${sourceActionId} not found in the draft queue.`);
5181
+ }
5182
+ return { target, source };
5183
+ }
5184
+ assertReplaceOrMergePrerequisites(target, source) {
5185
+ // ensure actions are in a state to be replaced/merged
5186
+ const { targetId: targetCacheKey, tag: targetTag, status: targetStatus, version: targetVersion, } = target;
5187
+ const { targetId: sourceCacheKey, tag: sourceTag, status: sourceStatus, version: sourceVersion, } = source;
5188
+ if (targetCacheKey !== sourceCacheKey) {
5189
+ throw Error('Cannot replace/merge actions for different targetIds.');
5190
+ }
5191
+ if (targetTag !== sourceTag) {
5192
+ throw Error('Cannot replace/merge actions for different tags.');
5193
+ }
5194
+ if (targetStatus === DraftActionStatus.Completed ||
5195
+ targetStatus === DraftActionStatus.Uploading) {
5196
+ throw Error(`Cannot replace/merge actions when targetAction is in ${targetStatus} status.`);
5197
+ }
5198
+ if (sourceStatus !== DraftActionStatus.Pending) {
5199
+ throw Error(`Cannot replace/merge actions when sourceAction is in ${sourceStatus} status.`);
5200
+ }
5201
+ if (targetVersion !== sourceVersion) {
5202
+ throw Error('Cannot replace/merge actions with different versions.');
5203
+ }
5204
+ }
5205
+ async replaceOrMergeActions(targetActionId, sourceActionId, merge) {
5206
+ // ids must be unique
5207
+ if (targetActionId === sourceActionId) {
5208
+ throw Error('targetActionId and sourceActionId cannot be the same.');
5209
+ }
5210
+ // cannot have a replace action already in progress
5211
+ if (this.replacingAction !== undefined) {
5212
+ throw Error('Cannot replace/merge actions while a replace/merge action operation is in progress.');
5213
+ }
5214
+ this.stopQueueManually();
5215
+ const promise = this.getActionsForReplaceOrMerge(targetActionId, sourceActionId).then(async ({ target, source }) => {
5216
+ // put in a try/finally block so we don't leave this.replacingAction
5217
+ // indefinitely set
5218
+ let updatedTarget;
5219
+ try {
5220
+ this.assertReplaceOrMergePrerequisites(target, source);
5221
+ const handler = this.getHandler(target.handler);
5222
+ updatedTarget = merge
5223
+ ? handler.mergeActions(target, source)
5224
+ : handler.handleReplaceAction(target, source);
5225
+ // update the target
5226
+ await this.draftStore.writeAction(updatedTarget);
5227
+ await this.notifyChangedListeners({
5228
+ type: DraftQueueEventType.ActionUpdated,
5229
+ action: updatedTarget,
5230
+ });
5231
+ // remove the source from queue
5232
+ await this.removeDraftAction(sourceActionId);
5233
+ }
5234
+ finally {
5235
+ this.replacingAction = undefined;
5236
+ await this.startQueueSafe();
5237
+ }
5238
+ return updatedTarget;
5239
+ });
5240
+ this.replacingAction = promise;
5241
+ return promise;
5242
+ }
5251
5243
  }
5252
5244
 
5253
5245
  const DRAFT_ACTION_KEY_JUNCTION = '__DraftAction__';
@@ -5681,56 +5673,53 @@ class AbstractResourceRequestActionHandler {
5681
5673
  }
5682
5674
  await this.ingestResponses(recordsToIngest, action);
5683
5675
  }
5684
- handleReplaceAction(actionId, withActionId, uploadingActionId, actions) {
5685
- // get the action to replace
5686
- const actionToReplace = actions.filter((action) => action.id === actionId)[0];
5687
- // get the replacing action
5688
- const replacingAction = actions.filter((action) => action.id === withActionId)[0];
5689
- // reject if either action is undefined
5690
- if (actionToReplace === undefined || replacingAction === undefined) {
5691
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
5692
- throw new Error('One or both actions does not exist');
5693
- }
5694
- // reject if either action is uploading
5695
- if (actionToReplace.id === uploadingActionId || replacingAction.id === uploadingActionId) {
5696
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
5697
- throw new Error('Cannot replace an draft action that is uploading');
5698
- }
5699
- // reject if these two draft actions aren't acting on the same target
5700
- if (actionToReplace.tag !== replacingAction.tag) {
5701
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
5702
- throw new Error('Cannot swap actions targeting different targets');
5703
- }
5704
- // reject if the replacing action is not pending
5705
- if (replacingAction.status !== DraftActionStatus.Pending) {
5706
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
5707
- throw new Error('Cannot replace with a non-pending action');
5708
- }
5676
+ handleReplaceAction(targetAction, sourceAction) {
5709
5677
  //reject if the action to replace is a POST action
5710
- const pendingAction = actionToReplace;
5678
+ const pendingAction = targetAction;
5711
5679
  if (pendingAction.data.method === 'post') {
5712
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
5713
- throw new Error('Cannot replace a POST action');
5680
+ throw Error('Cannot replace a POST action');
5714
5681
  }
5715
- if (this.isActionOfType(actionToReplace) &&
5716
- this.isActionOfType(replacingAction)) {
5717
- const actionToReplaceCopy = {
5718
- ...actionToReplace,
5719
- status: DraftActionStatus.Pending,
5720
- };
5721
- actionToReplace.status = DraftActionStatus.Pending;
5722
- actionToReplace.data = replacingAction.data;
5723
- return {
5724
- original: actionToReplaceCopy,
5725
- actionToReplace: actionToReplace,
5726
- replacingAction: replacingAction,
5727
- };
5682
+ if (this.isActionOfType(targetAction) &&
5683
+ this.isActionOfType(sourceAction)) {
5684
+ targetAction.status = DraftActionStatus.Pending;
5685
+ targetAction.data = sourceAction.data;
5686
+ return targetAction;
5728
5687
  }
5729
5688
  else {
5730
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
5731
- throw new Error('Incompatible Action types to replace one another');
5689
+ throw Error('Incompatible Action types to replace one another');
5732
5690
  }
5733
5691
  }
5692
+ mergeActions(targetAction, sourceAction) {
5693
+ const { id: targetId, data: targetData, metadata: targetMetadata, timestamp: targetTimestamp, } = targetAction;
5694
+ const { method: targetMethod, body: targetBody } = targetData;
5695
+ const { data: sourceData, metadata: sourceMetadata } = sourceAction;
5696
+ const { method: sourceMethod, body: sourceBody } = sourceData;
5697
+ if (targetMethod.toLowerCase() === 'delete' || sourceMethod.toLowerCase() === 'delete') {
5698
+ throw Error('Cannot merge DELETE actions.');
5699
+ }
5700
+ if (targetMethod.toLowerCase() === 'patch' && sourceMethod.toLowerCase() === 'post') {
5701
+ // overlaying a POST over a PATCH is not supported
5702
+ throw Error('Cannot merge a POST action over top of a PATCH action.');
5703
+ }
5704
+ // overlay top-level properties, maintain target's timestamp and id
5705
+ const merged = {
5706
+ ...targetAction,
5707
+ ...sourceAction,
5708
+ timestamp: targetTimestamp,
5709
+ id: targetId,
5710
+ };
5711
+ // overlay data
5712
+ // NOTE: we stick to the target's ResourceRequest properties (except body
5713
+ // which is merged) because we don't want to overwrite a POST with a PATCH
5714
+ // (all other cases should be fine or wouldn't have passed pre-requisites)
5715
+ merged.data = {
5716
+ ...targetData,
5717
+ body: this.mergeRequestBody(targetBody, sourceBody),
5718
+ };
5719
+ // overlay metadata
5720
+ merged.metadata = { ...targetMetadata, ...sourceMetadata };
5721
+ return merged;
5722
+ }
5734
5723
  shouldDeleteActionByTagOnRemoval(action) {
5735
5724
  return action.data.method === 'post';
5736
5725
  }
@@ -11581,68 +11570,17 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
11581
11570
  synchronousIngest(response) {
11582
11571
  return this.recordService.synchronousIngestRecord(response);
11583
11572
  }
11584
- mergeActions(targetAction, sourceAction) {
11585
- // NOTE: a lot of the logic in this method could be hoisted to the
11586
- // AbstractResourceRequestActionHandler, and then some new abstract mergeBody()
11587
- // method could be called there and implemented here. As of right now there
11588
- // are no other concrete ResourceRequest handlers implementing mergeActions
11589
- // so to keep this simple we aren't hoisting the shared stuff yet.
11590
- const { id: targetId, targetId: targetCacheKey, tag: targetTag, status: targetStatus, data: targetData, metadata: targetMetadata, timestamp: targetTimestamp, version: targetVersion, } = targetAction;
11591
- const { method: targetMethod, body: targetBody } = targetData;
11592
- const { targetId: sourceCacheKey, tag: sourceTag, status: sourceStatus, data: sourceData, metadata: sourceMetadata, version: sourceVersion, } = sourceAction;
11593
- const { method: sourceMethod, body: sourceBody } = sourceData;
11594
- // pre-requisites
11595
- if (targetCacheKey !== sourceCacheKey) {
11596
- throw Error('Cannot merge actions for different targetIds.');
11597
- }
11598
- if (targetTag !== sourceTag) {
11599
- throw Error('Cannot merge actions for different tags.');
11600
- }
11601
- if (targetStatus === DraftActionStatus.Completed ||
11602
- targetStatus === DraftActionStatus.Uploading) {
11603
- throw Error(`Cannot merge actions when targetAction is in ${targetStatus} status.`);
11604
- }
11605
- if (sourceStatus === DraftActionStatus.Completed ||
11606
- sourceStatus === DraftActionStatus.Uploading) {
11607
- throw Error(`Cannot merge actions when sourceAction is in ${sourceStatus} status.`);
11608
- }
11609
- if (targetMethod.toLowerCase() === 'delete' || sourceMethod.toLowerCase() === 'delete') {
11610
- throw Error('Cannot merge DELETE actions.');
11611
- }
11612
- if (targetMethod.toLowerCase() === 'patch' && sourceMethod.toLowerCase() === 'post') {
11613
- // overlaying a POST over a PATCH is not supported
11614
- throw Error('Cannot merge a POST action over top of a PATCH action.');
11615
- }
11616
- if (targetVersion !== sourceVersion) {
11617
- throw Error('Cannot merge actions with different versions.');
11618
- }
11619
- // overlay top-level properties, maintain target's timestamp and id
11620
- const merged = {
11621
- ...targetAction,
11622
- ...sourceAction,
11623
- timestamp: targetTimestamp,
11624
- id: targetId,
11625
- };
11626
- // overlay data
11573
+ mergeRequestBody(targetBody, sourceBody) {
11627
11574
  // IMPORTANT: spread operator isn't deep clone so we have to individually
11628
11575
  // spread nested objects (just "fields" for RecordInputReps)
11629
- // NOTE: we stick to the target's ResourceRequest properties (except body
11630
- // which is merged) because we don't want to overwrite a POST with a PATCH
11631
- // (all other cases should be fine or wouldn't have passed pre-requisites)
11632
- merged.data = {
11633
- ...targetData,
11634
- body: {
11635
- ...targetBody,
11636
- ...sourceBody,
11637
- fields: {
11638
- ...targetBody.fields,
11639
- ...sourceBody.fields,
11640
- },
11576
+ return {
11577
+ ...targetBody,
11578
+ ...sourceBody,
11579
+ fields: {
11580
+ ...targetBody.fields,
11581
+ ...sourceBody.fields,
11641
11582
  },
11642
11583
  };
11643
- // overlay metadata
11644
- merged.metadata = { ...targetMetadata, ...sourceMetadata };
11645
- return merged;
11646
11584
  }
11647
11585
  }
11648
11586
  function isField(key, data) {
@@ -12157,7 +12095,7 @@ class QuickActionExecutionRepresentationHandler extends AbstractResourceRequestA
12157
12095
  });
12158
12096
  luvio.storeIngest(key, ingestQuickActionExecutionRepresentation, response);
12159
12097
  }
12160
- mergeActions(_targetAction, _sourceAction) {
12098
+ mergeRequestBody() {
12161
12099
  throw Error('mergeActions not supported for QuickActionExecutionRepresentationHandler');
12162
12100
  }
12163
12101
  }
@@ -12844,7 +12782,7 @@ class ContentDocumentCompositeRepresentationActionHandler extends AbstractResour
12844
12782
  this.binaryStoreUrlsToUpdate.set(fileReference.handle, versionDataUrl);
12845
12783
  }
12846
12784
  }
12847
- mergeActions(_targetAction, _sourceAction) {
12785
+ mergeRequestBody() {
12848
12786
  throw Error('mergeActions not supported for ContentDocumentCompositeRepresentationActionHandler');
12849
12787
  }
12850
12788
  async ingestResponses(responses, action) {
@@ -15669,4 +15607,4 @@ register({
15669
15607
  });
15670
15608
 
15671
15609
  export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
15672
- // version: 1.124.4-f07bfc14d
15610
+ // version: 1.124.5-f65e6d350
@@ -19,7 +19,7 @@ export declare class NimbusDraftQueue implements DraftQueue {
19
19
  removeDraftAction(_actionId: string): Promise<void>;
20
20
  startQueue(): Promise<void>;
21
21
  stopQueue(): Promise<void>;
22
- replaceAction(_actionId: string, _withActionId: string): Promise<DraftAction<unknown, unknown>>;
22
+ replaceAction<Data, Response>(_actionId: string, _withActionId: string): Promise<DraftAction<Data, Response>>;
23
23
  mergeActions<Data, Response>(_targetActionId: string, _sourceActionId: string): Promise<DraftAction<Data, Response>>;
24
24
  setMetadata(_actionId: string, _metadata: DraftActionMetadata): Promise<DraftAction<unknown, unknown>>;
25
25
  addHandler(_handler: ActionHandler<unknown, unknown, unknown>): Promise<void>;