When I try to use Firebase.Firestore.set() with an object, I get an error saying "(FirebaseError): Function DocumentReference.set() called with invalid data. Unsupported field value: a custom ql object"
I'm using Firebase in a React class, and I tried creating the object right in the function and defining it separately as shown below:
if (authUser) {
const userObj = {
name: authUser.displayName,
uid: authUser.uid,
email: authUser.email,
emailVerified: authUser.emailVerified,
providerData: authUser.providerData
}
this.db.collection("users").doc(authUser.uid).set(userObj, { merge: true })
}
Most likely the providerData (which comes from the identity provider) contains data of a type that Firestore can't handle. To fix this problem, either don't store the provider data, or convert it into a compatible type with this hack:
providerData: JSON.parse(JSON.stringify(authUser.providerData))
Your problem is that you are trying to copy an instance of an object, (i guess is a graphql object) and firebase does not support that, you need to use primitive values. Make sure you copy strings on all the properties instead of pointers to the class.
Related
While it's possible to prevent deletion of Object properties by using freeze/seal/preventExtensions, I'd love to know whether it's possible to prevent deleting the object itself.
For example, in case I create an object in the global scope, and want to avoid nested functions or other modules from being able to delete that object, can I treat this global-scoped object simply as a property of the globalThis variable? Would it be possible to prevent deleting it in all hosts - Node, browsers, Deno?
My final goal is that, basically, I want to prevent overriding the object, rename it's properties/fields/symbols, or modifying it's values, or manipulating it's prototype chain as well.
So, please tell me how to keep this secret unchanged, undeleted (and maybe un-readable) along with all of it's fields and sub-fields:
const secretTree = {
name: 'barack obama',
password: 'ilovetrump',
subTrusts: [
{ name: 'biden', password: 'zZzZ' }
]
};
(function putin() {
delete secretTree;
globalThis.secretTree = { name: 'vlad', password: '123456' };
})();
// and also this:
// delete secretTree; const secretTree = ...
// and all other variations of deletion
Please, treat the case of null-prototyped object as well (in which __proto__: null).
Maybe, the correct way to approach this question and to describe it, is that we need to protect the "variable" itself from changing, as opposed to protect the "object" value inside it. To say, I want to "reserve" the variable name from any modifications, so forever I know that "globalThis.secretTree" will refer to something I trust on.
I tried to avoid some untrusted library functions from touching important objects.
Option 1: Object.defineProperty() with Object.freeze()
You can use Object.defineProperty() (or Object.defineProperties() or Reflect.defineProperty()):
By default, properties added using Object.defineProperty() are not writable, not enumerable, and not configurable.
You can also use Object.freeze() to freeze nested objects to make immutable structures.
Example:
Object.defineProperty(globalThis, "secretTree", {
value: Object.freeze({
name: "barack obama",
password: "ilovetrump",
subTrusts: Object.freeze([
Object.freeze({ name: "biden", password: "zZzZ" }),
]),
}),
});
Attempts to modify the data will fail silently or throw errors.
Option 2: Modules
Variables defined inside an ES module are scoped to that module. Code outside the module cannot get nor delete its data unless the module exports a reference to it.
example.mjs
export {}; // a module must have at least one `export` or `import`
const secretTree = { /* your data */ };
Other code attempting to access, modify, or delete it will fail to do so:
import * as data from "./example.mjs";
delete data.secretTree; // doesn't reference the actual `secretTree`
I am using the NestJs framework (love it by the way) and I want to check the incoming data so it conforms with an Enum in Typscript. So I have the following:
enum ProductAction {
PURCHASE = 'PURCHASE',
}
#Patch('products/:uuid')
async patchProducts(
#Param('uuid', ParseUUIDPipe) uuid: string,
#Body('action', ParseEnumPipe) action: ProductAction,
) {
switch(action) {
... code
}
The weird thing is that when I run this code, the first pipe gets compiled
2022-07-21 16:53:51 [error] [ExceptionHandler] Nest can't resolve dependencies of the ParseEnumPipe (?, Object). Please make sure that the argument Object at index [0] is available in the FriendsModule context.
What I am doing wrong?
You should use #Body('action', new ParseEnumPipe(ProductAction)) action: ProductAction because enums aren't directly reflected for Nest to read the metadata of, and because Nest is otherwise trying to figure out how to inject Object when it really should be injecting the enum.
I'm using TypeORM to connect to a Postgres Database and I'm really new to JavaScript and TypeORM etc. So what I'm trying to do which I suppose shouldn't be really difficult, is to access an object properties after returning its value from Postgres.
So when I use the findOne() method in TypeORM it returns a Promise of the Object I return, i.e. in the following example I want to return a single user from the db so I can read its properties and check if its password matches the one that is being supported with the username I search for.
#Get(':username/:pwd')
authUser(#Param('username') username: string, #Param('pwd') pwd: string): Promise<User> {
const userToAuth = this.userAuthService.findOneUser(username);
return userToAuth;
}
My question is: Is there a way to transform that Promise into a User object so I can access its properties (pwd in this case) so I can further check if the password is valid? Or is there anyway to work around this? Accessing the promises response directly would be valid too as when I use postman the method returns an object that looks like:
{
name: xxxx,
email: xxxx,
password: xxxx,
...
}
So if I could just read those properties directly from within the method it would be cool as well.
I hope everything's clear, if you need further info on the question I'll be glad to help! :)
You can convert your function into an async one and await until Promise<User> resolves:
#Get(':username/:pwd')
async authUser(#Param('username') username: string, #Param('pwd') pwd: string): Promise<User> {
const userToAuth = await this.userAuthService.findOneUser(username);
// Here you can run your validation logics, or further access user object internal properties
/* your-code-here */
// Finally you can return the result
return userToAuth;
}
I need to pass to the updateMany method in a Node/Typescript software a piece of query retrieved from the database:
{'$unset': {'extras' : {'origin': ''}}}
In the db, the above query is stored as a field of an Object:
"cleanup.aggregated_records_to_modify" : {
"update_fields_by" : "{'$unset': {'extras' : {'origin': ''}}}"
}
If I pass the update_fields_by to the updateMany mondodb Nodejs driver method, I have an error saying ""MongoError: the update operation document must contain atomic operators." (it receives a string instead of an object?!?); if, instead, I create an object variable:
const queryTemp = { $unset: { extras: { origin: "" } } };
to give to the updateMany, all goes well.
How can I retrieve the field from db and correctly pass it to the update method as an object?
If you use JSON.parse(foo) on your variable, to convert it from string to an object
There was a problem (a bug?) with the tool I use to manage MondoDB; I cannot store an object with a key starting with $ because I receive the error "Illegal argument: Invalid BSON field name $unset". I have add the $ symbol programmatically.
Consider following class in JavaScript:
Tools.UserBase = Tools.Class.define("Tools.UserBase", Tools.EntityBase, {
UserId: { type: System.Int32, key: true, computed: true },
IsActive: { type: System.Boolean },
IsAdmin: { type: System.Boolean },
UserName: { type: System.String },
UserToken: { type: System.Guid },
init: function () {
Tools.EntityBase.call(this, arguments);
},
onEndEdit: function () {
if (this.IsActive == false && this.IsAdmin == true) {
throw new Error("Can't disable admin user");
}
this.parentClass.onEndEdit();
}
});
When I execute this code:
var user = new Tools.UserBase()
I'll get following results:
UserBase {
IsActive: false
IsAdmin: false
UserId: 0
UserName: ""
UserToken: "00000000-0000-0000-0000-000000000000"
__BackingField__IsActive: false
__BackingField__IsAdmin: false
__BackingField__UserId: 0
__BackingField__UserName: ""
__BackingField__UserToken: "00000000-0000-0000-0000-000000000000"
__proto__: PrototypeConstructor }
Then I use following command to create json from user object.
JSON.stringify(user)
And I get following results:
""__BackingField__UserId":0,"__BackingField__IsActive":false,"__BackingField__IsAdmin":false,"__BackingField__UserName":"","__BackingField__UserToken":"00000000-0000-0000-0000-000000000000"}"
As you can see it serialize my object with its fields instead of its properties.
And I've no control on serialization process at all.
The deserialization process is the same, JSON.parse will create a plain object instead of typed objects.
(I'm not saying that it should do what I want, I'm looking for a solution for my situation)
Is there any JavaScript library which fits my needs? as like as Newtonsoft in .NET ?
Thanks in advance.
And I've no control on serialization process at all.
Yes you do. Give you class a toJSON method that returns an object with the expected properties and it will be recognized by JSON.stringify.
The deserialization process is the same, JSON.parse will create a plain object instead of typed objects.
Because JSON does represent plain objects, that is only natural :-) Still, you can pass a reviver function to JSON.parse, which can manipulate the returned objects and exchange them for class instances. For convenience, add a (static) fromJSON function to your class that you can use in the reviver.
Is there any JavaScript library which fits my needs?
Most MVC JavaScript libraries have built-in serialisation/deserialisation methods for their models. You can either use one of them or get inspired by their code to extend your Tools.Class suite.
But I want to have something like this JSON.parse(jsonStr , Person) and it creates a new person for me instead of plain object.
I've made an npm module named esserializer to solve this problem: save JavaScript class instance values during serialization, in plain JSON format, together with its class name information:
const ESSerializer = require('esserializer');
const serializedText = ESSerializer.serialize(anInstanceOfClassPerson);
Later on, during the deserialization stage (possibly on another machine), esserializer can recursively deserialize object instance, with all Class/Property/Method information retained, using the same class definition:
const deserializedObj = ESSerializer.deserialize(serializedText, [Person]);
// deserializedObj is a perfect copy of anInstanceOfClassPerson