@salesforce/lds-network-fetch 1.436.0 → 1.438.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.
@@ -62,7 +62,9 @@ var HttpStatusCode;
62
62
  HttpStatusCode[HttpStatusCode["Unauthorized"] = 401] = "Unauthorized";
63
63
  HttpStatusCode[HttpStatusCode["Forbidden"] = 403] = "Forbidden";
64
64
  HttpStatusCode[HttpStatusCode["NotFound"] = 404] = "NotFound";
65
+ HttpStatusCode[HttpStatusCode["TooManyRequests"] = 429] = "TooManyRequests";
65
66
  HttpStatusCode[HttpStatusCode["ServerError"] = 500] = "ServerError";
67
+ HttpStatusCode[HttpStatusCode["ServiceUnavailable"] = 503] = "ServiceUnavailable";
66
68
  HttpStatusCode[HttpStatusCode["GatewayTimeout"] = 504] = "GatewayTimeout";
67
69
  })(HttpStatusCode || (HttpStatusCode = {}));
68
70
  /**
@@ -125,7 +127,7 @@ var TypeCheckShapes;
125
127
  TypeCheckShapes[TypeCheckShapes["Integer"] = 3] = "Integer";
126
128
  TypeCheckShapes[TypeCheckShapes["Unsupported"] = 4] = "Unsupported";
127
129
  })(TypeCheckShapes || (TypeCheckShapes = {}));
128
- // engine version: 0.160.4-b7e0ea82
130
+ // engine version: 0.160.5-e6ada846
129
131
 
130
132
  const { keys: keys$1 } = Object;
131
133
 
@@ -216,11 +218,6 @@ function generateHeaders(headers) {
216
218
  return fetchHeaders;
217
219
  }
218
220
 
219
- /*!
220
- * Copyright (c) 2022, Salesforce, Inc.,
221
- * All rights reserved.
222
- * For full license text, see the LICENSE.txt file
223
- */
224
221
  function resolvedPromiseLike(result) {
225
222
  if (isPromiseLike(result)) {
226
223
  return result.then((nextResult) => nextResult);
@@ -256,7 +253,7 @@ function rejectedPromiseLike(reason) {
256
253
  };
257
254
  }
258
255
  function isPromiseLike(x) {
259
- return typeof (x == null ? void 0 : x.then) === "function";
256
+ return typeof x?.then === "function";
260
257
  }
261
258
 
262
259
  /**
@@ -329,6 +326,9 @@ function mergeRecordFields(first, second) {
329
326
  targetFields[fieldName] = sourceFields[fieldName];
330
327
  continue;
331
328
  }
329
+ if (targetField.displayValue === null && sourceField.displayValue !== null) {
330
+ targetField.displayValue = sourceField.displayValue;
331
+ }
332
332
  mergeRecordFields(targetField.value, sourceField.value);
333
333
  continue;
334
334
  }
@@ -744,9 +744,15 @@ function getStorageAndLogger(path) {
744
744
  }
745
745
  const platformFetchAdapter = platformNetworkAdapter(fetchNetworkAdapter);
746
746
  const platformFetchAdapterWithInterceptors = async (resourceRequest, resourceRequestContext, requestInterceptors, interceptorContext) => {
747
- const pending = requestInterceptors.reduce((previousPromise, interceptor) => previousPromise.then((resourceRequest) => interceptor(resourceRequest, interceptorContext)), resolvedPromiseLike(resourceRequest));
747
+ const pending = runRequestInterceptors(resourceRequest, requestInterceptors, interceptorContext);
748
748
  return pending.then((interceptedRequest) => platformFetchAdapter(interceptedRequest, resourceRequestContext));
749
749
  };
750
+ /**
751
+ * Runs the request interceptor chain on a request and returns the intercepted
752
+ * request. Exposed so callers (e.g. the retry path) can run interceptors once
753
+ * up front and then issue the actual network call separately on each attempt.
754
+ */
755
+ const runRequestInterceptors = (resourceRequest, requestInterceptors, interceptorContext) => requestInterceptors.reduce((previousPromise, interceptor) => previousPromise.then((resourceRequest) => interceptor(resourceRequest, interceptorContext)), resolvedPromiseLike(resourceRequest));
750
756
  async function getDurableCacheDataForIncomingRequest(resourceRequest, storageAndLogger, transactionKey) {
751
757
  if (!shouldForceRefresh(resourceRequest)) {
752
758
  if (storageAndLogger?.storage) {
@@ -795,12 +801,28 @@ async function handleSendFetchRequest(resourceRequest, resourceRequestContext, i
795
801
  context.queryParams = resourceRequest.queryParams;
796
802
  context.cmp = resourceRequestContext.sourceContext?.tagName || 'none';
797
803
  }
798
- const { request: requestInterceptors = [], response: responseInterceptors = [], finally: finallyInterceptors = [], } = interceptors;
804
+ const { request: requestInterceptors = [], retry: retryInterceptor, response: responseInterceptors = [], finally: finallyInterceptors = [], } = interceptors;
799
805
  const cachedData = await getDurableCacheDataForIncomingRequest(resourceRequest, storageAndLogger, transactionKey);
800
806
  if (cachedData !== undefined) {
801
807
  return createOkResponse$1(cachedData);
802
808
  }
803
- const response = platformFetchAdapterWithInterceptors(resourceRequest, resourceRequestContext, requestInterceptors, context);
809
+ let response;
810
+ if (retryInterceptor) {
811
+ // Run the request interceptor chain ONCE up front, then hand the
812
+ // intercepted request off to the retry interceptor. The retry
813
+ // interceptor's `doFetch` goes straight to the network — request
814
+ // interceptors don't re-run on retry attempts. This mirrors the
815
+ // OneStore retry pattern (`csrf-retry.ts` calls raw `fetch(...)` on
816
+ // retry) and avoids re-executing side-effecting interceptors that
817
+ // assume one-shot invocation per logical request (tracker
818
+ // registration, perf marks, etc.).
819
+ const intercepted = await runRequestInterceptors(resourceRequest, requestInterceptors, context);
820
+ const doFetch = (req) => platformFetchAdapter(req, resourceRequestContext);
821
+ response = retryInterceptor(intercepted, doFetch, context);
822
+ }
823
+ else {
824
+ response = platformFetchAdapterWithInterceptors(resourceRequest, resourceRequestContext, requestInterceptors, context);
825
+ }
804
826
  const interceptedResponse = Promise.resolve(responseInterceptors.reduce((previousPromise, interceptor) => previousPromise.then((response) => interceptor(response, context)), resolvedPromiseLike(response)));
805
827
  // This can probably be refactored once we add an error interceptor pattern to onestore, and then
806
828
  // the intial then here can also most likely be moved to a response interceptor as well
@@ -850,4 +872,4 @@ function instrument(newInstrumentation) {
850
872
  }
851
873
 
852
874
  export { instrument, setupFetchNetworkAdapter, setupLexNetworkAdapter };
853
- // version: 1.436.0-581b8a5964
875
+ // version: 1.438.0-0ec0a89235
@@ -1,4 +1,4 @@
1
1
  export { setupFetchNetworkAdapter, setupLexNetworkAdapter } from './networkAdapter';
2
2
  export type { RequestLogger } from './networkAdapter';
3
- export type { RequestInterceptor, ResponseInterceptor, Interceptors } from './utils';
3
+ export type { RequestInterceptor, ResponseInterceptor, LuvioRetryInterceptor, Interceptors, } from './utils';
4
4
  export { instrument, FetchNetworkInstrumentation } from './instrumentation';
@@ -11,15 +11,40 @@ type LdsStorageConfig = {
11
11
  * @returns LdsStorageConfig if we cache that resource, otherwise null.
12
12
  */
13
13
  export declare function getStorageAndLogger(path: string): LdsStorageConfig | null;
14
+ export declare const platformFetchAdapter: import("@luvio/engine").NetworkAdapter;
14
15
  export type RequestInterceptor<Context = any> = (fetchArgs: ResourceRequest, context?: Context) => PromiseLike<ResourceRequest>;
15
16
  export type ResponseInterceptor<Context = any> = (response: FetchResponse<any>, context?: Context) => PromiseLike<FetchResponse<any>>;
16
17
  export type FinallyInterceptor<Context = any> = (context?: Context) => PromiseLike<void> | void;
18
+ /**
19
+ * Owns the fetch lifecycle for a single inbound request: it may call `doFetch`
20
+ * any number of times (e.g. to retry on 429/503 or refresh a CSRF token) and
21
+ * resolves with the final FetchResponse.
22
+ *
23
+ * `request` is the result of running the request interceptor chain ONCE, up
24
+ * front. `doFetch(req)` issues the network call directly — request
25
+ * interceptors do NOT run again on retry attempts. The interceptor is
26
+ * responsible for any per-attempt mutations (e.g. swapping a refreshed CSRF
27
+ * token onto the request before the next `doFetch`).
28
+ *
29
+ * This mirrors the OneStore retry pattern, where retry interceptors call raw
30
+ * `fetch(...)` directly on retry, and avoids re-executing side-effecting
31
+ * request interceptors (tracker registration, perf marks) that assume
32
+ * one-shot invocation per logical request.
33
+ */
34
+ export type LuvioRetryInterceptor<Context = any> = (request: ResourceRequest, doFetch: (req: ResourceRequest) => Promise<FetchResponse<any>>, context?: Context) => Promise<FetchResponse<any>>;
17
35
  export type Interceptors<Context = any> = {
18
36
  createContext?: () => Context;
19
37
  request?: RequestInterceptor<Context>[];
38
+ retry?: LuvioRetryInterceptor<Context>;
20
39
  response?: ResponseInterceptor<Context>[];
21
40
  finally?: FinallyInterceptor<Context>[];
22
41
  };
23
42
  export declare const platformFetchAdapterWithInterceptors: (resourceRequest: ResourceRequest, resourceRequestContext: ResourceRequestContext, requestInterceptors: RequestInterceptor[], interceptorContext: any) => Promise<FetchResponse<any>>;
43
+ /**
44
+ * Runs the request interceptor chain on a request and returns the intercepted
45
+ * request. Exposed so callers (e.g. the retry path) can run interceptors once
46
+ * up front and then issue the actual network call separately on each attempt.
47
+ */
48
+ export declare const runRequestInterceptors: (resourceRequest: ResourceRequest, requestInterceptors: RequestInterceptor[], interceptorContext: any) => PromiseLike<ResourceRequest>;
24
49
  export declare function getDurableCacheDataForIncomingRequest(resourceRequest: ResourceRequest, storageAndLogger: LdsStorageConfig | null, transactionKey: string): Promise<unknown>;
25
50
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/lds-network-fetch",
3
- "version": "1.436.0",
3
+ "version": "1.438.0",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "description": "LDS Network Adapter using fetch",
6
6
  "main": "dist/ldsNetworkFetch.js",
@@ -34,11 +34,11 @@
34
34
  "release:corejar": "yarn build && ../core-build/scripts/core.js --name=lds-network-fetch"
35
35
  },
36
36
  "dependencies": {
37
- "@luvio/engine": "0.160.4",
38
- "@luvio/network-adapter-fetch": "0.160.4"
37
+ "@luvio/engine": "0.160.5",
38
+ "@luvio/network-adapter-fetch": "0.160.5"
39
39
  },
40
40
  "devDependencies": {
41
- "@salesforce/lds-network-aura": "^1.436.0"
41
+ "@salesforce/lds-network-aura": "^1.438.0"
42
42
  },
43
43
  "volta": {
44
44
  "extends": "../../package.json"