Common columns for all entity in nestjs - nestjs

let say there are different entity User, Role, Task
All these entities have createdBy, updatedBy, createdOn, updatedOn in common.
I want to know how can I create a base entity such that all entity extends base class in nest js using Typeform.

This is the place where should you use inheritance.
Basically, the idea is to have a base class/entity that gathers common logic or structure where many other classes/entities share that common logic.
For example:
Cat, Dog, Elephant are all having similar characterizations, so we might want to gather all these similar characterizations at a single place in order to avoid duplication of logic and code.
So let's see the simplest example only for basic understanding.
export class Animal {
protected numberOfLegs: number;
protected sound(): void;
}
export class Dog extends Animal {
constructor() {
super();
this.numberOfLegs = 4;
}
sound(): void {
console.log('BARK');
}
}
For your needs:
Export a base entity.
import { Entity, Column } from 'typeorm';
export class BaseEntity {
#Column()
createdBy: string;
#Column()
updatedBy: string;
#Column()
createdOn: Date;
#Column()
updatedOn: Date;
}
And then inherit it from derived entities.
import { Entity, Column } from 'typeorm';
import {BaseEntity} from './base-entity';
export class DerivedEntity extends BaseEntity {
#Column()
id: string;
...
}
Please read about inheritance which is a basic and very important principle in programming and OOP.

Related

How to create index number decrease postgresql with typeorm?

i read docs of typeorm but i don't see the way to handle my problem, i tried to create index in my entity but it not sort like i want.How can i do it?
#ObjectType()
#Entity()
export class Product extends BaseEntity {
#Field()
#PrimaryGeneratedColumn()
id!: number;
#Field()
#Column()
#Index()
paidCount!: number;
...
}

What is `Cat.name` in NestJS mongoose docs?

Reading the NestJS docs on the MongoDB technique, I've came along a confusing example:
#Injectable()
export class CatsService {
constructor(#InjectModel(Cat.name) private catModel: Model<CatDocument>) {}
async create(createCatDto: CreateCatDto): Promise<Cat> {
const createdCat = new this.catModel(createCatDto);
return createdCat.save();
}
async findAll(): Promise<Cat[]> {
return this.catModel.find().exec();
}
}
The line that confuses me is the constructor one; where to #InjectModel is given Cat.name. But, in the cats.schema.ts file, there's no inheritance from another class, nor any valorised static property with that name:
import { Prop, Schema, SchemaFactory } from '#nestjs/mongoose';
import { Document } from 'mongoose';
export type CatDocument = Cat & Document;
#Schema()
export class Cat {
#Prop()
name: string;
#Prop()
age: number;
#Prop()
breed: string;
}
export const CatSchema = SchemaFactory.createForClass(Cat);
Am I missing something or could it be a "bug" in the docs?
Cat.name in this case refers to the inherent static property name that all classes have (really all functions have). This gives us a built in constant that we can refer to without having to write our own, but if you'd prefer you can use the string 'Cat' as well. In this case, Cat.name is the string 'Cat', just a different way to reference it that is built in to all classes (and functions).
JavaScript docs on Function.name

TypeORM getRawOne<T> not returning type T

I'm working on refactoring a koa api to nest and am kinda stuck on refactoring the queries from native psql to typeorm. I have the following table, view and dto.
#Entity()
export class Challenge {
#PrimaryGeneratedColumn()
id!: number;
#Column()
endDate!: Date;
#CreateDateColumn()
createdAt!: Date;
}
#ViewEntity({
expression: (connection: Connection) => connection.createQueryBuilder()
.select('SUM(cp.points)', 'score')
.addSelect('cp.challenge', 'challengeId')
.addSelect('cp.user', 'userId')
.addSelect('RANK() OVER (PARTITION BY cp."challengeId" ORDER BY SUM(cp.points) DESC) AS rank')
.from(ChallengePoint, 'cp')
.groupBy('cp.challenge')
.addGroupBy('cp.user')
})
export class ChallengeRank {
#ViewColumn()
score!: number;
#ViewColumn()
rank!: number;
#ViewColumn()
challenge!: Challenge;
#ViewColumn()
user!: User;
}
export class ChallengeResultReponseDto {
#ApiProperty()
id!: number;
#ApiProperty()
endDate!: Date;
#ApiProperty()
createdAt!: Date;
#ApiProperty()
score: number;
#ApiProperty()
rank: number;
test() {
console.log("test")
}
}
As the object I want to return is not of any entity type, I'm kinda lost on how to select it and return the correct class. I tried the following:
this.challengeRepository.createQueryBuilder('c')
.select('c.id', 'id')
.addSelect('c.endDate', 'endDate')
.addSelect('c.createdAt', 'createdAt')
.addSelect('cr.score', 'score')
.addSelect('cr.rank', 'rank')
.leftJoin(ChallengeRank, 'cr', 'c.id = cr."challengeId" AND cr."userId" = :userId', { userId })
.where('c.id = :id', { id })
.getRawOne<ChallengeResultReponseDto>();
Which returns an object that has the correct fields, but that is not of the class type "ChallengeResultReponseDto". If I try to call the function "test" the application crashes. Further it feels weird to use the challengeRepository but not return a challenge, should I use the connection or entity manager for this instead?
I'm rather certain that getRawOne<T>() returns a JSON that looks like whatever you give the generic (T), but an not instance of that class. You should try using getOne() instead to get the instance of the returned entity

