ExceptionHandler No metadata for "Profile" was found in nest.js - nestjs

I was creating Nest.js project and faced some problems with it. I assume the problem lies within profile.entity.ts file since if I remove that file then all works ok. So, I have several files app.module.ts file:
import { Module } from '#nestjs/common';
import { TypeOrmModule } from '#nestjs/typeorm';
import { typeOrmConfig } from './config/typeorm.config';
import { ProfileModule } from './profile/profile.module';
#Module({
imports: [TypeOrmModule.forRoot(typeOrmConfig), ProfileModule],
controllers: [],
providers: [],
})
export class AppModule {}
profile.entity.ts
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from "typeorm";
#Entity()
export class Profile extends BaseEntity{
#PrimaryGeneratedColumn()
id: number;
#Column()
fullName: string;
#Column()
company: string;
#Column()
position: string;
#Column()
dateOfBirth: Date;
#Column()
phoneNumber: string;
#Column()
additionalPhoneNumber: string;
#Column()
email: string;
#Column()
additionalEmail: string;
#Column()
website: string;
#Column()
additionalWebsite: string;
#Column()
facebook: string;
#Column()
instagram: string;
#Column()
telegram: string;
#Column()
whatsapp: string;
#Column()
vk: string;
#Column()
tikTok: string;
#Column()
linkedIn: string;
#Column()
youTube: string;
#Column()
skype: string;
#Column()
modeDetails: string;
}
profile.module.ts
import { Module } from '#nestjs/common';
import { TypeOrmModule } from '#nestjs/typeorm';
import { ProfileController } from './profile.controller';
import { ProfileRepository } from './profile.repository';
import { ProfileService } from './profile.service';
#Module({
imports:[TypeOrmModule.forFeature([ProfileRepository])],
controllers: [ProfileController],
providers: [ProfileService]
})
export class ProfileModule {}
profile.repository.ts
import { Profile } from './profile.entity';
import { EntityRepository, Repository } from 'typeorm';
#EntityRepository(Profile)
export class ProfileRepository extends Repository<Profile> {}
typeorm.config.ts
import { TypeOrmModuleOptions } from "#nestjs/typeorm";
export const typeOrmConfig:TypeOrmModuleOptions={
type:'postgres',
host:'localhost',
port:5432,
username:'postgres',
password:'M',
database: 'profileManagement',
entities:[__dirname + '/../**/*.entity.ts'],
synchronize:true
}
Please help I cannot find the exact place where I did wrong

Change your entities from __dirname + '/../**/*.entity.ts' to __dirname + '/../**/*.entity.js'. What's happening is that when you transpile the code from ts to js the code moves from src to dist. At this time, there is no ts code in the dist, so the glob you're using doesn't find anything. If you use .js however, it will find matching files, and be able to make use of the metadata that is set there.

Related

How to create migration for entities with properties that have relation #ManyToOne and #OneToMany with TypeORM?

