Permalink
Browse files

First release

  • Loading branch information...
0 parents commit 1060a5630eb6e3a5c90c10ca36917d4c68cad3a9 @indutny committed Jan 22, 2011
Showing with 418 additions and 0 deletions.
  1. +1 −0 config.json
  2. +12 −0 config/db.js
  3. +103 −0 lib/helpers.js
  4. +125 −0 lib/loader.js
  5. +38 −0 modules/express/server.js
  6. +14 −0 modules/express/static.js
  7. +39 −0 modules/utils.js
  8. +18 −0 modules/your_site/pages.js
  9. +15 −0 package.json
  10. +32 −0 run
  11. +1 −0 static/css/style.css
  12. +4 −0 static/js/main.js
  13. +14 −0 views/layout.ejs
  14. +2 −0 views/pages/index.ejs
@@ -0,0 +1 @@
+{ "db": { "host": "localhost", "port": 5984, "auth": { "user": "admin", "pass": "admin" } }, "http": { "port": 8022 }}
@@ -0,0 +1,12 @@
+// This file will create database connection
+// And call "fn" when connection is ready
+module.exports = function(config, fn) {
+ var cradle = require('cradle'),
+ db = new (cradle.Connection)({
+ host: config.db.host || 'localhost',
+ port: config.db.port || 5984,
+ auth: config.db.auth
+ }).database(config.db.name);
+
+ fn(db);
+};
@@ -0,0 +1,103 @@
+var fs = require('fs'),
+ path = require('path'),
+ Script = process.binding('evals').Script;
+
+/**
+* Check, whether dir is directory or not
+*/
+var isDirectory = exports.isDirectory = function(dir) {
+ var stat;
+ return path.existsSync(dir) && (stat = fs.statSync(dir)) &&
+ stat.isDirectory();
+}
+
+/**
+* is obj function?
+*/
+exports.isFunction = function(obj) {
+ return typeof obj === 'function';
+}
+
+/**
+* Copy own properties of b to a
+*/
+exports.extend = function(a, b) {
+ if (!b) return a;
+
+ for (var i in b) {
+ if (b.hasOwnProperty(i)) a[i] = b[i];
+ }
+
+ return a;
+};
+
+/**
+* This function will be used to process files array
+*/
+exports.reduce = function(dir) {
+ dir = path.normalize(dir);
+
+ return function(accum, elem) {
+ var filepath = elem.substr(dir.length);
+
+ if (!filepath) return accum;
+
+ // Process only files
+ if (!isDirectory(elem)) {
+ accum.push({
+ extension: path.extname(filepath),
+ name: filepath.replace(/\.[^\.]+$/, ''),
+ filepath: elem
+ });
+ }
+
+ return accum;
+ }
+};
+
+/**
+* Compile script in a new context
+* Very common to nodejs module system
+*/
+exports.require = function(file, context) {
+ var content = fs.readFileSync(file.filepath);
+
+ if (file.extension !== '.js') {
+ return content;
+ }
+ try {
+ var fn = Script.runInNewContext('(function(require, __dirname, ' +
+ '__filename, module, exports) {\n' +
+ content +
+ '\n;})', context, file.filepath),
+ exports = {},
+ module = {exports: exports},
+ dirname = path.dirname(file.filepath);
+
+ fn(require, dirname, file.filepath, module, exports);
+ } catch (e) {
+ console.log('Failed to load: ' + file.filepath, e);
+ return {};
+ }
+ return module.exports;
+};
+
+/**
+* Helps storing modules in javascript object
+* a.b.c = x => {a:{b:{c: x}}}
+*/
+exports.store = function(storage, key, val) {
+ var previous;
+ key.split(/\.|\//g).forEach(function(subkey) {
+ subkey = subkey.trim();
+
+ previous = {
+ storage: storage,
+ subkey: subkey
+ };
+ storage = storage[subkey] || (storage[subkey] = {});
+ });
+
+ if (!previous) return;
+ previous.storage[previous.subkey] = val;
+};
@@ -0,0 +1,125 @@
+var fs = require('fs'),
+ path = require('path'),
+ sys = require('sys'),
+ watch = require('watch'),
+ helpers = require('./helpers');
+
+
+/**
+* Loader - loads all js files from a directory root,
+* compiles them and puts them into objects variable
+*/
+var loader = module.exports = function(dir, context, callback) {
+ if (!helpers.isDirectory(dir)) return;
+
+ // Add trailing slash
+ dir = dir.replace(/\/+$/, '') + '/';
+
+ // Context must be defined
+ context = context || {};
+
+ var objects = {},
+ weighted = [],
+ args = Array.prototype.slice.call(arguments, 1);
+
+ addInvokeMethods(context, weighted);
+
+ watch.walk(dir, function(err, files_obj) {
+ if (err) {
+ console.log(err);
+ return;
+ }
+
+ var files = [];
+
+ for (var file in files_obj) {
+ if (!files_obj.hasOwnProperty(file)) continue;
+
+ files.push(file);
+ }
+
+ // Replace kind of wildcard '?' with objects itself,
+ // So objects can be passed to context on demand
+ for (var i in context) if (context[i] === '?') context[i] = objects;
+
+ files.reduce(helpers.reduce(dir), []).forEach(function(file) {
+ var result = helpers.require(file, context);
+
+ // If module is disabled - do not load it
+ if (result.enabled === false) return;
+
+ // Add to modules object
+ var object = result;
+
+ helpers.store(objects, file.name, object);
+
+ // Add to weighted collection
+ weighted.push({
+ weight: parseInt(object.weight) || 0,
+ name: file.name,
+ value: object
+ });
+ });
+
+ // Sort objects in collection by weight
+ weighted.sort(function(a, b) {
+ return a.weight > b.weight;
+ });
+
+ // All objects are in place
+ // Invoke init
+ process.nextTick(function() {
+ context.invoke('init');
+ });
+
+ callback && callback(null, context.invoke.emitter);
+ });
+}
+
+/**
+* Adds invoke methods to execution context
+*
+* Provides cool syntax
+* invoke('init', arg1, arg2, arg3).array
+*/
+function addInvokeMethods(context, weighted) {
+ var len;
+
+ context.invoke = function(callbackName) {
+ var args = Array.prototype.slice.call(arguments, 1);
+
+ // Calculate length only once
+ len = len || weighted.length;
+
+ var array = [], object = {};
+
+ for (var i = 0; i < len; i++) {
+ var elem = weighted[i],
+ callback = elem.value[callbackName];
+
+ if (!elem.value.hasOwnProperty(callbackName) ||
+ !helpers.isFunction(callback)) continue;
+
+ try {
+ var result = callback.apply(elem, args);
+ array.push(result);
+ helpers.store(object, elem.name, result);
+ } catch (e) {
+ sys.puts(e);
+ }
+ }
+
+ // Invoke EventEmitter (for debug purposes)
+ context.invoke.emitter.emit.apply(
+ context.invoke.emitter,
+ arguments
+ );
+
+ return {
+ object: object,
+ array: array
+ };
+ };
+
+ context.invoke.emitter = new process.EventEmitter;
+}
@@ -0,0 +1,38 @@
+/**
+* Express.js: HTTP Server
+*
+* Adds .middleware(express) and .routes(app) callbacks
+*/
+
+/**
+* .init() callback
+*/
+exports.init = function() {
+ var express = require('express'),
+ middleware = invoke('middleware', express).array;
+
+ middleware.unshift(express.errorHandler());
+
+ var server = express.createServer.apply(express, middleware);
+
+ // Decode body and cookies
+ server.use(express.bodyDecoder());
+ server.use(express.cookieDecoder());
+
+ // Configure views
+ server.set('views', rootdir + '/views');
+ server.set('view engine', 'ejs');
+
+ // Apply routes
+ invoke('routes', server);
+
+ server.listen(config.http.port, function() {
+ console.log('Server has started listening on port ' + config.http.port);
+ invoke('http-listening');
+ });
+}
+
+/**
+* Module's weight
+*/
+exports.weight = -1E6;
@@ -0,0 +1,14 @@
+/**
+* Express.js : Static provider
+*
+* Servers static content
+*/
+
+/**
+* Export static content middleware
+*/
+exports.middleware = function(express) {
+ return express.staticProvider(rootdir + '/static/');
+}
+
+exports.weight = 6;
@@ -0,0 +1,39 @@
+/**
+* Adds middleware, that adds methods:
+* # json
+*/
+
+var Buffer = require('buffer').Buffer;
+
+/**
+* Exports middleware
+*/
+exports.middleware = function adds_json_method(express) {
+ return function(req, res, next) {
+ var jsonp = req.query && req.query.callback;
+
+ res.json = function(data, code) {
+ data = jsonp ? jsonp + '(' + JSON.stringify(data) + ')' :
+ JSON.stringify(data);
+
+ var headers = {
+ 'Content-Type': jsonp ? 'text/javascript' : 'application/json',
+ 'Content-Length': Buffer.byteLength(data)
+ };
+
+ if (res.header('Set-Cookie')) {
+ headers['Set-Cookie'] = res.header('Set-Cookie');
+ }
+
+ res.writeHead(code || 200, headers);
+ res.end(data);
+ };
+
+ next();
+ }
+}
+
+/**
+* Try to be first
+*/
+exports.weight = -1E9;
@@ -0,0 +1,18 @@
+/**
+* This should be your site's pages module
+*/
+
+exports.routes = function(app) {
+ function index_page(req, res) {
+ res.render('pages/index', {
+ locals: {
+ title: 'My node.modular site',
+ req: req
+ }
+ });
+ }
+
+ app.get('/', index_page);
+ app.get('/index', index_page);
+
+};
@@ -0,0 +1,15 @@
+{
+ "name": "your-app-name",
+ "description": "...",
+ "version": "0.0.1",
+ "author": "Fedor Indutny <fedor.indutny@gmail.com>",
+ "keywords": ["admin"],
+ "dependencies": {
+ "cradle": ">= 0.3.1",
+ "ejs": ">= 0.2.1",
+ "express": ">= 1.0.1",
+ "request": ">= 0.10.0",
+ "step": ">= 0.0.3"
+ },
+ "engines": { "node": ">= 0.2.6" }
+}
Oops, something went wrong.

0 comments on commit 1060a56

Please sign in to comment.