biz9-data
Version:
BiZ9-Data Package is an object-relational mapper (ORM) that lets you build a clean, portable, reusable, and high-level data access layer with Node.js for data driven applications. The package consists of create, read, update and destroy (CRUD) methods to
754 lines (751 loc) • 31.4 kB
JavaScript
/*
Copyright 2016 Certified CoderZ
Author: Brandon Poole Sr. (biz9framework@gmail.com)
License GNU General Public License v3.0
Description: BiZ9 Framework: Data
*/
const async = require('async');
const {Scriptz}=require("biz9-scriptz");
const {Data_Logic,Data_Field,Data_Type,Data_Table,Data_Value_Type}=require("biz9-data-logic");
const {Log,Str,Obj}=require("biz9-utility");
const {Cache} = require('./redis.js');
const {Foreign} = require('./foreign.js');
const {Group} = require('./group.js');
const {Join} = require('./join.js');
const {Adapter} = require('./adapter.js');
class Database {
static get = async (data_config,option) => {
/* options
- none
*/
let error=null;
let data={};
return new Promise((callback) => {
option = !Obj.check_is_empty(option) ? option : {biz9_config_file:null,app_id:null};
if(option.biz9_config_file==null){
option.biz9_config_file=null;
}else{
data_config = Scriptz.get_biz9_config(option);
}
if(option.app_id){
data_config.APP_ID = option.app_id;
}
if(data_config.APP_ID==null){
error=Log.append(error,"Database Error: Missing app_id.");
}
Adapter.get_database(data_config).then(([biz_error,biz_data])=>{
if(biz_error){
error=Log.append(error,biz_error);
}else{
biz_data.data_config=data_config;
biz_data.app_id=data_config.APP_ID;
callback([error,biz_data]);
}
}).catch(err => {
Log.error('Data-Database-Get',err);
error=Log.append(error,err);
});
});
}
static delete = async (database) => {
/* options
- none
*/
let error=null;
return new Promise((callback) => {
Adapter.delete_database(data_config).then(([biz_error,biz_data])=>{
if(biz_error){
error=Log.append(error,biz_error);
}else{
biz_data.data_config=data_config;
biz_data.app_id=data_config.APP_ID;
callback([err,null]);
}
}).catch(err => {
Log.error('Data-Db-Delete',err);
error=Log.append(error,err);
});
});
}
static info = async (database,option) => {
/* options
- none
*/
return new Promise((callback) => {
let data = [];
let error = null;
option = !Obj.check_is_empty(option) ? option : {};
async.series([
async function(call){
const collections = await database.listCollections().toArray();
for (const collectionInfo of collections) {
const collectionName = collectionInfo.name;
const collection = database.collection(collectionName);
const count = await collection.estimatedDocumentCount();
data.push({title:collectionName,item_count:count});
}
},
]).then(result => {
callback([error,data]);
}).catch(err => {
Log.error("Database-Info",err);
callback([err,null]);
});
});
}
}
class Data {
//9_post
static post = async (database,table,data,option) => {
/* options
- reset
- clean
- delete_cache
- overwrite
*/
return new Promise((callback) => {
let error = null;
let cache = {};
option = !Obj.check_is_empty(option) ? option : {};
async.series([
async function(call) {
const [biz_error,biz_data] = await Cache.get(database.data_config);
cache = biz_data;
},
//clean
function(call){
if(option.clean){
let new_data = {};
for(const field in data){
if(!Obj.check_is_array(data[field]) &&
Obj.check_is_value(data[field]) &&
!Str.check_if_str_exist(field,'_item_count') &&
!Str.check_if_str_exist(field,'_page_count'))
{
new_data[field] = data[field];
}
}
data = new_data;
call();
}else{
call();
}
},
//delete cache item
function(call){
if(option.delete_cache || option.overwrite){
Adapter.delete_item_cache(database,cache,table,data.id).then(([biz_error,biz_data])=>{
if(biz_error){
error=Log.append(error,biz_error);
}else{
call();
}
}).catch(err => {
Log.error('Data-Post-Delete-Cache',err);
error=Log.append(error,err);
});
}else{
call();
}
},
function(call){
Adapter.post_item(database,cache,table,data,option).then(([biz_error,biz_data])=>{
if(biz_error){
error=Log.append(error,biz_error);
}else{
data = biz_data;
call();
}
}).catch(err => {
Log.error('Data-Post-Post-Item-Apapter',err);
error=Log.append(error,err);
});
},
//reset
function(call){
if(option.reset && data.id){
Adapter.get_item(database,cache,data.table,data.id).then(([biz_error,biz_data])=>{
if(biz_error){
error=Log.append(error,biz_error);
}else{
data = biz_data;
call();
}
}).catch(err => {
Log.error('Data-Get-Reset',err);
error=Log.append(error,err);
});
}else{
call();
}
},
]).then(result => {
callback([error,data]);
}).catch(err => {
Log.error("Post-Data",err);
callback([err,{}]);
});
});
};
//9_post_items
static post_items = async (database,data_items) => {
/* option params
* n/a
*/
return new Promise((callback) => {
let cache = {};
let error = null;
async.series([
async function(call) {
const [biz_error,biz_data] = await Cache.get(database.data_config);
cache = biz_data;
},
async function(call){
const [biz_error,biz_data] = await Adapter.post_item_list(database,cache,data_items);
if(biz_error){
error=Log.append(error,biz_error);
}else{
data_items = biz_data;
}
},
]).then(result => {
callback([error,data_items]);
}).catch(err => {
Log.error("Post-List-Data",err);
callback([err,{}]);
});
});
};
//9_delete_search
static delete_search = async (database,table,filter,option) => {
/* options
- delete_group
*/
return new Promise((callback) => {
let error = null;
let data = Data_Logic.get(table,0,{data:{filter:filter}});
let cache = {};
data[Data_Type.RESULT_OK_DELETE] = false;
data[Data_Type.RESULT_OK_DELETE_COUNT] = 0;
let delete_item_query = { $or: [] };
let delete_group_list = [];
let delete_items = [];
option = !Obj.check_is_empty(option) ? option : {delete_group:true};
async.series([
async function(call) {
const [biz_error,biz_data] = await Cache.get(database.data_config);
cache = biz_data;
},
function(call){
let search = Data_Logic.get_search(table,filter,{},1,0);
Adapter.get_item_list(database,cache,search.table,search.filter,search.sort_by,search.page_current,search.page_size,option).then(([biz_error,items,item_count,page_count])=>{
if(biz_error){
error=Log.append(error,biz_error);
}else{
if(items.length>0){
delete_items = items;
}
call();
}
}).catch(err => {
Log.error('Data-Search',err);
error=Log.append(error,err);
});
},
async function(call){
for(const data_item of delete_items){
let query_field = {};
query_field[Data_Field.PARENT_ID] = data_item.id
delete_item_query.$or.push(query_field);
data[Data_Type.RESULT_OK_DELETE] = true;
const [biz_error,biz_data] = await Adapter.delete_item(database,cache,data_item.table,data_item.id);
if(parseInt(biz_data[Data_Type.RESULT_OK_DELETE_COUNT]) > 0){
data[Data_Type.RESULT_OK_DELETE_COUNT] = data[Data_Type.RESULT_OK_DELETE_COUNT] + parseInt(biz_data[Data_Type.RESULT_OK_DELETE_COUNT]);
}
}
},
function(call){
if(option.delete_group && delete_item_query.$or.length > 0){
let search = Data_Logic.get_search(table,{},{},1,0,{field:{id:1,title:1,table:1}});
Adapter.get_item_list(database,cache,search.table,search.filter,search.sort_by,search.page_current,search.page_size,option).then(([biz_error,items,item_count,page_count])=>{
if(biz_error){
error=Log.append(error,biz_error);
}else{
delete_group_list = items;
call();
}
});
}else{
call();
}
},
async function(call){
if(option.delete_group && delete_item_query.$or.length > 0){
data[Data_Type.RESULT_OK_GROUP_DELETE] = false;
let search = Data_Logic.get_search(Data_Table.GROUP,delete_item_query,{},1,0);
const [biz_error,biz_data] = await Adapter.delete_item_list(database,cache,search.table,search.filter);
if(biz_error){
error=Log.append(error,biz_error);
}else{
data[Data_Type.RESULT_OK_GROUP_DELETE] = true;
}
}
},
]).then(result => {
callback([error,data]);
}).catch(err => {
Log.error("Delete-List-Data",err);
callback([err,[]]);
});
});
};
//9_count
static count = async (database,table,filter) => {
/* option params
* none
*/
return new Promise((callback) => {
let error = null;
let cache = {};
let data = {};
async.series([
async function(call) {
const [biz_error,biz_data] = await Cache.get(database.data_config);
cache = biz_data;
},
async function(call){
const [biz_error,biz_data] = await Adapter.get_count_item_list(database,table,filter);
if(biz_error){
error=Log.append(error,biz_error);
}else{
data = biz_data.count;
}
},
]).then(result => {
callback([error,data]);
}).catch(err => {
Log.error("Count-List-Data",err);
callback([err,{}]);
});
});
};
//9_copy
static copy = async (database,table,id,option) => {
/*
* options
* - copy_group
*/
return new Promise((callback) => {
let error = null;
let cache = {};
let data = Data_Logic.get(table,id);
let top_data = Data_Logic.get(table,0);
let copy_data = Data_Logic.get(table,0);
option = !Obj.check_is_empty(option) ? option : {copy_group:true};
async.series([
async function(call) {
const [biz_error,biz_data] = await Cache.get(database.data_config);
cache = biz_data;
},
async function(call){
let data_group_option = Data_Logic.get_group();
const [biz_error,biz_data] = await Data.get(database,table,id,{groups:[data_group_option]});
if(biz_error){
error=Log.append(error,biz_error);
}else{
top_data=biz_data;
}
},
//top_item
async function(call){
if(top_data.id){
copy_data = Data_Logic.copy(table,top_data);
copy_data[Data_Field.TITLE] = 'Copy '+top_data[Data_Field.TITLE];
copy_data[Data_Field.TITLE_URL] = 'copy_'+top_data[Data_Field.TITLE_URL];
copy_data[Data_Field.SOURCE_ID] = top_data.id;
copy_data[Data_Field.SOURCE_TABLE] = top_data.table;
const [biz_error,biz_data] = await Data.post(database,copy_data.table,copy_data);
if(biz_error){
error=Log.append(error,biz_error);
}else{
copy_data=biz_data;
}
}else{
copy_data = Data_Logic.get_not_found(table,id);
}
},
//group
async function(call){
if(top_data.id && top_data.groups.length > 0 && option.copy_group){
copy_data.groups = [];
let post_groups = [];
for(const group of top_data.groups){
let copy_group = Data_Logic.copy(Data_Table.GROUP,group);
copy_group[Data_Field.TITLE] = group[Data_Field.TITLE];
copy_group[Data_Field.TITLE_URL] = group[Data_Field.TITLE_URL];
copy_group[Data_Field.SOURCE_ID] = group.id;
copy_group[Data_Field.SOURCE_TABLE] = group.table;
copy_group[Data_Field.PARENT_TABLE] = copy_data.table;
copy_group[Data_Field.PARENT_ID] = copy_data.id;
post_groups.push(copy_group);
}
const [biz_error,biz_data] = await Adapter.post_item_list(database,cache,post_groups);
if(biz_error){
error=Log.append(error,biz_error);
}else{
copy_data.groups=biz_data;
}
}
},
]).then(result => {
data = copy_data;
callback([error,data]);
}).catch(err => {
Log.error("Copy",err);
callback([err,{}]);
});
});
};
//9_get
static get = async(database,table,id,option) => {
/* Options
- cache_delete
- field
- foreigns
- groups
- id_field
- joins
- title
*/
return new Promise((callback) => {
let error= null;
let cache = null;
let data = Data_Logic.get(table,id);
let field_result_ok = false;
option = !Obj.check_is_empty(option) ? option : {};
async.series([
async function(call) {
const [biz_error,biz_data] = await Cache.get(database.data_config);
cache = biz_data;
},
function(call){
if(option.cache_delete){
Adapter.delete_item_cache(database,cache,data.table,data.id,option).then(([biz_error,biz_data])=>{
if(biz_error){
error=Log.append(error,biz_error);
}else{
call();
}
}).catch(err => {
Log.error('Data-Delete-Cache',err);
error=Log.append(error,err);
});
}else{
call();
}
},
//item_by_id
//title
function(call){
Adapter.get_item(database,cache,table,id,option).then(([biz_error,biz_data])=>{
if(biz_error){
error=Log.append(error,biz_error);
}else{
if(!option.title){
data = biz_data;
}else{
data = biz_data;
data[option.title] = Obj.merge({},biz_data);;
}
call();
}
}).catch(err => {
Log.error('Data-Get',err);
error=Log.append(error,err);
});
},
//9_get_join 9_join
function(call){
if(option.joins){
Join.get_data(database,cache,option).then(([biz_error,biz_data])=>{
if(biz_error){
error=Log.append(error,biz_error);
}else{
for(const search_item of biz_data){
data[search_item.title+"_"+Data_Type.JOIN] = search_item.data;
if(search_item.value_type == Data_Value_Type.ITEMS){
data[search_item.title] = search_item.data.items;
}else{
data[search_item.title] = search_item.data;
}
}
call();
}
}).catch(err => {
Log.error('Data-Get-Item-Join',err);
error=Log.append(error,err);
});
}else{
call();
}
},
//9_group 9_item_group
function(call){
if(option.groups && data.id){
Group.get_data(database,cache,[data],option).then(([biz_error,biz_data])=>{
if(biz_error){
error=Log.append(error,biz_error);
}else{
data = biz_data[0];
}
call();
}).catch(err => {
Log.error('Data-Item-Group',err);
error=Log.append(error,err);
});
}else{
call();
}
},
//9_foreigns 9_item_foreign
function(call){
if(option.foreigns && data.id){
Foreign.get_data(database,cache,[data],option).then(([biz_error,biz_data])=>{
if(biz_error){
error=Log.append(error,biz_error);
}else{
data = biz_data[0];
}
call();
}).catch(err => {
Log.error('Data-Search-Foreign',err);
error=Log.append(error,err);
});
}else{
call();
}
},
]).then(result => {
callback([error,data]);
}).catch(err => {
Log.error("DATA-GET-ERROR",err);
callback([error,{}]);
});
});
};
//9_search
static search = (database,table,filter,sort_by,page_current,page_size,option) => {
/* options
- field
- distinct
- foreigns
- joins
- groups
*/
return new Promise((callback) => {
let data = {table:table,item_count:0,page_count:1,filter:{},items:[]};
let cache = null;
let error = null;
option = !Obj.check_is_empty(option) ? option : {};
async.series([
async function(call) {
const [biz_error,biz_data] = await Cache.get(database.data_config);
cache = biz_data;
},
function(call){
let search = Data_Logic.get_search(table,filter,sort_by,page_current,page_size);
Adapter.get_item_list(database,cache,search.table,search.filter,search.sort_by,search.page_current,search.page_size,option).then(([biz_error,items,item_count,page_count])=>{
if(biz_error){
error=Log.append(error,biz_error);
}else{
data.item_count=item_count;
data.page_count=page_count;
data.search=search;
data[Data_Field.ITEMS]=items;
}
call();
}).catch(err => {
Log.error('Data-Search',err);
error=Log.append(error,err);
});
},
//9_items_join 9_search_join 9_joins
function(call){
if(option.joins){
Join.get_data(database,cache,option).then(([biz_error,biz_data])=>{
if(biz_error){
error=Log.append(error,biz_error);
}else{
for(const search_item of biz_data){
data[search_item.title+"_"+Data_Type.JOIN] = search_item.data;
if(search_item.value_type == Data_Value_Type.ITEMS){
data[search_item.title] = search_item.data.items;
}else{
data[search_item.title] = search_item.data;
}
}
call();
}
}).catch(err => {
Log.error('Data-Get-Item-Join',err);
error=Log.append(error,err);
});
}else{
call();
}
},
//9_foreign //9_item_foreign
function(call){
if(option.foreigns && data[Data_Field.ITEMS].length > 0){
Foreign.get_data(database,cache,data[Data_Field.ITEMS],option).then(([biz_error,biz_data])=>{
if(biz_error){
error=Log.append(error,biz_error);
}else{
data[Data_Field.ITEMS] = biz_data;
call();
}
}).catch(err => {
Log.error('Data-Search-Foreign',err);
error=Log.append(error,err);
});
}else{
call();
}
},
//9_group 9_item_group
function(call){
if(option.groups && data[Data_Field.ITEMS].length>0){
Group.get_data(database,cache,data[Data_Field.ITEMS],option).then(([biz_error,biz_data])=>{
if(biz_error){
error=Log.append(error,biz_error);
}else{
data[Data_Field.ITEMS] = biz_data;
}
call();
}).catch(err => {
Log.error('Data-Item-Group',err);
error=Log.append(error,err);
});
}else{
call();
}
},
]).then(result => {
callback([error,data]);
}).catch(err => {
Log.error('DATA-SEARCH-ERROR',err);
callback([err,[]]);
});
});
};
//9_delete
static delete = async(database,table,id,option) => {
/* options
- delete_group
*/
return new Promise((callback) => {
let error = null;
let cache = null;
let data = Data_Logic.get(table,id);
data[Data_Type.RESULT_OK_DELETE] = false;
data[Data_Type.RESULT_OK_DELETE_CACHE] = false;
data[Data_Type.RESULT_OK_DELETE_DATABASE] = false;
data[Data_Type.RESULT_OK_GROUP_DELETE] = false;
data[Data_Type.RESULT_OK_DELETE_COUNT] = 0;
option = !Obj.check_is_empty(option) ? option : {delete_group:true};
let delete_group_list = [];
async.series([
async function(call){
const [biz_error,biz_data] = await Cache.get(database.data_config);
cache = biz_data;
},
async function(call){
const [biz_error,biz_data] = await Adapter.delete_item(database,cache,table,id);
if(biz_error){
error=Log.append(error,biz_error);
}else{
if(biz_data[Data_Type.RESULT_OK_DELETE]){
data[Data_Type.RESULT_OK_DELETE_COUNT] = biz_data[Data_Type.RESULT_OK_DELETE_COUNT];
data[Data_Type.RESULT_OK_DELETE] = true;
data[Data_Type.RESULT_OK_DELETE_CACHE] = true;
data[Data_Type.RESULT_OK_DELETE_DATABASE] = true;
}
}
},
async function(call){
if(option.delete_group){
data[Data_Type.RESULT_OK_GROUP_DELETE] = false;
let filter = {parent_id:data.id};
const [biz_error,biz_data] = await Data.delete_search(database,Data_Table.GROUP,filter);
if(biz_error){
error=Log.append(error,biz_error);
}else{
if(biz_data[Data_Type.RESULT_OK_DELETE]){
data[Data_Type.RESULT_OK_GROUP_DELETE] = true;
}
}
}
},
]).then(result => {
callback([error,data]);
}).catch(err => {
Log.error("Delete-Item",err);
callback([err,{}]);
});
});
};
//9_data_post_bulk
static post_bulk = async (database,table,items) => {
/* options
- none
*/
return new Promise((callback) => {
let error = null;
let data = Data_Logic.get(table,0);
async.series([
async function(call){
const [biz_error,biz_data] = await Adapter.post_bulk(database,table,items);
if(biz_error){
error=Log.append(error,biz_error);
}else{
data = biz_data;
}
},
]).then(result => {
callback([error,data]);
}).catch(err => {
Log.error("Post-Bulk-Data",err);
callback([err,{}]);
});
});
};
//9_blank
static blank = async (database,table,items) => {
/* options
- none
*/
return new Promise((callback) => {
let error = null;
let data = {};
async.series([
async function(call){
const [biz_error,biz_data] = await get(database,table,items);
if(biz_error){
error=Log.append(error,biz_error);
}else{
data = biz_data;
}
},
]).then(result => {
callback([error,data]);
}).catch(err => {
Log.error("Blank-Data",err);
callback([err,{}]);
});
});
};
}
module.exports = {
Data,
Database
};