@salesforce/lds-runtime-one-app 1.454.0 → 1.455.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.
- package/dist/oneAppLdsEngineCreator.js +197 -126
- package/dist/types/http-utils.d.ts +20 -0
- package/dist/types/retry-interceptors/fetch-retry.d.ts +17 -0
- package/dist/types/retry-policies/fetch-throttling-retry-policy.d.ts +2 -1
- package/dist/types/retry-policies/luvio-fetch-throttling-retry-policy.d.ts +2 -1
- package/dist/types/retry-policies/unconfigured-retry-policy.d.ts +20 -0
- package/package.json +16 -16
- package/dist/types/retry-interceptors/csrf-retry.d.ts +0 -2
|
@@ -2588,7 +2588,7 @@ function buildServiceDescriptor$d(luvio) {
|
|
|
2588
2588
|
},
|
|
2589
2589
|
};
|
|
2590
2590
|
}
|
|
2591
|
-
// version: 1.
|
|
2591
|
+
// version: 1.455.0-c53c97de2a
|
|
2592
2592
|
|
|
2593
2593
|
class AuraGraphQLNormalizedCacheControlCommand extends AuraNormalizedCacheControlCommand {
|
|
2594
2594
|
constructor(config, documentRootType, services) {
|
|
@@ -2927,7 +2927,7 @@ function buildServiceDescriptor$9(notifyRecordUpdateAvailable, getNormalizedLuvi
|
|
|
2927
2927
|
},
|
|
2928
2928
|
};
|
|
2929
2929
|
}
|
|
2930
|
-
// version: 1.
|
|
2930
|
+
// version: 1.455.0-c53c97de2a
|
|
2931
2931
|
|
|
2932
2932
|
class RetryService {
|
|
2933
2933
|
constructor(defaultRetryPolicy) {
|
|
@@ -5849,7 +5849,7 @@ function getEnvironmentSetting(name) {
|
|
|
5849
5849
|
}
|
|
5850
5850
|
return undefined;
|
|
5851
5851
|
}
|
|
5852
|
-
// version: 1.
|
|
5852
|
+
// version: 1.455.0-96e9b41a18
|
|
5853
5853
|
|
|
5854
5854
|
/**
|
|
5855
5855
|
* Helpers for reaching the Aura framework from the LDS Aura runtime.
|
|
@@ -6422,6 +6422,45 @@ function getCsrfTokenManager() {
|
|
|
6422
6422
|
return cached;
|
|
6423
6423
|
}
|
|
6424
6424
|
|
|
6425
|
+
/**
|
|
6426
|
+
* Extracts the HTTP method from FetchParameters, matching the Fetch API's own
|
|
6427
|
+
* precedence: an options.method override wins over a Request object's method
|
|
6428
|
+
* (e.g. `fetch(new Request(url, { method: 'GET' }), { method: 'POST' })`
|
|
6429
|
+
* resolves to `POST`).
|
|
6430
|
+
*/
|
|
6431
|
+
function getFetchMethod([urlOrRequest, options]) {
|
|
6432
|
+
if (options && 'method' in options) {
|
|
6433
|
+
return options.method;
|
|
6434
|
+
}
|
|
6435
|
+
if (typeof urlOrRequest !== 'string' && 'method' in urlOrRequest) {
|
|
6436
|
+
return urlOrRequest.method;
|
|
6437
|
+
}
|
|
6438
|
+
return undefined;
|
|
6439
|
+
}
|
|
6440
|
+
/**
|
|
6441
|
+
* Only GET requests are safe to replay automatically on 429/503 — replaying a
|
|
6442
|
+
* write (POST/PUT/PATCH/DELETE) risks executing a mutation more than once.
|
|
6443
|
+
* Shared by both the Luvio and generic-fetch throttling retry policies so the
|
|
6444
|
+
* write-guard rule lives in exactly one place.
|
|
6445
|
+
*/
|
|
6446
|
+
function isRetryableMethod(method) {
|
|
6447
|
+
return method?.toLowerCase() === 'get';
|
|
6448
|
+
}
|
|
6449
|
+
/**
|
|
6450
|
+
* Determines if the HTTP method requires CSRF protection.
|
|
6451
|
+
* Only mutating operations (POST, PUT, PATCH, DELETE) require CSRF tokens.
|
|
6452
|
+
*/
|
|
6453
|
+
function isCsrfMethod(method) {
|
|
6454
|
+
if (!method) {
|
|
6455
|
+
return false;
|
|
6456
|
+
}
|
|
6457
|
+
const normalizedMethod = method.toLowerCase();
|
|
6458
|
+
return (normalizedMethod === 'post' ||
|
|
6459
|
+
normalizedMethod === 'put' ||
|
|
6460
|
+
normalizedMethod === 'patch' ||
|
|
6461
|
+
normalizedMethod === 'delete');
|
|
6462
|
+
}
|
|
6463
|
+
|
|
6425
6464
|
const CSRF_TOKEN_HEADER = 'X-CSRF-Token';
|
|
6426
6465
|
/**
|
|
6427
6466
|
* Resolves the CSRF token manager and returns the current token. Returns
|
|
@@ -6454,23 +6493,6 @@ function areCsrfGatesEnabled() {
|
|
|
6454
6493
|
return false;
|
|
6455
6494
|
}
|
|
6456
6495
|
}
|
|
6457
|
-
/**
|
|
6458
|
-
* Determines if the HTTP method requires CSRF protection.
|
|
6459
|
-
* Only mutating operations (POST, PUT, PATCH, DELETE) require CSRF tokens.
|
|
6460
|
-
*
|
|
6461
|
-
* @param method - The HTTP method to check
|
|
6462
|
-
* @returns true if the method requires CSRF protection
|
|
6463
|
-
*/
|
|
6464
|
-
function isCsrfMethod(method) {
|
|
6465
|
-
if (!method) {
|
|
6466
|
-
return false;
|
|
6467
|
-
}
|
|
6468
|
-
const normalizedMethod = method.toLowerCase();
|
|
6469
|
-
return (normalizedMethod === 'post' ||
|
|
6470
|
-
normalizedMethod === 'put' ||
|
|
6471
|
-
normalizedMethod === 'patch' ||
|
|
6472
|
-
normalizedMethod === 'delete');
|
|
6473
|
-
}
|
|
6474
6496
|
/**
|
|
6475
6497
|
* Builds a request interceptor that adds CSRF token headers to mutating requests.
|
|
6476
6498
|
* The CSRF token is fetched once and cached for subsequent requests.
|
|
@@ -6484,17 +6506,8 @@ function buildCsrfTokenInterceptor() {
|
|
|
6484
6506
|
if (!areCsrfGatesEnabled()) {
|
|
6485
6507
|
return resolvedPromiseLike$2(fetchArgs);
|
|
6486
6508
|
}
|
|
6487
|
-
const [urlOrRequest, options] = fetchArgs;
|
|
6488
|
-
// Determine the method from either Request object or options
|
|
6489
|
-
let method;
|
|
6490
|
-
if (typeof urlOrRequest !== 'string' && 'method' in urlOrRequest) {
|
|
6491
|
-
method = urlOrRequest.method;
|
|
6492
|
-
}
|
|
6493
|
-
else if (options && 'method' in options) {
|
|
6494
|
-
method = options.method;
|
|
6495
|
-
}
|
|
6496
6509
|
// Only add CSRF token for mutating operations
|
|
6497
|
-
if (isCsrfMethod(
|
|
6510
|
+
if (isCsrfMethod(getFetchMethod(fetchArgs))) {
|
|
6498
6511
|
const token = await getCsrfToken();
|
|
6499
6512
|
if (token) {
|
|
6500
6513
|
// eslint-disable-next-line no-param-reassign
|
|
@@ -6902,12 +6915,14 @@ const DEFAULT_CONFIG$2 = {
|
|
|
6902
6915
|
jitterPercent: 0.5,
|
|
6903
6916
|
};
|
|
6904
6917
|
class LuvioFetchThrottlingRetryPolicy extends RetryPolicy {
|
|
6905
|
-
constructor(config = DEFAULT_CONFIG$2) {
|
|
6918
|
+
constructor(config = DEFAULT_CONFIG$2, method) {
|
|
6906
6919
|
super();
|
|
6907
6920
|
this.config = config;
|
|
6921
|
+
this.method = method;
|
|
6908
6922
|
}
|
|
6909
6923
|
async shouldRetry(result, context) {
|
|
6910
|
-
return ((
|
|
6924
|
+
return (isRetryableMethod(this.method) &&
|
|
6925
|
+
(result.status === 429 || result.status === 503) &&
|
|
6911
6926
|
context.attempt < this.config.maxRetries &&
|
|
6912
6927
|
context.totalElapsedMs <= this.config.maxTimeToRetry);
|
|
6913
6928
|
}
|
|
@@ -6970,7 +6985,7 @@ function buildLuvioFetchRetryInterceptor() {
|
|
|
6970
6985
|
return (request, doFetch) => {
|
|
6971
6986
|
const csrfPolicy = new LuvioCsrfTokenRetryPolicy();
|
|
6972
6987
|
const composedPolicy = new ComposedRetryPolicy([
|
|
6973
|
-
new LuvioFetchThrottlingRetryPolicy(),
|
|
6988
|
+
new LuvioFetchThrottlingRetryPolicy(undefined, request.method),
|
|
6974
6989
|
csrfPolicy,
|
|
6975
6990
|
]);
|
|
6976
6991
|
const retryService = new RetryService(composedPolicy);
|
|
@@ -7520,28 +7535,118 @@ async function isCsrfError(response) {
|
|
|
7520
7535
|
}
|
|
7521
7536
|
}
|
|
7522
7537
|
|
|
7523
|
-
|
|
7538
|
+
const DEFAULT_CONFIG = {
|
|
7539
|
+
maxRetries: 3,
|
|
7540
|
+
maxTimeToRetry: 10000,
|
|
7541
|
+
baseDelay: 250,
|
|
7542
|
+
maxDelay: 5000,
|
|
7543
|
+
exponentialFactor: 2,
|
|
7544
|
+
jitterPercent: 0.5,
|
|
7545
|
+
};
|
|
7546
|
+
class FetchThrottlingRetryPolicy extends RetryPolicy {
|
|
7547
|
+
constructor(config = DEFAULT_CONFIG, method) {
|
|
7548
|
+
super();
|
|
7549
|
+
this.config = config;
|
|
7550
|
+
this.method = method;
|
|
7551
|
+
}
|
|
7552
|
+
async shouldRetry(result, context) {
|
|
7553
|
+
return (isRetryableMethod(this.method) &&
|
|
7554
|
+
(result.status === 429 || result.status === 503) &&
|
|
7555
|
+
context.attempt < this.config.maxRetries &&
|
|
7556
|
+
context.totalElapsedMs <= this.config.maxTimeToRetry);
|
|
7557
|
+
}
|
|
7558
|
+
async calculateDelay(result, context) {
|
|
7559
|
+
let delay;
|
|
7560
|
+
// If retry-after header is present and valid, use it
|
|
7561
|
+
const retryAfterHeader = this.parseRetryAfterHeader(result);
|
|
7562
|
+
if (retryAfterHeader !== undefined) {
|
|
7563
|
+
delay = Math.min(retryAfterHeader, this.config.maxDelay);
|
|
7564
|
+
}
|
|
7565
|
+
else {
|
|
7566
|
+
// Exponential backoff
|
|
7567
|
+
delay = Math.min(this.config.baseDelay * Math.pow(this.config.exponentialFactor, context.attempt), this.config.maxDelay);
|
|
7568
|
+
}
|
|
7569
|
+
// Add jitter to prevent thundering herd
|
|
7570
|
+
const jitter = delay * this.config.jitterPercent * (Math.random() - 0.5);
|
|
7571
|
+
return Math.max(0, delay + jitter);
|
|
7572
|
+
}
|
|
7573
|
+
parseRetryAfterHeader(result) {
|
|
7574
|
+
if (!result.headers) {
|
|
7575
|
+
return undefined;
|
|
7576
|
+
}
|
|
7577
|
+
const value = result.headers.get('Retry-After');
|
|
7578
|
+
if (!value) {
|
|
7579
|
+
return undefined;
|
|
7580
|
+
}
|
|
7581
|
+
// The Retry-After header can be either a number of seconds or an HTTP-date (IMF-fixdate)
|
|
7582
|
+
// Retry-After: <delay-seconds>
|
|
7583
|
+
// Retry-After: <http-date>
|
|
7584
|
+
const trimmed = value.trim();
|
|
7585
|
+
// Strictly treat only all-digits as seconds
|
|
7586
|
+
if (/^\d+$/.test(trimmed)) {
|
|
7587
|
+
const seconds = Number(trimmed);
|
|
7588
|
+
if (Number.isFinite(seconds) && seconds >= 0) {
|
|
7589
|
+
return seconds * 1000; // Convert to milliseconds
|
|
7590
|
+
}
|
|
7591
|
+
return undefined;
|
|
7592
|
+
}
|
|
7593
|
+
// Strict RFC 7231 IMF-fixdate format (e.g., "Sun, 06 Nov 1994 08:49:37 GMT")
|
|
7594
|
+
const IMF_FIXDATE = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), \d{2} (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{4} \d{2}:\d{2}:\d{2} GMT$/;
|
|
7595
|
+
if (!IMF_FIXDATE.test(trimmed)) {
|
|
7596
|
+
return undefined;
|
|
7597
|
+
}
|
|
7598
|
+
// Use Date.parse to avoid any engine-specific fallbacks
|
|
7599
|
+
const millis = Date.parse(trimmed);
|
|
7600
|
+
if (Number.isFinite(millis)) {
|
|
7601
|
+
return Math.max(0, millis - Date.now());
|
|
7602
|
+
}
|
|
7603
|
+
return undefined;
|
|
7604
|
+
}
|
|
7605
|
+
}
|
|
7606
|
+
|
|
7607
|
+
/**
|
|
7608
|
+
* A mutable holder for the current fetch args. CsrfTokenRetryPolicy's
|
|
7609
|
+
* prepareRetry hook updates `args` in place (e.g. to swap in a refreshed CSRF
|
|
7610
|
+
* token) so the retried fetch call picks up the change.
|
|
7611
|
+
*/
|
|
7612
|
+
function buildCsrfPolicy(mutableRequest) {
|
|
7613
|
+
const csrfPolicy = new CsrfTokenRetryPolicy();
|
|
7614
|
+
csrfPolicy.setRequestContext(mutableRequest);
|
|
7615
|
+
return csrfPolicy;
|
|
7616
|
+
}
|
|
7617
|
+
/**
|
|
7618
|
+
* Built fresh per request so the write-guard check sees this request's own
|
|
7619
|
+
* HTTP method, rather than one method baked in for the life of the service.
|
|
7620
|
+
*/
|
|
7621
|
+
function buildThrottlingPolicy(fetchArgs) {
|
|
7622
|
+
return new FetchThrottlingRetryPolicy(undefined, getFetchMethod(fetchArgs));
|
|
7623
|
+
}
|
|
7624
|
+
/**
|
|
7625
|
+
* Builds the retry interceptor used by the generic Conduit fetch service.
|
|
7626
|
+
*
|
|
7627
|
+
* Composes two independent per-request retry policies — throttling (429/503,
|
|
7628
|
+
* GET-only) and CSRF (401 token refresh) — built fresh per request rather
|
|
7629
|
+
* than reused off a shared defaultRetryPolicy. This keeps concurrent requests
|
|
7630
|
+
* from sharing mutable CSRF request-context state, and lets the throttling
|
|
7631
|
+
* policy see this request's own HTTP method.
|
|
7632
|
+
*
|
|
7633
|
+
* The `retryService` handed in by the framework is used only as the runner for
|
|
7634
|
+
* `applyRetry` — the real policy is always the per-request `composedPolicy`
|
|
7635
|
+
* passed as the override, never the service's own `defaultRetryPolicy`. When no
|
|
7636
|
+
* `retryService` is injected (e.g. the copilot/unauthorized descriptors, which
|
|
7637
|
+
* intentionally opt out of retries), we fall through to a plain fetch.
|
|
7638
|
+
*/
|
|
7639
|
+
function buildFetchRetryInterceptor() {
|
|
7524
7640
|
return async (fetchArgs, retryService, _context) => {
|
|
7525
7641
|
if (retryService) {
|
|
7526
|
-
// Create mutable context for CSRF retry policy
|
|
7527
7642
|
const mutableRequest = { args: fetchArgs };
|
|
7528
|
-
|
|
7529
|
-
|
|
7530
|
-
|
|
7531
|
-
|
|
7532
|
-
policy.setRequestContext(mutableRequest);
|
|
7533
|
-
}
|
|
7534
|
-
else if (policy instanceof ComposedRetryPolicy) {
|
|
7535
|
-
// Extract CSRF policy from composed policy
|
|
7536
|
-
const csrfPolicy = policy.getPolicyByType(CsrfTokenRetryPolicy);
|
|
7537
|
-
if (csrfPolicy) {
|
|
7538
|
-
csrfPolicy.setRequestContext(mutableRequest);
|
|
7539
|
-
}
|
|
7540
|
-
}
|
|
7541
|
-
// Retry service will call prepareRetry hook which updates mutableRequest.args
|
|
7643
|
+
const composedPolicy = new ComposedRetryPolicy([
|
|
7644
|
+
buildThrottlingPolicy(fetchArgs),
|
|
7645
|
+
buildCsrfPolicy(mutableRequest),
|
|
7646
|
+
]);
|
|
7542
7647
|
return retryService.applyRetry(async () => {
|
|
7543
7648
|
return fetch(...mutableRequest.args);
|
|
7544
|
-
});
|
|
7649
|
+
}, composedPolicy);
|
|
7545
7650
|
}
|
|
7546
7651
|
return fetch(...fetchArgs);
|
|
7547
7652
|
};
|
|
@@ -7784,7 +7889,7 @@ function buildCopilotFetchServiceDescriptor(logger) {
|
|
|
7784
7889
|
},
|
|
7785
7890
|
buildJwtRequestInterceptor(logger),
|
|
7786
7891
|
],
|
|
7787
|
-
retry:
|
|
7892
|
+
retry: buildFetchRetryInterceptor(),
|
|
7788
7893
|
finally: [buildThirdPartyTrackerFinishInterceptor()],
|
|
7789
7894
|
}),
|
|
7790
7895
|
tags: { specialHacksFor: 'copilot' },
|
|
@@ -7794,7 +7899,7 @@ function buildUnauthorizedFetchServiceDescriptor() {
|
|
|
7794
7899
|
const fetchService = buildServiceDescriptor$2({
|
|
7795
7900
|
createContext: createInstrumentationIdContext(),
|
|
7796
7901
|
request: [buildThirdPartyTrackerRegisterInterceptor()],
|
|
7797
|
-
retry:
|
|
7902
|
+
retry: buildFetchRetryInterceptor(),
|
|
7798
7903
|
finally: [buildThirdPartyTrackerFinishInterceptor()],
|
|
7799
7904
|
});
|
|
7800
7905
|
return {
|
|
@@ -10574,7 +10679,7 @@ function getLexRuntimeDefaultInterceptorConfig(logger) {
|
|
|
10574
10679
|
buildEntityEncodingInterceptor(),
|
|
10575
10680
|
buildFirstPartyHeaderInterceptor(),
|
|
10576
10681
|
],
|
|
10577
|
-
retry:
|
|
10682
|
+
retry: buildFetchRetryInterceptor(),
|
|
10578
10683
|
response: [
|
|
10579
10684
|
buildLexRuntime5xxStatusResponseInterceptor(logger),
|
|
10580
10685
|
buildLexRuntimeSessionExpirationResponseInterceptor(logger),
|
|
@@ -10617,73 +10722,6 @@ function buildLexRuntimeCompressedFetchServiceDescriptor(logger, retryService) {
|
|
|
10617
10722
|
};
|
|
10618
10723
|
}
|
|
10619
10724
|
|
|
10620
|
-
const DEFAULT_CONFIG = {
|
|
10621
|
-
maxRetries: 3,
|
|
10622
|
-
maxTimeToRetry: 10000,
|
|
10623
|
-
baseDelay: 250,
|
|
10624
|
-
maxDelay: 5000,
|
|
10625
|
-
exponentialFactor: 2,
|
|
10626
|
-
jitterPercent: 0.5,
|
|
10627
|
-
};
|
|
10628
|
-
class FetchThrottlingRetryPolicy extends RetryPolicy {
|
|
10629
|
-
constructor(config = DEFAULT_CONFIG) {
|
|
10630
|
-
super();
|
|
10631
|
-
this.config = config;
|
|
10632
|
-
}
|
|
10633
|
-
async shouldRetry(result, context) {
|
|
10634
|
-
return ((result.status === 429 || result.status === 503) &&
|
|
10635
|
-
context.attempt < this.config.maxRetries &&
|
|
10636
|
-
context.totalElapsedMs <= this.config.maxTimeToRetry);
|
|
10637
|
-
}
|
|
10638
|
-
async calculateDelay(result, context) {
|
|
10639
|
-
let delay;
|
|
10640
|
-
// If retry-after header is present and valid, use it
|
|
10641
|
-
const retryAfterHeader = this.parseRetryAfterHeader(result);
|
|
10642
|
-
if (retryAfterHeader !== undefined) {
|
|
10643
|
-
delay = Math.min(retryAfterHeader, this.config.maxDelay);
|
|
10644
|
-
}
|
|
10645
|
-
else {
|
|
10646
|
-
// Exponential backoff
|
|
10647
|
-
delay = Math.min(this.config.baseDelay * Math.pow(this.config.exponentialFactor, context.attempt), this.config.maxDelay);
|
|
10648
|
-
}
|
|
10649
|
-
// Add jitter to prevent thundering herd
|
|
10650
|
-
const jitter = delay * this.config.jitterPercent * (Math.random() - 0.5);
|
|
10651
|
-
return Math.max(0, delay + jitter);
|
|
10652
|
-
}
|
|
10653
|
-
parseRetryAfterHeader(result) {
|
|
10654
|
-
if (!result.headers) {
|
|
10655
|
-
return undefined;
|
|
10656
|
-
}
|
|
10657
|
-
const value = result.headers.get('Retry-After');
|
|
10658
|
-
if (!value) {
|
|
10659
|
-
return undefined;
|
|
10660
|
-
}
|
|
10661
|
-
// The Retry-After header can be either a number of seconds or an HTTP-date (IMF-fixdate)
|
|
10662
|
-
// Retry-After: <delay-seconds>
|
|
10663
|
-
// Retry-After: <http-date>
|
|
10664
|
-
const trimmed = value.trim();
|
|
10665
|
-
// Strictly treat only all-digits as seconds
|
|
10666
|
-
if (/^\d+$/.test(trimmed)) {
|
|
10667
|
-
const seconds = Number(trimmed);
|
|
10668
|
-
if (Number.isFinite(seconds) && seconds >= 0) {
|
|
10669
|
-
return seconds * 1000; // Convert to milliseconds
|
|
10670
|
-
}
|
|
10671
|
-
return undefined;
|
|
10672
|
-
}
|
|
10673
|
-
// Strict RFC 7231 IMF-fixdate format (e.g., "Sun, 06 Nov 1994 08:49:37 GMT")
|
|
10674
|
-
const IMF_FIXDATE = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), \d{2} (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{4} \d{2}:\d{2}:\d{2} GMT$/;
|
|
10675
|
-
if (!IMF_FIXDATE.test(trimmed)) {
|
|
10676
|
-
return undefined;
|
|
10677
|
-
}
|
|
10678
|
-
// Use Date.parse to avoid any engine-specific fallbacks
|
|
10679
|
-
const millis = Date.parse(trimmed);
|
|
10680
|
-
if (Number.isFinite(millis)) {
|
|
10681
|
-
return Math.max(0, millis - Date.now());
|
|
10682
|
-
}
|
|
10683
|
-
return undefined;
|
|
10684
|
-
}
|
|
10685
|
-
}
|
|
10686
|
-
|
|
10687
10725
|
const CSRF_TOKEN_KEY = 'salesforce_csrf_token';
|
|
10688
10726
|
const CSRF_STORAGE_NAME = 'ldsCSRFToken';
|
|
10689
10727
|
const BASE_URI = '/services/data/v68.0';
|
|
@@ -10827,6 +10865,35 @@ function buildCsrfTokenManager() {
|
|
|
10827
10865
|
});
|
|
10828
10866
|
}
|
|
10829
10867
|
|
|
10868
|
+
/**
|
|
10869
|
+
* The default policy for the runtime's shared retry service.
|
|
10870
|
+
*
|
|
10871
|
+
* Every fetch-service descriptor wired with the retry service also supplies its
|
|
10872
|
+
* own `retry:` interceptor, which passes a per-request policy as the override to
|
|
10873
|
+
* `applyRetry` — so this default is never consulted on any real path. It is
|
|
10874
|
+
* reachable only if a descriptor is registered with the retry service but omits
|
|
10875
|
+
* its `retry:` interceptor; in that case service-fetch-network falls back to
|
|
10876
|
+
* `retryService.applyRetry(fetch)` with no override, and this policy runs.
|
|
10877
|
+
*
|
|
10878
|
+
* That is a wiring mistake, not a runtime condition. We surface it loudly in
|
|
10879
|
+
* development rather than silently degrading to never-retry (the behavior of a
|
|
10880
|
+
* plain empty policy), following the repo convention for should-never-run paths.
|
|
10881
|
+
*/
|
|
10882
|
+
class UnconfiguredRetryPolicy extends RetryPolicy {
|
|
10883
|
+
async shouldRetry(_result, _context) {
|
|
10884
|
+
// istanbul ignore else: not exercised in NODE_ENV = production for test coverage
|
|
10885
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
10886
|
+
throw new Error('A fetch-service descriptor was registered with the retry service but did ' +
|
|
10887
|
+
'not supply a `retry:` interceptor. Retries would silently never run — ' +
|
|
10888
|
+
'add a `retry:` interceptor (e.g. buildFetchRetryInterceptor()) to the descriptor.');
|
|
10889
|
+
}
|
|
10890
|
+
return false;
|
|
10891
|
+
}
|
|
10892
|
+
async calculateDelay(_result, _context) {
|
|
10893
|
+
return 0;
|
|
10894
|
+
}
|
|
10895
|
+
}
|
|
10896
|
+
|
|
10830
10897
|
/* eslint-disable no-console */
|
|
10831
10898
|
/**
|
|
10832
10899
|
* Default storage configuration for the durable cache
|
|
@@ -11428,11 +11495,15 @@ function initializeOneStore(luvio) {
|
|
|
11428
11495
|
reader.unMarkMissing();
|
|
11429
11496
|
return linkedData.data;
|
|
11430
11497
|
});
|
|
11431
|
-
//
|
|
11432
|
-
|
|
11433
|
-
|
|
11434
|
-
|
|
11435
|
-
|
|
11498
|
+
// The real throttling/CSRF policies are built fresh per request in
|
|
11499
|
+
// buildFetchRetryInterceptor (retry-interceptors/fetch-retry.ts) so each
|
|
11500
|
+
// request gets its own CSRF context and sees its own HTTP method. This
|
|
11501
|
+
// default is never consulted by any current fetch-service descriptor (they
|
|
11502
|
+
// all supply their own `retry` interceptor + override); UnconfiguredRetryPolicy
|
|
11503
|
+
// exists so that if a future descriptor is wired with this retry service but
|
|
11504
|
+
// forgets its `retry:` interceptor, the silent never-retry fallback surfaces
|
|
11505
|
+
// loudly in development instead.
|
|
11506
|
+
const retryServiceDescriptor = buildServiceDescriptor$8(new UnconfiguredRetryPolicy());
|
|
11436
11507
|
const retryService = retryServiceDescriptor.service;
|
|
11437
11508
|
const csrfTokenManagerServiceDescriptor = buildRenewableResourceManagerDescriptor(CSRF_TOKEN_MANAGER_SERVICE, buildCsrfTokenManager());
|
|
11438
11509
|
const prefetchSfapJwtServiceDescriptor = {
|
|
@@ -11508,4 +11579,4 @@ function ldsEngineCreator() {
|
|
|
11508
11579
|
}
|
|
11509
11580
|
|
|
11510
11581
|
export { LexRequestStrategy, PDL_ENGINE_REGISTRATION_ID, PdlPrefetcherEventType, PdlRequestPriority, buildPredictorForContext, configService, ldsEngineCreator as default, initializeLDS, initializeOneStore, notifyUpdateAvailableFactory, registerRequestStrategy, saveRequestAsPrediction, subscribeToPrefetcherEvents, unregisterRequestStrategy, whenPredictionsReady };
|
|
11511
|
-
// version: 1.
|
|
11582
|
+
// version: 1.455.0-c53c97de2a
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { FetchParameters } from '@conduit-client/service-fetch-network/v1';
|
|
2
|
+
/**
|
|
3
|
+
* Extracts the HTTP method from FetchParameters, matching the Fetch API's own
|
|
4
|
+
* precedence: an options.method override wins over a Request object's method
|
|
5
|
+
* (e.g. `fetch(new Request(url, { method: 'GET' }), { method: 'POST' })`
|
|
6
|
+
* resolves to `POST`).
|
|
7
|
+
*/
|
|
8
|
+
export declare function getFetchMethod([urlOrRequest, options]: FetchParameters): string | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Only GET requests are safe to replay automatically on 429/503 — replaying a
|
|
11
|
+
* write (POST/PUT/PATCH/DELETE) risks executing a mutation more than once.
|
|
12
|
+
* Shared by both the Luvio and generic-fetch throttling retry policies so the
|
|
13
|
+
* write-guard rule lives in exactly one place.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isRetryableMethod(method: string | undefined): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Determines if the HTTP method requires CSRF protection.
|
|
18
|
+
* Only mutating operations (POST, PUT, PATCH, DELETE) require CSRF tokens.
|
|
19
|
+
*/
|
|
20
|
+
export declare function isCsrfMethod(method: string | undefined): boolean;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { RetryInterceptor } from '@conduit-client/service-fetch-network/v1';
|
|
2
|
+
/**
|
|
3
|
+
* Builds the retry interceptor used by the generic Conduit fetch service.
|
|
4
|
+
*
|
|
5
|
+
* Composes two independent per-request retry policies — throttling (429/503,
|
|
6
|
+
* GET-only) and CSRF (401 token refresh) — built fresh per request rather
|
|
7
|
+
* than reused off a shared defaultRetryPolicy. This keeps concurrent requests
|
|
8
|
+
* from sharing mutable CSRF request-context state, and lets the throttling
|
|
9
|
+
* policy see this request's own HTTP method.
|
|
10
|
+
*
|
|
11
|
+
* The `retryService` handed in by the framework is used only as the runner for
|
|
12
|
+
* `applyRetry` — the real policy is always the per-request `composedPolicy`
|
|
13
|
+
* passed as the override, never the service's own `defaultRetryPolicy`. When no
|
|
14
|
+
* `retryService` is injected (e.g. the copilot/unauthorized descriptors, which
|
|
15
|
+
* intentionally opt out of retries), we fall through to a plain fetch.
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildFetchRetryInterceptor(): RetryInterceptor;
|
|
@@ -10,7 +10,8 @@ type FetchThrottlingRetryPolicyConfig = {
|
|
|
10
10
|
};
|
|
11
11
|
export declare class FetchThrottlingRetryPolicy extends RetryPolicy<Response> {
|
|
12
12
|
private config;
|
|
13
|
-
|
|
13
|
+
private method?;
|
|
14
|
+
constructor(config?: FetchThrottlingRetryPolicyConfig, method?: string | undefined);
|
|
14
15
|
shouldRetry(result: Response, context: RetryContext<Response>): Promise<boolean>;
|
|
15
16
|
calculateDelay(result: Response, context: RetryContext<Response>): Promise<number>;
|
|
16
17
|
parseRetryAfterHeader(result: Response): number | undefined;
|
|
@@ -10,7 +10,8 @@ type LuvioFetchThrottlingRetryPolicyConfig = {
|
|
|
10
10
|
};
|
|
11
11
|
export declare class LuvioFetchThrottlingRetryPolicy extends RetryPolicy<FetchResponse<any>> {
|
|
12
12
|
private config;
|
|
13
|
-
|
|
13
|
+
private method?;
|
|
14
|
+
constructor(config?: LuvioFetchThrottlingRetryPolicyConfig, method?: string | undefined);
|
|
14
15
|
shouldRetry(result: FetchResponse<any>, context: RetryContext<FetchResponse<any>>): Promise<boolean>;
|
|
15
16
|
calculateDelay(result: FetchResponse<any>, context: RetryContext<FetchResponse<any>>): Promise<number>;
|
|
16
17
|
parseRetryAfterHeader(result: FetchResponse<any>): number | undefined;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { RetryContext } from '@conduit-client/service-retry/v1';
|
|
2
|
+
import { RetryPolicy } from '@conduit-client/service-retry/v1';
|
|
3
|
+
/**
|
|
4
|
+
* The default policy for the runtime's shared retry service.
|
|
5
|
+
*
|
|
6
|
+
* Every fetch-service descriptor wired with the retry service also supplies its
|
|
7
|
+
* own `retry:` interceptor, which passes a per-request policy as the override to
|
|
8
|
+
* `applyRetry` — so this default is never consulted on any real path. It is
|
|
9
|
+
* reachable only if a descriptor is registered with the retry service but omits
|
|
10
|
+
* its `retry:` interceptor; in that case service-fetch-network falls back to
|
|
11
|
+
* `retryService.applyRetry(fetch)` with no override, and this policy runs.
|
|
12
|
+
*
|
|
13
|
+
* That is a wiring mistake, not a runtime condition. We surface it loudly in
|
|
14
|
+
* development rather than silently degrading to never-retry (the behavior of a
|
|
15
|
+
* plain empty policy), following the repo convention for should-never-run paths.
|
|
16
|
+
*/
|
|
17
|
+
export declare class UnconfiguredRetryPolicy extends RetryPolicy<Response> {
|
|
18
|
+
shouldRetry(_result: Response, _context: RetryContext<Response>): Promise<boolean>;
|
|
19
|
+
calculateDelay(_result: Response, _context: RetryContext<Response>): Promise<number>;
|
|
20
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/lds-runtime-one-app",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.455.0",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
5
5
|
"description": "LDS engine for the one.app (LEX) runtime.",
|
|
6
6
|
"main": "dist/oneAppLdsEngineCreator.js",
|
|
@@ -36,15 +36,15 @@
|
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@conduit-client/service-provisioner": "3.26.3",
|
|
38
38
|
"@conduit-client/tools-core": "3.26.3",
|
|
39
|
-
"@salesforce/lds-adapters-apex": "^1.
|
|
40
|
-
"@salesforce/lds-adapters-uiapi": "^1.
|
|
41
|
-
"@salesforce/lds-ads-bridge": "^1.
|
|
42
|
-
"@salesforce/lds-aura-storage": "^1.
|
|
43
|
-
"@salesforce/lds-bindings": "^1.
|
|
44
|
-
"@salesforce/lds-instrumentation": "^1.
|
|
45
|
-
"@salesforce/lds-network-adapter": "^1.
|
|
46
|
-
"@salesforce/lds-network-aura": "^1.
|
|
47
|
-
"@salesforce/lds-network-fetch": "^1.
|
|
39
|
+
"@salesforce/lds-adapters-apex": "^1.455.0",
|
|
40
|
+
"@salesforce/lds-adapters-uiapi": "^1.455.0",
|
|
41
|
+
"@salesforce/lds-ads-bridge": "^1.455.0",
|
|
42
|
+
"@salesforce/lds-aura-storage": "^1.455.0",
|
|
43
|
+
"@salesforce/lds-bindings": "^1.455.0",
|
|
44
|
+
"@salesforce/lds-instrumentation": "^1.455.0",
|
|
45
|
+
"@salesforce/lds-network-adapter": "^1.455.0",
|
|
46
|
+
"@salesforce/lds-network-aura": "^1.455.0",
|
|
47
|
+
"@salesforce/lds-network-fetch": "^1.455.0",
|
|
48
48
|
"jwt-encode": "1.0.1"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
@@ -76,19 +76,19 @@
|
|
|
76
76
|
"@luvio/network-adapter-composable": "0.161.2",
|
|
77
77
|
"@luvio/network-adapter-fetch": "0.161.2",
|
|
78
78
|
"@lwc/state": "^0.29.0",
|
|
79
|
-
"@salesforce/lds-adapters-onestore-graphql": "^1.
|
|
79
|
+
"@salesforce/lds-adapters-onestore-graphql": "^1.455.0",
|
|
80
80
|
"@salesforce/lds-adapters-uiapi-lex": "^1.415.0",
|
|
81
|
-
"@salesforce/lds-durable-storage": "^1.
|
|
82
|
-
"@salesforce/lds-luvio-service": "^1.
|
|
83
|
-
"@salesforce/lds-luvio-uiapi-records-service": "^1.
|
|
81
|
+
"@salesforce/lds-durable-storage": "^1.455.0",
|
|
82
|
+
"@salesforce/lds-luvio-service": "^1.455.0",
|
|
83
|
+
"@salesforce/lds-luvio-uiapi-records-service": "^1.455.0"
|
|
84
84
|
},
|
|
85
85
|
"luvioBundlesize": [
|
|
86
86
|
{
|
|
87
87
|
"path": "./dist/oneAppLdsEngineCreator.js",
|
|
88
88
|
"maxSize": {
|
|
89
|
-
"none": "
|
|
89
|
+
"none": "418 kB",
|
|
90
90
|
"min": "190 kB",
|
|
91
|
-
"compressed": "
|
|
91
|
+
"compressed": "74 kB"
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
],
|