How do I use entity listeners in TypeORM without using decorators? - typeorm

I'm working on creating a users table. I want to be able to set the password field (which should ideally not be a saved field (not sure if typeorm allows that yet)) and on insert/update I want to look and see if the password field is set, if it is I want to save a new salt and a hashed password to the database instead. I found some thing that showed me how to do it with the #BeforeInsert entity listener, but i'm using javascript without decorators.
user.entity.js:
module.exports = new EntitySchema({
name: "User",
columns: {
id: { primary: true, type: "uuid", generated: "uuid" },
username: { type: "text", unique: true },
password: { type: "text"}, //i'd prefer this to be hashed_password and password to only be used in the listeners
salt: { type: "text" },
email: { type: "text", unique: true },
},
})

Related

Return ONLY selected fields within a TypeORM find request

I'm struggling in returning only selected fields in my TypeORM find request.
Assuming the following request
const data = await AppDataSource.manager.find(User, {
select: {
id: true,
hash: true,
firstname: true,
lastname: false,
},
take: 10, // Just here to shrink dataset
});
The script works pretty well excepted that it return every field of my model, with default value initialized.
[
User {
prefix: 'usr',
hash: 'usr_835b0ad2-XXXXXX',
email: undefined,
accountValidated: false,
role: 'free',
myKeyOne: true,
myKeyTwo: false,
gender: 'unspecified',
lastConnexion: 2023-01-19T10:11:02.733Z,
pendingDeletion: false,
deletionDate: undefined,
firstname: 'Clément',
lastname: undefined,
password: undefined,
facebookId: undefined,
googleId: undefined,
id: 158
},
...
]
Of course, it's not usable as it, because I have extensive relations, and thus the payload would be extremely heavy.
Are you aware of a method / a way to remove all unnecessary fields ?
i.e. I'm expecting
[
User {
id: 124,
hash: 'urs_XXXX',
firstname: 'Clément',
},
...
]
In older versions of typeorm I think you need to select with an array of strings, try:
select: ["id", "hash", "firstname"],
See this older version of the docs: https://github.com/typeorm/typeorm/blob/bc60dd559ba42af083ddea17f01205c78c83c7e0/docs/find-options.md
After hours of researches I've finally found out why it behaved like this.
TypeORM relies on class definitions and typescript so...
if you have typescript default values OR if you have rewrite your constructor, all the "default" properties are injected.
Assuming a User model
❌ You should not do
#Entity({ name: 'users' })
class User {
#Column()
firstname?: string;
#Column({ nullable: true })
lastname?: string;
#Column({ unique: true, nullable: false })
email!: string;
#Column({ name: 'account_validated', nullable: false})
accountValidated?: boolean = false
//Your other fields...
}
✅ You should do
#Entity({ name: 'users' })
class User {
#Column()
firstname?: string;
#Column({ nullable: true })
lastname?: string;
#Column({ unique: true, nullable: false })
email!: string;
// Use default argument of the decorator
#Column({ name: 'account_validated', nullable: false, default: false})
accountValidated?: boolean
//Your other fields...
}
And if you need in some way to init a default, then create a public static method which return the Entity instead of using the constructor.
#Entity({ name: 'users' })
class User {
//...fields
public static init(...params): User {
let _user = new User()
//...populate your object
return _user
}
}

JHipster yeoman repeating prompt based on option selected

Suppose I want to prompt the user to select among a list of database options with "type checkbox":
{
type: 'checkbox',
name: 'databaseType',
message: `Which ${chalk.yellow('*type*')} of database(s) would you like to use?`,
choices: response => {
const databaseOpts = [
{
value: 'mysql',
name: 'MySQL'
},
{
value: 'cassandra',
name: 'Cassandra'
},
{
value: 'mongodb',
name: 'MongoDB'
}
];
return databaseOpts;
},
default: 0
},
After this initial prompt, I want to get the response for whichever option(s) they selected and prompt them again for the name of the database based on their selection(s) then store them:
{
when: response => response.databaseType === 'mysql',
type: 'input',
name: 'selectedMySQL',
message: 'What is the name of your mysql database? ',
default: 'testmysql',
store: true
},
{
when: response => response.databaseType === 'cassandra',
type: 'input',
name: 'selectedCassandra',
message: 'What is the name of your cassandra database? ',
default: 'testcassandra',
store: true
},
{
when: response => response.databaseType === 'mongo',
type: 'input',
name: 'selectedMongo',
message: 'What is the name of your mongo database? ',
default: 'testmongo',
store: true
}
Sample Desired Output:
For example user's choices in databaseOpts: {mysql, mongodb}
It will then ask:
1) What is the name of your mysql database?:
2) What is the name of your mongo database?:
User enters the name(s) respectively which will be stored in selectedMySQL and selectedMongo.
I'm unfamiliar with yeoman syntax, but this is the logic I want to implement. Please help, Thanks.
I tried:
when: response => response.databaseType.databaseOpts === 'mysql'
but it's still skipping the response prompts.

Mongodb and Node js

