camo
Advanced tools
Comparing version 0.0.1 to 0.1.1
@@ -32,2 +32,6 @@ "use strict"; | ||
count(collection, query) { | ||
throw new TypeError('You must override count.'); | ||
} | ||
static connect(url) { | ||
@@ -34,0 +38,0 @@ throw new TypeError('You must override connect (static).'); |
@@ -11,2 +11,2 @@ var assertConnected = function(db) { | ||
return client; | ||
} | ||
}; |
@@ -6,3 +6,3 @@ "use strict"; | ||
var DatabaseClient = require('./client'); | ||
var MDBClient = require('mongodb').MongoClient | ||
var MDBClient = require('mongodb').MongoClient; | ||
@@ -58,2 +58,2 @@ class MongoClient extends DatabaseClient { | ||
module.exports = NeDbClient; | ||
module.exports = MongoClient; |
@@ -126,2 +126,13 @@ "use strict"; | ||
count(collection, query) { | ||
var that = this; | ||
return new Promise(function(resolve, reject) { | ||
var db = getCollection(collection, that._collections, that._path); | ||
db.count(query, function (error, count) { | ||
if (error) return reject(error); | ||
return resolve(count); | ||
}); | ||
}); | ||
} | ||
static connect(url) { | ||
@@ -128,0 +139,0 @@ var dbFolderPath = urlToPath(url); |
@@ -29,2 +29,2 @@ var NeDbClient = require('./clients/nedbclient'); | ||
} | ||
} | ||
}; |
@@ -6,2 +6,3 @@ "use strict"; | ||
var DB = require('./clients').getClient; | ||
var isSupportedType = require('./validate').isSupportedType; | ||
var isValidType = require('./validate').isValidType; | ||
@@ -13,2 +14,18 @@ var isInChoices = require('./validate').isInChoices; | ||
var normalizeType = function(property) { | ||
// TODO: Only copy over stuff we support | ||
var typeDeclaration = {}; | ||
if (property.type) { | ||
typeDeclaration = property; | ||
} else if (isSupportedType(property)) { | ||
typeDeclaration.type = property; | ||
} else { | ||
throw new Error('Unsupported type or bad variable. ' + | ||
'Remember, non-persisted objects must start with an underscore (_). Got:', property); | ||
} | ||
return typeDeclaration; | ||
}; | ||
// For more handler methods: | ||
@@ -20,5 +37,3 @@ // https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Proxy | ||
// Return current value, if set | ||
if (propKey in target._values | ||
&& target._values[propKey] !== null | ||
&& target._values[propKey] !== undefined) { | ||
if (propKey in target._values) { | ||
return target._values[propKey]; | ||
@@ -29,12 +44,5 @@ } | ||
if (propKey === 'id') { | ||
return target._values['_id']; | ||
return target._values._id; | ||
} | ||
// Maybe this hasn't been saved/loaded, so we | ||
// still need to grab the default value | ||
var def = target.getDefault(propKey); | ||
if (def !== null) { | ||
return def; | ||
} | ||
return Reflect.get(target, propKey); | ||
@@ -45,3 +53,4 @@ }, | ||
if (propKey in target._schema) { | ||
return target._values[propKey] = value; | ||
target._values[propKey] = value; | ||
return true; | ||
} | ||
@@ -51,3 +60,4 @@ | ||
if (propKey === 'id') { | ||
return target._values['_id'] = value; | ||
target._values._id = value; | ||
return true; | ||
} | ||
@@ -59,3 +69,5 @@ | ||
deleteProperty: function(target, propKey) { | ||
return delete target._schema[propKey] && delete target._values[propKey]; | ||
delete target._schema[propKey]; | ||
delete target._values[propKey]; | ||
return true; | ||
}, | ||
@@ -66,3 +78,3 @@ | ||
} | ||
} | ||
}; | ||
@@ -154,5 +166,5 @@ class Document { | ||
} else { | ||
valueNmae = typeof(value); | ||
valueName = typeof(value); | ||
} | ||
var err = new Error('Value assigned to ' + that._meta.collection + '.' + key + | ||
let err = new Error('Value assigned to ' + that._meta.collection + '.' + key + | ||
' should be ' + typeName + ', got ' + valueName); | ||
@@ -163,3 +175,3 @@ return reject(err); | ||
if (!isInChoices(that._schema[key].choices, value)) { | ||
var err = new Error('Value assigned to ' + that._meta.collection + '.' + key + | ||
let err = new Error('Value assigned to ' + that._meta.collection + '.' + key + | ||
' should be in [' + that._schema[key].choices.join(', ') + '], got ' + value); | ||
@@ -170,3 +182,3 @@ return reject(err); | ||
if (that._schema[key].min && value < that._schema[key].min) { | ||
var err = new Error('Value assigned to ' + that._meta.collection + '.' + key + | ||
let err = new Error('Value assigned to ' + that._meta.collection + '.' + key + | ||
' is less than min, ' + that._schema[key].min + ', got ' + value); | ||
@@ -177,3 +189,3 @@ return reject(err); | ||
if (that._schema[key].max && value > that._schema[key].max) { | ||
var err = new Error('Value assigned to ' + that._meta.collection + '.' + key + | ||
let err = new Error('Value assigned to ' + that._meta.collection + '.' + key + | ||
' is less than max, ' + that._schema[key].max + ', got ' + value); | ||
@@ -196,6 +208,6 @@ return reject(err); | ||
_.keys(that._values).forEach(function(key) { | ||
if (isModel(that._values[key]) // isModel OR | ||
|| (isArray(that._values[key]) // isArray AND contains value AND value isModel | ||
&& that._values[key].length > 0 | ||
&& isModel(that._values[key][0]))) { | ||
if (isModel(that._values[key]) || // isModel OR | ||
(isArray(that._values[key]) && // isArray AND contains value AND value isModel | ||
that._values[key].length > 0 && | ||
isModel(that._values[key][0]))) { | ||
@@ -241,4 +253,10 @@ // Handle array of references (ex: { type: [MyObject] }) | ||
// TODO: Need options to specify whether references should be loaded | ||
static loadOne(query) { | ||
static loadOne(query, options) { | ||
var that = this; | ||
var populate = true; | ||
if (options && options.hasOwnProperty('populate')) { | ||
populate = options.populate; | ||
} | ||
return DB().loadOne(this.collectionName(), query) | ||
@@ -251,3 +269,7 @@ .then(function(data) { | ||
var doc = that.fromData(data, that); | ||
return that.dereferenceDocuments(doc); | ||
if (populate) { | ||
return that.dereferenceDocuments(doc); | ||
} | ||
return doc; | ||
}); | ||
@@ -257,4 +279,10 @@ } | ||
// TODO: Need options to specify whether references should be loaded | ||
static loadMany(query) { | ||
static loadMany(query, options) { | ||
var that = this; | ||
var populate = true; | ||
if (options && options.hasOwnProperty('populate')) { | ||
populate = options.populate; | ||
} | ||
return DB().loadMany(this.collectionName(), query) | ||
@@ -269,6 +297,14 @@ .then(function(datas) { | ||
return that.dereferenceDocuments(documents); | ||
if (populate) { | ||
return that.dereferenceDocuments(documents); | ||
} | ||
return documents; | ||
}); | ||
} | ||
static count(query) { | ||
var that = this; | ||
return DB().count(this.collectionName(), query); | ||
} | ||
static clearCollection() { | ||
@@ -278,4 +314,32 @@ return DB().clearCollection(this.collectionName()); | ||
generateSchema() { | ||
var that = this; | ||
_.keys(this).forEach(function(k) { | ||
// Ignore private variables | ||
if (_.startsWith(k, '_')) { | ||
return; | ||
} | ||
// Normalize the type format | ||
that._schema[k] = normalizeType(that[k]); | ||
// Assign a default if needed | ||
if (isArray(that._schema[k].type)) { | ||
that._values[k] = that.getDefault(k) || []; | ||
} else { | ||
that._values[k] = that.getDefault(k); | ||
} | ||
// Should we delete these member variables so they | ||
// don't get in the way? Probably a waste of time | ||
// since the Proxy intercepts all gets/sets to them. | ||
//delete that[k]; | ||
}); | ||
} | ||
static create() { | ||
return new Proxy(new this(), schemaProxyHandler); | ||
var instance = new this(); | ||
instance.generateSchema(); | ||
return new Proxy(instance, schemaProxyHandler); | ||
} | ||
@@ -325,5 +389,5 @@ | ||
// Handle array of references (ex: { type: [MyObject] }) | ||
if (isArray(anInstance._schema[key].type) | ||
&& anInstance._schema[key].type.length > 0 | ||
&& isModel(anInstance._schema[key].type[0])) { | ||
if (isArray(anInstance._schema[key].type) && | ||
anInstance._schema[key].type.length > 0 && | ||
isModel(anInstance._schema[key].type[0])) { | ||
keys.push(key); | ||
@@ -377,3 +441,3 @@ } | ||
// Bulk load objects | ||
var p = type.loadMany({ '_id': { $in: keyIds } }) | ||
var p = type.loadMany({ '_id': { $in: keyIds } }, { populate: false }) | ||
.then(function(dereferences) { | ||
@@ -380,0 +444,0 @@ // Assign each dereferenced object to parent |
@@ -35,2 +35,8 @@ var _ = require('lodash'); | ||
var isSupportedType = function(t) { | ||
return (t === String || t === Number || t === Boolean || | ||
t === Buffer || t === Date || t === Array || | ||
isArray(t) || t === Object || (t.extendsDocument && t.extendsDocument())); | ||
}; | ||
var isType = function(value, type) { | ||
@@ -105,4 +111,5 @@ if (type === String) { | ||
exports.isModel = isModel; | ||
exports.isSupportedType = isSupportedType; | ||
exports.isType = isType; | ||
exports.isValidType = isValidType; | ||
exports.isInChoices = isInChoices; |
{ | ||
"name" : "camo", | ||
"version" : "0.0.1", | ||
"description" : "A lightweight ES6 ODM for NoSQL databases.", | ||
"author" : "Scott Robinson", | ||
"version" : "0.1.1", | ||
"description" : "A lightweight ES6 ODM for Mongo-like databases.", | ||
"author": { | ||
"name": "Scott Robinson", | ||
"email": "s.w.robinson@gmail.com" | ||
}, | ||
"keywords" : [ | ||
"es6", | ||
"odm", | ||
"mongodb", | ||
"nedb", | ||
"nosql", | ||
"document", | ||
"model", | ||
"schema", | ||
"database", | ||
"data", | ||
"datastore", | ||
"query", | ||
"db" | ||
], | ||
"homepage": "https://github.com/scottwrobinson/camo", | ||
"repository": { | ||
"type": "git", | ||
"url": "git@github.com:scottwrobinson/camo.git" | ||
}, | ||
"license": "MIT", | ||
"scripts": { | ||
@@ -16,5 +40,7 @@ "test": "mocha --harmony-proxies" | ||
}, | ||
"optionalDependencies": { | ||
"mongodb": "2.0.33", | ||
"nedb": "1.1.2" | ||
}, | ||
"devDependencies": { | ||
"mongodb": "2.0.33", | ||
"nedb": "1.1.2", | ||
"chai": "3.0.0", | ||
@@ -25,4 +51,5 @@ "mocha": "2.2.5" | ||
"node": true, | ||
"mocha": true, | ||
"esnext": true | ||
} | ||
} |
@@ -98,2 +98,32 @@ "use strict"; | ||
describe('#count()', function() { | ||
it('should return 0 objects from the collection', function(done) { | ||
var data1 = getData1(); | ||
var data2 = getData2(); | ||
Promise.all([data1.save(), data2.save()]).then(function(datas) { | ||
validateId(datas[0]); | ||
validateId(datas[1]); | ||
return Data.count({ number: 3 }); | ||
}).then(function(count) { | ||
expect(count).to.be.equal(0); | ||
}).then(done, done); | ||
}); | ||
it('should return 2 matching objects from the collection', function(done) { | ||
var data1 = getData1(); | ||
var data2 = getData2(); | ||
Promise.all([data1.save(), data2.save()]).then(function(datas) { | ||
validateId(datas[0]); | ||
validateId(datas[1]); | ||
return Data.count({}); | ||
}).then(function(count) { | ||
expect(count).to.be.equal(2); | ||
}).then(done, done); | ||
}); | ||
}); | ||
describe('#delete()', function() { | ||
@@ -100,0 +130,0 @@ it('should remove instance from the collection', function(done) { |
@@ -46,3 +46,3 @@ "use strict"; | ||
super('referencee1'); | ||
this.schema({ str: { type: String } }); | ||
this.str = String; | ||
} | ||
@@ -54,3 +54,4 @@ } | ||
super('referencer1'); | ||
this.schema({ ref: { type: ReferenceeModel }, num: { type: Number } }); | ||
this.ref = ReferenceeModel; | ||
this.num = { type: Number }; | ||
} | ||
@@ -90,3 +91,4 @@ } | ||
super('referencer2'); | ||
this.schema({ refs: { type: [ReferenceeModel] }, num: { type: Number } }); | ||
this.refs = [ReferenceeModel]; | ||
this.num = Number; | ||
} | ||
@@ -96,3 +98,2 @@ } | ||
var data = ReferencerModel.create(); | ||
data.refs = []; | ||
data.refs.push(ReferenceeModel.create()); | ||
@@ -124,2 +125,63 @@ data.refs.push(ReferenceeModel.create()); | ||
it('should allow circular references', function(done) { | ||
class Employee extends Document { | ||
constructor() { | ||
super('employee'); | ||
this.name = String; | ||
this.boss = Boss; | ||
} | ||
} | ||
class Boss extends Document { | ||
constructor() { | ||
super('boss'); | ||
this.salary = Number; | ||
this.employees = [Employee]; | ||
} | ||
} | ||
var employee = Employee.create(); | ||
employee.name = 'Scott'; | ||
var boss = Boss.create(); | ||
boss.salary = 10000000; | ||
employee.boss = boss; | ||
boss.save().then(function(b) { | ||
validateId(b); | ||
return employee.save(); | ||
}).then(function(e) { | ||
validateId(e); | ||
validateId(e.boss); | ||
boss.employees.push(employee); | ||
return boss.save(); | ||
}).then(function(b) { | ||
validateId(b); | ||
validateId(b.employees[0]); | ||
validateId(b.employees[0].boss); | ||
return Boss.loadOne({ salary: 10000000 }); | ||
}).then(function(b) { | ||
// If we had an issue with an infinite loop | ||
// of loading circular dependencies then the | ||
// test probably would have crashed by now, | ||
// so we're good. | ||
validateId(b); | ||
// Validate that boss employee ref was loaded | ||
validateId(b.employees[0]); | ||
// .loadOne should have only loaded 1 level | ||
// of references, so the boss's reference | ||
// to the employee is still the ID. | ||
expect(b.employees[0].boss).to.be.a('string'); | ||
}).then(done, done); | ||
}); | ||
it('should allow string types', function(done) { | ||
@@ -129,3 +191,3 @@ | ||
constructor() { | ||
super('data'); | ||
super('strings'); | ||
this.schema({ str: { type: String } }); | ||
@@ -148,3 +210,3 @@ } | ||
constructor() { | ||
super('data'); | ||
super('numbers1'); | ||
this.schema({ num: { type: Number } }); | ||
@@ -167,3 +229,3 @@ } | ||
constructor() { | ||
super('data'); | ||
super('booleans'); | ||
this.schema({ bool: { type: Boolean } }); | ||
@@ -186,3 +248,3 @@ } | ||
constructor() { | ||
super('data'); | ||
super('dates'); | ||
this.schema({ date: { type: Date } }); | ||
@@ -206,3 +268,3 @@ } | ||
constructor() { | ||
super('data'); | ||
super('objects'); | ||
this.schema({ obj: { type: Object } }); | ||
@@ -226,3 +288,3 @@ } | ||
constructor() { | ||
super('data'); | ||
super('buffers'); | ||
this.schema({ buf: { type: Buffer } }); | ||
@@ -245,3 +307,3 @@ } | ||
constructor() { | ||
super('data'); | ||
super('arrays'); | ||
this.schema({ arr: { type: Array } }); | ||
@@ -267,3 +329,3 @@ } | ||
constructor() { | ||
super('data'); | ||
super('arrays'); | ||
this.schema({ arr: { type: [String] } }); | ||
@@ -289,3 +351,3 @@ } | ||
constructor() { | ||
super('data'); | ||
super('numbers2'); | ||
this.schema({ num: { type: Number } }); | ||
@@ -309,3 +371,3 @@ } | ||
constructor() { | ||
super('data'); | ||
super('arrays'); | ||
this.schema({ arr: { type: [String] } }); | ||
@@ -312,0 +374,0 @@ } |
Sorry, the diff of this file is not supported yet
spdx disjunction for an artifact's license information
Licensespdx disjunction for an artifact's license information
Found 1 instance in 1 package
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
spdx disjunction for an artifact's license information
Licensespdx disjunction for an artifact's license information
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
64115
2
1
1480
1
1
215
4
4