@salesforce/lds-worker-api 1.229.0-dev5 → 1.229.0-dev6

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.
@@ -795,4 +795,4 @@ if (process.env.NODE_ENV !== 'production') {
795
795
  }
796
796
 
797
797
  export { createPrimingSession, draftManager, draftQueue, executeAdapter, executeMutatingAdapter, getImperativeAdapterNames, invokeAdapter, invokeAdapterWithDraftToReplace, invokeAdapterWithMetadata, nimbusDraftQueue, setMetadataTTL, setUiApiRecordTTL, subscribeToAdapter };
798
- // version: 1.229.0-dev5-c763e7f91
798
+ // version: 1.229.0-dev6-53f3d6911
@@ -2275,6 +2275,34 @@ var FragmentReadResultState$1;
2275
2275
  const FRAGMENT_READ_RESULT_MISSING = {
2276
2276
  state: FragmentReadResultState$1.Missing,
2277
2277
  };
2278
+ function resolveLink$1(reader, storeLink, version) {
2279
+ const { StoreLinkStateValues } = reader;
2280
+ const linkState = reader.getLinkState(storeLink);
2281
+ switch (linkState.state) {
2282
+ case StoreLinkStateValues.RefNotPresent:
2283
+ case StoreLinkStateValues.NotPresent:
2284
+ case StoreLinkStateValues.Missing:
2285
+ reader.markMissingLink(storeLink.__ref);
2286
+ reader.markMissing();
2287
+ return;
2288
+ case StoreLinkStateValues.Pending:
2289
+ reader.markPending();
2290
+ return;
2291
+ case StoreLinkStateValues.Null:
2292
+ return;
2293
+ }
2294
+ const { key: __ref } = linkState;
2295
+ return reader.read({
2296
+ recordId: __ref,
2297
+ node: {
2298
+ kind: 'Fragment',
2299
+ private: [],
2300
+ opaque: true,
2301
+ version,
2302
+ },
2303
+ variables: {},
2304
+ });
2305
+ }
2278
2306
  class Reader {
2279
2307
  constructor(store, variables, refresh, baseSnapshot, ttlStrategy) {
2280
2308
  this.store = store;
@@ -3841,7 +3869,7 @@ function createResourceParamsImpl(config, configMetadata) {
3841
3869
  }
3842
3870
  return resourceParams;
3843
3871
  }
3844
- // engine version: 0.146.0-dev3-502c4337
3872
+ // engine version: 0.146.0-dev4-c265089a
3845
3873
 
3846
3874
  /**
3847
3875
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -3968,7 +3996,7 @@ function withDefaultLuvio(callback) {
3968
3996
  }
3969
3997
  callbacks.push(callback);
3970
3998
  }
3971
- // version: 1.229.0-dev5-c763e7f91
3999
+ // version: 1.229.0-dev6-53f3d6911
3972
4000
 
3973
4001
  // TODO [TD-0081508]: once that TD is fulfilled we can probably change this file
3974
4002
  function instrumentAdapter$1(createFunction, _metadata) {
@@ -15429,7 +15457,7 @@ function gql(literals, ...subs) {
15429
15457
  }
15430
15458
  return superResult;
15431
15459
  }
15432
- // version: 1.229.0-dev5-c763e7f91
15460
+ // version: 1.229.0-dev6-53f3d6911
15433
15461
 
15434
15462
  function unwrap(data) {
15435
15463
  // The lwc-luvio bindings import a function from lwc called "unwrap".
@@ -16353,7 +16381,7 @@ function createGraphQLWireAdapterConstructor(luvio, adapter, metadata, astResolv
16353
16381
  const { apiFamily, name } = metadata;
16354
16382
  return createGraphQLWireAdapterConstructor$1(adapter, `${apiFamily}.${name}`, luvio, astResolver);
16355
16383
  }
16356
- // version: 1.229.0-dev5-c763e7f91
16384
+ // version: 1.229.0-dev6-53f3d6911
16357
16385
 
16358
16386
  /**
16359
16387
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -16452,7 +16480,7 @@ var TypeCheckShapes;
16452
16480
  TypeCheckShapes[TypeCheckShapes["Integer"] = 3] = "Integer";
16453
16481
  TypeCheckShapes[TypeCheckShapes["Unsupported"] = 4] = "Unsupported";
16454
16482
  })(TypeCheckShapes || (TypeCheckShapes = {}));
16455
- // engine version: 0.146.0-dev3-502c4337
16483
+ // engine version: 0.146.0-dev4-c265089a
16456
16484
 
16457
16485
  const { keys: ObjectKeys$3, create: ObjectCreate$3 } = Object;
16458
16486
 
@@ -41173,7 +41201,7 @@ withDefaultLuvio((luvio) => {
41173
41201
  throttle(60, 60000, createLDSAdapter(luvio, 'notifyListInfoUpdateAvailable', notifyUpdateAvailableFactory$1));
41174
41202
  throttle(60, 60000, createLDSAdapter(luvio, 'notifyQuickActionDefaultsUpdateAvailable', notifyUpdateAvailableFactory));
41175
41203
  });
41176
- // version: 1.229.0-dev5-577daa79a
41204
+ // version: 1.229.0-dev6-6005e174d
41177
41205
 
41178
41206
  var caseSensitiveUserId = '005B0000000GR4OIAW';
41179
41207
 
@@ -46329,8 +46357,12 @@ function uuidv4() {
46329
46357
 
46330
46358
  const HTTP_HEADER_RETRY_AFTER = 'Retry-After';
46331
46359
  const HTTP_HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key';
46360
+ const ERROR_CODE_IDEMPOTENCY_FEATURE_NOT_ENABLED = 'IDEMPOTENCY_FEATURE_NOT_ENABLED';
46361
+ const ERROR_CODE_IDEMPOTENCY_NOT_SUPPORTED = 'IDEMPOTENCY_NOT_SUPPORTED';
46332
46362
  const ERROR_CODE_IDEMPOTENCY_KEY_USED_DIFFERENT_USER = 'IDEMPOTENCY_KEY_USED_DIFFERENT_USER';
46333
46363
  const ERROR_CODE_IDEMPOTENCY_CONCURRENT_REQUEST = 'IDEMPOTENCY_CONCURRENT_REQUEST';
46364
+ const ERROR_CODE_IDEMPOTENCY_KEY_ALREADY_USED = 'IDEMPOTENCY_KEY_ALREADY_USED';
46365
+ const ERROR_CODE_IDEMPOTENCY_BACKEND_OPERATION_ERROR = 'IDEMPOTENCY_BACKEND_OPERATION_ERROR';
46334
46366
  /**
46335
46367
  * Get the retry after in milliseconds from the response headers, undefined if not specified.
46336
46368
  * The header could have two different format.
@@ -46360,7 +46392,9 @@ function buildLuvioOverrideForDraftAdapters(luvio, handler, extractTargetIdFromC
46360
46392
  const dispatchResourceRequest = async function (resourceRequest, _context) {
46361
46393
  const resourceRequestCopy = clone$1(resourceRequest);
46362
46394
  resourceRequestCopy.headers = resourceRequestCopy.headers || {};
46363
- resourceRequestCopy.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
46395
+ if (handler.hasIdempotencySupport()) {
46396
+ resourceRequestCopy.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
46397
+ }
46364
46398
  // enable return extra fields for record creation and record update http call
46365
46399
  if (resourceRequest.basePath === '/ui-api/records' &&
46366
46400
  (resourceRequest.method === 'post' || resourceRequest.method === 'patch')) {
@@ -47182,6 +47216,7 @@ class AbstractResourceRequestActionHandler {
47182
47216
  // the luvio store redirect table, during which a new draft might be enqueued
47183
47217
  // which would not see a necessary mapping.
47184
47218
  this.ephemeralRedirects = {};
47219
+ this.isIdempotencySupported = true;
47185
47220
  }
47186
47221
  enqueue(data) {
47187
47222
  return this.draftQueue.enqueue(this.handlerId, data);
@@ -47211,21 +47246,43 @@ class AbstractResourceRequestActionHandler {
47211
47246
  retryDelayInMs = getRetryAfterInMs(response.headers);
47212
47247
  shouldRetry = true;
47213
47248
  break;
47214
- case HttpStatusCode$1.ServerError:
47249
+ case HttpStatusCode$1.ServerError: {
47215
47250
  shouldRetry = true;
47251
+ if (this.handleIdempotencyServerError(response.body, updatedAction, false, ERROR_CODE_IDEMPOTENCY_BACKEND_OPERATION_ERROR)) {
47252
+ this.isIdempotencySupported = false;
47253
+ retryDelayInMs = 0;
47254
+ actionDataChanged = true;
47255
+ }
47216
47256
  break;
47257
+ }
47217
47258
  case 409 /* IdempotentWriteSpecificHttpStatusCode.Conflict */: {
47218
- const errorCode = response.body[0].errorCode;
47219
- if (errorCode === ERROR_CODE_IDEMPOTENCY_KEY_USED_DIFFERENT_USER) {
47220
- updatedAction.data.headers = updatedAction.data.headers || {};
47221
- updatedAction.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
47259
+ if (this.isUiApiErrors(response.body)) {
47260
+ const errorCode = response.body[0].errorCode;
47261
+ if (this.handleIdempotencyServerError(response.body, updatedAction, true, ERROR_CODE_IDEMPOTENCY_KEY_USED_DIFFERENT_USER)) {
47262
+ retryDelayInMs = 0;
47263
+ actionDataChanged = true;
47264
+ }
47265
+ else if (errorCode === ERROR_CODE_IDEMPOTENCY_CONCURRENT_REQUEST) {
47266
+ retryDelayInMs = getRetryAfterInMs(response.headers);
47267
+ }
47268
+ shouldRetry = true;
47269
+ }
47270
+ break;
47271
+ }
47272
+ case HttpStatusCode$1.BadRequest: {
47273
+ if (this.handleIdempotencyServerError(response.body, updatedAction, false, ERROR_CODE_IDEMPOTENCY_FEATURE_NOT_ENABLED, ERROR_CODE_IDEMPOTENCY_NOT_SUPPORTED)) {
47222
47274
  retryDelayInMs = 0;
47223
47275
  actionDataChanged = true;
47276
+ shouldRetry = true;
47224
47277
  }
47225
- else if (errorCode === ERROR_CODE_IDEMPOTENCY_CONCURRENT_REQUEST) {
47226
- retryDelayInMs = getRetryAfterInMs(response.headers);
47278
+ break;
47279
+ }
47280
+ case 422 /* IdempotentWriteSpecificHttpStatusCode.UnProcessableEntity */: {
47281
+ if (this.handleIdempotencyServerError(response.body, updatedAction, true, ERROR_CODE_IDEMPOTENCY_KEY_ALREADY_USED)) {
47282
+ retryDelayInMs = 0;
47283
+ actionDataChanged = true;
47284
+ shouldRetry = true;
47227
47285
  }
47228
- shouldRetry = true;
47229
47286
  break;
47230
47287
  }
47231
47288
  }
@@ -47244,6 +47301,27 @@ class AbstractResourceRequestActionHandler {
47244
47301
  return ProcessActionResult.NETWORK_ERROR;
47245
47302
  }
47246
47303
  }
47304
+ // true if response is an idempotency server error. updates or deletes idempotency key if the reponse is idempotency related error. Idempotency related error is in format of UiApiError array.
47305
+ handleIdempotencyServerError(responseBody, action, updateIdempotencyKey, ...targetErrorCodes) {
47306
+ if (this.isUiApiErrors(responseBody)) {
47307
+ const errorCode = responseBody[0].errorCode;
47308
+ if (targetErrorCodes.includes(errorCode)) {
47309
+ action.data.headers = action.data.headers || {};
47310
+ if (updateIdempotencyKey) {
47311
+ action.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
47312
+ }
47313
+ else {
47314
+ delete action.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY];
47315
+ }
47316
+ return true;
47317
+ }
47318
+ }
47319
+ return false;
47320
+ }
47321
+ // checks if the body is an array of UiApiError. Sometimes the body has `enhancedErrorType` field as an error indicator(one example is the field validation failure). In such case Action being processed updates to an Error Action.
47322
+ isUiApiErrors(body) {
47323
+ return body !== undefined && Array.isArray(body) && body.length > 0 && body[0].errorCode;
47324
+ }
47247
47325
  async buildPendingAction(request, queue) {
47248
47326
  const targetId = await this.getIdFromRequest(request);
47249
47327
  if (targetId === undefined) {
@@ -47457,6 +47535,10 @@ class AbstractResourceRequestActionHandler {
47457
47535
  ...targetData,
47458
47536
  body: this.mergeRequestBody(targetBody, sourceBody),
47459
47537
  };
47538
+ // Updates Idempotency key if target has one
47539
+ if (targetData.headers && targetData.headers[HTTP_HEADER_IDEMPOTENCY_KEY]) {
47540
+ merged.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
47541
+ }
47460
47542
  // overlay metadata
47461
47543
  merged.metadata = { ...targetMetadata, ...sourceMetadata };
47462
47544
  // put status back to pending to auto upload if queue is active and targed is at the head.
@@ -47493,6 +47575,9 @@ class AbstractResourceRequestActionHandler {
47493
47575
  getDraftIdsFromAction(action) {
47494
47576
  return [action.targetId];
47495
47577
  }
47578
+ hasIdempotencySupport() {
47579
+ return this.isIdempotencySupported;
47580
+ }
47496
47581
  async ingestResponses(responses, action) {
47497
47582
  const luvio = this.getLuvio();
47498
47583
  await luvio.handleSuccessResponse(() => {
@@ -57964,7 +58049,7 @@ register({
57964
58049
  id: '@salesforce/lds-network-adapter',
57965
58050
  instrument: instrument$1,
57966
58051
  });
57967
- // version: 1.229.0-dev5-c763e7f91
58052
+ // version: 1.229.0-dev6-53f3d6911
57968
58053
 
57969
58054
  const { create: create$2, keys: keys$2 } = Object;
57970
58055
  const { stringify: stringify$1, parse: parse$1 } = JSON;
@@ -72753,17 +72838,8 @@ function buildSelectionForField$7(source, reader, sel, variables, fragments, isC
72753
72838
  return sink;
72754
72839
  }
72755
72840
  function selectTypeLink(sel, fieldData, reader, key, sink, variables, fragments, version, selectFn, isCursorConnection) {
72756
- const resolvedLink = reader.read({
72757
- recordId: fieldData.__ref,
72758
- node: {
72759
- kind: 'Fragment',
72760
- private: [],
72761
- opaque: true,
72762
- version,
72763
- },
72764
- variables: {}
72765
- });
72766
- if (resolvedLink.data !== undefined) {
72841
+ const resolvedLink = resolveLink$1(reader, fieldData, version);
72842
+ if (resolvedLink && resolvedLink.data !== undefined) {
72767
72843
  if (isCursorConnection) {
72768
72844
  selectTypeLinkWithPagination(resolvedLink, sel, fieldData, reader, key, sink, variables, fragments, selectFn);
72769
72845
  }
@@ -73339,19 +73415,11 @@ function selectType$6(typename, sel, fieldData, reader, key, sink, variables, fr
73339
73415
  }
73340
73416
  case 'PolymorphicParentRelationship':
73341
73417
  case 'RecordRepresentation': {
73342
- const spanningFieldLink = reader.read({
73343
- recordId: fieldData.__ref,
73344
- node: {
73345
- kind: 'Fragment',
73346
- private: [],
73347
- opaque: true,
73348
- version: VERSION$f,
73349
- },
73350
- variables: {},
73351
- });
73352
- reader.markSeenId(fieldData.__ref);
73353
- const resolvedSpanningFieldValue = spanningFieldLink.data;
73418
+ const spanningFieldLink = resolveLink$1(reader, fieldData, VERSION$f);
73419
+ const resolvedSpanningFieldValue = spanningFieldLink && spanningFieldLink.data;
73420
+ const fieldDataRef = fieldData.__ref;
73354
73421
  if (resolvedSpanningFieldValue !== undefined) {
73422
+ reader.markSeenId(fieldDataRef);
73355
73423
  const { value: spanningFieldResult } = resolvedSpanningFieldValue;
73356
73424
  // Handle null values - graphql will return it at the field level, not return nested { value: null }
73357
73425
  if (spanningFieldResult === null || typeof spanningFieldResult !== 'object') {
@@ -73375,7 +73443,9 @@ function selectType$6(typename, sel, fieldData, reader, key, sink, variables, fr
73375
73443
  }
73376
73444
  }
73377
73445
  else {
73378
- reader.markMissingLink(fieldData.__ref);
73446
+ if (fieldDataRef !== undefined) {
73447
+ reader.markMissingLink(fieldDataRef);
73448
+ }
73379
73449
  reader.markMissing();
73380
73450
  }
73381
73451
  break;
@@ -76411,7 +76481,7 @@ register({
76411
76481
  configuration: { ...configurationForGraphQLAdapters },
76412
76482
  instrument,
76413
76483
  });
76414
- // version: 1.229.0-dev5-577daa79a
76484
+ // version: 1.229.0-dev6-6005e174d
76415
76485
 
76416
76486
  // On core the unstable adapters are re-exported with different names,
76417
76487
 
@@ -78658,7 +78728,7 @@ withDefaultLuvio((luvio) => {
78658
78728
  unstable_graphQL_imperative = createImperativeAdapter(luvio, createInstrumentedAdapter(ldsAdapter, adapterMetadata), adapterMetadata);
78659
78729
  graphQLImperative = ldsAdapter;
78660
78730
  });
78661
- // version: 1.229.0-dev5-577daa79a
78731
+ // version: 1.229.0-dev6-6005e174d
78662
78732
 
78663
78733
  var gqlApi = /*#__PURE__*/Object.freeze({
78664
78734
  __proto__: null,
@@ -79372,4 +79442,4 @@ const { luvio } = getRuntime();
79372
79442
  setDefaultLuvio({ luvio });
79373
79443
 
79374
79444
  export { createPrimingSession, draftManager, draftQueue, executeAdapter, executeMutatingAdapter, getImperativeAdapterNames, invokeAdapter, invokeAdapterWithDraftToReplace, invokeAdapterWithMetadata, nimbusDraftQueue, registerReportObserver, setMetadataTTL, setUiApiRecordTTL, subscribeToAdapter };
79375
- // version: 1.229.0-dev5-c763e7f91
79445
+ // version: 1.229.0-dev6-53f3d6911
@@ -2281,6 +2281,34 @@
2281
2281
  const FRAGMENT_READ_RESULT_MISSING = {
2282
2282
  state: FragmentReadResultState$1.Missing,
2283
2283
  };
2284
+ function resolveLink$1(reader, storeLink, version) {
2285
+ const { StoreLinkStateValues } = reader;
2286
+ const linkState = reader.getLinkState(storeLink);
2287
+ switch (linkState.state) {
2288
+ case StoreLinkStateValues.RefNotPresent:
2289
+ case StoreLinkStateValues.NotPresent:
2290
+ case StoreLinkStateValues.Missing:
2291
+ reader.markMissingLink(storeLink.__ref);
2292
+ reader.markMissing();
2293
+ return;
2294
+ case StoreLinkStateValues.Pending:
2295
+ reader.markPending();
2296
+ return;
2297
+ case StoreLinkStateValues.Null:
2298
+ return;
2299
+ }
2300
+ const { key: __ref } = linkState;
2301
+ return reader.read({
2302
+ recordId: __ref,
2303
+ node: {
2304
+ kind: 'Fragment',
2305
+ private: [],
2306
+ opaque: true,
2307
+ version,
2308
+ },
2309
+ variables: {},
2310
+ });
2311
+ }
2284
2312
  class Reader {
2285
2313
  constructor(store, variables, refresh, baseSnapshot, ttlStrategy) {
2286
2314
  this.store = store;
@@ -3847,7 +3875,7 @@
3847
3875
  }
3848
3876
  return resourceParams;
3849
3877
  }
3850
- // engine version: 0.146.0-dev3-502c4337
3878
+ // engine version: 0.146.0-dev4-c265089a
3851
3879
 
3852
3880
  /**
3853
3881
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -3974,7 +4002,7 @@
3974
4002
  }
3975
4003
  callbacks.push(callback);
3976
4004
  }
3977
- // version: 1.229.0-dev5-c763e7f91
4005
+ // version: 1.229.0-dev6-53f3d6911
3978
4006
 
3979
4007
  // TODO [TD-0081508]: once that TD is fulfilled we can probably change this file
3980
4008
  function instrumentAdapter$1(createFunction, _metadata) {
@@ -15435,7 +15463,7 @@
15435
15463
  }
15436
15464
  return superResult;
15437
15465
  }
15438
- // version: 1.229.0-dev5-c763e7f91
15466
+ // version: 1.229.0-dev6-53f3d6911
15439
15467
 
15440
15468
  function unwrap(data) {
15441
15469
  // The lwc-luvio bindings import a function from lwc called "unwrap".
@@ -16359,7 +16387,7 @@
16359
16387
  const { apiFamily, name } = metadata;
16360
16388
  return createGraphQLWireAdapterConstructor$1(adapter, `${apiFamily}.${name}`, luvio, astResolver);
16361
16389
  }
16362
- // version: 1.229.0-dev5-c763e7f91
16390
+ // version: 1.229.0-dev6-53f3d6911
16363
16391
 
16364
16392
  /**
16365
16393
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -16458,7 +16486,7 @@
16458
16486
  TypeCheckShapes[TypeCheckShapes["Integer"] = 3] = "Integer";
16459
16487
  TypeCheckShapes[TypeCheckShapes["Unsupported"] = 4] = "Unsupported";
16460
16488
  })(TypeCheckShapes || (TypeCheckShapes = {}));
16461
- // engine version: 0.146.0-dev3-502c4337
16489
+ // engine version: 0.146.0-dev4-c265089a
16462
16490
 
16463
16491
  const { keys: ObjectKeys$3, create: ObjectCreate$3 } = Object;
16464
16492
 
@@ -41179,7 +41207,7 @@
41179
41207
  throttle(60, 60000, createLDSAdapter(luvio, 'notifyListInfoUpdateAvailable', notifyUpdateAvailableFactory$1));
41180
41208
  throttle(60, 60000, createLDSAdapter(luvio, 'notifyQuickActionDefaultsUpdateAvailable', notifyUpdateAvailableFactory));
41181
41209
  });
41182
- // version: 1.229.0-dev5-577daa79a
41210
+ // version: 1.229.0-dev6-6005e174d
41183
41211
 
41184
41212
  var caseSensitiveUserId = '005B0000000GR4OIAW';
41185
41213
 
@@ -46335,8 +46363,12 @@
46335
46363
 
46336
46364
  const HTTP_HEADER_RETRY_AFTER = 'Retry-After';
46337
46365
  const HTTP_HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key';
46366
+ const ERROR_CODE_IDEMPOTENCY_FEATURE_NOT_ENABLED = 'IDEMPOTENCY_FEATURE_NOT_ENABLED';
46367
+ const ERROR_CODE_IDEMPOTENCY_NOT_SUPPORTED = 'IDEMPOTENCY_NOT_SUPPORTED';
46338
46368
  const ERROR_CODE_IDEMPOTENCY_KEY_USED_DIFFERENT_USER = 'IDEMPOTENCY_KEY_USED_DIFFERENT_USER';
46339
46369
  const ERROR_CODE_IDEMPOTENCY_CONCURRENT_REQUEST = 'IDEMPOTENCY_CONCURRENT_REQUEST';
46370
+ const ERROR_CODE_IDEMPOTENCY_KEY_ALREADY_USED = 'IDEMPOTENCY_KEY_ALREADY_USED';
46371
+ const ERROR_CODE_IDEMPOTENCY_BACKEND_OPERATION_ERROR = 'IDEMPOTENCY_BACKEND_OPERATION_ERROR';
46340
46372
  /**
46341
46373
  * Get the retry after in milliseconds from the response headers, undefined if not specified.
46342
46374
  * The header could have two different format.
@@ -46366,7 +46398,9 @@
46366
46398
  const dispatchResourceRequest = async function (resourceRequest, _context) {
46367
46399
  const resourceRequestCopy = clone$1(resourceRequest);
46368
46400
  resourceRequestCopy.headers = resourceRequestCopy.headers || {};
46369
- resourceRequestCopy.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
46401
+ if (handler.hasIdempotencySupport()) {
46402
+ resourceRequestCopy.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
46403
+ }
46370
46404
  // enable return extra fields for record creation and record update http call
46371
46405
  if (resourceRequest.basePath === '/ui-api/records' &&
46372
46406
  (resourceRequest.method === 'post' || resourceRequest.method === 'patch')) {
@@ -47188,6 +47222,7 @@
47188
47222
  // the luvio store redirect table, during which a new draft might be enqueued
47189
47223
  // which would not see a necessary mapping.
47190
47224
  this.ephemeralRedirects = {};
47225
+ this.isIdempotencySupported = true;
47191
47226
  }
47192
47227
  enqueue(data) {
47193
47228
  return this.draftQueue.enqueue(this.handlerId, data);
@@ -47217,21 +47252,43 @@
47217
47252
  retryDelayInMs = getRetryAfterInMs(response.headers);
47218
47253
  shouldRetry = true;
47219
47254
  break;
47220
- case HttpStatusCode$1.ServerError:
47255
+ case HttpStatusCode$1.ServerError: {
47221
47256
  shouldRetry = true;
47257
+ if (this.handleIdempotencyServerError(response.body, updatedAction, false, ERROR_CODE_IDEMPOTENCY_BACKEND_OPERATION_ERROR)) {
47258
+ this.isIdempotencySupported = false;
47259
+ retryDelayInMs = 0;
47260
+ actionDataChanged = true;
47261
+ }
47222
47262
  break;
47263
+ }
47223
47264
  case 409 /* IdempotentWriteSpecificHttpStatusCode.Conflict */: {
47224
- const errorCode = response.body[0].errorCode;
47225
- if (errorCode === ERROR_CODE_IDEMPOTENCY_KEY_USED_DIFFERENT_USER) {
47226
- updatedAction.data.headers = updatedAction.data.headers || {};
47227
- updatedAction.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
47265
+ if (this.isUiApiErrors(response.body)) {
47266
+ const errorCode = response.body[0].errorCode;
47267
+ if (this.handleIdempotencyServerError(response.body, updatedAction, true, ERROR_CODE_IDEMPOTENCY_KEY_USED_DIFFERENT_USER)) {
47268
+ retryDelayInMs = 0;
47269
+ actionDataChanged = true;
47270
+ }
47271
+ else if (errorCode === ERROR_CODE_IDEMPOTENCY_CONCURRENT_REQUEST) {
47272
+ retryDelayInMs = getRetryAfterInMs(response.headers);
47273
+ }
47274
+ shouldRetry = true;
47275
+ }
47276
+ break;
47277
+ }
47278
+ case HttpStatusCode$1.BadRequest: {
47279
+ if (this.handleIdempotencyServerError(response.body, updatedAction, false, ERROR_CODE_IDEMPOTENCY_FEATURE_NOT_ENABLED, ERROR_CODE_IDEMPOTENCY_NOT_SUPPORTED)) {
47228
47280
  retryDelayInMs = 0;
47229
47281
  actionDataChanged = true;
47282
+ shouldRetry = true;
47230
47283
  }
47231
- else if (errorCode === ERROR_CODE_IDEMPOTENCY_CONCURRENT_REQUEST) {
47232
- retryDelayInMs = getRetryAfterInMs(response.headers);
47284
+ break;
47285
+ }
47286
+ case 422 /* IdempotentWriteSpecificHttpStatusCode.UnProcessableEntity */: {
47287
+ if (this.handleIdempotencyServerError(response.body, updatedAction, true, ERROR_CODE_IDEMPOTENCY_KEY_ALREADY_USED)) {
47288
+ retryDelayInMs = 0;
47289
+ actionDataChanged = true;
47290
+ shouldRetry = true;
47233
47291
  }
47234
- shouldRetry = true;
47235
47292
  break;
47236
47293
  }
47237
47294
  }
@@ -47250,6 +47307,27 @@
47250
47307
  return ProcessActionResult.NETWORK_ERROR;
47251
47308
  }
47252
47309
  }
47310
+ // true if response is an idempotency server error. updates or deletes idempotency key if the reponse is idempotency related error. Idempotency related error is in format of UiApiError array.
47311
+ handleIdempotencyServerError(responseBody, action, updateIdempotencyKey, ...targetErrorCodes) {
47312
+ if (this.isUiApiErrors(responseBody)) {
47313
+ const errorCode = responseBody[0].errorCode;
47314
+ if (targetErrorCodes.includes(errorCode)) {
47315
+ action.data.headers = action.data.headers || {};
47316
+ if (updateIdempotencyKey) {
47317
+ action.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
47318
+ }
47319
+ else {
47320
+ delete action.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY];
47321
+ }
47322
+ return true;
47323
+ }
47324
+ }
47325
+ return false;
47326
+ }
47327
+ // checks if the body is an array of UiApiError. Sometimes the body has `enhancedErrorType` field as an error indicator(one example is the field validation failure). In such case Action being processed updates to an Error Action.
47328
+ isUiApiErrors(body) {
47329
+ return body !== undefined && Array.isArray(body) && body.length > 0 && body[0].errorCode;
47330
+ }
47253
47331
  async buildPendingAction(request, queue) {
47254
47332
  const targetId = await this.getIdFromRequest(request);
47255
47333
  if (targetId === undefined) {
@@ -47463,6 +47541,10 @@
47463
47541
  ...targetData,
47464
47542
  body: this.mergeRequestBody(targetBody, sourceBody),
47465
47543
  };
47544
+ // Updates Idempotency key if target has one
47545
+ if (targetData.headers && targetData.headers[HTTP_HEADER_IDEMPOTENCY_KEY]) {
47546
+ merged.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
47547
+ }
47466
47548
  // overlay metadata
47467
47549
  merged.metadata = { ...targetMetadata, ...sourceMetadata };
47468
47550
  // put status back to pending to auto upload if queue is active and targed is at the head.
@@ -47499,6 +47581,9 @@
47499
47581
  getDraftIdsFromAction(action) {
47500
47582
  return [action.targetId];
47501
47583
  }
47584
+ hasIdempotencySupport() {
47585
+ return this.isIdempotencySupported;
47586
+ }
47502
47587
  async ingestResponses(responses, action) {
47503
47588
  const luvio = this.getLuvio();
47504
47589
  await luvio.handleSuccessResponse(() => {
@@ -57970,7 +58055,7 @@
57970
58055
  id: '@salesforce/lds-network-adapter',
57971
58056
  instrument: instrument$1,
57972
58057
  });
57973
- // version: 1.229.0-dev5-c763e7f91
58058
+ // version: 1.229.0-dev6-53f3d6911
57974
58059
 
57975
58060
  const { create: create$2, keys: keys$2 } = Object;
57976
58061
  const { stringify: stringify$1, parse: parse$1 } = JSON;
@@ -72759,17 +72844,8 @@
72759
72844
  return sink;
72760
72845
  }
72761
72846
  function selectTypeLink(sel, fieldData, reader, key, sink, variables, fragments, version, selectFn, isCursorConnection) {
72762
- const resolvedLink = reader.read({
72763
- recordId: fieldData.__ref,
72764
- node: {
72765
- kind: 'Fragment',
72766
- private: [],
72767
- opaque: true,
72768
- version,
72769
- },
72770
- variables: {}
72771
- });
72772
- if (resolvedLink.data !== undefined) {
72847
+ const resolvedLink = resolveLink$1(reader, fieldData, version);
72848
+ if (resolvedLink && resolvedLink.data !== undefined) {
72773
72849
  if (isCursorConnection) {
72774
72850
  selectTypeLinkWithPagination(resolvedLink, sel, fieldData, reader, key, sink, variables, fragments, selectFn);
72775
72851
  }
@@ -73345,19 +73421,11 @@
73345
73421
  }
73346
73422
  case 'PolymorphicParentRelationship':
73347
73423
  case 'RecordRepresentation': {
73348
- const spanningFieldLink = reader.read({
73349
- recordId: fieldData.__ref,
73350
- node: {
73351
- kind: 'Fragment',
73352
- private: [],
73353
- opaque: true,
73354
- version: VERSION$f,
73355
- },
73356
- variables: {},
73357
- });
73358
- reader.markSeenId(fieldData.__ref);
73359
- const resolvedSpanningFieldValue = spanningFieldLink.data;
73424
+ const spanningFieldLink = resolveLink$1(reader, fieldData, VERSION$f);
73425
+ const resolvedSpanningFieldValue = spanningFieldLink && spanningFieldLink.data;
73426
+ const fieldDataRef = fieldData.__ref;
73360
73427
  if (resolvedSpanningFieldValue !== undefined) {
73428
+ reader.markSeenId(fieldDataRef);
73361
73429
  const { value: spanningFieldResult } = resolvedSpanningFieldValue;
73362
73430
  // Handle null values - graphql will return it at the field level, not return nested { value: null }
73363
73431
  if (spanningFieldResult === null || typeof spanningFieldResult !== 'object') {
@@ -73381,7 +73449,9 @@
73381
73449
  }
73382
73450
  }
73383
73451
  else {
73384
- reader.markMissingLink(fieldData.__ref);
73452
+ if (fieldDataRef !== undefined) {
73453
+ reader.markMissingLink(fieldDataRef);
73454
+ }
73385
73455
  reader.markMissing();
73386
73456
  }
73387
73457
  break;
@@ -76417,7 +76487,7 @@
76417
76487
  configuration: { ...configurationForGraphQLAdapters },
76418
76488
  instrument,
76419
76489
  });
76420
- // version: 1.229.0-dev5-577daa79a
76490
+ // version: 1.229.0-dev6-6005e174d
76421
76491
 
76422
76492
  // On core the unstable adapters are re-exported with different names,
76423
76493
 
@@ -78664,7 +78734,7 @@
78664
78734
  unstable_graphQL_imperative = createImperativeAdapter(luvio, createInstrumentedAdapter(ldsAdapter, adapterMetadata), adapterMetadata);
78665
78735
  graphQLImperative = ldsAdapter;
78666
78736
  });
78667
- // version: 1.229.0-dev5-577daa79a
78737
+ // version: 1.229.0-dev6-6005e174d
78668
78738
 
78669
78739
  var gqlApi = /*#__PURE__*/Object.freeze({
78670
78740
  __proto__: null,
@@ -79395,4 +79465,4 @@
79395
79465
  Object.defineProperty(exports, '__esModule', { value: true });
79396
79466
 
79397
79467
  }));
79398
- // version: 1.229.0-dev5-c763e7f91
79468
+ // version: 1.229.0-dev6-53f3d6911
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/lds-worker-api",
3
- "version": "1.229.0-dev5",
3
+ "version": "1.229.0-dev6",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "description": "",
6
6
  "main": "dist/standalone/es/lds-worker-api.js",
@@ -35,15 +35,15 @@
35
35
  },
36
36
  "devDependencies": {
37
37
  "@oat-sa/rollup-plugin-wildcard-external": "^1.0.0",
38
- "@salesforce/lds-adapters-graphql": "1.229.0-dev5",
39
- "@salesforce/lds-adapters-uiapi": "1.229.0-dev5",
40
- "@salesforce/lds-default-luvio": "1.229.0-dev5",
41
- "@salesforce/lds-drafts": "1.229.0-dev5",
42
- "@salesforce/lds-graphql-parser": "1.229.0-dev5",
43
- "@salesforce/lds-luvio-engine": "1.229.0-dev5",
44
- "@salesforce/lds-priming": "1.229.0-dev5",
45
- "@salesforce/lds-runtime-mobile": "1.229.0-dev5",
46
- "@salesforce/nimbus-plugin-lds": "1.229.0-dev5",
38
+ "@salesforce/lds-adapters-graphql": "1.229.0-dev6",
39
+ "@salesforce/lds-adapters-uiapi": "1.229.0-dev6",
40
+ "@salesforce/lds-default-luvio": "1.229.0-dev6",
41
+ "@salesforce/lds-drafts": "1.229.0-dev6",
42
+ "@salesforce/lds-graphql-parser": "1.229.0-dev6",
43
+ "@salesforce/lds-luvio-engine": "1.229.0-dev6",
44
+ "@salesforce/lds-priming": "1.229.0-dev6",
45
+ "@salesforce/lds-runtime-mobile": "1.229.0-dev6",
46
+ "@salesforce/nimbus-plugin-lds": "1.229.0-dev6",
47
47
  "ajv": "^8.11.0",
48
48
  "glob": "^7.1.5",
49
49
  "nimbus-types": "^2.0.0-alpha1",