Skip to content

Commit 17b6e63

Browse files
committed
Initial commit. Types 'email', 'url', 'counter'
0 parents  commit 17b6e63

File tree

10 files changed

+153
-0
lines changed

10 files changed

+153
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
**.swp

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "support/expresso"]
2+
path = support/expresso
3+
url = https://github.com/visionmedia/expresso.git

Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
EXPRESSO = support/expresso/bin/expresso -I lib --serial
2+
3+
TESTS = tests/*.test.js
4+
5+
test:
6+
@$(EXPRESSO) $(TESTS) $(TEST_FLAGS)
7+
8+
test-cov:
9+
@$(MAKE) TEST_FLAGS=--cov test
10+
11+
.PHONY: test test-cov

index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require("./lib/types");

lib/types/counter.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
module.exports.loadType = function (mongoose) {
2+
mongoose.type('counter')
3+
.extend('number')
4+
.default(0)
5+
.setup( function () { /** @scope is the Schema instance **/
6+
var schema = this;
7+
['incr', 'decr'].forEach( function (methodToAdd) {
8+
if (!schema._methods[methodToAdd]) {
9+
schema.method(methodToAdd, function (path, delta, fn) { /** @scope is a Document instance **/
10+
if (this.isNew || !this.id) throw new Error("You can only increment keys of documents that already have been persisted to mongodb.");
11+
var arg1type = typeof arguments[1];
12+
if (arg1type === "undefined") { // incr(path)
13+
delta = 1;
14+
} else if (arg1type === "function") { // incr(path, fn)
15+
fn = delta;
16+
delta = 1;
17+
} // Else we had invoked: incr(path, delta[, fn]); // i.e. arg1type === "number"
18+
var mongooseDoc = this,
19+
incObj = {}, fieldsObj = {};
20+
switch (methodToAdd) {
21+
case ('incr'):
22+
incObj[path] = delta;
23+
break;
24+
case('decr'):
25+
incObj[path] = -1 * delta;
26+
break;
27+
}
28+
fieldsObj[path] = 1;
29+
this._collection.findAndModify({'_id': this._id}, [], {'$inc': incObj}, {'new': true, fields: fieldsObj}, function (err, doc) {
30+
if (doc) mongooseDoc.set(path, doc[path], true);
31+
if (fn) fn(err, mongooseDoc);
32+
});
33+
});
34+
}
35+
});
36+
};

lib/types/email.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports.loadType = function (mongoose) {
2+
mongoose.type('email')
3+
.validate('email', function (value, callback) {
4+
return callback( /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/.test(value) );
5+
});
6+
};

lib/types/index.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports.loadTypes = function () {
2+
var mongoose = arguments[0],
3+
types = Array.prototype.slice.call(arguments, 1);
4+
types.forEach( function (type) {
5+
require("./" + type).loadType(mongoose);
6+
});
7+
};

lib/types/url.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
var Url = require("url");
2+
3+
module.exports.loadType = function (mongoose) {
4+
type('url')
5+
.extend('string')
6+
.validate('url', function (val, callback) {
7+
var urlRegexp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;
8+
return callback(urlRegexp.test(val));
9+
})
10+
.castSet(function (val, path) {
11+
return module.exports.normalizeUrl(val);
12+
});
13+
};
14+
15+
// See http://en.wikipedia.org/wiki/URL_normalization
16+
module.exports.normalizeUrl = (function () {
17+
var reorderQuery = function (query) {
18+
var orderedKeys = [], name, i, len, key, querystr = [];
19+
for (name in query) {
20+
for (i = 0, len = orderedKeys.length; i < len; i++) {
21+
if (orderedKeys[i] >= name) break;
22+
}
23+
orderedKeys.splice(i, 0, name);
24+
}
25+
for (i = 0, len = orderedKeys.length; i < len; i++) {
26+
key = orderedKeys[i];
27+
querystr.push(key + "=" + query[key]);
28+
}
29+
return querystr.join("&");
30+
};
31+
32+
return function (uri) {
33+
var parsedUrl = Url.parse(uri, true),
34+
urlstr = "";
35+
urlstr += parsedUrl.protocol.toLowerCase() + "//" + parsedUrl.hostname.toLowerCase().replace(/^www\./, "") + // Convert scheme and host to lower case; remove www. if it exists in hostname
36+
(parsedUrl.pathname ?
37+
parsedUrl.pathname.replace(/\/\.{1,2}\//g, "/").replace(/\/{2,}/, "/") : // Remove dot-segments; Remove duplicate slashes
38+
"/" // Add trailing /
39+
);
40+
if (parsedUrl.query) {
41+
urlstr += "?" + reorderQuery(parsedUrl.query);
42+
}
43+
if (parsedUrl.hash) {
44+
urlstr += parsedUrl.hash;
45+
}
46+
return urlstr;
47+
};
48+
})();

support/expresso

Submodule expresso added at 7f10ab7

tests/email.test.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
var assert = require('assert')
2+
, mongoose = require('mongoose').new()
3+
, document = mongoose.define
4+
, db = mongoose.connect('mongodb://localhost/mongoose_types_tests')
5+
, loadTypes = require("../").loadTypes;
6+
7+
loadTypes(mongoose, 'email');
8+
document('User')
9+
.email('email');
10+
11+
module.exports = {
12+
before: function(assert, done){
13+
db.on('connect', function () {
14+
mongoose.User.remove({}, function () {
15+
done();
16+
});
17+
});
18+
},
19+
'test invalid email validation': function (assert, done) {
20+
var user = new mongoose.User({email: 'hello'});
21+
user.save(function (err, _user) {
22+
assert.ok(_user.errors[0].name === 'email');
23+
assert.ok(_user.errors[0].path === 'email');
24+
assert.ok(_user.errors[0].type === 'validation');
25+
assert.ok(_user.errors[0].message === 'validation email failed for email');
26+
done();
27+
});
28+
},
29+
'test valid email validation': function (assert, done) {
30+
mongoose.User.create({ email: 'brian@brian.com' }, function (err, user) {
31+
assert.equal("undefined", typeof user.errors);
32+
assert.equal(false, user.isNew);
33+
done();
34+
});
35+
},
36+
teardown: function(){
37+
mongoose.disconnect();
38+
}
39+
};

0 commit comments

Comments
 (0)