I have 5 entities: User, Todos, Project, Section and Label. Relationships happen as follows:
Each User is associated with multiples Todo.
Each Todo is associated with a single User, Project and Section, and is associated with multiples Label.
Each Project is associated with a single User.
Each Section is associated with a single Project.
Each Label is associated with a single Todo.
The migration code to the #OneToOne relationship is done using the createForeignKey method, as done for project_id column at Section entity:
import {
MigrationInterface,
QueryRunner,
TableColumn,
TableForeignKey,
} from 'typeorm';
export class AddProjectIdToSections1669830961233 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.addColumn(
'sections',
new TableColumn({
name: 'project_id',
type: 'uuid',
isNullable: true,
})
);
await queryRunner.createForeignKey(
'sections',
new TableForeignKey({
name: 'SectionsProject',
columnNames: ['project_id'],
referencedTableName: 'projects',
referencedColumnNames: ['id'],
onDelete: 'SET NULL',
})
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropForeignKey('sections', 'SectionsProject');
await queryRunner.dropColumn('sections', 'project_id');
}
}
However, how do you use createForeignkey for relations of #OneToMany and #ManyToOne, and especially when the two happen round trip?
Entities code:
// User.entity.ts
import {
Column,
CreateDateColumn,
Entity,
OneToMany,
PrimaryGeneratedColumn,
} from 'typeorm';
import { Todo } from './Todo.entity';
#Entity('users')
export class User {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column()
name: string;
#Column()
email: string;
#Column()
password: string;
#Column({ nullable: true })
photoURL: string;
#Column()
language: string;
#CreateDateColumn()
created_at: Date;
#OneToMany(() => Todo, (todo) => todo.user)
todos: Todo[];
}
// Todo.entity.ts
import {
Column,
Entity,
JoinColumn,
ManyToOne,
OneToMany,
OneToOne,
PrimaryGeneratedColumn,
} from 'typeorm';
import { IProject } from '../types';
import { Label } from './Label.entity';
import { Project } from './Project.entity';
import { Section } from './Section.entity';
import { User } from './User.entity';
#Entity('todos')
export class Todo {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column()
title: string;
#Column()
description?: string;
#Column()
type: string;
#Column({ type: 'timestamptz' })
date: Date;
#Column()
priority: number;
#Column()
isCompleted: boolean;
#OneToOne(() => Project)
#JoinColumn({ name: 'project_id' })
project: IProject;
#OneToOne(() => Section)
#JoinColumn({ name: 'section_id' })
section?: Section;
#OneToMany(() => Label, (label) => label.todo, {
cascade: true,
})
labels: Label[];
#ManyToOne(() => User, (user) => user.todos)
#JoinColumn({ name: 'user_id' })
user: User;
}
// Project.entity.ts
import {
Column,
Entity,
JoinColumn,
OneToOne,
PrimaryGeneratedColumn,
} from 'typeorm';
import { User } from './User.entity';
#Entity('projects')
export class Project {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column()
type: string;
#Column()
title: string;
#Column()
colorName: string;
#Column()
class: string;
#OneToOne(() => User)
#JoinColumn({ name: 'user_id' })
user: User;
}
// Section.entity.ts
import {
Column,
Entity,
JoinColumn,
OneToOne,
PrimaryGeneratedColumn,
} from 'typeorm';
import { Project } from './Project.entity';
#Entity('sections')
export class Section {
#PrimaryGeneratedColumn('uuid')
readonly id: string;
#Column()
index: number;
#Column()
type: string;
#Column()
title: string;
#Column({ type: 'timestamptz' })
readonly date: Date;
#OneToOne(() => Project)
#JoinColumn({ name: 'project_id' })
project: Project;
}
// label.entity.ts
import {
Column,
Entity,
JoinColumn,
ManyToOne,
PrimaryGeneratedColumn,
} from 'typeorm';
import { Todo } from './Todo.entity';
#Entity('labels')
export class Label {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column()
type: string;
#Column()
title: string;
#Column()
colorName: string;
#Column()
class: string;
#ManyToOne(() => Todo, (todo) => todo.labels)
#JoinColumn({ name: 'todo_id' })
todo: Todo;
}

Typeorm migration with bi-directional manytomany resulting in TypeError: Class exends value undefined is not a constructor or null

I'm working on a nestjs project with TypeORM. I'm setting up a bidirectional ManyToMany relationship between two entities: Notes and Gcalevents. Every Note could be linked to multiple Gcalevents, and every Gcalevent could be linked to many Notes.
Snippets from my entity definitions look like this:
base.entity.ts:
export class BaseEntity {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column({ type: 'boolean', default: true })
isActive: boolean;
... // some more fields
}
note.entity.ts:
import { Gcalevent } from './gcalevent.entity';
import { BaseEntity } from './base.entity';
#Entity({ name: 'note' })
export class Note extends BaseEntity {
#Column({ type: 'varchar', length: 300 })
title: string;
...
#ManyToMany(() => Gcalevent, (gcalevent) => gcalevent.notes)
#JoinTable()
gcalevents: Gcalevent[]
}
gcalevent.entity.ts:
import { Note } from "./note.entity";
#Entity({ name: 'gcalevent' })
export class Gcalevent {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column({
type: 'varchar',
nullable: false,
})
eventId: string;
...
#ManyToMany(() => Note, (note) => note.gcalevents)
notes: Note[]
}
I believe I'm declaring the ManyToMany relationships correctly, but when I try to generate the TypeORM migration, I get the error TypeError: Class extends value undefined is not a constructor or null, which points to both the note.entity and gcalevent.entity files
I'm guessing this has something to do with the gcalevent.entity and note.entity files importing each other, combined with the note.entity file importing BaseEntity, but not sure how to fix it!
I had the same problem, I've found here
this "workaround" for the issue.
Try using "strings" instead of "types" in the #ManyToMany decorator:
note.entity.ts:
import { Gcalevent } from './gcalevent.entity';
import { BaseEntity } from './base.entity';
#Entity({ name: 'note' })
export class Note extends BaseEntity {
#Column({ type: 'varchar', length: 300 })
title: string;
...
#ManyToMany("Gcalevent","notes")
#JoinTable()
gcalevents: Gcalevent[]
}
gcalevent.entity.ts:
import { Note } from "./note.entity";
#Entity({ name: 'gcalevent' })
export class Gcalevent {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column({
type: 'varchar',
nullable: false,
})
eventId: string;
...
#ManyToMany("Note","gcalevents")
notes: Note[]
}

Exclude() method is not working for post method in Nestjs

