Skip to content

Commit

Permalink
fix: transform GeoPoint to plain object (#56)
Browse files Browse the repository at this point in the history
fix: transform GeoPoint to plain object
  • Loading branch information
wovalle authored Jun 26, 2019
2 parents 4000fc7 + 9bb110e commit 24a64c9
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 4 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ await todoRepository.update(mySuperTodoDocument); // Update todo
await todoRepository.delete(mySuperTodoDocument.id); // Delete todo
```

### Firebase Complex Data Types

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).

#### Limitations

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.

## Development

### Initial Setup
Expand Down
14 changes: 13 additions & 1 deletion src/BaseFirestoreRepository.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import BaseFirestoreRepository from './BaseFirestoreRepository';
import { getFixture, Album } from '../test/fixture';
import { getFixture, Album, Coordinates } from '../test/fixture';
import { expect } from 'chai';
import { Collection, SubCollection, ISubCollection, Initialize } from '.';
import { Type } from './';
const MockFirebase = require('mock-cloud-firestore');

@Collection('bands')
Expand All @@ -10,7 +11,12 @@ export class Band {
name: string;
formationYear: number;
lastShow: Date;

// Todo create fireorm bypass decorator
@Type(() => Coordinates)
lastShowCoordinates: Coordinates;
genres: Array<string>;

@SubCollection(Album)
albums?: ISubCollection<Album>;

Expand Down Expand Up @@ -329,6 +335,12 @@ describe('BaseRepository', () => {
expect(pt.lastShow).to.be.instanceOf(Date);
expect(pt.lastShow.toISOString()).to.equal('2010-10-14T00:00:00.000Z');
});
it('should correctly parse geopoints', async () => {
const pt = await bandRepository.findById('porcupine-tree');
expect(pt.lastShowCoordinates).to.be.instanceOf(Coordinates);
expect(pt.lastShowCoordinates.latitude).to.equal(51.5009088);
expect(pt.lastShowCoordinates.longitude).to.equal(-0.1795547);
});
});

describe('must handle subcollections', () => {
Expand Down
9 changes: 6 additions & 3 deletions src/BaseFirestoreRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export default class BaseFirestoreRepository<T extends IEntity>
// tslint:disable-next-line:no-unnecessary-type-assertion
const entity = plainToClass(
collection.entity as any,
this.parseTimestamp(doc.data() as T)
this.transformFirestoreTypes(doc.data() as T)
) as any;

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

private parseTimestamp = (obj: T): T => {
private transformFirestoreTypes = (obj: T): T => {
Object.keys(obj).forEach(key => {
if (!obj[key]) return;
if (typeof obj[key] === 'object' && 'toDate' in obj[key]) {
obj[key] = obj[key].toDate();
} else if (obj[key].constructor.name === 'GeoPoint') {
const { latitude, longitude } = obj[key];
obj[key] = { latitude, longitude };
} else if (typeof obj[key] === 'object') {
this.parseTimestamp(obj[key]);
this.transformFirestoreTypes(obj[key]);
}
});

Expand Down
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ export * from './helpers';
export { Initialize } from './MetadataStorage';

export { Collection, SubCollection, CustomRepository, BaseFirestoreRepository };

// Temporary while https://github.com/wovalle/fireorm/issues/58 is being fixed
export { Type } from 'class-transformer';
9 changes: 9 additions & 0 deletions test/fixture.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import { GeoPoint } from "@google-cloud/firestore";

export class Coordinates {
latitude: number;
longitude: number;
}
export class Album {
id: string;
name: string;
releaseDate: Date;
comment?: string;
}

export class BandEntity {
id: string;
name: string;
formationYear: number;
lastShow: Date;
lastShowCoordinates?: GeoPoint;
genres: Array<string>;
albums: Array<Album>;
}
Expand All @@ -29,6 +37,7 @@ const getColFixture = () => {
name: 'Porcupine Tree',
formationYear: 1987,
lastShow: new Date('2010-10-14'),
lastShowCoordinates: new GeoPoint(51.5009088, -0.1795547),
genres: ['psychedelic-rock', 'progressive-rock', 'progressive-metal'],
albums: [
{
Expand Down

0 comments on commit 24a64c9

Please sign in to comment.