Skip to content

Commit 189833b

Browse files
committed
Final indexeddb pass
1 parent b079c53 commit 189833b

File tree

19 files changed

+578
-398
lines changed

19 files changed

+578
-398
lines changed

common/api-review/data-connect.api.md

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ import { FirebaseError } from '@firebase/util';
1111
import { LogLevelString } from '@firebase/logger';
1212
import { Provider } from '@firebase/component';
1313

14+
// @public (undocumented)
15+
export const CacheOnly = "cacheOnly";
16+
17+
// @public
18+
export interface CacheSettings {
19+
// (undocumented)
20+
maxSizeBytes: number;
21+
// (undocumented)
22+
storage: DataConnectStorage;
23+
}
24+
1425
// @public
1526
export type CallerSdkType = 'Base' | 'Generated' | 'TanstackReactCore' | 'GeneratedReact' | 'TanstackAngularCore' | 'GeneratedAngular';
1627

@@ -98,7 +109,7 @@ export interface DataConnectOperationFailureResponseErrorInfo {
98109
}
99110

100111
// @public
101-
export interface DataConnectOptions extends ConnectorConfig {
112+
export interface DataConnectOptions extends ConnectorConfig, DataConnectSettings {
102113
// (undocumented)
103114
projectId: string;
104115
}
@@ -109,6 +120,15 @@ export interface DataConnectResult<Data, Variables> extends OpResult<Data> {
109120
ref: OperationRef<Data, Variables>;
110121
}
111122

123+
// @public (undocumented)
124+
export interface DataConnectSettings {
125+
// (undocumented)
126+
cacheSettings?: CacheSettings;
127+
}
128+
129+
// @public (undocumented)
130+
export type DataConnectStorage = typeof Memory | typeof Persistent;
131+
112132
// @public
113133
export interface DataConnectSubscription<Data, Variables> {
114134
// (undocumented)
@@ -126,13 +146,28 @@ export type DataSource = typeof SOURCE_CACHE | typeof SOURCE_SERVER;
126146
export function executeMutation<Data, Variables>(mutationRef: MutationRef<Data, Variables>): MutationPromise<Data, Variables>;
127147

128148
// @public
129-
export function executeQuery<Data, Variables>(queryRef: QueryRef<Data, Variables>): QueryPromise<Data, Variables>;
149+
export function executeQuery<Data, Variables>(queryRef: QueryRef<Data, Variables>, options?: ExecuteQueryOptions): QueryPromise<Data, Variables>;
150+
151+
// @public (undocumented)
152+
export interface ExecuteQueryOptions {
153+
// (undocumented)
154+
fetchPolicy: QueryFetchPolicy;
155+
}
130156

131157
// @public
158+
export function getDataConnect(options: ConnectorConfig, settings?: DataConnectSettings): DataConnect;
159+
160+
// @public (undocumented)
132161
export function getDataConnect(options: ConnectorConfig): DataConnect;
133162

134163
// @public
135-
export function getDataConnect(app: FirebaseApp, options: ConnectorConfig): DataConnect;
164+
export function getDataConnect(app: FirebaseApp, connectorConfig: ConnectorConfig): DataConnect;
165+
166+
// @public
167+
export function getDataConnect(app: FirebaseApp, connectorConfig: ConnectorConfig, settings: DataConnectSettings): DataConnect;
168+
169+
// @public (undocumented)
170+
export const Memory = "memory";
136171

137172
// @public (undocumented)
138173
export const MUTATION_STR = "mutation";
@@ -190,9 +225,18 @@ export interface OpResult<Data> {
190225
source: DataSource;
191226
}
192227

228+
// @public (undocumented)
229+
export const Persistent = "persistent";
230+
231+
// @public (undocumented)
232+
export const PreferCache = "preferCache";
233+
193234
// @public (undocumented)
194235
export const QUERY_STR = "query";
195236

237+
// @public (undocumented)
238+
export type QueryFetchPolicy = typeof PreferCache | typeof CacheOnly | typeof ServerOnly;
239+
196240
// @public
197241
export interface QueryPromise<Data, Variables> extends Promise<QueryResult<Data, Variables>> {
198242
}
@@ -239,6 +283,9 @@ export interface SerializedRef<Data, Variables> extends OpResult<Data> {
239283
refInfo: RefInfo<Variables>;
240284
}
241285

286+
// @public (undocumented)
287+
export const ServerOnly = "serverOnly";
288+
242289
// @public (undocumented)
243290
export function setLogLevel(logLevel: LogLevelString): void;
244291

common/api-review/util.api.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,11 @@ export class FirebaseError extends Error {
221221
// @public
222222
export type FirebaseSignInProvider = 'custom' | 'email' | 'password' | 'phone' | 'anonymous' | 'google.com' | 'facebook.com' | 'github.com' | 'twitter.com' | 'microsoft.com' | 'apple.com';
223223

224+
// Warning: (ae-missing-release-tag) "generateSHA256HashBrowser" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
225+
//
226+
// @public (undocumented)
227+
export function generateSHA256HashBrowser(input: string): Promise<string>;
228+
224229
// @public
225230
export const getDefaultAppConfig: () => Record<string, string> | undefined;
226231

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

Lines changed: 1 addition & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -15,94 +15,4 @@
1515
* limitations under the License.
1616
*/
1717

18-
import {
19-
OnCompleteSubscription,
20-
OnErrorSubscription,
21-
OnResultSubscription,
22-
QueryRef,
23-
QueryUnsubscribe,
24-
SubscriptionOptions,
25-
toQueryRef
26-
} from './api/query';
27-
import { OpResult, SerializedRef } from './api/Reference';
28-
import { DataConnectError, Code } from './core/error';
29-
30-
/**
31-
* Subscribe to a `QueryRef`
32-
* @param queryRefOrSerializedResult query ref or serialized result.
33-
* @param observer observer object to use for subscribing.
34-
* @returns `SubscriptionOptions`
35-
*/
36-
export function subscribe<Data, Variables>(
37-
queryRefOrSerializedResult:
38-
| QueryRef<Data, Variables>
39-
| SerializedRef<Data, Variables>,
40-
observer: SubscriptionOptions<Data, Variables>
41-
): QueryUnsubscribe;
42-
/**
43-
* Subscribe to a `QueryRef`
44-
* @param queryRefOrSerializedResult query ref or serialized result.
45-
* @param onNext Callback to call when result comes back.
46-
* @param onError Callback to call when error gets thrown.
47-
* @param onComplete Called when subscription completes.
48-
* @returns `SubscriptionOptions`
49-
*/
50-
export function subscribe<Data, Variables>(
51-
queryRefOrSerializedResult:
52-
| QueryRef<Data, Variables>
53-
| SerializedRef<Data, Variables>,
54-
onNext: OnResultSubscription<Data, Variables>,
55-
onError?: OnErrorSubscription,
56-
onComplete?: OnCompleteSubscription
57-
): QueryUnsubscribe;
58-
/**
59-
* Subscribe to a `QueryRef`
60-
* @param queryRefOrSerializedResult query ref or serialized result.
61-
* @param observerOrOnNext observer object or next function.
62-
* @param onError Callback to call when error gets thrown.
63-
* @param onComplete Called when subscription completes.
64-
* @returns `SubscriptionOptions`
65-
*/
66-
export function subscribe<Data, Variables>(
67-
queryRefOrSerializedResult:
68-
| QueryRef<Data, Variables>
69-
| SerializedRef<Data, Variables>,
70-
observerOrOnNext:
71-
| SubscriptionOptions<Data, Variables>
72-
| OnResultSubscription<Data, Variables>,
73-
onError?: OnErrorSubscription,
74-
onComplete?: OnCompleteSubscription
75-
): QueryUnsubscribe {
76-
let ref: QueryRef<Data, Variables>;
77-
let initialCache: OpResult<Data> | undefined;
78-
if ('refInfo' in queryRefOrSerializedResult) {
79-
const serializedRef: SerializedRef<Data, Variables> =
80-
queryRefOrSerializedResult;
81-
const { data, source, fetchTime } = serializedRef;
82-
initialCache = {
83-
data,
84-
source,
85-
fetchTime
86-
};
87-
ref = toQueryRef(serializedRef);
88-
} else {
89-
ref = queryRefOrSerializedResult;
90-
}
91-
let onResult: OnResultSubscription<Data, Variables> | undefined = undefined;
92-
if (typeof observerOrOnNext === 'function') {
93-
onResult = observerOrOnNext;
94-
} else {
95-
onResult = observerOrOnNext.onNext;
96-
onError = observerOrOnNext.onErr;
97-
onComplete = observerOrOnNext.onComplete;
98-
}
99-
if (!onResult) {
100-
throw new DataConnectError(Code.INVALID_ARGUMENT, 'Must provide onNext');
101-
}
102-
return ref.dataConnect._queryManager.addSubscription(
103-
ref,
104-
onResult,
105-
onError,
106-
initialCache
107-
);
108-
}
18+
export * from './core/query/subscribe';

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

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ import {
3030
updateEmulatorBanner
3131
} from '@firebase/util';
3232

33-
import { Cache as DataConnectCache } from '../cache/Cache';
33+
import { CacheSettings, DataConnectCache, InMemoryCacheProvider } from '../cache/Cache';
3434
import { AppCheckTokenProvider } from '../core/AppCheckTokenProvider';
3535
import { Code, DataConnectError } from '../core/error';
3636
import {
3737
AuthTokenProvider,
3838
FirebaseAuthProvider
3939
} from '../core/FirebaseAuthProvider';
40-
import { QueryManager } from '../core/QueryManager';
40+
import { QueryManager } from '../core/query/QueryManager';
4141
import { logDebug, logError } from '../logger';
4242
import {
4343
CallerSdkType,
@@ -46,8 +46,11 @@ import {
4646
TransportClass
4747
} from '../network';
4848
import { RESTTransport } from '../network/transport/rest';
49+
import { PROD_HOST } from '../util/url';
4950

5051
import { MutationManager } from './Mutation';
52+
import { IndexedDBCacheProvider } from '../cache/IndexedDBCacheProvider';
53+
import { CacheProvider } from '../cache/CacheProvider';
5154

5255
/**
5356
* Connector Config for calling Data Connect backend.
@@ -86,7 +89,7 @@ export function parseOptions(fullHost: string): TransportOptions {
8689
/**
8790
* DataConnectOptions including project id
8891
*/
89-
export interface DataConnectOptions extends ConnectorConfig, DataConnectInitOptions {
92+
export interface DataConnectOptions extends ConnectorConfig, DataConnectSettings {
9093
projectId: string;
9194
}
9295

@@ -122,7 +125,6 @@ export class DataConnect {
122125
this._transportOptions = parseOptions(host);
123126
}
124127
}
125-
this.cache = new DataConnectCache(this.dataConnectOptions.cacheSettings);
126128
}
127129
// @internal
128130
_useGeneratedSdk(): void {
@@ -168,16 +170,23 @@ export class DataConnect {
168170
this.app.options,
169171
this._authProvider
170172
);
171-
this.cache.setAuthProvider(this._authTokenProvider);
173+
174+
172175
}
176+
const connectorConfig: ConnectorConfig = {
177+
connector: this.dataConnectOptions.connector,
178+
service: this.dataConnectOptions.service,
179+
location: this.dataConnectOptions.location
180+
};
181+
this.cache = new DataConnectCache(this._authTokenProvider, this.app.options.projectId, connectorConfig, this._transportOptions.host || PROD_HOST, this.dataConnectOptions.cacheSettings);
182+
this.cache.setAuthProvider(this._authTokenProvider);
173183
if (this._appCheckProvider) {
174184
this._appCheckTokenProvider = new AppCheckTokenProvider(
175185
this.app,
176186
this._appCheckProvider
177187
);
178188
}
179189

180-
this._initialized = true;
181190
this._transport = new this._transportClass(
182191
this.dataConnectOptions,
183192
this.app.options.apiKey,
@@ -195,8 +204,10 @@ export class DataConnect {
195204
this._transportOptions.sslEnabled
196205
);
197206
}
207+
198208
this._queryManager = new QueryManager(this._transport, this.cache, this);
199209
this._mutationManager = new MutationManager(this._transport);
210+
this._initialized = true;
200211
}
201212

202213
// @internal
@@ -255,26 +266,36 @@ export function connectDataConnectEmulator(
255266
dc.enableEmulator({ host, port, sslEnabled });
256267
}
257268

258-
// TODO: Can we do something to make sure that this is more tree-shakable?
259-
export enum Storage {
260-
memory,
261-
persistent
269+
export type CacheProviderImpl = PublicIndexedDbProvider | PublicEphemeralDbProvider;
270+
271+
class PublicIndexedDbProvider {
272+
273+
/**
274+
* @internal
275+
*/
276+
initializeProvider(cacheId: string): CacheProvider {
277+
return new IndexedDBCacheProvider(cacheId);
278+
}
262279
}
263280

264-
export interface CacheSettings {
265-
storage: Storage;
266-
maxSizeBytes: number;
281+
class PublicEphemeralDbProvider {
282+
/**
283+
* @internal
284+
*/
285+
initializeProvider(cacheId: string): CacheProvider {
286+
return new InMemoryCacheProvider(cacheId);
287+
}
267288
}
268289

269-
export interface DataConnectInitOptions {
270-
cacheSettings?: CacheSettings;
290+
export interface DataConnectSettings {
291+
cacheSettings?: CacheProviderImpl;
271292
}
272293

273294
/**
274295
* Initialize DataConnect instance
275296
* @param options ConnectorConfig
276297
*/
277-
export function getDataConnect(options: ConnectorConfig, extraOptions?: DataConnectInitOptions): DataConnect;
298+
export function getDataConnect(options: ConnectorConfig, settings?: DataConnectSettings): DataConnect;
278299
export function getDataConnect(options: ConnectorConfig): DataConnect;
279300
/**
280301
* Initialize DataConnect instance
@@ -294,36 +315,39 @@ export function getDataConnect(
294315
export function getDataConnect(
295316
app: FirebaseApp,
296317
connectorConfig: ConnectorConfig,
297-
extraOptions: DataConnectInitOptions
318+
settings: DataConnectSettings
298319
): DataConnect;
299320

300321
export function getDataConnect(
301322
appOrConnectorConfig: FirebaseApp | ConnectorConfig,
302-
optionsOrConnectorConfig?: ConnectorConfig | DataConnectInitOptions,
303-
extraOptions?: DataConnectInitOptions
323+
settingsOrConnectorConfig?: ConnectorConfig | DataConnectSettings,
324+
settings?: DataConnectSettings
304325
): DataConnect {
305326
let app: FirebaseApp;
306327
let connectorConfig: ConnectorConfig;
307-
let options: DataConnectInitOptions;
328+
let realSettings: DataConnectSettings;
308329
if ('location' in appOrConnectorConfig) {
309330
connectorConfig = appOrConnectorConfig;
310331
app = getApp();
311-
options = optionsOrConnectorConfig as DataConnectInitOptions;
332+
realSettings = settingsOrConnectorConfig as DataConnectSettings;
312333
} else {
313334
app = appOrConnectorConfig;
314-
connectorConfig = optionsOrConnectorConfig as ConnectorConfig;
315-
options = extraOptions as DataConnectInitOptions;
335+
connectorConfig = settingsOrConnectorConfig as ConnectorConfig;
336+
realSettings = settings as DataConnectSettings;
316337
}
317338

318-
const dcOptions = {
319-
...options,
320-
connectorConfig
321-
};
339+
322340

323341
if (!app || Object.keys(app).length === 0) {
324342
app = getApp();
325343
}
344+
const dcOptions: DataConnectOptions = {
345+
...realSettings,
346+
...connectorConfig,
347+
projectId: app.options.projectId
348+
};
326349
const provider = _getProvider(app, 'data-connect');
350+
// TODO: Deal with the parsing of these options properly.
327351
const identifier = JSON.stringify(dcOptions);
328352
if (provider.isInitialized(identifier)) {
329353
const dcInstance = provider.getImmediate({ identifier });

0 commit comments

Comments
 (0)