18
18
19
19
import { QueryResult } from '../api' ;
20
20
21
- /** Value is any FDC scalar value. */
21
+ /** Internal utility type. Value is any FDC scalar value. */
22
22
// TODO: make this more accurate... what type should we use to represent any FDC scalar value?
23
23
type Value = string | number | boolean | null | undefined | object | Value [ ] ;
24
24
25
25
/**
26
- * Defines the shape of query result data that represents a single entity.
26
+ * Internal utility type. Defines the shape of query result data that represents a single entity.
27
27
* It must have __typename and __id for normalization.
28
28
*/
29
- // TODO: this is just a StubDataObject isn't it...?
30
- export interface QueryResultData {
29
+ interface QueryResultData {
31
30
[ key : string ] : Value ;
32
31
__typename ?: string ;
33
32
__id ?: string ;
34
33
}
35
34
36
35
/**
37
- * A type guard to check if a value is a QueryResultData object .
36
+ * A type guard to check if a value is normalizeable .
38
37
* @param value The value to check.
39
- * @returns True if the value is a QueryResultData object .
38
+ * @returns True if the value is normalizeable (it has the fields __typename and __id) .
40
39
*/
41
- function isCacheableQueryResultData ( value : unknown ) : value is QueryResultData {
40
+ function isNormalizeable ( value : unknown ) : value is QueryResultData {
42
41
return (
42
+ value !== undefined &&
43
43
value !== null &&
44
44
typeof value === 'object' &&
45
45
! Array . isArray ( value ) &&
@@ -49,27 +49,16 @@ function isCacheableQueryResultData(value: unknown): value is QueryResultData {
49
49
}
50
50
51
51
/**
52
- * Interface for a stub result tree, with fields which are stub data objects
52
+ * Interface for a stub result tree, with fields which are stub data objects.
53
+ * @public
53
54
*/
54
- // TODO: need a better way to represent that a query may return a single entity or a list of entities
55
- // ! ex: queryResult.data =
56
- // ! {
57
- // ! movies: [ <-- list
58
- // ! {...movie1...},
59
- // ! {...movie2...},
60
- // ! {...movie3...}
61
- // ! ],
62
- // ! currentUser: { <-- singleton
63
- // ! ...user...
64
- // ! }
65
- // ! }
66
- interface StubResultTree {
55
+ export interface StubResultTree {
67
56
[ key : string ] : StubDataObject | StubDataObjectList ;
68
57
}
69
58
70
59
/**
71
- * Interface for a stub data object, which acts as a "live" view into cached data.
72
- * Generated Data implements this interface.
60
+ * Interface for a stub data object, which acts as a snapshot view of cached data.
61
+ * Selection sets in generated data types extend this interface.
73
62
* @public
74
63
*/
75
64
export interface StubDataObject {
@@ -84,7 +73,7 @@ export interface StubDataObject {
84
73
class StubDataObjectList extends Array < StubDataObject > { }
85
74
86
75
/**
87
- * A class used to hold the single source of truth for an entity's values across all queries.
76
+ * A class used to hold an entity's normalized cached values across all queries.
88
77
* @public
89
78
*/
90
79
export class BackingDataObject {
@@ -107,14 +96,17 @@ export class BackingDataObject {
107
96
}
108
97
109
98
/**
110
- * Updates the value for a named property from the server and notifies all listeners.
99
+ * Updates the value for a named property from the server and notifies all listeners which depend
100
+ * on that value.
111
101
* @param value The new value from the server.
112
102
* @param key The key of the property to update.
113
103
*/
114
104
updateFromServer ( value : Value , key : string ) : void {
115
105
this . serverValues . set ( key , value ) ;
116
106
for ( const listener of this . listeners ) {
117
- listener [ key ] = value ;
107
+ if ( key in listener ) {
108
+ listener [ key ] = value ;
109
+ }
118
110
}
119
111
}
120
112
@@ -138,7 +130,9 @@ export class BackingDataObject {
138
130
updateLocal ( value : Value , key : string ) : void {
139
131
this . localValues . set ( key , value ) ;
140
132
for ( const listener of this . listeners ) {
141
- listener [ key ] = value ;
133
+ if ( key in listener ) {
134
+ listener [ key ] = value ;
135
+ }
142
136
}
143
137
}
144
138
}
@@ -148,8 +142,8 @@ export class BackingDataObject {
148
142
* @public
149
143
*/
150
144
export class Cache {
151
- /** A map of [query + variables] --> StubDataObjects returned from that query. */
152
- resultTreeCache = new Map < string , StubResultTree > ( ) ;
145
+ /** A map of [query + variables] --> StubResultTree returned from that query. */
146
+ srtCache = new Map < string , StubResultTree > ( ) ;
153
147
154
148
/** A map of [entity typename + id] --> BackingDataObject for that entity. */
155
149
bdoCache = new Map < string , BackingDataObject > ( ) ;
@@ -160,7 +154,7 @@ export class Cache {
160
154
* @param vars The variables used in the query.
161
155
* @returns A unique cache key string.
162
156
*/
163
- static makeResultTreeCacheKey ( queryName : string , vars : unknown ) : string {
157
+ static srtCacheKey ( queryName : string , vars : unknown ) : string {
164
158
return queryName + '|' + JSON . stringify ( vars ) ;
165
159
}
166
160
@@ -170,7 +164,7 @@ export class Cache {
170
164
* @param id The unique id / primary key of this entity.
171
165
* @returns A unique cache key string.
172
166
*/
173
- static makeBdoCacheKey ( typename : string , id : unknown ) : string {
167
+ static bdoCacheKey ( typename : string , id : unknown ) : string {
174
168
return typename + '|' + JSON . stringify ( id ) ;
175
169
}
176
170
@@ -181,12 +175,12 @@ export class Cache {
181
175
updateCache < Data extends object , Variables > (
182
176
queryResult : QueryResult < Data , Variables >
183
177
) : void {
184
- const resultTreeCacheKey = Cache . makeResultTreeCacheKey (
178
+ const resultTreeCacheKey = Cache . srtCacheKey (
185
179
queryResult . ref . name ,
186
180
queryResult . ref . variables
187
181
) ;
188
182
const stubResultTree = this . normalize ( queryResult . data ) as StubResultTree ;
189
- this . resultTreeCache . set ( resultTreeCacheKey , stubResultTree ) ;
183
+ this . srtCache . set ( resultTreeCacheKey , stubResultTree ) ;
190
184
}
191
185
192
186
/**
@@ -200,9 +194,9 @@ export class Cache {
200
194
return data . map ( item => this . normalize ( item ) ) ;
201
195
}
202
196
203
- if ( isCacheableQueryResultData ( data ) ) {
197
+ if ( isNormalizeable ( data ) ) {
204
198
const stub : StubDataObject = { } ;
205
- const bdoCacheKey = Cache . makeBdoCacheKey ( data . __typename , data . __id ) ;
199
+ const bdoCacheKey = Cache . bdoCacheKey ( data . __typename , data . __id ) ;
206
200
const existingBdo = this . bdoCache . get ( bdoCacheKey ) ;
207
201
208
202
// data is a single "movie" or "actor"
0 commit comments