How to create dynamic response model for Swagger in Nest JS - node.js

I created an API which is returning selected fields of user data.
User model:
#Exclude()
#Entity('users')
export class User extends Timestampable {
#ApiProperty()
#PrimaryGeneratedColumn()
id: number;
#ApiProperty()
#Expose({ groups: ['create', 'profile'] })
#Column({ unique: true })
email: string;
#ApiProperty()
#Expose({ groups: ['create'] })
#Column()
password: string;
#ApiProperty()
#Expose({ groups: ['profile'] })
#Column({ nullable: true })
firstName: string;
#ApiProperty()
#Expose({ groups: ['profile'] })
#Column({ nullable: true })
lastName: string;
#ApiProperty()
#Expose({ groups: ['profile'] })
#Column({ nullable: true })
paternalName: string;
#ApiProperty()
#Expose({ groups: ['profile'] })
#Column({ nullable: true })
phone: string;
#ApiProperty()
#Expose({ groups: ['profile'] })
#Column({ nullable: true, type: 'enum', enum: UserGender })
gender: UserGender;
}
Inside the controller, I just return:
return instanceToPlain(user, {
groups: ['profile'],
});
here will be returned only the fields of the user which have a profile group.
Everything working properly. But for swagger documentation I used:
{
schema: {shows
$ref: getSchemaPath(User),
},
}
and in the documentation, it shows all fields of the user.
How can I show only fields from the particular group?
One of the options create 2 different DTOs and use them but that solution in my opinion is not that good.

Related

insert or update on table violates foreign key constraint when I'm trying to make POST

When i'm trying to make a POST request, it records data in client table but doesn't in user_profile table, also it's doesn't record passportId in passport table. And also after request i got this error.
What am i missing?
{
"msg": "insert or update on table "user_profile" violates foreign key constraint "FK_259184fcdfba6d78485f5a048a0""
}
My ClientEntity:
#Entity()
export default class Client extends BaseEntity {
#PrimaryGeneratedColumn()
clientId: number;
#Column({ type: 'enum', enum: ClientStatus, default: ClientStatus.NOT_CLIENT })
clientStatus: ClientStatus;
#Column({ nullable: true })
countryOfResidence: string;
#Column({ nullable: true, length: 30 })
firstName: string;
#Column({ nullable: true, length: 30 })
lastName: string;
#Column({ nullable: true, length: 30 })
middleName: string;
#OneToOne(() => Passport)
#JoinColumn({ referencedColumnName: 'passportId', name: 'passportId' })
passportId: string;
#OneToOne(() => AuthVerification)
#JoinColumn({ referencedColumnName: 'mobilePhone', name: 'mobilePhone' })
mobilePhone: string;
#OneToOne(() => UserProfile, (userProfile) => userProfile.clientId)
userProfile: UserProfile;
}
My UserProfileEntity:
#Entity()
class UserProfile extends BaseEntity {
#PrimaryColumn()
#OneToOne(() => Client)
#JoinColumn({ referencedColumnName: 'clientId', name: 'clientId' })
clientId: number;
#Column({ nullable: true, default: false })
smsNotification: boolean;
#Column({ nullable: true, default: false })
pushNotification: boolean;
#Column({ nullable: true, default: false })
emailSubscription: boolean;
#Column({ length: 50, nullable: true })
securityQuestion: string;
#Column({ length: 50, nullable: true })
securityAnswer: string;
#Column({ length: 50, nullable: true, default: null })
email: string;
#Column({ length: 255, nullable: true })
password: string;
}
Line in migration with Constraint:
await queryRunner.query(
`ALTER TABLE "user_profile" ADD CONSTRAINT "FK_259184fcdfba6d78485f5a048a0" FOREIGN KEY ("clientId") REFERENCES "client"("clientId") ON DELETE NO ACTION ON UPDATE NO ACTION`
);
My register function:
public async registerNonClients(req: Request, res: Response) {
try {
const {
clientId,
mobilePhone,
password,
securityQuestion,
securityAnswer,
email,
firstName,
lastName,
middleName,
passportId,
countryOfResidence,
} = req.body;
await getRepository(Client).save({
clientId,
mobilePhone,
firstName,
lastName,
middleName,
countryOfResidence,
});
await getRepository(UserProfile).save({ clientId, password, securityQuestion, securityAnswer, email });
await getRepository(Passport).save({ passportId });
return res.status(StatusCodes.OK).json({ msg: 'Register successfull' });
} catch (error) {
return res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ msg: error.message });
}
}

