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

not able to update map (nested objects) #258

Open
GorvGoyl opened this issue May 25, 2021 · 3 comments
Open

not able to update map (nested objects) #258

GorvGoyl opened this issue May 25, 2021 · 3 comments

Comments

@GorvGoyl
Copy link

GorvGoyl commented May 25, 2021

I'm not able to update User object which contains map of AuthData.

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

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

Error:

Update() requires either a single JavaScript object or an alternating list of field/value pairs that can be followed by an optional precondition. Value for argument "dataOrField" is not a valid Firestore document. Couldn't serialize object of type "AuthData" (found in field "authData"). Firestore doesn't support JavaScript objects with custom prototypes (i.e. objects that were created via the "new" operator).

I though adding @Type(() => AuthData) should be sufficient to make that error go away. is there anything else required?
I also thought of adding plainToClass i.e. await userRepository.update(plainToClass(User, user); but firebase gives the same error.

@wovalle
Copy link
Owner

wovalle commented May 30, 2021

Hey! Can you reproduce the error in a minimal repo so we can take a look?

Also, I think this PR may fix the error, might get released soon.

@GorvGoyl
Copy link
Author

hey Wovalle, I found an easier approach than decorating maps in my collection classes in order to store data in firebase.
I made a helper function and use it like this await userRepository.update(plainObject(user))

export function plainObject(obj: any): any {
  return JSON.parse(JSON.stringify(obj));
}

in your experience is this approach okay?

@popcorn245
Copy link

Yeah I have done a similar approach but my approach might be a little overkill lol

/**
 * Cleans all JavaScript referneces and prototypes from Object
 * so it can be stored in Firestore.
 * @param input The JS Object to clean
 */
export default async function cleanObjectOfReferences(input: any) {
  const data = input;
  for (const key of Object.keys(input)) {
    const value = input[key];
    if (!value) continue;
    try {
      if (value?.constructor?.name === "Object") {
        data[key] = await cleanObjectOfReferences(value);
      } else if (value?.constructor?.name === "DocumentReference") {
        delete data[key];
      } else if (value?.constructor?.name === "Timestamp") {
        data[key] = value.toDate();
      } else if (value?.constructor?.name === "Array") {
        const cleanArray: any[] = [];
        for (const item of data[key]) {
          cleanArray.push(await cleanObjectOfReferences(item));
        }
        data[key] = cleanArray;
      } else if (
        typeof value === "object" &&
        value?.constructor?.name !== "Date"
      ) {
        data[key] = await cleanObjectOfReferences(
          JSON.parse(JSON.stringify(value))
        );
      }
    } catch (err) {
      delete data[key];
    }
  }

  return JSON.parse(JSON.stringify(data));
}

@wovalle is this where the @serialize() thing I have been seeing issues around solves?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants