Skip to content

Commit 0168b15

Browse files
authored
feat(firestore): Exposed Firestore APIs from firebase-admin/firestore entry point (#1151)
1 parent 32edcac commit 0168b15

9 files changed

+270
-16
lines changed

etc/firebase-admin.api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ export interface FirebaseError {
334334
}
335335

336336
// @public (undocumented)
337-
export function firestore(app?: app.App): _firestore.Firestore;
337+
export function firestore(app?: App): _firestore.Firestore;
338338

339339
// @public (undocumented)
340340
export namespace firestore {

etc/firebase-admin.firestore.api.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
## API Report File for "firebase-admin.firestore"
2+
3+
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
4+
5+
```ts
6+
7+
import { Agent } from 'http';
8+
import { BulkWriter } from '@google-cloud/firestore';
9+
import { BulkWriterOptions } from '@google-cloud/firestore';
10+
import { CollectionGroup } from '@google-cloud/firestore';
11+
import { CollectionReference } from '@google-cloud/firestore';
12+
import { DocumentChangeType } from '@google-cloud/firestore';
13+
import { DocumentData } from '@google-cloud/firestore';
14+
import { DocumentReference } from '@google-cloud/firestore';
15+
import { DocumentSnapshot } from '@google-cloud/firestore';
16+
import { FieldPath } from '@google-cloud/firestore';
17+
import { FieldValue } from '@google-cloud/firestore';
18+
import { Firestore } from '@google-cloud/firestore';
19+
import * as _firestore from '@google-cloud/firestore';
20+
import { FirestoreDataConverter } from '@google-cloud/firestore';
21+
import { GeoPoint } from '@google-cloud/firestore';
22+
import { GrpcStatus } from '@google-cloud/firestore';
23+
import { Precondition } from '@google-cloud/firestore';
24+
import { Query } from '@google-cloud/firestore';
25+
import { QueryDocumentSnapshot } from '@google-cloud/firestore';
26+
import { QueryPartition } from '@google-cloud/firestore';
27+
import { QuerySnapshot } from '@google-cloud/firestore';
28+
import { ReadOptions } from '@google-cloud/firestore';
29+
import { setLogFunction } from '@google-cloud/firestore';
30+
import { Settings } from '@google-cloud/firestore';
31+
import { Timestamp } from '@google-cloud/firestore';
32+
import { Transaction } from '@google-cloud/firestore';
33+
import { UpdateData } from '@google-cloud/firestore';
34+
import { v1 } from '@google-cloud/firestore';
35+
import { WriteBatch } from '@google-cloud/firestore';
36+
import { WriteResult } from '@google-cloud/firestore';
37+
38+
export { BulkWriter }
39+
40+
export { BulkWriterOptions }
41+
42+
export { CollectionGroup }
43+
44+
export { CollectionReference }
45+
46+
export { DocumentChangeType }
47+
48+
export { DocumentData }
49+
50+
export { DocumentReference }
51+
52+
export { DocumentSnapshot }
53+
54+
export { FieldPath }
55+
56+
export { FieldValue }
57+
58+
export { Firestore }
59+
60+
// Warning: (ae-forgotten-export) The symbol "App" needs to be exported by the entry point index.d.ts
61+
//
62+
// @public (undocumented)
63+
export function firestore(app?: App): _firestore.Firestore;
64+
65+
// @public (undocumented)
66+
export namespace firestore {
67+
import v1beta1 = _firestore.v1beta1;
68+
import v1 = _firestore.v1;
69+
import BulkWriter = _firestore.BulkWriter;
70+
import BulkWriterOptions = _firestore.BulkWriterOptions;
71+
import CollectionGroup = _firestore.CollectionGroup;
72+
import CollectionReference = _firestore.CollectionReference;
73+
import DocumentChangeType = _firestore.DocumentChangeType;
74+
import DocumentData = _firestore.DocumentData;
75+
import DocumentReference = _firestore.DocumentReference;
76+
import DocumentSnapshot = _firestore.DocumentSnapshot;
77+
import FieldPath = _firestore.FieldPath;
78+
import FieldValue = _firestore.FieldValue;
79+
import Firestore = _firestore.Firestore;
80+
import FirestoreDataConverter = _firestore.FirestoreDataConverter;
81+
import GeoPoint = _firestore.GeoPoint;
82+
import GrpcStatus = _firestore.GrpcStatus;
83+
import Precondition = _firestore.Precondition;
84+
import Query = _firestore.Query;
85+
import QueryDocumentSnapshot = _firestore.QueryDocumentSnapshot;
86+
import QueryPartition = _firestore.QueryPartition;
87+
import QuerySnapshot = _firestore.QuerySnapshot;
88+
import ReadOptions = _firestore.ReadOptions;
89+
import Settings = _firestore.Settings;
90+
import Timestamp = _firestore.Timestamp;
91+
import Transaction = _firestore.Transaction;
92+
import UpdateData = _firestore.UpdateData;
93+
import WriteBatch = _firestore.WriteBatch;
94+
import WriteResult = _firestore.WriteResult;
95+
import setLogFunction = _firestore.setLogFunction;
96+
}
97+
98+
export { FirestoreDataConverter }
99+
100+
export { GeoPoint }
101+
102+
// @public (undocumented)
103+
export function getFirestore(app?: App): _firestore.Firestore;
104+
105+
export { GrpcStatus }
106+
107+
export { Precondition }
108+
109+
export { Query }
110+
111+
export { QueryDocumentSnapshot }
112+
113+
export { QueryPartition }
114+
115+
export { QuerySnapshot }
116+
117+
export { ReadOptions }
118+
119+
export { setLogFunction }
120+
121+
export { Settings }
122+
123+
export { Timestamp }
124+
125+
export { Transaction }
126+
127+
export { UpdateData }
128+
129+
export { v1 }
130+
131+
export { WriteBatch }
132+
133+
export { WriteResult }
134+
135+
136+
// (No @packageDocumentation comment for this package)
137+
138+
```

generate-reports.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const entryPoints = {
3737
'firebase-admin/app': './lib/app/index.d.ts',
3838
'firebase-admin/auth': './lib/auth/index.d.ts',
3939
'firebase-admin/database': './lib/database/index.d.ts',
40+
'firebase-admin/firestore': './lib/firestore/index.d.ts',
4041
'firebase-admin/instance-id': './lib/instance-id/index.d.ts',
4142
};
4243

gulpfile.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ gulp.task('compile', function() {
9090
'lib/app/*.d.ts',
9191
'lib/auth/*.d.ts',
9292
'lib/database/*.d.ts',
93+
'lib/firestore/*.d.ts',
9394
'lib/instance-id/*.d.ts',
9495
'!lib/utils/index.d.ts',
9596
];

src/app/firebase-app.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import { Messaging } from '../messaging/messaging';
2929
import { Storage } from '../storage/storage';
3030
import { Database } from '../database/index';
3131
import { Firestore } from '@google-cloud/firestore';
32-
import { FirestoreService } from '../firestore/firestore-internal';
3332
import { InstanceId } from '../instance-id/index';
3433
import { ProjectManagement } from '../project-management/project-management';
3534
import { SecurityRules } from '../security-rules/security-rules';
@@ -313,11 +312,8 @@ export class FirebaseApp implements app.App {
313312
}
314313

315314
public firestore(): Firestore {
316-
const service: FirestoreService = this.ensureService_('firestore', () => {
317-
const firestoreService: typeof FirestoreService = require('../firestore/firestore-internal').FirestoreService;
318-
return new firestoreService(this);
319-
});
320-
return service.client;
315+
const fn = require('../firestore/index').getFirestore;
316+
return fn(this);
321317
}
322318

323319
/**

src/firestore/firestore-internal.ts

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

18-
import { FirebaseApp } from '../app/firebase-app';
1918
import { FirebaseFirestoreError } from '../utils/error';
2019
import { ServiceAccountCredential, isApplicationDefault } from '../app/credential-internal';
2120
import { Firestore, Settings } from '@google-cloud/firestore';
2221

2322
import * as validator from '../utils/validator';
2423
import * as utils from '../utils/index';
24+
import { App } from '../app';
2525

2626
export class FirestoreService {
2727

28-
private appInternal: FirebaseApp;
28+
private appInternal: App;
2929
private firestoreClient: Firestore;
3030

31-
constructor(app: FirebaseApp) {
31+
constructor(app: App) {
3232
this.firestoreClient = initFirestore(app);
3333
this.appInternal = app;
3434
}
3535

3636
/**
3737
* Returns the app associated with this Storage instance.
3838
*
39-
* @return {FirebaseApp} The app associated with this Storage instance.
39+
* @return The app associated with this Storage instance.
4040
*/
41-
get app(): FirebaseApp {
41+
get app(): App {
4242
return this.appInternal;
4343
}
4444

@@ -47,7 +47,7 @@ export class FirestoreService {
4747
}
4848
}
4949

50-
export function getFirestoreOptions(app: FirebaseApp): Settings {
50+
export function getFirestoreOptions(app: App): Settings {
5151
if (!validator.isNonNullObject(app) || !('options' in app)) {
5252
throw new FirebaseFirestoreError({
5353
code: 'invalid-argument',
@@ -85,7 +85,7 @@ export function getFirestoreOptions(app: FirebaseApp): Settings {
8585
});
8686
}
8787

88-
function initFirestore(app: FirebaseApp): Firestore {
88+
function initFirestore(app: App): Firestore {
8989
const options = getFirestoreOptions(app);
9090
let firestoreDatabase: typeof Firestore;
9191
try {

src/firestore/index.ts

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,54 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { app } from '../firebase-namespace-api';
1817
import * as _firestore from '@google-cloud/firestore';
18+
import { App, getApp } from '../app';
19+
import { FirebaseApp } from '../app/firebase-app';
20+
import { FirestoreService } from './firestore-internal';
1921

20-
export declare function firestore(app?: app.App): _firestore.Firestore;
22+
export {
23+
BulkWriter,
24+
BulkWriterOptions,
25+
CollectionGroup,
26+
CollectionReference,
27+
DocumentChangeType,
28+
DocumentData,
29+
DocumentReference,
30+
DocumentSnapshot,
31+
FieldPath,
32+
FieldValue,
33+
Firestore,
34+
FirestoreDataConverter,
35+
GeoPoint,
36+
GrpcStatus,
37+
Precondition,
38+
Query,
39+
QueryDocumentSnapshot,
40+
QueryPartition,
41+
QuerySnapshot,
42+
ReadOptions,
43+
Settings,
44+
Timestamp,
45+
Transaction,
46+
UpdateData,
47+
WriteBatch,
48+
WriteResult,
49+
v1,
50+
setLogFunction,
51+
} from '@google-cloud/firestore';
52+
53+
export function getFirestore(app?: App): _firestore.Firestore {
54+
if (typeof app === 'undefined') {
55+
app = getApp();
56+
}
57+
58+
const firebaseApp: FirebaseApp = app as FirebaseApp;
59+
const firestoreService = firebaseApp.getOrInitService(
60+
'firestore', (app) => new FirestoreService(app));
61+
return firestoreService.client;
62+
}
63+
64+
export declare function firestore(app?: App): _firestore.Firestore;
2165

2266
/* eslint-disable @typescript-eslint/no-namespace */
2367
export namespace firestore {

test/unit/firestore/index.spec.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*!
2+
* @license
3+
* Copyright 2021 Google Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
'use strict';
19+
20+
import * as chai from 'chai';
21+
import * as sinonChai from 'sinon-chai';
22+
import * as chaiAsPromised from 'chai-as-promised';
23+
24+
import * as mocks from '../../resources/mocks';
25+
import { App } from '../../../src/app/index';
26+
import { getFirestore, Firestore } from '../../../src/firestore/index';
27+
28+
chai.should();
29+
chai.use(sinonChai);
30+
chai.use(chaiAsPromised);
31+
32+
const expect = chai.expect;
33+
34+
describe('Firestore', () => {
35+
let mockApp: App;
36+
let mockCredentialApp: App;
37+
38+
const noProjectIdError = 'Failed to initialize Google Cloud Firestore client with the '
39+
+ 'available credentials. Must initialize the SDK with a certificate credential or '
40+
+ 'application default credentials to use Cloud Firestore API.';
41+
42+
beforeEach(() => {
43+
mockApp = mocks.app();
44+
mockCredentialApp = mocks.mockCredentialApp();
45+
});
46+
47+
describe('getFirestore()', () => {
48+
it('should throw when default app is not available', () => {
49+
expect(() => {
50+
return getFirestore();
51+
}).to.throw('The default Firebase app does not exist.');
52+
});
53+
54+
it('should reject given an invalid credential without project ID', () => {
55+
// Project ID not set in the environment.
56+
delete process.env.GOOGLE_CLOUD_PROJECT;
57+
delete process.env.GCLOUD_PROJECT;
58+
expect(() => getFirestore(mockCredentialApp)).to.throw(noProjectIdError);
59+
});
60+
61+
it('should not throw given a valid app', () => {
62+
expect(() => {
63+
return getFirestore(mockApp);
64+
}).not.to.throw();
65+
});
66+
67+
it('should return the same instance for a given app instance', () => {
68+
const db1: Firestore = getFirestore(mockApp);
69+
const db2: Firestore = getFirestore(mockApp);
70+
expect(db1).to.equal(db2);
71+
});
72+
});
73+
});

test/unit/index.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ import './storage/storage.spec';
5858

5959
// Firestore
6060
import './firestore/firestore.spec';
61+
import './firestore/index.spec';
6162

6263
// InstanceId
6364
import './instance-id/index.spec';

0 commit comments

Comments
 (0)