Socket
Socket
Sign inDemoInstall

stork-odm

Package Overview
Dependencies
103
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.1.7 to 0.1.8

test/binary_define_tests.js

6

lib/common.js

@@ -49,4 +49,6 @@ /*jslint node: true, nomen: true, white: true */

, isoStringPropertiesToDates: function(obj) {
Object.keys(obj).forEach(function(key) {
, isoStringPropertiesToDates: function(obj, properties) {
properties = properties || Object.keys(obj);
properties.forEach(function(key) {
if (obj[key].toString().match(dateRegex)) {

@@ -53,0 +55,0 @@ obj[key] = new Date(obj[key]);

@@ -66,2 +66,13 @@ /*jslint node: true, white: true */

definers.binary = function(name, options) {
if (name === undefined) {
throw new Error('binary definer requires a name');
}
this.properties[name] = {type: 'object'};
if (options) {
required(options, this.properties[name]);
}
this.binaryProperties.push(name);
};
definers.bool = function(name, options) {

@@ -68,0 +79,0 @@ if (name === undefined) {

@@ -24,2 +24,3 @@ /*jslint node: true, nomen: true, white: true */

, refProperties = schema.refProperties
, binaryProperties = schema.binaryProperties
, o = this

@@ -51,2 +52,31 @@ , result

binaryProperties.forEach(function(propertyName) {
var prop = o[propertyName]
, isBuffer = prop && prop instanceof Buffer
, isFiley = prop && prop.content instanceof Buffer && prop.type
;
if (prop === undefined) {
return;
}
result.errors = result.errors.filter(function (r) {
return !(r.property === propertyName && r.attribute === 'required');
});
result.errors = result.errors.filter(function (r) {
return !(r.property === propertyName && r.attribute === 'type');
});
if (!isBuffer && !isFiley) {
result.valid = false;
result.errors.push({
attribute: 'type',
property: propertyName,
expected: 'object',
message: 'must be of type Buffer or object like {type: [mime/type], content: [Buffer]}'
});
}
});
refProperties.forEach(function(propertyName) {

@@ -131,2 +161,18 @@ var prop = o[propertyName]

if (nproto._attachments) {
Object.keys(nproto._attachments).forEach(function (key) {
nproto[key] = {
type: nproto._attachments[key].content_type,
length: nproto._attachments[key].length,
digest: nproto._attachments[key].digest,
pipeFrom: function (db) {
var nanodb, att;
nanodb = common.makeNano(db, typeName + '#' + key);
att = nanodb.attachment.get(nproto._id, key);
return att.pipe.bind(att);
}
};
});
}
for (prop in nproto) {

@@ -133,0 +179,0 @@ if (typeof nproto[prop] === 'function') {

@@ -6,2 +6,3 @@ /*jslint node: true, nomen: true, white: true */

, util = require('utile')
, async = require('async')
;

@@ -98,3 +99,3 @@

to.sync = function(cb) {
to.sync = function(callback) {
var bsre = /\\/g

@@ -119,2 +120,3 @@ , sortKeyMap = function(o) {

}
, designDocName = '_design/' + typeName
;

@@ -135,3 +137,24 @@ Object.keys(schema.views).forEach(function(viewName) {

});
this.db.insert(doc, '_design/' + typeName, cb);
async.waterfall([
function(cb) {
/*jslint unparam: true*/
db.get(designDocName, function (e, entry) {
cb(null, entry);
});
/*jslint unparam: false*/
}
, function(entry) {
var params;
params = designDocName;
if (entry) {
/*jslint nomen: true*/
params = {
doc_name: params,
rev: entry._rev
};
/*jslint nomen: false*/
}
db.insert(doc, params, callback);
}
]);
};

@@ -138,0 +161,0 @@

@@ -6,2 +6,3 @@ /*jslint node: true, nomen: true, white: true, forin: true*/

, common = require('./common')
, uuid = require('node-uuid')
;

@@ -33,2 +34,6 @@

, childProperties = schema.childProperties
, binaryProperties = schema.binaryProperties
, insert
, attachments = []
, params
;

@@ -43,2 +48,31 @@

}
if (binaryProperties.length === 0) {
insert = db.insert.bind(db);
} else {
binaryProperties.forEach(function (prop) {
var value, attachment;
attachment = {name: prop};
value = state[prop];
if (value instanceof Buffer) {
attachment.data = value;
} else if (value) {
attachment.data = value.content;
attachment.content_type = value.type;
} else {
return;
}
state[prop] = prop;
attachments.push(attachment);
});
params = {
doc_name: state._id || uuid.v4()
};
if (state._rev) {
params.rev = state._rev;
}
insert = function(o, callback) {
db.multipart.insert(o, attachments, params, callback);
};
}
state = JSON.parse(JSON.stringify(state));

@@ -57,3 +91,3 @@ if (instance._rev) {

}
db.insert(state, function(err, result) {
insert(state, function(err, result) {
var childUpdates

@@ -97,3 +131,3 @@ ;

});
} else {
} else if(cb !== undefined) {
cb(err, instance);

@@ -100,0 +134,0 @@ }

@@ -6,4 +6,7 @@ /*jslint node: true, nomen: true, white: true */

, unseeable = require('./common').unseeable
, makeNano = require('./common').makeNano
, isoStringPropertiesToDates = require('./common').isoStringPropertiesToDates
, toForTypeNameAndSchema = require('./entity_to').toForTypeNameAndSchema
, newForTypeNameAndSchema = require('./entity_new').newForTypeNameAndSchema
, rehydrateForTypeNameAndSchema = require('./entity_new').rehydrateForTypeNameAndSchema
, fromForTypeNameAndSchema = require('./entity_from').fromForTypeNameAndSchema

@@ -19,2 +22,3 @@ ;

, refProperties: []
, binaryProperties: []
, views: {}

@@ -51,4 +55,44 @@ }

unseeable(entity, '$kind', typeName);
unseeable(entity, '$schema', schema);
return entity;
};
module.exports.from = function(db) {
var from;
db = makeNano(db, 'stork#from must be a couchdb url or nano db');
from = {
get: function (models, id, callback) {
var modelLookup = {};
models.forEach(function (model) {
modelLookup[model.$kind] = model;
});
db.get(id, function (e, record) {
var kind, schema, entity;
if (e) {
return callback(e);
}
isoStringPropertiesToDates(record);
try {
kind = record.kind;
schema = modelLookup[kind].$schema;
entity = rehydrateForTypeNameAndSchema(kind, schema)(id, record);
} catch (error) {
return callback(new Error('Could not create an entity for «' + id + '»'));
}
callback(null, entity);
});
}
};
unseeable(from, 'db', db);
return from;
};
{
"name": "stork-odm",
"version": "0.1.7",
"version": "0.1.8",
"description": "Stork provides a layer of document management over the CouchDB.",

@@ -26,10 +26,11 @@ "main": "./lib/stork.js",

"devDependencies": {
"nodeunit": "~0.8.3",
"nodeunit": "~0.9.0",
"should": "~3.3.0",
"autotest": "~0.2.6",
"nodemock": "~0.3.3",
"nodemock": "~0.3.4",
"grunt": "~0.4.2",
"grunt-jslint": "~1.1.2",
"grunt-contrib-nodeunit": "~0.3.0",
"grunt-contrib-watch": "^0.6.1"
"grunt-contrib-nodeunit": "~0.4.0",
"grunt-contrib-watch": "^0.6.1",
"memorystream": "^0.2.0"
},

@@ -44,4 +45,5 @@ "repository": {

"nano": "~5.7.0",
"async": "~0.7.0"
"async": "~0.9.0",
"node-uuid": "^1.4.1"
}
}

@@ -1,2 +0,3 @@

stork [![Build Status](https://travis-ci.org/curtissimo/stork.png?branch=master)](https://travis-ci.org/realistschuckle/stork) [![Dependency Status](https://gemnasium.com/curtissimo/stork.svg)](https://gemnasium.com/curtissimo/stork)
stork [![Build Status](https://travis-ci.org/curtissimo/stork.svg?branch=develop)](https://travis-ci.org/curtissimo/stork) [![Dependency Status](https://gemnasium.com/curtissimo/stork.svg)](https://gemnasium.com/curtissimo/stork)
=====

@@ -38,3 +39,3 @@ Stork provides a layer of document management over the CouchDB with multitenant

Comment = odm.devlier('comment', function() {
Comment = odm.deliver('comment', function() {
this.string('title', { required: true });

@@ -41,0 +42,0 @@ this.string('content');

@@ -94,1 +94,61 @@ var should = require('should')

};
exports['Entity#from has #get that handles binary properties'] = {
setUp: function(cb) {
this.entityName = util.randomString(10).replace('_', '');
this.Entity = odm.deliver(this.entityName, function() {
this.binary('b');
});
this.mockDb = function(id, err, result) {
var db = mock.mock('get')
.takes(id, empty)
.calls(1, [err, result]);
db.config = {url: true, db: true};
return db;
};
// Because node mock is stupid loud.
this.errorStream = console.error;
console.error = function() {};
cb();
}
, tearDown: function(cb) {
// Because node mock is stupid loud.
console.error = this.errorStream;
cb();
}
, 'by copying _attachments content_type and length information': function(t) {
var Entity = this.Entity
, value = {
_attachments: {
b: { content_type: 'image/png', length: 12345 }
}
}
, id = util.randomString(10).replace('_', '')
, db = this.mockDb(id, null, value)
;
Entity.from(db).get(id, function(err, result) {
result.b.type.should.be.equal('image/png');
result.b.length.should.be.equal(12345);
t.done();
});
}
, 'by having a pipeFrom method on the binary property': function(t) {
var Entity = this.Entity
, value = {
_attachments: {
b: { content_type: 'image/png', length: 12345 }
}
}
, id = util.randomString(10).replace('_', '')
, db = this.mockDb(id, null, value)
;
Entity.from(db).get(id, function(err, result) {
result.b.pipeFrom.should.be.Function;
t.done();
});
}
};

@@ -15,2 +15,5 @@ var should = require('should')

setUp: function(cb) {
var docName = '_design/entity'
, rev = 5
;
this.entity = function() {

@@ -21,4 +24,7 @@ return odm.deliver('entity', this.views);

var db = mock.mock('insert')
.takes(doc, '_design/entity', empty)
.takes(doc, {}, empty)
.calls(2, [err, result]);
db.mock('get')
.takes(docName, empty)
.calls(1, [err, {_id: docName, _rev: rev}]);
db.config = {url: true, db: true};

@@ -25,0 +31,0 @@ return db;

@@ -341,1 +341,68 @@ var should = require('should')

};
exports['instances that use #binary'] = {
setUp: function(cb) {
this.Person = odm.deliver('person', function() {
this.binary('photo');
});
this.mockDb = function(doc, att, params, mixin) {
var db = mock.mock('insert')
, callbackIndex = 3
, callbackArgs = [null]
, state = JSON.parse(JSON.stringify(doc))
;
db = db.takes(state, att, params, empty);
callbackArgs.push(mixin);
db = db.calls(callbackIndex, callbackArgs);
return {
multipart: db,
config: {url: true, db: true}
};
};
// Because node mock is stupid loud.
this.errorStream = console.error;
console.error = function() {};
cb();
}
, tearDown: function(cb) {
// Because node mock is stupid loud.
console.error = this.errorStream;
cb();
}
, 'calls #multipart#insert on save for Buffer binary property': function(t) {
var Person = this.Person
, buffer = new Buffer('123')
, inst = Person.new({photo: buffer, _id: 'moo'})
, state = {kind: 'person', photo: 'photo', _id: 'moo'}
, attachments = [{name: 'photo', data: buffer}]
, mixin = {_id: 'woot', _rev: 'another'}
, db = this.mockDb(state, attachments, {doc_name: 'moo'}, mixin)
;
inst.to(db).save(function(e, doc) {
should(e).not.be.ok;
t.done();
});
}
, 'calls #multipart#insert on save for object/Buffer binary property': function(t) {
var Person = this.Person
, buffer = new Buffer('123')
, binary = {content: new Buffer('123'), type: 'application/octet-stream'}
, inst = Person.new({photo: binary, _id: 'woot', _rev: 'another'})
, state = {kind: 'person', photo: 'photo'}
, attachments = [{name: 'photo', data: buffer, content_type: 'application/octet-stream'}]
, mixin = {_id: 'woot', _rev: 'another'}
, db = this.mockDb(state, attachments, {doc_name: 'woot', rev: 'another'}, mixin)
;
inst.to(db).save(function(e, doc) {
should(e).not.be.ok;
t.done();
});
}
};

@@ -5,2 +5,3 @@ var nano = require('nano')

, util = require('utile')
, MemoryStream = require('memorystream')
, odm = require('../lib/stork')

@@ -32,5 +33,14 @@ ;

dbms.db.destroy(db.config.db, function(err) {
dbms.db.create(db.config.db, function(err) {
cb(err);
});
if (err) {
console.log('could not destroy database', db.config.db);
// return cb(err);
}
setTimeout(function () {
dbms.db.create(db.config.db, function(err) {
if (err) {
console.log('could not create database', db.config.db);
}
cb(err);
});
}, 0);
});

@@ -62,2 +72,22 @@ }

, 'update entity design document': function(t) {
var entityName = 'defaulty'
, entity = odm.deliver(entityName)
;
entity.to(dburl).sync(function(e, answer1) {
if (e) {
return t.done(e);
}
entity.to(dburl).sync(function(e, answer2) {
if (e) {
return t.done(e);
}
answer1.id.should.equal(answer2.id);
answer1.rev.should.not.equal(answer2.rev);
t.done();
});
});
}
, 'create entity design document with sort': function(t) {

@@ -216,2 +246,5 @@ var entityName = 'sorty'

], function(err, results) {
if (err) {
return t.done(err);
}
var objs = results[results.length - 1]

@@ -255,2 +288,5 @@ ;

], function(err, results) {
if (err) {
return t.done(err);
}
async.series([

@@ -260,2 +296,5 @@ from.get.bind(from, results[1]._id)

], function(err, results) {
if (err) {
return t.done(err);
}
results[0].should.have.properties(nakeds[0]);

@@ -270,2 +309,43 @@ results[0].should.have.property('$schema', instances[0].$schema);

, 'get a previously saved object with stork#form': function(t) {
var entityName = 'sorty'
, Entity = odm.deliver(entityName, function() {
this.string('s', {required: true});
this.datetime('dt', {required: true});
})
, nakeds = [
{s: 'text', dt: new Date(2012, 6, 14), extra: 1}
, {s: 'txet', dt: new Date(2013, 9, 21), extra: -1}
]
, instances = [
Entity.new(nakeds[0])
, Entity.new(nakeds[1])
]
, from = odm.from(dburl)
;
async.series([
function(cb) { Entity.to(dburl).sync(cb); }
, function(cb) { instances[0].to(dburl).save(cb); }
, function(cb) { instances[1].to(dburl).save(cb); }
], function(err, results) {
if (err) {
return t.done(err);
}
async.series([
from.get.bind(from, [ Entity ], results[1]._id)
, from.get.bind(from, [ Entity ], results[2]._id)
], function(err, results) {
if (err) {
return t.done(err);
}
results[0].should.have.properties(nakeds[0]);
results[0].should.have.property('$schema', instances[0].$schema);
results[1].should.have.properties(nakeds[1]);
results[1].should.have.property('$schema', instances[1].$schema);
t.done();
});
});
}
, 'create entity design document with complex-key query': function(t) {

@@ -385,2 +465,5 @@ var entityName = util.randomString(10).replace('_', '')

], function(err, results) {
if (err) {
return t.done(err);
}
Entity.from(db).someView(function(err, results) {

@@ -496,2 +579,5 @@ results[0].should.have.properties(nakeds[1]);

], function(err, results) {
if (err) {
return t.done(err);
}
Entity.from(db).someView('key1', function(err, results) {

@@ -569,2 +655,110 @@ results[0].should.have.properties(nakeds[0]);

}
, 'save a binary property with a full specification': function(t) {
var Person = odm.deliver('person', function() {
this.binary('photo');
})
, person = Person.new({photo: {type: 'image/png', content: new Buffer('123')}})
;
person.to(dburl).save(function (e) {
if (e) {
return t.done(e);
}
db.attachment.get(person._id, 'photo', function (e, body) {
if (e) {
return t.done(e);
}
// should does not compare Buffer contents correctly
JSON.stringify(body).should.equal(JSON.stringify(new Buffer('123')));
db.get(person._id, function (e, p) {
if (e) {
return t.done(e);
}
p._attachments.photo.content_type.should.equal('image/png');
t.done();
});
});
});
}
, 'save a binary property with just the buffer': function(t) {
var Person = odm.deliver('person', function() {
this.binary('photo');
})
, person = Person.new({photo: new Buffer('abcdefg')})
;
person.to(dburl).save(function (e) {
if (e) {
return t.done(e);
}
db.attachment.get(person._id, 'photo', function (e, body) {
if (e) {
return t.done(e);
}
// should does not compare Buffer contents correctly
JSON.stringify(body).should.equal(JSON.stringify(new Buffer('abcdefg')));
db.get(person._id, function (e, p) {
if (e) {
return t.done(e);
}
p._attachments.photo.content_type.should.equal('application/octet-stream');
t.done();
});
});
});
}
, 'save an object with no binary value': function(t) {
var Person = odm.deliver('person', function() {
this.binary('photo');
})
, person = Person.new()
;
person.to(dburl).save(function (e) {
if (e) {
return t.done(e);
}
db.get(person._id, function (e, p) {
if (e) {
return t.done(e);
}
t.ok(p._attachments === undefined);
t.done();
});
});
}
, 'get a binary property with the pipeFrom method': function(t) {
var Person = odm.deliver('person', function() {
this.binary('photo');
})
, id = 'iAmLegend'
, person = Person.new({photo: new Buffer('abcdefg'), _id: id})
;
person.to(dburl).save(function (e) {
if (e) {
return t.done(e);
}
Person.from(dburl).get(id, function (e, per) {
if (e) {
return t.done(e);
}
var stream = new MemoryStream();
per.photo.pipeFrom(dburl)(stream);
stream.on('data', function(d) {
d.toString('utf8').should.be.equal('abcdefg');
});
stream.on('end', function () {
t.done();
});
stream.on('error', function(e) {
t.done(e);
});
});
});
}
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc