@Module({
imports: [
TypeOrmModule.forRoot({
type: 'sqlite',
database: 'db.sqlite',
synchronize: true
}),
UsersModule,
ReportsModule],
controllers: [AppController],
providers: [AppService],
})
@Entity()
export class User {
// 자동으로 생성되는 칼럼
// Primary Key 로 사용됨.
@PrimaryGeneratedColumn()
id: number;
// 이하 DB Column
@Column()
email: string;
@Column()
password: string;
}
@Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [UsersController],
providers: [UsersService]
})
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'sqlite',
database: 'db.sqlite',
synchronize: true,
entities: [User],
}),
UsersModule,
ReportsModule],
controllers: [AppController],
providers: [AppService],
})
constructor(
@InjectRepository(User) private repo: Repository<User>
) {}
create(email: string, password: string) {
const user = this.repo.create({email, password});
return this.repo.save(user);
}
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
email: string;
@Column()
password: string;
@AfterInsert()
logInsert() {
console.log(`Inserted User with ${this.id}`);
}
}
find(email: string) {
return this.repo.find({ where: { email }})
}
findOne(id: number) {
return this.repo.findOneBy({id})
}
updateData(id: number, attrs: Partial<User>) {
}
async update(id: number, attrs: Partial<User>) {
const user = await this.findOne(id);
if(!user) {
throw new Error('user not found');
}
// attr의 값을 user에 대입한다.
Object.assign(user, attrs)
return this.repo.save(user);
}
@Column()
@Exclude()
password: string;
@UseInterceptors(ClassSerializerInterceptor)
@Get('/:id')
async findUser(@Param('id') id: string) {
const user = await this.usersService.findOne(parseInt(id));
if (!user) throw new NotFoundException('user not found');
return user;
}
class CustomInterceptor {
intercept(context: ExecutionContext, next: CallHandler);
}
export class SerializeInterceptor implements NestInterceptor {
constructor(private dto: any) {}
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(
map(
(data: any) => {
return plainToInstance(UserDto, data, {
excludeExtraneousValues: true,
})
}
)
)
}
}
@UseInterceptors(SerializeInterceptor)
@Get()
findAllUsers(@Query('email') email: string) {
return this.usersService.find(email);
}
import { Expose } from "class-transformer";
export class UserDto {
@Expose()
id: number;
@Expose()
email: string;
}
return next.handle().pipe(
map(
(data: any) => {
return plainToInstance(UserDto, data, {
excludeExtraneousValues: true,
})
}
)
)
}
export function Serialize(dto: any) {
return UseInterceptors(new SerializeInterceptor(UserDto));
}
를 interceptor 코드에 추가하고
@Serialize(UserDto)
@Get()
findAllUsers(@Query('email') email: string) {
return this.usersService.find(email);
}
와 같이 사용시 여러 종류의 Dto에 대응하도록 구현할수 있다.
// report 에서 자신이 있는 부분을 알린다.
@OneToMany(() => Report, (report) => report.user)
reports: Report[];
// user에서 자신이 있는 부분을 알린다.
@ManyToOne(() => User, (user) => user.reports)
user: User;
this.repo
.createQueryBuilder()
.select('*')
.where('make = :make', {make: brand}) // :make에 make key 의 값이 들어간다. SQL Inject 방지용.
.andWhere('model = :model', {model})
.orderBy(':id', 'DESC')
.setParameters({ id })
.getRawMany()
import { ConfigService } from '@nestjs/config';
import { config } from 'dotenv';
import { DataSource } from 'typeorm';
config();
const configService = new ConfigService();
export default new DataSource({
type: 'mysql',
host: configService.get('DB_HOST'),
port: configService.get<number>('DB_PORT'),
username: configService.get('DB_USERNAME'),
password: configService.get('DB_PASSWORD'),
database: configService.get('DB_DATABASE'),
synchronize: false,
entities: ['src/**/*.entity.ts'],
migrations: ['src/database/migrations/*.ts'],
migrationsTableName: 'migrations',
});
"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js --dataSource ./data-source.ts",
"migration:create": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js migration:create ./src/database/migrations/Migration",
"migration:generate": "npm run typeorm migration:generate ./src/database/migrations/Migration",
"migration:run": "npm run typeorm migration:run",
"migration:revert": "npm run typeorm migration:revert",
import { MigrationInterface, QueryRunner } from 'typeorm';
export class Migration1675868794851 implements MigrationInterface {
name = 'Migration1675868794851';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE \`cat\` ADD \`kind\` varchar(255) NOT NULL`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE \`cat\` DROP COLUMN \`kind\``);
}
}
npm run migration:run
npm run migration:revert