Skip to content

Commit 81e6d80

Browse files
author
Brian Chen
authored
Merge 45aba16 into 2301aee
2 parents 2301aee + 45aba16 commit 81e6d80

File tree

7 files changed

+191
-26
lines changed

7 files changed

+191
-26
lines changed

.changeset/lemon-laws-brush.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'firebase': patch
3+
'@firebase/firestore': patch
4+
'@firebase/firestore-types': patch
5+
---
6+
7+
Added support to remove a FirestoreDataConverter on a Firestore reference by calling `withConverter(null)`

packages/firebase/index.d.ts

+58-3
Original file line numberDiff line numberDiff line change
@@ -9089,7 +9089,26 @@ declare namespace firebase.firestore {
90899089
* provided converter will convert between Firestore data and your custom
90909090
* type U.
90919091
*
9092-
* @param converter Converts objects to and from Firestore.
9092+
* Passing in `null` as the converter parameter removes the current
9093+
* converter.
9094+
*
9095+
* @param converter Converts objects to and from Firestore. Passing in
9096+
* `null` removes the current converter.
9097+
* @return A DocumentReference<U> that uses the provided converter.
9098+
*/
9099+
withConverter(converter: null): DocumentReference<DocumentData>;
9100+
/**
9101+
* Applies a custom data converter to this DocumentReference, allowing you
9102+
* to use your own custom model objects with Firestore. When you call
9103+
* set(), get(), etc. on the returned DocumentReference instance, the
9104+
* provided converter will convert between Firestore data and your custom
9105+
* type U.
9106+
*
9107+
* Passing in `null` as the converter parameter removes the current
9108+
* converter.
9109+
*
9110+
* @param converter Converts objects to and from Firestore. Passing in
9111+
* `null` removes the current converter.
90939112
* @return A DocumentReference<U> that uses the provided converter.
90949113
*/
90959114
withConverter<U>(
@@ -9544,7 +9563,25 @@ declare namespace firebase.firestore {
95449563
* returned Query, the provided converter will convert between Firestore
95459564
* data and your custom type U.
95469565
*
9547-
* @param converter Converts objects to and from Firestore.
9566+
* Passing in `null` as the converter parameter removes the current
9567+
* converter.
9568+
*
9569+
* @param converter Converts objects to and from Firestore. Passing in
9570+
* `null` removes the current converter.
9571+
* @return A Query<U> that uses the provided converter.
9572+
*/
9573+
withConverter(converter: null): Query<DocumentData>;
9574+
/**
9575+
* Applies a custom data converter to this Query, allowing you to use your
9576+
* own custom model objects with Firestore. When you call get() on the
9577+
* returned Query, the provided converter will convert between Firestore
9578+
* data and your custom type U.
9579+
*
9580+
* Passing in `null` as the converter parameter removes the current
9581+
* converter.
9582+
*
9583+
* @param converter Converts objects to and from Firestore. Passing in
9584+
* `null` removes the current converter.
95489585
* @return A Query<U> that uses the provided converter.
95499586
*/
95509587
withConverter<U>(converter: FirestoreDataConverter<U>): Query<U>;
@@ -9700,7 +9737,25 @@ declare namespace firebase.firestore {
97009737
* on the returned CollectionReference instance, the provided converter will
97019738
* convert between Firestore data and your custom type U.
97029739
*
9703-
* @param converter Converts objects to and from Firestore.
9740+
* Passing in `null` as the converter parameter removes the current
9741+
* converter.
9742+
*
9743+
* @param converter Converts objects to and from Firestore. Passing in
9744+
* `null` removes the current converter.
9745+
* @return A CollectionReference<U> that uses the provided converter.
9746+
*/
9747+
withConverter(converter: null): CollectionReference<DocumentData>;
9748+
/**
9749+
* Applies a custom data converter to this CollectionReference, allowing you
9750+
* to use your own custom model objects with Firestore. When you call add()
9751+
* on the returned CollectionReference instance, the provided converter will
9752+
* convert between Firestore data and your custom type U.
9753+
*
9754+
* Passing in `null` as the converter parameter removes the current
9755+
* converter.
9756+
*
9757+
* @param converter Converts objects to and from Firestore. Passing in
9758+
* `null` removes the current converter.
97049759
* @return A CollectionReference<U> that uses the provided converter.
97059760
*/
97069761
withConverter<U>(

packages/firestore-types/index.d.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ export class DocumentReference<T = DocumentData> {
286286
onCompletion?: () => void
287287
): () => void;
288288

289+
withConverter(converter: null): DocumentReference<DocumentData>;
289290
withConverter<U>(converter: FirestoreDataConverter<U>): DocumentReference<U>;
290291
}
291292

@@ -315,9 +316,9 @@ export class DocumentSnapshot<T = DocumentData> {
315316
isEqual(other: DocumentSnapshot<T>): boolean;
316317
}
317318

318-
export class QueryDocumentSnapshot<T = DocumentData> extends DocumentSnapshot<
319-
T
320-
> {
319+
export class QueryDocumentSnapshot<
320+
T = DocumentData
321+
> extends DocumentSnapshot<T> {
321322
private constructor();
322323

323324
data(options?: SnapshotOptions): T;
@@ -398,6 +399,7 @@ export class Query<T = DocumentData> {
398399
onCompletion?: () => void
399400
): () => void;
400401

402+
withConverter(converter: null): Query<DocumentData>;
401403
withConverter<U>(converter: FirestoreDataConverter<U>): Query<U>;
402404
}
403405

@@ -442,6 +444,7 @@ export class CollectionReference<T = DocumentData> extends Query<T> {
442444

443445
isEqual(other: CollectionReference<T>): boolean;
444446

447+
withConverter(converter: null): CollectionReference<DocumentData>;
445448
withConverter<U>(
446449
converter: FirestoreDataConverter<U>
447450
): CollectionReference<U>;

packages/firestore/src/api/database.ts

+28-10
Original file line numberDiff line numberDiff line change
@@ -830,14 +830,20 @@ export class DocumentReference<T = PublicDocumentData>
830830
);
831831
}
832832

833+
withConverter(converter: null): PublicDocumentReference<PublicDocumentData>;
833834
withConverter<U>(
834835
converter: PublicFirestoreDataConverter<U>
836+
): PublicDocumentReference<U>;
837+
withConverter<U>(
838+
converter: PublicFirestoreDataConverter<U> | null
835839
): PublicDocumentReference<U> {
836840
return new DocumentReference<U>(
837841
this.firestore,
838-
this._delegate.withConverter(
839-
FirestoreDataConverter.getInstance(this.firestore, converter)
840-
)
842+
converter
843+
? this._delegate.withConverter(
844+
FirestoreDataConverter.getInstance(this.firestore, converter)
845+
)
846+
: (this._delegate.withConverter(null) as ExpDocumentReference<U>)
841847
);
842848
}
843849
}
@@ -1141,12 +1147,18 @@ export class Query<T = PublicDocumentData>
11411147
return onSnapshot(this._delegate, options, observer);
11421148
}
11431149

1144-
withConverter<U>(converter: PublicFirestoreDataConverter<U>): Query<U> {
1150+
withConverter(converter: null): Query<PublicDocumentData>;
1151+
withConverter<U>(converter: PublicFirestoreDataConverter<U>): Query<U>;
1152+
withConverter<U>(
1153+
converter: PublicFirestoreDataConverter<U> | null
1154+
): Query<U> {
11451155
return new Query<U>(
11461156
this.firestore,
1147-
this._delegate.withConverter(
1148-
FirestoreDataConverter.getInstance(this.firestore, converter)
1149-
)
1157+
converter
1158+
? this._delegate.withConverter(
1159+
FirestoreDataConverter.getInstance(this.firestore, converter)
1160+
)
1161+
: (this._delegate.withConverter(null) as ExpQuery<U>)
11501162
);
11511163
}
11521164
}
@@ -1283,14 +1295,20 @@ export class CollectionReference<T = PublicDocumentData>
12831295
return refEqual(this._delegate, other._delegate);
12841296
}
12851297

1298+
withConverter(converter: null): CollectionReference<PublicDocumentData>;
12861299
withConverter<U>(
12871300
converter: PublicFirestoreDataConverter<U>
1301+
): CollectionReference<U>;
1302+
withConverter<U>(
1303+
converter: PublicFirestoreDataConverter<U> | null
12881304
): CollectionReference<U> {
12891305
return new CollectionReference<U>(
12901306
this.firestore,
1291-
this._delegate.withConverter(
1292-
FirestoreDataConverter.getInstance(this.firestore, converter)
1293-
)
1307+
converter
1308+
? this._delegate.withConverter(
1309+
FirestoreDataConverter.getInstance(this.firestore, converter)
1310+
)
1311+
: (this._delegate.withConverter(null) as ExpCollectionReference<U>)
12941312
);
12951313
}
12961314
}

