clever-orm
Advanced tools
Comparing version 1.2.3 to 2.0.0-rc1
@@ -1,78 +0,80 @@ | ||
var injector = require( 'injector' ) | ||
, util = require( 'util' ) | ||
, utils = require( 'utils' ) | ||
, async = require( 'async' ) | ||
, config = require( 'config' ) | ||
, path = require( 'path' ) | ||
, fs = require( 'fs' ) | ||
, debug = require( 'debug' )( 'cleverstack:cleverOrm:rebase' ) | ||
, ormUtils = utils.ormUtils | ||
'use strict'; | ||
var injector = require('injector') | ||
, util = require('util') | ||
, utils = require('utils') | ||
, async = require('async') | ||
, config = require('config') | ||
, path = require('path') | ||
, fs = require('fs') | ||
, debug = require('debug')('cleverstack:cleverOrm:rebase') | ||
, helpers = utils.helpers | ||
, env = utils.bootstrapEnv() | ||
, moduleLdr = env.moduleLoader; | ||
debug( 'Using configuration:' ); | ||
debug( util.inspect( config[ 'clever-orm' ].modelAssociations ) ); | ||
debug('Using configuration:'); | ||
debug(util.inspect(config['clever-orm'].modelAssociations)); | ||
// Rebase once our modules have loaded | ||
moduleLdr.on( 'modulesLoaded', function() { | ||
var sequelize = injector.getInstance( 'sequelize' ); | ||
moduleLdr.on('modulesLoaded', function() { | ||
var sequelize = injector.getInstance('sequelize'); | ||
debug('Forcing Database to be created! (Note: All your data will disapear!)'); | ||
async.waterfall( | ||
[ | ||
function createDatabase( callback ) { | ||
var query = 'CREATE DATABASE ' + ( config[ 'clever-orm' ].db.options.dialect === 'mysql' ? 'IF NOT EXISTS ' : '' ) + config[ 'clever-orm' ].db.database; | ||
debug('Forcing Database to be created! (Note: All your data will disapear!)'); | ||
async.waterfall( | ||
[ | ||
function createDatabase(callback) { | ||
var query = 'CREATE DATABASE ' + (config['clever-orm'].db.options.dialect === 'mysql' ? 'IF NOT EXISTS ' : '') + config['clever-orm'].db.database; | ||
sequelize.query( query, { raw: true } ) | ||
.then( function() { | ||
callback( null ); | ||
}) | ||
.catch( callback ); | ||
}, | ||
sequelize.query(query, { raw: true }) | ||
.then(function() { | ||
callback(null); | ||
}) | ||
.catch(callback); | ||
}, | ||
function rebaseDatabase( callback ) { | ||
sequelize | ||
.sync( { force: true } ) | ||
.then( function() { | ||
callback( null ); | ||
}) | ||
.catch( callback ); | ||
}, | ||
function rebaseDatabase(callback) { | ||
sequelize | ||
.sync({ force: true }) | ||
.then(function() { | ||
callback(null); | ||
}) | ||
.catch(callback); | ||
}, | ||
function runDialectSqlFile( callback ) { | ||
var dialectSqlFile = path.resolve( path.join( __dirname, '..', '..', '..', 'schema', config[ 'clever-orm' ].db.options.dialect + '.sql' ) ); | ||
if ( fs.existsSync( dialectSqlFile ) ) { | ||
fs.readFile( dialectSqlFile, function( err, sql ) { | ||
if ( err || !sql ) { | ||
debug( 'No specific dialect SQL found continuing...' ); | ||
return callback(); | ||
} | ||
function runDialectSqlFile(callback) { | ||
var dialectSqlFile = path.resolve(path.join(__dirname, '..', '..', '..', 'schema', config['clever-orm'].db.options.dialect + '.sql')); | ||
if (fs.existsSync(dialectSqlFile)) { | ||
fs.readFile(dialectSqlFile, function(err, sql) { | ||
if (err || !sql) { | ||
debug('No specific dialect SQL found continuing...'); | ||
return callback(); | ||
} | ||
debug( 'Running dialect specific SQL' ); | ||
sequelize.query( sql.toString(), null, { raw: true } ).then(function() { | ||
callback( null ); | ||
}) | ||
.catch( callback ); | ||
}); | ||
} else { | ||
callback( null ); | ||
} | ||
} | ||
], | ||
function shutdown( err ) { | ||
if ( err === null ) { | ||
debug( 'Database is rebased' ); | ||
process.exit( 0 ); | ||
} else { | ||
console.error('Error ' + env.config['clever-orm'].db.options.dialect, err); | ||
process.exit( 1 ); | ||
} | ||
debug('Running dialect specific SQL'); | ||
sequelize.query(sql.toString(), null, { raw: true }).then(function() { | ||
callback(null); | ||
}) | ||
.catch(callback); | ||
}); | ||
} else { | ||
callback(null); | ||
} | ||
); | ||
} | ||
], | ||
function shutdown(err) { | ||
if (err === null) { | ||
debug('Database is rebased'); | ||
process.exit(0); | ||
} else { | ||
console.error('Error ' + env.config['clever-orm'].db.options.dialect, err); | ||
process.exit(1); | ||
} | ||
} | ||
); | ||
}); | ||
ormUtils.supportSingleModule( env, process.argv && process.argv[ 2 ] != 'null' ? process.argv[ 2 ] : false ); | ||
helpers.supportSingleDbModule(env, 'clever-orm', process.argv && process.argv[2] != 'null' ? process.argv[2] : false); | ||
// Load | ||
moduleLdr.loadModules(); |
@@ -1,165 +0,196 @@ | ||
var utils = require( 'utils' ) | ||
, ormUtils = utils.ormUtils | ||
, async = require( 'async' ) | ||
'use strict'; | ||
var utils = require('utils') | ||
, helpers = utils.helpers | ||
, async = require('async') | ||
, env = utils.bootstrapEnv() | ||
, moduleLdr = env.moduleLoader | ||
, _ = require( 'underscore' ) | ||
, config = require( 'config' ) | ||
, debug = require( 'debug' )( 'cleverstack:cleverOrm:rebase' ) | ||
, inflect = require( 'i' )(); | ||
, _ = require('underscore') | ||
, config = require('config') | ||
, debug = require('debug')('cleverstack:cleverOrm:seed') | ||
, inflect = require('i')(); | ||
// Seed once our modules have loaded | ||
moduleLdr.on( 'modulesLoaded', function() { | ||
var seedData = require( 'seedData' ) | ||
, models = require( 'models' ); | ||
moduleLdr.on('modulesLoaded', function() { | ||
var seedData = require('seedData') | ||
, models = require('models'); | ||
var assocMap = {}; | ||
Object.keys( seedData ).forEach(function( modelName ) { | ||
assocMap[ modelName ] = []; | ||
}); | ||
var assocMap = {}; | ||
Object.keys(seedData).forEach(function(modelName) { | ||
assocMap[modelName] = []; | ||
}); | ||
async.waterfall( | ||
[ | ||
function createModels( callback ) { | ||
async.forEach( | ||
Object.keys( seedData ), | ||
function forEachSeedDataModel( modelName, cb ) { | ||
var ModelType = models[ modelName.replace( 'Model', '' ) ] | ||
, Models = seedData[ modelName ]; | ||
async.waterfall( | ||
[ | ||
function createModels(callback) { | ||
async.forEachSeries( | ||
Object.keys(seedData), | ||
function forEachSeedDataModel(modelName, cb) { | ||
var ModelType = models[modelName.replace('Model', '')] | ||
, Models = seedData[modelName]; | ||
if ( !ModelType || !Models || ModelType.type !== 'ORM' ) { | ||
return cb(); | ||
} | ||
if (!ModelType || !Models || ModelType.type !== 'ORM') { | ||
return cb(); | ||
} | ||
async.forEach( | ||
Models, | ||
function createModel( modelData, modelCb ) { | ||
var data = _.clone( modelData ) | ||
, associations = data.associations; | ||
async.forEachSeries( | ||
Models, | ||
function createModel(modelData, modelCb) { | ||
var data = _.clone(modelData) | ||
, associations = data.associations; | ||
delete data.associations; | ||
delete data.associations; | ||
ModelType | ||
.create( data ) | ||
.then(function( model ) { | ||
debug( 'Created ' + modelName ); | ||
if ( associations ) { | ||
model.associations = associations; | ||
} | ||
assocMap[ modelName ].push( model ); | ||
modelData.id = model.id; | ||
modelCb( null ); | ||
}) | ||
.catch( modelCb ); | ||
}, | ||
cb | ||
); | ||
}, | ||
callback | ||
) | ||
}, | ||
function associateModels( callback ) { | ||
async.forEachSeries( | ||
Object.keys( seedData ), | ||
function forEachSeedDataModel( modelName, cb ) { | ||
var ModelType = models[ modelName.replace( 'Model', '' ) ] | ||
, Models = seedData[ modelName ]; | ||
ModelType | ||
.create(data) | ||
.then(function(model) { | ||
debug('Created ' + modelName); | ||
if (associations) { | ||
model.associations = associations; | ||
} | ||
assocMap[modelName].push(model); | ||
modelData.id = model.id; | ||
if ( !ModelType || !Models || ModelType.type !== 'ORM' ) { | ||
return cb(); | ||
} | ||
process.nextTick(function() { | ||
modelCb(null); | ||
}); | ||
}) | ||
.catch(modelCb); | ||
}, | ||
function(err) { | ||
setImmediate(function() { | ||
cb(err); | ||
}); | ||
} | ||
); | ||
}, | ||
function(err) { | ||
setImmediate(function() { | ||
callback(err); | ||
}); | ||
} | ||
) | ||
}, | ||
function associateModels(callback) { | ||
async.forEachSeries( | ||
Object.keys(seedData), | ||
function forEachSeedDataModel(modelName, cb) { | ||
var ModelType = models[modelName.replace('Model', '')] | ||
, Models = seedData[modelName]; | ||
async.forEachSeries( | ||
Models, | ||
function associateModel( data, modelCb ) { | ||
if ( data.associations !== undefined ) { | ||
var assocLength = Object.keys( data.associations ).length | ||
, called = 0 | ||
, model = _.findWhere( assocMap[ modelName ], { id: data.id } ); | ||
if (!ModelType || !Models || ModelType.type !== 'ORM') { | ||
return cb(); | ||
} | ||
Object.keys( data.associations ).forEach( function( assocModelName ) { | ||
var required = data.associations[ assocModelName ] | ||
, associations = []; | ||
async.forEachSeries( | ||
Models, | ||
function associateModel(data, modelCb) { | ||
if (data.associations !== undefined) { | ||
var assocLength = Object.keys(data.associations).length | ||
, called = 0 | ||
, model = _.findWhere(assocMap[modelName], { id: data.id }); | ||
if ( !( required instanceof Array ) ) { | ||
required = [ required ]; | ||
} | ||
Object.keys(data.associations).forEach(function(assocModelName) { | ||
var required = data.associations[assocModelName] | ||
, associations = []; | ||
required.forEach( function( requiredModels ) { | ||
if ( typeof requiredModels !== 'array' ) { | ||
requiredModels = [ requiredModels ]; | ||
} | ||
requiredModels.forEach( function( requiredModel ) { | ||
if ( ( associatedModel = _.findWhere( assocMap[ assocModelName ], requiredModel )) !== undefined ) { | ||
associations.push( associatedModel.entity ); | ||
} | ||
}); | ||
}); | ||
if (!(required instanceof Array)) { | ||
required = [required]; | ||
} | ||
required.forEach(function(requiredModels) { | ||
if (typeof requiredModels !== 'array') { | ||
requiredModels = [requiredModels]; | ||
} | ||
requiredModels.forEach(function(requiredModel) { | ||
var associatedModel; | ||
if ((associatedModel = _.findWhere(assocMap[assocModelName], requiredModel)) !== undefined) { | ||
associations.push(associatedModel.entity); | ||
} | ||
}); | ||
}); | ||
if ( associations.length ) { | ||
assocModelName = assocModelName.replace( /(Model)$/g, '' ); | ||
var assocConfig = config[ 'clever-orm' ].modelAssociations[ modelName.replace( /(Model)$/g, '' ) ]; | ||
Object.keys( assocConfig ).every( function( associatedModelType ) { | ||
assocConfig[ associatedModelType ].forEach( function( entity ) { | ||
entity = entity instanceof Array ? entity : [ entity, {} ]; | ||
if ( assocModelName === entity[ 0 ] ) { | ||
assocModelName = inflect.camelize( entity[ 1 ].as ? entity[ 1 ].as : entity[ 0 ] ); | ||
return false; | ||
} | ||
if (associations.length) { | ||
assocModelName = assocModelName.replace(/(Model)$/g, ''); | ||
var assocConfig = config['clever-orm'].modelAssociations[ modelName.replace(/(Model)$/g, '')]; | ||
Object.keys(assocConfig).every(function(associatedModelType) { | ||
assocConfig[associatedModelType].forEach(function(entity) { | ||
entity = entity instanceof Array ? entity : [entity, {}]; | ||
return true; | ||
}); | ||
}); | ||
if (assocModelName === entity[0]) { | ||
assocModelName = inflect.camelize(entity[1].as ? entity[1].as : entity[0]); | ||
return false; | ||
} | ||
var funcName = 'set' + inflect.pluralize( assocModelName.replace( /(Model)$/g,'' ) ); | ||
return true; | ||
}); | ||
}); | ||
// Handle hasOne | ||
if ( typeof model.entity[ funcName ] !== 'function' ) { | ||
funcName = 'set' + assocModelName.replace( /(Model)$/g,'' ); | ||
associations = associations[ 0 ]; | ||
} | ||
var funcName = 'set' + inflect.pluralize(assocModelName.replace(/(Model)$/g,'')); | ||
debug( 'Calling ' + modelName + '.' + funcName + '()' ); | ||
model[ funcName ]( associations ) | ||
.then(function() { | ||
called++; | ||
// Handle hasOne | ||
if (typeof model.entity[funcName] !== 'function') { | ||
funcName = 'set' + assocModelName.replace(/(Model)$/g,''); | ||
associations = associations[0]; | ||
} | ||
if ( called == assocLength ) { | ||
modelCb( null ); | ||
} | ||
}) | ||
.catch( modelCb ); | ||
} else { | ||
modelCb( null ); | ||
} | ||
}); | ||
} else { | ||
modelCb( null ); | ||
} | ||
}, | ||
cb | ||
); | ||
}, | ||
callback | ||
) | ||
} | ||
], | ||
function forEachModelTypeComplete( err ) { | ||
if ( err === null || err === undefined ) { | ||
debug( 'Seed completed with no errors' ); | ||
process.exit( 0 ); | ||
} else { | ||
debug( err ); | ||
process.exit( 1 ); | ||
} | ||
} | ||
); | ||
debug('Calling ' + modelName + '.' + funcName + '()'); | ||
setImmediate(function() { | ||
model[funcName](associations) | ||
.then(function() { | ||
called++; | ||
if (called == assocLength) { | ||
modelCb(null); | ||
} | ||
}) | ||
.catch(modelCb); | ||
}); | ||
} else { | ||
setImmediate(function() { | ||
modelCb(null); | ||
}); | ||
} | ||
}); | ||
} else { | ||
setImmediate(function() { | ||
modelCb(null); | ||
}); | ||
} | ||
}, | ||
function(err) { | ||
setImmediate(function() { | ||
cb(err); | ||
}); | ||
} | ||
); | ||
}, | ||
function(err) { | ||
setImmediate(function() { | ||
callback(err); | ||
}); | ||
} | ||
) | ||
} | ||
], | ||
function forEachModelTypeComplete(err) { | ||
if (err === null || err === undefined) { | ||
debug('Seed completed with no errors'); | ||
process.exit(0); | ||
} else { | ||
console.error(err.parent ? err.parent.message : err.parent); | ||
console.error(err.stack); | ||
console.error(err); | ||
process.exit(1); | ||
} | ||
} | ||
); | ||
}); | ||
ormUtils.supportSingleModule( env, process.argv && process.argv[ 2 ] != 'null' ? process.argv[ 2 ] : false ); | ||
helpers.supportSingleDbModule(env, 'clever-orm', process.argv && process.argv[2] != 'null' ? process.argv[2] : false); | ||
// Load | ||
moduleLdr.loadModules(); |
{ | ||
"clever-orm": { | ||
"db": { | ||
"username": "root", | ||
"password": "", | ||
"database": "nodeseed", | ||
"options": { | ||
"host": "localhost", | ||
"dialect": "mysql", | ||
"port": 3306 | ||
} | ||
}, | ||
"modelAssociations": {} | ||
} | ||
"clever-orm": { | ||
"db": { | ||
"username": "root", | ||
"password": "", | ||
"database": "nodeseed", | ||
"options": { | ||
"host": "localhost", | ||
"dialect": "mysql", | ||
"port": 3306 | ||
} | ||
}, | ||
"modelAssociations": {} | ||
} | ||
} |
288
Gruntfile.js
'use strict'; | ||
var fs = require( 'fs' ) | ||
, path = require( 'path' ) | ||
, pkgJson = require( path.resolve( path.join( __dirname, '..', '..', 'package.json') ) ) | ||
, odmEnabled = pkgJson.bundledDependencies.indexOf( 'clever-odm' ) !== -1 | ||
, _ = require( 'underscore' ); | ||
var fs = require('fs') | ||
, path = require('path') | ||
, pkgJson = require(path.resolve(path.join(__dirname, '..', '..', 'package.json'))) | ||
, odmEnabled = pkgJson.bundledDependencies.indexOf('clever-odm') !== -1 | ||
, _ = require('underscore'); | ||
module.exports = function( grunt ) { | ||
// Arguments for individual module rebase/seed | ||
var dbTarget = grunt.option( 'module' ) || null; | ||
module.exports = function(grunt) { | ||
var defaultConfig = require(path.join(__dirname, 'config', 'default.json')) | ||
, configFile = null | ||
, config = {} | ||
, dbTarget = grunt.option('module') || null; | ||
return [{ | ||
prompt: { | ||
cleverOrmConfigPrompt: { | ||
options: { | ||
questions: [ | ||
{ | ||
config: 'cleverstackorm.username', | ||
type: 'input', | ||
message: 'Database username', | ||
default: '', | ||
}, | ||
{ | ||
config: 'cleverstackorm.password', | ||
type: 'password', | ||
message: 'Database password', | ||
default: '' | ||
}, | ||
{ | ||
config: 'cleverstackorm.database', | ||
type: 'input', | ||
message: 'Database name', | ||
default: '' | ||
}, | ||
{ | ||
config: 'cleverstackorm.dialect', | ||
type: 'list', | ||
message: 'Database dialect', | ||
choices: [ | ||
{ name: 'mysql' }, | ||
{ name: 'mariadb' }, | ||
{ name: 'postgres' }, | ||
{ name: 'sqlite' } | ||
] | ||
}, | ||
{ | ||
config: 'cleverstackorm.host', | ||
type: 'input', | ||
message: 'Database host', | ||
default: '127.0.0.1' | ||
}, | ||
{ | ||
config: 'cleverstackorm.port', | ||
type: 'input', | ||
message: 'Database port', | ||
default: '3306' | ||
} | ||
] | ||
return [{ | ||
prompt: { | ||
cleverOrmConfigPrompt: { | ||
options: { | ||
questions: [ | ||
{ | ||
config: 'cleverstackorm.environment', | ||
type: 'list', | ||
message: 'What environment is this configuration for?', | ||
choices: [ | ||
{ name: 'LOCAL' }, | ||
{ name: 'TEST' }, | ||
{ name: 'DEV' }, | ||
{ name: 'STAG' }, | ||
{ name: 'PROD' } | ||
], | ||
default: function() { | ||
return process.env.NODE_ENV ? process.env.NODE_ENV.toUpperCase() : 'LOCAL'; | ||
}, | ||
filter: function(env) { | ||
_.extend(config, defaultConfig); | ||
configFile = path.resolve(path.join(__dirname, '..', '..', 'config', env.toLowerCase() + '.json')); | ||
if (fs.existsSync(configFile)) { | ||
_.extend(config, require(configFile)); | ||
Object.keys(defaultConfig['clever-orm']).forEach(function(key) { | ||
if (typeof config['clever-orm'][key] === 'undefined') { | ||
config['clever-orm'][key] = defaultConfig['clever-orm'][key]; | ||
} | ||
}); | ||
} | ||
} | ||
}, | ||
exec: { | ||
ormRebase: { | ||
cmd: "node modules/clever-orm/bin/rebase.js " + dbTarget | ||
return true; | ||
} | ||
}, | ||
ormSeed: { | ||
cmd: "node modules/clever-orm/bin/seedModels.js " + dbTarget | ||
{ | ||
config: 'cleverstackorm.username', | ||
type: 'input', | ||
message: 'Database username', | ||
default: function() { | ||
return config['clever-orm'].db.username; | ||
} | ||
}, | ||
{ | ||
config: 'cleverstackorm.password', | ||
type: 'password', | ||
message: 'Database password', | ||
default: function() { | ||
return config['clever-orm'].db.password; | ||
} | ||
}, | ||
{ | ||
config: 'cleverstackorm.database', | ||
type: 'input', | ||
message: 'Database name', | ||
default: function() { | ||
return config['clever-orm'].db.database || 'nodeseed'; | ||
} | ||
}, | ||
{ | ||
config: 'cleverstackorm.dialect', | ||
type: 'list', | ||
message: 'Database dialect', | ||
choices: [ | ||
{ name: 'mysql' }, | ||
{ name: 'mssql' }, | ||
{ name: 'mariadb' }, | ||
{ name: 'postgres' }, | ||
{ name: 'sqlite' } | ||
], | ||
default: function() { | ||
return config['clever-orm'].db.dialect || 'mysql'; | ||
} | ||
}, | ||
{ | ||
config: 'cleverstackorm.host', | ||
type: 'input', | ||
message: 'Database host', | ||
default: function() { | ||
return config['clever-orm'].db.host || '127.0.0.1'; | ||
} | ||
}, | ||
{ | ||
config: 'cleverstackorm.port', | ||
type: 'input', | ||
message: 'Database port', | ||
default: function(answers) { | ||
var dialect = config['clever-orm'].db.dialect | ||
, port = config['clever-orm'].db.port; | ||
if (dialect && dialect !== answers['cleverstackorm.dialect']) { | ||
port = false; | ||
} | ||
if (!port) { | ||
switch(dialect) { | ||
case 'mysql': | ||
case 'mariadb': | ||
port = 3306; | ||
break; | ||
case 'mssql': | ||
port = 1433; | ||
break; | ||
case 'postgres': | ||
port = 5432; | ||
break; | ||
case 'sqlite': | ||
port = ''; | ||
break; | ||
} | ||
} | ||
return port; | ||
} | ||
} | ||
] | ||
} | ||
}, function( grunt ) { | ||
grunt.loadNpmTasks('grunt-prompt'); | ||
} | ||
}, | ||
exec: { | ||
ormRebase: { | ||
cmd: "node modules/clever-orm/bin/rebase.js " + dbTarget | ||
}, | ||
ormSeed: { | ||
cmd: "node modules/clever-orm/bin/seedModels.js " + dbTarget | ||
} | ||
} | ||
}, function(grunt) { | ||
grunt.loadNpmTasks('grunt-prompt'); | ||
// Register each command | ||
grunt.registerTask( 'db:ormRebase', [ 'exec:ormRebase' ] ); | ||
grunt.registerTask( 'db:ormSeed', [ 'exec:ormSeed' ] ); | ||
// Register grouped command | ||
grunt.registerTask( 'db:orm', [ 'db:ormRebase', 'db:ormSeed' ] ); | ||
// Register each command | ||
grunt.registerTask('db:ormRebase', ['exec:ormRebase']); | ||
grunt.registerTask('db:ormSeed', ['exec:ormSeed']); | ||
// Register grouped command | ||
grunt.registerTask('db:orm', ['db:ormRebase', 'db:ormSeed']); | ||
if ( odmEnabled ) { | ||
grunt.registerTask( 'db:rebase', [ 'db:ormRebase', 'db:odmRebase' ] ); | ||
grunt.registerTask( 'db:seed', [ 'db:ormSeed', 'db:odmSeed' ] ); | ||
grunt.registerTask( 'db', [ 'db:rebase', 'db:seed' ] ); | ||
} else { | ||
grunt.registerTask( 'db:rebase', [ 'db:ormRebase' ] ); | ||
grunt.registerTask( 'db:seed', [ 'db:ormSeed' ] ); | ||
grunt.registerTask( 'db', [ 'db:orm' ] ); | ||
} | ||
if (odmEnabled) { | ||
grunt.registerTask('db:rebase', ['db:ormRebase', 'db:odmRebase']); | ||
grunt.registerTask('db:seed', ['db:ormSeed', 'db:odmSeed']); | ||
grunt.registerTask('db', ['db:rebase', 'db:seed']); | ||
} else { | ||
grunt.registerTask('db:rebase', ['db:ormRebase']); | ||
grunt.registerTask('db:seed', ['db:ormSeed']); | ||
grunt.registerTask('db', ['db:orm']); | ||
} | ||
// grunt.registerTask( 'readme', 'Displays helpful information', function ( ) { | ||
// console.log( '(Manual) Installation instructions:' ); | ||
// console.log( '1. In the config file for your desired environment (ie. backend/config/local.json), update the clever-orm object with the details for your database.' ); | ||
// console.log( '' ); | ||
// console.log( '2. From your project\'s `backend` folder, run `NODE_ENV=local grunt db`.' ); | ||
// console.log( 'The database tables for your modules should now be installed and seeded with data!' ); | ||
// } ); | ||
// grunt.registerTask('readme', 'Displays helpful information', function () { | ||
// console.log('(Manual) Installation instructions:'); | ||
// console.log('1. In the config file for your desired environment (ie. backend/config/local.json), update the clever-orm object with the details for your database.'); | ||
// console.log(''); | ||
// console.log('2. From your project\'s `backend` folder, run `NODE_ENV=local grunt db`.'); | ||
// console.log('The database tables for your modules should now be installed and seeded with data!'); | ||
// }); | ||
grunt.registerTask( 'prompt:cleverOrmConfig', [ 'prompt:cleverOrmConfigPrompt', 'cleverOrmCreateConfig' ] ); | ||
grunt.registerTask( 'cleverOrmCreateConfig', 'Creates a .json config file for database credentials', function ( ) { | ||
var conf = grunt.config( 'cleverstackorm' ) | ||
, obj = require( path.resolve( path.join( process.cwd(), 'modules', 'clever-orm', 'config', 'default.json' ) ) ) | ||
, env = process.env.NODE_ENV ? process.env.NODE_ENV.toLowerCase() : 'local' | ||
, file = path.join( process.cwd( ), 'config', env + '.json' ); | ||
grunt.registerTask('prompt:cleverOrmConfig', ['prompt:cleverOrmConfigPrompt', 'cleverOrmCreateConfig']); | ||
grunt.registerTask('cleverOrmCreateConfig', 'Creates a .json config file for database credentials', function () { | ||
var conf = grunt.config('cleverstackorm') | ||
, obj = require(path.resolve(path.join(process.cwd(), 'modules', 'clever-orm', 'config', 'default.json'))) | ||
, env = process.env.NODE_ENV ? process.env.NODE_ENV.toLowerCase() : 'local' | ||
, file = path.join(process.cwd(), 'config', env + '.json'); | ||
if ( fs.existsSync( file ) ) { | ||
obj = _.extend( obj, require( file ) ); | ||
} | ||
if (fs.existsSync(file)) { | ||
obj = _.extend(obj, require(file)); | ||
} | ||
obj[ 'clever-orm' ] = obj[ 'clever-orm' ] || {}; | ||
obj['clever-orm'] = obj['clever-orm'] || {}; | ||
Object.keys( conf ).forEach( function ( key ) { | ||
if ([ 'host', 'dialect', 'port' ].indexOf( key ) > -1) { | ||
obj[ 'clever-orm' ].db.options = obj[ 'clever-orm' ].db.options || {}; | ||
obj[ 'clever-orm' ].db.options[ key ] = conf[ key ]; | ||
} else { | ||
obj[ 'clever-orm' ].db[ key ] = conf[ key ]; | ||
} | ||
} ); | ||
Object.keys(conf).forEach(function (key) { | ||
if (['host', 'dialect', 'port'].indexOf(key) > -1) { | ||
obj['clever-orm'].db.options = obj['clever-orm'].db.options || {}; | ||
obj['clever-orm'].db.options[key] = conf[key]; | ||
} else { | ||
obj['clever-orm'].db[key] = conf[key]; | ||
} | ||
}); | ||
fs.writeFileSync( file, JSON.stringify( obj, null, ' ' ) ); | ||
} ); | ||
}]; | ||
fs.writeFileSync(file, JSON.stringify(obj, null, ' ')); | ||
}); | ||
}]; | ||
}; |
770
module.js
@@ -1,528 +0,348 @@ | ||
var injector = require( 'injector' ) | ||
, Sequelize = require( 'sequelize' ) | ||
, Module = require( 'classes' ).Module | ||
, Model = require( 'classes' ).Model | ||
, Promise = require( 'bluebird' ) | ||
, async = require( 'async' ) | ||
, _ = require( 'underscore' ) | ||
, i = require( 'i' )(); | ||
var injector = require('injector') | ||
, Sequelize = require('sequelize') | ||
, path = require('path') | ||
, debug = require('debug') | ||
, Module = injector.getInstance('Module') | ||
, Model = injector.getInstance('Model') | ||
, inflect = injector.getInstance('inflect') | ||
, ormLib = require(path.resolve(path.join(__dirname, 'lib'))); | ||
module.exports = Module.extend({ | ||
module.exports = Module.extend( | ||
{ | ||
models: {}, | ||
models: {}, | ||
/** | ||
* A stored reference to the instance of sequelize that has a database connection | ||
* @type {Sequelize} | ||
*/ | ||
sequelize: null, | ||
sequelize: null, | ||
/** | ||
* preSetup event hook, that gets emitted inside of this.setup() before anything is actually done, | ||
* this forms part of the constructor for this module. | ||
* | ||
* We use this hook to setup a connection to the DB (through sequelize) and to setup any and all | ||
* debugging options that are available. | ||
* | ||
* @return {undefined} | ||
*/ | ||
preSetup: function() { | ||
var dbConfig = this.config.db | ||
, queryLogger = debug('cleverstack:queryLog'); | ||
preSetup: function() { | ||
this.debug( 'Opening database connection to ' + this.config.db.options.dialect + '...' ); | ||
if (!!dbConfig.options.logging || queryLogger.enabled) { | ||
if (!queryLogger.enabled) { | ||
debug.enable('cleverstack:queryLog'); | ||
queryLogger = debug('cleverstack:queryLog') | ||
} | ||
dbConfig.options.logging = queryLogger; | ||
} | ||
if ( !!this.config.db.options.logging ) { | ||
this.config.db.options.logging = console.log; | ||
} | ||
if (this.debug.enabled) { | ||
this.debug('Opening database connection to ' + dbConfig.options.dialect + '...'); | ||
} | ||
this.sequelize = new Sequelize(dbConfig.database, dbConfig.username, dbConfig.password, dbConfig.options); | ||
}, | ||
this.sequelize = new Sequelize( | ||
this.config.db.database, | ||
this.config.db.username, | ||
this.config.db.password, | ||
this.config.db.options | ||
); | ||
}, | ||
/** | ||
* preInit event hook, that gets emitted inside of this.init() before anything is actually done, | ||
* this forms part of the constructor for this module. | ||
* | ||
* We use this hook to add sequelize dependencies into the injector | ||
* | ||
* @return {undefined} | ||
*/ | ||
preInit: function() { | ||
injector.instance('Sequelize', Sequelize); | ||
injector.instance('sequelize', this.sequelize); | ||
}, | ||
preInit: function() { | ||
this.debug( 'Adding Sequelize module and sequelize instance to the injector...' ); | ||
/** | ||
* modulesLoaded event hook, that gets emitted by the ModuleLoader after all modules, | ||
* have loaded, including all of their models, so now we can define all of their associations. | ||
* | ||
* After associating every model with their associated models we must emit the 'ready' event | ||
* so that the ModuleLoader can progress its load() further. | ||
* | ||
* @return {undefined} | ||
*/ | ||
modulesLoaded: function() { | ||
ormLib.model.associations.define.apply(this, [this.config.modelAssociations]); | ||
this.emit('ready'); | ||
}, | ||
injector.instance( 'Sequelize', Sequelize ); | ||
injector.instance( 'sequelize', this.sequelize ); | ||
}, | ||
parseModelSchema: function(Static) { | ||
var parseDebug = this.proxy(function(msg) { | ||
this.debug(Static.modelName + 'Model: ' + msg); | ||
}) | ||
, sequelizeConf = { paranoid: false, timestamps: false } | ||
, fields = {}; | ||
modulesLoaded: function() { | ||
this.defineModelsAssociations(); | ||
this.emit( 'ready' ); | ||
}, | ||
if (this.models[Static.modelName] !== undefined) { | ||
parseDebug('Returning previously parsed and generated model...'); | ||
return this.models[Static.modelName]; | ||
} | ||
defineModelsAssociations: function() { | ||
this.debug( 'Defining model assocations' ); | ||
parseDebug('Parsing schema for model...'); | ||
Object.keys(Static.fields).forEach(this.proxy('defineField', Static, fields)); | ||
parseDebug('Configuring static object for sequelize...'); | ||
Object.keys( this.config.modelAssociations ).forEach( this.proxy( function( modelName ) { | ||
Object.keys( this.config.modelAssociations[ modelName ] ).forEach( this.proxy( 'defineModelAssociations', modelName ) ); | ||
})); | ||
this.setupOptions(parseDebug, sequelizeConf, Static); | ||
var models = require( 'models' ); | ||
this.setupBehaviours(parseDebug, sequelizeConf, Static); | ||
Object.keys( this.models ).forEach( this.proxy( function( modelName ) { | ||
var model = this.models[ modelName ] | ||
, Model = models[ modelName ]; | ||
// @TODO this is a templ hack to get functions available for queries | ||
Static.fn = this.sequelize.fn; | ||
Static.col = this.sequelize.col; | ||
Object.keys( model.associations ).forEach( this.proxy( function( assocationName ) { | ||
var association = model.associations[ assocationName ]; | ||
parseDebug('Setting sequelize as the connection (adapter) for the Model...'); | ||
Static.connection = this.sequelize; | ||
models[ association.source.name ].getters[ association.identifier ] = function() { | ||
if ( association.identifier === 'id' && Model.type.toLowerCase() === 'odm' ) { | ||
return this.entity._id; | ||
} else { | ||
return this.entity[ association.identifier ]; | ||
} | ||
} | ||
parseDebug('Generating new sequelize model using computed schema...'); | ||
var model = this.sequelize.define(Static.modelName, fields, sequelizeConf); | ||
var as = i[ association.associationType === 'HasMany' ? 'pluralize' : 'singularize' ]( association.as ); | ||
models[ association.source.name ].getters[ as ] = function() { | ||
return this.entity[ as ]; | ||
} | ||
parseDebug('Caching completed native model...'); | ||
this.models[Static.modelName] = model; | ||
models[ association.source.name ].setters[ association.identifier ] = | ||
models[ association.source.name ].setters[ as ] = function( val ) { | ||
this.entity[ association.as ] = val; | ||
}; | ||
return model; | ||
}, | ||
Object.keys( association.accessors ).forEach( function( accessorName ) { | ||
var accessor = association.accessors[ accessorName ]; | ||
setupOptions: function(parseDebug, sequelizeConf, Static) { | ||
parseDebug('Setup options...'); | ||
if ( typeof model.DAO.prototype[ accessor ] === 'function' ) { | ||
Model.prototype[ accessor ] = function( where, options ) { | ||
return new Promise( function( resolve, reject ) { | ||
if ( !/has/.test( accessor ) ) { | ||
where = where || {}; | ||
options = options ? _.clone( options ) : {}; | ||
if (Static.dbName !== false ) { | ||
parseDebug('Setting dbName=' + Static.dbName + ' (sequelize tableName option)...'); | ||
sequelizeConf.tableName = Static.dbName; | ||
} | ||
if ( where.entity ) { | ||
where = where.entity; | ||
} else if ( where instanceof Array && where[ 0 ].entity ) { | ||
where = where.map( function( entity ) { | ||
return entity.entity; | ||
}); | ||
} | ||
if (Static.freezeDbName !== false) { | ||
parseDebug('Setting freezeDbName=' + Static.freezeDbName + ' (sequelize freezeTableName option)...'); | ||
sequelizeConf.freezeTableName = Static.freezeDbName; | ||
} | ||
if ( !!options && options.save === false ) { | ||
this.entity[ accessor ]( where, options ); | ||
resolve(this); | ||
} else { | ||
this.entity[ accessor ]( where, options ) | ||
.then( function( entity ) { | ||
if (/set/.test(accessor) && this.entity[ as ]) { | ||
this.entity[ as ].entity = where; | ||
resolve( this ); | ||
} else { | ||
resolve( entity ); | ||
} | ||
}.bind(this)) | ||
.catch( reject ); | ||
} | ||
} else { | ||
this.entity[ accessor ].then( resolve ).catch( reject ); | ||
} | ||
}.bind( this )) | ||
} | ||
} | ||
}); | ||
})); | ||
})); | ||
}, | ||
if (Static.underscored !== undefined) { | ||
parseDebug('Setting underscored=' + Static.underscored + '...'); | ||
sequelizeConf.underscored = Static.underscored; | ||
} | ||
defineModelAssociations: function( modelName, assocType ) { | ||
var associatedWith = this.config.modelAssociations[ modelName ][ assocType ]; | ||
if ( ! associatedWith instanceof Array ) { | ||
associatedWith = [ associatedWith ]; | ||
} | ||
if (Static.engine !== false) { | ||
parseDebug('Setting engine=' + Static.engine + '...'); | ||
sequelizeConf.engine = Static.engine; | ||
} | ||
associatedWith.forEach( this.proxy( 'associateModels', modelName, assocType ) ); | ||
}, | ||
if (Static.charset !== false ) { | ||
parseDebug('Setting charset=' + Static.charset + '...'); | ||
sequelizeConf.charset = Static.charset; | ||
} | ||
associateModels: function( sourceModelName, assocType, assocTo ) { | ||
assocTo = assocTo instanceof Array ? _.clone(assocTo) : [assocTo, {}]; | ||
if (Static.comment !== false ) { | ||
parseDebug('Setting comment=' + Static.comment + '...'); | ||
sequelizeConf.comment = Static.comment; | ||
} | ||
var targetModelName = assocTo.shift() | ||
, associationOptions = assocTo.shift() | ||
, sourceModel = injector.getInstance(sourceModelName + 'Model') | ||
, targetModel = injector.getInstance((associationOptions.through ? associationOptions.through : targetModelName) + 'Model') | ||
, as = associationOptions.as || targetModelName.replace('Model',''); | ||
if (Static.collate !== false ) { | ||
parseDebug('Setting collate=' + Static.collate + '...'); | ||
sequelizeConf.collate = Static.collate; | ||
} | ||
if ( associationOptions.through ) { | ||
associationOptions.through = this.models[ associationOptions.through.replace( 'Model', '' ) ]; | ||
} | ||
if (Static.indexes !== false) { | ||
parseDebug('Setting indexes...'); | ||
sequelizeConf.indexes = Static.indexes; | ||
} | ||
}, | ||
this.debug( '%s %s %s %s', sourceModelName, assocType, targetModelName, associationOptions); | ||
this.models[ sourceModelName ][ assocType ]( this.models[targetModelName], associationOptions ); | ||
setupBehaviours: function(parseDebug, sequelizeConf, Static) { | ||
parseDebug('Setup behaviours...'); | ||
if (associationOptions.autoHooks !== false) { | ||
injector.getInstance('moduleLoader').on( 'routesInitialized', function() { | ||
if (assocType === 'belongsTo') { | ||
sourceModel.on('beforeCreate', function(modelData, queryOptions, callback) { | ||
if (modelData[as] !== undefined && modelData[as].entity === undefined && (typeof modelData[as] !== 'object' || modelData[as][targetModel.primaryKey[0]] === undefined)) { | ||
targetModel | ||
.find(typeof modelData[as] === 'object' ? _.clone(modelData[as]) : modelData[as], queryOptions) | ||
.then(function(instance) { | ||
modelData[as] = instance; | ||
callback(null); | ||
}) | ||
.catch(callback); | ||
} else { | ||
callback(null); | ||
} | ||
}); | ||
if (!!Static.softDeletable) { | ||
parseDebug('is softDeletable (' + Static.deletedAt + ')'); | ||
sourceModel.on('afterCreate', function(instance, modelData, queryOptions, callback) { | ||
if (modelData[as] !== undefined && modelData[as].entity !== undefined) { | ||
instance.entity[as] = modelData[as]; | ||
instance.entity.values[as] = modelData[as]; | ||
sequelizeConf.paranoid = Static.softDeletable; | ||
sequelizeConf.deletedAt = Static.deletedAt; | ||
callback(null); | ||
} else { | ||
callback(null); | ||
} | ||
}); | ||
if (Static.deletedAt !== 'deletedAt') { | ||
Static.aliases.push({ | ||
key : 'deletedAt', | ||
columnName : Static.deletedAt | ||
}); | ||
} | ||
} | ||
// sourceModel.on('beforeUpdate', function(modelData, queryOptions, callback) { | ||
// if (modelData[as] !== undefined && modelData[as].entity === undefined && (typeof modelData[as] !== 'object' || modelData[as][targetModel.primaryKey[0]] === undefined)) { | ||
// targetModel | ||
// .find(typeof modelData[as] === 'object' ? _.clone(modelData[as]) : modelData[as], queryOptions) | ||
// .then(function(instance) { | ||
// modelData[as] = instance; | ||
// callback(null); | ||
// }) | ||
// .catch(callback); | ||
// } else { | ||
// callback(null); | ||
// } | ||
// }); | ||
} else if (assocType === 'hasMany') { | ||
sourceModel.on('afterCreate', function(instance, modelData, queryOptions, callback) { | ||
var association = instance.Class.entity.associations[as]; | ||
if (!!Static.timeStampable) { | ||
parseDebug('is timeStampable (' + Static.timeStampable + ')'); | ||
// handle single association creation via the singular name | ||
// handle multiple association create via the plural name as an array of models | ||
// support nested association hasMany creation (plural and singular) with "Through", findBy ? | ||
// allow mapping of requestFields that will be used for create | ||
// allow definition of finders? | ||
sequelizeConf.timestamps = Static.timeStampable; | ||
sequelizeConf.createdAt = Static.createdAt; | ||
sequelizeConf.updatedAt = Static.updatedAt; | ||
} | ||
}, | ||
if (modelData[as] !== undefined && modelData[as] instanceof Array && modelData[as].length) { | ||
async.map( | ||
modelData[as], | ||
function createNestedHasManyModel(nestedModelData, done) { | ||
var data = _.extend( | ||
typeof nestedModelData === 'object' ? _.clone(nestedModelData) : { label: nestedModelData }, | ||
_.pick(instance, association.options.foreignKey) | ||
); | ||
defineField: function(Static, fields, name) { | ||
var fieldDefinition = {} | ||
, columnName = name | ||
, options = Static.fields[name] | ||
targetModel.create(data, queryOptions).then(function(targetInstance) { | ||
done(null, targetInstance); | ||
}) | ||
.catch(done); | ||
}, | ||
function createdNestedHasManyModels(err, associations) { | ||
if (!err) { | ||
instance.entity[as] = associations; | ||
instance.entity.values[as] = associations; | ||
// Allow direct syntax | ||
if (typeof options !== 'object' || options instanceof Array) { | ||
options = { | ||
type: options | ||
} | ||
} | ||
callback(null); | ||
} else { | ||
callback(err); | ||
} | ||
} | ||
); | ||
} else { | ||
callback(null); | ||
} | ||
}); | ||
// Handle array of "Something" | ||
if (options.type instanceof Array || options.type === Array) { | ||
options.of = (options.type.length > 0 && options.type[0] !== undefined) ? options.type[0] : String; | ||
options.type = Array; | ||
} | ||
// sourceModel.on('afterUpdate') | ||
} else if (assocType === 'hasOne') { | ||
sourceModel.on('afterCreate', function(instance, modelData, queryOptions, callback) { | ||
var association = instance.Class.entity.associations[as]; | ||
// Get the type | ||
fieldDefinition.type = this.getFieldType(Static, options, name); | ||
if (modelData[as] !== undefined && modelData[as].entity === undefined && typeof modelData[as] === 'object') { | ||
var data = _.extend( | ||
typeof modelData[as] === 'object' ? _.clone(modelData[as]) : { label: modelData[as] }, | ||
_.pick(instance, association.options.foreignKey) | ||
); | ||
if (options.columnName) { | ||
columnName = options.columnName; | ||
options.field = columnName; | ||
} else if (!!Static.underscored && inflect.underscore(name).split('_').length > 1) { | ||
columnName = inflect.underscore(name); | ||
options.field = columnName; | ||
} | ||
targetModel.create(data, queryOptions).then(function(targetInstance) { | ||
instance.entity[as] = targetInstance; | ||
instance.entity.values[as] = targetInstance; | ||
callback(null); | ||
}) | ||
.catch(callback); | ||
} else { | ||
callback(null); | ||
} | ||
}); | ||
} | ||
}); | ||
// Handle options | ||
['allowNull', 'primaryKey', 'autoIncrement', 'unique', 'default', 'comment'].forEach(function(optionName) { | ||
if (options[optionName] !== undefined) { | ||
if (optionName === 'primaryKey') { | ||
Static.primaryKeys.push(name); | ||
if (!Static.primaryKey) { | ||
Static.hasPrimaryKey = true; | ||
Static.singlePrimaryKey = true; | ||
Static.primaryKey = name; | ||
} else { | ||
Static.singlePrimaryKey = false; | ||
} | ||
} | ||
}, | ||
parseModelSchema: function( Static ) { | ||
var parseDebug = this.proxy(function( msg ) { | ||
this.debug( Static.modelName + 'Model: ' + msg ); | ||
}) | ||
, sequelizeConf = { paranoid: false, timestamps: false } | ||
, fields = {}; | ||
fieldDefinition[optionName === 'default' ? 'defaultValue' : optionName] = options[optionName]; | ||
} | ||
}); | ||
if ( this.models[ Static.modelName ] !== undefined ) { | ||
parseDebug( 'Returning previously parsed and generated model...' ); | ||
return this.models[ Static.modelName ]; | ||
} | ||
fields[columnName] = fieldDefinition; | ||
}, | ||
parseDebug( 'Parsing schema for model...' ); | ||
Object.keys( Static.fields ).forEach( this.proxy( 'defineField', Static, fields ) ); | ||
parseDebug( 'Configuring static object for sequelize...' ); | ||
getFieldType: function(Static, options, name) { | ||
var field; | ||
this.setupOptions( parseDebug, sequelizeConf, Static ); | ||
switch(options.type.type || options.type) { | ||
this.setupBehaviours( parseDebug, sequelizeConf, Static ); | ||
case Number: | ||
field = this.numberType(options); | ||
break; | ||
case String: | ||
if (options.length) { | ||
field = Sequelize.STRING(options.length); | ||
} else { | ||
field = Sequelize.STRING; | ||
} | ||
break; | ||
case Boolean: | ||
field = Sequelize.BOOLEAN; | ||
break; | ||
case Date: | ||
field = Sequelize.DATE; | ||
break; | ||
case Array: | ||
field = options.of ? Sequelize.ARRAY(this.getFieldType(Static, { type: options.of })) : Sequelize.ARRAY(Sequelize.STRING); | ||
break; | ||
case Buffer: | ||
field = Sequelize.STRING.BINARY; | ||
break; | ||
case Model.Types.ENUM: | ||
field = Sequelize.ENUM(options.values); | ||
break; | ||
case Model.Types.TINYINT: | ||
field = this.tinyIntType(options); | ||
break; | ||
case Model.Types.BIGINT: | ||
field = this.bigIntType(options); | ||
break; | ||
case Model.Types.FLOAT: | ||
field = this.floatType(options); | ||
break; | ||
case Model.Types.DECIMAL: | ||
field = this.decimalType(options); | ||
break; | ||
case Model.Types.TEXT: | ||
field = Sequelize.TEXT; | ||
break; | ||
case undefined: | ||
throw new Error(['You must define the type of field that', '"' + name + '"', 'is on the', '"' + Static.modelName + '" model'].join(' ')); | ||
default: | ||
throw new Error(['You must define a valid type for the field named', '"' + name + '"', 'on the', '"' + Static.modelName + '" model'].join(' ')); | ||
} | ||
// @TODO this is a templ hack to get functions available for queries | ||
Static.fn = this.sequelize.fn; | ||
Static.col = this.sequelize.col; | ||
return field; | ||
}, | ||
parseDebug( 'Setting sequelize as the connection (adapter) for the Model...' ); | ||
Static.connection = this.sequelize; | ||
numberType: function(options) { | ||
var field = !!options.length ? Sequelize.INTEGER(options.length) : Sequelize.INTEGER; | ||
if (!!options.unsigned && !!options.zerofill) { | ||
field = field.UNSIGNED.ZEROFILL; | ||
} else if (!!options.unsigned && !options.zerofill) { | ||
field = field.UNSIGNED; | ||
} else if (!options.unsigned && !!options.zerofill) { | ||
field = field.ZEROFILL; | ||
} | ||
return field; | ||
}, | ||
parseDebug( 'Generating new sequelize model using computed schema...' ); | ||
var model = this.sequelize.define( Static.modelName, fields, sequelizeConf ); | ||
tinyIntType: function(options) { | ||
var field = !!options.length ? 'TINYINT(' + options.length + ')' : 'TINYINT'; | ||
if (!!options.unsigned && !!options.zerofill) { | ||
field += ' UNSIGNED ZEROFILL'; | ||
} else if (!!options.unsigned && !options.zerofill) { | ||
field += ' UNSIGNED'; | ||
} else if (!options.unsigned && !!options.zerofill) { | ||
field += ' ZEROFILL'; | ||
} | ||
return field; | ||
}, | ||
parseDebug( 'Caching completed native model...' ); | ||
this.models[ Static.modelName ] = model; | ||
bigIntType: function(options) { | ||
var field = !!options.length ? Sequelize.BIGINT(options.length) : Sequelize.BIGINT; | ||
if (!!options.unsigned && !!options.zerofill) { | ||
field = field.UNSIGNED.ZEROFILL; | ||
} else if (!!options.unsigned && !options.zerofill) { | ||
field = field.UNSIGNED; | ||
} else if (!options.unsigned && !!options.zerofill) { | ||
field = field.ZEROFILL; | ||
} | ||
return field; | ||
}, | ||
return model; | ||
}, | ||
floatType: function(options) { | ||
var field = Sequelize.FLOAT; | ||
if (!!options.decimals) { | ||
field = Sequelize.FLOAT(options.length, options.decimals); | ||
} else if (!!options.length) { | ||
field = Sequelize.FLOAT(options.length); | ||
} | ||
setupOptions: function( parseDebug, sequelizeConf, Static ) { | ||
parseDebug( 'Setup options...' ); | ||
if (!!options.unsigned && !!options.zerofill) { | ||
field = field.UNSIGNED.ZEROFILL; | ||
} else if (!!options.unsigned && !options.zerofill) { | ||
field = field.UNSIGNED; | ||
} else if (!options.unsigned && !!options.zerofill) { | ||
field = field.ZEROFILL; | ||
} | ||
return field; | ||
}, | ||
if ( Static.dbName !== false ) { | ||
parseDebug( 'Setting dbName=' + Static.dbName + ' (sequelize tableName option)...' ); | ||
sequelizeConf.tableName = Static.dbName; | ||
} | ||
if ( Static.freezeDbName !== false ) { | ||
parseDebug( 'Setting freezeDbName=' + Static.freezeDbName + ' (sequelize freezeTableName option)...' ); | ||
sequelizeConf.freezeTableName = Static.freezeDbName; | ||
} | ||
if ( Static.underscored !== undefined ) { | ||
parseDebug( 'Setting underscored=' + Static.underscored + '...' ); | ||
sequelizeConf.underscored = Static.underscored; | ||
} | ||
if ( Static.engine !== false ) { | ||
parseDebug( 'Setting engine=' + Static.engine + '...' ); | ||
sequelizeConf.engine = Static.engine; | ||
} | ||
if ( Static.charset !== false ) { | ||
parseDebug( 'Setting charset=' + Static.charset + '...' ); | ||
sequelizeConf.charset = Static.charset; | ||
} | ||
if ( Static.comment !== false ) { | ||
parseDebug( 'Setting comment=' + Static.comment + '...' ); | ||
sequelizeConf.comment = Static.comment; | ||
} | ||
if ( Static.collate !== false ) { | ||
parseDebug( 'Setting collate=' + Static.collate + '...' ); | ||
sequelizeConf.collate = Static.collate; | ||
} | ||
if ( Static.indexes !== false ) { | ||
parseDebug( 'Setting indexes...' ); | ||
sequelizeConf.indexes = Static.indexes; | ||
} | ||
}, | ||
setupBehaviours: function( parseDebug, sequelizeConf, Static ) { | ||
parseDebug( 'Setup behaviours...' ); | ||
if ( !!Static.softDeletable ) { | ||
parseDebug( 'is softDeletable (' + Static.deletedAt + ')' ); | ||
sequelizeConf.paranoid = Static.softDeletable; | ||
sequelizeConf.deletedAt = Static.deletedAt; | ||
if ( Static.deletedAt !== 'deletedAt' ) { | ||
Static.aliases.push({ | ||
key : 'deletedAt', | ||
columnName : Static.deletedAt | ||
}); | ||
} | ||
} | ||
if ( !!Static.timeStampable ) { | ||
parseDebug( 'is timeStampable (' + Static.timeStampable + ')' ); | ||
sequelizeConf.timestamps = Static.timeStampable; | ||
sequelizeConf.createdAt = Static.createdAt; | ||
sequelizeConf.updatedAt = Static.updatedAt; | ||
} | ||
}, | ||
defineField: function( Static, fields, name ) { | ||
var fieldDefinition = {} | ||
, columnName = name | ||
, options = Static.fields[ name ] | ||
// Allow direct syntax | ||
if ( typeof options !== 'object' || options instanceof Array ) { | ||
options = { | ||
type: options | ||
} | ||
} | ||
// Handle array of "Something" | ||
if ( options.type instanceof Array || options.type === Array ) { | ||
options.of = ( options.type.length > 0 && options.type[ 0 ] !== undefined ) ? options.type[ 0 ] : String; | ||
options.type = Array; | ||
} | ||
// Get the type | ||
fieldDefinition.type = this.getFieldType( Static, options, name ); | ||
if ( options.columnName ) { | ||
columnName = options.columnName; | ||
options.field = columnName; | ||
} else if ( !!Static.underscored && i.underscore( name ).split( '_' ).length > 1 ) { | ||
columnName = i.underscore( name ); | ||
options.field = columnName; | ||
} | ||
// Handle options | ||
[ 'allowNull', 'primaryKey', 'autoIncrement', 'unique', 'default', 'comment' ].forEach(function( optionName ) { | ||
if ( options[ optionName ] !== undefined ) { | ||
if ( optionName === 'primaryKey' ) { | ||
Static.primaryKeys.push( name ); | ||
if (!Static.primaryKey) { | ||
Static.hasPrimaryKey = true; | ||
Static.singlePrimaryKey = true; | ||
Static.primaryKey = name; | ||
} else { | ||
Static.singlePrimaryKey = false; | ||
} | ||
} | ||
fieldDefinition[ optionName === 'default' ? 'defaultValue' : optionName ] = options[ optionName ]; | ||
} | ||
}); | ||
fields[ columnName ] = fieldDefinition; | ||
}, | ||
getFieldType: function( Static, options, name ) { | ||
var field; | ||
switch( options.type.type || options.type ) { | ||
case Number: | ||
field = this.numberType( options ); | ||
break; | ||
case String: | ||
if ( options.length ) { | ||
field = Sequelize.STRING( options.length ); | ||
} else { | ||
field = Sequelize.STRING; | ||
} | ||
break; | ||
case Boolean: | ||
field = Sequelize.BOOLEAN; | ||
break; | ||
case Date: | ||
field = Sequelize.DATE; | ||
break; | ||
case Array: | ||
field = options.of ? Sequelize.ARRAY( this.getFieldType( Static, { type: options.of } ) ) : Sequelize.ARRAY( Sequelize.STRING ); | ||
break; | ||
case Buffer: | ||
field = Sequelize.STRING.BINARY; | ||
break; | ||
case Model.Types.ENUM: | ||
field = Sequelize.ENUM( options.values ); | ||
break; | ||
case Model.Types.TINYINT: | ||
field = this.tinyIntType( options ); | ||
break; | ||
case Model.Types.BIGINT: | ||
field = this.bigIntType( options ); | ||
break; | ||
case Model.Types.FLOAT: | ||
field = this.floatType( options ); | ||
break; | ||
case Model.Types.DECIMAL: | ||
field = this.decimalType( options ); | ||
break; | ||
case Model.Types.TEXT: | ||
field = Sequelize.TEXT; | ||
break; | ||
case undefined: | ||
throw new Error( [ 'You must define the type of field that', '"' + name + '"', 'is on the', '"' + Static.modelName + '" model' ].join( ' ' ) ); | ||
default: | ||
throw new Error( [ 'You must define a valid type for the field named', '"' + name + '"', 'on the', '"' + Static.modelName + '" model' ].join( ' ' ) ); | ||
} | ||
return field; | ||
}, | ||
numberType: function( options ) { | ||
var field = !!options.length ? Sequelize.INTEGER( options.length ) : Sequelize.INTEGER; | ||
if ( !!options.unsigned && !!options.zerofill ) { | ||
field = field.UNSIGNED.ZEROFILL; | ||
} else if ( !!options.unsigned && !options.zerofill ) { | ||
field = field.UNSIGNED; | ||
} else if ( !options.unsigned && !!options.zerofill ) { | ||
field = field.ZEROFILL; | ||
} | ||
return field; | ||
}, | ||
tinyIntType: function( options ) { | ||
var field = !!options.length ? 'TINYINT(' + options.length + ')' : 'TINYINT'; | ||
if ( !!options.unsigned && !!options.zerofill ) { | ||
field += ' UNSIGNED ZEROFILL'; | ||
} else if ( !!options.unsigned && !options.zerofill ) { | ||
field += ' UNSIGNED'; | ||
} else if ( !options.unsigned && !!options.zerofill ) { | ||
field += ' ZEROFILL'; | ||
} | ||
return field; | ||
}, | ||
bigIntType: function( options ) { | ||
var field = !!options.length ? Sequelize.BIGINT( options.length ) : Sequelize.BIGINT; | ||
if ( !!options.unsigned && !!options.zerofill ) { | ||
field = field.UNSIGNED.ZEROFILL; | ||
} else if ( !!options.unsigned && !options.zerofill ) { | ||
field = field.UNSIGNED; | ||
} else if ( !options.unsigned && !!options.zerofill ) { | ||
field = field.ZEROFILL; | ||
} | ||
return field; | ||
}, | ||
floatType: function( options ) { | ||
var field = Sequelize.FLOAT; | ||
if ( !!options.decimals ) { | ||
field = Sequelize.FLOAT( options.length, options.decimals ); | ||
} else if ( !!options.length ) { | ||
field = Sequelize.FLOAT( options.length ); | ||
} | ||
if ( !!options.unsigned && !!options.zerofill ) { | ||
field = field.UNSIGNED.ZEROFILL; | ||
} else if ( !!options.unsigned && !options.zerofill ) { | ||
field = field.UNSIGNED; | ||
} else if ( !options.unsigned && !!options.zerofill ) { | ||
field = field.ZEROFILL; | ||
} | ||
return field; | ||
}, | ||
decimalType: function( options ) { | ||
var field = Sequelize.DECIMAL; | ||
if ( !!options.scale ) { | ||
field = Sequelize.DECIMAL( options.precision, options.scale ); | ||
} else if ( !!options.precision ) { | ||
field = Sequelize.DECIMAL( options.precision ); | ||
} | ||
return field; | ||
decimalType: function(options) { | ||
var field = Sequelize.DECIMAL; | ||
if (!!options.scale) { | ||
field = Sequelize.DECIMAL(options.precision, options.scale); | ||
} else if (!!options.precision) { | ||
field = Sequelize.DECIMAL(options.precision); | ||
} | ||
return field; | ||
} | ||
}); |
{ | ||
"name": "clever-orm", | ||
"description": "CleverStack ORM (SQL) Module", | ||
"version": "1.2.3", | ||
"main": "module.js", | ||
"author": { | ||
"name": "CleverStack", | ||
"email": "admin@cleverstack.io", | ||
"web": "http://cleverstack.io" | ||
}, | ||
"collaborators": [ | ||
"Richard Gustin <richard.gustin86@gmail.com>" | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/CleverStack/clever-orm.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/CleverStack/clever-orm/issues" | ||
}, | ||
"keywords": [ | ||
"cleverstack", | ||
"cleverstack-module", | ||
"cleverstack-backend", | ||
"orm", | ||
"sequelize", | ||
"backend", | ||
"mysql", | ||
"postgre", | ||
"sqlite", | ||
"dao", | ||
"object", | ||
"relational", | ||
"mapper" | ||
], | ||
"license": "BSD-2-Clause", | ||
"dependencies": { | ||
"mysql": "2.0.0-rc2", | ||
"sequelize": "2.0.3" | ||
}, | ||
"devDependencies": { | ||
"grunt": "~0.4.2", | ||
"grunt-prompt": "~1.3.0" | ||
}, | ||
"scripts": { | ||
"test": "grunt test:unit" | ||
} | ||
"name": "clever-orm", | ||
"description": "CleverStack ORM (SQL) Module", | ||
"version": "2.0.0-rc1", | ||
"main": "module.js", | ||
"author": { | ||
"name": "CleverStack", | ||
"email": "admin@cleverstack.io", | ||
"web": "http://cleverstack.io" | ||
}, | ||
"collaborators": [ | ||
"Richard Gustin <richard.gustin86@gmail.com>" | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/CleverStack/clever-orm.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/CleverStack/clever-orm/issues" | ||
}, | ||
"keywords": [ | ||
"cleverstack", | ||
"cleverstack-module", | ||
"cleverstack-backend", | ||
"orm", | ||
"sequelize", | ||
"backend", | ||
"mysql", | ||
"postgre", | ||
"sqlite", | ||
"dao", | ||
"object", | ||
"relational", | ||
"mapper" | ||
], | ||
"license": "BSD-2-Clause", | ||
"dependencies": { | ||
"mysql": "2.0.0-rc2", | ||
"sequelize": "2.0.3" | ||
}, | ||
"devDependencies": { | ||
"grunt": "~0.4.2", | ||
"grunt-prompt": "~1.3.0" | ||
}, | ||
"scripts": { | ||
"test": "grunt test:unit" | ||
} | ||
} |
@@ -1,37 +0,37 @@ | ||
module.exports = function ( Model, config ) { | ||
return Model.extend( 'Orm', | ||
{ | ||
type: 'ORM', | ||
softDeleteable: true, | ||
timeStampable: true | ||
module.exports = function(Model) { | ||
return Model.extend('Orm', | ||
{ | ||
type: 'ORM', | ||
softDeleteable: true, | ||
timeStampable: true | ||
}, | ||
{ | ||
id: { | ||
type: Number, | ||
primaryKey: true, | ||
autoIncrement: true | ||
}, | ||
{ | ||
id: { | ||
type: Number, | ||
primaryKey: true, | ||
autoIncrement: true | ||
}, | ||
str: String, | ||
bool: Boolean, | ||
date: Date, | ||
enum: Model.Types.ENUM( 'test' ), | ||
enumObj: { | ||
type: Model.Types.ENUM, | ||
values: [ 'test' ] | ||
}, | ||
buf: Buffer, | ||
bigint: Model.Types.BIGINT, | ||
bigintLen: Model.Types.BIGINT( 11 ), | ||
float: Model.Types.FLOAT, | ||
floatLen: Model.Types.FLOAT( 11 ), | ||
floatLenAndDec: Model.Types.FLOAT( 11, 10 ), | ||
dec: Model.Types.DECIMAL, | ||
decPrec: Model.Types.DECIMAL( 11 ), | ||
decPrecAndScale: Model.Types.DECIMAL( 10, 2 ), | ||
text: Model.Types.TEXT, | ||
textObj: { | ||
type: Model.Types.TEXT, | ||
required: true | ||
} | ||
}); | ||
str: String, | ||
bool: Boolean, | ||
date: Date, | ||
enum: Model.Types.ENUM('test'), | ||
enumObj: { | ||
type: Model.Types.ENUM, | ||
values: ['test'] | ||
}, | ||
buf: Buffer, | ||
bigint: Model.Types.BIGINT, | ||
bigintLen: Model.Types.BIGINT(11), | ||
float: Model.Types.FLOAT, | ||
floatLen: Model.Types.FLOAT(11), | ||
floatLenAndDec: Model.Types.FLOAT(11, 10), | ||
dec: Model.Types.DECIMAL, | ||
decPrec: Model.Types.DECIMAL(11), | ||
decPrecAndScale: Model.Types.DECIMAL(10, 2), | ||
text: Model.Types.TEXT, | ||
textObj: { | ||
type: Model.Types.TEXT, | ||
required: true | ||
} | ||
}); | ||
}; |
@@ -10,231 +10,232 @@ var Promise = require( 'bluebird' ) | ||
function createProject() { | ||
return new Promise( function( resolve, reject ) { | ||
var proc = spawn ( 'clever', [ 'init', '-f', '-A', prName, 'backend' ] ); | ||
return new Promise( function( resolve, reject ) { | ||
var proc = spawn ( 'clever', [ 'init', '-f', '-A', prName, 'backend' ] ); | ||
console.log( 'step #1 - create test project - begin\n' ); | ||
console.log( 'step #1 - create test project - begin\n' ); | ||
proc.stdout.on('data', function ( data ) { | ||
var str = data.toString(); | ||
proc.stdout.on('data', function ( data ) { | ||
var str = data.toString(); | ||
if ( str.match( /ing/ ) !== null ) { | ||
console.log( str ) | ||
} | ||
}); | ||
if ( str.match( /ing/ ) !== null ) { | ||
console.log( str ) | ||
} | ||
}); | ||
proc.stderr.on('data', function ( data ) { | ||
console.log( 'Error in step #1 - ' + data.toString() + '\n' ); | ||
reject ( data.toString() ); | ||
}); | ||
proc.stderr.on('data', function ( data ) { | ||
console.log( 'Error in step #1 - ' + data.toString() + '\n' ); | ||
reject ( data.toString() ); | ||
}); | ||
proc.on( 'close', function ( code ) { | ||
console.log('step #1 process exited with code ' + code + '\n'); | ||
resolve(); | ||
}); | ||
proc.on( 'close', function ( code ) { | ||
console.log('step #1 process exited with code ' + code + '\n'); | ||
resolve(); | ||
}); | ||
}); | ||
} | ||
function copyOrmModule() { | ||
return new Promise( function( resolve, reject ) { | ||
var pkgJson = path.join( __dirname, '../', prName, 'package.json' ) | ||
, fromDir = path.join( __dirname, '../' ) | ||
, toDir = path.join( __dirname, '../', prName, 'modules', 'clever-orm' ); | ||
return new Promise( function( resolve, reject ) { | ||
var pkgJson = path.join( __dirname, '../', prName, 'package.json' ) | ||
, fromDir = path.join( __dirname, '../' ) | ||
, toDir = path.join( __dirname, '../', prName, 'modules', 'clever-orm' ); | ||
console.log( 'step #2 - copy clever-orm module in test project - begin\n' ); | ||
console.log( 'step #2 - copy clever-orm module in test project - begin\n' ); | ||
function copyDir ( from, to ) { | ||
var files = fs.readdirSync( from ); | ||
function copyDir ( from, to ) { | ||
var files = fs.readdirSync( from ); | ||
if ( !fs.existsSync( to ) ) { | ||
fs.mkdir( to, function ( err ) { | ||
if ( err ) { | ||
console.log( 'error - ' + err) | ||
} | ||
}) | ||
} | ||
if ( !fs.existsSync( to ) ) { | ||
fs.mkdir( to, function ( err ) { | ||
if ( err ) { | ||
console.log( 'error - ' + err) | ||
} | ||
}) | ||
} | ||
files.forEach ( function ( file ) { | ||
fs.stat( path.join( from, file ), function ( err, stats ) { | ||
if ( err ) { | ||
console.log( 'Error in step #2 - ' + err + '\n'); | ||
reject ( err ); | ||
} | ||
files.forEach ( function ( file ) { | ||
fs.stat( path.join( from, file ), function ( err, stats ) { | ||
if ( err ) { | ||
console.log( 'Error in step #2 - ' + err + '\n'); | ||
reject ( err ); | ||
} | ||
if ( stats && stats.isFile() ) { | ||
copyFile ( path.join( from, file ), path.join( to, file ) ); | ||
} | ||
if ( stats && stats.isFile() ) { | ||
copyFile ( path.join( from, file ), path.join( to, file ) ); | ||
} | ||
if ( stats && stats.isDirectory() && file != prName ) { | ||
ncp( path.join( from, file ), path.join( to, file ), function ( err ) { | ||
if (err) { | ||
console.log( 'Error in step #2 - ' + err + '\n'); | ||
reject ( err ); | ||
} | ||
}); | ||
} | ||
}) | ||
}) | ||
} | ||
function copyFile ( from, to ) { | ||
var rs = fs.createReadStream( from ) | ||
, ws = fs.createWriteStream( to ); | ||
rs.on( 'error', function( err ) { | ||
console.log( err ); | ||
if ( stats && stats.isDirectory() && file != prName ) { | ||
ncp( path.join( from, file ), path.join( to, file ), function ( err ) { | ||
if (err) { | ||
console.log( 'Error in step #2 - ' + err + '\n'); | ||
reject ( err ); | ||
} | ||
}); | ||
} | ||
}) | ||
}) | ||
} | ||
ws.on( 'error', function(err) { | ||
console.log( err ); | ||
}); | ||
rs.pipe( ws ); | ||
} | ||
function copyFile ( from, to ) { | ||
var rs = fs.createReadStream( from ) | ||
, ws = fs.createWriteStream( to ); | ||
rs.on( 'error', function( err ) { | ||
console.log( err ); | ||
}); | ||
copyDir( fromDir, toDir ); | ||
ws.on( 'error', function(err) { | ||
console.log( err ); | ||
}); | ||
rs.pipe( ws ); | ||
} | ||
var packageJson = require( pkgJson ); | ||
if ( packageJson.bundledDependencies.indexOf( 'clever-orm' ) === -1 ) { | ||
packageJson.bundledDependencies.push( 'clever-orm' ); | ||
fs.writeFile( pkgJson, JSON.stringify( packageJson, null, ' ' ), function( e ) { | ||
if ( !!e ) { | ||
console.log( 'Error in step #2 - ' + e + '\n'); | ||
reject( e ); | ||
} else { | ||
console.log( 'step #2 - completed' ); | ||
resolve(); | ||
} | ||
}); | ||
copyDir( fromDir, toDir ); | ||
var packageJson = require( pkgJson ); | ||
if ( packageJson.bundledDependencies.indexOf( 'clever-orm' ) === -1 ) { | ||
packageJson.bundledDependencies.push( 'clever-orm' ); | ||
fs.writeFile( pkgJson, JSON.stringify( packageJson, null, ' ' ), function( e ) { | ||
if ( !!e ) { | ||
console.log( 'Error in step #2 - ' + e + '\n'); | ||
reject( e ); | ||
} else { | ||
console.log( 'step #2 - completed' ); | ||
resolve(); | ||
console.log( 'step #2 - completed' ); | ||
resolve(); | ||
} | ||
}); | ||
}); | ||
} else { | ||
console.log( 'step #2 - completed' ); | ||
resolve(); | ||
} | ||
}); | ||
} | ||
function cleverSetup() { | ||
return new Promise( function( resolve, reject ) { | ||
var proc = spawn ( 'clever', [ 'setup' ], { cwd: path.resolve( path.join( __dirname, '..', prName ) ) } ); | ||
console.log( 'step #3 - clever setup' ); | ||
return new Promise( function( resolve, reject ) { | ||
var proc = spawn ( 'clever', [ 'setup' ], { cwd: path.resolve( path.join( __dirname, '..', prName ) ) } ); | ||
console.log( 'step #3 - clever setup' ); | ||
proc.stderr.on('data', function (data) { | ||
console.log( 'Error in step #3 - ' + data.toString() + '\n'); | ||
reject ( data.toString() ); | ||
}); | ||
proc.stderr.on('data', function (data) { | ||
console.log( 'Error in step #3 - ' + data.toString() + '\n'); | ||
reject ( data.toString() ); | ||
}); | ||
proc.on('close', function (code) { | ||
console.log('step #3 process exited with code ' + code + '\n' ); | ||
resolve(); | ||
}); | ||
proc.on('close', function (code) { | ||
console.log('step #3 process exited with code ' + code + '\n' ); | ||
resolve(); | ||
}); | ||
}); | ||
} | ||
function configureOrmModule() { | ||
return new Promise( function( resolve, reject ) { | ||
var objs = [ | ||
{ reg: /Database username/ , write: 'travis\n' , done: false }, | ||
{ reg: /Database password/ , write: '\n' , done: false }, | ||
{ reg: /Database name/ , write: 'test_db\n' , done: false }, | ||
{ reg: /Database dialect/ , write: '\n' , done: false }, | ||
{ reg: /Database port/ , write: '3306\n' , done: false }, | ||
{ reg: /Database host/ , write: '127.0.0.1\n', done: false }, | ||
] | ||
, proc = spawn ( 'grunt', [ 'prompt:cleverOrmConfig' ], { cwd: path.resolve( path.join( __dirname, '..', prName ) ) } ); | ||
return new Promise( function( resolve, reject ) { | ||
var objs = [ | ||
{ reg: /What environment is this configuration for\?/, write: '\n', done: false }, | ||
{ reg: /Database username/ , write: 'travis\n' , done: false }, | ||
{ reg: /Database password/ , write: '\n' , done: false }, | ||
{ reg: /Database name/ , write: 'test_db\n' , done: false }, | ||
{ reg: /Database dialect/ , write: 'mysql\n' , done: false }, | ||
{ reg: /Database host/ , write: '127.0.0.1\n', done: false }, | ||
{ reg: /Database port/ , write: '3306\n' , done: false }, | ||
] | ||
, proc = spawn ( 'grunt', [ 'prompt:cleverOrmConfig' ], { cwd: path.resolve( path.join( __dirname, '..', prName ) ) } ); | ||
console.log( 'step #4 - install clever-orm module - begin\n' ); | ||
console.log( 'step #4 - install clever-orm module - begin\n' ); | ||
proc.stdout.on('data', function (data) { | ||
var str = data.toString(); | ||
proc.stdout.on('data', function (data) { | ||
var str = data.toString(); | ||
if ( str.match( /ing/ ) !== null ) { | ||
console.log( str ) | ||
} | ||
if ( str.match( /ing/ ) !== null ) { | ||
console.log( str ) | ||
} | ||
objs.forEach ( function ( obj, i ) { | ||
if ( obj.done !== true && str.match( obj.reg ) !== null ) { | ||
objs[i].done = true; | ||
proc.stdin.write( obj.write ); | ||
} | ||
}); | ||
}); | ||
objs.forEach ( function ( obj, i ) { | ||
if ( obj.done !== true && str.match( obj.reg ) !== null ) { | ||
objs[i].done = true; | ||
proc.stdin.write( obj.write ); | ||
} | ||
}); | ||
}); | ||
proc.stderr.on('data', function (data) { | ||
console.log( 'Error in step #4 - ' + data.toString() + '\n'); | ||
reject ( data.toString() ); | ||
}); | ||
proc.stderr.on('data', function (data) { | ||
console.log( 'Error in step #4 - ' + data.toString() + '\n'); | ||
reject ( data.toString() ); | ||
}); | ||
proc.on('close', function (code) { | ||
console.log('step #4 process exited with code ' + code + '\n' ); | ||
resolve(); | ||
}); | ||
proc.on('close', function (code) { | ||
console.log('step #4 process exited with code ' + code + '\n' ); | ||
resolve(); | ||
}); | ||
}); | ||
} | ||
function installTestModule() { | ||
return new Promise( function( resolve, reject ) { | ||
var pkgJson = path.resolve( path.join( __dirname, '..', prName, 'package.json' ) ) | ||
, packageJson = require( pkgJson ) | ||
, source = path.resolve( path.join( __dirname, '..', prName, 'tests', 'unit', 'test-module' ) ) | ||
, dest = path.resolve( path.join( __dirname, '..', prName, 'modules', 'test-module' ) ); | ||
return new Promise( function( resolve, reject ) { | ||
var pkgJson = path.resolve( path.join( __dirname, '..', prName, 'package.json' ) ) | ||
, packageJson = require( pkgJson ) | ||
, source = path.resolve( path.join( __dirname, '..', prName, 'tests', 'unit', 'test-module' ) ) | ||
, dest = path.resolve( path.join( __dirname, '..', prName, 'modules', 'test-module' ) ); | ||
console.log( 'step #5 - install test-module and add to bundledDependencies - begin' ); | ||
console.log( 'step #5 - install test-module and add to bundledDependencies - begin' ); | ||
rimraf( dest, function( e ) { | ||
if ( e === null ) { | ||
ncp( source, dest, function( err ) { | ||
if ( err !== null ) { | ||
console.log( 'Error in step #5 - ' + err + '\n'); | ||
reject( e ); | ||
} else if ( packageJson.bundledDependencies.indexOf( 'test-module' ) === -1 ) { | ||
packageJson.bundledDependencies.push( 'test-module' ); | ||
fs.writeFile( pkgJson, JSON.stringify( packageJson, null, ' ' ), function( e ) { | ||
if ( !!e ) { | ||
console.log( 'Error in step #5 - ' + e + '\n'); | ||
reject( e ); | ||
} else { | ||
console.log( 'step #5 - completed' ); | ||
resolve(); | ||
} | ||
}); | ||
} else { | ||
console.log( 'step #5 - completed' ); | ||
resolve(); | ||
} | ||
}); | ||
} else { | ||
console.log( 'Error in step #5 - ' + e + '\n' ); | ||
reject(); | ||
} | ||
rimraf( dest, function( e ) { | ||
if ( e === null ) { | ||
ncp( source, dest, function( err ) { | ||
if ( err !== null ) { | ||
console.log( 'Error in step #5 - ' + err + '\n'); | ||
reject( e ); | ||
} else if ( packageJson.bundledDependencies.indexOf( 'test-module' ) === -1 ) { | ||
packageJson.bundledDependencies.push( 'test-module' ); | ||
fs.writeFile( pkgJson, JSON.stringify( packageJson, null, ' ' ), function( e ) { | ||
if ( !!e ) { | ||
console.log( 'Error in step #5 - ' + e + '\n'); | ||
reject( e ); | ||
} else { | ||
console.log( 'step #5 - completed' ); | ||
resolve(); | ||
} | ||
}); | ||
} else { | ||
console.log( 'step #5 - completed' ); | ||
resolve(); | ||
} | ||
}); | ||
} else { | ||
console.log( 'Error in step #5 - ' + e + '\n' ); | ||
reject(); | ||
} | ||
}); | ||
}); | ||
}); | ||
} | ||
function rebaseDb() { | ||
return new Promise( function( resolve, reject ) { | ||
var proc = spawn( 'grunt', [ 'db' ], { stdio: 'inherit', cwd: path.resolve( path.join( __dirname, '..', prName ) ) } ); | ||
return new Promise( function( resolve, reject ) { | ||
var proc = spawn( 'grunt', [ 'db' ], { stdio: 'inherit', cwd: path.resolve( path.join( __dirname, '..', prName ) ) } ); | ||
console.log( 'step #6 - rebase db' ); | ||
console.log( 'step #6 - rebase db' ); | ||
proc.stderr.on('data', function (data) { | ||
console.log( 'Error in step #6 - ' + data.toString() + '\n'); | ||
reject( data.toString() ); | ||
}); | ||
proc.stderr.on('data', function (data) { | ||
console.log( 'Error in step #6 - ' + data.toString() + '\n'); | ||
reject( data.toString() ); | ||
}); | ||
proc.on('close', function (code) { | ||
console.log('step #6 process exited with code ' + code + '\n' ); | ||
resolve(); | ||
}); | ||
proc.on('close', function (code) { | ||
console.log('step #6 process exited with code ' + code + '\n' ); | ||
resolve(); | ||
}); | ||
}); | ||
} | ||
createProject() | ||
.then( copyOrmModule ) | ||
.then( cleverSetup ) | ||
.then( configureOrmModule ) | ||
.then( installTestModule ) | ||
.then( rebaseDb ) | ||
.catch( function (err) { | ||
console.log('Error - ' + err ); | ||
}); | ||
.then( copyOrmModule ) | ||
.then( cleverSetup ) | ||
.then( configureOrmModule ) | ||
.then( installTestModule ) | ||
.then( rebaseDb ) | ||
.catch( function (err) { | ||
console.log('Error - ' + err ); | ||
}); |
@@ -1,152 +0,153 @@ | ||
var utils = require( 'utils' ) | ||
, env = utils.bootstrapEnv() | ||
, path = require( 'path' ) | ||
'use strict'; | ||
var path = require('path') | ||
, injector = require('injector') | ||
, Model = injector.getInstance('Model') | ||
, underscore = require('underscore') | ||
, expect = require( 'chai' ).expect | ||
, injector = require( 'injector' ) | ||
, Model = injector.getInstance( 'Model' ) | ||
, packageJson = injector.getInstance( 'packageJson' ) | ||
, _ = require( 'underscore' ) | ||
, ormModel = path.resolve( path.join( __dirname, '..', 'assets', 'OrmModel.js' ) ) | ||
, ormModel = require( ormModel ) | ||
, ormModel = path.resolve(path.join(__dirname, '..', 'assets', 'OrmModel.js')) | ||
, ormModel = require(ormModel) | ||
, OrmModel; | ||
describe( 'test.ORM.Model', function() { | ||
describe('test.ORM.Model', function() { | ||
before( function( done ) { | ||
injector.inject( ormModel, function( _OrmModel ) { | ||
OrmModel = _OrmModel; | ||
injector.instance( 'OrmModel', OrmModel ); | ||
// run a sync | ||
injector.getInstance( 'sequelize' ).sync({force:true}) | ||
.then(function() { | ||
done(); | ||
}) | ||
.catch( done ); | ||
}); | ||
before(function(done) { | ||
injector.inject(ormModel, function(_OrmModel) { | ||
OrmModel = _OrmModel; | ||
injector.instance('OrmModel', OrmModel); | ||
// run a sync | ||
injector | ||
.getInstance('sequelize') | ||
.sync({force:true}) | ||
.then(function() { | ||
done(); | ||
}) | ||
.catch(done); | ||
}); | ||
}); | ||
describe( 'Definition', function() { | ||
it( 'Should have defined OrmModel as a Model', function( done ) { | ||
expect( OrmModel.prototype instanceof Model ).to.equal( true ); | ||
describe('Definition', function() { | ||
it('Should have defined OrmModel as a Model', function(done) { | ||
expect(OrmModel.prototype instanceof Model).to.equal(true); | ||
done(); | ||
}); | ||
done(); | ||
}); | ||
it( 'Should have String field', function( done ) { | ||
expect( OrmModel.fields ).to.have.property( 'str' ); | ||
expect( OrmModel.fields.str ).to.eql( String ); | ||
it('Should have String field', function(done) { | ||
expect(OrmModel.fields).to.have.property('str'); | ||
expect(OrmModel.fields.str).to.eql(String); | ||
done(); | ||
}); | ||
done(); | ||
}); | ||
it( 'Should have Boolean field', function( done ) { | ||
expect( OrmModel.fields ).to.have.property( 'bool' ); | ||
expect( OrmModel.fields.bool ).to.eql( Boolean ); | ||
done(); | ||
}); | ||
it('Should have Boolean field', function(done) { | ||
expect(OrmModel.fields).to.have.property('bool'); | ||
expect(OrmModel.fields.bool).to.eql(Boolean); | ||
done(); | ||
}); | ||
it( 'Should have Date field', function( done ) { | ||
expect( OrmModel.fields ).to.have.property( 'date' ); | ||
expect( OrmModel.fields.date ).to.eql( Date ); | ||
done(); | ||
}); | ||
it('Should have Date field', function(done) { | ||
expect(OrmModel.fields).to.have.property('date'); | ||
expect(OrmModel.fields.date).to.eql(Date); | ||
done(); | ||
}); | ||
it( 'Should have Enum field', function( done ) { | ||
expect( OrmModel.fields ).to.have.property( 'enum' ); | ||
expect( OrmModel.fields.enum ).to.have.property( 'type' ); | ||
expect( OrmModel.fields.enum.type.toString() ).to.equal( 'ENUM' ); | ||
expect( OrmModel.fields.enum ).to.have.property( 'values' ); | ||
expect( OrmModel.fields.enum.values ).to.be.an( 'array' ); | ||
expect( OrmModel.fields.enum.values.length ).to.equal( 1 ); | ||
expect( OrmModel.fields.enum.values[ 0 ] ).to.equal( 'test' ); | ||
it('Should have Enum field', function(done) { | ||
expect(OrmModel.fields).to.have.property('enum'); | ||
expect(OrmModel.fields.enum).to.have.property('type'); | ||
expect(OrmModel.fields.enum.type.toString()).to.equal('ENUM'); | ||
expect(OrmModel.fields.enum).to.have.property('values'); | ||
expect(OrmModel.fields.enum.values).to.be.an('array'); | ||
expect(OrmModel.fields.enum.values.length).to.equal(1); | ||
expect(OrmModel.fields.enum.values[ 0 ]).to.equal('test'); | ||
done(); | ||
}); | ||
done(); | ||
}); | ||
it( 'Should have Enum (defined by object notation) field', function( done ) { | ||
expect( OrmModel.fields ).to.have.property( 'enumObj' ); | ||
expect( OrmModel.fields.enumObj ).to.have.property( 'type' ); | ||
expect( OrmModel.fields.enumObj.type.toString() ).to.equal( 'ENUM' ); | ||
expect( OrmModel.fields.enumObj ).to.have.property( 'values' ); | ||
expect( OrmModel.fields.enumObj.values ).to.be.an( 'array' ); | ||
expect( OrmModel.fields.enumObj.values.length ).to.equal( 1 ); | ||
expect( OrmModel.fields.enumObj.values[ 0 ] ).to.equal( 'test' ); | ||
it('Should have Enum (defined by object notation) field', function(done) { | ||
expect(OrmModel.fields).to.have.property('enumObj'); | ||
expect(OrmModel.fields.enumObj).to.have.property('type'); | ||
expect(OrmModel.fields.enumObj.type.toString()).to.equal('ENUM'); | ||
expect(OrmModel.fields.enumObj).to.have.property('values'); | ||
expect(OrmModel.fields.enumObj.values).to.be.an('array'); | ||
expect(OrmModel.fields.enumObj.values.length).to.equal(1); | ||
expect(OrmModel.fields.enumObj.values[ 0 ]).to.equal('test'); | ||
done(); | ||
}); | ||
done(); | ||
}); | ||
it( 'Should have Buffer field', function( done ) { | ||
expect( OrmModel.fields ).to.have.property( 'buf' ); | ||
expect( OrmModel.fields.buf ).to.eql( Buffer ); | ||
it('Should have Buffer field', function(done) { | ||
expect(OrmModel.fields).to.have.property('buf'); | ||
expect(OrmModel.fields.buf).to.eql(Buffer); | ||
done(); | ||
}); | ||
done(); | ||
}); | ||
it( 'Should have bigint field', function( done ) { | ||
expect( OrmModel.fields ).to.have.property( 'bigint' ); | ||
expect( OrmModel.fields.bigint.toString() ).to.equal( 'BIGINT' ); | ||
it('Should have bigint field', function(done) { | ||
expect(OrmModel.fields).to.have.property('bigint'); | ||
expect(OrmModel.fields.bigint.toString()).to.equal('BIGINT'); | ||
done(); | ||
}); | ||
done(); | ||
}); | ||
it( 'Should have bigint with length field', function( done ) { | ||
expect( OrmModel.fields ).to.have.property( 'bigintLen' ); | ||
expect( OrmModel.fields.bigintLen ).to.have.property( 'length' ); | ||
expect( OrmModel.fields.bigintLen.length ).to.equal( 11 ); | ||
expect( OrmModel.fields.bigintLen.type.toString() ).to.equal( 'BIGINT' ); | ||
it('Should have bigint with length field', function(done) { | ||
expect(OrmModel.fields).to.have.property('bigintLen'); | ||
expect(OrmModel.fields.bigintLen).to.have.property('length'); | ||
expect(OrmModel.fields.bigintLen.length).to.equal(11); | ||
expect(OrmModel.fields.bigintLen.type.toString()).to.equal('BIGINT'); | ||
done(); | ||
}); | ||
done(); | ||
}); | ||
// @todo this is broken | ||
it.skip( 'Should have defined Orms table in MySQL', function( done ) { | ||
injector.getInstance( 'sequelize' ).query( 'describe ' + OrmModel.entity.tableName + ';', { raw: true }) | ||
.then(function( desc ) { | ||
var modelSchemaKeys = Object.keys( OrmModel.fields).map( function( fieldName ) { | ||
var field = OrmModel.fields[ fieldName ]; | ||
return field.field ? field.field : fieldName; | ||
}); | ||
expect( Object.keys( JSON.parse( JSON.stringify( desc ) ) ) ).to.eql( modelSchemaKeys ); | ||
done(); | ||
}) | ||
.catch( done ) | ||
}); | ||
// @todo this is broken | ||
it.skip('Should have defined Orms table in MySQL', function(done) { | ||
injector.getInstance('sequelize').query('describe ' + OrmModel.entity.tableName + ';', { raw: true }) | ||
.then(function(desc) { | ||
var modelSchemaKeys = Object.keys(OrmModel.fields).map(function(fieldName) { | ||
var field = OrmModel.fields[ fieldName ]; | ||
return field.field ? field.field : fieldName; | ||
}); | ||
expect(Object.keys(JSON.parse(JSON.stringify(desc)))).to.eql(modelSchemaKeys); | ||
done(); | ||
}) | ||
.catch(done) | ||
}); | ||
}); | ||
describe( 'Usage', function() { | ||
it( 'Should be able to create a new model instance', function( done ) { | ||
var entity = { | ||
str : 'String', | ||
bool : true, | ||
date : new Date(), | ||
enum : 'test', | ||
enumObj : 'test', | ||
buf : new Buffer( 'foobar' ), | ||
bigint : 1000000001, | ||
bigintLen : 1000000001, | ||
float : 10.1, | ||
floatLen : 100000000.1, | ||
floatLenAndDec : 1.12345678911, | ||
dec : 10, | ||
decPrec : 10, | ||
decPrecAndScale : 10, | ||
text : 'Text', | ||
textObj : 'TextObj' | ||
}; | ||
describe('Usage', function() { | ||
it('Should be able to create a new model instance', function(done) { | ||
var entity = { | ||
str : 'String', | ||
bool : true, | ||
date : new Date(), | ||
enum : 'test', | ||
enumObj : 'test', | ||
buf : new Buffer('foobar'), | ||
bigint : 1000000001, | ||
bigintLen : 1000000001, | ||
float : 10.1, | ||
floatLen : 100000000.1, | ||
floatLenAndDec : 1.12345678911, | ||
dec : 10, | ||
decPrec : 10, | ||
decPrecAndScale : 10, | ||
text : 'Text', | ||
textObj : 'TextObj' | ||
}; | ||
OrmModel | ||
.create( _.clone( entity ) ) | ||
.then( function( model ) { | ||
Object.keys( entity ).forEach( function( key ) { | ||
expect( model[ key ] ).to.eql( entity[ key ] ); | ||
}); | ||
done(); | ||
}) | ||
.catch( done ); | ||
}); | ||
OrmModel | ||
.create(underscore.clone(entity)) | ||
.then(function(model) { | ||
Object.keys(entity).forEach(function(key) { | ||
expect(model[ key ]).to.eql(entity[ key ]); | ||
}); | ||
done(); | ||
}) | ||
.catch(done); | ||
}); | ||
}); | ||
}); |
@@ -1,167 +0,16 @@ | ||
var inflect = require('i')() | ||
, utils = require('utils') | ||
, modelUtils = utils.modelUtils | ||
, inspect = modelUtils.debugInspect | ||
, underscore = require('underscore') | ||
, async = require('async') | ||
, injector = require('injector') | ||
, Exceptions = require('exceptions') | ||
, sequelize = require('sequelize') | ||
, util = require('util'); | ||
var path = require('path') | ||
, ormLib = require(path.resolve(path.join(__dirname, '..', 'lib'))); | ||
var ormUtils = module.exports = { | ||
supportSingleModule: function(env, moduleName) { | ||
if (moduleName) { | ||
env.packageJson.bundledDependencies.length = 0 | ||
env.packageJson.bundledDependencies.push('clever-orm', env); | ||
env.packageJson.bundledDependencies.push(moduleName, env); | ||
} | ||
}, | ||
eagerLoad: function(findOptions) { | ||
if (!!findOptions.include && findOptions.include instanceof Array) { | ||
for(var i = 0; i < findOptions.include.length; i++) { | ||
this.debug('eagerLoad(' + inspect(underscore.omit(findOptions.include[i], 'model', 'include')) + ', ' + inspect(findOptions.include[i].model.name) + ')'); | ||
if (findOptions.include[i].entity) { | ||
findOptions.include[i] = findOptions.include[i].entity; | ||
} else if (findOptions.include[i].model && findOptions.include[i].model.entity) { | ||
findOptions.include[i].model = findOptions.include[i].model.entity; | ||
} | ||
// Handle customColumnNames in nested include.where's | ||
if (findOptions.include[i].where) { | ||
modelUtils.aliasFieldsForQuery.apply(injector.getInstance(findOptions.include[i].model.name + 'Model'), [findOptions.include[i].where]); | ||
} | ||
// Handle nested includes | ||
if (findOptions.include[i].include) { | ||
ormUtils.eagerLoad.apply(this, [findOptions.include[i].include]); | ||
} | ||
} | ||
} | ||
}, | ||
afterEagerLoad: function(findOptions, model) { | ||
if (model !== null && findOptions.include && findOptions.include.length && model.entity.options.include) { | ||
var models = this.getDefinedModels(); | ||
Object.keys(model.entity.options.includeMap).forEach(function(modelName) { | ||
var _include = model.entity.options.includeMap[modelName] | ||
, as = inflect.camelize(_include.as, false) | ||
, csModel = models[_include.association.target ? _include.association.target.name : modelName]; | ||
this.debug('afterEagerLoad(' + inspect(_include.as) + ', ' + inspect(_include.model.name) + ')'); | ||
if (!!csModel && !!model.entity[as]) { | ||
if (model.entity[as] instanceof Array) { | ||
for (var i = 0; i < model.entity[as].length; i++) { | ||
if (!(model.entity[as][i] instanceof csModel)) { | ||
model.entity[as][i] = new csModel(model.entity[as][i]); | ||
ormUtils.afterEagerLoad.apply(csModel, [model.entity[as][i].entity.options, model.entity[as][i]]); | ||
} | ||
} | ||
} else { | ||
if (!(model.entity[as] instanceof csModel)) { | ||
model.entity[as] = new csModel(model.entity[as]); | ||
ormUtils.afterEagerLoad.apply(csModel, [model.entity[as].entity.options, model.entity[as]]); | ||
} | ||
} | ||
} | ||
} | ||
.bind(this)); | ||
} | ||
}, | ||
find: function(findOptions, queryOptions, callback) { | ||
this.debug('ormUtils.find(' + inspect(findOptions) + ')'); | ||
ormUtils.eagerLoad.apply(this, [findOptions, queryOptions]); | ||
this.entity | ||
.find(findOptions, queryOptions) | ||
.then(function( model ) { | ||
ormUtils.wrapModel.apply(this, [ findOptions, model, callback ]); | ||
}.bind(this)) | ||
.catch(callback); | ||
}, | ||
wrapModel: function(findOptions, model, callback) { | ||
if (model !== null) { | ||
model = new this(model); | ||
ormUtils.afterEagerLoad.apply(this, [findOptions, model]); | ||
return !callback ? model : callback( null, model ); | ||
} else { | ||
return !callback ? null : callback( null, null ); | ||
} | ||
}, | ||
findAll: function(findOptions, queryOptions, callback) { | ||
ormUtils.eagerLoad.apply(this, [findOptions, queryOptions]); | ||
this.entity | ||
.findAll(findOptions, queryOptions) | ||
.then(this.callback(function(results) { | ||
results = async.map( | ||
results instanceof Array ? results : [results], | ||
this.callback(ormUtils.wrapModel, findOptions), | ||
callback | ||
); | ||
})) | ||
.catch(callback); | ||
}, | ||
create: function(modelData, queryOptions, callback) { | ||
var data = underscore.pick(modelData, Object.keys(this.entity.attributes)); | ||
this.debug(util.format('ormUtils.create(%s)', Object.keys(data).join(', '))); | ||
this.entity.create(data, queryOptions).then(this.callback(function(entity) { | ||
callback(null, new this(entity)); | ||
})) | ||
.catch(sequelize.UniqueConstraintError, this.callback(function(e) { | ||
var columnName = Object.keys(e.fields).shift() | ||
, column = underscore.findWhere(this._aliases, { columnName: columnName }) | ||
, key = !!column ? column.key : columnName; | ||
callback(new Exceptions.DuplicateModel(util.format('%s with %s of "%s" already exists.', this._name, key, e.fields[columnName]))); | ||
})) | ||
.catch(callback); | ||
}, | ||
update: function(values, queryOptions, callback) { | ||
this.entity | ||
.update(values, queryOptions) | ||
.then(callback.bind(null, null)) | ||
.catch(callback); | ||
}, | ||
save: function(data, queryOptions, callback) { | ||
this.debug('ormUtils.save()'); | ||
this.entity | ||
.save(data, queryOptions) | ||
.then(callback.bind(null, null)) | ||
.catch(callback) | ||
}, | ||
destroy: function(queryOptions, callback) { | ||
this.debug('ormUtils.destroy()'); | ||
this.entity | ||
.destroy(queryOptions) | ||
.then(callback.bind(null, null)) | ||
.catch(callback) | ||
}, | ||
softDeleteable: function(findOptions, queryOptions, callback) { | ||
if (!!this.softDeleteable) { | ||
this.debug('softDeleteable(' + this.deletedAt + ')'); | ||
findOptions[this.deletedAt] = null; | ||
} | ||
callback && callback(null); | ||
} | ||
module.exports = { | ||
find : ormLib.model.find, | ||
save : ormLib.model.instance.save, | ||
create : ormLib.model.create, | ||
update : ormLib.model.update, | ||
destroy : ormLib.model.destroy, | ||
destroyInstance : ormLib.model.instance.destroy, | ||
findAll : ormLib.model.findAll, | ||
wrapModel : ormLib.model.instance.hydrator, | ||
eagerLoad : ormLib.model.associations.loaders.eager.load, | ||
afterEagerLoad : ormLib.model.associations.loaders.eager.afterLoad, | ||
softDeleteable : ormLib.model.behaviours.softDeleteable.whereCriteria | ||
}; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
84329
54
1879
2
53
2