@salesforce/lds-ads-bridge 1.431.0 → 1.433.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.
@@ -483,7 +483,7 @@ const callbacks$1 = [];
483
483
  function register(r) {
484
484
  callbacks$1.forEach((callback) => callback(r));
485
485
  }
486
- // version: 1.431.0-0cb7677555
486
+ // version: 1.433.0-8a15a98f24
487
487
 
488
488
  /**
489
489
  * Returns true if the value acts like a Promise, i.e. has a "then" function,
@@ -7000,7 +7000,7 @@ function getResponseCacheKeys$17(storeKeyMap, luvio, resourceParams, response) {
7000
7000
  function createResourceRequest$1g(config) {
7001
7001
  const headers = {};
7002
7002
  return {
7003
- baseUri: '/services/data/v67.0',
7003
+ baseUri: '/services/data/v68.0',
7004
7004
  basePath: '/ui-api/records/' + config.urlParams.recordId + '',
7005
7005
  method: 'get',
7006
7006
  body: null,
@@ -7377,7 +7377,7 @@ function ingestError$Q(luvio, params, error, snapshotRefresh) {
7377
7377
  function createResourceRequest$1f(config) {
7378
7378
  const headers = {};
7379
7379
  return {
7380
- baseUri: '/services/data/v67.0',
7380
+ baseUri: '/services/data/v68.0',
7381
7381
  basePath: '/ui-api/records/batch/' + config.urlParams.recordIds + '',
7382
7382
  method: 'get',
7383
7383
  body: null,
@@ -7900,6 +7900,9 @@ function isSpanningRecord(fieldValue) {
7900
7900
  function isStoreKeyRecordId(key) {
7901
7901
  return key.indexOf(RECORD_ID_PREFIX) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION) === -1;
7902
7902
  }
7903
+ function isStoreKeyRecordField(key) {
7904
+ return key.indexOf(RECORD_ID_PREFIX) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION) > -1;
7905
+ }
7903
7906
  /**
7904
7907
  * Returns a shallow copy of a record with its field values if it is a scalar and a reference and a
7905
7908
  * a RecordRepresentation with no field if the value if a spanning record.
@@ -8194,6 +8197,33 @@ class AdsBridge {
8194
8197
  this.isRecordEmitLocked = false;
8195
8198
  }
8196
8199
  }
8200
+ filterAndSynthesizeBaseIds(updatedEntries) {
8201
+ // Collect base record IDs that are directly present in the entries.
8202
+ const directBaseIds = new Set();
8203
+ for (let i = 0; i < updatedEntries.length; i++) {
8204
+ if (isStoreKeyRecordId(updatedEntries[i].id)) {
8205
+ directBaseIds.add(updatedEntries[i].id);
8206
+ }
8207
+ }
8208
+ // For field entries whose base record ID has no direct entry, synthesize one.
8209
+ const syntheticBaseIds = new Set();
8210
+ for (let i = 0; i < updatedEntries.length; i++) {
8211
+ if (isStoreKeyRecordField(updatedEntries[i].id)) {
8212
+ const baseId = updatedEntries[i].id.split(RECORD_FIELDS_KEY_JUNCTION)[0];
8213
+ if (!directBaseIds.has(baseId)) {
8214
+ syntheticBaseIds.add(baseId);
8215
+ }
8216
+ }
8217
+ }
8218
+ // Exclude all the store record ids not matching with the record id pattern.
8219
+ // Note: FieldValueRepresentation have the same prefix than RecordRepresentation so we
8220
+ // need to filter them out.
8221
+ const filteredUpdatedEntries = updatedEntries.filter((entry) => isStoreKeyRecordId(entry.id));
8222
+ syntheticBaseIds.forEach((baseId) => {
8223
+ push.call(filteredUpdatedEntries, { id: baseId });
8224
+ });
8225
+ return filteredUpdatedEntries;
8226
+ }
8197
8227
  /**
8198
8228
  * This method retrieves queries the store with with passed record ids to retrieve their
8199
8229
  * associated records and object info. Note that the passed ids are not Salesforce record id
@@ -8204,14 +8234,11 @@ class AdsBridge {
8204
8234
  let shouldEmit = false;
8205
8235
  const adsRecordMap = {};
8206
8236
  const adsObjectMap = {};
8207
- for (let i = 0; i < updatedEntries.length; i++) {
8208
- const storeRecordId = updatedEntries[i].id;
8209
- // Exclude all the store record ids not matching with the record id pattern.
8210
- // Note: FieldValueRepresentation have the same prefix than RecordRepresentation so we
8211
- // need to filter them out.
8212
- if (!isStoreKeyRecordId(storeRecordId)) {
8213
- continue;
8214
- }
8237
+ // W-21715343
8238
+ // Context for change: https://docs.google.com/document/d/1iF6M9jldEX_K9FOpdttLqVwO9uESUUrlyWi2mWnXtAQ/edit?usp=sharing
8239
+ const filteredUpdatedEntries = this.filterAndSynthesizeBaseIds(updatedEntries);
8240
+ for (let i = 0; i < filteredUpdatedEntries.length; i++) {
8241
+ const storeRecordId = filteredUpdatedEntries[i].id;
8215
8242
  const record = this.recordRepresentationIngestOverride !== undefined
8216
8243
  ? getShallowRecordDenormalized(luvio, storeRecordId)
8217
8244
  : getShallowRecord(luvio, storeRecordId);
package/dist/adsBridge.js CHANGED
@@ -58,6 +58,9 @@ function isSpanningRecord(fieldValue) {
58
58
  function isStoreKeyRecordId(key) {
59
59
  return key.indexOf(RECORD_ID_PREFIX) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION) === -1;
60
60
  }
61
+ function isStoreKeyRecordField(key) {
62
+ return key.indexOf(RECORD_ID_PREFIX) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION) > -1;
63
+ }
61
64
  /**
62
65
  * Returns a shallow copy of a record with its field values if it is a scalar and a reference and a
63
66
  * a RecordRepresentation with no field if the value if a spanning record.
@@ -356,6 +359,33 @@ class AdsBridge {
356
359
  this.isRecordEmitLocked = false;
357
360
  }
358
361
  }
362
+ filterAndSynthesizeBaseIds(updatedEntries) {
363
+ // Collect base record IDs that are directly present in the entries.
364
+ const directBaseIds = new Set();
365
+ for (let i = 0; i < updatedEntries.length; i++) {
366
+ if (isStoreKeyRecordId(updatedEntries[i].id)) {
367
+ directBaseIds.add(updatedEntries[i].id);
368
+ }
369
+ }
370
+ // For field entries whose base record ID has no direct entry, synthesize one.
371
+ const syntheticBaseIds = new Set();
372
+ for (let i = 0; i < updatedEntries.length; i++) {
373
+ if (isStoreKeyRecordField(updatedEntries[i].id)) {
374
+ const baseId = updatedEntries[i].id.split(RECORD_FIELDS_KEY_JUNCTION)[0];
375
+ if (!directBaseIds.has(baseId)) {
376
+ syntheticBaseIds.add(baseId);
377
+ }
378
+ }
379
+ }
380
+ // Exclude all the store record ids not matching with the record id pattern.
381
+ // Note: FieldValueRepresentation have the same prefix than RecordRepresentation so we
382
+ // need to filter them out.
383
+ const filteredUpdatedEntries = updatedEntries.filter((entry) => isStoreKeyRecordId(entry.id));
384
+ syntheticBaseIds.forEach((baseId) => {
385
+ push.call(filteredUpdatedEntries, { id: baseId });
386
+ });
387
+ return filteredUpdatedEntries;
388
+ }
359
389
  /**
360
390
  * This method retrieves queries the store with with passed record ids to retrieve their
361
391
  * associated records and object info. Note that the passed ids are not Salesforce record id
@@ -367,14 +397,11 @@ class AdsBridge {
367
397
  let shouldEmit = false;
368
398
  const adsRecordMap = {};
369
399
  const adsObjectMap = {};
370
- for (let i = 0; i < updatedEntries.length; i++) {
371
- const storeRecordId = updatedEntries[i].id;
372
- // Exclude all the store record ids not matching with the record id pattern.
373
- // Note: FieldValueRepresentation have the same prefix than RecordRepresentation so we
374
- // need to filter them out.
375
- if (!isStoreKeyRecordId(storeRecordId)) {
376
- continue;
377
- }
400
+ // W-21715343
401
+ // Context for change: https://docs.google.com/document/d/1iF6M9jldEX_K9FOpdttLqVwO9uESUUrlyWi2mWnXtAQ/edit?usp=sharing
402
+ const filteredUpdatedEntries = this.filterAndSynthesizeBaseIds(updatedEntries);
403
+ for (let i = 0; i < filteredUpdatedEntries.length; i++) {
404
+ const storeRecordId = filteredUpdatedEntries[i].id;
378
405
  const record = this.recordRepresentationIngestOverride !== undefined
379
406
  ? getShallowRecordDenormalized(luvio, storeRecordId)
380
407
  : getShallowRecord(luvio, storeRecordId);
@@ -435,4 +462,4 @@ function withAdsBridge(callback) {
435
462
  }
436
463
 
437
464
  export { instrument, withAdsBridge };
438
- // version: 1.431.0-0cb7677555
465
+ // version: 1.433.0-8a15a98f24
@@ -78,6 +78,7 @@ export default class AdsBridge {
78
78
  * mutations triggered by ADS to be emit back to ADS.
79
79
  */
