@salesforce/lds-runtime-mobile 1.100.3 → 1.100.4
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/main.js +172 -138
- package/package.json +15 -15
- package/sfdc/main.js +172 -138
package/dist/main.js
CHANGED
|
@@ -4344,6 +4344,44 @@ function makeStoreEval(preconditioner, objectInfoService, userId, contextProvide
|
|
|
4344
4344
|
return wrapStartEndEvents(storeEval);
|
|
4345
4345
|
}
|
|
4346
4346
|
|
|
4347
|
+
/**
|
|
4348
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
4349
|
+
* All rights reserved.
|
|
4350
|
+
* For full license text, see the LICENSE.txt file
|
|
4351
|
+
*/
|
|
4352
|
+
|
|
4353
|
+
class AsyncWorkerPool {
|
|
4354
|
+
constructor(concurrency) {
|
|
4355
|
+
this.queue = [];
|
|
4356
|
+
this.activeWorkers = 0;
|
|
4357
|
+
this.concurrency = concurrency;
|
|
4358
|
+
}
|
|
4359
|
+
push(workFn) {
|
|
4360
|
+
return new Promise((resolve, reject) => {
|
|
4361
|
+
this.queue.push(async () => {
|
|
4362
|
+
return workFn().then(resolve).catch(reject);
|
|
4363
|
+
});
|
|
4364
|
+
this.work();
|
|
4365
|
+
});
|
|
4366
|
+
}
|
|
4367
|
+
cancel() {
|
|
4368
|
+
this.queue = [];
|
|
4369
|
+
// TODO [W-12513105]: thread cancellation through to active workers
|
|
4370
|
+
}
|
|
4371
|
+
work() {
|
|
4372
|
+
while (this.queue.length > 0 && this.activeWorkers < this.concurrency) {
|
|
4373
|
+
this.activeWorkers += 1;
|
|
4374
|
+
const next = this.queue.shift();
|
|
4375
|
+
if (next) {
|
|
4376
|
+
next().finally(() => {
|
|
4377
|
+
this.activeWorkers -= 1;
|
|
4378
|
+
this.work();
|
|
4379
|
+
});
|
|
4380
|
+
}
|
|
4381
|
+
}
|
|
4382
|
+
}
|
|
4383
|
+
}
|
|
4384
|
+
|
|
4347
4385
|
/**
|
|
4348
4386
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
4349
4387
|
* All rights reserved.
|
|
@@ -4762,6 +4800,7 @@ class DurableDraftQueue {
|
|
|
4762
4800
|
this.timeoutHandler = undefined;
|
|
4763
4801
|
this.handlers = {};
|
|
4764
4802
|
this.draftStore = draftStore;
|
|
4803
|
+
this.workerPool = new AsyncWorkerPool(1);
|
|
4765
4804
|
}
|
|
4766
4805
|
addHandler(handler) {
|
|
4767
4806
|
const id = handler.handlerId;
|
|
@@ -4861,20 +4900,22 @@ class DurableDraftQueue {
|
|
|
4861
4900
|
});
|
|
4862
4901
|
}
|
|
4863
4902
|
async enqueue(handlerId, data) {
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4903
|
+
return this.workerPool.push(async () => {
|
|
4904
|
+
let queue = await this.getQueueActions();
|
|
4905
|
+
const handler = this.getHandler(handlerId);
|
|
4906
|
+
const pendingAction = (await handler.buildPendingAction(data, queue));
|
|
4907
|
+
await this.draftStore.writeAction(pendingAction);
|
|
4908
|
+
queue = await this.getQueueActions();
|
|
4909
|
+
await this.notifyChangedListeners({
|
|
4910
|
+
type: DraftQueueEventType.ActionAdded,
|
|
4911
|
+
action: pendingAction,
|
|
4912
|
+
});
|
|
4913
|
+
await handler.handleActionEnqueued(pendingAction, queue);
|
|
4914
|
+
if (this.state === DraftQueueState.Started) {
|
|
4915
|
+
this.processNextAction();
|
|
4916
|
+
}
|
|
4917
|
+
return pendingAction;
|
|
4872
4918
|
});
|
|
4873
|
-
await handler.handleActionEnqueued(pendingAction, queue);
|
|
4874
|
-
if (this.state === DraftQueueState.Started) {
|
|
4875
|
-
this.processNextAction();
|
|
4876
|
-
}
|
|
4877
|
-
return pendingAction;
|
|
4878
4919
|
}
|
|
4879
4920
|
registerOnChangedListener(listener) {
|
|
4880
4921
|
this.draftQueueChangedListeners.push(listener);
|
|
@@ -4886,27 +4927,29 @@ class DurableDraftQueue {
|
|
|
4886
4927
|
};
|
|
4887
4928
|
}
|
|
4888
4929
|
async actionCompleted(action) {
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
|
|
4930
|
+
return this.workerPool.push(async () => {
|
|
4931
|
+
const handler = this.getHandler(action.handler);
|
|
4932
|
+
let queue = await this.getQueueActions();
|
|
4933
|
+
const queueOperations = handler.getQueueOperationsForCompletingDrafts(queue, action);
|
|
4934
|
+
const idAndKeyMappings = handler.getRedirectMappings(action);
|
|
4935
|
+
const keyMappings = idAndKeyMappings === undefined
|
|
4936
|
+
? undefined
|
|
4937
|
+
: idAndKeyMappings.map((m) => {
|
|
4938
|
+
return { draftKey: m.draftKey, canonicalKey: m.canonicalKey };
|
|
4939
|
+
});
|
|
4940
|
+
await this.draftStore.completeAction(queueOperations, keyMappings);
|
|
4941
|
+
queue = await this.getQueueActions();
|
|
4942
|
+
this.retryIntervalMilliseconds = 0;
|
|
4943
|
+
this.uploadingActionId = undefined;
|
|
4944
|
+
await handler.handleActionCompleted(action, queueOperations, queue, values$1(this.handlers));
|
|
4945
|
+
await this.notifyChangedListeners({
|
|
4946
|
+
type: DraftQueueEventType.ActionCompleted,
|
|
4947
|
+
action,
|
|
4897
4948
|
});
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
this.uploadingActionId = undefined;
|
|
4902
|
-
await handler.handleActionCompleted(action, queueOperations, queue, values$1(this.handlers));
|
|
4903
|
-
await this.notifyChangedListeners({
|
|
4904
|
-
type: DraftQueueEventType.ActionCompleted,
|
|
4905
|
-
action,
|
|
4949
|
+
if (this.state === DraftQueueState.Started) {
|
|
4950
|
+
this.processNextAction();
|
|
4951
|
+
}
|
|
4906
4952
|
});
|
|
4907
|
-
if (this.state === DraftQueueState.Started) {
|
|
4908
|
-
this.processNextAction();
|
|
4909
|
-
}
|
|
4910
4953
|
}
|
|
4911
4954
|
async actionFailed(action, retry) {
|
|
4912
4955
|
this.uploadingActionId = undefined;
|
|
@@ -5356,6 +5399,13 @@ class AbstractResourceRequestActionHandler {
|
|
|
5356
5399
|
this.draftQueue = draftQueue;
|
|
5357
5400
|
this.networkAdapter = networkAdapter;
|
|
5358
5401
|
this.getLuvio = getLuvio;
|
|
5402
|
+
// NOTE[W-12567340]: This property stores in-memory mappings between draft
|
|
5403
|
+
// ids and canonical ids for the current session. Having a local copy of
|
|
5404
|
+
// these mappings is necessary to avoid a race condition between publishing
|
|
5405
|
+
// new mappings to the durable store and those mappings being loaded into
|
|
5406
|
+
// the luvio store redirect table, during which a new draft might be enqueued
|
|
5407
|
+
// which would not see a necessary mapping.
|
|
5408
|
+
this.ephemeralRedirects = {};
|
|
5359
5409
|
}
|
|
5360
5410
|
enqueue(data) {
|
|
5361
5411
|
return this.draftQueue.enqueue(this.handlerId, data);
|
|
@@ -5423,7 +5473,8 @@ class AbstractResourceRequestActionHandler {
|
|
|
5423
5473
|
}
|
|
5424
5474
|
getQueueOperationsForCompletingDrafts(queue, action) {
|
|
5425
5475
|
const queueOperations = [];
|
|
5426
|
-
|
|
5476
|
+
const redirects = this.getRedirectMappings(action);
|
|
5477
|
+
if (redirects !== undefined) {
|
|
5427
5478
|
const { length } = queue;
|
|
5428
5479
|
for (let i = 0; i < length; i++) {
|
|
5429
5480
|
const queueAction = queue[i];
|
|
@@ -5433,69 +5484,64 @@ class AbstractResourceRequestActionHandler {
|
|
|
5433
5484
|
continue;
|
|
5434
5485
|
}
|
|
5435
5486
|
if (isResourceRequestAction(queueAction)) {
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
basePath = basePath.replace(draftId, canonicalId);
|
|
5450
|
-
stringifiedBody = stringifiedBody.replace(draftId, canonicalId);
|
|
5451
|
-
queueOperationMutated = true;
|
|
5452
|
-
}
|
|
5453
|
-
// if the action is performed on a previous draft id, we need to replace the action
|
|
5454
|
-
// with a new one at the updated canonical key
|
|
5455
|
-
if (queueActionTag === draftKey) {
|
|
5456
|
-
updatedActionTag = canonicalKey;
|
|
5457
|
-
updatedActionTargetId = canonicalId;
|
|
5458
|
-
}
|
|
5487
|
+
let queueOperationMutated = false;
|
|
5488
|
+
let updatedActionTag = undefined;
|
|
5489
|
+
let updatedActionTargetId = undefined;
|
|
5490
|
+
const { tag: queueActionTag, data: queueActionRequest, id: queueActionId, } = queueAction;
|
|
5491
|
+
let { basePath, body } = queueActionRequest;
|
|
5492
|
+
let stringifiedBody = stringify$4(body);
|
|
5493
|
+
// for each redirected ID/key we loop over the operation to see if it needs
|
|
5494
|
+
// to be updated
|
|
5495
|
+
for (const { draftId, draftKey, canonicalId, canonicalKey } of redirects) {
|
|
5496
|
+
if (basePath.search(draftId) >= 0 || stringifiedBody.search(draftId) >= 0) {
|
|
5497
|
+
basePath = basePath.replace(draftId, canonicalId);
|
|
5498
|
+
stringifiedBody = stringifiedBody.replace(draftId, canonicalId);
|
|
5499
|
+
queueOperationMutated = true;
|
|
5459
5500
|
}
|
|
5460
|
-
if
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
}
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5501
|
+
// if the action is performed on a previous draft id, we need to replace the action
|
|
5502
|
+
// with a new one at the updated canonical key
|
|
5503
|
+
if (queueActionTag === draftKey) {
|
|
5504
|
+
updatedActionTag = canonicalKey;
|
|
5505
|
+
updatedActionTargetId = canonicalId;
|
|
5506
|
+
}
|
|
5507
|
+
}
|
|
5508
|
+
if (queueOperationMutated) {
|
|
5509
|
+
if (updatedActionTag !== undefined && updatedActionTargetId !== undefined) {
|
|
5510
|
+
const updatedAction = {
|
|
5511
|
+
...queueAction,
|
|
5512
|
+
tag: updatedActionTag,
|
|
5513
|
+
targetId: updatedActionTargetId,
|
|
5514
|
+
data: {
|
|
5515
|
+
...queueActionRequest,
|
|
5516
|
+
basePath: basePath,
|
|
5517
|
+
body: parse$4(stringifiedBody),
|
|
5518
|
+
},
|
|
5519
|
+
};
|
|
5520
|
+
// item needs to be replaced with a new item at the new record key
|
|
5521
|
+
queueOperations.push({
|
|
5522
|
+
type: QueueOperationType.Delete,
|
|
5523
|
+
id: queueActionId,
|
|
5524
|
+
});
|
|
5525
|
+
queueOperations.push({
|
|
5526
|
+
type: QueueOperationType.Add,
|
|
5527
|
+
action: updatedAction,
|
|
5528
|
+
});
|
|
5529
|
+
}
|
|
5530
|
+
else {
|
|
5531
|
+
const updatedAction = {
|
|
5532
|
+
...queueAction,
|
|
5533
|
+
data: {
|
|
5534
|
+
...queueActionRequest,
|
|
5535
|
+
basePath: basePath,
|
|
5536
|
+
body: parse$4(stringifiedBody),
|
|
5537
|
+
},
|
|
5538
|
+
};
|
|
5539
|
+
// item needs to be updated
|
|
5540
|
+
queueOperations.push({
|
|
5541
|
+
type: QueueOperationType.Update,
|
|
5542
|
+
id: queueActionId,
|
|
5543
|
+
action: updatedAction,
|
|
5544
|
+
});
|
|
5499
5545
|
}
|
|
5500
5546
|
}
|
|
5501
5547
|
}
|
|
@@ -5515,6 +5561,9 @@ class AbstractResourceRequestActionHandler {
|
|
|
5515
5561
|
const body = action.response.body;
|
|
5516
5562
|
const canonicalId = this.getIdFromResponseBody(body);
|
|
5517
5563
|
const draftId = action.targetId;
|
|
5564
|
+
if (draftId !== undefined && canonicalId !== undefined && draftId !== canonicalId) {
|
|
5565
|
+
this.ephemeralRedirects[draftId] = canonicalId;
|
|
5566
|
+
}
|
|
5518
5567
|
return [
|
|
5519
5568
|
{
|
|
5520
5569
|
draftId,
|
|
@@ -11296,12 +11345,18 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
|
|
|
11296
11345
|
const fieldName = fieldNames[i];
|
|
11297
11346
|
const fieldValue = bodyFields[fieldName];
|
|
11298
11347
|
if (typeof fieldValue === 'string' && this.isDraftId(fieldValue)) {
|
|
11299
|
-
const
|
|
11300
|
-
|
|
11301
|
-
|
|
11302
|
-
|
|
11303
|
-
|
|
11304
|
-
|
|
11348
|
+
const canonicalId = this.ephemeralRedirects[fieldValue];
|
|
11349
|
+
if (canonicalId !== undefined) {
|
|
11350
|
+
bodyFields[fieldName] = canonicalId;
|
|
11351
|
+
}
|
|
11352
|
+
else {
|
|
11353
|
+
const draftKey = this.buildTagForTargetId(fieldValue);
|
|
11354
|
+
const canonicalKey = this.getLuvio().storeGetCanonicalKey(draftKey);
|
|
11355
|
+
if (draftKey !== canonicalKey) {
|
|
11356
|
+
const canonicalId = extractRecordIdFromStoreKey(canonicalKey);
|
|
11357
|
+
if (canonicalId !== undefined) {
|
|
11358
|
+
bodyFields[fieldName] = canonicalId;
|
|
11359
|
+
}
|
|
11305
11360
|
}
|
|
11306
11361
|
}
|
|
11307
11362
|
}
|
|
@@ -11309,17 +11364,24 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
|
|
|
11309
11364
|
}
|
|
11310
11365
|
if (request.method === 'patch' || request.method === 'delete') {
|
|
11311
11366
|
const recordId = request.urlParams['recordId'];
|
|
11312
|
-
const
|
|
11313
|
-
|
|
11314
|
-
if (recordKey !== canonicalKey) {
|
|
11315
|
-
const canonicalId = extractRecordIdFromStoreKey(canonicalKey);
|
|
11316
|
-
if (canonicalId === undefined) {
|
|
11317
|
-
// could not resolve id from request -- return the request un-modified
|
|
11318
|
-
return request;
|
|
11319
|
-
}
|
|
11367
|
+
const canonicalId = this.ephemeralRedirects[recordId];
|
|
11368
|
+
if (canonicalId !== undefined) {
|
|
11320
11369
|
resolvedBasePath = resolvedBasePath.replace(recordId, canonicalId);
|
|
11321
11370
|
resolvedUrlParams = { ...resolvedUrlParams, recordId: canonicalId };
|
|
11322
11371
|
}
|
|
11372
|
+
else {
|
|
11373
|
+
const recordKey = this.buildTagForTargetId(recordId);
|
|
11374
|
+
const canonicalKey = this.getLuvio().storeGetCanonicalKey(recordKey);
|
|
11375
|
+
if (recordKey !== canonicalKey) {
|
|
11376
|
+
const canonicalId = extractRecordIdFromStoreKey(canonicalKey);
|
|
11377
|
+
if (canonicalId === undefined) {
|
|
11378
|
+
// could not resolve id from request -- return the request un-modified
|
|
11379
|
+
return request;
|
|
11380
|
+
}
|
|
11381
|
+
resolvedBasePath = resolvedBasePath.replace(recordId, canonicalId);
|
|
11382
|
+
resolvedUrlParams = { ...resolvedUrlParams, recordId: canonicalId };
|
|
11383
|
+
}
|
|
11384
|
+
}
|
|
11323
11385
|
}
|
|
11324
11386
|
return {
|
|
11325
11387
|
...request,
|
|
@@ -14667,34 +14729,6 @@ function setupInspection(luvio) {
|
|
|
14667
14729
|
* For full license text, see the LICENSE.txt file
|
|
14668
14730
|
*/
|
|
14669
14731
|
|
|
14670
|
-
class AsyncWorkerPool {
|
|
14671
|
-
constructor(concurrency) {
|
|
14672
|
-
this.queue = [];
|
|
14673
|
-
this.activeWorkers = 0;
|
|
14674
|
-
this.concurrency = concurrency;
|
|
14675
|
-
}
|
|
14676
|
-
push(workFn) {
|
|
14677
|
-
this.queue.push(workFn);
|
|
14678
|
-
this.work();
|
|
14679
|
-
}
|
|
14680
|
-
cancel() {
|
|
14681
|
-
this.queue = [];
|
|
14682
|
-
// TODO [W-12513105]: thread cancellation through to active workers
|
|
14683
|
-
}
|
|
14684
|
-
work() {
|
|
14685
|
-
while (this.queue.length > 0 && this.activeWorkers < this.concurrency) {
|
|
14686
|
-
this.activeWorkers += 1;
|
|
14687
|
-
const next = this.queue.shift();
|
|
14688
|
-
if (next) {
|
|
14689
|
-
next().finally(() => {
|
|
14690
|
-
this.activeWorkers -= 1;
|
|
14691
|
-
this.work();
|
|
14692
|
-
});
|
|
14693
|
-
}
|
|
14694
|
-
}
|
|
14695
|
-
}
|
|
14696
|
-
}
|
|
14697
|
-
|
|
14698
14732
|
class EventEmitter {
|
|
14699
14733
|
constructor() {
|
|
14700
14734
|
// @ts-ignore typescript doesn't like us setting this to an empty object for some reason
|
|
@@ -15247,4 +15281,4 @@ register({
|
|
|
15247
15281
|
});
|
|
15248
15282
|
|
|
15249
15283
|
export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
|
|
15250
|
-
// version: 1.100.
|
|
15284
|
+
// version: 1.100.4-ce1be23b7
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/lds-runtime-mobile",
|
|
3
|
-
"version": "1.100.
|
|
3
|
+
"version": "1.100.4",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
5
5
|
"description": "LDS runtime for mobile/hybrid environments.",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"release:corejar": "yarn build && ../core-build/scripts/core.js --name=lds-runtime-mobile"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@salesforce/lds-adapters-uiapi": "^1.100.
|
|
36
|
-
"@salesforce/lds-bindings": "^1.100.
|
|
37
|
-
"@salesforce/lds-instrumentation": "^1.100.
|
|
38
|
-
"@salesforce/lds-priming": "^1.100.
|
|
35
|
+
"@salesforce/lds-adapters-uiapi": "^1.100.4",
|
|
36
|
+
"@salesforce/lds-bindings": "^1.100.4",
|
|
37
|
+
"@salesforce/lds-instrumentation": "^1.100.4",
|
|
38
|
+
"@salesforce/lds-priming": "^1.100.4",
|
|
39
39
|
"@salesforce/user": "0.0.12",
|
|
40
40
|
"o11y": "244.0.0"
|
|
41
41
|
},
|
|
@@ -43,16 +43,16 @@
|
|
|
43
43
|
"@luvio/engine": "0.135.4",
|
|
44
44
|
"@luvio/environments": "0.135.4",
|
|
45
45
|
"@luvio/graphql-parser": "0.135.4",
|
|
46
|
-
"@salesforce/lds-adapters-graphql": "^1.100.
|
|
47
|
-
"@salesforce/lds-drafts": "^1.100.
|
|
48
|
-
"@salesforce/lds-drafts-adapters-uiapi": "^1.100.
|
|
49
|
-
"@salesforce/lds-graphql-eval": "^1.100.
|
|
50
|
-
"@salesforce/lds-network-adapter": "^1.100.
|
|
51
|
-
"@salesforce/lds-network-nimbus": "^1.100.
|
|
52
|
-
"@salesforce/lds-store-binary": "^1.100.
|
|
53
|
-
"@salesforce/lds-store-sql": "^1.100.
|
|
54
|
-
"@salesforce/lds-utils-adapters": "^1.100.
|
|
55
|
-
"@salesforce/nimbus-plugin-lds": "^1.100.
|
|
46
|
+
"@salesforce/lds-adapters-graphql": "^1.100.4",
|
|
47
|
+
"@salesforce/lds-drafts": "^1.100.4",
|
|
48
|
+
"@salesforce/lds-drafts-adapters-uiapi": "^1.100.4",
|
|
49
|
+
"@salesforce/lds-graphql-eval": "^1.100.4",
|
|
50
|
+
"@salesforce/lds-network-adapter": "^1.100.4",
|
|
51
|
+
"@salesforce/lds-network-nimbus": "^1.100.4",
|
|
52
|
+
"@salesforce/lds-store-binary": "^1.100.4",
|
|
53
|
+
"@salesforce/lds-store-sql": "^1.100.4",
|
|
54
|
+
"@salesforce/lds-utils-adapters": "^1.100.4",
|
|
55
|
+
"@salesforce/nimbus-plugin-lds": "^1.100.4",
|
|
56
56
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
|
57
57
|
"wait-for-expect": "^3.0.2"
|
|
58
58
|
},
|
package/sfdc/main.js
CHANGED
|
@@ -4344,6 +4344,44 @@ function makeStoreEval(preconditioner, objectInfoService, userId, contextProvide
|
|
|
4344
4344
|
return wrapStartEndEvents(storeEval);
|
|
4345
4345
|
}
|
|
4346
4346
|
|
|
4347
|
+
/**
|
|
4348
|
+
* Copyright (c) 2022, Salesforce, Inc.,
|
|
4349
|
+
* All rights reserved.
|
|
4350
|
+
* For full license text, see the LICENSE.txt file
|
|
4351
|
+
*/
|
|
4352
|
+
|
|
4353
|
+
class AsyncWorkerPool {
|
|
4354
|
+
constructor(concurrency) {
|
|
4355
|
+
this.queue = [];
|
|
4356
|
+
this.activeWorkers = 0;
|
|
4357
|
+
this.concurrency = concurrency;
|
|
4358
|
+
}
|
|
4359
|
+
push(workFn) {
|
|
4360
|
+
return new Promise((resolve, reject) => {
|
|
4361
|
+
this.queue.push(async () => {
|
|
4362
|
+
return workFn().then(resolve).catch(reject);
|
|
4363
|
+
});
|
|
4364
|
+
this.work();
|
|
4365
|
+
});
|
|
4366
|
+
}
|
|
4367
|
+
cancel() {
|
|
4368
|
+
this.queue = [];
|
|
4369
|
+
// TODO [W-12513105]: thread cancellation through to active workers
|
|
4370
|
+
}
|
|
4371
|
+
work() {
|
|
4372
|
+
while (this.queue.length > 0 && this.activeWorkers < this.concurrency) {
|
|
4373
|
+
this.activeWorkers += 1;
|
|
4374
|
+
const next = this.queue.shift();
|
|
4375
|
+
if (next) {
|
|
4376
|
+
next().finally(() => {
|
|
4377
|
+
this.activeWorkers -= 1;
|
|
4378
|
+
this.work();
|
|
4379
|
+
});
|
|
4380
|
+
}
|
|
4381
|
+
}
|
|
4382
|
+
}
|
|
4383
|
+
}
|
|
4384
|
+
|
|
4347
4385
|
/**
|
|
4348
4386
|
* Copyright (c) 2022, Salesforce, Inc.,
|
|
4349
4387
|
* All rights reserved.
|
|
@@ -4762,6 +4800,7 @@ class DurableDraftQueue {
|
|
|
4762
4800
|
this.timeoutHandler = undefined;
|
|
4763
4801
|
this.handlers = {};
|
|
4764
4802
|
this.draftStore = draftStore;
|
|
4803
|
+
this.workerPool = new AsyncWorkerPool(1);
|
|
4765
4804
|
}
|
|
4766
4805
|
addHandler(handler) {
|
|
4767
4806
|
const id = handler.handlerId;
|
|
@@ -4861,20 +4900,22 @@ class DurableDraftQueue {
|
|
|
4861
4900
|
});
|
|
4862
4901
|
}
|
|
4863
4902
|
async enqueue(handlerId, data) {
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4903
|
+
return this.workerPool.push(async () => {
|
|
4904
|
+
let queue = await this.getQueueActions();
|
|
4905
|
+
const handler = this.getHandler(handlerId);
|
|
4906
|
+
const pendingAction = (await handler.buildPendingAction(data, queue));
|
|
4907
|
+
await this.draftStore.writeAction(pendingAction);
|
|
4908
|
+
queue = await this.getQueueActions();
|
|
4909
|
+
await this.notifyChangedListeners({
|
|
4910
|
+
type: DraftQueueEventType.ActionAdded,
|
|
4911
|
+
action: pendingAction,
|
|
4912
|
+
});
|
|
4913
|
+
await handler.handleActionEnqueued(pendingAction, queue);
|
|
4914
|
+
if (this.state === DraftQueueState.Started) {
|
|
4915
|
+
this.processNextAction();
|
|
4916
|
+
}
|
|
4917
|
+
return pendingAction;
|
|
4872
4918
|
});
|
|
4873
|
-
await handler.handleActionEnqueued(pendingAction, queue);
|
|
4874
|
-
if (this.state === DraftQueueState.Started) {
|
|
4875
|
-
this.processNextAction();
|
|
4876
|
-
}
|
|
4877
|
-
return pendingAction;
|
|
4878
4919
|
}
|
|
4879
4920
|
registerOnChangedListener(listener) {
|
|
4880
4921
|
this.draftQueueChangedListeners.push(listener);
|
|
@@ -4886,27 +4927,29 @@ class DurableDraftQueue {
|
|
|
4886
4927
|
};
|
|
4887
4928
|
}
|
|
4888
4929
|
async actionCompleted(action) {
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
|
|
4930
|
+
return this.workerPool.push(async () => {
|
|
4931
|
+
const handler = this.getHandler(action.handler);
|
|
4932
|
+
let queue = await this.getQueueActions();
|
|
4933
|
+
const queueOperations = handler.getQueueOperationsForCompletingDrafts(queue, action);
|
|
4934
|
+
const idAndKeyMappings = handler.getRedirectMappings(action);
|
|
4935
|
+
const keyMappings = idAndKeyMappings === undefined
|
|
4936
|
+
? undefined
|
|
4937
|
+
: idAndKeyMappings.map((m) => {
|
|
4938
|
+
return { draftKey: m.draftKey, canonicalKey: m.canonicalKey };
|
|
4939
|
+
});
|
|
4940
|
+
await this.draftStore.completeAction(queueOperations, keyMappings);
|
|
4941
|
+
queue = await this.getQueueActions();
|
|
4942
|
+
this.retryIntervalMilliseconds = 0;
|
|
4943
|
+
this.uploadingActionId = undefined;
|
|
4944
|
+
await handler.handleActionCompleted(action, queueOperations, queue, values$1(this.handlers));
|
|
4945
|
+
await this.notifyChangedListeners({
|
|
4946
|
+
type: DraftQueueEventType.ActionCompleted,
|
|
4947
|
+
action,
|
|
4897
4948
|
});
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
this.uploadingActionId = undefined;
|
|
4902
|
-
await handler.handleActionCompleted(action, queueOperations, queue, values$1(this.handlers));
|
|
4903
|
-
await this.notifyChangedListeners({
|
|
4904
|
-
type: DraftQueueEventType.ActionCompleted,
|
|
4905
|
-
action,
|
|
4949
|
+
if (this.state === DraftQueueState.Started) {
|
|
4950
|
+
this.processNextAction();
|
|
4951
|
+
}
|
|
4906
4952
|
});
|
|
4907
|
-
if (this.state === DraftQueueState.Started) {
|
|
4908
|
-
this.processNextAction();
|
|
4909
|
-
}
|
|
4910
4953
|
}
|
|
4911
4954
|
async actionFailed(action, retry) {
|
|
4912
4955
|
this.uploadingActionId = undefined;
|
|
@@ -5356,6 +5399,13 @@ class AbstractResourceRequestActionHandler {
|
|
|
5356
5399
|
this.draftQueue = draftQueue;
|
|
5357
5400
|
this.networkAdapter = networkAdapter;
|
|
5358
5401
|
this.getLuvio = getLuvio;
|
|
5402
|
+
// NOTE[W-12567340]: This property stores in-memory mappings between draft
|
|
5403
|
+
// ids and canonical ids for the current session. Having a local copy of
|
|
5404
|
+
// these mappings is necessary to avoid a race condition between publishing
|
|
5405
|
+
// new mappings to the durable store and those mappings being loaded into
|
|
5406
|
+
// the luvio store redirect table, during which a new draft might be enqueued
|
|
5407
|
+
// which would not see a necessary mapping.
|
|
5408
|
+
this.ephemeralRedirects = {};
|
|
5359
5409
|
}
|
|
5360
5410
|
enqueue(data) {
|
|
5361
5411
|
return this.draftQueue.enqueue(this.handlerId, data);
|
|
@@ -5423,7 +5473,8 @@ class AbstractResourceRequestActionHandler {
|
|
|
5423
5473
|
}
|
|
5424
5474
|
getQueueOperationsForCompletingDrafts(queue, action) {
|
|
5425
5475
|
const queueOperations = [];
|
|
5426
|
-
|
|
5476
|
+
const redirects = this.getRedirectMappings(action);
|
|
5477
|
+
if (redirects !== undefined) {
|
|
5427
5478
|
const { length } = queue;
|
|
5428
5479
|
for (let i = 0; i < length; i++) {
|
|
5429
5480
|
const queueAction = queue[i];
|
|
@@ -5433,69 +5484,64 @@ class AbstractResourceRequestActionHandler {
|
|
|
5433
5484
|
continue;
|
|
5434
5485
|
}
|
|
5435
5486
|
if (isResourceRequestAction(queueAction)) {
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
basePath = basePath.replace(draftId, canonicalId);
|
|
5450
|
-
stringifiedBody = stringifiedBody.replace(draftId, canonicalId);
|
|
5451
|
-
queueOperationMutated = true;
|
|
5452
|
-
}
|
|
5453
|
-
// if the action is performed on a previous draft id, we need to replace the action
|
|
5454
|
-
// with a new one at the updated canonical key
|
|
5455
|
-
if (queueActionTag === draftKey) {
|
|
5456
|
-
updatedActionTag = canonicalKey;
|
|
5457
|
-
updatedActionTargetId = canonicalId;
|
|
5458
|
-
}
|
|
5487
|
+
let queueOperationMutated = false;
|
|
5488
|
+
let updatedActionTag = undefined;
|
|
5489
|
+
let updatedActionTargetId = undefined;
|
|
5490
|
+
const { tag: queueActionTag, data: queueActionRequest, id: queueActionId, } = queueAction;
|
|
5491
|
+
let { basePath, body } = queueActionRequest;
|
|
5492
|
+
let stringifiedBody = stringify$4(body);
|
|
5493
|
+
// for each redirected ID/key we loop over the operation to see if it needs
|
|
5494
|
+
// to be updated
|
|
5495
|
+
for (const { draftId, draftKey, canonicalId, canonicalKey } of redirects) {
|
|
5496
|
+
if (basePath.search(draftId) >= 0 || stringifiedBody.search(draftId) >= 0) {
|
|
5497
|
+
basePath = basePath.replace(draftId, canonicalId);
|
|
5498
|
+
stringifiedBody = stringifiedBody.replace(draftId, canonicalId);
|
|
5499
|
+
queueOperationMutated = true;
|
|
5459
5500
|
}
|
|
5460
|
-
if
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
}
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5501
|
+
// if the action is performed on a previous draft id, we need to replace the action
|
|
5502
|
+
// with a new one at the updated canonical key
|
|
5503
|
+
if (queueActionTag === draftKey) {
|
|
5504
|
+
updatedActionTag = canonicalKey;
|
|
5505
|
+
updatedActionTargetId = canonicalId;
|
|
5506
|
+
}
|
|
5507
|
+
}
|
|
5508
|
+
if (queueOperationMutated) {
|
|
5509
|
+
if (updatedActionTag !== undefined && updatedActionTargetId !== undefined) {
|
|
5510
|
+
const updatedAction = {
|
|
5511
|
+
...queueAction,
|
|
5512
|
+
tag: updatedActionTag,
|
|
5513
|
+
targetId: updatedActionTargetId,
|
|
5514
|
+
data: {
|
|
5515
|
+
...queueActionRequest,
|
|
5516
|
+
basePath: basePath,
|
|
5517
|
+
body: parse$4(stringifiedBody),
|
|
5518
|
+
},
|
|
5519
|
+
};
|
|
5520
|
+
// item needs to be replaced with a new item at the new record key
|
|
5521
|
+
queueOperations.push({
|
|
5522
|
+
type: QueueOperationType.Delete,
|
|
5523
|
+
id: queueActionId,
|
|
5524
|
+
});
|
|
5525
|
+
queueOperations.push({
|
|
5526
|
+
type: QueueOperationType.Add,
|
|
5527
|
+
action: updatedAction,
|
|
5528
|
+
});
|
|
5529
|
+
}
|
|
5530
|
+
else {
|
|
5531
|
+
const updatedAction = {
|
|
5532
|
+
...queueAction,
|
|
5533
|
+
data: {
|
|
5534
|
+
...queueActionRequest,
|
|
5535
|
+
basePath: basePath,
|
|
5536
|
+
body: parse$4(stringifiedBody),
|
|
5537
|
+
},
|
|
5538
|
+
};
|
|
5539
|
+
// item needs to be updated
|
|
5540
|
+
queueOperations.push({
|
|
5541
|
+
type: QueueOperationType.Update,
|
|
5542
|
+
id: queueActionId,
|
|
5543
|
+
action: updatedAction,
|
|
5544
|
+
});
|
|
5499
5545
|
}
|
|
5500
5546
|
}
|
|
5501
5547
|
}
|
|
@@ -5515,6 +5561,9 @@ class AbstractResourceRequestActionHandler {
|
|
|
5515
5561
|
const body = action.response.body;
|
|
5516
5562
|
const canonicalId = this.getIdFromResponseBody(body);
|
|
5517
5563
|
const draftId = action.targetId;
|
|
5564
|
+
if (draftId !== undefined && canonicalId !== undefined && draftId !== canonicalId) {
|
|
5565
|
+
this.ephemeralRedirects[draftId] = canonicalId;
|
|
5566
|
+
}
|
|
5518
5567
|
return [
|
|
5519
5568
|
{
|
|
5520
5569
|
draftId,
|
|
@@ -11296,12 +11345,18 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
|
|
|
11296
11345
|
const fieldName = fieldNames[i];
|
|
11297
11346
|
const fieldValue = bodyFields[fieldName];
|
|
11298
11347
|
if (typeof fieldValue === 'string' && this.isDraftId(fieldValue)) {
|
|
11299
|
-
const
|
|
11300
|
-
|
|
11301
|
-
|
|
11302
|
-
|
|
11303
|
-
|
|
11304
|
-
|
|
11348
|
+
const canonicalId = this.ephemeralRedirects[fieldValue];
|
|
11349
|
+
if (canonicalId !== undefined) {
|
|
11350
|
+
bodyFields[fieldName] = canonicalId;
|
|
11351
|
+
}
|
|
11352
|
+
else {
|
|
11353
|
+
const draftKey = this.buildTagForTargetId(fieldValue);
|
|
11354
|
+
const canonicalKey = this.getLuvio().storeGetCanonicalKey(draftKey);
|
|
11355
|
+
if (draftKey !== canonicalKey) {
|
|
11356
|
+
const canonicalId = extractRecordIdFromStoreKey(canonicalKey);
|
|
11357
|
+
if (canonicalId !== undefined) {
|
|
11358
|
+
bodyFields[fieldName] = canonicalId;
|
|
11359
|
+
}
|
|
11305
11360
|
}
|
|
11306
11361
|
}
|
|
11307
11362
|
}
|
|
@@ -11309,17 +11364,24 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
|
|
|
11309
11364
|
}
|
|
11310
11365
|
if (request.method === 'patch' || request.method === 'delete') {
|
|
11311
11366
|
const recordId = request.urlParams['recordId'];
|
|
11312
|
-
const
|
|
11313
|
-
|
|
11314
|
-
if (recordKey !== canonicalKey) {
|
|
11315
|
-
const canonicalId = extractRecordIdFromStoreKey(canonicalKey);
|
|
11316
|
-
if (canonicalId === undefined) {
|
|
11317
|
-
// could not resolve id from request -- return the request un-modified
|
|
11318
|
-
return request;
|
|
11319
|
-
}
|
|
11367
|
+
const canonicalId = this.ephemeralRedirects[recordId];
|
|
11368
|
+
if (canonicalId !== undefined) {
|
|
11320
11369
|
resolvedBasePath = resolvedBasePath.replace(recordId, canonicalId);
|
|
11321
11370
|
resolvedUrlParams = { ...resolvedUrlParams, recordId: canonicalId };
|
|
11322
11371
|
}
|
|
11372
|
+
else {
|
|
11373
|
+
const recordKey = this.buildTagForTargetId(recordId);
|
|
11374
|
+
const canonicalKey = this.getLuvio().storeGetCanonicalKey(recordKey);
|
|
11375
|
+
if (recordKey !== canonicalKey) {
|
|
11376
|
+
const canonicalId = extractRecordIdFromStoreKey(canonicalKey);
|
|
11377
|
+
if (canonicalId === undefined) {
|
|
11378
|
+
// could not resolve id from request -- return the request un-modified
|
|
11379
|
+
return request;
|
|
11380
|
+
}
|
|
11381
|
+
resolvedBasePath = resolvedBasePath.replace(recordId, canonicalId);
|
|
11382
|
+
resolvedUrlParams = { ...resolvedUrlParams, recordId: canonicalId };
|
|
11383
|
+
}
|
|
11384
|
+
}
|
|
11323
11385
|
}
|
|
11324
11386
|
return {
|
|
11325
11387
|
...request,
|
|
@@ -14667,34 +14729,6 @@ function setupInspection(luvio) {
|
|
|
14667
14729
|
* For full license text, see the LICENSE.txt file
|
|
14668
14730
|
*/
|
|
14669
14731
|
|
|
14670
|
-
class AsyncWorkerPool {
|
|
14671
|
-
constructor(concurrency) {
|
|
14672
|
-
this.queue = [];
|
|
14673
|
-
this.activeWorkers = 0;
|
|
14674
|
-
this.concurrency = concurrency;
|
|
14675
|
-
}
|
|
14676
|
-
push(workFn) {
|
|
14677
|
-
this.queue.push(workFn);
|
|
14678
|
-
this.work();
|
|
14679
|
-
}
|
|
14680
|
-
cancel() {
|
|
14681
|
-
this.queue = [];
|
|
14682
|
-
// TODO [W-12513105]: thread cancellation through to active workers
|
|
14683
|
-
}
|
|
14684
|
-
work() {
|
|
14685
|
-
while (this.queue.length > 0 && this.activeWorkers < this.concurrency) {
|
|
14686
|
-
this.activeWorkers += 1;
|
|
14687
|
-
const next = this.queue.shift();
|
|
14688
|
-
if (next) {
|
|
14689
|
-
next().finally(() => {
|
|
14690
|
-
this.activeWorkers -= 1;
|
|
14691
|
-
this.work();
|
|
14692
|
-
});
|
|
14693
|
-
}
|
|
14694
|
-
}
|
|
14695
|
-
}
|
|
14696
|
-
}
|
|
14697
|
-
|
|
14698
14732
|
class EventEmitter {
|
|
14699
14733
|
constructor() {
|
|
14700
14734
|
// @ts-ignore typescript doesn't like us setting this to an empty object for some reason
|
|
@@ -15247,4 +15281,4 @@ register({
|
|
|
15247
15281
|
});
|
|
15248
15282
|
|
|
15249
15283
|
export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
|
|
15250
|
-
// version: 1.100.
|
|
15284
|
+
// version: 1.100.4-ce1be23b7
|