@salesforce/lds-worker-api 1.100.2 → 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.2-ca56bb821
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.2-ca56bb821
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.2-ca56bb821
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.2-ca56bb821
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.2-ca56bb821
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,
@@ -53868,7 +53917,8 @@ const assignedToMeFragmentSelections = [
53868
53917
  },
53869
53918
  ];
53870
53919
  function removeSyntheticFields(result, query) {
53871
- const connectionSelection = query.definitions
53920
+ // It is possible that there are multiple record query.
53921
+ const connectionSelections = query.definitions
53872
53922
  .filter(isOperationDefinitionNode)
53873
53923
  .reduce((accu, definition) => {
53874
53924
  return accu.concat(definition.selectionSet.selections);
@@ -53879,10 +53929,12 @@ function removeSyntheticFields(result, query) {
53879
53929
  .filter(isFieldNode)
53880
53930
  .filter(nodeIsNamed('query'))
53881
53931
  .reduce(extractSelections, [])
53882
- .filter(isFieldNode)[0];
53932
+ .filter(isFieldNode);
53883
53933
  // queries that are not RecordQuery will be undefined here.
53884
- // we need to also check that connectionSelection is not undefined.
53885
- if (!connectionSelection || !connectionSelection.selectionSet) {
53934
+ // we need to also check that connectionSelections are not undefined. If any connectionSelection has no `selectionSet` defined, that is a malformed query.
53935
+ if (!connectionSelections ||
53936
+ connectionSelections.length === 0 ||
53937
+ connectionSelections.some((connection) => connection.selectionSet === undefined)) {
53886
53938
  return result;
53887
53939
  }
53888
53940
  const nodeJson = result.data.uiapi.query;
@@ -53891,10 +53943,15 @@ function removeSyntheticFields(result, query) {
53891
53943
  const output = { ...result };
53892
53944
  const outputApiParent = output.data.uiapi.query;
53893
53945
  const keys$1 = keys$3(nodeJson);
53894
- keys$1.forEach((apiName) => {
53946
+ keys$1.forEach((recordName) => {
53895
53947
  const outputApi = {};
53896
- createUserJsonOutput(connectionSelection, nodeJson[apiName], outputApi);
53897
- outputApiParent[apiName] = outputApi;
53948
+ // Each connectionSelection's maps its name or alias to one of returned records. The record name could be `apiName' or alias
53949
+ const targetConnection = connectionSelections.find((connection) => connection.name.value === recordName ||
53950
+ (connection.alias !== undefined && connection.alias.value === recordName));
53951
+ if (targetConnection !== undefined) {
53952
+ createUserJsonOutput(targetConnection, nodeJson[recordName], outputApi);
53953
+ outputApiParent[recordName] = outputApi;
53954
+ }
53898
53955
  });
53899
53956
  return output;
53900
53957
  }
@@ -54936,12 +54993,18 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
54936
54993
  const fieldName = fieldNames[i];
54937
54994
  const fieldValue = bodyFields[fieldName];
54938
54995
  if (typeof fieldValue === 'string' && this.isDraftId(fieldValue)) {
54939
- const draftKey = this.buildTagForTargetId(fieldValue);
54940
- const canonicalKey = this.getLuvio().storeGetCanonicalKey(draftKey);
54941
- if (draftKey !== canonicalKey) {
54942
- const canonicalId = extractRecordIdFromStoreKey(canonicalKey);
54943
- if (canonicalId !== undefined) {
54944
- 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
+ }
54945
55008
  }
54946
55009
  }
54947
55010
  }
@@ -54949,17 +55012,24 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
54949
55012
  }
54950
55013
  if (request.method === 'patch' || request.method === 'delete') {
54951
55014
  const recordId = request.urlParams['recordId'];
54952
- const recordKey = this.buildTagForTargetId(recordId);
54953
- const canonicalKey = this.getLuvio().storeGetCanonicalKey(recordKey);
54954
- if (recordKey !== canonicalKey) {
54955
- const canonicalId = extractRecordIdFromStoreKey(canonicalKey);
54956
- if (canonicalId === undefined) {
54957
- // could not resolve id from request -- return the request un-modified
54958
- return request;
54959
- }
55015
+ const canonicalId = this.ephemeralRedirects[recordId];
55016
+ if (canonicalId !== undefined) {
54960
55017
  resolvedBasePath = resolvedBasePath.replace(recordId, canonicalId);
54961
55018
  resolvedUrlParams = { ...resolvedUrlParams, recordId: canonicalId };
54962
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
+ }
54963
55033
  }
54964
55034
  return {
54965
55035
  ...request,
@@ -58192,34 +58262,6 @@ function setupInspection(luvio) {
58192
58262
  * For full license text, see the LICENSE.txt file
58193
58263
  */
58194
58264
 
58195
- class AsyncWorkerPool {
58196
- constructor(concurrency) {
58197
- this.queue = [];
58198
- this.activeWorkers = 0;
58199
- this.concurrency = concurrency;
58200
- }
58201
- push(workFn) {
58202
- this.queue.push(workFn);
58203
- this.work();
58204
- }
58205
- cancel() {
58206
- this.queue = [];
58207
- // TODO [W-12513105]: thread cancellation through to active workers
58208
- }
58209
- work() {
58210
- while (this.queue.length > 0 && this.activeWorkers < this.concurrency) {
58211
- this.activeWorkers += 1;
58212
- const next = this.queue.shift();
58213
- if (next) {
58214
- next().finally(() => {
58215
- this.activeWorkers -= 1;
58216
- this.work();
58217
- });
58218
- }
58219
- }
58220
- }
58221
- }
58222
-
58223
58265
  class EventEmitter {
58224
58266
  constructor() {
58225
58267
  // @ts-ignore typescript doesn't like us setting this to an empty object for some reason
@@ -58768,7 +58810,7 @@ register({
58768
58810
  id: '@salesforce/lds-network-adapter',
58769
58811
  instrument: instrument$1,
58770
58812
  });
58771
- // version: 1.100.2-ca56bb821
58813
+ // version: 1.100.4-ce1be23b7
58772
58814
 
58773
58815
  const { create: create$2, keys: keys$2 } = Object;
58774
58816
  const { stringify: stringify$1, parse: parse$1 } = JSON;
@@ -76421,7 +76463,7 @@ register({
76421
76463
  configuration: { ...configurationForGraphQLAdapters },
76422
76464
  instrument,
76423
76465
  });
76424
- // version: 1.100.2-ca56bb821
76466
+ // version: 1.100.4-ce1be23b7
76425
76467
 
76426
76468
  // On core the unstable adapters are re-exported with different names,
76427
76469
 
@@ -78550,7 +78592,7 @@ withDefaultLuvio((luvio) => {
78550
78592
  unstable_graphQL_imperative = createImperativeAdapter(luvio, createInstrumentedAdapter(ldsAdapter, adapterMetadata), adapterMetadata);
78551
78593
  graphQLImperative = ldsAdapter;
78552
78594
  });
78553
- // version: 1.100.2-ca56bb821
78595
+ // version: 1.100.4-ce1be23b7
78554
78596
 
78555
78597
  var gqlApi = /*#__PURE__*/Object.freeze({
78556
78598
  __proto__: null,
@@ -79224,4 +79266,4 @@ const { luvio } = getRuntime();
79224
79266
  setDefaultLuvio({ luvio });
79225
79267
 
79226
79268
  export { createPrimingSession, draftManager, draftQueue, executeAdapter, executeMutatingAdapter, getImperativeAdapterNames, invokeAdapter, invokeAdapterWithDraftToReplace, invokeAdapterWithMetadata, nimbusDraftQueue, registerReportObserver, setMetadataTTL, setUiApiRecordTTL, subscribeToAdapter };
79227
- // version: 1.100.2-ca56bb821
79269
+ // version: 1.100.4-ce1be23b7