@salesforce/lds-worker-api 1.100.3 → 1.100.4

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.
@@ -743,4 +743,4 @@ if (process.env.NODE_ENV !== 'production') {
743
743
  }
744
744
 
745
745
  export { createPrimingSession, draftManager, draftQueue, executeAdapter, executeMutatingAdapter, getImperativeAdapterNames, invokeAdapter, invokeAdapterWithDraftToReplace, invokeAdapterWithMetadata, nimbusDraftQueue, setMetadataTTL, setUiApiRecordTTL, subscribeToAdapter };
746
- // version: 1.100.3-8176c84f6
746
+ // version: 1.100.4-ce1be23b7
@@ -3776,7 +3776,7 @@ function withDefaultLuvio(callback) {
3776
3776
  }
3777
3777
  callbacks.push(callback);
3778
3778
  }
3779
- // version: 1.100.3-8176c84f6
3779
+ // version: 1.100.4-ce1be23b7
3780
3780
 
3781
3781
  // TODO [TD-0081508]: once that TD is fulfilled we can probably change this file
3782
3782
  function instrumentAdapter$1(createFunction, _metadata) {
@@ -15200,7 +15200,7 @@ function parseAndVisit(source) {
15200
15200
  updateReferenceMapWithKnownKey(ast, luvioDocumentNode);
15201
15201
  return luvioDocumentNode;
15202
15202
  }
15203
- // version: 1.100.3-8176c84f6
15203
+ // version: 1.100.4-ce1be23b7
15204
15204
 
15205
15205
  function unwrap(data) {
15206
15206
  // The lwc-luvio bindings import a function from lwc called "unwrap".
@@ -16081,7 +16081,7 @@ function createGraphQLWireAdapterConstructor(luvio, adapter, metadata) {
16081
16081
  const { apiFamily, name } = metadata;
16082
16082
  return createGraphQLWireAdapterConstructor$1(adapter, `${apiFamily}.${name}`, luvio, astResolver);
16083
16083
  }
16084
- // version: 1.100.3-8176c84f6
16084
+ // version: 1.100.4-ce1be23b7
16085
16085
 
16086
16086
  /**
16087
16087
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -43634,7 +43634,7 @@ withDefaultLuvio((luvio) => {
43634
43634
  dropFunction: instrumentation$2.notifyRecordUpdateAvailableDropped,
43635
43635
  });
43636
43636
  });
43637
- // version: 1.100.3-8176c84f6
43637
+ // version: 1.100.4-ce1be23b7
43638
43638
 
43639
43639
  var caseSensitiveUserId = '005B0000000GR4OIAW';
43640
43640
 
@@ -48006,6 +48006,44 @@ function makeStoreEval(preconditioner, objectInfoService, userId, contextProvide
48006
48006
  return wrapStartEndEvents(storeEval);
48007
48007
  }
48008
48008
 
48009
+ /**
48010
+ * Copyright (c) 2022, Salesforce, Inc.,
48011
+ * All rights reserved.
48012
+ * For full license text, see the LICENSE.txt file
48013
+ */
48014
+
48015
+ class AsyncWorkerPool {
48016
+ constructor(concurrency) {
48017
+ this.queue = [];
48018
+ this.activeWorkers = 0;
48019
+ this.concurrency = concurrency;
48020
+ }
48021
+ push(workFn) {
48022
+ return new Promise((resolve, reject) => {
48023
+ this.queue.push(async () => {
48024
+ return workFn().then(resolve).catch(reject);
48025
+ });
48026
+ this.work();
48027
+ });
48028
+ }
48029
+ cancel() {
48030
+ this.queue = [];
48031
+ // TODO [W-12513105]: thread cancellation through to active workers
48032
+ }
48033
+ work() {
48034
+ while (this.queue.length > 0 && this.activeWorkers < this.concurrency) {
48035
+ this.activeWorkers += 1;
48036
+ const next = this.queue.shift();
48037
+ if (next) {
48038
+ next().finally(() => {
48039
+ this.activeWorkers -= 1;
48040
+ this.work();
48041
+ });
48042
+ }
48043
+ }
48044
+ }
48045
+ }
48046
+
48009
48047
  /**
48010
48048
  * Copyright (c) 2022, Salesforce, Inc.,
48011
48049
  * All rights reserved.
@@ -48424,6 +48462,7 @@ class DurableDraftQueue {
48424
48462
  this.timeoutHandler = undefined;
48425
48463
  this.handlers = {};
48426
48464
  this.draftStore = draftStore;
48465
+ this.workerPool = new AsyncWorkerPool(1);
48427
48466
  }
48428
48467
  addHandler(handler) {
48429
48468
  const id = handler.handlerId;
@@ -48523,20 +48562,22 @@ class DurableDraftQueue {
48523
48562
  });
48524
48563
  }
48525
48564
  async enqueue(handlerId, data) {
48526
- let queue = await this.getQueueActions();
48527
- const handler = this.getHandler(handlerId);
48528
- const pendingAction = (await handler.buildPendingAction(data, queue));
48529
- await this.draftStore.writeAction(pendingAction);
48530
- queue = await this.getQueueActions();
48531
- await this.notifyChangedListeners({
48532
- type: DraftQueueEventType.ActionAdded,
48533
- action: pendingAction,
48565
+ return this.workerPool.push(async () => {
48566
+ let queue = await this.getQueueActions();
48567
+ const handler = this.getHandler(handlerId);
48568
+ const pendingAction = (await handler.buildPendingAction(data, queue));
48569
+ await this.draftStore.writeAction(pendingAction);
48570
+ queue = await this.getQueueActions();
48571
+ await this.notifyChangedListeners({
48572
+ type: DraftQueueEventType.ActionAdded,
48573
+ action: pendingAction,
48574
+ });
48575
+ await handler.handleActionEnqueued(pendingAction, queue);
48576
+ if (this.state === DraftQueueState.Started) {
48577
+ this.processNextAction();
48578
+ }
48579
+ return pendingAction;
48534
48580
  });
48535
- await handler.handleActionEnqueued(pendingAction, queue);
48536
- if (this.state === DraftQueueState.Started) {
48537
- this.processNextAction();
48538
- }
48539
- return pendingAction;
48540
48581
  }
48541
48582
  registerOnChangedListener(listener) {
48542
48583
  this.draftQueueChangedListeners.push(listener);
@@ -48548,27 +48589,29 @@ class DurableDraftQueue {
48548
48589
  };
48549
48590
  }
48550
48591
  async actionCompleted(action) {
48551
- const handler = this.getHandler(action.handler);
48552
- let queue = await this.getQueueActions();
48553
- const queueOperations = handler.getQueueOperationsForCompletingDrafts(queue, action);
48554
- const idAndKeyMappings = handler.getRedirectMappings(action);
48555
- const keyMappings = idAndKeyMappings === undefined
48556
- ? undefined
48557
- : idAndKeyMappings.map((m) => {
48558
- return { draftKey: m.draftKey, canonicalKey: m.canonicalKey };
48592
+ return this.workerPool.push(async () => {
48593
+ const handler = this.getHandler(action.handler);
48594
+ let queue = await this.getQueueActions();
48595
+ const queueOperations = handler.getQueueOperationsForCompletingDrafts(queue, action);
48596
+ const idAndKeyMappings = handler.getRedirectMappings(action);
48597
+ const keyMappings = idAndKeyMappings === undefined
48598
+ ? undefined
48599
+ : idAndKeyMappings.map((m) => {
48600
+ return { draftKey: m.draftKey, canonicalKey: m.canonicalKey };
48601
+ });
48602
+ await this.draftStore.completeAction(queueOperations, keyMappings);
48603
+ queue = await this.getQueueActions();
48604
+ this.retryIntervalMilliseconds = 0;
48605
+ this.uploadingActionId = undefined;
48606
+ await handler.handleActionCompleted(action, queueOperations, queue, values$1(this.handlers));
48607
+ await this.notifyChangedListeners({
48608
+ type: DraftQueueEventType.ActionCompleted,
48609
+ action,
48559
48610
  });
48560
- await this.draftStore.completeAction(queueOperations, keyMappings);
48561
- queue = await this.getQueueActions();
48562
- this.retryIntervalMilliseconds = 0;
48563
- this.uploadingActionId = undefined;
48564
- await handler.handleActionCompleted(action, queueOperations, queue, values$1(this.handlers));
48565
- await this.notifyChangedListeners({
48566
- type: DraftQueueEventType.ActionCompleted,
48567
- action,
48611
+ if (this.state === DraftQueueState.Started) {
48612
+ this.processNextAction();
48613
+ }
48568
48614
  });
48569
- if (this.state === DraftQueueState.Started) {
48570
- this.processNextAction();
48571
- }
48572
48615
  }
48573
48616
  async actionFailed(action, retry) {
48574
48617
  this.uploadingActionId = undefined;
@@ -49004,6 +49047,13 @@ class AbstractResourceRequestActionHandler {
49004
49047
  this.draftQueue = draftQueue;
49005
49048
  this.networkAdapter = networkAdapter;
49006
49049
  this.getLuvio = getLuvio;
49050
+ // NOTE[W-12567340]: This property stores in-memory mappings between draft
49051
+ // ids and canonical ids for the current session. Having a local copy of
49052
+ // these mappings is necessary to avoid a race condition between publishing
49053
+ // new mappings to the durable store and those mappings being loaded into
49054
+ // the luvio store redirect table, during which a new draft might be enqueued
49055
+ // which would not see a necessary mapping.
49056
+ this.ephemeralRedirects = {};
49007
49057
  }
49008
49058
  enqueue(data) {
49009
49059
  return this.draftQueue.enqueue(this.handlerId, data);
@@ -49071,7 +49121,8 @@ class AbstractResourceRequestActionHandler {
49071
49121
  }
49072
49122
  getQueueOperationsForCompletingDrafts(queue, action) {
49073
49123
  const queueOperations = [];
49074
- if (action.data.method === 'post') {
49124
+ const redirects = this.getRedirectMappings(action);
49125
+ if (redirects !== undefined) {
49075
49126
  const { length } = queue;
49076
49127
  for (let i = 0; i < length; i++) {
49077
49128
  const queueAction = queue[i];
@@ -49081,69 +49132,64 @@ class AbstractResourceRequestActionHandler {
49081
49132
  continue;
49082
49133
  }
49083
49134
  if (isResourceRequestAction(queueAction)) {
49084
- const redirects = this.getRedirectMappings(action);
49085
- if (redirects !== undefined) {
49086
- let queueOperationMutated = false;
49087
- let updatedActionTag = undefined;
49088
- let updatedActionTargetId = undefined;
49089
- const { tag: queueActionTag, data: queueActionRequest, id: queueActionId, } = queueAction;
49090
- let { basePath, body } = queueActionRequest;
49091
- let stringifiedBody = stringify$4(body);
49092
- // for each redirected ID/key we loop over the operation to see if it needs
49093
- // to be updated
49094
- for (const { draftId, draftKey, canonicalId, canonicalKey } of redirects) {
49095
- if (basePath.search(draftId) >= 0 ||
49096
- stringifiedBody.search(draftId) >= 0) {
49097
- basePath = basePath.replace(draftId, canonicalId);
49098
- stringifiedBody = stringifiedBody.replace(draftId, canonicalId);
49099
- queueOperationMutated = true;
49100
- }
49101
- // if the action is performed on a previous draft id, we need to replace the action
49102
- // with a new one at the updated canonical key
49103
- if (queueActionTag === draftKey) {
49104
- updatedActionTag = canonicalKey;
49105
- updatedActionTargetId = canonicalId;
49106
- }
49135
+ let queueOperationMutated = false;
49136
+ let updatedActionTag = undefined;
49137
+ let updatedActionTargetId = undefined;
49138
+ const { tag: queueActionTag, data: queueActionRequest, id: queueActionId, } = queueAction;
49139
+ let { basePath, body } = queueActionRequest;
49140
+ let stringifiedBody = stringify$4(body);
49141
+ // for each redirected ID/key we loop over the operation to see if it needs
49142
+ // to be updated
49143
+ for (const { draftId, draftKey, canonicalId, canonicalKey } of redirects) {
49144
+ if (basePath.search(draftId) >= 0 || stringifiedBody.search(draftId) >= 0) {
49145
+ basePath = basePath.replace(draftId, canonicalId);
49146
+ stringifiedBody = stringifiedBody.replace(draftId, canonicalId);
49147
+ queueOperationMutated = true;
49107
49148
  }
49108
- if (queueOperationMutated) {
49109
- if (updatedActionTag !== undefined &&
49110
- updatedActionTargetId !== undefined) {
49111
- const updatedAction = {
49112
- ...queueAction,
49113
- tag: updatedActionTag,
49114
- targetId: updatedActionTargetId,
49115
- data: {
49116
- ...queueActionRequest,
49117
- basePath: basePath,
49118
- body: parse$4(stringifiedBody),
49119
- },
49120
- };
49121
- // item needs to be replaced with a new item at the new record key
49122
- queueOperations.push({
49123
- type: QueueOperationType.Delete,
49124
- id: queueActionId,
49125
- });
49126
- queueOperations.push({
49127
- type: QueueOperationType.Add,
49128
- action: updatedAction,
49129
- });
49130
- }
49131
- else {
49132
- const updatedAction = {
49133
- ...queueAction,
49134
- data: {
49135
- ...queueActionRequest,
49136
- basePath: basePath,
49137
- body: parse$4(stringifiedBody),
49138
- },
49139
- };
49140
- // item needs to be updated
49141
- queueOperations.push({
49142
- type: QueueOperationType.Update,
49143
- id: queueActionId,
49144
- action: updatedAction,
49145
- });
49146
- }
49149
+ // if the action is performed on a previous draft id, we need to replace the action
49150
+ // with a new one at the updated canonical key
49151
+ if (queueActionTag === draftKey) {
49152
+ updatedActionTag = canonicalKey;
49153
+ updatedActionTargetId = canonicalId;
49154
+ }
49155
+ }
49156
+ if (queueOperationMutated) {
49157
+ if (updatedActionTag !== undefined && updatedActionTargetId !== undefined) {
49158
+ const updatedAction = {
49159
+ ...queueAction,
49160
+ tag: updatedActionTag,
49161
+ targetId: updatedActionTargetId,
49162
+ data: {
49163
+ ...queueActionRequest,
49164
+ basePath: basePath,
49165
+ body: parse$4(stringifiedBody),
49166
+ },
49167
+ };
49168
+ // item needs to be replaced with a new item at the new record key
49169
+ queueOperations.push({
49170
+ type: QueueOperationType.Delete,
49171
+ id: queueActionId,
49172
+ });
49173
+ queueOperations.push({
49174
+ type: QueueOperationType.Add,
49175
+ action: updatedAction,
49176
+ });
49177
+ }
49178
+ else {
49179
+ const updatedAction = {
49180
+ ...queueAction,
49181
+ data: {
49182
+ ...queueActionRequest,
49183
+ basePath: basePath,
49184
+ body: parse$4(stringifiedBody),
49185
+ },
49186
+ };
49187
+ // item needs to be updated
49188
+ queueOperations.push({
49189
+ type: QueueOperationType.Update,
49190
+ id: queueActionId,
49191
+ action: updatedAction,
49192
+ });
49147
49193
  }
49148
49194
  }
49149
49195
  }
@@ -49163,6 +49209,9 @@ class AbstractResourceRequestActionHandler {
49163
49209
  const body = action.response.body;
49164
49210
  const canonicalId = this.getIdFromResponseBody(body);
49165
49211
  const draftId = action.targetId;
49212
+ if (draftId !== undefined && canonicalId !== undefined && draftId !== canonicalId) {
49213
+ this.ephemeralRedirects[draftId] = canonicalId;
49214
+ }
49166
49215
  return [
49167
49216
  {
49168
49217
  draftId,
@@ -54944,12 +54993,18 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
54944
54993
  const fieldName = fieldNames[i];
54945
54994
  const fieldValue = bodyFields[fieldName];
54946
54995
  if (typeof fieldValue === 'string' && this.isDraftId(fieldValue)) {
54947
- const draftKey = this.buildTagForTargetId(fieldValue);
54948
- const canonicalKey = this.getLuvio().storeGetCanonicalKey(draftKey);
54949
- if (draftKey !== canonicalKey) {
54950
- const canonicalId = extractRecordIdFromStoreKey(canonicalKey);
54951
- if (canonicalId !== undefined) {
54952
- bodyFields[fieldName] = canonicalId;
54996
+ const canonicalId = this.ephemeralRedirects[fieldValue];
54997
+ if (canonicalId !== undefined) {
54998
+ bodyFields[fieldName] = canonicalId;
54999
+ }
55000
+ else {
55001
+ const draftKey = this.buildTagForTargetId(fieldValue);
55002
+ const canonicalKey = this.getLuvio().storeGetCanonicalKey(draftKey);
55003
+ if (draftKey !== canonicalKey) {
55004
+ const canonicalId = extractRecordIdFromStoreKey(canonicalKey);
55005
+ if (canonicalId !== undefined) {
55006
+ bodyFields[fieldName] = canonicalId;
55007
+ }
54953
55008
  }
54954
55009
  }
54955
55010
  }
@@ -54957,17 +55012,24 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
54957
55012
  }
54958
55013
  if (request.method === 'patch' || request.method === 'delete') {
54959
55014
  const recordId = request.urlParams['recordId'];
54960
- const recordKey = this.buildTagForTargetId(recordId);
54961
- const canonicalKey = this.getLuvio().storeGetCanonicalKey(recordKey);
54962
- if (recordKey !== canonicalKey) {
54963
- const canonicalId = extractRecordIdFromStoreKey(canonicalKey);
54964
- if (canonicalId === undefined) {
54965
- // could not resolve id from request -- return the request un-modified
54966
- return request;
54967
- }
55015
+ const canonicalId = this.ephemeralRedirects[recordId];
55016
+ if (canonicalId !== undefined) {
54968
55017
  resolvedBasePath = resolvedBasePath.replace(recordId, canonicalId);
54969
55018
  resolvedUrlParams = { ...resolvedUrlParams, recordId: canonicalId };
54970
55019
  }
55020
+ else {
55021
+ const recordKey = this.buildTagForTargetId(recordId);
55022
+ const canonicalKey = this.getLuvio().storeGetCanonicalKey(recordKey);
55023
+ if (recordKey !== canonicalKey) {
55024
+ const canonicalId = extractRecordIdFromStoreKey(canonicalKey);
55025
+ if (canonicalId === undefined) {
55026
+ // could not resolve id from request -- return the request un-modified
55027
+ return request;
55028
+ }
55029
+ resolvedBasePath = resolvedBasePath.replace(recordId, canonicalId);
55030
+ resolvedUrlParams = { ...resolvedUrlParams, recordId: canonicalId };
55031
+ }
55032
+ }
54971
55033
  }
54972
55034
  return {
54973
55035
  ...request,
@@ -58200,34 +58262,6 @@ function setupInspection(luvio) {
58200
58262
  * For full license text, see the LICENSE.txt file
58201
58263
  */
58202
58264
 
58203
- class AsyncWorkerPool {
58204
- constructor(concurrency) {
58205
- this.queue = [];
58206
- this.activeWorkers = 0;
58207
- this.concurrency = concurrency;
58208
- }
58209
- push(workFn) {
58210
- this.queue.push(workFn);
58211
- this.work();
58212
- }
58213
- cancel() {
58214
- this.queue = [];
58215
- // TODO [W-12513105]: thread cancellation through to active workers
58216
- }
58217
- work() {
58218
- while (this.queue.length > 0 && this.activeWorkers < this.concurrency) {
58219
- this.activeWorkers += 1;
58220
- const next = this.queue.shift();
58221
- if (next) {
58222
- next().finally(() => {
58223
- this.activeWorkers -= 1;
58224
- this.work();
58225
- });
58226
- }
58227
- }
58228
- }
58229
- }
58230
-
58231
58265
  class EventEmitter {
58232
58266
  constructor() {
58233
58267
  // @ts-ignore typescript doesn't like us setting this to an empty object for some reason
@@ -58776,7 +58810,7 @@ register({
58776
58810
  id: '@salesforce/lds-network-adapter',
58777
58811
  instrument: instrument$1,
58778
58812
  });
58779
- // version: 1.100.3-8176c84f6
58813
+ // version: 1.100.4-ce1be23b7
58780
58814
 
58781
58815
  const { create: create$2, keys: keys$2 } = Object;
58782
58816
  const { stringify: stringify$1, parse: parse$1 } = JSON;
@@ -76429,7 +76463,7 @@ register({
76429
76463
  configuration: { ...configurationForGraphQLAdapters },
76430
76464
  instrument,
76431
76465
  });
76432
- // version: 1.100.3-8176c84f6
76466
+ // version: 1.100.4-ce1be23b7
76433
76467
 
76434
76468
  // On core the unstable adapters are re-exported with different names,
76435
76469
 
@@ -78558,7 +78592,7 @@ withDefaultLuvio((luvio) => {
78558
78592
  unstable_graphQL_imperative = createImperativeAdapter(luvio, createInstrumentedAdapter(ldsAdapter, adapterMetadata), adapterMetadata);
78559
78593
  graphQLImperative = ldsAdapter;
78560
78594
  });
78561
- // version: 1.100.3-8176c84f6
78595
+ // version: 1.100.4-ce1be23b7
78562
78596
 
78563
78597
  var gqlApi = /*#__PURE__*/Object.freeze({
78564
78598
  __proto__: null,
@@ -79232,4 +79266,4 @@ const { luvio } = getRuntime();
79232
79266
  setDefaultLuvio({ luvio });
79233
79267
 
79234
79268
  export { createPrimingSession, draftManager, draftQueue, executeAdapter, executeMutatingAdapter, getImperativeAdapterNames, invokeAdapter, invokeAdapterWithDraftToReplace, invokeAdapterWithMetadata, nimbusDraftQueue, registerReportObserver, setMetadataTTL, setUiApiRecordTTL, subscribeToAdapter };
79235
- // version: 1.100.3-8176c84f6
79269
+ // version: 1.100.4-ce1be23b7
@@ -3782,7 +3782,7 @@
3782
3782
  }
3783
3783
  callbacks.push(callback);
3784
3784
  }
3785
- // version: 1.100.3-8176c84f6
3785
+ // version: 1.100.4-ce1be23b7
3786
3786
 
3787
3787
  // TODO [TD-0081508]: once that TD is fulfilled we can probably change this file
3788
3788
  function instrumentAdapter$1(createFunction, _metadata) {
@@ -15206,7 +15206,7 @@
15206
15206
  updateReferenceMapWithKnownKey(ast, luvioDocumentNode);
15207
15207
  return luvioDocumentNode;
15208
15208
  }
15209
- // version: 1.100.3-8176c84f6
15209
+ // version: 1.100.4-ce1be23b7
15210
15210
 
15211
15211
  function unwrap(data) {
15212
15212
  // The lwc-luvio bindings import a function from lwc called "unwrap".
@@ -16087,7 +16087,7 @@
16087
16087
  const { apiFamily, name } = metadata;
16088
16088
  return createGraphQLWireAdapterConstructor$1(adapter, `${apiFamily}.${name}`, luvio, astResolver);
16089
16089
  }
16090
- // version: 1.100.3-8176c84f6
16090
+ // version: 1.100.4-ce1be23b7
16091
16091
 
16092
16092
  /**
16093
16093
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -43640,7 +43640,7 @@
43640
43640
  dropFunction: instrumentation$2.notifyRecordUpdateAvailableDropped,
43641
43641
  });
43642
43642
  });
43643
- // version: 1.100.3-8176c84f6
43643
+ // version: 1.100.4-ce1be23b7
43644
43644
 
43645
43645
  var caseSensitiveUserId = '005B0000000GR4OIAW';
43646
43646
 
@@ -48012,6 +48012,44 @@
48012
48012
  return wrapStartEndEvents(storeEval);
48013
48013
  }
48014
48014
 
48015
+ /**
48016
+ * Copyright (c) 2022, Salesforce, Inc.,
48017
+ * All rights reserved.
48018
+ * For full license text, see the LICENSE.txt file
48019
+ */
48020
+
48021
+ class AsyncWorkerPool {
48022
+ constructor(concurrency) {
48023
+ this.queue = [];
48024
+ this.activeWorkers = 0;
48025
+ this.concurrency = concurrency;
48026
+ }
48027
+ push(workFn) {
48028
+ return new Promise((resolve, reject) => {
48029
+ this.queue.push(async () => {
48030
+ return workFn().then(resolve).catch(reject);
48031
+ });
48032
+ this.work();
48033
+ });
48034
+ }
48035
+ cancel() {
48036
+ this.queue = [];
48037
+ // TODO [W-12513105]: thread cancellation through to active workers
48038
+ }
48039
+ work() {
48040
+ while (this.queue.length > 0 && this.activeWorkers < this.concurrency) {
48041
+ this.activeWorkers += 1;
48042
+ const next = this.queue.shift();
48043
+ if (next) {
48044
+ next().finally(() => {
48045
+ this.activeWorkers -= 1;
48046
+ this.work();
48047
+ });
48048
+ }
48049
+ }
48050
+ }
48051
+ }
48052
+
48015
48053
  /**
48016
48054
  * Copyright (c) 2022, Salesforce, Inc.,
48017
48055
  * All rights reserved.
@@ -48430,6 +48468,7 @@
48430
48468
  this.timeoutHandler = undefined;
48431
48469
  this.handlers = {};
48432
48470
  this.draftStore = draftStore;
48471
+ this.workerPool = new AsyncWorkerPool(1);
48433
48472
  }
48434
48473
  addHandler(handler) {
48435
48474
  const id = handler.handlerId;
@@ -48529,20 +48568,22 @@
48529
48568
  });
48530
48569
  }
48531
48570
  async enqueue(handlerId, data) {
48532
- let queue = await this.getQueueActions();
48533
- const handler = this.getHandler(handlerId);
48534
- const pendingAction = (await handler.buildPendingAction(data, queue));
48535
- await this.draftStore.writeAction(pendingAction);
48536
- queue = await this.getQueueActions();
48537
- await this.notifyChangedListeners({
48538
- type: DraftQueueEventType.ActionAdded,
48539
- action: pendingAction,
48571
+ return this.workerPool.push(async () => {
48572
+ let queue = await this.getQueueActions();
48573
+ const handler = this.getHandler(handlerId);
48574
+ const pendingAction = (await handler.buildPendingAction(data, queue));
48575
+ await this.draftStore.writeAction(pendingAction);
48576
+ queue = await this.getQueueActions();
48577
+ await this.notifyChangedListeners({
48578
+ type: DraftQueueEventType.ActionAdded,
48579
+ action: pendingAction,
48580
+ });
48581
+ await handler.handleActionEnqueued(pendingAction, queue);
48582
+ if (this.state === DraftQueueState.Started) {
48583
+ this.processNextAction();
48584
+ }
48585
+ return pendingAction;
48540
48586
  });
48541
- await handler.handleActionEnqueued(pendingAction, queue);
48542
- if (this.state === DraftQueueState.Started) {
48543
- this.processNextAction();
48544
- }
48545
- return pendingAction;
48546
48587
  }
48547
48588
  registerOnChangedListener(listener) {
48548
48589
  this.draftQueueChangedListeners.push(listener);
@@ -48554,27 +48595,29 @@
48554
48595
  };
48555
48596
  }
48556
48597
  async actionCompleted(action) {
48557
- const handler = this.getHandler(action.handler);
48558
- let queue = await this.getQueueActions();
48559
- const queueOperations = handler.getQueueOperationsForCompletingDrafts(queue, action);
48560
- const idAndKeyMappings = handler.getRedirectMappings(action);
48561
- const keyMappings = idAndKeyMappings === undefined
48562
- ? undefined
48563
- : idAndKeyMappings.map((m) => {
48564
- return { draftKey: m.draftKey, canonicalKey: m.canonicalKey };
48598
+ return this.workerPool.push(async () => {
48599
+ const handler = this.getHandler(action.handler);
48600
+ let queue = await this.getQueueActions();
48601
+ const queueOperations = handler.getQueueOperationsForCompletingDrafts(queue, action);
48602
+ const idAndKeyMappings = handler.getRedirectMappings(action);
48603
+ const keyMappings = idAndKeyMappings === undefined
48604
+ ? undefined
48605
+ : idAndKeyMappings.map((m) => {
48606
+ return { draftKey: m.draftKey, canonicalKey: m.canonicalKey };
48607
+ });
48608
+ await this.draftStore.completeAction(queueOperations, keyMappings);
48609
+ queue = await this.getQueueActions();
48610
+ this.retryIntervalMilliseconds = 0;
48611
+ this.uploadingActionId = undefined;
48612
+ await handler.handleActionCompleted(action, queueOperations, queue, values$1(this.handlers));
48613
+ await this.notifyChangedListeners({
48614
+ type: DraftQueueEventType.ActionCompleted,
48615
+ action,
48565
48616
  });
48566
- await this.draftStore.completeAction(queueOperations, keyMappings);
48567
- queue = await this.getQueueActions();
48568
- this.retryIntervalMilliseconds = 0;
48569
- this.uploadingActionId = undefined;
48570
- await handler.handleActionCompleted(action, queueOperations, queue, values$1(this.handlers));
48571
- await this.notifyChangedListeners({
48572
- type: DraftQueueEventType.ActionCompleted,
48573
- action,
48617
+ if (this.state === DraftQueueState.Started) {
48618
+ this.processNextAction();
48619
+ }
48574
48620
  });
48575
- if (this.state === DraftQueueState.Started) {
48576
- this.processNextAction();
48577
- }
48578
48621
  }
48579
48622
  async actionFailed(action, retry) {
48580
48623
  this.uploadingActionId = undefined;
@@ -49010,6 +49053,13 @@
49010
49053
  this.draftQueue = draftQueue;
49011
49054
  this.networkAdapter = networkAdapter;
49012
49055
  this.getLuvio = getLuvio;
49056
+ // NOTE[W-12567340]: This property stores in-memory mappings between draft
49057
+ // ids and canonical ids for the current session. Having a local copy of
49058
+ // these mappings is necessary to avoid a race condition between publishing
49059
+ // new mappings to the durable store and those mappings being loaded into
49060
+ // the luvio store redirect table, during which a new draft might be enqueued
49061
+ // which would not see a necessary mapping.
49062
+ this.ephemeralRedirects = {};
49013
49063
  }
49014
49064
  enqueue(data) {
49015
49065
  return this.draftQueue.enqueue(this.handlerId, data);
@@ -49077,7 +49127,8 @@
49077
49127
  }
49078
49128
  getQueueOperationsForCompletingDrafts(queue, action) {
49079
49129
  const queueOperations = [];
49080
- if (action.data.method === 'post') {
49130
+ const redirects = this.getRedirectMappings(action);
49131
+ if (redirects !== undefined) {
49081
49132
  const { length } = queue;
49082
49133
  for (let i = 0; i < length; i++) {
49083
49134
  const queueAction = queue[i];
@@ -49087,69 +49138,64 @@
49087
49138
  continue;
49088
49139
  }
49089
49140
  if (isResourceRequestAction(queueAction)) {
49090
- const redirects = this.getRedirectMappings(action);
49091
- if (redirects !== undefined) {
49092
- let queueOperationMutated = false;
49093
- let updatedActionTag = undefined;
49094
- let updatedActionTargetId = undefined;
49095
- const { tag: queueActionTag, data: queueActionRequest, id: queueActionId, } = queueAction;
49096
- let { basePath, body } = queueActionRequest;
49097
- let stringifiedBody = stringify$4(body);
49098
- // for each redirected ID/key we loop over the operation to see if it needs
49099
- // to be updated
49100
- for (const { draftId, draftKey, canonicalId, canonicalKey } of redirects) {
49101
- if (basePath.search(draftId) >= 0 ||
49102
- stringifiedBody.search(draftId) >= 0) {
49103
- basePath = basePath.replace(draftId, canonicalId);
49104
- stringifiedBody = stringifiedBody.replace(draftId, canonicalId);
49105
- queueOperationMutated = true;
49106
- }
49107
- // if the action is performed on a previous draft id, we need to replace the action
49108
- // with a new one at the updated canonical key
49109
- if (queueActionTag === draftKey) {
49110
- updatedActionTag = canonicalKey;
49111
- updatedActionTargetId = canonicalId;
49112
- }
49141
+ let queueOperationMutated = false;
49142
+ let updatedActionTag = undefined;
49143
+ let updatedActionTargetId = undefined;
49144
+ const { tag: queueActionTag, data: queueActionRequest, id: queueActionId, } = queueAction;
49145
+ let { basePath, body } = queueActionRequest;
49146
+ let stringifiedBody = stringify$4(body);
49147
+ // for each redirected ID/key we loop over the operation to see if it needs
49148
+ // to be updated
49149
+ for (const { draftId, draftKey, canonicalId, canonicalKey } of redirects) {
49150
+ if (basePath.search(draftId) >= 0 || stringifiedBody.search(draftId) >= 0) {
49151
+ basePath = basePath.replace(draftId, canonicalId);
49152
+ stringifiedBody = stringifiedBody.replace(draftId, canonicalId);
49153
+ queueOperationMutated = true;
49113
49154
  }
49114
- if (queueOperationMutated) {
49115
- if (updatedActionTag !== undefined &&
49116
- updatedActionTargetId !== undefined) {
49117
- const updatedAction = {
49118
- ...queueAction,
49119
- tag: updatedActionTag,
49120
- targetId: updatedActionTargetId,
49121
- data: {
49122
- ...queueActionRequest,
49123
- basePath: basePath,
49124
- body: parse$4(stringifiedBody),
49125
- },
49126
- };
49127
- // item needs to be replaced with a new item at the new record key
49128
- queueOperations.push({
49129
- type: QueueOperationType.Delete,
49130
- id: queueActionId,
49131
- });
49132
- queueOperations.push({
49133
- type: QueueOperationType.Add,
49134
- action: updatedAction,
49135
- });
49136
- }
49137
- else {
49138
- const updatedAction = {
49139
- ...queueAction,
49140
- data: {
49141
- ...queueActionRequest,
49142
- basePath: basePath,
49143
- body: parse$4(stringifiedBody),
49144
- },
49145
- };
49146
- // item needs to be updated
49147
- queueOperations.push({
49148
- type: QueueOperationType.Update,
49149
- id: queueActionId,
49150
- action: updatedAction,
49151
- });
49152
- }
49155
+ // if the action is performed on a previous draft id, we need to replace the action
49156
+ // with a new one at the updated canonical key
49157
+ if (queueActionTag === draftKey) {
49158
+ updatedActionTag = canonicalKey;
49159
+ updatedActionTargetId = canonicalId;
49160
+ }
49161
+ }
49162
+ if (queueOperationMutated) {
49163
+ if (updatedActionTag !== undefined && updatedActionTargetId !== undefined) {
49164
+ const updatedAction = {
49165
+ ...queueAction,
49166
+ tag: updatedActionTag,
49167
+ targetId: updatedActionTargetId,
49168
+ data: {
49169
+ ...queueActionRequest,
49170
+ basePath: basePath,
49171
+ body: parse$4(stringifiedBody),
49172
+ },
49173
+ };
49174
+ // item needs to be replaced with a new item at the new record key
49175
+ queueOperations.push({
49176
+ type: QueueOperationType.Delete,
49177
+ id: queueActionId,
49178
+ });
49179
+ queueOperations.push({
49180
+ type: QueueOperationType.Add,
49181
+ action: updatedAction,
49182
+ });
49183
+ }
49184
+ else {
49185
+ const updatedAction = {
49186
+ ...queueAction,
49187
+ data: {
49188
+ ...queueActionRequest,
49189
+ basePath: basePath,
49190
+ body: parse$4(stringifiedBody),
49191
+ },
49192
+ };
49193
+ // item needs to be updated
49194
+ queueOperations.push({
49195
+ type: QueueOperationType.Update,
49196
+ id: queueActionId,
49197
+ action: updatedAction,
49198
+ });
49153
49199
  }
49154
49200
  }
49155
49201
  }
@@ -49169,6 +49215,9 @@
49169
49215
  const body = action.response.body;
49170
49216
  const canonicalId = this.getIdFromResponseBody(body);
49171
49217
  const draftId = action.targetId;
49218
+ if (draftId !== undefined && canonicalId !== undefined && draftId !== canonicalId) {
49219
+ this.ephemeralRedirects[draftId] = canonicalId;
49220
+ }
49172
49221
  return [
49173
49222
  {
49174
49223
  draftId,
@@ -54950,12 +54999,18 @@
54950
54999
  const fieldName = fieldNames[i];
54951
55000
  const fieldValue = bodyFields[fieldName];
54952
55001
  if (typeof fieldValue === 'string' && this.isDraftId(fieldValue)) {
54953
- const draftKey = this.buildTagForTargetId(fieldValue);
54954
- const canonicalKey = this.getLuvio().storeGetCanonicalKey(draftKey);
54955
- if (draftKey !== canonicalKey) {
54956
- const canonicalId = extractRecordIdFromStoreKey(canonicalKey);
54957
- if (canonicalId !== undefined) {
54958
- bodyFields[fieldName] = canonicalId;
55002
+ const canonicalId = this.ephemeralRedirects[fieldValue];
55003
+ if (canonicalId !== undefined) {
55004
+ bodyFields[fieldName] = canonicalId;
55005
+ }
55006
+ else {
55007
+ const draftKey = this.buildTagForTargetId(fieldValue);
55008
+ const canonicalKey = this.getLuvio().storeGetCanonicalKey(draftKey);
55009
+ if (draftKey !== canonicalKey) {
55010
+ const canonicalId = extractRecordIdFromStoreKey(canonicalKey);
55011
+ if (canonicalId !== undefined) {
55012
+ bodyFields[fieldName] = canonicalId;
55013
+ }
54959
55014
  }
54960
55015
  }
54961
55016
  }
@@ -54963,17 +55018,24 @@
54963
55018
  }
54964
55019
  if (request.method === 'patch' || request.method === 'delete') {
54965
55020
  const recordId = request.urlParams['recordId'];
54966
- const recordKey = this.buildTagForTargetId(recordId);
54967
- const canonicalKey = this.getLuvio().storeGetCanonicalKey(recordKey);
54968
- if (recordKey !== canonicalKey) {
54969
- const canonicalId = extractRecordIdFromStoreKey(canonicalKey);
54970
- if (canonicalId === undefined) {
54971
- // could not resolve id from request -- return the request un-modified
54972
- return request;
54973
- }
55021
+ const canonicalId = this.ephemeralRedirects[recordId];
55022
+ if (canonicalId !== undefined) {
54974
55023
  resolvedBasePath = resolvedBasePath.replace(recordId, canonicalId);
54975
55024
  resolvedUrlParams = { ...resolvedUrlParams, recordId: canonicalId };
54976
55025
  }
55026
+ else {
55027
+ const recordKey = this.buildTagForTargetId(recordId);
55028
+ const canonicalKey = this.getLuvio().storeGetCanonicalKey(recordKey);
55029
+ if (recordKey !== canonicalKey) {
55030
+ const canonicalId = extractRecordIdFromStoreKey(canonicalKey);
55031
+ if (canonicalId === undefined) {
55032
+ // could not resolve id from request -- return the request un-modified
55033
+ return request;
55034
+ }
55035
+ resolvedBasePath = resolvedBasePath.replace(recordId, canonicalId);
55036
+ resolvedUrlParams = { ...resolvedUrlParams, recordId: canonicalId };
55037
+ }
55038
+ }
54977
55039
  }
54978
55040
  return {
54979
55041
  ...request,
@@ -58206,34 +58268,6 @@
58206
58268
  * For full license text, see the LICENSE.txt file
58207
58269
  */
58208
58270
 
58209
- class AsyncWorkerPool {
58210
- constructor(concurrency) {
58211
- this.queue = [];
58212
- this.activeWorkers = 0;
58213
- this.concurrency = concurrency;
58214
- }
58215
- push(workFn) {
58216
- this.queue.push(workFn);
58217
- this.work();
58218
- }
58219
- cancel() {
58220
- this.queue = [];
58221
- // TODO [W-12513105]: thread cancellation through to active workers
58222
- }
58223
- work() {
58224
- while (this.queue.length > 0 && this.activeWorkers < this.concurrency) {
58225
- this.activeWorkers += 1;
58226
- const next = this.queue.shift();
58227
- if (next) {
58228
- next().finally(() => {
58229
- this.activeWorkers -= 1;
58230
- this.work();
58231
- });
58232
- }
58233
- }
58234
- }
58235
- }
58236
-
58237
58271
  class EventEmitter {
58238
58272
  constructor() {
58239
58273
  // @ts-ignore typescript doesn't like us setting this to an empty object for some reason
@@ -58782,7 +58816,7 @@
58782
58816
  id: '@salesforce/lds-network-adapter',
58783
58817
  instrument: instrument$1,
58784
58818
  });
58785
- // version: 1.100.3-8176c84f6
58819
+ // version: 1.100.4-ce1be23b7
58786
58820
 
58787
58821
  const { create: create$2, keys: keys$2 } = Object;
58788
58822
  const { stringify: stringify$1, parse: parse$1 } = JSON;
@@ -76435,7 +76469,7 @@
76435
76469
  configuration: { ...configurationForGraphQLAdapters },
76436
76470
  instrument,
76437
76471
  });
76438
- // version: 1.100.3-8176c84f6
76472
+ // version: 1.100.4-ce1be23b7
76439
76473
 
76440
76474
  // On core the unstable adapters are re-exported with different names,
76441
76475
 
@@ -78564,7 +78598,7 @@
78564
78598
  unstable_graphQL_imperative = createImperativeAdapter(luvio, createInstrumentedAdapter(ldsAdapter, adapterMetadata), adapterMetadata);
78565
78599
  graphQLImperative = ldsAdapter;
78566
78600
  });
