fireorm
fireorm copied to clipboard
not able to update map (nested objects)
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.
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.
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?
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?