Select query builder with relations error, cannot read property joincolumns of undefined on referenced column typeorm expressjs

I have two entities, users and roleuser, I have one to many mapping from user to role and many to one on user. while I am querying the result set, I am getting error as cannot read property joincolumns of undefined.Could anyone help me in solving this error, what am I doing wrong
Here are my entities.
// mosaique_user
#Entity()
export class MosaiqueUser {
#PrimaryGeneratedColumn()
id: number;
#Column({nullable: true, length: 100})
name: string;
#Column({unique: true, length: 255})
email: string;
#Column({nullable: true})
password: string;
#Column({nullable: true})
is_temp: number;
#Column({nullable: true})
salt: string;
#Column({nullable: true, default: 2})
status: number;
#Column({nullable: true, default: 2})
apply_status: number;
#Column({ type: 'timestamp', nullable: true})
created_at: Date;
#Column({ type: 'timestamp', nullable: true})
updated_at: Date;
#Column({ nullable: true})
created_by: number;
#Column({ nullable: true})
updated_by: number;
#OneToOne(() => MosaiqueUserProfile, userprofile => userprofile.user)
userprofile: MosaiqueUserProfile;
#OneToMany(() => RoleUser, userRole => userRole.user_id, {
cascade: true,
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
})
#JoinColumn({ referencedColumnName: 'user_id' })
userRoles!: RoleUser[];
}
// role_user
#Entity()
export class RoleUser {
#PrimaryGeneratedColumn()
id: number;
#Column()
user_id: number;
#Column()
role_id: number;
#CreateDateColumn()
created_at: Date;
#UpdateDateColumn()
updated_at: Date;
#ManyToOne(() => MosaiqueUser, user => user.userRoles)
#JoinColumn({ name: 'user_id' })
user!: MosaiqueUser;
#ManyToOne(() => MRole, role => role.userRoles)
#JoinColumn({ name: 'role_id' })
role!: MRole;
}
// with relations query
let userData = await this.mosaiqueUser.find({
relations: ['userRoles'],
where: {'id':1}
});
Error
(node:57872) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'joinColumns' of undefined
at C:\Sites\Dynamodb\TypeORMProject\src\query-builder\SelectQueryBuilder.ts:1549:61
at Array.map ()
at SelectQueryBuilder.createJoinExpression (C:\Sites\Dynamodb\TypeORMProject\src\query-builder\SelectQueryBuilder.ts:1520:57)
at SelectQueryBuilder.getQuery (C:\Sites\Dynamodb\TypeORMProject\src\query-builder\SelectQueryBuilder.ts:57:21)
at SelectQueryBuilder.QueryBuilder.getQueryAndParameters (C:\Sites\Dynamodb\TypeORMProject\src\query-builder\QueryBuilder.ts:446:28)
at SelectQueryBuilder. (C:\Sites\Dynamodb\TypeORMProject\src\query-builder\SelectQueryBuilder.ts:2112:40)
at step (C:\Sites\Dynamodb\TypeORMProject\node_modules\tslib\tslib.js:144:27)
at Object.next (C:\Sites\Dynamodb\TypeORMProject\node_modules\tslib\tslib.js:125:57)
at C:\Sites\Dynamodb\TypeORMProject\node_modules\tslib\tslib.js:118:75
at new Promise ()

Insert or update on table violates foreign key constraint error