NestJS - Creating Business Objects From Other Services

Nowadays I'm playing around with NestJS and trying to understand the best practices of NestJS world.
By following official documentations I have created service/dto/entity/controller for my business object called 'Cat'.
(also using SequelizeJS)
cat.entity.ts
#Table({
freezeTableName: true,
})
export class Cat extends Model<Cat> {
#AllowNull(false)
#Column
name: string;
#Column
breed: string;
}
create-cat.dto.ts
export class CreateCatDto {
#IsString()
readonly name: string;
#IsString()
readonly breed: string;
}
cat.service.ts
export class CatService {
constructor(#Inject('CAT_REPOSITORY') private readonly CAT_REPOSITORY: typeof Cat) {}
async create(createCatDto: CreateCatDto): Promise<Cat> {
const cat = new Cat();
cat.name = createCatDto.name;
cat.breed = createCatDto.breed;
return await cat.save();
}
}
Now I can make POST requests to my controller and create Cat objects successfully. But I want to create a 'Cat' from other service and the create() method only takes CreateCatDto which I cannot/shouldn't initialize (it's read-only).
How can I call create(createCatDto: CreateCatDto) from other services? How you are handling this kind of requirements with NestJS? Should I create one more method like createFromEntity(cat: Cat) and use it?
try this:
const cat: CreateCatDto = { name: 'Miau', breed: 'some' };

How to create two subclasses of the model class in sequelize-typescript?

I'm creating a node.js server with sequelize using sequelize-typescript. I have one entity - name it Employee.
In database all profiles stores in the same table but have two different types - say Manager and Operator.
Each type has its own relations with different tables - say:
Manager -> ManagerOptions
Operator -> OperatorOptions
I've created a model Employee and two subclasses - Manager and Operator. Each extending Employee, so have same base properties, and also have some additional properties in each subclass, such as ManagerOprtions and OperatorOptions.
// Employee.ts
import { Table, Column, Model } from 'sequelize-typescript';
#Table({
tableName: 'employees'
})
export class Employee extends Model<Employee> {
#Column public type_id: number;
#Column public name: string;
#Column public url: string;
}
// Manager.ts
import { Column, HasOne } from 'sequelize-typescript';
import { Employee } from './Employee';
import { ManagerInfo } from './ManagerInfo';
export class Manager extends Employee {
#Column public subordinate_count: number;
#HasOne(() => ManagerInfo, {
foreignKey: 'manager_id',
as: 'info'
})
public info: ManagerInfo;
}
// Operator.ts
import { Column, HasOne } from 'sequelize-typescript';
import { Employee } from './Employee';
import { OperatorInfo } from './OperatorInfo';
export class Operator extends Employee {
#Column public calls_count: number;
#HasOne(() => OperatorInfo, {
foreignKey: 'operator_id',
as: 'info'
})
public info: OperatorInfo;
}
How do I create such relations using sequelize-typescript (or just sequelize, if you're not familiar with this lib), so I can search Employees by name and have different models in the result set?
Search: "Mar"
Results:
+---------------------------------------+
| 1 Mark Operator OperatorOptions |
| 2 Mary Manager ManagerOptions |
+---------------------------------------+
Hope I've explained it right.

Resources