diff --git a/.gitmodules b/.gitmodules new file mode 100755 index 0000000..1ffc49c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,35 @@ +[submodule "deps/node-mongodb-native"] + path = deps/node-mongodb-native + url = http://github.com/christkv/node-mongodb-native.git + +[submodule "deps/step"] + path = deps/step + url = http://github.com/creationix/step.git + +[submodule "deps/nodejs-autorestart"] + path = deps/nodejs-autorestart + url = http://github.com/shimondoodkin/nodejs-autorestart.git + +[submodule "deps/nodejs-clone-extend"] + path = deps/nodejs-clone-extend + url = http://github.com/shimondoodkin/nodejs-clone-extend.git + +[submodule "deps/nodejs-meta-templates"] + path = deps/nodejs-meta-templates + url = http://github.com/shimondoodkin/nodejs-meta-templates.git + +[submodule "deps/node-formidable"] + path = deps/node-formidable + url = http://github.com/felixge/node-formidable.git + +[submodule "deps/node-microseconds"] + path = deps/node-microseconds + url = http://github.com/tmpvar/node-microseconds.git + +[submodule "deps/jMediaelement"] + path = deps/jMediaelement + url = http://github.com/aFarkas/jMediaelement.git + +[submodule "deps/restler"] + path = deps/restler + url = http://github.com/ashleydev/restler.git diff --git a/Fast Websites.odp b/Fast Websites.odp new file mode 100755 index 0000000..4435512 Binary files /dev/null and b/Fast Websites.odp differ diff --git a/README.md b/README.md index e1af2aa..2e3ef46 100755 --- a/README.md +++ b/README.md @@ -1,3 +1,55 @@ + +it is database managment system for mongo db + + +in general there is global local variable + +app + +it is passed in all function + +an include file contains one function +function main(app) // app is like dependeny injection +{ + this // usualy: this=app, but might be an other object yo like to extend in this function + this.foo=function(){}; +} + +the app object contation libraries +for example +app.sys +app.phpjs + +the objects inside the app object + +app.models +app.pages // controllers +app.route_urls + +//objects to clonbe and extend: +app.basicmodel // has function that simplify access to mongodb +app.basicfields + +it requires some effort to make this work because of many libraries not all of them included in gitmoduls +also the documentation is not ready yet. + +how it works: +you define some models inside a module main function. +by cloning and extending app.basicmodel +and cloning and extending app.basicfields.somefiled + +then you have a managment interface in http://hostname/admin/ +and you can create "page" type controllers in templates/website +to build the website + +a page is a templates_object as defined in double templets (meta templates) +a page also contains a path or pathbegins propery it is for the router. + +feel free to ask questions I will give you guidence. + +--------------------------------------------------------- +# old readme: + ## The idea: the idea is to create somthing similar to hkvstore.com's Phpmaker or Aspmaker or Microsoft Dot.NET 3 sp1 DynamicData application. diff --git a/basicapp.js b/basicapp.js new file mode 100755 index 0000000..fbbb493 --- /dev/null +++ b/basicapp.js @@ -0,0 +1,124 @@ +/* +there is: +app // application +app.[lib name]=lib // dependency sharing +app.models.[model name]=model object // models +app.pages.[controller name]=controller object // controllers +app.url_routes.[route name]=route object // application routes + +templates: +temlates are parts of a templates object: +var tempaltes_object={ +load_tempalts:{temaplte_name1:"filename.html"}, +prepere_templates:{temaplte_name2:function(vars,callback){var echo=""; if(callback)callback(echo);else return echo;}}, // never used actualy +prepeare_data:function(currenttempaltename,callback){ var template_prepere_data={}; callback(template_prepere_data);} +} + +there is a shared function of prepere a templates object. +aftrer it is ran: + +the result is a tempaltes object with functions by their names: + +var tempaltes_object={ +load_tempalts:{temaplte_name1:"filename.html"}, +prepere_templates:{temaplte_name2:function(vars,callback){var echo=""; if(callback)callback(echo);else return echo;}}, // never used actualy +prepeare_data:function(currenttempaltename,callback){ var template_prepere_data={}; callback(template_prepere_data);} +} + +temaplte_name1:function(...){...} +temaplte_name2:function(...){...} + +you use templates like this: +tamplates_object.function(vars,callback); + +a template: + +structure of a tempaltes function: + +function(vars,callback) +{ + var echo=""; + //my code is here + if(callback) + callback(echo); + else + return echo; +} + +example of a tempalte and the result: +template.html: +hello world + +function(vars,callback) +{ + var echo=""; + echo +="hello world "; + if(vars.name){ + echo +=vars.name; + } + if(callback) + callback(echo); + else + return echo; +} + +*/ + +var app={};this.app = app; + + +app.libs={}; + +app.autoreload = require('deps/node-hot-reload'); app.autoreload.path=__dirname; +app._ = require('deps/nodejs-clone-extend/merger'); // lets do: _.extend(same,otherobjexts), _.clone(obj) - creates new reference, see source to understand // +app.phpjs = require('phpjs'); // http://phpjs.org/packages/view/2693/name:806d77a73ce93d851a4620f4a788acd7 +app.date = require('date'); // http://phpjs.org/packages/view/2693/name:806d77a73ce93d851a4620f4a788acd7 + +app.path = require('path'); +app.fs = require('fs'); +app.doubletemplate = require('deps/nodejs-meta-templates/doubletemplate');; +app.httputils = require('httputils'); +app.ObjectID = require('deps/node-mongodb-native/lib/mongodb/bson/bson').ObjectID; +app.step = require('deps/step/lib/step'); +app.sys = require('sys'); +app.inflow = require('deps/node-inflow'); +app.url = require('url'); // allaws to parse urls + +app.files_path=__dirname+'/files/'; +app.root_path=__dirname; +app.templates_path=__dirname+'/templates/'; app.doubletemplate.templates_path=app.templates_path; + +app.server={port:8000}; +app.websocket={port:8000}; +app.database={name:'test',server:'localhost',port:27017}; +app.models={}; +app.urls_route_before=[]; +app.url_routes=[]; +app.url_routes_after=[]; + +app.menus={}; +app.collections={}; + + +require('./basicapp_shared_templates').main(app); + +require('./basicfields').main(app); +require('./basicmodel').main(app); + +require('./basicapp_loaddata').main(app); +require('./basicapp_subitems').main(app); + +require('./basicapp_handle_request').main(app); +require('./basicapp_extend_request').main(app); +require('./basicapp_init').main(app); +require('./basicapp_pages').main(app); +require('./dbutil').main(app); + +/* +// auto reload httputils modul during development + + app.autoreload.watchrel("httputils.js", function (newmodule) + { + app.httputils=newmodule; + }); +*/ \ No newline at end of file diff --git a/basicapp_extend_request.js b/basicapp_extend_request.js new file mode 100755 index 0000000..86c6e36 --- /dev/null +++ b/basicapp_extend_request.js @@ -0,0 +1,84 @@ +this.main=function(app) +{ + +var cookie = { + req:null, + get:function() { + var req = this.req; + return (req.headers.cookie ? this.parse(req.headers.cookie) : {}); + }, + parse:function(str) { + var obj = {}, + pairs = str.split(/[;,] */); + for (var i = 0, len = pairs.length; i < len; ++i) { + var pair = pairs[i], + eqlIndex = pair.indexOf('='), + key = pair.substr(0, eqlIndex).trim().toLowerCase(), + val = pair.substr(++eqlIndex, pair.length).trim(); + // Quoted values + if (val[0] === '"') { + val = val.slice(1, -1); + } + // Only assign once + if (obj[key] === undefined) { + //obj[key] = querystring.unescape(val, true); + obj[key] = val; + } + } + return obj; + } +}; + + +function getuser(callback){ + var req = this; + data = req.cookie.get(); + if (data.user_id){ + data.user_id = app.ObjectID.createFromHexString(data.user_id); + app.models.t2_users.getall({_id:data.user_id} , function(result){ + if (result.length>0){ + req.user = result[0]; + callback(req.user); + } else { + callback(false); + } + + }); + } else { + callback(false); + } +} + +function redirect(res, url, callback, code ) { + res.writeHead( code || 302, {'Location': url } ); + res.end(); + if(callback)callback(); +}; + +function query_to_string(query){ + var query_string = ''; + var prefix = '?'; + for (var name in query){ + query_string+= prefix + name + '=' + query[name]; + prefix = '&'; + } + return query_string; +} + + + app.extendrequest=function (req) + { + req.cookie = cookie; + req.cookie.req = req; + req.user = null; + req.getuser = getuser; + req.redirect = redirect; + req.query_to_string = query_to_string; + /* + + req.sessions={} + req.sessions.req=req; + req.sessions.save=session.save; + */ + }; +} \ No newline at end of file diff --git a/basicapp_handle_request.js b/basicapp_handle_request.js new file mode 100755 index 0000000..ca61e4d --- /dev/null +++ b/basicapp_handle_request.js @@ -0,0 +1,173 @@ +this.main=function (app) +{ + + app.dynamicallyCreateServerHandlerFunction=function () + { + return function (req,res) + { + if (req.method==='POST') + { + app.httputils.realpost(req,res,function (querydata) + { + //req.post=querydata; + app.serveRequest(req,res); + }); + } + else + { + app.serveRequest(req,res); + } + } + }; + + var app_loaded=false; + app.serveRequest=function(req, res, newi) // rename to route + { + this.extendrequest(req); + var shared={ 'req':req, 'res':res, 'app':app, 'pages':app.pages ,'libs':app.libs }; + + app.httputils.get_user(req); + if(!app_loaded) + { + process.on('uncaughtException', function (err) { + console.log('Caught exception: ' + err.stack); + }); + app_loaded=true; + } + + try + { + if (!req.parsedurl) + { + req.parsedurl=app.url.parse(req.url,true); + if(!req.parsedurl.pathname) req.parsedurl={pathname:'error_in_url'}; + if(!req.parsedurl.query)req.parsedurl.query={}; + //console.log(req.parsedurl.pathname); + //console.log(decodeURIComponent(req.parsedurl.pathname)); + + if(req.parsedurl && req.parsedurl.pathname)req.parsedurl.pathname=decodeURIComponent(req.parsedurl.pathname.replace(/\+/g, '%20')); + //req.times=[]; + //req.times_start=milliseconds(); + //req.times.push(milliseconds()-req.times_start); + } + //console.log(' serveRequest '+newi); + if(!newi) newi=0; + + var myurl=req.parsedurl; + var urlmatch=false; + + + for(var i=newi;iUnhandeld requestUnhandeld request \r\n the url: \r\n "+req.parsedurl.pathname+" \r\n did not matched any handler click here to go to the main page"); + res.end(); + } + } + catch(error) + { + console.log("error: "+req.parsedurl.pathname); + //app.urls[0][1][app.urls[0][2]](req, res); + res.writeHead(202, { 'Content-Type': 'text/html;charset:utf-8'}); + res.write("Server ErrorServer Error in Handle Request (url: "+req.parsedurl.pathname+"): \r\n
"+error.stack+"
\r\n click here to go to the main page"); + res.end(); + } + }; + + +/* + app.setupWebSocket=function() + { + // Websocket TCP server + var wsServer = ws.createServer({log: false}); + wsServer.listen(config.websocket_port); + + wsServer.addListener("connection", function (conn) { + console.log("ws connect: " + conn._id); + conn.addListener("close", function () { + console.log("ws close: " + conn._id); + }); + }); + + this.wsServer = wsServer; + + console.log('Web Socket server running at ws://*:' + app.websocket_port); + }; + + + app.addAllMetrics=function(db) { + var self = this; + + Metric.allMetrics(function(metric) { + metric.init(db); + metric.wsServer = self.wsServer; + self.metrics.push(metric); + }); + }; +*/ + +} \ No newline at end of file diff --git a/basicapp_init.js b/basicapp_init.js new file mode 100755 index 0000000..db254d5 --- /dev/null +++ b/basicapp_init.js @@ -0,0 +1,72 @@ +this.main=function(app) +{ +//app.milliseconds=milliseconds, + app.init_first=function(modules) + { + // install modules and setup models + console.log("starting to install modules and to setup models"); + for(var i =0; i < modules.length ; i++ ) + modules[i].setupfirst(app); + + console.log("start app.load_app_templates"); + app.load_app_templates(); + console.log("start modules[i].setup"); + for(var i =0; i < modules.length ; i++ ) modules[i].setup(app) ; + console.log("start app.models[i].setupfirst"); + for(var i in app.models) app.models[i].setupfirst(app); + console.log("start app.models[i].setup"); + for(var i in app.models) app.models[i].setup(app); + console.log("end install modules and setup models"); + // end install modules and setup models + }; + + app.init=function(db,modules,callback) + { + //setup cllections and continue to setup pages + console.log("start app.init"); + app.setupDb(db, function() + { + console.log("start app.models[i].setuplast"); + // last install modules and setup models + for(var i in app.models) app.models[i].setuplast(app); + console.log("start app.modules[i].setuplast"); + for(var i =0; i < modules.length ; i++ ) modules[i].setuplast(app) ; + app.setuppages(); + // end last install modules and setup models + + callback(); + + }); + // this.setupWebSocket(); + // probably it is posible to start services here + }; + app.init_last=function() + { + // probably database based init can go here + }; + + app.setupDb=function(db, callback) { + + // simple version: + // db.createCollection('visits', function(err, collection) + // { + // db.collection('visits', function(err, collection) + // { + // model.collection = collection; callback(); }); }); + + app.inflow.each({'app':app},app.models,function (model,key){ + var next=this; + //console.log('create collection: app.models.'+model.modelname+'.collection = '+model.general.name); + model.modelname=key; + //db.createCollection(model.general.name, function(err, collection) { + db.collection(model.general.name , function(err, collection) { + //console.log('collection created!'); + model.collection = collection; + next(); + }); + //}); + + },callback); + + }; +}; \ No newline at end of file diff --git a/basicapp_loaddata.js b/basicapp_loaddata.js new file mode 100755 index 0000000..2bb2540 --- /dev/null +++ b/basicapp_loaddata.js @@ -0,0 +1,341 @@ +this.main =function main(app) +{ + + app.fake_load_data= function(items_to_load,retdata,callback) + { + var call_count=1; + + for(var items_to_load_key2 in items_to_load) + { + if(items_to_load.hasOwnProperty(items_to_load_key2)) + { + var info_of_model_to_load2=items_to_load[items_to_load_key2]; + call_count++; + (function(info_of_model_to_load,items_to_load_key) { + process.nextTick(function () + { + var loaded_subitems={},items={}; + // + retdata['item_name'] = items_to_load_key; + retdata[items_to_load_key] = app._.clone(info_of_model_to_load.empty_object); + // + //console.log(sys.inspect(info_of_model_to_load)) + retdata['error_name'] = 'error_' +items_to_load_key; + retdata['error_' +items_to_load_key] = null; + // + retdata['cursor_name'] = 'cursor_' +items_to_load_key; + retdata['cursor_' +items_to_load_key] = items; + // + if(info_of_model_to_load.load_one) + { + retdata['item_name'] = items_to_load_key; + retdata[items_to_load_key] = app._.clone(info_of_model_to_load.model.empty_object); + } + // + if(info_of_model_to_load.askey) + { + var askey={}; + //for(var i=0;i0?items[0]:app._.clone(info_of_model_to_load.model.empty_object); + } + // + if(info_of_model_to_load.askey) + { + var askey={}; + for(var i=0;i0?items[0]:app._.clone(info_of_model_to_load.model.empty_object); + } + // + if(info_of_model_to_load.askey) + { + var askey={}; + // for(var i=0;i0?items[0]:app._.clone(info_of_model_to_load.model.empty_object); + } + + // + if(info_of_model_to_load.askey) + { + var askey={}; + for(var i=0;i