From da8464521b80542aaec1977ad0dad0db888e6733 Mon Sep 17 00:00:00 2001 From: Maximo Dominguez Date: Fri, 21 Jun 2019 19:41:26 -0400 Subject: [PATCH 1/6] fix: transform GeoPoint to plain object closes #48 I think this is kind of a hack, but it's what's being done with firestore timestamps. You can find more information about this issue [here](https://github.com/typestack/class-transformer/issues/174) --- src/BaseFirestoreRepository.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/BaseFirestoreRepository.ts b/src/BaseFirestoreRepository.ts index decff670..0ec3be07 100644 --- a/src/BaseFirestoreRepository.ts +++ b/src/BaseFirestoreRepository.ts @@ -76,7 +76,7 @@ export default class BaseFirestoreRepository // 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; /* @@ -106,13 +106,16 @@ export default class BaseFirestoreRepository 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]); } }); From fa27f919beb32d05a57d1b7ec085a87a110d150b Mon Sep 17 00:00:00 2001 From: "willy.ovalle@klarna.com" Date: Mon, 24 Jun 2019 23:29:41 +0200 Subject: [PATCH 2/6] test: wip: adding test for geopoint --- src/BaseFirestoreRepository.spec.ts | 14 +++++++++++++- test/fixture.ts | 9 +++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/BaseFirestoreRepository.spec.ts b/src/BaseFirestoreRepository.spec.ts index c864efb2..1689f03d 100644 --- a/src/BaseFirestoreRepository.spec.ts +++ b/src/BaseFirestoreRepository.spec.ts @@ -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 'class-transformer'; const MockFirebase = require('mock-cloud-firestore'); @Collection('bands') @@ -10,7 +11,12 @@ export class Band { name: string; formationYear: number; lastShow: Date; + + // Todo create fireorm bypass decorator + @Type(() => Coordinates) + lastShowCoordinates: Coordinates; genres: Array; + @SubCollection(Album) albums?: ISubCollection; @@ -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', () => { diff --git a/test/fixture.ts b/test/fixture.ts index 25a8bffc..29bef916 100644 --- a/test/fixture.ts +++ b/test/fixture.ts @@ -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; albums: Array; } @@ -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: [ { From 7bcaa6c9c946af0fd856ce08686f0b1155a1cfcc Mon Sep 17 00:00:00 2001 From: Willy Ovalle Date: Wed, 26 Jun 2019 21:17:35 +0200 Subject: [PATCH 3/6] chore: exporting class-transformer's @Type --- src/BaseFirestoreRepository.spec.ts | 2 +- src/index.ts | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/BaseFirestoreRepository.spec.ts b/src/BaseFirestoreRepository.spec.ts index 1689f03d..52a1a49f 100644 --- a/src/BaseFirestoreRepository.spec.ts +++ b/src/BaseFirestoreRepository.spec.ts @@ -2,7 +2,7 @@ import BaseFirestoreRepository from './BaseFirestoreRepository'; import { getFixture, Album, Coordinates } from '../test/fixture'; import { expect } from 'chai'; import { Collection, SubCollection, ISubCollection, Initialize } from '.'; -import { Type } from 'class-transformer'; +import { Type } from './'; const MockFirebase = require('mock-cloud-firestore'); @Collection('bands') diff --git a/src/index.ts b/src/index.ts index 27e9a6eb..0ce013bf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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'; From dff5709f358922e414c1b57477cdc5b8e260317d Mon Sep 17 00:00:00 2001 From: Willy Ovalle Date: Wed, 26 Jun 2019 21:37:42 +0200 Subject: [PATCH 4/6] docs: editing README with GeoPoint example --- README.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7a7ee929..26a4ee69 100644 --- a/README.md +++ b/README.md @@ -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 @@ -115,20 +123,20 @@ This repo uses [Sematic Release](https://github.com/semantic-release/semantic-re Manual Release If, by any reason, a manual release must be done, these are the instructions: -- To release a new version to npm, first we have to create a new tag: +- To release a new version to npm, first we have to create a new tag: ```bash npm version [ major | minor | patch ] -m "Relasing version" git push --follow-tags ``` -- Then we can publish the package to npm registry: +- Then we can publish the package to npm registry: ```bash npm publish ``` -- To deploy the documentation +- To deploy the documentation ```bash yarn deploy:documentation # or npm deploy:documentation @@ -138,7 +146,7 @@ yarn deploy:documentation # or npm deploy:documentation ### Documentation -- Fireorm uses [typedoc](https://typedoc.org/) to automatically build the API documentation, to generate it: +- Fireorm uses [typedoc](https://typedoc.org/) to automatically build the API documentation, to generate it: ```bash yarn build:documentation # or npm build:documentation @@ -157,7 +165,6 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d -
Willy Ovalle
Willy Ovalle

💻 📖 💡 🤔 👀 ⚠️
Maximo Dominguez
Maximo Dominguez

🤔 💻
Nathan Jones
Nathan Jones

💻
From c634fbb4098ce157c5927c831bef8b6d010675fc Mon Sep 17 00:00:00 2001 From: Willy Ovalle Date: Wed, 26 Jun 2019 21:52:17 +0200 Subject: [PATCH 5/6] =?UTF-8?q?chore:=20fixing=20README=20spacing=20?= =?UTF-8?q?=F0=9F=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 26a4ee69..70330bab 100644 --- a/README.md +++ b/README.md @@ -123,20 +123,20 @@ This repo uses [Sematic Release](https://github.com/semantic-release/semantic-re Manual Release If, by any reason, a manual release must be done, these are the instructions: -- To release a new version to npm, first we have to create a new tag: +- To release a new version to npm, first we have to create a new tag: ```bash npm version [ major | minor | patch ] -m "Relasing version" git push --follow-tags ``` -- Then we can publish the package to npm registry: +- Then we can publish the package to npm registry: ```bash npm publish ``` -- To deploy the documentation +- To deploy the documentation ```bash yarn deploy:documentation # or npm deploy:documentation @@ -146,7 +146,7 @@ yarn deploy:documentation # or npm deploy:documentation ### Documentation -- Fireorm uses [typedoc](https://typedoc.org/) to automatically build the API documentation, to generate it: +- Fireorm uses [typedoc](https://typedoc.org/) to automatically build the API documentation, to generate it: ```bash yarn build:documentation # or npm build:documentation @@ -165,6 +165,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d +
Willy Ovalle
Willy Ovalle

💻 📖 💡 🤔 👀 ⚠️
Maximo Dominguez
Maximo Dominguez

🤔 💻
Nathan Jones
Nathan Jones

💻
From 9bb110ea1b92398f91faad367da9e951484de192 Mon Sep 17 00:00:00 2001 From: Willy Ovalle Date: Wed, 26 Jun 2019 22:09:58 +0200 Subject: [PATCH 6/6] fix: removing extra colon --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 70330bab..e42e7b51 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ await todoRepository.delete(mySuperTodoDocument.id); // Delete todo 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: +#### 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.