Coder Social home page Coder Social logo

typegoose's Issues

Plugins

Dear Szokodiakos

Thank you for Typegoose that helps a lot in simplifying code and improve maintainability. I have an issue and could not understand why and how it happens when using 'mongoose-paginate' as the Typegoose plugin, I have followed the guides for similar issue in this git but it still does not work, could you help look at and kindly advise why plugin does not return result?
Extracted code is as below (which worked well if I use plugin with native mongoose but not via Typegoose)

import {
prop,
Typegoose,
InstanceType,
staticMethod,
plugin,
} from 'typegoose';

// tslint:disable-next-line:no-var-requires
import * as paginate from "mongoose-paginate";

export interface PageinateResult {
docs: [InstanceType];
total?: number;
limit?: number;
}

@plugin(paginate)
export class ClientType extends Typegoose {
@prop({ required: true, minlength: 5, index: true })
name: string;

@prop()
status?: string;

static paginate: (query, options) => Promise<PageinateResult<ClientType>>;    
// I thought the issue happens here but try several scenarios still not work

}
export const model = new ClientType().getModelForClass(ClientType);

Then

// As I use multi DB thus below
var client = new ClientType().getModelForClass(ClientType, {schemaOptions: {collection: 'Client'}, existingConnection: mongooseConnection});

Where I expect it returns the documents, it only return the unfulfilled Promise
client.paginate(query, options)
.then(result => {
console.log(result)
});

Thank you for your advices.

findById read empty arrays when the items are defined with a "_id" field

