Skip to content

Commit 94efee4

Browse files
WIP
1 parent 8846f61 commit 94efee4

File tree

11 files changed

+631
-118
lines changed

11 files changed

+631
-118
lines changed

packages/firestore/exp/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,6 @@ export interface FirestoreError {
487487

488488
declare module '@firebase/component' {
489489
interface NameServiceMapping {
490-
'firestore/lite': FirebaseFirestore;
490+
'firestore-exp': FirebaseFirestore;
491491
}
492492
}

packages/firestore/exp/index.node.ts

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

18+
import { version } from '../package.json';
19+
import { _registerComponent, registerVersion } from '@firebase/app-exp';
20+
import { Component, ComponentType } from '@firebase/component';
21+
import { Firestore } from './src/api/database';
22+
1823
export { FieldPath, documentId } from '../lite/src/api/field_path';
1924

25+
export {
26+
Firestore,
27+
initializeFirestore,
28+
getFirestore
29+
} from './src/api/database';
30+
31+
export { DocumentSnapshot, QueryDocumentSnapshot } from './src/api/snapshot';
32+
33+
export { SnapshotMetadata } from '../src/api/database';
34+
35+
export { DocumentReference, doc, collection } from '../lite/src/api/reference';
36+
37+
export { getDoc } from './src/api/reference';
38+
2039
export {
2140
FieldValue,
2241
deleteField,
@@ -33,3 +52,22 @@ export { Blob } from '../src/api/blob';
3352
export { GeoPoint } from '../src/api/geo_point';
3453

3554
export { Timestamp } from '../src/api/timestamp';
55+
56+
export function registerFirestore(): void {
57+
_registerComponent(
58+
new Component(
59+
'firestore-exp',
60+
container => {
61+
const app = container.getProvider('app-exp').getImmediate()!;
62+
return ((app, auth) => new Firestore(app, auth))(
63+
app,
64+
container.getProvider('auth-internal')
65+
);
66+
},
67+
ComponentType.PUBLIC
68+
)
69+
);
70+
registerVersion('firestore-exp', version, 'node');
71+
}
72+
73+
registerFirestore();
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/**
2+
* @license
3+
* Copyright 2020 Google LLC
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+
import * as firestore from '../../index';
19+
20+
import { _getProvider } from '@firebase/app-exp';
21+
import { FirebaseApp, _FirebaseService } from '@firebase/app-types-exp';
22+
import { Provider } from '@firebase/component';
23+
24+
import { FirebaseAuthInternalName } from '@firebase/auth-interop-types';
25+
import { FirestoreClient } from '../../../src/core/firestore_client';
26+
import { AsyncQueue } from '../../../src/util/async_queue';
27+
import {
28+
ComponentProvider,
29+
MemoryComponentProvider
30+
} from '../../../src/core/component_provider';
31+
32+
import { Firestore as LiteFirestore } from '../../../lite/src/api/database';
33+
34+
/**
35+
* The root reference to the Firestore Lite database.
36+
*/
37+
export class Firestore extends LiteFirestore
38+
implements firestore.FirebaseFirestore, _FirebaseService {
39+
private readonly _queue = new AsyncQueue();
40+
private _componentProvider: ComponentProvider = new MemoryComponentProvider();
41+
private readonly _persistenceKey: string;
42+
43+
// Assigned via _configureClient()
44+
protected _settings?: firestore.Settings;
45+
private _firestoreClientPromise?: Promise<FirestoreClient>;
46+
47+
constructor(
48+
app: FirebaseApp,
49+
authProvider: Provider<FirebaseAuthInternalName>
50+
) {
51+
super(app, authProvider);
52+
this._persistenceKey = app.name;
53+
}
54+
55+
_getSettings(): firestore.Settings {
56+
if (!this._settings) {
57+
this._settings = {};
58+
}
59+
return this._settings;
60+
}
61+
62+
_getFirestoreClient(): Promise<FirestoreClient> {
63+
if (!this._firestoreClientPromise) {
64+
const settings = this._getSettings();
65+
const databaseInfo = this._makeDatabaseInfo(
66+
settings.host,
67+
settings.ssl,
68+
settings.experimentalForceLongPolling
69+
);
70+
71+
const firestoreClient = new FirestoreClient(
72+
databaseInfo,
73+
this._credentials,
74+
this._queue
75+
);
76+
77+
this._firestoreClientPromise = firestoreClient
78+
.start(this._componentProvider, { durable: false })
79+
.then(() => firestoreClient);
80+
}
81+
82+
return this._firestoreClientPromise;
83+
}
84+
85+
async delete(): Promise<void> {
86+
// TODO(firestoreexp): Call terminate() once implemented
87+
}
88+
}
89+
90+
export function initializeFirestore(
91+
app: FirebaseApp,
92+
settings: firestore.Settings
93+
): Firestore {
94+
const firestore = _getProvider(
95+
app,
96+
'firestore-exp'
97+
).getImmediate() as Firestore;
98+
firestore._configureClient(settings);
99+
return firestore;
100+
}
101+
102+
export function getFirestore(app: FirebaseApp): Firestore {
103+
return _getProvider(app, 'firestore-exp').getImmediate() as Firestore;
104+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/**
2+
* @license
3+
* Copyright 2020 Google LLC
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+
import * as firestore from '../../index';
19+
20+
import { Firestore } from './database';
21+
import { DocumentKeyReference } from '../../../src/api/user_data_reader';
22+
import { debugAssert } from '../../../src/util/assert';
23+
import { cast } from '../../../lite/src/api/util';
24+
import { DocumentSnapshot } from './snapshot';
25+
import { Rejecter, Resolver } from '../../../src/util/promise';
26+
import {
27+
getDocViaSnapshotListener,
28+
SnapshotMetadata
29+
} from '../../../src/api/database';
30+
import { ViewSnapshot } from '../../../src/core/view_snapshot';
31+
import { DocumentReference } from '../../../lite/src/api/reference';
32+
33+
export function getDoc<T>(
34+
reference: firestore.DocumentReference<T>
35+
): Promise<firestore.DocumentSnapshot<T>> {
36+
const ref = cast<DocumentReference<T>>(reference, DocumentReference);
37+
const firestore = cast<Firestore>(ref.firestore, Firestore);
38+
return firestore._getFirestoreClient().then(async firestoreClient => {
39+
return new Promise(
40+
(resolve: Resolver<firestore.DocumentSnapshot<T>>, reject: Rejecter) => {
41+
getDocViaSnapshotListener(
42+
firestoreClient,
43+
ref,
44+
async snapshot => {
45+
const viewSnapshot = await snapshot;
46+
resolve(
47+
viewSnapshot
48+
? convertToDocSnapshot(viewSnapshot, firestore, ref)
49+
: undefined
50+
);
51+
},
52+
reject
53+
);
54+
}
55+
);
56+
});
57+
}
58+
59+
function convertToDocSnapshot<T>(
60+
snapshot: ViewSnapshot,
61+
firestore: Firestore,
62+
ref: DocumentKeyReference<T>
63+
): DocumentSnapshot<T> {
64+
debugAssert(
65+
snapshot.docs.size <= 1,
66+
'Too many documents returned on a document query'
67+
);
68+
const doc = snapshot.docs.get(ref._key);
69+
70+
return new DocumentSnapshot(
71+
firestore,
72+
ref._key,
73+
doc,
74+
ref._converter,
75+
new SnapshotMetadata(snapshot.hasPendingWrites, snapshot.fromCache)
76+
);
77+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/**
2+
* @license
3+
* Copyright 2020 Google LLC
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+
import * as firestore from '../../index';
19+
20+
import { DocumentKey } from '../../../src/model/document_key';
21+
import { Document } from '../../../src/model/document';
22+
import {
23+
ServerTimestampBehavior,
24+
UserDataWriter
25+
} from '../../../src/api/user_data_writer';
26+
import {
27+
fieldPathFromArgument,
28+
DocumentSnapshot as LiteDocumentSnapshot
29+
} from '../../../lite/src/api/snapshot';
30+
import { Firestore } from './database';
31+
import { cast } from '../../../lite/src/api/util';
32+
import { DocumentReference } from '../../../lite/src/api/reference';
33+
34+
const DEFAULT_SERVER_TIMESTAMP_BEHAVIOR: ServerTimestampBehavior = 'none';
35+
36+
export class DocumentSnapshot<T = firestore.DocumentData>
37+
extends LiteDocumentSnapshot<T>
38+
implements firestore.DocumentSnapshot<T> {
39+
private readonly _firestoreImpl: Firestore;
40+
41+
constructor(
42+
readonly _firestore: Firestore,
43+
key: DocumentKey,
44+
document: Document | null,
45+
converter: firestore.FirestoreDataConverter<T> | null,
46+
readonly metadata: firestore.SnapshotMetadata
47+
) {
48+
super(_firestore, key, document, converter);
49+
this._firestoreImpl = cast(firestore, Firestore);
50+
}
51+
52+
exists(): this is firestore.QueryDocumentSnapshot<T> {
53+
return super.exists();
54+
}
55+
56+
data(options: firestore.SnapshotOptions = {}): T | undefined {
57+
if (!this._document) {
58+
return undefined;
59+
} else if (this._converter) {
60+
// We only want to use the converter and create a new DocumentSnapshot
61+
// if a converter has been provided.
62+
const snapshot = new QueryDocumentSnapshot(
63+
this._firestore,
64+
this._key,
65+
this._document,
66+
/* converter= */ null,
67+
this.metadata
68+
);
69+
return this._converter.fromFirestore(snapshot);
70+
} else {
71+
const userDataWriter = new UserDataWriter(
72+
this._firestoreImpl._databaseId,
73+
/* timestampsInSnapshots= */ true,
74+
options.serverTimestamps || DEFAULT_SERVER_TIMESTAMP_BEHAVIOR,
75+
key =>
76+
new DocumentReference(this._firestore, key, /* converter= */ null)
77+
);
78+
return userDataWriter.convertValue(this._document.toProto()) as T;
79+
}
80+
}
81+
82+
get(
83+
fieldPath: string | firestore.FieldPath,
84+
options: firestore.SnapshotOptions = {}
85+
): unknown {
86+
if (this._document) {
87+
const value = this._document
88+
.data()
89+
.field(fieldPathFromArgument('DocumentSnapshot.get', fieldPath));
90+
if (value !== null) {
91+
const userDataWriter = new UserDataWriter(
92+
this._firestoreImpl._databaseId,
93+
/* timestampsInSnapshots= */ true,
94+
options.serverTimestamps || DEFAULT_SERVER_TIMESTAMP_BEHAVIOR,
95+
key => new DocumentReference(this._firestore, key, this._converter)
96+
);
97+
return userDataWriter.convertValue(value);
98+
}
99+
}
100+
return undefined;
101+
}
102+
}
103+
104+
export class QueryDocumentSnapshot<T = firestore.DocumentData>
105+
extends DocumentSnapshot<T>
106+
implements firestore.QueryDocumentSnapshot<T> {
107+
data(options?: firestore.SnapshotOptions): T {
108+
return super.data(options) as T;
109+
}
110+
}

packages/firestore/exp/test/deps/verify_dependencies.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@ import { expect } from 'chai';
2020
import { extractDependencies } from '../../../../../scripts/exp/extract-deps.helpers';
2121

2222
import * as dependencies from './dependencies.json';
23-
import * as pkg from '../../../package.json';
23+
import * as pkg from '../../package.json';
2424
import { forEach } from '../../../src/util/obj';
2525

2626
// TODO(firestorexp): Enable test
2727
// eslint-disable-next-line no-restricted-properties
2828
describe.skip('Dependencies', () => {
2929
forEach(dependencies, (api, { dependencies }) => {
3030
it(api, () => {
31-
return extractDependencies(api, pkg.exp).then(extractedDependencies => {
31+
return extractDependencies(api, pkg.main).then(extractedDependencies => {
3232
expect(extractedDependencies.classes).to.have.members(
3333
dependencies.classes,
3434
'for classes'

0 commit comments

Comments
 (0)