@@ -20,6 +20,12 @@ import * as firestore from '../../index';
20
20
import { DocumentKey } from '../../../src/model/document_key' ;
21
21
import { Firestore } from './database' ;
22
22
import { DocumentKeyReference } from '../../../src/api/user_data_reader' ;
23
+ import { Query as InternalQuery } from '../../../src/core/query' ;
24
+ import { FirebaseFirestore , FirestoreDataConverter } from '../../index' ;
25
+ import { ResourcePath } from '../../../src/model/path' ;
26
+ import { Code , FirestoreError } from '../../../src/util/error' ;
27
+ import { AutoId } from '../../../src/util/misc' ;
28
+ import { tryCast } from './util' ;
23
29
24
30
/**
25
31
* A reference to a particular document in a collection in the database.
@@ -49,3 +55,222 @@ export class DocumentReference<T = firestore.DocumentData>
49
55
return new DocumentReference < U > ( this . firestore , this . _key , converter ) ;
50
56
}
51
57
}
58
+
59
+ export class Query < T = firestore . DocumentData > implements firestore . Query < T > {
60
+ constructor (
61
+ readonly firestore : Firestore ,
62
+ readonly _query : InternalQuery ,
63
+ readonly _converter ?: FirestoreDataConverter < T >
64
+ ) { }
65
+
66
+ where (
67
+ fieldPath : string | firestore . FieldPath ,
68
+ opStr : firestore . WhereFilterOp ,
69
+ value : unknown
70
+ ) : firestore . Query < T > {
71
+ // TODO(firestorelite): Implement
72
+ throw new Error ( 'Not implemented' ) ;
73
+ }
74
+
75
+ orderBy (
76
+ fieldPath : string | firestore . FieldPath ,
77
+ directionStr ?: firestore . OrderByDirection
78
+ ) : firestore . Query < T > {
79
+ // TODO(firestorelite): Implement
80
+ throw new Error ( 'Not implemented' ) ;
81
+ }
82
+
83
+ limit ( limit : number ) : firestore . Query < T > {
84
+ // TODO(firestorelite): Implement
85
+ throw new Error ( 'Not implemented' ) ;
86
+ }
87
+
88
+ limitToLast ( limit : number ) : firestore . Query < T > {
89
+ // TODO(firestorelite): Implement
90
+ throw new Error ( 'Not implemented' ) ;
91
+ }
92
+
93
+ startAfter (
94
+ docOrField : unknown | firestore . DocumentSnapshot < unknown > ,
95
+ ...fields : unknown [ ]
96
+ ) : firestore . Query < T > {
97
+ // TODO(firestorelite): Implement
98
+ throw new Error ( 'Not implemented' ) ;
99
+ }
100
+
101
+ startAt (
102
+ docOrField : unknown | firestore . DocumentSnapshot < unknown > ,
103
+ ...fields : unknown [ ]
104
+ ) : firestore . Query < T > {
105
+ // TODO(firestorelite): Implement
106
+ throw new Error ( 'Not implemented' ) ;
107
+ }
108
+
109
+ endAt (
110
+ docOrField : unknown | firestore . DocumentSnapshot < unknown > ,
111
+ ...fields : unknown [ ]
112
+ ) : firestore . Query < T > {
113
+ // TODO(firestorelite): Implement
114
+ throw new Error ( 'Not implemented' ) ;
115
+ }
116
+
117
+ endBefore (
118
+ docOrField : unknown | firestore . DocumentSnapshot < unknown > ,
119
+ ...fields : unknown [ ]
120
+ ) : firestore . Query < T > {
121
+ // TODO(firestorelite): Implement
122
+ throw new Error ( 'Not implemented' ) ;
123
+ }
124
+
125
+ withConverter < U > (
126
+ converter : firestore . FirestoreDataConverter < U >
127
+ ) : firestore . Query < U > {
128
+ return new Query < U > ( this . firestore , this . _query , converter ) ;
129
+ }
130
+ }
131
+
132
+ export class CollectionReference < T = firestore . DocumentData > extends Query < T >
133
+ implements firestore . CollectionReference < T > {
134
+ constructor (
135
+ readonly firestore : Firestore ,
136
+ readonly _path : ResourcePath ,
137
+ readonly _converter ?: firestore . FirestoreDataConverter < T >
138
+ ) {
139
+ super ( firestore , InternalQuery . atPath ( _path ) , _converter ) ;
140
+ }
141
+
142
+ get id ( ) : string {
143
+ return this . _query . path . lastSegment ( ) ;
144
+ }
145
+
146
+ get path ( ) : string {
147
+ return this . _query . path . canonicalString ( ) ;
148
+ }
149
+
150
+ withConverter < U > (
151
+ converter : firestore . FirestoreDataConverter < U >
152
+ ) : firestore . CollectionReference < U > {
153
+ return new CollectionReference < U > ( this . firestore , this . _path , converter ) ;
154
+ }
155
+ }
156
+
157
+ export function collection (
158
+ firestore : FirebaseFirestore ,
159
+ collectionPath : string
160
+ ) : CollectionReference < firestore . DocumentData > ;
161
+ export function collection (
162
+ reference : DocumentReference ,
163
+ collectionPath : string
164
+ ) : CollectionReference < firestore . DocumentData > ;
165
+ export function collection (
166
+ parent : firestore . FirebaseFirestore | firestore . DocumentReference < unknown > ,
167
+ relativePath : string
168
+ ) : CollectionReference < firestore . DocumentData > {
169
+ if ( relativePath . length === 0 ) {
170
+ throw new FirestoreError (
171
+ Code . INVALID_ARGUMENT ,
172
+ `Invalid path (${ relativePath } ). Empty paths are not supported.`
173
+ ) ;
174
+ }
175
+
176
+ const path = ResourcePath . fromString ( relativePath ) ;
177
+ if ( parent instanceof Firestore ) {
178
+ if ( DocumentKey . isDocumentKey ( path ) ) {
179
+ throw new FirestoreError (
180
+ Code . INVALID_ARGUMENT ,
181
+ `Invalid path (${ path } ). Path points to a document.`
182
+ ) ;
183
+ }
184
+ return new CollectionReference ( parent , path ) ;
185
+ } else {
186
+ const doc = tryCast ( parent , DocumentReference ) ;
187
+ const absolutePath = doc . _key . path . child ( path ) ;
188
+ if ( DocumentKey . isDocumentKey ( absolutePath ) ) {
189
+ throw new FirestoreError (
190
+ Code . INVALID_ARGUMENT ,
191
+ `Invalid path (${ absolutePath } ). Path points to a document.`
192
+ ) ;
193
+ }
194
+ return new CollectionReference ( doc . firestore , absolutePath ) ;
195
+ }
196
+ }
197
+
198
+ export function doc (
199
+ firestore : FirebaseFirestore ,
200
+ documentPath : string
201
+ ) : DocumentReference < firestore . DocumentData > ;
202
+ export function doc < T > (
203
+ reference : CollectionReference < T > ,
204
+ documentPath ?: string
205
+ ) : DocumentReference < T > ;
206
+ export function doc < T > (
207
+ parent : firestore . FirebaseFirestore | firestore . CollectionReference < T > ,
208
+ relativePath ?: string
209
+ ) : DocumentReference {
210
+ // We allow omission of 'pathString' but explicitly prohibit passing in both
211
+ // 'undefined' and 'null'.
212
+ if ( arguments . length === 1 ) {
213
+ relativePath = AutoId . newId ( ) ;
214
+ }
215
+
216
+ if ( ! relativePath ) {
217
+ throw new FirestoreError (
218
+ Code . INVALID_ARGUMENT ,
219
+ `Invalid path (${ relativePath } ). Empty paths are not supported.`
220
+ ) ;
221
+ }
222
+
223
+ const path = ResourcePath . fromString ( relativePath ) ;
224
+ if ( parent instanceof Firestore ) {
225
+ if ( ! DocumentKey . isDocumentKey ( path ) ) {
226
+ throw new FirestoreError (
227
+ Code . INVALID_ARGUMENT ,
228
+ `Invalid path (${ path } ). Path points to a collection.`
229
+ ) ;
230
+ }
231
+ return new DocumentReference ( parent , new DocumentKey ( path ) ) ;
232
+ } else {
233
+ const coll = tryCast ( parent , CollectionReference ) ;
234
+ const absolutePath = coll . _path . child ( path ) ;
235
+ if ( ! DocumentKey . isDocumentKey ( absolutePath ) ) {
236
+ throw new FirestoreError (
237
+ Code . INVALID_ARGUMENT ,
238
+ `Invalid path (${ absolutePath } ). Path points to a collection.`
239
+ ) ;
240
+ }
241
+ return new DocumentReference (
242
+ coll . firestore ,
243
+ new DocumentKey ( absolutePath ) ,
244
+ coll . _converter
245
+ ) ;
246
+ }
247
+ }
248
+
249
+ export function parent (
250
+ reference : CollectionReference < unknown >
251
+ ) : DocumentReference < firestore . DocumentData > | null ;
252
+ export function parent < T > (
253
+ reference : DocumentReference < T >
254
+ ) : CollectionReference < T > ;
255
+ export function parent < T > (
256
+ child : firestore . CollectionReference < unknown > | firestore . DocumentReference < T >
257
+ ) : DocumentReference < firestore . DocumentData > | CollectionReference < T > | null {
258
+ if ( child instanceof CollectionReference ) {
259
+ const parentPath = child . _path . popLast ( ) ;
260
+ if ( parentPath . isEmpty ( ) ) {
261
+ return null ;
262
+ } else {
263
+ return new DocumentReference (
264
+ child . firestore ,
265
+ new DocumentKey ( parentPath )
266
+ ) ;
267
+ }
268
+ } else {
269
+ const doc = tryCast ( child , DocumentReference ) as DocumentReference < T > ;
270
+ return new CollectionReference < T > (
271
+ doc . firestore ,
272
+ doc . _key . path . popLast ( ) ,
273
+ doc . _converter
274
+ ) ;
275
+ }
276
+ }
0 commit comments