i am new in node js, and I am trying to build an app quiz engine using node js and mongo DB. I am not sure what I need to make a schema for quiz engine. So anyone can help me.
Here is an example of a User Schema...
var userSchema = new Schema({
name: {
type: String,
unique: true,
required: true
},
password: {
type: String,
required: true
}
});
But like the comment stated, you will have to be more specific.
As far as i can guess, a quiz will be given by user and it will have questions. So, you can make two entities :
i) User entity
ii) Quiz/Questions entity
User entity schema :
module.exports = {
attributes = {
name: {
type: String,
required: true
},
password: {
type: String,
required: true
}
password: {
type: String,
required: true
}
}
};
Question entity schema :
module.exports = {
attributes = {
questionLabel: {
type: 'String',
required: true
},
choices: {
type: 'Array',
required: true
}
};
Hello this is my schema
enter code here var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var img_schema = new Schema({
title:{type:String,require:true},
creator:{type:Schema.Types.ObjectId, ref: "User" },
extension:{type:String,require:true},
foto:{type:String,require:true},
uso:{type:String,require:true}
});
var Imagen = mongoose.model("Imagen",img_schema);
module.exports = Imagen;
This is the example of user schema. you can replace with your requirement.
// User Schema
var UserSchema = mongoose.Schema({
username: {
type: String,
index: true
},
password: {
type: String
},
email: {
type: String
},
name: {
type: String
},
profileimage:{
type: String
}
});
var User = module.exports = mongoose.model('User', UserSchema);
I will suggest you to use mongoose to define your mongoDB collection schemas. Mongoose facilitates a lot of processes between nodejs and mongoDB.
You can install mongoose using following command:
npm i mongoose
Then create a schema like this:
import mongoose from 'mongoose';
const { Schema } = mongoose; //Pulling schema out of mongoose object
const QuizEngineSchema = new Schema({
name: String,
phoneNumber: Number,
// other data that you need to save in your model
},
{timestamps: true},
{id: false});
//Plugging the Schema into the model
const QuizEngine = mongoose.Model('QuizEngine',QuizEngineSchema);
export default QuizEngine;
Hope this helps!

Overriding Symfony Form's Save Function

I have two issues, need some help with.
I have a table which is referenced by a foreign key to a second table:
member_child:
_attributes: { phpName: MemberChild }
id: { type: INTEGER, size: '11', primaryKey: true, autoIncrement: true, required: true }
member_id: { type: INTEGER, size: '11', required: true, foreignTable: member, foreignReference: id }
child_id: { type: INTEGER, size: '11', required: true, foreignTable: child, foreignReference: id }
and child:
child:
_attributes: { phpName: Child }
id: { type: INTEGER, size: '11', primaryKey: true, autoIncrement: true, required: true, onDelete: cascade }
username: { type: VARCHAR, size: '45', required: true, defaultValue: '' }
display: { type: TINYINT, size: '1', required: true, defaultValue: '1' }
...etc
(obviously this is propel)
Now, when I want to create a child object, using a form, I need to do two things:
On submit, submit a member id
override the doSave function so when the child is created, I can also create the member_child object
How can I accomplish these issues?
I agree, you can use embedForm like pankar said. Also you can override save method of your forms like this:
$this->childForm = new ChildForm();
$this->childMemberForm = new ChildMemberForm();
//binding, checking if form was sent etc.
if ($this->childForm->isValid() && $this->childMemberForm->isValid())
{
//save method should return saved object
$childObject = $this->childForm->save();
//therefore this id could be used by next object
$this->childMemberForm->save(childObject->getId());
}
I hope that will help you!
You can always use the built-in Symfony feature sfForm::embedForm in your parent form in order to save the child one, but I haven't figure out a a way of properly get this working.
One post I came across some time ago actually did provide me with the solution. Have a look and see if it fits your needs. Of course it's in Doctrine but I suppose it can be easily ported in Propel

An example on how to embed forms in Symfony

I am using Symfony 1.3.2 with Propel ORM on Ubuntu 9.10.
I have a user profile table, which has many other tables linked to it (i.e. user_profile.id is a FK in many other tables.
My db schema looks something like this:
user_profile:
_attributes: { phpName: UserProfile }
id: ~
guard_id: { type: integer, foreignTable: sf_guard_user, foreignReference: id, required: true }
address: { type: longvarchar, required: true }
vehicle_type:
_attributes: { phpName: VehicleType }
id: ~
name: { type: varchar(32), required: true }
user_vehicle:
_attributes: { phpName: UserVehicle }
id: ~
user_id: { type: integer, foreignTable: user_profile, foreignReference: id, required: true }
vehicle_type: { type: integer, foreignTable: vehicle_type, foreignReference: id, required: true }
license_plate: { type: varchar(16), required: true }
user_child:
_attributes: { phpName: UserChild }
id: ~
user_id: { type: integer, foreignTable: user_profile, foreignReference: id, required: true }
gender: { type: boolean, required: true }
name: { type: varchar(32), required: true }
I would like to embed the other objects that link to the user profile object, in the user profile form, so that when I am performing CRUD on a user profile form, the related objects (e.g. UserVehicle, UserJob are also CRUD at the same time as the user profile object).
I need a simple snippet that will show how to:
Embed the various related objects (i.e. UserVehicle, UserChild) into the UserProfile form
Create/Update/Delete the various related objects as the operation is being carried (please note, a user can have more than 0-N vehicles or children assigned to them
Have you read the documentation?:
// lib/form/doctrine/ProductForm.class.php
public function configure()
{
$subForm = new sfForm();
for ($i = 0; $i < 2; $i++)
{
$productPhoto = new ProductPhoto();
$productPhoto->Product = $this->getObject();
$form = new ProductPhotoForm($productPhoto);
$subForm->embedForm($i, $form);
}
$this->embedForm('newPhotos', $subForm);
}
For the create/delete/update part, this article might give some help.
I never found the official approach right for my needs. I developed a completely different approach. In the company where I used to work we used in production this new approach, finding it a bit more elastic and simple. The key concept is "don't use Symfony's Form class and you will discover that embedding forms can be a very simple task"
I hope this can help you embedding forms.

Resources