Skip to content
This repository has been archived by the owner on Jun 29, 2021. It is now read-only.

WIP: Discriminators #333

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 55 additions & 11 deletions src/typegoose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export { getClassForDocument } from './utils';
export type InstanceType<T> = T & mongoose.Document;
export type ModelType<T> = mongoose.Model<InstanceType<T>> & T;

export interface GetModelForClassOptions {
export interface ModelForClassOptions {
/** An Existing Mongoose Connection */
existingMongoose?: mongoose.Mongoose;
/** Supports all Mongoose's Schema Options */
Expand All @@ -42,7 +42,7 @@ export class Typegoose {
*/
public getModelForClass<T>(
t: T,
{ existingMongoose, schemaOptions, existingConnection }: GetModelForClassOptions = {}
{ existingMongoose, schemaOptions, existingConnection }: ModelForClassOptions = {}
) {
const name = this.constructor.name;
if (!models[name]) {
Expand All @@ -68,23 +68,32 @@ export class Typegoose {
*/
public setModelForClass<T>(
t: T,
{ existingMongoose, schemaOptions, existingConnection }: GetModelForClassOptions = {}
{ existingMongoose, schemaOptions, existingConnection }: ModelForClassOptions = {}
) {
const name = this.constructor.name;

const sch = this.buildSchema<T>(t, { existingMongoose, schemaOptions });

let model = mongoose.model.bind(mongoose);
return this.buildModel(sch, { existingMongoose, existingConnection });
}

/**
* Build a model from the Given Schema
* @param sch The Schema to build from
* @param __namedParameters Options
*/
public buildModel<T>(
sch: mongoose.Schema<any>,
{ existingMongoose, existingConnection }: ModelForClassOptions = {}
) {
const name = this.constructor.name;

let model = mongoose.model.bind(mongoose) as typeof mongoose.model;
if (existingConnection) {
model = existingConnection.model.bind(existingConnection);
} else if (existingMongoose) {
model = existingMongoose.model.bind(existingMongoose);
}

models[name] = model(name, sch);
constructors[name] = this.constructor;

return models[name] as ModelType<this> & T;
return _buildModel(model(name, sch), name);
}

/**
Expand All @@ -93,7 +102,7 @@ export class Typegoose {
* @param schemaOptions Options for the Schema
* @returns Returns the Build Schema
*/
public buildSchema<T>(t: T, { schemaOptions }: GetModelForClassOptions = {}) {
public buildSchema<T>(t: T, { schemaOptions }: ModelForClassOptions = {}) {
const name = this.constructor.name;

// get schema of current model
Expand Down Expand Up @@ -188,3 +197,38 @@ function _buildSchema<T>(t: T, name: string, schemaOptions: any, sch?: mongoose.

return sch;
}

// This below are Functions that dont need to be in the class

/**
* Add a model to the models Array & the constructors Array
* @private
* @param model The Model to add
* @param param1
*/
function _buildModel<T extends mongoose.Model<any>>(model: T, name: string) {
models[name] = model;
constructors[name] = model.constructor;

return models[name] as ModelType<T> & T;
}

/**
* Build a Model from a given Schema & the given Discriminator
* @param from The Model to build From
* @param id The Identifier like in Mongoose
* @param sch The Build Schema (from .buildSchema)
* @param t Optional class to set the name, defaults to param id
*/
export function buildDiscriminator<T extends Typegoose, Z>(
from: ModelType<T>, id: string, sch: mongoose.Schema<T>, t?: Z
) {
const model = from.discriminator(id, sch);

let name = id;
if (t && t.constructor.name) {
name = t.constructor.name;
}

return _buildModel(model, name);
}
16 changes: 16 additions & 0 deletions test/models/discriminators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { buildDiscriminator, prop, Typegoose } from '../../src/typegoose';

export class DisMain extends Typegoose {
@prop({ required: true })
public main1: string;
}

export class DisAbove extends DisMain {
@prop({ required: true })
public above1: string;
}

export const DisMainModel = new DisMain().getModelForClass(DisMain);
export const DisAboveModel = buildDiscriminator(
DisMainModel, 'id_hello', new DisAbove().buildSchema(DisAbove), new DisAbove()
);