elersong / fireorm24

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

Fix Serialization Error for Objects with Custom Prototypes #33

Open elersong opened 2 months ago

elersong commented 2 months ago

Description

Attempting to update a Fireorm object containing a map of custom objects results in a serialization error. Firestore does not support JavaScript objects with custom prototypes, leading to issues when saving such objects.

Steps to Reproduce

  1. Create a Fireorm model containing a map of custom objects.
  2. Attempt to update an instance of this model in Firestore.
  3. Observe the serialization error.

Expected Behavior

The update should serialize the custom objects correctly and save them to Firestore without errors.

Actual Behavior

A serialization error occurs, stating that Firestore does not support JavaScript 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 AuthData {
     id = "";
     email = "";
     displayName = "";
     emailVerified = false;
    }
    
    @Collection("users")
    class User {
     id = "";
     @Type(() => AuthData)
     authData? = new AuthData();
    }
    
    const userRepository = getRepository(User);
    const user = new User();
    user.id = "user123";
    user.authData = new AuthData();
    user.authData.email = "test@example.com";
    
    saveEntity(user);
  3. Helper Function:

    • Provide a helper function to convert objects to plain objects before saving to Firestore.
    function plainObject(obj: any): any {
     return JSON.parse(JSON.stringify(obj));
    }
    
    // Example usage
    const user = new User();
    user.id = "user123";
    user.authData = new AuthData();
    user.authData.email = "test@example.com";
    
    userRepository.update(plainObject(user));
  4. 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 user = new User();
     user.id = "user123";
     user.authData = new AuthData();
     user.authData.email = "test@example.com";
    
     const plainUser = plainObject(user);
     expect(plainUser.authData.email).toBe("test@example.com");
    });

Example Implementation

class AuthData {
  id = "";
  email = "";
  displayName = "";
  emailVerified = false;
}

@Collection("users")
class User {
  id = "";
  @Type(() => AuthData)
  authData? = new AuthData();
}

const userRepository = getRepository(User);

const user = new User();
user.id = "user123";
user.authData = new AuthData();
user.authData.email = "test@example.com";

userRepository.update(plainObject(user));

Original Issue

elersong commented 2 months ago

Potentially connected to #31