Hi.
I'm using yet typegoose 3.5.2 because 3.6.0 don't works for me (see #68).

I defined a model with the "_id" field to simplify the configuration of data on db. This is not frequently but it works and it is admitted with mongoose.

When I load in memory a doc defined with an array of items wich are defined with an "_id" field, the array is empty.

Below the source file.

import * as tg from 'typegoose';

export class perm extends tg.Typegoose {
    @tg.prop() routerFunction : string;
    @tg.prop() permit: boolean;
}

export const permModel = new perm().getModelForClass(perm);


export class group extends tg.Typegoose {
    @tg.prop( { required: true, index: true, unique: true } ) _id: string;
    @tg.prop( { required: true, index: true, unique: true } ) name : string;
    @tg.arrayProp( { itemsRef: perm } ) perms ?: tg.Ref<perm>[];
}

export const groupModel = new group().getModelForClass(group);

export class admin extends tg.Typegoose {
    @tg.prop() name : string;
    @tg.arrayProp( { itemsRef: group } ) groups ?: tg.Ref<group>[];
    @tg.arrayProp( { itemsRef: perm } ) perms ?: tg.Ref<perm>[];
}

export const adminModel = new admin().getModelForClass(admin);

adminModel.findById('an id').exec((err, data) => {
   console.log(data); // prints correctly the perms array data but an empty groups array
}

Troubles with reciprocal reference fields in the models

Hi.
Please, can you help me to solve a problem with reciprocal reference fields in the models?
Yes, it seems strange but usefull in something situations.

If you have two classes with reciprocal reference fields in the models, you can receive an Error (In property user: Object is not a primitive type nor a Typegoose schema (Not extending it).) during che compilation phase.
Maybe because one of the classes is not yet defined. This happens also if the two classes are in the same file.
I searched for a foreward instruction without success.

Below a short example:

import { prop, staticMethod, instanceMethod, Typegoose, ModelType, InstanceType, Ref } from 'typegoose';

export class Admin extends Typegoose {
    @prop() firstName: string;
    @prop({ ref: User }) user?: Ref<User>;
}
export const AdminModel = new Admin().getModelForClass(Admin);

export class UserRole {
    @prop({ ref: Admin }) admin?: Ref<Admin>;
}

export class User extends Typegoose {
    @prop({ required: true }) email: string;
    @prop({ required: true }) username: string;
    @prop() roles?: UserRole;
}
export const UserModel = new User().getModelForClass(User);

Thank you in advance.

Optional object fields always created

Models containing fields of a custom class type seem to always be created when retrieving a document from the collection, even if said field is optional.

For example, the model:

class Thing extends Typegoose {
    @prop() text: string;
}

class Container extends Typegoose {
    @prop() numeric: number;
    @prop() custom?: Thing;
}

The collection:

[ { numeric: 1 } ] // _id omitted for brevity

If you query and log the result to the console, it logs the expected value

Collection.findOne({ numeric: 1 }).then(r => console.log(r));

logs

{ numeric: 1 } // _id omitted for brevity

But you can somehow still access the non-existent 'custom' field and it will return an empty object

Collection.findOne({ numeric: 1 }).then(r => console.log(r['bonus']));

logs

{ }

whereas it should be undefined since it isn't defined in the document.

I'm not exactly sure that this is Typegoose's fault, but I don't think this should happen using just Mongoose, but I haven't tried. 😕

Populate across different DBs

I have two DB with a Mongoose instance for each one, which I use as an existingMongoose property when I create a new getModelForClass instance.
In a model associated to the first Mongoose instance I have a ref to a model in the second Mongoose instance.
And of course, when I try to populate the ref of the first model (Which refers to the second Mongoose instance) I get a MissingSchemaError: Schema hasn't been registered for model because it is not registered in the first Mongoose instance.
This is supported by Mongoose (http://mongoosejs.com/docs/populate.html#cross-db-populate) but Typegoose expects a fully Mongoose instance, not a connection created with createConnection to associate a model to it.

Is there any workaround for this??

(I'm open to implement this if you give me some guidance :) )

Support for compound indexes

I have not found any reference about how to define compound indexes using Typegoose.
Is there any way to do it?

Thanks.

'expires' option in @prop decorator missing

Hi.
It's very usefull the 'expires' option for the schema field definition when data type is Data.

Below a mongoose example:

new Schema({ 
   createdAt: { type: Date, expires: 60*60*24 }
});

Please, can you consider to implement it?
Thank you!

defining propArray as a type that extends typegoose results in an error

_\node_modules\mongoose\lib\index.js:477
  if (schema.$globalPluginsApplied) {
                    
TypeError: Cannot read property '$globalPluginsApplied' of undefined
    at Mongoose._applyPlugins (_\node_modules\mongoose\lib\index.js:477:14)
    at Mongoose._applyPlugins (_\node_modules\mongoose\lib\index.js:487:10)
    at Mongoose.model (_\node_modules\mongoose\lib\index.js:396:10)
    at TestModel.setModelForClass (_\node_modules\typegoose\lib\typegoose.js:44:31)
    at TestModel.getModelForClass (_\node_modules\typegoose\lib\typegoose.js:20:18)

Setup looks like the following:

export const TestModel = new Test().getModelForClass(Test, {existingConnection: mongoose});

export class Test extends Typegoose {
    @prop({index:true})
    userId:string;
    @arrayProp({ items: Item})
    items?: Item[];
export class Item extends Typegoose {
    @prop({index:true})
    id:string;
    @prop()
    name: string;
}

using mongoose 4.13.6

Tests failing in the version published in master.

I'm getting this erros while running the test in master, it seems to be related to the last changes of plugins.

> [email protected] lint /home/dgomez/Proyectos/OpenSource/typegoose
> tslint --type-check --project tsconfig.json

Error at src/typegoose.ts:53:29: Property 'mongoosePlugin' does not exist on type 'string'.
Error at src/typegoose.ts:53:52: Property 'options' does not exist on type 'string'.
Error at src/typegoose.ts:59:19: Property 'get' does not exist on type 'string'.
Error at src/typegoose.ts:60:38: Property 'get' does not exist on type 'string'.
Error at src/typegoose.ts:62:19: Property 'set' does not exist on type 'string'.
Error at src/typegoose.ts:63:38: Property 'set' does not exist on type 'string'.

Data not saving correctly

I want to save a mongoose document with a typegoose sub-document but data isn't saving correctly.

Car Model does not extend Typegoose
import * as mongoose from 'mongoose' const Model = mongoose.Schema const CarModel = new Model ({ color: String, driver: { type: Schema.Types.ObjectId, ref: 'UserModel' }, })

UserModel extends Typegoose
`export class User extends Typegoose {
@prop()
public name: string;
}

export const UserModel = new User().getModelForClass(User)`

Different file to create Data to save
const autoMobile = {};
autoMobile.color = 'black';
autoMobile.driver = new UserModel({name: 'Bob'});
Car.create(autoMobile, (createdCar: any) => { return createdCar; })

Everything is saved correctly except the name attribute on the userModel. Mogoose even creates the ID correctly. Any help is much appreciated

Removing 'id' field from Typegoose

Would it be possible to remove the id field from the Typegoose class?

My documents have their own id field which are numbers instead of strings, so TypeScript gives me an error telling me that I haven't extended the Typegoose class properly. However, removing the id field from the Typegoose typings allows it to compile and work just fine.

If having the id field is necessary in some way, maybe consider renaming it to _id since id does not necessarily seem to be reserved in MongoDB.

Objects within Schema

I want to do the following (regular Mongoose):

let personSchema = new mongoose.Schema({
  id: String,
  address: {
    street: String,
    streetnumber: Number,
  }
});

With Typegoose:

class Person extends Typegoose {
  @prop()
  id: string;

 @prop()
  address: {
    street: string;
    streetnumber: number;
  }
});

But it says: Object is not a primitive type nor a Typegoose schema (Not extending it).

If i do like described in the readme(creating a seperate class for address) Typegoose would create a new schema and a seperate document for address and that is not what i want to do.

@instanceMethod not working

I can't make @instancemethod work at all. Even with this simple example:

// on the User model class:
@instanceMethod
    public changeName(this: InstanceType<User>) {
        this.name = "blabla";
    }

In some other file where I create an User:

const user: User = await UserService.getOneBy...(..); //this succesfully creates an user based on db
user.doSomething();

I get this error:

error TS2684: The 'this' context of type 'User' is not assignable to method's 'this' of type 'InstanceType<User>'.
  Type 'User' is not assignable to type 'Document'.
    Property 'increment' is missing in type 'User'.

Any clue?

Thanks in advance!
José

Stuck on findOne

I probably made a mistake implementing Typegoose somewhere (btw, awesome project!) but on the first User.findOne() my request is freezing.

This is my (simplified) model:

export class UserClass extends Typegoose {
  @prop()
  _id: string

  @prop({
    required: true
  })
  name: string

  @prop({
    required: true
  })
  email: string

  @prop({
    required: true
  })
  password: string
}

Exposed like this:

export const User = new UserClass().getModelForClass(UserClass)

And called like this:

import { UserClass, User } from 'server/models/user/model'

  const user = await User.findOne({
    email
  })

But it gets stuck on the User.findOne line and never returns from it.

Last thing the console prints before that is DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated even though I'm using (mongoose as any).Promise = Promise.
Before Typegoose I didn't get the deprecation warning and the Promise line did work.

Typegoose 3.6.0
Node v8.5.0

Any ideas?

Limited Hooks methods

type Method = 'init' | 'validate' | 'save' | 'remove';

please add all methods, like 'findOne', 'find' ... etc.

i can't create a class with @pre findOne

Fields loaded are more than in the Model definition

Hi.
Great job but I have encountered maybe a trouble:
If I use the 'find' method of my little example in that I defined only two fields (username and email), if there are more fields in the database (firstname, lastname, username, email, password, ...), Typegoose load all the field. If I use the mongoose schema, mongoose load only the two field. It seems like when you define an empty schema.
Can you explain me that?
Below I attached my source files: server, the model and a route page.

user.model.ts
IndexRoute.ts
server.ts

Thank you! Typegoose is really THE typescript solution for mongoose.

EDIT (06/oct/2017):
I found the solution using the 'projection' parameter of the 'find' method.
I don't know if there is a typegoose method or a better idea to compose the projection string:

let proj = Object.keys(UserModel.schema.obj).join(' ');

public index(req: Request, res: Response, next: NextFunction) {
       let proj = Object.keys(UserModel.schema.obj).join(' ');

        UserModel.find({}, proj, (err, data) => { 
            if(err) {
                res.status(200).json({msg: 'err', "err": err});
                return next(err);
            }
            res.status(200).json({msg: 'ok', "data": data});
           // prints:
           // {"msg":"ok","data": [{"_id":"57669d50a87cfa704393bf54","username":"myusername","email":"[email protected]"}]}
        });

    }

Using Mongoose Plugins ?

Is there any way to use the very useful Plugins from mongoose ? Or anything allowing me to re-use a bunch of properties in several models ?

Re-using the a sub schema could be a solution but it does not allow custom pre-validation on on the added properties. I've also tried using typescript mixins, but this method needs to redeclare the variables in the implementing class.

Any ideas about this ?

Thanks in advance.

Troubles with 3.6.0 version of Typegoose

Hi.
I used an old version of typegoose and all works correctly.
To day I tested the 3.6.0 version of Typegoose and I encountered some troubles.

I tested my project with the 3.5.2 version of Typegoose and it works correctly again.

With the debugger I checked that the execution is looped at the count instance method of 'pgLoginAttemptModel' in the 'getIpUserCount' function.

The source file is:

import * as async from 'async';
export class pgLoginAttempt extends Typegoose {
  
    @prop({ default: '', index: true }) ip: string;
    @prop({ default: '', index: true }) user: string;
    @prop({ default: Date.now()}) time: Date;

}
      
export const pgLoginAttemptModel = new pgLoginAttempt().getModelForClass(pgLoginAttempt, { schemaOptions: { collection: 'pg-login-attempts'}});

protected abuseFilter(successEvent: string) {

        let getIpCount = (done) => {
            let conditions = { ip: req.app.ip };

            pgLoginAttemptModel.count(conditions, (err, count) => {
                if (err) return done(err);
                done(null, count);
            });
        };

        let getIpUserCount = (done) => {
            let conditions = { ip: req.app.ip, user: req.body.username };

            pgLoginAttemptModel.count(conditions, (err, count) => {
                if (err) return done(err);
                done(null, count);
            });
        };

        let asyncFinally = (err, results) => {
            if (err) return this.emit(this.err, err);

            if (results.ip >= 5 || results.ipUser >= 5) {
                return this.emit(this.fail);
            }
            else {
                this.emit(successEvent);
            }
        };

        async.parallel({ ip: getIpCount, ipUser: getIpUserCount }, asyncFinally);
};

Feature: Class Type reflection capabilities

I would love to see the reflection capabilities with class instances, just like obj.constructor works like.

I use class-transformer for document serialization:

import { Typegoose, prop as Property } from "typegoose";
import { Exclude, Expose } from "class-transformer";

@Exclude()
export class User extends Typegoose {

    @Expose()
    id: string;

    @Expose()
    @Property({ unique: true })
    email: string;

    @Property()
    password: string;

}

export const UserModel = new User().getModelForClass(User);

It would be amazing to be able to write generic serialize method which could take the original ClassType from the mongoose document and invoke plaintToClass(ClassType, object) without explicit specifying the constructor class function.

Examples:

// instead writing in http framework controllers methods
const dbUser = await UserModel.findOne({ email: "test" });
const clsUser = plainToClass(User, dbUser!);
return classToPlain(clsUser);

// I would like to return plain document
return await UserModel.findOne({ email: "test" });

// and the `serialize` method would be invoked by http framework before sending response to client
function serialize(document) {
    const ClassType = getClassTypeForTypegooseDocument(document);
    return plainToClass(ClassType, document);
}

I know that your main goal is to define the schema by class but since you don't return the class itself as a document (like TypeORM does) it would be necessary to provide posibility to get the class of the document of schema created by the class 😉

I think that the best way would be to store this.constructor function from getModelForClass inside typegoose's constructors dictionary and then get the constructor by model name with the model name from docObj.constructor.modelName 😃

Possible to use references in instance methods

Something like:

class GuildMember extends Typegoose {
    @prop({ref: User})
    public user: Ref<User>;

    public get id() {
        return this.user.identifier; // <------ identifier doesn't exist on `Ref`
    }
}

Automatic pluralizing collection names

Typegoose automatically pluralizing my collection names. for example my collection is device_warehouse, on the db it became device_warehouses with "s". I hope I can get feedback soon.

Add missing SchemaType Options (unique, index, etc).

I'm not quite sure why there is an agrupation of the "allowed" SchemaType Options (required, enum, default, min, max, etc) in the code (BasePropOptions, ValidateNumberOptions, etc). I guess you want TS to ensure what is being sent in the @prop() and @arrayProp() annotations... right?

The annoying part of this is that we should add the missing SchemaType Options manually 😢

I've already tested adding unique and index in the BasePropOptions:

export interface BasePropOptions {
  unique?: boolean; // Unique is always boolean!
  index?: boolean; // Same here.
...

...and they work just fine. Would you like a PR for this? This is another simple addition ;)

TypeError: Class constructor Typegoose cannot be invoked without 'new'

Hi,
I'm for some reason getting this error "TypeError: Class constructor Typegoose cannot be invoked without 'new'"

I have a class like this:

export class Item extends Typegoose {
	@prop()
	name: string;

	@prop()
	description: string;

	@prop({ref: Asset})
	question: Asset;

	@prop({enum: ItemTypes})
	itemType: ItemTypes;

	@prop({enum: ItemModes})
	itemMode: ItemModes;
}

I also have service which uses the class like this:

export class ItemsService {
	private itemModel;

	constructor(
	) {
		this.itemModel = new Item().getModelForClass(Item);
	}
}

As TS compiles:

TypeError: Class constructor Typegoose cannot be invoked without 'new'
    at new Item (/Users/anvlkv/Projects/intervey/intervey-api/src/models/item.ts:40:42)
    at new ItemsService (/Users/anvlkv/Projects/intervey/intervey-api/src/server/services/itemsService.ts:11:20)
    at new SequenceService (/Users/anvlkv/Projects/intervey/intervey-api/src/server/services/sequenceService.ts:13:23)
    at Object.<anonymous> (/Users/anvlkv/Projects/intervey/intervey-api/src/server/routes/InterviewerRoutes.ts:9:42)
    at Module._compile (module.js:570:32)
    at Module.m._compile (/Users/anvlkv/Projects/intervey/intervey-api/node_modules/ts-node/src/index.ts:392:23)
    at Module._extensions..js (module.js:579:10)
    at Object.require.extensions.(anonymous function) [as .ts] (/Users/anvlkv/Projects/intervey/intervey-api/node_modules/ts-node/src/index.ts:395:12)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.require (module.js:497:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/Users/anvlkv/Projects/intervey/intervey-api/src/server/main.ts:4:1)
    at Module._compile (module.js:570:32)
    at Module.m._compile (/Users/anvlkv/Projects/intervey/intervey-api/node_modules/ts-node/src/index.ts:392:23)
[nodemon] app crashed - waiting for file changes before starting...

The strangest part is that my src/models/item.ts is only 33 lines and problem supposed to be at line 40.

Type return of getModelForClass

Hi, I'm trying typegoose since yesterday, and I have a question related to your implementation. (Thanks a lot for your work, this package rocks!):

Why can't we assign a model as a type?

import { prop, Typegoose} from 'typegoose'

class User extends Typegoose {
    ...
    @prop({ required: true})
    public firstName: string;
    ...
}

export default new User().getModelForClass(User);
import User from './User'

let user:User = new User(); // -> Does not work because User is not a type 

Error with required nested elements

If you put { required: true } in the prop annotation over a nested element you get this error:

TypeError: Undefined type undefined at job.required
Did you try nesting Schemas? You can only nest using refs or arrays.

You can try it with the same code of your md file example:

class Job extends Typegoose {
    @prop()
    title: string;

    @prop()
    position: string;
}

class Contact extends Typegoose {

    @prop({ required: true }) // Added the required constraint
    job: Job;


}

The work around is... not using "required: true" over nested elements (yay!).

I'm using:
Hapi 16.4.3,
typegoose 3.0.0,
typescript 2.4.1,
ts-node 3.1.0,

Once again, let me know if you can reproduce this.
Thanks in advance!

Support inheritance from abstractModel (old: staticMethod not giving model as this)

Using the following code:

export default abstract class AbstractModel extends Typegoose {
    @staticMethod
    public static findByIdentifier(this: ModelType<AbstractModel>, identifier: Long) {
        return new Promise((resolve, reject) => {
            console.log(this);
            this.findOne({identifier}).then(resolve).catch(reject);
        });
    }

    @prop({required: true, index: true, unique: true})
    public identifier: string;
}

this is always an instance of the model, instead of the model type, so i can't call findOne.

Feel like im missing something...

Error with nested classes order

I got the following error when trying to nest models...:

Error: There is no metadata for the "job" property. Check if emitDecoratorMetadata is enable in tsconfig.json
at [...]/node_modules/typegoose/src/prop.ts:148:11

... if the nested model is defined after the parent one (this is the same example of your md file, without the Car ref):

import { prop, Typegoose } from 'typegoose';

class User extends Typegoose {
    @prop()
    name?: string;

    @prop({ required: true })
    age: number;

    @prop()
    job?: Job;


}

class Job extends Typegoose {
    @prop()
    title?: string;

    @prop()
    position?: string;
}


export const UserModel = new User().getModelForClass(User);

The work around is to define Job before User.

I'm using:
Hapi 16.4.3,
typegoose 3.0.0,
typescript 2.4.1,
ts-node 3.1.0,

And yes, I have "emitDecoratorMetadata": true in tsconfig 😉

Let me know if you can reproduce this!
Thanks!

How to use InstanceType?

I have my class like this:

export class User extends Typegoose {
}

How can I add mongoose.Document or InstanceType to it? Because now I have to do this in all my functions:

export async function addUser(args: IAddUserArgs): Promise<User & mongoose.Document> {
}

Which is a bit annoying because I have to import mongoose in every file that imports User.

I'm not sure how to do this with my limited TS knowledge :)

Schema methods should not be undefined

If a schema has no instance methods defined by the user, mongoose will still try to access its structure when timestamps are enabled for it.

The following error will occur:

TypeError: Cannot set property 'initializeTimestamps' of undefined

The cause is that schema.methods is undefined and mongoose tries to add a new method by:
this.methods.initializeTimestamps = function { ... }

A solution to this is simple: typegoose.ts:37:

sch.methods = instanceMethods || {};

Pre and Pos methods

First of all, The idea is awesome!

I just wanted to know about how to implement 'pre' and 'pos' save methods in typegoose way.

Thanks!

Cannot set custom mongoose.Promise when using Typegoose

I'm using typegoose 3.6.0 with mongoose 4.13.0.

Setting mongoose.Promise doesn't work when using Typegoose, even if setting it everywhere I import mongoose. As a result (I'm assuming) the mongoose promises are never executed. Removing Typegoose solves the problem.

Eveywhere I import mongoose:

const mongoose = require("mongoose")
(<any>mongoose).Promise = global.Promise;

Defining the model:

export enum Role {
    USER = "user",
    CONTRIBUTOR = "contributor",
    ADMIN = "admin"
}

export class UserProto extends Typegoose {
    _id: mongoose.Types.ObjectId;
    createdAt: Date;
    updatedAt: Date;

    @prop({ enum: Role, default: Role.USER })
    role: Role;
}

export const User = new UserProto().getModelForClass(UserProto, { schemaOptions: { timestamps: true }});

"in save" is never logged

let user = new User({role: Role.USER});
user.save().then((doc) => {
      console.log("in save");
      
      return doc.toObject();
    }).catch((err) => {
      console.log("error");
    }); 

'plugin' documentation in README.md file improving

Hi.
I'm using typegoose increasingly in a production project; it works and keep clean the source code. Thank you!

Maybe, in the README.md file you can specify the following tips about 'plugin':

1- plugin source file written in typescript: check the export instructions

If the plugin is developed with Typescript language and it is not a 3rd part software, check the first line of the transpilled file.
From Typescript 2.2 the first transpilled js line after the 'use strict' line, is 'Object.defineProperty(exports, "__esModule", { value: true });' and a mongoose error is generated because a function is needed at start of plugin.
To avoid this error you can start the plugin in the Typescript source file with the line:

module.exports = exports = function findOrCreatePlugin (schema, options?) {
...
}

2- plugin static methods in typegoose class

staticMethod decorator and an empy body {} are mandatory for a correct and complete method signature also when you add manually the static methods for typing information about a schema.statics function in a plugin.

@staticMethod public static findOrCreate(condition: InstanceType<User>): Promise<{ doc: InstanceType<User>, created: boolean }> {};

Whitout these two warnings in the README.md it's possible to lose a lot of work time.

Unnecessary package.json dependencies

Why mongoose is a real dependency of typegoose? It should be a peerDependency and users should install it by themselves, as they still need to explicitly use it by themselves:

import * as mongoose from 'mongoose';
mongoose.connect('mongodb://localhost:27017/test');

So when they use different version than the typegoose one, there will be problems with no errors marked by npm - two copies of mongoose in one project.

Also, you distribute on npm the compiled version and "main" points to "lib/typegoose.js" which is correct. So why you have typescript listed in dependecies? Lib consumers doesn't need this, they can use the lib even with flow+babel, as long as they produce api-compatible js transpiled code.

import 'reflect-metadata'; is also not needed in typegoose source - it's only a runtime shim for Reflect.metadata to make TS decorator class type reflection works. Again, users should import it in their entry file as some of them might want to use core-js polyfill instead.

feathers-mongoose

Hi,

I am trying to use Typegoose with feathers-mongoose and I guess I am making some beginner´s mistake, because I can´t get it to work.

My model class looks like this:

export class PostalCode extends Typegoose{
    @prop({ required: true })
    code: String
    @prop({ required: true })
    city: String
}

I thought, I could simply replace the model creation (which is commented out and works fine) with the getModelForClass statement, but this doesn´t work:

const service = require('feathers-mongoose');

function services() {
    /* var postalCodeSchema = mongoose.Schema({
        code: String,
         city: String
     });

    var PostalCodeModel = mongoose.model('PostalCode', postalCodeSchema); */

    var PostalCodeModel = new PostalCode().getModelForClass(PostalCode);

    this.use('/postalcode', service({
           Model: PostalCodeModel,   
           paginate: {
            default: 2,
            max: 4
           }
      }));
} 

I would be great if you could give me a hint, what I did wrong.

Thanks Alex

.save() never returns

Hi. I'm trying to follow your example and having difficulties.
my project structure is:
app.ts
server.ts
models
-->user.model.ts
routes
-->users.ts

in app.ts I'm defining the connection to the database:

constructor() {
    this.mongoose = new mongoose.Mongoose();
    this.express = express();
    this.express.use("/users", usersRouter);
    this.mongoose.connect("mongodb:\/\/localhost:27017/example", (err) => {
        if (err) {
            console.log('[-] Error connecting  to database mongodb:\/\/localhost:27017/example" - ${err.message}');
            throw err;
        } else {
            console.log('[*] Connected to database mongodb:\/\/localhost:27017/example');
        }
    });
}

server.ts is only there to start the server itself:

let app = new App();
app.express.listen(3000, () => {
    console.log('[*] server started on port 3000');
});

I've created a user model with Typegoose and added an API call via express to add a user to the system:
routes/users.ts (where i call 'addUser' from the model):

private static readonly UserModel = new User().getModelForClass(User);
usersRouter.post("/register", (req, res, next) => {
    let newUser = new Models.UserModel({
        email: req.body.email,
        name: req.body.name,
        password: req.body.password,
        username: req.body.username,
    });
    UserModel.addUser(newUser, (err, user) => {
        if (err) {
            res.json({
                msg: "Failed regisgter user",
                success: false,
            });
        } else {
            res.json({
                msg: "registered user",
                success: true,
            });
        }
    });
}

models/user.model.ts

export class User extends Typegoose {
    @staticMethod
    public static async addUser(newUser: InstanceType<User>, callback: (err: any, product: InstanceType<User>) => void)) {
        await newUser.save(callback);
    }
    @prop({required: true})
    public email: string;
    @prop()
    public name?: string;
    @prop({required: true})
    public password: string;
    @prop({required: true})
    public username: string;
}

everything's going fine until the line newUser.save();
the callback never get called... I also don't see any traffic in mongo.

The project work on JavaScript, now I'm trying to move to TS. Is there something I missed during the transmission or is it an issue?

GeoJSON Support

Hi,

is it possible to use GeoJSON with Typegoose?
I'm not able to create an index so I can search it with $nearSphere.

What I've tried is to create the following model to store the data:

export class LocationData extends Typegoose {
    @prop()
    public type: string;

    @arrayProp({ items: Number })
    public coordinates: [number];
}

In my user model I have added the following attribute:

export class User extends Typegoose {
    @prop()
    public currentLocation: LocationData;
}

Since there must be an index on currentLocation to be able to perform the $nearSphere query I tried @prop({index: true}).

But I got the following error message:

TypeError: Undefined type `undefined` at `currentLocation.index`
  Did you try nesting Schemas? You can only nest using refs or arrays.

Some tutorials said you must define your own type to store the location data.
But how do I do it with Typegoose?

The mongoose way is:

var locationSchema = new Schema({  
  loc: {
    type: {
      type: "String",
      required: true,
      enum: ['Point', 'LineString', 'Polygon'],
      default: 'Point'
    },
    coordinates: [Number]
  }
});

locationSchema.index({ 'loc': '2dsphere' });
var Location = mongoose.model( 'Location', locationSchema );

What do I need to do to solve this issue?

Enhanced enum support

Right now, you support string array as an enum:

// Enum-like type and definition example.
type Gender = 'male' | 'female';
const Genders = {
  MALE: 'male' as Gender,
  FEMALE: 'female' as Gender,
};

@prop({ enum: Object.values(Genders) })
gender?: Gender;

However we have string enum support in TS now. It would be nice if the decorator function accept also the object type as the enum value and get the string values using Object.values(object) inside:

// true enum type
enum Gender {
  MALE = 'male',
  FEMALE = 'female',
};

@prop({ enum: Gender })
gender?: Gender;

So the signature of the BasePropOptions would be enum?: string[]|object; and you can in runtime check if Array.isArray(enum) to behave like now or convert enum object to values.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.