New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

waterline

Package Overview
Dependencies
Maintainers
1
Versions
165
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

waterline - npm Package Compare versions

Comparing version 0.4.7 to 0.5.0

test/adapter/save.test.js

111

adapter.js

@@ -126,3 +126,3 @@ var async = require('async');

}, function (err) {
if (err) throw err;
if (err) return cb(err);
async.forEach(_.keys(deprecatedAttributes), function (attrName, cb) {

@@ -143,5 +143,50 @@ adapterDef.removeAttribute(collectionName, attrName, deprecatedAttributes[attrName], cb);

//////////////////////////////////////////////////////////////////////
this.__save = function (collectionName, values, cb) {
// TODO: create or update model in adapter, using id to determine the model in question
// BUT don't include the save() method!
// TODO: use whatever the primary key is configured to, not just `id`
var pk = 'id';
var pkValue = values[pk];
// TODO: use updateOrCreate()
this.update(collectionName, pkValue, values, cb);
};
this.__destroy = function (collectionName, cb) {
// TODO: destroy in adapter, using id to determine the model in question
cb("destroy() NOT SUPPORTED YET!");
};
// Build a callback function which will decorate a model
// with a save() method
this.decorateModel = function (collectionName, cb) {
return function (err, set) {
if (_.isArray(set)) {
// Add save() method to set
_.each(set, function (model) {
if (!_.isObject(model)) return;
if (!model.save) model.save = _.bind(self.__save, self, collectionName, model);
if (!model.destroy) model.destroy = _.bind(self.__destroy, self, collectionName, model);
});
return cb(err,set);
}
else if (_.isObject(set)) {
// Add save() method to model
if (!set.save) set.save = _.bind(self.__save, self, collectionName, set);
if (!set.destroy) set.destroy = _.bind(self.__destroy, self, collectionName, set);
return cb(err,set);
}
else return cb(err,set);
};
};
this.create = function(collectionName, values, cb) {
// Build enhanced callback fn
cb = this.decorateModel(collectionName, cb);
if(!adapterDef.create) return cb("No create() method defined in adapter!");
adapterDef.create(collectionName, values, cb);

@@ -152,2 +197,5 @@ };

this.findAll = function(collectionName, criteria, cb) {
// Build enhanced callback fn
cb = this.decorateModel(collectionName, cb);
if(!adapterDef.find) return cb("No find() method defined in adapter!");

@@ -160,2 +208,3 @@ criteria = normalize.criteria(criteria);

this.find = function(collectionName, criteria, cb) {
// If no criteria specified AT ALL, use first model

@@ -165,4 +214,4 @@ if (!criteria) criteria = {limit: 1};

this.findAll(collectionName, criteria, function (err, models) {
if (!models) return cb();
if (models.length < 1) return cb();
if (!models) return cb(err);
if (models.length < 1) return cb(err);
else if (models.length > 1) return cb("More than one "+collectionName+" returned!");

@@ -174,2 +223,5 @@ else return cb(null,models[0]);

this.count = function(collectionName, criteria, cb) {
// Build enhanced callback fn
cb = this.decorateModel(collectionName, cb);
var self = this;

@@ -187,2 +239,5 @@ criteria = normalize.criteria(criteria);

this.update = function(collectionName, criteria, values, cb) {
// Build enhanced callback fn
cb = this.decorateModel(collectionName, cb);
if(!adapterDef.update) return cb("No update() method defined in adapter!");

@@ -195,2 +250,5 @@ criteria = normalize.criteria(criteria);

this.destroy = function(collectionName, criteria, cb) {
// Build enhanced callback fn
cb = this.decorateModel(collectionName, cb);
if(!adapterDef.destroy) return cb("No destroy() method defined in adapter!");

@@ -212,2 +270,5 @@ criteria = normalize.criteria(criteria);

if(adapterDef.findOrCreate) {
// Build enhanced callback fn
cb = this.decorateModel(collectionName, cb);
adapterDef.findOrCreate(collectionName, criteria, values, cb);

@@ -240,6 +301,11 @@ }

this.createEach = function (collectionName, valuesList, cb) {
var my = this;
var self = this;
// Custom user adapter behavior
if (adapterDef.createEach) adapterDef.createEach.apply(this,arguments);
if (adapterDef.createEach) {
// Build enhanced callback fn
cb = this.decorateModel(collectionName, cb);
adapterDef.createEach(collectionName, valuesList, cb);
}

@@ -249,5 +315,5 @@ // Default behavior

// Create transaction name based on collection
my.transaction(collectionName+'.waterline.default.createEach', function (err,done) {
self.transaction(collectionName+'.waterline.default.createEach', function (err,done) {
async.forEach(valuesList, function (values,cb) {
my.create(collectionName, values, cb);
self.create(collectionName, values, cb);
}, done);

@@ -258,7 +324,12 @@ },cb);

// If an optimized findOrCreateEach exists, use it, otherwise use an asynchronous loop with create()
this.findOrCreateEach = function (collectionName, valuesList, cb) {
var my = this;
this.findOrCreateEach = function (collectionName, attributesToCheck, valuesList, cb) {
var self = this;
// Custom user adapter behavior
if (adapterDef.findOrCreateEach) adapterDef.findOrCreateEach(collectionName,valuesList,cb);
if (adapterDef.findOrCreateEach) {
// Build enhanced callback fn
cb = this.decorateModel(collectionName, cb);
adapterDef.findOrCreateEach(collectionName, attributesToCheck, valuesList, cb);
}

@@ -268,5 +339,13 @@ // Default behavior

// Create transaction name based on collection
my.transaction(collectionName+'.waterline.default.createEach', function (err,done) {
self.transaction(collectionName+'.waterline.default.findOrCreateEach', function (err,done) {
async.forEach(valuesList, function (values,cb) {
my.findOrCreate(collectionName, values, null, cb);
// Check that each of the criteria keys match:
// build a criteria query
var criteria = {};
_.each(attributesToCheck, function (attrName) {
criteria[attrName] = values[attrName];
});
return self.findOrCreate(collectionName, criteria, values, cb);
}, done);

@@ -294,3 +373,3 @@ },cb);

if (adapterDef.transaction) return adapterDef.transaction(transactionName, atomicLogic, afterUnlock);
else if (!adapterDef.commitLog) throw new Error("Cannot process transaction. Commit log disabled in adapter, and no custom transaction logic is defined.");
else if (!adapterDef.commitLog) return afterUnlock("Cannot process transaction. Commit log disabled in adapter, and no custom transaction logic is defined.");

@@ -309,3 +388,3 @@ // Generate unique lock

console.error("But the transactionCollection is: ",this.transactionCollection);
throw new Error("Transaction collection not defined!");
return afterUnlock("Transaction collection not defined!");
}

@@ -432,3 +511,3 @@ this.transactionCollection.create(newLock, function afterCreatingTransaction(err, newLock) {

this.drop(collection.identity, function afterDrop (err, data) {
if(err) cb(err);
if(err) return cb(err);
else self.define(collection.identity, collection, cb);

@@ -435,0 +514,0 @@ });

78

collection.js

@@ -80,4 +80,4 @@ //////////////////////////////////////////////////////////////////////

var usage = _.str.capitalize(this.identity) + '.' + actualMethodName + '(someValue,[options],callback)';
if(_.isUndefined(value)) usageError('No value specified!', usage);
if(options.where) usageError('Cannot specify `where` option in a dynamic ' + method + '*() query!', usage);
if(_.isUndefined(value)) return usageError('No value specified!', usage, cb);
if(options.where) return usageError('Cannot specify `where` option in a dynamic ' + method + '*() query!', usage, cb);

@@ -263,3 +263,3 @@

if(_.isFunction(criteria) || _.isFunction(options)) {
return usageError('Invalid options specified!', usage);
return usageError('Invalid options specified!', usage, cb);
}

@@ -294,3 +294,3 @@

return this.find(criteria, options, cb);
} else usageError('Criteria must be string or object!', usage);
} else return usageError('Criteria must be string or object!', usage, cb);
};

@@ -302,3 +302,3 @@

return this.findAll(criteria, options, cb);
} else usageError('Criteria must be string or object!', usage);
} else return usageError('Criteria must be string or object!', usage, cb);
};

@@ -314,3 +314,3 @@

return this.findAll(criteria, options, cb);
} else usageError('Criteria must be a string or object!', usage);
} else return usageError('Criteria must be a string or object!', usage, cb);
throw new notImplementedError();

@@ -327,3 +327,3 @@ };

return this.findAll(criteria, options, cb);
} else usageError('Criteria must be a string or object!', usage);
} else return usageError('Criteria must be a string or object!', usage, cb);
throw new notImplementedError();

@@ -340,3 +340,3 @@ };

return this.findAll(criteria, options, cb);
} else usageError('Criteria must be a string or object!', usage);
} else return usageError('Criteria must be a string or object!', usage, cb);
throw new notImplementedError();

@@ -369,5 +369,5 @@ };

criteria = _.extend({}, criteria, options);
} else usageError('Invalid options specified!', usage);
} else return usageError('Invalid options specified!', usage, cb);
if(!_.isFunction(cb)) usageError('Invalid callback specified!', usage);
if(!_.isFunction(cb)) return usageError('Invalid callback specified!', usage, cb);

@@ -386,4 +386,4 @@ return adapter.count(this.identity, criteria, cb);

var usage = _.str.capitalize(this.identity) + '.update(criteria, newValues, callback)';
if(!newValues) usageError('No updated values specified!', usage);
if(!_.isFunction(cb)) usageError('Invalid callback specified!', usage);
if(!newValues) return usageError('No updated values specified!', usage, cb);
if(!_.isFunction(cb)) return usageError('Invalid callback specified!', usage, cb);

@@ -444,9 +444,12 @@ // TODO: Validate constraints using Anchor

}
if (_.isArray(criteria)) {
return this.findOrCreateEach(criteria,cb);
// This is actually an implicit call to findOrCreateEach
if (_.isArray(criteria) && _.isArray(values)) {
return this.findOrCreateEach(criteria, values, cb);
}
var usage = _.str.capitalize(this.identity) + '.findOrCreate(criteria, values, callback)';
if(!criteria) usageError('No criteria option specified!', usage);
if(!_.isFunction(cb)) usageError('Invalid callback specified!', usage);
var usage = _.str.capitalize(this.identity) + '.findOrCreate([criteria], values, callback)';
if(!criteria) return usageError('No criteria option specified!', usage, cb);
if(!_.isFunction(cb)) return usageError('Invalid callback specified!', usage, cb);
return adapter.findOrCreate(this.identity, criteria, values, cb);

@@ -460,6 +463,7 @@ };

