@salesforce/lds-runtime-aura 1.301.0 → 1.303.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 +1262 -416
- package/dist/types/jwt-authorized-fetch-service.d.ts +2 -0
- package/dist/types/network-sfap.d.ts +1 -1
- package/dist/types/predictive-loading/pages/object-home-page.d.ts +10 -5
- package/dist/types/predictive-loading/pages/record-home-page.d.ts +10 -4
- package/dist/types/predictive-loading/prefetcher/lex-predictive-prefetcher.d.ts +21 -4
- package/dist/types/predictive-loading/prefetcher/predictive-prefetcher.d.ts +1 -15
- package/dist/types/predictive-loading/request-strategy/get-apex-request-strategy.d.ts +0 -4
- package/dist/types/predictive-loading/request-strategy/get-components-request-strategy.d.ts +4 -7
- package/dist/types/predictive-loading/request-strategy/get-list-info-by-name-request-strategy.d.ts +0 -4
- package/dist/types/predictive-loading/request-strategy/get-list-infos-by-object-name-request-strategy.d.ts +0 -4
- package/dist/types/predictive-loading/request-strategy/get-list-object-info-request-strategy.d.ts +16 -0
- package/dist/types/predictive-loading/request-strategy/get-list-records-by-name-request-strategy.d.ts +0 -4
- package/dist/types/predictive-loading/request-strategy/get-object-info-request-strategy.d.ts +2 -2
- package/dist/types/predictive-loading/request-strategy/get-object-infos-request-strategy.d.ts +2 -4
- package/dist/types/predictive-loading/request-strategy/get-related-list-records-request-strategy.d.ts +2 -2
- package/dist/types/predictive-loading/request-strategy/get-related-lists-actions-request-strategy.d.ts +1 -1
- package/dist/types/predictive-loading/request-strategy/index.d.ts +1 -1
- package/dist/types/predictive-loading/request-strategy/luvio-adapter-request-strategy.d.ts +6 -77
- package/dist/types/predictive-loading/request-strategy/request-strategy.d.ts +65 -4
- package/package.json +32 -24
- package/dist/types/predictive-loading/request-strategy/config-based-request-strategy.d.ts +0 -15
- package/dist/types/predictive-loading/request-strategy/luvio-adapter-request.d.ts +0 -8
package/dist/ldsEngineCreator.js
CHANGED
|
@@ -19,23 +19,437 @@ import useApexPredictions from '@salesforce/gate/lds.pdl.useApexPredictions';
|
|
|
19
19
|
import useRelatedListsPredictions from '@salesforce/gate/lds.pdl.useRelatedListsPredictions';
|
|
20
20
|
import useCmpDefPredictions from '@salesforce/gate/lds.pdl.useCmpDefPredictions';
|
|
21
21
|
import applyPredictionRequestLimit from '@salesforce/gate/lds.pdl.applyRequestLimit';
|
|
22
|
-
import
|
|
22
|
+
import useExactMatchesPlusGate from '@salesforce/gate/lds.pdl.useExactMatchesPlus';
|
|
23
23
|
import { GetApexWireAdapterFactory, registerPrefetcher as registerPrefetcher$1 } from 'force/ldsAdaptersApex';
|
|
24
|
-
import { instrument, getRecordAvatarsAdapterFactory, getRecordAdapterFactory, coerceFieldIdArray, getRecordsAdapterFactory, getRecordActionsAdapterFactory, getObjectInfosAdapterFactory, coerceObjectIdArray, getObjectInfoAdapterFactory, coerceObjectId, getRelatedListsActionsAdapterFactory, getRelatedListInfoBatchAdapterFactory, getRelatedListRecordsBatchAdapterFactory, getRelatedListRecordsAdapterFactory, getListInfoByNameAdapterFactory, getListInfosByObjectNameAdapterFactory, getListRecordsByNameAdapterFactory, configuration, InMemoryRecordRepresentationQueryEvaluator, UiApiNamespace, RecordRepresentationRepresentationType, registerPrefetcher } from 'force/ldsAdaptersUiapi';
|
|
25
|
-
import {
|
|
24
|
+
import { instrument, getRecordAvatarsAdapterFactory, getRecordAdapterFactory, coerceFieldIdArray, getRecordsAdapterFactory, getRecordActionsAdapterFactory, getObjectInfosAdapterFactory, coerceObjectIdArray, getObjectInfoAdapterFactory, coerceObjectId, getRelatedListsActionsAdapterFactory, getRelatedListInfoBatchAdapterFactory, getRelatedListRecordsBatchAdapterFactory, getRelatedListRecordsAdapterFactory, getListInfoByNameAdapterFactory, getListInfosByObjectNameAdapterFactory, getListRecordsByNameAdapterFactory, getListObjectInfoAdapterFactory, configuration, InMemoryRecordRepresentationQueryEvaluator, UiApiNamespace, RecordRepresentationRepresentationType, registerPrefetcher } from 'force/ldsAdaptersUiapi';
|
|
25
|
+
import { BaseCommand, convertAuraResponseToData, convertFetchResponseToData } from 'force/luvioRuntime5';
|
|
26
|
+
import { serviceBroker } from 'force/luvioServiceBroker5';
|
|
26
27
|
import oneStoreEnabled from '@salesforce/gate/lds.oneStoreEnabled.ltng';
|
|
27
28
|
import oneStoreUiapiEnabled from '@salesforce/gate/lds.oneStoreUiapiEnabled.ltng';
|
|
28
29
|
import { getDefinition, executeGlobalControllerRawResponse } from 'aura';
|
|
30
|
+
import { buildJwtNetworkAdapter } from 'force/ldsNetworkFetchWithJwt';
|
|
31
|
+
import auraNetworkAdapter, { dispatchAuraAction, defaultActionConfig, instrument as instrument$1, forceRecordTransactionsDisabled, ldsNetworkAdapterInstrument } from 'force/ldsNetwork';
|
|
29
32
|
import { LRUCache, instrumentAdapter, instrumentLuvio, setupInstrumentation as setupInstrumentation$1, logObjectInfoChanged as logObjectInfoChanged$1, updatePercentileHistogramMetric, incrementCounterMetric, incrementGetRecordNotifyChangeAllowCount, incrementGetRecordNotifyChangeDropCount, incrementNotifyRecordUpdateAvailableAllowCount, incrementNotifyRecordUpdateAvailableDropCount, setLdsAdaptersUiapiInstrumentation, setLdsNetworkAdapterInstrumentation, executeAsyncActivity, METRIC_KEYS, onIdleDetected } from 'force/ldsInstrumentation';
|
|
30
33
|
import { REFRESH_ADAPTER_EVENT, ADAPTER_UNFULFILLED_ERROR, instrument as instrument$2 } from 'force/ldsBindings';
|
|
31
34
|
import { counter, registerCacheStats, perfStart, perfEnd, registerPeriodicLogger, interaction, timer } from 'instrumentation/service';
|
|
32
|
-
import auraNetworkAdapter, { instrument as instrument$1, forceRecordTransactionsDisabled, ldsNetworkAdapterInstrument, dispatchAuraAction, defaultActionConfig } from 'force/ldsNetwork';
|
|
33
35
|
import { instrument as instrument$3 } from 'force/adsBridge';
|
|
34
36
|
import { withRegistration, register, setDefaultLuvio } from 'force/ldsEngine';
|
|
35
37
|
import { createStorage, clearStorages } from 'force/ldsStorage';
|
|
36
|
-
import { buildJwtNetworkAdapter } from 'force/ldsNetworkFetchWithJwt';
|
|
37
38
|
import { getObjectInfo, getObjectInfos } from 'force/ldsAdaptersUiapiLex';
|
|
38
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
42
|
+
* All rights reserved.
|
|
43
|
+
* For full license text, see the LICENSE.txt file
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* An implementation of BaseCommand that makes network requests but does not try to
|
|
49
|
+
* use the store.
|
|
50
|
+
*/
|
|
51
|
+
class NetworkCommand extends BaseCommand {
|
|
52
|
+
constructor(services) {
|
|
53
|
+
super();
|
|
54
|
+
this.services = services;
|
|
55
|
+
}
|
|
56
|
+
execute() {
|
|
57
|
+
return this.fetch();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function buildNetworkCommandBaseClassService() {
|
|
61
|
+
return {
|
|
62
|
+
type: 'networkCommandBaseClass',
|
|
63
|
+
version: '1.0',
|
|
64
|
+
service: NetworkCommand,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
70
|
+
* All rights reserved.
|
|
71
|
+
* For full license text, see the LICENSE.txt file
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* An implementation of BaseCommand that makes network requests but does not try to
|
|
77
|
+
* use the store.
|
|
78
|
+
*/
|
|
79
|
+
class AuraNetworkCommand extends NetworkCommand {
|
|
80
|
+
constructor(services) {
|
|
81
|
+
super(services);
|
|
82
|
+
this.services = services;
|
|
83
|
+
this.actionConfig = {
|
|
84
|
+
background: false,
|
|
85
|
+
hotspot: true,
|
|
86
|
+
longRunning: false,
|
|
87
|
+
storable: false,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
fetch() {
|
|
91
|
+
return convertAuraResponseToData(this.services.auraNetwork(this.endpoint, this.auraParams, this.actionConfig));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function buildAuraNetworkCommandBaseClassService() {
|
|
95
|
+
return {
|
|
96
|
+
type: 'auraNetworkCommandBaseClass',
|
|
97
|
+
version: '1.0',
|
|
98
|
+
service: AuraNetworkCommand,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
104
|
+
* All rights reserved.
|
|
105
|
+
* For full license text, see the LICENSE.txt file
|
|
106
|
+
*/
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* An implementation of BaseCommand that makes network requests but does not try to
|
|
111
|
+
* use the store.
|
|
112
|
+
*/
|
|
113
|
+
class FetchNetworkCommand extends NetworkCommand {
|
|
114
|
+
constructor(services) {
|
|
115
|
+
super(services);
|
|
116
|
+
this.services = services;
|
|
117
|
+
}
|
|
118
|
+
fetch() {
|
|
119
|
+
return convertFetchResponseToData(this.services.fetch(...this.fetchParams));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function buildFetchNetworkCommandBaseClassService() {
|
|
123
|
+
return {
|
|
124
|
+
type: 'fetchNetworkCommandBaseClass',
|
|
125
|
+
version: '1.0',
|
|
126
|
+
service: FetchNetworkCommand,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
132
|
+
* All rights reserved.
|
|
133
|
+
* For full license text, see the LICENSE.txt file
|
|
134
|
+
*/
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
function resolvedPromiseLike(result) {
|
|
138
|
+
// Don't nest anything promise like
|
|
139
|
+
if (isPromiseOrPromiseLike(result)) {
|
|
140
|
+
return result.then((nextResult) => nextResult);
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
then: (onFulfilled, _onRejected) => {
|
|
144
|
+
if (onFulfilled) {
|
|
145
|
+
try {
|
|
146
|
+
return resolvedPromiseLike(onFulfilled(result));
|
|
147
|
+
}
|
|
148
|
+
catch (e) {
|
|
149
|
+
return rejectedPromiseLike(e);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// assume TResult1 == Result and just pass result down the chain
|
|
153
|
+
return resolvedPromiseLike(result);
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Returns a PromiseLike object that rejects with the specified reason.
|
|
159
|
+
*
|
|
160
|
+
* @param reason rejection value
|
|
161
|
+
* @returns PromiseLike that rejects with reason
|
|
162
|
+
*/
|
|
163
|
+
function rejectedPromiseLike(reason) {
|
|
164
|
+
if (isPromiseOrPromiseLike(reason)) {
|
|
165
|
+
return reason.then((nextResult) => nextResult);
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
then: (_onFulfilled, onRejected) => {
|
|
169
|
+
if (onRejected) {
|
|
170
|
+
try {
|
|
171
|
+
return resolvedPromiseLike(onRejected(reason));
|
|
172
|
+
}
|
|
173
|
+
catch (e) {
|
|
174
|
+
return rejectedPromiseLike(e);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// assume TResult2 == Result and just pass rejection down the chain
|
|
178
|
+
return rejectedPromiseLike(reason);
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function isPromiseOrPromiseLike(value) {
|
|
183
|
+
return (value instanceof Promise ||
|
|
184
|
+
(typeof value === 'object' && value !== null && typeof value.then === 'function'));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Converts an arbitrary value to an Error.
|
|
189
|
+
*
|
|
190
|
+
* @param x anything
|
|
191
|
+
* @returns Error corresponding to x
|
|
192
|
+
*/
|
|
193
|
+
function toError(x) {
|
|
194
|
+
if (x instanceof Error) {
|
|
195
|
+
return x;
|
|
196
|
+
}
|
|
197
|
+
return new Error(`${x}`);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
class Ok {
|
|
201
|
+
constructor(value) {
|
|
202
|
+
this.value = value;
|
|
203
|
+
}
|
|
204
|
+
isOk() {
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
isErr() {
|
|
208
|
+
return !this.isOk();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
class Err {
|
|
212
|
+
constructor(error) {
|
|
213
|
+
this.error = error;
|
|
214
|
+
}
|
|
215
|
+
isOk() {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
isErr() {
|
|
219
|
+
return !this.isOk();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const ok = (value) => new Ok(value);
|
|
223
|
+
const err = (err) => new Err(err);
|
|
224
|
+
// an error to indicate that the data inside a Result construct
|
|
225
|
+
// is missing or incomplete
|
|
226
|
+
class DataNotFoundError extends Error {
|
|
227
|
+
constructor(message) {
|
|
228
|
+
super(message);
|
|
229
|
+
this.name = 'DataNotFoundError';
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
class DataIncompleteError extends Error {
|
|
233
|
+
constructor(message, partialData) {
|
|
234
|
+
super(message);
|
|
235
|
+
this.partialData = partialData;
|
|
236
|
+
this.name = 'DataIncompleteError';
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function isDataNotFoundError(error) {
|
|
240
|
+
return error instanceof DataNotFoundError || error.name === 'DataNotFoundError';
|
|
241
|
+
}
|
|
242
|
+
function isDataIncompleteError(error) {
|
|
243
|
+
return error instanceof DataIncompleteError || error.name === 'DataIncompleteError';
|
|
244
|
+
}
|
|
245
|
+
function isCacheHitOrError(value) {
|
|
246
|
+
if (value.isErr() && (isDataIncompleteError(value.error) || isDataNotFoundError(value.error))) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
254
|
+
* All rights reserved.
|
|
255
|
+
* For full license text, see the LICENSE.txt file
|
|
256
|
+
*/
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* An implementation of BaseCommand that supports streaming responses and does not use the store.
|
|
261
|
+
*/
|
|
262
|
+
class StreamingCommand extends BaseCommand {
|
|
263
|
+
constructor(services) {
|
|
264
|
+
super();
|
|
265
|
+
this.services = services;
|
|
266
|
+
}
|
|
267
|
+
execute() {
|
|
268
|
+
return this.convertFetchStreamResponseToData(this.services.fetch(...this.fetchParams));
|
|
269
|
+
}
|
|
270
|
+
convertFetchStreamResponseToData(response) {
|
|
271
|
+
return response.then((response) => {
|
|
272
|
+
if (response.ok && response.body) {
|
|
273
|
+
return ok(this.decodeByteStream(response.body));
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
return err(toError(response.ok ? 'Response body not present' : response.statusText));
|
|
277
|
+
}
|
|
278
|
+
}, (reason) => err(toError(reason)));
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
function buildStreamingCommandBaseClassService() {
|
|
282
|
+
return {
|
|
283
|
+
type: 'streamingCommandBaseClass',
|
|
284
|
+
version: '1.0',
|
|
285
|
+
service: StreamingCommand,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
291
|
+
* All rights reserved.
|
|
292
|
+
* For full license text, see the LICENSE.txt file
|
|
293
|
+
*/
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* An implementation of StreamingCommand that handles SSE (Server-Sent Event) streams.
|
|
298
|
+
*/
|
|
299
|
+
class SSECommand extends StreamingCommand {
|
|
300
|
+
constructor(services) {
|
|
301
|
+
super(services);
|
|
302
|
+
this.services = services;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Decodes the bytes returned by fetch into the correct shape.
|
|
306
|
+
*
|
|
307
|
+
* @param byteStream ReadableStream<Uint8Array> returned by fetch
|
|
308
|
+
* @returns ReadableStream<StreamedData> that will be the result of the Command
|
|
309
|
+
*/
|
|
310
|
+
decodeByteStream(byteStream) {
|
|
311
|
+
return this.decodeSSEStream(byteStream
|
|
312
|
+
// eslint-disable-next-line no-undef
|
|
313
|
+
.pipeThrough(new TextDecoderStream())
|
|
314
|
+
.pipeThrough(new SSEParsingStream()));
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
function buildSSECommandBaseClassService() {
|
|
318
|
+
return {
|
|
319
|
+
type: 'SSECommandBaseClass',
|
|
320
|
+
version: '1.0',
|
|
321
|
+
service: SSECommand,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
const sseRegex = /^(?<field>[^:]*?)(: ?(?<value>.*?))?(?:\r\n?|\n)/;
|
|
325
|
+
// +-------v------++--------v--------++-----v----+
|
|
326
|
+
// | | |
|
|
327
|
+
// | | CRLF | CR | LF
|
|
328
|
+
// | |
|
|
329
|
+
// | ": value", or ": comment" if no field name (optional)
|
|
330
|
+
// |
|
|
331
|
+
// field name (optional); can be entire line if no ":"
|
|
332
|
+
class SSEParsingStream extends TransformStream {
|
|
333
|
+
constructor() {
|
|
334
|
+
let ignoreLeadingLF = false, partialLine = '', data = '', event = '', id = '', retry;
|
|
335
|
+
super({
|
|
336
|
+
transform(chunk, controller) {
|
|
337
|
+
// account for case where chunk boundary splits \r\n
|
|
338
|
+
if (ignoreLeadingLF && chunk.startsWith('\n')) {
|
|
339
|
+
// eslint-disable-next-line no-param-reassign
|
|
340
|
+
chunk = chunk.slice(1);
|
|
341
|
+
}
|
|
342
|
+
ignoreLeadingLF = chunk.endsWith('\r');
|
|
343
|
+
// prepend partial last line from previous chunk
|
|
344
|
+
let text = partialLine + chunk;
|
|
345
|
+
let match;
|
|
346
|
+
while ((match = text.match(sseRegex))) {
|
|
347
|
+
text = text.slice(match[0].length);
|
|
348
|
+
// blank linke, end of text/event-stream message
|
|
349
|
+
if (match.groups.field === '' && match.groups.value === undefined) {
|
|
350
|
+
// drop messages with no data
|
|
351
|
+
if (data === '') {
|
|
352
|
+
event = '';
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
// strip trailing \n from data
|
|
356
|
+
if (data.endsWith('\n')) {
|
|
357
|
+
data = data.slice(0, -1);
|
|
358
|
+
}
|
|
359
|
+
const sseMessage = {
|
|
360
|
+
data,
|
|
361
|
+
id,
|
|
362
|
+
// default event value is "message"
|
|
363
|
+
event: event || 'message',
|
|
364
|
+
};
|
|
365
|
+
if (retry !== undefined) {
|
|
366
|
+
sseMessage.retry = retry;
|
|
367
|
+
}
|
|
368
|
+
controller.enqueue(sseMessage);
|
|
369
|
+
// clear data & event for next message; id and retry persist until changed
|
|
370
|
+
data = event = '';
|
|
371
|
+
}
|
|
372
|
+
// data: line
|
|
373
|
+
else if (match.groups.field === 'data') {
|
|
374
|
+
data += (match.groups.value || '') + '\n';
|
|
375
|
+
}
|
|
376
|
+
// event: line
|
|
377
|
+
else if (match.groups.field === 'event') {
|
|
378
|
+
event = match.groups.value || '';
|
|
379
|
+
}
|
|
380
|
+
// id: line
|
|
381
|
+
else if (match.groups.field === 'id') {
|
|
382
|
+
const idValue = match.groups.value || '';
|
|
383
|
+
if (!idValue.includes('\u0000')) {
|
|
384
|
+
id = idValue;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
// retry: line
|
|
388
|
+
else if (match.groups.field === 'retry') {
|
|
389
|
+
// ignore bogus values
|
|
390
|
+
if (/^\d+$/.exec(match.groups.value)) {
|
|
391
|
+
retry = parseInt(match.groups.value);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
// comment or unrecognized field, ignore
|
|
395
|
+
else ;
|
|
396
|
+
}
|
|
397
|
+
// save partial line for next chunk
|
|
398
|
+
partialLine = text;
|
|
399
|
+
},
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
406
|
+
* All rights reserved.
|
|
407
|
+
* For full license text, see the LICENSE.txt file
|
|
408
|
+
*/
|
|
409
|
+
|
|
410
|
+
function buildInstrumentCommand(services) {
|
|
411
|
+
const meter = services.instrumentation.metrics.getMeter('onestore');
|
|
412
|
+
return function instrumentCommand(commandClass, commandName) {
|
|
413
|
+
const invocationCounter = meter.createCounter(`${commandName}.command.invocation.count`);
|
|
414
|
+
const errorCounter = meter.createCounter(`${commandName}.command.error.count`);
|
|
415
|
+
const durationHistogram = meter.createHistogram(`${commandName}.command.duration`);
|
|
416
|
+
return class extends commandClass {
|
|
417
|
+
execute(...args) {
|
|
418
|
+
invocationCounter.add(1);
|
|
419
|
+
let result;
|
|
420
|
+
const start = performance.now();
|
|
421
|
+
function recordDuration() {
|
|
422
|
+
const end = performance.now();
|
|
423
|
+
durationHistogram.record(end - start);
|
|
424
|
+
}
|
|
425
|
+
try {
|
|
426
|
+
result = super.execute(...args);
|
|
427
|
+
}
|
|
428
|
+
catch (e) {
|
|
429
|
+
errorCounter.add(1);
|
|
430
|
+
throw e;
|
|
431
|
+
}
|
|
432
|
+
if (typeof result === 'object' && result !== null && 'then' in result) {
|
|
433
|
+
result.then(recordDuration, () => {
|
|
434
|
+
errorCounter.add(1);
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
recordDuration();
|
|
439
|
+
}
|
|
440
|
+
return result;
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
function buildInstrumentCommandServiceDescriptor(services) {
|
|
446
|
+
return {
|
|
447
|
+
type: 'instrumentCommand',
|
|
448
|
+
version: '1.0',
|
|
449
|
+
service: buildInstrumentCommand(services),
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
|
|
39
453
|
/**
|
|
40
454
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
41
455
|
* All rights reserved.
|
|
@@ -274,66 +688,9 @@ class TTLFilteredStore {
|
|
|
274
688
|
*/
|
|
275
689
|
|
|
276
690
|
|
|
277
|
-
function resolvedPromiseLike$1(result) {
|
|
278
|
-
// Don't nest anything promise like
|
|
279
|
-
if (isPromiseOrPromiseLike$1(result)) {
|
|
280
|
-
return result.then((nextResult) => nextResult);
|
|
281
|
-
}
|
|
282
|
-
return {
|
|
283
|
-
then: (onFulfilled, _onRejected) => {
|
|
284
|
-
if (onFulfilled) {
|
|
285
|
-
try {
|
|
286
|
-
return resolvedPromiseLike$1(onFulfilled(result));
|
|
287
|
-
}
|
|
288
|
-
catch (e) {
|
|
289
|
-
return rejectedPromiseLike$1(e);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
// assume TResult1 == Result and just pass result down the chain
|
|
293
|
-
return resolvedPromiseLike$1(result);
|
|
294
|
-
},
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
691
|
/**
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
* @param reason rejection value
|
|
301
|
-
* @returns PromiseLike that rejects with reason
|
|
302
|
-
*/
|
|
303
|
-
function rejectedPromiseLike$1(reason) {
|
|
304
|
-
if (isPromiseOrPromiseLike$1(reason)) {
|
|
305
|
-
return reason.then((nextResult) => nextResult);
|
|
306
|
-
}
|
|
307
|
-
return {
|
|
308
|
-
then: (_onFulfilled, onRejected) => {
|
|
309
|
-
if (onRejected) {
|
|
310
|
-
try {
|
|
311
|
-
return resolvedPromiseLike$1(onRejected(reason));
|
|
312
|
-
}
|
|
313
|
-
catch (e) {
|
|
314
|
-
return rejectedPromiseLike$1(e);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
// assume TResult2 == Result and just pass rejection down the chain
|
|
318
|
-
return rejectedPromiseLike$1(reason);
|
|
319
|
-
},
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
|
-
function isPromiseOrPromiseLike$1(value) {
|
|
323
|
-
return (value instanceof Promise ||
|
|
324
|
-
(typeof value === 'object' && value !== null && typeof value.then === 'function'));
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* Copyright (c) 2022, Salesforce, Inc.,
|
|
329
|
-
* All rights reserved.
|
|
330
|
-
* For full license text, see the LICENSE.txt file
|
|
331
|
-
*/
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* Implementation of CacheInclusionPolicy that uses a single level, in memory,
|
|
336
|
-
* synchronous L1 cache.
|
|
692
|
+
* Implementation of CacheInclusionPolicy that uses a single level, in memory,
|
|
693
|
+
* synchronous L1 cache.
|
|
337
694
|
*/
|
|
338
695
|
class InMemoryCacheInclusionPolicy {
|
|
339
696
|
/**
|
|
@@ -343,7 +700,7 @@ class InMemoryCacheInclusionPolicy {
|
|
|
343
700
|
const { l1, readFromL1 } = options;
|
|
344
701
|
// l1 is all we've got
|
|
345
702
|
const readResult = readFromL1(l1);
|
|
346
|
-
return resolvedPromiseLike
|
|
703
|
+
return resolvedPromiseLike(readResult);
|
|
347
704
|
}
|
|
348
705
|
/**
|
|
349
706
|
* Writes data to a single level in memory store.
|
|
@@ -351,7 +708,7 @@ class InMemoryCacheInclusionPolicy {
|
|
|
351
708
|
write(options) {
|
|
352
709
|
const { l1, writeToL1 } = options;
|
|
353
710
|
writeToL1(l1);
|
|
354
|
-
return resolvedPromiseLike
|
|
711
|
+
return resolvedPromiseLike(undefined);
|
|
355
712
|
}
|
|
356
713
|
}
|
|
357
714
|
/**
|
|
@@ -374,32 +731,6 @@ function buildInMemoryCacheInclusionPolicyService() {
|
|
|
374
731
|
*/
|
|
375
732
|
|
|
376
733
|
|
|
377
|
-
// an error to indicate that the data inside a WithErrors construct
|
|
378
|
-
// is missing or incomplete
|
|
379
|
-
let DataNotFoundError$1 = class DataNotFoundError extends Error {
|
|
380
|
-
constructor(message) {
|
|
381
|
-
super(message);
|
|
382
|
-
this.name = 'DataNotFoundError';
|
|
383
|
-
}
|
|
384
|
-
};
|
|
385
|
-
function isDataNotFoundError$1(error) {
|
|
386
|
-
return error instanceof DataNotFoundError$1 || error.name === 'DataNotFoundError';
|
|
387
|
-
}
|
|
388
|
-
function isCacheHitOrError$1(value) {
|
|
389
|
-
// return cache result if data was found or error was encountered
|
|
390
|
-
const { data, errors } = value;
|
|
391
|
-
const cacheHit = data !== undefined && errors.length === 0;
|
|
392
|
-
const errorEncountered = errors.length > 0 && !isDataNotFoundError$1(errors[0]);
|
|
393
|
-
return cacheHit || errorEncountered;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
/**
|
|
397
|
-
* Copyright (c) 2022, Salesforce, Inc.,
|
|
398
|
-
* All rights reserved.
|
|
399
|
-
* For full license text, see the LICENSE.txt file
|
|
400
|
-
*/
|
|
401
|
-
|
|
402
|
-
|
|
403
734
|
class CacheThenNetworkPolicy {
|
|
404
735
|
constructor(services, validator) {
|
|
405
736
|
this.services = services;
|
|
@@ -417,7 +748,7 @@ class CacheThenNetworkPolicy {
|
|
|
417
748
|
writeToCache: (services, networkResult) => this.writeWithValidation(() => writeToCacheOriginal(networkResult, services)),
|
|
418
749
|
});
|
|
419
750
|
return readFromCacheDedupe({ ...this.services, store: ttlStore }).then((value) => {
|
|
420
|
-
if (isCacheHitOrError
|
|
751
|
+
if (isCacheHitOrError(value)) {
|
|
421
752
|
return value;
|
|
422
753
|
}
|
|
423
754
|
// result not found in cache, try network
|
|
@@ -453,24 +784,154 @@ function buildCacheThenNetworkPolicy(services, validator) {
|
|
|
453
784
|
* For full license text, see the LICENSE.txt file
|
|
454
785
|
*/
|
|
455
786
|
|
|
787
|
+
class NoopOTelTraceAPI {
|
|
788
|
+
getTracer(_name, _version, _options) {
|
|
789
|
+
return new NoopTracer();
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
class NoopTracer {
|
|
793
|
+
startSpan(_name, _options, _context) {
|
|
794
|
+
return new NoopSpan();
|
|
795
|
+
}
|
|
796
|
+
startActiveSpan(name, options, context, fn) {
|
|
797
|
+
let opts;
|
|
798
|
+
let ctx;
|
|
799
|
+
let fun;
|
|
800
|
+
if (typeof options === 'function') {
|
|
801
|
+
fun = options;
|
|
802
|
+
}
|
|
803
|
+
else {
|
|
804
|
+
opts = options;
|
|
805
|
+
if (typeof context === 'function') {
|
|
806
|
+
fun = context;
|
|
807
|
+
}
|
|
808
|
+
else {
|
|
809
|
+
ctx = context;
|
|
810
|
+
fun = fn;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
const span = this.startSpan(name, opts, ctx);
|
|
814
|
+
try {
|
|
815
|
+
return fun(span);
|
|
816
|
+
}
|
|
817
|
+
finally {
|
|
818
|
+
span.end();
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
class NoopSpan {
|
|
823
|
+
spanContext() {
|
|
824
|
+
// TODO: I'll need to double check, but I think even if we provide a
|
|
825
|
+
// noop implementation, there is still a requirement to pass along context
|
|
826
|
+
return {
|
|
827
|
+
spanId: 'noopSpanId',
|
|
828
|
+
traceId: 'noopTraceId',
|
|
829
|
+
traceFlags: 0,
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
setAttribute(_key, _value) {
|
|
833
|
+
return this;
|
|
834
|
+
}
|
|
835
|
+
setAttributes(_attributes) {
|
|
836
|
+
return this;
|
|
837
|
+
}
|
|
838
|
+
addEvent(_name, _attributesOrStartTime, _startTime) {
|
|
839
|
+
return this;
|
|
840
|
+
}
|
|
841
|
+
setStatus(_status) {
|
|
842
|
+
return this;
|
|
843
|
+
}
|
|
844
|
+
updateName(_name) {
|
|
845
|
+
return this;
|
|
846
|
+
}
|
|
847
|
+
end(_endTime) {
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
isRecording() {
|
|
851
|
+
return false;
|
|
852
|
+
}
|
|
853
|
+
recordException(_exception, _time) {
|
|
854
|
+
return;
|
|
855
|
+
}
|
|
856
|
+
}
|
|
456
857
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
constructor(message) {
|
|
461
|
-
super(message);
|
|
462
|
-
this.name = 'DataNotFoundError';
|
|
858
|
+
class NoopOTelMetricsAPI {
|
|
859
|
+
getMeter(__name, _version, __options) {
|
|
860
|
+
return new NoopMeter();
|
|
463
861
|
}
|
|
464
862
|
}
|
|
465
|
-
|
|
466
|
-
|
|
863
|
+
class NoopMeter {
|
|
864
|
+
createHistogram(_name, _options) {
|
|
865
|
+
return new NoopHistogram();
|
|
866
|
+
}
|
|
867
|
+
createCounter(_name, _options) {
|
|
868
|
+
return new NoopCounter();
|
|
869
|
+
}
|
|
870
|
+
createUpDownCounter(_name, _options) {
|
|
871
|
+
return new NoopUpDownCounter();
|
|
872
|
+
}
|
|
873
|
+
createObservableGauge(_name, _options) {
|
|
874
|
+
return new NoopObservableGuage();
|
|
875
|
+
}
|
|
876
|
+
createObservableCounter(_name, _options) {
|
|
877
|
+
return new NoopObservableCounter();
|
|
878
|
+
}
|
|
879
|
+
createObservableUpDownCounter(_name, _options) {
|
|
880
|
+
return new NoopObservableUpDownCounter();
|
|
881
|
+
}
|
|
882
|
+
addBatchObservableCallback(_callback, _observables) {
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
removeBatchObservableCallback(_callback, _observables) {
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
467
888
|
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
889
|
+
class NoopCounter {
|
|
890
|
+
add(_value, _attributes, _context) {
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
class NoopHistogram {
|
|
895
|
+
record(_value, _attributes, _context) {
|
|
896
|
+
return;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
class NoopUpDownCounter {
|
|
900
|
+
add(_value, _attributes, _context) {
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
class NoopObservableCounter {
|
|
905
|
+
addCallback(_callback) {
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
removeCallback(_callback) {
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
class NoopObservableGuage {
|
|
913
|
+
addCallback(_callback) {
|
|
914
|
+
return;
|
|
915
|
+
}
|
|
916
|
+
removeCallback(_callback) {
|
|
917
|
+
return;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
class NoopObservableUpDownCounter {
|
|
921
|
+
addCallback(_callback) {
|
|
922
|
+
return;
|
|
923
|
+
}
|
|
924
|
+
removeCallback(_callback) {
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
/* eslint-disable no-dupe-class-members */
|
|
930
|
+
function buildNoopInstrumentationService() {
|
|
931
|
+
return {
|
|
932
|
+
trace: new NoopOTelTraceAPI(),
|
|
933
|
+
metrics: new NoopOTelMetricsAPI(),
|
|
934
|
+
};
|
|
474
935
|
}
|
|
475
936
|
|
|
476
937
|
/**
|
|
@@ -604,63 +1065,6 @@ function buildKeyBasedRequestDedupeService() {
|
|
|
604
1065
|
*/
|
|
605
1066
|
|
|
606
1067
|
|
|
607
|
-
function resolvedPromiseLike(result) {
|
|
608
|
-
// Don't nest anything promise like
|
|
609
|
-
if (isPromiseOrPromiseLike(result)) {
|
|
610
|
-
return result.then((nextResult) => nextResult);
|
|
611
|
-
}
|
|
612
|
-
return {
|
|
613
|
-
then: (onFulfilled, _onRejected) => {
|
|
614
|
-
if (onFulfilled) {
|
|
615
|
-
try {
|
|
616
|
-
return resolvedPromiseLike(onFulfilled(result));
|
|
617
|
-
}
|
|
618
|
-
catch (e) {
|
|
619
|
-
return rejectedPromiseLike(e);
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
// assume TResult1 == Result and just pass result down the chain
|
|
623
|
-
return resolvedPromiseLike(result);
|
|
624
|
-
},
|
|
625
|
-
};
|
|
626
|
-
}
|
|
627
|
-
/**
|
|
628
|
-
* Returns a PromiseLike object that rejects with the specified reason.
|
|
629
|
-
*
|
|
630
|
-
* @param reason rejection value
|
|
631
|
-
* @returns PromiseLike that rejects with reason
|
|
632
|
-
*/
|
|
633
|
-
function rejectedPromiseLike(reason) {
|
|
634
|
-
if (isPromiseOrPromiseLike(reason)) {
|
|
635
|
-
return reason.then((nextResult) => nextResult);
|
|
636
|
-
}
|
|
637
|
-
return {
|
|
638
|
-
then: (_onFulfilled, onRejected) => {
|
|
639
|
-
if (onRejected) {
|
|
640
|
-
try {
|
|
641
|
-
return resolvedPromiseLike(onRejected(reason));
|
|
642
|
-
}
|
|
643
|
-
catch (e) {
|
|
644
|
-
return rejectedPromiseLike(e);
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
// assume TResult2 == Result and just pass rejection down the chain
|
|
648
|
-
return rejectedPromiseLike(reason);
|
|
649
|
-
},
|
|
650
|
-
};
|
|
651
|
-
}
|
|
652
|
-
function isPromiseOrPromiseLike(value) {
|
|
653
|
-
return (value instanceof Promise ||
|
|
654
|
-
(typeof value === 'object' && value !== null && typeof value.then === 'function'));
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
/**
|
|
658
|
-
* Copyright (c) 2022, Salesforce, Inc.,
|
|
659
|
-
* All rights reserved.
|
|
660
|
-
* For full license text, see the LICENSE.txt file
|
|
661
|
-
*/
|
|
662
|
-
|
|
663
|
-
|
|
664
1068
|
/**
|
|
665
1069
|
* A simple implementation of KeyKeySubscriptionService.
|
|
666
1070
|
*/
|
|
@@ -734,15 +1138,536 @@ class DefaultTypeRegistry {
|
|
|
734
1138
|
}
|
|
735
1139
|
}
|
|
736
1140
|
/**
|
|
737
|
-
* Constructs an in-memory implementation of StoreService.
|
|
1141
|
+
* Constructs an in-memory implementation of StoreService.
|
|
1142
|
+
*
|
|
1143
|
+
* @returns in-memory implementation of StoreService
|
|
1144
|
+
*/
|
|
1145
|
+
function buildDefaultTypeRegistryService() {
|
|
1146
|
+
return {
|
|
1147
|
+
type: 'typeRegistry',
|
|
1148
|
+
version: '1.0',
|
|
1149
|
+
service: new DefaultTypeRegistry(),
|
|
1150
|
+
};
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
/**
|
|
1154
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
1155
|
+
* All rights reserved.
|
|
1156
|
+
* For full license text, see the LICENSE.txt file
|
|
1157
|
+
*/
|
|
1158
|
+
|
|
1159
|
+
function e(e){this.message=e;}e.prototype=new Error,e.prototype.name="InvalidCharacterError";var r="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 t(e){var t=e.replace(/-/g,"+").replace(/_/g,"/");switch(t.length%4){case 0:break;case 2:t+="==";break;case 3:t+="=";break;default:throw "Illegal base64url string!"}try{return function(e){return decodeURIComponent(r(e).replace(/(.)/g,(function(e,r){var t=r.charCodeAt(0).toString(16).toUpperCase();return t.length<2&&(t="0"+t),"%"+t})))}(t)}catch(e){return r(t)}}function n(e){this.message=e;}function o(e,r){if("string"!=typeof e)throw new n("Invalid token specified");var o=!0===(r=r||{}).header?0:1;try{return JSON.parse(t(e.split(".")[o]))}catch(e){throw new n("Invalid token specified: "+e.message)}}n.prototype=new Error,n.prototype.name="InvalidTokenError";
|
|
1160
|
+
|
|
1161
|
+
/**
|
|
1162
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
1163
|
+
* All rights reserved.
|
|
1164
|
+
* For full license text, see the LICENSE.txt file
|
|
1165
|
+
*/
|
|
1166
|
+
|
|
1167
|
+
const LogLevelMap = {
|
|
1168
|
+
TRACE: 4,
|
|
1169
|
+
DEBUG: 3,
|
|
1170
|
+
INFO: 2,
|
|
1171
|
+
WARN: 1,
|
|
1172
|
+
ERROR: 0,
|
|
1173
|
+
};
|
|
1174
|
+
/**
|
|
1175
|
+
* A simple Logger implementation.
|
|
1176
|
+
*/
|
|
1177
|
+
class ConsoleLogger {
|
|
1178
|
+
constructor(level = 'WARN',
|
|
1179
|
+
// eslint-disable-next-line no-console
|
|
1180
|
+
printer = console.log, formatter = (level, message) => `${level}: ${message}`) {
|
|
1181
|
+
this.level = level;
|
|
1182
|
+
this.printer = printer;
|
|
1183
|
+
this.formatter = formatter;
|
|
1184
|
+
this.messages = [];
|
|
1185
|
+
}
|
|
1186
|
+
trace(message) {
|
|
1187
|
+
this.log('TRACE', message);
|
|
1188
|
+
}
|
|
1189
|
+
debug(message) {
|
|
1190
|
+
this.log('DEBUG', message);
|
|
1191
|
+
}
|
|
1192
|
+
info(message) {
|
|
1193
|
+
this.log('INFO', message);
|
|
1194
|
+
}
|
|
1195
|
+
warn(message) {
|
|
1196
|
+
this.log('WARN', message);
|
|
1197
|
+
}
|
|
1198
|
+
error(message) {
|
|
1199
|
+
this.log('ERROR', message);
|
|
1200
|
+
}
|
|
1201
|
+
log(level, message) {
|
|
1202
|
+
if (LogLevelMap[level] > LogLevelMap[this.level]) {
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
1205
|
+
this.printer(this.formatter(level, message));
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
/**
|
|
1209
|
+
* Constructs a new LoggerService.
|
|
1210
|
+
*/
|
|
1211
|
+
function loggerService(level, printer, formatter) {
|
|
1212
|
+
return new ConsoleLogger(level, printer, formatter);
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
/**
|
|
1216
|
+
* Represents a JWT token with its decoded info and optional extra info.
|
|
1217
|
+
*
|
|
1218
|
+
* @typeparam T - Type of the additional payload in the JWT.
|
|
1219
|
+
* @typeparam ExtraInfo - Type of the additional information.
|
|
1220
|
+
*/
|
|
1221
|
+
class JwtToken {
|
|
1222
|
+
/**
|
|
1223
|
+
* Create a new JwtToken.
|
|
1224
|
+
*
|
|
1225
|
+
* @param _token - The JWT string.
|
|
1226
|
+
* @param _decodedInfo - The decoded information from the JWT.
|
|
1227
|
+
* @param _extraInfo - Any additional information associated with the JWT.
|
|
1228
|
+
*/
|
|
1229
|
+
constructor(_token, _decodedInfo, _extraInfo) {
|
|
1230
|
+
this._token = _token;
|
|
1231
|
+
this._decodedInfo = _decodedInfo;
|
|
1232
|
+
this._extraInfo = _extraInfo;
|
|
1233
|
+
}
|
|
1234
|
+
/**
|
|
1235
|
+
* Get the JWT string.
|
|
1236
|
+
*
|
|
1237
|
+
* @returns The JWT string.
|
|
1238
|
+
*/
|
|
1239
|
+
get token() {
|
|
1240
|
+
return this._token;
|
|
1241
|
+
}
|
|
1242
|
+
/**
|
|
1243
|
+
* Get the additional information associated with the JWT.
|
|
1244
|
+
*
|
|
1245
|
+
* @returns The additional information.
|
|
1246
|
+
*/
|
|
1247
|
+
get extraInfo() {
|
|
1248
|
+
return this._extraInfo;
|
|
1249
|
+
}
|
|
1250
|
+
/**
|
|
1251
|
+
* Get the decoded information from the JWT.
|
|
1252
|
+
*
|
|
1253
|
+
* @returns The decoded information.
|
|
1254
|
+
*/
|
|
1255
|
+
get decodedInfo() {
|
|
1256
|
+
return this._decodedInfo;
|
|
1257
|
+
}
|
|
1258
|
+
/**
|
|
1259
|
+
* Get the remaining time in seconds until the JWT expires.
|
|
1260
|
+
*
|
|
1261
|
+
* @returns The remaining time in seconds.
|
|
1262
|
+
*/
|
|
1263
|
+
get tokenRemainingSeconds() {
|
|
1264
|
+
return this.decodedInfo.exp - Date.now() / 1000;
|
|
1265
|
+
}
|
|
1266
|
+
/**
|
|
1267
|
+
* Check if the JWT is expired.
|
|
1268
|
+
*
|
|
1269
|
+
* @returns True if the JWT is expired, false otherwise.
|
|
1270
|
+
*/
|
|
1271
|
+
get isExpired() {
|
|
1272
|
+
return this.tokenRemainingSeconds <= 0;
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
/**
|
|
1277
|
+
* Default logger if none is provided. Is overwritten in non-production environments.
|
|
1278
|
+
*/
|
|
1279
|
+
let defaultLogger = {
|
|
1280
|
+
trace: () => { },
|
|
1281
|
+
debug: () => { },
|
|
1282
|
+
info: () => { },
|
|
1283
|
+
warn: () => { },
|
|
1284
|
+
error: () => { },
|
|
1285
|
+
};
|
|
1286
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
1287
|
+
defaultLogger = loggerService();
|
|
1288
|
+
}
|
|
1289
|
+
/**
|
|
1290
|
+
* Decodes JWT token information and provides a default expiry if none is present.
|
|
1291
|
+
*
|
|
1292
|
+
* @param token - JWT token as a string.
|
|
1293
|
+
* @param defaultTokenTTLInSeconds - Default expiry time in seconds if "exp" claim is not present in token.
|
|
1294
|
+
* @param logger - Logger for logging warnings and errors.
|
|
1295
|
+
*
|
|
1296
|
+
* @returns An object of decoded JWT token information.
|
|
1297
|
+
*/
|
|
1298
|
+
function computeDecodedInfo(token, defaultTokenTTLInSeconds, logger) {
|
|
1299
|
+
const decodedInfo = o(token);
|
|
1300
|
+
if (decodedInfo.exp === undefined) {
|
|
1301
|
+
logger.warn(`"exp" claim is not present in the provided token.`);
|
|
1302
|
+
decodedInfo.exp = Date.now() / 1000 + defaultTokenTTLInSeconds;
|
|
1303
|
+
}
|
|
1304
|
+
return decodedInfo;
|
|
1305
|
+
}
|
|
1306
|
+
/**
|
|
1307
|
+
* A repository for JWT tokens.
|
|
1308
|
+
*/
|
|
1309
|
+
class JwtRepository {
|
|
1310
|
+
/**
|
|
1311
|
+
* @param limitInSeconds - Time in seconds before the token's expiry to notify observers.
|
|
1312
|
+
* @param defaultTokenTTLInSeconds - Default token expiry time in seconds if "exp" claim is not present in token.
|
|
1313
|
+
* @param logger - Logger for logging warnings and errors.
|
|
1314
|
+
*/
|
|
1315
|
+
constructor(limitInSeconds = 5, defaultTokenTTLInSeconds = 120, logger = defaultLogger) {
|
|
1316
|
+
this.limitInSeconds = limitInSeconds;
|
|
1317
|
+
this.defaultTokenTTLInSeconds = defaultTokenTTLInSeconds;
|
|
1318
|
+
this.logger = logger;
|
|
1319
|
+
this.observers = [];
|
|
1320
|
+
}
|
|
1321
|
+
/**
|
|
1322
|
+
* Get the current token.
|
|
1323
|
+
*/
|
|
1324
|
+
get token() {
|
|
1325
|
+
return this._token;
|
|
1326
|
+
}
|
|
1327
|
+
/**
|
|
1328
|
+
* Set the current token.
|
|
1329
|
+
*
|
|
1330
|
+
* @param token - JWT token as a string.
|
|
1331
|
+
* @param extraInfo - Optional extra information.
|
|
1332
|
+
*/
|
|
1333
|
+
setToken(token, extraInfo) {
|
|
1334
|
+
const decodedInfo = computeDecodedInfo(token, this.defaultTokenTTLInSeconds, this.logger);
|
|
1335
|
+
this._token = new JwtToken(token, decodedInfo, extraInfo);
|
|
1336
|
+
this.observeTokenExpiration();
|
|
1337
|
+
return this._token;
|
|
1338
|
+
}
|
|
1339
|
+
/**
|
|
1340
|
+
* Remove the current token.
|
|
1341
|
+
*/
|
|
1342
|
+
removeToken() {
|
|
1343
|
+
this._token = undefined;
|
|
1344
|
+
this.clearTimeoutHandler();
|
|
1345
|
+
}
|
|
1346
|
+
/**
|
|
1347
|
+
* Subscribe to the token nearing its expiration.
|
|
1348
|
+
*
|
|
1349
|
+
* @param cb - Callback function to execute when token is nearing expiration.
|
|
1350
|
+
*/
|
|
1351
|
+
subscribeToTokenNearExpiration(cb) {
|
|
1352
|
+
this.observers.push(cb);
|
|
1353
|
+
this.observeTokenExpiration();
|
|
1354
|
+
return () => {
|
|
1355
|
+
this.observers = this.observers.filter((observer) => observer !== cb);
|
|
1356
|
+
};
|
|
1357
|
+
}
|
|
1358
|
+
/**
|
|
1359
|
+
* Clear the timeout handler.
|
|
1360
|
+
*/
|
|
1361
|
+
clearTimeoutHandler() {
|
|
1362
|
+
if (this.timeoutHandler !== undefined) {
|
|
1363
|
+
clearTimeout(this.timeoutHandler);
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
/**
|
|
1367
|
+
* Observe and handle token expiration.
|
|
1368
|
+
*/
|
|
1369
|
+
observeTokenExpiration() {
|
|
1370
|
+
this.clearTimeoutHandler();
|
|
1371
|
+
if (this.observers.length === 0 || this.token === undefined) {
|
|
1372
|
+
return;
|
|
1373
|
+
}
|
|
1374
|
+
this.timeoutHandler = setTimeout(() => this.notifyTokenIsExpiring(), this.computeTimeoutTimeInMs());
|
|
1375
|
+
}
|
|
1376
|
+
/**
|
|
1377
|
+
* Compute the timeout time in milliseconds.
|
|
1378
|
+
*/
|
|
1379
|
+
computeTimeoutTimeInMs() {
|
|
1380
|
+
const remainingSeconds = this.token.tokenRemainingSeconds;
|
|
1381
|
+
let timeoutTimeInSeconds = remainingSeconds - this.limitInSeconds;
|
|
1382
|
+
return timeoutTimeInSeconds < 0 ? 0 : timeoutTimeInSeconds * 1000;
|
|
1383
|
+
}
|
|
1384
|
+
/**
|
|
1385
|
+
* Notify all observers that the token is expiring.
|
|
1386
|
+
*/
|
|
1387
|
+
notifyTokenIsExpiring() {
|
|
1388
|
+
this.observers.forEach((cb) => {
|
|
1389
|
+
try {
|
|
1390
|
+
cb.call(undefined, this.token);
|
|
1391
|
+
}
|
|
1392
|
+
catch (e) {
|
|
1393
|
+
this.logger.error(e.message);
|
|
1394
|
+
}
|
|
1395
|
+
});
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
/**
|
|
1400
|
+
* JwtManager class.
|
|
1401
|
+
* It provides methods for managing JWT (Json Web Token), such as retrieving and refreshing.
|
|
1402
|
+
*
|
|
1403
|
+
* @template T The data type the JwtToken carries. Default to unknown.
|
|
1404
|
+
* @template ExtraInfo The type of the optional extra information returned by the getJwt method. Defaults to undefined.
|
|
1405
|
+
* @property {JwtRepository<T, ExtraInfo>} jwtRepository JwtRepository instance used for token management.
|
|
1406
|
+
* @property {JwtResolver<ExtraInfo>} resolver JwtResolver instance used for token retrieval.
|
|
1407
|
+
*/
|
|
1408
|
+
class JwtManager {
|
|
1409
|
+
/**
|
|
1410
|
+
* Constructor for JwtManager class.
|
|
1411
|
+
*
|
|
1412
|
+
* @param {JwtRepository<T, ExtraInfo>} jwtRepository JwtRepository instance used for token management.
|
|
1413
|
+
* @param {JwtResolver<ExtraInfo>} resolver JwtResolver instance used for token retrieval.
|
|
1414
|
+
* @param {JwtManagerOptions} options JwtManagerOptions bag to customize behavior.
|
|
1415
|
+
*/
|
|
1416
|
+
constructor(jwtRepository, resolver, options) {
|
|
1417
|
+
this.jwtRepository = jwtRepository;
|
|
1418
|
+
this.resolver = resolver;
|
|
1419
|
+
if (options === null || options === void 0 ? void 0 : options.keepTokenUpdated) {
|
|
1420
|
+
jwtRepository.subscribeToTokenNearExpiration(() => this.refreshToken());
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
/**
|
|
1424
|
+
* Method to get a JWT token.
|
|
1425
|
+
* If there's a token request in progress, it will return the Promise of this request.
|
|
1426
|
+
* If the current token is undefined or expired, it will initiate a token refresh.
|
|
1427
|
+
* Otherwise, it will return the current token.
|
|
1428
|
+
*
|
|
1429
|
+
* @returns {JwtToken<T, ExtraInfo> | Promise<JwtToken<T, ExtraInfo>>} The current token or the Promise of a token request.
|
|
1430
|
+
*/
|
|
1431
|
+
getJwt() {
|
|
1432
|
+
if (this.inflightPromise) {
|
|
1433
|
+
return this.inflightPromise;
|
|
1434
|
+
}
|
|
1435
|
+
const token = this.jwtRepository.token;
|
|
1436
|
+
if (token === undefined || token.isExpired) {
|
|
1437
|
+
return this.refreshToken();
|
|
1438
|
+
}
|
|
1439
|
+
return token;
|
|
1440
|
+
}
|
|
1441
|
+
/**
|
|
1442
|
+
* Method to refresh a JWT token.
|
|
1443
|
+
* If a refresh request is already in progress, it will return the Promise of this request.
|
|
1444
|
+
* Otherwise, it will start a new refresh request and return its Promise.
|
|
1445
|
+
*
|
|
1446
|
+
* @returns {Promise<JwtToken<T, ExtraInfo>>} Promise of the refreshed token.
|
|
1447
|
+
*/
|
|
1448
|
+
refreshToken() {
|
|
1449
|
+
if (this.inflightPromise === undefined) {
|
|
1450
|
+
this.inflightPromise = new Promise((resolve, reject) => {
|
|
1451
|
+
this.resolver
|
|
1452
|
+
.getJwt()
|
|
1453
|
+
.then(({ jwt, extraInfo }) => {
|
|
1454
|
+
this.inflightPromise = undefined;
|
|
1455
|
+
const token = this.jwtRepository.setToken(jwt, extraInfo);
|
|
1456
|
+
resolve(token);
|
|
1457
|
+
})
|
|
1458
|
+
.catch((reason) => {
|
|
1459
|
+
this.inflightPromise = undefined;
|
|
1460
|
+
reject(reason);
|
|
1461
|
+
});
|
|
1462
|
+
});
|
|
1463
|
+
}
|
|
1464
|
+
return this.inflightPromise;
|
|
1465
|
+
}
|
|
1466
|
+
/**
|
|
1467
|
+
* Method to check if a token refresh is in progress.
|
|
1468
|
+
*
|
|
1469
|
+
* @returns {boolean} true if a token refresh is in progress, false otherwise.
|
|
1470
|
+
*/
|
|
1471
|
+
get isRefreshingToken() {
|
|
1472
|
+
return this.inflightPromise !== undefined;
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
/**
|
|
1477
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
1478
|
+
* All rights reserved.
|
|
1479
|
+
* For full license text, see the LICENSE.txt file
|
|
1480
|
+
*/
|
|
1481
|
+
|
|
1482
|
+
|
|
1483
|
+
function buildFetchService(interceptors = { request: [] }) {
|
|
1484
|
+
return {
|
|
1485
|
+
type: 'fetch',
|
|
1486
|
+
version: '1.0',
|
|
1487
|
+
service: function (...args) {
|
|
1488
|
+
const { request: requestInterceptors = [] } = interceptors;
|
|
1489
|
+
const pending = requestInterceptors.reduce((previousPromise, interceptor) => previousPromise.then(interceptor), resolvedPromiseLike(args));
|
|
1490
|
+
return pending.then((args) => fetch(...args));
|
|
1491
|
+
},
|
|
1492
|
+
};
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
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';
|
|
1496
|
+
function setHeaderAuthorization({ token }, [resource, options = {}]) {
|
|
1497
|
+
let hasAuthorizationHeaderBeenSet = false;
|
|
1498
|
+
const Authorization = `Bearer ${token}`;
|
|
1499
|
+
// The following is necessary because fetch(RequestInfo, options|RequestInit)
|
|
1500
|
+
// does not merge properties from options|RequestInit.headers into RequestInfo.headers,
|
|
1501
|
+
// instead it will pave over RequestInfo.headers if options|RequestInit.headers
|
|
1502
|
+
// is defined. Therefore, this function must preserve any pre-existing headers
|
|
1503
|
+
// properties across two different arguments that themselves may be four
|
|
1504
|
+
// different data types.
|
|
1505
|
+
//
|
|
1506
|
+
// - a string
|
|
1507
|
+
// - an instance of URL
|
|
1508
|
+
// - an instance of Request
|
|
1509
|
+
//
|
|
1510
|
+
// And for this argument we only need to guard against overwriting an
|
|
1511
|
+
// existing `headers` property whose value is an instance of Headers.
|
|
1512
|
+
// This will only be valid when the resource argument is an instance of
|
|
1513
|
+
// Request, which implicitly holds a property called `headers` whose
|
|
1514
|
+
// value is an instance of Headers AND options has not been explicitly
|
|
1515
|
+
// provided, or has but does not have a headers property. The existance
|
|
1516
|
+
// of an explicit headers property would likely be intentional, so
|
|
1517
|
+
// we defer to the calling code.
|
|
1518
|
+
if (resource instanceof Request && !(options === null || options === void 0 ? void 0 : options.headers)) {
|
|
1519
|
+
// If the resource object's headers instance already contains an
|
|
1520
|
+
// "Authorization" header, then we have to assume this is a mistake
|
|
1521
|
+
// so throw an exception that will result in the fetch call returning
|
|
1522
|
+
// a rejected promise.
|
|
1523
|
+
if (resource.headers.has('Authorization')) {
|
|
1524
|
+
throw new Error(UNEXPECTED_AUTHORIZATION_HEADER_MESSAGE);
|
|
1525
|
+
}
|
|
1526
|
+
// Otherwise, set the "Authorization" header with the provided
|
|
1527
|
+
// JWT value (because options?.headers also doesn't exist)
|
|
1528
|
+
resource.headers.set('Authorization', Authorization);
|
|
1529
|
+
hasAuthorizationHeaderBeenSet = true;
|
|
1530
|
+
}
|
|
1531
|
+
// When the options object is provided, it may already have a
|
|
1532
|
+
// `headers` property whose value is an instance of Headers, or
|
|
1533
|
+
// a `headers` property that is a plain object comprised of key=>value
|
|
1534
|
+
// pairs that will be converted into a Headers object by fetch().
|
|
1535
|
+
//
|
|
1536
|
+
// If the options object contains a property called `headers` whose value
|
|
1537
|
+
// is an instance of Headers...
|
|
1538
|
+
if ((options === null || options === void 0 ? void 0 : options.headers) instanceof Headers) {
|
|
1539
|
+
// ...Check to see if that object contains an "Authorization" header.
|
|
1540
|
+
// If it does, then we have to assume this is a mistake so throw an
|
|
1541
|
+
// exception.
|
|
1542
|
+
if (options === null || options === void 0 ? void 0 : options.headers.has('Authorization')) {
|
|
1543
|
+
throw new Error(UNEXPECTED_AUTHORIZATION_HEADER_MESSAGE);
|
|
1544
|
+
}
|
|
1545
|
+
// Otherwise, set the "Authorization" header with the provided
|
|
1546
|
+
// JWT token value:
|
|
1547
|
+
options === null || options === void 0 ? void 0 : options.headers.set('Authorization', Authorization);
|
|
1548
|
+
}
|
|
1549
|
+
else {
|
|
1550
|
+
// Else, check if options contains a `headers` property whose value
|
|
1551
|
+
// is a plain object comprised of key=>value pairs. If this
|
|
1552
|
+
// object contains a property called "Authorization", then we have
|
|
1553
|
+
// to assume this is a mistake so throw an exception.
|
|
1554
|
+
if ((options === null || options === void 0 ? void 0 : options.headers) && Reflect.has(options === null || options === void 0 ? void 0 : options.headers, 'Authorization')) {
|
|
1555
|
+
throw new Error(UNEXPECTED_AUTHORIZATION_HEADER_MESSAGE);
|
|
1556
|
+
}
|
|
1557
|
+
// Otherwise, add a property called "Authorization", whose value is
|
|
1558
|
+
// the provided JWT value, as long as it has not been set on Request
|
|
1559
|
+
if (!hasAuthorizationHeaderBeenSet) {
|
|
1560
|
+
options.headers = {
|
|
1561
|
+
...options === null || options === void 0 ? void 0 : options.headers,
|
|
1562
|
+
Authorization,
|
|
1563
|
+
};
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
return [resource, options];
|
|
1567
|
+
}
|
|
1568
|
+
function buildJwtRequestHeaderInterceptor(jwtManager, jwtRequestModifier = (_e, fetchArgs) => fetchArgs) {
|
|
1569
|
+
return (args) => {
|
|
1570
|
+
return resolvedPromiseLike(jwtManager.getJwt()).then((token) => {
|
|
1571
|
+
const fetchArgsWithRequestHeaderAuthorization = setHeaderAuthorization(token, args);
|
|
1572
|
+
return token.extraInfo
|
|
1573
|
+
? jwtRequestModifier(token.extraInfo, fetchArgsWithRequestHeaderAuthorization)
|
|
1574
|
+
: fetchArgsWithRequestHeaderAuthorization;
|
|
1575
|
+
});
|
|
1576
|
+
};
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
const SALESFORCE_API_BASE_URI_FLAG = 'api.salesforce.com';
|
|
1580
|
+
const SFAPController = 'SalesforceApiPlatformController';
|
|
1581
|
+
const SFAPJwtMethod = 'getSFAPLightningJwtService';
|
|
1582
|
+
/**
|
|
1583
|
+
* We expect jwt info and baseUri to be present in the response.
|
|
1584
|
+
*
|
|
1585
|
+
* @param body
|
|
1586
|
+
*/
|
|
1587
|
+
function validateResponse(body) {
|
|
1588
|
+
if (!body || !body.jwt || !body.baseUri) {
|
|
1589
|
+
// wrapped the invocation in env conditional
|
|
1590
|
+
// eslint-disable-next-line @salesforce/lds/no-error-in-production
|
|
1591
|
+
throw new Error(`Expected jwt info and baseUri to be present but instead got: ${JSON.stringify(body)}`);
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
/**
|
|
1595
|
+
* Resolves Jwt token for SFAP by calling Aura action
|
|
1596
|
+
* {@link JwtResolver} for platform SFAP
|
|
1597
|
+
*/
|
|
1598
|
+
const platformSfapJwtResolver = {
|
|
1599
|
+
getJwt() {
|
|
1600
|
+
return new Promise((resolve, reject) => {
|
|
1601
|
+
dispatchAuraAction(`${SFAPController}.${SFAPJwtMethod}`, {}, defaultActionConfig)
|
|
1602
|
+
.then((response) => {
|
|
1603
|
+
const body = response.body;
|
|
1604
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
1605
|
+
validateResponse(body);
|
|
1606
|
+
}
|
|
1607
|
+
resolve({
|
|
1608
|
+
jwt: body.jwt,
|
|
1609
|
+
extraInfo: {
|
|
1610
|
+
baseUri: body.baseUri,
|
|
1611
|
+
},
|
|
1612
|
+
});
|
|
1613
|
+
})
|
|
1614
|
+
.catch((error) => {
|
|
1615
|
+
if (error instanceof Error) {
|
|
1616
|
+
reject(error.message);
|
|
1617
|
+
return;
|
|
1618
|
+
}
|
|
1619
|
+
// AuraFetchResponse errors
|
|
1620
|
+
const { status } = error;
|
|
1621
|
+
if (status !== HttpStatusCode.ServerError) {
|
|
1622
|
+
// ConnectInJavaError
|
|
1623
|
+
reject(error.body.message);
|
|
1624
|
+
return;
|
|
1625
|
+
}
|
|
1626
|
+
reject(error.body.error);
|
|
1627
|
+
});
|
|
1628
|
+
});
|
|
1629
|
+
},
|
|
1630
|
+
};
|
|
1631
|
+
/**
|
|
1632
|
+
* This hook is used to modify the resource request before it is sent to the server.
|
|
1633
|
+
* SFAP uses extraInfo assocaiated JwtToken to update the baseUri for the resource request.
|
|
738
1634
|
*
|
|
739
|
-
* @
|
|
1635
|
+
* @param resourceRequest
|
|
1636
|
+
* @param jwtToken
|
|
1637
|
+
* @returns resourceRequest with updated baseUri
|
|
740
1638
|
*/
|
|
741
|
-
function
|
|
1639
|
+
const modifySfapResourceRequest = function (resourceRequest, jwtToken) {
|
|
1640
|
+
const { baseUri } = jwtToken.extraInfo;
|
|
742
1641
|
return {
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
1642
|
+
...resourceRequest,
|
|
1643
|
+
baseUri,
|
|
1644
|
+
};
|
|
1645
|
+
};
|
|
1646
|
+
const sfapNetworkAdapter = buildJwtNetworkAdapter(platformSfapJwtResolver, modifySfapResourceRequest);
|
|
1647
|
+
const composedNetworkAdapter$1 = {
|
|
1648
|
+
shouldHandleRequest(resourceRequest) {
|
|
1649
|
+
return resourceRequest.baseUri === SALESFORCE_API_BASE_URI_FLAG;
|
|
1650
|
+
},
|
|
1651
|
+
adapter: sfapNetworkAdapter,
|
|
1652
|
+
};
|
|
1653
|
+
|
|
1654
|
+
function buildJwtAuthorizedSfapFetchService() {
|
|
1655
|
+
const jwtRepository = new JwtRepository();
|
|
1656
|
+
const jwtManager = new JwtManager(jwtRepository, platformSfapJwtResolver);
|
|
1657
|
+
const jwtRequestModifier = ({ baseUri }, [resource, request]) => {
|
|
1658
|
+
if (typeof resource !== 'string') {
|
|
1659
|
+
// istanbul ignore else: this will not be tested in NODE_ENV = production for test coverage
|
|
1660
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
1661
|
+
throw new Error('JwtAuthorizedSfapFetchService expects a string path');
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
return [`${baseUri}${resource}`, request];
|
|
1665
|
+
};
|
|
1666
|
+
const jwtRequestHeaderInterceptor = buildJwtRequestHeaderInterceptor(jwtManager, jwtRequestModifier);
|
|
1667
|
+
const jwtAuthorizedFetchService = buildFetchService({ request: [jwtRequestHeaderInterceptor] });
|
|
1668
|
+
return {
|
|
1669
|
+
...jwtAuthorizedFetchService,
|
|
1670
|
+
tags: { authenticationScopes: 'sfap_api' },
|
|
746
1671
|
};
|
|
747
1672
|
}
|
|
748
1673
|
|
|
@@ -774,9 +1699,10 @@ class LexDefaultPage extends PredictivePrefetchPage {
|
|
|
774
1699
|
}
|
|
775
1700
|
|
|
776
1701
|
class RecordHomePage extends PredictivePrefetchPage {
|
|
777
|
-
constructor(context, requestStrategies) {
|
|
1702
|
+
constructor(context, requestStrategies, options) {
|
|
778
1703
|
super(context);
|
|
779
1704
|
this.requestStrategies = requestStrategies;
|
|
1705
|
+
this.options = options;
|
|
780
1706
|
const { recordId: _, ...rest } = this.context;
|
|
781
1707
|
this.similarContext = {
|
|
782
1708
|
recordId: '*',
|
|
@@ -784,12 +1710,27 @@ class RecordHomePage extends PredictivePrefetchPage {
|
|
|
784
1710
|
};
|
|
785
1711
|
}
|
|
786
1712
|
buildSaveRequestData(request) {
|
|
1713
|
+
const requestBuckets = [];
|
|
787
1714
|
const { adapterName } = request;
|
|
788
1715
|
const matchingRequestStrategy = this.requestStrategies[adapterName];
|
|
789
1716
|
if (matchingRequestStrategy === undefined) {
|
|
790
1717
|
return [];
|
|
791
1718
|
}
|
|
792
|
-
|
|
1719
|
+
if (matchingRequestStrategy.isContextDependent(this.context, request)) {
|
|
1720
|
+
requestBuckets.push({
|
|
1721
|
+
context: this.similarContext,
|
|
1722
|
+
request: matchingRequestStrategy.transformForSaveSimilarRequest(request),
|
|
1723
|
+
});
|
|
1724
|
+
// When `options.useExactMatchesPlus` is not enabled, we can save this request on the similar bucket only
|
|
1725
|
+
if (!this.options.useExactMatchesPlus) {
|
|
1726
|
+
return requestBuckets;
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
requestBuckets.push({
|
|
1730
|
+
context: this.context,
|
|
1731
|
+
request: matchingRequestStrategy.transformForSave(request),
|
|
1732
|
+
});
|
|
1733
|
+
return requestBuckets;
|
|
793
1734
|
}
|
|
794
1735
|
resolveSimilarRequest(similarRequest) {
|
|
795
1736
|
const { adapterName } = similarRequest;
|
|
@@ -823,18 +1764,34 @@ class RecordHomePage extends PredictivePrefetchPage {
|
|
|
823
1764
|
}
|
|
824
1765
|
|
|
825
1766
|
class ObjectHomePage extends PredictivePrefetchPage {
|
|
826
|
-
constructor(context, requestStrategies) {
|
|
1767
|
+
constructor(context, requestStrategies, options) {
|
|
827
1768
|
super(context);
|
|
828
1769
|
this.requestStrategies = requestStrategies;
|
|
1770
|
+
this.options = options;
|
|
829
1771
|
this.similarContext = context;
|
|
830
1772
|
}
|
|
831
1773
|
buildSaveRequestData(request) {
|
|
1774
|
+
const requestBuckets = [];
|
|
832
1775
|
const { adapterName } = request;
|
|
833
1776
|
const matchingRequestStrategy = this.requestStrategies[adapterName];
|
|
834
|
-
if (matchingRequestStrategy) {
|
|
835
|
-
return
|
|
1777
|
+
if (matchingRequestStrategy === undefined) {
|
|
1778
|
+
return [];
|
|
836
1779
|
}
|
|
837
|
-
|
|
1780
|
+
if (matchingRequestStrategy.isContextDependent(this.context, request)) {
|
|
1781
|
+
requestBuckets.push({
|
|
1782
|
+
context: this.similarContext,
|
|
1783
|
+
request: matchingRequestStrategy.transformForSaveSimilarRequest(request),
|
|
1784
|
+
});
|
|
1785
|
+
// When `options.useExactMatchesPlus` is not enabled, we can save this request on the similar bucket only
|
|
1786
|
+
if (!this.options.useExactMatchesPlus) {
|
|
1787
|
+
return requestBuckets;
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
requestBuckets.push({
|
|
1791
|
+
context: this.context,
|
|
1792
|
+
request: matchingRequestStrategy.transformForSave(request),
|
|
1793
|
+
});
|
|
1794
|
+
return requestBuckets;
|
|
838
1795
|
}
|
|
839
1796
|
// no similar requests between LVs
|
|
840
1797
|
resolveSimilarRequest(similarRequest) {
|
|
@@ -867,6 +1824,12 @@ class ObjectHomePage extends PredictivePrefetchPage {
|
|
|
867
1824
|
recentListsOnly: true,
|
|
868
1825
|
},
|
|
869
1826
|
},
|
|
1827
|
+
{
|
|
1828
|
+
adapterName: 'getListObjectInfo',
|
|
1829
|
+
config: {
|
|
1830
|
+
objectApiName: objectApiName,
|
|
1831
|
+
},
|
|
1832
|
+
},
|
|
870
1833
|
];
|
|
871
1834
|
}
|
|
872
1835
|
// Identifies a valid ObjectHomeContext
|
|
@@ -1454,10 +2417,9 @@ function logCRUDLightningInteraction(eventSource, attributes) {
|
|
|
1454
2417
|
const instrumentation = new Instrumentation();
|
|
1455
2418
|
|
|
1456
2419
|
class ApplicationPredictivePrefetcher {
|
|
1457
|
-
constructor(context, repository, requestRunner
|
|
2420
|
+
constructor(context, repository, requestRunner) {
|
|
1458
2421
|
this.repository = repository;
|
|
1459
2422
|
this.requestRunner = requestRunner;
|
|
1460
|
-
this.options = options;
|
|
1461
2423
|
this.isRecording = false;
|
|
1462
2424
|
this.queuedPredictionRequests = [];
|
|
1463
2425
|
this._context = context;
|
|
@@ -1590,27 +2552,35 @@ class LexPredictivePrefetcher extends ApplicationPredictivePrefetcher {
|
|
|
1590
2552
|
// These strategies need to be in sync with the "predictiveDataLoadCapable" list
|
|
1591
2553
|
// from scripts/lds-uiapi-plugin.js
|
|
1592
2554
|
requestStrategies, options) {
|
|
1593
|
-
super(context, repository, requestRunner
|
|
2555
|
+
super(context, repository, requestRunner);
|
|
1594
2556
|
this.requestStrategies = requestStrategies;
|
|
2557
|
+
this.options = options;
|
|
1595
2558
|
this.page = this.getPage();
|
|
1596
2559
|
}
|
|
1597
2560
|
getPage() {
|
|
1598
2561
|
if (RecordHomePage.handlesContext(this.context)) {
|
|
1599
|
-
return new RecordHomePage(this.context, this.requestStrategies);
|
|
2562
|
+
return new RecordHomePage(this.context, this.requestStrategies, this.options);
|
|
1600
2563
|
}
|
|
1601
2564
|
else if (ObjectHomePage.handlesContext(this.context)) {
|
|
1602
|
-
return new ObjectHomePage(this.context, this.requestStrategies);
|
|
2565
|
+
return new ObjectHomePage(this.context, this.requestStrategies, this.options);
|
|
1603
2566
|
}
|
|
1604
2567
|
return new LexDefaultPage(this.context);
|
|
1605
2568
|
}
|
|
2569
|
+
getAllPageRequests() {
|
|
2570
|
+
const exactPageRequests = this.getExactPageRequest();
|
|
2571
|
+
if (exactPageRequests.length > 0 && this.options.useExactMatchesPlus === true) {
|
|
2572
|
+
return exactPageRequests;
|
|
2573
|
+
}
|
|
2574
|
+
const similarPageRequests = this.getSimilarPageRequests();
|
|
2575
|
+
return [...exactPageRequests, ...similarPageRequests];
|
|
2576
|
+
}
|
|
1606
2577
|
async predict() {
|
|
1607
2578
|
const alwaysRequests = this.page.getAlwaysRunRequests();
|
|
1608
|
-
// IMPORTANT: The `await` has no effect on this operation because `
|
|
1609
|
-
//
|
|
1610
|
-
//
|
|
1611
|
-
//
|
|
1612
|
-
const
|
|
1613
|
-
const exactPageRequests = await this.getExactPageRequest();
|
|
2579
|
+
// IMPORTANT: The `await` has no effect on this operation because `getAllPageRequests`
|
|
2580
|
+
// is sync; however if removed, it will have a negative effect when used with
|
|
2581
|
+
// Aura Network: predictions will be boxcar'd, which likely will result in a
|
|
2582
|
+
// perf regression.
|
|
2583
|
+
const pageRequests = await this.getAllPageRequests();
|
|
1614
2584
|
const alwaysRequestEntries = alwaysRequests.map((request) => {
|
|
1615
2585
|
return {
|
|
1616
2586
|
request,
|
|
@@ -1618,8 +2588,7 @@ class LexPredictivePrefetcher extends ApplicationPredictivePrefetcher {
|
|
|
1618
2588
|
};
|
|
1619
2589
|
});
|
|
1620
2590
|
const reducedPredictions = this.requestRunner.reduceRequests([
|
|
1621
|
-
...
|
|
1622
|
-
...similarPageRequests,
|
|
2591
|
+
...pageRequests,
|
|
1623
2592
|
...alwaysRequestEntries,
|
|
1624
2593
|
]); // In future - remove alwaysRequestEntries when on OneStore
|
|
1625
2594
|
const nonCmpDefPredictions = reducedPredictions.filter((r) => !isCmpDefsRequest(r));
|
|
@@ -1784,19 +2753,6 @@ class PrefetchRepository {
|
|
|
1784
2753
|
}
|
|
1785
2754
|
|
|
1786
2755
|
class RequestStrategy {
|
|
1787
|
-
transformForSave(request) {
|
|
1788
|
-
return request;
|
|
1789
|
-
}
|
|
1790
|
-
reduce(requests) {
|
|
1791
|
-
return requests;
|
|
1792
|
-
}
|
|
1793
|
-
}
|
|
1794
|
-
|
|
1795
|
-
class LuvioAdapterRequestStrategy extends RequestStrategy {
|
|
1796
|
-
constructor(options = {}) {
|
|
1797
|
-
super();
|
|
1798
|
-
this.prefetcherOptions = options;
|
|
1799
|
-
}
|
|
1800
2756
|
/**
|
|
1801
2757
|
* Perform any transformations required to prepare the request for saving.
|
|
1802
2758
|
*
|
|
@@ -1809,6 +2765,14 @@ class LuvioAdapterRequestStrategy extends RequestStrategy {
|
|
|
1809
2765
|
transformForSave(request) {
|
|
1810
2766
|
return request;
|
|
1811
2767
|
}
|
|
2768
|
+
/**
|
|
2769
|
+
* Transforms the request for saving similar requests
|
|
2770
|
+
* @param request Request to transform for saving similar requests
|
|
2771
|
+
* @returns Transformed request
|
|
2772
|
+
*/
|
|
2773
|
+
transformForSaveSimilarRequest(request) {
|
|
2774
|
+
return this.transformForSave(request);
|
|
2775
|
+
}
|
|
1812
2776
|
/**
|
|
1813
2777
|
* Filter requests to only those that are for this strategy.
|
|
1814
2778
|
*
|
|
@@ -1887,58 +2851,6 @@ class LuvioAdapterRequestStrategy extends RequestStrategy {
|
|
|
1887
2851
|
isContextDependent(_context, _request) {
|
|
1888
2852
|
return false;
|
|
1889
2853
|
}
|
|
1890
|
-
/**
|
|
1891
|
-
* Builds request for saving,
|
|
1892
|
-
* - transforming the request
|
|
1893
|
-
* - handling the cases where the request is context dependent (this is homework for the subclass)
|
|
1894
|
-
* @param _similarContext Context with at least one parameter as a wildcard '*'
|
|
1895
|
-
* @param context Exact context for a given page
|
|
1896
|
-
* @param request Request to build save request data for
|
|
1897
|
-
* @returns Save request data
|
|
1898
|
-
*/
|
|
1899
|
-
buildSaveRequestData(similarContext, context, request) {
|
|
1900
|
-
const saveRequestDataBuckets = [];
|
|
1901
|
-
if (this.isContextDependent(context, request)) {
|
|
1902
|
-
saveRequestDataBuckets.push({
|
|
1903
|
-
request: this.transformForSaveSimilarRequest(request),
|
|
1904
|
-
context: similarContext,
|
|
1905
|
-
});
|
|
1906
|
-
const useSaveBuckets = this.prefetcherOptions && this.prefetcherOptions.useSaveBuckets;
|
|
1907
|
-
if (!useSaveBuckets) {
|
|
1908
|
-
return saveRequestDataBuckets;
|
|
1909
|
-
}
|
|
1910
|
-
}
|
|
1911
|
-
saveRequestDataBuckets.push({
|
|
1912
|
-
request: this.transformForSave(request),
|
|
1913
|
-
context,
|
|
1914
|
-
});
|
|
1915
|
-
return saveRequestDataBuckets;
|
|
1916
|
-
}
|
|
1917
|
-
/**
|
|
1918
|
-
* Transforms the request for saving similar requests
|
|
1919
|
-
* @param request Request to transform for saving similar requests
|
|
1920
|
-
* @returns Transformed request
|
|
1921
|
-
*/
|
|
1922
|
-
transformForSaveSimilarRequest(request) {
|
|
1923
|
-
return this.transformForSave(request);
|
|
1924
|
-
}
|
|
1925
|
-
}
|
|
1926
|
-
|
|
1927
|
-
/**
|
|
1928
|
-
* This is a base class for non-luvio request strategies, which needs to be treated as
|
|
1929
|
-
* LuvioAdapterRequestStrategy.
|
|
1930
|
-
*/
|
|
1931
|
-
class ConfigBasedRequestStrategy extends LuvioAdapterRequestStrategy {
|
|
1932
|
-
constructor() {
|
|
1933
|
-
super(...arguments);
|
|
1934
|
-
/**
|
|
1935
|
-
* Config based request strategies are not based on Luvio factory, however
|
|
1936
|
-
* the lex-predictive*, they all expect a LuvioAdapterRequestStrategy.
|
|
1937
|
-
*/
|
|
1938
|
-
this.adapterFactory = (_luvio) => {
|
|
1939
|
-
return (config) => this.executeWithConfig(config);
|
|
1940
|
-
};
|
|
1941
|
-
}
|
|
1942
2854
|
}
|
|
1943
2855
|
|
|
1944
2856
|
const noop = () => { };
|
|
@@ -2039,12 +2951,12 @@ function requestComponents(config) {
|
|
|
2039
2951
|
// dismiss the error.
|
|
2040
2952
|
}
|
|
2041
2953
|
}
|
|
2042
|
-
class GetComponentsDefStrategy extends
|
|
2954
|
+
class GetComponentsDefStrategy extends RequestStrategy {
|
|
2043
2955
|
constructor() {
|
|
2044
2956
|
super(...arguments);
|
|
2045
2957
|
this.adapterName = 'getComponentsDef';
|
|
2046
2958
|
}
|
|
2047
|
-
|
|
2959
|
+
execute(config) {
|
|
2048
2960
|
return requestComponents(config);
|
|
2049
2961
|
}
|
|
2050
2962
|
buildConcreteRequest(similarRequest, _context) {
|
|
@@ -2052,14 +2964,6 @@ class GetComponentsDefStrategy extends ConfigBasedRequestStrategy {
|
|
|
2052
2964
|
...similarRequest,
|
|
2053
2965
|
};
|
|
2054
2966
|
}
|
|
2055
|
-
buildSaveRequestData(similarContext, _context, request) {
|
|
2056
|
-
return [
|
|
2057
|
-
{
|
|
2058
|
-
request: this.transformForSave(request),
|
|
2059
|
-
context: similarContext,
|
|
2060
|
-
},
|
|
2061
|
-
];
|
|
2062
|
-
}
|
|
2063
2967
|
transformForSave(request) {
|
|
2064
2968
|
return {
|
|
2065
2969
|
...request,
|
|
@@ -2074,6 +2978,26 @@ class GetComponentsDefStrategy extends ConfigBasedRequestStrategy {
|
|
|
2074
2978
|
reqB.forEach((c) => result.add(c));
|
|
2075
2979
|
return [...result];
|
|
2076
2980
|
}
|
|
2981
|
+
isContextDependent(_context, _request) {
|
|
2982
|
+
return true;
|
|
2983
|
+
}
|
|
2984
|
+
}
|
|
2985
|
+
|
|
2986
|
+
const LDS_PDL_CMP_IDENTIFIER = 'lds:pdl';
|
|
2987
|
+
const DEFAULT_RESOURCE_CONTEXT = {
|
|
2988
|
+
sourceContext: { tagName: LDS_PDL_CMP_IDENTIFIER },
|
|
2989
|
+
};
|
|
2990
|
+
class LuvioAdapterRequestStrategy extends RequestStrategy {
|
|
2991
|
+
constructor(luvio) {
|
|
2992
|
+
super();
|
|
2993
|
+
this.luvio = luvio;
|
|
2994
|
+
}
|
|
2995
|
+
execute(config, requestContext) {
|
|
2996
|
+
return this.adapterFactory(this.luvio)(config, {
|
|
2997
|
+
...DEFAULT_RESOURCE_CONTEXT,
|
|
2998
|
+
...requestContext,
|
|
2999
|
+
});
|
|
3000
|
+
}
|
|
2077
3001
|
}
|
|
2078
3002
|
|
|
2079
3003
|
function normalizeRecordIds$1(recordIds) {
|
|
@@ -2358,14 +3282,6 @@ class GetObjectInfosRequestStrategy extends LuvioAdapterRequestStrategy {
|
|
|
2358
3282
|
}
|
|
2359
3283
|
return reducedRequests;
|
|
2360
3284
|
}
|
|
2361
|
-
buildSaveRequestData(similarContext, context, request) {
|
|
2362
|
-
return [
|
|
2363
|
-
{
|
|
2364
|
-
request: this.transformForSave(request),
|
|
2365
|
-
context,
|
|
2366
|
-
},
|
|
2367
|
-
];
|
|
2368
|
-
}
|
|
2369
3285
|
}
|
|
2370
3286
|
|
|
2371
3287
|
class GetObjectInfoRequestStrategy extends LuvioAdapterRequestStrategy {
|
|
@@ -2637,14 +3553,6 @@ class GetApexRequestStrategy extends LuvioAdapterRequestStrategy {
|
|
|
2637
3553
|
buildConcreteRequest(similarRequest) {
|
|
2638
3554
|
return similarRequest;
|
|
2639
3555
|
}
|
|
2640
|
-
buildSaveRequestData(_similarContext, context, request) {
|
|
2641
|
-
return [
|
|
2642
|
-
{
|
|
2643
|
-
request: this.transformForSave(request),
|
|
2644
|
-
context,
|
|
2645
|
-
},
|
|
2646
|
-
];
|
|
2647
|
-
}
|
|
2648
3556
|
}
|
|
2649
3557
|
|
|
2650
3558
|
const GET_LIST_INFO_BY_NAME_ADAPTER_NAME = 'getListInfoByName';
|
|
@@ -2667,14 +3575,6 @@ class GetListInfoByNameRequestStrategy extends LuvioAdapterRequestStrategy {
|
|
|
2667
3575
|
},
|
|
2668
3576
|
};
|
|
2669
3577
|
}
|
|
2670
|
-
buildSaveRequestData(_similarContext, context, request) {
|
|
2671
|
-
return [
|
|
2672
|
-
{
|
|
2673
|
-
request: this.transformForSave(request),
|
|
2674
|
-
context,
|
|
2675
|
-
},
|
|
2676
|
-
];
|
|
2677
|
-
}
|
|
2678
3578
|
canCombine(reqA, reqB) {
|
|
2679
3579
|
return (reqA.objectApiName === reqB.objectApiName &&
|
|
2680
3580
|
reqA.listViewApiName === reqB.listViewApiName);
|
|
@@ -2704,14 +3604,6 @@ class GetListInfosByObjectNameRequestStrategy extends LuvioAdapterRequestStrateg
|
|
|
2704
3604
|
},
|
|
2705
3605
|
};
|
|
2706
3606
|
}
|
|
2707
|
-
buildSaveRequestData(_similarContext, context, request) {
|
|
2708
|
-
return [
|
|
2709
|
-
{
|
|
2710
|
-
request: this.transformForSave(request),
|
|
2711
|
-
context,
|
|
2712
|
-
},
|
|
2713
|
-
];
|
|
2714
|
-
}
|
|
2715
3607
|
canCombine(reqA, reqB) {
|
|
2716
3608
|
return (reqA.objectApiName === reqB.objectApiName &&
|
|
2717
3609
|
reqA.q === reqB.q &&
|
|
@@ -2753,36 +3645,50 @@ class GetListRecordsByNameRequestStrategy extends LuvioAdapterRequestStrategy {
|
|
|
2753
3645
|
// to build the key should solve this issue till then we can't move fields into optional fields
|
|
2754
3646
|
return request;
|
|
2755
3647
|
}
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
3648
|
+
}
|
|
3649
|
+
|
|
3650
|
+
const GET_LIST_OBJECT_INFO_ADAPTER_NAME = 'getListObjectInfo';
|
|
3651
|
+
class GetListObjectInfoRequestStrategy extends LuvioAdapterRequestStrategy {
|
|
3652
|
+
constructor() {
|
|
3653
|
+
super(...arguments);
|
|
3654
|
+
this.adapterName = GET_LIST_OBJECT_INFO_ADAPTER_NAME;
|
|
3655
|
+
this.adapterFactory = getListObjectInfoAdapterFactory;
|
|
3656
|
+
}
|
|
3657
|
+
buildConcreteRequest(similarRequest) {
|
|
3658
|
+
return similarRequest;
|
|
3659
|
+
}
|
|
3660
|
+
transformForSave(request) {
|
|
3661
|
+
return {
|
|
3662
|
+
...request,
|
|
3663
|
+
config: {
|
|
3664
|
+
...request.config,
|
|
3665
|
+
// (!): if we are saving this request is because the adapter already verified is valid.
|
|
3666
|
+
objectApiName: coerceObjectId(request.config.objectApiName),
|
|
2761
3667
|
},
|
|
2762
|
-
|
|
3668
|
+
};
|
|
2763
3669
|
}
|
|
2764
3670
|
}
|
|
2765
3671
|
|
|
2766
|
-
const LDS_PDL_CMP_IDENTIFIER = 'lds:pdl';
|
|
2767
3672
|
class LexRequestRunner {
|
|
2768
3673
|
constructor(luvio) {
|
|
2769
3674
|
this.luvio = luvio;
|
|
2770
3675
|
this.requestStrategies = {
|
|
2771
|
-
getRecord: new GetRecordRequestStrategy(
|
|
2772
|
-
getRecords: new GetRecordsRequestStrategy(
|
|
2773
|
-
getRecordActions: new GetRecordActionsRequestStrategy(
|
|
2774
|
-
getRecordAvatars: new GetRecordAvatarsRequestStrategy(
|
|
2775
|
-
getObjectInfo: new GetObjectInfoRequestStrategy(
|
|
2776
|
-
getObjectInfos: new GetObjectInfosRequestStrategy(
|
|
2777
|
-
getRelatedListsActions: new GetRelatedListsActionsRequestStrategy(
|
|
2778
|
-
getRelatedListInfoBatch: new GetRelatedListInfoBatchRequestStrategy(
|
|
2779
|
-
getRelatedListRecords: new GetRelatedListRecordsRequestStrategy(
|
|
2780
|
-
getRelatedListRecordsBatch: new GetRelatedListRecordsBatchRequestStrategy(
|
|
2781
|
-
getListInfoByName: new GetListInfoByNameRequestStrategy(
|
|
2782
|
-
getListRecordsByName: new GetListRecordsByNameRequestStrategy(
|
|
2783
|
-
getApex: new GetApexRequestStrategy(
|
|
2784
|
-
getComponentsDef: new GetComponentsDefStrategy(
|
|
2785
|
-
getListInfosByObjectName: new GetListInfosByObjectNameRequestStrategy(
|
|
3676
|
+
getRecord: new GetRecordRequestStrategy(luvio),
|
|
3677
|
+
getRecords: new GetRecordsRequestStrategy(luvio),
|
|
3678
|
+
getRecordActions: new GetRecordActionsRequestStrategy(luvio),
|
|
3679
|
+
getRecordAvatars: new GetRecordAvatarsRequestStrategy(luvio),
|
|
3680
|
+
getObjectInfo: new GetObjectInfoRequestStrategy(luvio),
|
|
3681
|
+
getObjectInfos: new GetObjectInfosRequestStrategy(luvio),
|
|
3682
|
+
getRelatedListsActions: new GetRelatedListsActionsRequestStrategy(luvio),
|
|
3683
|
+
getRelatedListInfoBatch: new GetRelatedListInfoBatchRequestStrategy(luvio),
|
|
3684
|
+
getRelatedListRecords: new GetRelatedListRecordsRequestStrategy(luvio),
|
|
3685
|
+
getRelatedListRecordsBatch: new GetRelatedListRecordsBatchRequestStrategy(luvio),
|
|
3686
|
+
getListInfoByName: new GetListInfoByNameRequestStrategy(luvio),
|
|
3687
|
+
getListRecordsByName: new GetListRecordsByNameRequestStrategy(luvio),
|
|
3688
|
+
getApex: new GetApexRequestStrategy(luvio),
|
|
3689
|
+
getComponentsDef: new GetComponentsDefStrategy(),
|
|
3690
|
+
getListInfosByObjectName: new GetListInfosByObjectNameRequestStrategy(luvio),
|
|
3691
|
+
getListObjectInfo: new GetListObjectInfoRequestStrategy(luvio),
|
|
2786
3692
|
};
|
|
2787
3693
|
}
|
|
2788
3694
|
reduceRequests(requests) {
|
|
@@ -2792,10 +3698,7 @@ class LexRequestRunner {
|
|
|
2792
3698
|
}
|
|
2793
3699
|
runRequest(request) {
|
|
2794
3700
|
if (request.adapterName in this.requestStrategies) {
|
|
2795
|
-
|
|
2796
|
-
return Promise.resolve(adapterFactory(this.luvio)(request.config, {
|
|
2797
|
-
sourceContext: { tagName: LDS_PDL_CMP_IDENTIFIER },
|
|
2798
|
-
})).then();
|
|
3701
|
+
return Promise.resolve(this.requestStrategies[request.adapterName].execute(request.config)).then();
|
|
2799
3702
|
}
|
|
2800
3703
|
return Promise.resolve(undefined);
|
|
2801
3704
|
}
|
|
@@ -2820,7 +3723,7 @@ const DEFAULT_STORAGE_OPTIONS = {
|
|
|
2820
3723
|
persistent: true,
|
|
2821
3724
|
secure: true,
|
|
2822
3725
|
maxSize: 7 * 1024 * 1024,
|
|
2823
|
-
expiration:
|
|
3726
|
+
expiration: 5 * 24 * 60 * 60,
|
|
2824
3727
|
clearOnInit: false,
|
|
2825
3728
|
debugLogging: false,
|
|
2826
3729
|
version: 3,
|
|
@@ -2889,81 +3792,6 @@ function buildComposableNetworkAdapter(composedAdapters) {
|
|
|
2889
3792
|
};
|
|
2890
3793
|
}
|
|
2891
3794
|
|
|
2892
|
-
const SALESFORCE_API_BASE_URI_FLAG = 'api.salesforce.com';
|
|
2893
|
-
const SFAPController = 'SalesforceApiPlatformController';
|
|
2894
|
-
const SFAPJwtMethod = 'getSFAPLightningJwtService';
|
|
2895
|
-
/**
|
|
2896
|
-
* We expect jwt info and baseUri to be present in the response.
|
|
2897
|
-
*
|
|
2898
|
-
* @param body
|
|
2899
|
-
*/
|
|
2900
|
-
function validateResponse(body) {
|
|
2901
|
-
if (!body || !body.jwt || !body.baseUri) {
|
|
2902
|
-
// wrapped the invocation in env conditional
|
|
2903
|
-
// eslint-disable-next-line @salesforce/lds/no-error-in-production
|
|
2904
|
-
throw new Error(`Expected jwt info and baseUri to be present but instead got: ${JSON.stringify(body)}`);
|
|
2905
|
-
}
|
|
2906
|
-
}
|
|
2907
|
-
/**
|
|
2908
|
-
* Resolves Jwt token for SFAP by calling Aura action
|
|
2909
|
-
* {@link JwtResolver} for platform SFAP
|
|
2910
|
-
*/
|
|
2911
|
-
const platformSfapJwtResolver = {
|
|
2912
|
-
getJwt() {
|
|
2913
|
-
return new Promise((resolve, reject) => {
|
|
2914
|
-
dispatchAuraAction(`${SFAPController}.${SFAPJwtMethod}`, {}, defaultActionConfig)
|
|
2915
|
-
.then((response) => {
|
|
2916
|
-
const body = response.body;
|
|
2917
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
2918
|
-
validateResponse(body);
|
|
2919
|
-
}
|
|
2920
|
-
resolve({
|
|
2921
|
-
jwt: body.jwt,
|
|
2922
|
-
extraInfo: {
|
|
2923
|
-
baseUri: body.baseUri,
|
|
2924
|
-
},
|
|
2925
|
-
});
|
|
2926
|
-
})
|
|
2927
|
-
.catch((error) => {
|
|
2928
|
-
if (error instanceof Error) {
|
|
2929
|
-
reject(error.message);
|
|
2930
|
-
return;
|
|
2931
|
-
}
|
|
2932
|
-
// AuraFetchResponse errors
|
|
2933
|
-
const { status } = error;
|
|
2934
|
-
if (status !== HttpStatusCode.ServerError) {
|
|
2935
|
-
// ConnectInJavaError
|
|
2936
|
-
reject(error.body.message);
|
|
2937
|
-
return;
|
|
2938
|
-
}
|
|
2939
|
-
reject(error.body.error);
|
|
2940
|
-
});
|
|
2941
|
-
});
|
|
2942
|
-
},
|
|
2943
|
-
};
|
|
2944
|
-
/**
|
|
2945
|
-
* This hook is used to modify the resource request before it is sent to the server.
|
|
2946
|
-
* SFAP uses extraInfo assocaiated JwtToken to update the baseUri for the resource request.
|
|
2947
|
-
*
|
|
2948
|
-
* @param resourceRequest
|
|
2949
|
-
* @param jwtToken
|
|
2950
|
-
* @returns resourceRequest with updated baseUri
|
|
2951
|
-
*/
|
|
2952
|
-
const modifySfapResourceRequest = function (resourceRequest, jwtToken) {
|
|
2953
|
-
const { baseUri } = jwtToken.extraInfo;
|
|
2954
|
-
return {
|
|
2955
|
-
...resourceRequest,
|
|
2956
|
-
baseUri,
|
|
2957
|
-
};
|
|
2958
|
-
};
|
|
2959
|
-
const sfapNetworkAdapter = buildJwtNetworkAdapter(platformSfapJwtResolver, modifySfapResourceRequest);
|
|
2960
|
-
const composedNetworkAdapter$1 = {
|
|
2961
|
-
shouldHandleRequest(resourceRequest) {
|
|
2962
|
-
return resourceRequest.baseUri === SALESFORCE_API_BASE_URI_FLAG;
|
|
2963
|
-
},
|
|
2964
|
-
adapter: sfapNetworkAdapter,
|
|
2965
|
-
};
|
|
2966
|
-
|
|
2967
3795
|
const composedNetworkAdapter = buildComposableNetworkAdapter([
|
|
2968
3796
|
composedNetworkAdapter$1,
|
|
2969
3797
|
// The aura network adapter must be the default.
|
|
@@ -3033,27 +3861,28 @@ function setupPredictivePrefetcher(luvio) {
|
|
|
3033
3861
|
const inflightRequestLimit = applyPredictionRequestLimit.isOpen({ fallback: false })
|
|
3034
3862
|
? HARDCODED_REQUEST_LIMIT
|
|
3035
3863
|
: 1000;
|
|
3036
|
-
const
|
|
3864
|
+
const useExactMatchesPlus = useExactMatchesPlusGate.isOpen({ fallback: false });
|
|
3037
3865
|
const prefetcherOptions = {
|
|
3038
3866
|
inflightRequestLimit,
|
|
3039
|
-
|
|
3867
|
+
useExactMatchesPlus,
|
|
3040
3868
|
};
|
|
3041
3869
|
const prefetcher = new LexPredictivePrefetcher({ context: 'unknown' }, repository, requestRunner, {
|
|
3042
|
-
getRecord: new GetRecordRequestStrategy(
|
|
3043
|
-
getRecords: new GetRecordsRequestStrategy(
|
|
3044
|
-
getRecordActions: new GetRecordActionsRequestStrategy(
|
|
3045
|
-
getRecordAvatars: new GetRecordAvatarsRequestStrategy(
|
|
3046
|
-
getObjectInfo: new GetObjectInfoRequestStrategy(
|
|
3047
|
-
getObjectInfos: new GetObjectInfosRequestStrategy(
|
|
3048
|
-
getRelatedListsActions: new GetRelatedListsActionsRequestStrategy(
|
|
3049
|
-
getRelatedListRecords: new GetRelatedListRecordsRequestStrategy(
|
|
3050
|
-
getRelatedListRecordsBatch: new GetRelatedListRecordsBatchRequestStrategy(
|
|
3051
|
-
getRelatedListInfoBatch: new GetRelatedListInfoBatchRequestStrategy(
|
|
3052
|
-
getListInfoByName: new GetListInfoByNameRequestStrategy(
|
|
3053
|
-
getListRecordsByName: new GetListRecordsByNameRequestStrategy(
|
|
3054
|
-
|
|
3055
|
-
getComponentsDef: new GetComponentsDefStrategy(
|
|
3056
|
-
getListInfosByObjectName: new GetListInfosByObjectNameRequestStrategy(
|
|
3870
|
+
getRecord: new GetRecordRequestStrategy(luvio),
|
|
3871
|
+
getRecords: new GetRecordsRequestStrategy(luvio),
|
|
3872
|
+
getRecordActions: new GetRecordActionsRequestStrategy(luvio),
|
|
3873
|
+
getRecordAvatars: new GetRecordAvatarsRequestStrategy(luvio),
|
|
3874
|
+
getObjectInfo: new GetObjectInfoRequestStrategy(luvio),
|
|
3875
|
+
getObjectInfos: new GetObjectInfosRequestStrategy(luvio),
|
|
3876
|
+
getRelatedListsActions: new GetRelatedListsActionsRequestStrategy(luvio),
|
|
3877
|
+
getRelatedListRecords: new GetRelatedListRecordsRequestStrategy(luvio),
|
|
3878
|
+
getRelatedListRecordsBatch: new GetRelatedListRecordsBatchRequestStrategy(luvio),
|
|
3879
|
+
getRelatedListInfoBatch: new GetRelatedListInfoBatchRequestStrategy(luvio),
|
|
3880
|
+
getListInfoByName: new GetListInfoByNameRequestStrategy(luvio),
|
|
3881
|
+
getListRecordsByName: new GetListRecordsByNameRequestStrategy(luvio),
|
|
3882
|
+
getApex: new GetApexRequestStrategy(luvio),
|
|
3883
|
+
getComponentsDef: new GetComponentsDefStrategy(),
|
|
3884
|
+
getListInfosByObjectName: new GetListInfosByObjectNameRequestStrategy(luvio),
|
|
3885
|
+
getListObjectInfo: new GetListObjectInfoRequestStrategy(luvio),
|
|
3057
3886
|
}, prefetcherOptions);
|
|
3058
3887
|
registerPrefetcher(luvio, prefetcher);
|
|
3059
3888
|
if (useApexPredictions.isOpen({ fallback: false })) {
|
|
@@ -3184,7 +4013,15 @@ function initializeOneStore() {
|
|
|
3184
4013
|
defaultCachePolicyName: 'cache-then-network',
|
|
3185
4014
|
},
|
|
3186
4015
|
};
|
|
4016
|
+
const jwtAuthorizedSfapFetchService = buildJwtAuthorizedSfapFetchService();
|
|
4017
|
+
// TODO [W-1234567]: Export descriptor builder for o11y and noop instrumentaiton
|
|
4018
|
+
const instrumentationServiceDescriptor = {
|
|
4019
|
+
type: 'instrumentation',
|
|
4020
|
+
version: '1.0',
|
|
4021
|
+
service: buildNoopInstrumentationService(),
|
|
4022
|
+
};
|
|
3187
4023
|
const services = [
|
|
4024
|
+
jwtAuthorizedSfapFetchService,
|
|
3188
4025
|
keySubscriptionServiceDescriptor,
|
|
3189
4026
|
metadataRepositoryServiceDescriptor,
|
|
3190
4027
|
storeServiceDescriptor,
|
|
@@ -3193,6 +4030,15 @@ function initializeOneStore() {
|
|
|
3193
4030
|
buildDefaultTypeRegistryService(),
|
|
3194
4031
|
buildAuraNetworkService(),
|
|
3195
4032
|
buildInMemoryCacheInclusionPolicyService(),
|
|
4033
|
+
buildAuraNetworkCommandBaseClassService(),
|
|
4034
|
+
buildFetchNetworkCommandBaseClassService(),
|
|
4035
|
+
buildNetworkCommandBaseClassService(),
|
|
4036
|
+
buildStreamingCommandBaseClassService(),
|
|
4037
|
+
buildSSECommandBaseClassService(),
|
|
4038
|
+
instrumentationServiceDescriptor,
|
|
4039
|
+
buildInstrumentCommandServiceDescriptor({
|
|
4040
|
+
instrumentation: instrumentationServiceDescriptor.service,
|
|
4041
|
+
}),
|
|
3196
4042
|
];
|
|
3197
4043
|
serviceBroker.publish(services);
|
|
3198
4044
|
}
|
|
@@ -3221,4 +4067,4 @@ function ldsEngineCreator() {
|
|
|
3221
4067
|
}
|
|
3222
4068
|
|
|
3223
4069
|
export { buildPredictorForContext, ldsEngineCreator as default, initializeLDS, initializeOneStore };
|
|
3224
|
-
// version: 1.
|
|
4070
|
+
// version: 1.303.0-a698c7cc67
|