1818
1919import { QueryResult } from '../api' ;
2020
21- /** Value is any FDC scalar value. */
21+ /** Value is any FDC scalar value. */ // TODO: make this more accurate
2222type Value = string | number | boolean | null | undefined | object | Value [ ] ;
2323
24+ /**
25+ * Defines the shape of query result data - "movies", "actor", etc.
26+ */
2427export interface QueryResultData {
2528 [ key : string ] : Value ;
2629 __typename ?: string ;
2730 __id ?: string ;
2831}
2932
3033/**
31- * Interface representing the result tree for an operation.
32- * @public
33- */
34- export interface StubResultTree {
35- [ key : string ] : StubDataObject | StubDataObjectList ;
36- }
37-
38- /**
39- * Creates a unique cache key for a given query and its variables.
34+ * Creates a unique StrubResultTree cache key for a given query and its variables.
4035 * @param queryName The name of the query.
4136 * @param vars The variables used in the query.
4237 * @returns A unique cache key string.
4338 * @public
4439 */
45- export function makeStubCacheKey ( queryName : string , vars : unknown ) : string {
40+ export function makeResultTreeCacheKey (
41+ queryName : string ,
42+ vars : unknown
43+ ) : string {
4644 return queryName + '|' + JSON . stringify ( vars ) ;
4745}
4846
4947/**
50- * Creates a unique cache key for a given query and its variables .
51- * @param queryName The name of the query .
52- * @param vars The variables used in the query .
48+ * Creates a unique BackingDataObject cache key for a given entity .
49+ * @param typename The typename of the entity being cached .
50+ * @param id The unique id / primary key of this entity .
5351 * @returns A unique cache key string.
5452 * @public
5553 */
@@ -63,8 +61,6 @@ export function makeBdoCacheKey(typename: string, id: unknown): string {
6361 * @public
6462 */
6563export interface StubDataObject {
66- /** A stable unique key identifying the entity across types. */
67- readonly typedKey : string ;
6864 [ key : string ] : Value | StubDataObject ;
6965}
7066
@@ -84,7 +80,7 @@ export class BackingDataObject {
8480 * Stable unique key identifying the entity across types.
8581 * TypeName + CompositePrimaryKey.
8682 */
87- private typedKey : string ;
83+ readonly typedKey : string ;
8884
8985 /** Represents values received from the server. */
9086 private serverValues : Map < string , Value > ;
@@ -147,7 +143,7 @@ export class Cache {
147143 * A map of ([query + variables] --> stubs returned from that query).
148144 * @public
149145 */
150- stubTreeCache = new Map < string , StubDataObject > ( ) ;
146+ resultTreeCache = new Map < string , StubDataObject [ ] > ( ) ;
151147
152148 /**
153149 * A map of ([entity typename + id] --> BackingDataObject for that entity).
@@ -163,53 +159,79 @@ export class Cache {
163159 updateCache < Data extends QueryResultData | QueryResultData [ ] , Variables > (
164160 queryResult : QueryResult < Data , Variables >
165161 ) : void {
166- const queryKey = makeStubCacheKey (
167- queryResult . ref . name ,
168- queryResult . ref . variables
169- ) ;
170-
162+ const stubDataObjects : StubDataObject [ ] = [ ] ; // ! if this is going to be mapped to the query name | variables, consider the fact that not all queries return a list of objects...
171163 // key = "movies" or "actor", etc.
172164 // eslint-disable-next-line guard-for-in
173165 for ( const key in queryResult . data ) {
174166 const queryData = queryResult . data [ key ] ;
175167 if ( Array . isArray ( queryData ) ) {
176- queryData . forEach ( qd => this . updateBdoCache ( qd ) ) ;
168+ queryData . forEach ( qd => {
169+ const sdo : StubDataObject = {
170+ ...Object . entries ( qd )
171+ // todo: add in non-cacheable fields
172+ } ;
173+ stubDataObjects . push ( sdo ) ;
174+ const bdo : BackingDataObject = this . updateBdoCache ( qd , sdo ) ;
175+ } ) ;
177176 } else {
178- this . updateBdoCache ( queryData as QueryResultData ) ; // ! i don't think i should need a type assertion here, yet TS complains without it...
177+ const sdo : StubDataObject = {
178+ ...Object . entries ( queryData )
179+ // todo: add in non-cacheable fields
180+ } ;
181+ stubDataObjects . push ( sdo ) ;
182+ const bdo = this . updateBdoCache ( queryData as QueryResultData , sdo ) ; // ! i don't think i should need a type assertion here, yet TS complains without it...
179183 }
180184 }
181-
182- // todo: add StubDataObjects to StrubResultTree
185+ this . updateResultTreeCache (
186+ queryResult . ref . name ,
187+ queryResult . ref . variables ,
188+ stubDataObjects
189+ ) ;
183190 }
184191
185192 /**
186193 * Update the BackingDataObject cache, either adding a new BDO or updating an existing BDO
187194 * @param data A single entity from the database.
195+ * @returns the BackingDataObject created/upated.
188196 */
189- private updateBdoCache < Data extends QueryResultData > ( data : Data ) : void {
190- const typedKey = makeBdoCacheKey ( data [ '__typename' ] , data [ '__id' ] ) ;
191- const existingBdo = this . bdoCache . get ( typedKey ) ;
192- const stubDataObject : StubDataObject = {
193- typedKey
194- // todo: add in non-cacheable fields
195- } ;
196-
197- if ( existingBdo ) {
197+ private updateBdoCache < Data extends QueryResultData > (
198+ data : Data ,
199+ stubDataObject : StubDataObject
200+ ) : BackingDataObject {
201+ const bdoCacheKey = makeBdoCacheKey ( data [ '__typename' ] , data [ '__id' ] ) ;
202+ let backingDataObject = this . bdoCache . get ( bdoCacheKey ) ;
203+
204+ if ( backingDataObject ) {
198205 // BDO already exists, so update its values from the new data.
199206 for ( const [ key , value ] of Object . entries ( data ) ) {
200207 // key = "id" or "title", etc.
201- existingBdo . updateFromServer ( value , key ) ;
208+ backingDataObject . updateFromServer ( value , key ) ;
202209 }
203- existingBdo . listeners . add ( stubDataObject ) ;
210+ backingDataObject . listeners . add ( stubDataObject ) ;
204211 } else {
205212 // BDO does not exist, so create a new one.
206213 const serverValues = new Map < string , Value > ( Object . entries ( data ) ) ;
207- const backingDataObject = new BackingDataObject (
208- typedKey ,
214+ backingDataObject = new BackingDataObject (
215+ bdoCacheKey ,
209216 [ stubDataObject ] ,
210217 serverValues
211218 ) ;
212- this . bdoCache . set ( typedKey , backingDataObject ) ;
219+ this . bdoCache . set ( bdoCacheKey , backingDataObject ) ;
213220 }
221+ return backingDataObject ;
222+ }
223+
224+ /**
225+ * Update the StubResultTree cache, either adding a new StubResultTree or updating an existing
226+ * StubResultTree
227+ * @param data A single entity from the database.
228+ */
229+ private updateResultTreeCache < Variables > (
230+ queryName : string ,
231+ variables : Variables ,
232+ stubDataObjects : StubDataObject [ ]
233+ ) : void {
234+ const resultTreeCacheKey = makeResultTreeCacheKey ( queryName , variables ) ;
235+ this . resultTreeCache . set ( resultTreeCacheKey , stubDataObjects ) ;
214236 }
215237}
0 commit comments