elersong / fireorm24

ORM for Firebase Firestore 🔥 updated for 2024
MIT License
1 stars 0 forks source link

Support Complex Data Types with Custom Prototypes #31

Open elersong opened 2 months ago

elersong commented 2 months ago

Description

Firestore does not support JavaScript objects with custom prototypes, such as those created via the new operator. This limitation causes issues when trying to save instances of classes with custom prototypes to Firestore. A workaround is needed to serialize these objects correctly before storing them in Firestore.

Steps to Reproduce

  1. Create a class with custom prototypes.
  2. Attempt to save an instance of this class to Firestore using Fireorm.
  3. Observe the error stating that Firestore does not support objects with custom prototypes.

Expected Behavior

Ability to save instances of classes with custom prototypes to Fireorm, with proper serialization to comply with Firestore's requirements.

Actual Behavior

Firestore throws an error when attempting to save objects with custom prototypes.

Acceptance Criteria

Additional Context

Proposed API Changes

  1. Serialize Entities to Plain Objects:

    • Implement a mechanism to serialize entities to plain objects before saving to Firestore.
    import { plainToClass, classToPlain } from 'class-transformer';
    
    async function saveEntity(entity: any) {
     const plainObject = classToPlain(entity);
     await firestore.collection('collectionName').add(plainObject);
    }
  2. Support for Custom Prototypes:

    • Ensure the serialization mechanism supports custom prototypes and complex data types.
    class GeoP {
     latitude: number;
     longitude: number;
    }
    
    @Collection()
    class SomeModel {
     @Type(() => GeoP)
     geop: GeoP;
    }
    
    const someGeoPInstance = new GeoP();
    someGeoPInstance.latitude = 19.3753433;
    someGeoPInstance.longitude = -99.0438667;
    
    const someModelInstance = new SomeModel();
    someModelInstance.geop = someGeoPInstance;
    
    saveEntity(someModelInstance);
  3. Unit Tests:

    • Add unit tests to validate the serialization of complex data types with custom prototypes.
    test('should serialize complex data types to plain objects', async () => {
     const someGeoPInstance = new GeoP();
     someGeoPInstance.latitude = 19.3753433;
     someGeoPInstance.longitude = -99.0438667;
    
     const someModelInstance = new SomeModel();
     someModelInstance.geop = someGeoPInstance;
    
     const plainObject = classToPlain(someModelInstance);
     expect(plainObject).toEqual({
       geop: {
         latitude: 19.3753433,
         longitude: -99.0438667,
       },
     });
    });

Example Implementation

class GeoP {
  latitude: number;
  longitude: number;
}

@Collection()
class SomeModel {
  @Type(() => GeoP)
  geop: GeoP;
}

const someGeoPInstance = new GeoP();
someGeoPInstance.latitude = 19.3753433;
someGeoPInstance.longitude = -99.0438667;

const someModelInstance = new SomeModel();
someModelInstance.geop = someGeoPInstance;

const plainObject = classToPlain(someModelInstance);
firestore.collection('SomeModel').add(plainObject);

Original Issue