Need an example in the documentation of how to work with inherited entities
Opened this issue ยท 2 comments
๐ Documentation
We need an example in the documentation of how to work with inherited entities.
There are two Entities in the same table.
How do I make FilterableUnpagedRelation
with a common DTO?
registerEnumType(ContactType, {
name: 'ContactType',
});
@Entity('person_contact')
@TableInheritance({ column: { type: 'varchar', name: 'type' } })
export class ContactEntity {
@PrimaryGeneratedColumn('uuid')
id: string;
@ManyToOne(() => PersonEntity, (person) => person.id)
@JoinColumn({ name: 'owner_id' })
ownerId: PersonEntity;
@Column({ type: 'text', nullable: true })
description: string;
type: ContactType;
email: string;
phone: string;
}
@ChildEntity(ContactType.email)
export class EmailContactEntity extends ContactEntity {
@Column({
nullable: false,
type: 'varchar',
length: 255,
})
@IsEmail()
@Index({ unique: true })
email: string;
}
@ChildEntity(ContactType.phone)
export class PhoneContactEntity extends ContactEntity {
@Column({
nullable: false,
type: 'varchar',
length: 25,
comment: '(DC2Type:phone_number)',
})
@IsPhoneNumber('RU')
@Index({ unique: true })
phone: string;
}
I need to transform PhoneContactEntity
EmailContactEntity
to
ContactDTO
where value is either a phone number or an email.
@ObjectType('contact')
export class ContactDTO {
@Field(() => ID)
id: string;
@FilterableField(() => ContactType, { nullable: false })
type: ContactType;
@FilterableField()
value: string;
@Field({ nullable: true })
description: string;
}
I'm trying to do it through assemblers
, but how use two assemblers for one DTO
Or choose a way to store data in different tables?
Could you not just create resolver etc for ContactDTO and add a @ResolveField
for value
that returns one of the two?
We do something similiar for the Creator
type, which is just a UserEntity
in the database:
import { Parent, ResolveField, Resolver } from '@nestjs/graphql'
import { UserType } from '@constants/user'
import { UserEntity } from '@database/main/user.entity'
import { Creator, CreatorType } from './creator.type'
@Resolver(() => Creator)
export class CreatorResolver {
@ResolveField()
public name(@Parent() creator: UserEntity): string {
if (this.isSpecialUser(creator)) {
return creator.fullName
}
return creator.firstName
}
@ResolveField()
public type(@Parent() creator: UserEntity): string {
if (this.isSpecialUser(creator)) {
switch (creator.type) {
case UserType.API:
return CreatorType.API
case UserType.System:
return CreatorType.System
case UserType.Integration:
return CreatorType.Integration
}
}
return CreatorType.User
}
private isSpecialUser(creator: UserEntity) {
return [UserType.API, UserType.Integration, UserType.System].includes(creator.type as UserType)
}
}
This is not exactly the pattern. When we use ChildEntity
, we create our own Entity and DTO for each Child.
Resolver
should convert ChildEntity
to ContactDTO
based on the type. ContactEntity
is abstract.
I wrote such a Resolver, but automatic filtering in the scheme does not work on it
User {
name: String!
contacts: [ContactDTO]
}
I realized that this is not an easy solution, so for now I keep all types of contacts in one column and additionally verify before saving