feat: refactor entity classes to use mixins, add rateable mixin to book and copy
This commit is contained in:
parent
8bfaba185b
commit
2006815b2b
|
@ -1,7 +1,7 @@
|
||||||
import { Entity, PrimaryGeneratedColumn } from 'typeorm';
|
import { Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export abstract class Base {
|
export class BaseEntity {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn()
|
||||||
public id: number;
|
public id: number;
|
||||||
}
|
}
|
|
@ -1,9 +1,10 @@
|
||||||
import { Entity, ManyToMany } from 'typeorm';
|
import { Entity, ManyToMany } from 'typeorm';
|
||||||
|
import { BaseEntity } from '../base-entity';
|
||||||
import { MultiNamed } from './base/multi-named';
|
import { MultiNamed } from './base/multi-named';
|
||||||
import { Book } from './book';
|
import { Book } from './book';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Author extends MultiNamed {
|
export class Author extends MultiNamed(BaseEntity) {
|
||||||
@ManyToMany(() => Book, {
|
@ManyToMany(() => Book, {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
import { Column, Entity } from 'typeorm';
|
import { Column, Entity } from 'typeorm';
|
||||||
import { Base } from '../../base';
|
|
||||||
|
|
||||||
|
export function MultiNamed<T extends Constructor>(BaseClass: T) {
|
||||||
@Entity()
|
@Entity()
|
||||||
export abstract class MultiNamed extends Base {
|
class MixinClass extends BaseClass {
|
||||||
@Column()
|
@Column()
|
||||||
public nameCanonical: string;
|
public nameCanonical: string;
|
||||||
|
|
||||||
@Column('simple-array')
|
@Column('simple-array')
|
||||||
public names: string[];
|
public names: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return MixinClass;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { Column, Entity } from 'typeorm';
|
||||||
|
|
||||||
|
export function Rateable<T extends Constructor>(BaseClass: T) {
|
||||||
|
@Entity()
|
||||||
|
class MixinClass extends BaseClass {
|
||||||
|
@Column({ nullable: true })
|
||||||
|
public rating: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MixinClass;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"extends": ["../../../../../tslint.json"],
|
||||||
|
"rules": {
|
||||||
|
"typedef": false
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,15 @@
|
||||||
import { Entity, JoinTable, ManyToMany, OneToMany } from 'typeorm';
|
import { Entity, JoinTable, ManyToMany, OneToMany } from 'typeorm';
|
||||||
|
import { BaseEntity } from '../base-entity';
|
||||||
import { Author } from './author';
|
import { Author } from './author';
|
||||||
import { MultiNamed } from './base/multi-named';
|
import { MultiNamed } from './base/multi-named';
|
||||||
|
import { Rateable } from './base/rateable';
|
||||||
import { Character } from './character';
|
import { Character } from './character';
|
||||||
import { Copy } from './copy';
|
import { Copy } from './copy';
|
||||||
import { Fiction } from './fiction';
|
import { Fiction } from './fiction';
|
||||||
import { Tag } from './tag';
|
import { Tag } from './tag';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Book extends MultiNamed {
|
export class Book extends Rateable(MultiNamed(BaseEntity)) {
|
||||||
@OneToMany(
|
@OneToMany(
|
||||||
() => Copy,
|
() => Copy,
|
||||||
(copy: Copy) => copy.original,
|
(copy: Copy) => copy.original,
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import { Entity, ManyToMany } from 'typeorm';
|
import { Entity, ManyToMany } from 'typeorm';
|
||||||
|
import { BaseEntity } from '../base-entity';
|
||||||
import { MultiNamed } from './base/multi-named';
|
import { MultiNamed } from './base/multi-named';
|
||||||
import { Book } from './book';
|
import { Book } from './book';
|
||||||
import { Fiction } from './fiction';
|
import { Fiction } from './fiction';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Character extends MultiNamed {
|
export class Character extends MultiNamed(BaseEntity) {
|
||||||
@ManyToMany(() => Book, {
|
@ManyToMany(() => Book, {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Column, Entity, ManyToOne } from 'typeorm';
|
import { Column, Entity, ManyToOne } from 'typeorm';
|
||||||
import { Base } from '../base';
|
import { BaseEntity } from '../base-entity';
|
||||||
import { Copy } from './copy';
|
import { Copy } from './copy';
|
||||||
|
|
||||||
const enum CopyTypes {
|
const enum CopyTypes {
|
||||||
|
@ -10,7 +10,7 @@ const enum CopyTypes {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class CopyType extends Base {
|
export class CopyType extends BaseEntity {
|
||||||
@ManyToOne(
|
@ManyToOne(
|
||||||
() => Copy,
|
() => Copy,
|
||||||
(copy: Copy) => copy.types,
|
(copy: Copy) => copy.types,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Column, Entity, JoinTable, ManyToMany, ManyToOne, OneToMany } from 'typeorm';
|
import { Column, Entity, JoinTable, ManyToMany, ManyToOne, OneToMany } from 'typeorm';
|
||||||
import { Base } from '../base';
|
import { BaseEntity } from '../base-entity';
|
||||||
|
import { Rateable } from './base/rateable';
|
||||||
import { Book } from './book';
|
import { Book } from './book';
|
||||||
import { CopyType } from './copy-type';
|
import { CopyType } from './copy-type';
|
||||||
import { Language } from './language';
|
import { Language } from './language';
|
||||||
|
@ -7,7 +8,7 @@ import { Source } from './source';
|
||||||
import { Translator } from './translator';
|
import { Translator } from './translator';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Copy extends Base {
|
export class Copy extends Rateable(BaseEntity) {
|
||||||
@ManyToOne(
|
@ManyToOne(
|
||||||
() => Book,
|
() => Book,
|
||||||
(book: Book) => book.copies,
|
(book: Book) => book.copies,
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import { Entity, ManyToMany } from 'typeorm';
|
import { Entity, ManyToMany } from 'typeorm';
|
||||||
|
import { BaseEntity } from '../base-entity';
|
||||||
import { MultiNamed } from './base/multi-named';
|
import { MultiNamed } from './base/multi-named';
|
||||||
import { Book } from './book';
|
import { Book } from './book';
|
||||||
import { Character } from './character';
|
import { Character } from './character';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Fiction extends MultiNamed {
|
export class Fiction extends MultiNamed(BaseEntity) {
|
||||||
@ManyToMany(() => Book, {
|
@ManyToMany(() => Book, {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { Column, Entity, ManyToMany } from 'typeorm';
|
import { Column, Entity, ManyToMany } from 'typeorm';
|
||||||
import { Base } from '../base';
|
import { BaseEntity } from '../base-entity';
|
||||||
import { Copy } from './copy';
|
import { Copy } from './copy';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Language extends Base {
|
export class Language extends BaseEntity {
|
||||||
@Column({
|
@Column({
|
||||||
nullable: false,
|
nullable: false,
|
||||||
unique: true,
|
unique: true,
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { Entity, OneToMany } from 'typeorm';
|
import { Entity, OneToMany } from 'typeorm';
|
||||||
|
import { BaseEntity } from '../base-entity';
|
||||||
import { MultiNamed } from './base/multi-named';
|
import { MultiNamed } from './base/multi-named';
|
||||||
import { Source } from './source';
|
import { Source } from './source';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Site extends MultiNamed {
|
export class Site extends MultiNamed(BaseEntity) {
|
||||||
@OneToMany(
|
@OneToMany(
|
||||||
() => Source,
|
() => Source,
|
||||||
(source: Source) => source.site,
|
(source: Source) => source.site,
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Column, Entity, ManyToMany, ManyToOne } from 'typeorm';
|
import { Column, Entity, ManyToMany, ManyToOne } from 'typeorm';
|
||||||
import { Base } from '../base';
|
import { BaseEntity } from '../base-entity';
|
||||||
import { Copy } from './copy';
|
import { Copy } from './copy';
|
||||||
import { Site } from './site';
|
import { Site } from './site';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Source extends Base {
|
export class Source extends BaseEntity {
|
||||||
@Column({
|
@Column({
|
||||||
nullable: false,
|
nullable: false,
|
||||||
unique: true,
|
unique: true,
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { Entity, ManyToMany } from 'typeorm';
|
import { Entity, ManyToMany } from 'typeorm';
|
||||||
|
import { BaseEntity } from '../base-entity';
|
||||||
import { MultiNamed } from './base/multi-named';
|
import { MultiNamed } from './base/multi-named';
|
||||||
import { Book } from './book';
|
import { Book } from './book';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Tag extends MultiNamed {
|
export class Tag extends MultiNamed(BaseEntity) {
|
||||||
@ManyToMany(() => Book, {
|
@ManyToMany(() => Book, {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { Entity, ManyToMany } from 'typeorm';
|
import { Entity, ManyToMany } from 'typeorm';
|
||||||
|
import { BaseEntity } from '../base-entity';
|
||||||
import { MultiNamed } from './base/multi-named';
|
import { MultiNamed } from './base/multi-named';
|
||||||
import { Copy } from './copy';
|
import { Copy } from './copy';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Translator extends MultiNamed {
|
export class Translator extends MultiNamed(BaseEntity) {
|
||||||
@ManyToMany(() => Copy, {
|
@ManyToMany(() => Copy, {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class addRating1574452206367 implements MigrationInterface {
|
||||||
|
name = 'addRating1574452206367';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<any> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "temporary_copy" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "favorited" boolean NOT NULL DEFAULT (0), "isDigital" boolean NOT NULL, "originalId" integer NOT NULL, "rating" integer, CONSTRAINT "FK_e8ce0011cf0a8b9fdc8ad908a44" FOREIGN KEY ("originalId") REFERENCES "book" ("id") ON DELETE CASCADE ON UPDATE CASCADE)`,
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`INSERT INTO "temporary_copy"("id", "favorited", "isDigital", "originalId") SELECT "id", "favorited", "isDigital", "originalId" FROM "copy"`,
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TABLE "copy"`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "temporary_copy" RENAME TO "copy"`, undefined);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "temporary_book" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "nameCanonical" varchar NOT NULL, "names" text NOT NULL, "rating" integer)`,
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`INSERT INTO "temporary_book"("id", "nameCanonical", "names") SELECT "id", "nameCanonical", "names" FROM "book"`,
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TABLE "book"`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "temporary_book" RENAME TO "book"`, undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<any> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "book" RENAME TO "temporary_book"`, undefined);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "book" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "nameCanonical" varchar NOT NULL, "names" text NOT NULL)`,
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`INSERT INTO "book"("id", "nameCanonical", "names") SELECT "id", "nameCanonical", "names" FROM "temporary_book"`,
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TABLE "temporary_book"`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "copy" RENAME TO "temporary_copy"`, undefined);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "copy" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "favorited" boolean NOT NULL DEFAULT (0), "isDigital" boolean NOT NULL, "originalId" integer NOT NULL, CONSTRAINT "FK_e8ce0011cf0a8b9fdc8ad908a44" FOREIGN KEY ("originalId") REFERENCES "book" ("id") ON DELETE CASCADE ON UPDATE CASCADE)`,
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`INSERT INTO "copy"("id", "favorited", "isDigital", "originalId") SELECT "id", "favorited", "isDigital", "originalId" FROM "temporary_copy"`,
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TABLE "temporary_copy"`, undefined);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"extends": ["../../../../tslint.json"],
|
||||||
|
"rules": {
|
||||||
|
"class-name": false,
|
||||||
|
"member-access": false,
|
||||||
|
"typedef": false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
type Constructor<T = {}> = new (...args: any[]) => T;
|
Loading…
Reference in New Issue