@salesforce/lds-drafts 1.302.0 → 1.304.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.
package/dist/ldsDrafts.js CHANGED
@@ -669,7 +669,7 @@ class DurableDraftQueue {
669
669
  if (status === DraftActionStatus.Error) {
670
670
  this.state = DraftQueueState.Error;
671
671
  this.processingAction = undefined;
672
- this.notifyChangedListeners({
672
+ await this.notifyChangedListeners({
673
673
  type: DraftQueueEventType.ActionFailed,
674
674
  action: action,
675
675
  });
@@ -685,7 +685,7 @@ class DurableDraftQueue {
685
685
  if (this.state === DraftQueueState.Waiting) {
686
686
  this.state = DraftQueueState.Started;
687
687
  }
688
- this.notifyChangedListeners({
688
+ await this.notifyChangedListeners({
689
689
  type: DraftQueueEventType.ActionUploading,
690
690
  action: { ...action, status: DraftActionStatus.Uploading },
691
691
  });
@@ -762,6 +762,31 @@ class DurableDraftQueue {
762
762
  await this.startQueue();
763
763
  }
764
764
  }
765
+ async updateDraftAction(action) {
766
+ // stop queue manually
767
+ this.stopQueueManually();
768
+ const actionStatus = await this.statusOfAction(action.id);
769
+ if (actionStatus === DraftActionStatus.Uploading) {
770
+ return Promise.reject('cannot update an uploading action');
771
+ }
772
+ // save the action into the draft store
773
+ await this.draftStore.writeAction(action);
774
+ // make the handler replay these drafts on the record
775
+ const handler = this.getHandler(action.handler);
776
+ const queue = await this.getQueueActions();
777
+ await handler.handleActionEnqueued(action, queue);
778
+ // start queue safely
779
+ return this.startQueueSafe();
780
+ }
781
+ async statusOfAction(actionId) {
782
+ const queue = await this.getQueueActions();
783
+ const actions = queue.filter((action) => action.id === actionId);
784
+ if (actions.length === 0) {
785
+ return Promise.reject('cannot update non-existent action');
786
+ }
787
+ const action = actions[0];
788
+ return action.status;
789
+ }
765
790
  replaceAction(targetActionId, sourceActionId) {
766
791
  return this.replaceOrMergeActions(targetActionId, sourceActionId, false);
767
792
  }
@@ -792,17 +817,21 @@ class DurableDraftQueue {
792
817
  });
793
818
  return action;
794
819
  }
795
- scheduleRetryWithSpecifiedDelay(retryDelayInMs) {
820
+ async scheduleRetryWithSpecifiedDelay(retryDelayInMs) {
821
+ await this.notifyChangedListeners({
822
+ type: DraftQueueEventType.QueueStateChanged,
823
+ state: DraftQueueState.Waiting,
824
+ });
796
825
  this.timeoutHandler = setTimeout(() => {
797
826
  if (this.state !== DraftQueueState.Stopped) {
798
827
  this.processNextAction();
799
828
  }
800
829
  }, retryDelayInMs);
801
830
  }
802
- scheduleRetry() {
831
+ async scheduleRetry() {
803
832
  const newInterval = this.retryIntervalMilliseconds * 2;
804
833
  this.retryIntervalMilliseconds = Math.min(Math.max(newInterval, this.minimumRetryInterval), this.maximumRetryInterval);
805
- this.scheduleRetryWithSpecifiedDelay(this.retryIntervalMilliseconds);
834
+ return this.scheduleRetryWithSpecifiedDelay(this.retryIntervalMilliseconds);
806
835
  }
807
836
  async getActionsForReplaceOrMerge(targetActionId, sourceActionId) {
808
837
  const actions = await this.getQueueActions();
@@ -928,7 +957,8 @@ class DurableDraftStore {
928
957
  const actionArray = [];
929
958
  for (let i = 0, len = keys$1.length; i < len; i++) {
930
959
  const key = keys$1[i];
931
- actionArray.push(draftStore[key]);
960
+ // clone draft so we don't expose the internal draft store
961
+ actionArray.push(clone(draftStore[key]));
932
962
  }
933
963
  return actionArray;
934
964
  });
@@ -1577,6 +1607,7 @@ var DraftQueueOperationType;
1577
1607
  DraftQueueOperationType["ItemUpdated"] = "updated";
1578
1608
  DraftQueueOperationType["QueueStarted"] = "started";
1579
1609
  DraftQueueOperationType["QueueStopped"] = "stopped";
1610
+ DraftQueueOperationType["QueueWaiting"] = "waiting";
1580
1611
  })(DraftQueueOperationType || (DraftQueueOperationType = {}));
1581
1612
  /**
1582
1613
  * Converts the internal DraftAction's ResourceRequest into
@@ -1619,6 +1650,16 @@ function toQueueState(queue) {
1619
1650
  };
1620
1651
  }
1621
1652
  class DraftManager {
1653
+ shouldEmitEvent(event) {
1654
+ // Waiting events cannot be emitted prior to 252 native clients
1655
+ // TODO [W-16102411]: we can safely remove this backwards compatible code in 256
1656
+ if (isDraftQueueStateChangeEvent(event) &&
1657
+ event.state === DraftQueueState.Waiting &&
1658
+ this.listenerVersion === undefined) {
1659
+ return false;
1660
+ }
1661
+ return this.draftEventsShouldBeEmitted.includes(event.type);
1662
+ }
1622
1663
  constructor(draftQueue) {
1623
1664
  this.listeners = [];
1624
1665
  this.draftEventsShouldBeEmitted = [
@@ -1632,7 +1673,7 @@ class DraftManager {
1632
1673
  ];
1633
1674
  this.draftQueue = draftQueue;
1634
1675
  draftQueue.registerOnChangedListener((event) => {
1635
- if (this.draftEventsShouldBeEmitted.includes(event.type)) {
1676
+ if (this.shouldEmitEvent(event)) {
1636
1677
  return this.callListeners(event);
1637
1678
  }
1638
1679
  return Promise.resolve();
@@ -1662,6 +1703,8 @@ class DraftManager {
1662
1703
  return DraftQueueOperationType.QueueStarted;
1663
1704
  case DraftQueueState.Stopped:
1664
1705
  return DraftQueueOperationType.QueueStopped;
1706
+ case DraftQueueState.Waiting:
1707
+ return DraftQueueOperationType.QueueWaiting;
1665
1708
  default:
1666
1709
  throw Error('Unsupported event type');
1667
1710
  }
@@ -1719,7 +1762,8 @@ class DraftManager {
1719
1762
  *
1720
1763
  * @param listener The listener closure to subscribe to changes
1721
1764
  */
1722
- registerDraftQueueChangedListener(listener) {
1765
+ registerDraftQueueChangedListener(listener, version = undefined) {
1766
+ this.listenerVersion = version;
1723
1767
  this.listeners.push(listener);
1724
1768
  return () => {
1725
1769
  this.listeners = this.listeners.filter((l) => {
@@ -1746,6 +1790,60 @@ class DraftManager {
1746
1790
  };
1747
1791
  });
1748
1792
  }
1793
+ async mergePerformQuickAction(actionId, fields) {
1794
+ if (!this.isValidFieldMap(fields)) {
1795
+ return Promise.reject('fields is not valid');
1796
+ }
1797
+ const queue = await this.draftQueue.getQueueActions();
1798
+ const actions = queue.filter((action) => action.id === actionId);
1799
+ if (actions.length === 0) {
1800
+ return Promise.reject('cannot edit non-existent action');
1801
+ }
1802
+ const action = actions[0];
1803
+ if (!this.isPerformQuickActionDraft(action, 'post')) {
1804
+ return Promise.reject('cannot edit incompatible action type or uploading actions');
1805
+ }
1806
+ action.data.body.fields = { ...action.data.body.fields, ...fields };
1807
+ await this.draftQueue.updateDraftAction(action);
1808
+ return this.buildDraftQueueItem(action);
1809
+ }
1810
+ isValidFieldMap(fields) {
1811
+ const keys$1 = keys(fields);
1812
+ const validTypes = ['string', 'number', 'null', 'boolean'];
1813
+ for (let i = 0; i < keys$1.length; i++) {
1814
+ const key = keys$1[i];
1815
+ const value = fields[key];
1816
+ if (!validTypes.includes(typeof value)) {
1817
+ return false;
1818
+ }
1819
+ }
1820
+ return true;
1821
+ }
1822
+ isPerformQuickActionDraft(action, method) {
1823
+ const data = action.data;
1824
+ const isPerformQuickAction = data.basePath.startsWith('/ui-api/actions/perform-quick-action/');
1825
+ const methodMatches = data.method === method;
1826
+ const notUploading = action.status !== DraftActionStatus.Uploading;
1827
+ return isPerformQuickAction && methodMatches && notUploading;
1828
+ }
1829
+ async mergePerformUpdateRecordQuickAction(actionId, fields) {
1830
+ if (!this.isValidFieldMap(fields)) {
1831
+ return Promise.reject('fields is not valid');
1832
+ }
1833
+ const queue = await this.draftQueue.getQueueActions();
1834
+ const actions = queue.filter((action) => action.id === actionId);
1835
+ if (actions.length === 0) {
1836
+ return Promise.reject('cannot edit non-existent action');
1837
+ }
1838
+ const action = actions[0];
1839
+ if (!this.isPerformQuickActionDraft(action, 'patch')) {
1840
+ return Promise.reject('cannot edit incompatible action type or uploading actions');
1841
+ }
1842
+ const data = action.data;
1843
+ data.body.fields = { ...data.body.fields, ...fields };
1844
+ await this.draftQueue.updateDraftAction(action);
1845
+ return this.buildDraftQueueItem(action);
1846
+ }
1749
1847
  buildDraftQueueItem(action) {
1750
1848
  const operationType = getOperationTypeFrom(action);
1751
1849
  const { id, status, timestamp, targetId, metadata } = action;
@@ -1,6 +1,8 @@
1
1
  import type { CustomActionResult } from './actionHandlers/CustomActionHandler';
2
- import type { DraftActionStatus, DraftQueue, DraftActionMetadata } from './DraftQueue';
2
+ import type { DraftQueue, DraftAction, DraftActionMetadata, PendingDraftAction } from './DraftQueue';
3
+ import { DraftActionStatus } from './DraftQueue';
3
4
  import { DraftQueueState } from './DraftQueue';
5
+ import type { ResourceRequest } from '@luvio/engine';
4
6
  /**
5
7
  * Representation of the current state of the draft queue.
6
8
  * Includes the overall state as well as a list of draft
@@ -14,6 +16,9 @@ export type DraftQueueItemMetadata = {
14
16
  [key: string]: string;
15
17
  };
16
18
  export type DraftManagerCustomActionExecutor = (item: DraftQueueItem, completed: (result: CustomActionResult) => void) => void;
19
+ export type FieldMap = {
20
+ [key: string]: string | number | null | boolean;
21
+ };
17
22
  /**
18
23
  * An item in the draft queue that loosely maps to
19
24
  * a DraftAction
@@ -68,7 +73,8 @@ export declare enum DraftQueueOperationType {
68
73
  ItemFailed = "failed",
69
74
  ItemUpdated = "updated",
70
75
  QueueStarted = "started",
71
- QueueStopped = "stopped"
76
+ QueueStopped = "stopped",
77
+ QueueWaiting = "waiting"
72
78
  }
73
79
  /**
74
80
  * A closure that draft queue change listeners pass to
@@ -78,7 +84,9 @@ export declare type DraftQueueListener = (state: DraftManagerState, operationTyp
78
84
  export declare class DraftManager {
79
85
  private draftQueue;
80
86
  private listeners;
87
+ private listenerVersion;
81
88
  private draftEventsShouldBeEmitted;
89
+ private shouldEmitEvent;
82
90
  constructor(draftQueue: DraftQueue);
83
91
  private draftQueueEventTypeToOperationType;
84
92
  private draftQueueStateToOperationType;
@@ -113,7 +121,7 @@ export declare class DraftManager {
113
121
  *
114
122
  * @param listener The listener closure to subscribe to changes
115
123
  */
116
- registerDraftQueueChangedListener(listener: DraftQueueListener): () => Promise<void>;
124
+ registerDraftQueueChangedListener(listener: DraftQueueListener, version?: 252 | undefined): () => Promise<void>;
117
125
  /**
118
126
  * Creates a custom action handler for the given handler
119
127
  * @param handlerId
@@ -121,6 +129,10 @@ export declare class DraftManager {
121
129
  * @returns
122
130
  */
123
131
  setCustomActionExecutor(handlerId: string, executor: DraftManagerCustomActionExecutor): Promise<() => Promise<void>>;
132
+ mergePerformQuickAction(actionId: string, fields: FieldMap): Promise<DraftQueueItem>;
133
+ private isValidFieldMap;
134
+ isPerformQuickActionDraft(action: DraftAction<unknown, unknown>, method: string): action is PendingDraftAction<ResourceRequest>;
135
+ mergePerformUpdateRecordQuickAction(actionId: string, fields: FieldMap): Promise<DraftQueueItem>;
124
136
  private buildDraftQueueItem;
125
137
  private callListeners;
126
138
  /**
@@ -204,6 +204,13 @@ export interface DraftQueue {
204
204
  * @param actionId The action identifier
205
205
  */
206
206
  removeDraftAction(actionId: string): Promise<void>;
207
+ /**
208
+ * Saves the specified action into the queue, overwriting previous values
209
+ * of the action with the new ones
210
+ *
211
+ * @param action The action to update with the passed in values
212
+ */
213
+ updateDraftAction<Data, Response>(action: DraftAction<Data, Response>): Promise<void>;
207
214
  /**
208
215
  * Replaces the resource request of `withActionId` for the resource request
209
216
  * of `actionId`. Action ids cannot be equal. Both actions must be acting
@@ -1,4 +1,4 @@
1
- import type { DraftQueue, DraftAction, CompletedDraftAction, DraftQueueChangeListener, DraftActionMetadata, EnqueueResult } from './DraftQueue';
1
+ import type { DraftQueue, DraftAction, CompletedDraftAction, PendingDraftAction, DraftQueueChangeListener, DraftActionMetadata, EnqueueResult } from './DraftQueue';
2
2
  import { ProcessActionResult, DraftQueueState } from './DraftQueue';
3
3
  import type { CustomActionExecutor } from './actionHandlers/CustomActionHandler';
4
4
  import type { ActionHandler } from './actionHandlers/ActionHandler';
@@ -45,6 +45,8 @@ export declare class DurableDraftQueue implements DraftQueue {
45
45
  */
46
46
  private startQueueSafe;
47
47
  removeDraftAction(actionId: string): Promise<void>;
48
+ updateDraftAction<Data>(action: PendingDraftAction<Data>): Promise<void>;
49
+ private statusOfAction;
48
50
  replaceAction<Data, Response>(targetActionId: string, sourceActionId: string): Promise<DraftAction<Data, Response>>;
49
51
  mergeActions<Data, Response>(targetActionId: string, sourceActionId: string): Promise<DraftAction<Data, Response>>;
50
52
  setMetadata(actionId: string, metadata: DraftActionMetadata): Promise<DraftAction<unknown, unknown>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/lds-drafts",
3
- "version": "1.302.0",
3
+ "version": "1.304.0",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "description": "LDS Drafts",
6
6
  "main": "dist/ldsDrafts.js",
@@ -24,8 +24,11 @@
24
24
  "release:corejar": "yarn build && ../core-build/scripts/core.js --adapter=lds-drafts"
25
25
  },
26
26
  "dependencies": {
27
- "@luvio/engine": "0.155.1",
28
- "@luvio/environments": "0.155.1",
29
- "@salesforce/lds-utils-adapters": "^1.302.0"
27
+ "@luvio/engine": "0.156.3",
28
+ "@luvio/environments": "0.156.3",
29
+ "@salesforce/lds-utils-adapters": "^1.304.0"
30
+ },
31
+ "volta": {
32
+ "extends": "../../package.json"
30
33
  }
31
34
  }