Skip to content

Commit 24a64c9

Browse files
authored
fix: transform GeoPoint to plain object (#56)
fix: transform GeoPoint to plain object
2 parents 4000fc7 + 9bb110e commit 24a64c9

File tree

5 files changed

+39
-4
lines changed

5 files changed

+39
-4
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@ await todoRepository.update(mySuperTodoDocument); // Update todo
7777
await todoRepository.delete(mySuperTodoDocument.id); // Delete todo
7878
```
7979

80+
### Firebase Complex Data Types
81+
82+
Firestore has support for [complex data types](https://firebase.google.com/docs/firestore/manage-data/data-types) such as GeoPoint and Reference. Full handling of complex data types is [being handled in this issue](https://github.com/wovalle/fireorm/issues/58). Temporarily, Fireorm will export [Class Transformer's @Type](https://github.com/typestack/class-transformer#working-with-nested-objects) decorator. It receives a lamda where you have to return the type you want to cast to. [See GeoPoint Example](https://github.com/wovalle/fireorm/blob/master/src/BaseFirestoreRepository.spec.ts#L338-L344).
83+
84+
#### Limitations
85+
86+
If you want to cast GeoPoints to your custom class, it must have `latitude: number` and `longitude: number` as public class fields. Hopefully this won't be a limitation in v1.
87+
8088
## Development
8189

8290
### Initial Setup

src/BaseFirestoreRepository.spec.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import BaseFirestoreRepository from './BaseFirestoreRepository';
2-
import { getFixture, Album } from '../test/fixture';
2+
import { getFixture, Album, Coordinates } from '../test/fixture';
33
import { expect } from 'chai';
44
import { Collection, SubCollection, ISubCollection, Initialize } from '.';
5+
import { Type } from './';
56
const MockFirebase = require('mock-cloud-firestore');
67

78
@Collection('bands')
@@ -10,7 +11,12 @@ export class Band {
1011
name: string;
1112
formationYear: number;
1213
lastShow: Date;
14+
15+
// Todo create fireorm bypass decorator
16+
@Type(() => Coordinates)
17+
lastShowCoordinates: Coordinates;
1318
genres: Array<string>;
19+
1420
@SubCollection(Album)
1521
albums?: ISubCollection<Album>;
1622

@@ -329,6 +335,12 @@ describe('BaseRepository', () => {
329335
expect(pt.lastShow).to.be.instanceOf(Date);
330336
expect(pt.lastShow.toISOString()).to.equal('2010-10-14T00:00:00.000Z');
331337
});
338+
it('should correctly parse geopoints', async () => {
339+
const pt = await bandRepository.findById('porcupine-tree');
340+
expect(pt.lastShowCoordinates).to.be.instanceOf(Coordinates);
341+
expect(pt.lastShowCoordinates.latitude).to.equal(51.5009088);
342+
expect(pt.lastShowCoordinates.longitude).to.equal(-0.1795547);
343+
});
332344
});
333345

334346
describe('must handle subcollections', () => {

src/BaseFirestoreRepository.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export default class BaseFirestoreRepository<T extends IEntity>
7676
// tslint:disable-next-line:no-unnecessary-type-assertion
7777
const entity = plainToClass(
7878
collection.entity as any,
79-
this.parseTimestamp(doc.data() as T)
79+
this.transformFirestoreTypes(doc.data() as T)
8080
) as any;
8181

8282
/*
@@ -106,13 +106,16 @@ export default class BaseFirestoreRepository<T extends IEntity>
106106
return q.docs.map(this.extractTFromDocSnap);
107107
};
108108

109-
private parseTimestamp = (obj: T): T => {
109+
private transformFirestoreTypes = (obj: T): T => {
110110
Object.keys(obj).forEach(key => {
111111
if (!obj[key]) return;
112112
if (typeof obj[key] === 'object' && 'toDate' in obj[key]) {
113113
obj[key] = obj[key].toDate();
114+
} else if (obj[key].constructor.name === 'GeoPoint') {
115+
const { latitude, longitude } = obj[key];
116+
obj[key] = { latitude, longitude };
114117
} else if (typeof obj[key] === 'object') {
115-
this.parseTimestamp(obj[key]);
118+
this.transformFirestoreTypes(obj[key]);
116119
}
117120
});
118121

src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ export * from './helpers';
88
export { Initialize } from './MetadataStorage';
99

1010
export { Collection, SubCollection, CustomRepository, BaseFirestoreRepository };
11+
12+
// Temporary while https://github.com/wovalle/fireorm/issues/58 is being fixed
13+
export { Type } from 'class-transformer';

test/fixture.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
1+
import { GeoPoint } from "@google-cloud/firestore";
2+
3+
export class Coordinates {
4+
latitude: number;
5+
longitude: number;
6+
}
17
export class Album {
28
id: string;
39
name: string;
410
releaseDate: Date;
511
comment?: string;
612
}
13+
714
export class BandEntity {
815
id: string;
916
name: string;
1017
formationYear: number;
1118
lastShow: Date;
19+
lastShowCoordinates?: GeoPoint;
1220
genres: Array<string>;
1321
albums: Array<Album>;
1422
}
@@ -29,6 +37,7 @@ const getColFixture = () => {
2937
name: 'Porcupine Tree',
3038
formationYear: 1987,
3139
lastShow: new Date('2010-10-14'),
40+
lastShowCoordinates: new GeoPoint(51.5009088, -0.1795547),
3241
genres: ['psychedelic-rock', 'progressive-rock', 'progressive-metal'],
3342
albums: [
3443
{

0 commit comments

Comments
 (0)