schematize
Version:
An encapsulation of 'Sequelize' and 'treble' packages to handle 3 databases using external schema files.
290 lines (257 loc) • 9.52 kB
JavaScript
/****************************************************
"schematize"
An encapsulation sequelize and treble to manage
3 mySql databases with external schemas.
var schematize = require("schematize")(db,schema [,db3]);
*****************************************************/
// TODO : add extra control on db & schema arguments
var varServer = require("varserver")();
var Path = require("path");
var schemasPath= varServer.get("schematizePath" , {
admin:"schemas/admin/",
modele:"schemas/modele/",
user:"schemas/user/"
});
var promiseError = {
success:function(){return this;},
done:function(){return this;},
error:function(err){err();return this;},
fail:function(err){err();return this;},
then:function(succ,err){err();return this;}
};
function schemabatch(db , schemas , db3, force) {
var remain = schemas.length,
tables={},
err=false,
onsuccess = function(){},
onerror = function(){},
successSchemaEvt = function(name) {return function(e){tables[ name ] = e; remain--; if (!remain) {err ? onerror(tables) : onsuccess(tables);} }},
errorSchemaEvt = function(name) {return function(e){err=true; tables[ name ] = null; remain--; if (!remain) {err ? onerror(tables) : onsuccess(tables);} }};
for(var index=0; index<schemas.length; index++) {
schematize(db,schemas[index],db3,force)
.success( successSchemaEvt(schemas[index]) )
.error( errorSchemaEvt(schemas[index]) );
}
return {
success:function(e){onsuccess=e;return this;},
error:function(e){onerror=e;return this;},
then:function(succ,err){onsuccess=succ||onsuccess;onerror=err||onerror;return this;}
};
}
function schematize(db, schema, db3, force) {
var oSchema, oTable, oFields, oFieldsNoHidden, oFieldsKey;
var jSchema;
var pSchema; // schema file path
var onsuccess=function(){};
var onerror=function(){};
// if schema is an array of strings, call 'schemabatch'
if (typeof schema =="object" && "length" in schema) return schemabatch(db,schema,db3,force);
switch (db){
case "a":
case "admin" : db = "admin"; pSchema = Path.join(schemasPath.admin, schema); break;
case "m":
case "modele" : db = "modele"; pSchema = Path.join(schemasPath.modele, schema) ; break;
default : db = "user"; pSchema = Path.join(schemasPath.user, schema);
}
try {
oSchema = require(pSchema);
}
catch(err){
return promiseError;
}
jSchema = oSchema(require("./myTypes"))[1];
for(var field in jSchema) {
delete jSchema[field].validate;
delete jSchema[field].defaultValue;
delete jSchema[field].allowNull;
delete jSchema[field].unique;
jSchema[field].type = jSchema[field].type.valueOf();
if (jSchema[field].hidden) delete jSchema[field];
}
oSchema = oSchema(require('sequelize'));
oCon = db3?db3.get(db):null;
oFields = [];
oFieldsNoHidden = [];
oFieldsKey = [];
for(var field in oSchema[1]) {
oFields.push(field);
if (oSchema[1][field].primaryKey) oFieldsKey.push(field);
if (!oSchema[1][field].hidden) oFieldsNoHidden.push(field);
}
if (!oFieldsKey.length) {
oFieldsKey.push("id");
oFields.push("id");
oFieldsNoHidden.push("id");
} // if no primary key given, "id" default primary key added
oTable = oCon?oCon.define.apply( oCon , oSchema ):null;
var sentObj={
fields:getFields,
schema:function(){return oSchema[1]},
jSchema:function(){return {s:jSchema,k:oFieldsKey};},
table:function(con){if (con) oTable = con.define.apply( con , oSchema );return oTable;},
find:findData,
findAll:loadData,
update:updateData,
destroy:destroyData,
create:addData,
count:countData
}
if (db3) {
oTable.sync({force:!!force})
.then(
function(){ onsuccess(sentObj); },
onerror
);
return {
success:function(succ){onsuccess=succ;return this;},
error:function(err){onerror=err;return this;},
then:function(succ,err){onsuccess=succ||onsuccess; onerror=err||onerror;return this;}
}
}
else { // no connection given: operation succeded without syncing database
return {
success:function(succ){succ(sentObj);return this;},
error:function(err){return this;},
then:function(succ,err){succ(sentObj);return this;}
}
}
function getFields(type){
switch(type){
case "nohidden": return oFieldsNoHidden;
case "primary": return oFieldsKey;
default : return oFields;
}
}
function loadData( Options ) {
var onsuccess = function(){},
onerror = function(){};
if (!oTable) return promiseError;
Options = Options || {};
if (typeof Options.limit !== "number") Options.limit = 20;
oTable.findAll(Options).then( function(result){onsuccess(data2func(result));}, function(e){onerror();} );
return {
success:function(e){onsuccess=e;return this;},
error:function(e){onerror=e;return this;},
then:function(success,error){onsuccess=success||onsuccess;onerror=error||onerror;return this;}
};
}
function countData( Options ) {
var onsuccess = function(){},
onerror = function(){};
if (!oTable) return promiseError;
oTable.count(Options).then( function(result){onsuccess(result);}, function(e){onerror();} );
return {
success:function(e){onsuccess=e;return this;},
error:function(e){onerror=e;return this;},
then:function(success,error){onsuccess=success||onsuccess;onerror=error||onerror;return this;}
};
}
function updateData(values , where , fields) {
var onsuccess = function(){},
onerror = function(){};
if (!oTable) return promiseError;
oTable.update(values , where , fields).then( function(result){onsuccess(data2func(result));}, function(){onerror();} );
return {
success:function(e){onsuccess=e;return this;},
error:function(e){onerror=e;return this;},
then:function(success,error){onsuccess=success||onsuccess;onerror=error||onerror;return this;}
}
}
function addData(values , fields) {
var onsuccess = function(){},
onerror = function(){};
if (!oTable) return promiseError;
oTable.create(values , fields).then( function(result){onsuccess(data2func(result));}, function(e){onerror(e);} );
return {
success:function(e){onsuccess=e;return this;},
error:function(e){onerror=e;return this;},
then:function(success,error){onsuccess=success||onsuccess;onerror=error||onerror;return this;}
}
}
function destroyData(where) {
var onsuccess = function(){},
onerror = function(){};
if (!oTable) return promiseError;
oTable.destroy(where).then( function(result){onsuccess(data2func(result));}, function(){onerror();} );
return {
success:function(e){onsuccess=e;return this;},
error:function(e){onerror=e;return this;},
then:function(success,error){onsuccess=success||onsuccess;onerror=error||onerror;return this;}
}
}
// receive the result of find or findAll
// return a function:
// data2func(result)( fields ) is an array
// data2func(result)( fields , key ) is an object
function data2func(data){
if (!data) return function(){};
if (typeof data.length == "number") return function(fields,key,methods, noHidden){return array2data( data , fields , key , methods, noHidden);}
else return function(fields, methods, noHidden){return modele2data( data, fields, methods, noHidden );}
}
// Options : findAll values +
// other possible values: (page, bypage) ==>> (limite,offset)
function findData( Options ) {
var onsuccess = function(){},
onerror = function(){};
if (!oTable) return promiseError;
if (Options && Options.page){
Options.limit = Options.bypage || 20;
Options.offset = Options.limit * (Options.page-1);
delete Options.bypage;
delete Options.page;
}
oTable.find(Options).then( function(result){onsuccess(data2func(result),result);}, function(err){onerror(null);} );
return {
success:function(e){onsuccess=e;return this;},
error:function(e){onerror=e;return this;},
then:function(success,error){onsuccess=success||onsuccess;onerror=error||onerror;return this;}
};
}
function modele2data(data, fields, methods, noHidden) {
var result;
if (!data) result = null; // no data
else if (typeof fields=="string") {
result = data[ fields ];
}
else {
result = {}
fields = fields || (noHidden?oFieldsNoHidden:oFields);
fields.forEach(function(field){ if (data[ field ] !== null) result[ field ] = data[ field ];})
if (methods) methods.forEach(function(method){ result[method] = data[ method ].call(data);})
}
return result;
}
// if you give a 'key', you get an {Object}
// Without a 'key' you get an [Array]
function array2data(data, fields, key, methods, noHidden) {
var result = key ? {} : [];
data.forEach( function(model){
var value = modele2data(model , fields , methods, noHidden);
key ?
(((model[key] !== null) && (typeof model[key] !== "undefined")) ? (result[model[key]] = value) : null )
:
(result.push( value ));
});
return result;
}
}
schematize.config = function( options ){
if (options){
if (options.path){
if (typeof options.path == "string") {
schemasPath.admin = options.path + "admin/";
schemasPath.modele = options.path + "modele/";
schemasPath.user = options.path + "user/";
varServer.set("schematizePath" , schemasPath);
}
else {
if (options.path.admin) schemasPath.admin = options.path.admin;
if (options.path.modele) schemasPath.modele = options.path.modele;
if (options.path.user) schemasPath.user = options.path.user;
varServer.set("schematizePath" , schemasPath);
}
}
}
return schematize;
}
module.exports = schematize;