@salesforce/lds-runtime-aura 1.401.0 → 1.403.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/ldsEngineCreator.js +2698 -1406
- package/dist/types/__mocks__/instrumentation/service.d.ts +2 -2
- package/dist/types/__mocks__/instrumentation:thirdPartyTracker.d.ts +2 -5
- package/dist/types/fetch-service-descriptors/lex-fetch-service.d.ts +1 -1
- package/dist/types/finally-interceptors/third-party-tracker-finish.d.ts +2 -0
- package/dist/types/finally-interceptors/transport-receive.d.ts +3 -0
- package/dist/types/instrumentation-utils.d.ts +4 -0
- package/dist/types/locker-wire-bindings.d.ts +3 -0
- package/dist/types/request-interceptors/csrf-manager.d.ts +38 -0
- package/dist/types/request-interceptors/csrf-token.d.ts +18 -0
- package/dist/types/request-interceptors/third-party-tracker-register.d.ts +2 -0
- package/dist/types/request-interceptors/transport-send.d.ts +5 -0
- package/dist/types/retry-policies/csrf-token-retry-policy.d.ts +72 -0
- package/dist/types/retry-policies/fetch-throttling-retry-policy.d.ts +2 -2
- package/package.json +37 -37
- package/dist/types/request-interceptors/request-id.d.ts +0 -4
package/dist/ldsEngineCreator.js
CHANGED
|
@@ -26,21 +26,22 @@ import { GetApexWireAdapterFactory, registerPrefetcher as registerPrefetcher$1 }
|
|
|
26
26
|
import { instrument, getRecordAvatarsAdapterFactory, getRecordAdapterFactory, coerceFieldIdArray, getRecordsAdapterFactory, getRecordActionsAdapterFactory, getObjectInfosAdapterFactory, coerceObjectIdArray, getObjectInfoAdapterFactory, coerceObjectId, getRelatedListsActionsAdapterFactory, getRelatedListInfoBatchAdapterFactory, getRelatedListInfoAdapterFactory, getRelatedListRecordsBatchAdapterFactory, getRelatedListRecordsAdapterFactory, getListInfoByNameAdapterFactory, getListInfosByObjectNameAdapterFactory, getListRecordsByNameAdapterFactory, getListObjectInfoAdapterFactory, getRelatedListsInfoAdapterFactory, getRelatedListActionsAdapterFactory, getRecordId18Array, buildRecordRepKeyFromId, configuration, InMemoryRecordRepresentationQueryEvaluator, UiApiNamespace, RecordRepresentationRepresentationType, registerPrefetcher, RecordRepresentationVersion } from 'force/ldsAdaptersUiapi';
|
|
27
27
|
import { getInstrumentation } from 'o11y/client';
|
|
28
28
|
import { findExecutableOperation, buildGraphQLInputExtension, addTypenameToDocument } from 'force/luvioGraphqlNormalization';
|
|
29
|
-
import { print } from 'force/luvioOnestoreGraphqlParser';
|
|
29
|
+
import { print, wrapConfigAndVerify, resolveAst, validateGraphQLOperations } from 'force/luvioOnestoreGraphqlParser';
|
|
30
30
|
import { setServices } from 'force/luvioServiceProvisioner1';
|
|
31
|
+
import { assertIsValid, MissingRequiredPropertyError, JsonSchemaViolationError } from 'force/luvioJsonschemaValidate5';
|
|
31
32
|
import { dispatchGlobalEvent, unstable_loadComponentDefs, executeGlobalControllerRawResponse } from 'aura';
|
|
32
33
|
import auraNetworkAdapter, { dispatchAuraAction, defaultActionConfig, instrument as instrument$1, forceRecordTransactionsDisabled as forceRecordTransactionsDisabled$1, ldsNetworkAdapterInstrument, CrudEventState, CrudEventType, UIAPI_RECORDS_PATH, UIAPI_RELATED_LIST_RECORDS_BATCH_PATH, UIAPI_RELATED_LIST_RECORDS_PATH } from 'force/ldsNetwork';
|
|
33
|
-
import { pageScopedCache } from 'instrumentation/utility';
|
|
34
|
-
import { instrument as instrument$2, generateRequestId, setupLexNetworkAdapter, internalRequestTracker } from 'force/ldsNetworkFetch';
|
|
35
34
|
import { ThirdPartyTracker } from 'instrumentation:thirdPartyTracker';
|
|
35
|
+
import { markStart, markEnd, counter, registerCacheStats, perfStart, perfEnd, registerPeriodicLogger, interaction, timer } from 'instrumentation/service';
|
|
36
|
+
import { instrument as instrument$2, setupLexNetworkAdapter, internalRequestTracker, generateRequestId as generateRequestId$1 } from 'force/ldsNetworkFetch';
|
|
36
37
|
import { REFRESH_ADAPTER_EVENT, ADAPTER_UNFULFILLED_ERROR, instrument as instrument$3 } from 'force/ldsBindings';
|
|
37
|
-
import {
|
|
38
|
-
import { LRUCache, instrumentAdapter, instrumentLuvio, setupInstrumentation as setupInstrumentation$1, logObjectInfoChanged as logObjectInfoChanged$1, updatePercentileHistogramMetric, incrementCounterMetric, incrementGetRecordNotifyChangeAllowCount, incrementGetRecordNotifyChangeDropCount, incrementNotifyRecordUpdateAvailableAllowCount, incrementNotifyRecordUpdateAvailableDropCount, setLdsAdaptersUiapiInstrumentation, logError, setLdsNetworkAdapterInstrumentation, incrementStateCreatedCount, executeAsyncActivity, METRIC_KEYS, onIdleDetected } from 'force/ldsInstrumentation';
|
|
38
|
+
import { LRUCache, instrumentAdapter, instrumentLuvio, setupInstrumentation as setupInstrumentation$1, logObjectInfoChanged as logObjectInfoChanged$1, updatePercentileHistogramMetric, incrementCounterMetric, incrementGetRecordNotifyChangeAllowCount, incrementGetRecordNotifyChangeDropCount, incrementNotifyRecordUpdateAvailableAllowCount, incrementNotifyRecordUpdateAvailableDropCount, setLdsAdaptersUiapiInstrumentation, logError as logError$2, setLdsNetworkAdapterInstrumentation, incrementStateCreatedCount, executeAsyncActivity, METRIC_KEYS, onIdleDetected } from 'force/ldsInstrumentation';
|
|
39
39
|
import { instrument as instrument$4 } from 'force/adsBridge';
|
|
40
40
|
import { instrument as instrument$5 } from '@lwc/state';
|
|
41
41
|
import { withRegistration, register, setDefaultLuvio } from 'force/ldsEngine';
|
|
42
|
-
import
|
|
42
|
+
import { pageScopedCache } from 'instrumentation/utility';
|
|
43
43
|
import { createStorage, clearStorages } from 'force/ldsStorage';
|
|
44
|
+
import useHotspotLimit from '@salesforce/gate/lds.pdl.useHotspotLimit';
|
|
44
45
|
import useHttpUiapiOneApp from '@salesforce/gate/lds.useHttpUiapiOneApp';
|
|
45
46
|
import useHttpUiapiOneRuntime from '@salesforce/gate/lds.useHttpUiapiOneRuntime';
|
|
46
47
|
|
|
@@ -52,14 +53,15 @@ import useHttpUiapiOneRuntime from '@salesforce/gate/lds.useHttpUiapiOneRuntime'
|
|
|
52
53
|
const { create: create$1, freeze, keys: keys$2, entries: entries$1 } = Object;
|
|
53
54
|
const { isArray: isArray$3 } = Array;
|
|
54
55
|
const { stringify: stringify$3, parse: parse$2 } = JSON;
|
|
55
|
-
const
|
|
56
|
+
const WeakSetConstructor = WeakSet;
|
|
57
|
+
const LogLevelMap = {
|
|
56
58
|
TRACE: 4,
|
|
57
59
|
DEBUG: 3,
|
|
58
60
|
INFO: 2,
|
|
59
61
|
WARN: 1,
|
|
60
62
|
ERROR: 0
|
|
61
63
|
};
|
|
62
|
-
|
|
64
|
+
class ConsoleLogger {
|
|
63
65
|
constructor(level = "WARN", printer = console.log, formatter = (level2, message) => `${level2}: ${message}`) {
|
|
64
66
|
this.level = level;
|
|
65
67
|
this.printer = printer;
|
|
@@ -82,12 +84,15 @@ let ConsoleLogger$1 = class ConsoleLogger {
|
|
|
82
84
|
this.log("ERROR", message);
|
|
83
85
|
}
|
|
84
86
|
log(level, message) {
|
|
85
|
-
if (LogLevelMap
|
|
87
|
+
if (LogLevelMap[level] > LogLevelMap[this.level]) {
|
|
86
88
|
return;
|
|
87
89
|
}
|
|
88
90
|
this.printer(this.formatter(level, message));
|
|
89
91
|
}
|
|
90
|
-
}
|
|
92
|
+
}
|
|
93
|
+
function loggerService(level, printer, formatter) {
|
|
94
|
+
return new ConsoleLogger(level, printer, formatter);
|
|
95
|
+
}
|
|
91
96
|
let Ok$2 = class Ok {
|
|
92
97
|
constructor(value) {
|
|
93
98
|
this.value = value;
|
|
@@ -131,41 +136,41 @@ function buildSubscribableResult$1(result, subscribe, refresh) {
|
|
|
131
136
|
return err$1({ failure: result.error, subscribe, refresh });
|
|
132
137
|
}
|
|
133
138
|
}
|
|
134
|
-
function resolvedPromiseLike$
|
|
135
|
-
if (isPromiseLike$
|
|
139
|
+
function resolvedPromiseLike$2(result) {
|
|
140
|
+
if (isPromiseLike$2(result)) {
|
|
136
141
|
return result.then((nextResult) => nextResult);
|
|
137
142
|
}
|
|
138
143
|
return {
|
|
139
144
|
then: (onFulfilled, _onRejected) => {
|
|
140
145
|
try {
|
|
141
|
-
return resolvedPromiseLike$
|
|
146
|
+
return resolvedPromiseLike$2(onFulfilled(result));
|
|
142
147
|
} catch (e) {
|
|
143
148
|
if (onFulfilled === void 0) {
|
|
144
|
-
return resolvedPromiseLike$
|
|
149
|
+
return resolvedPromiseLike$2(result);
|
|
145
150
|
}
|
|
146
|
-
return rejectedPromiseLike$
|
|
151
|
+
return rejectedPromiseLike$2(e);
|
|
147
152
|
}
|
|
148
153
|
}
|
|
149
154
|
};
|
|
150
155
|
}
|
|
151
|
-
function rejectedPromiseLike$
|
|
152
|
-
if (isPromiseLike$
|
|
156
|
+
function rejectedPromiseLike$2(reason) {
|
|
157
|
+
if (isPromiseLike$2(reason)) {
|
|
153
158
|
return reason.then((nextResult) => nextResult);
|
|
154
159
|
}
|
|
155
160
|
return {
|
|
156
161
|
then: (_onFulfilled, onRejected) => {
|
|
157
162
|
if (typeof onRejected === "function") {
|
|
158
163
|
try {
|
|
159
|
-
return resolvedPromiseLike$
|
|
164
|
+
return resolvedPromiseLike$2(onRejected(reason));
|
|
160
165
|
} catch (e) {
|
|
161
|
-
return rejectedPromiseLike$
|
|
166
|
+
return rejectedPromiseLike$2(e);
|
|
162
167
|
}
|
|
163
168
|
}
|
|
164
|
-
return rejectedPromiseLike$
|
|
169
|
+
return rejectedPromiseLike$2(reason);
|
|
165
170
|
}
|
|
166
171
|
};
|
|
167
172
|
}
|
|
168
|
-
function isPromiseLike$
|
|
173
|
+
function isPromiseLike$2(x) {
|
|
169
174
|
return typeof (x == null ? void 0 : x.then) === "function";
|
|
170
175
|
}
|
|
171
176
|
function stableJSONStringify$2(node) {
|
|
@@ -271,6 +276,24 @@ class FetchResponse extends Error {
|
|
|
271
276
|
this.statusText = getStatusText(status);
|
|
272
277
|
}
|
|
273
278
|
}
|
|
279
|
+
const deeplyFrozen = new WeakSetConstructor();
|
|
280
|
+
function deepFreeze(value) {
|
|
281
|
+
if (typeof value !== "object" || value === null || deeplyFrozen.has(value)) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
deeplyFrozen.add(value);
|
|
285
|
+
if (isArray$3(value)) {
|
|
286
|
+
for (let i = 0, len = value.length; i < len; i += 1) {
|
|
287
|
+
deepFreeze(value[i]);
|
|
288
|
+
}
|
|
289
|
+
} else {
|
|
290
|
+
const keys$1 = keys$2(value);
|
|
291
|
+
for (let i = 0, len = keys$1.length; i < len; i += 1) {
|
|
292
|
+
deepFreeze(value[keys$1[i]]);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
freeze(value);
|
|
296
|
+
}
|
|
274
297
|
class InternalError extends Error {
|
|
275
298
|
constructor(data) {
|
|
276
299
|
super();
|
|
@@ -285,6 +308,15 @@ class UserVisibleError extends Error {
|
|
|
285
308
|
this.type = "user-visible";
|
|
286
309
|
}
|
|
287
310
|
}
|
|
311
|
+
function isUserVisibleError$1(error) {
|
|
312
|
+
return error instanceof Error && "type" in error && error.type === "user-visible";
|
|
313
|
+
}
|
|
314
|
+
function logError$1(error) {
|
|
315
|
+
if (isUserVisibleError$1(error)) {
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
console.error("OneStore Command threw an error that we did not expect", error);
|
|
319
|
+
}
|
|
288
320
|
|
|
289
321
|
/*!
|
|
290
322
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
@@ -341,7 +373,7 @@ let NetworkCommand$1 = class NetworkCommand extends BaseCommand {
|
|
|
341
373
|
async afterRequestHooks(_options) {
|
|
342
374
|
}
|
|
343
375
|
};
|
|
344
|
-
function buildServiceDescriptor$
|
|
376
|
+
function buildServiceDescriptor$r() {
|
|
345
377
|
return {
|
|
346
378
|
type: "networkCommandBaseClass",
|
|
347
379
|
version: "1.0",
|
|
@@ -440,10 +472,10 @@ class AuraNetworkCommand extends NetworkCommand$1 {
|
|
|
440
472
|
} else if (this.shouldUseFetch()) {
|
|
441
473
|
return this.convertFetchResponseToData(this.services.fetch(...this.fetchParams));
|
|
442
474
|
}
|
|
443
|
-
return resolvedPromiseLike$
|
|
475
|
+
return resolvedPromiseLike$2(err$1(toError("Aura/Fetch network services not found")));
|
|
444
476
|
}
|
|
445
477
|
}
|
|
446
|
-
function buildServiceDescriptor$
|
|
478
|
+
function buildServiceDescriptor$q() {
|
|
447
479
|
return {
|
|
448
480
|
type: "auraNetworkCommandBaseClass",
|
|
449
481
|
version: "1.0",
|
|
@@ -493,41 +525,41 @@ function buildSubscribableResult(result, subscribe, refresh) {
|
|
|
493
525
|
return err({ failure: result.error, subscribe, refresh });
|
|
494
526
|
}
|
|
495
527
|
}
|
|
496
|
-
function resolvedPromiseLike$
|
|
497
|
-
if (isPromiseLike$
|
|
528
|
+
function resolvedPromiseLike$1(result) {
|
|
529
|
+
if (isPromiseLike$1(result)) {
|
|
498
530
|
return result.then((nextResult) => nextResult);
|
|
499
531
|
}
|
|
500
532
|
return {
|
|
501
533
|
then: (onFulfilled, _onRejected) => {
|
|
502
534
|
try {
|
|
503
|
-
return resolvedPromiseLike$
|
|
535
|
+
return resolvedPromiseLike$1(onFulfilled(result));
|
|
504
536
|
} catch (e) {
|
|
505
537
|
if (onFulfilled === void 0) {
|
|
506
|
-
return resolvedPromiseLike$
|
|
538
|
+
return resolvedPromiseLike$1(result);
|
|
507
539
|
}
|
|
508
|
-
return rejectedPromiseLike$
|
|
540
|
+
return rejectedPromiseLike$1(e);
|
|
509
541
|
}
|
|
510
542
|
}
|
|
511
543
|
};
|
|
512
544
|
}
|
|
513
|
-
function rejectedPromiseLike$
|
|
514
|
-
if (isPromiseLike$
|
|
545
|
+
function rejectedPromiseLike$1(reason) {
|
|
546
|
+
if (isPromiseLike$1(reason)) {
|
|
515
547
|
return reason.then((nextResult) => nextResult);
|
|
516
548
|
}
|
|
517
549
|
return {
|
|
518
550
|
then: (_onFulfilled, onRejected) => {
|
|
519
551
|
if (typeof onRejected === "function") {
|
|
520
552
|
try {
|
|
521
|
-
return resolvedPromiseLike$
|
|
553
|
+
return resolvedPromiseLike$1(onRejected(reason));
|
|
522
554
|
} catch (e) {
|
|
523
|
-
return rejectedPromiseLike$
|
|
555
|
+
return rejectedPromiseLike$1(e);
|
|
524
556
|
}
|
|
525
557
|
}
|
|
526
|
-
return rejectedPromiseLike$
|
|
558
|
+
return rejectedPromiseLike$1(reason);
|
|
527
559
|
}
|
|
528
560
|
};
|
|
529
561
|
}
|
|
530
|
-
function isPromiseLike$
|
|
562
|
+
function isPromiseLike$1(x) {
|
|
531
563
|
return typeof (x == null ? void 0 : x.then) === "function";
|
|
532
564
|
}
|
|
533
565
|
function deepEquals$1(x, y) {
|
|
@@ -762,7 +794,7 @@ class CacheControlCommand extends BaseCommand {
|
|
|
762
794
|
});
|
|
763
795
|
}
|
|
764
796
|
}
|
|
765
|
-
return resolvedPromiseLike$
|
|
797
|
+
return resolvedPromiseLike$1(void 0);
|
|
766
798
|
}
|
|
767
799
|
get operationType() {
|
|
768
800
|
return "query";
|
|
@@ -1038,7 +1070,7 @@ let AuraCacheControlCommand$1 = class AuraCacheControlCommand extends CacheContr
|
|
|
1038
1070
|
} else if (this.shouldUseFetch()) {
|
|
1039
1071
|
return this.convertFetchResponseToData(this.services.fetch(...this.fetchParams));
|
|
1040
1072
|
}
|
|
1041
|
-
return resolvedPromiseLike$
|
|
1073
|
+
return resolvedPromiseLike$2(err$1(toError("Aura/Fetch network services not found")));
|
|
1042
1074
|
}
|
|
1043
1075
|
coerceAuraErrors(auraErrors) {
|
|
1044
1076
|
return toError(auraErrors[0]);
|
|
@@ -1112,9 +1144,9 @@ class AuraResourceCacheControlCommand extends AuraCacheControlCommand$1 {
|
|
|
1112
1144
|
var _a;
|
|
1113
1145
|
const data = (_a = cache.get(this.buildKey())) == null ? void 0 : _a.value;
|
|
1114
1146
|
if (data === void 0) {
|
|
1115
|
-
return resolvedPromiseLike$
|
|
1147
|
+
return resolvedPromiseLike$2(err$1(new Error("Failed to find data in cache")));
|
|
1116
1148
|
}
|
|
1117
|
-
return resolvedPromiseLike$
|
|
1149
|
+
return resolvedPromiseLike$2(ok$2(data));
|
|
1118
1150
|
}
|
|
1119
1151
|
writeToCache(cache, networkResult) {
|
|
1120
1152
|
if (networkResult.isOk()) {
|
|
@@ -1125,13 +1157,13 @@ class AuraResourceCacheControlCommand extends AuraCacheControlCommand$1 {
|
|
|
1125
1157
|
}
|
|
1126
1158
|
});
|
|
1127
1159
|
}
|
|
1128
|
-
return resolvedPromiseLike$
|
|
1160
|
+
return resolvedPromiseLike$2(void 0);
|
|
1129
1161
|
}
|
|
1130
1162
|
buildKey() {
|
|
1131
1163
|
return `{"endpoint":${this.endpoint},"params":${stableJSONStringify$2(this.auraParams)}}`;
|
|
1132
1164
|
}
|
|
1133
1165
|
}
|
|
1134
|
-
function buildServiceDescriptor$
|
|
1166
|
+
function buildServiceDescriptor$p() {
|
|
1135
1167
|
return {
|
|
1136
1168
|
type: "auraResourceCacheControlCommand",
|
|
1137
1169
|
version: "1.0",
|
|
@@ -1181,7 +1213,7 @@ class AuraCacheControlCommand extends CacheControlCommand {
|
|
|
1181
1213
|
} else if (this.shouldUseFetch()) {
|
|
1182
1214
|
return this.convertFetchResponseToData(this.services.fetch(...this.fetchParams));
|
|
1183
1215
|
}
|
|
1184
|
-
return resolvedPromiseLike$
|
|
1216
|
+
return resolvedPromiseLike$2(err$1(toError("Aura/Fetch network services not found")));
|
|
1185
1217
|
}
|
|
1186
1218
|
coerceAuraErrors(auraErrors) {
|
|
1187
1219
|
return toError(auraErrors[0]);
|
|
@@ -1254,11 +1286,11 @@ class AuraNormalizedCacheControlCommand extends AuraCacheControlCommand {
|
|
|
1254
1286
|
readFromCache(cache) {
|
|
1255
1287
|
const data = this.buildResultType().query(cache, this.buildQuery());
|
|
1256
1288
|
if (data.isErr()) {
|
|
1257
|
-
return resolvedPromiseLike$
|
|
1289
|
+
return resolvedPromiseLike$2(
|
|
1258
1290
|
err$1(new Error(`Failed to build data from type: ${stringify$3(data.error)}`))
|
|
1259
1291
|
);
|
|
1260
1292
|
}
|
|
1261
|
-
return resolvedPromiseLike$
|
|
1293
|
+
return resolvedPromiseLike$2(ok$2(data.value));
|
|
1262
1294
|
}
|
|
1263
1295
|
writeToCache(cache, networkResult) {
|
|
1264
1296
|
if (networkResult.isOk()) {
|
|
@@ -1267,10 +1299,10 @@ class AuraNormalizedCacheControlCommand extends AuraCacheControlCommand {
|
|
|
1267
1299
|
this.buildWriteInput(networkResult.value)
|
|
1268
1300
|
);
|
|
1269
1301
|
}
|
|
1270
|
-
return resolvedPromiseLike$
|
|
1302
|
+
return resolvedPromiseLike$2(void 0);
|
|
1271
1303
|
}
|
|
1272
1304
|
}
|
|
1273
|
-
function buildServiceDescriptor$
|
|
1305
|
+
function buildServiceDescriptor$o() {
|
|
1274
1306
|
return {
|
|
1275
1307
|
type: "auraNormalizedCacheControlCommand",
|
|
1276
1308
|
version: "1.0",
|
|
@@ -1343,11 +1375,11 @@ class HttpNormalizedCacheControlCommand extends HttpCacheControlCommand {
|
|
|
1343
1375
|
readFromCache(cache) {
|
|
1344
1376
|
const data = this.buildResultType().query(cache, this.buildQuery());
|
|
1345
1377
|
if (data.isErr()) {
|
|
1346
|
-
return resolvedPromiseLike$
|
|
1378
|
+
return resolvedPromiseLike$2(
|
|
1347
1379
|
err$1(new Error(`Failed to build data from type: ${stringify$3(data.error)}`))
|
|
1348
1380
|
);
|
|
1349
1381
|
}
|
|
1350
|
-
return resolvedPromiseLike$
|
|
1382
|
+
return resolvedPromiseLike$2(ok$2(data.value));
|
|
1351
1383
|
}
|
|
1352
1384
|
writeToCache(cache, networkResult) {
|
|
1353
1385
|
if (networkResult.isOk()) {
|
|
@@ -1356,10 +1388,10 @@ class HttpNormalizedCacheControlCommand extends HttpCacheControlCommand {
|
|
|
1356
1388
|
this.buildWriteInput(networkResult.value)
|
|
1357
1389
|
);
|
|
1358
1390
|
}
|
|
1359
|
-
return resolvedPromiseLike$
|
|
1391
|
+
return resolvedPromiseLike$2(void 0);
|
|
1360
1392
|
}
|
|
1361
1393
|
}
|
|
1362
|
-
function buildServiceDescriptor$
|
|
1394
|
+
function buildServiceDescriptor$n() {
|
|
1363
1395
|
return {
|
|
1364
1396
|
type: "httpNormalizedCacheControlCommand",
|
|
1365
1397
|
version: "1.0",
|
|
@@ -1537,7 +1569,7 @@ _FetchNetworkCommand.availableDecorators = {
|
|
|
1537
1569
|
abortable: createAbortableDecorator
|
|
1538
1570
|
};
|
|
1539
1571
|
let FetchNetworkCommand = _FetchNetworkCommand;
|
|
1540
|
-
function buildServiceDescriptor$
|
|
1572
|
+
function buildServiceDescriptor$m() {
|
|
1541
1573
|
return {
|
|
1542
1574
|
type: "fetchNetworkCommandBaseClass",
|
|
1543
1575
|
version: "1.0",
|
|
@@ -1573,7 +1605,7 @@ class StreamingCommand extends BaseCommand {
|
|
|
1573
1605
|
);
|
|
1574
1606
|
}
|
|
1575
1607
|
}
|
|
1576
|
-
function buildServiceDescriptor$
|
|
1608
|
+
function buildServiceDescriptor$l() {
|
|
1577
1609
|
return {
|
|
1578
1610
|
type: "streamingCommandBaseClass",
|
|
1579
1611
|
version: "1.0",
|
|
@@ -1656,7 +1688,7 @@ class SSEParsingStream extends TransformStream {
|
|
|
1656
1688
|
});
|
|
1657
1689
|
}
|
|
1658
1690
|
}
|
|
1659
|
-
function buildServiceDescriptor$
|
|
1691
|
+
function buildServiceDescriptor$k() {
|
|
1660
1692
|
return {
|
|
1661
1693
|
type: "SSECommandBaseClass",
|
|
1662
1694
|
version: "1.0",
|
|
@@ -1707,7 +1739,7 @@ function buildInstrumentCommand(services) {
|
|
|
1707
1739
|
};
|
|
1708
1740
|
};
|
|
1709
1741
|
}
|
|
1710
|
-
function buildServiceDescriptor$
|
|
1742
|
+
function buildServiceDescriptor$j(instrumentation) {
|
|
1711
1743
|
return {
|
|
1712
1744
|
type: "instrumentCommand",
|
|
1713
1745
|
version: "1.0",
|
|
@@ -1977,7 +2009,7 @@ class O11yInstrumentation {
|
|
|
1977
2009
|
this.metrics = new O11yOTelMetricsAPI(this.services);
|
|
1978
2010
|
}
|
|
1979
2011
|
}
|
|
1980
|
-
function buildServiceDescriptor$
|
|
2012
|
+
function buildServiceDescriptor$i(logger) {
|
|
1981
2013
|
return {
|
|
1982
2014
|
type: "instrumentation",
|
|
1983
2015
|
version: "1.0",
|
|
@@ -2230,7 +2262,7 @@ let DefaultCache$1 = class DefaultCache {
|
|
|
2230
2262
|
return new FixedTimeWritableCache$1(this, generatedTime);
|
|
2231
2263
|
}
|
|
2232
2264
|
};
|
|
2233
|
-
function buildServiceDescriptor$
|
|
2265
|
+
function buildServiceDescriptor$h() {
|
|
2234
2266
|
return {
|
|
2235
2267
|
type: "cache",
|
|
2236
2268
|
version: "1.0",
|
|
@@ -2453,7 +2485,7 @@ class CacheController {
|
|
|
2453
2485
|
yield* this.services.cacheInclusionPolicy.findAndModify(query, cacheUpdate);
|
|
2454
2486
|
}
|
|
2455
2487
|
}
|
|
2456
|
-
function buildServiceDescriptor$
|
|
2488
|
+
function buildServiceDescriptor$g(cache, cacheInclusionPolicy, instrumentation) {
|
|
2457
2489
|
return {
|
|
2458
2490
|
type: "cacheController",
|
|
2459
2491
|
version: "1.0",
|
|
@@ -2466,48 +2498,6 @@ function buildServiceDescriptor$9(cache, cacheInclusionPolicy, instrumentation)
|
|
|
2466
2498
|
* All rights reserved.
|
|
2467
2499
|
* For full license text, see the LICENSE.txt file
|
|
2468
2500
|
*/
|
|
2469
|
-
/*!
|
|
2470
|
-
* Copyright (c) 2022, Salesforce, Inc.,
|
|
2471
|
-
* All rights reserved.
|
|
2472
|
-
* For full license text, see the LICENSE.txt file
|
|
2473
|
-
*/
|
|
2474
|
-
function resolvedPromiseLike$1(result) {
|
|
2475
|
-
if (isPromiseLike$1(result)) {
|
|
2476
|
-
return result.then((nextResult) => nextResult);
|
|
2477
|
-
}
|
|
2478
|
-
return {
|
|
2479
|
-
then: (onFulfilled, _onRejected) => {
|
|
2480
|
-
try {
|
|
2481
|
-
return resolvedPromiseLike$1(onFulfilled(result));
|
|
2482
|
-
} catch (e) {
|
|
2483
|
-
if (onFulfilled === void 0) {
|
|
2484
|
-
return resolvedPromiseLike$1(result);
|
|
2485
|
-
}
|
|
2486
|
-
return rejectedPromiseLike$1(e);
|
|
2487
|
-
}
|
|
2488
|
-
}
|
|
2489
|
-
};
|
|
2490
|
-
}
|
|
2491
|
-
function rejectedPromiseLike$1(reason) {
|
|
2492
|
-
if (isPromiseLike$1(reason)) {
|
|
2493
|
-
return reason.then((nextResult) => nextResult);
|
|
2494
|
-
}
|
|
2495
|
-
return {
|
|
2496
|
-
then: (_onFulfilled, onRejected) => {
|
|
2497
|
-
if (typeof onRejected === "function") {
|
|
2498
|
-
try {
|
|
2499
|
-
return resolvedPromiseLike$1(onRejected(reason));
|
|
2500
|
-
} catch (e) {
|
|
2501
|
-
return rejectedPromiseLike$1(e);
|
|
2502
|
-
}
|
|
2503
|
-
}
|
|
2504
|
-
return rejectedPromiseLike$1(reason);
|
|
2505
|
-
}
|
|
2506
|
-
};
|
|
2507
|
-
}
|
|
2508
|
-
function isPromiseLike$1(x) {
|
|
2509
|
-
return typeof (x == null ? void 0 : x.then) === "function";
|
|
2510
|
-
}
|
|
2511
2501
|
const EventTypeWildcard = Symbol("EventTypeWildcard");
|
|
2512
2502
|
class DefaultPubSubService {
|
|
2513
2503
|
constructor() {
|
|
@@ -2535,14 +2525,14 @@ class DefaultPubSubService {
|
|
|
2535
2525
|
return;
|
|
2536
2526
|
}
|
|
2537
2527
|
const returnVal = subscription.callback.call(subscription, event);
|
|
2538
|
-
if (isPromiseLike$
|
|
2528
|
+
if (isPromiseLike$2(returnVal)) {
|
|
2539
2529
|
promises.push(returnVal);
|
|
2540
2530
|
}
|
|
2541
2531
|
});
|
|
2542
2532
|
if (promises.length > 0) {
|
|
2543
2533
|
return Promise.all(promises).then(() => void 0);
|
|
2544
2534
|
}
|
|
2545
|
-
return resolvedPromiseLike$
|
|
2535
|
+
return resolvedPromiseLike$2(void 0);
|
|
2546
2536
|
}
|
|
2547
2537
|
getSubscriptions(event) {
|
|
2548
2538
|
const eventTypeSubscriptions = this.subscriptions.get(event.type);
|
|
@@ -2563,7 +2553,7 @@ class DefaultPubSubService {
|
|
|
2563
2553
|
return matchingSubscriptions;
|
|
2564
2554
|
}
|
|
2565
2555
|
}
|
|
2566
|
-
function buildServiceDescriptor$
|
|
2556
|
+
function buildServiceDescriptor$f() {
|
|
2567
2557
|
return {
|
|
2568
2558
|
type: "pubSub",
|
|
2569
2559
|
version: "1.0",
|
|
@@ -2626,7 +2616,7 @@ class NDJSONParsingStream extends TransformStream {
|
|
|
2626
2616
|
});
|
|
2627
2617
|
}
|
|
2628
2618
|
}
|
|
2629
|
-
function buildServiceDescriptor$
|
|
2619
|
+
function buildServiceDescriptor$e() {
|
|
2630
2620
|
return {
|
|
2631
2621
|
type: "NDJSONCommandBaseClass",
|
|
2632
2622
|
version: "1.0",
|
|
@@ -2667,7 +2657,7 @@ function buildServiceDescriptor$7() {
|
|
|
2667
2657
|
* };
|
|
2668
2658
|
* ```
|
|
2669
2659
|
*/
|
|
2670
|
-
function buildServiceDescriptor$
|
|
2660
|
+
function buildServiceDescriptor$d(luvio) {
|
|
2671
2661
|
return {
|
|
2672
2662
|
type: 'luvio',
|
|
2673
2663
|
version: '1.0',
|
|
@@ -2676,7 +2666,7 @@ function buildServiceDescriptor$6(luvio) {
|
|
|
2676
2666
|
},
|
|
2677
2667
|
};
|
|
2678
2668
|
}
|
|
2679
|
-
// version: 1.
|
|
2669
|
+
// version: 1.403.0-5476a05446
|
|
2680
2670
|
|
|
2681
2671
|
/*!
|
|
2682
2672
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
@@ -2798,7 +2788,7 @@ class AuraGraphQLNormalizedCacheControlCommand extends AuraNormalizedCacheContro
|
|
|
2798
2788
|
return buildSubscribableResult$1(result, this.buildSubscribe(), () => this.refresh());
|
|
2799
2789
|
});
|
|
2800
2790
|
}
|
|
2801
|
-
return resolvedPromiseLike$
|
|
2791
|
+
return resolvedPromiseLike$2(
|
|
2802
2792
|
buildSubscribableResult$1(
|
|
2803
2793
|
err$1(toError("Aura/Fetch network services not found")),
|
|
2804
2794
|
this.buildSubscribe(),
|
|
@@ -2840,7 +2830,7 @@ class AuraGraphQLNormalizedCacheControlCommand extends AuraNormalizedCacheContro
|
|
|
2840
2830
|
});
|
|
2841
2831
|
}
|
|
2842
2832
|
}
|
|
2843
|
-
function buildServiceDescriptor$
|
|
2833
|
+
function buildServiceDescriptor$c() {
|
|
2844
2834
|
return {
|
|
2845
2835
|
type: "auraGraphQLNormalizedCacheControlCommand",
|
|
2846
2836
|
version: "1.0",
|
|
@@ -2958,7 +2948,7 @@ class HttpGraphQLNormalizedCacheControlCommand extends HttpNormalizedCacheContro
|
|
|
2958
2948
|
});
|
|
2959
2949
|
}
|
|
2960
2950
|
}
|
|
2961
|
-
function buildServiceDescriptor$
|
|
2951
|
+
function buildServiceDescriptor$b() {
|
|
2962
2952
|
return {
|
|
2963
2953
|
type: "httpGraphQLNormalizedCacheControlCommand",
|
|
2964
2954
|
version: "1.0",
|
|
@@ -2982,7 +2972,7 @@ class FeatureFlagsService {
|
|
|
2982
2972
|
return this.flags.get(flagName) || defaultValue;
|
|
2983
2973
|
}
|
|
2984
2974
|
}
|
|
2985
|
-
function buildServiceDescriptor$
|
|
2975
|
+
function buildServiceDescriptor$a() {
|
|
2986
2976
|
return {
|
|
2987
2977
|
version: "1.0",
|
|
2988
2978
|
service: new FeatureFlagsService(),
|
|
@@ -3004,7 +2994,7 @@ function buildServiceDescriptor$3() {
|
|
|
3004
2994
|
* *******************************************************************************************
|
|
3005
2995
|
*/
|
|
3006
2996
|
/* proxy-compat-disable */
|
|
3007
|
-
function buildServiceDescriptor$
|
|
2997
|
+
function buildServiceDescriptor$9(notifyRecordUpdateAvailable, getNormalizedLuvioRecord) {
|
|
3008
2998
|
return {
|
|
3009
2999
|
type: 'luvioUiapiRecords',
|
|
3010
3000
|
version: '1.0',
|
|
@@ -3014,7 +3004,7 @@ function buildServiceDescriptor$2(notifyRecordUpdateAvailable, getNormalizedLuvi
|
|
|
3014
3004
|
},
|
|
3015
3005
|
};
|
|
3016
3006
|
}
|
|
3017
|
-
// version: 1.
|
|
3007
|
+
// version: 1.403.0-5476a05446
|
|
3018
3008
|
|
|
3019
3009
|
/*!
|
|
3020
3010
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
@@ -3037,9 +3027,12 @@ class RetryService {
|
|
|
3037
3027
|
totalElapsedMs: Date.now() - startTime,
|
|
3038
3028
|
lastResult: result
|
|
3039
3029
|
};
|
|
3040
|
-
while (policy.shouldRetry(result, context)) {
|
|
3041
|
-
const delay = policy.calculateDelay(result, context);
|
|
3030
|
+
while (await policy.shouldRetry(result, context)) {
|
|
3031
|
+
const delay = await policy.calculateDelay(result, context);
|
|
3042
3032
|
await this.delay(delay);
|
|
3033
|
+
if (policy.prepareRetry) {
|
|
3034
|
+
await policy.prepareRetry(result, context);
|
|
3035
|
+
}
|
|
3043
3036
|
attempt++;
|
|
3044
3037
|
result = await operation();
|
|
3045
3038
|
context = {
|
|
@@ -3058,7 +3051,109 @@ class RetryService {
|
|
|
3058
3051
|
}
|
|
3059
3052
|
class RetryPolicy {
|
|
3060
3053
|
}
|
|
3061
|
-
|
|
3054
|
+
class ComposedRetryPolicy extends RetryPolicy {
|
|
3055
|
+
constructor(policies) {
|
|
3056
|
+
super();
|
|
3057
|
+
this.policies = policies;
|
|
3058
|
+
}
|
|
3059
|
+
/**
|
|
3060
|
+
* Returns true if any of the composed policies want to retry.
|
|
3061
|
+
*
|
|
3062
|
+
* Uses OR logic: if ANY policy returns true, this returns true.
|
|
3063
|
+
* Policies are checked in order and evaluation short-circuits on the first match.
|
|
3064
|
+
*/
|
|
3065
|
+
async shouldRetry(result, context) {
|
|
3066
|
+
for (const policy of this.policies) {
|
|
3067
|
+
if (await policy.shouldRetry(result, context)) {
|
|
3068
|
+
return true;
|
|
3069
|
+
}
|
|
3070
|
+
}
|
|
3071
|
+
return false;
|
|
3072
|
+
}
|
|
3073
|
+
/**
|
|
3074
|
+
* Returns the delay from the first policy that wants to retry.
|
|
3075
|
+
*
|
|
3076
|
+
* If multiple policies want to retry, only the FIRST policy's delay is used.
|
|
3077
|
+
* Policy order in the constructor array determines priority.
|
|
3078
|
+
* If no policy wants to retry, returns 0.
|
|
3079
|
+
*
|
|
3080
|
+
* @example
|
|
3081
|
+
* ```typescript
|
|
3082
|
+
* // If both PolicyA (1000ms) and PolicyB (5000ms) want to retry:
|
|
3083
|
+
* const composed = new ComposedRetryPolicy([policyA, policyB]);
|
|
3084
|
+
* composed.calculateDelay(result, context); // Returns 1000ms (PolicyA wins)
|
|
3085
|
+
* ```
|
|
3086
|
+
*/
|
|
3087
|
+
async calculateDelay(result, context) {
|
|
3088
|
+
for (const policy of this.policies) {
|
|
3089
|
+
if (await policy.shouldRetry(result, context)) {
|
|
3090
|
+
return policy.calculateDelay(result, context);
|
|
3091
|
+
}
|
|
3092
|
+
}
|
|
3093
|
+
return 0;
|
|
3094
|
+
}
|
|
3095
|
+
/**
|
|
3096
|
+
* Calls prepareRetry on policies that both:
|
|
3097
|
+
* 1. Implement the prepareRetry hook, AND
|
|
3098
|
+
* 2. Returned true from shouldRetry for this result
|
|
3099
|
+
*
|
|
3100
|
+
* This allows only the matching policies to perform preparation work (e.g., token refresh).
|
|
3101
|
+
* All matching prepareRetry calls run in parallel for efficiency.
|
|
3102
|
+
*
|
|
3103
|
+
* **Important**: prepareRetry only runs on policies that matched shouldRetry. This ensures
|
|
3104
|
+
* you don't perform unnecessary work or side effects for unrelated retry conditions.
|
|
3105
|
+
*
|
|
3106
|
+
* **Note**: If multiple policies match and have prepareRetry, ensure they don't have
|
|
3107
|
+
* conflicting side effects since they run in parallel.
|
|
3108
|
+
*
|
|
3109
|
+
* @example
|
|
3110
|
+
* ```typescript
|
|
3111
|
+
* // Status 401 occurs
|
|
3112
|
+
* const composed = new ComposedRetryPolicy([
|
|
3113
|
+
* authPolicy, // shouldRetry(401) → true, has prepareRetry
|
|
3114
|
+
* throttlePolicy, // shouldRetry(401) → false, has prepareRetry
|
|
3115
|
+
* ]);
|
|
3116
|
+
*
|
|
3117
|
+
* await composed.prepareRetry(result, context);
|
|
3118
|
+
* // → Only authPolicy.prepareRetry() runs (because it matched)
|
|
3119
|
+
* // → throttlePolicy.prepareRetry() does NOT run (didn't match)
|
|
3120
|
+
* ```
|
|
3121
|
+
*/
|
|
3122
|
+
async prepareRetry(result, context) {
|
|
3123
|
+
const matchingPolicies = [];
|
|
3124
|
+
for (const policy of this.policies) {
|
|
3125
|
+
if (policy.prepareRetry !== void 0 && await policy.shouldRetry(result, context)) {
|
|
3126
|
+
matchingPolicies.push(policy);
|
|
3127
|
+
}
|
|
3128
|
+
}
|
|
3129
|
+
if (matchingPolicies.length > 0) {
|
|
3130
|
+
await Promise.all(
|
|
3131
|
+
matchingPolicies.map((policy) => policy.prepareRetry(result, context))
|
|
3132
|
+
);
|
|
3133
|
+
}
|
|
3134
|
+
}
|
|
3135
|
+
/**
|
|
3136
|
+
* Returns all composed policies.
|
|
3137
|
+
* Useful for accessing or configuring individual policies after composition.
|
|
3138
|
+
*/
|
|
3139
|
+
getPolicies() {
|
|
3140
|
+
return this.policies;
|
|
3141
|
+
}
|
|
3142
|
+
/**
|
|
3143
|
+
* Helper to get a specific policy by type.
|
|
3144
|
+
* Useful for calling policy-specific methods after composition.
|
|
3145
|
+
*
|
|
3146
|
+
* @example
|
|
3147
|
+
* ```typescript
|
|
3148
|
+
* const csrfPolicy = composedPolicy.getPolicyByType(CsrfTokenRetryPolicy);
|
|
3149
|
+
* csrfPolicy?.setRequestContext(mutableRequest);
|
|
3150
|
+
* ```
|
|
3151
|
+
*/
|
|
3152
|
+
getPolicyByType(policyType) {
|
|
3153
|
+
return this.policies.find((policy) => policy instanceof policyType);
|
|
3154
|
+
}
|
|
3155
|
+
}
|
|
3156
|
+
function buildServiceDescriptor$8(defaultRetryPolicy) {
|
|
3062
3157
|
return {
|
|
3063
3158
|
version: "1.0",
|
|
3064
3159
|
service: new RetryService(defaultRetryPolicy),
|
|
@@ -3071,898 +3166,1509 @@ function buildServiceDescriptor$1(defaultRetryPolicy) {
|
|
|
3071
3166
|
* All rights reserved.
|
|
3072
3167
|
* For full license text, see the LICENSE.txt file
|
|
3073
3168
|
*/
|
|
3074
|
-
function
|
|
3075
|
-
|
|
3169
|
+
function isUserVisibleError(error) {
|
|
3170
|
+
return error instanceof Error && "type" in error && error.type === "user-visible";
|
|
3076
3171
|
}
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
if (t2.length % 4 == 1) throw new e$1("'atob' failed: The string to be decoded is not correctly encoded.");
|
|
3081
|
-
for (var n2, o2, a = 0, i = 0, c = ""; o2 = t2.charAt(i++); ~o2 && (n2 = a % 4 ? 64 * n2 + o2 : o2, a++ % 4) ? c += String.fromCharCode(255 & n2 >> (-2 * a & 6)) : 0) o2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(o2);
|
|
3082
|
-
return c;
|
|
3083
|
-
};
|
|
3084
|
-
function t(e2) {
|
|
3085
|
-
var t2 = e2.replace(/-/g, "+").replace(/_/g, "/");
|
|
3086
|
-
switch (t2.length % 4) {
|
|
3087
|
-
case 0:
|
|
3088
|
-
break;
|
|
3089
|
-
case 2:
|
|
3090
|
-
t2 += "==";
|
|
3091
|
-
break;
|
|
3092
|
-
case 3:
|
|
3093
|
-
t2 += "=";
|
|
3094
|
-
break;
|
|
3095
|
-
default:
|
|
3096
|
-
throw "Illegal base64url string!";
|
|
3097
|
-
}
|
|
3098
|
-
try {
|
|
3099
|
-
return (function(e3) {
|
|
3100
|
-
return decodeURIComponent(r(e3).replace(/(.)/g, (function(e4, r2) {
|
|
3101
|
-
var t3 = r2.charCodeAt(0).toString(16).toUpperCase();
|
|
3102
|
-
return t3.length < 2 && (t3 = "0" + t3), "%" + t3;
|
|
3103
|
-
})));
|
|
3104
|
-
})(t2);
|
|
3105
|
-
} catch (e3) {
|
|
3106
|
-
return r(t2);
|
|
3107
|
-
}
|
|
3172
|
+
function throwUserlandError(error) {
|
|
3173
|
+
logError(error);
|
|
3174
|
+
throw buildUserlandError(error);
|
|
3108
3175
|
}
|
|
3109
|
-
function
|
|
3110
|
-
|
|
3176
|
+
function emitError(callback, error) {
|
|
3177
|
+
logError(error);
|
|
3178
|
+
callback({ data: void 0, error: buildUserlandError(error) });
|
|
3111
3179
|
}
|
|
3112
|
-
function
|
|
3113
|
-
if (
|
|
3114
|
-
|
|
3115
|
-
try {
|
|
3116
|
-
return JSON.parse(t(e2.split(".")[o2]));
|
|
3117
|
-
} catch (e3) {
|
|
3118
|
-
throw new n$1("Invalid token specified: " + e3.message);
|
|
3180
|
+
function buildUserlandError(error) {
|
|
3181
|
+
if (isUserVisibleError(error)) {
|
|
3182
|
+
return error.data;
|
|
3119
3183
|
}
|
|
3184
|
+
return new Error("Internal error in Lightning Data Service adapter occurred.");
|
|
3120
3185
|
}
|
|
3121
|
-
|
|
3186
|
+
function logError(error) {
|
|
3187
|
+
if (isUserVisibleError(error)) {
|
|
3188
|
+
return;
|
|
3189
|
+
}
|
|
3190
|
+
console.error("OneStore Command threw an error that we did not expect", error);
|
|
3191
|
+
}
|
|
3192
|
+
|
|
3122
3193
|
/*!
|
|
3123
3194
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
3124
3195
|
* All rights reserved.
|
|
3125
3196
|
* For full license text, see the LICENSE.txt file
|
|
3126
3197
|
*/
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
}
|
|
3147
|
-
info(message) {
|
|
3148
|
-
this.log("INFO", message);
|
|
3149
|
-
}
|
|
3150
|
-
warn(message) {
|
|
3151
|
-
this.log("WARN", message);
|
|
3198
|
+
function buildBaseImperativeInvoker(getCommand, transformResult) {
|
|
3199
|
+
return async (...params) => {
|
|
3200
|
+
const command = getCommand({ params, assertIsValid });
|
|
3201
|
+
try {
|
|
3202
|
+
return command.execute().then((result) => transformResult(result));
|
|
3203
|
+
} catch (error) {
|
|
3204
|
+
throwUserlandError(error);
|
|
3205
|
+
}
|
|
3206
|
+
};
|
|
3207
|
+
}
|
|
3208
|
+
const supportedCachePolicyTypes = ["no-cache", "only-if-cached"];
|
|
3209
|
+
function requestContextIsSupportedCachePolicy(requestContext) {
|
|
3210
|
+
return typeof requestContext === "object" && requestContext !== null && "cachePolicy" in requestContext && typeof requestContext.cachePolicy === "object" && requestContext.cachePolicy !== null && "type" in requestContext.cachePolicy && typeof requestContext.cachePolicy.type === "string" && supportedCachePolicyTypes.includes(
|
|
3211
|
+
requestContext.cachePolicy.type
|
|
3212
|
+
);
|
|
3213
|
+
}
|
|
3214
|
+
function getOverridesForLegacyRequestContext(requestContext) {
|
|
3215
|
+
if (requestContextIsSupportedCachePolicy(requestContext)) {
|
|
3216
|
+
return { cacheControlConfig: { type: requestContext.cachePolicy.type } };
|
|
3152
3217
|
}
|
|
3153
|
-
|
|
3154
|
-
|
|
3218
|
+
return {};
|
|
3219
|
+
}
|
|
3220
|
+
function handleEmit(res, callback) {
|
|
3221
|
+
const consumerEmittedData = {
|
|
3222
|
+
data: void 0,
|
|
3223
|
+
errors: void 0
|
|
3224
|
+
};
|
|
3225
|
+
if (res.isOk()) {
|
|
3226
|
+
consumerEmittedData.data = res.value.data;
|
|
3227
|
+
} else {
|
|
3228
|
+
const { data, errors } = toGraphQLResponseFromFailure$1(res.error);
|
|
3229
|
+
consumerEmittedData.data = data;
|
|
3230
|
+
consumerEmittedData.errors = errors;
|
|
3155
3231
|
}
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3232
|
+
callback(consumerEmittedData);
|
|
3233
|
+
}
|
|
3234
|
+
function toGraphQLResponseFromFailure$1(failure) {
|
|
3235
|
+
if (isUserVisibleError$1(failure)) {
|
|
3236
|
+
return {
|
|
3237
|
+
data: failure.data.data,
|
|
3238
|
+
errors: failure.data.errors
|
|
3239
|
+
};
|
|
3161
3240
|
}
|
|
3241
|
+
logError$1(failure);
|
|
3242
|
+
return {
|
|
3243
|
+
data: void 0,
|
|
3244
|
+
errors: [{ message: "Internal error in GraphQL adapter occurred", locations: [] }]
|
|
3245
|
+
};
|
|
3162
3246
|
}
|
|
3163
|
-
|
|
3164
|
-
|
|
3247
|
+
class DefaultImperativeBindingsService {
|
|
3248
|
+
bind(getCommand) {
|
|
3249
|
+
return buildBaseImperativeInvoker(getCommand, (result) => {
|
|
3250
|
+
if (result.isOk()) {
|
|
3251
|
+
deepFreeze(result.value);
|
|
3252
|
+
return isSubscribableResult(result) ? result.value.data : result.value;
|
|
3253
|
+
}
|
|
3254
|
+
throw toError(isSubscribableResult(result) ? result.error.failure : result.error);
|
|
3255
|
+
});
|
|
3256
|
+
}
|
|
3165
3257
|
}
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
* @param _extraInfo - Any additional information associated with the JWT.
|
|
3173
|
-
*/
|
|
3174
|
-
constructor(_token, _decodedInfo, _extraInfo) {
|
|
3175
|
-
this._token = _token;
|
|
3176
|
-
this._decodedInfo = _decodedInfo;
|
|
3177
|
-
this._extraInfo = _extraInfo;
|
|
3178
|
-
}
|
|
3179
|
-
/**
|
|
3180
|
-
* Get the JWT string.
|
|
3181
|
-
*
|
|
3182
|
-
* @returns The JWT string.
|
|
3183
|
-
*/
|
|
3184
|
-
get token() {
|
|
3185
|
-
return this._token;
|
|
3186
|
-
}
|
|
3187
|
-
/**
|
|
3188
|
-
* Get the additional information associated with the JWT.
|
|
3189
|
-
*
|
|
3190
|
-
* @returns The additional information.
|
|
3191
|
-
*/
|
|
3192
|
-
get extraInfo() {
|
|
3193
|
-
return this._extraInfo;
|
|
3194
|
-
}
|
|
3195
|
-
/**
|
|
3196
|
-
* Get the decoded information from the JWT.
|
|
3197
|
-
*
|
|
3198
|
-
* @returns The decoded information.
|
|
3199
|
-
*/
|
|
3200
|
-
get decodedInfo() {
|
|
3201
|
-
return this._decodedInfo;
|
|
3202
|
-
}
|
|
3203
|
-
/**
|
|
3204
|
-
* Get the remaining time in seconds until the JWT expires.
|
|
3205
|
-
*
|
|
3206
|
-
* @returns The remaining time in seconds.
|
|
3207
|
-
*/
|
|
3208
|
-
get tokenRemainingSeconds() {
|
|
3209
|
-
return this.decodedInfo.exp - Date.now() / 1e3;
|
|
3210
|
-
}
|
|
3211
|
-
/**
|
|
3212
|
-
* Check if the JWT is expired.
|
|
3213
|
-
*
|
|
3214
|
-
* @returns True if the JWT is expired, false otherwise.
|
|
3215
|
-
*/
|
|
3216
|
-
get isExpired() {
|
|
3217
|
-
return this.tokenRemainingSeconds <= 0;
|
|
3218
|
-
}
|
|
3258
|
+
function buildServiceDescriptor$6() {
|
|
3259
|
+
return {
|
|
3260
|
+
type: "defaultImperativeBindings",
|
|
3261
|
+
version: "1.0",
|
|
3262
|
+
service: new DefaultImperativeBindingsService()
|
|
3263
|
+
};
|
|
3219
3264
|
}
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
error: () => {
|
|
3265
|
+
class QueryImperativeBindingsService {
|
|
3266
|
+
bind(getCommand) {
|
|
3267
|
+
return buildBaseImperativeInvoker(getCommand, (result) => {
|
|
3268
|
+
if (result.isOk()) {
|
|
3269
|
+
deepFreeze(result.value);
|
|
3270
|
+
return isSubscribableResult(result) ? { data: result.value.data } : { data: result.value };
|
|
3271
|
+
}
|
|
3272
|
+
throw toError(isSubscribableResult(result) ? result.error.failure : result.error);
|
|
3273
|
+
});
|
|
3230
3274
|
}
|
|
3231
|
-
};
|
|
3232
|
-
if (process.env.NODE_ENV !== "production") {
|
|
3233
|
-
defaultLogger = loggerService();
|
|
3234
3275
|
}
|
|
3235
|
-
function
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
}
|
|
3241
|
-
return decodedInfo;
|
|
3276
|
+
function buildServiceDescriptor$5() {
|
|
3277
|
+
return {
|
|
3278
|
+
type: "queryImperativeBindings",
|
|
3279
|
+
version: "1.0",
|
|
3280
|
+
service: new QueryImperativeBindingsService()
|
|
3281
|
+
};
|
|
3242
3282
|
}
|
|
3243
|
-
class
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
*/
|
|
3249
|
-
constructor(limitInSeconds = 5, defaultTokenTTLInSeconds = 120, logger = defaultLogger) {
|
|
3250
|
-
this.limitInSeconds = limitInSeconds;
|
|
3251
|
-
this.defaultTokenTTLInSeconds = defaultTokenTTLInSeconds;
|
|
3252
|
-
this.logger = logger;
|
|
3253
|
-
this.observers = [];
|
|
3254
|
-
}
|
|
3255
|
-
/**
|
|
3256
|
-
* Get the current token.
|
|
3257
|
-
*/
|
|
3258
|
-
get token() {
|
|
3259
|
-
return this._token;
|
|
3260
|
-
}
|
|
3261
|
-
/**
|
|
3262
|
-
* Set the current token.
|
|
3263
|
-
*
|
|
3264
|
-
* @param token - JWT token as a string.
|
|
3265
|
-
* @param extraInfo - Optional extra information.
|
|
3266
|
-
*/
|
|
3267
|
-
setToken(token, extraInfo) {
|
|
3268
|
-
const decodedInfo = computeDecodedInfo(
|
|
3269
|
-
token,
|
|
3270
|
-
this.defaultTokenTTLInSeconds,
|
|
3271
|
-
this.logger
|
|
3283
|
+
class SubscribableImperativeBindingsService {
|
|
3284
|
+
bind(getCommand, exposeRefresh = false) {
|
|
3285
|
+
return buildBaseImperativeInvoker(
|
|
3286
|
+
getCommand,
|
|
3287
|
+
(result) => this.transformResult(result, exposeRefresh)
|
|
3272
3288
|
);
|
|
3273
|
-
this._token = new JwtToken(token, decodedInfo, extraInfo);
|
|
3274
|
-
this.observeTokenExpiration();
|
|
3275
|
-
return this._token;
|
|
3276
3289
|
}
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3290
|
+
transformResult(result, exposeRefresh = false) {
|
|
3291
|
+
if (!isSubscribableResult(result)) {
|
|
3292
|
+
console.error(
|
|
3293
|
+
"Non-subscribable result encountered - please use correct operation type"
|
|
3294
|
+
);
|
|
3295
|
+
throw new Error("Internal error in Lightning Data Service adapter occurred");
|
|
3296
|
+
}
|
|
3297
|
+
if (result.isOk()) {
|
|
3298
|
+
deepFreeze(result.value.data);
|
|
3299
|
+
const api = {
|
|
3300
|
+
data: result.value.data,
|
|
3301
|
+
subscribe: (cb) => {
|
|
3302
|
+
result.value.subscribe((result2) => {
|
|
3303
|
+
if (result2.isErr()) {
|
|
3304
|
+
return cb({ data: void 0, error: toError(result2.error) });
|
|
3305
|
+
}
|
|
3306
|
+
return cb({ data: result2.value, error: void 0 });
|
|
3307
|
+
});
|
|
3308
|
+
}
|
|
3309
|
+
};
|
|
3310
|
+
if (exposeRefresh) {
|
|
3311
|
+
return {
|
|
3312
|
+
...api,
|
|
3313
|
+
refresh: () => {
|
|
3314
|
+
return result.value.refresh().then((res) => {
|
|
3315
|
+
if (res.isOk()) {
|
|
3316
|
+
return void 0;
|
|
3317
|
+
}
|
|
3318
|
+
throw res.error;
|
|
3319
|
+
});
|
|
3320
|
+
}
|
|
3321
|
+
};
|
|
3322
|
+
} else {
|
|
3323
|
+
return api;
|
|
3324
|
+
}
|
|
3325
|
+
} else {
|
|
3326
|
+
throw toError(result.error.failure);
|
|
3327
|
+
}
|
|
3283
3328
|
}
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3329
|
+
}
|
|
3330
|
+
function buildServiceDescriptor$4() {
|
|
3331
|
+
return {
|
|
3332
|
+
type: "subscribableImperativeBindings",
|
|
3333
|
+
version: "1.0",
|
|
3334
|
+
service: new SubscribableImperativeBindingsService()
|
|
3335
|
+
};
|
|
3336
|
+
}
|
|
3337
|
+
class LegacyImperativeBindingsService {
|
|
3338
|
+
bind(getCommand) {
|
|
3339
|
+
const invoke = async (config, requestContext, callback) => {
|
|
3340
|
+
const command = getCommand({ config, assertIsValid });
|
|
3341
|
+
try {
|
|
3342
|
+
const overrides = getOverridesForLegacyRequestContext(requestContext);
|
|
3343
|
+
const result = await command.execute(overrides);
|
|
3344
|
+
if (result.isOk()) {
|
|
3345
|
+
deepFreeze(result.value);
|
|
3346
|
+
callback({ data: result.value.data, error: void 0 });
|
|
3347
|
+
} else {
|
|
3348
|
+
callback({ data: void 0, error: toError(result.error.failure) });
|
|
3349
|
+
}
|
|
3350
|
+
} catch (error) {
|
|
3351
|
+
emitError(callback, error);
|
|
3352
|
+
}
|
|
3353
|
+
};
|
|
3354
|
+
const subscribe = (config, requestContext, callback) => {
|
|
3355
|
+
const command = getCommand({ config, assertIsValid });
|
|
3356
|
+
let unsubscribe = () => {
|
|
3357
|
+
};
|
|
3358
|
+
try {
|
|
3359
|
+
const overrides = getOverridesForLegacyRequestContext(requestContext);
|
|
3360
|
+
command.execute(overrides).then(
|
|
3361
|
+
(result) => {
|
|
3362
|
+
if (!result.isOk()) {
|
|
3363
|
+
callback({ data: void 0, error: toError(result.error.failure) });
|
|
3364
|
+
return;
|
|
3365
|
+
}
|
|
3366
|
+
unsubscribe = result.value.subscribe((res) => {
|
|
3367
|
+
if (res.isOk()) {
|
|
3368
|
+
callback({ data: res.value, error: void 0 });
|
|
3369
|
+
} else {
|
|
3370
|
+
callback({ data: void 0, error: toError(res.error) });
|
|
3371
|
+
}
|
|
3372
|
+
});
|
|
3373
|
+
callback({ data: result.value.data, error: void 0 });
|
|
3374
|
+
},
|
|
3375
|
+
(e) => {
|
|
3376
|
+
emitError(callback, e);
|
|
3377
|
+
}
|
|
3378
|
+
);
|
|
3379
|
+
} catch (e) {
|
|
3380
|
+
emitError(callback, e);
|
|
3381
|
+
}
|
|
3382
|
+
return () => {
|
|
3383
|
+
unsubscribe();
|
|
3384
|
+
};
|
|
3294
3385
|
};
|
|
3386
|
+
return { invoke, subscribe };
|
|
3295
3387
|
}
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3388
|
+
}
|
|
3389
|
+
function buildServiceDescriptor$3() {
|
|
3390
|
+
return {
|
|
3391
|
+
type: "legacyImperativeBindings",
|
|
3392
|
+
version: "1.0",
|
|
3393
|
+
service: new LegacyImperativeBindingsService()
|
|
3394
|
+
};
|
|
3395
|
+
}
|
|
3396
|
+
class GraphQLImperativeBindingsService {
|
|
3397
|
+
bind(getCommand, exposeRefresh = false) {
|
|
3398
|
+
return async (...params) => {
|
|
3399
|
+
try {
|
|
3400
|
+
if (params.length) {
|
|
3401
|
+
params[0] = wrapConfigAndVerify(params[0]);
|
|
3402
|
+
}
|
|
3403
|
+
return await buildBaseImperativeInvoker(getCommand, (result) => this.transformResult(result, exposeRefresh))(...params);
|
|
3404
|
+
} catch (error) {
|
|
3405
|
+
logError$1(error);
|
|
3406
|
+
return {
|
|
3407
|
+
data: void 0,
|
|
3408
|
+
errors: [
|
|
3409
|
+
{ message: "Internal error in GraphQL adapter occurred", locations: [] }
|
|
3410
|
+
]
|
|
3411
|
+
};
|
|
3412
|
+
}
|
|
3413
|
+
};
|
|
3303
3414
|
}
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
if (
|
|
3310
|
-
|
|
3415
|
+
transformResult(result, exposeRefresh = false) {
|
|
3416
|
+
const consumerEmittedData = {
|
|
3417
|
+
data: void 0,
|
|
3418
|
+
errors: void 0
|
|
3419
|
+
};
|
|
3420
|
+
if (result.isOk()) {
|
|
3421
|
+
deepFreeze(result.value);
|
|
3422
|
+
consumerEmittedData.data = result.value.data.data;
|
|
3423
|
+
consumerEmittedData.subscribe = (cb) => {
|
|
3424
|
+
result.value.subscribe((res) => {
|
|
3425
|
+
const consumerEmittedData2 = {
|
|
3426
|
+
data: void 0,
|
|
3427
|
+
errors: void 0
|
|
3428
|
+
};
|
|
3429
|
+
if (res.isOk()) {
|
|
3430
|
+
consumerEmittedData2.data = res.value.data;
|
|
3431
|
+
} else {
|
|
3432
|
+
if (isUserVisibleError$1(res.error)) {
|
|
3433
|
+
consumerEmittedData2.data = res.error.data.data;
|
|
3434
|
+
consumerEmittedData2.errors = res.error.data.errors;
|
|
3435
|
+
} else {
|
|
3436
|
+
logError$1(res.error);
|
|
3437
|
+
consumerEmittedData2.errors = [
|
|
3438
|
+
{
|
|
3439
|
+
message: "Internal error in GraphQL adapter occurred",
|
|
3440
|
+
locations: []
|
|
3441
|
+
}
|
|
3442
|
+
];
|
|
3443
|
+
}
|
|
3444
|
+
}
|
|
3445
|
+
cb(consumerEmittedData2);
|
|
3446
|
+
});
|
|
3447
|
+
};
|
|
3448
|
+
if (exposeRefresh) {
|
|
3449
|
+
consumerEmittedData.refresh = () => {
|
|
3450
|
+
return new Promise((resolve, reject) => {
|
|
3451
|
+
try {
|
|
3452
|
+
result.value.refresh().then((res) => {
|
|
3453
|
+
if (res.isOk()) {
|
|
3454
|
+
resolve();
|
|
3455
|
+
} else {
|
|
3456
|
+
reject(
|
|
3457
|
+
new Error(
|
|
3458
|
+
"Internal error in GraphQL adapter occurred: Failed to refresh GraphQL data"
|
|
3459
|
+
)
|
|
3460
|
+
);
|
|
3461
|
+
}
|
|
3462
|
+
});
|
|
3463
|
+
} catch (error) {
|
|
3464
|
+
logError$1(error);
|
|
3465
|
+
reject(
|
|
3466
|
+
new Error(
|
|
3467
|
+
"Internal error in GraphQL adapter occurred: Failed to refresh GraphQL data"
|
|
3468
|
+
)
|
|
3469
|
+
);
|
|
3470
|
+
}
|
|
3471
|
+
});
|
|
3472
|
+
};
|
|
3473
|
+
}
|
|
3474
|
+
} else {
|
|
3475
|
+
const resp = toGraphQLResponseFromFailure$1(result.error.failure);
|
|
3476
|
+
consumerEmittedData.data = resp.data;
|
|
3477
|
+
consumerEmittedData.errors = resp.errors;
|
|
3311
3478
|
}
|
|
3312
|
-
|
|
3313
|
-
() => this.notifyTokenIsExpiring(),
|
|
3314
|
-
this.computeTimeoutTimeInMs()
|
|
3315
|
-
);
|
|
3316
|
-
}
|
|
3317
|
-
/**
|
|
3318
|
-
* Compute the timeout time in milliseconds.
|
|
3319
|
-
*/
|
|
3320
|
-
computeTimeoutTimeInMs() {
|
|
3321
|
-
const remainingSeconds = this.token.tokenRemainingSeconds;
|
|
3322
|
-
let timeoutTimeInSeconds = remainingSeconds - this.limitInSeconds;
|
|
3323
|
-
return timeoutTimeInSeconds < 0 ? 0 : timeoutTimeInSeconds * 1e3;
|
|
3479
|
+
return consumerEmittedData;
|
|
3324
3480
|
}
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3481
|
+
}
|
|
3482
|
+
function buildServiceDescriptor$2$1() {
|
|
3483
|
+
return {
|
|
3484
|
+
type: "graphQLImperativeBindings",
|
|
3485
|
+
version: "1.0",
|
|
3486
|
+
service: new GraphQLImperativeBindingsService()
|
|
3487
|
+
};
|
|
3488
|
+
}
|
|
3489
|
+
class GraphQLLegacyImperativeBindingsService {
|
|
3490
|
+
bind(getCommand) {
|
|
3491
|
+
const invoke = async (config, requestContext, callback) => {
|
|
3492
|
+
config = wrapConfigAndVerify(config);
|
|
3493
|
+
const command = getCommand({ config, assertIsValid });
|
|
3330
3494
|
try {
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3495
|
+
const overrides = getOverridesForLegacyRequestContext(requestContext);
|
|
3496
|
+
const result = await command.execute(overrides);
|
|
3497
|
+
const consumerEmittedData = {
|
|
3498
|
+
data: void 0,
|
|
3499
|
+
errors: void 0
|
|
3500
|
+
};
|
|
3501
|
+
if (result.isOk()) {
|
|
3502
|
+
deepFreeze(result.value);
|
|
3503
|
+
consumerEmittedData.data = result.value.data.data;
|
|
3504
|
+
} else {
|
|
3505
|
+
const { data, errors } = toGraphQLResponseFromFailure$1(result.error.failure);
|
|
3506
|
+
consumerEmittedData.data = data;
|
|
3507
|
+
consumerEmittedData.errors = errors;
|
|
3508
|
+
}
|
|
3509
|
+
callback(consumerEmittedData);
|
|
3510
|
+
} catch (error) {
|
|
3511
|
+
logError$1(error);
|
|
3512
|
+
callback({
|
|
3513
|
+
data: void 0,
|
|
3514
|
+
errors: [
|
|
3515
|
+
{ message: "Internal error in GraphQL adapter occurred", locations: [] }
|
|
3516
|
+
]
|
|
3517
|
+
});
|
|
3334
3518
|
}
|
|
3335
|
-
}
|
|
3519
|
+
};
|
|
3520
|
+
const subscribe = (config, requestContext, callback) => {
|
|
3521
|
+
config = wrapConfigAndVerify(config);
|
|
3522
|
+
const command = getCommand({ config, assertIsValid });
|
|
3523
|
+
let unsubscribe = () => {
|
|
3524
|
+
};
|
|
3525
|
+
const overrides = getOverridesForLegacyRequestContext(requestContext);
|
|
3526
|
+
command.execute(overrides).then((result) => {
|
|
3527
|
+
const consumerEmittedData = {
|
|
3528
|
+
data: void 0,
|
|
3529
|
+
errors: void 0
|
|
3530
|
+
};
|
|
3531
|
+
if (result.isOk()) {
|
|
3532
|
+
deepFreeze(result.value);
|
|
3533
|
+
consumerEmittedData.data = result.value.data.data;
|
|
3534
|
+
unsubscribe = result.value.subscribe(
|
|
3535
|
+
(res) => {
|
|
3536
|
+
handleEmit(res, callback);
|
|
3537
|
+
}
|
|
3538
|
+
);
|
|
3539
|
+
} else {
|
|
3540
|
+
const { data, errors } = toGraphQLResponseFromFailure$1(result.error.failure);
|
|
3541
|
+
consumerEmittedData.data = data;
|
|
3542
|
+
consumerEmittedData.errors = errors;
|
|
3543
|
+
unsubscribe = result.error.subscribe(
|
|
3544
|
+
(res) => {
|
|
3545
|
+
handleEmit(res, callback);
|
|
3546
|
+
}
|
|
3547
|
+
);
|
|
3548
|
+
}
|
|
3549
|
+
callback(consumerEmittedData);
|
|
3550
|
+
});
|
|
3551
|
+
return () => {
|
|
3552
|
+
unsubscribe();
|
|
3553
|
+
};
|
|
3554
|
+
};
|
|
3555
|
+
return { invoke, subscribe };
|
|
3336
3556
|
}
|
|
3337
3557
|
}
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
* Method to refresh a JWT token.
|
|
3373
|
-
* If a refresh request is already in progress, it will return the Promise of this request.
|
|
3374
|
-
* Otherwise, it will start a new refresh request and return its Promise.
|
|
3375
|
-
*
|
|
3376
|
-
* @returns {Promise<JwtToken<T, ExtraInfo>>} Promise of the refreshed token.
|
|
3377
|
-
*/
|
|
3378
|
-
refreshToken() {
|
|
3379
|
-
if (this.inflightPromise === void 0) {
|
|
3380
|
-
this.inflightPromise = new Promise((resolve, reject) => {
|
|
3381
|
-
this.resolver.getJwt().then(({ jwt, extraInfo }) => {
|
|
3382
|
-
this.inflightPromise = void 0;
|
|
3383
|
-
const token = this.jwtRepository.setToken(jwt, extraInfo);
|
|
3384
|
-
resolve(token);
|
|
3385
|
-
}).catch((reason) => {
|
|
3386
|
-
this.inflightPromise = void 0;
|
|
3387
|
-
reject(reason);
|
|
3388
|
-
});
|
|
3389
|
-
});
|
|
3390
|
-
}
|
|
3391
|
-
return this.inflightPromise;
|
|
3392
|
-
}
|
|
3393
|
-
/**
|
|
3394
|
-
* Method to check if a token refresh is in progress.
|
|
3395
|
-
*
|
|
3396
|
-
* @returns {boolean} true if a token refresh is in progress, false otherwise.
|
|
3397
|
-
*/
|
|
3398
|
-
get isRefreshingToken() {
|
|
3399
|
-
return this.inflightPromise !== void 0;
|
|
3558
|
+
function buildServiceDescriptor$1$1() {
|
|
3559
|
+
return {
|
|
3560
|
+
type: "graphQLLegacyImperativeBindings",
|
|
3561
|
+
version: "1.0",
|
|
3562
|
+
service: new GraphQLLegacyImperativeBindingsService()
|
|
3563
|
+
};
|
|
3564
|
+
}
|
|
3565
|
+
class GraphQLMutationBindingsService {
|
|
3566
|
+
bind(getCommand) {
|
|
3567
|
+
return async (...params) => {
|
|
3568
|
+
try {
|
|
3569
|
+
if (params.length) {
|
|
3570
|
+
params[0] = wrapConfigAndVerify(params[0], {
|
|
3571
|
+
acceptedOperations: ["mutation"]
|
|
3572
|
+
});
|
|
3573
|
+
}
|
|
3574
|
+
const command = getCommand({ params, assertIsValid });
|
|
3575
|
+
const result = await command.execute({ cacheControlConfig: { type: "no-cache" } });
|
|
3576
|
+
if (result.isOk()) {
|
|
3577
|
+
deepFreeze(result.value);
|
|
3578
|
+
return result.value.data;
|
|
3579
|
+
} else {
|
|
3580
|
+
return toGraphQLResponseFromFailure$1(result.error.failure);
|
|
3581
|
+
}
|
|
3582
|
+
} catch (error) {
|
|
3583
|
+
logError$1(error);
|
|
3584
|
+
return {
|
|
3585
|
+
data: void 0,
|
|
3586
|
+
errors: [
|
|
3587
|
+
{ message: "Internal error in GraphQL adapter occurred", locations: [] }
|
|
3588
|
+
]
|
|
3589
|
+
};
|
|
3590
|
+
}
|
|
3591
|
+
};
|
|
3400
3592
|
}
|
|
3401
3593
|
}
|
|
3594
|
+
function buildServiceDescriptor$7() {
|
|
3595
|
+
return {
|
|
3596
|
+
type: "graphQLMutationBindings",
|
|
3597
|
+
version: "1.0",
|
|
3598
|
+
service: new GraphQLMutationBindingsService()
|
|
3599
|
+
};
|
|
3600
|
+
}
|
|
3402
3601
|
|
|
3403
3602
|
/*!
|
|
3404
3603
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
3405
3604
|
* All rights reserved.
|
|
3406
3605
|
* For full license text, see the LICENSE.txt file
|
|
3407
3606
|
*/
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3607
|
+
class Sanitizer {
|
|
3608
|
+
constructor(obj) {
|
|
3609
|
+
this.obj = obj;
|
|
3610
|
+
this.copy = {};
|
|
3611
|
+
this.currentPath = {
|
|
3612
|
+
key: "",
|
|
3613
|
+
value: obj,
|
|
3614
|
+
parent: null,
|
|
3615
|
+
data: this.copy
|
|
3616
|
+
};
|
|
3617
|
+
}
|
|
3618
|
+
sanitize() {
|
|
3619
|
+
const sanitizer = this;
|
|
3620
|
+
JSON.stringify(this.obj, function(key, value) {
|
|
3621
|
+
if (key === "") {
|
|
3622
|
+
return value;
|
|
3623
|
+
}
|
|
3624
|
+
const parent = this;
|
|
3625
|
+
if (parent !== sanitizer.currentPath.value) {
|
|
3626
|
+
sanitizer.exit(parent);
|
|
3627
|
+
}
|
|
3628
|
+
if (typeof value === "object" && value !== null) {
|
|
3629
|
+
sanitizer.enter(key, value);
|
|
3630
|
+
return value;
|
|
3631
|
+
}
|
|
3632
|
+
sanitizer.currentPath.data[key] = value;
|
|
3633
|
+
return value;
|
|
3634
|
+
});
|
|
3635
|
+
return this.copy;
|
|
3636
|
+
}
|
|
3637
|
+
enter(key, value) {
|
|
3638
|
+
const { currentPath: parentPath } = this;
|
|
3639
|
+
const data = parentPath.data[key] = Array.isArray(value) ? [] : {};
|
|
3640
|
+
this.currentPath = {
|
|
3641
|
+
key,
|
|
3642
|
+
value,
|
|
3643
|
+
parent: parentPath,
|
|
3644
|
+
data
|
|
3645
|
+
};
|
|
3646
|
+
}
|
|
3647
|
+
exit(parent) {
|
|
3648
|
+
while (this.currentPath.value !== parent) {
|
|
3649
|
+
this.currentPath = this.currentPath.parent || this.currentPath;
|
|
3416
3650
|
}
|
|
3417
|
-
resource.headers.set(headerName, headerValue);
|
|
3418
|
-
hasHeaderBeenSet = true;
|
|
3419
3651
|
}
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3652
|
+
}
|
|
3653
|
+
function sanitize(obj) {
|
|
3654
|
+
return new Sanitizer(obj).sanitize();
|
|
3655
|
+
}
|
|
3656
|
+
function isIncompleteConfigError(err) {
|
|
3657
|
+
return err instanceof MissingRequiredPropertyError || err instanceof JsonSchemaViolationError && err.validationErrors.find(
|
|
3658
|
+
(validationError) => validationError instanceof MissingRequiredPropertyError
|
|
3659
|
+
) !== void 0;
|
|
3660
|
+
}
|
|
3661
|
+
class CommandWireAdapterConstructor {
|
|
3662
|
+
constructor(callback, sourceContext, options) {
|
|
3663
|
+
this.callback = callback;
|
|
3664
|
+
this.connected = false;
|
|
3665
|
+
this.exposeRefresh = false;
|
|
3666
|
+
if (!(options == null ? void 0 : options.skipEmptyEmit)) {
|
|
3667
|
+
this.emit();
|
|
3423
3668
|
}
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3669
|
+
}
|
|
3670
|
+
connect() {
|
|
3671
|
+
this.connected = true;
|
|
3672
|
+
this.invokeAdapter();
|
|
3673
|
+
}
|
|
3674
|
+
disconnect() {
|
|
3675
|
+
this.unsubscribe();
|
|
3676
|
+
this.connected = false;
|
|
3677
|
+
}
|
|
3678
|
+
update(config, _context) {
|
|
3679
|
+
this.unsubscribe();
|
|
3680
|
+
this.config = sanitize(config);
|
|
3681
|
+
this.invokeAdapter();
|
|
3682
|
+
}
|
|
3683
|
+
emit(result) {
|
|
3684
|
+
try {
|
|
3685
|
+
if (result === void 0) {
|
|
3686
|
+
this.callback({ data: void 0, error: void 0 });
|
|
3687
|
+
} else {
|
|
3688
|
+
const consumerEmittedRefresh = () => {
|
|
3689
|
+
if (!this.refresh) {
|
|
3690
|
+
return Promise.resolve();
|
|
3691
|
+
}
|
|
3692
|
+
return new Promise((resolve, reject) => {
|
|
3693
|
+
if (!this.refresh) {
|
|
3694
|
+
resolve();
|
|
3695
|
+
return;
|
|
3696
|
+
}
|
|
3697
|
+
this.refresh().then((res) => {
|
|
3698
|
+
if (res.isOk()) {
|
|
3699
|
+
resolve();
|
|
3700
|
+
} else {
|
|
3701
|
+
reject(
|
|
3702
|
+
new Error(
|
|
3703
|
+
"Internal error in Lightning Data Service adapter occurred: Failed to refresh data"
|
|
3704
|
+
)
|
|
3705
|
+
);
|
|
3706
|
+
}
|
|
3707
|
+
});
|
|
3708
|
+
});
|
|
3709
|
+
};
|
|
3710
|
+
let consumerEmittedData = {
|
|
3711
|
+
data: void 0,
|
|
3712
|
+
error: void 0
|
|
3713
|
+
};
|
|
3714
|
+
if (this.exposeRefresh && this.refresh) {
|
|
3715
|
+
consumerEmittedData.refresh = consumerEmittedRefresh;
|
|
3716
|
+
}
|
|
3717
|
+
if (result.isErr()) {
|
|
3718
|
+
if (isSubscribableResult(result)) {
|
|
3719
|
+
consumerEmittedData.error = result.error.failure;
|
|
3720
|
+
} else {
|
|
3721
|
+
consumerEmittedData.error = result.error;
|
|
3722
|
+
}
|
|
3723
|
+
} else {
|
|
3724
|
+
if (isSubscribableResult(result)) {
|
|
3725
|
+
deepFreeze(result.value.data);
|
|
3726
|
+
consumerEmittedData.data = result.value.data;
|
|
3727
|
+
} else {
|
|
3728
|
+
deepFreeze(result.value);
|
|
3729
|
+
consumerEmittedData.data = result.value;
|
|
3730
|
+
}
|
|
3731
|
+
}
|
|
3732
|
+
this.callback(consumerEmittedData);
|
|
3733
|
+
}
|
|
3734
|
+
} catch (e) {
|
|
3735
|
+
this.handleExecutionThrow(e);
|
|
3428
3736
|
}
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3737
|
+
}
|
|
3738
|
+
invokeAdapter() {
|
|
3739
|
+
if (!this.connected || this.config === void 0) {
|
|
3740
|
+
return;
|
|
3741
|
+
}
|
|
3742
|
+
if (this.configSchema) {
|
|
3743
|
+
try {
|
|
3744
|
+
assertIsValid(this.config, this.configSchema);
|
|
3745
|
+
} catch (err) {
|
|
3746
|
+
if (isIncompleteConfigError(err)) {
|
|
3747
|
+
return;
|
|
3748
|
+
}
|
|
3749
|
+
throw err;
|
|
3750
|
+
}
|
|
3751
|
+
}
|
|
3752
|
+
const initialConfig = this.config;
|
|
3753
|
+
const command = this.getCommand();
|
|
3754
|
+
try {
|
|
3755
|
+
command.execute().then((result) => {
|
|
3756
|
+
if (!this.connected || this.config !== initialConfig) {
|
|
3757
|
+
return;
|
|
3758
|
+
}
|
|
3759
|
+
this.refresh = void 0;
|
|
3760
|
+
if (result.isOk()) {
|
|
3761
|
+
if (isSubscribableResult(result)) {
|
|
3762
|
+
const value = result.value;
|
|
3763
|
+
this.unsubscriber = value.subscribe((updatedResult) => {
|
|
3764
|
+
if (!this.connected || this.config !== initialConfig) {
|
|
3765
|
+
this.unsubscribe();
|
|
3766
|
+
return;
|
|
3767
|
+
}
|
|
3768
|
+
this.emit(updatedResult);
|
|
3769
|
+
});
|
|
3770
|
+
this.refresh = value.refresh;
|
|
3771
|
+
this.emit(ok$2(value.data));
|
|
3772
|
+
} else {
|
|
3773
|
+
this.emit(result);
|
|
3774
|
+
}
|
|
3775
|
+
} else {
|
|
3776
|
+
if (isSubscribableResult(result)) {
|
|
3777
|
+
const value = result.error;
|
|
3778
|
+
this.unsubscriber = value.subscribe((updatedResult) => {
|
|
3779
|
+
if (!this.connected || this.config !== initialConfig) {
|
|
3780
|
+
this.unsubscribe();
|
|
3781
|
+
return;
|
|
3782
|
+
}
|
|
3783
|
+
this.emit(updatedResult);
|
|
3784
|
+
});
|
|
3785
|
+
this.refresh = value.refresh;
|
|
3786
|
+
this.emit(result);
|
|
3787
|
+
} else {
|
|
3788
|
+
this.unsubscriber = () => {
|
|
3789
|
+
};
|
|
3790
|
+
this.emit(result);
|
|
3791
|
+
}
|
|
3792
|
+
}
|
|
3793
|
+
});
|
|
3794
|
+
} catch (e) {
|
|
3795
|
+
this.handleExecutionThrow(e);
|
|
3796
|
+
}
|
|
3797
|
+
}
|
|
3798
|
+
handleExecutionThrow(error) {
|
|
3799
|
+
emitError(this.callback, error);
|
|
3800
|
+
}
|
|
3801
|
+
unsubscribe() {
|
|
3802
|
+
if (this.unsubscriber) {
|
|
3803
|
+
this.unsubscriber();
|
|
3804
|
+
delete this.unsubscriber;
|
|
3434
3805
|
}
|
|
3435
3806
|
}
|
|
3436
|
-
return [resource, options];
|
|
3437
3807
|
}
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
}
|
|
3808
|
+
function toGraphQLResponseFromFailure(failure) {
|
|
3809
|
+
if (isUserVisibleError$1(failure)) {
|
|
3810
|
+
return {
|
|
3811
|
+
data: failure.data.data,
|
|
3812
|
+
errors: failure.data.errors
|
|
3813
|
+
};
|
|
3814
|
+
}
|
|
3815
|
+
logError$1(failure);
|
|
3816
|
+
return {
|
|
3817
|
+
data: void 0,
|
|
3818
|
+
errors: [{ message: "Internal error in GraphQL adapter occurred", locations: [] }]
|
|
3819
|
+
};
|
|
3445
3820
|
}
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
return
|
|
3449
|
-
|
|
3450
|
-
|
|
3821
|
+
class LWCWireBindingsService {
|
|
3822
|
+
bind(getCommand, configSchema, exposeRefresh = false) {
|
|
3823
|
+
return class extends CommandWireAdapterConstructor {
|
|
3824
|
+
constructor() {
|
|
3825
|
+
super(...arguments);
|
|
3826
|
+
this.configSchema = configSchema;
|
|
3827
|
+
this.exposeRefresh = exposeRefresh;
|
|
3828
|
+
}
|
|
3829
|
+
getCommand() {
|
|
3830
|
+
return getCommand(this.config);
|
|
3831
|
+
}
|
|
3832
|
+
};
|
|
3833
|
+
}
|
|
3834
|
+
}
|
|
3835
|
+
function buildServiceDescriptor$1() {
|
|
3836
|
+
return {
|
|
3837
|
+
type: "lwcWireBindings",
|
|
3838
|
+
version: "1.0",
|
|
3839
|
+
service: new LWCWireBindingsService()
|
|
3840
|
+
};
|
|
3841
|
+
}
|
|
3842
|
+
class GraphQLCommandWireAdapterConstructor extends CommandWireAdapterConstructor {
|
|
3843
|
+
emit(result) {
|
|
3844
|
+
try {
|
|
3845
|
+
if (result === void 0) {
|
|
3846
|
+
this.callback({ data: void 0, errors: void 0 });
|
|
3847
|
+
} else {
|
|
3848
|
+
const consumerEmittedRefresh = () => {
|
|
3849
|
+
if (!this.refresh) {
|
|
3850
|
+
return Promise.resolve();
|
|
3851
|
+
}
|
|
3852
|
+
return new Promise((resolve, reject) => {
|
|
3853
|
+
if (!this.refresh) {
|
|
3854
|
+
resolve();
|
|
3855
|
+
return;
|
|
3856
|
+
}
|
|
3857
|
+
this.refresh().then((res) => {
|
|
3858
|
+
if (res.isOk()) {
|
|
3859
|
+
resolve();
|
|
3860
|
+
} else {
|
|
3861
|
+
reject(
|
|
3862
|
+
new Error(
|
|
3863
|
+
"Internal error in GraphQL adapter occurred: Failed to refresh GraphQL data"
|
|
3864
|
+
)
|
|
3865
|
+
);
|
|
3866
|
+
}
|
|
3867
|
+
});
|
|
3868
|
+
});
|
|
3869
|
+
};
|
|
3870
|
+
let consumerEmittedData = {
|
|
3871
|
+
data: void 0,
|
|
3872
|
+
errors: void 0
|
|
3873
|
+
};
|
|
3874
|
+
if (this.exposeRefresh && this.refresh) {
|
|
3875
|
+
consumerEmittedData.refresh = consumerEmittedRefresh;
|
|
3876
|
+
}
|
|
3877
|
+
if (result.isErr()) {
|
|
3878
|
+
const failure = isSubscribableResult(result) ? result.error.failure : result.error;
|
|
3879
|
+
const resp = toGraphQLResponseFromFailure(failure);
|
|
3880
|
+
consumerEmittedData.data = resp.data;
|
|
3881
|
+
consumerEmittedData.errors = resp.errors;
|
|
3882
|
+
} else {
|
|
3883
|
+
consumerEmittedData.data = result.value.data;
|
|
3884
|
+
}
|
|
3885
|
+
deepFreeze(consumerEmittedData);
|
|
3886
|
+
this.callback(consumerEmittedData);
|
|
3887
|
+
}
|
|
3888
|
+
} catch (e) {
|
|
3889
|
+
logError$1(e);
|
|
3890
|
+
this.handleExecutionThrow(e);
|
|
3891
|
+
}
|
|
3892
|
+
}
|
|
3893
|
+
handleExecutionThrow(e) {
|
|
3894
|
+
logError$1(e);
|
|
3895
|
+
this.callback({
|
|
3896
|
+
data: void 0,
|
|
3897
|
+
errors: [{ message: "Internal error in GraphQL adapter occurred", locations: [] }]
|
|
3451
3898
|
});
|
|
3899
|
+
}
|
|
3900
|
+
update(config, _context) {
|
|
3901
|
+
this.unsubscribe();
|
|
3902
|
+
const resolvedQuery = resolveAst(config.query);
|
|
3903
|
+
if (resolvedQuery) {
|
|
3904
|
+
validateGraphQLOperations(
|
|
3905
|
+
{ query: resolvedQuery, operationName: config == null ? void 0 : config.operationName },
|
|
3906
|
+
{ acceptedOperations: ["query"] }
|
|
3907
|
+
);
|
|
3908
|
+
}
|
|
3909
|
+
this.config = {
|
|
3910
|
+
...sanitize(config),
|
|
3911
|
+
query: resolvedQuery
|
|
3912
|
+
};
|
|
3913
|
+
this.invokeAdapter();
|
|
3914
|
+
}
|
|
3915
|
+
}
|
|
3916
|
+
class LWCGraphQLWireBindingsService {
|
|
3917
|
+
bind(getCommand, configSchema, exposeRefresh = false) {
|
|
3918
|
+
return class extends GraphQLCommandWireAdapterConstructor {
|
|
3919
|
+
constructor() {
|
|
3920
|
+
super(...arguments);
|
|
3921
|
+
this.configSchema = configSchema;
|
|
3922
|
+
this.exposeRefresh = exposeRefresh;
|
|
3923
|
+
}
|
|
3924
|
+
getCommand() {
|
|
3925
|
+
return getCommand(this.config);
|
|
3926
|
+
}
|
|
3927
|
+
};
|
|
3928
|
+
}
|
|
3929
|
+
}
|
|
3930
|
+
function buildServiceDescriptor$2() {
|
|
3931
|
+
return {
|
|
3932
|
+
type: "lwcGraphQLWireBindings",
|
|
3933
|
+
version: "1.0",
|
|
3934
|
+
service: new LWCGraphQLWireBindingsService()
|
|
3452
3935
|
};
|
|
3453
3936
|
}
|
|
3454
3937
|
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3938
|
+
function createLockerCompatibleWireConstructor(DelegateCtor) {
|
|
3939
|
+
function Constructor(callback, sourceContext, options) {
|
|
3940
|
+
const delegate = new DelegateCtor(callback, sourceContext, options);
|
|
3941
|
+
this.connect = () => delegate.connect();
|
|
3942
|
+
this.disconnect = () => delegate.disconnect();
|
|
3943
|
+
this.update = (config, context) => delegate.update(config, context);
|
|
3944
|
+
}
|
|
3945
|
+
return Constructor;
|
|
3946
|
+
}
|
|
3947
|
+
function buildLWCWireBindingsServiceDescriptor() {
|
|
3948
|
+
const base = buildServiceDescriptor$1();
|
|
3949
|
+
const originalBind = base.service.bind.bind(base.service);
|
|
3950
|
+
const bind = (...args) => {
|
|
3951
|
+
const ctor = originalBind(...args);
|
|
3952
|
+
return createLockerCompatibleWireConstructor(ctor);
|
|
3953
|
+
};
|
|
3954
|
+
return {
|
|
3955
|
+
...base,
|
|
3956
|
+
service: {
|
|
3957
|
+
...base.service,
|
|
3958
|
+
bind,
|
|
3959
|
+
},
|
|
3960
|
+
};
|
|
3961
|
+
}
|
|
3962
|
+
function buildLWCGraphQLWireBindingsServiceDescriptor() {
|
|
3963
|
+
const base = buildServiceDescriptor$2();
|
|
3964
|
+
const originalBind = base.service.bind.bind(base.service);
|
|
3965
|
+
const bind = (...args) => {
|
|
3966
|
+
const ctor = originalBind(...args);
|
|
3967
|
+
return createLockerCompatibleWireConstructor(ctor);
|
|
3968
|
+
};
|
|
3969
|
+
return {
|
|
3970
|
+
...base,
|
|
3971
|
+
service: {
|
|
3972
|
+
...base.service,
|
|
3973
|
+
bind,
|
|
3974
|
+
},
|
|
3975
|
+
};
|
|
3976
|
+
}
|
|
3466
3977
|
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
var StoreRecordType;
|
|
3472
|
-
(function (StoreRecordType) {
|
|
3473
|
-
StoreRecordType["Error"] = "error";
|
|
3474
|
-
})(StoreRecordType || (StoreRecordType = {}));
|
|
3475
|
-
var StoreLinkStateValues$1;
|
|
3476
|
-
(function (StoreLinkStateValues) {
|
|
3477
|
-
StoreLinkStateValues[StoreLinkStateValues["NotPresent"] = 0] = "NotPresent";
|
|
3478
|
-
StoreLinkStateValues[StoreLinkStateValues["RefNotPresent"] = 1] = "RefNotPresent";
|
|
3479
|
-
StoreLinkStateValues[StoreLinkStateValues["RefPresent"] = 2] = "RefPresent";
|
|
3480
|
-
StoreLinkStateValues[StoreLinkStateValues["Null"] = 3] = "Null";
|
|
3481
|
-
StoreLinkStateValues[StoreLinkStateValues["Missing"] = 4] = "Missing";
|
|
3482
|
-
StoreLinkStateValues[StoreLinkStateValues["Pending"] = 5] = "Pending";
|
|
3483
|
-
})(StoreLinkStateValues$1 || (StoreLinkStateValues$1 = {}));
|
|
3484
|
-
var StoreResolveResultState;
|
|
3485
|
-
(function (StoreResolveResultState) {
|
|
3486
|
-
StoreResolveResultState[StoreResolveResultState["Found"] = 0] = "Found";
|
|
3487
|
-
StoreResolveResultState[StoreResolveResultState["Error"] = 1] = "Error";
|
|
3488
|
-
StoreResolveResultState[StoreResolveResultState["Null"] = 2] = "Null";
|
|
3489
|
-
StoreResolveResultState[StoreResolveResultState["NotPresent"] = 3] = "NotPresent";
|
|
3490
|
-
StoreResolveResultState[StoreResolveResultState["Stale"] = 4] = "Stale";
|
|
3491
|
-
})(StoreResolveResultState || (StoreResolveResultState = {}));
|
|
3492
|
-
var HttpStatusCode;
|
|
3493
|
-
(function (HttpStatusCode) {
|
|
3494
|
-
HttpStatusCode[HttpStatusCode["Ok"] = 200] = "Ok";
|
|
3495
|
-
HttpStatusCode[HttpStatusCode["Created"] = 201] = "Created";
|
|
3496
|
-
HttpStatusCode[HttpStatusCode["NoContent"] = 204] = "NoContent";
|
|
3497
|
-
HttpStatusCode[HttpStatusCode["NotModified"] = 304] = "NotModified";
|
|
3498
|
-
HttpStatusCode[HttpStatusCode["BadRequest"] = 400] = "BadRequest";
|
|
3499
|
-
HttpStatusCode[HttpStatusCode["Unauthorized"] = 401] = "Unauthorized";
|
|
3500
|
-
HttpStatusCode[HttpStatusCode["Forbidden"] = 403] = "Forbidden";
|
|
3501
|
-
HttpStatusCode[HttpStatusCode["NotFound"] = 404] = "NotFound";
|
|
3502
|
-
HttpStatusCode[HttpStatusCode["ServerError"] = 500] = "ServerError";
|
|
3503
|
-
HttpStatusCode[HttpStatusCode["GatewayTimeout"] = 504] = "GatewayTimeout";
|
|
3504
|
-
})(HttpStatusCode || (HttpStatusCode = {}));
|
|
3505
|
-
/**
|
|
3506
|
-
* A type guard function for determining if an unknown object is a {@link FormData}
|
|
3507
|
-
*/
|
|
3508
|
-
function isFormData(obj) {
|
|
3509
|
-
return (typeof obj === 'object' &&
|
|
3510
|
-
obj !== null &&
|
|
3511
|
-
'namedEntries' in obj &&
|
|
3512
|
-
isArray$1(obj.namedEntries));
|
|
3513
|
-
}
|
|
3514
|
-
/**
|
|
3515
|
-
* A type guard function for determining if an unknown object is a {@link FileReference}
|
|
3978
|
+
/*!
|
|
3979
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
3980
|
+
* All rights reserved.
|
|
3981
|
+
* For full license text, see the LICENSE.txt file
|
|
3516
3982
|
*/
|
|
3517
|
-
function
|
|
3518
|
-
|
|
3519
|
-
entryValue !== null &&
|
|
3520
|
-
'isFileReference' in entryValue &&
|
|
3521
|
-
entryValue.isFileReference === true);
|
|
3983
|
+
function e$1(e2) {
|
|
3984
|
+
this.message = e2;
|
|
3522
3985
|
}
|
|
3523
|
-
|
|
3524
|
-
(function
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
})(GraphNodeType || (GraphNodeType = {}));
|
|
3530
|
-
|
|
3531
|
-
var StoreLinkStateValues;
|
|
3532
|
-
(function (StoreLinkStateValues) {
|
|
3533
|
-
StoreLinkStateValues[StoreLinkStateValues["NotPresent"] = 0] = "NotPresent";
|
|
3534
|
-
StoreLinkStateValues[StoreLinkStateValues["RefNotPresent"] = 1] = "RefNotPresent";
|
|
3535
|
-
StoreLinkStateValues[StoreLinkStateValues["RefPresent"] = 2] = "RefPresent";
|
|
3536
|
-
StoreLinkStateValues[StoreLinkStateValues["Null"] = 3] = "Null";
|
|
3537
|
-
StoreLinkStateValues[StoreLinkStateValues["Missing"] = 4] = "Missing";
|
|
3538
|
-
StoreLinkStateValues[StoreLinkStateValues["Pending"] = 5] = "Pending";
|
|
3539
|
-
})(StoreLinkStateValues || (StoreLinkStateValues = {}));
|
|
3540
|
-
var FragmentReadResultState;
|
|
3541
|
-
(function (FragmentReadResultState) {
|
|
3542
|
-
FragmentReadResultState[FragmentReadResultState["Missing"] = 0] = "Missing";
|
|
3543
|
-
FragmentReadResultState[FragmentReadResultState["Success"] = 1] = "Success";
|
|
3544
|
-
FragmentReadResultState[FragmentReadResultState["Error"] = 2] = "Error";
|
|
3545
|
-
})(FragmentReadResultState || (FragmentReadResultState = {}));
|
|
3546
|
-
({
|
|
3547
|
-
state: FragmentReadResultState.Missing,
|
|
3548
|
-
});
|
|
3549
|
-
|
|
3550
|
-
var ResourceParamType;
|
|
3551
|
-
(function (ResourceParamType) {
|
|
3552
|
-
ResourceParamType[ResourceParamType["UrlParameter"] = 0] = "UrlParameter";
|
|
3553
|
-
ResourceParamType[ResourceParamType["QueryParameter"] = 1] = "QueryParameter";
|
|
3554
|
-
ResourceParamType[ResourceParamType["Body"] = 2] = "Body";
|
|
3555
|
-
ResourceParamType[ResourceParamType["Header"] = 3] = "Header";
|
|
3556
|
-
})(ResourceParamType || (ResourceParamType = {}));
|
|
3557
|
-
var TypeCheckShapes;
|
|
3558
|
-
(function (TypeCheckShapes) {
|
|
3559
|
-
TypeCheckShapes[TypeCheckShapes["String"] = 0] = "String";
|
|
3560
|
-
TypeCheckShapes[TypeCheckShapes["Boolean"] = 1] = "Boolean";
|
|
3561
|
-
TypeCheckShapes[TypeCheckShapes["Number"] = 2] = "Number";
|
|
3562
|
-
TypeCheckShapes[TypeCheckShapes["Integer"] = 3] = "Integer";
|
|
3563
|
-
TypeCheckShapes[TypeCheckShapes["Unsupported"] = 4] = "Unsupported";
|
|
3564
|
-
})(TypeCheckShapes || (TypeCheckShapes = {}));
|
|
3565
|
-
// engine version: 0.158.7-bafe2646
|
|
3566
|
-
|
|
3567
|
-
const { keys: keys$1 } = Object;
|
|
3568
|
-
|
|
3569
|
-
// we're going to intentionally bundle this small bit of luvio engine code into
|
|
3570
|
-
// this module to keep it runtime dependency-free
|
|
3571
|
-
const fetchNetworkAdapter = async (resourceRequest, _resourceRequestContext) => {
|
|
3572
|
-
const { baseUri, basePath, body: requestBody, queryParams, method, headers } = resourceRequest;
|
|
3573
|
-
const qs = generateQueryString(queryParams);
|
|
3574
|
-
const path = `${baseUri}${basePath}${qs}`;
|
|
3575
|
-
let body;
|
|
3576
|
-
// some endpoints use FormData for POST request body, check here
|
|
3577
|
-
// if we have a POST body that is FormData
|
|
3578
|
-
if (method === 'post' && isFormData(requestBody)) {
|
|
3579
|
-
// we will populate a DOM FormData and pass that to fetch
|
|
3580
|
-
const newForm = new FormData();
|
|
3581
|
-
for (const { name, value } of requestBody.namedEntries) {
|
|
3582
|
-
// if this is a string or real DOM File then we can
|
|
3583
|
-
// just add it to FormData
|
|
3584
|
-
if (typeof value === 'string' || value instanceof File) {
|
|
3585
|
-
newForm.append(name, value);
|
|
3586
|
-
}
|
|
3587
|
-
// this network adapter doesn't currently support FileReference's
|
|
3588
|
-
else if (isFileReference(value)) {
|
|
3589
|
-
throw Error(`Luvio fetchNetworkAdapter does not support FileReference's`);
|
|
3590
|
-
}
|
|
3591
|
-
// else we have a Luvio File that isn't a real DOM file,
|
|
3592
|
-
// so we need to turn it into a DOM file
|
|
3593
|
-
else {
|
|
3594
|
-
const buffer = await value.arrayBuffer();
|
|
3595
|
-
newForm.append(name, new File([new Uint8Array(buffer)], value.name, {
|
|
3596
|
-
type: value.type,
|
|
3597
|
-
}));
|
|
3598
|
-
}
|
|
3599
|
-
}
|
|
3600
|
-
body = newForm;
|
|
3601
|
-
}
|
|
3602
|
-
else if (requestBody === null) {
|
|
3603
|
-
body = null;
|
|
3604
|
-
}
|
|
3605
|
-
else {
|
|
3606
|
-
body = JSON.stringify(requestBody);
|
|
3607
|
-
headers['Content-Type'] = 'application/json';
|
|
3608
|
-
}
|
|
3609
|
-
const response = await fetch(path, {
|
|
3610
|
-
method: method.toUpperCase(),
|
|
3611
|
-
headers: generateHeaders(headers),
|
|
3612
|
-
body,
|
|
3613
|
-
});
|
|
3614
|
-
const { status, ok, statusText } = response;
|
|
3615
|
-
// coerce headers
|
|
3616
|
-
const responseHeaders = {};
|
|
3617
|
-
response.headers.forEach((value, key) => {
|
|
3618
|
-
responseHeaders[key] = value;
|
|
3619
|
-
});
|
|
3620
|
-
// parse body
|
|
3621
|
-
let responseBody = null;
|
|
3622
|
-
if (status !== 204) {
|
|
3623
|
-
const contentType = responseHeaders['content-type'];
|
|
3624
|
-
responseBody =
|
|
3625
|
-
contentType && contentType.startsWith('application/json')
|
|
3626
|
-
? await response.json()
|
|
3627
|
-
: await response.text();
|
|
3628
|
-
}
|
|
3629
|
-
return {
|
|
3630
|
-
body: responseBody,
|
|
3631
|
-
status,
|
|
3632
|
-
statusText,
|
|
3633
|
-
ok,
|
|
3634
|
-
headers: responseHeaders,
|
|
3635
|
-
};
|
|
3986
|
+
e$1.prototype = new Error(), e$1.prototype.name = "InvalidCharacterError";
|
|
3987
|
+
var r = "undefined" != typeof window && window.atob && window.atob.bind(window) || function(r2) {
|
|
3988
|
+
var t2 = String(r2).replace(/=+$/, "");
|
|
3989
|
+
if (t2.length % 4 == 1) throw new e$1("'atob' failed: The string to be decoded is not correctly encoded.");
|
|
3990
|
+
for (var n2, o2, a = 0, i = 0, c = ""; o2 = t2.charAt(i++); ~o2 && (n2 = a % 4 ? 64 * n2 + o2 : o2, a++ % 4) ? c += String.fromCharCode(255 & n2 >> (-2 * a & 6)) : 0) o2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(o2);
|
|
3991
|
+
return c;
|
|
3636
3992
|
};
|
|
3637
|
-
function
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3993
|
+
function t(e2) {
|
|
3994
|
+
var t2 = e2.replace(/-/g, "+").replace(/_/g, "/");
|
|
3995
|
+
switch (t2.length % 4) {
|
|
3996
|
+
case 0:
|
|
3997
|
+
break;
|
|
3998
|
+
case 2:
|
|
3999
|
+
t2 += "==";
|
|
4000
|
+
break;
|
|
4001
|
+
case 3:
|
|
4002
|
+
t2 += "=";
|
|
4003
|
+
break;
|
|
4004
|
+
default:
|
|
4005
|
+
throw "Illegal base64url string!";
|
|
4006
|
+
}
|
|
4007
|
+
try {
|
|
4008
|
+
return (function(e3) {
|
|
4009
|
+
return decodeURIComponent(r(e3).replace(/(.)/g, (function(e4, r2) {
|
|
4010
|
+
var t3 = r2.charCodeAt(0).toString(16).toUpperCase();
|
|
4011
|
+
return t3.length < 2 && (t3 = "0" + t3), "%" + t3;
|
|
4012
|
+
})));
|
|
4013
|
+
})(t2);
|
|
4014
|
+
} catch (e3) {
|
|
4015
|
+
return r(t2);
|
|
4016
|
+
}
|
|
3646
4017
|
}
|
|
3647
|
-
function
|
|
3648
|
-
|
|
3649
|
-
for (const key of keys$1(headers)) {
|
|
3650
|
-
fetchHeaders.set(key, headers[key]);
|
|
3651
|
-
}
|
|
3652
|
-
return fetchHeaders;
|
|
4018
|
+
function n$1(e2) {
|
|
4019
|
+
this.message = e2;
|
|
3653
4020
|
}
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
*/
|
|
3663
|
-
function validateResponse(body) {
|
|
3664
|
-
if (!body || !body.jwt || !body.baseUri) {
|
|
3665
|
-
// wrapped the invocation in env conditional
|
|
3666
|
-
// eslint-disable-next-line @salesforce/lds/no-error-in-production
|
|
3667
|
-
throw new Error(`Expected jwt info and baseUri to be present but instead got: ${JSON.stringify(body)}`);
|
|
3668
|
-
}
|
|
4021
|
+
function o(e2, r2) {
|
|
4022
|
+
if ("string" != typeof e2) throw new n$1("Invalid token specified");
|
|
4023
|
+
var o2 = true === (r2 = r2 || {}).header ? 0 : 1;
|
|
4024
|
+
try {
|
|
4025
|
+
return JSON.parse(t(e2.split(".")[o2]));
|
|
4026
|
+
} catch (e3) {
|
|
4027
|
+
throw new n$1("Invalid token specified: " + e3.message);
|
|
4028
|
+
}
|
|
3669
4029
|
}
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
4030
|
+
n$1.prototype = new Error(), n$1.prototype.name = "InvalidTokenError";
|
|
4031
|
+
class JwtToken {
|
|
4032
|
+
/**
|
|
4033
|
+
* Create a new JwtToken.
|
|
4034
|
+
*
|
|
4035
|
+
* @param _token - The JWT string.
|
|
4036
|
+
* @param _decodedInfo - The decoded information from the JWT.
|
|
4037
|
+
* @param _extraInfo - Any additional information associated with the JWT.
|
|
4038
|
+
*/
|
|
4039
|
+
constructor(_token, _decodedInfo, _extraInfo) {
|
|
4040
|
+
this._token = _token;
|
|
4041
|
+
this._decodedInfo = _decodedInfo;
|
|
4042
|
+
this._extraInfo = _extraInfo;
|
|
4043
|
+
}
|
|
4044
|
+
/**
|
|
4045
|
+
* Get the JWT string.
|
|
4046
|
+
*
|
|
4047
|
+
* @returns The JWT string.
|
|
4048
|
+
*/
|
|
4049
|
+
get token() {
|
|
4050
|
+
return this._token;
|
|
4051
|
+
}
|
|
4052
|
+
/**
|
|
4053
|
+
* Get the additional information associated with the JWT.
|
|
4054
|
+
*
|
|
4055
|
+
* @returns The additional information.
|
|
4056
|
+
*/
|
|
4057
|
+
get extraInfo() {
|
|
4058
|
+
return this._extraInfo;
|
|
4059
|
+
}
|
|
4060
|
+
/**
|
|
4061
|
+
* Get the decoded information from the JWT.
|
|
4062
|
+
*
|
|
4063
|
+
* @returns The decoded information.
|
|
4064
|
+
*/
|
|
4065
|
+
get decodedInfo() {
|
|
4066
|
+
return this._decodedInfo;
|
|
4067
|
+
}
|
|
4068
|
+
/**
|
|
4069
|
+
* Get the remaining time in seconds until the JWT expires.
|
|
4070
|
+
*
|
|
4071
|
+
* @returns The remaining time in seconds.
|
|
4072
|
+
*/
|
|
4073
|
+
get tokenRemainingSeconds() {
|
|
4074
|
+
return this.decodedInfo.exp - Date.now() / 1e3;
|
|
4075
|
+
}
|
|
4076
|
+
/**
|
|
4077
|
+
* Check if the JWT is expired.
|
|
4078
|
+
*
|
|
4079
|
+
* @returns True if the JWT is expired, false otherwise.
|
|
4080
|
+
*/
|
|
4081
|
+
get isExpired() {
|
|
4082
|
+
return this.tokenRemainingSeconds <= 0;
|
|
4083
|
+
}
|
|
4084
|
+
}
|
|
4085
|
+
let defaultLogger = {
|
|
4086
|
+
trace: () => {
|
|
4087
|
+
},
|
|
4088
|
+
debug: () => {
|
|
4089
|
+
},
|
|
4090
|
+
info: () => {
|
|
4091
|
+
},
|
|
4092
|
+
warn: () => {
|
|
4093
|
+
},
|
|
4094
|
+
error: () => {
|
|
4095
|
+
}
|
|
3706
4096
|
};
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
4097
|
+
if (process.env.NODE_ENV !== "production") {
|
|
4098
|
+
defaultLogger = loggerService();
|
|
4099
|
+
}
|
|
4100
|
+
function computeDecodedInfo(token, defaultTokenTTLInSeconds, logger) {
|
|
4101
|
+
const decodedInfo = o(token);
|
|
4102
|
+
if (decodedInfo.exp === void 0) {
|
|
4103
|
+
logger.warn(`"exp" claim is not present in the provided token.`);
|
|
4104
|
+
decodedInfo.exp = Date.now() / 1e3 + defaultTokenTTLInSeconds;
|
|
4105
|
+
}
|
|
4106
|
+
return decodedInfo;
|
|
4107
|
+
}
|
|
4108
|
+
class JwtRepository {
|
|
4109
|
+
/**
|
|
4110
|
+
* @param limitInSeconds - Time in seconds before the token's expiry to notify observers.
|
|
4111
|
+
* @param defaultTokenTTLInSeconds - Default token expiry time in seconds if "exp" claim is not present in token.
|
|
4112
|
+
* @param logger - Logger for logging warnings and errors.
|
|
4113
|
+
*/
|
|
4114
|
+
constructor(limitInSeconds = 5, defaultTokenTTLInSeconds = 120, logger = defaultLogger) {
|
|
4115
|
+
this.limitInSeconds = limitInSeconds;
|
|
4116
|
+
this.defaultTokenTTLInSeconds = defaultTokenTTLInSeconds;
|
|
4117
|
+
this.logger = logger;
|
|
4118
|
+
this.observers = [];
|
|
4119
|
+
}
|
|
4120
|
+
/**
|
|
4121
|
+
* Get the current token.
|
|
4122
|
+
*/
|
|
4123
|
+
get token() {
|
|
4124
|
+
return this._token;
|
|
4125
|
+
}
|
|
4126
|
+
/**
|
|
4127
|
+
* Set the current token.
|
|
4128
|
+
*
|
|
4129
|
+
* @param token - JWT token as a string.
|
|
4130
|
+
* @param extraInfo - Optional extra information.
|
|
4131
|
+
*/
|
|
4132
|
+
setToken(token, extraInfo) {
|
|
4133
|
+
const decodedInfo = computeDecodedInfo(
|
|
4134
|
+
token,
|
|
4135
|
+
this.defaultTokenTTLInSeconds,
|
|
4136
|
+
this.logger
|
|
4137
|
+
);
|
|
4138
|
+
this._token = new JwtToken(token, decodedInfo, extraInfo);
|
|
4139
|
+
this.observeTokenExpiration();
|
|
4140
|
+
return this._token;
|
|
4141
|
+
}
|
|
4142
|
+
/**
|
|
4143
|
+
* Remove the current token.
|
|
4144
|
+
*/
|
|
4145
|
+
removeToken() {
|
|
4146
|
+
this._token = void 0;
|
|
4147
|
+
this.clearTimeoutHandler();
|
|
4148
|
+
}
|
|
4149
|
+
/**
|
|
4150
|
+
* Subscribe to the token nearing its expiration.
|
|
4151
|
+
*
|
|
4152
|
+
* @param cb - Callback function to execute when token is nearing expiration.
|
|
4153
|
+
*/
|
|
4154
|
+
subscribeToTokenNearExpiration(cb) {
|
|
4155
|
+
this.observers.push(cb);
|
|
4156
|
+
this.observeTokenExpiration();
|
|
4157
|
+
return () => {
|
|
4158
|
+
this.observers = this.observers.filter((observer) => observer !== cb);
|
|
3719
4159
|
};
|
|
3720
|
-
}
|
|
3721
|
-
/**
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
4160
|
+
}
|
|
4161
|
+
/**
|
|
4162
|
+
* Clear the timeout handler.
|
|
4163
|
+
*/
|
|
4164
|
+
clearTimeoutHandler() {
|
|
4165
|
+
if (this.timeoutHandler !== void 0) {
|
|
4166
|
+
clearTimeout(this.timeoutHandler);
|
|
4167
|
+
}
|
|
4168
|
+
}
|
|
4169
|
+
/**
|
|
4170
|
+
* Observe and handle token expiration.
|
|
4171
|
+
*/
|
|
4172
|
+
observeTokenExpiration() {
|
|
4173
|
+
this.clearTimeoutHandler();
|
|
4174
|
+
if (this.observers.length === 0 || this.token === void 0) {
|
|
4175
|
+
return;
|
|
4176
|
+
}
|
|
4177
|
+
this.timeoutHandler = setTimeout(
|
|
4178
|
+
() => this.notifyTokenIsExpiring(),
|
|
4179
|
+
this.computeTimeoutTimeInMs()
|
|
4180
|
+
);
|
|
4181
|
+
}
|
|
4182
|
+
/**
|
|
4183
|
+
* Compute the timeout time in milliseconds.
|
|
4184
|
+
*/
|
|
4185
|
+
computeTimeoutTimeInMs() {
|
|
4186
|
+
const remainingSeconds = this.token.tokenRemainingSeconds;
|
|
4187
|
+
let timeoutTimeInSeconds = remainingSeconds - this.limitInSeconds;
|
|
4188
|
+
return timeoutTimeInSeconds < 0 ? 0 : timeoutTimeInSeconds * 1e3;
|
|
4189
|
+
}
|
|
4190
|
+
/**
|
|
4191
|
+
* Notify all observers that the token is expiring.
|
|
4192
|
+
*/
|
|
4193
|
+
notifyTokenIsExpiring() {
|
|
4194
|
+
this.observers.forEach((cb) => {
|
|
4195
|
+
try {
|
|
4196
|
+
cb.call(void 0, this.token);
|
|
4197
|
+
} catch (e2) {
|
|
4198
|
+
this.logger.error(e2.message);
|
|
4199
|
+
}
|
|
4200
|
+
});
|
|
4201
|
+
}
|
|
4202
|
+
}
|
|
4203
|
+
class JwtManager {
|
|
4204
|
+
/**
|
|
4205
|
+
* Constructor for JwtManager class.
|
|
4206
|
+
*
|
|
4207
|
+
* @param {JwtRepository<T, ExtraInfo>} jwtRepository JwtRepository instance used for token management.
|
|
4208
|
+
* @param {JwtResolver<ExtraInfo>} resolver JwtResolver instance used for token retrieval.
|
|
4209
|
+
* @param {JwtManagerOptions} options JwtManagerOptions bag to customize behavior.
|
|
4210
|
+
*/
|
|
4211
|
+
constructor(jwtRepository, resolver, options) {
|
|
4212
|
+
this.jwtRepository = jwtRepository;
|
|
4213
|
+
this.resolver = resolver;
|
|
4214
|
+
if (options == null ? void 0 : options.keepTokenUpdated) {
|
|
4215
|
+
jwtRepository.subscribeToTokenNearExpiration(() => this.refreshToken());
|
|
4216
|
+
}
|
|
4217
|
+
}
|
|
4218
|
+
/**
|
|
4219
|
+
* Method to get a JWT token.
|
|
4220
|
+
* If there's a token request in progress, it will return the Promise of this request.
|
|
4221
|
+
* If the current token is undefined or expired, it will initiate a token refresh.
|
|
4222
|
+
* Otherwise, it will return the current token.
|
|
4223
|
+
*
|
|
4224
|
+
* @returns {JwtToken<T, ExtraInfo> | Promise<JwtToken<T, ExtraInfo>>} The current token or the Promise of a token request.
|
|
4225
|
+
*/
|
|
4226
|
+
getJwt() {
|
|
4227
|
+
if (this.inflightPromise) {
|
|
4228
|
+
return this.inflightPromise;
|
|
4229
|
+
}
|
|
4230
|
+
const token = this.jwtRepository.token;
|
|
4231
|
+
if (token === void 0 || token.isExpired) {
|
|
4232
|
+
return this.refreshToken();
|
|
4233
|
+
}
|
|
4234
|
+
return token;
|
|
4235
|
+
}
|
|
4236
|
+
/**
|
|
4237
|
+
* Method to refresh a JWT token.
|
|
4238
|
+
* If a refresh request is already in progress, it will return the Promise of this request.
|
|
4239
|
+
* Otherwise, it will start a new refresh request and return its Promise.
|
|
4240
|
+
*
|
|
4241
|
+
* @returns {Promise<JwtToken<T, ExtraInfo>>} Promise of the refreshed token.
|
|
4242
|
+
*/
|
|
4243
|
+
refreshToken() {
|
|
4244
|
+
if (this.inflightPromise === void 0) {
|
|
4245
|
+
this.inflightPromise = new Promise((resolve, reject) => {
|
|
4246
|
+
this.resolver.getJwt().then(({ jwt, extraInfo }) => {
|
|
4247
|
+
this.inflightPromise = void 0;
|
|
4248
|
+
const token = this.jwtRepository.setToken(jwt, extraInfo);
|
|
4249
|
+
resolve(token);
|
|
4250
|
+
}).catch((reason) => {
|
|
4251
|
+
this.inflightPromise = void 0;
|
|
4252
|
+
reject(reason);
|
|
4253
|
+
});
|
|
4254
|
+
});
|
|
4255
|
+
}
|
|
4256
|
+
return this.inflightPromise;
|
|
4257
|
+
}
|
|
4258
|
+
/**
|
|
4259
|
+
* Method to check if a token refresh is in progress.
|
|
4260
|
+
*
|
|
4261
|
+
* @returns {boolean} true if a token refresh is in progress, false otherwise.
|
|
4262
|
+
*/
|
|
4263
|
+
get isRefreshingToken() {
|
|
4264
|
+
return this.inflightPromise !== void 0;
|
|
4265
|
+
}
|
|
4266
|
+
}
|
|
4267
|
+
|
|
4268
|
+
/*!
|
|
4269
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
4270
|
+
* All rights reserved.
|
|
4271
|
+
* For full license text, see the LICENSE.txt file
|
|
3728
4272
|
*/
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
let jwtToken;
|
|
3738
|
-
try {
|
|
3739
|
-
jwtToken = await jwtManager.getJwt();
|
|
4273
|
+
function setHeader(headerName, headerValue, [resource, options = {}], {
|
|
4274
|
+
throwOnExisting = false,
|
|
4275
|
+
errorMessage = `Unexpected ${headerName} header encountered`
|
|
4276
|
+
} = {}) {
|
|
4277
|
+
let hasHeaderBeenSet = false;
|
|
4278
|
+
if (resource instanceof Request && !(options == null ? void 0 : options.headers)) {
|
|
4279
|
+
if (throwOnExisting && resource.headers.has(headerName)) {
|
|
4280
|
+
throw new Error(errorMessage);
|
|
3740
4281
|
}
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
4282
|
+
resource.headers.set(headerName, headerValue);
|
|
4283
|
+
hasHeaderBeenSet = true;
|
|
4284
|
+
}
|
|
4285
|
+
if ((options == null ? void 0 : options.headers) instanceof Headers) {
|
|
4286
|
+
if (throwOnExisting && options.headers.has(headerName)) {
|
|
4287
|
+
throw new Error(errorMessage);
|
|
3746
4288
|
}
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
4289
|
+
options.headers.set(headerName, headerValue);
|
|
4290
|
+
} else {
|
|
4291
|
+
if (throwOnExisting && (options == null ? void 0 : options.headers) && Reflect.has(options.headers, headerName)) {
|
|
4292
|
+
throw new Error(errorMessage);
|
|
4293
|
+
}
|
|
4294
|
+
if (!hasHeaderBeenSet) {
|
|
4295
|
+
options.headers = {
|
|
4296
|
+
...options == null ? void 0 : options.headers,
|
|
4297
|
+
[headerName]: headerValue
|
|
4298
|
+
};
|
|
3757
4299
|
}
|
|
4300
|
+
}
|
|
4301
|
+
return [resource, options];
|
|
4302
|
+
}
|
|
4303
|
+
const UNEXPECTED_AUTHORIZATION_HEADER_MESSAGE = "Unexpected Authorization header encountered. To specify a custom Authorization header, use a Fetch service that is not configured with JwtRequestHeaderInterceptor";
|
|
4304
|
+
function setHeaderAuthorization({ token }, fetchParams) {
|
|
4305
|
+
const authorizationValue = `Bearer ${token}`;
|
|
4306
|
+
return setHeader("Authorization", authorizationValue, fetchParams, {
|
|
4307
|
+
throwOnExisting: true,
|
|
4308
|
+
errorMessage: UNEXPECTED_AUTHORIZATION_HEADER_MESSAGE
|
|
4309
|
+
});
|
|
4310
|
+
}
|
|
4311
|
+
function buildJwtRequestHeaderInterceptor(jwtManager, jwtRequestModifier = (_e, fetchArgs) => fetchArgs) {
|
|
4312
|
+
return (args) => {
|
|
4313
|
+
return resolvedPromiseLike$2(jwtManager.getJwt()).then((token) => {
|
|
4314
|
+
const fetchArgsWithRequestHeaderAuthorization = setHeaderAuthorization(token, args);
|
|
4315
|
+
return token.extraInfo ? jwtRequestModifier(token.extraInfo, fetchArgsWithRequestHeaderAuthorization) : fetchArgsWithRequestHeaderAuthorization;
|
|
4316
|
+
});
|
|
4317
|
+
};
|
|
3758
4318
|
}
|
|
3759
|
-
const composedNetworkAdapter$1 = {
|
|
3760
|
-
shouldHandleRequest(resourceRequest) {
|
|
3761
|
-
return resourceRequest.baseUri === SALESFORCE_API_BASE_URI_FLAG;
|
|
3762
|
-
},
|
|
3763
|
-
adapter: sfapNetworkAdapter,
|
|
3764
|
-
};
|
|
3765
4319
|
|
|
3766
|
-
|
|
4320
|
+
var SnapshotState;
|
|
4321
|
+
(function (SnapshotState) {
|
|
4322
|
+
SnapshotState["Fulfilled"] = "Fulfilled";
|
|
4323
|
+
SnapshotState["Unfulfilled"] = "Unfulfilled";
|
|
4324
|
+
SnapshotState["Error"] = "Error";
|
|
4325
|
+
SnapshotState["Pending"] = "Pending";
|
|
4326
|
+
SnapshotState["Stale"] = "Stale";
|
|
4327
|
+
})(SnapshotState || (SnapshotState = {}));
|
|
4328
|
+
const { isArray: isArray$1 } = Array;
|
|
3767
4329
|
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
4330
|
+
Promise.resolve();
|
|
4331
|
+
|
|
4332
|
+
var StoreErrorStatus;
|
|
4333
|
+
(function (StoreErrorStatus) {
|
|
4334
|
+
StoreErrorStatus[StoreErrorStatus["RESOURCE_NOT_FOUND"] = 404] = "RESOURCE_NOT_FOUND";
|
|
4335
|
+
})(StoreErrorStatus || (StoreErrorStatus = {}));
|
|
4336
|
+
var StoreRecordType;
|
|
4337
|
+
(function (StoreRecordType) {
|
|
4338
|
+
StoreRecordType["Error"] = "error";
|
|
4339
|
+
})(StoreRecordType || (StoreRecordType = {}));
|
|
4340
|
+
var StoreLinkStateValues$1;
|
|
4341
|
+
(function (StoreLinkStateValues) {
|
|
4342
|
+
StoreLinkStateValues[StoreLinkStateValues["NotPresent"] = 0] = "NotPresent";
|
|
4343
|
+
StoreLinkStateValues[StoreLinkStateValues["RefNotPresent"] = 1] = "RefNotPresent";
|
|
4344
|
+
StoreLinkStateValues[StoreLinkStateValues["RefPresent"] = 2] = "RefPresent";
|
|
4345
|
+
StoreLinkStateValues[StoreLinkStateValues["Null"] = 3] = "Null";
|
|
4346
|
+
StoreLinkStateValues[StoreLinkStateValues["Missing"] = 4] = "Missing";
|
|
4347
|
+
StoreLinkStateValues[StoreLinkStateValues["Pending"] = 5] = "Pending";
|
|
4348
|
+
})(StoreLinkStateValues$1 || (StoreLinkStateValues$1 = {}));
|
|
4349
|
+
var StoreResolveResultState;
|
|
4350
|
+
(function (StoreResolveResultState) {
|
|
4351
|
+
StoreResolveResultState[StoreResolveResultState["Found"] = 0] = "Found";
|
|
4352
|
+
StoreResolveResultState[StoreResolveResultState["Error"] = 1] = "Error";
|
|
4353
|
+
StoreResolveResultState[StoreResolveResultState["Null"] = 2] = "Null";
|
|
4354
|
+
StoreResolveResultState[StoreResolveResultState["NotPresent"] = 3] = "NotPresent";
|
|
4355
|
+
StoreResolveResultState[StoreResolveResultState["Stale"] = 4] = "Stale";
|
|
4356
|
+
})(StoreResolveResultState || (StoreResolveResultState = {}));
|
|
4357
|
+
var HttpStatusCode;
|
|
4358
|
+
(function (HttpStatusCode) {
|
|
4359
|
+
HttpStatusCode[HttpStatusCode["Ok"] = 200] = "Ok";
|
|
4360
|
+
HttpStatusCode[HttpStatusCode["Created"] = 201] = "Created";
|
|
4361
|
+
HttpStatusCode[HttpStatusCode["NoContent"] = 204] = "NoContent";
|
|
4362
|
+
HttpStatusCode[HttpStatusCode["NotModified"] = 304] = "NotModified";
|
|
4363
|
+
HttpStatusCode[HttpStatusCode["BadRequest"] = 400] = "BadRequest";
|
|
4364
|
+
HttpStatusCode[HttpStatusCode["Unauthorized"] = 401] = "Unauthorized";
|
|
4365
|
+
HttpStatusCode[HttpStatusCode["Forbidden"] = 403] = "Forbidden";
|
|
4366
|
+
HttpStatusCode[HttpStatusCode["NotFound"] = 404] = "NotFound";
|
|
4367
|
+
HttpStatusCode[HttpStatusCode["ServerError"] = 500] = "ServerError";
|
|
4368
|
+
HttpStatusCode[HttpStatusCode["GatewayTimeout"] = 504] = "GatewayTimeout";
|
|
4369
|
+
})(HttpStatusCode || (HttpStatusCode = {}));
|
|
4370
|
+
/**
|
|
4371
|
+
* A type guard function for determining if an unknown object is a {@link FormData}
|
|
4372
|
+
*/
|
|
4373
|
+
function isFormData(obj) {
|
|
4374
|
+
return (typeof obj === 'object' &&
|
|
4375
|
+
obj !== null &&
|
|
4376
|
+
'namedEntries' in obj &&
|
|
4377
|
+
isArray$1(obj.namedEntries));
|
|
4378
|
+
}
|
|
4379
|
+
/**
|
|
4380
|
+
* A type guard function for determining if an unknown object is a {@link FileReference}
|
|
4381
|
+
*/
|
|
4382
|
+
function isFileReference(entryValue) {
|
|
4383
|
+
return (typeof entryValue === 'object' &&
|
|
4384
|
+
entryValue !== null &&
|
|
4385
|
+
'isFileReference' in entryValue &&
|
|
4386
|
+
entryValue.isFileReference === true);
|
|
4387
|
+
}
|
|
4388
|
+
var GraphNodeType;
|
|
4389
|
+
(function (GraphNodeType) {
|
|
4390
|
+
GraphNodeType["Link"] = "Link";
|
|
4391
|
+
GraphNodeType["Node"] = "Node";
|
|
4392
|
+
GraphNodeType["Error"] = "Error";
|
|
4393
|
+
GraphNodeType["Locked"] = "Locked";
|
|
4394
|
+
})(GraphNodeType || (GraphNodeType = {}));
|
|
4395
|
+
|
|
4396
|
+
var StoreLinkStateValues;
|
|
4397
|
+
(function (StoreLinkStateValues) {
|
|
4398
|
+
StoreLinkStateValues[StoreLinkStateValues["NotPresent"] = 0] = "NotPresent";
|
|
4399
|
+
StoreLinkStateValues[StoreLinkStateValues["RefNotPresent"] = 1] = "RefNotPresent";
|
|
4400
|
+
StoreLinkStateValues[StoreLinkStateValues["RefPresent"] = 2] = "RefPresent";
|
|
4401
|
+
StoreLinkStateValues[StoreLinkStateValues["Null"] = 3] = "Null";
|
|
4402
|
+
StoreLinkStateValues[StoreLinkStateValues["Missing"] = 4] = "Missing";
|
|
4403
|
+
StoreLinkStateValues[StoreLinkStateValues["Pending"] = 5] = "Pending";
|
|
4404
|
+
})(StoreLinkStateValues || (StoreLinkStateValues = {}));
|
|
4405
|
+
var FragmentReadResultState;
|
|
4406
|
+
(function (FragmentReadResultState) {
|
|
4407
|
+
FragmentReadResultState[FragmentReadResultState["Missing"] = 0] = "Missing";
|
|
4408
|
+
FragmentReadResultState[FragmentReadResultState["Success"] = 1] = "Success";
|
|
4409
|
+
FragmentReadResultState[FragmentReadResultState["Error"] = 2] = "Error";
|
|
4410
|
+
})(FragmentReadResultState || (FragmentReadResultState = {}));
|
|
4411
|
+
({
|
|
4412
|
+
state: FragmentReadResultState.Missing,
|
|
4413
|
+
});
|
|
4414
|
+
|
|
4415
|
+
var ResourceParamType;
|
|
4416
|
+
(function (ResourceParamType) {
|
|
4417
|
+
ResourceParamType[ResourceParamType["UrlParameter"] = 0] = "UrlParameter";
|
|
4418
|
+
ResourceParamType[ResourceParamType["QueryParameter"] = 1] = "QueryParameter";
|
|
4419
|
+
ResourceParamType[ResourceParamType["Body"] = 2] = "Body";
|
|
4420
|
+
ResourceParamType[ResourceParamType["Header"] = 3] = "Header";
|
|
4421
|
+
})(ResourceParamType || (ResourceParamType = {}));
|
|
4422
|
+
var TypeCheckShapes;
|
|
4423
|
+
(function (TypeCheckShapes) {
|
|
4424
|
+
TypeCheckShapes[TypeCheckShapes["String"] = 0] = "String";
|
|
4425
|
+
TypeCheckShapes[TypeCheckShapes["Boolean"] = 1] = "Boolean";
|
|
4426
|
+
TypeCheckShapes[TypeCheckShapes["Number"] = 2] = "Number";
|
|
4427
|
+
TypeCheckShapes[TypeCheckShapes["Integer"] = 3] = "Integer";
|
|
4428
|
+
TypeCheckShapes[TypeCheckShapes["Unsupported"] = 4] = "Unsupported";
|
|
4429
|
+
})(TypeCheckShapes || (TypeCheckShapes = {}));
|
|
4430
|
+
// engine version: 0.158.7-bafe2646
|
|
4431
|
+
|
|
4432
|
+
const { keys: keys$1 } = Object;
|
|
4433
|
+
|
|
4434
|
+
// we're going to intentionally bundle this small bit of luvio engine code into
|
|
4435
|
+
// this module to keep it runtime dependency-free
|
|
4436
|
+
const fetchNetworkAdapter = async (resourceRequest, _resourceRequestContext) => {
|
|
4437
|
+
const { baseUri, basePath, body: requestBody, queryParams, method, headers } = resourceRequest;
|
|
4438
|
+
const qs = generateQueryString(queryParams);
|
|
4439
|
+
const path = `${baseUri}${basePath}${qs}`;
|
|
4440
|
+
let body;
|
|
4441
|
+
// some endpoints use FormData for POST request body, check here
|
|
4442
|
+
// if we have a POST body that is FormData
|
|
4443
|
+
if (method === 'post' && isFormData(requestBody)) {
|
|
4444
|
+
// we will populate a DOM FormData and pass that to fetch
|
|
4445
|
+
const newForm = new FormData();
|
|
4446
|
+
for (const { name, value } of requestBody.namedEntries) {
|
|
4447
|
+
// if this is a string or real DOM File then we can
|
|
4448
|
+
// just add it to FormData
|
|
4449
|
+
if (typeof value === 'string' || value instanceof File) {
|
|
4450
|
+
newForm.append(name, value);
|
|
3780
4451
|
}
|
|
3781
|
-
|
|
3782
|
-
|
|
4452
|
+
// this network adapter doesn't currently support FileReference's
|
|
4453
|
+
else if (isFileReference(value)) {
|
|
4454
|
+
throw Error(`Luvio fetchNetworkAdapter does not support FileReference's`);
|
|
3783
4455
|
}
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
if (response.body.errorCode === 'INVALID_SESSION_ID') {
|
|
3792
|
-
window.setTimeout(() => {
|
|
3793
|
-
dispatchGlobalEvent('aura:invalidSession');
|
|
3794
|
-
}, 0);
|
|
4456
|
+
// else we have a Luvio File that isn't a real DOM file,
|
|
4457
|
+
// so we need to turn it into a DOM file
|
|
4458
|
+
else {
|
|
4459
|
+
const buffer = await value.arrayBuffer();
|
|
4460
|
+
newForm.append(name, new File([new Uint8Array(buffer)], value.name, {
|
|
4461
|
+
type: value.type,
|
|
4462
|
+
}));
|
|
3795
4463
|
}
|
|
3796
4464
|
}
|
|
3797
|
-
|
|
4465
|
+
body = newForm;
|
|
4466
|
+
}
|
|
4467
|
+
else if (requestBody === null) {
|
|
4468
|
+
body = null;
|
|
4469
|
+
}
|
|
4470
|
+
else {
|
|
4471
|
+
body = JSON.stringify(requestBody);
|
|
4472
|
+
headers['Content-Type'] = 'application/json';
|
|
4473
|
+
}
|
|
4474
|
+
const response = await fetch(path, {
|
|
4475
|
+
method: method.toUpperCase(),
|
|
4476
|
+
headers: generateHeaders(headers),
|
|
4477
|
+
body,
|
|
4478
|
+
});
|
|
4479
|
+
const { status, ok, statusText } = response;
|
|
4480
|
+
// coerce headers
|
|
4481
|
+
const responseHeaders = {};
|
|
4482
|
+
response.headers.forEach((value, key) => {
|
|
4483
|
+
responseHeaders[key] = value;
|
|
4484
|
+
});
|
|
4485
|
+
// parse body
|
|
4486
|
+
let responseBody = null;
|
|
4487
|
+
if (status !== 204) {
|
|
4488
|
+
const contentType = responseHeaders['content-type'];
|
|
4489
|
+
responseBody =
|
|
4490
|
+
contentType && contentType.startsWith('application/json')
|
|
4491
|
+
? await response.json()
|
|
4492
|
+
: await response.text();
|
|
4493
|
+
}
|
|
4494
|
+
return {
|
|
4495
|
+
body: responseBody,
|
|
4496
|
+
status,
|
|
4497
|
+
statusText,
|
|
4498
|
+
ok,
|
|
4499
|
+
headers: responseHeaders,
|
|
3798
4500
|
};
|
|
3799
|
-
}
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
* Returns the numeric value in parentheses.
|
|
3805
|
-
*
|
|
3806
|
-
* @param responseBody The response body text to parse.
|
|
3807
|
-
* @returns The extracted error ID, or null if not found.
|
|
3808
|
-
*/
|
|
3809
|
-
function extractErrorIdFromResponse(responseBody) {
|
|
3810
|
-
try {
|
|
3811
|
-
const parsed = JSON.parse(responseBody);
|
|
3812
|
-
if (Array.isArray(parsed) && parsed.length > 0 && parsed[0].message) {
|
|
3813
|
-
const message = parsed[0].message;
|
|
3814
|
-
// Look for pattern: "ErrorId if you contact support: XXXXXX-XXXXX (YYYYY)"
|
|
3815
|
-
const match = message.match(/ErrorId[^:]*:\s*[\d-]+\s*\((-?\d+)\)/);
|
|
3816
|
-
if (match && match[1]) {
|
|
3817
|
-
return parseInt(match[1], 10);
|
|
3818
|
-
}
|
|
3819
|
-
}
|
|
4501
|
+
};
|
|
4502
|
+
function generateQueryString(params) {
|
|
4503
|
+
const queryStrings = [];
|
|
4504
|
+
for (const key of keys$1(params)) {
|
|
4505
|
+
queryStrings.push(`${key}=${params[key]}`);
|
|
3820
4506
|
}
|
|
3821
|
-
|
|
3822
|
-
|
|
4507
|
+
if (queryStrings.length > 0) {
|
|
4508
|
+
return `?${queryStrings.join('&')}`;
|
|
3823
4509
|
}
|
|
3824
|
-
return
|
|
4510
|
+
return '';
|
|
3825
4511
|
}
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
* @param idInput The input value to hash.
|
|
3831
|
-
* @returns A unique error ID in Salesforce-compatible numeric format.
|
|
3832
|
-
*/
|
|
3833
|
-
function generateErrorId(idInput) {
|
|
3834
|
-
let hash = 0;
|
|
3835
|
-
if (!idInput || idInput.length === 0) {
|
|
3836
|
-
return hash;
|
|
3837
|
-
}
|
|
3838
|
-
let i, chr;
|
|
3839
|
-
for (i = 0; i < idInput.length; i++) {
|
|
3840
|
-
chr = idInput.charCodeAt(i);
|
|
3841
|
-
hash = (hash << 5) - hash + chr;
|
|
3842
|
-
hash |= 0; // Convert to 32bit integer
|
|
4512
|
+
function generateHeaders(headers) {
|
|
4513
|
+
const fetchHeaders = new Headers();
|
|
4514
|
+
for (const key of keys$1(headers)) {
|
|
4515
|
+
fetchHeaders.set(key, headers[key]);
|
|
3843
4516
|
}
|
|
3844
|
-
return
|
|
4517
|
+
return fetchHeaders;
|
|
3845
4518
|
}
|
|
4519
|
+
|
|
4520
|
+
const SALESFORCE_API_BASE_URI_FLAG = 'api.salesforce.com';
|
|
4521
|
+
const X_REQUEST_ID_HEADER = 'x-request-id';
|
|
4522
|
+
const SFAPController = 'SalesforceApiPlatformController';
|
|
4523
|
+
const SFAPJwtMethod = 'getSFAPLightningJwtService';
|
|
3846
4524
|
/**
|
|
3847
|
-
*
|
|
3848
|
-
* Tries to extract server-provided ErrorId first, falls back to generated hash.
|
|
4525
|
+
* We expect jwt info and baseUri to be present in the response.
|
|
3849
4526
|
*
|
|
3850
|
-
* @param
|
|
3851
|
-
* @param status The HTTP status code (for fallback).
|
|
3852
|
-
* @param statusText The HTTP status text (for fallback, optional).
|
|
3853
|
-
* @returns A numeric error ID.
|
|
4527
|
+
* @param body
|
|
3854
4528
|
*/
|
|
3855
|
-
function
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
4529
|
+
function validateResponse(body) {
|
|
4530
|
+
if (!body || !body.jwt || !body.baseUri) {
|
|
4531
|
+
// wrapped the invocation in env conditional
|
|
4532
|
+
// eslint-disable-next-line @salesforce/lds/no-error-in-production
|
|
4533
|
+
throw new Error(`Expected jwt info and baseUri to be present but instead got: ${JSON.stringify(body)}`);
|
|
3859
4534
|
}
|
|
3860
|
-
// Fallback to generated error ID using status and timestamp
|
|
3861
|
-
// statusText is optional and may not always be present
|
|
3862
|
-
const context = [status, statusText || '', Date.now()].join('|');
|
|
3863
|
-
return generateErrorId(context);
|
|
3864
|
-
}
|
|
3865
|
-
function buildLexRuntime5xxStatusResponseInterceptor(logger) {
|
|
3866
|
-
return async (response) => {
|
|
3867
|
-
if (response.status >= 500 && response.status < 600) {
|
|
3868
|
-
const internalLogMessage = `LEX runtime 5xx: ${response.status} ${response.statusText || ''}`.trim();
|
|
3869
|
-
logger.warn(internalLogMessage);
|
|
3870
|
-
const userMessage = 'A server error occurred. Please try again later.';
|
|
3871
|
-
// Try to extract ErrorId from response body, fallback to generated ID
|
|
3872
|
-
let errorId;
|
|
3873
|
-
try {
|
|
3874
|
-
const responseText = await response.clone().text();
|
|
3875
|
-
errorId = getOrGenerateErrorId(responseText, response.status, response.statusText);
|
|
3876
|
-
}
|
|
3877
|
-
catch (e) {
|
|
3878
|
-
// If reading response fails, use fallback
|
|
3879
|
-
const context = [response.status, response.statusText, Date.now()].join('|');
|
|
3880
|
-
errorId = generateErrorId(context);
|
|
3881
|
-
}
|
|
3882
|
-
// Create an error object similar to Aura's current shape for system errors
|
|
3883
|
-
const error = {
|
|
3884
|
-
message: userMessage,
|
|
3885
|
-
severity: 'ALERT',
|
|
3886
|
-
name: 'LEXRuntimeError',
|
|
3887
|
-
stack: null,
|
|
3888
|
-
handled: false,
|
|
3889
|
-
reported: false,
|
|
3890
|
-
id: errorId,
|
|
3891
|
-
};
|
|
3892
|
-
const evtArgs = {
|
|
3893
|
-
message: error.message,
|
|
3894
|
-
error: null,
|
|
3895
|
-
auraError: error,
|
|
3896
|
-
};
|
|
3897
|
-
// Fire the event asynchronously, similar to the legacy setTimeout pattern
|
|
3898
|
-
window.setTimeout(() => {
|
|
3899
|
-
dispatchGlobalEvent('markup://aura:systemError', evtArgs);
|
|
3900
|
-
}, 0);
|
|
3901
|
-
// Throw a simple error to terminate the request completely
|
|
3902
|
-
// The consumer has NOT opted in to handle 5xx errors, so we don't return any response
|
|
3903
|
-
// The systemError event above will handle showing the gack dialog
|
|
3904
|
-
throw new Error(error.message);
|
|
3905
|
-
}
|
|
3906
|
-
return response;
|
|
3907
|
-
};
|
|
3908
|
-
}
|
|
3909
|
-
function buildLexRuntimeLuvio5xxStatusResponseInterceptor() {
|
|
3910
|
-
return async (response) => {
|
|
3911
|
-
if (response.status >= 500 && response.status < 600) {
|
|
3912
|
-
const userMessage = 'A server error occurred. Please try again later.';
|
|
3913
|
-
// Try to extract ErrorId from response body, fallback to generated ID
|
|
3914
|
-
let errorId;
|
|
3915
|
-
try {
|
|
3916
|
-
const responseBody = response.body ? JSON.stringify(response.body) : '';
|
|
3917
|
-
errorId = getOrGenerateErrorId(responseBody, response.status, response.statusText);
|
|
3918
|
-
}
|
|
3919
|
-
catch (e) {
|
|
3920
|
-
// If reading response fails, use fallback
|
|
3921
|
-
const context = [response.status, response.statusText, Date.now()].join('|');
|
|
3922
|
-
errorId = generateErrorId(context);
|
|
3923
|
-
}
|
|
3924
|
-
// Create an error object similar to Aura's current shape for system errors
|
|
3925
|
-
const error = {
|
|
3926
|
-
message: userMessage,
|
|
3927
|
-
severity: 'ALERT',
|
|
3928
|
-
name: 'LEXRuntimeError',
|
|
3929
|
-
stack: null,
|
|
3930
|
-
handled: false,
|
|
3931
|
-
reported: false,
|
|
3932
|
-
id: errorId,
|
|
3933
|
-
};
|
|
3934
|
-
const evtArgs = {
|
|
3935
|
-
message: error.message,
|
|
3936
|
-
error: null,
|
|
3937
|
-
auraError: error,
|
|
3938
|
-
};
|
|
3939
|
-
// Fire the event asynchronously, similar to the legacy setTimeout pattern
|
|
3940
|
-
window.setTimeout(() => {
|
|
3941
|
-
dispatchGlobalEvent('markup://aura:systemError', evtArgs);
|
|
3942
|
-
}, 0);
|
|
3943
|
-
// Throw a simple error to terminate the request completely
|
|
3944
|
-
// The consumer has NOT opted in to handle 5xx errors, so we don't return any response
|
|
3945
|
-
// The systemError event above will handle showing the gack dialog
|
|
3946
|
-
throw new Error(error.message);
|
|
3947
|
-
}
|
|
3948
|
-
return response;
|
|
3949
|
-
};
|
|
3950
4535
|
}
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
4536
|
+
/**
|
|
4537
|
+
* Resolves Jwt token for SFAP by calling Aura action
|
|
4538
|
+
* {@link JwtResolver} for platform SFAP
|
|
4539
|
+
*/
|
|
4540
|
+
const platformSfapJwtResolver = {
|
|
4541
|
+
getJwt() {
|
|
4542
|
+
return new Promise((resolve, reject) => {
|
|
4543
|
+
dispatchAuraAction(`${SFAPController}.${SFAPJwtMethod}`, {}, defaultActionConfig)
|
|
4544
|
+
.then((response) => {
|
|
4545
|
+
const body = response.body;
|
|
4546
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
4547
|
+
validateResponse(body);
|
|
4548
|
+
}
|
|
4549
|
+
resolve({
|
|
4550
|
+
jwt: body.jwt,
|
|
4551
|
+
extraInfo: {
|
|
4552
|
+
baseUri: body.baseUri,
|
|
4553
|
+
},
|
|
4554
|
+
});
|
|
4555
|
+
})
|
|
4556
|
+
.catch((error) => {
|
|
4557
|
+
if (error instanceof Error) {
|
|
4558
|
+
reject(error.message);
|
|
4559
|
+
return;
|
|
4560
|
+
}
|
|
4561
|
+
// AuraFetchResponse errors
|
|
4562
|
+
const { status } = error;
|
|
4563
|
+
if (status !== HttpStatusCode$2.ServerError) {
|
|
4564
|
+
// ConnectInJavaError
|
|
4565
|
+
reject(error.body.message);
|
|
4566
|
+
return;
|
|
4567
|
+
}
|
|
4568
|
+
reject(error.body.error);
|
|
4569
|
+
});
|
|
3961
4570
|
});
|
|
3962
|
-
|
|
4571
|
+
},
|
|
4572
|
+
};
|
|
4573
|
+
const jwtManager = new JwtManager(new JwtRepository(), platformSfapJwtResolver);
|
|
4574
|
+
const authenticateRequest = (resourceRequest, jwt) => {
|
|
4575
|
+
const { token } = jwt;
|
|
4576
|
+
const { headers } = resourceRequest;
|
|
4577
|
+
// Only supporting Bearer <auth-scheme>
|
|
4578
|
+
const authenticatedHeaders = {
|
|
4579
|
+
...headers,
|
|
4580
|
+
Authorization: `Bearer ${token}`,
|
|
4581
|
+
};
|
|
4582
|
+
return {
|
|
4583
|
+
...resourceRequest,
|
|
4584
|
+
headers: authenticatedHeaders,
|
|
4585
|
+
};
|
|
4586
|
+
};
|
|
4587
|
+
/**
|
|
4588
|
+
* This hook is used to modify the resource request before it is sent to the server.
|
|
4589
|
+
* SFAP uses extraInfo assocaiated JwtToken to update the baseUri for the resource request.
|
|
4590
|
+
*
|
|
4591
|
+
* @param resourceRequest
|
|
4592
|
+
* @param jwtToken
|
|
4593
|
+
* @returns resourceRequest with updated baseUri
|
|
4594
|
+
*/
|
|
4595
|
+
const modifySfapResourceRequest = function (resourceRequest, jwtToken) {
|
|
4596
|
+
const { baseUri } = jwtToken.extraInfo;
|
|
4597
|
+
return {
|
|
4598
|
+
...resourceRequest,
|
|
4599
|
+
baseUri,
|
|
3963
4600
|
};
|
|
4601
|
+
};
|
|
4602
|
+
// used for instrumentation and tracking
|
|
4603
|
+
let sfapRequestCount = 0;
|
|
4604
|
+
const sfapNetworkAdapter = async (resourceRequest, resourceRequestContext) => {
|
|
4605
|
+
let jwtToken;
|
|
4606
|
+
try {
|
|
4607
|
+
jwtToken = await jwtManager.getJwt();
|
|
4608
|
+
}
|
|
4609
|
+
catch (error) {
|
|
4610
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
4611
|
+
throw new Error(`There was an error while fetching Jwt token: ${JSON.stringify(error)}`);
|
|
4612
|
+
}
|
|
4613
|
+
return Promise.reject(new LdsNetworkAdapterErrorResponse('Unable to fetch the jwt required to make this request', error));
|
|
4614
|
+
}
|
|
4615
|
+
let authenticatedRequest = authenticateRequest(resourceRequest, jwtToken);
|
|
4616
|
+
authenticatedRequest = modifySfapResourceRequest(authenticatedRequest, jwtToken);
|
|
4617
|
+
// --- instrumentation block --- start
|
|
4618
|
+
const uniqueRequestTaskIdentifier = 'sfap-' + sfapRequestCount++;
|
|
4619
|
+
const uniqueRequestGuid = generateRequestId();
|
|
4620
|
+
// request id header allows logging the request id and searching for the request logs
|
|
4621
|
+
authenticatedRequest.headers[X_REQUEST_ID_HEADER] = uniqueRequestGuid;
|
|
4622
|
+
let fetchComplete = false;
|
|
4623
|
+
ThirdPartyTracker.registerHandler(uniqueRequestTaskIdentifier, 'sfap-request', () => fetchComplete);
|
|
4624
|
+
markStart('transport', 'request', {
|
|
4625
|
+
auraXHRId: uniqueRequestTaskIdentifier,
|
|
4626
|
+
requestLength: -1,
|
|
4627
|
+
background: false,
|
|
4628
|
+
actionDefs: ['sfap'],
|
|
4629
|
+
requestId: uniqueRequestGuid,
|
|
4630
|
+
});
|
|
4631
|
+
// --- instrumentation block --- end
|
|
4632
|
+
const fetchNetworkAdapterPromise = fetchNetworkAdapter(authenticatedRequest);
|
|
4633
|
+
// --- instrumentation block --- start
|
|
4634
|
+
fetchNetworkAdapterPromise.finally(function requestCompleteTracker() {
|
|
4635
|
+
ThirdPartyTracker.markLoaded(uniqueRequestTaskIdentifier);
|
|
4636
|
+
fetchComplete = true;
|
|
4637
|
+
markEnd('transport', 'request', {
|
|
4638
|
+
auraXHRId: uniqueRequestTaskIdentifier,
|
|
4639
|
+
});
|
|
4640
|
+
});
|
|
4641
|
+
// --- instrumentation block --- end
|
|
4642
|
+
return fetchNetworkAdapterPromise;
|
|
4643
|
+
};
|
|
4644
|
+
class LdsNetworkAdapterErrorResponse extends Error {
|
|
4645
|
+
constructor(message, _error) {
|
|
4646
|
+
super(message);
|
|
4647
|
+
this._error = _error;
|
|
4648
|
+
this.errorType = 'networkAdapterError';
|
|
4649
|
+
this.name = this.constructor.name;
|
|
4650
|
+
}
|
|
4651
|
+
}
|
|
4652
|
+
const composedNetworkAdapter$1 = {
|
|
4653
|
+
shouldHandleRequest(resourceRequest) {
|
|
4654
|
+
return resourceRequest.baseUri === SALESFORCE_API_BASE_URI_FLAG;
|
|
4655
|
+
},
|
|
4656
|
+
adapter: sfapNetworkAdapter,
|
|
4657
|
+
};
|
|
4658
|
+
function generateRequestId() {
|
|
4659
|
+
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
|
|
4660
|
+
// as nov. 2025 caniuse says this has 93.5% support (all modern browsers)
|
|
4661
|
+
return crypto.randomUUID();
|
|
4662
|
+
}
|
|
4663
|
+
else {
|
|
4664
|
+
// fallback to Math.random() if crypto.randomUUID is not available (unlikely)
|
|
4665
|
+
return (Math.random().toString(36).substring(2, 15) +
|
|
4666
|
+
Math.random().toString(36).substring(2, 15));
|
|
4667
|
+
}
|
|
3964
4668
|
}
|
|
3965
4669
|
|
|
4670
|
+
function e(e){this.message=e;}e.prototype=new Error,e.prototype.name="InvalidCharacterError";"undefined"!=typeof window&&window.atob&&window.atob.bind(window)||function(r){var t=String(r).replace(/=+$/,"");if(t.length%4==1)throw new e("'atob' failed: The string to be decoded is not correctly encoded.");for(var n,o,a=0,i=0,c="";o=t.charAt(i++);~o&&(n=a%4?64*n+o:o,a++%4)?c+=String.fromCharCode(255&n>>(-2*a&6)):0)o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(o);return c};function n(e){this.message=e;}n.prototype=new Error,n.prototype.name="InvalidTokenError";
|
|
4671
|
+
|
|
3966
4672
|
/**
|
|
3967
4673
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
3968
4674
|
* All rights reserved.
|
|
@@ -4001,7 +4707,7 @@ function getEnvironmentSetting(name) {
|
|
|
4001
4707
|
}
|
|
4002
4708
|
return undefined;
|
|
4003
4709
|
}
|
|
4004
|
-
// version: 1.
|
|
4710
|
+
// version: 1.403.0-5476a05446
|
|
4005
4711
|
|
|
4006
4712
|
/**
|
|
4007
4713
|
* Observability / Critical Availability Program (230+)
|
|
@@ -4343,506 +5049,858 @@ class Instrumentation {
|
|
|
4343
5049
|
this.refreshAdapterEvents[adapterName] += 1;
|
|
4344
5050
|
this.lastRefreshApiCall = null;
|
|
4345
5051
|
}
|
|
4346
|
-
/**
|
|
4347
|
-
* Increments call stat for incoming refresh api call, and sets the name
|
|
4348
|
-
* to be used in {@link aggregateRefreshCalls}
|
|
4349
|
-
* @param from The name of the refresh function called.
|
|
4350
|
-
*/
|
|
4351
|
-
handleRefreshApiCall(apiName) {
|
|
4352
|
-
this.refreshApiCallEventStats[apiName] += 1;
|
|
4353
|
-
// set function call to be used with aggregateRefreshCalls
|
|
4354
|
-
this.lastRefreshApiCall = apiName;
|
|
5052
|
+
/**
|
|
5053
|
+
* Increments call stat for incoming refresh api call, and sets the name
|
|
5054
|
+
* to be used in {@link aggregateRefreshCalls}
|
|
5055
|
+
* @param from The name of the refresh function called.
|
|
5056
|
+
*/
|
|
5057
|
+
handleRefreshApiCall(apiName) {
|
|
5058
|
+
this.refreshApiCallEventStats[apiName] += 1;
|
|
5059
|
+
// set function call to be used with aggregateRefreshCalls
|
|
5060
|
+
this.lastRefreshApiCall = apiName;
|
|
5061
|
+
}
|
|
5062
|
+
/**
|
|
5063
|
+
* W-7302241
|
|
5064
|
+
* Logs refresh call summary stats as a LightningInteraction.
|
|
5065
|
+
*/
|
|
5066
|
+
logRefreshStats() {
|
|
5067
|
+
if (keys(this.refreshAdapterEvents).length > 0) {
|
|
5068
|
+
interaction(REFRESH_PAYLOAD_TARGET, REFRESH_PAYLOAD_SCOPE, this.refreshAdapterEvents, REFRESH_EVENTSOURCE, REFRESH_EVENTTYPE, this.refreshApiCallEventStats);
|
|
5069
|
+
this.resetRefreshStats();
|
|
5070
|
+
}
|
|
5071
|
+
}
|
|
5072
|
+
/**
|
|
5073
|
+
* Resets the stat trackers for refresh call events.
|
|
5074
|
+
*/
|
|
5075
|
+
resetRefreshStats() {
|
|
5076
|
+
this.refreshAdapterEvents = {};
|
|
5077
|
+
this.refreshApiCallEventStats = {
|
|
5078
|
+
[REFRESH_APEX_KEY]: 0,
|
|
5079
|
+
[REFRESH_UIAPI_KEY]: 0,
|
|
5080
|
+
[SUPPORTED_KEY]: 0,
|
|
5081
|
+
[UNSUPPORTED_KEY]: 0,
|
|
5082
|
+
};
|
|
5083
|
+
this.lastRefreshApiCall = null;
|
|
5084
|
+
}
|
|
5085
|
+
/**
|
|
5086
|
+
* W-7801618
|
|
5087
|
+
* Counter for occurrences where the incoming record to be merged has a different apiName.
|
|
5088
|
+
* Dynamically generated metric, stored in an {@link RecordApiNameChangeCounters} object.
|
|
5089
|
+
*
|
|
5090
|
+
* @param context The transaction context.
|
|
5091
|
+
*
|
|
5092
|
+
* Note: Short-lived metric candidate, remove at the end of 230
|
|
5093
|
+
*/
|
|
5094
|
+
incrementRecordApiNameChangeCount(_incomingApiName, existingApiName) {
|
|
5095
|
+
let apiNameChangeCounter = this.recordApiNameChangeCounters[existingApiName];
|
|
5096
|
+
if (apiNameChangeCounter === undefined) {
|
|
5097
|
+
apiNameChangeCounter = counter(createMetricsKey(NAMESPACE, RECORD_API_NAME_CHANGE_COUNT_METRIC_NAME, existingApiName));
|
|
5098
|
+
this.recordApiNameChangeCounters[existingApiName] = apiNameChangeCounter;
|
|
5099
|
+
}
|
|
5100
|
+
apiNameChangeCounter.increment(1);
|
|
5101
|
+
}
|
|
5102
|
+
/**
|
|
5103
|
+
* W-8620679
|
|
5104
|
+
* Increment the counter for an UnfulfilledSnapshotError coming from luvio
|
|
5105
|
+
*
|
|
5106
|
+
* @param context The transaction context.
|
|
5107
|
+
*/
|
|
5108
|
+
incrementAdapterRequestErrorCount(context) {
|
|
5109
|
+
// We are consolidating all apex adapter instrumentation calls under a single key
|
|
5110
|
+
const adapterName = normalizeAdapterName(context.adapterName);
|
|
5111
|
+
let adapterRequestErrorCounter = this.adapterUnfulfilledErrorCounters[adapterName];
|
|
5112
|
+
if (adapterRequestErrorCounter === undefined) {
|
|
5113
|
+
adapterRequestErrorCounter = counter(createMetricsKey(OBSERVABILITY_NAMESPACE, ADAPTER_ERROR_COUNT_METRIC_NAME, adapterName));
|
|
5114
|
+
this.adapterUnfulfilledErrorCounters[adapterName] = adapterRequestErrorCounter;
|
|
5115
|
+
}
|
|
5116
|
+
adapterRequestErrorCounter.increment(1);
|
|
5117
|
+
totalAdapterErrorMetric.increment(1);
|
|
5118
|
+
}
|
|
5119
|
+
}
|
|
5120
|
+
function createMetricsKey(owner, name, unit) {
|
|
5121
|
+
let metricName = name;
|
|
5122
|
+
if (unit) {
|
|
5123
|
+
metricName = metricName + '.' + unit;
|
|
5124
|
+
}
|
|
5125
|
+
return {
|
|
5126
|
+
get() {
|
|
5127
|
+
return { owner: owner, name: metricName };
|
|
5128
|
+
},
|
|
5129
|
+
};
|
|
5130
|
+
}
|
|
5131
|
+
/**
|
|
5132
|
+
* Returns whether adapter is an Apex one or not.
|
|
5133
|
+
* @param adapterName The name of the adapter.
|
|
5134
|
+
*/
|
|
5135
|
+
function isApexAdapter(adapterName) {
|
|
5136
|
+
return adapterName.indexOf(APEX_ADAPTER_NAME) > -1;
|
|
5137
|
+
}
|
|
5138
|
+
/**
|
|
5139
|
+
* Normalizes getApex adapter names to `Apex.getApex`. Non-Apex adapters will be prefixed with
|
|
5140
|
+
* API family, if supplied. Example: `UiApi.getRecord`.
|
|
5141
|
+
*
|
|
5142
|
+
* Note: If you are adding additional logging that can come from getApex adapter contexts that provide
|
|
5143
|
+
* the full getApex adapter name (i.e. getApex_[namespace]_[class]_[function]_[continuation]),
|
|
5144
|
+
* ensure to call this method to normalize all logging to 'getApex'. This
|
|
5145
|
+
* is because Argus has a 50k key cardinality limit. More context: W-8379680.
|
|
5146
|
+
*
|
|
5147
|
+
* @param adapterName The name of the adapter.
|
|
5148
|
+
* @param apiFamily The API family of the adapter.
|
|
5149
|
+
*/
|
|
5150
|
+
function normalizeAdapterName(adapterName, apiFamily) {
|
|
5151
|
+
if (isApexAdapter(adapterName)) {
|
|
5152
|
+
return NORMALIZED_APEX_ADAPTER_NAME;
|
|
5153
|
+
}
|
|
5154
|
+
return apiFamily ? `${apiFamily}.${adapterName}` : adapterName;
|
|
5155
|
+
}
|
|
5156
|
+
const timerMetricTracker = create(null);
|
|
5157
|
+
/**
|
|
5158
|
+
* Calls instrumentation/service telemetry timer
|
|
5159
|
+
* @param name Name of the metric
|
|
5160
|
+
* @param duration number to update backing percentile histogram, negative numbers ignored
|
|
5161
|
+
*/
|
|
5162
|
+
function updateTimerMetric(name, duration) {
|
|
5163
|
+
let metric = timerMetricTracker[name];
|
|
5164
|
+
if (metric === undefined) {
|
|
5165
|
+
metric = timer(createMetricsKey(NAMESPACE, name));
|
|
5166
|
+
timerMetricTracker[name] = metric;
|
|
5167
|
+
}
|
|
5168
|
+
timerMetricAddDuration(metric, duration);
|
|
5169
|
+
}
|
|
5170
|
+
function timerMetricAddDuration(timer, duration) {
|
|
5171
|
+
// Guard against negative values since it causes error to be thrown by MetricsService
|
|
5172
|
+
if (duration >= 0) {
|
|
5173
|
+
timer.addDuration(duration);
|
|
5174
|
+
}
|
|
5175
|
+
}
|
|
5176
|
+
/**
|
|
5177
|
+
* W-10315098
|
|
5178
|
+
* Increments the counter associated with the request response. Counts are bucketed by status.
|
|
5179
|
+
*/
|
|
5180
|
+
const requestResponseMetricTracker = create(null);
|
|
5181
|
+
function incrementRequestResponseCount(cb) {
|
|
5182
|
+
const status = cb().status;
|
|
5183
|
+
let metric = requestResponseMetricTracker[status];
|
|
5184
|
+
if (metric === undefined) {
|
|
5185
|
+
metric = counter(createMetricsKey(OBSERVABILITY_NAMESPACE, NETWORK_ADAPTER_RESPONSE_METRIC_NAME, `${status.valueOf()}`));
|
|
5186
|
+
requestResponseMetricTracker[status] = metric;
|
|
5187
|
+
}
|
|
5188
|
+
metric.increment();
|
|
5189
|
+
}
|
|
5190
|
+
function logObjectInfoChanged() {
|
|
5191
|
+
logObjectInfoChanged$1();
|
|
5192
|
+
}
|
|
5193
|
+
/**
|
|
5194
|
+
* Create a new instrumentation cache stats and return it.
|
|
5195
|
+
*
|
|
5196
|
+
* @param name The cache logger name.
|
|
5197
|
+
*/
|
|
5198
|
+
function registerLdsCacheStats(name) {
|
|
5199
|
+
return registerCacheStats(`${NAMESPACE}:${name}`);
|
|
5200
|
+
}
|
|
5201
|
+
/**
|
|
5202
|
+
* Add or overwrite hooks that require aura implementations
|
|
5203
|
+
*/
|
|
5204
|
+
function setAuraInstrumentationHooks() {
|
|
5205
|
+
instrument({
|
|
5206
|
+
recordConflictsResolved: (serverRequestCount) => {
|
|
5207
|
+
// Ignore 0 values which can originate from ADS bridge
|
|
5208
|
+
if (serverRequestCount > 0) {
|
|
5209
|
+
updatePercentileHistogramMetric('record-conflicts-resolved', serverRequestCount);
|
|
5210
|
+
}
|
|
5211
|
+
},
|
|
5212
|
+
nullDisplayValueConflict: ({ fieldType, areValuesEqual }) => {
|
|
5213
|
+
const metricName = `merge-null-dv-count.${fieldType}`;
|
|
5214
|
+
if (fieldType === 'scalar') {
|
|
5215
|
+
incrementCounterMetric(`${metricName}.${areValuesEqual}`);
|
|
5216
|
+
}
|
|
5217
|
+
else {
|
|
5218
|
+
incrementCounterMetric(metricName);
|
|
5219
|
+
}
|
|
5220
|
+
},
|
|
5221
|
+
getRecordNotifyChangeAllowed: incrementGetRecordNotifyChangeAllowCount,
|
|
5222
|
+
getRecordNotifyChangeDropped: incrementGetRecordNotifyChangeDropCount,
|
|
5223
|
+
notifyRecordUpdateAvailableAllowed: incrementNotifyRecordUpdateAvailableAllowCount,
|
|
5224
|
+
notifyRecordUpdateAvailableDropped: incrementNotifyRecordUpdateAvailableDropCount,
|
|
5225
|
+
recordApiNameChanged: instrumentation.incrementRecordApiNameChangeCount.bind(instrumentation),
|
|
5226
|
+
weakEtagZero: instrumentation.aggregateWeakETagEvents.bind(instrumentation),
|
|
5227
|
+
getRecordNotifyChangeNetworkResult: instrumentation.notifyChangeNetwork.bind(instrumentation),
|
|
5228
|
+
});
|
|
5229
|
+
withRegistration('@salesforce/lds-adapters-uiapi', (reg) => setLdsAdaptersUiapiInstrumentation(reg));
|
|
5230
|
+
instrument$1({
|
|
5231
|
+
logCrud: logCRUDLightningInteraction,
|
|
5232
|
+
networkResponse: incrementRequestResponseCount,
|
|
5233
|
+
});
|
|
5234
|
+
instrument$2({
|
|
5235
|
+
error: logError$2,
|
|
5236
|
+
});
|
|
5237
|
+
instrument$3({
|
|
5238
|
+
refreshCalled: instrumentation.handleRefreshApiCall.bind(instrumentation),
|
|
5239
|
+
instrumentAdapter: instrumentation.instrumentAdapter.bind(instrumentation),
|
|
5240
|
+
});
|
|
5241
|
+
instrument$4({
|
|
5242
|
+
timerMetricAddDuration: updateTimerMetric,
|
|
5243
|
+
});
|
|
5244
|
+
// Our getRecord through aggregate-ui CRUD logging has moved
|
|
5245
|
+
// to lds-network-adapter. We still need to respect the
|
|
5246
|
+
// orgs environment setting
|
|
5247
|
+
if (forceRecordTransactionsDisabled$1 === false) {
|
|
5248
|
+
ldsNetworkAdapterInstrument({
|
|
5249
|
+
getRecordAggregateResolve: (cb) => {
|
|
5250
|
+
const { recordId, apiName } = cb();
|
|
5251
|
+
logCRUDLightningInteraction('read', {
|
|
5252
|
+
recordId,
|
|
5253
|
+
recordType: apiName,
|
|
5254
|
+
state: 'SUCCESS',
|
|
5255
|
+
});
|
|
5256
|
+
},
|
|
5257
|
+
getRecordAggregateReject: (cb) => {
|
|
5258
|
+
const recordId = cb();
|
|
5259
|
+
logCRUDLightningInteraction('read', {
|
|
5260
|
+
recordId,
|
|
5261
|
+
state: 'ERROR',
|
|
5262
|
+
});
|
|
5263
|
+
},
|
|
5264
|
+
});
|
|
5265
|
+
}
|
|
5266
|
+
withRegistration('@salesforce/lds-network-adapter', (reg) => setLdsNetworkAdapterInstrumentation(reg));
|
|
5267
|
+
}
|
|
5268
|
+
let stateManagerInstrumentationHooksInitialized = false;
|
|
5269
|
+
function setStateManagerInstrumentationHooks() {
|
|
5270
|
+
if (stateManagerInstrumentationHooksInitialized) {
|
|
5271
|
+
return;
|
|
4355
5272
|
}
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
5273
|
+
instrument$5({
|
|
5274
|
+
stateCreated: incrementStateCreatedCount,
|
|
5275
|
+
});
|
|
5276
|
+
stateManagerInstrumentationHooksInitialized = true;
|
|
5277
|
+
}
|
|
5278
|
+
/**
|
|
5279
|
+
* Initialize the instrumentation and instrument the LDS instance and the InMemoryStore.
|
|
5280
|
+
*
|
|
5281
|
+
* @param luvio The Luvio instance to instrument.
|
|
5282
|
+
* @param store The InMemoryStore to instrument.
|
|
5283
|
+
*/
|
|
5284
|
+
function setupInstrumentation(luvio, store) {
|
|
5285
|
+
setupInstrumentation$1(luvio, store);
|
|
5286
|
+
setAuraInstrumentationHooks();
|
|
5287
|
+
setStateManagerInstrumentationHooks();
|
|
5288
|
+
}
|
|
5289
|
+
/**
|
|
5290
|
+
* Note: locator.scope is set to 'force_record' in order for the instrumentation gate to work, which will
|
|
5291
|
+
* disable all crud operations if it is on.
|
|
5292
|
+
* @param eventSource - Source of the logging event.
|
|
5293
|
+
* @param attributes - Free form object of attributes to log.
|
|
5294
|
+
*/
|
|
5295
|
+
function logCRUDLightningInteraction(eventSource, attributes) {
|
|
5296
|
+
interaction(eventSource, 'force_record', null, eventSource, 'crud', attributes);
|
|
5297
|
+
}
|
|
5298
|
+
const instrumentation = new Instrumentation();
|
|
5299
|
+
|
|
5300
|
+
const forceRecordTransactionsDisabled = getEnvironmentSetting(EnvironmentSettings.ForceRecordTransactionsDisabled);
|
|
5301
|
+
//TODO: Some duplication here that can be most likely moved to a util class
|
|
5302
|
+
const NO_RECORD_ID_204 = '204_NO_RECORD_ID';
|
|
5303
|
+
const NO_RECORD_TYPE_204 = '204_NO_RECORD_TYPE';
|
|
5304
|
+
let crudInstrumentationCallbacks = {};
|
|
5305
|
+
let crudRLInstrumentationCallbacks = {};
|
|
5306
|
+
if (forceRecordTransactionsDisabled === false) {
|
|
5307
|
+
// Record callbacks
|
|
5308
|
+
crudInstrumentationCallbacks = {
|
|
5309
|
+
createRecordRejectFunction: (config) => {
|
|
5310
|
+
logCRUDLightningInteraction(CrudEventType.CREATE, {
|
|
5311
|
+
// recordId: config.params.recordInput.apiName, // seems wrong?
|
|
5312
|
+
recordId: config.params.recordId || NO_RECORD_ID_204,
|
|
5313
|
+
state: CrudEventState.ERROR,
|
|
5314
|
+
});
|
|
5315
|
+
},
|
|
5316
|
+
createRecordResolveFunction: (config) => {
|
|
5317
|
+
const recordId = config.body ? config.body.id : NO_RECORD_ID_204;
|
|
5318
|
+
const recordType = config.body ? config.body.apiName : NO_RECORD_TYPE_204;
|
|
5319
|
+
logCRUDLightningInteraction(CrudEventType.CREATE, {
|
|
5320
|
+
recordId,
|
|
5321
|
+
recordType,
|
|
5322
|
+
state: CrudEventState.SUCCESS,
|
|
5323
|
+
});
|
|
5324
|
+
},
|
|
5325
|
+
deleteRecordRejectFunction: (config) => {
|
|
5326
|
+
logCRUDLightningInteraction(CrudEventType.DELETE, {
|
|
5327
|
+
recordId: config.params.recordId,
|
|
5328
|
+
state: CrudEventState.ERROR,
|
|
5329
|
+
});
|
|
5330
|
+
},
|
|
5331
|
+
deleteRecordResolveFunction: (config) => {
|
|
5332
|
+
logCRUDLightningInteraction(CrudEventType.DELETE, {
|
|
5333
|
+
recordId: config.params.recordId,
|
|
5334
|
+
state: CrudEventState.SUCCESS,
|
|
5335
|
+
});
|
|
5336
|
+
},
|
|
5337
|
+
// These should be handled by the network adapater?
|
|
5338
|
+
// getRecordAggregateRejectFunction: (config: InstrumentationRejectConfig) => {
|
|
5339
|
+
// logCRUDLightningInteraction(CrudEventType.READ, {
|
|
5340
|
+
// recordId: config.params.recordId,
|
|
5341
|
+
// state: CrudEventState.ERROR,
|
|
5342
|
+
// });
|
|
5343
|
+
// },
|
|
5344
|
+
// getRecordAggregateResolveFunction: (config: InstrumentationResolveConfig) => {
|
|
5345
|
+
// logCRUDLightningInteraction(CrudEventType.READ, {
|
|
5346
|
+
// recordId: config.params.recordId,
|
|
5347
|
+
// recordType: config.body.apiName,
|
|
5348
|
+
// state: CrudEventState.SUCCESS,
|
|
5349
|
+
// });
|
|
5350
|
+
// },
|
|
5351
|
+
getRecordRejectFunction: (config) => {
|
|
5352
|
+
logCRUDLightningInteraction(CrudEventType.READ, {
|
|
5353
|
+
recordId: config.params.recordId,
|
|
5354
|
+
state: CrudEventState.ERROR,
|
|
5355
|
+
});
|
|
5356
|
+
},
|
|
5357
|
+
getRecordResolveFunction: (config) => {
|
|
5358
|
+
logCRUDLightningInteraction(CrudEventType.READ, {
|
|
5359
|
+
recordId: config.params.recordId,
|
|
5360
|
+
recordType: config.body.apiName,
|
|
5361
|
+
state: CrudEventState.SUCCESS,
|
|
5362
|
+
});
|
|
5363
|
+
},
|
|
5364
|
+
updateRecordRejectFunction: (config) => {
|
|
5365
|
+
logCRUDLightningInteraction(CrudEventType.UPDATE, {
|
|
5366
|
+
recordId: config.params.recordId,
|
|
5367
|
+
state: CrudEventState.ERROR,
|
|
5368
|
+
});
|
|
5369
|
+
},
|
|
5370
|
+
updateRecordResolveFunction: (config) => {
|
|
5371
|
+
const recordType = config.body ? config.body.apiName : NO_RECORD_TYPE_204;
|
|
5372
|
+
logCRUDLightningInteraction(CrudEventType.UPDATE, {
|
|
5373
|
+
recordId: config.params.recordId,
|
|
5374
|
+
recordType,
|
|
5375
|
+
state: CrudEventState.SUCCESS,
|
|
5376
|
+
});
|
|
5377
|
+
},
|
|
5378
|
+
};
|
|
5379
|
+
// Related list callbacks
|
|
5380
|
+
crudRLInstrumentationCallbacks = {
|
|
5381
|
+
getRelatedListRecordsRejectFunction: (config) => {
|
|
5382
|
+
logCRUDLightningInteraction(CrudEventType.READS, {
|
|
5383
|
+
parentRecordId: config.params.parentRecordId,
|
|
5384
|
+
relatedListId: config.params.relatedListId,
|
|
5385
|
+
state: CrudEventState.ERROR,
|
|
5386
|
+
});
|
|
5387
|
+
},
|
|
5388
|
+
getRelatedListRecordsResolveFunction: (config) => {
|
|
5389
|
+
logGetRelatedListRecordsInteraction(config.body);
|
|
5390
|
+
},
|
|
5391
|
+
getRelatedListRecordsBatchRejectFunction: (config) => {
|
|
5392
|
+
logCRUDLightningInteraction(CrudEventType.READS, {
|
|
5393
|
+
parentRecordId: config.params.parentRecordId,
|
|
5394
|
+
relatedListIds: config.params.relatedListParameters.map((entry) => entry.relatedListId),
|
|
5395
|
+
state: CrudEventState.ERROR,
|
|
5396
|
+
});
|
|
5397
|
+
},
|
|
5398
|
+
getRelatedListRecordsBatchResolveFunction: (config) => {
|
|
5399
|
+
config.body.results.forEach((res) => {
|
|
5400
|
+
// Log for each RL that was returned from batch endpoint
|
|
5401
|
+
if (res.statusCode === 200) {
|
|
5402
|
+
logGetRelatedListRecordsInteraction(res.result);
|
|
5403
|
+
}
|
|
5404
|
+
});
|
|
5405
|
+
},
|
|
5406
|
+
};
|
|
5407
|
+
}
|
|
5408
|
+
// Helper function copied from ui-api
|
|
5409
|
+
function logGetRelatedListRecordsInteraction(body) {
|
|
5410
|
+
const records = body.records;
|
|
5411
|
+
// Don't log anything if the related list has no records.
|
|
5412
|
+
if (records.length === 0) {
|
|
5413
|
+
return;
|
|
4365
5414
|
}
|
|
5415
|
+
const recordIds = records.map((record) => {
|
|
5416
|
+
return record.id;
|
|
5417
|
+
});
|
|
4366
5418
|
/**
|
|
4367
|
-
*
|
|
5419
|
+
* In almost every case - the relatedList records will all be of the same apiName, but there is an edge case for
|
|
5420
|
+
Activities entity that could return Events & Tasks- so handle that case by returning a joined string.
|
|
5421
|
+
ADS Implementation only looks at the first record returned to determine the apiName.
|
|
5422
|
+
See force/recordLibrary/recordMetricsPlugin.js _getRecordType method.
|
|
4368
5423
|
*/
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
5424
|
+
logCRUDLightningInteraction(CrudEventType.READS, {
|
|
5425
|
+
parentRecordId: body.listReference.inContextOfRecordId,
|
|
5426
|
+
relatedListId: body.listReference.relatedListId,
|
|
5427
|
+
recordIds,
|
|
5428
|
+
recordType: body.records[0].apiName,
|
|
5429
|
+
state: CrudEventState.SUCCESS,
|
|
5430
|
+
});
|
|
5431
|
+
}
|
|
5432
|
+
const crudInstrumentationConfig = {
|
|
5433
|
+
records: {
|
|
5434
|
+
post: {
|
|
5435
|
+
rejectFn: crudInstrumentationCallbacks.createRecordRejectFunction,
|
|
5436
|
+
resolveFn: crudInstrumentationCallbacks.createRecordResolveFunction,
|
|
5437
|
+
},
|
|
5438
|
+
get: {
|
|
5439
|
+
rejectFn: crudInstrumentationCallbacks.getRecordRejectFunction,
|
|
5440
|
+
resolveFn: crudInstrumentationCallbacks.getRecordResolveFunction,
|
|
5441
|
+
},
|
|
5442
|
+
patch: {
|
|
5443
|
+
rejectFn: crudInstrumentationCallbacks.updateRecordRejectFunction,
|
|
5444
|
+
resolveFn: crudInstrumentationCallbacks.updateRecordResolveFunction,
|
|
5445
|
+
},
|
|
5446
|
+
delete: {
|
|
5447
|
+
rejectFn: crudInstrumentationCallbacks.deleteRecordRejectFunction,
|
|
5448
|
+
resolveFn: crudInstrumentationCallbacks.deleteRecordResolveFunction,
|
|
5449
|
+
},
|
|
5450
|
+
},
|
|
5451
|
+
relatedListRecords: {
|
|
5452
|
+
post: {
|
|
5453
|
+
rejectFn: crudRLInstrumentationCallbacks.getRelatedListRecordsRejectFunction,
|
|
5454
|
+
resolveFn: crudRLInstrumentationCallbacks.getRelatedListRecordsResolveFunction,
|
|
5455
|
+
},
|
|
5456
|
+
},
|
|
5457
|
+
relatedListRecordsBatch: {
|
|
5458
|
+
post: {
|
|
5459
|
+
rejectFn: crudRLInstrumentationCallbacks.getRelatedListRecordsBatchRejectFunction,
|
|
5460
|
+
resolveFn: crudRLInstrumentationCallbacks.getRelatedListRecordsBatchResolveFunction,
|
|
5461
|
+
},
|
|
5462
|
+
},
|
|
5463
|
+
};
|
|
5464
|
+
function checkAndLogCrudInteraction(request, isResolve, error, response) {
|
|
5465
|
+
let configPath;
|
|
5466
|
+
const baseUrl = `${request.baseUri}${request.basePath}`;
|
|
5467
|
+
if (baseUrl.startsWith(UIAPI_RECORDS_PATH)) {
|
|
5468
|
+
configPath = crudInstrumentationConfig['records']; // maybe use a constant for this
|
|
4378
5469
|
}
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
* Counter for occurrences where the incoming record to be merged has a different apiName.
|
|
4382
|
-
* Dynamically generated metric, stored in an {@link RecordApiNameChangeCounters} object.
|
|
4383
|
-
*
|
|
4384
|
-
* @param context The transaction context.
|
|
4385
|
-
*
|
|
4386
|
-
* Note: Short-lived metric candidate, remove at the end of 230
|
|
4387
|
-
*/
|
|
4388
|
-
incrementRecordApiNameChangeCount(_incomingApiName, existingApiName) {
|
|
4389
|
-
let apiNameChangeCounter = this.recordApiNameChangeCounters[existingApiName];
|
|
4390
|
-
if (apiNameChangeCounter === undefined) {
|
|
4391
|
-
apiNameChangeCounter = counter(createMetricsKey(NAMESPACE, RECORD_API_NAME_CHANGE_COUNT_METRIC_NAME, existingApiName));
|
|
4392
|
-
this.recordApiNameChangeCounters[existingApiName] = apiNameChangeCounter;
|
|
4393
|
-
}
|
|
4394
|
-
apiNameChangeCounter.increment(1);
|
|
5470
|
+
else if (baseUrl.startsWith(UIAPI_RELATED_LIST_RECORDS_BATCH_PATH)) {
|
|
5471
|
+
configPath = crudInstrumentationConfig['relatedListRecordsBatch'];
|
|
4395
5472
|
}
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
this.adapterUnfulfilledErrorCounters[adapterName] = adapterRequestErrorCounter;
|
|
5473
|
+
else if (baseUrl.startsWith(UIAPI_RELATED_LIST_RECORDS_PATH)) {
|
|
5474
|
+
configPath = crudInstrumentationConfig['relatedListRecords'];
|
|
5475
|
+
}
|
|
5476
|
+
if (configPath) {
|
|
5477
|
+
const crudCallbacks = configPath[request.method];
|
|
5478
|
+
if (crudCallbacks) {
|
|
5479
|
+
if (isResolve && crudCallbacks.resolveFn) {
|
|
5480
|
+
crudCallbacks.resolveFn(setResolveConfig(request, response));
|
|
5481
|
+
}
|
|
5482
|
+
else if (crudCallbacks.rejectFn) {
|
|
5483
|
+
crudCallbacks.rejectFn(setRejectConfig(request, error));
|
|
5484
|
+
}
|
|
4409
5485
|
}
|
|
4410
|
-
adapterRequestErrorCounter.increment(1);
|
|
4411
|
-
totalAdapterErrorMetric.increment(1);
|
|
4412
5486
|
}
|
|
4413
5487
|
}
|
|
4414
|
-
function
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
metricName = metricName + '.' + unit;
|
|
4418
|
-
}
|
|
5488
|
+
function setResolveConfig(request, response) {
|
|
5489
|
+
const responseBody = response ? response.body : {};
|
|
5490
|
+
const urlParams = request.urlParams || {};
|
|
4419
5491
|
return {
|
|
4420
|
-
|
|
4421
|
-
|
|
5492
|
+
body: responseBody,
|
|
5493
|
+
params: {
|
|
5494
|
+
recordId: urlParams.recordId,
|
|
4422
5495
|
},
|
|
4423
5496
|
};
|
|
4424
5497
|
}
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
5498
|
+
function setRejectConfig(request, error) {
|
|
5499
|
+
const requestBody = request.body || {};
|
|
5500
|
+
const urlParams = request.urlParams || {};
|
|
5501
|
+
return {
|
|
5502
|
+
err: error,
|
|
5503
|
+
params: {
|
|
5504
|
+
recordId: urlParams.recordId,
|
|
5505
|
+
// pass these in even if they're undefined
|
|
5506
|
+
parentRecordId: urlParams.parentRecordId,
|
|
5507
|
+
relatedListId: urlParams.relatedListId,
|
|
5508
|
+
relatedListParameters: requestBody.relatedListParameters,
|
|
5509
|
+
},
|
|
5510
|
+
};
|
|
4431
5511
|
}
|
|
5512
|
+
|
|
4432
5513
|
/**
|
|
4433
|
-
*
|
|
4434
|
-
*
|
|
5514
|
+
* Builds a Luvio Request interceptor that adds page-scoped cache headers
|
|
5515
|
+
* to ResourceRequest objects used by the Luvio network adapter.
|
|
4435
5516
|
*
|
|
4436
|
-
*
|
|
4437
|
-
*
|
|
4438
|
-
* ensure to call this method to normalize all logging to 'getApex'. This
|
|
4439
|
-
* is because Argus has a 50k key cardinality limit. More context: W-8379680.
|
|
5517
|
+
* This interceptor works with the Luvio ResourceRequest format, which has
|
|
5518
|
+
* a simpler structure than FetchParameters - headers are always a plain object.
|
|
4440
5519
|
*
|
|
4441
|
-
* @
|
|
4442
|
-
* @param apiFamily The API family of the adapter.
|
|
4443
|
-
*/
|
|
4444
|
-
function normalizeAdapterName(adapterName, apiFamily) {
|
|
4445
|
-
if (isApexAdapter(adapterName)) {
|
|
4446
|
-
return NORMALIZED_APEX_ADAPTER_NAME;
|
|
4447
|
-
}
|
|
4448
|
-
return apiFamily ? `${apiFamily}.${adapterName}` : adapterName;
|
|
4449
|
-
}
|
|
4450
|
-
const timerMetricTracker = create(null);
|
|
4451
|
-
/**
|
|
4452
|
-
* Calls instrumentation/service telemetry timer
|
|
4453
|
-
* @param name Name of the metric
|
|
4454
|
-
* @param duration number to update backing percentile histogram, negative numbers ignored
|
|
5520
|
+
* @returns A RequestInterceptor function for Luvio network requests
|
|
4455
5521
|
*/
|
|
4456
|
-
function
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
if (duration >= 0) {
|
|
4467
|
-
timer.addDuration(duration);
|
|
4468
|
-
}
|
|
5522
|
+
function buildLuvioPageScopedCacheRequestInterceptor() {
|
|
5523
|
+
return (resourceRequest) => {
|
|
5524
|
+
// Ensure headers object exists
|
|
5525
|
+
if (!resourceRequest.headers) {
|
|
5526
|
+
resourceRequest.headers = {};
|
|
5527
|
+
}
|
|
5528
|
+
// Pass the headers to pageScopedCache which will mutate them
|
|
5529
|
+
pageScopedCache.addHeader(resourceRequest.headers);
|
|
5530
|
+
return resolvedPromiseLike$2(resourceRequest);
|
|
5531
|
+
};
|
|
4469
5532
|
}
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
5533
|
+
|
|
5534
|
+
function buildLexRuntimeAuthExpirationRedirectResponseInterceptor(logger) {
|
|
5535
|
+
return async (response) => {
|
|
5536
|
+
if (response.status === 401) {
|
|
5537
|
+
try {
|
|
5538
|
+
const coercedResponse = (await coerceResponseToFetchResponse(response.clone()));
|
|
5539
|
+
if (coercedResponse.body.errorCode === 'INVALID_SESSION_ID') {
|
|
5540
|
+
logger.warn(`Received ${response.status} status code from LEX runtime service`);
|
|
5541
|
+
// Fire the event asynchronously, similar to the legacy setTimeout pattern
|
|
5542
|
+
window.setTimeout(() => {
|
|
5543
|
+
dispatchGlobalEvent('aura:invalidSession');
|
|
5544
|
+
}, 0);
|
|
5545
|
+
}
|
|
5546
|
+
}
|
|
5547
|
+
catch (error) {
|
|
5548
|
+
logger.warn(`Error parsing response from LEX runtime service: ${error}`);
|
|
5549
|
+
}
|
|
5550
|
+
}
|
|
5551
|
+
return response;
|
|
5552
|
+
};
|
|
4483
5553
|
}
|
|
4484
|
-
function
|
|
4485
|
-
|
|
5554
|
+
function buildLexRuntimeLuvioAuthExpirationRedirectResponseInterceptor() {
|
|
5555
|
+
return async (response) => {
|
|
5556
|
+
if (response.status === 401) {
|
|
5557
|
+
if (response.body.errorCode === 'INVALID_SESSION_ID') {
|
|
5558
|
+
window.setTimeout(() => {
|
|
5559
|
+
dispatchGlobalEvent('aura:invalidSession');
|
|
5560
|
+
}, 0);
|
|
5561
|
+
}
|
|
5562
|
+
}
|
|
5563
|
+
return response;
|
|
5564
|
+
};
|
|
4486
5565
|
}
|
|
5566
|
+
|
|
4487
5567
|
/**
|
|
4488
|
-
*
|
|
5568
|
+
* Extracts the ErrorId from a server error response message.
|
|
5569
|
+
* Looks for pattern: "ErrorId if you contact support: 1033627214-37969 (-1272663771)"
|
|
5570
|
+
* Returns the numeric value in parentheses.
|
|
4489
5571
|
*
|
|
4490
|
-
* @param
|
|
4491
|
-
|
|
4492
|
-
function registerLdsCacheStats(name) {
|
|
4493
|
-
return registerCacheStats(`${NAMESPACE}:${name}`);
|
|
4494
|
-
}
|
|
4495
|
-
/**
|
|
4496
|
-
* Add or overwrite hooks that require aura implementations
|
|
5572
|
+
* @param responseBody The response body text to parse.
|
|
5573
|
+
* @returns The extracted error ID, or null if not found.
|
|
4497
5574
|
*/
|
|
4498
|
-
function
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
incrementCounterMetric(`${metricName}.${areValuesEqual}`);
|
|
4510
|
-
}
|
|
4511
|
-
else {
|
|
4512
|
-
incrementCounterMetric(metricName);
|
|
4513
|
-
}
|
|
4514
|
-
},
|
|
4515
|
-
getRecordNotifyChangeAllowed: incrementGetRecordNotifyChangeAllowCount,
|
|
4516
|
-
getRecordNotifyChangeDropped: incrementGetRecordNotifyChangeDropCount,
|
|
4517
|
-
notifyRecordUpdateAvailableAllowed: incrementNotifyRecordUpdateAvailableAllowCount,
|
|
4518
|
-
notifyRecordUpdateAvailableDropped: incrementNotifyRecordUpdateAvailableDropCount,
|
|
4519
|
-
recordApiNameChanged: instrumentation.incrementRecordApiNameChangeCount.bind(instrumentation),
|
|
4520
|
-
weakEtagZero: instrumentation.aggregateWeakETagEvents.bind(instrumentation),
|
|
4521
|
-
getRecordNotifyChangeNetworkResult: instrumentation.notifyChangeNetwork.bind(instrumentation),
|
|
4522
|
-
});
|
|
4523
|
-
withRegistration('@salesforce/lds-adapters-uiapi', (reg) => setLdsAdaptersUiapiInstrumentation(reg));
|
|
4524
|
-
instrument$1({
|
|
4525
|
-
logCrud: logCRUDLightningInteraction,
|
|
4526
|
-
networkResponse: incrementRequestResponseCount,
|
|
4527
|
-
});
|
|
4528
|
-
instrument$2({
|
|
4529
|
-
error: logError,
|
|
4530
|
-
});
|
|
4531
|
-
instrument$3({
|
|
4532
|
-
refreshCalled: instrumentation.handleRefreshApiCall.bind(instrumentation),
|
|
4533
|
-
instrumentAdapter: instrumentation.instrumentAdapter.bind(instrumentation),
|
|
4534
|
-
});
|
|
4535
|
-
instrument$4({
|
|
4536
|
-
timerMetricAddDuration: updateTimerMetric,
|
|
4537
|
-
});
|
|
4538
|
-
// Our getRecord through aggregate-ui CRUD logging has moved
|
|
4539
|
-
// to lds-network-adapter. We still need to respect the
|
|
4540
|
-
// orgs environment setting
|
|
4541
|
-
if (forceRecordTransactionsDisabled$1 === false) {
|
|
4542
|
-
ldsNetworkAdapterInstrument({
|
|
4543
|
-
getRecordAggregateResolve: (cb) => {
|
|
4544
|
-
const { recordId, apiName } = cb();
|
|
4545
|
-
logCRUDLightningInteraction('read', {
|
|
4546
|
-
recordId,
|
|
4547
|
-
recordType: apiName,
|
|
4548
|
-
state: 'SUCCESS',
|
|
4549
|
-
});
|
|
4550
|
-
},
|
|
4551
|
-
getRecordAggregateReject: (cb) => {
|
|
4552
|
-
const recordId = cb();
|
|
4553
|
-
logCRUDLightningInteraction('read', {
|
|
4554
|
-
recordId,
|
|
4555
|
-
state: 'ERROR',
|
|
4556
|
-
});
|
|
4557
|
-
},
|
|
4558
|
-
});
|
|
5575
|
+
function extractErrorIdFromResponse(responseBody) {
|
|
5576
|
+
try {
|
|
5577
|
+
const parsed = JSON.parse(responseBody);
|
|
5578
|
+
if (Array.isArray(parsed) && parsed.length > 0 && parsed[0].message) {
|
|
5579
|
+
const message = parsed[0].message;
|
|
5580
|
+
// Look for pattern: "ErrorId if you contact support: XXXXXX-XXXXX (YYYYY)"
|
|
5581
|
+
const match = message.match(/ErrorId[^:]*:\s*[\d-]+\s*\((-?\d+)\)/);
|
|
5582
|
+
if (match && match[1]) {
|
|
5583
|
+
return parseInt(match[1], 10);
|
|
5584
|
+
}
|
|
5585
|
+
}
|
|
4559
5586
|
}
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
let stateManagerInstrumentationHooksInitialized = false;
|
|
4563
|
-
function setStateManagerInstrumentationHooks() {
|
|
4564
|
-
if (stateManagerInstrumentationHooksInitialized) {
|
|
4565
|
-
return;
|
|
5587
|
+
catch (e) {
|
|
5588
|
+
// If parsing fails, return null to use fallback
|
|
4566
5589
|
}
|
|
4567
|
-
|
|
4568
|
-
stateCreated: incrementStateCreatedCount,
|
|
4569
|
-
});
|
|
4570
|
-
stateManagerInstrumentationHooksInitialized = true;
|
|
5590
|
+
return null;
|
|
4571
5591
|
}
|
|
4572
5592
|
/**
|
|
4573
|
-
*
|
|
5593
|
+
* Generates a unique error ID for tracking specific error occurrences.
|
|
5594
|
+
* Used as fallback when server doesn't provide an ErrorId.
|
|
4574
5595
|
*
|
|
4575
|
-
* @param
|
|
4576
|
-
* @
|
|
5596
|
+
* @param idInput The input value to hash.
|
|
5597
|
+
* @returns A unique error ID in Salesforce-compatible numeric format.
|
|
4577
5598
|
*/
|
|
4578
|
-
function
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
5599
|
+
function generateErrorId(idInput) {
|
|
5600
|
+
let hash = 0;
|
|
5601
|
+
if (!idInput || idInput.length === 0) {
|
|
5602
|
+
return hash;
|
|
5603
|
+
}
|
|
5604
|
+
let i, chr;
|
|
5605
|
+
for (i = 0; i < idInput.length; i++) {
|
|
5606
|
+
chr = idInput.charCodeAt(i);
|
|
5607
|
+
hash = (hash << 5) - hash + chr;
|
|
5608
|
+
hash |= 0; // Convert to 32bit integer
|
|
5609
|
+
}
|
|
5610
|
+
return hash;
|
|
4582
5611
|
}
|
|
4583
5612
|
/**
|
|
4584
|
-
*
|
|
4585
|
-
*
|
|
4586
|
-
*
|
|
4587
|
-
* @param
|
|
5613
|
+
* Gets error ID from response body or generates a fallback.
|
|
5614
|
+
* Tries to extract server-provided ErrorId first, falls back to generated hash.
|
|
5615
|
+
*
|
|
5616
|
+
* @param responseBody The response body to parse.
|
|
5617
|
+
* @param status The HTTP status code (for fallback).
|
|
5618
|
+
* @param statusText The HTTP status text (for fallback, optional).
|
|
5619
|
+
* @returns A numeric error ID.
|
|
4588
5620
|
*/
|
|
4589
|
-
function
|
|
4590
|
-
|
|
5621
|
+
function getOrGenerateErrorId(responseBody, status, statusText) {
|
|
5622
|
+
const extractedId = extractErrorIdFromResponse(responseBody);
|
|
5623
|
+
if (extractedId !== null) {
|
|
5624
|
+
return extractedId;
|
|
5625
|
+
}
|
|
5626
|
+
// Fallback to generated error ID using status and timestamp
|
|
5627
|
+
// statusText is optional and may not always be present
|
|
5628
|
+
const context = [status, statusText || '', Date.now()].join('|');
|
|
5629
|
+
return generateErrorId(context);
|
|
4591
5630
|
}
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
const
|
|
4598
|
-
|
|
4599
|
-
let
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
//
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
}
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
}
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
// recordId: config.params.recordId,
|
|
4635
|
-
// state: CrudEventState.ERROR,
|
|
4636
|
-
// });
|
|
4637
|
-
// },
|
|
4638
|
-
// getRecordAggregateResolveFunction: (config: InstrumentationResolveConfig) => {
|
|
4639
|
-
// logCRUDLightningInteraction(CrudEventType.READ, {
|
|
4640
|
-
// recordId: config.params.recordId,
|
|
4641
|
-
// recordType: config.body.apiName,
|
|
4642
|
-
// state: CrudEventState.SUCCESS,
|
|
4643
|
-
// });
|
|
4644
|
-
// },
|
|
4645
|
-
getRecordRejectFunction: (config) => {
|
|
4646
|
-
logCRUDLightningInteraction(CrudEventType.READ, {
|
|
4647
|
-
recordId: config.params.recordId,
|
|
4648
|
-
state: CrudEventState.ERROR,
|
|
4649
|
-
});
|
|
4650
|
-
},
|
|
4651
|
-
getRecordResolveFunction: (config) => {
|
|
4652
|
-
logCRUDLightningInteraction(CrudEventType.READ, {
|
|
4653
|
-
recordId: config.params.recordId,
|
|
4654
|
-
recordType: config.body.apiName,
|
|
4655
|
-
state: CrudEventState.SUCCESS,
|
|
4656
|
-
});
|
|
4657
|
-
},
|
|
4658
|
-
updateRecordRejectFunction: (config) => {
|
|
4659
|
-
logCRUDLightningInteraction(CrudEventType.UPDATE, {
|
|
4660
|
-
recordId: config.params.recordId,
|
|
4661
|
-
state: CrudEventState.ERROR,
|
|
4662
|
-
});
|
|
4663
|
-
},
|
|
4664
|
-
updateRecordResolveFunction: (config) => {
|
|
4665
|
-
const recordType = config.body ? config.body.apiName : NO_RECORD_TYPE_204;
|
|
4666
|
-
logCRUDLightningInteraction(CrudEventType.UPDATE, {
|
|
4667
|
-
recordId: config.params.recordId,
|
|
4668
|
-
recordType,
|
|
4669
|
-
state: CrudEventState.SUCCESS,
|
|
4670
|
-
});
|
|
4671
|
-
},
|
|
4672
|
-
};
|
|
4673
|
-
// Related list callbacks
|
|
4674
|
-
crudRLInstrumentationCallbacks = {
|
|
4675
|
-
getRelatedListRecordsRejectFunction: (config) => {
|
|
4676
|
-
logCRUDLightningInteraction(CrudEventType.READS, {
|
|
4677
|
-
parentRecordId: config.params.parentRecordId,
|
|
4678
|
-
relatedListId: config.params.relatedListId,
|
|
4679
|
-
state: CrudEventState.ERROR,
|
|
4680
|
-
});
|
|
4681
|
-
},
|
|
4682
|
-
getRelatedListRecordsResolveFunction: (config) => {
|
|
4683
|
-
logGetRelatedListRecordsInteraction(config.body);
|
|
4684
|
-
},
|
|
4685
|
-
getRelatedListRecordsBatchRejectFunction: (config) => {
|
|
4686
|
-
logCRUDLightningInteraction(CrudEventType.READS, {
|
|
4687
|
-
parentRecordId: config.params.parentRecordId,
|
|
4688
|
-
relatedListIds: config.params.relatedListParameters.map((entry) => entry.relatedListId),
|
|
4689
|
-
state: CrudEventState.ERROR,
|
|
4690
|
-
});
|
|
4691
|
-
},
|
|
4692
|
-
getRelatedListRecordsBatchResolveFunction: (config) => {
|
|
4693
|
-
config.body.results.forEach((res) => {
|
|
4694
|
-
// Log for each RL that was returned from batch endpoint
|
|
4695
|
-
if (res.statusCode === 200) {
|
|
4696
|
-
logGetRelatedListRecordsInteraction(res.result);
|
|
4697
|
-
}
|
|
4698
|
-
});
|
|
4699
|
-
},
|
|
5631
|
+
function buildLexRuntime5xxStatusResponseInterceptor(logger) {
|
|
5632
|
+
return async (response) => {
|
|
5633
|
+
if (response.status >= 500 && response.status < 600) {
|
|
5634
|
+
const internalLogMessage = `LEX runtime 5xx: ${response.status} ${response.statusText || ''}`.trim();
|
|
5635
|
+
logger.warn(internalLogMessage);
|
|
5636
|
+
const userMessage = 'A server error occurred. Please try again later.';
|
|
5637
|
+
// Try to extract ErrorId from response body, fallback to generated ID
|
|
5638
|
+
let errorId;
|
|
5639
|
+
try {
|
|
5640
|
+
const responseText = await response.clone().text();
|
|
5641
|
+
errorId = getOrGenerateErrorId(responseText, response.status, response.statusText);
|
|
5642
|
+
}
|
|
5643
|
+
catch (e) {
|
|
5644
|
+
// If reading response fails, use fallback
|
|
5645
|
+
const context = [response.status, response.statusText, Date.now()].join('|');
|
|
5646
|
+
errorId = generateErrorId(context);
|
|
5647
|
+
}
|
|
5648
|
+
// Create an error object similar to Aura's current shape for system errors
|
|
5649
|
+
const error = {
|
|
5650
|
+
message: userMessage,
|
|
5651
|
+
severity: 'ALERT',
|
|
5652
|
+
name: 'LEXRuntimeError',
|
|
5653
|
+
stack: null,
|
|
5654
|
+
handled: false,
|
|
5655
|
+
reported: false,
|
|
5656
|
+
id: errorId,
|
|
5657
|
+
};
|
|
5658
|
+
const evtArgs = {
|
|
5659
|
+
message: error.message,
|
|
5660
|
+
error: null,
|
|
5661
|
+
auraError: error,
|
|
5662
|
+
};
|
|
5663
|
+
// Fire the event asynchronously, similar to the legacy setTimeout pattern
|
|
5664
|
+
window.setTimeout(() => {
|
|
5665
|
+
dispatchGlobalEvent('markup://aura:systemError', evtArgs);
|
|
5666
|
+
}, 0);
|
|
5667
|
+
// Throw a simple error to terminate the request completely
|
|
5668
|
+
// The consumer has NOT opted in to handle 5xx errors, so we don't return any response
|
|
5669
|
+
// The systemError event above will handle showing the gack dialog
|
|
5670
|
+
throw new Error(error.message);
|
|
5671
|
+
}
|
|
5672
|
+
return response;
|
|
4700
5673
|
};
|
|
4701
5674
|
}
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
5675
|
+
function buildLexRuntimeLuvio5xxStatusResponseInterceptor() {
|
|
5676
|
+
return async (response) => {
|
|
5677
|
+
if (response.status >= 500 && response.status < 600) {
|
|
5678
|
+
const userMessage = 'A server error occurred. Please try again later.';
|
|
5679
|
+
// Try to extract ErrorId from response body, fallback to generated ID
|
|
5680
|
+
let errorId;
|
|
5681
|
+
try {
|
|
5682
|
+
const responseBody = response.body ? JSON.stringify(response.body) : '';
|
|
5683
|
+
errorId = getOrGenerateErrorId(responseBody, response.status, response.statusText);
|
|
5684
|
+
}
|
|
5685
|
+
catch (e) {
|
|
5686
|
+
// If reading response fails, use fallback
|
|
5687
|
+
const context = [response.status, response.statusText, Date.now()].join('|');
|
|
5688
|
+
errorId = generateErrorId(context);
|
|
5689
|
+
}
|
|
5690
|
+
// Create an error object similar to Aura's current shape for system errors
|
|
5691
|
+
const error = {
|
|
5692
|
+
message: userMessage,
|
|
5693
|
+
severity: 'ALERT',
|
|
5694
|
+
name: 'LEXRuntimeError',
|
|
5695
|
+
stack: null,
|
|
5696
|
+
handled: false,
|
|
5697
|
+
reported: false,
|
|
5698
|
+
id: errorId,
|
|
5699
|
+
};
|
|
5700
|
+
const evtArgs = {
|
|
5701
|
+
message: error.message,
|
|
5702
|
+
error: null,
|
|
5703
|
+
auraError: error,
|
|
5704
|
+
};
|
|
5705
|
+
// Fire the event asynchronously, similar to the legacy setTimeout pattern
|
|
5706
|
+
window.setTimeout(() => {
|
|
5707
|
+
dispatchGlobalEvent('markup://aura:systemError', evtArgs);
|
|
5708
|
+
}, 0);
|
|
5709
|
+
// Throw a simple error to terminate the request completely
|
|
5710
|
+
// The consumer has NOT opted in to handle 5xx errors, so we don't return any response
|
|
5711
|
+
// The systemError event above will handle showing the gack dialog
|
|
5712
|
+
throw new Error(error.message);
|
|
5713
|
+
}
|
|
5714
|
+
return response;
|
|
5715
|
+
};
|
|
5716
|
+
}
|
|
5717
|
+
|
|
5718
|
+
const CSRF_TOKEN_KEY = 'salesforce_csrf_token';
|
|
5719
|
+
const CSRF_STORAGE_NAME = 'ldsCSRFToken';
|
|
5720
|
+
const CSRF_STORAGE_CONFIG = {
|
|
5721
|
+
name: CSRF_STORAGE_NAME,
|
|
5722
|
+
persistent: true,
|
|
5723
|
+
secure: true,
|
|
5724
|
+
maxSize: 1024,
|
|
5725
|
+
expiration: 24 * 60 * 60,
|
|
5726
|
+
clearOnInit: false,
|
|
5727
|
+
debugLogging: false,
|
|
5728
|
+
};
|
|
5729
|
+
/**
|
|
5730
|
+
* Manages CSRF token fetching and caching for secure requests.
|
|
5731
|
+
* Implements a singleton pattern to ensure consistent token management across the application.
|
|
5732
|
+
*/
|
|
5733
|
+
class CsrfTokenManager {
|
|
5734
|
+
constructor() {
|
|
5735
|
+
// Initialize AuraStorage
|
|
5736
|
+
this.storage = createStorage(CSRF_STORAGE_CONFIG);
|
|
5737
|
+
// Try to load token from AuraStorage on initialization
|
|
5738
|
+
this.tokenPromise = this.loadOrFetchToken();
|
|
5739
|
+
}
|
|
5740
|
+
static getInstance() {
|
|
5741
|
+
if (!CsrfTokenManager.instance) {
|
|
5742
|
+
CsrfTokenManager.instance = new CsrfTokenManager();
|
|
5743
|
+
}
|
|
5744
|
+
return CsrfTokenManager.instance;
|
|
4708
5745
|
}
|
|
4709
|
-
const recordIds = records.map((record) => {
|
|
4710
|
-
return record.id;
|
|
4711
|
-
});
|
|
4712
5746
|
/**
|
|
4713
|
-
*
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
See force/recordLibrary/recordMetricsPlugin.js _getRecordType method.
|
|
5747
|
+
* Obtain a CSRF token, either from AuraStorage or by fetching a fresh one.
|
|
5748
|
+
*
|
|
5749
|
+
* @private
|
|
4717
5750
|
*/
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
}
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
rejectFn: crudInstrumentationCallbacks.getRecordRejectFunction,
|
|
4734
|
-
resolveFn: crudInstrumentationCallbacks.getRecordResolveFunction,
|
|
4735
|
-
},
|
|
4736
|
-
patch: {
|
|
4737
|
-
rejectFn: crudInstrumentationCallbacks.updateRecordRejectFunction,
|
|
4738
|
-
resolveFn: crudInstrumentationCallbacks.updateRecordResolveFunction,
|
|
4739
|
-
},
|
|
4740
|
-
delete: {
|
|
4741
|
-
rejectFn: crudInstrumentationCallbacks.deleteRecordRejectFunction,
|
|
4742
|
-
resolveFn: crudInstrumentationCallbacks.deleteRecordResolveFunction,
|
|
4743
|
-
},
|
|
4744
|
-
},
|
|
4745
|
-
relatedListRecords: {
|
|
4746
|
-
post: {
|
|
4747
|
-
rejectFn: crudRLInstrumentationCallbacks.getRelatedListRecordsRejectFunction,
|
|
4748
|
-
resolveFn: crudRLInstrumentationCallbacks.getRelatedListRecordsResolveFunction,
|
|
4749
|
-
},
|
|
4750
|
-
},
|
|
4751
|
-
relatedListRecordsBatch: {
|
|
4752
|
-
post: {
|
|
4753
|
-
rejectFn: crudRLInstrumentationCallbacks.getRelatedListRecordsBatchRejectFunction,
|
|
4754
|
-
resolveFn: crudRLInstrumentationCallbacks.getRelatedListRecordsBatchResolveFunction,
|
|
4755
|
-
},
|
|
4756
|
-
},
|
|
4757
|
-
};
|
|
4758
|
-
function checkAndLogCrudInteraction(request, isResolve, error, response) {
|
|
4759
|
-
let configPath;
|
|
4760
|
-
const baseUrl = `${request.baseUri}${request.basePath}`;
|
|
4761
|
-
if (baseUrl.startsWith(UIAPI_RECORDS_PATH)) {
|
|
4762
|
-
configPath = crudInstrumentationConfig['records']; // maybe use a constant for this
|
|
5751
|
+
async loadOrFetchToken() {
|
|
5752
|
+
// First try to get token from AuraStorage
|
|
5753
|
+
if (this.storage) {
|
|
5754
|
+
try {
|
|
5755
|
+
const cachedToken = await this.storage.get(CSRF_TOKEN_KEY);
|
|
5756
|
+
if (typeof cachedToken === 'string' && cachedToken) {
|
|
5757
|
+
return cachedToken;
|
|
5758
|
+
}
|
|
5759
|
+
}
|
|
5760
|
+
catch {
|
|
5761
|
+
// If storage read fails, continue to fetch
|
|
5762
|
+
}
|
|
5763
|
+
}
|
|
5764
|
+
// No cached token, fetch from server
|
|
5765
|
+
return this.fetchFreshToken();
|
|
4763
5766
|
}
|
|
4764
|
-
|
|
4765
|
-
|
|
5767
|
+
/**
|
|
5768
|
+
* Call API endpoint to acquire a CSRF token and cache it.
|
|
5769
|
+
*
|
|
5770
|
+
* @private
|
|
5771
|
+
*/
|
|
5772
|
+
async fetchFreshToken() {
|
|
5773
|
+
try {
|
|
5774
|
+
const response = await fetch('/session/csrf', {
|
|
5775
|
+
method: 'GET',
|
|
5776
|
+
credentials: 'same-origin',
|
|
5777
|
+
});
|
|
5778
|
+
if (!response.ok) {
|
|
5779
|
+
return undefined;
|
|
5780
|
+
}
|
|
5781
|
+
const data = await response.json();
|
|
5782
|
+
const token = data.csrfToken;
|
|
5783
|
+
if (token && this.storage) {
|
|
5784
|
+
// Cache the token in AuraStorage
|
|
5785
|
+
try {
|
|
5786
|
+
await this.storage.set(CSRF_TOKEN_KEY, token);
|
|
5787
|
+
}
|
|
5788
|
+
catch {
|
|
5789
|
+
// Non-fatal: token is still available even if caching fails
|
|
5790
|
+
}
|
|
5791
|
+
}
|
|
5792
|
+
return token;
|
|
5793
|
+
}
|
|
5794
|
+
catch {
|
|
5795
|
+
return undefined;
|
|
5796
|
+
}
|
|
4766
5797
|
}
|
|
4767
|
-
|
|
4768
|
-
|
|
5798
|
+
/**
|
|
5799
|
+
* Returns the current token value as a Promise.
|
|
5800
|
+
*/
|
|
5801
|
+
async getToken() {
|
|
5802
|
+
return this.tokenPromise;
|
|
4769
5803
|
}
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
5804
|
+
/**
|
|
5805
|
+
* Obtains and returns a new token value as a promise.
|
|
5806
|
+
* This will clear the cached token and fetch a fresh one.
|
|
5807
|
+
*/
|
|
5808
|
+
async refreshToken() {
|
|
5809
|
+
// Clear cached token
|
|
5810
|
+
if (this.storage) {
|
|
5811
|
+
try {
|
|
5812
|
+
await this.storage.remove(CSRF_TOKEN_KEY);
|
|
4775
5813
|
}
|
|
4776
|
-
|
|
4777
|
-
|
|
5814
|
+
catch {
|
|
5815
|
+
// Non-fatal: continue with refresh even if clear fails
|
|
4778
5816
|
}
|
|
4779
5817
|
}
|
|
5818
|
+
// Fetch (and cache) fresh token
|
|
5819
|
+
this.tokenPromise = this.fetchFreshToken();
|
|
5820
|
+
return this.tokenPromise;
|
|
5821
|
+
}
|
|
5822
|
+
/**
|
|
5823
|
+
* Reset the singleton instance (useful for testing).
|
|
5824
|
+
* @internal
|
|
5825
|
+
*/
|
|
5826
|
+
static resetInstance() {
|
|
5827
|
+
CsrfTokenManager.instance = null;
|
|
4780
5828
|
}
|
|
4781
5829
|
}
|
|
4782
|
-
|
|
4783
|
-
const responseBody = response ? response.body : {};
|
|
4784
|
-
const urlParams = request.urlParams || {};
|
|
4785
|
-
return {
|
|
4786
|
-
body: responseBody,
|
|
4787
|
-
params: {
|
|
4788
|
-
recordId: urlParams.recordId,
|
|
4789
|
-
},
|
|
4790
|
-
};
|
|
4791
|
-
}
|
|
4792
|
-
function setRejectConfig(request, error) {
|
|
4793
|
-
const requestBody = request.body || {};
|
|
4794
|
-
const urlParams = request.urlParams || {};
|
|
4795
|
-
return {
|
|
4796
|
-
err: error,
|
|
4797
|
-
params: {
|
|
4798
|
-
recordId: urlParams.recordId,
|
|
4799
|
-
// pass these in even if they're undefined
|
|
4800
|
-
parentRecordId: urlParams.parentRecordId,
|
|
4801
|
-
relatedListId: urlParams.relatedListId,
|
|
4802
|
-
relatedListParameters: requestBody.relatedListParameters,
|
|
4803
|
-
},
|
|
4804
|
-
};
|
|
4805
|
-
}
|
|
5830
|
+
CsrfTokenManager.instance = null;
|
|
4806
5831
|
|
|
5832
|
+
const CSRF_TOKEN_HEADER = 'X-CSRF-Token';
|
|
4807
5833
|
/**
|
|
4808
|
-
*
|
|
4809
|
-
*
|
|
4810
|
-
*
|
|
4811
|
-
* This interceptor works with the Luvio ResourceRequest format, which has
|
|
4812
|
-
* a simpler structure than FetchParameters - headers are always a plain object.
|
|
5834
|
+
* Determines if the HTTP method requires CSRF protection.
|
|
5835
|
+
* Only mutating operations (POST, PUT, PATCH, DELETE) require CSRF tokens.
|
|
4813
5836
|
*
|
|
4814
|
-
* @
|
|
5837
|
+
* @param method - The HTTP method to check
|
|
5838
|
+
* @returns true if the method requires CSRF protection
|
|
4815
5839
|
*/
|
|
4816
|
-
function
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
};
|
|
5840
|
+
function isCsrfMethod(method) {
|
|
5841
|
+
if (!method) {
|
|
5842
|
+
return false;
|
|
5843
|
+
}
|
|
5844
|
+
const normalizedMethod = method.toLowerCase();
|
|
5845
|
+
return (normalizedMethod === 'post' ||
|
|
5846
|
+
normalizedMethod === 'put' ||
|
|
5847
|
+
normalizedMethod === 'patch' ||
|
|
5848
|
+
normalizedMethod === 'delete');
|
|
4826
5849
|
}
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
5850
|
+
/**
|
|
5851
|
+
* Builds a request interceptor that adds CSRF token headers to mutating requests.
|
|
5852
|
+
* The CSRF token is fetched once and cached for subsequent requests.
|
|
5853
|
+
* Only POST, PUT, PATCH, and DELETE requests will have the CSRF token added.
|
|
5854
|
+
*
|
|
5855
|
+
* @returns A RequestInterceptor function for FetchParameters
|
|
5856
|
+
*/
|
|
5857
|
+
function buildCsrfTokenInterceptor() {
|
|
5858
|
+
const csrfTokenManager = CsrfTokenManager.getInstance();
|
|
4830
5859
|
return async (fetchArgs) => {
|
|
4831
|
-
|
|
4832
|
-
|
|
5860
|
+
const [urlOrRequest, options] = fetchArgs;
|
|
5861
|
+
// Determine the method from either Request object or options
|
|
5862
|
+
let method;
|
|
5863
|
+
if (typeof urlOrRequest !== 'string' && 'method' in urlOrRequest) {
|
|
5864
|
+
method = urlOrRequest.method;
|
|
5865
|
+
}
|
|
5866
|
+
else if (options && 'method' in options) {
|
|
5867
|
+
method = options.method;
|
|
5868
|
+
}
|
|
5869
|
+
// Only add CSRF token for mutating operations
|
|
5870
|
+
if (isCsrfMethod(method)) {
|
|
5871
|
+
const token = await csrfTokenManager.getToken();
|
|
5872
|
+
if (token) {
|
|
5873
|
+
fetchArgs = setHeader(CSRF_TOKEN_HEADER, token, fetchArgs);
|
|
5874
|
+
}
|
|
5875
|
+
}
|
|
5876
|
+
return resolvedPromiseLike$2(fetchArgs);
|
|
4833
5877
|
};
|
|
4834
5878
|
}
|
|
4835
|
-
|
|
4836
|
-
|
|
5879
|
+
/**
|
|
5880
|
+
* Builds a Luvio request interceptor that adds CSRF token headers to mutating requests.
|
|
5881
|
+
* The CSRF token is fetched once and cached for subsequent requests.
|
|
5882
|
+
* Only POST, PUT, PATCH, and DELETE requests will have the CSRF token added.
|
|
5883
|
+
*
|
|
5884
|
+
* @returns A request interceptor function for Luvio ResourceRequest objects
|
|
5885
|
+
*/
|
|
5886
|
+
function buildLuvioCsrfTokenInterceptor() {
|
|
5887
|
+
const csrfTokenManager = CsrfTokenManager.getInstance();
|
|
5888
|
+
return async (resourceRequest) => {
|
|
4837
5889
|
// Ensure headers object exists
|
|
4838
5890
|
if (!resourceRequest.headers) {
|
|
4839
5891
|
resourceRequest.headers = {};
|
|
4840
5892
|
}
|
|
4841
|
-
//
|
|
4842
|
-
if (
|
|
4843
|
-
|
|
5893
|
+
// Only add CSRF token for mutating operations
|
|
5894
|
+
if (isCsrfMethod(resourceRequest.method)) {
|
|
5895
|
+
// Don't overwrite existing CSRF token header if it already exists
|
|
5896
|
+
if (!resourceRequest.headers[CSRF_TOKEN_HEADER]) {
|
|
5897
|
+
const token = await csrfTokenManager.getToken();
|
|
5898
|
+
if (token) {
|
|
5899
|
+
resourceRequest.headers[CSRF_TOKEN_HEADER] = token;
|
|
5900
|
+
}
|
|
5901
|
+
}
|
|
4844
5902
|
}
|
|
4845
|
-
return resolvedPromiseLike$
|
|
5903
|
+
return resolvedPromiseLike$2(resourceRequest);
|
|
4846
5904
|
};
|
|
4847
5905
|
}
|
|
4848
5906
|
|
|
@@ -4907,7 +5965,7 @@ const composedFetchNetworkAdapter = {
|
|
|
4907
5965
|
return API_PATH_MATCHERS.some((matcher) => matcher.test(path));
|
|
4908
5966
|
},
|
|
4909
5967
|
adapter: setupLexNetworkAdapter(requestTracker, requestLogger, {
|
|
4910
|
-
request: [buildLuvioPageScopedCacheRequestInterceptor(),
|
|
5968
|
+
request: [buildLuvioPageScopedCacheRequestInterceptor(), buildLuvioCsrfTokenInterceptor()],
|
|
4911
5969
|
response: [
|
|
4912
5970
|
buildLexRuntimeLuvio5xxStatusResponseInterceptor(),
|
|
4913
5971
|
buildLexRuntimeLuvioAuthExpirationRedirectResponseInterceptor(),
|
|
@@ -4915,13 +5973,195 @@ const composedFetchNetworkAdapter = {
|
|
|
4915
5973
|
}),
|
|
4916
5974
|
};
|
|
4917
5975
|
|
|
5976
|
+
function buildThirdPartyTrackerFinishInterceptor() {
|
|
5977
|
+
return async (context) => {
|
|
5978
|
+
if (context && context.instrumentationId) {
|
|
5979
|
+
instrumentationTracker.markFinished(context.instrumentationId);
|
|
5980
|
+
}
|
|
5981
|
+
};
|
|
5982
|
+
}
|
|
5983
|
+
|
|
5984
|
+
function buildThirdPartyTrackerRegisterInterceptor() {
|
|
5985
|
+
return async (fetchArgs, context) => {
|
|
5986
|
+
if (context && context.instrumentationId) {
|
|
5987
|
+
instrumentationTracker.registerHandler(context.instrumentationId, 'onestore-inflight-network-request', () => {
|
|
5988
|
+
// return false until we signal we are finished
|
|
5989
|
+
return false;
|
|
5990
|
+
});
|
|
5991
|
+
}
|
|
5992
|
+
return resolvedPromiseLike$2(fetchArgs);
|
|
5993
|
+
};
|
|
5994
|
+
}
|
|
5995
|
+
|
|
5996
|
+
function createInstrumentationIdContext() {
|
|
5997
|
+
return () => ({
|
|
5998
|
+
instrumentationId: generateRequestId$1(),
|
|
5999
|
+
});
|
|
6000
|
+
}
|
|
6001
|
+
function createStartMark(requestId) {
|
|
6002
|
+
const startMark = markStart('transport', 'request');
|
|
6003
|
+
startMark.context = {
|
|
6004
|
+
auraXHRId: requestId,
|
|
6005
|
+
background: false,
|
|
6006
|
+
actionDefs: ['lds-fetch'],
|
|
6007
|
+
requestId,
|
|
6008
|
+
requestLength: -1, // not known
|
|
6009
|
+
};
|
|
6010
|
+
}
|
|
6011
|
+
|
|
6012
|
+
function buildPageScopedCacheRequestInterceptor() {
|
|
6013
|
+
return async (fetchArgs) => {
|
|
6014
|
+
const pageScopedCacheHeaders = {};
|
|
6015
|
+
// Allow the instrumentation util to set up the header value on our "dummy" header object
|
|
6016
|
+
pageScopedCache.addHeader(pageScopedCacheHeaders);
|
|
6017
|
+
let returnedFetchArgs = fetchArgs;
|
|
6018
|
+
// If it set a value, add it to our fetchParams
|
|
6019
|
+
Object.entries(pageScopedCacheHeaders).forEach(([key, value]) => {
|
|
6020
|
+
returnedFetchArgs = setHeader(key, value, returnedFetchArgs);
|
|
6021
|
+
});
|
|
6022
|
+
return resolvedPromiseLike$2(returnedFetchArgs);
|
|
6023
|
+
};
|
|
6024
|
+
}
|
|
6025
|
+
|
|
6026
|
+
const SFDC_REQUEST_ID_KEY = 'X-SFDC-Request-Id';
|
|
6027
|
+
function buildTransportMarksSendInterceptor() {
|
|
6028
|
+
return async (fetchArgs, context) => {
|
|
6029
|
+
// First set the requestId header. If there's not context, it means we won't be able to track the mark and something is hosed, and so not worth even trying
|
|
6030
|
+
if (context && context.instrumentationId) {
|
|
6031
|
+
const requestId = context.instrumentationId;
|
|
6032
|
+
fetchArgs = setHeader(SFDC_REQUEST_ID_KEY, requestId, fetchArgs);
|
|
6033
|
+
createStartMark(requestId);
|
|
6034
|
+
}
|
|
6035
|
+
return resolvedPromiseLike$2(fetchArgs);
|
|
6036
|
+
};
|
|
6037
|
+
}
|
|
6038
|
+
|
|
6039
|
+
function buildTransportMarksReceiveInterceptor() {
|
|
6040
|
+
return async (context) => {
|
|
6041
|
+
if (context && context.instrumentationId) {
|
|
6042
|
+
markEnd('transport', 'request', { auraXHRId: context.instrumentationId });
|
|
6043
|
+
}
|
|
6044
|
+
};
|
|
6045
|
+
}
|
|
6046
|
+
|
|
6047
|
+
const DEFAULT_CONFIG$1 = {
|
|
6048
|
+
maxRetries: 1, // Only retry once after token refresh
|
|
6049
|
+
};
|
|
6050
|
+
/**
|
|
6051
|
+
* Retry policy that handles CSRF token expiration errors.
|
|
6052
|
+
*
|
|
6053
|
+
* When a request fails with a CSRF token error this policy will:
|
|
6054
|
+
* 1. Detect the error condition in shouldRetry
|
|
6055
|
+
* 2. Refresh the CSRF token in prepareRetry hook
|
|
6056
|
+
* 3. Update the request headers with the new token via mutable context
|
|
6057
|
+
* 4. Retry the request once (maxRetries = 1)
|
|
6058
|
+
*
|
|
6059
|
+
*/
|
|
6060
|
+
class CsrfTokenRetryPolicy extends RetryPolicy {
|
|
6061
|
+
constructor(config = DEFAULT_CONFIG$1) {
|
|
6062
|
+
super();
|
|
6063
|
+
this.config = config;
|
|
6064
|
+
this.csrfTokenManager = CsrfTokenManager.getInstance();
|
|
6065
|
+
}
|
|
6066
|
+
/**
|
|
6067
|
+
* Allows the fetch service to pass mutable request context.
|
|
6068
|
+
* This is a side-channel that enables request modification between retries.
|
|
6069
|
+
*
|
|
6070
|
+
* @param context - Mutable container holding fetch arguments
|
|
6071
|
+
*/
|
|
6072
|
+
setRequestContext(context) {
|
|
6073
|
+
this.requestContext = context;
|
|
6074
|
+
}
|
|
6075
|
+
/**
|
|
6076
|
+
* Determines if a failed request should be retried due to CSRF token issues.
|
|
6077
|
+
*/
|
|
6078
|
+
async shouldRetry(result, context) {
|
|
6079
|
+
// Only retry once
|
|
6080
|
+
if (context.attempt >= this.config.maxRetries) {
|
|
6081
|
+
return false;
|
|
6082
|
+
}
|
|
6083
|
+
// Only retry on 400 status
|
|
6084
|
+
if (result.status !== 400) {
|
|
6085
|
+
return false;
|
|
6086
|
+
}
|
|
6087
|
+
// Check if this is a CSRF error by examining the response body
|
|
6088
|
+
// This avoids retrying all 400s (validation errors, bad requests, etc.)
|
|
6089
|
+
return await isCsrfError(result);
|
|
6090
|
+
}
|
|
6091
|
+
/**
|
|
6092
|
+
* CSRF token refresh should happen immediately with no delay.
|
|
6093
|
+
*/
|
|
6094
|
+
async calculateDelay(_result, _context) {
|
|
6095
|
+
return 0; // No delay - retry immediately after token refresh
|
|
6096
|
+
}
|
|
6097
|
+
/**
|
|
6098
|
+
* Called by retry service before each retry attempt.
|
|
6099
|
+
*
|
|
6100
|
+
* This hook is supported by the Conduit retry service (with prepareRetry support).
|
|
6101
|
+
* It performs token refresh and request update:
|
|
6102
|
+
* 1. Refreshes the CSRF token from the server
|
|
6103
|
+
* 2. Updates the mutable request context with the new token
|
|
6104
|
+
*
|
|
6105
|
+
* Note: We already validated this is a CSRF error in shouldRetry,
|
|
6106
|
+
* so we can proceed directly to token refresh.
|
|
6107
|
+
*
|
|
6108
|
+
* The fetch service must call setRequestContext() to provide the mutable args container.
|
|
6109
|
+
* When the retry service re-executes the operation, it will use the updated args.
|
|
6110
|
+
*
|
|
6111
|
+
* @param _result - The failed response that triggered the retry (unused, already validated)
|
|
6112
|
+
* @param _context - Current retry context (unused but part of interface)
|
|
6113
|
+
*/
|
|
6114
|
+
async prepareRetry(_result, _context) {
|
|
6115
|
+
// Refresh the CSRF token (we already know this is a CSRF error from shouldRetry)
|
|
6116
|
+
const newToken = await this.csrfTokenManager.refreshToken();
|
|
6117
|
+
if (!newToken || !this.requestContext) {
|
|
6118
|
+
// If we can't get a new token or don't have request context,
|
|
6119
|
+
// the retry will fail again but that's expected
|
|
6120
|
+
return;
|
|
6121
|
+
}
|
|
6122
|
+
// Update the fetch arguments with the new token using the setHeader utility
|
|
6123
|
+
this.requestContext.args = setHeader('X-CSRF-Token', newToken, this.requestContext.args);
|
|
6124
|
+
}
|
|
6125
|
+
}
|
|
6126
|
+
/**
|
|
6127
|
+
* Helper to check if a response indicates a CSRF token error.
|
|
6128
|
+
*
|
|
6129
|
+
* @param response - The response to check
|
|
6130
|
+
* @returns true if the response indicates a CSRF token error (INVALID_ACCESS_TOKEN)
|
|
6131
|
+
*/
|
|
6132
|
+
async function isCsrfError(response) {
|
|
6133
|
+
try {
|
|
6134
|
+
// Clone to avoid consuming the original response
|
|
6135
|
+
const cloned = response.clone();
|
|
6136
|
+
const body = await cloned.json();
|
|
6137
|
+
// Check the error array format: data[0].errorCode
|
|
6138
|
+
const errorCode = body?.data?.[0]?.errorCode;
|
|
6139
|
+
return errorCode === 'INVALID_ACCESS_TOKEN';
|
|
6140
|
+
}
|
|
6141
|
+
catch {
|
|
6142
|
+
// If we can't parse the body (network error, non-JSON response, etc.),
|
|
6143
|
+
// assume it's not a CSRF error
|
|
6144
|
+
return false;
|
|
6145
|
+
}
|
|
6146
|
+
}
|
|
6147
|
+
|
|
4918
6148
|
function buildLexRuntimeDefaultFetchServiceDescriptor(logger, retryService) {
|
|
4919
6149
|
const fetchService = buildLexConnectFetchServiceDescriptor({
|
|
4920
|
-
|
|
6150
|
+
createContext: createInstrumentationIdContext(),
|
|
6151
|
+
request: [
|
|
6152
|
+
buildThirdPartyTrackerRegisterInterceptor(),
|
|
6153
|
+
buildPageScopedCacheRequestInterceptor(),
|
|
6154
|
+
buildTransportMarksSendInterceptor(),
|
|
6155
|
+
buildCsrfTokenInterceptor(),
|
|
6156
|
+
],
|
|
4921
6157
|
response: [
|
|
4922
6158
|
buildLexRuntime5xxStatusResponseInterceptor(logger),
|
|
4923
6159
|
buildLexRuntimeAuthExpirationRedirectResponseInterceptor(logger),
|
|
4924
6160
|
],
|
|
6161
|
+
finally: [
|
|
6162
|
+
buildTransportMarksReceiveInterceptor(),
|
|
6163
|
+
buildThirdPartyTrackerFinishInterceptor(),
|
|
6164
|
+
],
|
|
4925
6165
|
}, retryService);
|
|
4926
6166
|
return {
|
|
4927
6167
|
...fetchService,
|
|
@@ -4929,38 +6169,69 @@ function buildLexRuntimeDefaultFetchServiceDescriptor(logger, retryService) {
|
|
|
4929
6169
|
}
|
|
4930
6170
|
function buildLexRuntimeAllow5xxFetchServiceDescriptor(logger, retryService) {
|
|
4931
6171
|
const fetchService = buildLexConnectFetchServiceDescriptor({
|
|
4932
|
-
|
|
6172
|
+
createContext: createInstrumentationIdContext(),
|
|
6173
|
+
request: [
|
|
6174
|
+
buildThirdPartyTrackerRegisterInterceptor(),
|
|
6175
|
+
buildPageScopedCacheRequestInterceptor(),
|
|
6176
|
+
buildTransportMarksSendInterceptor(),
|
|
6177
|
+
buildCsrfTokenInterceptor(),
|
|
6178
|
+
],
|
|
4933
6179
|
response: [buildLexRuntimeAuthExpirationRedirectResponseInterceptor(logger)],
|
|
6180
|
+
finally: [
|
|
6181
|
+
buildTransportMarksReceiveInterceptor(),
|
|
6182
|
+
buildThirdPartyTrackerFinishInterceptor(),
|
|
6183
|
+
],
|
|
4934
6184
|
}, retryService);
|
|
4935
6185
|
return {
|
|
4936
6186
|
...fetchService,
|
|
4937
6187
|
tags: { interceptors: 'allow_500s' },
|
|
4938
6188
|
};
|
|
4939
6189
|
}
|
|
4940
|
-
|
|
6190
|
+
// Temporarily cloned from conduit fetch until the retry service is updated there
|
|
6191
|
+
function buildLexConnectFetchServiceDescriptor(interceptors = { request: [], response: [], finally: [] }, retryService) {
|
|
4941
6192
|
return {
|
|
4942
6193
|
type: 'fetch',
|
|
4943
6194
|
version: '1.0',
|
|
4944
6195
|
service: function (...args) {
|
|
4945
|
-
|
|
4946
|
-
const
|
|
4947
|
-
const
|
|
4948
|
-
|
|
4949
|
-
// return false until we signal we are finished
|
|
4950
|
-
return false;
|
|
4951
|
-
});
|
|
6196
|
+
// Create context per request if factory is provided
|
|
6197
|
+
const context = interceptors.createContext?.();
|
|
6198
|
+
const { request: requestInterceptors = [], response: responseInterceptors = [], finally: finallyInterceptors = [], } = interceptors;
|
|
6199
|
+
const pending = requestInterceptors.reduce((previousPromise, interceptor) => previousPromise.then((args) => interceptor(args, context)), resolvedPromiseLike$2(args));
|
|
4952
6200
|
return Promise.resolve(pending)
|
|
4953
|
-
.then((
|
|
6201
|
+
.then((interceptedArgs) => {
|
|
4954
6202
|
if (retryService) {
|
|
4955
|
-
|
|
6203
|
+
// Create mutable context for CSRF retry policy
|
|
6204
|
+
const mutableRequest = { args: interceptedArgs };
|
|
6205
|
+
// Pass context to CSRF policy if it's being used
|
|
6206
|
+
const policy = retryService.defaultRetryPolicy;
|
|
6207
|
+
// Handle both direct CSRF policy and composed policy
|
|
6208
|
+
if (policy instanceof CsrfTokenRetryPolicy) {
|
|
6209
|
+
policy.setRequestContext(mutableRequest);
|
|
6210
|
+
}
|
|
6211
|
+
else if (policy instanceof ComposedRetryPolicy) {
|
|
6212
|
+
// Extract CSRF policy from composed policy
|
|
6213
|
+
const csrfPolicy = policy.getPolicyByType(CsrfTokenRetryPolicy);
|
|
6214
|
+
if (csrfPolicy) {
|
|
6215
|
+
csrfPolicy.setRequestContext(mutableRequest);
|
|
6216
|
+
}
|
|
6217
|
+
}
|
|
6218
|
+
// Retry service will call prepareRetry hook which updates mutableRequest.args
|
|
6219
|
+
return retryService.applyRetry(async () => {
|
|
6220
|
+
return await fetch(...mutableRequest.args);
|
|
6221
|
+
});
|
|
4956
6222
|
}
|
|
4957
|
-
return fetch(...
|
|
6223
|
+
return fetch(...interceptedArgs);
|
|
4958
6224
|
})
|
|
4959
6225
|
.then((response) => {
|
|
4960
|
-
|
|
6226
|
+
// Success path - run response interceptors
|
|
6227
|
+
return responseInterceptors.reduce((previousPromise, interceptor) => previousPromise.then((response) => interceptor(response, context)), resolvedPromiseLike$2(response));
|
|
4961
6228
|
})
|
|
4962
6229
|
.finally(() => {
|
|
4963
|
-
|
|
6230
|
+
// Always run finally interceptors for cleanup
|
|
6231
|
+
if (finallyInterceptors.length > 0) {
|
|
6232
|
+
// Run all finally interceptors sequentially
|
|
6233
|
+
return finallyInterceptors.reduce((previousPromise, interceptor) => previousPromise.then(() => interceptor(context)), Promise.resolve());
|
|
6234
|
+
}
|
|
4964
6235
|
});
|
|
4965
6236
|
},
|
|
4966
6237
|
};
|
|
@@ -4971,7 +6242,9 @@ const sfapJwtRepository = new JwtRepository();
|
|
|
4971
6242
|
const sfapJwtManager = new JwtManager(sfapJwtRepository, platformSfapJwtResolver);
|
|
4972
6243
|
function buildJwtAuthorizedSfapFetchServiceDescriptor(logger) {
|
|
4973
6244
|
const jwtAuthorizedFetchService = buildLexConnectFetchServiceDescriptor({
|
|
4974
|
-
|
|
6245
|
+
createContext: createInstrumentationIdContext(),
|
|
6246
|
+
request: [buildThirdPartyTrackerRegisterInterceptor(), buildJwtRequestInterceptor(logger)],
|
|
6247
|
+
finally: [buildThirdPartyTrackerFinishInterceptor()],
|
|
4975
6248
|
});
|
|
4976
6249
|
return {
|
|
4977
6250
|
...jwtAuthorizedFetchService,
|
|
@@ -4990,7 +6263,9 @@ function buildCopilotFetchServiceDescriptor(logger) {
|
|
|
4990
6263
|
// Interceptor here with the logic in buildJwtAuthorizedSfapFetchServiceDescriptor()
|
|
4991
6264
|
// above.
|
|
4992
6265
|
...buildLexConnectFetchServiceDescriptor({
|
|
6266
|
+
createContext: createInstrumentationIdContext(),
|
|
4993
6267
|
request: [
|
|
6268
|
+
buildThirdPartyTrackerRegisterInterceptor(),
|
|
4994
6269
|
// Note that this function is VERY closely tied to the fetchParams generated
|
|
4995
6270
|
// by copilotStartSessionCommand. Any changes to those parameters will require
|
|
4996
6271
|
// corresponding updates to the logic below.
|
|
@@ -5003,9 +6278,9 @@ function buildCopilotFetchServiceDescriptor(logger) {
|
|
|
5003
6278
|
requestInit.method !== 'POST' ||
|
|
5004
6279
|
!requestInit.body ||
|
|
5005
6280
|
typeof requestInit.body !== 'string') {
|
|
5006
|
-
return resolvedPromiseLike$
|
|
6281
|
+
return resolvedPromiseLike$2(args);
|
|
5007
6282
|
}
|
|
5008
|
-
return resolvedPromiseLike$
|
|
6283
|
+
return resolvedPromiseLike$2(sfapJwtManager.getJwt()).then((token) => {
|
|
5009
6284
|
// replace the body's instanceConfig.endpoint with the JWT's iss value
|
|
5010
6285
|
const body = JSON.parse(requestInit.body);
|
|
5011
6286
|
if (!body || !token.decodedInfo || !token.decodedInfo.iss) {
|
|
@@ -5030,12 +6305,17 @@ function buildCopilotFetchServiceDescriptor(logger) {
|
|
|
5030
6305
|
},
|
|
5031
6306
|
buildJwtRequestInterceptor(logger),
|
|
5032
6307
|
],
|
|
6308
|
+
finally: [buildThirdPartyTrackerFinishInterceptor()],
|
|
5033
6309
|
}),
|
|
5034
6310
|
tags: { specialHacksFor: 'copilot' },
|
|
5035
6311
|
};
|
|
5036
6312
|
}
|
|
5037
6313
|
function buildUnauthorizedFetchServiceDescriptor() {
|
|
5038
|
-
const fetchService = buildLexConnectFetchServiceDescriptor(
|
|
6314
|
+
const fetchService = buildLexConnectFetchServiceDescriptor({
|
|
6315
|
+
createContext: createInstrumentationIdContext(),
|
|
6316
|
+
request: [buildThirdPartyTrackerRegisterInterceptor()],
|
|
6317
|
+
finally: [buildThirdPartyTrackerFinishInterceptor()],
|
|
6318
|
+
});
|
|
5039
6319
|
return {
|
|
5040
6320
|
...fetchService,
|
|
5041
6321
|
tags: { authenticationScopes: '' },
|
|
@@ -7785,12 +9065,12 @@ class FetchThrottlingRetryPolicy extends RetryPolicy {
|
|
|
7785
9065
|
super();
|
|
7786
9066
|
this.config = config;
|
|
7787
9067
|
}
|
|
7788
|
-
shouldRetry(result, context) {
|
|
9068
|
+
async shouldRetry(result, context) {
|
|
7789
9069
|
return ((result.status === 429 || result.status === 503) &&
|
|
7790
9070
|
context.attempt < this.config.maxRetries &&
|
|
7791
9071
|
context.totalElapsedMs <= this.config.maxTimeToRetry);
|
|
7792
9072
|
}
|
|
7793
|
-
calculateDelay(result, context) {
|
|
9073
|
+
async calculateDelay(result, context) {
|
|
7794
9074
|
let delay;
|
|
7795
9075
|
// If retry-after header is present and valid, use it
|
|
7796
9076
|
const retryAfterHeader = this.parseRetryAfterHeader(result);
|
|
@@ -8407,18 +9687,18 @@ function initializeLDS() {
|
|
|
8407
9687
|
}
|
|
8408
9688
|
// Initializes OneStore in LEX
|
|
8409
9689
|
function initializeOneStore(luvio) {
|
|
8410
|
-
const loggerService = new ConsoleLogger
|
|
8411
|
-
const cacheServiceDescriptor = buildServiceDescriptor$
|
|
8412
|
-
const instrumentationServiceDescriptor = buildServiceDescriptor$
|
|
9690
|
+
const loggerService = new ConsoleLogger('ERROR');
|
|
9691
|
+
const cacheServiceDescriptor = buildServiceDescriptor$h();
|
|
9692
|
+
const instrumentationServiceDescriptor = buildServiceDescriptor$i(loggerService);
|
|
8413
9693
|
const inMemoryCacheInclusionPolicyServiceDescriptor = buildInMemoryCacheInclusionPolicyService(cacheServiceDescriptor.service);
|
|
8414
9694
|
const durableCacheInclusionPolicyServiceDescriptor = buildAuraDurableCacheInclusionPolicyService();
|
|
8415
9695
|
const durableCacheControlService = {
|
|
8416
|
-
...buildServiceDescriptor$
|
|
9696
|
+
...buildServiceDescriptor$g(cacheServiceDescriptor.service, durableCacheInclusionPolicyServiceDescriptor.service, instrumentationServiceDescriptor.service),
|
|
8417
9697
|
tags: { storage: 'durable' },
|
|
8418
9698
|
};
|
|
8419
|
-
const featureFlagsServiceDescriptor = buildServiceDescriptor$
|
|
9699
|
+
const featureFlagsServiceDescriptor = buildServiceDescriptor$a();
|
|
8420
9700
|
const featureFlagsService = featureFlagsServiceDescriptor.service;
|
|
8421
|
-
const luvioUiapiRecordsServiceDescriptor = buildServiceDescriptor$
|
|
9701
|
+
const luvioUiapiRecordsServiceDescriptor = buildServiceDescriptor$9((configs) => {
|
|
8422
9702
|
return notifyUpdateAvailableFactory(luvio)(configs);
|
|
8423
9703
|
}, (recordId, reader) => {
|
|
8424
9704
|
const recordKey = buildRecordRepKeyFromId(recordId);
|
|
@@ -8437,8 +9717,11 @@ function initializeOneStore(luvio) {
|
|
|
8437
9717
|
reader.unMarkMissing();
|
|
8438
9718
|
return linkedData.data;
|
|
8439
9719
|
});
|
|
8440
|
-
|
|
8441
|
-
const
|
|
9720
|
+
// Compose both throttling and CSRF retry policies
|
|
9721
|
+
const throttlingPolicy = new FetchThrottlingRetryPolicy();
|
|
9722
|
+
const csrfPolicy = new CsrfTokenRetryPolicy();
|
|
9723
|
+
const retryPolicy = new ComposedRetryPolicy([throttlingPolicy, csrfPolicy]);
|
|
9724
|
+
const retryServiceDescriptor = buildServiceDescriptor$8(retryPolicy);
|
|
8442
9725
|
const retryService = retryServiceDescriptor.service;
|
|
8443
9726
|
// set flags based on gates
|
|
8444
9727
|
featureFlagsService.set('useOneStoreGraphQL', useOneStoreGraphql.isOpen({ fallback: false }));
|
|
@@ -8449,27 +9732,36 @@ function initializeOneStore(luvio) {
|
|
|
8449
9732
|
buildJwtAuthorizedSfapFetchServiceDescriptor(loggerService),
|
|
8450
9733
|
buildCopilotFetchServiceDescriptor(loggerService),
|
|
8451
9734
|
buildAuraNetworkService(),
|
|
8452
|
-
buildServiceDescriptor$
|
|
9735
|
+
buildServiceDescriptor$j(instrumentationServiceDescriptor.service),
|
|
8453
9736
|
// Ordering of services matters - L1 only CacheControlService must come before durable
|
|
8454
|
-
buildServiceDescriptor$
|
|
9737
|
+
buildServiceDescriptor$g(cacheServiceDescriptor.service, inMemoryCacheInclusionPolicyServiceDescriptor.service, instrumentationServiceDescriptor.service),
|
|
8455
9738
|
durableCacheControlService,
|
|
8456
|
-
buildServiceDescriptor$
|
|
8457
|
-
buildServiceDescriptor$7(),
|
|
8458
|
-
buildServiceDescriptor$f(),
|
|
8459
|
-
buildServiceDescriptor$k(),
|
|
9739
|
+
buildServiceDescriptor$q(),
|
|
8460
9740
|
buildServiceDescriptor$e(),
|
|
8461
|
-
buildServiceDescriptor$
|
|
8462
|
-
buildServiceDescriptor$
|
|
8463
|
-
buildServiceDescriptor$
|
|
8464
|
-
buildServiceDescriptor$
|
|
8465
|
-
buildServiceDescriptor$
|
|
9741
|
+
buildServiceDescriptor$m(),
|
|
9742
|
+
buildServiceDescriptor$r(),
|
|
9743
|
+
buildServiceDescriptor$l(),
|
|
9744
|
+
buildServiceDescriptor$k(),
|
|
9745
|
+
buildServiceDescriptor$p(),
|
|
9746
|
+
buildServiceDescriptor$o(),
|
|
9747
|
+
buildServiceDescriptor$n(),
|
|
9748
|
+
buildServiceDescriptor$f(),
|
|
8466
9749
|
buildLexRuntimeAllow5xxFetchServiceDescriptor(loggerService, retryService),
|
|
8467
|
-
buildServiceDescriptor$
|
|
9750
|
+
buildServiceDescriptor$d(luvio),
|
|
8468
9751
|
luvioUiapiRecordsServiceDescriptor,
|
|
8469
|
-
buildServiceDescriptor$
|
|
8470
|
-
buildServiceDescriptor$
|
|
9752
|
+
buildServiceDescriptor$c(),
|
|
9753
|
+
buildServiceDescriptor$b(),
|
|
8471
9754
|
featureFlagsServiceDescriptor,
|
|
8472
9755
|
retryServiceDescriptor,
|
|
9756
|
+
buildServiceDescriptor$6(),
|
|
9757
|
+
buildServiceDescriptor$5(),
|
|
9758
|
+
buildServiceDescriptor$4(),
|
|
9759
|
+
buildServiceDescriptor$3(),
|
|
9760
|
+
buildServiceDescriptor$2$1(),
|
|
9761
|
+
buildServiceDescriptor$1$1(),
|
|
9762
|
+
buildServiceDescriptor$7(),
|
|
9763
|
+
buildLWCWireBindingsServiceDescriptor(),
|
|
9764
|
+
buildLWCGraphQLWireBindingsServiceDescriptor(),
|
|
8473
9765
|
];
|
|
8474
9766
|
setServices(services);
|
|
8475
9767
|
}
|
|
@@ -8489,4 +9781,4 @@ function ldsEngineCreator() {
|
|
|
8489
9781
|
}
|
|
8490
9782
|
|
|
8491
9783
|
export { LexRequestStrategy, PdlRequestPriority, buildPredictorForContext, ldsEngineCreator as default, initializeLDS, initializeOneStore, notifyUpdateAvailableFactory, registerRequestStrategy, saveRequestAsPrediction, unregisterRequestStrategy, whenPredictionsReady };
|
|
8492
|
-
// version: 1.
|
|
9784
|
+
// version: 1.403.0-bc09fbc54b
|