UNPKG

json-object-editor

Version:

JOE the Json Object Editor | Platform Edition

240 lines (227 loc) 10.1 kB
var fs = require('fs'); //const request = require('request'); function Storage(specs){ var moduleName = colorize('[storage] ','module'); var self = this; var specs = specs || {mongo:true}; this.Api = { get:function(collection,specs){ var specs = specs || {}; var callback = specs.callback; var query = specs.query; var path = specs.path; //make http request with querystring console.log('api for collection -'+collection); } } this.File = { get:function(collection,specs){ var specs = specs || {}; var callback = specs.callback; var query = specs.query || {}; if(query._id && !query._id.isCuid()){ query._id = mongojs.ObjectId(query._id); } query[JOE.webconfig.deleted] = {$in:[false,'false','False',undefined]}; fs.readFile(JOE.dataDir+collection+'.json', 'utf8', function(err,data){ if(err){ console.log(err); callback([]); } callback(data); }); } } JOE.dataDir = dataDir = JOE.appDir+'/'+JOE.webconfig.dataDir+'/'; //JOE.schemaDir = schemaDir = JOE.appDir+'/'+JOE.webconfig.schemaDir+'/'; // function setupFolder(dir,name,watchHandler){ // if (!fs.existsSync(dir)){ // fs.mkdirSync(dir); // } // var watchHandler = watchHandler || // function(event,filename){ // console.log(name+' dir updated >'+filename||'no filename') // } // fs.watch(dir,watchHandler); // console.log(name+' stored in: '+dir); // } //setupFolder(dataDir,'data'); JOE.Utils.setupFileFolder(dataDir,'data'); this.load = function(collection,query,callback){ if(JOE.Schemas.schema[collection] && JOE.Schemas.schema[collection].storage && JOE.Schemas.schema[collection].storage.type){ var schema_storage = JOE.Schemas.schema[collection].storage; var query = schema_storage.query || query || {}; var path = schema_storage.path || ''; //console.log('mysql query',query); console.log('collection: '+collection,schema_storage); switch(schema_storage.type.toLowerCase()){ case 'mongodb': case 'mongo': JOE.Mongo.get(collection,{query:query,callback:callback}); break; case 'mysql': case 'sql': JOE.MySQL.get(collection,{query:query,callback:callback}); break; case 'file': self.File.get(collection,{query:query,callback:callback}); break; case 'api': self.Api.get(collection,{path:path,query:query,callback:callback}); break; } }else{ var query = query || {}; if(JOE.Mongo){ JOE.Mongo.get(collection,{query:query,callback:callback}); }else{ self.File.get(collection,{query:query,callback:callback}); } } } this.save = function(data,collection,callback,specs){ var callback = callback || function(err,data){ if(err){ console.log(JOE.Utils.color('[error] ','red')+err); } logit(colorize(data,'gray')); }; try{ var specs = $c.merge({history:true},(specs||{})); var user = specs.user || {name:'anonymous'}; if(JOE.Mongo){ logit(moduleName+' mongo saving -> '+colorize(collection,'schema')); var save_callback = function(err,data){ callback(err,data); if (!specs || specs.push !== false) { JOE.io.emit('item_updated', { results: [data] }); } if(!err){ var ts = new Date().toISOString(); var cached = JOE.Cache.findByID(data.itemtype,data._id); var events = 'save'; if(!cached){ events = 'create,save'; } var event_specs = {timestamp:ts}; var history_payload = { itemid:data._id, collection:collection, user:{_id:user._id,name:user.name}, timestamp:ts, historical:data }; //var cached = JOE.Cache.findByID(data.itemtype,data._id); if(cached){ history_payload.changes = $c.changes(cached,data); //sanitize for(var hvar in history_payload.changes){ if(hvar.indexOf('$') != -1){ history_payload.changes[hvar.replace(/\$/g,'__')] = history_payload.changes[hvar]; delete history_payload.changes[hvar]; } } event_specs.cached = cached; }else{ history_payload.created = true; } if(history_payload.changes.status){ events+= ',status'; event_specs.status =JOE.Cache.findByID('status',history_payload.changes.status)||{}; } if( history_payload.changes[JOE.webconfig.deleted] && data[JOE.webconfig.deleted] ){ events+= ',delete'; history_payload.deleted = true; } event_specs.historical_info = history_payload; JOE.Schemas.events(data,events,event_specs); JOE.Mongo.saveHistory(history_payload); } } if(!specs.history){ save_callback=function(err,data){ var ts = new Date().toISOString(); callback(err,data); if(data.itemtype == "comments"){ //TODO events for comments. return; } var ts = new Date().toISOString(); var cached = JOE.Cache.findByID(data.itemtype,data._id); var events = 'save'; if(!cached){ events = 'create,save'; } JOE.Schemas.events(data,events,{timestamp:ts}); } } JOE.Mongo.save(data,collection,save_callback); }else{ console.log('JOE.Mongo not connected'); } }catch(e){ callback(colorize('[storage]','error')+' error:' + e); } }; return self; } module.exports = new Storage(); /** * Save data to the specified collection. * * This function handles saving data to a MongoDB collection or a file-based storage system. * It supports history tracking, event triggering, and user attribution for the saved data. * * @param {Object} data - The data object to be saved. Must include at least the `itemtype` property. * @param {String} collection - The name of the collection where the data will be saved. * @param {Function} [callback] - Optional callback function to handle the result of the save operation. * The callback receives two arguments: `err` (error) and `data` (saved data). * @param {Object} [specs] - Additional specifications for the save operation. * - `history` (Boolean): Whether to track history for the saved data (default: true). * - `user` (Object): The user performing the save operation. Should include `_id` and `name`. * * ### Features: * - **MongoDB Integration**: Saves data to MongoDB if connected. * - **File-Based Fallback**: If MongoDB is not connected, it falls back to file-based storage. * - **History Tracking**: Tracks changes to the data and saves historical records. * - **Event Triggering**: Triggers events for `create`, `save`, `status`, and `delete` actions. * - **User Attribution**: Associates the save operation with a user for auditing purposes. * * ### Example Usage: * * ```javascript * const data = { * _id: "12345", * itemtype: "campaign", * name: "New Campaign", * status: "active" * }; * * const collection = "campaigns"; * * const callback = function(err, savedData) { * if (err) { * console.error("Error saving data:", err); * } else { * console.log("Data saved successfully:", savedData); * } * }; * * const specs = { * history: true, * user: { _id: "67890", name: "John Doe" } * }; * * JOE.Storage.save(data, collection, callback, specs); * ``` * * ### Error Handling: * - If an error occurs during the save operation, it is logged to the console and passed to the callback. * * ### Notes: * - The `itemtype` property in the `data` object is required for proper event handling. * - If `history` is disabled in `specs`, historical tracking and event triggering are skipped. */