Allow Model classes to override primary key fields

This commit is contained in:
Alice Gaudon 2020-09-06 10:23:32 +02:00
parent f6b326f802
commit f07704c6dc
3 changed files with 24 additions and 15 deletions

View File

@ -1,4 +1,5 @@
import User from "./User"; import User from "./User";
import Model from "../../db/Model";
import {OneModelRelation} from "../../db/ModelRelation"; import {OneModelRelation} from "../../db/ModelRelation";
import ModelFactory from "../../db/ModelFactory"; import ModelFactory from "../../db/ModelFactory";
import {EMAIL_REGEX} from "../../db/Validator"; import {EMAIL_REGEX} from "../../db/Validator";

View File

@ -5,7 +5,7 @@ import ModelComponent from "./ModelComponent";
import {Type} from "../Utils"; import {Type} from "../Utils";
import ModelFactory from "./ModelFactory"; import ModelFactory from "./ModelFactory";
import ModelRelation from "./ModelRelation"; import ModelRelation from "./ModelRelation";
import ModelQuery, {ModelQueryResult, SelectFields, SelectFieldValue} from "./ModelQuery"; import ModelQuery, {ModelQueryResult} from "./ModelQuery";
import {Request} from "express"; import {Request} from "express";
export default abstract class Model { export default abstract class Model {
@ -16,27 +16,31 @@ export default abstract class Model {
+ 's'; + 's';
} }
public static create<T extends Model>(this: Type<T>, data: any): T { public static getPrimaryKeyFields(): string[] {
return ['id'];
}
public static create<T extends Model>(this: ModelType<T>, data: any): T {
return ModelFactory.get(this).create(data); return ModelFactory.get(this).create(data);
} }
public static select<T extends Model>(this: Type<T>, ...fields: string[]): ModelQuery<T> { public static select<T extends Model>(this: ModelType<T>, ...fields: string[]): ModelQuery<T> {
return ModelFactory.get(this).select(...fields); return ModelFactory.get(this).select(...fields);
} }
public static update<T extends Model>(this: Type<T>, data: { [key: string]: any }): ModelQuery<T> { public static update<T extends Model>(this: ModelType<T>, data: { [key: string]: any }): ModelQuery<T> {
return ModelFactory.get(this).update(data); return ModelFactory.get(this).update(data);
} }
public static delete<T extends Model>(this: Type<T>): ModelQuery<T> { public static delete<T extends Model>(this: ModelType<T>): ModelQuery<T> {
return ModelFactory.get(this).delete(); return ModelFactory.get(this).delete();
} }
public static async getById<T extends Model>(this: Type<T>, ...id: any): Promise<T | null> { public static async getById<T extends Model>(this: ModelType<T>, ...id: any): Promise<T | null> {
return ModelFactory.get(this).getById(...id); return ModelFactory.get(this).getById(...id);
} }
public static async paginate<T extends Model>(this: Type<T>, request: Request, perPage: number = 20, query?: ModelQuery<T>): Promise<ModelQueryResult<T>> { public static async paginate<T extends Model>(this: ModelType<T>, request: Request, perPage: number = 20, query?: ModelQuery<T>): Promise<ModelQueryResult<T>> {
return ModelFactory.get(this).paginate(request, perPage, query); return ModelFactory.get(this).paginate(request, perPage, query);
} }
@ -222,3 +226,9 @@ export default abstract class Model {
}); });
} }
} }
export interface ModelType<T extends Model> extends Type<T> {
table: string;
getPrimaryKeyFields(): string[];
}

View File

@ -1,27 +1,26 @@
import ModelComponent from "./ModelComponent"; import ModelComponent from "./ModelComponent";
import Model from "./Model"; import Model, {ModelType} from "./Model";
import ModelQuery, {ModelQueryResult, SelectFields} from "./ModelQuery"; import ModelQuery, {ModelQueryResult, SelectFields} from "./ModelQuery";
import {Request} from "express"; import {Request} from "express";
import {Type} from "../Utils";
export default class ModelFactory<T extends Model> { export default class ModelFactory<T extends Model> {
private static readonly factories: { [modelType: string]: ModelFactory<any> } = {}; private static readonly factories: { [modelType: string]: ModelFactory<any> } = {};
public static register<M extends Model>(modelType: Type<M>) { public static register<M extends Model>(modelType: ModelType<M>) {
if (this.factories[modelType.name]) throw new Error(`Factory for type ${modelType.name} already defined.`); if (this.factories[modelType.name]) throw new Error(`Factory for type ${modelType.name} already defined.`);
this.factories[modelType.name] = new ModelFactory<M>(modelType); this.factories[modelType.name] = new ModelFactory<M>(modelType);
} }
public static get<M extends Model>(modelType: Type<M>): ModelFactory<M> { public static get<M extends Model>(modelType: ModelType<M>): ModelFactory<M> {
const factory = this.factories[modelType.name]; const factory = this.factories[modelType.name];
if (!factory) throw new Error(`No factory registered for ${modelType.name}.`); if (!factory) throw new Error(`No factory registered for ${modelType.name}.`);
return factory; return factory;
} }
private readonly modelType: Type<T>; private readonly modelType: ModelType<T>;
private readonly components: ModelComponentFactory<T>[] = []; private readonly components: ModelComponentFactory<T>[] = [];
protected constructor(modelType: Type<T>) { protected constructor(modelType: ModelType<T>) {
this.modelType = modelType; this.modelType = modelType;
} }
@ -39,7 +38,6 @@ export default class ModelFactory<T extends Model> {
} }
public get table(): string { public get table(): string {
// @ts-ignore
return this.modelType.table; return this.modelType.table;
} }
@ -56,7 +54,7 @@ export default class ModelFactory<T extends Model> {
} }
public getPrimaryKeyFields(): string[] { public getPrimaryKeyFields(): string[] {
return ['id']; return this.modelType.getPrimaryKeyFields();
} }
public getPrimaryKey(modelData: any): any[] { public getPrimaryKey(modelData: any): any[] {