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

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
hasezoey committed Jul 29, 2019
1 parent a3c7cee commit 877c8f7
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 11 deletions.
66 changes: 55 additions & 11 deletions src/typegoose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,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 @@ -43,7 +43,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 @@ -69,23 +69,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 @@ -94,7 +103,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 @@ -189,3 +198,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);
}
18 changes: 18 additions & 0 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { getClassForDocument } from '../src/utils';
import { Genders } from './enums/genders';
import { Role } from './enums/role';
import { Car as CarType, model as Car } from './models/car';
import { DisAbove, DisAboveModel, DisMain, DisMainModel } from './models/discriminators';
import { model as InternetUser } from './models/internet-user';
import { BeverageModel as Beverage, InventoryModel as Inventory, ScooterModel as Scooter } from './models/inventory';
import { AddressNested, PersonNested, PersonNestedModel } from './models/nested-object';
Expand All @@ -28,6 +29,23 @@ describe('Typegoose', () => {

describe('Hooks', HookTest.bind(this));

it('TEST should do it discriminated', async () => {
await (new DisMainModel({ main1: 'Hello from Main1' } as DisMain)).save();

await (new DisAboveModel({ above1: 'Hello From Above', main1: 'Hello From Above' } as DisAbove)).save();

const foundMain = (await DisMainModel.find({}).exec())[0].toObject();
const foundAbove = (await DisAboveModel.find({}).exec())[0].toObject();

expect(foundMain).to.have.property('main1', 'Hello from Main1');
expect(foundMain).to.not.have.property('above1');
expect(foundMain).to.not.have.property('__t');

expect(foundAbove).to.have.property('main1', 'Hello From Above');
expect(foundAbove).to.have.property('above1', 'Hello From Above');
expect(foundAbove).to.have.property('__t', 'id_hello');
});

it('should create a User with connections', async () => {
const car = await Car.create({
model: 'Tesla',
Expand Down
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()
);

0 comments on commit 877c8f7

Please sign in to comment.