@salesforce/lds-worker-api 1.467.0 → 1.468.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.
@@ -4276,7 +4276,7 @@ function withDefaultLuvio(callback) {
4276
4276
  }
4277
4277
  callbacks.push(callback);
4278
4278
  }
4279
- // version: 1.467.0-4f065d2a2a
4279
+ // version: 1.468.0-9ef0fbdaee
4280
4280
 
4281
4281
  // TODO [TD-0081508]: once that TD is fulfilled we can probably change this file
4282
4282
  function instrumentAdapter$1(createFunction, _metadata) {
@@ -5320,7 +5320,7 @@ function createGraphQLWireAdapterConstructor(luvio, adapter, metadata, astResolv
5320
5320
  const { apiFamily, name } = metadata;
5321
5321
  return createGraphQLWireAdapterConstructor$1(adapter, `${apiFamily}.${name}`, luvio, astResolver);
5322
5322
  }
5323
- // version: 1.467.0-4f065d2a2a
5323
+ // version: 1.468.0-9ef0fbdaee
5324
5324
 
5325
5325
  function isSupportedEntity(_objectApiName) {
5326
5326
  return true;
@@ -32565,7 +32565,7 @@ withDefaultLuvio((luvio) => {
32565
32565
  throttle(60, 60000, setupNotifyAllListRecordUpdateAvailable(luvio));
32566
32566
  throttle(60, 60000, setupNotifyAllListInfoSummaryUpdateAvailable(luvio));
32567
32567
  });
32568
- // version: 1.467.0-049a8b6027
32568
+ // version: 1.468.0-c060a9b9c6
32569
32569
 
32570
32570
  var draftQueueMaxRetryAttemptsGate = {
32571
32571
  isOpen: function (e) {
@@ -32646,6 +32646,15 @@ var allowUpdatesForNonCachedRecords = {
32646
32646
  },
32647
32647
  };
32648
32648
 
32649
+ var sideEffectRefreshKillSwitch = {
32650
+ isOpen: function (e) {
32651
+ return e.fallback;
32652
+ },
32653
+ hasError: function () {
32654
+ return !0;
32655
+ },
32656
+ };
32657
+
32649
32658
  var caseSensitiveUserId = '005B0000000GR4OIAW';
32650
32659
 
32651
32660
  /**
@@ -48701,6 +48710,48 @@ class DurableDraftQueue {
48701
48710
  await this.startQueue();
48702
48711
  }
48703
48712
  }
48713
+ /**
48714
+ * Builds the set of actions deleted by removing `action`, validating
48715
+ * before any store mutation. Same-tag actions are ordered newest-first so
48716
+ * the clicked create is handled last and each intermediate side-effect
48717
+ * replay reflects a valid undo prefix.
48718
+ */
48719
+ resolveActionsToRemove(action, queue, isUploading) {
48720
+ const shouldDeleteRelated = this.getHandler(action.handler).shouldDeleteActionByTagOnRemoval(action);
48721
+ const removedActions = shouldDeleteRelated
48722
+ ? queue.filter((a) => a.tag === action.tag).reverse()
48723
+ : [action];
48724
+ const uploading = removedActions.find((a) => isUploading(a.id));
48725
+ if (uploading !== undefined) {
48726
+ // eslint-disable-next-line @salesforce/lds/no-error-in-production
48727
+ throw new Error(`Cannot remove an uploading draft action with ID ${uploading.id}`);
48728
+ }
48729
+ return {
48730
+ shouldDeleteRelated,
48731
+ removed: removedActions.map((a) => ({
48732
+ action: a,
48733
+ handler: this.getHandler(a.handler),
48734
+ })),
48735
+ };
48736
+ }
48737
+ /**
48738
+ * Runs every removed action's handler cleanup before emitting any
48739
+ * ActionDeleted event, so listeners observe the final side-effect state.
48740
+ */
48741
+ async notifyActionsRemoved(removed, queue) {
48742
+ const removedIds = new Set(removed.map(({ action }) => action.id));
48743
+ const remaining = queue.filter((a) => !removedIds.has(a.id));
48744
+ for (const { action, handler } of removed) {
48745
+ await handler.handleActionRemoved(action, remaining);
48746
+ }
48747
+ for (const { action } of removed) {
48748
+ await this.notifyChangedListeners({
48749
+ type: DraftQueueEventType.ActionDeleted,
48750
+ action,
48751
+ draftCount: this.draftStore.getCount(),
48752
+ });
48753
+ }
48754
+ }
48704
48755
  async removeDraftAction(actionId) {
48705
48756
  const queue = await this.getQueueActions();
48706
48757
  //Get the store key for the removed action
@@ -48710,32 +48761,18 @@ class DurableDraftQueue {
48710
48761
  throw new Error(`No removable action with id ${actionId}`);
48711
48762
  }
48712
48763
  const action = actions[0];
48713
- if (action.id === this.uploadingActionId) {
48714
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
48715
- throw new Error(`Cannot remove an uploading draft action with ID ${actionId}`);
48716
- }
48717
- const handler = this.getHandler(action.handler);
48718
- const shouldDeleteRelated = handler.shouldDeleteActionByTagOnRemoval(action);
48764
+ const { shouldDeleteRelated, removed } = this.resolveActionsToRemove(action, queue, (id) => id === this.uploadingActionId);
48719
48765
  if (shouldDeleteRelated) {
48720
48766
  await this.draftStore.deleteByTag(action.tag);
48721
- queue.forEach((queuedAction) => {
48722
- if (queuedAction.tag === action.tag) {
48723
- this.uploadStartTimes.delete(queuedAction.id);
48724
- this.actionQueueWaitEmittedIds.delete(queuedAction.id);
48725
- }
48726
- });
48727
48767
  }
48728
48768
  else {
48729
48769
  await this.draftStore.deleteDraft(action.id);
48730
- this.uploadStartTimes.delete(action.id);
48731
- this.actionQueueWaitEmittedIds.delete(action.id);
48732
48770
  }
48733
- await handler.handleActionRemoved(action, queue.filter((x) => x.id !== actionId));
48734
- await this.notifyChangedListeners({
48735
- type: DraftQueueEventType.ActionDeleted,
48736
- action,
48737
- draftCount: this.draftStore.getCount(),
48771
+ removed.forEach(({ action: a }) => {
48772
+ this.uploadStartTimes.delete(a.id);
48773
+ this.actionQueueWaitEmittedIds.delete(a.id);
48738
48774
  });
48775
+ await this.notifyActionsRemoved(removed, queue);
48739
48776
  if (this.userState === DraftQueueState.Started &&
48740
48777
  this.state !== DraftQueueState.Started &&
48741
48778
  this.replacingAction === undefined) {
@@ -48774,15 +48811,12 @@ class DurableDraftQueue {
48774
48811
  return this.replaceOrMergeActions(targetActionId, sourceActionId, true);
48775
48812
  }
48776
48813
  async retryAction(actionId) {
48777
- this.stopQueueManually(true);
48778
- const actions = await this.getQueueActions();
48779
- const target = actions[0];
48780
- if (!target || target.id !== actionId) {
48781
- throw Error(`Action ${actionId} not found at the head of the draft queue`);
48782
- }
48814
+ // Validate before stopping so a rejected retry leaves the queue state untouched.
48815
+ const target = await this.getRetryTarget(actionId);
48783
48816
  if (!isDraftError(target)) {
48784
48817
  throw Error(`Action ${actionId} is not in Error state`);
48785
48818
  }
48819
+ this.stopQueueManually(true);
48786
48820
  // A manual retry is a fresh start: clear the persisted upload retry-attempt
48787
48821
  // count so the action doesn't immediately re-cap after a single failure.
48788
48822
  const { [DRAFT_ACTION_RETRY_COUNT_METADATA_KEY]: _retryCount, ...metadataWithoutRetryCount } = target.metadata || {};
@@ -48801,6 +48835,18 @@ class DurableDraftQueue {
48801
48835
  await this.startQueueSafe();
48802
48836
  return pendingAction;
48803
48837
  }
48838
+ /**
48839
+ * The action `retryAction` may retry. Only the head: an errored head is what blocks a
48840
+ * strictly ordered queue.
48841
+ */
48842
+ async getRetryTarget(actionId) {
48843
+ const actions = await this.getQueueActions();
48844
+ const target = actions[0];
48845
+ if (!target || target.id !== actionId) {
48846
+ throw Error(`Action ${actionId} not found at the head of the draft queue`);
48847
+ }
48848
+ return target;
48849
+ }
48804
48850
  async setMetadata(actionId, metadata) {
48805
48851
  const keys$1 = keys$4(metadata);
48806
48852
  const compatibleKeys = keys$1.filter((key) => {
@@ -50403,27 +50449,17 @@ class PerformanceDraftQueue extends DurableDraftQueue {
50403
50449
  throw new Error(`No removable action with id ${actionId}`);
50404
50450
  }
50405
50451
  const action = actions[0];
50406
- if (this.uploadingActionIds.has(action.id)) {
50407
- // eslint-disable-next-line @salesforce/lds/no-error-in-production
50408
- throw new Error(`Cannot remove an uploading draft action with ID ${actionId}`);
50409
- }
50452
+ const { shouldDeleteRelated, removed } = this.resolveActionsToRemove(action, queue, (id) => this.uploadingActionIds.has(id));
50410
50453
  // A removed action must not leave a dangling backoff timer that would
50411
50454
  // later fire and re-drive the scheduler for an id that no longer exists.
50412
- this.clearActionRetry(action.id);
50413
- const handler = this.getHandler(action.handler);
50414
- const shouldDeleteRelated = handler.shouldDeleteActionByTagOnRemoval(action);
50455
+ removed.forEach(({ action: a }) => this.clearActionRetry(a.id));
50415
50456
  if (shouldDeleteRelated) {
50416
50457
  await this.draftStore.deleteByTag(action.tag);
50417
50458
  }
50418
50459
  else {
50419
50460
  await this.draftStore.deleteDraft(action.id);
50420
50461
  }
50421
- await handler.handleActionRemoved(action, queue.filter((x) => x.id !== actionId));
50422
- await this.notifyChangedListeners({
50423
- type: DraftQueueEventType.ActionDeleted,
50424
- action,
50425
- draftCount: this.draftStore.getCount(),
50426
- });
50462
+ await this.notifyActionsRemoved(removed, queue);
50427
50463
  if (this.userState === DraftQueueState.Started &&
50428
50464
  this.state !== DraftQueueState.Started &&
50429
50465
  this.replacingAction === undefined) {
@@ -50562,6 +50598,27 @@ class PerformanceDraftQueue extends DurableDraftQueue {
50562
50598
  }
50563
50599
  return super.startQueue();
50564
50600
  }
50601
+ /**
50602
+ * The head of the shared store may belong to the other queue, so targets are resolved
50603
+ * against the actions this queue owns. With strict ordering only the owned head can be
50604
+ * retried (it is what blocks dispatch); without it an errored action blocks nothing, so
50605
+ * any errored action this queue owns can be retried.
50606
+ */
50607
+ async getRetryTarget(actionId) {
50608
+ const owned = await this.getOwnedQueueActions();
50609
+ if (this.strictOrdering) {
50610
+ const head = owned[0];
50611
+ if (!head || head.id !== actionId) {
50612
+ throw Error(`Action ${actionId} not found at the head of the draft queue`);
50613
+ }
50614
+ return head;
50615
+ }
50616
+ const target = owned.find((action) => action.id === actionId);
50617
+ if (target === undefined) {
50618
+ throw Error(`Action ${actionId} not found in the draft queue`);
50619
+ }
50620
+ return target;
50621
+ }
50565
50622
  async retryAllErrors() {
50566
50623
  const actions = await this.getOwnedQueueActions();
50567
50624
  const errored = actions.filter((a) => a.status === DraftActionStatus.Error);
@@ -50666,6 +50723,8 @@ class RoutingDraftQueue {
50666
50723
  removeHandler(id) {
50667
50724
  return this.primary.removeHandler(id);
50668
50725
  }
50726
+ // Removes only the action itself. Removing a binary action through RoutingDraftManager also
50727
+ // removes the serial actions that depend on it; this façade does not.
50669
50728
  async removeDraftAction(actionId) {
50670
50729
  const owner = await this.routeByActionId(actionId);
50671
50730
  return owner.removeDraftAction(actionId);
@@ -51107,27 +51166,12 @@ function isResourceRequestAction$1(action) {
51107
51166
  return (dataAsAny !== undefined && dataAsAny.method !== undefined && dataAsAny.body !== undefined);
51108
51167
  }
51109
51168
 
51110
- function hasGetOwnedQueueActions(queue) {
51111
- return typeof queue.getOwnedQueueActions === 'function';
51112
- }
51113
- function hasGetCreatedDraftIds(queue) {
51114
- return typeof queue.getCreatedDraftIds === 'function';
51115
- }
51116
- function hasGetOwnedActionsReferencing(queue) {
51117
- return typeof queue.getOwnedActionsReferencing === 'function';
51118
- }
51119
- function hasRetryAllErrors(queue) {
51120
- return typeof queue.retryAllErrors === 'function';
51121
- }
51122
51169
  /**
51123
51170
  * Gate-ON DraftManager: the concurrent-binary upload variant, instantiated only when the
51124
51171
  * `concurrentBinaryQueue` feature flag is on. It wraps a strict-ordering serial draft queue
51125
51172
  * plus a parallel binary queue over one shared store, stamps each draft's routing `lane`, and
51126
- * drives the binary-queue lifecycle/read methods the native Pending Images UI consumes.
51127
- *
51128
- * The base `DraftManager` (gate-OFF) keeps every one of these methods as an inert stub so the
51129
- * native bridge surface is identical regardless of the flag; this subclass supplies the real
51130
- * behavior. Current (non-SCE) users never instantiate this class — they run the unchanged base.
51173
+ * routes lifecycle, remove, and retry calls to the queue that owns each action. Current
51174
+ * (non-SCE) users never instantiate this class — they run the unchanged base.
51131
51175
  */
51132
51176
  class RoutingDraftManager extends DraftManager {
51133
51177
  constructor(draftQueue, binaryQueue, laneLabels) {
@@ -51137,6 +51181,7 @@ class RoutingDraftManager extends DraftManager {
51137
51181
  __nimbus.plugins.JSLoggerPlugin !== undefined
51138
51182
  ? __nimbus.plugins.JSLoggerPlugin
51139
51183
  : undefined;
51184
+ this.serialQueue = draftQueue;
51140
51185
  this.binaryQueue = binaryQueue;
51141
51186
  this.laneLabels = laneLabels;
51142
51187
  // Surface binary-queue change events through the same listener pipeline as the serial
@@ -51151,21 +51196,6 @@ class RoutingDraftManager extends DraftManager {
51151
51196
  }))
51152
51197
  .then(toQueueState(this.draftQueue));
51153
51198
  }
51154
- /**
51155
- * Get the current state of each of the DraftActions in the binary DraftQueue
51156
- * (ContentDocument/Version/Link uploads).
51157
- */
51158
- getBinaryQueue() {
51159
- const queue = this.binaryQueue;
51160
- const getActions = hasGetOwnedQueueActions(queue)
51161
- ? queue.getOwnedQueueActions()
51162
- : queue.getQueueActions();
51163
- return getActions
51164
- .then((queueActions) => {
51165
- return queueActions.map(this.buildDraftQueueItem);
51166
- })
51167
- .then(toQueueState(queue));
51168
- }
51169
51199
  /**
51170
51200
  * Starts both the serial and binary draft queues and begins processing their items.
51171
51201
  */
@@ -51180,40 +51210,58 @@ class RoutingDraftManager extends DraftManager {
51180
51210
  return Promise.all([this.draftQueue.stopQueue(), this.binaryQueue.stopQueue()]).then(() => undefined);
51181
51211
  }
51182
51212
  /**
51183
- * Starts the binary draft queue (for ContentDocument/Version/Link uploads). Separate from
51184
- * startQueue() so the binary queue can be paused/resumed independently from the regular
51185
- * draft queue and from stopQueueWhileRunning() interruptions.
51213
+ * Pauses both queues while `action` runs. Nests each queue's own stopQueueWhileRunning so
51214
+ * each restarts afterwards only if it was user-started before.
51186
51215
  */
51187
- startBinaryQueue() {
51188
- return this.binaryQueue.startQueue();
51189
- }
51190
- /** Stops the binary draft queue; pairs with startBinaryQueue(). */
51191
- stopBinaryQueue() {
51192
- return this.binaryQueue.stopQueue();
51216
+ stopQueueWhileRunning(action) {
51217
+ return this.draftQueue.stopQueueWhileRunning(() => this.binaryQueue.stopQueueWhileRunning(action));
51193
51218
  }
51194
51219
  async retryAllErrors() {
51195
- if (hasRetryAllErrors(this.draftQueue)) {
51196
- await this.draftQueue.retryAllErrors();
51197
- }
51198
- if (hasRetryAllErrors(this.binaryQueue)) {
51199
- await this.binaryQueue.retryAllErrors();
51200
- }
51220
+ await this.serialQueue.retryAllErrors();
51221
+ await this.binaryQueue.retryAllErrors();
51201
51222
  }
51202
51223
  /**
51203
51224
  * Routes the remove to the queue that owns the action. The serial queue reads the shared
51204
51225
  * store, so it sees binary-owned actions too, but has no handler registered for them and
51205
51226
  * would throw.
51227
+ *
51228
+ * A binary remove pauses the serial queue so a dependent can't start uploading between the
51229
+ * uploading check and its removal. Only the serial queue: stopping the binary queue would
51230
+ * clear every binary action's retry backoff. The serial queue's own removeDraftAction
51231
+ * restarts it, so the pause covers the first dependent only.
51206
51232
  */
51207
51233
  removeDraftAction(actionId) {
51208
51234
  return this.binaryActionsById()
51209
51235
  .then((binaryById) => {
51210
51236
  const binaryAction = binaryById.get(actionId);
51211
51237
  return binaryAction !== undefined
51212
- ? this.removeBinaryActionAndDependents(binaryAction)
51238
+ ? this.serialQueue.stopQueueWhileRunning(() => this.removeBinaryActionAndDependents(binaryAction))
51213
51239
  : this.draftQueue.removeDraftAction(actionId);
51214
51240
  })
51215
51241
  .then(() => this.getQueue());
51216
51242
  }
51243
+ /**
51244
+ * Routes to the queue that owns the action, for the same reason as removeDraftAction.
51245
+ * Native sets metadata on every image upload right after enqueueing it, so a serial-only
51246
+ * setMetadata fails the upload call and native never links the image to its record.
51247
+ */
51248
+ async setMetadata(actionId, metadata) {
51249
+ const binaryById = await this.binaryActionsById();
51250
+ if (!binaryById.has(actionId)) {
51251
+ return super.setMetadata(actionId, metadata);
51252
+ }
51253
+ const updated = await this.binaryQueue.setMetadata(actionId, metadata);
51254
+ return this.buildDraftQueueItem(this.stampLane(updated, true));
51255
+ }
51256
+ /** Routes to the queue that owns the action, for the same reason as removeDraftAction. */
51257
+ async retryAction(actionId) {
51258
+ const binaryById = await this.binaryActionsById();
51259
+ if (!binaryById.has(actionId)) {
51260
+ return super.retryAction(actionId);
51261
+ }
51262
+ const retried = await this.binaryQueue.retryAction(actionId);
51263
+ return this.buildDraftQueueItem(this.stampLane(retried, true));
51264
+ }
51217
51265
  /**
51218
51266
  * Removes a binary action plus the serial actions that reference a draft id it creates
51219
51267
  * (e.g. the ContentDocumentLink native enqueues to link an uploaded image to a record).
@@ -51251,29 +51299,17 @@ class RoutingDraftManager extends DraftManager {
51251
51299
  }
51252
51300
  }
51253
51301
  serialActionsDependingOn(action) {
51254
- const binary = this.binaryQueue;
51255
- const serial = this.draftQueue;
51256
- if (!hasGetCreatedDraftIds(binary) || !hasGetOwnedActionsReferencing(serial)) {
51257
- return Promise.resolve([]);
51258
- }
51259
- const draftIds = binary.getCreatedDraftIds(action);
51302
+ const draftIds = this.binaryQueue.getCreatedDraftIds(action);
51260
51303
  return draftIds.length === 0
51261
51304
  ? Promise.resolve([])
51262
- : serial.getOwnedActionsReferencing(draftIds);
51305
+ : this.serialQueue.getOwnedActionsReferencing(draftIds);
51263
51306
  }
51264
51307
  /**
51265
51308
  * Binary-lane actions keyed by id, carrying the lane's transient `Uploading` status.
51266
51309
  * `getQueue` uses it to stamp the `concurrentBinary` lane and source the correct status.
51267
- * An empty map means "treat every action as serial" — returned both when the binary queue
51268
- * can't report ownership and (harmlessly) when it is simply empty; the caller doesn't need
51269
- * to tell those apart.
51270
51310
  */
51271
51311
  binaryActionsById() {
51272
- const binary = this.binaryQueue;
51273
- if (!hasGetOwnedQueueActions(binary)) {
51274
- return Promise.resolve(new Map());
51275
- }
51276
- return binary
51312
+ return this.binaryQueue
51277
51313
  .getOwnedQueueActions()
51278
51314
  .then((actions) => new Map(actions.map((action) => [action.id, action])));
51279
51315
  }
@@ -83815,6 +83851,12 @@ function batchLog(line) {
83815
83851
  // debug-only
83816
83852
  }
83817
83853
  }
83854
+ // Ingestion timestamp that makes the uploaded record stale for the next read. Ingested at
83855
+ // epoch+1 the record is expired under any ttl: the record ttl, a record ttl override, the
83856
+ // default ttl override or a host metadata ttl. (Not 0, which falsy checks treat as missing.)
83857
+ // Expiring it with luvio.storeExpirePossibleStaleRecords or a 0 ttl does not work when a ttl
83858
+ // override is set, since the override replaces the ttl.
83859
+ const STALE_INGESTION_TIMESTAMP = 1;
83818
83860
  class UiApiActionHandler extends AbstractResourceRequestActionHandler {
83819
83861
  constructor(getLuvio, networkAdapter, draftQueue, getRecordAdapter, objectInfoService, isDraftId, recordService, sideEffectService, durableRecordStore) {
83820
83862
  super(draftQueue, networkAdapter, getLuvio, recordService);
@@ -83829,6 +83871,8 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
83829
83871
  this.durableRecordStore = durableRecordStore;
83830
83872
  this.handlerId = LDS_ACTION_HANDLER_ID;
83831
83873
  this.sideEffectHooks = [];
83874
+ // side effect field values of the create actions being completed, by action id
83875
+ this.injectedFieldsByActionId = new Map();
83832
83876
  recordService.registerRecordHandler(this);
83833
83877
  }
83834
83878
  setSideEffectHooks(hooks) {
@@ -83939,7 +83983,40 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
83939
83983
  await this.evictKey(completedAction.tag);
83940
83984
  return;
83941
83985
  }
83942
- return super.handleActionCompleted(completedAction, queueOperations);
83986
+ if (method !== 'post') {
83987
+ return super.handleActionCompleted(completedAction, queueOperations);
83988
+ }
83989
+ // super removes the action's side effects before it ingests the response, so what the
83990
+ // create's side effects set has to be captured first
83991
+ const injectedFields = this.getFieldsToInject(completedAction);
83992
+ if (injectedFields !== undefined) {
83993
+ this.injectedFieldsByActionId.set(completedAction.id, injectedFields);
83994
+ }
83995
+ try {
83996
+ await super.handleActionCompleted(completedAction, queueOperations);
83997
+ }
83998
+ finally {
83999
+ this.injectedFieldsByActionId.delete(completedAction.id);
84000
+ }
84001
+ }
84002
+ // The create response only has the fields that were requested, so a field that only a side
84003
+ // effect sets (e.g. ProductConsumed.IsProduct2Serialized) is missing from the cached
84004
+ // server record once the draft's effects are gone. Returns the values of those fields.
84005
+ // Only called for a POST: handleActionCompleted hands every other method straight to super.
84006
+ getFieldsToInject(completedAction) {
84007
+ if (sideEffectRefreshKillSwitch.isOpen({ fallback: false })) {
84008
+ return undefined;
84009
+ }
84010
+ const fields = {};
84011
+ this.recordService.getEffectsForAction(completedAction).forEach((effect) => {
84012
+ if (effect.type === 'record-field-set' && effect.key === completedAction.tag) {
84013
+ fields[effect.fieldName] = { value: effect.value, displayValue: null };
84014
+ }
84015
+ });
84016
+ if (keys$3(fields).length === 0) {
84017
+ return undefined;
84018
+ }
84019
+ return fields;
83943
84020
  }
83944
84021
  async fetchReferenceRecord(referenceFields) {
83945
84022
  const promises = referenceFields.map(async (referenceFieldInfo) => {
@@ -84602,10 +84679,35 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
84602
84679
  getTypeCacheKeys$1u$1(cacheKeys, this.getLuvio(), record);
84603
84680
  return cacheKeys;
84604
84681
  }
84605
- synchronousIngest(response) {
84682
+ synchronousIngest(response, action) {
84606
84683
  const luvio = this.getLuvio();
84684
+ const injected = this.injectedFieldsByActionId.get(action.id);
84685
+ if (injected === undefined) {
84686
+ const key = keyBuilderFromType$g(luvio, response);
84687
+ luvio.storeIngest(key, ingest$1o$1, response);
84688
+ return;
84689
+ }
84690
+ // never replace what the server sent
84691
+ const fields = { ...response.fields };
84692
+ let injectedAny = false;
84693
+ keys$3(injected).forEach((fieldName) => {
84694
+ if (fields[fieldName] === undefined) {
84695
+ fields[fieldName] = injected[fieldName];
84696
+ injectedAny = true;
84697
+ }
84698
+ });
84607
84699
  const key = keyBuilderFromType$g(luvio, response);
84608
- luvio.storeIngest(key, ingest$1o$1, response);
84700
+ luvio.storeIngest(key, ingest$1o$1, { ...response, fields });
84701
+ if (injectedAny) {
84702
+ // after ingestRecord, which publishes the metadata with a fresh ttl
84703
+ luvio.publishStoreMetadata(key, {
84704
+ ttl: TTL$k,
84705
+ representationName: 'RecordRepresentation',
84706
+ namespace: 'UiApi',
84707
+ version: VERSION$1v$1,
84708
+ ingestionTimestamp: STALE_INGESTION_TIMESTAMP,
84709
+ });
84710
+ }
84609
84711
  }
84610
84712
  mergeRequestBody(targetBody, sourceBody) {
84611
84713
  // IMPORTANT: spread operator isn't deep clone so we have to individually
@@ -84675,6 +84777,10 @@ class UiApiDraftRecordService {
84675
84777
  await this.sideEffectStore.removeEffects(operations);
84676
84778
  return new Set(operations.map((o) => o.key));
84677
84779
  }
84780
+ // returns the side effects queued for the given action, oldest first
84781
+ getEffectsForAction(action) {
84782
+ return this.sideEffectStore.getEffectsByTag(action.id);
84783
+ }
84678
84784
  // reads a set of records out of the durable store, re-applies current side
84679
84785
  // effects and persists the changed record
84680
84786
  async reapplyRecordSideEffects(recordKeys, lifecycle) {
@@ -93611,21 +93717,10 @@ function makeNetworkAdapterChunkRecordFields(networkAdapter, instrumentationSink
93611
93717
  *
93612
93718
  * This instance is leveraged in the LMR webview which proxies DraftQueue requests
93613
93719
  * to a concrete implementation running in jscore.
93614
- *
93615
- * The Nimbus plugin name targeted by this proxy can be parameterized via the
93616
- * constructor (defaults to 'LdsDraftQueue'); pass 'LdsPerformanceDraftQueue' to
93617
- * target the primer's Performance Upload draft queue.
93618
93720
  */
93619
93721
  class NimbusDraftQueue {
93620
- constructor(pluginName = 'LdsDraftQueue') {
93621
- this.pluginName = pluginName;
93622
- }
93623
- get callProxyMethod() {
93624
- const plugin = __nimbus.plugins[this.pluginName];
93625
- return plugin && plugin.callProxyMethod;
93626
- }
93627
93722
  enqueue(handlerId, data, observabilityContext) {
93628
- const callProxyMethod = this.callProxyMethod;
93723
+ const callProxyMethod = __nimbus.plugins.LdsDraftQueue.callProxyMethod;
93629
93724
  if (callProxyMethod === undefined) {
93630
93725
  return Promise.reject(new Error('callProxyMethod not defined on the nimbus plugin'));
93631
93726
  }
@@ -93652,7 +93747,7 @@ class NimbusDraftQueue {
93652
93747
  return Promise.reject(new Error('Cannot call processNextAction from the NimbusDraftQueue'));
93653
93748
  }
93654
93749
  getQueueActions() {
93655
- const callProxyMethod = this.callProxyMethod;
93750
+ const callProxyMethod = __nimbus.plugins.LdsDraftQueue.callProxyMethod;
93656
93751
  if (callProxyMethod === undefined) {
93657
93752
  return Promise.reject(new Error('callProxyMethod not defined on the nimbus plugin'));
93658
93753
  }
@@ -93665,7 +93760,7 @@ class NimbusDraftQueue {
93665
93760
  });
93666
93761
  }
93667
93762
  getDataForAction(action) {
93668
- const callProxyMethod = this.callProxyMethod;
93763
+ const callProxyMethod = __nimbus.plugins.LdsDraftQueue.callProxyMethod;
93669
93764
  if (callProxyMethod === undefined) {
93670
93765
  return Promise.reject('callProxyMethod not defined on the nimbus plugin');
93671
93766
  }
@@ -93871,7 +93966,7 @@ function buildLdsDraftQueue(durableStore, draftStore, options) {
93871
93966
  if (typeof __nimbus !== 'undefined' &&
93872
93967
  __nimbus.plugins !== undefined &&
93873
93968
  __nimbus.plugins.LdsDraftQueue !== undefined) {
93874
- return new NimbusDraftQueue('LdsDraftQueue');
93969
+ return new NimbusDraftQueue();
93875
93970
  }
93876
93971
  // Legacy gate-OFF path: no shared store / options → today's plain queue.
93877
93972
  if (draftStore === undefined && options === undefined) {
@@ -93886,14 +93981,10 @@ function buildLdsDraftQueue(durableStore, draftStore, options) {
93886
93981
  }
93887
93982
  /**
93888
93983
  * Builds the Performance Upload draft queue (ContentDocument/Version/Link
93889
- * multipart uploads, concurrency > 1). Only constructed on the gate-ON path.
93984
+ * multipart uploads, concurrency > 1). Only constructed on the gate-ON path, in the
93985
+ * worker realm.
93890
93986
  */
93891
93987
  function buildLdsPerformanceDraftQueue(durableStore, draftStore, options) {
93892
- if (typeof __nimbus !== 'undefined' &&
93893
- __nimbus.plugins !== undefined &&
93894
- __nimbus.plugins.LdsPerformanceDraftQueue !== undefined) {
93895
- return new NimbusDraftQueue('LdsPerformanceDraftQueue');
93896
- }
93897
93988
  const store = draftStore ?? new DurableDraftStore(durableStore);
93898
93989
  const draftQueue = new PerformanceDraftQueue(store, options);
93899
93990
  return instrumentDraftQueue(draftQueue);
@@ -98821,7 +98912,10 @@ let NetworkCommand$1 = class NetworkCommand extends BaseCommand {
98821
98912
  if (isSubscribableResult(newResult)) {
98822
98913
  const value = newResult.isOk() ? ok$1(newResult.value.data) : err$1(newResult.error.failure);
98823
98914
  this.subscriptions.forEach((cb) => {
98824
- cb(value);
98915
+ try {
98916
+ cb(value);
98917
+ } catch {
98918
+ }
98825
98919
  });
98826
98920
  }
98827
98921
  return ok$1(void 0);
@@ -99763,7 +99857,10 @@ class NetworkCommand extends BaseCommand {
99763
99857
  if (isSubscribableResult(newResult)) {
99764
99858
  const value = newResult.isOk() ? ok$1(newResult.value.data) : err$1(newResult.error.failure);
99765
99859
  this.subscriptions.forEach((cb) => {
99766
- cb(value);
99860
+ try {
99861
+ cb(value);
99862
+ } catch {
99863
+ }
99767
99864
  });
99768
99865
  }
99769
99866
  return ok$1(void 0);
@@ -99785,6 +99882,79 @@ function applyOperationRequestOptions$1(init, operationType, requestOptions) {
99785
99882
  }
99786
99883
  };
99787
99884
  }
99885
+ function fetchFromNetwork(getRequest, hooks, contextSeed) {
99886
+ try {
99887
+ const {
99888
+ services,
99889
+ params: [input, init],
99890
+ operationType,
99891
+ requestOptions
99892
+ } = getRequest();
99893
+ const initWithOptions = applyOperationRequestOptions$1(init, operationType, requestOptions);
99894
+ const seed = operationType === void 0 ? contextSeed : { operationType, ...contextSeed };
99895
+ const initWithSeed = seed === void 0 ? initWithOptions : { ...initWithOptions, __contextSeed: seed };
99896
+ const fetchCall = initWithSeed === void 0 ? services.fetch(input) : services.fetch(input, initWithSeed);
99897
+ return convertFetchResponseToData(fetchCall, hooks);
99898
+ } catch (reason) {
99899
+ return resolvedPromiseLike$2(err$1(toError(reason)));
99900
+ }
99901
+ }
99902
+ function convertFetchResponseToData(response, hooks) {
99903
+ return response.then(
99904
+ (response2) => {
99905
+ if (response2.ok) {
99906
+ let resultPromise;
99907
+ if (hooks.isSemanticNullResponse(response2)) {
99908
+ resultPromise = Promise.resolve(ok$1(null));
99909
+ } else if (hooks.isProtocolNoBodyStatus(response2.status) && !hooks.isSemanticNullResponse(response2)) {
99910
+ resultPromise = Promise.resolve(
99911
+ err$1(
99912
+ toError(
99913
+ `Unexpected ${response2.status} response: no-content status was not declared in the API specification. Declare this response in your OAS without a content property.`
99914
+ )
99915
+ )
99916
+ );
99917
+ } else {
99918
+ resultPromise = response2.json().then(
99919
+ (json) => ok$1(json),
99920
+ (reason) => err$1(toError(reason))
99921
+ );
99922
+ }
99923
+ return resultPromise.finally(() => {
99924
+ try {
99925
+ hooks.afterRequestHooks({ statusCode: response2.status });
99926
+ } catch {
99927
+ }
99928
+ });
99929
+ } else {
99930
+ return hooks.coerceError(response2).then((coercedError) => {
99931
+ return err$1(coercedError);
99932
+ }).finally(() => {
99933
+ try {
99934
+ hooks.afterRequestHooks({ statusCode: response2.status });
99935
+ } catch {
99936
+ }
99937
+ });
99938
+ }
99939
+ },
99940
+ (reason) => err$1(toError(reason))
99941
+ );
99942
+ }
99943
+ function completeRefresh(result, getSubscriptions, options = {}) {
99944
+ const { previousResult } = options;
99945
+ if (!options.suppressEqualSuccesses || result.isErr() || !previousResult || previousResult.isErr() || !deepEquals$1(previousResult.value, result.value)) {
99946
+ const subscriptions = getSubscriptions();
99947
+ const callbacks = options.skipRemovedSubscriptions ? [...subscriptions] : subscriptions;
99948
+ callbacks.forEach((callback) => {
99949
+ if (options.skipRemovedSubscriptions && !getSubscriptions().includes(callback)) return;
99950
+ try {
99951
+ callback(result);
99952
+ } catch {
99953
+ }
99954
+ });
99955
+ }
99956
+ return options.reportFailure && result.isErr() ? result : ok$1(void 0);
99957
+ }
99788
99958
  function isAbortableCommand(command) {
99789
99959
  return !!command && typeof command === "object" && "isAbortableCommand" in command && command.isAbortableCommand === true;
99790
99960
  }
@@ -99813,18 +99983,18 @@ function createAbortableDecorator(command, options) {
99813
99983
  }
99814
99984
  if (prop === "fetchParams") {
99815
99985
  const originalFetchParams = Reflect.get(target, prop, receiver);
99816
- const isInternal = Reflect.get(target, "isInternalExecution", receiver) === true;
99986
+ const suppressAbortSignal = Reflect.get(target, "isInternalExecution", receiver) === true;
99817
99987
  if (typeof originalFetchParams === "function") {
99818
99988
  return function(...args) {
99819
99989
  const originalReturnValue = originalFetchParams.apply(this, args);
99820
- if (!isInternal) {
99990
+ if (!suppressAbortSignal) {
99821
99991
  const [url, init = {}] = originalReturnValue;
99822
99992
  return [url, { signal, ...init }];
99823
99993
  }
99824
99994
  return originalReturnValue;
99825
99995
  };
99826
99996
  } else {
99827
- if (!isInternal && originalFetchParams && Array.isArray(originalFetchParams)) {
99997
+ if (!suppressAbortSignal && originalFetchParams && Array.isArray(originalFetchParams)) {
99828
99998
  const [url, init = {}] = originalFetchParams;
99829
99999
  return [url, { signal, ...init }];
99830
100000
  }
@@ -99851,38 +100021,35 @@ const _FetchNetworkCommand = class _FetchNetworkCommand extends NetworkCommand {
99851
100021
  this.services = services;
99852
100022
  this.additionalNullResponses = [];
99853
100023
  }
99854
- /**
99855
- * The command's operation type. Generated command subclasses override this
99856
- * getter with their concrete operation (see the generator's
99857
- * `generateOperationType`); the base returns `undefined` for commands that
99858
- * don't declare one (e.g. hand-written commands). Transport-layer
99859
- * interceptors use it to tell a read (`query`) apart from a write — see
99860
- * `fetch`, which folds it into the context seed and derives
99861
- * `onestore.retrySafe` from it.
99862
- */
99863
100024
  get operationType() {
99864
100025
  return void 0;
99865
100026
  }
99866
- /** Declared `onestore` options (`handleServerError`, `compression`); generated overrides (`generateRequestOptionsGetter`). */
99867
100027
  get requestOptions() {
99868
100028
  return void 0;
99869
100029
  }
99870
100030
  fetch(contextSeed) {
99871
- try {
99872
- const [input, init] = this.fetchParams;
99873
- const operationType = this.operationType;
99874
- const initWithOptions = applyOperationRequestOptions$1(
99875
- init,
99876
- operationType,
99877
- this.requestOptions
99878
- );
99879
- const seed = operationType === void 0 ? contextSeed : { operationType, ...contextSeed };
99880
- const initWithSeed = seed === void 0 ? initWithOptions : { ...initWithOptions, __contextSeed: seed };
99881
- const fetchCall = initWithSeed === void 0 ? this.services.fetch(input) : this.services.fetch(input, initWithSeed);
99882
- return this.convertFetchResponseToData(fetchCall);
99883
- } catch (reason) {
99884
- return resolvedPromiseLike$2(err$1(toError(reason)));
99885
- }
100031
+ return fetchFromNetwork(
100032
+ () => ({
100033
+ services: this.services,
100034
+ params: this.fetchParams,
100035
+ operationType: this.operationType,
100036
+ requestOptions: this.requestOptions
100037
+ }),
100038
+ {
100039
+ isSemanticNullResponse: (response) => this.isSemanticNullResponse(response),
100040
+ isProtocolNoBodyStatus: (status) => this.isProtocolNoBodyStatus(status),
100041
+ coerceError: (response) => this.coerceError(response),
100042
+ afterRequestHooks: (options) => this.afterRequestHooks(options)
100043
+ },
100044
+ contextSeed
100045
+ );
100046
+ }
100047
+ refresh() {
100048
+ return this.execute().then((newResult) => {
100049
+ if (!isSubscribableResult(newResult)) return ok$1(void 0);
100050
+ const result = newResult.isOk() ? ok$1(newResult.value.data) : err$1(newResult.error.failure);
100051
+ return completeRefresh(result, () => this.subscriptions);
100052
+ });
99886
100053
  }
99887
100054
  isSemanticNullResponse(response) {
99888
100055
  return this.additionalNullResponses.includes(response.status);
@@ -99890,53 +100057,9 @@ const _FetchNetworkCommand = class _FetchNetworkCommand extends NetworkCommand {
99890
100057
  isProtocolNoBodyStatus(status) {
99891
100058
  return status === 204 || status === 205;
99892
100059
  }
99893
- isUndeclaredNoBodyResponse(response) {
99894
- return this.isProtocolNoBodyStatus(response.status) && !this.isSemanticNullResponse(response);
99895
- }
99896
100060
  async coerceError(errorResponse) {
99897
100061
  return toError(errorResponse.statusText);
99898
100062
  }
99899
- convertFetchResponseToData(response) {
99900
- return response.then(
99901
- (response2) => {
99902
- if (response2.ok) {
99903
- let resultPromise;
99904
- if (this.isSemanticNullResponse(response2)) {
99905
- resultPromise = Promise.resolve(ok$1(null));
99906
- } else if (this.isUndeclaredNoBodyResponse(response2)) {
99907
- resultPromise = Promise.resolve(
99908
- err$1(
99909
- toError(
99910
- `Unexpected ${response2.status} response: no-content status was not declared in the API specification. Declare this response in your OAS without a content property.`
99911
- )
99912
- )
99913
- );
99914
- } else {
99915
- resultPromise = response2.json().then(
99916
- (json) => ok$1(json),
99917
- (reason) => err$1(toError(reason))
99918
- );
99919
- }
99920
- return resultPromise.finally(() => {
99921
- try {
99922
- this.afterRequestHooks({ statusCode: response2.status });
99923
- } catch {
99924
- }
99925
- });
99926
- } else {
99927
- return this.coerceError(response2).then((coercedError) => {
99928
- return err$1(coercedError);
99929
- }).finally(() => {
99930
- try {
99931
- this.afterRequestHooks({ statusCode: response2.status });
99932
- } catch {
99933
- }
99934
- });
99935
- }
99936
- },
99937
- (reason) => err$1(toError(reason))
99938
- );
99939
- }
99940
100063
  };
99941
100064
  _FetchNetworkCommand.availableDecorators = {
99942
100065
  abortable: createAbortableDecorator
@@ -101000,7 +101123,7 @@ function buildServiceDescriptor$b(luvio) {
101000
101123
  },
101001
101124
  };
101002
101125
  }
101003
- // version: 1.467.0-4f065d2a2a
101126
+ // version: 1.468.0-9ef0fbdaee
101004
101127
 
101005
101128
  /**
101006
101129
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -101026,7 +101149,7 @@ function buildServiceDescriptor$a(notifyRecordUpdateAvailable, getNormalizedLuvi
101026
101149
  },
101027
101150
  };
101028
101151
  }
101029
- // version: 1.467.0-4f065d2a2a
101152
+ // version: 1.468.0-9ef0fbdaee
101030
101153
 
101031
101154
  function findExecutableOperation$1(input) {
101032
101155
  const operations = input.query.definitions.filter(
@@ -101889,6 +102012,53 @@ function buildBaseImperativeInvoker(getCommand, transformResult) {
101889
102012
  }
101890
102013
  };
101891
102014
  }
102015
+ function assertSubscribable(result, report) {
102016
+ if (!isSubscribableResult(result)) {
102017
+ report("Non-subscribable result encountered - please use correct operation type");
102018
+ throw new Error("Internal error in Lightning Data Service adapter occurred");
102019
+ }
102020
+ }
102021
+ function toQueryUpdate(result) {
102022
+ return result.isOk() ? { data: result.value, error: void 0 } : { data: void 0, error: unwrapUserlandError(result.error) };
102023
+ }
102024
+ class SubscribableImperativeBindingsService {
102025
+ bind(getCommand, exposeRefresh = false) {
102026
+ return buildBaseImperativeInvoker(
102027
+ getCommand,
102028
+ (result) => this.transformResult(result, exposeRefresh)
102029
+ );
102030
+ }
102031
+ transformResult(result, exposeRefresh = false) {
102032
+ assertSubscribable(result, (message) => console.error(message));
102033
+ if (result.isErr()) throwUnwrappedUserlandError(result.error.failure);
102034
+ deepFreeze(result.value.data);
102035
+ const api = {
102036
+ data: result.value.data,
102037
+ subscribe: (callback) => result.value.subscribe((update) => {
102038
+ const { data, error } = toQueryUpdate(update);
102039
+ return callback({ data, error });
102040
+ })
102041
+ };
102042
+ if (exposeRefresh) {
102043
+ return {
102044
+ ...api,
102045
+ refresh: () => result.value.refresh().then((refreshed) => {
102046
+ if (refreshed.isOk()) return void 0;
102047
+ throw refreshed.error;
102048
+ })
102049
+ };
102050
+ }
102051
+ return api;
102052
+ }
102053
+ }
102054
+ function buildServiceDescriptor$7() {
102055
+ return {
102056
+ type: "subscribableImperativeBindings",
102057
+ version: "1.0",
102058
+ service: new SubscribableImperativeBindingsService()
102059
+ };
102060
+ }
102061
+
101892
102062
  const supportedCachePolicyTypes = ["no-cache", "only-if-cached"];
101893
102063
  function requestContextIsSupportedCachePolicy(requestContext) {
101894
102064
  return typeof requestContext === "object" && requestContext !== null && "cachePolicy" in requestContext && typeof requestContext.cachePolicy === "object" && requestContext.cachePolicy !== null && "type" in requestContext.cachePolicy && typeof requestContext.cachePolicy.type === "string" && supportedCachePolicyTypes.includes(
@@ -101941,7 +102111,7 @@ class DefaultImperativeBindingsService {
101941
102111
  });
101942
102112
  }
101943
102113
  }
101944
- function buildServiceDescriptor$6() {
102114
+ function buildServiceDescriptor$5() {
101945
102115
  return {
101946
102116
  type: "defaultImperativeBindings",
101947
102117
  version: "1.0",
@@ -101961,70 +102131,13 @@ class QueryImperativeBindingsService {
101961
102131
  });
101962
102132
  }
101963
102133
  }
101964
- function buildServiceDescriptor$5() {
102134
+ function buildServiceDescriptor$4() {
101965
102135
  return {
101966
102136
  type: "queryImperativeBindings",
101967
102137
  version: "1.0",
101968
102138
  service: new QueryImperativeBindingsService()
101969
102139
  };
101970
102140
  }
101971
- class SubscribableImperativeBindingsService {
101972
- bind(getCommand, exposeRefresh = false) {
101973
- return buildBaseImperativeInvoker(
101974
- getCommand,
101975
- (result) => this.transformResult(result, exposeRefresh)
101976
- );
101977
- }
101978
- transformResult(result, exposeRefresh = false) {
101979
- if (!isSubscribableResult(result)) {
101980
- console.error(
101981
- "Non-subscribable result encountered - please use correct operation type"
101982
- );
101983
- throw new Error("Internal error in Lightning Data Service adapter occurred");
101984
- }
101985
- if (result.isOk()) {
101986
- deepFreeze(result.value.data);
101987
- const api = {
101988
- data: result.value.data,
101989
- subscribe: (cb) => {
101990
- return result.value.subscribe((result2) => {
101991
- if (result2.isErr()) {
101992
- return cb({
101993
- data: void 0,
101994
- error: unwrapUserlandError(result2.error)
101995
- });
101996
- }
101997
- return cb({ data: result2.value, error: void 0 });
101998
- });
101999
- }
102000
- };
102001
- if (exposeRefresh) {
102002
- return {
102003
- ...api,
102004
- refresh: () => {
102005
- return result.value.refresh().then((res) => {
102006
- if (res.isOk()) {
102007
- return void 0;
102008
- }
102009
- throw res.error;
102010
- });
102011
- }
102012
- };
102013
- } else {
102014
- return api;
102015
- }
102016
- } else {
102017
- throwUnwrappedUserlandError(result.error.failure);
102018
- }
102019
- }
102020
- }
102021
- function buildServiceDescriptor$4() {
102022
- return {
102023
- type: "subscribableImperativeBindings",
102024
- version: "1.0",
102025
- service: new SubscribableImperativeBindingsService()
102026
- };
102027
- }
102028
102141
  class LegacyImperativeBindingsService {
102029
102142
  bind(getCommand) {
102030
102143
  const invoke = async (config, requestContext, callback) => {
@@ -102326,7 +102439,7 @@ class GraphQLMutationBindingsService {
102326
102439
  };
102327
102440
  }
102328
102441
  }
102329
- function buildServiceDescriptor$7() {
102442
+ function buildServiceDescriptor$6() {
102330
102443
  return {
102331
102444
  type: "graphQLMutationBindings",
102332
102445
  version: "1.0",
@@ -103474,13 +103587,13 @@ function initializeOneStore(sqliteStore, luvio) {
103474
103587
  featureFlagsServiceDescriptor,
103475
103588
  buildServiceDescriptor$b(luvio),
103476
103589
  luvioUiapiRecordsServiceDescriptor,
103477
- buildServiceDescriptor$6(),
103478
103590
  buildServiceDescriptor$5(),
103479
103591
  buildServiceDescriptor$4(),
103592
+ buildServiceDescriptor$7(),
103480
103593
  buildServiceDescriptor$3(),
103481
103594
  buildServiceDescriptor$2$1(),
103482
103595
  buildServiceDescriptor$1$2(),
103483
- buildServiceDescriptor$7(),
103596
+ buildServiceDescriptor$6(),
103484
103597
  buildServiceDescriptor$1$1(),
103485
103598
  buildServiceDescriptor$2(),
103486
103599
  // TODO [W-18753648]: See note above.
@@ -103645,12 +103758,19 @@ function getRuntime({ primeUser = false } = {}) {
103645
103758
  logInfo(`Serial draft queue created with batching=${useQueueBatching}, strictOrdering=true`);
103646
103759
  lazyDraftQueue = buildLdsDraftQueue(lazyDurableStore, sharedDraftStore, {
103647
103760
  // No peer queues when there's no binary lane (batching-only).
103648
- getPeerQueues: () => (useConcurrentBinaryQueue ? [lazyBinaryDraftQueue] : []),
103761
+ getPeerQueues: () => lazyBinaryDraftQueue !== undefined ? [lazyBinaryDraftQueue] : [],
103649
103762
  concurrency: 1,
103650
103763
  strictOrdering: true,
103651
103764
  queueBatching: useQueueBatching,
103652
103765
  });
103653
- if (useConcurrentBinaryQueue) {
103766
+ // The binary lane lives only in the worker realm. In the WebView realm the serial
103767
+ // queue is a Nimbus proxy to the worker's routing façade, which already routes
103768
+ // binary uploads to the worker's binary lane; a local binary queue there would
103769
+ // take uploads the worker never sees. Only worker-realm queues expose
103770
+ // isHandlerRegistered.
103771
+ if (useConcurrentBinaryQueue &&
103772
+ typeof lazyDraftQueue.isHandlerRegistered ===
103773
+ 'function') {
103654
103774
  lazyBinaryDraftQueue = buildLdsPerformanceDraftQueue(lazyDurableStore, sharedDraftStore, {
103655
103775
  getPeerQueues: () => [lazyDraftQueue],
103656
103776
  concurrency: 4,
@@ -103671,27 +103791,19 @@ function getRuntime({ primeUser = false } = {}) {
103671
103791
  const updateRecordQuickActionHandler = new UpdateRecordQuickActionExecutionRepresentationHandler(() => lazyLuvio, draftService, lazyDraftQueue, lazyNetworkAdapter, isGenerated, lazySideEffectService);
103672
103792
  // Route the CD composite to the concurrent binary queue when gate-ON so
103673
103793
  // multipart uploads run in parallel and don't block other DML.
103674
- const contentDocumentTargetQueue = useConcurrentBinaryQueue
103675
- ? lazyBinaryDraftQueue
103676
- : lazyDraftQueue;
103677
- logInfo(`ContentDocumentVersion handler routed to ${useConcurrentBinaryQueue ? 'concurrent draft queue' : 'serial draft queue'}`);
103794
+ const contentDocumentTargetQueue = lazyBinaryDraftQueue ?? lazyDraftQueue;
103795
+ logInfo(`ContentDocumentVersion handler routed to ${lazyBinaryDraftQueue !== undefined ? 'concurrent draft queue' : 'serial draft queue'}`);
103678
103796
  const contentDocumentCompositeActionHandler = new ContentDocumentCompositeRepresentationActionHandler(() => lazyLuvio, userId, draftService, lazyObjectInfoService, contentDocumentTargetQueue, lazyNetworkAdapter, isGenerated, NimbusBinaryStore, lazySideEffectService);
103679
103797
  lazyDraftQueue.addHandler(uiApiRecordHandler);
103680
103798
  lazyDraftQueue.addHandler(quickActionHandler);
103681
103799
  lazyDraftQueue.addHandler(updateRecordQuickActionHandler);
103682
103800
  contentDocumentTargetQueue.addHandler(contentDocumentCompositeActionHandler);
103683
- // Build the routing façade only with the flag on AND over concrete, handler-owning
103684
- // queues. Only the worker-realm queues expose isHandlerRegistered; the WebView realm's
103685
- // Nimbus proxies lack it. Feature-detect that method rather than sniffing the realm via
103686
- // `window`: it tests the exact invariant the DurableDraftQueue casts below rely on, and
103687
- // stays correct in non-browser (e.g. jest) realms where `window` is an unreliable realm
103688
- // signal. The flag must stay the first term — it short-circuits the queue accesses, and
103689
- // the gate-OFF path never builds lazyBinaryDraftQueue (it is undefined there).
103690
- const shouldBuildRoutingQueue = useConcurrentBinaryQueue &&
103691
- typeof lazyDraftQueue.isHandlerRegistered ===
103692
- 'function' &&
103693
- typeof lazyBinaryDraftQueue
103694
- .isHandlerRegistered === 'function';
103801
+ // Build the routing façade and manager only when the binary lane exists: flag on and
103802
+ // in the worker realm, over concrete, handler-owning queues (see where it is built).
103803
+ // Feature-detecting isHandlerRegistered rather than sniffing the realm via `window` tests
103804
+ // the exact invariant the queue casts below rely on, and stays correct in non-browser
103805
+ // (e.g. jest) realms where `window` is an unreliable realm signal.
103806
+ const shouldBuildRoutingQueue = lazyBinaryDraftQueue !== undefined;
103695
103807
  if (shouldBuildRoutingQueue) {
103696
103808
  // Serial is the primary/fallback lane, so the bridged `draftQueue` routes enqueue
103697
103809
  // by handler ownership in the worker. Lane labels are stamped onto each action
@@ -103706,7 +103818,9 @@ function getRuntime({ primeUser = false } = {}) {
103706
103818
  },
103707
103819
  ]);
103708
103820
  }
103709
- lazyDraftManager = useConcurrentBinaryQueue
103821
+ // The WebView realm's (unused) manager falls back to the base DraftManager: native only
103822
+ // drives the worker-realm manager, and RoutingDraftManager needs the concrete queues.
103823
+ lazyDraftManager = shouldBuildRoutingQueue
103710
103824
  ? new RoutingDraftManager(lazyDraftQueue, lazyBinaryDraftQueue, DRAFT_QUEUE_LANE)
103711
103825
  : new DraftManager(lazyDraftQueue);
103712
103826
  const objectInfoCachingEnvironment = enableObjectInfoCaching(durableEnv, lazyObjectInfoService.ensureObjectInfoCached);
@@ -103784,8 +103898,6 @@ function getRuntime({ primeUser = false } = {}) {
103784
103898
  environment: lazyEnvironment,
103785
103899
  draftManager: lazyDraftManager,
103786
103900
  draftQueue: lazyRoutingDraftQueue ?? lazyDraftQueue,
103787
- serialDraftQueue: lazyDraftQueue,
103788
- binaryDraftQueue: lazyBinaryDraftQueue,
103789
103901
  createPrimingSession: (config) => {
103790
103902
  return primingSessionFactory({
103791
103903
  store: lazyDurableStore,
@@ -103811,7 +103923,7 @@ register$1({
103811
103923
  id: '@salesforce/lds-network-adapter',
103812
103924
  instrument: instrument$2,
103813
103925
  });
103814
- // version: 1.467.0-4f065d2a2a
103926
+ // version: 1.468.0-9ef0fbdaee
103815
103927
 
103816
103928
  const { create: create$2, keys: keys$2 } = Object;
103817
103929
  const { stringify, parse } = JSON;
@@ -111361,7 +111473,7 @@ function registerCallback(cb) {
111361
111473
  cb(graphql_v1_import, graphql_imperative$1, graphql_imperative_legacy_v1_import, graphql_state_manager);
111362
111474
  }
111363
111475
  }
111364
- // version: 1.467.0-049a8b6027
111476
+ // version: 1.468.0-c060a9b9c6
111365
111477
 
111366
111478
  function createFragmentMap(documentNode) {
111367
111479
  const fragments = {};
@@ -140590,7 +140702,7 @@ register$1({
140590
140702
  configuration: { ...configurationForGraphQLAdapters$1 },
140591
140703
  instrument: instrument$1,
140592
140704
  });
140593
- // version: 1.467.0-049a8b6027
140705
+ // version: 1.468.0-c060a9b9c6
140594
140706
 
140595
140707
  // On core the unstable adapters are re-exported with different names,
140596
140708
  // we want to match them here.
@@ -140742,7 +140854,7 @@ withDefaultLuvio((luvio) => {
140742
140854
  unstable_graphQL_imperative = createImperativeAdapter(luvio, createInstrumentedAdapter(ldsAdapter, adapterMetadata), adapterMetadata);
140743
140855
  graphQLImperative = ldsAdapter;
140744
140856
  });
140745
- // version: 1.467.0-049a8b6027
140857
+ // version: 1.468.0-c060a9b9c6
140746
140858
 
140747
140859
  var gqlApi = /*#__PURE__*/Object.freeze({
140748
140860
  __proto__: null,
@@ -141594,7 +141706,7 @@ const callbacks$1 = [];
141594
141706
  function register(r) {
141595
141707
  callbacks$1.forEach((callback) => callback(r));
141596
141708
  }
141597
- // version: 1.467.0-4f065d2a2a
141709
+ // version: 1.468.0-9ef0fbdaee
141598
141710
 
141599
141711
  /**
141600
141712
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -142883,4 +142995,4 @@ const { luvio } = getRuntime();
142883
142995
  setDefaultLuvio({ luvio });
142884
142996
 
142885
142997
  export { createPrimingSession, draftManager, draftQueue, evictCacheRecordsByIds, evictExpiredCacheEntries, executeAdapter, executeMutatingAdapter, getImperativeAdapterNames, importLuvioAdapterModule, importOneStoreAdapterModule, invokeAdapter, invokeAdapterWithDraftToMerge, invokeAdapterWithDraftToMergeAndMetadata, invokeAdapterWithDraftToReplace, invokeAdapterWithMetadata, nimbusDraftQueue, registerReportObserver, setMetadataTTL, setUiApiRecordTTL, stopEviction, subscribeToAdapter };
142886
- // version: 1.467.0-4f065d2a2a
142998
+ // version: 1.468.0-9ef0fbdaee