Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

0.0.1

  • Loading branch information...
commit 1ec6a202224409b0477c2cdd818fc5fb38557c54 1 parent 0c8eddc
@morozovsk authored
Showing with 589 additions and 0 deletions.
  1. +283 −0 controller.js
  2. +142 −0 index.js
  3. +11 −0 package.json
  4. +153 −0 xml.js
View
283 controller.js
@@ -0,0 +1,283 @@
+module.exports = function (mvc, app, request, response) {
+ this._app = app;
+ this._request = request;
+ this._response = response;
+ this._params = request.params;
+ this._param = request.param;
+ this._query = request.query;
+ this._cookies = request.cookies;
+ this._partial = response.partial;
+ this._redirect = response.redirect;
+
+ this._formats = [];
+ this._view = {};
+ this._template = null;
+ this._layout = null;
+
+ this._local = response.local;
+ this._locals = response.locals;
+
+ this._render = function () {
+ return response.render(request.params.controller + '/' + request.params.action, this._view);
+ }
+
+ this._json = function () {
+ return response.json(this._view);
+ }
+
+ this._jsonp = function () {
+ return response.send(request.query.callback + '(' + JSON.stringify(this._view) + ');');
+ }
+
+ this._xml = function () {
+ return response.send(require('mvc/xml').XML.stringify(this._view));
+ }
+
+ this._output = function () {
+ if (this._formats.length) {
+ for (var i in this._formats) {
+ if (request.is(this._formats[i])) {
+ if (this._formats[i] == 'html') {
+ this._render();
+ } else if (this._formats[i] == 'json') {
+ response._json();
+ } else if (this._formats[i] == 'javascript') {
+ response._jsonp();
+ } else if (this._formats[i] == 'xml') {
+ response._xml();
+ }
+ break;
+ }
+ }
+ response.end();
+ } else {
+ this._render();
+ }
+ }
+
+ this._model = function (modelName, moduleName) {
+ if (moduleName == undefined) {
+ moduleName = app.set('defaultModule');
+ }
+
+ if (mvc.models[moduleName] == undefined || mvc.models[moduleName][modelName] == undefined) {
+ throw new Error('Model ' + modelName + ' does not exist in module ' + moduleName);
+ }
+
+ return mvc.models[moduleName][modelName];
+ }
+
+ this._queryParam = function (name, defaultValue) {
+ if (request.query[name] !== undefined) {
+ return this.query[name];
+ }
+
+ return defaultValue;
+ };
+
+ this._url = function (params) {
+ var url = '/';
+
+ if (params.module !== undefined && params.module !== app.set('defaultModule') || params.controller !== undefined && params.controller !== app.set('defaultController') || params.action !== undefined && params.action !== app.set('defaultController')) {
+ url += (params.module == undefined ? app.set('defaultModule') : params.module);
+
+ if (params.controller !== undefined && params.controller !== app.set('defaultController') || params.action !== undefined && params.action !== app.set('defaultController')) {
+ url += '/' + (params.controller == undefined ? app.set('defaultController') : params.controller);
+
+ if (params.action !== undefined && params.action !== app.set('defaultController')) {
+ url += '/' + (params.action ? app.set('defaultAction') : params.action);
+ }
+ }
+ }
+
+ delete params.module;
+ delete params.controller;
+ delete params.action;
+
+ var qs = require('qs').stringify(params);
+
+ if (qs) {
+ url += '?' + qs;
+ }
+
+ return url;
+ }
+
+ /*this._forward = function (action, controller, module, query) {
+
+ }*/
+}
+
+//module.exports.qwe = function(){}
+
+/*
+ this.redirect = function (target) {
+ var url;
+ if (typeof target == 'string') {
+ url = target;
+ }
+ else if (typeof this.app.router.url == 'function') {
+ if (this.name && !target.controller)
+ target.controller = this.name;
+ if (this.params.format && !target.format)
+ target.format = this.params.format;
+
+ url = this.app.router.url(target);
+ }
+
+ if (!url) {
+ var contr = target.controller || this.name;
+ var act = target.action;
+ var ext = target.format || this.params.format;
+ var id = target.id;
+ contr = geddy.string.decamelize(contr);
+ url = '/' + contr;
+ url += act ? '/' + act : '';
+ url += id ? '/' + id : '';
+ if (ext) {
+ url += '.' + ext;
+ }
+ }
+
+ this.content = '';
+
+ _doResponse.apply(this, [302, {'Location': url}]);
+ };
+
+ this.transfer = function (action) {
+ this.params.action = action;
+ this._handleAction(action);
+ };
+
+ this.respond = function (content, opts) {
+ var options = opts || {}
+ , format = typeof opts == 'string' ? options : options.format
+ , negotiated = _negotiateContent.call(this, format);
+
+ // Error during content-negotiation may result in an error response;
+ // do not continue
+ if (this.completed) {
+ return;
+ }
+
+ this.format = negotiated.format;
+ this.contentType = negotiated.contentType;
+
+ if (!this.contentType) {
+ var err = new errors.NotAcceptableError('Not an acceptable media type.');
+ this.error(err);
+ }
+
+ if (options.template) {
+ this.template = options.template;
+ }
+ if (options.layout) {
+ this.layout = 'app/views/' + options.layout;
+ }
+
+ // If content needs formatting
+ if (typeof content != 'string') {
+ if (this.format) {
+ // Special-case HTML -- will go out to template-rendering code,
+ // and then come back here with content as a string
+ if (this.format == 'html') {
+ this.renderTemplate(content);
+ return;
+ }
+ // Otherwise format according to ... format
+ else {
+ content = controller.formatters[this.format](content, this);
+ }
+ }
+ // If we couldn't perform content-negotiaton successfully, bail
+ // with error
+ else {
+ _throwUndefinedFormatError.call(this);
+ return;
+ }
+ }
+
+ this.content = content;
+ _doResponse.apply(this, [200, {'Content-Type': this.contentType}]);
+
+ };
+
+
+ this.renderTemplate = function (data) {
+ var _this = this
+ , dirName;
+
+ dirName = geddy.inflection.pluralize(this.name);
+ dirName = geddy.string.snakeize(dirName);
+
+ // Calculate the template if not set
+ this.template = this.template ||
+ 'app/views/' + dirName + '/' + this.params.action;
+
+ // Calculate the layout if not set
+ this.layout = this.layout ||
+ 'app/views/layouts/' + dirName;
+
+ var templater = new Templater();
+ var content = '';
+
+ templater.addListener('data', function (d) {
+ // Buffer for now, but could stream
+ content += d;
+ });
+
+ templater.addListener('end', function () {
+ _this.respond(content, 'html');
+ });
+
+ templater.render(data, {
+ layout: this.layout
+ , template: this.template
+ , controller: this.name
+ , action: this.params.action
+ });
+ };
+
+ this.url = function (params) {
+ var url = false;
+
+ // attempt the stringification with defaults mixed in
+ params = geddy.mixin({controller:'Application', action:'index' }, params);
+
+ // iterate through the existing routes until a suitable match is found
+ for (var i in this.routes) {
+ // do the controller & acton match?
+ if (typeof(this.routes[i].params.controller) != 'undefined' &&
+ this.routes[i].params.controller != params.controller) {
+ continue;
+ }
+ if (typeof(this.routes[i].params.action) != 'undefined' &&
+ this.routes[i].params.action != params.action) {
+ continue;
+ }
+
+ url = this.routes[i].stringify(params);
+ if (url) {
+ break;
+ }
+ }
+
+ // no love? return false
+ if (!url) {
+ return false;
+ }
+
+
+ // build the possibly empty query string
+ //var qs = require('../../deps/qs').stringify(url[1]);
+
+ // if there is a query string...
+ //if (qs.length > 0) {
+ //return url[0] + '?' + qs;
+ //}
+
+
+ // just return the url
+ return url[0];
+ };
+ }*/
View
142 index.js
@@ -0,0 +1,142 @@
+module.exports.app = {}
+module.exports.controllers = {}
+module.exports.models = {}
+
+module.exports.init = function(app) {
+ module.exports.app = app;
+ var util = require('util');
+ var path = require('path');
+ var fs = require('fs');
+
+ var loadModule = function (modulePath, moduleName) {
+ var loadComponents = function (type) {
+ var componentsPath = path.join(modulePath, app.set(type + 'Directory'));
+ //console.log(componentsPath);
+ module.exports[type + 's'][moduleName] = {};
+
+ var components = [];
+
+ try {
+ components = fs.readdirSync(componentsPath);
+ } catch (e) {}
+
+ if (components.length) {
+ var componentPath, componentName;
+ for (var i = 0; i < components.length; i++) {
+ componentPath = path.join(componentsPath, components[i]);
+ //console.log(componentPath);
+
+ componentName = components[i];
+ if (componentName.slice(-3) == '.js') {
+ componentName = componentName.slice(0,-3);
+ }
+
+ var component = require(componentPath);
+
+ module.exports[type +'s'][moduleName][componentName] = component;
+ }
+ }
+ }
+
+ loadComponents('controller');
+ loadComponents('model');
+ }
+
+ var appPath = path.join(process.cwd() ,app.set('applicationDirectory'));
+
+ loadModule(appPath, app.set('defaultModule'));
+
+ var modulesPath = path.join(process.cwd(), app.set('applicationDirectory'), app.set('moduleDirectory'));
+
+ //console.log(util.inspect(module.exports));
+
+ //console.log(modulesPath);
+ var modules = [];
+ try {
+ modules = fs.readdirSync(modulesPath);
+ } catch (e) {}
+ //console.log(modules)
+
+ if (modules.length) {
+ for (var i = 0; i < modules.length; i++) {
+ //console.log(modules[i]);
+ //console.log(util.inspect(module.exports.controllers));
+ loadModule(path.join(modulesPath, modules[i]), modules[i]);
+ }
+ }
+
+ //load models and controllers;
+
+ app.all('/:module?/:controller?/:action?', function(req, res, next) {
+ req.params.module = req.param('module', app.set('defaultModule'));
+ req.params.controller = req.param('controller', app.set('defaultController'));
+ req.params.action = req.param('action', app.set('defaultAction'));
+
+ if (module.exports.controllers[req.params.module] == undefined) {
+ req.params.controller = req.params.module;
+ req.params.module = app.set('defaultModule');
+ }
+
+ //res.end(util.inspect(req.params));return;
+
+ if (module.exports.controllers[req.params.module] == undefined || module.exports.controllers[req.params.module][req.params.controller] == undefined) {
+ next();
+ return;
+ }
+
+ var controller = new module.exports.controllers[req.params.module][req.params.controller]();
+
+ if (controller[req.params.action + 'Action'] == undefined) {
+ next();
+ return;
+ }
+
+ //var path = require('path');
+
+ if (req.params.module == app.set('defaultModule')) {
+ app.set('views', process.cwd() + path.join(app.set('applicationDirectory'), app.set('viewDirectory')));
+ } else {
+ app.set('views', process.cwd() + path.join(app.set('applicationDirectory'), app.set('moduleDirectory'), req.params.module, app.set('viewDirectory')));
+ }
+
+ //console.log(app.set('views'));
+
+ try {
+ var helper = require('mvc/controller');
+ helper = new helper(module.exports, module.exports.app, req, res);
+ for (var i in helper) {
+ controller[i] = helper[i];
+ }
+
+ //controller._render('index');
+ //controller._model('message2s');
+
+
+ if (controller.before != undefined) {
+ controller.before();
+ }
+
+ controller[req.params.action + 'Action']();
+
+ //console.log(controller.asd);
+ //res.render(req.params.controller + '/' + req.params.action, controller._view);
+
+ if (controller.after != undefined) {
+ controller.after();
+ }
+
+ //controller._output();
+
+ //res.end();
+
+ //console.log(util.inspect(req.params));
+
+
+ //require('/var/www/mrzjs/eval2.js');
+ } catch(e) {
+ console.log(e.stack.toString());
+ res.end(e.stack.toString());
+ }
+ //console.log('Server running at http://127.0.0.1:8124/');
+ });
+}
View
11 package.json
@@ -0,0 +1,11 @@
+{
+ "name": "mvc",
+ "description": "mvc for expess",
+ "version": "0.0.1",
+ "homepage": "https://github.com/morozovsk/mvc",
+ "repository": "https://github.com/morozovsk/mvc",
+ "author": "morozovsk <morozovsk@gmail.com> (https://github.com/morozovsk)",
+ "engines": {
+ "node": "*"
+ }
+}
View
153 xml.js
@@ -0,0 +1,153 @@
+exports.XML = new (function () {
+ var whitespace = true
+ , indentLevel = 4;
+
+ var tagFromType = function (item, prev) {
+ var ret
+ , type
+ , types;
+ if (item instanceof Array) {
+ ret = 'array';
+ }
+ else {
+ types = ['string', 'number', 'boolean', 'object'];
+ for (var i = 0, ii = types.length; i < ii; i++) {
+ type = types[i];
+ if (typeof item == type) {
+ ret = type;
+ }
+ }
+ }
+ if (prev && ret != prev) {
+ return 'record'
+ }
+ else {
+ return ret;
+ }
+ }
+
+ , obj2xml = function (o, name, level) {
+ var pack
+ , item
+ , n
+ , currentIndent = (new Array(level * indentLevel)).join(' ')
+ , nextIndent = (new Array((level + 1) * indentLevel)).join(' ')
+ , xml = '';
+ switch (typeof o) {
+ case 'string':
+ case 'number':
+ case 'boolean':
+ xml = o.toString();
+ break;
+ case 'object':
+ // Arrays
+ if (o instanceof Array) {
+
+ // Pack the processed version of each item into an array that
+ // can be turned into a tag-list with a `join` method below
+ // As the list gets iterated, if all items are the same type,
+ // that's the tag-name for the individual tags. If the items are
+ // a mixed, the tag-name is 'record'
+ pack = [];
+ for (var i = 0, ii = o.length; i < ii; i++) {
+ item = o[i];
+ if (!name) {
+ // Pass any previous tag-name, so it's possible to know if
+ // all items are the same type, or it's mixed types
+ n = tagFromType(item, n);
+ }
+ pack.push(obj2xml(item, '', level + 1));
+ }
+
+ // If this thing is attached to a named property on an object,
+ // use the name for the containing tag-name
+ if (name) {
+ n = name;
+ }
+
+ // If this is a top-level item, wrap in a top-level containing tag
+ if (level == 0) {
+ xml += currentIndent + '<' + n + 's type="array">\n'
+ }
+ xml += nextIndent + '<' + n + '>' +
+ pack.join('</' + n + '>\n' + nextIndent +
+ '<' + n + '>') + '</' + n + '>\n';
+
+ // If this is a top-level item, close the top-level containing tag
+ if (level == 0) {
+ xml += currentIndent + '</' + n + 's>';
+ }
+ }
+ // Generic objects
+ else {
+ n = name || 'object';
+
+ // If this is a top-level item, wrap in a top-level containing tag
+ if (level == 0) {
+ xml = currentIndent + '<' + n + '>\n';
+ }
+ for (var p in o) {
+ item = o[p];
+
+ xml += nextIndent;
+
+ if (p == '#cdata') {
+ xml += '<![CDATA[' + item + ']]>\n';
+ }
+ else {
+ xml += '<' + p;
+ // Complex values, going to have items with multiple tags
+ // inside
+ if (typeof item == 'object') {
+ if (item instanceof Array) {
+ xml += ' type="array">\n'
+ }
+ else {
+ xml += '>\n';
+ }
+ }
+ // Scalars, just a value and closing tag
+ else {
+ xml += '>'
+ }
+ xml += obj2xml(item, p, level + 1);
+
+ // Objects and Arrays, need indentation before closing tag
+ if (typeof item == 'object') {
+ xml += nextIndent;
+ }
+ xml += '</' + p + '>\n';
+ }
+ }
+ // If this is a top-level item, close the top-level containing tag
+ if (level == 0) {
+ xml += currentIndent + '</' + n + '>\n';
+ }
+ }
+ break;
+ default:
+ // No default
+ }
+ return xml;
+ };
+
+ this.setNoWhitespace = function () {
+ indentLevel = 0;
+ whitespace = false;
+ };
+
+ this.setIndentLevel = function (level) {
+ indentLevel = level;
+ };
+
+ this.stringify = function (o) {
+ var xml = '';
+ xml += '<?xml version="1.0" encoding="UTF-8"?>\n';
+ xml += obj2xml(o, '', 0);
+ if (!whitespace) {
+ xml = xml.replace(/>\n/g, '>');
+ }
+ return xml;
+ };
+
+})();
Please sign in to comment.
Something went wrong with that request. Please try again.