Skip to content

Commit e476774

Browse files
committed
WIP
1 parent 764d4ee commit e476774

File tree

7 files changed

+69
-30
lines changed

7 files changed

+69
-30
lines changed

packages/data-connect/src/api/DataConnect.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import {
3131
} from '@firebase/util';
3232

3333
import { Cache as DataConnectCache } from '../cache/Cache';
34+
import { CacheProvider } from '../cache/CacheProvider';
35+
import { IndexedDBCacheProvider } from '../cache/IndexedDBCacheProvider';
3436
import { AppCheckTokenProvider } from '../core/AppCheckTokenProvider';
3537
import { Code, DataConnectError } from '../core/error';
3638
import {
@@ -168,6 +170,7 @@ export class DataConnect {
168170
this.app.options,
169171
this._authProvider
170172
);
173+
this.cache.setAuthProvider(this._authTokenProvider);
171174
}
172175
if (this._appCheckProvider) {
173176
this._appCheckTokenProvider = new AppCheckTokenProvider(
@@ -254,6 +257,10 @@ export function connectDataConnectEmulator(
254257
dc.enableEmulator({ host, port, sslEnabled });
255258
}
256259

260+
export interface DataConnectConfigureOptions {
261+
cacheProvider: CacheProvider
262+
}
263+
257264
/**
258265
* Initialize DataConnect instance
259266
* @param options ConnectorConfig
@@ -266,21 +273,31 @@ export function getDataConnect(options: ConnectorConfig): DataConnect;
266273
*/
267274
export function getDataConnect(
268275
app: FirebaseApp,
269-
options: ConnectorConfig
276+
options: ConnectorConfig,
277+
additionalOptions?: DataConnectConfigureOptions
270278
): DataConnect;
271279
export function getDataConnect(
272280
appOrOptions: FirebaseApp | ConnectorConfig,
273-
optionalOptions?: ConnectorConfig
281+
optionalOptionsOrCacheOptions?: ConnectorConfig | DataConnectConfigureOptions,
282+
additionalOptionsOrCacheOptions?: DataConnectConfigureOptions
274283
): DataConnect {
275284
let app: FirebaseApp;
276285
let dcOptions: ConnectorConfig;
286+
let cacheOptions: DataConnectConfigureOptions;
277287
if ('location' in appOrOptions) {
278288
dcOptions = appOrOptions;
279289
app = getApp();
290+
cacheOptions = optionalOptionsOrCacheOptions as DataConnectConfigureOptions;
280291
} else {
281-
dcOptions = optionalOptions!;
292+
dcOptions = optionalOptionsOrCacheOptions as ConnectorConfig;
293+
cacheOptions = additionalOptionsOrCacheOptions as DataConnectConfigureOptions;
282294
app = appOrOptions;
283295
}
296+
// TODO: initialize data connect with this.
297+
if(!cacheOptions) {
298+
// TODO: Make this a class that gets passed in.
299+
cacheOptions.cacheProvider = new IndexedDBCacheProvider();
300+
}
284301

285302
if (!app || Object.keys(app).length === 0) {
286303
app = getApp();

packages/data-connect/src/api/query.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,27 @@ export interface QueryPromise<Data, Variables>
7171
// reserved for special actions like cancellation
7272
}
7373

74+
75+
export enum QueryFetchPolicy {
76+
preferCache,
77+
cacheOnly,
78+
serverOnly
79+
}
80+
81+
export interface ExecuteQueryOptions {
82+
fetchPolicy: QueryFetchPolicy;
83+
}
84+
7485
/**
7586
* Execute Query
7687
* @param queryRef query to execute.
7788
* @returns `QueryPromise`
7889
*/
7990
export function executeQuery<Data, Variables>(
80-
queryRef: QueryRef<Data, Variables>
91+
queryRef: QueryRef<Data, Variables>,
92+
options?: ExecuteQueryOptions
8193
): QueryPromise<Data, Variables> {
82-
return queryRef.dataConnect._queryManager.executeQuery(queryRef);
94+
return queryRef.dataConnect._queryManager.executeQuery(queryRef, options);
8395
}
8496

8597
/**
@@ -102,10 +114,10 @@ export function queryRef<Data>(
102114
export function queryRef<Data, Variables>(
103115
dcInstance: DataConnect,
104116
queryName: string,
105-
variables: Variables
117+
variables: Variables,
106118
): QueryRef<Data, Variables>;
107119
/**
108-
* Execute QueryG
120+
* Execute Query
109121
* @param dcInstance Data Connect instance to use.
110122
* @param queryName Query to execute
111123
* @param variables Variables to execute with

packages/data-connect/src/cache/BackingDataObject.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ export interface BackingDataObjectJson {
88

99
export class BackingDataObject {
1010
toStorableJson(): BackingDataObjectJson {
11-
// TODO: This might not be ok.
1211
return {
1312
globalID: this.globalID,
1413
map: this.map,

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

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { isIndexedDBAvailable } from '@firebase/util';
22

33
import { DataConnectError } from '../core/error';
4+
import { type AuthTokenProvider } from '../core/FirebaseAuthProvider';
45

56
import { BackingDataObject } from './BackingDataObject';
67
import { CacheProvider } from './CacheProvider';
@@ -9,23 +10,33 @@ import { IndexedDBCacheProvider } from './IndexedDBCacheProvider';
910
import { ResultTree } from './ResultTree';
1011
import { ResultTreeProcessor } from './ResultTreeProcessor';
1112

13+
1214
export interface ServerValues {
1315
ttl: number;
1416
}
1517

16-
17-
18+
// TODO: Figure out how to deal with caching across browsers.
1819
export class Cache {
20+
setAuthProvider(_authTokenProvider: AuthTokenProvider): void {
21+
this.authProvider.addTokenChangeListener((newToken) => {
22+
this.updateToken(newToken);
23+
});
24+
}
1925
private cacheProvider: CacheProvider;
20-
constructor() {
21-
// TODO: Include identifier for cacheprovider
26+
private authProvider: AuthTokenProvider;
27+
updateToken(_newToken: string): void {
28+
// TODO: notify cacheproviders
29+
this.initializeNewProviders();
30+
}
31+
initializeNewProviders(): void {
2232
if (!isIndexedDBAvailable()) {
2333
this.cacheProvider = new EphemeralCacheProvider();
2434
} else {
2535
this.cacheProvider = new IndexedDBCacheProvider();
2636
}
27-
// TODO: Create one for Tanstack
28-
// TODO: Deal with auth changes.
37+
}
38+
constructor() {
39+
this.initializeNewProviders();
2940
}
3041
containsResultTree(queryId: string): boolean {
3142
const resultTree = this.cacheProvider.getResultTree(queryId);
@@ -43,7 +54,6 @@ export class Cache {
4354
`${queryId} not found in cache. Call "update() first."`
4455
);
4556
}
46-
// TODO: Make sure that this serializes the references, not the objects themselves.
4757
return processor.hydrateResults(resultTree.getRootStub());
4858
}
4959
update(queryId: string, serverValues: ServerValues): string[] {

packages/data-connect/src/cache/IndexedDBCacheProvider.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ export class IndexedDBCacheProvider implements CacheProvider {
2525
dbResolve(db);
2626
};
2727
request.onsuccess = async (event) => {
28-
// TODO: Check version
2928
const db = (event.target as IDBOpenDBRequest).result;
3029
const tx = db.transaction(
3130
[BDO_OBJECT_STORE_NAME, SRT_OBJECT_STORE_NAME],

packages/data-connect/src/cache/StubDataObject.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ export class StubDataObject {
2121
if(typeof values === 'undefined' && typeof cacheProvider === 'undefined' && typeof acc === 'undefined') {
2222
return;
2323
}
24-
// TODO: validate that all other fields have been passed in.
2524
if (typeof values !== 'object' || Array.isArray(values)) {
2625
throw new DataConnectError(
2726
'invalid-argument',

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

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18-
import { DataConnect } from '../api';
18+
import { DataConnect, ExecuteQueryOptions, QueryFetchPolicy } from '../api';
1919
import {
2020
DataConnectSubscription,
2121
OnErrorSubscription,
@@ -162,22 +162,22 @@ export class QueryManager {
162162
return unsubscribe;
163163
}
164164
executeQuery<Data, Variables>(
165-
queryRef: QueryRef<Data, Variables>
165+
queryRef: QueryRef<Data, Variables>,
166+
options?: ExecuteQueryOptions
166167
): QueryPromise<Data, Variables> {
167168
if (queryRef.refType !== QUERY_STR) {
168169
throw new DataConnectError(
169170
Code.INVALID_ARGUMENT,
170-
`ExecuteQuery can only execute query operation`
171+
`ExecuteQuery can only execute query operations`
171172
);
172173
}
173174
const key = encoderImpl({
174175
name: queryRef.name,
175176
variables: queryRef.variables,
176177
refType: QUERY_STR
177178
});
178-
// TODO: Check if the cache is stale
179-
// TODO: isStale doesn't exist when parsing the raw JSON. Fix the parsing.
180-
if(this.cache.containsResultTree(key) && !this.cache.getResultTree(key)?.isStale()) {
179+
180+
if (options.fetchPolicy !== QueryFetchPolicy.serverOnly && this.cache.containsResultTree(key) && !this.cache.getResultTree(key).isStale()) {
181181
const cacheResult: Data = JSON.parse(this.cache.getResultJSON(key));
182182
const result: QueryResult<Data, Variables> = {
183183
...cacheResult,
@@ -191,11 +191,15 @@ export class QueryManager {
191191

192192
return Promise.resolve(result);
193193
} else {
194-
logDebug(
195-
`No Cache found for query ${
196-
queryRef.name
197-
} with variables ${JSON.stringify(queryRef.variables)}. Calling executeQuery`
198-
);
194+
if(options.fetchPolicy === QueryFetchPolicy.serverOnly) {
195+
logDebug(`Skipping cache for fetch policy "serverOnly"`);
196+
} else {
197+
logDebug(
198+
`No Cache found for query ${
199+
queryRef.name
200+
} with variables ${JSON.stringify(queryRef.variables)}. Calling executeQuery`
201+
);
202+
}
199203
}
200204
const result = this.transport.invokeQuery<Data, Variables>(
201205
queryRef.name,
@@ -219,8 +223,7 @@ export class QueryManager {
219223
}
220224
if(this.cache.containsResultTree(key)) {
221225
this.cache.getResultTree(key).updateAccessed();
222-
}
223-
const impactedQueries = this.cache.update(key, result.data as ServerValues);
226+
} const impactedQueries = this.cache.update(key, result.data as ServerValues);
224227
this.publishCacheResultsToSubscribers(impactedQueries);
225228
return result;
226229
},

0 commit comments

Comments
 (0)