Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Create gh-pages branch via GitHub

  • Loading branch information...
commit 9dd1731cd426af1824da494a8bd28947028ce71b 1 parent c5e813b
@Shogun147 authored
Showing with 120 additions and 54 deletions.
  1. +119 −53 index.html
  2. +1 −1  params.json
View
172 index.html
@@ -1,38 +1,34 @@
-<!doctype html>
+<!DOCTYPE html>
<html>
<head>
- <meta charset="utf-8">
+ <meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="chrome=1">
- <title>Katana by Shogun147</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+ <link href='https://fonts.googleapis.com/css?family=Architects+Daughter' rel='stylesheet' type='text/css'>
+ <link rel="stylesheet" type="text/css" href="stylesheets/stylesheet.css" media="screen" />
+ <link rel="stylesheet" type="text/css" href="stylesheets/pygment_trac.css" media="screen" />
+ <link rel="stylesheet" type="text/css" href="stylesheets/print.css" media="print" />
- <link rel="stylesheet" href="stylesheets/styles.css">
- <link rel="stylesheet" href="stylesheets/pygment_trac.css">
- <script src="javascripts/scale.fix.js"></script>
- <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
- </head>
- <body>
- <div class="wrapper">
- <header>
- <h1 class="header">Katana</h1>
- <p class="header">Easy to use, modular web framework for any Node.js samurai</p>
-
- <ul>
- <li class="download"><a class="buttons" href="https://github.com/Shogun147/Katana/zipball/master">Download ZIP</a></li>
- <li class="download"><a class="buttons" href="https://github.com/Shogun147/Katana/tarball/master">Download TAR</a></li>
- <li><a class="buttons github" href="https://github.com/Shogun147/Katana">View On GitHub</a></li>
- </ul>
-
- <p class="header">This project is maintained by <a class="header name" href="https://github.com/Shogun147">Shogun147</a></p>
+ <title>Katana by Shogun147</title>
+ </head>
- </header>
- <section>
- <h1>
-<a name="katana" class="anchor" href="#katana"><span class="octicon octicon-link"></span></a><a href="https://github.com/Shogun147/Katana">Katana</a>
-</h1>
+ <body>
+ <header>
+ <div class="inner">
+ <h1>Katana</h1>
+ <h2>Easy to use, modular web framework for any Node.js samurai</h2>
+ <a href="https://github.com/Shogun147/Katana" class="button"><small>View project on</small>GitHub</a>
+ </div>
+ </header>
+
+ <div id="content-wrapper">
+ <div class="inner clearfix">
+ <section id="main-content">
+ <p><a href="https://github.com/Shogun147/Katana"><img src="https://raw.github.com/Shogun147/Katana/master/katana.jpg"></a></p>
<p>Easy to use, modular web framework for any Node.js samurai, focuses on simplicity, maintainability and performance.</p>
@@ -295,10 +291,10 @@ <h1 class="header">Katana</h1>
<ul>
<li><code>katana module install auth</code></li>
<li><code>katana module install auth@0.1.0</code></li>
-<li><code>katana module install Shogun147:Katana-auth</code></li>
-<li><code>katana module install Shogun147:Katana-auth@0.1.0</code></li>
-<li><code>katana module install https://github.com/Shogun147/Katana-auth/tarball/master</code></li>
-<li><code>katana module install http://my-site.com/downloads/module/v1.0.5</code></li>
+<li><code>katana module install auth Shogun147:Katana-auth</code></li>
+<li><code>katana module install auth Shogun147:Katana-auth@0.1.0</code></li>
+<li><code>katana module install auth https://github.com/Shogun147/Katana-auth/tarball/master</code></li>
+<li><code>katana module install auth http://my-site.com/downloads/module/v1.0.5</code></li>
</ul>
</li>
<li><p><code>katana module uninstall &lt;name&gt;</code> - uninstall and remove module</p></li>
@@ -328,6 +324,10 @@ <h1 class="header">Katana</h1>
<span class="p">});</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Home_Controller</span><span class="p">;</span>
+
+<span class="c1">// to not expose this class as a global, create it as anonymous</span>
+<span class="kd">var</span> <span class="nx">HomeController</span> <span class="o">=</span> <span class="nx">Class</span><span class="p">({</span> <span class="p">...</span> <span class="p">});</span> <span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">HomeController</span><span class="p">;</span>
+
</pre></div>
<p>And now we can access this <code>index</code> action by opening http://katana:8000/, without any uri path this will use default controller and action from config which are <code>home</code> and <code>index</code>. Also we can access them directly by opening http://katana:8000/<code>home</code>/ with <code>index</code> as default action or http://katana:8000/<code>home</code>/<code>index</code>.</p>
@@ -440,18 +440,19 @@ <h1 class="header">Katana</h1>
<span class="nx">Response</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="s1">'index'</span><span class="p">,</span> <span class="p">{</span> <span class="nx">title</span><span class="o">:</span> <span class="s1">'Hello World'</span> <span class="p">});</span> <span class="c1">// this will render index.html file from views</span>
<span class="c1">// get rendered content</span>
- <span class="kd">var</span> <span class="nx">content</span> <span class="o">=</span> <span class="nx">View</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="s1">'index'</span><span class="p">,</span> <span class="p">{</span> <span class="nx">title</span><span class="o">:</span> <span class="s1">'Hello World'</span> <span class="p">});</span>
- <span class="c1">// and latter send response</span>
- <span class="nx">Response</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="nx">content</span><span class="p">);</span>
+ <span class="nx">View</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="s1">'index'</span><span class="p">,</span> <span class="p">{</span> <span class="nx">title</span><span class="o">:</span> <span class="s1">'Hello World'</span> <span class="p">},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">error</span><span class="p">,</span> <span class="nx">content</span><span class="p">)</span> <span class="p">{</span>
+ <span class="c1">// and latter send response</span>
+ <span class="nx">Response</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="nx">content</span><span class="p">);</span>
+ <span class="p">});</span>
<span class="c1">// render a view from module</span>
<span class="nx">Users</span><span class="p">.</span><span class="nx">find</span><span class="p">({},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">error</span><span class="p">,</span> <span class="nx">users</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">Response</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">'Error! Blablabla'</span><span class="p">);</span> <span class="p">}</span>
<span class="c1">// again module name separated by colon, and then path to the view</span>
- <span class="kd">var</span> <span class="nx">list</span> <span class="o">=</span> <span class="nx">View</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="s1">'auth:list'</span><span class="p">,</span> <span class="nx">users</span><span class="p">);</span>
-
- <span class="nx">Response</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="s1">'index'</span><span class="p">,</span> <span class="p">{</span> <span class="nx">users</span><span class="o">:</span> <span class="nx">list</span> <span class="p">});</span>
+ <span class="nx">View</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="s1">'auth:list'</span><span class="p">,</span> <span class="nx">users</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">error</span><span class="p">,</span> <span class="nx">list</span><span class="p">)</span> <span class="p">{</span>
+ <span class="nx">Response</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="s1">'index'</span><span class="p">,</span> <span class="p">{</span> <span class="nx">users</span><span class="o">:</span> <span class="nx">list</span> <span class="p">});</span>
+ <span class="p">});</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="p">}</span>
@@ -479,12 +480,12 @@ <h1 class="header">Katana</h1>
<span class="k">this</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">total_requests</span><span class="o">++</span><span class="p">;</span>
<span class="c1">// by render the view with this.render method, the controller data will pass to this view</span>
- <span class="kd">var</span> <span class="nx">content</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="s1">'index'</span><span class="p">);</span> <span class="c1">// &lt;?-title?&gt;, &lt;?-total_requests?&gt;</span>
+ <span class="k">this</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="s1">'index'</span><span class="p">,</span> <span class="p">...);</span> <span class="c1">// &lt;?-title?&gt;, &lt;?-total_requests?&gt;</span>
<span class="c1">// we may also rewrite globals by set them on render</span>
- <span class="kd">var</span> <span class="nx">content</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="s1">'index'</span><span class="p">,</span> <span class="p">{</span> <span class="nx">title</span><span class="o">:</span> <span class="s1">'This is rewritted title'</span><span class="p">,</span> <span class="nx">foo</span><span class="o">:</span> <span class="s1">'bar'</span> <span class="p">});</span>
-
- <span class="nx">Response</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="nx">content</span><span class="p">);</span>
+ <span class="k">this</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="s1">'index'</span><span class="p">,</span> <span class="p">{</span> <span class="nx">title</span><span class="o">:</span> <span class="s1">'This is rewritted title'</span><span class="p">,</span> <span class="nx">foo</span><span class="o">:</span> <span class="s1">'bar'</span> <span class="p">},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">error</span><span class="p">,</span> <span class="nx">content</span><span class="p">)</span> <span class="p">{</span>
+ <span class="nx">Response</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="nx">content</span><span class="p">);</span>
+ <span class="p">});</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">});</span>
@@ -496,6 +497,56 @@ <h1 class="header">Katana</h1>
<p>Katana application emit specific events for different steps.
Few of them are available for middlewares, the others are for bootstrap control flow.</p>
+<ul>
+<li>
+<code>run</code> - on app initialization, but after bootstrapping</li>
+<li>
+<code>ready</code> - app is ready and started listening requests</li>
+<li>
+<code>connection</code> - emits just after the server get a new http.request.
+the listener will get 3 arguments:
+
+<ul>
+<li>
+<code>request</code> is a <code>http.IncomingMessage</code>
+</li>
+<li>
+<code>response</code> is a <code>http.ServerResponse</code>
+</li>
+<li>
+<code>next</code> callback so app flow will continue. If is not called then we must send response manually, also no other listeners or controller methods will be runned.</li>
+</ul>
+</li>
+<li>
+<code>request</code> - emits after request route is resolve and request data is prepared
+
+<ul>
+<li>
+<code>request</code> is a <code>Katana.Core.Request</code>
+</li>
+<li>
+<code>response</code> is a <code>Katana.Core.Response</code>
+</li>
+<li>
+<code>next</code> callback
+<code>request</code> and <code>response</code> in and after this event are the same as controller methods gets as arguments.</li>
+</ul>
+</li>
+</ul><p>This events could be used to write some middlewares, same as in Express framework.</p>
+
+<div class="highlight"><pre><span class="c1">// in express</span>
+<span class="nx">App</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">next</span><span class="p">){</span>
+ <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">method</span><span class="p">,</span> <span class="nx">req</span><span class="p">.</span><span class="nx">url</span><span class="p">);</span>
+ <span class="nx">next</span><span class="p">();</span>
+<span class="p">});</span>
+
+<span class="c1">// in katana</span>
+<span class="nx">App</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'request'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span>
+ <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">method</span><span class="p">,</span> <span class="nx">req</span><span class="p">.</span><span class="nx">uri</span><span class="p">);</span>
+ <span class="nx">next</span><span class="p">();</span>
+<span class="p">})</span>
+</pre></div>
+
<p>For example, <code>auth</code> module can listen <code>request</code> event to assign a user model for request (see Modules).</p>
<p>Or a <code>chat</code> module which need application server to create a socket.io server.</p>
@@ -503,15 +554,15 @@ <h1 class="header">Katana</h1>
<div class="highlight"><pre><span class="kd">var</span> <span class="nx">socket_io</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'socket.io'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">io</span><span class="p">;</span>
-<span class="c1">// ready event is emitted when Http.Server start listening</span>
+<span class="c1">// waiting app ready</span>
<span class="nx">App</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'ready'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
- <span class="nx">io</span> <span class="o">=</span> <span class="nx">socket_io</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="nx">App</span><span class="p">.</span><span class="nx">server</span><span class="p">);</span>
+ <span class="nx">io</span> <span class="o">=</span> <span class="nx">socket_io</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="nx">App</span><span class="p">.</span><span class="nx">server</span><span class="p">);</span>
- <span class="nx">io</span><span class="p">.</span><span class="nx">sockets</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'connection'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">socket</span><span class="p">)</span> <span class="p">{</span>
- <span class="c1">// …</span>
- <span class="p">});</span>
+ <span class="nx">io</span><span class="p">.</span><span class="nx">sockets</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'connection'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">socket</span><span class="p">)</span> <span class="p">{</span>
+ <span class="c1">// …</span>
+ <span class="p">});</span>
- <span class="nx">callback</span><span class="p">();</span>
+ <span class="nx">callback</span><span class="p">();</span>
<span class="p">});</span>
</pre></div>
@@ -592,6 +643,8 @@ <h1 class="header">Katana</h1>
<ul>
<li>
+<a href="https://github.com/Shogun147/TodoMVC">TodoMVC</a> - AngularJS MVC app with RESTful API on backend</li>
+<li>
<a href="https://github.com/Shogun147/Katana-ToDo">ToDo</a> - Simple todo application</li>
</ul><h2>
<a name="contributing" class="anchor" href="#contributing"><span class="octicon octicon-link"></span></a>Contributing</h2>
@@ -603,14 +656,27 @@ <h1 class="header">Katana</h1>
<p>The MIT License</p>
-<p>Copyright © 2012 D.G. Shogun <a href="mailto:Shogun147@gmail.com">Shogun147@gmail.com</a></p>
- </section>
- <footer>
- <p><small>Hosted on <a href="https://pages.github.com">GitHub Pages</a> using the Dinky theme</small></p>
- </footer>
+<p>Copyright © 2013 D.G. Shogun <a href="mailto:Shogun147@gmail.com">Shogun147@gmail.com</a></p>
+ </section>
+
+ <aside id="sidebar">
+ <a href="https://github.com/Shogun147/Katana/zipball/master" class="button">
+ <small>Download</small>
+ .zip file
+ </a>
+ <a href="https://github.com/Shogun147/Katana/tarball/master" class="button">
+ <small>Download</small>
+ .tar.gz file
+ </a>
+
+ <p class="repo-owner"><a href="https://github.com/Shogun147/Katana"></a> is maintained by <a href="https://github.com/Shogun147">Shogun147</a>.</p>
+
+ <p>This page was generated by <a href="pages.github.com">GitHub Pages</a> using the Architect theme by <a href="https://twitter.com/jasonlong">Jason Long</a>.</p>
+ </aside>
+ </div>
</div>
- <!--[if !IE]><script>fixScale(document);</script><![endif]-->
- <script type="text/javascript">
+
+ <script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
View
2  params.json
@@ -1 +1 @@
-{"name":"Katana","tagline":"Easy to use, modular web framework for any Node.js samurai","body":"# [Katana](https://github.com/Shogun147/Katana) \r\n\r\nEasy to use, modular web framework for any Node.js samurai, focuses on simplicity, maintainability and performance.\r\n\r\n## Contents\r\n\r\n* [Features](#features)\r\n* [Installation](#installation)\r\n* [Quick start](#quick-start)\r\n* [Routing](#routing)\r\n* [Modules](#modules)\r\n* [Controllers](#controllers)\r\n * [Hooks](#hooks)\r\n* [Models](#models)\r\n* [Views](#views)\r\n* [Events](#events)\r\n* [Sessions](#sessions)\r\n* [Logging](#logging)\r\n* [Examples](#examples)\r\n* [Contributing](#contributing)\r\n* [License](#license)\r\n\r\n## Features\r\n\r\n* Powerful, flexible classical router\r\n* Scalable through HMVC architecture \r\n* Environment based configuration\r\n* Application quick generators\r\n* Cookies and Session support\r\n* Templating, partials support\r\n* Fully non-blocking\r\n* …\r\n\r\n## Installation\r\n\r\nFastest way to get Katana is to install it with NPM:\r\n\r\n```bash\r\n$ npm install -g katana\r\n```\r\n\r\n## Quick start\r\n\r\nThe quickest way to start is to utilize the Katana executable to generate an application:\r\n\r\n```bash\r\n$ katana create app\r\n$ cd app\r\n$ npm install\r\n```\r\n\r\nThe app path is optional and is relative to current path.\r\n\r\nThen you are ready to start the server:\r\n\r\n```bash\r\n$ node app\r\n```\r\n\r\n### Basic application layout after creation will look like this:\r\n .\r\n ├── app.js\r\n ├── application\r\n │   ├── config\r\n │   │   ├── development\r\n │   │   │   ├── application.js\r\n │   │   │   ├── routing.js\r\n │   │   │   └── stores.js\r\n │   │   └── production\r\n │   ├── controllers\r\n │   │   └── home.js\r\n │   ├── models\r\n │   └── views\r\n │   └── index.html\r\n ├── modules\r\n ├── public\r\n │   ├── images\r\n │   ├── scripts\r\n │   └── css\r\n └── temp\r\n\r\n## Routing\r\n\r\nClassical routing is one the most powerful futures of Katana framework. It uses uri segments to determine the controller and action for a requested URI.<br>\r\nSo unlike in other Node.js framework you may just add controllers and actions without the need to create routing rules, but also let you write your own rules which may change the path.<br>\r\nWithout any rules, uri path will be treated as: http://katana:8000/`controller`/`action`/`arg1`/../`argN`\r\n\r\nSo if uri path is: `http://katana:8000/account/login`<br>\r\nThen `controller=account` and `action=login`.\r\n\r\nIf there no uri segments then default path will be used, `home` as controller and `index` as action.\r\n\r\nYou can also rewrite path by set the routing rule, for example to view user profile:\r\n\r\n```javascript\r\nroutes: {\r\n // each request method may have it's own routes\r\n get: [\r\n ['user/:user_id', 'users/profile']\r\n ]\r\n\r\n // also you can set routes for all methods\r\n all: [\r\n // if routes will not match for requested method then will try this routes\r\n ]\r\n}\r\n```\r\n\r\nor you may set request method as route prefix:\r\n\r\n\r\n```javascript\r\nroutes: [\r\n ['get user/:user_id', 'users/profile'], // will route this for get method\r\n ['* user/:user_id', 'users/profile'] // all methods\r\n ['user/:user_id', 'users/profile'] // if not set then will check all methods\r\n]\r\n```\r\n\r\n\r\nThis will set `controller=users` and `action=profile` and user_id will be available as `Request.params.user_id`.\r\n\r\nOr you may pass this request to mvc module:\r\n\r\n```javascript\r\nroutes: {\r\n get: [\r\n ['user/:user_id', '#auth/users/profile']\r\n ]\r\n}\r\n```\r\n\r\nThe `#` symbol meen that this request will pass to `auth` module, `controller=users` and `action=profile`.\r\n\r\nYou could also set format for user_id like so:\r\n\r\n```javascript\r\nroutes: {\r\n get: [\r\n ['user/:user_id([0-9]+)', '#auth/users/profile']\r\n ]\r\n}\r\n```\r\n\r\n`!important:` mvc modules may have their own routing rules.\r\n\r\nWe may also have controllers in subdirectories. Just set the directory path in square brackets.<br>\r\nFor example there is an `users` controller in `controllers/api` directory. The routing will look like:\r\n```javascript\r\nroutes: [\r\n ['api/users/*', '[api]/users/:1'] // the slash after closing ] is optional\r\n]\r\n```\r\n\r\nRESTful routes:\r\n```javascript\r\n routes: [\r\n ['get api/:resource', '[api]:resource/index'],\r\n ['get api/:resource/new', '[api]:resource/new'],\r\n ['post api/:resource', '[api]:resource/create'],\r\n ['get api/:resource/:id', '[api]:resource/show'],\r\n ['get api/:resource/:id/edit', '[api]:resource/edit'],\r\n ['put api/:resource/:id', '[api]:resource/update'],\r\n ['delete api/:resource/:id', '[api]:resource/remove']\r\n ]\r\n```\r\nThis means in `api` directory you could have a controller for each resource with methods `index`, `new`, `create`, `show`, `edit`, `update` and `remove`.<br>\r\nIf you use such HTTP methods as `put` or `delete` you must have some middleware which will rewrite the method. You could install [methodOverride](https://github.com/Shogun147/Katana-methodOverride) module with `katana module install methodOverride` command in your app root. Don't forget to enable it with `katana module enable methodOverride`.<br>\r\nOn the client side, set desired method in hidden field with `_method` name:\r\n```html\r\n<form action=\"/api\" method=\"post\">\r\n <input type=\"hidden\" name=\"_method\" value=\"put\">\r\n</form>\r\n```\r\nField name could be changed in the main module file.\r\n\r\nMore examples:\r\n \r\n```javascript\r\n['news/:category/rss.:format(xml|json)?', 'news/rss'] will allow:\r\n news/any_category/rss\r\n news/any_category/rss.xml\r\n news/any_category/rss.json\r\n\r\n and News controller:\r\n\r\n methods: {\r\n rss: function(Response, Request) {\r\n // Now we can use Request.params.category and Request.params.format\r\n var format = Request.params.format || 'xml'; // default xml\r\n\r\n ...\r\n }\r\n }\r\n```\r\n\r\n\r\n## Modules\r\n\r\nIn Katana modules can be used as mvc part or your application or as middleware.\r\n\r\nFor mvc modules you can use routing the same way as for main mvc.<br>\r\nAlso you can run them as widgets by calling run method: \r\n\r\n```javascript\r\nModule('auth').run('users/list');\r\n```\r\n\r\nThis will run `list` action of `users` controller from `auth` module.\r\n\r\nMiddleware modules can listen specific application events and interact as they need.\r\n\r\nFor example auth module can look like this:\r\n\r\n```javascript\r\nvar User = App.Model('auth:user'); // get user model of auth module\r\n\r\n// listen new request event\r\nApp.on('request', function(Request, Response, callback) {\r\n Request.user = new User(Request.session);\r\n\r\n callback(); // callback when we're done here, required for application to continue\r\n});\r\n```\r\n\r\nand then in our controller we can access user object as `Request.user`.\r\n\r\n### Sharing modules\r\n\r\n[Katana](https://github.com/Shogun147/Katana) comes with an basic modules sharing system which allow to download public modules and install them for application.\r\n\r\nKatana binary has few new commands for interacting with modules:\r\n\r\n* `katana modules` - list all available modules.\r\n* `katana module search <str>` - search modules that contain `str` in name or description.\r\n* `katana module update` - update modules list and their info.\r\n* `katana module install <name> [url]` - install or reinstall app module.\r\n * `name` or `name@version` - module name\r\n * `url` or `username:repository` or `username:repository@version` - optional url or github username:repository combination.\r\n\r\n If only `name` is provided then download url will be builded from module data contained in modules registry file. The name could also be followed by an version tag.<br>\r\n If second argument is an url then module will be downloaded from that url.<br>\r\n If second argument is an combination of `username:repository@version` then the url will be: `https://github.com/:username/:repository/tarball/:version`.<br>\r\n If no `version` provided then requested one will be last available version for module in registry. If no valid version will be detected then `master` brunch will be requested.<br>\r\n For custom download url modules still must be gzipped tarballs.<br>\r\n Examples of install:\r\n * `katana module install auth`\r\n * `katana module install auth@0.1.0`\r\n * `katana module install Shogun147:Katana-auth`\r\n * `katana module install Shogun147:Katana-auth@0.1.0`\r\n * `katana module install https://github.com/Shogun147/Katana-auth/tarball/master`\r\n * `katana module install http://my-site.com/downloads/module/v1.0.5`\r\n\r\n* `katana module uninstall <name>` - uninstall and remove module\r\n* `katana module enable <name>` - enable module\r\n* `katana module disable <name>` - disable module\r\n\r\nFor each of this actions [`install`, `uninstall`, `enable`, `disable`] modules could have their hooks which would be called. The hooks are stored in hooks directory of module.<br>\r\nThe hooks are useful when there is a need to do something unique on this actions. For ex the `install` hook (modules/:name/hooks/install.js) could create new tables in the database or copy modules assets to public directory…\r\n\r\nThe module registry is downloaded from `https://raw.github.com/Shogun147/Katana/master/modules.json`. To add new modules to the list just fork this file and send an pull request. This will make your module listed on `katana modules` command and on search.\r\n\r\n## Controllers\r\n\r\nControllers are almost most important part of any application, they handle incoming requests and send responses.\r\n\r\nA simple controller looks like this:\r\n\r\n```javascript\r\n// define our controller Class\r\nClass('Home_Controller', {\r\n isa: App.Controller, // extend Katana Core Controller\r\n\r\n methods: {\r\n index: function(Response, Request) {\r\n Response.send('Hello World!');\r\n }\r\n }\r\n});\r\n\r\nmodule.exports = new Home_Controller;\r\n```\r\n\r\nAnd now we can access this `index` action by opening http://katana:8000/, without any uri path this will use default controller and action from config which are `home` and `index`. Also we can access them directly by opening http://katana:8000/`home`/ with `index` as default action or http://katana:8000/`home`/`index`.\r\n\r\n### Hooks\r\n\r\nDue the power of Joose [Method Modifiers](http://joose.github.com/Joose/doc/html/Joose/Manual/MethodModifiers.html) (`before`, `after`, `override` and `around`) we may change the way class methods are called, actions that may happen before or after method call or even modify results that they could return.\r\n\r\nFor example let's restrict index method only for logged in users:\r\n\r\n```javascript\r\nClass('Home_Controller', {\r\n isa: App.Controller,\r\n\r\n methods: {\r\n index: function(Response, Request) {\r\n Response.send('Hello World!');\r\n }\r\n },\r\n\r\n around: {\r\n // the same name for the method we want to wrap\r\n index: function(method, Response, Request) {\r\n var User = Request.user;\r\n\r\n // if the user is not logged in then redirect to login page\r\n if (!User.logged_in()) {\r\n return Request.redirect('/login');\r\n }\r\n\r\n // else we call original method\r\n method(Response, Request);\r\n }\r\n }\r\n});\r\n```\r\n\r\nThe `call` modifier allow as to use regular expressions and apply that hook to all methods that matches the condition.\r\n\r\nFor example let's restrict access for all methods:\r\n\r\n```javascript\r\nClass('Home_Controller', {\r\n isa: App.Controller,\r\n\r\n methods: {\r\n index: function(Response, Request) {\r\n Response.send('Hello World!');\r\n }\r\n },\r\n\r\n call: {\r\n // use regexp instead of methods name\r\n // this will apply to all controller methods calls\r\n '.*': function(method, Response, Request) {\r\n var User = Request.user;\r\n\r\n // if the user is not logged in then redirect to login page\r\n if (!User.logged_in()) {\r\n return Request.redirect('/login');\r\n }\r\n\r\n // else we call original method\r\n method(Response, Request);\r\n }\r\n }\r\n});\r\n```\r\n\r\n\r\n## Models\r\n\r\nKatana did not limit the developer to define a model in some way or to use a specific module. It just autoload all from the models directory of application or a module and store them in a local registry.\r\n\r\nYou can access them like this:<br>\r\n\r\n```javascript\r\nvar News = App.Model('news'); // get model object\r\n```\r\n\r\nTo get a model from module you need to separate module name and model path with colon `:`, for example to get `user` model of `auth` module call: `App.Model('auth:user')`.\r\n\r\nModel file can look like this:\r\n\r\n```javascript\r\nvar Mongoose = App.Store('mongoose'); // get mongoose connection, look at stores config file\r\nvar Schema = require('mongoose').Schema;\r\n\r\nvar User = new Schema({\r\n username: String,\r\n password: String,\r\n email: String,\r\n signed_at: Date,\r\n roles: ['user', 'moderator', 'administrator']\r\n});\r\n\r\nmodule.exports = Mongoose.model('User', User);\r\n```\r\n\r\n## Views\r\n\r\nTo render a view you can use a few methods:\r\n\r\n```javascript\r\nvar View = App.View;\r\n\r\nClass('Home_Controller', {\r\n isa: App.Controller,\r\n\r\n methods: {\r\n index: function(Response, Request) {\r\n // directly render and send a view content\r\n Response.render('index', { title: 'Hello World' }); // this will render index.html file from views\r\n\r\n // get rendered content\r\n var content = View.render('index', { title: 'Hello World' });\r\n // and latter send response\r\n Response.send(content);\r\n\r\n // render a view from module\r\n Users.find({}, function(error, users) {\r\n if (error) { return Response.send('Error! Blablabla'); }\r\n\r\n // again module name separated by colon, and then path to the view\r\n var list = View.render('auth:list', users);\r\n\r\n Response.render('index', { users: list });\r\n });\r\n }\r\n }\r\n});\r\n```\r\n\r\nControllers can also have their global data, which will be passed for the this.render calls:\r\n \r\n```javascript\r\nClass('Home_Controller', {\r\n isa: App.Controller,\r\n\r\n have: {\r\n // set global controller data\r\n data: {\r\n title: 'This is title for all pages for this controller',\r\n total_requests: 0\r\n }\r\n },\r\n\r\n methods: {\r\n index: function(Response) {\r\n // you can also set global controller data from actions\r\n this.set('copyright', 'blablabla');\r\n // or\r\n this.data.total_requests++;\r\n \r\n // by render the view with this.render method, the controller data will pass to this view\r\n var content = this.render('index'); // <?-title?>, <?-total_requests?>\r\n \r\n // we may also rewrite globals by set them on render\r\n var content = this.render('index', { title: 'This is rewritted title', foo: 'bar' });\r\n \r\n Response.send(content);\r\n }\r\n }\r\n});\r\n```\r\n\r\n## Events\r\n\r\nKatana application emit specific events for different steps.\r\nFew of them are available for middlewares, the others are for bootstrap control flow.\r\n\r\nFor example, `auth` module can listen `request` event to assign a user model for request (see Modules).\r\n\r\nOr a `chat` module which need application server to create a socket.io server.\r\n\r\n```javascript\r\nvar socket_io = require('socket.io');\r\nvar io;\r\n\r\n// ready event is emitted when Http.Server start listening\r\nApp.on('ready', function(callback) {\r\n io = socket_io.listen(App.server);\r\n \r\n io.sockets.on('connection', function (socket) {\r\n // …\r\n });\r\n \r\n callback();\r\n});\r\n```\r\n\r\n## Sessions\r\n\r\nKatana has build in module for supporting sessions.\r\nThis gives you a way to associate data with each particular visitor of your app and have that data persist between requests.\r\n\r\n### Data stores\r\nFor now Katana support only 2 session data stores (more to come):\r\n\r\n* **Memory** (by default): useful for development. Session data is saved in memory at worker-process level, which means this will not work with cluster. Also, all sessions disappear when app is restarted.\r\n\r\n* **Redis**: Sessions are saved in a redis noSQL database and persist across app restarts. Requires a Redis server or clusters.\r\n\r\n### Using sessions\r\n\r\nFirst of all you need to enable sessions in application config file.\r\nThe default session config look like this:\r\n\r\n```javascript\r\nsession: {\r\n // enable or disable session support\r\n enabled: true,\r\n\r\n // session identifier name for cookie of\r\n key_name: 'session_id',\r\n\r\n // session id length\r\n key_length: 32,\r\n\r\n // lifetime before delete inactive session\r\n lifetime: 1000 * 60 * 60 * 24 * 7,\r\n\r\n // session store, one from config/stores.js\r\n store: 'redis',\r\n \r\n // default data for new sessions\r\n defaults: {\r\n \r\n }\r\n}\r\n```\r\n\r\nOnce you enable sessions, the session object will be assigned to each request and data will be loaded automatically from the session store.\r\nThen this object could be accessed as `Request.session`.\r\nFor now available public methods are `set`, `get` and `remove`.\r\n\r\nExample counter of user requests:\r\n\r\n```javascript\r\nindex: function(Response, Request) {\r\n var Session = Request.session;\r\n\r\n // get current requests count, default 0\r\n var counter = Session.get('requests', 0);\r\n\r\n counter++;\r\n\r\n // set new value\r\n Session.set('requests', counter);\r\n\r\n // Session data will be automatically saved in store before sending response\r\n // Also will save session id in the cookie with key_name from config\r\n Response.send('You have visited this page '+ counter +' times');\r\n}\r\n```\r\n\r\n## Logging\r\n\r\nKatana uses [winston](https://github.com/flatiron/winston) module to log.\r\nAvailable as `App.Log` you could add more transports or options to it. Check official docs for this.\r\n\r\n## Examples\r\n\r\n* [ToDo](https://github.com/Shogun147/Katana-ToDo) - Simple todo application\r\n\r\n## Contributing\r\nAnyone interested or who like the framework idea can contribute by sending new ideas, issues or pull requests. Any help would be appreciated.\r\n\r\n## License\r\nThe MIT License\r\n\r\nCopyright © 2012 D.G. Shogun <Shogun147@gmail.com>\r\n","google":"Katana nodejs node.js framework router modules mvc hmvc controllers async","note":"Don't delete this file! It's used internally to help with page regeneration."}
+{"name":"Katana","tagline":"Easy to use, modular web framework for any Node.js samurai","body":"<a href=\"https://github.com/Shogun147/Katana\"><img src=\"https://raw.github.com/Shogun147/Katana/master/katana.jpg\"/></a>\r\n\r\nEasy to use, modular web framework for any Node.js samurai, focuses on simplicity, maintainability and performance.\r\n\r\n## Contents\r\n\r\n* [Features](#features)\r\n* [Installation](#installation)\r\n* [Quick start](#quick-start)\r\n* [Routing](#routing)\r\n* [Modules](#modules)\r\n* [Controllers](#controllers)\r\n * [Hooks](#hooks)\r\n* [Models](#models)\r\n* [Views](#views)\r\n* [Events](#events)\r\n* [Sessions](#sessions)\r\n* [Logging](#logging)\r\n* [Examples](#examples)\r\n* [Contributing](#contributing)\r\n* [License](#license)\r\n\r\n## Features\r\n\r\n* Powerful, flexible classical router\r\n* Scalable through HMVC architecture \r\n* Environment based configuration\r\n* Application quick generators\r\n* Cookies and Session support\r\n* Templating, partials support\r\n* Fully non-blocking\r\n* …\r\n\r\n## Installation\r\n\r\nFastest way to get Katana is to install it with NPM:\r\n\r\n```bash\r\n$ npm install -g katana\r\n```\r\n\r\n## Quick start\r\n\r\nThe quickest way to start is to utilize the Katana executable to generate an application:\r\n\r\n```bash\r\n$ katana create app\r\n$ cd app\r\n$ npm install\r\n```\r\n\r\nThe app path is optional and is relative to current path.\r\n\r\nThen you are ready to start the server:\r\n\r\n```bash\r\n$ node app\r\n```\r\n\r\n### Basic application layout after creation will look like this:\r\n .\r\n ├── app.js\r\n ├── application\r\n │   ├── config\r\n │   │   ├── development\r\n │   │   │   ├── application.js\r\n │   │   │   ├── routing.js\r\n │   │   │   └── stores.js\r\n │   │   └── production\r\n │   ├── controllers\r\n │   │   └── home.js\r\n │   ├── models\r\n │   └── views\r\n │   └── index.html\r\n ├── modules\r\n ├── public\r\n │   ├── images\r\n │   ├── scripts\r\n │   └── css\r\n └── temp\r\n\r\n## Routing\r\n\r\nClassical routing is one the most powerful futures of Katana framework. It uses uri segments to determine the controller and action for a requested URI.<br>\r\nSo unlike in other Node.js framework you may just add controllers and actions without the need to create routing rules, but also let you write your own rules which may change the path.<br>\r\nWithout any rules, uri path will be treated as: http://katana:8000/`controller`/`action`/`arg1`/../`argN`\r\n\r\nSo if uri path is: `http://katana:8000/account/login`<br>\r\nThen `controller=account` and `action=login`.\r\n\r\nIf there no uri segments then default path will be used, `home` as controller and `index` as action.\r\n\r\nYou can also rewrite path by set the routing rule, for example to view user profile:\r\n\r\n```javascript\r\nroutes: {\r\n // each request method may have it's own routes\r\n get: [\r\n ['user/:user_id', 'users/profile']\r\n ]\r\n\r\n // also you can set routes for all methods\r\n all: [\r\n // if routes will not match for requested method then will try this routes\r\n ]\r\n}\r\n```\r\n\r\nor you may set request method as route prefix:\r\n\r\n\r\n```javascript\r\nroutes: [\r\n ['get user/:user_id', 'users/profile'], // will route this for get method\r\n ['* user/:user_id', 'users/profile'] // all methods\r\n ['user/:user_id', 'users/profile'] // if not set then will check all methods\r\n]\r\n```\r\n\r\n\r\nThis will set `controller=users` and `action=profile` and user_id will be available as `Request.params.user_id`.\r\n\r\nOr you may pass this request to mvc module:\r\n\r\n```javascript\r\nroutes: {\r\n get: [\r\n ['user/:user_id', '#auth/users/profile']\r\n ]\r\n}\r\n```\r\n\r\nThe `#` symbol meen that this request will pass to `auth` module, `controller=users` and `action=profile`.\r\n\r\nYou could also set format for user_id like so:\r\n\r\n```javascript\r\nroutes: {\r\n get: [\r\n ['user/:user_id([0-9]+)', '#auth/users/profile']\r\n ]\r\n}\r\n```\r\n\r\n`!important:` mvc modules may have their own routing rules.\r\n\r\nWe may also have controllers in subdirectories. Just set the directory path in square brackets.<br>\r\nFor example there is an `users` controller in `controllers/api` directory. The routing will look like:\r\n```javascript\r\nroutes: [\r\n ['api/users/*', '[api]/users/:1'] // the slash after closing ] is optional\r\n]\r\n```\r\n\r\nRESTful routes:\r\n```javascript\r\n routes: [\r\n ['get api/:resource', '[api]:resource/index'],\r\n ['get api/:resource/new', '[api]:resource/new'],\r\n ['post api/:resource', '[api]:resource/create'],\r\n ['get api/:resource/:id', '[api]:resource/show'],\r\n ['get api/:resource/:id/edit', '[api]:resource/edit'],\r\n ['put api/:resource/:id', '[api]:resource/update'],\r\n ['delete api/:resource/:id', '[api]:resource/remove']\r\n ]\r\n```\r\nThis means in `api` directory you could have a controller for each resource with methods `index`, `new`, `create`, `show`, `edit`, `update` and `remove`.<br>\r\nIf you use such HTTP methods as `put` or `delete` you must have some middleware which will rewrite the method. You could install [methodOverride](https://github.com/Shogun147/Katana-methodOverride) module with `katana module install methodOverride` command in your app root. Don't forget to enable it with `katana module enable methodOverride`.<br>\r\nOn the client side, set desired method in hidden field with `_method` name:\r\n```html\r\n<form action=\"/api\" method=\"post\">\r\n <input type=\"hidden\" name=\"_method\" value=\"put\">\r\n</form>\r\n```\r\nField name could be changed in the main module file.\r\n\r\nMore examples:\r\n \r\n```javascript\r\n['news/:category/rss.:format(xml|json)?', 'news/rss'] will allow:\r\n news/any_category/rss\r\n news/any_category/rss.xml\r\n news/any_category/rss.json\r\n\r\n and News controller:\r\n\r\n methods: {\r\n rss: function(Response, Request) {\r\n // Now we can use Request.params.category and Request.params.format\r\n var format = Request.params.format || 'xml'; // default xml\r\n\r\n ...\r\n }\r\n }\r\n```\r\n\r\n\r\n## Modules\r\n\r\nIn Katana modules can be used as mvc part or your application or as middleware.\r\n\r\nFor mvc modules you can use routing the same way as for main mvc.<br>\r\nAlso you can run them as widgets by calling run method: \r\n\r\n```javascript\r\nModule('auth').run('users/list');\r\n```\r\n\r\nThis will run `list` action of `users` controller from `auth` module.\r\n\r\nMiddleware modules can listen specific application events and interact as they need.\r\n\r\nFor example auth module can look like this:\r\n\r\n```javascript\r\nvar User = App.Model('auth:user'); // get user model of auth module\r\n\r\n// listen new request event\r\nApp.on('request', function(Request, Response, callback) {\r\n Request.user = new User(Request.session);\r\n\r\n callback(); // callback when we're done here, required for application to continue\r\n});\r\n```\r\n\r\nand then in our controller we can access user object as `Request.user`.\r\n\r\n### Sharing modules\r\n\r\n[Katana](https://github.com/Shogun147/Katana) comes with an basic modules sharing system which allow to download public modules and install them for application.\r\n\r\nKatana binary has few new commands for interacting with modules:\r\n\r\n* `katana modules` - list all available modules.\r\n* `katana module search <str>` - search modules that contain `str` in name or description.\r\n* `katana module update` - update modules list and their info.\r\n* `katana module install <name> [url]` - install or reinstall app module.\r\n * `name` or `name@version` - module name\r\n * `url` or `username:repository` or `username:repository@version` - optional url or github username:repository combination.\r\n\r\n If only `name` is provided then download url will be builded from module data contained in modules registry file. The name could also be followed by an version tag.<br>\r\n If second argument is an url then module will be downloaded from that url.<br>\r\n If second argument is an combination of `username:repository@version` then the url will be: `https://github.com/:username/:repository/tarball/:version`.<br>\r\n If no `version` provided then requested one will be last available version for module in registry. If no valid version will be detected then `master` brunch will be requested.<br>\r\n For custom download url modules still must be gzipped tarballs.<br>\r\n Examples of install:\r\n * `katana module install auth`\r\n * `katana module install auth@0.1.0`\r\n * `katana module install auth Shogun147:Katana-auth`\r\n * `katana module install auth Shogun147:Katana-auth@0.1.0`\r\n * `katana module install auth https://github.com/Shogun147/Katana-auth/tarball/master`\r\n * `katana module install auth http://my-site.com/downloads/module/v1.0.5`\r\n\r\n* `katana module uninstall <name>` - uninstall and remove module\r\n* `katana module enable <name>` - enable module\r\n* `katana module disable <name>` - disable module\r\n\r\nFor each of this actions [`install`, `uninstall`, `enable`, `disable`] modules could have their hooks which would be called. The hooks are stored in hooks directory of module.<br>\r\nThe hooks are useful when there is a need to do something unique on this actions. For ex the `install` hook (modules/:name/hooks/install.js) could create new tables in the database or copy modules assets to public directory…\r\n\r\nThe module registry is downloaded from `https://raw.github.com/Shogun147/Katana/master/modules.json`. To add new modules to the list just fork this file and send an pull request. This will make your module listed on `katana modules` command and on search.\r\n\r\n## Controllers\r\n\r\nControllers are almost most important part of any application, they handle incoming requests and send responses.\r\n\r\nA simple controller looks like this:\r\n\r\n```javascript\r\n// define our controller Class\r\nClass('Home_Controller', {\r\n isa: App.Controller, // extend Katana Core Controller\r\n\r\n methods: {\r\n index: function(Response, Request) {\r\n Response.send('Hello World!');\r\n }\r\n }\r\n});\r\n\r\nmodule.exports = new Home_Controller;\r\n\r\n// to not expose this class as a global, create it as anonymous\r\nvar HomeController = Class({ ... }); module.exports = new HomeController;\r\n\r\n```\r\n\r\nAnd now we can access this `index` action by opening http://katana:8000/, without any uri path this will use default controller and action from config which are `home` and `index`. Also we can access them directly by opening http://katana:8000/`home`/ with `index` as default action or http://katana:8000/`home`/`index`.\r\n\r\n### Hooks\r\n\r\nDue the power of Joose [Method Modifiers](http://joose.github.com/Joose/doc/html/Joose/Manual/MethodModifiers.html) (`before`, `after`, `override` and `around`) we may change the way class methods are called, actions that may happen before or after method call or even modify results that they could return.\r\n\r\nFor example let's restrict index method only for logged in users:\r\n\r\n```javascript\r\nClass('Home_Controller', {\r\n isa: App.Controller,\r\n\r\n methods: {\r\n index: function(Response, Request) {\r\n Response.send('Hello World!');\r\n }\r\n },\r\n\r\n around: {\r\n // the same name for the method we want to wrap\r\n index: function(method, Response, Request) {\r\n var User = Request.user;\r\n\r\n // if the user is not logged in then redirect to login page\r\n if (!User.logged_in()) {\r\n return Request.redirect('/login');\r\n }\r\n\r\n // else we call original method\r\n method(Response, Request);\r\n }\r\n }\r\n});\r\n```\r\n\r\nThe `call` modifier allow as to use regular expressions and apply that hook to all methods that matches the condition.\r\n\r\nFor example let's restrict access for all methods:\r\n\r\n```javascript\r\nClass('Home_Controller', {\r\n isa: App.Controller,\r\n\r\n methods: {\r\n index: function(Response, Request) {\r\n Response.send('Hello World!');\r\n }\r\n },\r\n\r\n call: {\r\n // use regexp instead of methods name\r\n // this will apply to all controller methods calls\r\n '.*': function(method, Response, Request) {\r\n var User = Request.user;\r\n\r\n // if the user is not logged in then redirect to login page\r\n if (!User.logged_in()) {\r\n return Request.redirect('/login');\r\n }\r\n\r\n // else we call original method\r\n method(Response, Request);\r\n }\r\n }\r\n});\r\n```\r\n\r\n\r\n## Models\r\n\r\nKatana did not limit the developer to define a model in some way or to use a specific module. It just autoload all from the models directory of application or a module and store them in a local registry.\r\n\r\nYou can access them like this:<br>\r\n\r\n```javascript\r\nvar News = App.Model('news'); // get model object\r\n```\r\n\r\nTo get a model from module you need to separate module name and model path with colon `:`, for example to get `user` model of `auth` module call: `App.Model('auth:user')`.\r\n\r\nModel file can look like this:\r\n\r\n```javascript\r\nvar Mongoose = App.Store('mongoose'); // get mongoose connection, look at stores config file\r\nvar Schema = require('mongoose').Schema;\r\n\r\nvar User = new Schema({\r\n username: String,\r\n password: String,\r\n email: String,\r\n signed_at: Date,\r\n roles: ['user', 'moderator', 'administrator']\r\n});\r\n\r\nmodule.exports = Mongoose.model('User', User);\r\n```\r\n\r\n## Views\r\n\r\nTo render a view you can use a few methods:\r\n\r\n```javascript\r\nvar View = App.View;\r\n\r\nClass('Home_Controller', {\r\n isa: App.Controller,\r\n\r\n methods: {\r\n index: function(Response, Request) {\r\n // directly render and send a view content\r\n Response.render('index', { title: 'Hello World' }); // this will render index.html file from views\r\n\r\n // get rendered content\r\n View.render('index', { title: 'Hello World' }, function(error, content) {\r\n // and latter send response\r\n Response.send(content);\r\n });\r\n\r\n // render a view from module\r\n Users.find({}, function(error, users) {\r\n if (error) { return Response.send('Error! Blablabla'); }\r\n\r\n // again module name separated by colon, and then path to the view\r\n View.render('auth:list', users, function(error, list) {\r\n Response.render('index', { users: list });\r\n });\r\n });\r\n }\r\n }\r\n});\r\n```\r\n\r\nControllers can also have their global data, which will be passed for the this.render calls:\r\n \r\n```javascript\r\nClass('Home_Controller', {\r\n isa: App.Controller,\r\n\r\n have: {\r\n // set global controller data\r\n data: {\r\n title: 'This is title for all pages for this controller',\r\n total_requests: 0\r\n }\r\n },\r\n\r\n methods: {\r\n index: function(Response) {\r\n // you can also set global controller data from actions\r\n this.set('copyright', 'blablabla');\r\n // or\r\n this.data.total_requests++;\r\n \r\n // by render the view with this.render method, the controller data will pass to this view\r\n this.render('index', ...); // <?-title?>, <?-total_requests?>\r\n \r\n // we may also rewrite globals by set them on render\r\n this.render('index', { title: 'This is rewritted title', foo: 'bar' }, function(error, content) {\r\n Response.send(content);\r\n });\r\n }\r\n }\r\n});\r\n```\r\n\r\n## Events\r\n\r\nKatana application emit specific events for different steps.\r\nFew of them are available for middlewares, the others are for bootstrap control flow.\r\n\r\n* `run` - on app initialization, but after bootstrapping\r\n* `ready` - app is ready and started listening requests\r\n* `connection` - emits just after the server get a new http.request.\r\n the listener will get 3 arguments:\r\n - `request` is a `http.IncomingMessage`\r\n - `response` is a `http.ServerResponse`\r\n - `next` callback so app flow will continue. If is not called then we must send response manually, also no other listeners or controller methods will be runned.\r\n* `request` - emits after request route is resolve and request data is prepared\r\n - `request` is a `Katana.Core.Request`\r\n - `response` is a `Katana.Core.Response`\r\n - `next` callback\r\n `request` and `response` in and after this event are the same as controller methods gets as arguments.\r\n\r\nThis events could be used to write some middlewares, same as in Express framework.\r\n```javascript\r\n// in express\r\nApp.use(function(req, res, next){\r\n console.log(req.method, req.url);\r\n next();\r\n});\r\n\r\n// in katana\r\nApp.on('request', function(req, res, next) {\r\n console.log(req.method, req.uri);\r\n next();\r\n})\r\n```\r\n\r\nFor example, `auth` module can listen `request` event to assign a user model for request (see Modules).\r\n\r\nOr a `chat` module which need application server to create a socket.io server.\r\n\r\n```javascript\r\nvar socket_io = require('socket.io');\r\nvar io;\r\n\r\n// waiting app ready\r\nApp.on('ready', function(callback) {\r\n io = socket_io.listen(App.server);\r\n \r\n io.sockets.on('connection', function (socket) {\r\n // …\r\n });\r\n \r\n callback();\r\n});\r\n```\r\n\r\n## Sessions\r\n\r\nKatana has build in module for supporting sessions.\r\nThis gives you a way to associate data with each particular visitor of your app and have that data persist between requests.\r\n\r\n### Data stores\r\nFor now Katana support only 2 session data stores (more to come):\r\n\r\n* **Memory** (by default): useful for development. Session data is saved in memory at worker-process level, which means this will not work with cluster. Also, all sessions disappear when app is restarted.\r\n\r\n* **Redis**: Sessions are saved in a redis noSQL database and persist across app restarts. Requires a Redis server or clusters.\r\n\r\n### Using sessions\r\n\r\nFirst of all you need to enable sessions in application config file.\r\nThe default session config look like this:\r\n\r\n```javascript\r\nsession: {\r\n // enable or disable session support\r\n enabled: true,\r\n\r\n // session identifier name for cookie of\r\n key_name: 'session_id',\r\n\r\n // session id length\r\n key_length: 32,\r\n\r\n // lifetime before delete inactive session\r\n lifetime: 1000 * 60 * 60 * 24 * 7,\r\n\r\n // session store, one from config/stores.js\r\n store: 'redis',\r\n \r\n // default data for new sessions\r\n defaults: {\r\n \r\n }\r\n}\r\n```\r\n\r\nOnce you enable sessions, the session object will be assigned to each request and data will be loaded automatically from the session store.\r\nThen this object could be accessed as `Request.session`.\r\nFor now available public methods are `set`, `get` and `remove`.\r\n\r\nExample counter of user requests:\r\n\r\n```javascript\r\nindex: function(Response, Request) {\r\n var Session = Request.session;\r\n\r\n // get current requests count, default 0\r\n var counter = Session.get('requests', 0);\r\n\r\n counter++;\r\n\r\n // set new value\r\n Session.set('requests', counter);\r\n\r\n // Session data will be automatically saved in store before sending response\r\n // Also will save session id in the cookie with key_name from config\r\n Response.send('You have visited this page '+ counter +' times');\r\n}\r\n```\r\n\r\n## Logging\r\n\r\nKatana uses [winston](https://github.com/flatiron/winston) module to log.\r\nAvailable as `App.Log` you could add more transports or options to it. Check official docs for this.\r\n\r\n## Examples\r\n\r\n* [TodoMVC](https://github.com/Shogun147/TodoMVC) - AngularJS MVC app with RESTful API on backend\r\n* [ToDo](https://github.com/Shogun147/Katana-ToDo) - Simple todo application\r\n\r\n## Contributing\r\nAnyone interested or who like the framework idea can contribute by sending new ideas, issues or pull requests. Any help would be appreciated.\r\n\r\n## License\r\nThe MIT License\r\n\r\nCopyright © 2013 D.G. Shogun <Shogun147@gmail.com>\r\n","google":"Katana nodejs node.js framework router modules mvc hmvc controllers async","note":"Don't delete this file! It's used internally to help with page regeneration."}

0 comments on commit 9dd1731

Please sign in to comment.
Something went wrong with that request. Please try again.