I'm trying to make a POST-request and getting this error
{
"msg": "insert or update on table "client" violates foreign key constraint "FK_e61c5ecfaabf7e6d9285fbfb070""
}
My Client entity:
#Entity()
export default class Client extends BaseEntity {
#PrimaryGeneratedColumn()
clientId: number;
#Column({ type: 'enum', enum: ClientStatus, default: ClientStatus.NOT_CLIENT })
clientStatus: ClientStatus;
#Column({ nullable: true })
countryOfResidence: string;
#Column({ nullable: true, length: 30 })
firstName: string;
#Column({ nullable: true, length: 30 })
lastName: string;
#Column({ nullable: true, length: 30 })
surName: string;
#OneToOne(() => Passport)
#JoinColumn({ referencedColumnName: 'passportId', name: 'passportId' })
passportId: string;
#OneToOne(() => AuthVerification)
#JoinColumn({ referencedColumnName: 'mobilePhone', name: 'mobilePhone' })
mobilePhone: string;
#OneToOne(() => UserProfile, (userProfile) => userProfile.clientId)
userProfile: UserProfile;
}
My AuthVerification entity:
#Entity()
class AuthVerification extends BaseEntity {
#PrimaryColumn()
#OneToOne(() => Client)
mobilePhone: string;
#Column({ nullable: true })
email: string;
#Column({ nullable: false, length: 6 })
verificationCode: string;
}
Line in migration where constraint key mentioned:
await queryRunner.query(
`ALTER TABLE "client" ADD CONSTRAINT "FK_e61c5ecfaabf7e6d9285fbfb070" FOREIGN KEY ("mobilePhone") REFERENCES "auth_verification"("mobilePhone") ON DELETE NO ACTION ON UPDATE NO ACTION`
);
So, I can't figure out where the problem is.

Use repository.clear() to clear two tables with ManyToOne

Is there any ways to clear two tables connected with ManyToOne?
Table A
#Entity('table_A')
export class TableA{
#PrimaryGeneratedColumn()
id: number;
#Column()
B_ID: number;
#ManyToOne(() => TableB)
tableB: TableB;
#Column()
userId: number;
#ManyToOne(() => User)
user: User;
}
Table B
#Entity('table_B')
export class TableB{
#PrimaryGeneratedColumn()
id: number;
#Column({ name: 'time', type: 'text' })
time: Date;
#Column({ name: 'msgid', type: 'int', nullable: true })
msgid: number;
#Column({ name: 'event', type: 'text', nullable: true })
event: string;
}
I can use this.tableARepository.clear(); to clear Table_A but when I run this.tableBRepository.clear(); Data in Table A restores.
Anyone have a clue on this? Any help is much appreciated.

How to Get data in mutiple #ManyToMany in Nest.js

I have a ManyToMany relation between two entities and I don't know how can I Get data from the join table "device_users_user"
#Entity()
export class Device{
#PrimaryColumn()
Name:string;
#Column({ nullable: true})
Port:number;
#Column({ nullable: true})
IPadress:string;
#Column({ nullable: true})
Location:string;
#ManyToMany(type => User)
#JoinTable()
users: User[];
}
#Entity()
export class User{
#PrimaryColumn()
Id:number;
#Column({ nullable: true})
Departement:string;
#Column({ nullable: true})
FirstName:string;
#Column({ nullable: true})
LastName:string;
#Column({ nullable: true})
CardNumber:string;
#Column({ nullable: true})
MobilePhone:string;
}
You cannot query the join table directly, using the TypeORM API's (unless you try to do a raw query, but I assume this is not what you want to achieve... And I don't recommend it, as table names might be changed...).
However, as you declared the relation using #ManyToMany, you can load the users of your devices with a Query Builder, for instance:
const devicesWithUsers = await deviceRepository.createQueryBuilder('device')
.leftJoin('device.users', 'user')
.where(/* whatever you need */)
.getMany();
The documentation of TypeORM gives more examples, e.g.:
const user = await createQueryBuilder("user")
.leftJoinAndSelect("user.photos", "photo")
.where("user.name = :name", { name: "Timber" })
.getOne();
which could gives, as a result:
{
id: 1,
name: "Timber",
photos: [{
id: 1,
url: "me-with-chakram.jpg"
}, {
id: 2,
url: "me-with-trees.jpg"
}]
}

Resources