80
80
  private lockLdsRecordEmit;
81
+ private filterAndSynthesizeBaseIds;
81
82
  /**
82
83
  * This method retrieves queries the store with with passed record ids to retrieve their
83
84
  * associated records and object info. Note that the passed ids are not Salesforce record id
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/lds-ads-bridge",
3
- "version": "1.431.0",
3
+ "version": "1.433.0",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "description": "Bridge to sync data between LDS and ADS",
6
6
  "main": "dist/adsBridge.js",
@@ -30,9 +30,9 @@
30
30
  "release:corejar": "yarn build && ../core-build/scripts/core.js --name=lds-ads-bridge"
31
31
  },
32
32
  "devDependencies": {
33
- "@salesforce/lds-adapters-uiapi": "^1.431.0",
34
- "@salesforce/lds-runtime-mobile": "^1.431.0",
35
- "@salesforce/lds-uiapi-record-utils-mobile": "^1.431.0"
33
+ "@salesforce/lds-adapters-uiapi": "^1.433.0",
34
+ "@salesforce/lds-runtime-mobile": "^1.433.0",
35
+ "@salesforce/lds-uiapi-record-utils-mobile": "^1.433.0"
36
36
  },
37
37
  "volta": {
38
38
  "extends": "../../package.json"
@@ -41,9 +41,9 @@
41
41
  {
42
42
  "path": "./dist/adsBridge.js",
43
43
  "maxSize": {
44
- "none": "17 kB",
45
- "min": "5.51 kB",
46
- "compressed": "4 kB"
44
+ "none": "18.4 kB",
45
+ "min": "6 kB",
46
+ "compressed": "4.3 kB"
47
47
  }
48
48
  }
49
49
  ]
@@ -1,5 +1,10 @@
1
1
  import { Luvio, InMemoryStore, Environment } from '@luvio/engine';
2
- import { keyBuilderRecord, ingestRecord, type Registration } from '@salesforce/lds-adapters-uiapi';
2
+ import {
3
+ keyBuilderRecord,
4
+ ingestRecord,
5
+ type Registration,
6
+ ingestRecordSuccess,
7
+ } from '@salesforce/lds-adapters-uiapi';
3
8
  import { expect } from '@jest/globals';
4
9
 
5
10
  import AdsBridge from '../ads-bridge';
@@ -417,6 +422,159 @@ describe('AdsBridge', () => {
417
422
  });
418
423
  });
419
424
 
425
+ // W-21715343
426
+ // Context for change: https://docs.google.com/document/d/1iF6M9jldEX_K9FOpdttLqVwO9uESUUrlyWi2mWnXtAQ/edit?usp=sharing
427
+ it('correctly emits the updated Case record to ADS when refreshSnapshot is called, and the Case record was updated via spanning record updates on the Task record', async () => {
428
+ const initialLdsState = JSON.parse(JSON.stringify(require('./initial_record.json')));
429
+ const addRecordsGet = JSON.parse(JSON.stringify(require('./task_record_gvp_get.json')));
430
+ const addRecordsSave = JSON.parse(
431
+ JSON.stringify(require('./task_record_gvp_save.json'))
432
+ );
433
+ const addRecordsGet2 = JSON.parse(
434
+ JSON.stringify(require('./task_record_gvp_get2.json'))
435
+ );
436
+
437
+ const { bridge, luvio } = createBridge();
438
+ const caseId: string = initialLdsState.id;
439
+
440
+ const selector = {
441
+ recordId: keyBuilderRecord(luvio, { recordId: caseId }),
442
+ node: { kind: 'Fragment' as const, private: [] as string[] },
443
+ variables: {},
444
+ };
445
+
446
+ // Creating a refreshable snapshot of the Case record as we don't have the wire adapter bindings available to us in jest environment to refresh the snapshot manually.
447
+ const snapshot = luvio.storeLookup(selector, {
448
+ config: { recordId: caseId },
449
+ resolve: async () => {
450
+ const response = await luvio.dispatchResourceRequest({
451
+ baseUri: '',
452
+ basePath: `/ui-api/records/${caseId}`,
453
+ method: 'get',
454
+ body: null,
455
+ queryParams: {},
456
+ urlParams: {},
457
+ headers: {},
458
+ priority: 'normal',
459
+ });
460
+ const config = {
461
+ optionalFields: ['Case.Id'],
462
+ recordId: caseId,
463
+ };
464
+ const trackedFields = ['Case.Status'];
465
+ ingestRecordSuccess(luvio, config, caseId, trackedFields, response as any, 0);
466
+ await luvio.storeBroadcast();
467
+ return luvio.storeLookup(selector);
468
+ },
469
+ });
470
+
471
+ // 1. Prime LDS with the Case fixture (via addRecord → storeIngest + storeBroadcast).
472
+ addRecord(luvio, initialLdsState);
473
+
474
+ const expectedStatus = queryRecord(luvio, { recordId: caseId }).data.fields.Status;
475
+ expect(expectedStatus).toEqual({ value: 'New', displayValue: 'New' });
476
+
477
+ luvio.dispatchResourceRequest = jest.fn();
478
+
479
+ const fn = jest.fn();
480
+ bridge.receiveFromLdsCallback = fn;
481
+
482
+ // 2. Ingest the Task (+ spanning Case__r) via addRecords().
483
+ bridge.addRecords(addRecordsGet); // A RecordGvp.getRecord call is made to get the initial Task record when switching from the Case record to the Task record in console mode.
484
+ bridge.addRecords(addRecordsSave); // Clicking the complete button on the Task record which does a RecordGvp.saveRecord call.
485
+ bridge.addRecords(addRecordsGet2); // A RecordGvp.getRecord call is made to get the updated Task record.
486
+
487
+ expect(luvio.dispatchResourceRequest).toHaveBeenCalledTimes(0);
488
+
489
+ // 3. Synthesize the closed Case record server response which is expected to be received when the refreshSnapshot is called.
490
+ const closedCaseResponse = JSON.parse(JSON.stringify(require('./initial_record.json')));
491
+ closedCaseResponse.fields.Status = { value: 'Closed', displayValue: 'Closed' };
492
+ closedCaseResponse.weakEtag = addRecordsGet2[0].weakEtag;
493
+ closedCaseResponse.systemModstamp = addRecordsGet2[0].systemModstamp;
494
+ closedCaseResponse.lastModifiedDate = addRecordsGet2[0].lastModifiedDate;
495
+
496
+ luvio.dispatchResourceRequest = jest
497
+ .fn()
498
+ .mockResolvedValueOnce({ body: closedCaseResponse })
499
+ .mockImplementation(() => new Promise(() => {}));
500
+
501
+ // 4. Refresh the snapshot to get the updated Case record. This was previously not working because the interactions on the ADS-Bridge had updated the Case record with the latest weakEtag, but NOT the updated Status field value.
502
+ const refreshedSnapshot = await luvio.refreshSnapshot(snapshot);
503
+ expect((refreshedSnapshot.data as any).fields.Status).toEqual(
504
+ expect.objectContaining({ value: 'Closed' })
505
+ );
506
+
507
+ // 5. With the ADS-Bridge changes, the Case record is now emitted when the refreshSnapshot is called.
508
+ expect(fn.mock.calls[0]).toMatchInlineSnapshot(`
509
+ Array [
510
+ Object {
511
+ "500xx000000boDJAAY": Object {
512
+ "Case": Object {
513
+ "isPrimary": true,
514
+ "record": Object {
515
+ "apiName": "Case",
516
+ "childRelationships": Object {},
517
+ "eTag": "",
518
+ "fields": Object {
519
+ "CaseNumber": Object {
520
+ "displayValue": null,
521
+ "value": "00001026",
522
+ },
523
+ "Id": Object {
524
+ "displayValue": null,
525
+ "value": "500xx000000boDJAAY",
526
+ },
527
+ "IsEscalated": Object {
528
+ "displayValue": null,
529
+ "value": false,
530
+ },
531
+ "MasterRecordId": Object {
532
+ "displayValue": null,
533
+ "value": null,
534
+ },
535
+ "Priority": Object {
536
+ "displayValue": "Medium",
537
+ "value": "Medium",
538
+ },
539
+ "RecordTypeId": Object {
540
+ "displayValue": null,
541
+ "value": "012000000000000AAA",
542
+ },
543
+ "Status": Object {
544
+ "displayValue": "Closed",
545
+ "value": "Closed",
546
+ },
547
+ "Subject": Object {
548
+ "displayValue": null,
549
+ "value": "Fixture subject",
550
+ },
551
+ "SystemModstamp": Object {
552
+ "displayValue": null,
553
+ "value": "2026-04-11T00:46:56.000Z",
554
+ },
555
+ },
556
+ "id": "500xx000000boDJAAY",
557
+ "lastModifiedById": "005xx000001X8gHAAS",
558
+ "lastModifiedDate": "2026-04-13T20:54:41.000Z",
559
+ "recordTypeId": "012000000000000AAA",
560
+ "recordTypeInfo": null,
561
+ "systemModstamp": "2026-04-13T20:54:41.000Z",
562
+ "weakEtag": 1776113681000,
563
+ },
564
+ },
565
+ },
566
+ },
567
+ Object {
568
+ "Case": Object {
569
+ "_entityLabel": "Case",
570
+ "_keyPrefix": "500",
571
+ "_nameField": "Name",
572
+ },
573
+ },
574
+ ]
575
+ `);
576
+ });
577
+
420
578
  describe('displayValue', () => {
421
579
  it('does not let null overwrite non-null displayValue', () => {
422
580
  const { bridge, luvio } = createBridge();
@@ -1383,6 +1541,82 @@ describe('AdsBridge', () => {
1383
1541
  });
1384
1542
  });
1385
1543
 
1544
+ describe('filterAndSynthesizeBaseIds', () => {
1545
+ const BASE_KEY = 'UiApi::RecordRepresentation:001xx000000001AAA';
1546
+ const FIELD_KEY = 'UiApi::RecordRepresentation:001xx000000001AAA__fields__Name';
1547
+ const BASE_KEY_2 = 'UiApi::RecordRepresentation:001xx000000002AAA';
1548
+ const FIELD_KEY_2A = 'UiApi::RecordRepresentation:001xx000000002AAA__fields__Name';
1549
+ const FIELD_KEY_2B = 'UiApi::RecordRepresentation:001xx000000002AAA__fields__Id';
1550
+ const NON_RECORD_KEY = 'SomeOther::Thing:abc123';
1551
+
1552
+ function callFilter(bridge: AdsBridge, entries: { id: string }[]): { id: string }[] {
1553
+ return (bridge as any).filterAndSynthesizeBaseIds(entries);
1554
+ }
1555
+
1556
+ it('returns an empty array when given an empty array', () => {
1557
+ const { bridge } = createBridge();
1558
+ expect(callFilter(bridge, [])).toEqual([]);
1559
+ });
1560
+
1561
+ it('filters out non-record entries', () => {
1562
+ const { bridge } = createBridge();
1563
+ const result = callFilter(bridge, [{ id: NON_RECORD_KEY }]);
1564
+ expect(result).toEqual([]);
1565
+ });
1566
+
1567
+ it('returns base record entries unchanged', () => {
1568
+ const { bridge } = createBridge();
1569
+ const result = callFilter(bridge, [{ id: BASE_KEY }]);
1570
+ expect(result).toEqual([{ id: BASE_KEY }]);
1571
+ });
1572
+
1573
+ it('synthesizes a base record entry for a field entry with no direct base entry', () => {
1574
+ const { bridge } = createBridge();
1575
+ const result = callFilter(bridge, [{ id: FIELD_KEY }]);
1576
+ expect(result).toEqual([{ id: BASE_KEY }]);
1577
+ });
1578
+
1579
+ it('does not synthesize a duplicate base entry when a direct base entry is already present', () => {
1580
+ const { bridge } = createBridge();
1581
+ const result = callFilter(bridge, [{ id: BASE_KEY }, { id: FIELD_KEY }]);
1582
+ expect(result).toHaveLength(1);
1583
+ expect(result).toEqual([{ id: BASE_KEY }]);
1584
+ });
1585
+
1586
+ it('synthesizes exactly one base entry for multiple field entries sharing the same base', () => {
1587
+ const { bridge } = createBridge();
1588
+ const result = callFilter(bridge, [{ id: FIELD_KEY_2A }, { id: FIELD_KEY_2B }]);
1589
+ expect(result).toHaveLength(1);
1590
+ expect(result).toEqual([{ id: BASE_KEY_2 }]);
1591
+ });
1592
+
1593
+ it('returns base entries and synthesizes entries for fields whose base is not directly present', () => {
1594
+ const { bridge } = createBridge();
1595
+ const entries = [
1596
+ { id: BASE_KEY },
1597
+ { id: FIELD_KEY },
1598
+ { id: FIELD_KEY_2A },
1599
+ { id: FIELD_KEY_2B },
1600
+ ];
1601
+ const result = callFilter(bridge, entries);
1602
+ expect(result).toHaveLength(2);
1603
+ expect(result).toContainEqual({ id: BASE_KEY });
1604
+ expect(result).toContainEqual({ id: BASE_KEY_2 });
1605
+ });
1606
+
1607
+ it('filters out non-record entries while still processing valid entries', () => {
1608
+ const { bridge } = createBridge();
1609
+ const result = callFilter(bridge, [
1610
+ { id: NON_RECORD_KEY },
1611
+ { id: BASE_KEY },
1612
+ { id: FIELD_KEY_2A },
1613
+ ]);
1614
+ expect(result).toHaveLength(2);
1615
+ expect(result).toContainEqual({ id: BASE_KEY });
1616
+ expect(result).toContainEqual({ id: BASE_KEY_2 });
1617
+ });
1618
+ });
1619
+
1386
1620
  describe('isDMOEntity', () => {
1387
1621
  it('should return true for DMO record', () => {
1388
1622
  const record = createRecord({
@@ -0,0 +1,50 @@
1
+ {
2
+ "apiName": "Case",
3
+ "childRelationships": {},
4
+ "eTag": "",
5
+ "fields": {
6
+ "Id": {
7
+ "displayValue": null,
8
+ "value": "500xx000000boDJAAY"
9
+ },
10
+ "RecordTypeId": {
11
+ "displayValue": null,
12
+ "value": "012000000000000AAA"
13
+ },
14
+ "IsEscalated": {
15
+ "displayValue": null,
16
+ "value": false
17
+ },
18
+ "MasterRecordId": {
19
+ "displayValue": null,
20
+ "value": null
21
+ },
22
+ "SystemModstamp": {
23
+ "displayValue": null,
24
+ "value": "2026-04-11T00:46:56.000Z"
25
+ },
26
+ "CaseNumber": {
27
+ "displayValue": null,
28
+ "value": "00001026"
29
+ },
30
+ "Priority": {
31
+ "displayValue": "Medium",
32
+ "value": "Medium"
33
+ },
34
+ "Status": {
35
+ "displayValue": "New",
36
+ "value": "New"
37
+ },
38
+ "Subject": {
39
+ "displayValue": null,
40
+ "value": "Fixture subject"
41
+ }
42
+ },
43
+ "id": "500xx000000boDJAAY",
44
+ "lastModifiedById": "005xx000001X8gHAAS",
45
+ "lastModifiedDate": "2026-04-13T20:50:18.000Z",
46
+ "recordTypeId": "012000000000000AAA",
47
+ "recordTypeInfo": null,
48
+ "systemModstamp": "2026-04-13T20:50:18.000Z",
49
+ "weakEtag": 1776113418000
50
+ }
@@ -0,0 +1,233 @@
1
+ [
2
+ {
3
+ "apiName": "Task",
4
+ "childRelationships": {},
5
+ "eTag": "2d24f5c26414c4f90731ba59a83c8d71",
6
+ "fields": {
7
+ "ActivityDate": {
8
+ "displayValue": null,
9
+ "value": null
10
+ },
11
+ "Case__c": {
12
+ "displayValue": null,
13
+ "value": "500xx000000boDJAAY"
14
+ },
15
+ "Case__r": {
16
+ "displayValue": "00001027",
17
+ "value": {
18
+ "apiName": "Case",
19
+ "childRelationships": {},
20
+ "eTag": "f9130f3feb968a9bb7e0c222a78ef1dc",
21
+ "fields": {
22
+ "CaseNumber": {
23
+ "displayValue": null,
24
+ "value": "00001027"
25
+ },
26
+ "Id": {
27
+ "displayValue": null,
28
+ "value": "500xx000000boDJAAY"
29
+ }
30
+ },
31
+ "id": "500xx000000boDJAAY",
32
+ "lastModifiedById": "005xx000001X8gHAAS",
33
+ "lastModifiedDate": "2026-04-13T20:50:18.000Z",
34
+ "recordTypeId": "012000000000000AAA",
35
+ "recordTypeInfo": null,
36
+ "systemModstamp": "2026-04-13T20:50:18.000Z",
37
+ "weakEtag": 1776113418000
38
+ }
39
+ },
40
+ "CreatedBy": {
41
+ "displayValue": "Ethan Chan",
42
+ "value": {
43
+ "apiName": "User",
44
+ "childRelationships": {},
45
+ "eTag": "2ca65e8b3117284d9253195c82c5f03d",
46
+ "fields": {
47
+ "FirstName": {
48
+ "displayValue": null,
49
+ "value": "Ethan"
50
+ },
51
+ "Id": {
52
+ "displayValue": null,
53
+ "value": "005xx000001X8gHAAS"
54
+ },
55
+ "LastName": {
56
+ "displayValue": null,
57
+ "value": "Chan"
58
+ },
59
+ "Name": {
60
+ "displayValue": null,
61
+ "value": "Ethan Chan"
62
+ }
63
+ },
64
+ "id": "005xx000001X8gHAAS",
65
+ "lastModifiedById": "005xx000001X8gHAAS",
66
+ "lastModifiedDate": "2026-04-13T19:07:57.000Z",
67
+ "recordTypeId": null,
68
+ "recordTypeInfo": null,
69
+ "systemModstamp": "2026-04-13T19:07:57.000Z",
70
+ "weakEtag": 1776107277000
71
+ }
72
+ },
73
+ "CreatedById": {
74
+ "displayValue": null,
75
+ "value": "005xx000001X8gHAAS"
76
+ },
77
+ "CreatedDate": {
78
+ "displayValue": "4/13/2026, 12:09 PM",
79
+ "value": "2026-04-13T19:09:48.000Z"
80
+ },
81
+ "Description": {
82
+ "displayValue": null,
83
+ "value": null
84
+ },
85
+ "Id": {
86
+ "displayValue": null,
87
+ "value": "00Txx000003rIcmEAE"
88
+ },
89
+ "IsClosed": {
90
+ "displayValue": null,
91
+ "value": false
92
+ },
93
+ "LastModifiedBy": {
94
+ "displayValue": "Ethan Chan",
95
+ "value": {
96
+ "apiName": "User",
97
+ "childRelationships": {},
98
+ "eTag": "2ca65e8b3117284d9253195c82c5f03d",
99
+ "fields": {
100
+ "FirstName": {
101
+ "displayValue": null,
102
+ "value": "Ethan"
103
+ },
104
+ "Id": {
105
+ "displayValue": null,
106
+ "value": "005xx000001X8gHAAS"
107
+ },
108
+ "LastName": {
109
+ "displayValue": null,
110
+ "value": "Chan"
111
+ },
112
+ "Name": {
113
+ "displayValue": null,
114
+ "value": "Ethan Chan"
115
+ }
116
+ },
117
+ "id": "005xx000001X8gHAAS",
118
+ "lastModifiedById": "005xx000001X8gHAAS",
119
+ "lastModifiedDate": "2026-04-13T19:07:57.000Z",
120
+ "recordTypeId": null,
121
+ "recordTypeInfo": null,
122
+ "systemModstamp": "2026-04-13T19:07:57.000Z",
123
+ "weakEtag": 1776107277000
124
+ }
125
+ },
126
+ "LastModifiedById": {
127
+ "displayValue": null,
128
+ "value": "005xx000001X8gHAAS"
129
+ },
130
+ "LastModifiedDate": {
131
+ "displayValue": "4/13/2026, 1:50 PM",
132
+ "value": "2026-04-13T20:50:05.000Z"
133
+ },
134
+ "Owner": {
135
+ "displayValue": "Ethan Chan",
136
+ "value": {
137
+ "apiName": "Name",
138
+ "childRelationships": {},
139
+ "eTag": "202a115a07830e8af0343368d4d309d4",
140
+ "fields": {
141
+ "FirstName": {
142
+ "displayValue": null,
143
+ "value": "Ethan"
144
+ },
145
+ "Id": {
146
+ "displayValue": null,
147
+ "value": "005xx000001X8gHAAS"
148
+ },
149
+ "LastName": {
150
+ "displayValue": null,
151
+ "value": "Chan"
152
+ },
153
+ "Name": {
154
+ "displayValue": null,
155
+ "value": "Ethan Chan"
156
+ }
157
+ },
158
+ "id": "005xx000001X8gHAAS",
159
+ "lastModifiedById": null,
160
+ "lastModifiedDate": null,
161
+ "recordTypeId": null,
162
+ "recordTypeInfo": null,
163
+ "systemModstamp": null,
164
+ "weakEtag": 0
165
+ }
166
+ },
167
+ "OwnerId": {
168
+ "displayValue": null,
169
+ "value": "005xx000001X8gHAAS"
170
+ },
171
+ "Priority": {
172
+ "displayValue": "High",
173
+ "value": "High"
174
+ },
175
+ "Status": {
176
+ "displayValue": "Not Started",
177
+ "value": "Not Started"
178
+ },
179
+ "Subject": {
180
+ "displayValue": null,
181
+ "value": "Call"
182
+ },
183
+ "SystemModstamp": {
184
+ "displayValue": "4/13/2026, 1:50 PM",
185
+ "value": "2026-04-13T20:50:05.000Z"
186
+ },
187
+ "What": {
188
+ "displayValue": "00001027",
189
+ "value": {
190
+ "apiName": "Name",
191
+ "childRelationships": {},
192
+ "eTag": "deffd76450e8f3c8fc116a1cb6a0bb6b",
193
+ "fields": {
194
+ "Id": {
195
+ "displayValue": null,
196
+ "value": "500xx000000boDJAAY"
197
+ },
198
+ "Name": {
199
+ "displayValue": null,
200
+ "value": "00001027"
201
+ }
202
+ },
203
+ "id": "500xx000000boDJAAY",
204
+ "lastModifiedById": null,
205
+ "lastModifiedDate": null,
206
+ "recordTypeId": null,
207
+ "recordTypeInfo": null,
208
+ "systemModstamp": null,
209
+ "weakEtag": 0
210
+ }
211
+ },
212
+ "WhatId": {
213
+ "displayValue": null,
214
+ "value": "500xx000000boDJAAY"
215
+ },
216
+ "Who": {
217
+ "displayValue": null,
218
+ "value": null
219
+ },
220
+ "WhoId": {
221
+ "displayValue": null,
222
+ "value": null
223
+ }
224
+ },
225
+ "id": "00Txx000003rIcmEAE",
226
+ "lastModifiedById": "005xx000001X8gHAAS",
227
+ "lastModifiedDate": "2026-04-13T20:50:05.000Z",
228
+ "recordTypeId": "012000000000000AAA",
229
+ "recordTypeInfo": null,
230
+ "systemModstamp": "2026-04-13T20:50:05.000Z",
231
+ "weakEtag": 1776113405000
232
+ }
233
+ ]
@@ -0,0 +1,233 @@
1
+ [
2
+ {
3
+ "apiName": "Task",
4
+ "childRelationships": {},
5
+ "eTag": "49e9f990d8b63da61c32917c3a0ef32b",
6
+ "fields": {
7
+ "ActivityDate": {
8
+ "displayValue": null,
9
+ "value": null
10
+ },
11
+ "Case__c": {
12
+ "displayValue": null,
13
+ "value": "500xx000000boDJAAY"
14
+ },
15
+ "Case__r": {
16
+ "displayValue": "00001027",
17
+ "value": {
18
+ "apiName": "Case",
19
+ "childRelationships": {},
20
+ "eTag": "d1912a07365b1f4f276cc2b60f857107",
21
+ "fields": {
22
+ "CaseNumber": {
23
+ "displayValue": null,
24
+ "value": "00001027"
25
+ },
26
+ "Id": {
27
+ "displayValue": null,
28
+ "value": "500xx000000boDJAAY"
29
+ }
30
+ },
31
+ "id": "500xx000000boDJAAY",
32
+ "lastModifiedById": "005xx000001X8gHAAS",
33
+ "lastModifiedDate": "2026-04-13T20:54:41.000Z",
34
+ "recordTypeId": "012000000000000AAA",
35
+ "recordTypeInfo": null,
36
+ "systemModstamp": "2026-04-13T20:54:41.000Z",
37
+ "weakEtag": 1776113681000
38
+ }
39
+ },
40
+ "CreatedBy": {
41
+ "displayValue": "Ethan Chan",
42
+ "value": {
43
+ "apiName": "User",
44
+ "childRelationships": {},
45
+ "eTag": "2ca65e8b3117284d9253195c82c5f03d",
46
+ "fields": {
47
+ "FirstName": {
48
+ "displayValue": null,
49
+ "value": "Ethan"
50
+ },
51
+ "Id": {
52
+ "displayValue": null,
53
+ "value": "005xx000001X8gHAAS"
54
+ },
55
+ "LastName": {
56
+ "displayValue": null,
57
+ "value": "Chan"
58
+ },
59
+ "Name": {
60
+ "displayValue": null,
61
+ "value": "Ethan Chan"
62
+ }
63
+ },
64
+ "id": "005xx000001X8gHAAS",
65
+ "lastModifiedById": "005xx000001X8gHAAS",
66
+ "lastModifiedDate": "2026-04-13T19:07:57.000Z",
67
+ "recordTypeId": null,
68
+ "recordTypeInfo": null,
69
+ "systemModstamp": "2026-04-13T19:07:57.000Z",
70
+ "weakEtag": 1776107277000
71
+ }
72
+ },
73
+ "CreatedById": {
74
+ "displayValue": null,
75
+ "value": "005xx000001X8gHAAS"
76
+ },
77
+ "CreatedDate": {
78
+ "displayValue": "4/13/2026, 12:09 PM",
79
+ "value": "2026-04-13T19:09:48.000Z"
80
+ },
81
+ "Description": {
82
+ "displayValue": null,
83
+ "value": null
84
+ },
85
+ "Id": {
86
+ "displayValue": null,
87
+ "value": "00Txx000003rIcmEAE"
88
+ },
89
+ "IsClosed": {
90
+ "displayValue": null,
91
+ "value": true
92
+ },
93
+ "LastModifiedBy": {
94
+ "displayValue": "Ethan Chan",
95
+ "value": {
96
+ "apiName": "User",
97
+ "childRelationships": {},
98
+ "eTag": "2ca65e8b3117284d9253195c82c5f03d",
99
+ "fields": {
100
+ "FirstName": {
101
+ "displayValue": null,
102
+ "value": "Ethan"
103
+ },
104
+ "Id": {
105
+ "displayValue": null,
106
+ "value": "005xx000001X8gHAAS"
107
+ },
108
+ "LastName": {
109
+ "displayValue": null,
110
+ "value": "Chan"
111
+ },
112
+ "Name": {
113
+ "displayValue": null,
114
+ "value": "Ethan Chan"
115
+ }
116
+ },
117
+ "id": "005xx000001X8gHAAS",
118
+ "lastModifiedById": "005xx000001X8gHAAS",
119
+ "lastModifiedDate": "2026-04-13T19:07:57.000Z",
120
+ "recordTypeId": null,
121
+ "recordTypeInfo": null,
122
+ "systemModstamp": "2026-04-13T19:07:57.000Z",
123
+ "weakEtag": 1776107277000
124
+ }
125
+ },
126
+ "LastModifiedById": {
127
+ "displayValue": null,
128
+ "value": "005xx000001X8gHAAS"
129
+ },
130
+ "LastModifiedDate": {
131
+ "displayValue": "4/13/2026, 1:54 PM",
132
+ "value": "2026-04-13T20:54:41.000Z"
133
+ },
134
+ "Owner": {
135
+ "displayValue": "Ethan Chan",
136
+ "value": {
137
+ "apiName": "Name",
138
+ "childRelationships": {},
139
+ "eTag": "202a115a07830e8af0343368d4d309d4",
140
+ "fields": {
141
+ "FirstName": {
142
+ "displayValue": null,
143
+ "value": "Ethan"
144
+ },
145
+ "Id": {
146
+ "displayValue": null,
147
+ "value": "005xx000001X8gHAAS"
148
+ },
149
+ "LastName": {
150
+ "displayValue": null,
151
+ "value": "Chan"
152
+ },
153
+ "Name": {
154
+ "displayValue": null,
155
+ "value": "Ethan Chan"
156
+ }
157
+ },
158
+ "id": "005xx000001X8gHAAS",
159
+ "lastModifiedById": null,
160
+ "lastModifiedDate": null,
161
+ "recordTypeId": null,
162
+ "recordTypeInfo": null,
163
+ "systemModstamp": null,
164
+ "weakEtag": 0
165
+ }
166
+ },
167
+ "OwnerId": {
168
+ "displayValue": null,
169
+ "value": "005xx000001X8gHAAS"
170
+ },
171
+ "Priority": {
172
+ "displayValue": "High",
173
+ "value": "High"
174
+ },
175
+ "Status": {
176
+ "displayValue": "Completed",
177
+ "value": "Completed"
178
+ },
179
+ "Subject": {
180
+ "displayValue": null,
181
+ "value": "Call"
182
+ },
183
+ "SystemModstamp": {
184
+ "displayValue": "4/13/2026, 1:54 PM",
185
+ "value": "2026-04-13T20:54:41.000Z"
186
+ },
187
+ "What": {
188
+ "displayValue": "00001027",
189
+ "value": {
190
+ "apiName": "Name",
191
+ "childRelationships": {},
192
+ "eTag": "deffd76450e8f3c8fc116a1cb6a0bb6b",
193
+ "fields": {
194
+ "Id": {
195
+ "displayValue": null,
196
+ "value": "500xx000000boDJAAY"
197
+ },
198
+ "Name": {
199
+ "displayValue": null,
200
+ "value": "00001027"
201
+ }
202
+ },
203
+ "id": "500xx000000boDJAAY",
204
+ "lastModifiedById": null,
205
+ "lastModifiedDate": null,
206
+ "recordTypeId": null,
207
+ "recordTypeInfo": null,
208
+ "systemModstamp": null,
209
+ "weakEtag": 0
210
+ }
211
+ },
212
+ "WhatId": {
213
+ "displayValue": null,
214
+ "value": "500xx000000boDJAAY"
215
+ },
216
+ "Who": {
217
+ "displayValue": null,
218
+ "value": null
219
+ },
220
+ "WhoId": {
221
+ "displayValue": null,
222
+ "value": null
223
+ }
224
+ },
225
+ "id": "00Txx000003rIcmEAE",
226
+ "lastModifiedById": "005xx000001X8gHAAS",
227
+ "lastModifiedDate": "2026-04-13T20:54:41.000Z",
228
+ "recordTypeId": "012000000000000AAA",
229
+ "recordTypeInfo": null,
230
+ "systemModstamp": "2026-04-13T20:54:41.000Z",
231
+ "weakEtag": 1776113681000
232
+ }
233
+ ]
@@ -0,0 +1,233 @@
1
+ [
2
+ {
3
+ "apiName": "Task",
4
+ "childRelationships": {},
5
+ "eTag": "e339e322e2906b92f0faa82d0b0987e2",
6
+ "fields": {
7
+ "ActivityDate": {
8
+ "displayValue": null,
9
+ "value": null
10
+ },
11
+ "Case__c": {
12
+ "displayValue": null,
13
+ "value": "500xx000000boDJAAY"
14
+ },
15
+ "Case__r": {
16
+ "displayValue": "00001027",
17
+ "value": {
18
+ "apiName": "Case",
19
+ "childRelationships": {},
20
+ "eTag": "1e500759421709c0bff030ea20a7485d",
21
+ "fields": {
22
+ "CaseNumber": {
23
+ "displayValue": null,
24
+ "value": "00001027"
25
+ },
26
+ "Id": {
27
+ "displayValue": null,
28
+ "value": "500xx000000boDJAAY"
29
+ }
30
+ },
31
+ "id": "500xx000000boDJAAY",
32
+ "lastModifiedById": null,
33
+ "lastModifiedDate": null,
34
+ "recordTypeId": "012000000000000AAA",
35
+ "recordTypeInfo": null,
36
+ "systemModstamp": null,
37
+ "weakEtag": 0
38
+ }
39
+ },
40
+ "CreatedBy": {
41
+ "displayValue": "Ethan Chan",
42
+ "value": {
43
+ "apiName": "User",
44
+ "childRelationships": {},
45
+ "eTag": "6209fb69d2a4b5c09799b1bd5f93bcca",
46
+ "fields": {
47
+ "FirstName": {
48
+ "displayValue": null,
49
+ "value": "Ethan"
50
+ },
51
+ "Id": {
52
+ "displayValue": null,
53
+ "value": "005xx000001X8gHAAS"
54
+ },
55
+ "LastName": {
56
+ "displayValue": null,
57
+ "value": "Chan"
58
+ },
59
+ "Name": {
60
+ "displayValue": null,
61
+ "value": "Ethan Chan"
62
+ }
63
+ },
64
+ "id": "005xx000001X8gHAAS",
65
+ "lastModifiedById": null,
66
+ "lastModifiedDate": null,
67
+ "recordTypeId": null,
68
+ "recordTypeInfo": null,
69
+ "systemModstamp": null,
70
+ "weakEtag": 0
71
+ }
72
+ },
73
+ "CreatedById": {
74
+ "displayValue": null,
75
+ "value": "005xx000001X8gHAAS"
76
+ },
77
+ "CreatedDate": {
78
+ "displayValue": "4/13/2026, 12:09 PM",
79
+ "value": "2026-04-13T19:09:48.000Z"
80
+ },
81
+ "Description": {
82
+ "displayValue": null,
83
+ "value": null
84
+ },
85
+ "Id": {
86
+ "displayValue": null,
87
+ "value": "00Txx000003rIcmEAE"
88
+ },
89
+ "IsClosed": {
90
+ "displayValue": null,
91
+ "value": true
92
+ },
93
+ "LastModifiedBy": {
94
+ "displayValue": "Ethan Chan",
95
+ "value": {
96
+ "apiName": "User",
97
+ "childRelationships": {},
98
+ "eTag": "6209fb69d2a4b5c09799b1bd5f93bcca",
99
+ "fields": {
100
+ "FirstName": {
101
+ "displayValue": null,
102
+ "value": "Ethan"
103
+ },
104
+ "Id": {
105
+ "displayValue": null,
106
+ "value": "005xx000001X8gHAAS"
107
+ },
108
+ "LastName": {
109
+ "displayValue": null,
110
+ "value": "Chan"
111
+ },
112
+ "Name": {
113
+ "displayValue": null,
114
+ "value": "Ethan Chan"
115
+ }
116
+ },
117
+ "id": "005xx000001X8gHAAS",
118
+ "lastModifiedById": null,
119
+ "lastModifiedDate": null,
120
+ "recordTypeId": null,
121
+ "recordTypeInfo": null,
122
+ "systemModstamp": null,
123
+ "weakEtag": 0
124
+ }
125
+ },
126
+ "LastModifiedById": {
127
+ "displayValue": null,
128
+ "value": "005xx000001X8gHAAS"
129
+ },
130
+ "LastModifiedDate": {
131
+ "displayValue": "4/13/2026, 1:54 PM",
132
+ "value": "2026-04-13T20:54:41.000Z"
133
+ },
134
+ "Owner": {
135
+ "displayValue": "Ethan Chan",
136
+ "value": {
137
+ "apiName": "Name",
138
+ "childRelationships": {},
139
+ "eTag": "202a115a07830e8af0343368d4d309d4",
140
+ "fields": {
141
+ "FirstName": {
142
+ "displayValue": null,
143
+ "value": "Ethan"
144
+ },
145
+ "Id": {
146
+ "displayValue": null,
147
+ "value": "005xx000001X8gHAAS"
148
+ },
149
+ "LastName": {
150
+ "displayValue": null,
151
+ "value": "Chan"
152
+ },
153
+ "Name": {
154
+ "displayValue": null,
155
+ "value": "Ethan Chan"
156
+ }
157
+ },
158
+ "id": "005xx000001X8gHAAS",
159
+ "lastModifiedById": null,
160
+ "lastModifiedDate": null,
161
+ "recordTypeId": null,
162
+ "recordTypeInfo": null,
163
+ "systemModstamp": null,
164
+ "weakEtag": 0
165
+ }
166
+ },
167
+ "OwnerId": {
168
+ "displayValue": null,
169
+ "value": "005xx000001X8gHAAS"
170
+ },
171
+ "Priority": {
172
+ "displayValue": "High",
173
+ "value": "High"
174
+ },
175
+ "Status": {
176
+ "displayValue": "Completed",
177
+ "value": "Completed"
178
+ },
179
+ "Subject": {
180
+ "displayValue": null,
181
+ "value": "Call"
182
+ },
183
+ "SystemModstamp": {
184
+ "displayValue": "4/13/2026, 1:54 PM",
185
+ "value": "2026-04-13T20:54:41.000Z"
186
+ },
187
+ "What": {
188
+ "displayValue": "00001027",
189
+ "value": {
190
+ "apiName": "Name",
191
+ "childRelationships": {},
192
+ "eTag": "deffd76450e8f3c8fc116a1cb6a0bb6b",
193
+ "fields": {
194
+ "Id": {
195
+ "displayValue": null,
196
+ "value": "500xx000000boDJAAY"
197
+ },
198
+ "Name": {
199
+ "displayValue": null,
200
+ "value": "00001027"
201
+ }
202
+ },
203
+ "id": "500xx000000boDJAAY",
204
+ "lastModifiedById": null,
205
+ "lastModifiedDate": null,
206
+ "recordTypeId": null,
207
+ "recordTypeInfo": null,
208
+ "systemModstamp": null,
209
+ "weakEtag": 0
210
+ }
211
+ },
212
+ "WhatId": {
213
+ "displayValue": null,
214
+ "value": "500xx000000boDJAAY"
215
+ },
216
+ "Who": {
217
+ "displayValue": null,
218
+ "value": null
219
+ },
220
+ "WhoId": {
221
+ "displayValue": null,
222
+ "value": null
223
+ }
224
+ },
225
+ "id": "00Txx000003rIcmEAE",
226
+ "lastModifiedById": "005xx000001X8gHAAS",
227
+ "lastModifiedDate": "2026-04-13T20:54:41.000Z",
228
+ "recordTypeId": "012000000000000AAA",
229
+ "recordTypeInfo": null,
230
+ "systemModstamp": "2026-04-13T20:54:41.000Z",
231
+ "weakEtag": 1776113681000
232
+ }
233
+ ]
package/src/ads-bridge.ts CHANGED
@@ -107,6 +107,10 @@ function isStoreKeyRecordId(key: string) {
107
107
  return key.indexOf(RECORD_ID_PREFIX) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION) === -1;
108
108
  }
109
109
 
110
+ function isStoreKeyRecordField(key: string) {
111
+ return key.indexOf(RECORD_ID_PREFIX) > -1 && key.indexOf(RECORD_FIELDS_KEY_JUNCTION) > -1;
112
+ }
113
+
110
114
  /**
111
115
  * Returns a shallow copy of a record with its field values if it is a scalar and a reference and a
112
116
  * a RecordRepresentation with no field if the value if a spanning record.
@@ -488,6 +492,37 @@ export default class AdsBridge {
488
492
  }
489
493
  }
490
494
 
495
+ private filterAndSynthesizeBaseIds(updatedEntries: { id: string }[]): { id: string }[] {
496
+ // Collect base record IDs that are directly present in the entries.
497
+ const directBaseIds = new Set<string>();
498
+ for (let i = 0; i < updatedEntries.length; i++) {
499
+ if (isStoreKeyRecordId(updatedEntries[i].id)) {
500
+ directBaseIds.add(updatedEntries[i].id);
501
+ }
502
+ }
503
+
504
+ // For field entries whose base record ID has no direct entry, synthesize one.
505
+ const syntheticBaseIds = new Set<string>();
506
+ for (let i = 0; i < updatedEntries.length; i++) {
507
+ if (isStoreKeyRecordField(updatedEntries[i].id)) {
508
+ const baseId = updatedEntries[i].id.split(RECORD_FIELDS_KEY_JUNCTION)[0];
509
+ if (!directBaseIds.has(baseId)) {
510
+ syntheticBaseIds.add(baseId);
511
+ }
512
+ }
513
+ }
514
+ // Exclude all the store record ids not matching with the record id pattern.
515
+ // Note: FieldValueRepresentation have the same prefix than RecordRepresentation so we
516
+ // need to filter them out.
517
+ const filteredUpdatedEntries: { id: string }[] = updatedEntries.filter((entry) =>
518
+ isStoreKeyRecordId(entry.id)
519
+ );
520
+ syntheticBaseIds.forEach((baseId) => {
521
+ ArrayPrototypePush.call(filteredUpdatedEntries, { id: baseId });
522
+ });
523
+ return filteredUpdatedEntries;
524
+ }
525
+
491
526
  /**
492
527
  * This method retrieves queries the store with with passed record ids to retrieve their
493
528
  * associated records and object info. Note that the passed ids are not Salesforce record id
@@ -504,16 +539,11 @@ export default class AdsBridge {
504
539
  const adsRecordMap: AdsRecordMap = {};
505
540
  const adsObjectMap: AdsObjectMetadataMap = {};
506
541
 
507
- for (let i = 0; i < updatedEntries.length; i++) {
508
- const storeRecordId = updatedEntries[i].id;
509
-
510
- // Exclude all the store record ids not matching with the record id pattern.
511
- // Note: FieldValueRepresentation have the same prefix than RecordRepresentation so we
512
- // need to filter them out.
513
- if (!isStoreKeyRecordId(storeRecordId)) {
514
- continue;
515
- }
516
-
542
+ // W-21715343
543
+ // Context for change: https://docs.google.com/document/d/1iF6M9jldEX_K9FOpdttLqVwO9uESUUrlyWi2mWnXtAQ/edit?usp=sharing
544
+ const filteredUpdatedEntries = this.filterAndSynthesizeBaseIds(updatedEntries);
545
+ for (let i = 0; i < filteredUpdatedEntries.length; i++) {
546
+ const storeRecordId = filteredUpdatedEntries[i].id;
517
547
  const record =
518
548
  this.recordRepresentationIngestOverride !== undefined
519
549
  ? getShallowRecordDenormalized(luvio, storeRecordId)