18
18
19
19
import { QueryResult } from '../api' ;
20
20
21
- /** Value is any FDC scalar value. */
21
+ /** Value is any FDC scalar value. */ // TODO: make this more accurate
22
22
type Value = string | number | boolean | null | undefined | object | Value [ ] ;
23
23
24
+ /**
25
+ * Defines the shape of query result data - "movies", "actor", etc.
26
+ */
24
27
export interface QueryResultData {
25
28
[ key : string ] : Value ;
26
29
__typename ?: string ;
27
30
__id ?: string ;
28
31
}
29
32
30
33
/**
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.
40
35
* @param queryName The name of the query.
41
36
* @param vars The variables used in the query.
42
37
* @returns A unique cache key string.
43
38
* @public
44
39
*/
45
- export function makeStubCacheKey ( queryName : string , vars : unknown ) : string {
40
+ export function makeResultTreeCacheKey (
41
+ queryName : string ,
42
+ vars : unknown
43
+ ) : string {
46
44
return queryName + '|' + JSON . stringify ( vars ) ;
47
45
}
48
46
49
47
/**
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 .
53
51
* @returns A unique cache key string.
54
52
* @public
55
53
*/
@@ -63,8 +61,6 @@ export function makeBdoCacheKey(typename: string, id: unknown): string {
63
61
* @public
64
62
*/
65
63
export interface StubDataObject {
66
- /** A stable unique key identifying the entity across types. */
67
- readonly typedKey : string ;
68
64
[ key : string ] : Value | StubDataObject ;
69
65
}
70
66
@@ -84,7 +80,7 @@ export class BackingDataObject {
84
80
* Stable unique key identifying the entity across types.
85
81
* TypeName + CompositePrimaryKey.
86
82
*/
87
- private typedKey : string ;
83
+ readonly typedKey : string ;
88
84
89
85
/** Represents values received from the server. */
90
86
private serverValues : Map < string , Value > ;
@@ -147,7 +143,7 @@ export class Cache {
147
143
* A map of ([query + variables] --> stubs returned from that query).
148
144
* @public
149
145
*/
150
- stubTreeCache = new Map < string , StubDataObject > ( ) ;
146
+ resultTreeCache = new Map < string , StubDataObject [ ] > ( ) ;
151
147
152
148
/**
153
149
* A map of ([entity typename + id] --> BackingDataObject for that entity).
@@ -163,53 +159,79 @@ export class Cache {
163
159
updateCache < Data extends QueryResultData | QueryResultData [ ] , Variables > (
164
160
queryResult : QueryResult < Data , Variables >
165
161
) : 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...
171
163
// key = "movies" or "actor", etc.
172
164
// eslint-disable-next-line guard-for-in
173
165
for ( const key in queryResult . data ) {
174
166
const queryData = queryResult . data [ key ] ;
175
167
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
+ } ) ;
177
176
} 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...
179
183
}
180
184
}
181
-
182
- // todo: add StubDataObjects to StrubResultTree
185
+ this . updateResultTreeCache (
186
+ queryResult . ref . name ,
187
+ queryResult . ref . variables ,
188
+ stubDataObjects
189
+ ) ;
183
190
}
184
191
185
192
/**
186
193
* Update the BackingDataObject cache, either adding a new BDO or updating an existing BDO
187
194
* @param data A single entity from the database.
195
+ * @returns the BackingDataObject created/upated.
188
196
*/
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 ) {
198
205
// BDO already exists, so update its values from the new data.
199
206
for ( const [ key , value ] of Object . entries ( data ) ) {
200
207
// key = "id" or "title", etc.
201
- existingBdo . updateFromServer ( value , key ) ;
208
+ backingDataObject . updateFromServer ( value , key ) ;
202
209
}
203
- existingBdo . listeners . add ( stubDataObject ) ;
210
+ backingDataObject . listeners . add ( stubDataObject ) ;
204
211
} else {
205
212
// BDO does not exist, so create a new one.
206
213
const serverValues = new Map < string , Value > ( Object . entries ( data ) ) ;
207
- const backingDataObject = new BackingDataObject (
208
- typedKey ,
214
+ backingDataObject = new BackingDataObject (
215
+ bdoCacheKey ,
209
216
[ stubDataObject ] ,
210
217
serverValues
211
218
) ;
212
- this . bdoCache . set ( typedKey , backingDataObject ) ;
219
+ this . bdoCache . set ( bdoCacheKey , backingDataObject ) ;
213
220
}
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 ) ;
214
236
}
215
237
}
0 commit comments