alamid-schema

Extendable mongoose-like schemas for node.js and the browser

alamid-schema

Extendable mongoose-like schemas for node.js and the browser


If you like mongoose schemas and you want to use them standalone, alamid-schema is the right module for you.

alamid-schema helps you with

  • validation of data
  • using mongoose-like schemas without using mongoose
  • sharing data-definition between client & server
  • normalizing data (coming soon)
  • striping readable/writeable fields (coming soon)

Use it on the server to...

  • normalize and validate incoming requests
  • strip private fields from the response

Use it on the client to...

  • validate forms
  • define view models
var Schema = require("alamid-schema");
 
var Panda = new Schema("Panda", {
    name: String,
    age: {
        type: Number,
        required: true,
        writable: false,
        readable: true
    },
    mood: {
        type: String,
        enum: ["grumpy", "happy"]
    },
    birthday: Date
});

You can define your schema with concrete values...

var PandaSchema = new Schema({
    name: "panda",
    age: 12,
    friends: {
        type: []
    }
});

...or with abstract types...

var PandaSchema = new Schema({
    name: String,
    age: Number,
    friends: {
        type: Array
    }
});

Sometimes you want to extend your Schema and add new properties.

var PandaSchema = new Schema({
    name: String,
    age: Number,
    friends: {
        type: Array
    }
});
 
var SuperPanda = PandaSchema.extend("SuperPanda", {
    xRay: true,
    canFly: {
        type: Boolean
    }
});

We have a superpanda now... which can fly and has xray eyes! That's basically the same as...

var SuperPanda = new Schema({
    name: String,
    age: Number,
    friends: {
        type: Array
    },
    xRay: true, //added 
    canFly: {   //added  
        type: Boolean
    }
});

Overwriting properties

If you define a property in the schema you are extending with, the extending schema takes precedence.

var Animal = new Schema({
    name: String,
    age: String
});
 
var Panda = Animal.extend("Panda", {
    age: Number
    color: String
});

equals...

var Panda = new Schema("Panda", {
    name: String,
    age: Number,   //overwritten 
    color: String  //added  
});

The validation plugins adds - suprise! - validation support.

var Schema = require("alamid-schema");
Schema.use(require("alamid-schema/plugins/validation"));
 
var PandaSchema = new Schema({
    name: {
        type: String,
        required: true
    },
    age: {
        type: Number,
        min: 9,
        max: 99
    },
    mood: {
        type: String,
        enum: ["happy", "sleepy"]
    },
    birthday: Date
});
 
var panda = {
    name: "Hugo",
    age: 3,
    mood: "happy"
};
 
PandaSchema.validate(panda, function(validation) {
 
    if(!validation.result) {
        console.log(validation);
        return;
    }
 
    console.log("happy panda");
});

outputs...

{
    result: false,
    failedFields: {
        age: [ 'min' ] 
    }
}

Included validators:

  • required
  • min (Number)
  • max (Number)
  • enum

Writing custom validators:

You can write sync and async validators..

 
//sync 
function oldEnough(age) {
    return age > 18 || "too-young";
}
 
//async 
function nameIsUnique(namecallback) {
 
    fs.readFile(__dirname + "/names.json", function(errnames) {
        if(err) {
            throw err;
        }
 
        names = JSON.parse(names);
 
        callback(names.indexOf(name) === -1 || "name-already-taken");
    });
}
 
var PandaSchema = new Schema({
    name: {
        type: String,
        required: true,
        validate: nameIsUnique
    },
    age: {
        type: Number,
        validate: oldEnough,
        max: 99
    }
});
 
var panda = {
    name: "hugo",
    age: 3,
    mood: "happy"
};
 
PandaSchema.validate(panda, function(validation) {
 
    if(!validation.result) {
        console.log(validation.failedFields);
        return;
    }
    console.log("happy panda");
});

outputs...

{ 
    name: [ "name-already-taken" ], 
    age:  [ "too-young" ]
}

Note: validators will be called with this bound to model.

Instead of using a callback it is possible to return a Promise instead.

PandaSchema.validate(panda)
  .then(function (res) {
    // ... 
  });

We included an ES2015 shim in case you are using Node.js < 0.12 or a browser without native Promise support.

Creates a new schema.

Returns a subset with the given keys of the current schema. You may pass an array with keys or just the keys as arguments.

Creates a new schema that inherits from the current schema. Field definitions are merged where appropriate. If a definition conflicts with the parent definition, the child's definition supersedes.

You can define readable and writable fields in the schema. As default every field is read- and writable.

var PandaSchema = new Schema({
    id: {
        type: Number,
        required: true,
        readable: true,
        writable: false
    },
    lastModified: {
        readable: true,
        writable: false
    }
};

Validate given model using the schema-definitions.

Callback will be called with a validation object with result (Boolean) and failedFields (Object).