Data "corrupts" on insert
Opened this issue · 2 comments
Hii there,
I'm trying to use AloeDB to keep track of user mutes.
However, I'm trying to insert data that, on runtime is an instance of a custom Time
class (that allows for easier manipulation of datetime data).
This is what creating the object looks like:
interface IMutedUser {
id: string;
username: string;
start: any;
expiry: any;
reason: string;
}
const mute: IMutedUser = {
id: userId.value,
username: user.username,
start: new Time(),
expiry: new Time().addHours(1),
reason: (reasonObj) ? reasonObj.value : 'No reason specified.'
}
And this is how it looks on runtime:
{
id: "1234567890",
username: "FinlayDaG33k",
start: Time { time: 2021-06-03T07:42:45.463Z },
expiry: Time { time: 2021-06-03T08:42:45.463Z },
reason: "No reason specified."
}
Now I insert the data into my database like this:
await AppData.mutedUsers.insertOne(mute);
And suddenly, the object has changed to this:
{
id: "1234567890",
username: "FinlayDaG33k",
start: Time {},
expiry: Time {},
reason: "No reason specified."
}
This causes issues later in the code where the mute
object's Time
instance will be used to format a message.
Additionally, in the output JSON, it shows the following:
[
{
"id": "1234567890",
"username": "FinlayDaG33k",
"start": {},
"expiry": {},
"reason": "No reason specified."
}
]
So the dates are just not saved at all.
Is there a way to get around this?
I mainly work in CakePHP and there we have a beforeSave
method that allows us to specify behaviour that needs to be done before saving the data as well as an afterFind
that allows us to specify behaviour that needs to be done when obtaining an entity from the database.
In AloeDB, this could look something like this:
// Open the database
const db = new Database<IMutedUser>(`muted-users.json`);
// Do some things before saving an entity
db.beforeSave((entity: IMutedUser) => {
entity.start = entity.start.getTime; // Get the "vanilla" DateTime object
entity.expiry = entity.expiry.getTime; // Get the "vanilla" DateTime object
return entity;
});
// Do some things after loading an entity
db.afterLoad((entity: IMutedUser) => {
entity.start = new Time(entity.start); // Instantiate our custom Time class with DateTime object
entity.expiry = new Time(entity.expiry); // Instantiate our custom Time class with DateTime object
return entity;
});
Hi! Only primitive types, arrays and objects are supported now. So all fields with complex types such as Dates, Maps, Sets, etc. are automatically removed.
The beforeSave
and afterLoad
example you gave looks pretty cool, so I'll try to add it in the next update. Also, I'm thinking of adding Dates support, but not sure how to do that yet.
I think, as a temporary option, you could do something like that:
const mute: IMutedUser = {
id: userId.value,
username: user.username,
start: new Time(),
expiry: new Time().addHours(1),
reason: (reasonObj) ? reasonObj.value : 'No reason specified.'
}
mute.start = mute.start.time.toJSON();
mute.expiry = mute.expiry.time.toJSON();
await AppData.mutedUsers.insertOne(mute);
Hii there,
Yea, I solved it in a similar fashion for now (because I need the mute
object as-is for later`).
const mute: IMutedUser = {
id: userId.value,
username: user.username,
start: new Time().getTime,
expiry: new Time().addHours(1).getTime,
reason: (reasonObj) ? reasonObj.value : 'No reason specified.'
}
// ... Some more stuff
await AppData.mutedUsers.insertOne({
id: mute.id,
username: mute.username,
start: mute.start.toString(),
expiry: mute.expiry.toString(),
reason: mute.reason
});
// ... Some more stuff that needs the start and expiry
Adding a beforeSave
and afterLoad
will also add some additional benefits (like encrypting and decrypting data, automatically hashing user passwords while saving) etc.
Additionally, it may be wise to add some information to the beforeSave
on whether its an insert or an update.
Below is just a little mock-up so you should be able to understand what I mean:
class DbSaveEvent {
private isNew: boolean;
public get isNew() { return this.isNew; }
construct() {
this.isNew = true;
}
}
db.beforeSave((entity: IUser, event: DbSaveEvent) => {
if(event.isNew) {
entity.password = securePasswordHashingThingyMahJingles(entity.password);
}
});;