@salesforce/lds-runtime-aura 1.284.0 → 1.286.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
CHANGED
|
@@ -16,6 +16,7 @@ import { HttpStatusCode, InMemoryStore as InMemoryStore$1, Environment, Luvio, I
|
|
|
16
16
|
import ldsTrackedFieldsBehaviorGate from '@salesforce/gate/lds.useNewTrackedFieldBehavior';
|
|
17
17
|
import usePredictiveLoading from '@salesforce/gate/lds.usePredictiveLoading';
|
|
18
18
|
import { instrument, getRecordAvatarsAdapterFactory, getRecordAdapterFactory, coerceFieldIdArray, getRecordsAdapterFactory, getRecordActionsAdapterFactory, getObjectInfosAdapterFactory, getObjectInfoAdapterFactory, getRelatedListsActionsAdapterFactory, getRelatedListInfoBatchAdapterFactory, getRelatedListRecordsBatchAdapterFactory, getRelatedListRecordsAdapterFactory, configuration, InMemoryRecordRepresentationQueryEvaluator, UiApiNamespace, RecordRepresentationRepresentationType, registerPrefetcher } from 'force/ldsAdaptersUiapi';
|
|
19
|
+
import { withRegistration as withRegistration$1 } from 'force/luvioRegistry';
|
|
19
20
|
import oneStoreEnabled from '@salesforce/gate/lds.oneStoreEnabled.ltng';
|
|
20
21
|
import { executeGlobalControllerRawResponse } from 'aura';
|
|
21
22
|
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';
|
|
@@ -23,9 +24,10 @@ import { REFRESH_ADAPTER_EVENT, ADAPTER_UNFULFILLED_ERROR, instrument as instrum
|
|
|
23
24
|
import { counter, registerCacheStats, perfStart, perfEnd, registerPeriodicLogger, interaction, timer } from 'instrumentation/service';
|
|
24
25
|
import auraNetworkAdapter, { instrument as instrument$1, forceRecordTransactionsDisabled, ldsNetworkAdapterInstrument, dispatchAuraAction, defaultActionConfig } from 'force/ldsNetwork';
|
|
25
26
|
import { instrument as instrument$3 } from 'force/adsBridge';
|
|
26
|
-
import { withRegistration
|
|
27
|
+
import { withRegistration, register, setDefaultLuvio } from 'force/ldsEngine';
|
|
27
28
|
import { createStorage, clearStorages } from 'force/ldsStorage';
|
|
28
29
|
import { buildJwtNetworkAdapter } from 'force/ldsNetworkFetchWithJwt';
|
|
30
|
+
import { getObjectInfo, getObjectInfos } from 'force/ldsAdaptersUiapiLex';
|
|
29
31
|
|
|
30
32
|
/**
|
|
31
33
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
@@ -33,61 +35,6 @@ import { buildJwtNetworkAdapter } from 'force/ldsNetworkFetchWithJwt';
|
|
|
33
35
|
* For full license text, see the LICENSE.txt file
|
|
34
36
|
*/
|
|
35
37
|
|
|
36
|
-
const { hasOwnProperty } = Object.prototype;
|
|
37
|
-
|
|
38
|
-
function resolvedPromiseLike(result) {
|
|
39
|
-
// Don't nest anything promise like
|
|
40
|
-
if (isPromiseLike(result)) {
|
|
41
|
-
return result.then((nextResult) => nextResult);
|
|
42
|
-
}
|
|
43
|
-
return {
|
|
44
|
-
then: (onFulfilled, _onRejected) => {
|
|
45
|
-
if (onFulfilled) {
|
|
46
|
-
try {
|
|
47
|
-
return resolvedPromiseLike(onFulfilled(result));
|
|
48
|
-
}
|
|
49
|
-
catch (e) {
|
|
50
|
-
return rejectedPromiseLike(e);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
// assume TResult1 == Result and just pass result down the chain
|
|
54
|
-
return resolvedPromiseLike(result);
|
|
55
|
-
},
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Returns a PromiseLike object that rejects with the specified reason.
|
|
60
|
-
*
|
|
61
|
-
* @param reason rejection value
|
|
62
|
-
* @returns PromiseLike that rejects with reason
|
|
63
|
-
*/
|
|
64
|
-
function rejectedPromiseLike(reason) {
|
|
65
|
-
if (isPromiseLike(reason)) {
|
|
66
|
-
return reason.then((nextResult) => nextResult);
|
|
67
|
-
}
|
|
68
|
-
return {
|
|
69
|
-
then: (_onFulfilled, onRejected) => {
|
|
70
|
-
if (onRejected) {
|
|
71
|
-
try {
|
|
72
|
-
return resolvedPromiseLike(onRejected(reason));
|
|
73
|
-
}
|
|
74
|
-
catch (e) {
|
|
75
|
-
return rejectedPromiseLike(e);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
// assume TResult2 == Result and just pass rejection down the chain
|
|
79
|
-
return rejectedPromiseLike(reason);
|
|
80
|
-
},
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
function isPromiseLike(value) {
|
|
84
|
-
return (value instanceof Promise ||
|
|
85
|
-
(typeof value === 'object' &&
|
|
86
|
-
value !== null &&
|
|
87
|
-
hasOwnProperty.call(value, 'then') &&
|
|
88
|
-
typeof value.then === 'function'));
|
|
89
|
-
}
|
|
90
|
-
|
|
91
38
|
/**
|
|
92
39
|
* A collection of keys, in no particular order.
|
|
93
40
|
*/
|
|
@@ -234,6 +181,412 @@ function buildInMemoryMetadataRepositoryService() {
|
|
|
234
181
|
};
|
|
235
182
|
}
|
|
236
183
|
|
|
184
|
+
/**
|
|
185
|
+
* A RecordableStore wraps another Store and is used to record which keys in the
|
|
186
|
+
* other Store are read/written.
|
|
187
|
+
*/
|
|
188
|
+
class RecordableStore {
|
|
189
|
+
constructor(baseStore) {
|
|
190
|
+
this.baseStore = baseStore;
|
|
191
|
+
this.keysRead = new KeySetImpl();
|
|
192
|
+
this.missingKeysRead = new KeySetImpl();
|
|
193
|
+
this.keysUpdated = new KeySetImpl();
|
|
194
|
+
}
|
|
195
|
+
delete(key, options) {
|
|
196
|
+
this.keysUpdated.add(key);
|
|
197
|
+
this.baseStore.delete(key, options);
|
|
198
|
+
}
|
|
199
|
+
get(key, options) {
|
|
200
|
+
this.keysRead.add(key);
|
|
201
|
+
const value = this.baseStore.get(key, options);
|
|
202
|
+
if (value === undefined) {
|
|
203
|
+
this.missingKeysRead.add(key);
|
|
204
|
+
}
|
|
205
|
+
return value;
|
|
206
|
+
}
|
|
207
|
+
set(key, value, options) {
|
|
208
|
+
this.keysUpdated.add(key);
|
|
209
|
+
this.baseStore.set(key, value, options);
|
|
210
|
+
}
|
|
211
|
+
length() {
|
|
212
|
+
return this.baseStore.length();
|
|
213
|
+
}
|
|
214
|
+
keys() {
|
|
215
|
+
return this.baseStore.keys();
|
|
216
|
+
}
|
|
217
|
+
toKeySet(keys) {
|
|
218
|
+
return this.baseStore.toKeySet(keys);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* A TTLFilteredStore wraps another Store and filters data from that Store
|
|
224
|
+
* to entries whose metadata indicates that it has not yet expired.
|
|
225
|
+
*/
|
|
226
|
+
class TTLFilteredStore {
|
|
227
|
+
constructor(baseStore, metadataRepository, now = Date.now()) {
|
|
228
|
+
this.baseStore = baseStore;
|
|
229
|
+
this.metadataRepository = metadataRepository;
|
|
230
|
+
this.now = now;
|
|
231
|
+
}
|
|
232
|
+
delete(key, options) {
|
|
233
|
+
this.baseStore.delete(key, options);
|
|
234
|
+
}
|
|
235
|
+
get(key, options) {
|
|
236
|
+
const metadata = this.metadataRepository.get(key);
|
|
237
|
+
if (metadata && metadata.expirationTime <= this.now) {
|
|
238
|
+
return undefined;
|
|
239
|
+
}
|
|
240
|
+
return this.baseStore.get(key, options);
|
|
241
|
+
}
|
|
242
|
+
set(key, value, options) {
|
|
243
|
+
this.baseStore.set(key, value, options);
|
|
244
|
+
}
|
|
245
|
+
length() {
|
|
246
|
+
return this.keys().length;
|
|
247
|
+
}
|
|
248
|
+
keys() {
|
|
249
|
+
return new KeySetImpl(this.baseStore
|
|
250
|
+
.keys()
|
|
251
|
+
.elements()
|
|
252
|
+
.filter((key) => this.get(key) !== undefined));
|
|
253
|
+
}
|
|
254
|
+
toKeySet(keys) {
|
|
255
|
+
return this.baseStore.toKeySet(keys);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
261
|
+
* All rights reserved.
|
|
262
|
+
* For full license text, see the LICENSE.txt file
|
|
263
|
+
*/
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Utility function to generate a strongly-typed, empty set of Services. Aside from
|
|
268
|
+
* having the correct type, the returned set behaves as {} except it will throw an
|
|
269
|
+
* exception if an attempt is made to get a Service that has not been set.
|
|
270
|
+
*
|
|
271
|
+
* @typeParam Services the set of Services that will be stored in the set, typically
|
|
272
|
+
* expressed as an intersection of Service types, e.g. FooService & BarService
|
|
273
|
+
* @returns empty set of Services
|
|
274
|
+
*/
|
|
275
|
+
function emptyServices() {
|
|
276
|
+
return new Proxy({}, {
|
|
277
|
+
get(services, serviceName, receiver) {
|
|
278
|
+
if (!(serviceName in services)) {
|
|
279
|
+
throw new Error(`service ${serviceName.toString()} not found`);
|
|
280
|
+
}
|
|
281
|
+
return Reflect.get(services, serviceName, receiver);
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Indicates if a given instance of a service satisfies a request. Note that this function
|
|
287
|
+
* assumes the version numbers are valid strings.
|
|
288
|
+
*
|
|
289
|
+
* @param provided ServiceVersion of the service instance to be provided
|
|
290
|
+
* @param requested ServiceVersion requested
|
|
291
|
+
* @returns true if the service instance to be provided satisfies the request
|
|
292
|
+
*/
|
|
293
|
+
function satisfies(provided, requested) {
|
|
294
|
+
const providedN = provided.split('.').map((s) => parseInt(s));
|
|
295
|
+
const requestedN = requested.split('.').map((s) => parseInt(s));
|
|
296
|
+
return providedN[0] === requestedN[0] && providedN[1] >= requestedN[1];
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function resolvedPromiseLike(result) {
|
|
300
|
+
// Don't nest anything promise like
|
|
301
|
+
if (isPromiseOrPromiseLike(result)) {
|
|
302
|
+
return result.then((nextResult) => nextResult);
|
|
303
|
+
}
|
|
304
|
+
return {
|
|
305
|
+
then: (onFulfilled, _onRejected) => {
|
|
306
|
+
if (onFulfilled) {
|
|
307
|
+
try {
|
|
308
|
+
return resolvedPromiseLike(onFulfilled(result));
|
|
309
|
+
}
|
|
310
|
+
catch (e) {
|
|
311
|
+
return rejectedPromiseLike(e);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
// assume TResult1 == Result and just pass result down the chain
|
|
315
|
+
return resolvedPromiseLike(result);
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Returns a PromiseLike object that rejects with the specified reason.
|
|
321
|
+
*
|
|
322
|
+
* @param reason rejection value
|
|
323
|
+
* @returns PromiseLike that rejects with reason
|
|
324
|
+
*/
|
|
325
|
+
function rejectedPromiseLike(reason) {
|
|
326
|
+
if (isPromiseOrPromiseLike(reason)) {
|
|
327
|
+
return reason.then((nextResult) => nextResult);
|
|
328
|
+
}
|
|
329
|
+
return {
|
|
330
|
+
then: (_onFulfilled, onRejected) => {
|
|
331
|
+
if (onRejected) {
|
|
332
|
+
try {
|
|
333
|
+
return resolvedPromiseLike(onRejected(reason));
|
|
334
|
+
}
|
|
335
|
+
catch (e) {
|
|
336
|
+
return rejectedPromiseLike(e);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
// assume TResult2 == Result and just pass rejection down the chain
|
|
340
|
+
return rejectedPromiseLike(reason);
|
|
341
|
+
},
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
function isPromiseOrPromiseLike(value) {
|
|
345
|
+
return (value instanceof Promise ||
|
|
346
|
+
(typeof value === 'object' && value !== null && typeof value.then === 'function'));
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// an error to indicate that the data inside a WithErrors construct
|
|
350
|
+
// is missing or incomplete
|
|
351
|
+
class DataNotFoundError extends Error {
|
|
352
|
+
constructor(message) {
|
|
353
|
+
super(message);
|
|
354
|
+
this.name = 'DataNotFoundError';
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
function isDataNotFoundError(error) {
|
|
358
|
+
return error instanceof DataNotFoundError || error.name === 'DataNotFoundError';
|
|
359
|
+
}
|
|
360
|
+
function isCacheHitOrError(value) {
|
|
361
|
+
// return cache result if data was found or error was encountered
|
|
362
|
+
const { data, errors } = value;
|
|
363
|
+
const cacheHit = data !== undefined && errors.length === 0;
|
|
364
|
+
const errorEncountered = errors.length > 0 && !isDataNotFoundError(errors[0]);
|
|
365
|
+
return cacheHit || errorEncountered;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
370
|
+
* All rights reserved.
|
|
371
|
+
* For full license text, see the LICENSE.txt file
|
|
372
|
+
*/
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Implementation of CacheInclusionPolicy that uses a single level, in memory,
|
|
377
|
+
* synchronous L1 cache.
|
|
378
|
+
*/
|
|
379
|
+
class InMemoryCacheInclusionPolicy {
|
|
380
|
+
/**
|
|
381
|
+
* Reads data out of a single level in memory store.
|
|
382
|
+
*/
|
|
383
|
+
read(options) {
|
|
384
|
+
const { l1, readFromL1 } = options;
|
|
385
|
+
// l1 is all we've got
|
|
386
|
+
const readResult = readFromL1(l1);
|
|
387
|
+
return resolvedPromiseLike(readResult);
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Writes data to a single level in memory store.
|
|
391
|
+
*/
|
|
392
|
+
write(options) {
|
|
393
|
+
const { l1, writeToL1 } = options;
|
|
394
|
+
writeToL1(l1);
|
|
395
|
+
return resolvedPromiseLike(undefined);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Constructs an in-memory-only CacheInclusionPolicy.
|
|
400
|
+
*
|
|
401
|
+
* @returns in-memory-only CacheInclusionPolicy
|
|
402
|
+
*/
|
|
403
|
+
function buildInMemoryCacheInclusionPolicyService() {
|
|
404
|
+
return {
|
|
405
|
+
cacheInclusionPolicy: new InMemoryCacheInclusionPolicy(),
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
411
|
+
* All rights reserved.
|
|
412
|
+
* For full license text, see the LICENSE.txt file
|
|
413
|
+
*/
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
class CacheThenNetworkPolicy {
|
|
417
|
+
constructor(services, validator) {
|
|
418
|
+
this.services = services;
|
|
419
|
+
this.validator = validator;
|
|
420
|
+
this.policyName = 'cache-then-network';
|
|
421
|
+
}
|
|
422
|
+
run(options) {
|
|
423
|
+
const { readFromCache: readFromCacheOriginal, readFromNetwork: readFromNetworkOriginal, writeToCache: writeToCacheOriginal, buildResult, } = options;
|
|
424
|
+
// filter what data readFromCache is allowed to access from the store
|
|
425
|
+
const now = Date.now();
|
|
426
|
+
let ttlStore = new TTLFilteredStore(this.services.store, this.services.metadataRepository, now);
|
|
427
|
+
const { readFromCache: readFromCacheDedupe, readFromNetwork: readFromNetworkDedupe, writeToCache: writeToCacheDedupe, } = this.services.requestDedupe.applyDedupe({
|
|
428
|
+
readFromCache: (services) => this.readWithValidation(() => readFromCacheOriginal(services)),
|
|
429
|
+
readFromNetwork: readFromNetworkOriginal,
|
|
430
|
+
writeToCache: (services, networkResult) => this.writeWithValidation(() => writeToCacheOriginal(networkResult, services)),
|
|
431
|
+
});
|
|
432
|
+
return readFromCacheDedupe({ ...this.services, store: ttlStore }).then((value) => {
|
|
433
|
+
if (isCacheHitOrError(value)) {
|
|
434
|
+
return value;
|
|
435
|
+
}
|
|
436
|
+
// result not found in cache, try network
|
|
437
|
+
return readFromNetworkDedupe()
|
|
438
|
+
.then((value) => {
|
|
439
|
+
return writeToCacheDedupe(this.services, value).then(() => value);
|
|
440
|
+
})
|
|
441
|
+
.then((value) => {
|
|
442
|
+
const builtResult = buildResult(value, this.services);
|
|
443
|
+
this.validator.validateBuildResult(builtResult);
|
|
444
|
+
return builtResult;
|
|
445
|
+
});
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
readWithValidation(readFromCache) {
|
|
449
|
+
const readResult = readFromCache();
|
|
450
|
+
this.validator.validateReadResult(readResult);
|
|
451
|
+
return readResult;
|
|
452
|
+
}
|
|
453
|
+
writeWithValidation(writeToCache) {
|
|
454
|
+
const writeResult = writeToCache();
|
|
455
|
+
this.validator.validateWriteResult(writeResult);
|
|
456
|
+
return writeResult;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
function buildCacheThenNetworkPolicy(services, validator) {
|
|
460
|
+
return new CacheThenNetworkPolicy(services, validator);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
465
|
+
* All rights reserved.
|
|
466
|
+
* For full license text, see the LICENSE.txt file
|
|
467
|
+
*/
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Exported for testing purposes only
|
|
472
|
+
*/
|
|
473
|
+
class KeyBasedRequestDedupe {
|
|
474
|
+
constructor() {
|
|
475
|
+
// TODO [W-12965475]: This class is a first pass at network deduplication. No consuming Commands should
|
|
476
|
+
// directly try to leverage this, as it will be refactored/removed in the future.
|
|
477
|
+
// This map tracks the mapping of the key set a given network request response is expected to contain
|
|
478
|
+
// to that network request's outstanding promise. Entries are added to this map when a request has
|
|
479
|
+
// a set of expected keys, and a new network request promise is created.
|
|
480
|
+
this.outstandingNetworkRequests = new Map();
|
|
481
|
+
// This map tracks the mapping of the keys a given read is waiting for to a resolve function that notifies the read
|
|
482
|
+
// that the keys it needs may now be present in the cache. This resolve function can be called when any network
|
|
483
|
+
// response is ingested, and the ingested keys contain the keys the read needs. This map is added to when
|
|
484
|
+
// we believe that an outstanding request may contain the keys needed to satisfy a read.
|
|
485
|
+
this.outstandingReads = new Map();
|
|
486
|
+
}
|
|
487
|
+
applyDedupe({ readFromCache, readFromNetwork, writeToCache, }) {
|
|
488
|
+
const closureVariables = { expectedNetworkKeys: undefined };
|
|
489
|
+
return {
|
|
490
|
+
readFromCache: this.buildDedupedReadFromCache(readFromCache, closureVariables),
|
|
491
|
+
readFromNetwork: this.buildDedupedReadFromNetwork(readFromNetwork, closureVariables),
|
|
492
|
+
writeToCache: this.buildDedupedWriteToCache(writeToCache),
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
buildDedupedReadFromCache(readFromCache, closureVariables) {
|
|
496
|
+
const dedupedReadFromCache = (services) => {
|
|
497
|
+
const recordableStore = new RecordableStore(services.store);
|
|
498
|
+
return readFromCache({ ...services, store: recordableStore }).then((value) => {
|
|
499
|
+
const missingKeys = recordableStore.missingKeysRead;
|
|
500
|
+
// if cache result was final, or we got a cache miss even though
|
|
501
|
+
// we don't recognize anything as missing then we're done
|
|
502
|
+
if (isCacheHitOrError(value) || missingKeys.length === 0) {
|
|
503
|
+
return value;
|
|
504
|
+
}
|
|
505
|
+
// if we end up making a network request, we expect that it will return
|
|
506
|
+
// everything that was initially missing
|
|
507
|
+
if (!closureVariables.expectedNetworkKeys) {
|
|
508
|
+
closureVariables.expectedNetworkKeys = missingKeys;
|
|
509
|
+
}
|
|
510
|
+
// build a list of the Promises for all the outstanding network requests
|
|
511
|
+
// that are expected to return at least one of our missing keys
|
|
512
|
+
let unrequestedKeys = services.store.toKeySet(missingKeys.elements());
|
|
513
|
+
const matchingRequests = Array.from(this.outstandingNetworkRequests.entries()).reduce((matches, [outstandingRequestKeys, promise]) => {
|
|
514
|
+
if (outstandingRequestKeys.overlaps(missingKeys)) {
|
|
515
|
+
matches.push(promise);
|
|
516
|
+
unrequestedKeys = unrequestedKeys.difference(outstandingRequestKeys);
|
|
517
|
+
}
|
|
518
|
+
return matches;
|
|
519
|
+
}, []);
|
|
520
|
+
// if outstanding requests are not expected to return all the keys we need,
|
|
521
|
+
// return the cache read result
|
|
522
|
+
if (unrequestedKeys.length > 0) {
|
|
523
|
+
return value;
|
|
524
|
+
}
|
|
525
|
+
// Create a promise that can be resolved if any outstanding requests satisfy
|
|
526
|
+
// the missing keys
|
|
527
|
+
const otherResultMatchesPromise = new Promise((resolve) => {
|
|
528
|
+
this.outstandingReads.set(closureVariables.expectedNetworkKeys, resolve);
|
|
529
|
+
});
|
|
530
|
+
// wait for one of the matching network requests to come back, then retry
|
|
531
|
+
return Promise.race([otherResultMatchesPromise, ...matchingRequests])
|
|
532
|
+
.then(() => {
|
|
533
|
+
this.outstandingReads.delete(closureVariables.expectedNetworkKeys);
|
|
534
|
+
return dedupedReadFromCache(services);
|
|
535
|
+
})
|
|
536
|
+
.catch(() => {
|
|
537
|
+
this.outstandingReads.delete(closureVariables.expectedNetworkKeys);
|
|
538
|
+
return dedupedReadFromCache(services);
|
|
539
|
+
});
|
|
540
|
+
});
|
|
541
|
+
};
|
|
542
|
+
return dedupedReadFromCache;
|
|
543
|
+
}
|
|
544
|
+
buildDedupedReadFromNetwork(readFromNetwork, closureVariables) {
|
|
545
|
+
return () => {
|
|
546
|
+
if (closureVariables.expectedNetworkKeys === undefined ||
|
|
547
|
+
closureVariables.expectedNetworkKeys.length === 0) {
|
|
548
|
+
return readFromNetwork();
|
|
549
|
+
}
|
|
550
|
+
const deleteOutstandingRequest = () => this.outstandingNetworkRequests.delete(closureVariables.expectedNetworkKeys);
|
|
551
|
+
const networkPromise = readFromNetwork().then((value) => {
|
|
552
|
+
deleteOutstandingRequest();
|
|
553
|
+
return value;
|
|
554
|
+
}, (reason) => {
|
|
555
|
+
deleteOutstandingRequest();
|
|
556
|
+
return new Promise((_resolve, rejects) => {
|
|
557
|
+
rejects(reason);
|
|
558
|
+
});
|
|
559
|
+
});
|
|
560
|
+
this.outstandingNetworkRequests.set(closureVariables.expectedNetworkKeys, networkPromise);
|
|
561
|
+
return networkPromise;
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
buildDedupedWriteToCache(writeToCache) {
|
|
565
|
+
return (services, networkResult) => {
|
|
566
|
+
const recordableStore = new RecordableStore(services.store);
|
|
567
|
+
const result = writeToCache({ ...services, store: recordableStore }, networkResult);
|
|
568
|
+
return result.then(() => {
|
|
569
|
+
const updatedKeys = recordableStore.keysUpdated;
|
|
570
|
+
Array.from(this.outstandingReads.entries()).forEach(([outstandingReadKeys, resolve]) => {
|
|
571
|
+
if (outstandingReadKeys.isSubsetOf(updatedKeys)) {
|
|
572
|
+
resolve();
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
});
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
function buildKeyBasedRequestDedupeService() {
|
|
580
|
+
return { requestDedupe: new KeyBasedRequestDedupe() };
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
585
|
+
* All rights reserved.
|
|
586
|
+
* For full license text, see the LICENSE.txt file
|
|
587
|
+
*/
|
|
588
|
+
|
|
589
|
+
|
|
237
590
|
/**
|
|
238
591
|
* A simple implementation of KeyKeySubscriptionService.
|
|
239
592
|
*/
|
|
@@ -272,6 +625,13 @@ function buildDefaultKeySubscriptionService() {
|
|
|
272
625
|
};
|
|
273
626
|
}
|
|
274
627
|
|
|
628
|
+
/**
|
|
629
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
630
|
+
* All rights reserved.
|
|
631
|
+
* For full license text, see the LICENSE.txt file
|
|
632
|
+
*/
|
|
633
|
+
|
|
634
|
+
|
|
275
635
|
class DefaultTypeNotFoundError extends Error {
|
|
276
636
|
}
|
|
277
637
|
class DefaultTypeRegistry {
|
|
@@ -308,69 +668,9 @@ function buildDefaultTypeRegistryService() {
|
|
|
308
668
|
};
|
|
309
669
|
}
|
|
310
670
|
|
|
311
|
-
/**
|
|
312
|
-
* Copyright (c) 2022, Salesforce, Inc.,
|
|
313
|
-
* All rights reserved.
|
|
314
|
-
* For full license text, see the LICENSE.txt file
|
|
315
|
-
*/
|
|
316
|
-
|
|
317
|
-
/**
|
|
318
|
-
* Registrations that have already occurred.
|
|
319
|
-
*
|
|
320
|
-
* Note that Registrations are maintained as a list rather than a map to allow
|
|
321
|
-
* the same id to be registered multiple times with potentially different
|
|
322
|
-
* data.
|
|
323
|
-
*/
|
|
324
|
-
const registrations = [];
|
|
325
|
-
/**
|
|
326
|
-
* Invokes callback for each Registration, both past & future. That is, callback
|
|
327
|
-
* will be invoked exactly as many times as register() is called.
|
|
328
|
-
*
|
|
329
|
-
* Note that Registration ids are not guaranteed to be unique. The meaning of
|
|
330
|
-
* multiple Registrations with the same id is determined by the caller(s) of
|
|
331
|
-
* register().
|
|
332
|
-
*/
|
|
333
|
-
function forEachRegistration(callback) {
|
|
334
|
-
registrations.forEach((r) => callback(r));
|
|
335
|
-
}
|
|
336
|
-
/**
|
|
337
|
-
* Invokes callback when the specified id is registered.
|
|
338
|
-
*
|
|
339
|
-
* Note that callback may be invoked:
|
|
340
|
-
*
|
|
341
|
-
* - multiple times if multiple calls to register() specify the id
|
|
342
|
-
* - never if the specified id is never registered
|
|
343
|
-
*/
|
|
344
|
-
function withRegistration(id, callback) {
|
|
345
|
-
forEachRegistration((r) => {
|
|
346
|
-
if (r.id === id) {
|
|
347
|
-
callback(r);
|
|
348
|
-
}
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* Copyright (c) 2022, Salesforce, Inc.,
|
|
354
|
-
* All rights reserved.
|
|
355
|
-
* For full license text, see the LICENSE.txt file
|
|
356
|
-
*/
|
|
357
|
-
|
|
358
|
-
/**
|
|
359
|
-
* Indicates if a given instance of a service satisfies a request. Note that this function
|
|
360
|
-
* assumes the version numbers are valid strings.
|
|
361
|
-
*
|
|
362
|
-
* @param provided ServiceVersion of the service instance to be provided
|
|
363
|
-
* @param requested ServiceVersion requested
|
|
364
|
-
* @returns true if the service instance to be provided satisfies the request
|
|
365
|
-
*/
|
|
366
|
-
function satisfies(provided, requested) {
|
|
367
|
-
const providedN = provided.split('.').map((s) => parseInt(s));
|
|
368
|
-
const requestedN = requested.split('.').map((s) => parseInt(s));
|
|
369
|
-
return providedN[0] === requestedN[0] && providedN[1] >= requestedN[1];
|
|
370
|
-
}
|
|
371
|
-
|
|
372
671
|
const PDL_EXECUTE_ASYNC_OPTIONS = {
|
|
373
672
|
LOG_ERROR_ONLY: true,
|
|
673
|
+
ERROR_SCOPE: 'lds-predictive-loading',
|
|
374
674
|
};
|
|
375
675
|
|
|
376
676
|
class PredictivePrefetchPage {
|
|
@@ -998,7 +1298,7 @@ function setAuraInstrumentationHooks() {
|
|
|
998
1298
|
weakEtagZero: instrumentation.aggregateWeakETagEvents.bind(instrumentation),
|
|
999
1299
|
getRecordNotifyChangeNetworkResult: instrumentation.notifyChangeNetwork.bind(instrumentation),
|
|
1000
1300
|
});
|
|
1001
|
-
withRegistration
|
|
1301
|
+
withRegistration('@salesforce/lds-adapters-uiapi', (reg) => setLdsAdaptersUiapiInstrumentation(reg));
|
|
1002
1302
|
instrument$1({
|
|
1003
1303
|
logCrud: logCRUDLightningInteraction,
|
|
1004
1304
|
networkResponse: incrementRequestResponseCount,
|
|
@@ -1032,7 +1332,7 @@ function setAuraInstrumentationHooks() {
|
|
|
1032
1332
|
},
|
|
1033
1333
|
});
|
|
1034
1334
|
}
|
|
1035
|
-
withRegistration
|
|
1335
|
+
withRegistration('@salesforce/lds-network-adapter', (reg) => setLdsNetworkAdapterInstrumentation(reg));
|
|
1036
1336
|
}
|
|
1037
1337
|
/**
|
|
1038
1338
|
* Initialize the instrumentation and instrument the LDS instance and the InMemoryStore.
|
|
@@ -2299,22 +2599,29 @@ function initializeLDS() {
|
|
|
2299
2599
|
}
|
|
2300
2600
|
// Initializes OneStore in LEX
|
|
2301
2601
|
function initializeOneStore() {
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
...buildInMemoryStoreService(),
|
|
2307
|
-
...buildDefaultTypeRegistryService(),
|
|
2308
|
-
...buildAuraNetworkService(),
|
|
2602
|
+
const validator = {
|
|
2603
|
+
validateReadResult() { },
|
|
2604
|
+
validateWriteResult() { },
|
|
2605
|
+
validateBuildResult() { },
|
|
2309
2606
|
};
|
|
2607
|
+
const services = emptyServices();
|
|
2608
|
+
// Build default set of services
|
|
2609
|
+
Object.assign(services, buildDefaultKeySubscriptionService(), buildInMemoryMetadataRepositoryService(), buildInMemoryStoreService(), buildDefaultTypeRegistryService(), buildAuraNetworkService(), buildInMemoryCacheInclusionPolicyService(), {
|
|
2610
|
+
cachePolicy: {
|
|
2611
|
+
cachePolicies: [buildCacheThenNetworkPolicy(services, validator)],
|
|
2612
|
+
defaultCachePolicyName: 'cache-then-network',
|
|
2613
|
+
},
|
|
2614
|
+
}, buildKeyBasedRequestDedupeService());
|
|
2310
2615
|
const serviceVersions = {
|
|
2311
2616
|
keySubscription: "1.0" /* KeySubscriptionServiceInfo.VERSION */,
|
|
2312
2617
|
metadataRepository: "1.0" /* MetadataRepositoryServiceInfo.VERSION */,
|
|
2313
2618
|
store: "1.0" /* StoreServiceInfo.VERSION */,
|
|
2314
2619
|
typeRegistry: "1.0" /* TypeRegistryServiceInfo.VERSION */,
|
|
2315
2620
|
auraNetwork: "1.0" /* AuraNetworkServiceInfo.VERSION */,
|
|
2621
|
+
cacheInclusionPolicy: "1.0" /* CacheInclusionPolicyServiceInfo.VERSION */,
|
|
2622
|
+
cachePolicy: "1.0" /* CachePolicyServiceInfo.VERSION */,
|
|
2316
2623
|
};
|
|
2317
|
-
withRegistration('commandModule', (registration) => {
|
|
2624
|
+
withRegistration$1('commandModule', (registration) => {
|
|
2318
2625
|
const matchingServices = {};
|
|
2319
2626
|
if (Object.entries(registration.services).every(([service, version]) => service in services &&
|
|
2320
2627
|
satisfies(serviceVersions[service], version) &&
|
|
@@ -2322,13 +2629,11 @@ function initializeOneStore() {
|
|
|
2322
2629
|
registration.setServices(matchingServices);
|
|
2323
2630
|
}
|
|
2324
2631
|
});
|
|
2325
|
-
withRegistration('commandModule-uiapi', (registration) => {
|
|
2632
|
+
withRegistration$1('commandModule-uiapi', (registration) => {
|
|
2326
2633
|
if (Object.entries(registration.services).every(([service, version]) => service in services &&
|
|
2327
2634
|
satisfies(serviceVersions[service], version) &&
|
|
2328
2635
|
(services[service]))) {
|
|
2329
|
-
|
|
2330
|
-
// https://github.com/salesforce-experience-platform-emu/lds-lightning-platform/pull/4961/files#r1522283942
|
|
2331
|
-
const { getObjectInfo, getObjectInfos } = registration.setServices(services);
|
|
2636
|
+
registration.setServices(services);
|
|
2332
2637
|
configuration.setGetObjectInfoAdapter(getObjectInfo);
|
|
2333
2638
|
configuration.setGetObjectInfosAdapter(getObjectInfos);
|
|
2334
2639
|
}
|
|
@@ -2351,4 +2656,4 @@ function ldsEngineCreator() {
|
|
|
2351
2656
|
}
|
|
2352
2657
|
|
|
2353
2658
|
export { buildPredictorForContext, ldsEngineCreator as default, initializeLDS, initializeOneStore };
|
|
2354
|
-
// version: 1.
|
|
2659
|
+
// version: 1.286.0-09e7e5207
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/lds-runtime-aura",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.286.0",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
5
5
|
"description": "LDS engine for Aura runtime",
|
|
6
6
|
"main": "dist/ldsEngineCreator.js",
|
|
@@ -35,25 +35,34 @@
|
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@luvio/registry": "^3.0.0",
|
|
38
|
-
"@luvio/runtime": "3.
|
|
39
|
-
"@
|
|
40
|
-
"@
|
|
41
|
-
"@
|
|
42
|
-
"@
|
|
43
|
-
"@
|
|
44
|
-
"@
|
|
45
|
-
"@
|
|
38
|
+
"@luvio/runtime": "^3.5.0",
|
|
39
|
+
"@luvio/service-cache-inclusion-policy": "^1.0.0",
|
|
40
|
+
"@luvio/service-cache-policy": "^1.0.0",
|
|
41
|
+
"@luvio/service-dedupe": "^1.0.0",
|
|
42
|
+
"@luvio/service-network": "^1.0.0",
|
|
43
|
+
"@luvio/service-store": "^1.0.0",
|
|
44
|
+
"@luvio/service-subscription": "^1.0.0",
|
|
45
|
+
"@luvio/service-type-registry": "^1.0.0",
|
|
46
|
+
"@luvio/utils": "^3.6.0",
|
|
47
|
+
"@salesforce/lds-adapters-uiapi": "^1.286.0",
|
|
48
|
+
"@salesforce/lds-ads-bridge": "^1.286.0",
|
|
49
|
+
"@salesforce/lds-aura-storage": "^1.286.0",
|
|
50
|
+
"@salesforce/lds-bindings": "^1.286.0",
|
|
51
|
+
"@salesforce/lds-instrumentation": "^1.286.0",
|
|
52
|
+
"@salesforce/lds-network-aura": "^1.286.0",
|
|
53
|
+
"@salesforce/lds-network-fetch-with-jwt": "^1.286.0"
|
|
46
54
|
},
|
|
47
55
|
"dependencies": {
|
|
48
|
-
"@luvio/network-adapter-composable": "0.154.
|
|
56
|
+
"@luvio/network-adapter-composable": "0.154.16",
|
|
57
|
+
"@salesforce/lds-adapters-uiapi-lex": "^1.286.0"
|
|
49
58
|
},
|
|
50
59
|
"luvioBundlesize": [
|
|
51
60
|
{
|
|
52
61
|
"path": "./dist/ldsEngineCreator.js",
|
|
53
62
|
"maxSize": {
|
|
54
|
-
"none": "
|
|
55
|
-
"min": "
|
|
56
|
-
"compressed": "
|
|
63
|
+
"none": "101 kB",
|
|
64
|
+
"min": "42 kB",
|
|
65
|
+
"compressed": "18.5 kB"
|
|
57
66
|
}
|
|
58
67
|
}
|
|
59
68
|
],
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export declare enum KeySubscriptionServiceInfo {
|
|
2
|
-
NAME = "keySubscription",
|
|
3
|
-
VERSION = "1.0"
|
|
4
|
-
}
|
|
5
|
-
export declare enum MetadataRepositoryServiceInfo {
|
|
6
|
-
NAME = "metadataRepository",
|
|
7
|
-
VERSION = "1.0"
|
|
8
|
-
}
|
|
9
|
-
export declare enum StoreServiceInfo {
|
|
10
|
-
NAME = "store",
|
|
11
|
-
VERSION = "1.0"
|
|
12
|
-
}
|
|
13
|
-
export declare enum TypeRegistryServiceInfo {
|
|
14
|
-
NAME = "typeRegistry",
|
|
15
|
-
VERSION = "1.0"
|
|
16
|
-
}
|
|
17
|
-
export declare enum AuraNetworkServiceInfo {
|
|
18
|
-
NAME = "auraNetwork",
|
|
19
|
-
VERSION = "1.0"
|
|
20
|
-
}
|
|
21
|
-
export declare function buildDefaultKeySubscriptionService(): void;
|
|
22
|
-
export declare function buildInMemoryMetadataRepositoryService(): void;
|
|
23
|
-
export declare function buildInMemoryStoreService(): void;
|
|
24
|
-
export declare function buildDefaultTypeRegistryService(): void;
|
|
25
|
-
export declare function buildAuraNetworkService(): void;
|