@salesforce/lds-runtime-mobile 1.229.0-dev4 → 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.
Files changed (3) hide show
  1. package/dist/main.js +97 -21
  2. package/package.json +16 -16
  3. package/sfdc/main.js +97 -21
package/dist/main.js CHANGED
@@ -5077,8 +5077,12 @@ function uuidv4() {
5077
5077
 
5078
5078
  const HTTP_HEADER_RETRY_AFTER = 'Retry-After';
5079
5079
  const HTTP_HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key';
5080
+ const ERROR_CODE_IDEMPOTENCY_FEATURE_NOT_ENABLED = 'IDEMPOTENCY_FEATURE_NOT_ENABLED';
5081
+ const ERROR_CODE_IDEMPOTENCY_NOT_SUPPORTED = 'IDEMPOTENCY_NOT_SUPPORTED';
5080
5082
  const ERROR_CODE_IDEMPOTENCY_KEY_USED_DIFFERENT_USER = 'IDEMPOTENCY_KEY_USED_DIFFERENT_USER';
5081
5083
  const ERROR_CODE_IDEMPOTENCY_CONCURRENT_REQUEST = 'IDEMPOTENCY_CONCURRENT_REQUEST';
5084
+ const ERROR_CODE_IDEMPOTENCY_KEY_ALREADY_USED = 'IDEMPOTENCY_KEY_ALREADY_USED';
5085
+ const ERROR_CODE_IDEMPOTENCY_BACKEND_OPERATION_ERROR = 'IDEMPOTENCY_BACKEND_OPERATION_ERROR';
5082
5086
  /**
5083
5087
  * Get the retry after in milliseconds from the response headers, undefined if not specified.
5084
5088
  * The header could have two different format.
@@ -5108,7 +5112,9 @@ function buildLuvioOverrideForDraftAdapters(luvio, handler, extractTargetIdFromC
5108
5112
  const dispatchResourceRequest = async function (resourceRequest, _context) {
5109
5113
  const resourceRequestCopy = clone$1(resourceRequest);
5110
5114
  resourceRequestCopy.headers = resourceRequestCopy.headers || {};
5111
- resourceRequestCopy.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
5115
+ if (handler.hasIdempotencySupport()) {
5116
+ resourceRequestCopy.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
5117
+ }
5112
5118
  // enable return extra fields for record creation and record update http call
5113
5119
  if (resourceRequest.basePath === '/ui-api/records' &&
5114
5120
  (resourceRequest.method === 'post' || resourceRequest.method === 'patch')) {
@@ -5944,6 +5950,7 @@ class AbstractResourceRequestActionHandler {
5944
5950
  // the luvio store redirect table, during which a new draft might be enqueued
5945
5951
  // which would not see a necessary mapping.
5946
5952
  this.ephemeralRedirects = {};
5953
+ this.isIdempotencySupported = true;
5947
5954
  }
5948
5955
  enqueue(data) {
5949
5956
  return this.draftQueue.enqueue(this.handlerId, data);
@@ -5973,21 +5980,43 @@ class AbstractResourceRequestActionHandler {
5973
5980
  retryDelayInMs = getRetryAfterInMs(response.headers);
5974
5981
  shouldRetry = true;
5975
5982
  break;
5976
- case HttpStatusCode.ServerError:
5983
+ case HttpStatusCode.ServerError: {
5977
5984
  shouldRetry = true;
5985
+ if (this.handleIdempotencyServerError(response.body, updatedAction, false, ERROR_CODE_IDEMPOTENCY_BACKEND_OPERATION_ERROR)) {
5986
+ this.isIdempotencySupported = false;
5987
+ retryDelayInMs = 0;
5988
+ actionDataChanged = true;
5989
+ }
5978
5990
  break;
5991
+ }
5979
5992
  case 409 /* IdempotentWriteSpecificHttpStatusCode.Conflict */: {
5980
- const errorCode = response.body[0].errorCode;
5981
- if (errorCode === ERROR_CODE_IDEMPOTENCY_KEY_USED_DIFFERENT_USER) {
5982
- updatedAction.data.headers = updatedAction.data.headers || {};
5983
- updatedAction.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
5993
+ if (this.isUiApiErrors(response.body)) {
5994
+ const errorCode = response.body[0].errorCode;
5995
+ if (this.handleIdempotencyServerError(response.body, updatedAction, true, ERROR_CODE_IDEMPOTENCY_KEY_USED_DIFFERENT_USER)) {
5996
+ retryDelayInMs = 0;
5997
+ actionDataChanged = true;
5998
+ }
5999
+ else if (errorCode === ERROR_CODE_IDEMPOTENCY_CONCURRENT_REQUEST) {
6000
+ retryDelayInMs = getRetryAfterInMs(response.headers);
6001
+ }
6002
+ shouldRetry = true;
6003
+ }
6004
+ break;
6005
+ }
6006
+ case HttpStatusCode.BadRequest: {
6007
+ if (this.handleIdempotencyServerError(response.body, updatedAction, false, ERROR_CODE_IDEMPOTENCY_FEATURE_NOT_ENABLED, ERROR_CODE_IDEMPOTENCY_NOT_SUPPORTED)) {
5984
6008
  retryDelayInMs = 0;
5985
6009
  actionDataChanged = true;
6010
+ shouldRetry = true;
5986
6011
  }
5987
- else if (errorCode === ERROR_CODE_IDEMPOTENCY_CONCURRENT_REQUEST) {
5988
- retryDelayInMs = getRetryAfterInMs(response.headers);
6012
+ break;
6013
+ }
6014
+ case 422 /* IdempotentWriteSpecificHttpStatusCode.UnProcessableEntity */: {
6015
+ if (this.handleIdempotencyServerError(response.body, updatedAction, true, ERROR_CODE_IDEMPOTENCY_KEY_ALREADY_USED)) {
6016
+ retryDelayInMs = 0;
6017
+ actionDataChanged = true;
6018
+ shouldRetry = true;
5989
6019
  }
5990
- shouldRetry = true;
5991
6020
  break;
5992
6021
  }
5993
6022
  }
@@ -6006,6 +6035,27 @@ class AbstractResourceRequestActionHandler {
6006
6035
  return ProcessActionResult.NETWORK_ERROR;
6007
6036
  }
6008
6037
  }
6038
+ // 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.
6039
+ handleIdempotencyServerError(responseBody, action, updateIdempotencyKey, ...targetErrorCodes) {
6040
+ if (this.isUiApiErrors(responseBody)) {
6041
+ const errorCode = responseBody[0].errorCode;
6042
+ if (targetErrorCodes.includes(errorCode)) {
6043
+ action.data.headers = action.data.headers || {};
6044
+ if (updateIdempotencyKey) {
6045
+ action.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
6046
+ }
6047
+ else {
6048
+ delete action.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY];
6049
+ }
6050
+ return true;
6051
+ }
6052
+ }
6053
+ return false;
6054
+ }
6055
+ // 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.
6056
+ isUiApiErrors(body) {
6057
+ return body !== undefined && Array.isArray(body) && body.length > 0 && body[0].errorCode;
6058
+ }
6009
6059
  async buildPendingAction(request, queue) {
6010
6060
  const targetId = await this.getIdFromRequest(request);
6011
6061
  if (targetId === undefined) {
@@ -6219,6 +6269,10 @@ class AbstractResourceRequestActionHandler {
6219
6269
  ...targetData,
6220
6270
  body: this.mergeRequestBody(targetBody, sourceBody),
6221
6271
  };
6272
+ // Updates Idempotency key if target has one
6273
+ if (targetData.headers && targetData.headers[HTTP_HEADER_IDEMPOTENCY_KEY]) {
6274
+ merged.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
6275
+ }
6222
6276
  // overlay metadata
6223
6277
  merged.metadata = { ...targetMetadata, ...sourceMetadata };
6224
6278
  // put status back to pending to auto upload if queue is active and targed is at the head.
@@ -6255,6 +6309,9 @@ class AbstractResourceRequestActionHandler {
6255
6309
  getDraftIdsFromAction(action) {
6256
6310
  return [action.targetId];
6257
6311
  }
6312
+ hasIdempotencySupport() {
6313
+ return this.isIdempotencySupported;
6314
+ }
6258
6315
  async ingestResponses(responses, action) {
6259
6316
  const luvio = this.getLuvio();
6260
6317
  await luvio.handleSuccessResponse(() => {
@@ -10215,16 +10272,18 @@ function injectFilter(filterNode, idState, parentPath, isParentPolymorphic, obje
10215
10272
  if (!isIdField) {
10216
10273
  let subSelectionNodes = [];
10217
10274
  let subFieldsHasId = false;
10218
- filterNode.value.fields.forEach((subFieldNode) => {
10219
- // Check if the filter field has the 'Id'
10220
- if (isFieldAnIdField(subFieldNode.name.value, objectInfos[objectInfoName])) {
10221
- subFieldsHasId = true;
10222
- updateIDInfo(subFieldNode, idState, draftFunctions);
10223
- }
10224
- // try injecting the fields within predicate no matter it has relation or not.
10225
- let subResults = injectFilter(subFieldNode, idState, curPath, isPolymorphicField, objectInfos, pathToObjectApiNamesMap, draftFunctions, existingFields ? existingFields[0] : undefined);
10226
- subSelectionNodes = subSelectionNodes.concat(subResults);
10227
- });
10275
+ if (isSpanning) {
10276
+ filterNode.value.fields.forEach((subFieldNode) => {
10277
+ // Check if the filter field has the 'Id'
10278
+ if (isFieldAnIdField(subFieldNode.name.value, objectInfos[objectInfoName])) {
10279
+ subFieldsHasId = true;
10280
+ updateIDInfo(subFieldNode, idState, draftFunctions);
10281
+ }
10282
+ // try injecting the fields within predicate no matter it has relation or not.
10283
+ let subResults = injectFilter(subFieldNode, idState, curPath, isPolymorphicField, objectInfos, pathToObjectApiNamesMap, draftFunctions, existingFields ? existingFields[0] : undefined);
10284
+ subSelectionNodes = subSelectionNodes.concat(subResults);
10285
+ });
10286
+ }
10228
10287
  if (!subFieldsHasId) {
10229
10288
  // Check if the query field has the 'Id'
10230
10289
  const existingIdsInQuery = existingFields &&
@@ -10253,6 +10312,7 @@ function injectFilter(filterNode, idState, parentPath, isParentPolymorphic, obje
10253
10312
  }
10254
10313
  //Inject Conditions: 1. Same field does not exist 2. Same fields has different children. 3. Filter spanning field does not have Id. 4. InLineFragment does not have the '__typename' field
10255
10314
  if (!existingFields ||
10315
+ existingFields.length === 0 ||
10256
10316
  subSelectionNodes.length > 0 ||
10257
10317
  (isSpanning && !subFieldsHasId) ||
10258
10318
  (isInlineFragment && !isTypeNameExisting)) {
@@ -12955,7 +13015,7 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
12955
13015
  // Fulfilled snapshot (this only happens in this code path if
12956
13016
  // the error is network error or 504), otherwise we spread over
12957
13017
  // the non-eval'ed snapshot (which will be either Fulfilled or Stale)
12958
- return nonEvaluatedSnapshot.state === 'Error'
13018
+ const resultSnapshot = nonEvaluatedSnapshot.state === 'Error'
12959
13019
  ? createLocalEvalSnapshot(gqlResult, seenRecords, recordId, rebuildWithLocalEval)
12960
13020
  : {
12961
13021
  ...nonEvaluatedSnapshot,
@@ -12964,6 +13024,22 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
12964
13024
  seenRecords,
12965
13025
  rebuildWithLocalEval,
12966
13026
  };
13027
+ const { refresh, state } = resultSnapshot;
13028
+ if (state !== 'Error' && refresh) {
13029
+ // after refreshing a graphql snapshot, we want to force a rebuild regardless
13030
+ // of if the call failed or not or if the data changed or not because we want
13031
+ // to make sure any potential new drafts are picked up
13032
+ resultSnapshot.refresh = {
13033
+ ...refresh,
13034
+ resolve: (config) => {
13035
+ return refresh.resolve(config).finally(() => {
13036
+ luvio.storePublish(resultSnapshot.recordId, undefined);
13037
+ luvio.storeBroadcast();
13038
+ });
13039
+ },
13040
+ };
13041
+ }
13042
+ return resultSnapshot;
12967
13043
  };
12968
13044
  }
12969
13045
 
@@ -16845,4 +16921,4 @@ register({
16845
16921
  });
16846
16922
 
16847
16923
  export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
16848
- // version: 1.229.0-dev4-07d38781a
16924
+ // version: 1.229.0-dev6-53f3d6911
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/lds-runtime-mobile",
3
- "version": "1.229.0-dev4",
3
+ "version": "1.229.0-dev6",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "description": "LDS runtime for mobile/hybrid environments.",
6
6
  "main": "dist/main.js",
@@ -32,25 +32,25 @@
32
32
  "release:corejar": "yarn build && ../core-build/scripts/core.js --name=lds-runtime-mobile"
33
33
  },
34
34
  "dependencies": {
35
- "@salesforce/lds-adapters-uiapi": "1.229.0-dev4",
36
- "@salesforce/lds-bindings": "1.229.0-dev4",
37
- "@salesforce/lds-instrumentation": "1.229.0-dev4",
38
- "@salesforce/lds-priming": "1.229.0-dev4",
35
+ "@salesforce/lds-adapters-uiapi": "1.229.0-dev6",
36
+ "@salesforce/lds-bindings": "1.229.0-dev6",
37
+ "@salesforce/lds-instrumentation": "1.229.0-dev6",
38
+ "@salesforce/lds-priming": "1.229.0-dev6",
39
39
  "@salesforce/user": "0.0.21",
40
40
  "o11y": "244.0.0"
41
41
  },
42
42
  "devDependencies": {
43
- "@salesforce/lds-adapters-graphql": "1.229.0-dev4",
44
- "@salesforce/lds-drafts": "1.229.0-dev4",
45
- "@salesforce/lds-drafts-adapters-uiapi": "1.229.0-dev4",
46
- "@salesforce/lds-graphql-eval": "1.229.0-dev4",
47
- "@salesforce/lds-network-adapter": "1.229.0-dev4",
48
- "@salesforce/lds-network-nimbus": "1.229.0-dev4",
49
- "@salesforce/lds-store-binary": "1.229.0-dev4",
50
- "@salesforce/lds-store-nimbus": "1.229.0-dev4",
51
- "@salesforce/lds-store-sql": "1.229.0-dev4",
52
- "@salesforce/lds-utils-adapters": "1.229.0-dev4",
53
- "@salesforce/nimbus-plugin-lds": "1.229.0-dev4",
43
+ "@salesforce/lds-adapters-graphql": "1.229.0-dev6",
44
+ "@salesforce/lds-drafts": "1.229.0-dev6",
45
+ "@salesforce/lds-drafts-adapters-uiapi": "1.229.0-dev6",
46
+ "@salesforce/lds-graphql-eval": "1.229.0-dev6",
47
+ "@salesforce/lds-network-adapter": "1.229.0-dev6",
48
+ "@salesforce/lds-network-nimbus": "1.229.0-dev6",
49
+ "@salesforce/lds-store-binary": "1.229.0-dev6",
50
+ "@salesforce/lds-store-nimbus": "1.229.0-dev6",
51
+ "@salesforce/lds-store-sql": "1.229.0-dev6",
52
+ "@salesforce/lds-utils-adapters": "1.229.0-dev6",
53
+ "@salesforce/nimbus-plugin-lds": "1.229.0-dev6",
54
54
  "babel-plugin-dynamic-import-node": "^2.3.3",
55
55
  "wait-for-expect": "^3.0.2"
56
56
  },
package/sfdc/main.js CHANGED
@@ -5077,8 +5077,12 @@ function uuidv4() {
5077
5077
 
5078
5078
  const HTTP_HEADER_RETRY_AFTER = 'Retry-After';
5079
5079
  const HTTP_HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key';
5080
+ const ERROR_CODE_IDEMPOTENCY_FEATURE_NOT_ENABLED = 'IDEMPOTENCY_FEATURE_NOT_ENABLED';
5081
+ const ERROR_CODE_IDEMPOTENCY_NOT_SUPPORTED = 'IDEMPOTENCY_NOT_SUPPORTED';
5080
5082
  const ERROR_CODE_IDEMPOTENCY_KEY_USED_DIFFERENT_USER = 'IDEMPOTENCY_KEY_USED_DIFFERENT_USER';
5081
5083
  const ERROR_CODE_IDEMPOTENCY_CONCURRENT_REQUEST = 'IDEMPOTENCY_CONCURRENT_REQUEST';
5084
+ const ERROR_CODE_IDEMPOTENCY_KEY_ALREADY_USED = 'IDEMPOTENCY_KEY_ALREADY_USED';
5085
+ const ERROR_CODE_IDEMPOTENCY_BACKEND_OPERATION_ERROR = 'IDEMPOTENCY_BACKEND_OPERATION_ERROR';
5082
5086
  /**
5083
5087
  * Get the retry after in milliseconds from the response headers, undefined if not specified.
5084
5088
  * The header could have two different format.
@@ -5108,7 +5112,9 @@ function buildLuvioOverrideForDraftAdapters(luvio, handler, extractTargetIdFromC
5108
5112
  const dispatchResourceRequest = async function (resourceRequest, _context) {
5109
5113
  const resourceRequestCopy = clone$1(resourceRequest);
5110
5114
  resourceRequestCopy.headers = resourceRequestCopy.headers || {};
5111
- resourceRequestCopy.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
5115
+ if (handler.hasIdempotencySupport()) {
5116
+ resourceRequestCopy.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
5117
+ }
5112
5118
  // enable return extra fields for record creation and record update http call
5113
5119
  if (resourceRequest.basePath === '/ui-api/records' &&
5114
5120
  (resourceRequest.method === 'post' || resourceRequest.method === 'patch')) {
@@ -5944,6 +5950,7 @@ class AbstractResourceRequestActionHandler {
5944
5950
  // the luvio store redirect table, during which a new draft might be enqueued
5945
5951
  // which would not see a necessary mapping.
5946
5952
  this.ephemeralRedirects = {};
5953
+ this.isIdempotencySupported = true;
5947
5954
  }
5948
5955
  enqueue(data) {
5949
5956
  return this.draftQueue.enqueue(this.handlerId, data);
@@ -5973,21 +5980,43 @@ class AbstractResourceRequestActionHandler {
5973
5980
  retryDelayInMs = getRetryAfterInMs(response.headers);
5974
5981
  shouldRetry = true;
5975
5982
  break;
5976
- case HttpStatusCode.ServerError:
5983
+ case HttpStatusCode.ServerError: {
5977
5984
  shouldRetry = true;
5985
+ if (this.handleIdempotencyServerError(response.body, updatedAction, false, ERROR_CODE_IDEMPOTENCY_BACKEND_OPERATION_ERROR)) {
5986
+ this.isIdempotencySupported = false;
5987
+ retryDelayInMs = 0;
5988
+ actionDataChanged = true;
5989
+ }
5978
5990
  break;
5991
+ }
5979
5992
  case 409 /* IdempotentWriteSpecificHttpStatusCode.Conflict */: {
5980
- const errorCode = response.body[0].errorCode;
5981
- if (errorCode === ERROR_CODE_IDEMPOTENCY_KEY_USED_DIFFERENT_USER) {
5982
- updatedAction.data.headers = updatedAction.data.headers || {};
5983
- updatedAction.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
5993
+ if (this.isUiApiErrors(response.body)) {
5994
+ const errorCode = response.body[0].errorCode;
5995
+ if (this.handleIdempotencyServerError(response.body, updatedAction, true, ERROR_CODE_IDEMPOTENCY_KEY_USED_DIFFERENT_USER)) {
5996
+ retryDelayInMs = 0;
5997
+ actionDataChanged = true;
5998
+ }
5999
+ else if (errorCode === ERROR_CODE_IDEMPOTENCY_CONCURRENT_REQUEST) {
6000
+ retryDelayInMs = getRetryAfterInMs(response.headers);
6001
+ }
6002
+ shouldRetry = true;
6003
+ }
6004
+ break;
6005
+ }
6006
+ case HttpStatusCode.BadRequest: {
6007
+ if (this.handleIdempotencyServerError(response.body, updatedAction, false, ERROR_CODE_IDEMPOTENCY_FEATURE_NOT_ENABLED, ERROR_CODE_IDEMPOTENCY_NOT_SUPPORTED)) {
5984
6008
  retryDelayInMs = 0;
5985
6009
  actionDataChanged = true;
6010
+ shouldRetry = true;
5986
6011
  }
5987
- else if (errorCode === ERROR_CODE_IDEMPOTENCY_CONCURRENT_REQUEST) {
5988
- retryDelayInMs = getRetryAfterInMs(response.headers);
6012
+ break;
6013
+ }
6014
+ case 422 /* IdempotentWriteSpecificHttpStatusCode.UnProcessableEntity */: {
6015
+ if (this.handleIdempotencyServerError(response.body, updatedAction, true, ERROR_CODE_IDEMPOTENCY_KEY_ALREADY_USED)) {
6016
+ retryDelayInMs = 0;
6017
+ actionDataChanged = true;
6018
+ shouldRetry = true;
5989
6019
  }
5990
- shouldRetry = true;
5991
6020
  break;
5992
6021
  }
5993
6022
  }
@@ -6006,6 +6035,27 @@ class AbstractResourceRequestActionHandler {
6006
6035
  return ProcessActionResult.NETWORK_ERROR;
6007
6036
  }
6008
6037
  }
6038
+ // 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.
6039
+ handleIdempotencyServerError(responseBody, action, updateIdempotencyKey, ...targetErrorCodes) {
6040
+ if (this.isUiApiErrors(responseBody)) {
6041
+ const errorCode = responseBody[0].errorCode;
6042
+ if (targetErrorCodes.includes(errorCode)) {
6043
+ action.data.headers = action.data.headers || {};
6044
+ if (updateIdempotencyKey) {
6045
+ action.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
6046
+ }
6047
+ else {
6048
+ delete action.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY];
6049
+ }
6050
+ return true;
6051
+ }
6052
+ }
6053
+ return false;
6054
+ }
6055
+ // 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.
6056
+ isUiApiErrors(body) {
6057
+ return body !== undefined && Array.isArray(body) && body.length > 0 && body[0].errorCode;
6058
+ }
6009
6059
  async buildPendingAction(request, queue) {
6010
6060
  const targetId = await this.getIdFromRequest(request);
6011
6061
  if (targetId === undefined) {
@@ -6219,6 +6269,10 @@ class AbstractResourceRequestActionHandler {
6219
6269
  ...targetData,
6220
6270
  body: this.mergeRequestBody(targetBody, sourceBody),
6221
6271
  };
6272
+ // Updates Idempotency key if target has one
6273
+ if (targetData.headers && targetData.headers[HTTP_HEADER_IDEMPOTENCY_KEY]) {
6274
+ merged.data.headers[HTTP_HEADER_IDEMPOTENCY_KEY] = uuidv4();
6275
+ }
6222
6276
  // overlay metadata
6223
6277
  merged.metadata = { ...targetMetadata, ...sourceMetadata };
6224
6278
  // put status back to pending to auto upload if queue is active and targed is at the head.
@@ -6255,6 +6309,9 @@ class AbstractResourceRequestActionHandler {
6255
6309
  getDraftIdsFromAction(action) {
6256
6310
  return [action.targetId];
6257
6311
  }
6312
+ hasIdempotencySupport() {
6313
+ return this.isIdempotencySupported;
6314
+ }
6258
6315
  async ingestResponses(responses, action) {
6259
6316
  const luvio = this.getLuvio();
6260
6317
  await luvio.handleSuccessResponse(() => {
@@ -10215,16 +10272,18 @@ function injectFilter(filterNode, idState, parentPath, isParentPolymorphic, obje
10215
10272
  if (!isIdField) {
10216
10273
  let subSelectionNodes = [];
10217
10274
  let subFieldsHasId = false;
10218
- filterNode.value.fields.forEach((subFieldNode) => {
10219
- // Check if the filter field has the 'Id'
10220
- if (isFieldAnIdField(subFieldNode.name.value, objectInfos[objectInfoName])) {
10221
- subFieldsHasId = true;
10222
- updateIDInfo(subFieldNode, idState, draftFunctions);
10223
- }
10224
- // try injecting the fields within predicate no matter it has relation or not.
10225
- let subResults = injectFilter(subFieldNode, idState, curPath, isPolymorphicField, objectInfos, pathToObjectApiNamesMap, draftFunctions, existingFields ? existingFields[0] : undefined);
10226
- subSelectionNodes = subSelectionNodes.concat(subResults);
10227
- });
10275
+ if (isSpanning) {
10276
+ filterNode.value.fields.forEach((subFieldNode) => {
10277
+ // Check if the filter field has the 'Id'
10278
+ if (isFieldAnIdField(subFieldNode.name.value, objectInfos[objectInfoName])) {
10279
+ subFieldsHasId = true;
10280
+ updateIDInfo(subFieldNode, idState, draftFunctions);
10281
+ }
10282
+ // try injecting the fields within predicate no matter it has relation or not.
10283
+ let subResults = injectFilter(subFieldNode, idState, curPath, isPolymorphicField, objectInfos, pathToObjectApiNamesMap, draftFunctions, existingFields ? existingFields[0] : undefined);
10284
+ subSelectionNodes = subSelectionNodes.concat(subResults);
10285
+ });
10286
+ }
10228
10287
  if (!subFieldsHasId) {
10229
10288
  // Check if the query field has the 'Id'
10230
10289
  const existingIdsInQuery = existingFields &&
@@ -10253,6 +10312,7 @@ function injectFilter(filterNode, idState, parentPath, isParentPolymorphic, obje
10253
10312
  }
10254
10313
  //Inject Conditions: 1. Same field does not exist 2. Same fields has different children. 3. Filter spanning field does not have Id. 4. InLineFragment does not have the '__typename' field
10255
10314
  if (!existingFields ||
10315
+ existingFields.length === 0 ||
10256
10316
  subSelectionNodes.length > 0 ||
10257
10317
  (isSpanning && !subFieldsHasId) ||
10258
10318
  (isInlineFragment && !isTypeNameExisting)) {
@@ -12955,7 +13015,7 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
12955
13015
  // Fulfilled snapshot (this only happens in this code path if
12956
13016
  // the error is network error or 504), otherwise we spread over
12957
13017
  // the non-eval'ed snapshot (which will be either Fulfilled or Stale)
12958
- return nonEvaluatedSnapshot.state === 'Error'
13018
+ const resultSnapshot = nonEvaluatedSnapshot.state === 'Error'
12959
13019
  ? createLocalEvalSnapshot(gqlResult, seenRecords, recordId, rebuildWithLocalEval)
12960
13020
  : {
12961
13021
  ...nonEvaluatedSnapshot,
@@ -12964,6 +13024,22 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
12964
13024
  seenRecords,
12965
13025
  rebuildWithLocalEval,
12966
13026
  };
13027
+ const { refresh, state } = resultSnapshot;
13028
+ if (state !== 'Error' && refresh) {
13029
+ // after refreshing a graphql snapshot, we want to force a rebuild regardless
13030
+ // of if the call failed or not or if the data changed or not because we want
13031
+ // to make sure any potential new drafts are picked up
13032
+ resultSnapshot.refresh = {
13033
+ ...refresh,
13034
+ resolve: (config) => {
13035
+ return refresh.resolve(config).finally(() => {
13036
+ luvio.storePublish(resultSnapshot.recordId, undefined);
13037
+ luvio.storeBroadcast();
13038
+ });
13039
+ },
13040
+ };
13041
+ }
13042
+ return resultSnapshot;
12967
13043
  };
12968
13044
  }
12969
13045
 
@@ -16845,4 +16921,4 @@ register({
16845
16921
  });
16846
16922
 
16847
16923
  export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
16848
- // version: 1.229.0-dev4-07d38781a
16924
+ // version: 1.229.0-dev6-53f3d6911