Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

meadow

Package Overview
Dependencies
Maintainers
1
Versions
60
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

meadow - npm Package Compare versions

Comparing version 0.1.9 to 0.1.10

source/behaviors/Meadow-Count.js

2

package.json
{
"name": "meadow",
"version": "0.1.9",
"version": "0.1.10",
"description": "A data access library.",

@@ -5,0 +5,0 @@ "main": "source/Meadow.js",

@@ -16,4 +16,3 @@ /**

*/
var libAsync = require('async');
var libUnderscore = require('underscore')
var libUnderscore = require('underscore');

@@ -45,3 +44,13 @@ // Multi server query generation

var _Query = libFoxHound.new(_Fable).setScope(_Scope);
// The custom query loader
var _RawQueries = require('./Meadow-RawQuery.js').new(_Fable);
// The core behaviors.. abstracted into their own modules to encapsulate complexity
var _CreateBehavior = require('./behaviors/Meadow-Create.js');
var _ReadBehavior = require('./behaviors/Meadow-Read.js');
var _ReadsBehavior = require('./behaviors/Meadow-Reads.js');
var _UpdateBehavior = require('./behaviors/Meadow-Update.js');
var _DeleteBehavior = require('./behaviors/Meadow-Delete.js');
var _CountBehavior = require('./behaviors/Meadow-Count.js');
// The data provider

@@ -60,50 +69,11 @@ var _Provider = false;

/**
* Load the schema and metadata from a package file
*
* @method loadFromPackage
* @return {Object} Returns a new Meadow, or false if it failed
*/
* Load a Meadow Package JSON, create a Meadow object from it.
*/
var _MeadowPackageLoader = require('./Meadow-PackageLoader.js');
var loadFromPackage = function(pPackage)
{
// Use the package loader to grab the configuration objects and clone a new Meadow.
var tmpPackage = false;
try
{
tmpPackage = require(pPackage);
}
catch(pError)
{
_Fable.log.error('Error loading Fable package', {Package:pPackage});
return false;
}
return _MeadowPackageLoader(this, pPackage);
};
// Spool up a new Meadow object
var tmpNewMeadow = createNew(_Fable);
// Safely set the parameters
if (typeof(tmpPackage.Scope) === 'string')
{
tmpNewMeadow.setScope(tmpPackage.Scope);
}
if (typeof(tmpPackage.DefaultIdentifier) === 'string')
{
tmpNewMeadow.setDefaultIdentifier(tmpPackage.DefaultIdentifier);
}
if (Array.isArray(tmpPackage.Schema))
{
tmpNewMeadow.setSchema(tmpPackage.Schema);
}
if (typeof(tmpPackage.JsonSchema) === 'object')
{
tmpNewMeadow.setJsonSchema(tmpPackage.JsonSchema);
}
if (typeof(tmpPackage.DefaultObject) === 'object')
{
tmpNewMeadow.setDefault(tmpPackage.DefaultObject)
}
return tmpNewMeadow;
}
/**

@@ -217,307 +187,54 @@ * Set the scope

return this;
}
};
/**
* Create a record asynchronously, calling fCallBack with the marshalled record(s) or error in them at end
*
* TODO: Add a second behavior that creates records without returning them and takes an array of records.
* Create a record
*/
var doCreate = function(pQuery, fCallBack)
{
libAsync.waterfall(
[
// Step 1: Get the record from the data source
function (fStageComplete)
{
pQuery.query.IDUser = _IDUser;
// Make sure the user submitted a record
if (!pQuery.query.records)
{
return fStageComplete('No record submitted', pQuery, false);
}
// Merge in the default record with the passed-in record for completeness
pQuery.query.records[0] = libUnderscore.extend(_Schema.defaultObject, pQuery.query.records[0]);
// This odd lambda is to use the async waterfall without spilling logic into the provider create code
_Provider.Create(pQuery, function(){ fStageComplete(pQuery.result.error, pQuery); });
},
// Step 2: Marshal the record into a POJO
function (pQuery, fStageComplete)
{
if (pQuery.parameters.result.value === false)
{
// The value is not set (it should be set to the value for our DefaultIdentifier)
return fStageComplete('Creation failed', pQuery, false);
}
var tmpIDRecord = pQuery.result.value;
fStageComplete(pQuery.result.error, pQuery, tmpIDRecord);
},
// Step 3: Read the record
function (pQuery, pIDRecord, fStageComplete)
{
var tmpQueryRead = pQuery.clone().addFilter(_DefaultIdentifier, pIDRecord);
// This odd lambda is to use the async waterfall without spilling logic into the provider read code complexity
_Provider.Read(tmpQueryRead, function(){ fStageComplete(tmpQueryRead.result.error, pQuery, tmpQueryRead); });
},
// Step 4: Marshal the record into a POJO
function (pQuery, pQueryRead, fStageComplete)
{
if (pQueryRead.parameters.result.value.length < 1)
{
// There is not at least one record returned
return fStageComplete('No record found after create.', pQuery, pQueryRead, false);
}
return _CreateBehavior(this, pQuery, fCallBack);
};
var tmpRecord = marshalRecordFromSourceToObject(pQueryRead.result.value[0]);
fStageComplete(pQuery.result.error, pQuery, pQueryRead, tmpRecord);
}
],
function(pError, pQuery, pQueryRead, pRecord)
{
if (pError)
{
_Fable.log.warn('Error during the create waterfall', {Error:pError, Query: pQuery.query});
}
// Call the callback passed in with the record as the first parameter, query second.
fCallBack(pError, pQuery, pQueryRead, pRecord);
}
);
return this;
}
/**
* Read a record asynchronously, calling fCallBack with the marshalled record(s) or error in them at end
* Read a record
*/
var doRead = function(pQuery, fCallBack)
{
// Read the record from the source
libAsync.waterfall(
[
// Step 1: Get the record from the data source
function (fStageComplete)
{
// This odd lambda is to use the async waterfall without spilling logic into the provider read code
_Provider.Read(pQuery, function(){ fStageComplete(pQuery.result.error, pQuery); });
},
// Step 2: Marshal the record into a POJO
function (pQuery, fStageComplete)
{
if (pQuery.parameters.result.value.length < 1)
{
// The value is not an array
return fStageComplete(false, pQuery, false);
}
return _ReadBehavior(this, pQuery, fCallBack);
};
var tmpRecord = marshalRecordFromSourceToObject(pQuery.result.value[0]);
fStageComplete(pQuery.result.error, pQuery, tmpRecord);
}
],
function(pError, pQuery, pRecord)
{
if (pError)
{
_Fable.log.warn('Error during the read waterfall', {Error:pError, Query: pQuery.query});
}
// Call the callback passed in with the record as the first parameter, query second.
fCallBack(pError, pQuery, pRecord);
}
);
return this;
}
/**
* Read many records asynchronously, calling fCallBack with the marshalled record(s) or error in them at end
* Read multiple records
*/
var doReads = function(pQuery, fCallBack)
{
// Read the record(s) from the source
libAsync.waterfall(
[
// Step 1: Get a record from the data source
function (fStageComplete)
{
// This odd lambda is to use the async waterfall without spilling logic into the provider read code
_Provider.Read(pQuery, function(){ fStageComplete(pQuery.result.error, pQuery); });
},
// Step 2: Marshal all the records into a POJO asynchronously
function (pQuery, fStageComplete)
{
var tmpRecords = [];
return _ReadsBehavior(this, pQuery, fCallBack);
};
libAsync.each
(
pQuery.parameters.result.value,
function(pRow, pQueueCallback)
{
tmpRecords.push(marshalRecordFromSourceToObject(pRow));
pQueueCallback();
},
function()
{
// Now complete the waterfall
fStageComplete(pQuery.result.error, pQuery, tmpRecords);
}
);
}
],
function(pError, pQuery, pRecords)
{
if (pError)
{
_Fable.log.warn('Error during the read multiple waterfall', {Error:pError, Query: pQuery.query});
}
fCallBack(pError, pQuery, pRecords);
}
);
return this;
}
/**
* Update a record asynchronously, calling fCallBack with the marshalled record(s) or error in them at end
* Update a record
*/
var doUpdate = function(pQuery, fCallBack)
{
// Update the record(s) from the source
libAsync.waterfall(
[
// Step 1: Update the record
function (fStageComplete)
{
pQuery.query.IDUser = _IDUser;
// Make sure the user submitted a record
if (!pQuery.query.records)
{
return fStageComplete('No record submitted', pQuery, false);
}
// Make sure there is a default identifier
if (!pQuery.query.records[0].hasOwnProperty(_DefaultIdentifier))
{
return fStageComplete('Automated update missing default identifier', pQuery, false);
}
return _UpdateBehavior(this, pQuery, fCallBack);
};
// Now see if there is anything in the schema that is an Update action that isn't in this query
for (var i = 0; i < _Schema.schema.length; i++)
{
switch (_Schema.schema[i].Type)
{
case 'UpdateIDUser':
case 'UpdateDate':
pQuery.query.records[0][_Schema.schema[i].Column] = false;
break;
}
}
// Set the update filter
pQuery.addFilter(_DefaultIdentifier, pQuery.query.records[0][_DefaultIdentifier]);
// Sanity check on update
if ((pQuery.parameters.filter === false) || (pQuery.parameters.filter.length < 1))
{
return fStageComplete('Automated update missing filters... aborting!', pQuery, false);
}
// This odd lambda is to use the async waterfall without spilling logic into the provider read code
_Provider.Update(pQuery, function(){ fStageComplete(pQuery.result.error, pQuery); });
},
// Step 2: Check that the record was updated
function (pQuery, fStageComplete)
{
if (typeof(pQuery.parameters.result.value) !== 'object')
{
// The value is not an object
return fStageComplete('No record updated.', pQuery, false);
}
fStageComplete(pQuery.result.error, pQuery);
},
// Step 3: Read the record
function (pQuery, fStageComplete)
{
// We can clone the query, since it has the criteria for the update in it already (filters survive a clone)
var tmpQueryRead = pQuery.clone();
// This odd lambda is to use the async waterfall without spilling logic into the provider read code
_Provider.Read(tmpQueryRead, function(){ fStageComplete(tmpQueryRead.result.error, pQuery, tmpQueryRead); });
},
// Step 4: Marshal the record into a POJO
function (pQuery, pQueryRead, fStageComplete)
{
var tmpRecord = marshalRecordFromSourceToObject(pQueryRead.result.value[0]);
// TODO: Add error handling for marshaling
fStageComplete(pQuery.result.error, pQuery, pQueryRead, tmpRecord);
}
],
function(pError, pQuery, pQueryRead, pRecord)
{
if (pError)
{
_Fable.log.warn('Error during Update waterfall', {Error:pError, Query: pQuery.query});
}
fCallBack(pError, pQuery, pQueryRead, pRecord);
}
);
return this;
}
/**
* Delete a record asynchronously, calling fCallBack with the marshalled record(s) or error in them at end
* Delete a record
*/
var doDelete = function(pQuery, fCallBack)
{
// TODO: Check if this recordset has implicit delete tracking
// Delete the record(s) from the source
libAsync.waterfall(
[
// Step 1: Delete the record
function (fStageComplete)
{
// This odd lambda is to use the async waterfall without spilling logic into the provider read code complexity
_Provider.Delete(pQuery, function(){ fStageComplete(pQuery.result.error, pQuery, pQuery.result.value); });
}
],
function(pError, pQuery, pRecord)
{
fCallBack(pError, pQuery, pRecord);
}
);
return _DeleteBehavior(this, pQuery, fCallBack);
};
return this;
}
/**
* Count a record asynchronously, calling fCallBack with the marshalled record(s) or error in them at end
* Count multiple records
*/
var doCount = function(pQuery, fCallBack)
{
// Count the record(s) from the source
libAsync.waterfall(
[
// Step 1: Get the record from the data source
function (fStageComplete)
{
// This odd lambda is to use the async waterfall without spilling logic into the provider read code complexity
_Provider.Count(pQuery, function(){ fStageComplete(pQuery.result.error, pQuery); });
},
// Step 2: Marshal the record into a POJO
function (pQuery, fStageComplete)
{
if (typeof(pQuery.parameters.result.value) !== 'number')
{
// The value is not a number
return fStageComplete('Count did not return valid results.', pQuery, false);
}
return _CountBehavior(this, pQuery, fCallBack);
};
fStageComplete(pQuery.result.error, pQuery, pQuery.result.value);
}
],
function(pError, pQuery, pCount)
{
fCallBack(pError, pQuery, pCount);
}
);
return this;
}
/**

@@ -533,6 +250,6 @@ * Take the stored representation of our object and stuff the proper values

_Provider.marshalRecordFromSourceToObject(tmpNewObject, pRecord, _Schema.schema);
// This turns on magical validation
//_Fable.log.trace('Validation', {Value:tmpNewObject, Validation:_Schema.validateObject(tmpNewObject)})
// Now return the new object
return tmpNewObject;
}
};

@@ -552,2 +269,3 @@ /**

validateObject: _Schema.validateObject,
marshalRecordFromSourceToObject: marshalRecordFromSourceToObject,

@@ -557,5 +275,3 @@ setProvider: setProvider,

// Schema management
loadFromPackage: loadFromPackage,
//
setScope: setScope,

@@ -596,2 +312,14 @@ setSchema: setSchema,

/**
* Entity Schema
*
* @property schema
* @type object
*/
Object.defineProperty(tmpNewMeadowObject, 'schemaFull',
{
get: function() { return _Schema; },
enumerable: true
});
/**
* Default Identifier

@@ -621,2 +349,16 @@ *

/**
* User Identifier
*
* Used to stamp user identity into Create/Update operations.
*
* @property userIdentifier
* @type string
*/
Object.defineProperty(tmpNewMeadowObject, 'userIdentifier',
{
get: function() { return _IDUser; },
enumerable: true
});
/**
* Query (FoxHound) object

@@ -645,2 +387,26 @@ *

/**
* Raw Queries
*
* @property rawQueries
* @type object
*/
Object.defineProperty(tmpNewMeadowObject, 'rawQueries',
{
get: function() { return _RawQueries; },
enumerable: true
});
/**
* Provider
*
* @property provider
* @type object
*/
Object.defineProperty(tmpNewMeadowObject, 'provider',
{
get: function() { return _Provider; },
enumerable: true
});
/**
* Provider Name

@@ -647,0 +413,0 @@ *

@@ -46,5 +46,8 @@ /**

var marshalRecordFromSourceToObject = function(pObject, pRecord, pSchema)
// The Meadow marshaller also passes in the Schema as the third parameter, but this is a blunt function ATM.
var marshalRecordFromSourceToObject = function(pObject, pRecord)
{
// For now, crudely assign everything in pRecord to pObject
// This is safe in this context, and we don't want to slow down marshalling with millions of hasOwnProperty checks
/*jshint -W089 */
for(var tmpColumn in pRecord)

