@nik-kita/typeorm-single-table-inheritance-decorators
v1.0.5
Published
> _This is amateur library. Use it on your own risk_
Downloads
3
Readme
About
This is amateur library. Use it on your own risk
STI or Single Table Inheritance is the cool feature in Typeorm that allow you to define many abstractions with common properties etc. under the one table.
It is absolutely your choose are you need this feature and so on... But if you want to use it, you may meet some problems with difference behavior if it was not inherited child table-abstractions but real tables.
The common example is NOT NULL
constraint. Because only one child has some property
other child will always have NULL
for it. So how define this constraint particularly
for special child?
One of the solutions is to use @Check
decorator with custom constraint logic.
For example in our case it should be something like:
@Column()
@Check("type = 'OurChildType' AND onlyInThisChildProp IS NOT NULL")
onlyInThisChildProp: string;
But you see that there are a lot of manual code and raw sql etc. So this is what this package do. It simply encapsulate these all for you.
Full example of usage, copied from test's fixtures:
/* eslint-disable max-classes-per-file */
import {
ChildEntity, Column, Entity, PrimaryGeneratedColumn, TableInheritance,
} from 'typeorm';
import { NotNullForChildTypes } from '@nik-kita/typeorm-single-table-inheritance-decorators/with-snake-strategy';
export const stiTableName = 'sti_family' as const;
// eslint-disable-next-line no-shadow
export enum TestStiChildEnum {
SON = 'Son',
DAUGHTER = 'Daughter',
BROTHER = 'Brother',
SISTER = 'Sister',
}
@TableInheritance({
column: {
name: 'type',
type: 'enum',
enum: [TestStiChildEnum.SON, TestStiChildEnum.DAUGHTER, TestStiChildEnum.BROTHER, TestStiChildEnum.SISTER],
},
})
@Entity(stiTableName)
export abstract class TestStiParent {
@PrimaryGeneratedColumn('uuid')
id!: string;
@Column({
nullable: true,
})
common?: string;
@Column({
nullable: true,
})
@NotNullForChildTypes([TestStiChildEnum.BROTHER, TestStiChildEnum.SISTER])
car?: string;
}
@ChildEntity(TestStiChildEnum.BROTHER)
export class TestStiBrother extends TestStiParent {
}
@ChildEntity(TestStiChildEnum.SISTER)
export class TestStiSister extends TestStiParent {
}
@ChildEntity(TestStiChildEnum.SON)
export class TestStiSon extends TestStiParent {
@Column({
nullable: true,
})
@NotNullForChildTypes([TestStiChildEnum.SON])
lego?: string;
}
@ChildEntity(TestStiChildEnum.DAUGHTER)
export class TestStiDaughter extends TestStiParent {
@Column()
barby?: string;
}
Bla bla bla...
- You see that the same functional is exists in many variants:
- for default (raw) naming, when your class's property
firstName
will stored in database asfirstname
of you may be implicitly define class's name in sql convention likefirst_name
... - for "snake" naming strategy getted from this package
- for default (raw) naming, when your class's property