Security News
Oracle Drags Its Feet in the JavaScript Trademark Dispute
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Invisible is a JavaScript (and CoffeeScript!) library that leverages browserify to achieve the Holy Grail of web programming: model reuse in the client and the server.
Install with npm:
npm install invisible
Wire up Invisible into your express app:
express = require("express");
path = require("path");
invisible = require("invisible");
app = express();
invisible.createServer(app, path.join(__dirname, "models"))
To make your models available everywhere, define them and call Invisible.createModel
Invisible = require("invisible");
crypto = require("crypto");
_s = require("underscore.string");
function Person(firstName, lastName, email){
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
Person.prototype.fullName = function(){
return this.firstName + ' ' + this.lastName;
}
Person.prototype.getAvatarUrl = function(){
cleanMail = _s.trim(this.email).toLowerCase();
hash = crypto.createHash("md5").update(cleanMail).digest("hex");
return "http://www.gravatar.com/avatar/" + hash;
}
module.exports = Invisible.createModel("Person", Person);
Now your models will be available under the Invisible namespace. Require as usual in the server:
Invisible = require("invisible")
john = new Invisible.Person("John", "Doe", "john.doe@mail.com");
john.fullName(); //John Doe
In the client, just add the invisible script:
<script src="invisible.js"></script>
<script>
jane = new Invisible.Person("Jane", "Doe", "jane.doe@mail.com");
alert(jane.fullName()); //Jane Doe
</script>
Invisible.js uses browserify to expose you server defined models in the browser, so you can use any broserify-able library to implement them. Note that this integration is seamless, no need to build a bundle, Invisible.js does that for you on the fly.
In addition to making your models available everywhere, Invisible extends them with methods to handle persistence. In the server this means interacting with MongoDB and in the client making requests to an auto-generated REST API, that subsequently performs the same DB action.
jane.save(function(err, result){
if (err){
console.log("something went wrong");
} else {
console.log("Jane's id is " + jane._id);
console.log("which equals " + result._id);
}
})
The first time the save method is called, it creates the model in the database and sets its _id
attribute.
Subsequent calls update the model. Validations are called upon saving, see the validations section for details.
Note that a full Invisible model instance is passed to the callback, and the calling instance is also updated when the process is done.
jane.delete(function(err, result){
if (err){
console.log("something went wrong");
} else {
console.log("Jane is no more.");
}
})
Invisible.Person.query(function(err, results){
if (err){
console.log("something went wrong");
} else {
console.log("Saved persons are:");
for (var i = 0; i < results.length; i++){
console.log(results[i].fullName());
}
}
});
Invisible.Person.query({firstName: "Jane"}, function(err, results){
if (err){
console.log("something went wrong");
} else {
console.log("Persons named Jane are:");
for (var i = 0; i < results.length; i++){
console.log(results[i].fullName());
}
}
});
Invisible.Person.query({}, {sort: "lastName", limit: 10}, function(err, results){
if (err){
console.log("something went wrong");
} else {
console.log("First 10 persons are:");
for (var i = 0; i < results.length; i++){
console.log(results[i].fullName());
}
}
});
Queries the database for existent models. The first two optional arguments correspond to the Query object and Query options in the MongoDB Node.JS driver. The one difference is that when using ids you can pass strings, that will be converted to ObjectID when necessary.
Invisible.Person.findById(jane._id, function(err, model){
if (err){
console.log("something went wrong");
} else {
console.log("Jane's name is " + model.firstName);
console.log("But we knew that!");
}
})
Looks into the database for a model with the specified _id
value. As in the query method, you can pass
a string id instead of an ObjectID instance.
Invisible.js integrates with revalidator to handle model validations.
A validate
method is added to each model which looks for a defined validation schema, and is executed each time
a model is saved, both in the client and the server. For example:
function Person(email){
this.email = email;
}
Person.prototype.validations = {
properties: {
email: {
format: 'email',
required: true
}
}
}
john = new Person("john.doe@none.com");
john.save(function(err, result){
console.log("All OK here.");
});
john.email = "invalid";
john.save(function(err, result){
console.log(err);
/* Prints: {valid: false, errors: [{attribute: 'format',
property: 'email', message: 'is not a valid email'}]} */
})
Invisible.js also introduces "method" validations, which allow you to specify a method which should be called in the validation process. This way asynchronic validations, such as querying the database, can be performed:
Person.prototype.validations = {
methods: ['checkUnique']
}
Person.prototype.checkUnique = function(cb) {
Invisible.Person.query({email: this.email}, function(err, res){
if (res.length > 0){
cb({valid: false, errors: ["email already registered"]});
} else {
cb({valid: true, errors: []});
}
});
}
The custom validation method takes a callback and should call it with the return format of revalidator: an object with a "valid" boolean field and an "errors" list. Note that the method validations are only called if the properties validations succeed, and stop the validation process upon the first failure.
Invisible.js uses socket.io to emmit an event whenever something changes for a model, and lets you add listener functions to react to those changes in realtime.
Invisible.Person.onNew(function(model){
console.log(model.fullName() + " has been created");
});
Invisible.Person.onUpdate(function(model){
console.log(model.fullName() + " has been updated");
});
Invisible.Person.onDelete(function(model){
console.log(model.fullName() + " has been deleted");
});
FAQs
DRY models for client and server
The npm package invisible receives a total of 40 weekly downloads. As such, invisible popularity was classified as not popular.
We found that invisible demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.