@@ -54,2 +57,3 @@ {

}
/*jshint +W089 */
};

@@ -65,3 +69,5 @@

if (pQuery.logLevel > 0)
{
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
}

@@ -73,3 +79,4 @@ var tmpSQLConnection = getSQLConnection();

pQuery.query.parameters,
function(pError, pRows, pFields)
// The MySQL library also returns the Fields as the third parameter
function(pError, pRows)
{

@@ -103,3 +110,5 @@ tmpResult.error = pError;

if (pQuery.logLevel > 0)
{
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
}

@@ -111,3 +120,4 @@ var tmpSQLConnection = getSQLConnection();

pQuery.query.parameters,
function(pError, pRows, pFields)
// The MySQL library also returns the Fields as the third parameter
function(pError, pRows)
{

@@ -130,3 +140,5 @@ tmpResult.error = pError;

if (pQuery.logLevel > 0)
{
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
}

@@ -138,3 +150,4 @@ var tmpSQLConnection = getSQLConnection();

pQuery.query.parameters,
function(pError, pRows, pFields)
// The MySQL library also returns the Fields as the third parameter
function(pError, pRows)
{

@@ -157,3 +170,5 @@ tmpResult.error = pError;

if (pQuery.logLevel > 0)
{
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
}

@@ -165,3 +180,4 @@ var tmpSQLConnection = getSQLConnection();

pQuery.query.parameters,
function(pError, pRows, pFields)
// The MySQL library also returns the Fields as the third parameter
function(pError, pRows)
{

@@ -192,3 +208,5 @@ tmpResult.error = pError;

if (pQuery.logLevel > 0)
{
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
}

@@ -200,3 +218,4 @@ var tmpSQLConnection = getSQLConnection();

pQuery.query.parameters,
function(pError, pRows, pFields)
// The MySQL library also returns the Fields as the third parameter
function(pError, pRows)
{

@@ -208,3 +227,3 @@ tmpResult.executed = true;

{
tmpResult.value = pRows[0]['RowCount'];
tmpResult.value = pRows[0].RowCount;
}

@@ -211,0 +230,0 @@ catch(pErrorGettingRowcount)

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

}
var _Fable = pFable;
//var _Fable = pFable;
var marshalRecordFromSourceToObject = function(pObject, pRecord, pSchema)
//var marshalRecordFromSourceToObject = function(pObject, pRecord, pSchema)
var marshalRecordFromSourceToObject = function()
{

@@ -24,0 +25,0 @@ // Do nothing ... this is the NONE provider after all

@@ -567,22 +567,2 @@ /**

(
'Create a record in the database with bad fields',
function(fDone)
{
var testMeadow = newMeadow();
var tmpQuery = testMeadow.query
.addRecord({Name:'Tina', TypeWriter:'Chameleon'});
testMeadow.doCreate(tmpQuery,
function(pError, pQuery, pQueryRead, pRecord)
{
Expect(pError)
.to.be.an('object');
fDone();
}
)
}
);
test
(
'Create a record in the database with no record',

@@ -779,2 +759,176 @@ function(fDone)

);
test
(
'Set a raw Query',
function(fDone)
{
var testMeadow = newMeadow();
testMeadow.rawQueries.setQuery('Read', 'SELECT Something from SomethingElse;');
Expect(testMeadow.rawQueries.getQuery('Read'))
.to.equal('SELECT Something from SomethingElse;');
fDone();
}
);
test
(
'Load a raw Query',
function(fDone)
{
var testMeadow = newMeadow();
testMeadow.rawQueries.loadQuery('Read', __dirname+ '/Meadow-Provider-MySQL-AnimalReadQuery.sql',
function(pSuccess)
{
Expect(testMeadow.rawQueries.getQuery('Read'))
.to.contain('SELECT');
fDone();
});
}
);
test
(
'Load a bad raw Query',
function(fDone)
{
var testMeadow = newMeadow();
testMeadow.rawQueries.loadQuery('Read', __dirname+ '/Meadow-Provider-MySQL-BADAnimalReadQuery.sql',
function(pSuccess)
{
Expect(testMeadow.rawQueries.getQuery('Read'))
.to.equal('');
fDone();
});
}
);
test
(
'Load a raw query with no callback',
function()
{
var testMeadow = newMeadow();
testMeadow.rawQueries.loadQuery('Read', __dirname+ '/Meadow-Provider-MySQL-AnimalReadQuery.sql');
}
);
test
(
'Check for a query that is not there',
function()
{
var testMeadow = newMeadow();
Expect(testMeadow.rawQueries.getQuery('Read'))
.to.equal(false);
}
);
test
(
'Read a record from a custom query',
function(fDone)
{
var testMeadow = newMeadow();
testMeadow.rawQueries.loadQuery('Read', __dirname+ '/Meadow-Provider-MySQL-AnimalReadQuery.sql',
function(pSuccess)
{
// Now try to read the record
testMeadow.doRead(testMeadow.query.addFilter('IDAnimal', 2),
function(pError, pQuery, pRecord)
{
Expect(pRecord.AnimalTypeCustom)
.to.equal('Bunny');
fDone();
}
)
});
}
);
test
(
'Read records from a custom query, then delete one, then read them again then update and create.',
function(fDone)
{
var testMeadow = newMeadow();
testMeadow.setDefaultIdentifier('IDAnimal');
testMeadow.rawQueries.setQuery('Delete', 'DELETE FROM FableTest WHERE IDAnimal = 1;')
testMeadow.rawQueries.setQuery('Count', 'SELECT 1337 AS RowCount;')
testMeadow.rawQueries.setQuery('Read', 'SELECT IDAnimal, Type AS AnimalTypeCustom FROM FableTest <%= Where %>')
testMeadow.rawQueries.setQuery('Update', "UPDATE FableTest SET Type = 'FrogLeg' <%= Where %>")
// And this, my friends, is why we use async.js
testMeadow.rawQueries.loadQuery('Reads', __dirname+ '/Meadow-Provider-MySQL-AnimalReadQuery.sql',
function(pSuccess)
{
// Now try to read the record
testMeadow.doReads(testMeadow.query.addFilter('IDAnimal', 2),
function(pError, pQuery, pRecords)
{
Expect(pRecords[1].AnimalTypeCustom)
.to.equal('HumanGirl');
testMeadow.doDelete(testMeadow.query.addFilter('IDAnimal', 2),
function(pError, pQuery, pRecord)
{
// It returns the number of rows deleted
Expect(pRecord)
.to.equal(1);
testMeadow.doCount(testMeadow.query.addFilter('IDAnimal', 2),
function(pError, pQuery, pRecord)
{
// It returns the number of rows deleted
Expect(pRecord)
.to.equal(1337);
var tmpQuery = testMeadow.query
.addRecord({IDAnimal:5, Type:'Bartfast'});
testMeadow.doUpdate(tmpQuery,
function(pError, pQuery, pQueryRead, pRecord)
{
// We should have a record ....
Expect(pRecord.AnimalTypeCustom)
.to.equal('Bartfast');
var tmpQuery = testMeadow.query
.addRecord({Name:'Bambi', Type:'CustomSheep'});
testMeadow.doCreate(tmpQuery,
function(pError, pQuery, pQueryRead, pRecord)
{
// We should have a record ....
Expect(pRecord.AnimalTypeCustom)
.to.equal('CustomSheep');
fDone();
}
)
}
)
}
)
}
)
}
)
}
);
}
);
test
(
'Create a record in the database with bad fields',
function(fDone)
{
var testMeadow = newMeadow();
// NOTE: Bad fields passed in are polluting the schema forever.
var tmpQuery = testMeadow.query
.addRecord({Name:'Tina', TypeWriter:'Chameleon'});
testMeadow.doCreate(tmpQuery,
function(pError, pQuery, pQueryRead, pRecord)
{
Expect(pError)
.to.be.an('object');
fDone();
}
)
}
);
}

@@ -781,0 +935,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