1.4.0 • Published 9 years ago

mongoman v1.4.0

Weekly downloads
1
License
-
Repository
github
Last release
9 years ago

Mongoman

Build Status

A node utility to simplify schema and model management. Most utility is wrapped around the mongoose module. If you would like to use mongoman as a replacement for mongoose, mongoose is aliased at both mon.mongoose and mon.goose

Key

Usage

npm install mongoman

leverage mongoman to cut down on bloat in model creation. For example, this

var mongoose = require('mongoose');

var newSchema = new mongoose.Schema({
  email : {
    type       : String,
    required   : true,
    validation : [{
      msg       : 'invalid email',
      validator : function (value) {
        return /^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/.test(value);
      }
    }]
  password : {
    type       : String,
    required   : true,
    validation : [{
      msg       : 'too short',
      validator : function (value) {
        return value.length >= 6
      }
    }]
  }
});

mongoose.model('ExampleModel', newSchema);

becomes this

var mon = require('mongoman');

mon.register('ExampleModel', {
  email    : mon().string().required().email().fin(),
  password : mon().string().required().min(6).fin()
});

The focus of mongoman is to simplify validation and schema creation. However, I do recommed looking at the utilities section for some helpful utilities.

Property Builder

The core use of mongoman is schema creation via property building. To make a new schema, simply use the property builder chain, initiated with mongoman() and terminated with fin(). For example. a simple user schema might look something like this

mon = require('mongoman');

var user = {

  // validates the name to be a required string that fits the regex
  name : mon().string().required().regex(/[a-z]+\s*[a-z+]/i).fin(),

  // sets the registered propert to default tothe current date-time
  registered : mon().date().default(new Date()).fin(),

  // validates the age to be a required integer of at least 18
  age : mon().required().number().integer.min(18).fin()

}

Every validation middleware function has a default error, but errors can be augmented to inlude a property name by passing in a value to the mon() function call.

mon().email().fin(); // validation error : 'invalid email'
mon('My email').email().fin(); // validation error : 'My email is not a valid email'

Universal

If a property or validation isn't included as a supported chainable function, you can easily include it using the following functions.

prop.set(key, value)

Set the key/value passed in for the property

  schema.newProp = mon().set('type', String).fin();

prop.validate(errorMsg, valFunction)

Bind the validation function to the property, throwing the error message if it returns false

  function isOdd (value) {
    return (value % 2) == 1
  }

  schema.newProp = mon().validate('newProp must be odd', isOdd).fin();

prop.index(key|value, [value])

Bind the key and value to the index attribute of the property. Providing only one parameter will set index equal to that parameter

  schema.newProp = mon().index('unique', false).fin();
  // or
  schema.newProp = mon().index('hashed').fin();

Types

prop.string()

Set property type to String

  schema.newProp = mon().string().fin();

prop.date()

Set property type to Date

  schema.newProp = mon().date().fin();

prop.number()

Set property type to Number

  schema.newProp = mon().number().fin();

prop.buffer()

Set property type to Buffer

  schema.newProp = mon().buffer().fin();

prop.mixed()

Set property type to be mixed

  schema.newProp = mon().mixed().fin();

prop.objectId()

Set property type to be an object ID

  schema.newProp = mon().objectId().fin();

prop.array()

Set property type to be Array

  schema.newProp = mon().array().fin();

prop.schema(ref, type)

Set property type to be a reference to another schema

ref -- Required - name of referred schema type -- Optional - Defaults ObjectId, possible values (Number, String, Buffer)

  schema.newProp = mon().schema('schemaName').fin();

Middleware

Any time [] is a function parameter, its is optional.

Shared

prop.onGet(function)

type: any

Passes the value of the property into the function. the returned value is what is exposed to the document on get

  schema.newProp = mon().onGet(function (value) {
    return value ? value + '-example' : value;
  }).fin();

prop.onSet(function)

type: any

Passes the value of the property into the function. the returned value is what is saved to the document on get

  schema.newProp = mon().onSet(function (value) {
    return value ? value + '-example' : value;
  }).fin();

Date

prop.expires(dateTime)

type: date

Sets the expiration of the date

  schema.newProp = mon().expires('1.5h').fin();

String

prop.toUppercase()

type: string

Sets the value to uppercase

  schema.newProp = mon().toUppercase().fin();

prop.toLowercase()

type: string

Sets the value lowercase

  schema.newProp = mon().toLowercase().fin();

prop.trim()

type: string

Trims the whitespace off the beginning and end of the string

  schema.newProp = mon().trim().fin();

Validation

important: using validations that do not apply to the property type will throw an error. To allow them to pass silently, set mongo configuration strict : false.

Any time [] is a function parameter, its is optional. any time [message] is included, a default message will be used unless this parameter is specified.

Shared

prop.required()

type: any

return an error if the property is not defined

  schema.newProp = mon().required().fin();

prop.default(value)

type: any

If no value is set for the property, set it to the default value passed in

  schema.newProp = mon().default('default value').fin();

prop.select([bool])

type: any

[bool] true or undefined if this path should always be included in the results, false if it should be excluded by default. This setting can be overridden at the query level.

  schema.newProp = mon().select().fin();

prop.enum(values, [message])

type: any

If the value submitted is not uncluded in the list of enumerated properties, an error is returned.

  schema.newProp = mon().enum(['foo', 'bar'], 'custom error').fin();

prop.unique([bool])

type: any

Insures a unique index is generated for the property. defaults to true. False causes the DB to be indifferent

  schema.newProp = mon().unique().fin();

prop.ref(model)

type: any

Creates a reference to another model. This is used to populate data from another document

  schema.newProp = mon().objectId().ref('fooModel').fin();

prop.min(value, [message])

type: string (length), array (length), number (value), date (value), object (keys), buffer (length)

Check that the value being saved is greater than or equal to the value passed into the property builder

  schema.newProp = mon().min(5).fin();

prop.max(value, [message])

type: string (length), array (length), number (value), date (value), object (keys), buffer (length)

Check that the value being saved is less than or equal to the value passed into the property builder

  schema.newProp = mon().max(5).fin();

prop.length(value, [message])

type: string (length), array (length), object (keys), buffer (length)

Check that the value being saved is the same length as the value passed into the property builder

  schema.newProp = mon().length(5).fin();

Arrays

prop.sparse()

return an error if the array contains undefined values

  schema.newProp = mon().array().sparse().fin();

Strings

prop.alphanum([message])

return an error if the string contains non alpha-numeric values

  schema.newProp = mon().string().alphanum().fin();

prop.regex(expression, [message])

return an error if the string does not match the expression

  schema.newProp = mon().string().regex(expression).fin();

prop.email([message])

return an error if the string is not a valid email address

  schema.newProp = mon().string().email().fin();

prop.token([message])

return an error if the string is not a valid token

  schema.newProp = mon().string().token().fin();

prop.guid([message])

return an error if the string is not a valid GUID

  schema.newProp = mon().string().guid().fin();

prop.hostname([message])

return an error if the string is not a valid hostname

  schema.newProp = mon().string().hostname().fin();

prop.url([message])

return an error if the string is not a valid url

  schema.newProp = mon().string().url().fin();

prop.uppercase([message])

return an error if the string is not uppercase

  schema.newProp = mon().string().uppercase().fin();

prop.lowercase([message])

return an error if the string is not lowercase

  schema.newProp = mon().string().lowercase().fin();

Numbers

prop.greater(limit, [message])

return an error if the number is below the limit

  schema.newProp = mon().number().greater(5).fin();

prop.less(limit, [message])

return an error if the number is above the limit

  schema.newProp = mon().number().less(5).fin();

prop.integer([message])

return an error if the string is not an integer

  schema.newProp = mon().string().integer().fin();

Utilities

mon.drop(collection)

drop a collection by name (normally just 'db')

mon.drop('db');

mon.connect([options])

takes options, defaulting to 'mongodb://localhost/database'. returns an instance of the database. also accessable through mon.db

var db = mon.connect();

mon.schema(schema)

returns an instance of a schema with the given schema object definition

var mySchema = mon.schema({
  name : mon().string().required().fin()
});

mon.model(modelName)

returns the model matching the given name

var MyModel = mon.model('MyModel');

mon.new(modelName)

returns a new instance of the model specified. applies the inputs if they are defined

var tester = mon.new('MyModel', {
  name : 'tester'
});

mon.register(schema, [options])

registers a new model with the given schema and options. The options object is where middleware, methods, index properties, and virtual properties are defined. A minimalistic model is defined below

var mon    = require('mongoman');
var bcrypt = require('bcrypt-nodejs');

mon.register('Person', {
  firstName : mon().string().required().fin(),
  lastName  : mon().string().required().fin(),
  secret    : mon().string().fin()
}, {
  middleware : {
    pre : {
      save : function (callback) {
        if (this.isModified('secret'))  {
          this.secret = bcrypt.hashSync(this.secret, bcrypt.genSaltSync());
        }

        return callback();
      }
    }
  },
  methods : {
    findFamily : function (callback) {
      return mon.model('Person').find({
        lastName : this.lastName
      }, callback);
    },
    compareSecret : function(submitted, callback) {
      var result = bcrypt.compareSync(submitted, this.secret);
      return callback(null, result);
    }
  },
  statics : {
    findByFirst : function (first, callback) {
      return mon.model('Person').find({
        firstName : first
      }, callback);
    }
  },
  virtuals : {
    fullName : {
      get : function () {
        return this.firstName + ' ' + this.lastName;
      }
    }
  }
});

mon.registerAll(directory, [regex])

traverses the directory tree requiring all js files (to register models on server startup). optional regex to filter files

./models/foo.js

var mon = require('mongoman');
mon.register('foo', { foo : mon().string().fin() });

./models/sub_models/bar_model.js

var mon = require('mongoman');
mon.register('bar', { bar : mon().string().fin() });

./server.js

// ... server setup

mon.connect();

mon.registerAll('../models', /_model/); // registers ['bar']

// OR

mon.registerAll('../models'); // registers ['foo', 'bar']

// ... server finalizing

Running Unit Tests

To run the unit tests, execute the following:

  npm test

Please make sure all unit tests pass before making a new PR

1.4.0

9 years ago

1.3.0

9 years ago

1.2.0

9 years ago

1.1.0

9 years ago

1.0.0

9 years ago

0.0.4

9 years ago

0.0.3

9 years ago

0.0.2

9 years ago

0.0.1

9 years ago