I have tried adding toJSON(){return classtoPlain(this)} in my entity still its not working.
Here is my controller
#Controller('users')
#UseInterceptors(ClassSerializerInterceptor)
export class UsersController {
constructor(private readonly usersService: UsersService) {}
#HttpCode(200)
#Post()
async create(#Body() user: User): Promise<User> {
return await this.usersService.create(user).catch((err) => {
throw new HttpException({ message: err.message }, HttpStatus.BAD_REQUEST);
});
}
Here is my Entity
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
import { Gender } from '../Constants/enum';
import { Exclude, instanceToPlain } from 'class-transformer';
#Entity()
export class User {
#PrimaryGeneratedColumn()
id: number;
#Column()
firstName: string;
#Column()
lastName?: string;
#Column({
type: 'enum',
enum: Gender,
})
gender: Gender;
#Column({ unique: true })
email: string;
#Column()
#Exclude({ toPlainOnly: true })
password: string;
constructor(partial: Partial<User>) {
Object.assign(this, partial);
}
toJSON() {
return instanceToPlain(this);
}
}
Here is my service
import { Injectable } from '#nestjs/common';
import { InjectRepository } from '#nestjs/typeorm';
import { Repository } from 'typeorm';
import { UpdateUserDto } from './dto/update-user.dto';
import { User } from './entities/user.entity';
#Injectable()
export class UsersService {
constructor(
#InjectRepository(User)
private readonly user_detailsRepository: Repository<User>,
) {}
create(user: User) {
return this.user_detailsRepository.save(user);
}
I have tried many solutions but still nothing works.
For GET its working but for post its showing the password field.If any one can provide any solution it would be great.
You're mixing between Entity definition/validation, which typeORM functions/decorators (in your case) should handle. And DTO definition, which class-transformer/validator should handle
So you should define a createUserDTO.ts file like below, and use it as in the controller/service file:
export class createUserDTO {
#IsNotEmpty()
#IsString()
firstName: string;
#IsNotEmpty()
#IsString()
lastName?: string;
#IsNotEmpty()
#IsEnum(Gender)
gender: Gender;
#IsNotEmpty()
email: string;
#Exclude({ toPlainOnly: true })
password: string;
}
The entity file shouldn't have the password column (just omit the field completely), should look like this:
#Entity()
export class User {
#PrimaryGeneratedColumn()
id: number;
#Column()
firstName: string;
#Column()
lastName?: string;
#Column({
type: 'enum',
enum: Gender,
})
gender: Gender;
#Column({ unique: true })
email: string;
}
Then, when you call return this.user_detailsRepository.save(userDto);, it should work fine

How to handle empty strings with class validators in TypeORM

I want to create users from my Postman, I want to test my API endpoints, as it stands, it is possible to create a user if I pass something like " " as a value for the name column, how can I handle that in TypeORM? I don't know any class validator. My Dto file is below:
import { IsNotEmpty, IsString } from 'class-validator';
export class CreateRoomUserDto {
#IsNotEmpty()
#IsString()
public name: string;
#IsNotEmpty()
#IsString()
public room_interest: string;
#IsNotEmpty()
#IsString()
public occupation: string;
}
This is the entity file below
#import { IsNotEmpty } from 'class-validator';
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, OneToMany } from 'typeorm';
import { RoomUser } from '#/interfaces/room-user.interface';
Entity()
export class RoomUserEntity implements RoomUser {
#PrimaryGeneratedColumn()
id: string;
#Column()
#IsNotEmpty()
name: string;
#Column()
#IsNotEmpty()
room_interest: string;
#Column()
#IsNotEmpty()
occupation: string;
#CreateDateColumn()
createdAt: Date;
#Column()
#UpdateDateColumn()
updatedAt: Date;
}
The code below solves the problem, however, it is only able to catch the error if it is an empty array with just white space but it is not able to do anything if there's a white space at the beginning and/or the end of the string.
export class CreateRoomUserDto {
#IsNotEmpty()
#IsString()
#Transform(({ value }: TransformFnParams) => value?.trim())
public name: string;
#IsNotEmpty()
#IsString()
#Transform(({ value }: TransformFnParams) => value?.trim())
public room_interest: string;
#IsNotEmpty()
#IsString()
#Transform(({ value }: TransformFnParams) => value?.trim())
public occupation: string;
}

typeorm shows me this error: TypeError: Object prototype may only be an Object or null: undefined

I am new at typeorm and I created a user entity like this:
User.ts:
import {DefaultBaseEntity} from "../defaults/DefaultBaseEntity";
import {Entity, Column} from "typeorm";
#Entity("users")
export class User extends DefaultBaseEntity {
#Column()
username: string;
#Column()
email: string;
#Column()
password: string;
#Column()
account_type: string;
#Column()
photo_url: string;
#Column()
discipline: string;
#Column()
class: string;
#Column()
confirmed: number;
}
and this is DefaultBaseEntity.ts
import { BaseEntity, PrimaryGeneratedColumn, Column } from "typeorm";
export declare class DefaultBaseEntity extends BaseEntity {
#PrimaryGeneratedColumn()
id: string;
#Column()
createdAt: Date;
#Column()
updatedAt: Date;
constructor();
}
when I run the app it returns me this error: TypeError: Object prototype may only be an Object or null: undefined for running the app I use ts-node. What I missed?

Resources