Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Complex Data Types with Custom Prototypes #31

Open
elersong opened this issue Jul 13, 2024 · 0 comments
Open

Support Complex Data Types with Custom Prototypes #31

elersong opened this issue Jul 13, 2024 · 0 comments
Labels
bug Something isn't working from_willyovale An issue described in original project, but never implemented

Comments

@elersong
Copy link
Owner

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

  • Implement a serialization mechanism to convert objects with custom prototypes to plain objects before saving to Firestore.
  • Ensure compatibility with Fireorm's existing functionality.
  • Add unit tests to validate the correct serialization of complex data types.

Additional Context

  • March 2, 2021: Initial issue raised about problems with complex data types.
  • March 8, 2021: Acknowledgment of the issue and request for a minimal reproduction repo.
  • March 11, 2021: Discussion about Firestore's limitation and suggestion to serialize objects to plain objects.
  • April 27, 2021: Mention of a pull request potentially solving the issue.
  • May 11, 2021: Clarification on the need for a generic mapping between Firestore "primitives" and fields in custom models.

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

@elersong elersong added bug Something isn't working from_willyovale An issue described in original project, but never implemented labels Jul 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working from_willyovale An issue described in original project, but never implemented
Projects
None yet
Development

No branches or pull requests

1 participant