this.createEach = function(valuesList, cb) {
var usage = _.str.capitalize(this.identity) + '.createEach(valuesList, callback)';
if(!valuesList) usageError('No valuesList specified!', usage);
if(!_.isArray(valuesList)) usageError('Invalid valuesList specified (should be an array!)', usage);
if(!_.isFunction(cb)) usageError('Invalid callback specified!', usage);
if(!valuesList) return usageError('No valuesList specified!', usage, cb);
if(!_.isArray(valuesList)) return usageError('Invalid valuesList specified (should be an array!)', usage, cb);
if(!_.isFunction(cb)) return usageError('Invalid callback specified!', usage, cb);
adapter.createEach(this.identity, valuesList, cb);

@@ -470,8 +474,14 @@ };

// For any that don't exist, create them
this.findOrCreateEach = function(valuesList, cb) {
var usage = _.str.capitalize(this.identity) + '.findOrCreateEach(valuesList, callback)';
if(!valuesList) usageError('No valuesList specified!', usage);
if(!_.isArray(valuesList)) usageError('Invalid valuesList specified (should be an array!)', usage);
if(!_.isFunction(cb)) usageError('Invalid callback specified!', usage);
adapter.findOrCreateEach(this.identity, valuesList, cb);
this.findOrCreateEach = function(attributesToCheck, valuesList, cb) {
if(_.isFunction(valuesList)) {
cb = valuesList;
valuesList = null;
}
var usage = _.str.capitalize(this.identity) + '.findOrCreateEach(attributesToCheck, valuesList, callback)';
if(!_.isFunction(cb)) return usageError('Invalid callback specified!', usage, cb);
if(!attributesToCheck) return usageError('No attributesToCheck specified!', usage, cb);
if(!_.isArray(attributesToCheck)) return usageError('No attributesToCheck specified!', usage, cb);
if(!valuesList) return usageError('No valuesList specified!', usage, cb);
if(!_.isArray(valuesList)) return usageError('Invalid valuesList specified (should be an array!)', usage, cb);
adapter.findOrCreateEach(this.identity, attributesToCheck, valuesList, cb);
};

@@ -485,7 +495,7 @@

if(!atomicLogic) {
return usageError('Missing required parameter: atomicLogicFunction!', usage);
return usageError('Missing required parameter: atomicLogicFunction!', usage, cb);
} else if(!_.isFunction(atomicLogic)) {
return usageError('Invalid atomicLogicFunction! Not a function: ' + atomicLogic, usage);
return usageError('Invalid atomicLogicFunction! Not a function: ' + atomicLogic, usage, cb);
} else if(afterUnlock && !_.isFunction(afterUnlock)) {
return usageError('Invalid afterUnlockFunction! Not a function: ' + afterUnlock, usage);
return usageError('Invalid afterUnlockFunction! Not a function: ' + afterUnlock, usage, cb);
} else return adapter.transaction(this.identity + '.' + transactionName, atomicLogic, afterUnlock);

@@ -554,5 +564,9 @@ };