packages/firestore/src/lite/reference.ts

+17-3
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,18 @@ export class DocumentReference<T = DocumentData> {
138138
* instance, the provided converter will convert between Firestore data and
139139
* your custom type `U`.
140140
*
141-
* @param converter - Converts objects to and from Firestore.
141+
* Passing in `null` as the converter parameter removes the current
142+
* converter.
143+
*
144+
* @param converter - Converts objects to and from Firestore. Passing in
145+
* `null` removes the current converter.
142146
* @returns A `DocumentReference<U>` that uses the provided converter.
143147
*/
144-
withConverter<U>(converter: FirestoreDataConverter<U>): DocumentReference<U> {
148+
withConverter(converter: null): DocumentReference<DocumentData>;
149+
withConverter<U>(converter: FirestoreDataConverter<U>): DocumentReference<U>;
150+
withConverter<U>(
151+
converter: FirestoreDataConverter<U> | null
152+
): DocumentReference<U> {
145153
return new DocumentReference<U>(this.firestore, converter, this._key);
146154
}
147155
}
@@ -180,7 +188,9 @@ export class Query<T = DocumentData> {
180188
* @param converter - Converts objects to and from Firestore.
181189
* @returns A `Query<U>` that uses the provided converter.
182190
*/
183-
withConverter<U>(converter: FirestoreDataConverter<U>): Query<U> {
191+
withConverter(converter: null): Query<DocumentData>;
192+
withConverter<U>(converter: FirestoreDataConverter<U>): Query<U>;
193+
withConverter<U>(converter: FirestoreDataConverter<U> | null): Query<U> {
184194
return new Query<U>(this.firestore, converter, this._query);
185195
}
186196
}
@@ -240,8 +250,12 @@ export class CollectionReference<T = DocumentData> extends Query<T> {
240250
* @param converter - Converts objects to and from Firestore.
241251
* @returns A `CollectionReference<U>` that uses the provided converter.
242252
*/
253+
withConverter(converter: null): CollectionReference<DocumentData>;
243254
withConverter<U>(
244255
converter: FirestoreDataConverter<U>
256+
): CollectionReference<U>;
257+
withConverter<U>(
258+
converter: FirestoreDataConverter<U> | null
245259
): CollectionReference<U> {
246260
return new CollectionReference<U>(this.firestore, converter, this._path);
247261
}

packages/firestore/test/integration/api/database.test.ts

+37
Original file line numberDiff line numberDiff line change
@@ -1395,6 +1395,18 @@ apiDescribe('Database', (persistence: boolean) => {
13951395
});
13961396
});
13971397

1398+
it('for DocumentReference.withConverter(null) ', () => {
1399+
return withTestDb(persistence, async db => {
1400+
const docRef = db
1401+
.collection('posts')
1402+
.doc()
1403+
.withConverter(postConverter)
1404+
.withConverter(null);
1405+
1406+
expect(() => docRef.set(new Post('post', 'author'))).to.throw();
1407+
});
1408+
});
1409+
13981410
it('for CollectionReference.withConverter()', () => {
13991411
return withTestDb(persistence, async db => {
14001412
const coll = db.collection('posts').withConverter(postConverter);
@@ -1407,6 +1419,17 @@ apiDescribe('Database', (persistence: boolean) => {
14071419
});
14081420
});
14091421

1422+
it('for CollectionReference.withConverter(null)', () => {
1423+
return withTestDb(persistence, async db => {
1424+
const coll = db
1425+
.collection('posts')
1426+
.withConverter(postConverter)
1427+
.withConverter(null);
1428+
1429+
expect(() => coll.add(new Post('post', 'author'))).to.throw();
1430+
});
1431+
});
1432+
14101433
it('for Query.withConverter()', () => {
14111434
return withTestDb(persistence, async db => {
14121435
await db
@@ -1424,6 +1447,20 @@ apiDescribe('Database', (persistence: boolean) => {
14241447
});
14251448
});
14261449

1450+
it('for Query.withConverter(null)', () => {
1451+
return withTestDb(persistence, async db => {
1452+
await db
1453+
.doc('postings/post1')
1454+
.set({ title: 'post1', author: 'author1' });
1455+
const posts = await db
1456+
.collectionGroup('postings')
1457+
.withConverter(postConverter)
1458+
.withConverter(null)
1459+
.get();
1460+
expect(posts.docs[0].data()).to.not.be.an.instanceof(Post);
1461+
});
1462+
});
1463+
14271464
it('requires the correct converter for Partial usage', async () => {
14281465
return withTestDb(persistence, async db => {
14291466
const ref = db

packages/firestore/test/lite/integration.test.ts

+38-7
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,15 @@ describe('withConverter() support', () => {
11141114
});
11151115
});
11161116

1117+
it('for DocumentReference.withConverter(null) applies default converter', () => {
1118+
return withTestCollection(async coll => {
1119+
coll = coll.withConverter(postConverter).withConverter(null);
1120+
expect(() =>
1121+
setDoc(doc(coll, 'post1'), new Post('post', 'author'))
1122+
).to.throw();
1123+
});
1124+
});
1125+
11171126
it('for CollectionReference.withConverter()', () => {
11181127
return withTestCollection(async coll => {
11191128
coll = coll.withConverter(postConverter);
@@ -1125,16 +1134,38 @@ describe('withConverter() support', () => {
11251134
});
11261135
});
11271136

1128-
it('for Query.withConverter()', () => {
1129-
return withTestCollection(async coll => {
1130-
coll = coll.withConverter(postConverter);
1131-
await setDoc(doc(coll, 'post1'), new Post('post1', 'author1'));
1132-
const posts = await getDocs(coll);
1133-
expect(posts.size).to.equal(1);
1134-
expect(posts.docs[0].data()!.byline()).to.equal('post1, by author1');
1137+
it('for CollectionReference.withConverter(null) applies default converter', () => {
1138+
return withTestDoc(async doc => {
1139+
doc = doc.withConverter(postConverter).withConverter(null);
1140+
expect(() => setDoc(doc, new Post('post', 'author'))).to.throw();
11351141
});
11361142
});
11371143

1144+
it('for Query.withConverter()', () => {
1145+
return withTestCollectionAndInitialData(
1146+
[{ title: 'post', author: 'author' }],
1147+
async collRef => {
1148+
let query1 = query(collRef, where('title', '==', 'post'));
1149+
query1 = query1.withConverter(postConverter);
1150+
const result = await getDocs(query1);
1151+
expect(result.docs[0].data()).to.be.an.instanceOf(Post);
1152+
expect(result.docs[0].data()!.byline()).to.equal('post, by author');
1153+
}
1154+
);
1155+
});
1156+
1157+
it('for Query.withConverter(null) applies default converter', () => {
1158+
return withTestCollectionAndInitialData(
1159+
[{ title: 'post', author: 'author' }],
1160+
async collRef => {
1161+
let query1 = query(collRef, where('title', '==', 'post'));
1162+
query1 = query1.withConverter(postConverter).withConverter(null);
1163+
const result = await getDocs(query1);
1164+
expect(result.docs[0]).to.not.be.an.instanceOf(Post);
1165+
}
1166+
);
1167+
});
1168+
11381169
it('keeps the converter when calling parent() with a DocumentReference', () => {
11391170
return withTestDb(async db => {
11401171
const coll = doc(db, 'root/doc').withConverter(postConverter);

0 commit comments

Comments
 (0)