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.0.5202 to 0.0.5204

augmentAttributes.js

277

adapter.js

@@ -54,31 +54,5 @@ var async = require('async');

// If id is not defined, add it
// TODO: Make this check for ANY primary key
if(this.config.defaultPK && !attributes.id) {
attributes.id = {
type: 'INTEGER',
autoIncrement: true,
'default': 'AUTO_INCREMENT',
constraints: {
unique: true,
primaryKey: true
}
};
}
// Marshal attributes to a standard format
attributes = require('./augmentAttributes')(attributes,this.config);
// If the adapter config allows it, and they aren't already specified,
// extend definition with updatedAt and createdAt
var now = {type: 'DATE', 'default': 'NOW'};
if(this.config.createdAt && !attributes.createdAt) attributes.createdAt = now;
if(this.config.updatedAt && !attributes.updatedAt) attributes.updatedAt = now;
// Convert string-defined attributes into fully defined objects
for(var attr in attributes) {
if(_.isString(attributes[attr])) {
attributes[attr] = {
type: attributes[attr]
};
}
}
// Verify that collection doesn't already exist

@@ -100,4 +74,66 @@ // and then define it and trigger callback

};
this.alter = function(collectionName, newAttrs, cb) {
adapter.alter ? adapter.alter(collectionName, newAttrs, cb) : cb();
this.alter = function(collectionName, attributes, cb) {
var self = this;
adapter.alter ? adapter.alter(collectionName, attributes, cb) : defaultAlter(cb);
// Default behavior
function defaultAlter(done) {
// Alter the schema
self.describe(collectionName, function afterDescribe (err, oldAttributes) {
if (err) return done(err);
// Keep track of previously undefined attributes
// for use when updating the actual data
var newAttributes = {};
// Iterate through each attribute in the new definition
_.each(attributes, function checkAttribute(attribute,attrName) {
// If the attribute doesn't exist, create it
if (!oldAttributes[attrName]) {
newAttributes[attrName] = attribute;
}
// If the old attribute is not exactly the same, or it doesn't exist, (re)create it
if ( !oldAttributes[attrName] || !_.isEqual(oldAttributes[attrName],attribute) ) {
oldAttributes[attrName] = attribute;
}
});
// Then alter the actual data as necessary
self.find(collectionName,null, function afterFind (err,data) {
if (err) return done(err);
// Update the data belonging to this attribute to reflect the new properties
// Realistically, this will mainly be about constraints, and primarily uniquness
// It'd be good if waterline could enforce all constraints at this time,
// but there's a trade-off with destroying people's data
// TODO: Figure this out
// For new columns, just use the default value if one exists (otherwise use null)
_.each(newAttributes, function checkAttribute(attribute,attrName) {
if (attribute.defaultValue) {
data[attrName] = attribute.defaultValue;
}
});
// Create deferred object
var $$ = new parley();
var $_self = $$(self);
// Dumbly drop the table and redefine it
$_self.drop(collectionName);
$_self.define(collectionName, attributes);
// Then dumbly add the data back in
$_self.createAll(collectionName,data);
$$(function(xcb) { done && done(); xcb(); })();
});
});
}
};

@@ -120,11 +156,13 @@

adapter.create ? adapter.create(collectionName, values, cb) : cb();
adapter.create(collectionName, values, cb);
// TODO: Return model instance Promise object for joins, etc.
};
this.find = function(collectionName, options, cb) {
this.find = function(collectionName, criteria, cb) {
if(!adapter.find) return cb("No find() method defined in adapter!");
options = normalizeCriteria(options);
adapter.find ? adapter.find(collectionName, options, cb) : cb();
criteria = normalizeCriteria(criteria);
if (_.isString(criteria)) return cb(criteria);
adapter.find(collectionName, criteria, cb);
// TODO: Return model instance Promise object for joins, etc.

@@ -135,2 +173,3 @@ };

criteria = normalizeCriteria(criteria);
if (_.isString(criteria)) return cb(criteria);

@@ -141,3 +180,3 @@ // TODO: Validate constraints using Anchor

adapter.update ? adapter.update(collectionName, criteria, values, cb) : cb();
adapter.update(collectionName, criteria, values, cb);

@@ -149,4 +188,6 @@ // TODO: Return model instance Promise object for joins, etc.

criteria = normalizeCriteria(criteria);
adapter.destroy ? adapter.destroy(collectionName, criteria, cb) : cb();
if (_.isString(criteria)) return cb(criteria);
adapter.destroy(collectionName, criteria, cb);
// TODO: Return model instance Promise object for joins, etc.

@@ -161,2 +202,4 @@ };