function usageError(err, usage) {
console.error("\n\n");
throw new Error(err + '\n==============================================\nProper usage :: \n' + usage + '\n==============================================\n');
function usageError(err, usage, cb) {
var message = err + '\n==============================================\nProper usage :: \n' + usage + '\n==============================================\n';
if (cb) return cb(message);
else {
console.error("\n\n");
throw new Error(message);
}
}

@@ -559,0 +573,0 @@

// Global adapter defaults
module.exports = {
// By default assume the app path is the current directory
appPath: __dirname,
// ms to wait before warning that a tranaction is taking too long

@@ -5,0 +8,0 @@ // TODO: move this logic as a configuration option into the actual transaction collection

{
"name": "waterline",
"version": "0.4.7",
"version": "0.5.0",
"description": "Adaptable data access layer for Node.js",

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

@@ -93,5 +93,12 @@ /**

it ('should not fail',function (done) {
User.findOrCreateEach(testData,done);
User.findOrCreateEach(['name','type'], testData, done);
});
it ('SHOULD fail when only one arg is specified',function (done) {
User.findOrCreateEach(testData, function (err) {
if (err) return done();
else done("Should have failed, since no attributesToCheck arg was specified!");
});
});
it ('should have saved the proper values (with auto-increment values)',function (done) {

@@ -98,0 +105,0 @@ User.findAll({type: testName},function (err,users) {

@@ -14,2 +14,3 @@ // Dependencies

var util = require('sails-util');
var fs = require('fs-extra');

@@ -28,2 +29,5 @@ /**

// Trim slashes off of app path
waterlineConfig.appPath = _.str.rtrim(waterlineConfig.appPath,'/');
// Only tear down waterline once

@@ -134,9 +138,18 @@ // (if teardown() is called explicitly, don't tear it down when the process exits)

function requireAdapter(adapterName, collectionName) {
try {
log('Loading module ' + adapterName + "...");
return require(adapterName)();
// First, try to stat the adapter module
var modulePath = waterlineConfig.appPath+'/node_modules/'+adapterName;
var exists = fs.existsSync(modulePath);
log.verbose('Loading module ' + adapterName + "...");
// If it exists, require it.
if (exists) return require(modulePath)();
else {
var err = "Unknown adapter ("+adapterName+") in collection (" + collectionName +")";
log.error(err);
log.error("Try running: npm install "+adapterName);
log.error("To save the adapter as a permanent dependency, run: npm install "+adapterName+" --save");
process.exit(1);
}
catch (e) {
throw new Error("Unknown adapter ("+adapterName+") in collection (" + collectionName +")");
}
}

@@ -143,0 +156,0 @@

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