78567
- // version: 1.100.3-8176c84f6
78601
+ // version: 1.100.4-ce1be23b7
78568
78602
 
78569
78603
  var gqlApi = /*#__PURE__*/Object.freeze({
78570
78604
  __proto__: null,
@@ -79255,4 +79289,4 @@
79255
79289
  Object.defineProperty(exports, '__esModule', { value: true });
79256
79290
 
79257
79291
  }));
79258
- // version: 1.100.3-8176c84f6
79292
+ // version: 1.100.4-ce1be23b7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/lds-worker-api",
3
- "version": "1.100.3",
3
+ "version": "1.100.4",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "description": "",
6
6
  "main": "dist/standalone/umd/lds-worker-api.js",
@@ -37,15 +37,15 @@
37
37
  "@luvio/engine": "0.135.4",
38
38
  "@luvio/environments": "0.135.4",
39
39
  "@oat-sa/rollup-plugin-wildcard-external": "^0.1.0",
40
- "@salesforce/lds-adapters-graphql": "^1.100.3",
41
- "@salesforce/lds-adapters-uiapi": "^1.100.3",
42
- "@salesforce/lds-default-luvio": "^1.100.3",
43
- "@salesforce/lds-drafts": "^1.100.3",
44
- "@salesforce/lds-graphql-parser": "^1.100.3",
45
- "@salesforce/lds-luvio-engine": "^1.100.3",
46
- "@salesforce/lds-priming": "^1.100.3",
47
- "@salesforce/lds-runtime-mobile": "^1.100.3",
48
- "@salesforce/nimbus-plugin-lds": "^1.100.3",
40
+ "@salesforce/lds-adapters-graphql": "^1.100.4",
41
+ "@salesforce/lds-adapters-uiapi": "^1.100.4",
42
+ "@salesforce/lds-default-luvio": "^1.100.4",
43
+ "@salesforce/lds-drafts": "^1.100.4",
44
+ "@salesforce/lds-graphql-parser": "^1.100.4",
45
+ "@salesforce/lds-luvio-engine": "^1.100.4",
46
+ "@salesforce/lds-priming": "^1.100.4",
47
+ "@salesforce/lds-runtime-mobile": "^1.100.4",
48
+ "@salesforce/nimbus-plugin-lds": "^1.100.4",
49
49
  "ajv": "^8.11.0",
50
50
  "glob": "^7.1.5",
51
51
  "nimbus-types": "^2.0.0-alpha1",