Socket
Socket
Sign inDemoInstall

cascading-relations

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cascading-relations - npm Package Compare versions

Comparing version 0.5.0 to 0.6.0

541

index.js

@@ -9,71 +9,73 @@ var Q, dot, mongoose;

module.exports = {
plugin: function(schema, options) {
schema.virtual('_related').get(function() {
return this.$__.related;
}).set(function(val) {
return this.$__.related = val;
});
schema.set('toObject', {
virtuals: true
});
schema.set('toJSON', {
virtuals: true
});
schema.post('init', function(next) {
var info, orig, path, val, _ref;
if (this.$__.populated != null) {
this._related = {};
_ref = this.$__.populated;
for (path in _ref) {
info = _ref[path];
val = info.value;
orig = dot.get(this, path);
dot.set(this, path, val);
dot.set(this._related, path, orig);
module.exports = function(schema, options) {
schema.virtual('_related').get(function() {
return this.$__.related;
}).set(function(val) {
return this.$__.related = val;
});
schema.set('toObject', {
virtuals: true
});
schema.set('toJSON', {
virtuals: true
});
schema.post('init', function(next) {
var info, orig, path, val, _ref;
if (this.$__.populated != null) {
this._related = {};
_ref = this.$__.populated;
for (path in _ref) {
info = _ref[path];
val = info.value;
orig = dot.get(this, path);
dot.set(this, path, val);
dot.set(this._related, path, orig);
}
}
return true;
});
schema.methods.cascadeSave = function(callback, allow) {
if (allow == null) {
allow = null;
}
this.$__.cascadeSave = true;
this.$__.cascadeSaveLimitRelations = allow;
return this.save(callback);
};
schema.methods.$__saveRelation = function(path, val) {
var allowedRelation, deferred, key, newVal, promises,
_this = this;
deferred = Q.defer();
allowedRelation = function(rel) {
var allowed, _i, _len, _ref;
_ref = _this.$__.cascadeSaveLimitRelations;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
allowed = _ref[_i];
if (allowed.substr(0, rel.length) === rel) {
return true;
}
}
return true;
});
schema.methods.cascadeSave = function() {
this.$__.cascadeSave = true;
return this.save.apply(this, arguments);
return false;
};
schema.methods.$__saveRelation = function(path, val) {
var deferred, key, newVal, promises;
deferred = Q.defer();
promises = [];
if (this.schema.paths[path]) {
if (this.schema.paths[path].instance === 'ObjectID' && (this.schema.paths[path].options.ref != null)) {
promises.push(this.$__saveSingleRelationAtPath(path));
} else if (this.schema.paths[path].options.type instanceof Array && this.schema.paths[path].caster && this.schema.paths[path].caster.instance === 'ObjectID' && (this.schema.paths[path].caster.options.ref != null)) {
promises.push(this.$__saveMultiRelationAtPath(path));
}
} else if (typeof val === 'object') {
for (key in val) {
newVal = val[key];
promises.push(this.$__saveRelation(path + '.' + key, newVal));
}
if (this.$__.cascadeSaveLimitRelations && !allowedRelation(path)) {
deferred.resolve();
return deferred.promise;
}
promises = [];
if (this.schema.paths[path]) {
if (this.schema.paths[path].instance === 'ObjectID' && (this.schema.paths[path].options.ref != null)) {
promises.push(this.$__saveSingleRelationAtPath(path));
} else if (this.schema.paths[path].options.type instanceof Array && this.schema.paths[path].caster && this.schema.paths[path].caster.instance === 'ObjectID' && (this.schema.paths[path].caster.options.ref != null)) {
promises.push(this.$__saveMultiRelationAtPath(path));
}
if (!promises.length) {
deferred.resolve();
} else {
Q.all(promises).then(function() {
return deferred.resolve();
}, function(err) {
return deferred.reject(err);
});
} else if (typeof val === 'object') {
for (key in val) {
newVal = val[key];
promises.push(this.$__saveRelation(path + '.' + key, newVal));
}
return deferred.promise;
};
schema.methods.$__saveSingleRelationAtPath = function(path) {
var data, deferred, ref, through,
_this = this;
deferred = Q.defer();
ref = this.schema.paths[path].options.ref;
through = this.schema.paths[path].options.$through;
data = dot.get(this.get('_related'), path);
this.$__saveRelatedDoc(path, data, ref, through).then(function(res) {
_this.$__.populateRelations[path] = res;
_this.set(path, res._id);
}
if (!promises.length) {
deferred.resolve();
} else {
Q.all(promises).then(function() {
return deferred.resolve();

@@ -83,95 +85,103 @@ }, function(err) {

});
return deferred.promise;
};
schema.methods.$__saveMultiRelationAtPath = function(path) {
var data, deferred, doc, promises, ref, through, _i, _len,
_this = this;
deferred = Q.defer();
ref = this.schema.paths[path].caster.options.ref;
through = this.schema.paths[path].caster.options.through;
data = dot.get(this.get('_related'), path);
promises = [];
if (!(data instanceof Array)) {
deferred.reject(new Error("Data for multi relation must be an array!"));
} else {
for (_i = 0, _len = data.length; _i < _len; _i++) {
doc = data[_i];
promises.push(this.$__saveRelatedDoc(path, doc, ref, through));
}
Q.all(promises).then(function(results) {
var result, _j, _len1;
_this.$__.populateRelations[path] = {};
for (_j = 0, _len1 = results.length; _j < _len1; _j++) {
result = results[_j];
_this.$__.populateRelations[path][result._id.toString()] = result;
}
return deferred.resolve();
});
}
return deferred.promise;
};
schema.methods.$__saveSingleRelationAtPath = function(path) {
var data, deferred, ref, through,
_this = this;
deferred = Q.defer();
ref = this.schema.paths[path].options.ref;
through = this.schema.paths[path].options.$through;
data = dot.get(this.get('_related'), path);
this.$__saveRelatedDoc(path, data, ref, through).then(function(res) {
_this.$__.populateRelations[path] = res;
_this.set(path, res._id);
return deferred.resolve();
}, function(err) {
return deferred.reject(err);
});
return deferred.promise;
};
schema.methods.$__saveMultiRelationAtPath = function(path) {
var data, deferred, doc, promises, ref, through, _i, _len,
_this = this;
deferred = Q.defer();
ref = this.schema.paths[path].caster.options.ref;
through = this.schema.paths[path].caster.options.through;
data = dot.get(this.get('_related'), path);
promises = [];
if (!(data instanceof Array)) {
deferred.reject(new Error("Data for multi relation must be an array!"));
} else {
for (_i = 0, _len = data.length; _i < _len; _i++) {
doc = data[_i];
promises.push(this.$__saveRelatedDoc(path, doc, ref, through));
}
return deferred.promise;
};
schema.methods.$__saveRelatedDoc = function(path, data, ref, through) {
var d, deferred, isArray, method, modelClass, newMod, orig,
_this = this;
deferred = Q.defer();
if (through) {
d = dot.get(data, through);
if (d instanceof Array) {
if (d.indexOf(this._id) < 0) {
d.push(this._id);
dot.set(data, through, d);
}
} else {
dot.set(data, through, this._id);
Q.all(promises).then(function(results) {
var result, _j, _len1;
_this.$__.populateRelations[path] = {};
for (_j = 0, _len1 = results.length; _j < _len1; _j++) {
result = results[_j];
_this.$__.populateRelations[path][result._id.toString()] = result;
}
return deferred.resolve();
});
}
return deferred.promise;
};
schema.methods.$__saveRelatedDoc = function(path, data, ref, through) {
var allowed, d, deferred, isArray, method, modelClass, newArr, newMod, orig, _i, _len, _ref,
_this = this;
deferred = Q.defer();
if (through) {
d = dot.get(data, through);
if (d instanceof Array) {
if (d.indexOf(this._id) < 0) {
d.push(this._id);
dot.set(data, through, d);
}
} else {
dot.set(data, through, this._id);
}
modelClass = mongoose.model(ref);
orig = this.get(path);
if (orig instanceof Array) {
isArray = true;
}
modelClass = mongoose.model(ref);
orig = this.get(path);
if (orig instanceof Array) {
isArray = true;
} else {
isArray = false;
}
if (data._id) {
if (isArray) {
orig.push(data._id);
this.set(path, orig);
} else {
isArray = false;
this.set(path, data._id);
}
if (data._id) {
if (isArray) {
orig.push(data._id);
this.set(path, orig);
} else {
this.set(path, data._id);
modelClass.findById(data._id, function(err, res) {
var allowed, method, newArr, _i, _len, _ref;
if (err) {
return deferred.reject(err);
} else if (!res) {
return deferred.reject(new Error('Could not find ref {ref} with ID ', +data._id.toString()));
}
modelClass.findById(data._id, function(err, res) {
var method;
if (err) {
return deferred.reject(err);
} else if (!res) {
return deferred.reject(new Error('Could not find ref {ref} with ID ', +data._id.toString()));
delete data._id;
res.set(data);
newArr = null;
if ((res.cascadeSave != null) && typeof res.cascadeSave === 'function') {
method = 'cascadeSave';
if (_this.$__.cascadeSaveLimitRelations) {
newArr = [];
_ref = _this.$__.cascadeSaveLimitRelations;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
allowed = _ref[_i];
if (allowed.substr(0, path.length + 1) === (path + '.')) {
newArr.push(allowed.substr(path.length + 1));
}
}
}
delete data._id;
res.set(data);
if ((res.cascadeSave != null) && typeof res.cascadeSave === 'function') {
method = 'cascadeSave';
} else {
method = 'save';
}
return res[method](function(err, res) {
if (err) {
return deferred.reject(err);
}
return deferred.resolve(res);
});
});
} else {
newMod = new modelClass(data);
if (isArray) {
orig.push(newMod._id);
this.set(path, orig);
} else {
this.set(path, newMod._id);
}
if ((newMod.cascadeSave != null) && typeof newMod.cascadeSave === 'function') {
method = 'cascadeSave';
} else {
method = 'save';
}
newMod[method](function(err, res) {
return res[method](function(err, res) {
if (err) {

@@ -181,117 +191,146 @@ return deferred.reject(err);

return deferred.resolve(res);
});
}, newArr);
});
} else {
newMod = new modelClass(data);
if (isArray) {
orig.push(newMod._id);
this.set(path, orig);
} else {
this.set(path, newMod._id);
}
return deferred.promise;
};
schema.pre('save', function(next) {
var path, promises, val, _ref;
if (this.$__.cascadeSave) {
this.$__.populateRelations = {};
if (this._related != null) {
promises = [];
_ref = this._related;
for (path in _ref) {
val = _ref[path];
promises.push(this.$__saveRelation(path, val));
if ((newMod.cascadeSave != null) && typeof newMod.cascadeSave === 'function') {
method = 'cascadeSave';
if (this.$__.cascadeSaveLimitRelations) {
newArr = [];
_ref = this.$__.cascadeSaveLimitRelations;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
allowed = _ref[_i];
if (allowed.substr(0, path.length + 1) === (path + '.')) {
newArr.push(allowed.substr(path.length + 1));
}
}
return Q.all(promises).then(function() {
return next();
}, function(err) {
return next(err);
});
} else {
return next();
}
} else {
method = 'save';
}
newMod[method](function(err, res) {
if (err) {
return deferred.reject(err);
}
return deferred.resolve(res);
}, newArr);
}
return deferred.promise;
};
schema.pre('save', function(next) {
var path, promises, val, _ref;
if (this.$__.cascadeSave) {
this.$__.populateRelations = {};
if (this._related != null) {
promises = [];
_ref = this._related;
for (path in _ref) {
val = _ref[path];
promises.push(this.$__saveRelation(path, val));
}
return Q.all(promises).then(function() {
return next();
}, function(err) {
return next(err);
});
} else {
return next();
}
});
schema.post('save', function(doc) {
var curVal, id, newRelated, newVal, path, rels, _i, _len, _ref;
if (this.$__.cascadeSave) {
newRelated = {};
_ref = doc.$__.populateRelations;
for (path in _ref) {
rels = _ref[path];
curVal = this.get(path);
if (curVal instanceof Array) {
newVal = [];
for (_i = 0, _len = curVal.length; _i < _len; _i++) {
id = curVal[_i];
if (rels[id.toString()] != null) {
newVal.push(rels[id.toString()]);
} else {
newVal.push(id);
}
}
dot.set(newRelated, path, newVal);
} else {
if (rels._id === curVal) {
dot.set(newRelated, path, rels);
} else {
return next();
}
});
schema.post('save', function(doc) {
var curVal, id, newRelated, newVal, path, rels, _i, _len, _ref;
if (this.$__.cascadeSave) {
newRelated = {};
_ref = doc.$__.populateRelations;
for (path in _ref) {
rels = _ref[path];
curVal = this.get(path);
if (curVal instanceof Array) {
newVal = [];
for (_i = 0, _len = curVal.length; _i < _len; _i++) {
id = curVal[_i];
if (rels[id.toString()] != null) {
newVal.push(rels[id.toString()]);
} else {
dot.set(newRelated, path, curVal);
newVal.push(id);
}
}
dot.set(newRelated, path, newVal);
} else {
if (rels._id === curVal) {
dot.set(newRelated, path, rels);
} else {
dot.set(newRelated, path, curVal);
}
}
this.set('_related', newRelated);
this.$__.cascadeSave = false;
}
return true;
});
schema.methods.$__handleDeletion = function(path) {
if (this.schema.paths[path].instance === 'ObjectID' && (this.schema.paths[path].options.ref != null)) {
return this.$__handleDeletionAtSingleRelationPath(path);
} else if (this.schema.paths[path].options.type instanceof Array && this.schema.paths[path].caster && this.schema.paths[path].caster.instance === 'ObjectID' && (this.schema.paths[path].caster.options.ref != null)) {
return this.$__handleDeletionAtMultiRelationPath(path);
}
};
schema.methods.$__handleDeletionAtSingleRelationPath = function(path) {
var cascade, ref, through;
ref = this.schema.paths[path].options.ref;
cascade = this.schema.paths[path].options.$cascadeDelete;
through = this.schema.paths[path].options.$through;
return this.$__handleDeletionOfDoc(ref, this.get(path), cascade, through);
};
schema.methods.$__handleDeletionAtMultiRelationPath = function(path) {
var cascade, data, id, ref, through, _i, _len, _results;
ref = this.schema.paths[path].caster.options.ref;
cascade = this.schema.paths[path].caster.options.$cascadeDelete;
through = this.schema.paths[path].caster.options.$through;
data = this.get(path);
_results = [];
for (_i = 0, _len = data.length; _i < _len; _i++) {
id = data[_i];
_results.push(this.$__handleDeletionOfDoc(ref, id, cascade, through));
}
return _results;
};
schema.methods.$__handleDeletionOfDoc = function(ref, id, cascade, through) {
var modelClass;
modelClass = mongoose.model(ref);
if (cascade) {
return modelClass.findById(id, function(err, res) {
if (res) {
return res.remove();
}
});
} else if (through) {
return modelClass.findById(id, function(err, res) {
if (res) {
res.set(through, null);
return res.save();
}
});
}
};
return schema.post('remove', function(doc) {
var config, path, _ref, _results;
_ref = this.schema.paths;
_results = [];
for (path in _ref) {
config = _ref[path];
_results.push(this.$__handleDeletion(path));
}
return _results;
});
}
this.set('_related', newRelated);
this.$__.cascadeSave = false;
}
return true;
});
schema.methods.$__handleDeletion = function(path) {
if (this.schema.paths[path].instance === 'ObjectID' && (this.schema.paths[path].options.ref != null)) {
return this.$__handleDeletionAtSingleRelationPath(path);
} else if (this.schema.paths[path].options.type instanceof Array && this.schema.paths[path].caster && this.schema.paths[path].caster.instance === 'ObjectID' && (this.schema.paths[path].caster.options.ref != null)) {
return this.$__handleDeletionAtMultiRelationPath(path);
}
};
schema.methods.$__handleDeletionAtSingleRelationPath = function(path) {
var cascade, ref, through;
ref = this.schema.paths[path].options.ref;
cascade = this.schema.paths[path].options.$cascadeDelete;
through = this.schema.paths[path].options.$through;
return this.$__handleDeletionOfDoc(ref, this.get(path), cascade, through);
};
schema.methods.$__handleDeletionAtMultiRelationPath = function(path) {
var cascade, data, id, ref, through, _i, _len, _results;
ref = this.schema.paths[path].caster.options.ref;
cascade = this.schema.paths[path].caster.options.$cascadeDelete;
through = this.schema.paths[path].caster.options.$through;
data = this.get(path);
_results = [];
for (_i = 0, _len = data.length; _i < _len; _i++) {
id = data[_i];
_results.push(this.$__handleDeletionOfDoc(ref, id, cascade, through));
}
return _results;
};
schema.methods.$__handleDeletionOfDoc = function(ref, id, cascade, through) {
var modelClass;
modelClass = mongoose.model(ref);
if (cascade) {
return modelClass.findById(id, function(err, res) {
if (res) {
return res.remove();
}
});
} else if (through) {
return modelClass.findById(id, function(err, res) {
if (res) {
res.set(through, null);
return res.save();
}
});
}
};
return schema.post('remove', function(doc) {
var config, path, _ref, _results;
_ref = this.schema.paths;
_results = [];
for (path in _ref) {
config = _ref[path];
_results.push(this.$__handleDeletion(path));
}
return _results;
});
};
{
"name": "cascading-relations",
"version": "0.5.0",
"version": "0.6.0",
"description": "",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -65,7 +65,7 @@ var barClass, barSchema, bazClass, bazSchema, fooClass, fooSchema, mongoose, relations, should;

fooSchema.plugin(relations.plugin);
fooSchema.plugin(relations);
barSchema.plugin(relations.plugin);
barSchema.plugin(relations);
bazSchema.plugin(relations.plugin);
bazSchema.plugin(relations);

@@ -195,3 +195,3 @@ barClass = mongoose.model('Bar', barSchema);

});
return it('should do normal save without cascading', function(done) {
it('should do normal save without cascading', function(done) {
var foo;

@@ -211,2 +211,32 @@ foo = new fooClass({

});
return it('should do a save while limiting cascaded relations', function(done) {
var foo;
foo = new fooClass({
title: 'My Foo',
_related: {
_bar: {
title: 'My Bar',
_related: {
_baz: {
title: 'My Baz'
}
}
},
multi: {
_bar: {
title: 'My Bar 2',
_related: {
_baz: {
title: 'My Baz 2'
}
}
}
}
}
});
return foo.cascadeSave(function(err, res) {
should.not.exist(res._related._bar._baz);
return done();
}, ['_bar', 'multi._bar', 'multi._bar._baz']);
});
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc