Skip to content

Commit a87d5e0

Browse files
committed
add nested entities to normalized caching
1 parent 337fe46 commit a87d5e0

File tree

2 files changed

+46
-37
lines changed

2 files changed

+46
-37
lines changed

packages/data-connect/src/core/Cache.ts

Lines changed: 45 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ type Value = string | number | boolean | null | undefined | object | Value[];
2727
*/
2828
export interface QueryResultData {
2929
[key: string]: Value;
30-
__typename: string;
31-
__id: string;
30+
__typename?: string;
31+
__id?: string;
3232
}
3333

3434
/**
@@ -169,46 +169,55 @@ export class Cache {
169169
queryResult.ref.name,
170170
queryResult.ref.variables
171171
);
172-
const stubResultTree: StubResultTree = {};
173-
174-
// eslint-disable-next-line guard-for-in
175-
for (const key in queryResult.data) {
176-
const entityOrEntityList = (queryResult.data as Record<string, unknown>)[
177-
key
178-
];
179-
if (Array.isArray(entityOrEntityList)) {
180-
const sdoList: StubDataObjectList = [];
181-
entityOrEntityList.forEach(entity => {
182-
if (isCacheableQueryResultData(entity)) {
183-
const stubDataObject = this.cacheData(entity);
184-
sdoList.push(stubDataObject);
185-
}
186-
});
187-
stubResultTree[key] = sdoList;
188-
} else if (isCacheableQueryResultData(entityOrEntityList)) {
189-
const stubDataObject = this.cacheData(entityOrEntityList);
190-
stubResultTree[key] = stubDataObject;
191-
}
192-
}
172+
const stubResultTree = this.normalize(queryResult.data) as StubResultTree;
193173
this.resultTreeCache.set(resultTreeCacheKey, stubResultTree);
194174
}
195175

196176
/**
197-
* Caches a single entity: gets or creates its BDO and returns a linked stub.
198-
* @param data A single entity object from the query result.
199-
* @returns A StubDataObject linked to the entity's BackingDataObject.
177+
* Recursively traverses a data object, normalizing cacheable entities into BDOs
178+
* and replacing them with stubs.
179+
* @param data The data to normalize (can be an object, array, or primitive).
180+
* @returns The normalized data with stubs.
200181
*/
201-
private cacheData(data: QueryResultData): StubDataObject {
202-
const stubDataaObject: StubDataObject = { ...data };
203-
const bdoCacheKey = Cache.makeBdoCacheKey(data.__typename, data.__id);
204-
const existingBdo = this.bdoCache.get(bdoCacheKey);
205-
206-
if (existingBdo) {
207-
this.updateBdo(existingBdo, data, stubDataaObject);
208-
} else {
209-
this.createBdo(bdoCacheKey, data, stubDataaObject);
182+
private normalize(data: QueryResultData | Value): Value | StubDataObject {
183+
if (Array.isArray(data)) {
184+
return data.map(item => this.normalize(item));
185+
}
186+
187+
if (isCacheableQueryResultData(data)) {
188+
const stub: StubDataObject = {};
189+
const bdoCacheKey = Cache.makeBdoCacheKey(data.__typename, data.__id);
190+
const existingBdo = this.bdoCache.get(bdoCacheKey);
191+
192+
// data is a single "movie" or "actor"
193+
// key is a field of the returned data
194+
for (const key in data) {
195+
// eslint-disable-next-line no-prototype-builtins
196+
if (data.hasOwnProperty(key)) {
197+
stub[key] = this.normalize(data[key]);
198+
}
199+
}
200+
201+
if (existingBdo) {
202+
this.updateBdo(existingBdo, stub, stub);
203+
} else {
204+
this.createBdo(bdoCacheKey, stub, stub);
205+
}
206+
return stub;
207+
}
208+
209+
if (typeof data === 'object' && data !== null) {
210+
const newObj: { [key: string]: Value } = {};
211+
for (const key in data) {
212+
// eslint-disable-next-line no-prototype-builtins
213+
if (data.hasOwnProperty(key)) {
214+
newObj[key] = this.normalize(data[key]);
215+
}
216+
}
217+
return newObj;
210218
}
211-
return stubDataaObject;
219+
220+
return data;
212221
}
213222

214223
/**

packages/data-connect/test/unit/Cache.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ describe('Normalized Cache Tests', () => {
202202
expect(stubList[0].title).to.equal('Inception');
203203
expect(stubList[1].title).to.equal('The Matrix');
204204

205-
// 2. Check that two new BDOs were created in the BDO Cache
205+
// 2. Check that four new BDOs were created in the BDO Cache
206206
expect(cache.bdoCache.size).to.equal(4); // movie1, review1, reviewer1, movie2
207207
const bdo1 = cache.bdoCache.get(Cache.makeBdoCacheKey('Movie', '1'))!;
208208
const bdo2 = cache.bdoCache.get(Cache.makeBdoCacheKey('Movie', '2'))!;

0 commit comments

Comments
 (0)