Skip to content

Commit 5e4f80b

Browse files
committed
Migrate firestore to component framework (#2329)
* Migrate Firestore to component framework * [AUTOMATED]: Prettier Code Styling * remove unused import * removed unnecessary type assertion * update getImmeidate call
1 parent b1d6d10 commit 5e4f80b

File tree

7 files changed

+81
-44
lines changed

7 files changed

+81
-44
lines changed

packages/firestore/index.node.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,11 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
1817
import firebase from '@firebase/app';
19-
import { FirebaseNamespace } from '@firebase/app-types';
2018
import * as types from '@firebase/firestore-types';
2119
import { configureForFirebase } from './src/platform/config';
2220
import './src/platform_node/node_init';
21+
import { FirebaseNamespace } from '@firebase/app-types';
2322

2423
export function registerFirestore(instance: FirebaseNamespace): void {
2524
configureForFirebase(instance);

packages/firestore/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616
*/
1717

1818
import firebase from '@firebase/app';
19-
import { FirebaseNamespace } from '@firebase/app-types';
20-
import { Firestore } from './src/api/database';
2119
import { configureForFirebase } from './src/platform/config';
2220
import './src/platform_browser/browser_init';
2321

2422
import * as types from '@firebase/firestore-types';
23+
import { FirebaseNamespace } from '@firebase/app-types';
2524

2625
export function registerFirestore(instance: FirebaseNamespace): void {
2726
configureForFirebase(instance);

packages/firestore/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"@firebase/webchannel-wrapper": "0.2.29",
3636
"@grpc/proto-loader": "^0.5.0",
3737
"@firebase/util": "0.2.31",
38+
"@firebase/component": "0.1.0",
3839
"grpc": "1.24.1",
3940
"tslib": "1.10.0"
4041
},

packages/firestore/src/api/credentials.ts

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@
1515
* limitations under the License.
1616
*/
1717

18-
import { FirebaseApp } from '@firebase/app-types';
1918
import { _FirebaseApp } from '@firebase/app-types/private';
2019
import { User } from '../auth/user';
2120
import { assert } from '../util/assert';
2221
import { Code, FirestoreError } from '../util/error';
22+
import { FirebaseAuthInternal } from '@firebase/auth-interop-types';
23+
import { Provider } from '@firebase/component';
2324

2425
// TODO(mikelehen): This should be split into multiple files and probably
2526
// moved to an auth/ folder to match other platforms.
@@ -148,7 +149,9 @@ export class FirebaseCredentialsProvider implements CredentialsProvider {
148149

149150
private forceRefresh = false;
150151

151-
constructor(private readonly app: FirebaseApp) {
152+
private auth: FirebaseAuthInternal | null;
153+
154+
constructor(authProvider: Provider<FirebaseAuthInternal>) {
152155
this.tokenListener = () => {
153156
this.tokenCounter++;
154157
this.currentUser = this.getUser();
@@ -160,10 +163,26 @@ export class FirebaseCredentialsProvider implements CredentialsProvider {
160163

161164
this.tokenCounter = 0;
162165

163-
// Will fire at least once where we set this.currentUser
164-
(this.app as _FirebaseApp).INTERNAL.addAuthTokenListener(
165-
this.tokenListener
166-
);
166+
this.auth = authProvider.getImmediate({ optional: true });
167+
168+
if (this.auth) {
169+
this.auth.addAuthTokenListener(this.tokenListener!);
170+
} else {
171+
// if auth is not available, invoke tokenListener once with null token
172+
this.tokenListener(null);
173+
authProvider.get().then(
174+
auth => {
175+
this.auth = auth;
176+
if (this.tokenListener) {
177+
// tokenListener can be removed by removeChangeListener()
178+
this.auth.addAuthTokenListener(this.tokenListener);
179+
}
180+
},
181+
() => {
182+
/* this.authProvider.get() never rejects */
183+
}
184+
);
185+
}
167186
}
168187

169188
getToken(): Promise<Token | null> {
@@ -178,29 +197,32 @@ export class FirebaseCredentialsProvider implements CredentialsProvider {
178197
const initialTokenCounter = this.tokenCounter;
179198
const forceRefresh = this.forceRefresh;
180199
this.forceRefresh = false;
181-
return (this.app as _FirebaseApp).INTERNAL.getToken(forceRefresh).then(
182-
tokenData => {
183-
// Cancel the request since the token changed while the request was
184-
// outstanding so the response is potentially for a previous user (which
185-
// user, we can't be sure).
186-
if (this.tokenCounter !== initialTokenCounter) {
187-
throw new FirestoreError(
188-
Code.ABORTED,
189-
'getToken aborted due to token change.'
200+
201+
if (!this.auth) {
202+
return Promise.resolve(null);
203+
}
204+
205+
return this.auth.getToken(forceRefresh).then(tokenData => {
206+
// Cancel the request since the token changed while the request was
207+
// outstanding so the response is potentially for a previous user (which
208+
// user, we can't be sure).
209+
if (this.tokenCounter !== initialTokenCounter) {
210+
throw new FirestoreError(
211+
Code.ABORTED,
212+
'getToken aborted due to token change.'
213+
);
214+
} else {
215+
if (tokenData) {
216+
assert(
217+
typeof tokenData.accessToken === 'string',
218+
'Invalid tokenData returned from getToken():' + tokenData
190219
);
220+
return new OAuthToken(tokenData.accessToken, this.currentUser);
191221
} else {
192-
if (tokenData) {
193-
assert(
194-
typeof tokenData.accessToken === 'string',
195-
'Invalid tokenData returned from getToken():' + tokenData
196-
);
197-
return new OAuthToken(tokenData.accessToken, this.currentUser);
198-
} else {
199-
return null;
200-
}
222+
return null;
201223
}
202224
}
203-
);
225+
});
204226
}
205227

206228
invalidateToken(): void {
@@ -223,9 +245,10 @@ export class FirebaseCredentialsProvider implements CredentialsProvider {
223245
this.changeListener !== null,
224246
'removeChangeListener() called when no listener registered'
225247
);
226-
(this.app as _FirebaseApp).INTERNAL.removeAuthTokenListener(
227-
this.tokenListener!
228-
);
248+
249+
if (this.auth) {
250+
this.auth.removeAuthTokenListener(this.tokenListener!);
251+
}
229252
this.tokenListener = null;
230253
this.changeListener = null;
231254
}
@@ -235,7 +258,7 @@ export class FirebaseCredentialsProvider implements CredentialsProvider {
235258
// This method should only be called in the AuthTokenListener callback
236259
// to guarantee to get the actual user.
237260
private getUser(): User {
238-
const currentUid = (this.app as _FirebaseApp).INTERNAL.getUid();
261+
const currentUid = this.auth && this.auth.getUid();
239262
assert(
240263
currentUid === null || typeof currentUid === 'string',
241264
'Received invalid UID: ' + currentUid

packages/firestore/src/api/database.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ import {
104104
fieldPathFromArgument,
105105
UserDataConverter
106106
} from './user_data_converter';
107+
import { FirebaseAuthInternal } from '@firebase/auth-interop-types';
108+
import { Provider } from '@firebase/component';
107109

108110
// settings() defaults:
109111
const DEFAULT_HOST = 'firestore.googleapis.com';
@@ -307,15 +309,18 @@ export class Firestore implements firestore.FirebaseFirestore, FirebaseService {
307309

308310
readonly _dataConverter: UserDataConverter;
309311

310-
constructor(databaseIdOrApp: FirestoreDatabase | FirebaseApp) {
312+
constructor(
313+
databaseIdOrApp: FirestoreDatabase | FirebaseApp,
314+
authProvider: Provider<FirebaseAuthInternal>
315+
) {
311316
if (typeof (databaseIdOrApp as FirebaseApp).options === 'object') {
312317
// This is very likely a Firebase app object
313318
// TODO(b/34177605): Can we somehow use instanceof?
314319
const app = databaseIdOrApp as FirebaseApp;
315320
this._firebaseApp = app;
316321
this._databaseId = Firestore.databaseIdFromApp(app);
317322
this._persistenceKey = app.name;
318-
this._credentials = new FirebaseCredentialsProvider(app);
323+
this._credentials = new FirebaseCredentialsProvider(authProvider);
319324
} else {
320325
const external = databaseIdOrApp as FirestoreDatabase;
321326
if (!external.projectId) {

packages/firestore/src/platform/config.ts

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

18-
import { FirebaseApp, FirebaseNamespace } from '@firebase/app-types';
18+
import { FirebaseNamespace } from '@firebase/app-types';
1919
import { _FirebaseNamespace } from '@firebase/app-types/private';
2020
import { PublicBlob } from '../api/blob';
2121
import {
@@ -36,6 +36,7 @@ import { PublicFieldValue } from '../api/field_value';
3636
import { GeoPoint } from '../api/geo_point';
3737
import { Timestamp } from '../api/timestamp';
3838
import { shallowCopy } from '../util/obj';
39+
import { Component, ComponentType } from '@firebase/component';
3940

4041
const firestoreNamespace = {
4142
Firestore: PublicFirestore,
@@ -60,10 +61,15 @@ const firestoreNamespace = {
6061
* Configures Firestore as part of the Firebase SDK by calling registerService.
6162
*/
6263
export function configureForFirebase(firebase: FirebaseNamespace): void {
63-
(firebase as _FirebaseNamespace).INTERNAL.registerService(
64-
'firestore',
65-
(app: FirebaseApp) => new Firestore(app),
66-
shallowCopy(firestoreNamespace)
64+
(firebase as _FirebaseNamespace).INTERNAL.registerComponent(
65+
new Component(
66+
'firestore',
67+
container => {
68+
const app = container.getProvider('app').getImmediate()!;
69+
return new Firestore(app, container.getProvider('auth-internal'));
70+
},
71+
ComponentType.PUBLIC
72+
).setServiceProps(shallowCopy(firestoreNamespace))
6773
);
6874
}
6975

packages/firestore/test/util/api_helpers.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,18 @@ import { Document } from '../../src/model/document';
3737
import { DocumentSet } from '../../src/model/document_set';
3838
import { JsonObject } from '../../src/model/field_value';
3939
import { doc, key, path as pathFrom } from './helpers';
40+
import { Provider, ComponentContainer } from '@firebase/component';
4041

4142
/**
4243
* A mock Firestore. Will not work for integration test.
4344
*/
44-
export const FIRESTORE = new Firestore({
45-
projectId: 'projectid',
46-
database: 'database'
47-
});
45+
export const FIRESTORE = new Firestore(
46+
{
47+
projectId: 'projectid',
48+
database: 'database'
49+
},
50+
new Provider('auth-interop', new ComponentContainer('default'))
51+
);
4852

4953
export function firestore(): Firestore {
5054
return FIRESTORE;

0 commit comments

Comments
 (0)