criteria = normalizeCriteria(criteria);
if (_.isString(criteria)) return cb(criteria);
if(adapter.findOrCreate) adapter.findOrCreate(collectionName, criteria, values, cb);

@@ -176,2 +219,4 @@ else {

criteria = normalizeCriteria(criteria);
if (_.isString(criteria)) return cb(criteria);
if(adapter.findAndUpdate) adapter.findAndUpdate(collectionName, criteria, values, cb);

@@ -184,2 +229,4 @@ else this.update(collectionName, criteria, values, cb);

criteria = normalizeCriteria(criteria);
if (_.isString(criteria)) return cb(criteria);
if(adapter.findAndDestroy) adapter.findAndDestroy(collectionName, criteria, cb);

@@ -201,3 +248,6 @@ else this.destroy(collectionName, criteria, cb);

// Custom user adapter behavior
if (adapter.createAll) adapter.createAll(collectionName,valuesList,cb);
// Default behavior
else {

@@ -224,4 +274,9 @@ async.forEach(valuesList, function (values,cb) {

// App-level transaction
this.transaction = function(transactionName, cb) {
/**
* App-level transaction
* @transactionName a unique identifier for this transaction
* @atomicLogic the logic to be run atomically
* @afterUnlock (optional) the function to trigger after unlock() is called
*/
this.transaction = function(transactionName, atomicLogic, afterUnlock) {
var self = this;

@@ -233,9 +288,10 @@

name: transactionName,
timestamp: epoch(),
cb: cb
atomicLogic: atomicLogic,
afterUnlock: afterUnlock
};
// console.log("Generating lock "+newLock.uuid+" ("+transactionName+")");
// console.log("Generating lock "+newLock.uuid+" ("+transactionName+")",newLock);
// write new lock to commit log
this.transactionCollection.create(newLock, function(err) {
if(err) return cb(err, function() {
this.transactionCollection.create(newLock, function afterCreatingTransaction(err) {
if(err) return atomicLogic(err, function() {
throw err;

@@ -245,4 +301,4 @@ });

// Check if lock was written, and is the oldest with the proper name
self.transactionCollection.findAll(function(err, locks) {
if(err) return cb(err, function() {
self.transactionCollection.findAll(function afterLookingUpTransactions(err, locks) {
if(err) return atomicLogic(err, function() {
throw err;

@@ -252,16 +308,14 @@ });

var conflict = false;
_.each(locks, function(entry) {
_.each(locks, function eachLock (entry) {
// If a conflict IS found, respect the oldest
// (the conflict-causer is responsible for cleaning up his entry-- ignore it!)
if(entry.name === newLock.name && entry.uuid !== newLock.uuid && true && //entry.timestamp <= newLock.timestamp &&
entry.id < newLock.id) conflict = entry;
if(entry.name === newLock.name &&
entry.uuid !== newLock.uuid &&
entry.id < newLock.id) conflict = entry;
});
// If there are no conflicts, the lock is acquired!
if(!conflict) self.lock(newLock, newLock.cb);
if(!conflict) acquireLock(newLock);
// Otherwise, get in line
// In other words, do nothing--
// unlock() will grant lock request in order it was received
// Otherwise, get in line: a lock was acquired before mine, do nothing
else {

@@ -280,5 +334,12 @@ /*

this.lock = function(newLock, cb) {
var self = this;
// console.log("====> Lock "+newLock.id+" acquired "+newLock.uuid+" ("+newLock.name+")");
/**
* acquireLock() is run after the lock is acquired, but before passing control to the atomic app logic
*
* @newLock the object representing the lock to acquire
* @name name of the lock
* @atomicLogic the transactional logic to be run atomically
* @afterUnlock (optional) the function to run after the lock is subsequently released
*/
var acquireLock = function(newLock) {
// console.log("====> Lock "+newLock.id+" acquired "+newLock.uuid+" ("+newLock.name+")",newLock);

@@ -289,5 +350,5 @@ var warningTimer = setTimeout(function() {

cb(null, function unlock(cb) {
newLock.atomicLogic(null, function unlock () {
clearTimeout(warningTimer);
self.unlock(newLock, cb);
releaseLock(newLock,arguments);
});

@@ -297,7 +358,12 @@ };

this.unlock = function(currentLock, cb) {
var self = this;
// releaseLock() will grant pending lock requests in the order they were received
//
// @currentLock the lock currently acquired
// @afterUnlockArgs the arguments to pass to the afterUnlock function
var releaseLock = function(currentLock, afterUnlockArgs) {
var cb = currentLock.afterUnlock;
// Get all locks
self.transactionCollection.findAll(function(err, locks) {
self.transactionCollection.findAll(function afterLookingUpTransactions(err, locks) {
if(err) return cb && cb(err);

@@ -315,12 +381,13 @@

uuid: currentLock.uuid
}, function(err) {
}, function afterLockReleased (err) {
if(err) return cb && cb(err);
// Trigger unlock's callback if specified
cb && cb();
// > NOTE: do this before triggering the next queued transaction
// to prevent transactions from monopolizing the event loop
cb && cb.apply(null, afterUnlockArgs);
// Now allow the nextInLine lock to be acquired
// This marks the end of the previous transaction
nextInLine && self.lock(nextInLine, nextInLine.cb);
nextInLine && acquireLock(nextInLine);
});

@@ -346,3 +413,3 @@ });

var self = this;
this.drop(collection.identity, function(err, data) {
this.drop(collection.identity, function afterDrop (err, data) {
if(err) cb(err);

@@ -358,52 +425,9 @@ else self.define(collection.identity, collection, cb);

// Check that collection exists-- if it doesn't go ahead and add it and get out
this.describe(collection.identity, function(err, data) {
this.describe(collection.identity, function afterDescribe (err, data) {
data = _.clone(data);
if(err) return cb(err);
else if(!data) return self.define(collection.identity, collection, cb);
// TODO: move all of this to the alter() call in the adapter
// If it *DOES* exist, we'll try to guess what changes need to be made
// Iterate through each attribute in this collection's schema
_.each(collection.attributes, function checkAttribute(attribute,attrName) {
// Make sure that a comparable field exists in the data store
if (!data[attrName]) {
data[attrName] = attribute;
// Add the default value for this new attribute to each row in the data model
// TODO
}
// And that it matches completely
else {
data[attrName] = attribute;
// Update the data belonging to this attribute to reflect the new properties
// Realistically, this will mainly be about constraints, and primarily uniquness
// It'd be good if waterline could enforce all constraints at this time,
// but there's a trade-off with destroying people's data
// TODO
}
});
// Now iterate through each attribute in the adapter's data store
// and remove any that don't have an analog in the collection definition
// Also prune the data belonging to removed attributes from rows
// TODO:
// Persist that
// Check that the attribute exists in the data store
// TODO
// If not, alter the collection to include it
// TODO
// Iterate through each attribute in this collection
// and make sure that a comparable field exists in the model
// TODO
// If not, alter the collection and remove it
// TODO
// cb();
else if(!data) return self.define(collection.identity, collection.attributes, cb);
// Otherwise, if it *DOES* exist, we'll try and guess what changes need to be made
else self.alter(collection.identity, collection.attributes, cb);
});

@@ -418,12 +442,2 @@ },

// Always grant access to a few of Adapter's methods to the user adapter instance
// (things that may or may not be defined by the user adapter)
adapter.transaction = function(name, cb) {
return self.transaction(name, cb);
};
// adapter.teardown = adapter.teardown || self.teardown;
// adapter.teardownCollection = adapter.teardownCollection || self.teardownCollection;
// Bind adapter methods to self

@@ -486,5 +500,6 @@ _.bindAll(adapter);

_.each(criteria, function(val, key) {
if(val === undefined) delete criteria[key];
if(_.isUndefined(val)) delete criteria[key];
});
// Convert id and id strings into a criteria
if((_.isFinite(criteria) || _.isString(criteria)) && +criteria > 0) {

@@ -495,5 +510,7 @@ criteria = {

}
if(!_.isObject(criteria)) {
throw 'Invalid options/criteria :: ' + criteria;
}
// Return string to indicate an error
if(!_.isObject(criteria)) return ('Invalid options/criteria :: ' + criteria);
// If criteria doesn't seem to contain operational keys, assume all the keys are criteria
if(!criteria.where && !criteria.limit && !criteria.skip && !criteria.offset && !criteria.order) {

@@ -513,8 +530,2 @@ criteria = {

return criteria;
}
// Number of miliseconds since the Unix epoch Jan 1st, 1970
function epoch() {
return(new Date()).getTime();
}
module.exports = require('waterline-dirty')({
inMemory: true,
migrate: 'drop'
inMemory: true
});

@@ -75,4 +75,7 @@ var _ = require('underscore');

var attributes = _.clone(this.attributes) || {};
attributes = require('./augmentAttributes')(attributes,_.extend({},config,this.config));
// For each defined attribute, create a dynamic finder function
_.each(this.attributes,function (attrDef, attrName) {
_.each(attributes,function (attrDef, attrName) {
self['findBy'+_.str.capitalize(attrName)] = self.generateDynamicFinder(attrName);

@@ -85,3 +88,2 @@ });

//////////////////////////////////////////

@@ -243,4 +245,14 @@ // Promises / Deferred Objects

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

@@ -247,0 +259,0 @@

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

@@ -40,4 +40,4 @@ "main": "waterline.js",

"microtime": "~0.3.3",
"waterline-dirty": "0.0.03"
"waterline-dirty": "0.0.0501"
}
}

@@ -20,6 +20,5 @@ /**

it('should be able to acquire lock', function(done) {
User.transaction("test", function(err, unlock) {
unlock();
done(err);
});
User.transaction("test", function(err, cb) {
cb();
},done);
});

@@ -32,3 +31,3 @@

User.transaction('test', function(err, unlock1) {
if(err) return done(err);
if(err) throw new Error(err);
if(!unlock1) throw new Error("No unlock() method provided!");

@@ -39,3 +38,3 @@

User.transaction('test', function(err, unlock2) {
if(err) return done(err);
if(err) throw new Error(err);
if(!unlock2) throw new Error("No unlock() method provided!");

@@ -46,14 +45,13 @@

// Release lock so other tests can use the 'test' transaction
unlock2();
if(_.isEqual(orderingTest, ['lock', 'unlock', 'lock'])) done();
if(_.isEqual(orderingTest, ['lock', 'unlock', 'lock'])) unlock2();
else {
console.error(orderingTest);
throw "The lock was acquired by two users at once!";
throw new Error("The lock was acquired by two users at once!");
}
});
}, done);
// Set timeout to release the lock after a 1/20 of a second
setTimeout(function() {
unlock1(testAppendUnlock);
testAppendUnlock();
unlock1();
}, 50);

@@ -96,2 +94,4 @@ });

User.transaction('test_create',function(err,unlock) {
if (err) throw new Error(err);
User.create({

@@ -101,17 +101,16 @@ name: constellation,

},function(err) {
if (err) throw new Error(err);
// Wait a short moment to introduce an element of choas
setTimeout(function() {
unlock();
cb();
},Math.round(Math.random())*5);
});
});
},cb);
}, function(err) {
if (err) throw new Error(err);
User.find({ type: type },function (err,users) {
if(users.length != items.length) {
console.error("Users: ");
console.error(users);
return done('Proper users were not created!');
}
done();
if(users.length === items.length) return done();
else return done('Proper users were not created!');
});

@@ -118,0 +117,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