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

Fix Serialization Error for Objects with Custom Prototypes #33

Open
elersong opened this issue Jul 13, 2024 · 1 comment
Open

Fix Serialization Error for Objects with Custom Prototypes #33

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

Comments

@elersong
Copy link
Owner

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

  • Implement a mechanism to serialize 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

  • May 25, 2021: Initial issue raised about the serialization error.
  • May 30, 2021: Discussion about potential fixes and workarounds, including using a helper function to convert objects to plain objects.
  • May 30, 2021: Suggestion to use a helper function to clean objects of references and prototypes.

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 = "[email protected]";
    
    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 = "[email protected]";
    
    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 = "[email protected]";
    
      const plainUser = plainObject(user);
      expect(plainUser.authData.email).toBe("[email protected]");
    });

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 = "[email protected]";

userRepository.update(plainObject(user));

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
@elersong
Copy link
Owner Author

Potentially connected to #31

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