{"_id":"tower","_rev":"132-349a03533f603e37123105d543ebd83a","name":"tower","description":"Small components for building apps, manipulating data, and managing a distributed infrastructure.","dist-tags":{"latest":"0.5.11"},"versions":{"0.3.0":{"name":"tower","version":"0.3.0","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower.js","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower.js/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.js.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.1.6","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","shift":">= 0.1.5","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7"},"devDependencies":{"coffee-script":">= 1.1.3","stylus":">= 0.17.0","jade":">= 0.16.2","coffeekup":">= 0.3.1","mustache":">= 0.3.1-dev","markdown":">= 0.2.1","uglify-js":">= 1.1.1","design.io":">= 0.1.0"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.3.0","_engineSupported":true,"_npmVersion":"1.0.105","_nodeVersion":"v0.6.1","_defaultsLoaded":true,"dist":{"shasum":"469d1838f7744b14f1a71f684f25a7a0c68bff7a","tarball":"https://registry.npmjs.org/tower/-/tower-0.3.0.tgz","integrity":"sha512-lFuA0CMyYSGTrvBTZHQpjWMk74CF+TrIJ8+vFDOjvzEDrx/XQbVchYXGicvPrn2CNbulSg+Va1JDlg7H2E5jEw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA6rprGOTjk72bs1GqqLj/b8tCnCUxTdq4BChF8mD+iwAiB5QuxQAiAHq5RY9MMydBK/7VEy28TzJoYhQCNvbS4RCA=="}]}},"0.3.1":{"name":"tower","version":"0.3.1","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower.js","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower.js/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.js.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","shift":">= 0.1.5","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","ejs":">= 0.6.1","restler":">= 0.0.1","useragent":">= 1.0.5","stylus":">= 0.17.0"},"devDependencies":{"coffee-script":">= 1.1.3","stylus":">= 0.17.0","jade":">= 0.16.2","coffeekup":">= 0.3.1","mustache":">= 0.3.1-dev","markdown":">= 0.2.1","uglify-js":">= 1.1.1","design.io":">= 0.1.0","mocha":">= 0.8.1","gzip":">= 0.1.0","ejs":">= 0.6.1"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.3.1","_engineSupported":true,"_npmVersion":"1.0.105","_nodeVersion":"v0.6.1","_defaultsLoaded":true,"dist":{"shasum":"05465c21f60241081be7716e231be4a94c090ea0","tarball":"https://registry.npmjs.org/tower/-/tower-0.3.1.tgz","integrity":"sha512-rpoYFKE3lYL0jpr23mTpY1MfiP6CmhO1opoQgxXMQV5AtiJrioguOh3wZ41jGRkrU3RMj6RCkLEKBhy4oG+3Zg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFbPuqcM4W7eu4mbbPapFlYWsCIJlahzdVeEyeQzgmYcAiBvRWCA1tH4hCIV8cEq2f08ZHM2igQ6j3DmpfzA1CZbQw=="}]}},"0.3.2":{"name":"tower","version":"0.3.2","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","shift":">= 0.1.5","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","ejs":">= 0.6.1","restler":">= 0.0.1","useragent":">= 1.0.5","stylus":">= 0.17.0"},"devDependencies":{"coffee-script":">= 1.1.3","stylus":">= 0.17.0","jade":">= 0.16.2","coffeekup":">= 0.3.1","mustache":">= 0.3.1-dev","markdown":">= 0.2.1","uglify-js":">= 1.1.1","design.io":">= 0.1.0","mocha":">= 0.8.1","gzip":">= 0.1.0","ejs":">= 0.6.1"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.3.2","_engineSupported":true,"_npmVersion":"1.0.105","_nodeVersion":"v0.6.1","_defaultsLoaded":true,"dist":{"shasum":"b49d53919abc5ffd06a027381354853a0b7e0347","tarball":"https://registry.npmjs.org/tower/-/tower-0.3.2.tgz","integrity":"sha512-1P5HIEgBYVCoIMET6Q8JKdYLJHtWD/wLr1LVdzVtAOsmVyutyNjtNOa7yw//NzLEiQq19U3EBdsQtAac5QFviw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDfz0IF+ljwRZ8wBzQ+o2/6rK7Z76rMIGae6vi5aPCf/QIhAIeGH/1eVC1u15oVczhdC3FaZMOtoqGjXUzRGhCR7B2B"}]}},"0.3.9":{"name":"tower","version":"0.3.9","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","mint":">= 0.3.0","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","restler":">= 0.0.1","useragent":">= 1.0.5","URIjs":">= 1.4.2"},"devDependencies":{"coffee-script":">= 1.2.0","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","design.io":">= 0.3.0","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5"},"scripts":{"test":"mocha $(find test -name \"*Test.coffee\") -r coffee-script $@"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.3.9","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.1","_nodeVersion":"v0.6.1","_defaultsLoaded":true,"dist":{"shasum":"3b5c4fd11aa74dada8a760d4a07978e494b4e2af","tarball":"https://registry.npmjs.org/tower/-/tower-0.3.9.tgz","integrity":"sha512-APjWz+xOSJtot5oHCEYD3OjePWmirjpi9Tv7fzBhG/mGWbdK533YQ29EcEmp3px0WHOLFmg1hXjZypBCcE3X7Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDxBM7Lyp0B1Cz1329oDiV2uG3Kq8x/+Ej/NtnBBATiyAiAsO9srEXesQydrfaMpGM9v6Ws7onZUuwodjiqwG+Oiqw=="}]}},"0.3.9-1":{"name":"tower","version":"0.3.9-1","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","mint":">= 0.3.0","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","restler":">= 0.0.1","useragent":">= 1.0.5","URIjs":">= 1.4.2"},"devDependencies":{"coffee-script":">= 1.2.0","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","design.io":">= 0.3.0","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5"},"scripts":{"test":"mocha $(find test -name \"*Test.coffee\") -r coffee-script $@"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.3.9-1","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.1","_nodeVersion":"v0.6.1","_defaultsLoaded":true,"dist":{"shasum":"5db4580421a98eadfb6255ab9ba7faa9c10dee98","tarball":"https://registry.npmjs.org/tower/-/tower-0.3.9-1.tgz","integrity":"sha512-s8zVENO60LSCengNg4hotMynI+hcDe4MagPJmXrkOFuItHtjmqqp0s769W68iirG/P6raEoqnK6/s29ONworBg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICjvLFb+2g8SdaU78K8yhvP5Te34n7PiR6g64UbqPoS4AiEAgYukXQ26peYDU+ORqAr9mqh7Lm0IkJykRrnmb3Ub0I0="}]}},"0.3.9-2":{"name":"tower","version":"0.3.9-2","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","mint":">= 0.3.0","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","restler":">= 0.0.1","useragent":">= 1.0.5","URIjs":">= 1.4.2"},"devDependencies":{"coffee-script":">= 1.2.0","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","design.io":">= 0.3.0","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5"},"scripts":{"test":"mocha $(find test -name \"*Test.coffee\") -r coffee-script $@"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.3.9-2","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.1","_nodeVersion":"v0.6.1","_defaultsLoaded":true,"dist":{"shasum":"1f6fc4529ee0c1ec6ae1110b97c7b35f99521ca0","tarball":"https://registry.npmjs.org/tower/-/tower-0.3.9-2.tgz","integrity":"sha512-0j2P5Sw2HxiQ/z6eN95RPB+aJF/rCnf0VUyhhcnzwtaoVsTbG7MfUci+0Ob/hEmt7bFSVtA67r4bJXo5E3cILw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAo106gDB6rUbWrTDlqlcZvwXpJ0OHs+ndaNkYZOOsZcAiEAxaR64Fqx3vvc81z3OutbgJMR1C2trLyDi17SyOHup5M="}]}},"0.3.9-3":{"name":"tower","version":"0.3.9-3","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","mint":">= 0.3.0","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","restler":">= 0.0.1","useragent":">= 1.0.5","URIjs":">= 1.4.2"},"devDependencies":{"coffee-script":">= 1.2.0","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","design.io":">= 0.3.0","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5"},"scripts":{"test":"mocha $(find test -name \"*Test.coffee\") -r coffee-script $@"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.3.9-3","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.1","_nodeVersion":"v0.6.1","_defaultsLoaded":true,"dist":{"shasum":"3c37f3d6463a20577ed6d7a2939c481fb01ad4ee","tarball":"https://registry.npmjs.org/tower/-/tower-0.3.9-3.tgz","integrity":"sha512-xLnz/mX3taGOCwdIl4Uj4pX/1bocUfEF6CAWrd0p/2Kb4htde6eS5k9zqTxupUkaT/ilJhlUVSsbdmcNVpPbNA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICEWW9vmOd+3HBhHidPJpdzUg1iohUI6gEKyHbjrOAeGAiEAmFgiHSc24PZrkqEFkH4XsDVvy0v8K94fRpoXZY0PT1Y="}]}},"0.3.9-4":{"name":"tower","version":"0.3.9-4","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","mint":">= 0.3.0","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","restler":">= 0.0.1","useragent":">= 1.0.5","URIjs":">= 1.4.2"},"devDependencies":{"coffee-script":">= 1.2.0","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","design.io":">= 0.3.0","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5"},"scripts":{"test":"mocha $(find test -name \"*Test.coffee\") -r coffee-script $@"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.3.9-4","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.1","_nodeVersion":"v0.6.1","_defaultsLoaded":true,"dist":{"shasum":"b1f41c093ffd701e4f0311d9417836c76c4feb70","tarball":"https://registry.npmjs.org/tower/-/tower-0.3.9-4.tgz","integrity":"sha512-8cfsUM/rJdIY/0ogHS6KhD09A94nGDEbN/OexHVJjQbMwIs8IOQHz+0cnJojw9WBJcc+EGHmYCyPR3dP8l+sag==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGcOYX3XzyTXb+Zcta/jvzkFT9Ti4gqo4R42W/4ebBqyAiAS8EcvTRw8i3NCNBApC44+jJgNb0gMgb6eMTgntsZjOw=="}]}},"0.3.9-5":{"name":"tower","version":"0.3.9-5","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","mint":">= 0.3.0","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","restler":">= 0.0.1","useragent":">= 1.0.5","URIjs":">= 1.4.2"},"devDependencies":{"coffee-script":">= 1.2.0","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","design.io":">= 0.3.0","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5"},"scripts":{"test":"mocha $(find test -name \"*Test.coffee\") -r coffee-script $@"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.3.9-5","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.1","_nodeVersion":"v0.6.1","_defaultsLoaded":true,"dist":{"shasum":"67ca7393e645adf57dca820166acdf0db910e791","tarball":"https://registry.npmjs.org/tower/-/tower-0.3.9-5.tgz","integrity":"sha512-3b+QHV5x3LIpX1iovXc8YPSjiva2mT8R1cCXls8c3BHoos8jPempoRszGSubo1gceToXjIV2gehHeuDZcyJnLQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEAYVb2IEMGcQQGaaz7jfiM5YvOkJBAo/2uDwBX+5kUVAiEAuVt0o5m04VCSVq8r/07KvZZMI3SfmpTacCSETa/42NU="}]}},"0.3.9-6":{"name":"tower","version":"0.3.9-6","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","mint":">= 0.3.0","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","restler":">= 0.0.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.4.0"},"devDependencies":{"coffee-script":">= 1.2.0","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5"},"scripts":{"test":"mocha $(find test -name \"*Test.coffee\") -r coffee-script $@"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.3.9-6","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.1","_nodeVersion":"v0.6.1","_defaultsLoaded":true,"dist":{"shasum":"181c589db7eb357630cc0703bf3810925a34c855","tarball":"https://registry.npmjs.org/tower/-/tower-0.3.9-6.tgz","integrity":"sha512-I21qGMJDAtV1iow8UmQmBSyqwhKAV+ABGJwFkEmYR92ZeMeCgfK+hvJeBjDv/zCfBhv9OUse9/BZegx+DYthsg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCGeY0EJjdqbSzgk3/260nAlh8/JKS8BhxrtVdIyIeCVgIhAMUHfilgi2OpaFlMBvrM0AzoESWCKN+xmAksXkrVO8tA"}]}},"0.3.9-7":{"name":"tower","version":"0.3.9-7","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","mint":">= 0.3.0","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","restler":">= 0.0.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.4.0"},"devDependencies":{"coffee-script":">= 1.2.0","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5"},"scripts":{"test":"mocha $(find test -name \"*Test.coffee\") -r coffee-script $@"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.3.9-7","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.1","_nodeVersion":"v0.6.1","_defaultsLoaded":true,"dist":{"shasum":"6432b75beefdee87d60fd2d0a23346a73f19d5a7","tarball":"https://registry.npmjs.org/tower/-/tower-0.3.9-7.tgz","integrity":"sha512-sS9jATQnh3lzQKm4eZ9NBPfskufxbQ78yAf0bB3Zsy882QJA8yZPhmHsnRlxmGbhRTzO8lTnvF2T567+qfGC9A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCxDbUCqWVRATx6y5QLSMDo39IEnT9SlPtJ3xC7gdK58AIgFUEHW5OPVQgyfqL+qLq6yEKBbSi7YeObBAa6whOYdwc="}]}},"0.3.9-8":{"name":"tower","version":"0.3.9-8","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","mint":">= 0.3.0","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","restler":">= 0.0.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.4.0","node-uuid":">= 1.3.0"},"devDependencies":{"coffee-script":">= 1.2.0","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5","mongodb":">= 0.9.9"},"scripts":{"test":"mocha $(find test -name \"*Test.coffee\") -r coffee-script $@"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.3.9-8","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.4","_nodeVersion":"v0.6.11","_defaultsLoaded":true,"dist":{"shasum":"749c9c49e2ac5dde5e96b8b6a1b896d94cefdbed","tarball":"https://registry.npmjs.org/tower/-/tower-0.3.9-8.tgz","integrity":"sha512-g6M20T+gxCMC7sOePwS4CzcFk0DSaGt78BD1H4Cdua4K9UFfIXPYTbr7DZWyVSOI7ZXbvleS6WmBi1Gz8Mvkbg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCSFK464skBChkTuneD2txSvk90Q8vT2UNrP3T/Ox5LKwIhAKBrXikn2PI5tsZtkN6/F8F/TDGiKAfhymn9VqtZt9qb"}]}},"0.3.9-9":{"name":"tower","version":"0.3.9-9","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","mint":">= 0.3.0","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","restler":">= 0.0.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.4.0","node-uuid":">= 1.3.0"},"devDependencies":{"coffee-script":">= 1.2.0","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5","mongodb":">= 0.9.9"},"scripts":{"test":"mocha $(find test -name \"*Test.coffee\") -r coffee-script $@"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.3.9-9","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.4","_nodeVersion":"v0.6.11","_defaultsLoaded":true,"dist":{"shasum":"c176a35ba93bfa6ccec8fda45ea6e058dd1cfd28","tarball":"https://registry.npmjs.org/tower/-/tower-0.3.9-9.tgz","integrity":"sha512-Lw5qP+z2H7TSYPPgvyqZ4Rbc5sG+t8phqTZDN1nLhBo+8kd4G/rdMAaakQVbSxpck2Z7oq3wyYbKRVGYhBJ07Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB56Q69vYPRvN9OFBSU44A6eMyXvdCWJj05PcvTWiCSiAiB8KA4YHngkyfNZsSho9zrn57rbwR98tsHHOpoihUGThQ=="}]}},"0.3.9-10":{"name":"tower","version":"0.3.9-10","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","mint":">= 0.3.1","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","restler":">= 0.0.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.4.0","node-uuid":">= 1.3.0"},"devDependencies":{"cli-table":">= 0.0.1","findit":">= 0.1.1","coffee-script":">= 1.2.0","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5","mongodb":">= 0.9.9","eco":">= 0.1.0"},"scripts":{"test":"mocha $(find test -name \"*Test.coffee\") -r coffee-script $@"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.3.9-10","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.4","_nodeVersion":"v0.6.11","_defaultsLoaded":true,"dist":{"shasum":"b3ae0e55f2115f62ca04dbd305514b8c494117f4","tarball":"https://registry.npmjs.org/tower/-/tower-0.3.9-10.tgz","integrity":"sha512-N51to93ac6zpOBjFc92mgfFj8ru0DkdVVhlIM2UzuMroWRqHz6GOjcGF4LkudabKchHAGSt8VvU3jQkMMIZVpw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCJCH3Tx6jcolsXnMuWcube8BG4yMoR0o7ayw3Z50kqFwIgLhK0gGDOJ0pFU4IEHsLsNQLTKI2a4gb9UX40IeRzijo="}]}},"0.3.9-11":{"name":"tower","version":"0.3.9-11","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","mint":">= 0.3.1","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","restler":">= 0.0.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.4.0","node-uuid":">= 1.3.0"},"devDependencies":{"cli-table":">= 0.0.1","findit":">= 0.1.1","coffee-script":">= 1.2.0","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5","mongodb":">= 0.9.9","eco":">= 0.1.0"},"scripts":{"test":"mocha $(find test -name \"*Test.coffee\") -r coffee-script $@"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.3.9-11","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.4","_nodeVersion":"v0.6.11","_defaultsLoaded":true,"dist":{"shasum":"63b24b553e15a1707b0cbb0a9518b2aae93e8a0b","tarball":"https://registry.npmjs.org/tower/-/tower-0.3.9-11.tgz","integrity":"sha512-mRTm6UnjpWnMiv/eo42A1Tw7KJznnRt3HNKZd8W4Vq1zYLlrboM4jYCZ6BIEP8xBprg10weMLqZSIqAg9QyJ+w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC7xX6xGSCR2k99c8I+aixB/WTCvhdHKbc9VPZGzHNMzwIhAOmi8VieYIHZc6C5SAsfCNnepuwvAiDWqm6H26kUx5tt"}]}},"0.3.9-12":{"name":"tower","version":"0.3.9-12","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","mint":">= 0.3.1","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","restler":">= 0.0.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.4.0","node-uuid":">= 1.3.0"},"devDependencies":{"cli-table":">= 0.0.1","findit":">= 0.1.1","coffee-script":">= 1.2.0","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5","mongodb":">= 0.9.9","eco":">= 0.1.0"},"scripts":{"test":"mocha $(find test -name \"*Test.coffee\") -r coffee-script $@"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.3.9-12","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.4","_nodeVersion":"v0.6.11","_defaultsLoaded":true,"dist":{"shasum":"d1478dd56151f6ade7b94df37bc2594eaa14e006","tarball":"https://registry.npmjs.org/tower/-/tower-0.3.9-12.tgz","integrity":"sha512-h478Or0NKXdkspP6egLMimaJ3Q0F1Y7bAFvKOqrw5K/ZxyCbCRTIfmigqMzGsX8C3nhV6NqY+RCNv46BZE9DzQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCz/LnUJpNPXpRB/n4M+9J6CoY6oG8ierpw7ysX8bCkNwIhALHHrc53WF3F+RJ9OYnQRDps40JXJFWrCDltTF3RF26U"}]}},"0.3.9-13":{"name":"tower","version":"0.3.9-13","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","mint":">= 0.3.1","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","restler":">= 0.0.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.4.0","node-uuid":">= 1.3.0"},"devDependencies":{"cli-table":">= 0.0.1","findit":">= 0.1.1","coffee-script":">= 1.2.0","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5","mongodb":">= 0.9.9","eco":">= 0.1.0"},"scripts":{"test":"mocha $(find test -name \"*Test.coffee\") -r coffee-script $@"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.3.9-13","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.4","_nodeVersion":"v0.6.11","_defaultsLoaded":true,"dist":{"shasum":"8f4a1cb083e4e880ed5e89e0c73d1b95535a40c5","tarball":"https://registry.npmjs.org/tower/-/tower-0.3.9-13.tgz","integrity":"sha512-Gwu4iVEf5PwoHYEjkArTo5K/MdTTpO7NIuum7DPeGJDmutwi8iA2TRkf+zzvoavgAf2kDpeGjbrN/ftKaTsJGg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC1mWeYCHJThqUc0hxrfHMs6LITGuipqRF//5ba8N8cQAiEAgDWUVctXBpA1RxbWeL+BfjjbnADMuP4zPeLtfPjknLY="}]}},"0.4.0":{"name":"tower","version":"0.4.0","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","mint":">= 0.3.1","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","restler":">= 0.0.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.4.0","node-uuid":">= 1.3.0"},"devDependencies":{"cli-table":">= 0.0.1","findit":">= 0.1.1","coffee-script":">= 1.2.0","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5","mongodb":">= 0.9.9","eco":">= 0.1.0"},"scripts":{"test":"mocha $(find test -name \"*Test.coffee\") -r coffee-script $@"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.4.0","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.4","_nodeVersion":"v0.6.11","_defaultsLoaded":true,"dist":{"shasum":"1c34b1791bbb2fa4344a5276c911b1ac0298aba9","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.0.tgz","integrity":"sha512-HndVjzhFscW7iWGmp4ySWiUv2kXz1z4zQLzo+Mehn2gLT8CS1885qig75D1r3HwUQlQYi2RwQq+WomV0giC5PA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCUx/r4ClvzefNHn+w9F8pfiL1y1Pu6djlDd3nVyK/AVwIhAOcP8P0JH5GDTvkpPsoRsatt/3IPal/gQwnu5gQ/Pg0D"}]}},"0.4.0-2":{"name":"tower","version":"0.4.0-2","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","mint":">= 0.3.1","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","restler":">= 0.0.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.5.1","node-uuid":">= 1.3.0","geolib":">= 0.0.1","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":"git://github.com/viatropos/node.inflection.git"},"devDependencies":{"cli-table":">= 0.0.1","findit":">= 0.1.1","coffee-script":">= 1.2.0","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5","mongodb":">= 0.9.9","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0"},"scripts":{"test":"mocha $(find test -name \"*Test.coffee\")","docs":"codo"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.4.0-2","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.4","_nodeVersion":"v0.6.14","_defaultsLoaded":true,"dist":{"shasum":"c0a65d350b2f7664d4a842c3c1b3a1ff68201db0","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.0-2.tgz","integrity":"sha512-7GhyROzFvo4se+8fX+t965AJlZugUmDft4+EXv8xuXXk94yUKHRyMElowzH0yCvZCdeqV1a8Md3q1rKQmK85LA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDg2QLqW7RstBxlqUKxZPrlXpqoRzo8cCYMLkggQ/Xz5wIgF0cMCrk8dVf4JLwGRM6Q7u5LQ++kPpUnKtTOb41bO54="}]}},"0.4.0-3":{"name":"tower","version":"0.4.0-3","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.1.6","underscore.string":">= 1.2.0","mime":">= 1.2.4","connect":">= 1.7.1","qs":">= 0.3.1","async":">= 0.1.12","lingo":">= 0.0.4","underscore.logger":">= 0.3.1","mint":">= 0.3.1","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":">= 2.5.1","socket.io":">= 0.8.7","coffee-script":">= 1.2.0","coffeekup":">= 0.3.1","restler":">= 0.0.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.5.1","node-uuid":">= 1.3.0","geolib":">= 0.0.1","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":"git://github.com/viatropos/node.inflection.git"},"devDependencies":{"cli-table":">= 0.0.1","findit":">= 0.1.1","coffee-script":">= 1.2.0","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5","mongodb":">= 0.9.9-7","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4"},"scripts":{"test":"mocha $(find test -name \"*Test.coffee\")","docs":"codo"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.4.0-3","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.4","_nodeVersion":"v0.6.14","_defaultsLoaded":true,"dist":{"shasum":"06bd6b371bd9b3f91a1a8c6baaab4a13d9ea9f72","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.0-3.tgz","integrity":"sha512-RoZQO5B5vlHJkeU7BVG8LNXdHP6Wqk4W+LNeExcg7EOGbTPMx0vkV4C0KCCP9kIHDYRGuSG9+nyqep0vV6ygqg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC9ILRy12f8fx/zsCQ+Tiiir/uwYp/RmFAAuCpZPAn+NAiEArFiBN73JbwAQENqaMnrcH3IemH2+/q9tHA/OUFUJHdk="}]}},"0.4.0-5":{"name":"tower","version":"0.4.0-5","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.0.0","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","underscore.logger":">= 0.3.1","mint":">= 0.3.4","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"2.x","socket.io":">= 0.8.7","coffee-script":">= 1.3.1","coffeekup":">= 0.3.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.5.1","node-uuid":">= 1.3.0","geolib":">= 0.0.1","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","superagent":">= 0.4.0","ember-metal":">= 0.9.2","ember-runtime":">= 0.9.2","wrench":">= 1.3.8"},"devDependencies":{"cli-table":">= 0.0.1","findit":">= 0.1.1","coffee-script":">= 1.3.1","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5","mongodb":">= 0.9.9-8","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4"},"scripts":{"test":"node_modules/mocha/bin/mocha $(find test -name \"*Test.coffee\")","docs":"codo"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.4.0-5","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.16","_nodeVersion":"v0.6.14","_defaultsLoaded":true,"dist":{"shasum":"67337ae0c6c6b337344b4aa3ab671b65652ac2b9","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.0-5.tgz","integrity":"sha512-FYwS5C+IuTjoQvVsmzidiomUU7taqUqaiJqhizrQM8qLckfQb8w6uw28pshQmZqb5RtKpZUs7MSvIpLjtB4EoQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGOPd12wuc3cXISe3UYl9NMYYxGH7jbwT1TMMpE3AGuNAiBlxdd6N7RVxaBGX052Gg18LXx8/qX/I6kAvb42AtqbkQ=="}]}},"0.4.0-6":{"name":"tower","version":"0.4.0-6","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.0.0","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","underscore.logger":">= 0.3.1","mint":">= 0.3.4","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"2.x","socket.io":">= 0.8.7","coffee-script":">= 1.3.1","coffeekup":">= 0.3.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.5.1","node-uuid":">= 1.3.0","geolib":">= 0.0.1","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","superagent":">= 0.4.0","ember-metal":">= 0.9.2","ember-runtime":">= 0.9.2","wrench":">= 1.3.8"},"devDependencies":{"cli-table":">= 0.0.1","findit":">= 0.1.1","coffee-script":">= 1.3.1","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5","mongodb":">= 0.9.9-8","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4"},"scripts":{"test":"node_modules/mocha/bin/mocha $(find test -name \"*Test.coffee\")","docs":"codo"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.4.0-6","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.16","_nodeVersion":"v0.6.14","_defaultsLoaded":true,"dist":{"shasum":"6c88efc07fc9e836a65626e909fc0a174c5b1e69","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.0-6.tgz","integrity":"sha512-xktDW7nmuLyzObvcrIDAv9T/Phsu1NQh8iUwd6QL6IG7G4vTPA86F97NOkuvkFwFdUSeYrimpSmccr7p+ocZ6A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDpvJSccg6554LVHgR+RNCTQ2tuO5yve6702LbRaAVi1AIhAPi8A67f+xtDPz/Cf9FkQ586/Du5fVvV4eZr8QhygGqR"}]}},"0.4.0-7":{"name":"tower","version":"0.4.0-7","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.0.0","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","underscore.logger":">= 0.3.1","mint":">= 0.3.4","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"2.x","socket.io":">= 0.8.7","coffee-script":">= 1.3.1","coffeekup":">= 0.3.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.5.1","node-uuid":">= 1.3.0","geolib":">= 0.0.1","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","superagent":">= 0.4.0","ember-metal":">= 0.9.2","ember-runtime":">= 0.9.2","wrench":">= 1.3.8"},"devDependencies":{"cli-table":">= 0.0.1","findit":">= 0.1.1","coffee-script":">= 1.3.1","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5","mongodb":">= 0.9.9-8","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4"},"scripts":{"test":"node_modules/mocha/bin/mocha $(find test -name \"*Test.coffee\")","docs":"codo"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.4.0-7","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.16","_nodeVersion":"v0.6.14","_defaultsLoaded":true,"dist":{"shasum":"a89f2f1ad260d65a30029cb6605258ea29b5c8a9","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.0-7.tgz","integrity":"sha512-hK5gtMusOZtsv9+uIwggLKgnCohhBx1m++D+wqz3mDdokov7NugBtpvYzJPDNursiLNbHNME1pzaG3k5tySSgA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDOAurOQldvIXq8kjnvPAhzwcRP7cEtyqZ9N4SCPoPXegIhANRwDeoaiO6CPydolrkRdMvSaxqn+LKQtE058oJcOlKB"}]}},"0.4.0-8":{"name":"tower","version":"0.4.0-8","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.0.0","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","underscore.logger":">= 0.3.1","mint":">= 0.3.4","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"2.x","socket.io":">= 0.8.7","coffee-script":">= 1.3.1","coffeekup":">= 0.3.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.5.1","node-uuid":">= 1.3.0","geolib":">= 0.0.1","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","superagent":">= 0.4.0","ember-metal":">= 0.9.2","ember-runtime":">= 0.9.2","wrench":">= 1.3.8"},"devDependencies":{"cli-table":">= 0.0.1","findit":">= 0.1.1","coffee-script":">= 1.3.1","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5","mongodb":">= 0.9.9-8","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4"},"scripts":{"test":"node_modules/mocha/bin/mocha $(find test -name \"*Test.coffee\")","docs":"codo"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.4.0-8","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.16","_nodeVersion":"v0.6.14","_defaultsLoaded":true,"dist":{"shasum":"4bcccaec1f46918d12582e1dca005e0a8b123c5d","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.0-8.tgz","integrity":"sha512-mbe+MPHw8Y1azb5QJY1QefsuDG2RFllVZmp86wpsGFpV6hSOgFZy3Vv8VD4X8WURJzxwbpUCOJMfNjJ5DVSArg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFX1KsIFCbTkZU2x3Fe++psgEODR9y9wHczUUQQWx3ysAiAUVcprZeLWO1zQ53uJGrkW4rwDNfuSgZ7VfgSmpI1LnA=="}]}},"0.4.0-9":{"name":"tower","version":"0.4.0-9","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.0.0","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","underscore.logger":">= 0.3.1","mint":">= 0.3.4","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"2.x","socket.io":">= 0.8.7","coffee-script":">= 1.3.1","coffeekup":">= 0.3.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.5.1","node-uuid":">= 1.3.0","geolib":">= 0.0.1","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","superagent":">= 0.4.0","ember-metal":">= 0.9.2","ember-runtime":">= 0.9.2","wrench":">= 1.3.8"},"devDependencies":{"cli-table":">= 0.0.1","findit":">= 0.1.1","coffee-script":">= 1.3.1","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5","mongodb":">= 0.9.9-8","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4"},"scripts":{"test":"node_modules/mocha/bin/mocha $(find test -name \"*Test.coffee\")","docs":"codo"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.4.0-9","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.16","_nodeVersion":"v0.6.14","_defaultsLoaded":true,"dist":{"shasum":"b4ac9ef00d4b12d1a04fd7d253783103335bdf48","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.0-9.tgz","integrity":"sha512-XTgrVF/mS+vsHn0+ZwD9XIVDn1ZuiQv3KoLiooJVWi2RqImiTVT0B/9raH9FxjB208eibyA6Pog5Y98m9c6swg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCLLBt3qooiXrAHvulZlQY/IPxH/mniOc97jdf94NFUyQIhAOiKrIlwVGY820QTKqqXmUZIJ77W+xz/1/ssRzuVqSKl"}]}},"0.4.0-10":{"name":"tower","version":"0.4.0-10","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.0.0","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","underscore.logger":">= 0.3.1","mint":">= 0.3.4","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"2.x","socket.io":">= 0.8.7","coffee-script":">= 1.3.1","coffeekup":">= 0.3.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.5.1","node-uuid":">= 1.3.0","geolib":">= 0.0.1","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","superagent":">= 0.4.0","ember-metal":">= 0.9.2","ember-runtime":">= 0.9.2","wrench":">= 1.3.8"},"devDependencies":{"cli-table":">= 0.0.1","findit":">= 0.1.1","coffee-script":">= 1.3.1","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5","mongodb":">= 0.9.9-8","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4"},"scripts":{"test":"node_modules/mocha/bin/mocha $(find test -name \"*Test.coffee\")","docs":"codo"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.4.0-10","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.16","_nodeVersion":"v0.6.14","_defaultsLoaded":true,"dist":{"shasum":"9795ba23491dd604d6321380cddfdb22b5d22041","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.0-10.tgz","integrity":"sha512-pdxhnfCPEIxcwnWVOl7AkQdF6j/ZEpWqPl3UzxECmL52jmn2rSsWHCmrXnuQL5UBEFnQUSOthrTF7ZqbqF7PWQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICanRTdLDt5sLpztcnAcD/JQj3MIIls+B6a119CcVYmcAiAfSR2fYoZcNQ5duNGjAJspYudQR6+ZV6yWenhafYEmyA=="}]}},"0.4.0-11":{"name":"tower","version":"0.4.0-11","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.0.0","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","underscore.logger":">= 0.3.1","mint":">= 0.3.4","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"2.x","socket.io":">= 0.8.7","coffee-script":">= 1.3.1","coffeekup":">= 0.3.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.5.1","node-uuid":">= 1.3.0","geolib":">= 0.0.1","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","superagent":">= 0.4.0","ember-metal":">= 0.9.2","ember-runtime":">= 0.9.2","wrench":">= 1.3.8"},"devDependencies":{"cli-table":">= 0.0.1","findit":">= 0.1.1","coffee-script":">= 1.3.1","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5","mongodb":">= 0.9.9-8","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4"},"scripts":{"test":"node_modules/mocha/bin/mocha $(find test -name \"*Test.coffee\")","docs":"codo"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.4.0-11","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.16","_nodeVersion":"v0.6.14","_defaultsLoaded":true,"dist":{"shasum":"e6e256bcabaebf34f8a9b9138ac88956ec6a3d9e","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.0-11.tgz","integrity":"sha512-xPOhfUIOaavi8D0UQR1Ekn9cO3x5fz/IIMhA1stLV2r0PSwp9WzwmjZGeMshk+PPYT/EotSbNuYw95cGK7xx1w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIES+Ert4A+Y2TDwvKnbtJ/iscx8JK2R6fI+K8PhOi+kfAiEAreyvjPrB3F5EVkynccvP0nswAMbjuI+CJhY7gMaE5h8="}]}},"0.4.0-12":{"name":"tower","version":"0.4.0-12","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.0.0","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","underscore.logger":">= 0.3.1","mint":">= 0.3.4","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"2.x","socket.io":">= 0.8.7","coffee-script":">= 1.3.1","coffeekup":">= 0.3.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.5.1","node-uuid":">= 1.3.0","geolib":">= 0.0.1","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","superagent":">= 0.4.0","ember-metal":">= 0.9.2","ember-runtime":">= 0.9.2","wrench":">= 1.3.8"},"devDependencies":{"cli-table":">= 0.0.1","findit":">= 0.1.1","coffee-script":">= 1.3.1","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5","mongodb":">= 0.9.9-8","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4"},"scripts":{"test":"node_modules/mocha/bin/mocha $(find test -name \"*Test.coffee\")","docs":"codo"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.4.0-12","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.16","_nodeVersion":"v0.6.14","_defaultsLoaded":true,"dist":{"shasum":"4ab7b87adb7841761f66ea2b635393c02aea6976","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.0-12.tgz","integrity":"sha512-X01zclZs8RTGXXck/pFm4y/dQ4PNch5aCTY8JheFamrpT5Z59X2mz5F9bMAC8u9INY3OOzTrb7Lz2XGcxvybOw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDjG6RmTPu3z+6fjHXXNAlv7yC8aaIfC8kMZSJmRoz5+wIgLwydhbCDwUsKlVPRTWJ33yQrjdM/cw4fgjyqi2thmvs="}]}},"0.4.0-13":{"name":"tower","version":"0.4.0-13","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"lib/tower.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"git://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.0.0","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","underscore.logger":">= 0.3.1","mint":">= 0.3.4","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"2.x","socket.io":">= 0.8.7","coffee-script":">= 1.3.1","coffeekup":">= 0.3.1","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.5.1","node-uuid":">= 1.3.0","geolib":">= 0.0.1","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","superagent":">= 0.4.0","ember-metal":">= 0.9.2","ember-runtime":">= 0.9.2","wrench":">= 1.3.8"},"devDependencies":{"cli-table":">= 0.0.1","findit":">= 0.1.1","coffee-script":">= 1.3.1","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","forever":">= 0.8.5","mongodb":">= 0.9.9-8","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4"},"scripts":{"test":"node_modules/mocha/bin/mocha $(find test -name \"*Test.coffee\")","docs":"codo"},"_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"_id":"tower@0.4.0-13","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.16","_nodeVersion":"v0.6.14","_defaultsLoaded":true,"dist":{"shasum":"9a6186d4a58c6f4ab94765406eacaebc2eaac3ac","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.0-13.tgz","integrity":"sha512-/TwIt3Fimvv9Oe3+WGdOlcEW54XTRuLs5wrbtAYLiC1Jr9V6R89s3LiqfMJ/1crrs4zyTUKW3hI1Y7J9cE0FPw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC7b96w5C5/pDwkISQK6VPVzObRbyKcp7sfeuaa1z049QIhAI4lTTSy56w6ah76ui7jSh2YaFLkgEpUfcq638eCmcH4"}]}},"0.4.1":{"name":"tower","version":"0.4.1","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.4.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.0.0","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","underscore.logger":">= 0.3.1","mint":">= 0.3.4","ejs":">= 0.6.1","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"2.x","socket.io":">= 0.8.7","useragent":">= 1.0.5","URIjs":">= 1.4.2","moment":">= 1.5.1","node-uuid":">= 1.3.0","geolib":">= 0.0.1","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","superagent":">= 0.4.0","ember-metal-node":">= 0.9.7","ember-runtime-node":">= 0.9.7","ember-states-node":">= 0.9.7","wrench":">= 1.3.8","temp":"~0.4.0","knox":"0.0.11","gm":"~1.4.1","nodemailer":"~0.3.21","coffee-script":"git://github.com/viatropos/coffee-script.git"},"devDependencies":{"cli-table":">= 0.0.1","findit":">= 0.1.1","stylus":">= 0.17.0","ejs":">= 0.6.1","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","gzip":">= 0.1.0","mongodb":">= 0.9.9-8","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","socket.io-client":">= 0.9.5","fibers":"~0.6.8"},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"codo","postinstall":"npm install git://github.com/viatropos/coffeecup.git --force && npm install git://github.com/viatropos/coffee-script.git --force"},"readme":"# Tower.js <img src=\"http://i.imgur.com/e3VLW.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Issues**: http://github.com/viatropos/tower/issues\n- **Roadmap**: http://github.com/viatropos/tower/wiki/roadmap\n\nNote, Tower is still very early alpha (0.4.0).  Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going.  If your up for it please contribute!  The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release.  From there, it's performance optimization, workflow streamlining, and creating some awesome examples.  1.0 will be a plug-and-chug real-time app framework.\n\nTower is soon going to support only Node.js 0.8.0+. This stuff moves fast.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Contributor Note\n\nAll of the base ideas are now pretty much in the Tower codebase, now it's just a matter of fleshing out the edge cases and a few implementations. Here's what's new:\n\n- Background jobs in Redis. The `Model.enqueue` and `Model#enqueue` methods are convention for off-loading expensive tasks to the background. You then run `cake work` and it will start the [kue](https://github.com/LearnBoost/kue) background worker to process items in the different redis queues. That process is running in a totally separate environment, but they can communicate b/c of redis' nice pub/sub api. This still needs to be fleshed out and tested a bit more but the basics are there.\n- Attachments. File uploading is working, as well as image resizing with imagemagick. I've started working on post-processing using background redis jobs as well. Tower should have a standard set of attachment \"processors\" to make uploading/processing attachments dead-simple (it's still pretty hard in Rails). This includes from any format to standard formats (video/audio/docs/images/etc.), video/audio/image processing/compression, text extraction and resizing, and document processing (pdf text extraction, MS Word to text, etc.). It's all pretty straight forward, just need to wrap command-line tools. See http://documentcloud.github.com/docsplit/.\n- Authentication. I don't think I've merged the authentication code yet, but an older version is here: https://github.com/viatropos/tower-authentication-example. The whole logging in with email/facebook/etc. should be completely solved. Right now mongodb session support is working locally, I will merge it when I finish with some other stuff.\n- Subdomains. Subdomains should be first-class citizens. We need to thoroughly test them in production. JSONP support exists (to do `GET` requests across domains), need to test that out. Need to get a better/leaner URL parser, but what's in there now works. Need to test authentication/sessions/cookies across subdomains.\n- Authorization. I've started on the authorization system (inspired from [cancan](https://github.com/ryanb/cancan/)). It works and is pretty awesome :). Just need to add some controller hooks to make it plug-and-chug.\n- Mass-assignment protection. I've implemented the basics of \"mass assignment protection\" (see the [Rails Security Guide](http://guides.rubyonrails.org/security.html#mass-assignment)), need to test it out a bit more. Also need to handle input sanitization.\n- Embedded Documents. I've mapped out how this could be implemented but it's still on the todo list.\n- Associations (hasMany, hasManyThrough, belongsTo, hasOne). They all work well (tested manually on the client as well, pretty awesome seeing hasManyThrough relations save on the client). There's a good amount of work to be done on making sure `user.address == address.user`, that kind of reflection stuff (especially for binding on the view). Wrote down a lot of ideas on how to implement an \"identity map\", but we have to be careful about garbage collection if we're going to store references to the request/controller objects in some hidden \"thread\" (see some of the recent commits for notes - early/mid July). Also need to make the validations/callbacks more robust for `acceptsNestedAttributesFor`, but it's all working at a basic level.\n- The Cursor. The cursor is _super_ awesome :). There's a ton more ideas on how to make it even more awesome, but for now it does what it's supposed to. I'd like to simplify the notification system eventually (telling the client of model changes).\n- User stamping. This should be a fundamental part of the model layer (similar to time stamping). The base mixin has been started but isn't ready yet - it requires setting up the identity-map/thread idea so you can pass around the `currentUser` transparently between cursors/models in the context of a single request.\n- Versioning. Versioning is a tricky concept to implement, and it is not required for all apps. But it is generic enough and useful enough that it is going to be included in Tower (eventually as a separate sub-package). It allows you to keep a history of model changes (and alongside userstamping, who made those changes). I have started this as well.\n- Soft deleting models. Sometimes you want to allow users to \"delete\" their data, but you don't _really_ want it deleted from the database. To do this you just add a `deletedAt` field to your model, and then make it so all queries by default ignore models without `deletedAt == null`. You want this kind of stuff to do things like \"restore your deleted account\", or just know what's happened historically in your app (as a startup for example).\n- Ember Views. This is the next big thing to do, but it's really independent of Tower. Tower can create some helpers like form builders and whatnot, but that might take a long time - particularly b/c there's going to be a lot of work put in to make sure performance is top-notch with all those views.\n- Client Routes. The base code for mapping routes.coffee into the Ember routing system is there, but the Ember API is changing weekly almost so I haven't gotten back to it. It should only take a few hours to wire up.\n\nIf you're excited to work on one of these things let me know and I'll point you to where things are and all that. Once all of this stuff is reasonably complete (mid August hopefully), this will merge into master. From there it's going to be \"robustifying\" everything, and hardcore performance tuning.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nIf you would like to mess around with the tower source code, clone it and start the grunt watcher to compile all of the coffeescripts:\n\n```\nmake watch\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Structure\n\nHere's how you might organize a blog:\n\n```\n.\n|-- app\n|   |-- client\n|   |   |-- stylesheets\n|   |-- controllers\n|   |   |-- admin\n|   |   |   |-- postsController.coffee\n|   |   |   `-- usersController.coffee\n|   |   |-- commentsController.coffee\n|   |   |-- postsController.coffee\n|   |   |-- sessionsController.coffee\n|   |   `-- usersController.coffee\n|   |-- models\n|   |   |-- comment.coffee\n|   |   |-- post.coffee\n|   |   `-- user.coffee\n|   |-- views\n|   |   |-- admin\n|   |   |   `-- posts\n|   |   |       |-- _form.coffee\n|   |   |       |-- edit.coffee\n|   |   |       |-- index.coffee\n|   |   |       |-- new.coffee\n|   |   |       |-- show.coffee\n|   |   |-- layouts\n|   |   |   `-- application.coffee\n|   |   |-- shared\n|   |   `-- posts\n|   |       |-- index.coffee\n|   |       `-- show.coffee\n|   `-- helpers\n|       |-- admin\n|       |   |-- postsHelper.coffee\n|       |   `-- usersHelper.coffee\n|       `-- postsHelper.coffee\n`-- config\n|    |-- application.coffee\n|    |-- assets.coffee\n|    |-- databases.coffee\n|    |-- environments\n|       |-- development.coffee\n|       |-- production.coffee\n|       `-- test.coffee\n|    |-- locale\n|       `-- en.coffee\n|    |-- routes.coffee\n`-- test\n|    |-- helper.coffee\n|    |-- models\n|    |   |-- postTest.coffee\n|    |   |-- userTest.coffee\n|    `-- acceptance\n|        |-- login.coffee\n|        |-- signup.coffee\n|        `-- posts.coffee\n```\n\n## Application\n\n``` coffeescript\n# config/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n``` coffeescript\n# app/models/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n``` coffeescript\n# app/models/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n``` coffeescript\n# app/models/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Views\n\nViews adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\n## Controllers\n\n``` coffeescript\n# app/controllers/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render \"index\", locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render \"new\"\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render \"posts/edit\"\n      @success.json => @render text: \"success!\"\n      @failure.html => @render text: \"Error\", status: 404\n      @failure.json => @render text: \"Error\", status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render \"show\"\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render \"edit\"\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: \"show\"\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: \"index\"\n```\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# config/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: \"app-development\"\n      port: 27017\n      host: \"127.0.0.1\"\n    test:\n      name: \"app-test\"\n      port: 27017\n      host: \"127.0.0.1\"\n    staging:\n      name: \"app-staging\"\n      port: 27017\n      host: \"127.0.0.1\"\n    production:\n      name: \"app-production\"\n      port: 27017\n      host: \"127.0.0.1\"\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: \"me@gmail.com\"\n```\n\n## Internationalization\n\n``` coffeescript\n# config/locales/en.coffee\nmodule.exports =\n  hello: \"world\"\n  forms:\n    titles:\n      signup: \"Signup\"\n  pages:\n    titles:\n      home: \"Welcome to %{site}\"\n  posts:\n    comments:\n      none: \"No comments\"\n      one: \"1 comment\"\n      other: \"%{count} comments\"\n  messages:\n    past:\n      none: \"You never had any messages\"\n      one: \"You had 1 message\"\n      other: \"You had %{count} messages\"\n    present:\n      one: \"You have 1 message\"\n    future:\n      one: \"You might have 1 message\"\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# config/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      \"/vendor/javascripts/jquery.js\"\n      \"/vendor/javascripts/underscore.js\"\n      \"/vendor/javascripts/socket.io\"\n      \"/vendor/javascripts/tower.js\"\n    ]\n    \n    lib: [\n      \"/lib/grid.js\"\n      \"/lib/profiler.js\"\n    ]\n    \n    application: [\n      \"/app/models/post.js\"\n      \"/app/models/comment.js\"\n    ]\n    \n  stylesheets:\n    vendor: [\n      \"/vendor/stylesheets/reset.css\"\n    ]\n    application: [\n      \"/app/assets/stylesheets/application.css\"\n      \"/app/assets/stylesheets/theme.css\"\n    ]\n```\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\n## Examples\n\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n## Unsolved Complexities\n\n- Handling transactions from the client. How would you save the data for credit/account (subtract one record, add to another) so if one fails both revert back (if you try to keep it simplified and only POST individual records at a time)? You can do embedded models on MongoDB, and transactions on MySQL perhaps. Then if `acceptsNestedAttributesFor` is specified it will send nested data in JSON POST rather than separate. Obviously it's better to not do this on the server, but we should see if it's possible to do otherwise, and if not, publicize why.\n\n## Decisions (need to finalize)\n\n- for uniqueness validation, if it fails on the client, should it try fetching the record from the server? (and loading the record into the client memory store). Reasons for include having to do less work as a coder (lazy loads data). Reasons against include making HTTP requests to the server without necessarily expecting to - or you may not want it to fetch. Perhaps you can specify an option (`lazy: true`) or something, and on the client if true it will make the request (or `autofetch: true`)\n- For non-transactional (yet still complex) associations, such as `group hasMany users through memberships`, you can save one record at a time, so the client should be instant. But if the first record created fails (say you do `group.members.create()`, which creates a user, then a membership tying the two together), what should the client tell the user? Some suggest a global notification (perhaps an alert bar) saying a more generic message such as \"please refresh the page, some data is out of sync\". But if the data is very important, ideally the code would know how to take the user (who might click this notification) to a form to try saving the `hasMany through` association again. If it continues to fail, it's probably either a bug in the code, or we should be able to know if the server is having issues (like it's crashed or power went out) - then if it's a bug we can have them notify us (some button perhaps) or if it's a real server problem we prepared for we can notify something like \"sorry, having server issues, try again later\". Other that that, it's up to you to build the validations properly so the data is saved\n\n## Todo\n\n- use require in the browser to lazy load scripts\n- gruntjs\n- term-css\n- https://github.com/kuno/GeoIP\n- global timestamps/userstamps config boolean, to DRY model `@timestamps()` if desired\n- make tower into subpackages: (model/client, model/server, model/shared, controller/client, etc...)\n- http://jsperf.com/angular-vs-knockout-vs-ember/2\n\n## New Stuff (api is todo, can access now through Tower.router)\n\n``` coffeescript\n@resources 'posts'\n@namespace 'admin', ->\n  @resources 'posts'\n```\n\n``` coffeescript\nTower.urlFor(App.Post)\nTower.urlFor('root.posts.index')\n```\n\n``` coffeescript\n# GET\nApp.indexPosts(title: 'A') # App.action, Tower.action, which one?\nApp.showPost(id: 1)\nApp.newPost()\nApp.editPost(id: 1)\n# Non-GET\nApp.createPost()\nApp.updatePost(id: 1)\nApp.destroyPost(id: 1)\n```\n\n``` html\n{{#each post in App.postsController.all}}\n<a {{action editPost post href=true}}>Edit</a>\n{{/each}}\n```\n\n``` coffeescript\n# @todo\nApp.indexAdminPosts() # /admin/posts\nApp.indexPostComments(postId: 1) # /posts/1/comments\n```\n\n## Changelog\n\n- `brew install tree`, then you can type command `tree` to see project structure (https://github.com/cowboy/grunt-node-example)\n- todo: need to test installing different versions of node with https://github.com/creationix/nvm\n- https://gist.github.com/1398757","_id":"tower@0.4.1","dist":{"shasum":"0cd713a7a746f2c0dfa26400eb9cdec71f3f28f0","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.1.tgz","integrity":"sha512-A+qH3hpDNFCuaaeuG8uOogct2XS/VCXjO+Cz09kOtynchao3aww0rr5W2syZgvsqDpZm/MPMubqPm165uvkDug==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC2qdwZFq6OACRyTdE8KLnWKPlbWxMVXKSn1c/WNSwJAAIhAO5Im798NM70g3m5D6eIDohM2juL5mRlnMCjgC8ZPBhg"}]}},"0.4.2-pre":{"name":"tower","version":"0.4.2-pre","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","underscore.logger":">= 0.3.1","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","mint":">= 0.3.4","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"2.x","URIjs":">= 1.4.2","moment":">= 1.5.1","node-uuid":">= 1.3.0","geolib":">= 0.0.1","superagent":">= 0.4.0","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","ember-metal-node":">= 0.9.7","ember-runtime-node":">= 0.9.7","ember-states-node":">= 0.9.7","coffee-script":">= 1.3.3","wrench":">= 1.3.8"},"devDependencies":{"findit":">= 0.1.1"},"testDependencies":{"stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 0.9.9-8","coffee-script":">= 1.3.3","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.8.7","socket.io-client":">= 0.9.5","hook.io":"~0.8.10","fibers":"~0.6.8"},"globalDependencies":{"ejs":">= 0.6.1"},"localDependencies":{"useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0"},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"codo","postinstall":"$(./bin/dependencies)"},"readme":"# Tower.js <img src=\"http://i.imgur.com/e3VLW.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower-docs\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If your up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Contributor Note\n\nAll of the base ideas are now pretty much in the Tower codebase, now it's just a matter of fleshing out the edge cases and a few implementations. Here's what's new:\n\n- Background jobs in Redis. The `Model.enqueue` and `Model#enqueue` methods are convention for off-loading expensive tasks to the background. You then run `cake work` and it will start the [kue](https://github.com/LearnBoost/kue) background worker to process items in the different redis queues. That process is running in a totally separate environment, but they can communicate b/c of redis' nice pub/sub api. This still needs to be fleshed out and tested a bit more but the basics are there.\n- Attachments. File uploading is working, as well as image resizing with imagemagick. I've started working on post-processing using background redis jobs as well. Tower should have a standard set of attachment \"processors\" to make uploading/processing attachments dead-simple (it's still pretty hard in Rails). This includes from any format to standard formats (video/audio/docs/images/etc.), video/audio/image processing/compression, text extraction and resizing, and document processing (pdf text extraction, MS Word to text, etc.). It's all pretty straight forward, just need to wrap command-line tools. See http://documentcloud.github.com/docsplit/.\n- Authentication. I don't think I've merged the authentication code yet, but an older version is here: https://github.com/viatropos/tower-authentication-example. The whole logging in with email/facebook/etc. should be completely solved. Right now mongodb session support is working locally, I will merge it when I finish with some other stuff.\n- Subdomains. Subdomains should be first-class citizens. We need to thoroughly test them in production. JSONP support exists (to do `GET` requests across domains), need to test that out. Need to get a better/leaner URL parser, but what's in there now works. Need to test authentication/sessions/cookies across subdomains.\n- Authorization. I've started on the authorization system (inspired from [cancan](https://github.com/ryanb/cancan/)). It works and is pretty awesome :). Just need to add some controller hooks to make it plug-and-chug.\n- Mass-assignment protection. I've implemented the basics of \"mass assignment protection\" (see the [Rails Security Guide](http://guides.rubyonrails.org/security.html#mass-assignment)), need to test it out a bit more. Also need to handle input sanitization.\n- Embedded Documents. I've mapped out how this could be implemented but it's still on the todo list.\n- Associations (hasMany, hasManyThrough, belongsTo, hasOne). They all work well (tested manually on the client as well, pretty awesome seeing hasManyThrough relations save on the client). There's a good amount of work to be done on making sure `user.address == address.user`, that kind of reflection stuff (especially for binding on the view). Wrote down a lot of ideas on how to implement an \"identity map\", but we have to be careful about garbage collection if we're going to store references to the request/controller objects in some hidden \"thread\" (see some of the recent commits for notes - early/mid July). Also need to make the validations/callbacks more robust for `acceptsNestedAttributesFor`, but it's all working at a basic level.\n- The Cursor. The cursor is _super_ awesome :). There's a ton more ideas on how to make it even more awesome, but for now it does what it's supposed to. I'd like to simplify the notification system eventually (telling the client of model changes).\n- User stamping. This should be a fundamental part of the model layer (similar to time stamping). The base mixin has been started but isn't ready yet - it requires setting up the identity-map/thread idea so you can pass around the `currentUser` transparently between cursors/models in the context of a single request.\n- Versioning. Versioning is a tricky concept to implement, and it is not required for all apps. But it is generic enough and useful enough that it is going to be included in Tower (eventually as a separate sub-package). It allows you to keep a history of model changes (and alongside userstamping, who made those changes). I have started this as well.\n- Soft deleting models. Sometimes you want to allow users to \"delete\" their data, but you don't _really_ want it deleted from the database. To do this you just add a `deletedAt` field to your model, and then make it so all queries by default ignore models without `deletedAt == null`. You want this kind of stuff to do things like \"restore your deleted account\", or just know what's happened historically in your app (as a startup for example).\n- Ember Views. This is the next big thing to do, but it's really independent of Tower. Tower can create some helpers like form builders and whatnot, but that might take a long time - particularly b/c there's going to be a lot of work put in to make sure performance is top-notch with all those views.\n- Client Routes. The base code for mapping routes.coffee into the Ember routing system is there, but the Ember API is changing weekly almost so I haven't gotten back to it. It should only take a few hours to wire up.\n\nIf you're excited to work on one of these things let me know and I'll point you to where things are and all that. Once all of this stuff is reasonably complete (mid August hopefully), this will merge into master. From there it's going to be \"robustifying\" everything, and hardcore performance tuning.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nIf you would like to mess around with the tower source code, clone it and start the grunt watcher to compile all of the coffeescripts:\n\n```\nmake watch\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\nFor developing, you may also want to link tower and tower-tasks globally so you can reuse it between multiple projects:\n\n```\ncd <tower repo>\nnpm link\ncd lib/tower-tasks\nnpm link\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Structure\n\nHere's how you might organize a blog:\n\n```\n.\n|-- app\n|   |-- client\n|   |   |-- stylesheets\n|   |-- controllers\n|   |   |-- admin\n|   |   |   |-- postsController.coffee\n|   |   |   `-- usersController.coffee\n|   |   |-- commentsController.coffee\n|   |   |-- postsController.coffee\n|   |   |-- sessionsController.coffee\n|   |   `-- usersController.coffee\n|   |-- models\n|   |   |-- comment.coffee\n|   |   |-- post.coffee\n|   |   `-- user.coffee\n|   |-- views\n|   |   |-- admin\n|   |   |   `-- posts\n|   |   |       |-- _form.coffee\n|   |   |       |-- edit.coffee\n|   |   |       |-- index.coffee\n|   |   |       |-- new.coffee\n|   |   |       |-- show.coffee\n|   |   |-- layouts\n|   |   |   `-- application.coffee\n|   |   |-- shared\n|   |   `-- posts\n|   |       |-- index.coffee\n|   |       `-- show.coffee\n|   `-- helpers\n|       |-- admin\n|       |   |-- postsHelper.coffee\n|       |   `-- usersHelper.coffee\n|       `-- postsHelper.coffee\n`-- config\n|    |-- application.coffee\n|    |-- assets.coffee\n|    |-- databases.coffee\n|    |-- environments\n|       |-- development.coffee\n|       |-- production.coffee\n|       `-- test.coffee\n|    |-- locale\n|       `-- en.coffee\n|    |-- routes.coffee\n`-- test\n|    |-- helper.coffee\n|    |-- models\n|    |   |-- postTest.coffee\n|    |   |-- userTest.coffee\n|    `-- acceptance\n|        |-- login.coffee\n|        |-- signup.coffee\n|        `-- posts.coffee\n```\n\n## Application\n\n``` coffeescript\n# config/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n``` coffeescript\n# app/models/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n``` coffeescript\n# app/models/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n``` coffeescript\n# app/models/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Views\n\nViews adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\n## Controllers\n\n``` coffeescript\n# app/controllers/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render \"index\", locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render \"new\"\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render \"posts/edit\"\n      @success.json => @render text: \"success!\"\n      @failure.html => @render text: \"Error\", status: 404\n      @failure.json => @render text: \"Error\", status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render \"show\"\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render \"edit\"\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: \"show\"\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: \"index\"\n```\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# config/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: \"app-development\"\n      port: 27017\n      host: \"127.0.0.1\"\n    test:\n      name: \"app-test\"\n      port: 27017\n      host: \"127.0.0.1\"\n    staging:\n      name: \"app-staging\"\n      port: 27017\n      host: \"127.0.0.1\"\n    production:\n      name: \"app-production\"\n      port: 27017\n      host: \"127.0.0.1\"\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: \"me@gmail.com\"\n```\n\n## Internationalization\n\n``` coffeescript\n# config/locales/en.coffee\nmodule.exports =\n  hello: \"world\"\n  forms:\n    titles:\n      signup: \"Signup\"\n  pages:\n    titles:\n      home: \"Welcome to %{site}\"\n  posts:\n    comments:\n      none: \"No comments\"\n      one: \"1 comment\"\n      other: \"%{count} comments\"\n  messages:\n    past:\n      none: \"You never had any messages\"\n      one: \"You had 1 message\"\n      other: \"You had %{count} messages\"\n    present:\n      one: \"You have 1 message\"\n    future:\n      one: \"You might have 1 message\"\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# config/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      \"/vendor/javascripts/jquery.js\"\n      \"/vendor/javascripts/underscore.js\"\n      \"/vendor/javascripts/socket.io\"\n      \"/vendor/javascripts/tower.js\"\n    ]\n    \n    lib: [\n      \"/lib/grid.js\"\n      \"/lib/profiler.js\"\n    ]\n    \n    application: [\n      \"/app/models/post.js\"\n      \"/app/models/comment.js\"\n    ]\n    \n  stylesheets:\n    vendor: [\n      \"/vendor/stylesheets/reset.css\"\n    ]\n    application: [\n      \"/app/assets/stylesheets/application.css\"\n      \"/app/assets/stylesheets/theme.css\"\n    ]\n```\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n## Examples\n\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n## Unsolved Complexities\n\n- Handling transactions from the client. How would you save the data for credit/account (subtract one record, add to another) so if one fails both revert back (if you try to keep it simplified and only POST individual records at a time)? You can do embedded models on MongoDB, and transactions on MySQL perhaps. Then if `acceptsNestedAttributesFor` is specified it will send nested data in JSON POST rather than separate. Obviously it's better to not do this on the server, but we should see if it's possible to do otherwise, and if not, publicize why.\n\n## Decisions (need to finalize)\n\n- for uniqueness validation, if it fails on the client, should it try fetching the record from the server? (and loading the record into the client memory store). Reasons for include having to do less work as a coder (lazy loads data). Reasons against include making HTTP requests to the server without necessarily expecting to - or you may not want it to fetch. Perhaps you can specify an option (`lazy: true`) or something, and on the client if true it will make the request (or `autofetch: true`)\n- For non-transactional (yet still complex) associations, such as `group hasMany users through memberships`, you can save one record at a time, so the client should be instant. But if the first record created fails (say you do `group.members.create()`, which creates a user, then a membership tying the two together), what should the client tell the user? Some suggest a global notification (perhaps an alert bar) saying a more generic message such as \"please refresh the page, some data is out of sync\". But if the data is very important, ideally the code would know how to take the user (who might click this notification) to a form to try saving the `hasMany through` association again. If it continues to fail, it's probably either a bug in the code, or we should be able to know if the server is having issues (like it's crashed or power went out) - then if it's a bug we can have them notify us (some button perhaps) or if it's a real server problem we prepared for we can notify something like \"sorry, having server issues, try again later\". Other that that, it's up to you to build the validations properly so the data is saved\n\n## Todo\n\n- use require in the browser to lazy load scripts\n- gruntjs\n- term-css\n- https://github.com/kuno/GeoIP\n- global timestamps/userstamps config boolean, to DRY model `@timestamps()` if desired\n- make tower into subpackages: (model/client, model/server, model/shared, controller/client, etc...)\n- http://jsperf.com/angular-vs-knockout-vs-ember/2\n\n## New Stuff (api is todo, can access now through Tower.router)\n\n``` coffeescript\n@resources 'posts'\n@namespace 'admin', ->\n  @resources 'posts'\n```\n\n``` coffeescript\nTower.urlFor(App.Post)\nTower.urlFor('root.posts.index')\n```\n\n``` coffeescript\n# GET\nApp.indexPosts(title: 'A') # App.action, Tower.action, which one?\nApp.showPost(id: 1)\nApp.newPost()\nApp.editPost(id: 1)\n# Non-GET\nApp.createPost()\nApp.updatePost(id: 1)\nApp.destroyPost(id: 1)\n```\n\n``` html\n{{#each post in App.postsController.all}}\n<a {{action editPost post href=true}}>Edit</a>\n{{/each}}\n```\n\n``` coffeescript\n# @todo\nApp.indexAdminPosts() # /admin/posts\nApp.indexPostComments(postId: 1) # /posts/1/comments\n```\n\n## Changelog\n\n- `brew install tree`, then you can type command `tree` to see project structure (https://github.com/cowboy/grunt-node-example)\n- todo: need to test installing different versions of node with https://github.com/creationix/nvm\n- https://gist.github.com/1398757\n\n## Contributing to Tower\n\n### Running Tests\n\nRun server tests:\n\n```\nmake test\n```\n\nTo run client tests, first start the test server on port `3210`, and then run phantomjs:\n\n```\nnode test/example -p 3210\n```","_id":"tower@0.4.2-pre","dist":{"shasum":"a02ca8e5a8a2a48477cd2259ab237b4e2424ced8","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-pre.tgz","integrity":"sha512-MpC6X6zSKX6T/dLTFUPtJEbIO5V4QmtwtX4Ib2aMijRLwelY9+rjQsLQCBpEJMjGF18m6cY04t4d0Lwc6JQRFA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAgV2UVq/6q0yGM9ehxgNddWEmNKl080pyx1drB1t6buAiEAy9elfHegUvMu7OgJ4d9kyAChqQRgzqgPsU8gQi3RVcg="}]}},"0.4.2-pree":{"name":"tower","version":"0.4.2-pree","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","underscore.logger":">= 0.3.1","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","mint":">= 0.3.4","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"2.x","URIjs":">= 1.4.2","moment":">= 1.5.1","node-uuid":">= 1.3.0","geolib":">= 0.0.1","superagent":">= 0.4.0","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","ember-metal-node":">= 0.9.7","ember-runtime-node":">= 0.9.7","ember-states-node":">= 0.9.7","coffee-script":">= 1.3.3","wrench":">= 1.3.8","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0"},"devDependencies":{"findit":">= 0.1.1"},"testDependencies":{"stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 0.9.9-8","coffee-script":">= 1.3.3","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.8.7","socket.io-client":">= 0.9.5","hook.io":"~0.8.10","fibers":"~0.6.8"},"globalDependencies":{"ejs":">= 0.6.1"},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"codo","postinstall":"$(./bin/dependencies)"},"readme":"# Tower.js <img src=\"http://i.imgur.com/e3VLW.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower-docs\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If your up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Contributor Note\n\nAll of the base ideas are now pretty much in the Tower codebase, now it's just a matter of fleshing out the edge cases and a few implementations. Here's what's new:\n\n- Background jobs in Redis. The `Model.enqueue` and `Model#enqueue` methods are convention for off-loading expensive tasks to the background. You then run `cake work` and it will start the [kue](https://github.com/LearnBoost/kue) background worker to process items in the different redis queues. That process is running in a totally separate environment, but they can communicate b/c of redis' nice pub/sub api. This still needs to be fleshed out and tested a bit more but the basics are there.\n- Attachments. File uploading is working, as well as image resizing with imagemagick. I've started working on post-processing using background redis jobs as well. Tower should have a standard set of attachment \"processors\" to make uploading/processing attachments dead-simple (it's still pretty hard in Rails). This includes from any format to standard formats (video/audio/docs/images/etc.), video/audio/image processing/compression, text extraction and resizing, and document processing (pdf text extraction, MS Word to text, etc.). It's all pretty straight forward, just need to wrap command-line tools. See http://documentcloud.github.com/docsplit/.\n- Authentication. I don't think I've merged the authentication code yet, but an older version is here: https://github.com/viatropos/tower-authentication-example. The whole logging in with email/facebook/etc. should be completely solved. Right now mongodb session support is working locally, I will merge it when I finish with some other stuff.\n- Subdomains. Subdomains should be first-class citizens. We need to thoroughly test them in production. JSONP support exists (to do `GET` requests across domains), need to test that out. Need to get a better/leaner URL parser, but what's in there now works. Need to test authentication/sessions/cookies across subdomains.\n- Authorization. I've started on the authorization system (inspired from [cancan](https://github.com/ryanb/cancan/)). It works and is pretty awesome :). Just need to add some controller hooks to make it plug-and-chug.\n- Mass-assignment protection. I've implemented the basics of \"mass assignment protection\" (see the [Rails Security Guide](http://guides.rubyonrails.org/security.html#mass-assignment)), need to test it out a bit more. Also need to handle input sanitization.\n- Embedded Documents. I've mapped out how this could be implemented but it's still on the todo list.\n- Associations (hasMany, hasManyThrough, belongsTo, hasOne). They all work well (tested manually on the client as well, pretty awesome seeing hasManyThrough relations save on the client). There's a good amount of work to be done on making sure `user.address == address.user`, that kind of reflection stuff (especially for binding on the view). Wrote down a lot of ideas on how to implement an \"identity map\", but we have to be careful about garbage collection if we're going to store references to the request/controller objects in some hidden \"thread\" (see some of the recent commits for notes - early/mid July). Also need to make the validations/callbacks more robust for `acceptsNestedAttributesFor`, but it's all working at a basic level.\n- The Cursor. The cursor is _super_ awesome :). There's a ton more ideas on how to make it even more awesome, but for now it does what it's supposed to. I'd like to simplify the notification system eventually (telling the client of model changes).\n- User stamping. This should be a fundamental part of the model layer (similar to time stamping). The base mixin has been started but isn't ready yet - it requires setting up the identity-map/thread idea so you can pass around the `currentUser` transparently between cursors/models in the context of a single request.\n- Versioning. Versioning is a tricky concept to implement, and it is not required for all apps. But it is generic enough and useful enough that it is going to be included in Tower (eventually as a separate sub-package). It allows you to keep a history of model changes (and alongside userstamping, who made those changes). I have started this as well.\n- Soft deleting models. Sometimes you want to allow users to \"delete\" their data, but you don't _really_ want it deleted from the database. To do this you just add a `deletedAt` field to your model, and then make it so all queries by default ignore models without `deletedAt == null`. You want this kind of stuff to do things like \"restore your deleted account\", or just know what's happened historically in your app (as a startup for example).\n- Ember Views. This is the next big thing to do, but it's really independent of Tower. Tower can create some helpers like form builders and whatnot, but that might take a long time - particularly b/c there's going to be a lot of work put in to make sure performance is top-notch with all those views.\n- Client Routes. The base code for mapping routes.coffee into the Ember routing system is there, but the Ember API is changing weekly almost so I haven't gotten back to it. It should only take a few hours to wire up.\n\nIf you're excited to work on one of these things let me know and I'll point you to where things are and all that. Once all of this stuff is reasonably complete (mid August hopefully), this will merge into master. From there it's going to be \"robustifying\" everything, and hardcore performance tuning.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nIf you would like to mess around with the tower source code, clone it and start the grunt watcher to compile all of the coffeescripts:\n\n```\nmake watch\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\nFor developing, you may also want to link tower and tower-tasks globally so you can reuse it between multiple projects:\n\n```\ncd <tower repo>\nnpm link\ncd lib/tower-tasks\nnpm link\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Structure\n\nHere's how you might organize a blog:\n\n```\n.\n|-- app\n|   |-- client\n|   |   |-- stylesheets\n|   |-- controllers\n|   |   |-- admin\n|   |   |   |-- postsController.coffee\n|   |   |   `-- usersController.coffee\n|   |   |-- commentsController.coffee\n|   |   |-- postsController.coffee\n|   |   |-- sessionsController.coffee\n|   |   `-- usersController.coffee\n|   |-- models\n|   |   |-- comment.coffee\n|   |   |-- post.coffee\n|   |   `-- user.coffee\n|   |-- views\n|   |   |-- admin\n|   |   |   `-- posts\n|   |   |       |-- _form.coffee\n|   |   |       |-- edit.coffee\n|   |   |       |-- index.coffee\n|   |   |       |-- new.coffee\n|   |   |       |-- show.coffee\n|   |   |-- layouts\n|   |   |   `-- application.coffee\n|   |   |-- shared\n|   |   `-- posts\n|   |       |-- index.coffee\n|   |       `-- show.coffee\n|   `-- helpers\n|       |-- admin\n|       |   |-- postsHelper.coffee\n|       |   `-- usersHelper.coffee\n|       `-- postsHelper.coffee\n`-- config\n|    |-- application.coffee\n|    |-- assets.coffee\n|    |-- databases.coffee\n|    |-- environments\n|       |-- development.coffee\n|       |-- production.coffee\n|       `-- test.coffee\n|    |-- locale\n|       `-- en.coffee\n|    |-- routes.coffee\n`-- test\n|    |-- helper.coffee\n|    |-- models\n|    |   |-- postTest.coffee\n|    |   |-- userTest.coffee\n|    `-- acceptance\n|        |-- login.coffee\n|        |-- signup.coffee\n|        `-- posts.coffee\n```\n\n## Application\n\n``` coffeescript\n# config/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n``` coffeescript\n# app/models/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n``` coffeescript\n# app/models/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n``` coffeescript\n# app/models/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Views\n\nViews adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\n## Controllers\n\n``` coffeescript\n# app/controllers/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render \"index\", locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render \"new\"\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render \"posts/edit\"\n      @success.json => @render text: \"success!\"\n      @failure.html => @render text: \"Error\", status: 404\n      @failure.json => @render text: \"Error\", status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render \"show\"\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render \"edit\"\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: \"show\"\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: \"index\"\n```\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# config/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: \"app-development\"\n      port: 27017\n      host: \"127.0.0.1\"\n    test:\n      name: \"app-test\"\n      port: 27017\n      host: \"127.0.0.1\"\n    staging:\n      name: \"app-staging\"\n      port: 27017\n      host: \"127.0.0.1\"\n    production:\n      name: \"app-production\"\n      port: 27017\n      host: \"127.0.0.1\"\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: \"me@gmail.com\"\n```\n\n## Internationalization\n\n``` coffeescript\n# config/locales/en.coffee\nmodule.exports =\n  hello: \"world\"\n  forms:\n    titles:\n      signup: \"Signup\"\n  pages:\n    titles:\n      home: \"Welcome to %{site}\"\n  posts:\n    comments:\n      none: \"No comments\"\n      one: \"1 comment\"\n      other: \"%{count} comments\"\n  messages:\n    past:\n      none: \"You never had any messages\"\n      one: \"You had 1 message\"\n      other: \"You had %{count} messages\"\n    present:\n      one: \"You have 1 message\"\n    future:\n      one: \"You might have 1 message\"\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# config/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      \"/vendor/javascripts/jquery.js\"\n      \"/vendor/javascripts/underscore.js\"\n      \"/vendor/javascripts/socket.io\"\n      \"/vendor/javascripts/tower.js\"\n    ]\n    \n    lib: [\n      \"/lib/grid.js\"\n      \"/lib/profiler.js\"\n    ]\n    \n    application: [\n      \"/app/models/post.js\"\n      \"/app/models/comment.js\"\n    ]\n    \n  stylesheets:\n    vendor: [\n      \"/vendor/stylesheets/reset.css\"\n    ]\n    application: [\n      \"/app/assets/stylesheets/application.css\"\n      \"/app/assets/stylesheets/theme.css\"\n    ]\n```\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n## Examples\n\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n## Unsolved Complexities\n\n- Handling transactions from the client. How would you save the data for credit/account (subtract one record, add to another) so if one fails both revert back (if you try to keep it simplified and only POST individual records at a time)? You can do embedded models on MongoDB, and transactions on MySQL perhaps. Then if `acceptsNestedAttributesFor` is specified it will send nested data in JSON POST rather than separate. Obviously it's better to not do this on the server, but we should see if it's possible to do otherwise, and if not, publicize why.\n\n## Decisions (need to finalize)\n\n- for uniqueness validation, if it fails on the client, should it try fetching the record from the server? (and loading the record into the client memory store). Reasons for include having to do less work as a coder (lazy loads data). Reasons against include making HTTP requests to the server without necessarily expecting to - or you may not want it to fetch. Perhaps you can specify an option (`lazy: true`) or something, and on the client if true it will make the request (or `autofetch: true`)\n- For non-transactional (yet still complex) associations, such as `group hasMany users through memberships`, you can save one record at a time, so the client should be instant. But if the first record created fails (say you do `group.members.create()`, which creates a user, then a membership tying the two together), what should the client tell the user? Some suggest a global notification (perhaps an alert bar) saying a more generic message such as \"please refresh the page, some data is out of sync\". But if the data is very important, ideally the code would know how to take the user (who might click this notification) to a form to try saving the `hasMany through` association again. If it continues to fail, it's probably either a bug in the code, or we should be able to know if the server is having issues (like it's crashed or power went out) - then if it's a bug we can have them notify us (some button perhaps) or if it's a real server problem we prepared for we can notify something like \"sorry, having server issues, try again later\". Other that that, it's up to you to build the validations properly so the data is saved\n\n## Todo\n\n- use require in the browser to lazy load scripts\n- gruntjs\n- term-css\n- https://github.com/kuno/GeoIP\n- global timestamps/userstamps config boolean, to DRY model `@timestamps()` if desired\n- make tower into subpackages: (model/client, model/server, model/shared, controller/client, etc...)\n- http://jsperf.com/angular-vs-knockout-vs-ember/2\n\n## New Stuff (api is todo, can access now through Tower.router)\n\n``` coffeescript\n@resources 'posts'\n@namespace 'admin', ->\n  @resources 'posts'\n```\n\n``` coffeescript\nTower.urlFor(App.Post)\nTower.urlFor('root.posts.index')\n```\n\n``` coffeescript\n# GET\nApp.indexPosts(title: 'A') # App.action, Tower.action, which one?\nApp.showPost(id: 1)\nApp.newPost()\nApp.editPost(id: 1)\n# Non-GET\nApp.createPost()\nApp.updatePost(id: 1)\nApp.destroyPost(id: 1)\n```\n\n``` html\n{{#each post in App.postsController.all}}\n<a {{action editPost post href=true}}>Edit</a>\n{{/each}}\n```\n\n``` coffeescript\n# @todo\nApp.indexAdminPosts() # /admin/posts\nApp.indexPostComments(postId: 1) # /posts/1/comments\n```\n\n## Changelog\n\n- `brew install tree`, then you can type command `tree` to see project structure (https://github.com/cowboy/grunt-node-example)\n- todo: need to test installing different versions of node with https://github.com/creationix/nvm\n- https://gist.github.com/1398757\n\n## Contributing to Tower\n\n### Running Tests\n\nRun server tests:\n\n```\nmake test\n```\n\nTo run client tests, first start the test server on port `3210`, and then run phantomjs:\n\n```\nnode test/example -p 3210\n```","_id":"tower@0.4.2-pree","dist":{"shasum":"6a7303380a83db67a4326842afa6971096306257","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-pree.tgz","integrity":"sha512-bghkac2fSJQ0jgXNAzyUPtnG4nlCRGz6wunZF0ZfioMMvWAWpwcYB6WLOjQs5T5RLiyY6yf1a28a9t8PZHISxg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC3pTMdWLAPGGNVxEQVCKMjmqCYF81QIqkUtQ/I/VwdQwIhAIPfn6/zoSM8/eL/cMmJ/SuGlRBgBvCitNvFm5IOFPDo"}]}},"0.4.2":{"name":"tower","version":"0.4.2","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","underscore.logger":">= 0.3.1","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","mint":">= 0.3.4","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"2.x","URIjs":">= 1.4.2","moment":">= 1.5.1","node-uuid":">= 1.3.0","geolib":">= 0.0.1","superagent":">= 0.4.0","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","ember-metal-node":">= 0.9.7","ember-runtime-node":">= 0.9.7","ember-states-node":">= 0.9.7","coffee-script":">= 1.3.3","wrench":">= 1.3.8","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0"},"devDependencies":{"findit":">= 0.1.1"},"testDependencies":{"stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 0.9.9-8","coffee-script":">= 1.3.3","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.8.7","socket.io-client":">= 0.9.5","hook.io":"~0.8.10","fibers":"~0.6.8"},"globalDependencies":{"ejs":">= 0.6.1"},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"codo","postinstall":"$(./bin/dependencies)"},"readme":"# Tower.js <img src=\"http://i.imgur.com/e3VLW.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower-docs\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If your up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Contributor Note\n\nAll of the base ideas are now pretty much in the Tower codebase, now it's just a matter of fleshing out the edge cases and a few implementations. Here's what's new:\n\n- Background jobs in Redis. The `Model.enqueue` and `Model#enqueue` methods are convention for off-loading expensive tasks to the background. You then run `cake work` and it will start the [kue](https://github.com/LearnBoost/kue) background worker to process items in the different redis queues. That process is running in a totally separate environment, but they can communicate b/c of redis' nice pub/sub api. This still needs to be fleshed out and tested a bit more but the basics are there.\n- Attachments. File uploading is working, as well as image resizing with imagemagick. I've started working on post-processing using background redis jobs as well. Tower should have a standard set of attachment \"processors\" to make uploading/processing attachments dead-simple (it's still pretty hard in Rails). This includes from any format to standard formats (video/audio/docs/images/etc.), video/audio/image processing/compression, text extraction and resizing, and document processing (pdf text extraction, MS Word to text, etc.). It's all pretty straight forward, just need to wrap command-line tools. See http://documentcloud.github.com/docsplit/.\n- Authentication. I don't think I've merged the authentication code yet, but an older version is here: https://github.com/viatropos/tower-authentication-example. The whole logging in with email/facebook/etc. should be completely solved. Right now mongodb session support is working locally, I will merge it when I finish with some other stuff.\n- Subdomains. Subdomains should be first-class citizens. We need to thoroughly test them in production. JSONP support exists (to do `GET` requests across domains), need to test that out. Need to get a better/leaner URL parser, but what's in there now works. Need to test authentication/sessions/cookies across subdomains.\n- Authorization. I've started on the authorization system (inspired from [cancan](https://github.com/ryanb/cancan/)). It works and is pretty awesome :). Just need to add some controller hooks to make it plug-and-chug.\n- Mass-assignment protection. I've implemented the basics of \"mass assignment protection\" (see the [Rails Security Guide](http://guides.rubyonrails.org/security.html#mass-assignment)), need to test it out a bit more. Also need to handle input sanitization.\n- Embedded Documents. I've mapped out how this could be implemented but it's still on the todo list.\n- Associations (hasMany, hasManyThrough, belongsTo, hasOne). They all work well (tested manually on the client as well, pretty awesome seeing hasManyThrough relations save on the client). There's a good amount of work to be done on making sure `user.address == address.user`, that kind of reflection stuff (especially for binding on the view). Wrote down a lot of ideas on how to implement an \"identity map\", but we have to be careful about garbage collection if we're going to store references to the request/controller objects in some hidden \"thread\" (see some of the recent commits for notes - early/mid July). Also need to make the validations/callbacks more robust for `acceptsNestedAttributesFor`, but it's all working at a basic level.\n- The Cursor. The cursor is _super_ awesome :). There's a ton more ideas on how to make it even more awesome, but for now it does what it's supposed to. I'd like to simplify the notification system eventually (telling the client of model changes).\n- User stamping. This should be a fundamental part of the model layer (similar to time stamping). The base mixin has been started but isn't ready yet - it requires setting up the identity-map/thread idea so you can pass around the `currentUser` transparently between cursors/models in the context of a single request.\n- Versioning. Versioning is a tricky concept to implement, and it is not required for all apps. But it is generic enough and useful enough that it is going to be included in Tower (eventually as a separate sub-package). It allows you to keep a history of model changes (and alongside userstamping, who made those changes). I have started this as well.\n- Soft deleting models. Sometimes you want to allow users to \"delete\" their data, but you don't _really_ want it deleted from the database. To do this you just add a `deletedAt` field to your model, and then make it so all queries by default ignore models without `deletedAt == null`. You want this kind of stuff to do things like \"restore your deleted account\", or just know what's happened historically in your app (as a startup for example).\n- Ember Views. This is the next big thing to do, but it's really independent of Tower. Tower can create some helpers like form builders and whatnot, but that might take a long time - particularly b/c there's going to be a lot of work put in to make sure performance is top-notch with all those views.\n- Client Routes. The base code for mapping routes.coffee into the Ember routing system is there, but the Ember API is changing weekly almost so I haven't gotten back to it. It should only take a few hours to wire up.\n\nIf you're excited to work on one of these things let me know and I'll point you to where things are and all that. Once all of this stuff is reasonably complete (mid August hopefully), this will merge into master. From there it's going to be \"robustifying\" everything, and hardcore performance tuning.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nIf you would like to mess around with the tower source code, clone it and start the grunt watcher to compile all of the coffeescripts:\n\n```\nmake watch\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\nFor developing, you may also want to link tower and tower-tasks globally so you can reuse it between multiple projects:\n\n```\ncd <tower repo>\nnpm link\ncd lib/tower-tasks\nnpm link\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Structure\n\nHere's how you might organize a blog:\n\n```\n.\n|-- app\n|   |-- client\n|   |   |-- stylesheets\n|   |-- controllers\n|   |   |-- admin\n|   |   |   |-- postsController.coffee\n|   |   |   `-- usersController.coffee\n|   |   |-- commentsController.coffee\n|   |   |-- postsController.coffee\n|   |   |-- sessionsController.coffee\n|   |   `-- usersController.coffee\n|   |-- models\n|   |   |-- comment.coffee\n|   |   |-- post.coffee\n|   |   `-- user.coffee\n|   |-- views\n|   |   |-- admin\n|   |   |   `-- posts\n|   |   |       |-- _form.coffee\n|   |   |       |-- edit.coffee\n|   |   |       |-- index.coffee\n|   |   |       |-- new.coffee\n|   |   |       |-- show.coffee\n|   |   |-- layouts\n|   |   |   `-- application.coffee\n|   |   |-- shared\n|   |   `-- posts\n|   |       |-- index.coffee\n|   |       `-- show.coffee\n|   `-- helpers\n|       |-- admin\n|       |   |-- postsHelper.coffee\n|       |   `-- usersHelper.coffee\n|       `-- postsHelper.coffee\n`-- config\n|    |-- application.coffee\n|    |-- assets.coffee\n|    |-- databases.coffee\n|    |-- environments\n|       |-- development.coffee\n|       |-- production.coffee\n|       `-- test.coffee\n|    |-- locale\n|       `-- en.coffee\n|    |-- routes.coffee\n`-- test\n|    |-- helper.coffee\n|    |-- models\n|    |   |-- postTest.coffee\n|    |   |-- userTest.coffee\n|    `-- acceptance\n|        |-- login.coffee\n|        |-- signup.coffee\n|        `-- posts.coffee\n```\n\n## Application\n\n``` coffeescript\n# config/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n``` coffeescript\n# app/models/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n``` coffeescript\n# app/models/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n``` coffeescript\n# app/models/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Views\n\nViews adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\n## Controllers\n\n``` coffeescript\n# app/controllers/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render \"index\", locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render \"new\"\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render \"posts/edit\"\n      @success.json => @render text: \"success!\"\n      @failure.html => @render text: \"Error\", status: 404\n      @failure.json => @render text: \"Error\", status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render \"show\"\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render \"edit\"\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: \"show\"\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: \"index\"\n```\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# config/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: \"app-development\"\n      port: 27017\n      host: \"127.0.0.1\"\n    test:\n      name: \"app-test\"\n      port: 27017\n      host: \"127.0.0.1\"\n    staging:\n      name: \"app-staging\"\n      port: 27017\n      host: \"127.0.0.1\"\n    production:\n      name: \"app-production\"\n      port: 27017\n      host: \"127.0.0.1\"\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: \"me@gmail.com\"\n```\n\n## Internationalization\n\n``` coffeescript\n# config/locales/en.coffee\nmodule.exports =\n  hello: \"world\"\n  forms:\n    titles:\n      signup: \"Signup\"\n  pages:\n    titles:\n      home: \"Welcome to %{site}\"\n  posts:\n    comments:\n      none: \"No comments\"\n      one: \"1 comment\"\n      other: \"%{count} comments\"\n  messages:\n    past:\n      none: \"You never had any messages\"\n      one: \"You had 1 message\"\n      other: \"You had %{count} messages\"\n    present:\n      one: \"You have 1 message\"\n    future:\n      one: \"You might have 1 message\"\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# config/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      \"/vendor/javascripts/jquery.js\"\n      \"/vendor/javascripts/underscore.js\"\n      \"/vendor/javascripts/socket.io\"\n      \"/vendor/javascripts/tower.js\"\n    ]\n    \n    lib: [\n      \"/lib/grid.js\"\n      \"/lib/profiler.js\"\n    ]\n    \n    application: [\n      \"/app/models/post.js\"\n      \"/app/models/comment.js\"\n    ]\n    \n  stylesheets:\n    vendor: [\n      \"/vendor/stylesheets/reset.css\"\n    ]\n    application: [\n      \"/app/assets/stylesheets/application.css\"\n      \"/app/assets/stylesheets/theme.css\"\n    ]\n```\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n## Examples\n\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n## Unsolved Complexities\n\n- Handling transactions from the client. How would you save the data for credit/account (subtract one record, add to another) so if one fails both revert back (if you try to keep it simplified and only POST individual records at a time)? You can do embedded models on MongoDB, and transactions on MySQL perhaps. Then if `acceptsNestedAttributesFor` is specified it will send nested data in JSON POST rather than separate. Obviously it's better to not do this on the server, but we should see if it's possible to do otherwise, and if not, publicize why.\n\n## Decisions (need to finalize)\n\n- for uniqueness validation, if it fails on the client, should it try fetching the record from the server? (and loading the record into the client memory store). Reasons for include having to do less work as a coder (lazy loads data). Reasons against include making HTTP requests to the server without necessarily expecting to - or you may not want it to fetch. Perhaps you can specify an option (`lazy: true`) or something, and on the client if true it will make the request (or `autofetch: true`)\n- For non-transactional (yet still complex) associations, such as `group hasMany users through memberships`, you can save one record at a time, so the client should be instant. But if the first record created fails (say you do `group.members.create()`, which creates a user, then a membership tying the two together), what should the client tell the user? Some suggest a global notification (perhaps an alert bar) saying a more generic message such as \"please refresh the page, some data is out of sync\". But if the data is very important, ideally the code would know how to take the user (who might click this notification) to a form to try saving the `hasMany through` association again. If it continues to fail, it's probably either a bug in the code, or we should be able to know if the server is having issues (like it's crashed or power went out) - then if it's a bug we can have them notify us (some button perhaps) or if it's a real server problem we prepared for we can notify something like \"sorry, having server issues, try again later\". Other that that, it's up to you to build the validations properly so the data is saved\n\n## Todo\n\n- use require in the browser to lazy load scripts\n- gruntjs\n- term-css\n- https://github.com/kuno/GeoIP\n- global timestamps/userstamps config boolean, to DRY model `@timestamps()` if desired\n- make tower into subpackages: (model/client, model/server, model/shared, controller/client, etc...)\n- http://jsperf.com/angular-vs-knockout-vs-ember/2\n\n## New Stuff (api is todo, can access now through Tower.router)\n\n``` coffeescript\n@resources 'posts'\n@namespace 'admin', ->\n  @resources 'posts'\n```\n\n``` coffeescript\nTower.urlFor(App.Post)\nTower.urlFor('root.posts.index')\n```\n\n``` coffeescript\n# GET\nApp.indexPosts(title: 'A') # App.action, Tower.action, which one?\nApp.showPost(id: 1)\nApp.newPost()\nApp.editPost(id: 1)\n# Non-GET\nApp.createPost()\nApp.updatePost(id: 1)\nApp.destroyPost(id: 1)\n```\n\n``` html\n{{#each post in App.postsController.all}}\n<a {{action editPost post href=true}}>Edit</a>\n{{/each}}\n```\n\n``` coffeescript\n# @todo\nApp.indexAdminPosts() # /admin/posts\nApp.indexPostComments(postId: 1) # /posts/1/comments\n```\n\n## Changelog\n\n- `brew install tree`, then you can type command `tree` to see project structure (https://github.com/cowboy/grunt-node-example)\n- todo: need to test installing different versions of node with https://github.com/creationix/nvm\n- https://gist.github.com/1398757\n\n## Contributing to Tower\n\n### Running Tests\n\nRun server tests:\n\n```\nmake test\n```\n\nTo run client tests, first start the test server on port `3210`, and then run phantomjs:\n\n```\nnode test/example -p 3210\n```","_id":"tower@0.4.2","dist":{"shasum":"3ff1c7b4b499e80a2f357ad614f170bb97998c9c","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2.tgz","integrity":"sha512-G4oC/TQb28arRtlG17pKoIjR/+lHW+IbyBgXo7qRic4pL1aO88hPNvKsoUzUbpHPQpBWLILt5XSvK2yu+TjlHw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCH10W+EsjSDwcKeMbcqTcP1BPst+a43S8hYeQ5s3qo/AIgR28eah+dP+A3rfBdp1r9czXsKjBT7a8g2Bqh8T7cHE8="}]}},"0.4.2-1":{"name":"tower","version":"0.4.2-1","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","underscore.logger":">= 0.3.1","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","mint":">= 0.3.4","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"2.x","URIjs":">= 1.4.2","moment":">= 1.5.1","node-uuid":">= 1.3.0","geolib":">= 0.0.1","superagent":">= 0.4.0","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","ember-metal-node":">= 0.9.7","ember-runtime-node":">= 0.9.7","ember-states-node":">= 0.9.7","coffee-script":">= 1.3.3","wrench":">= 1.3.8","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0"},"devDependencies":{"findit":">= 0.1.1","ejs":">= 0.6.1"},"testDependencies":{"stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 0.9.9-8","coffee-script":">= 1.3.3","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.8.7","socket.io-client":">= 0.9.5","hook.io":"~0.8.10","fibers":"~0.6.8"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"codo","postinstall":"$(./bin/dependencies)"},"readme":"# Tower.js <img src=\"http://i.imgur.com/e3VLW.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower-docs\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If your up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Contributor Note\n\nAll of the base ideas are now pretty much in the Tower codebase, now it's just a matter of fleshing out the edge cases and a few implementations. Here's what's new:\n\n- Background jobs in Redis. The `Model.enqueue` and `Model#enqueue` methods are convention for off-loading expensive tasks to the background. You then run `cake work` and it will start the [kue](https://github.com/LearnBoost/kue) background worker to process items in the different redis queues. That process is running in a totally separate environment, but they can communicate b/c of redis' nice pub/sub api. This still needs to be fleshed out and tested a bit more but the basics are there.\n- Attachments. File uploading is working, as well as image resizing with imagemagick. I've started working on post-processing using background redis jobs as well. Tower should have a standard set of attachment \"processors\" to make uploading/processing attachments dead-simple (it's still pretty hard in Rails). This includes from any format to standard formats (video/audio/docs/images/etc.), video/audio/image processing/compression, text extraction and resizing, and document processing (pdf text extraction, MS Word to text, etc.). It's all pretty straight forward, just need to wrap command-line tools. See http://documentcloud.github.com/docsplit/.\n- Authentication. I don't think I've merged the authentication code yet, but an older version is here: https://github.com/viatropos/tower-authentication-example. The whole logging in with email/facebook/etc. should be completely solved. Right now mongodb session support is working locally, I will merge it when I finish with some other stuff.\n- Subdomains. Subdomains should be first-class citizens. We need to thoroughly test them in production. JSONP support exists (to do `GET` requests across domains), need to test that out. Need to get a better/leaner URL parser, but what's in there now works. Need to test authentication/sessions/cookies across subdomains.\n- Authorization. I've started on the authorization system (inspired from [cancan](https://github.com/ryanb/cancan/)). It works and is pretty awesome :). Just need to add some controller hooks to make it plug-and-chug.\n- Mass-assignment protection. I've implemented the basics of \"mass assignment protection\" (see the [Rails Security Guide](http://guides.rubyonrails.org/security.html#mass-assignment)), need to test it out a bit more. Also need to handle input sanitization.\n- Embedded Documents. I've mapped out how this could be implemented but it's still on the todo list.\n- Associations (hasMany, hasManyThrough, belongsTo, hasOne). They all work well (tested manually on the client as well, pretty awesome seeing hasManyThrough relations save on the client). There's a good amount of work to be done on making sure `user.address == address.user`, that kind of reflection stuff (especially for binding on the view). Wrote down a lot of ideas on how to implement an \"identity map\", but we have to be careful about garbage collection if we're going to store references to the request/controller objects in some hidden \"thread\" (see some of the recent commits for notes - early/mid July). Also need to make the validations/callbacks more robust for `acceptsNestedAttributesFor`, but it's all working at a basic level.\n- The Cursor. The cursor is _super_ awesome :). There's a ton more ideas on how to make it even more awesome, but for now it does what it's supposed to. I'd like to simplify the notification system eventually (telling the client of model changes).\n- User stamping. This should be a fundamental part of the model layer (similar to time stamping). The base mixin has been started but isn't ready yet - it requires setting up the identity-map/thread idea so you can pass around the `currentUser` transparently between cursors/models in the context of a single request.\n- Versioning. Versioning is a tricky concept to implement, and it is not required for all apps. But it is generic enough and useful enough that it is going to be included in Tower (eventually as a separate sub-package). It allows you to keep a history of model changes (and alongside userstamping, who made those changes). I have started this as well.\n- Soft deleting models. Sometimes you want to allow users to \"delete\" their data, but you don't _really_ want it deleted from the database. To do this you just add a `deletedAt` field to your model, and then make it so all queries by default ignore models without `deletedAt == null`. You want this kind of stuff to do things like \"restore your deleted account\", or just know what's happened historically in your app (as a startup for example).\n- Ember Views. This is the next big thing to do, but it's really independent of Tower. Tower can create some helpers like form builders and whatnot, but that might take a long time - particularly b/c there's going to be a lot of work put in to make sure performance is top-notch with all those views.\n- Client Routes. The base code for mapping routes.coffee into the Ember routing system is there, but the Ember API is changing weekly almost so I haven't gotten back to it. It should only take a few hours to wire up.\n\nIf you're excited to work on one of these things let me know and I'll point you to where things are and all that. Once all of this stuff is reasonably complete (mid August hopefully), this will merge into master. From there it's going to be \"robustifying\" everything, and hardcore performance tuning.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nIf you would like to mess around with the tower source code, clone it and start the grunt watcher to compile all of the coffeescripts:\n\n```\nmake watch\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\nFor developing, you may also want to link tower and tower-tasks globally so you can reuse it between multiple projects:\n\n```\ncd <tower repo>\nnpm link\ncd lib/tower-tasks\nnpm link\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Structure\n\nHere's how you might organize a blog:\n\n```\n.\n|-- app\n|   |-- client\n|   |   |-- stylesheets\n|   |-- controllers\n|   |   |-- admin\n|   |   |   |-- postsController.coffee\n|   |   |   `-- usersController.coffee\n|   |   |-- commentsController.coffee\n|   |   |-- postsController.coffee\n|   |   |-- sessionsController.coffee\n|   |   `-- usersController.coffee\n|   |-- models\n|   |   |-- comment.coffee\n|   |   |-- post.coffee\n|   |   `-- user.coffee\n|   |-- views\n|   |   |-- admin\n|   |   |   `-- posts\n|   |   |       |-- _form.coffee\n|   |   |       |-- edit.coffee\n|   |   |       |-- index.coffee\n|   |   |       |-- new.coffee\n|   |   |       |-- show.coffee\n|   |   |-- layouts\n|   |   |   `-- application.coffee\n|   |   |-- shared\n|   |   `-- posts\n|   |       |-- index.coffee\n|   |       `-- show.coffee\n|   `-- helpers\n|       |-- admin\n|       |   |-- postsHelper.coffee\n|       |   `-- usersHelper.coffee\n|       `-- postsHelper.coffee\n`-- config\n|    |-- application.coffee\n|    |-- assets.coffee\n|    |-- databases.coffee\n|    |-- environments\n|       |-- development.coffee\n|       |-- production.coffee\n|       `-- test.coffee\n|    |-- locale\n|       `-- en.coffee\n|    |-- routes.coffee\n`-- test\n|    |-- helper.coffee\n|    |-- models\n|    |   |-- postTest.coffee\n|    |   |-- userTest.coffee\n|    `-- acceptance\n|        |-- login.coffee\n|        |-- signup.coffee\n|        `-- posts.coffee\n```\n\n## Application\n\n``` coffeescript\n# config/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n``` coffeescript\n# app/models/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n``` coffeescript\n# app/models/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n``` coffeescript\n# app/models/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Views\n\nViews adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\n## Controllers\n\n``` coffeescript\n# app/controllers/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render \"index\", locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render \"new\"\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render \"posts/edit\"\n      @success.json => @render text: \"success!\"\n      @failure.html => @render text: \"Error\", status: 404\n      @failure.json => @render text: \"Error\", status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render \"show\"\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render \"edit\"\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: \"show\"\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: \"index\"\n```\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# config/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: \"app-development\"\n      port: 27017\n      host: \"127.0.0.1\"\n    test:\n      name: \"app-test\"\n      port: 27017\n      host: \"127.0.0.1\"\n    staging:\n      name: \"app-staging\"\n      port: 27017\n      host: \"127.0.0.1\"\n    production:\n      name: \"app-production\"\n      port: 27017\n      host: \"127.0.0.1\"\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: \"me@gmail.com\"\n```\n\n## Internationalization\n\n``` coffeescript\n# config/locales/en.coffee\nmodule.exports =\n  hello: \"world\"\n  forms:\n    titles:\n      signup: \"Signup\"\n  pages:\n    titles:\n      home: \"Welcome to %{site}\"\n  posts:\n    comments:\n      none: \"No comments\"\n      one: \"1 comment\"\n      other: \"%{count} comments\"\n  messages:\n    past:\n      none: \"You never had any messages\"\n      one: \"You had 1 message\"\n      other: \"You had %{count} messages\"\n    present:\n      one: \"You have 1 message\"\n    future:\n      one: \"You might have 1 message\"\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# config/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      \"/vendor/javascripts/jquery.js\"\n      \"/vendor/javascripts/underscore.js\"\n      \"/vendor/javascripts/socket.io\"\n      \"/vendor/javascripts/tower.js\"\n    ]\n    \n    lib: [\n      \"/lib/grid.js\"\n      \"/lib/profiler.js\"\n    ]\n    \n    application: [\n      \"/app/models/post.js\"\n      \"/app/models/comment.js\"\n    ]\n    \n  stylesheets:\n    vendor: [\n      \"/vendor/stylesheets/reset.css\"\n    ]\n    application: [\n      \"/app/assets/stylesheets/application.css\"\n      \"/app/assets/stylesheets/theme.css\"\n    ]\n```\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n## Examples\n\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n## Unsolved Complexities\n\n- Handling transactions from the client. How would you save the data for credit/account (subtract one record, add to another) so if one fails both revert back (if you try to keep it simplified and only POST individual records at a time)? You can do embedded models on MongoDB, and transactions on MySQL perhaps. Then if `acceptsNestedAttributesFor` is specified it will send nested data in JSON POST rather than separate. Obviously it's better to not do this on the server, but we should see if it's possible to do otherwise, and if not, publicize why.\n\n## Decisions (need to finalize)\n\n- for uniqueness validation, if it fails on the client, should it try fetching the record from the server? (and loading the record into the client memory store). Reasons for include having to do less work as a coder (lazy loads data). Reasons against include making HTTP requests to the server without necessarily expecting to - or you may not want it to fetch. Perhaps you can specify an option (`lazy: true`) or something, and on the client if true it will make the request (or `autofetch: true`)\n- For non-transactional (yet still complex) associations, such as `group hasMany users through memberships`, you can save one record at a time, so the client should be instant. But if the first record created fails (say you do `group.members.create()`, which creates a user, then a membership tying the two together), what should the client tell the user? Some suggest a global notification (perhaps an alert bar) saying a more generic message such as \"please refresh the page, some data is out of sync\". But if the data is very important, ideally the code would know how to take the user (who might click this notification) to a form to try saving the `hasMany through` association again. If it continues to fail, it's probably either a bug in the code, or we should be able to know if the server is having issues (like it's crashed or power went out) - then if it's a bug we can have them notify us (some button perhaps) or if it's a real server problem we prepared for we can notify something like \"sorry, having server issues, try again later\". Other that that, it's up to you to build the validations properly so the data is saved\n\n## Todo\n\n- use require in the browser to lazy load scripts\n- gruntjs\n- term-css\n- https://github.com/kuno/GeoIP\n- global timestamps/userstamps config boolean, to DRY model `@timestamps()` if desired\n- make tower into subpackages: (model/client, model/server, model/shared, controller/client, etc...)\n- http://jsperf.com/angular-vs-knockout-vs-ember/2\n\n## New Stuff (api is todo, can access now through Tower.router)\n\n``` coffeescript\n@resources 'posts'\n@namespace 'admin', ->\n  @resources 'posts'\n```\n\n``` coffeescript\nTower.urlFor(App.Post)\nTower.urlFor('root.posts.index')\n```\n\n``` coffeescript\n# GET\nApp.indexPosts(title: 'A') # App.action, Tower.action, which one?\nApp.showPost(id: 1)\nApp.newPost()\nApp.editPost(id: 1)\n# Non-GET\nApp.createPost()\nApp.updatePost(id: 1)\nApp.destroyPost(id: 1)\n```\n\n``` html\n{{#each post in App.postsController.all}}\n<a {{action editPost post href=true}}>Edit</a>\n{{/each}}\n```\n\n``` coffeescript\n# @todo\nApp.indexAdminPosts() # /admin/posts\nApp.indexPostComments(postId: 1) # /posts/1/comments\n```\n\n## Changelog\n\n- `brew install tree`, then you can type command `tree` to see project structure (https://github.com/cowboy/grunt-node-example)\n- todo: need to test installing different versions of node with https://github.com/creationix/nvm\n- https://gist.github.com/1398757\n\n## Contributing to Tower\n\n### Running Tests\n\nRun server tests:\n\n```\nmake test\n```\n\nTo run client tests, first start the test server on port `3210`, and then run phantomjs:\n\n```\nnode test/example -p 3210\n```","_id":"tower@0.4.2-1","dist":{"shasum":"99259661000a372b3d0b174e0d03c985172b92b2","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-1.tgz","integrity":"sha512-peNc+xBG9e5JBEEsHE6GbWAe7ZZrGYWjEuO5l82Ct+Cx2JMcdmiLNzVZJJY5lJdqIY1UAXWNQ9FIKjWicpfPOw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGEFJdwyu42CB5au5UkHPE8KZOvjCaYFNX+DICcps1L+AiB2gtaolzjQkfb8utMca9ODRbXn/2/CzVPY/75BdeTAXg=="}]}},"0.4.2-2":{"name":"tower","version":"0.4.2-2","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","underscore.logger":">= 0.3.1","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","mint":">= 0.3.4","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"2.x","URIjs":">= 1.4.2","moment":">= 1.5.1","node-uuid":">= 1.3.0","geolib":">= 0.0.1","superagent":">= 0.4.0","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","coffee-script":">= 1.3.3","wrench":">= 1.3.8","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0"},"devDependencies":{"findit":">= 0.1.1","ejs":">= 0.6.1"},"testDependencies":{"stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 0.9.9-8","coffee-script":">= 1.3.3","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.8.7","socket.io-client":">= 0.9.5","fibers":"~0.6.8"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"codo","postinstall":"$(./bin/dependencies)"},"readme":"# Tower.js <img src=\"http://i.imgur.com/e3VLW.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower-docs\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If your up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Contributor Note\n\nAll of the base ideas are now pretty much in the Tower codebase, now it's just a matter of fleshing out the edge cases and a few implementations. Here's what's new:\n\n- Background jobs in Redis. The `Model.enqueue` and `Model#enqueue` methods are convention for off-loading expensive tasks to the background. You then run `cake work` and it will start the [kue](https://github.com/LearnBoost/kue) background worker to process items in the different redis queues. That process is running in a totally separate environment, but they can communicate b/c of redis' nice pub/sub api. This still needs to be fleshed out and tested a bit more but the basics are there.\n- Attachments. File uploading is working, as well as image resizing with imagemagick. I've started working on post-processing using background redis jobs as well. Tower should have a standard set of attachment \"processors\" to make uploading/processing attachments dead-simple (it's still pretty hard in Rails). This includes from any format to standard formats (video/audio/docs/images/etc.), video/audio/image processing/compression, text extraction and resizing, and document processing (pdf text extraction, MS Word to text, etc.). It's all pretty straight forward, just need to wrap command-line tools. See http://documentcloud.github.com/docsplit/.\n- Authentication. I don't think I've merged the authentication code yet, but an older version is here: https://github.com/viatropos/tower-authentication-example. The whole logging in with email/facebook/etc. should be completely solved. Right now mongodb session support is working locally, I will merge it when I finish with some other stuff.\n- Subdomains. Subdomains should be first-class citizens. We need to thoroughly test them in production. JSONP support exists (to do `GET` requests across domains), need to test that out. Need to get a better/leaner URL parser, but what's in there now works. Need to test authentication/sessions/cookies across subdomains.\n- Authorization. I've started on the authorization system (inspired from [cancan](https://github.com/ryanb/cancan/)). It works and is pretty awesome :). Just need to add some controller hooks to make it plug-and-chug.\n- Mass-assignment protection. I've implemented the basics of \"mass assignment protection\" (see the [Rails Security Guide](http://guides.rubyonrails.org/security.html#mass-assignment)), need to test it out a bit more. Also need to handle input sanitization.\n- Embedded Documents. I've mapped out how this could be implemented but it's still on the todo list.\n- Associations (hasMany, hasManyThrough, belongsTo, hasOne). They all work well (tested manually on the client as well, pretty awesome seeing hasManyThrough relations save on the client). There's a good amount of work to be done on making sure `user.address == address.user`, that kind of reflection stuff (especially for binding on the view). Wrote down a lot of ideas on how to implement an \"identity map\", but we have to be careful about garbage collection if we're going to store references to the request/controller objects in some hidden \"thread\" (see some of the recent commits for notes - early/mid July). Also need to make the validations/callbacks more robust for `acceptsNestedAttributesFor`, but it's all working at a basic level.\n- The Cursor. The cursor is _super_ awesome :). There's a ton more ideas on how to make it even more awesome, but for now it does what it's supposed to. I'd like to simplify the notification system eventually (telling the client of model changes).\n- User stamping. This should be a fundamental part of the model layer (similar to time stamping). The base mixin has been started but isn't ready yet - it requires setting up the identity-map/thread idea so you can pass around the `currentUser` transparently between cursors/models in the context of a single request.\n- Versioning. Versioning is a tricky concept to implement, and it is not required for all apps. But it is generic enough and useful enough that it is going to be included in Tower (eventually as a separate sub-package). It allows you to keep a history of model changes (and alongside userstamping, who made those changes). I have started this as well.\n- Soft deleting models. Sometimes you want to allow users to \"delete\" their data, but you don't _really_ want it deleted from the database. To do this you just add a `deletedAt` field to your model, and then make it so all queries by default ignore models without `deletedAt == null`. You want this kind of stuff to do things like \"restore your deleted account\", or just know what's happened historically in your app (as a startup for example).\n- Ember Views. This is the next big thing to do, but it's really independent of Tower. Tower can create some helpers like form builders and whatnot, but that might take a long time - particularly b/c there's going to be a lot of work put in to make sure performance is top-notch with all those views.\n- Client Routes. The base code for mapping routes.coffee into the Ember routing system is there, but the Ember API is changing weekly almost so I haven't gotten back to it. It should only take a few hours to wire up.\n\nIf you're excited to work on one of these things let me know and I'll point you to where things are and all that. Once all of this stuff is reasonably complete (mid August hopefully), this will merge into master. From there it's going to be \"robustifying\" everything, and hardcore performance tuning.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nIf you would like to mess around with the tower source code, clone it and start the grunt watcher to compile all of the coffeescripts:\n\n```\nmake watch\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Views\n\nViews adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n## Examples\n\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n## Unsolved Complexities\n\n- Handling transactions from the client. How would you save the data for credit/account (subtract one record, add to another) so if one fails both revert back (if you try to keep it simplified and only POST individual records at a time)? You can do embedded models on MongoDB, and transactions on MySQL perhaps. Then if `acceptsNestedAttributesFor` is specified it will send nested data in JSON POST rather than separate. Obviously it's better to not do this on the server, but we should see if it's possible to do otherwise, and if not, publicize why.\n\n## Decisions (need to finalize)\n\n- for uniqueness validation, if it fails on the client, should it try fetching the record from the server? (and loading the record into the client memory store). Reasons for include having to do less work as a coder (lazy loads data). Reasons against include making HTTP requests to the server without necessarily expecting to - or you may not want it to fetch. Perhaps you can specify an option (`lazy: true`) or something, and on the client if true it will make the request (or `autofetch: true`)\n- For non-transactional (yet still complex) associations, such as `group hasMany users through memberships`, you can save one record at a time, so the client should be instant. But if the first record created fails (say you do `group.members.create()`, which creates a user, then a membership tying the two together), what should the client tell the user? Some suggest a global notification (perhaps an alert bar) saying a more generic message such as \"please refresh the page, some data is out of sync\". But if the data is very important, ideally the code would know how to take the user (who might click this notification) to a form to try saving the `hasMany through` association again. If it continues to fail, it's probably either a bug in the code, or we should be able to know if the server is having issues (like it's crashed or power went out) - then if it's a bug we can have them notify us (some button perhaps) or if it's a real server problem we prepared for we can notify something like \"sorry, having server issues, try again later\". Other that that, it's up to you to build the validations properly so the data is saved\n\n## Todo\n\n- use require in the browser to lazy load scripts\n- gruntjs\n- term-css\n- https://github.com/kuno/GeoIP\n- global timestamps/userstamps config boolean, to DRY model `@timestamps()` if desired\n- make tower into subpackages: (model/client, model/server, model/shared, controller/client, etc...)\n- http://jsperf.com/angular-vs-knockout-vs-ember/2\n\n## New Stuff (api is todo, can access now through Tower.router)\n\n``` coffeescript\n@resources 'posts'\n@namespace 'admin', ->\n  @resources 'posts'\n```\n\n``` coffeescript\nTower.urlFor(App.Post)\nTower.urlFor('root.posts.index')\n```\n\n``` coffeescript\n# GET\nApp.indexPosts(title: 'A') # App.action, Tower.action, which one?\nApp.showPost(id: 1)\nApp.newPost()\nApp.editPost(id: 1)\n# Non-GET\nApp.createPost()\nApp.updatePost(id: 1)\nApp.destroyPost(id: 1)\n```\n\n``` html\n{{#each post in App.postsController.all}}\n<a {{action editPost post href=true}}>Edit</a>\n{{/each}}\n```\n\n``` coffeescript\n# @todo\nApp.indexAdminPosts() # /admin/posts\nApp.indexPostComments(postId: 1) # /posts/1/comments\n```\n\n## Changelog\n\n- `brew install tree`, then you can type command `tree` to see project structure (https://github.com/cowboy/grunt-node-example)\n- todo: need to test installing different versions of node with https://github.com/creationix/nvm\n- https://gist.github.com/1398757\n\n## Contributing to Tower\n\n### Running Tests\n\nRun server tests:\n\n```\nmake test\n```\n\nTo run client tests, first start the test server on port `3210`, and then run phantomjs:\n\n```\nnode test/example -p 3210\n```","_id":"tower@0.4.2-2","dist":{"shasum":"f1b776ad71089d5891813910e9bd86ec4ef257d2","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-2.tgz","integrity":"sha512-bV6BhC5S7LUp7yNS4jE4x8895TETXajEIr9EBqW6elAOPlxBxzuY8tMVNk3v/fhdIGcaTnBLgEza8CtdlPSQ2w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHfkbNIrr/ZpRAScNlF5UMRBSZBqjM7WIYKoif6R09JVAiAHQkDMDKi16wupQ2C/yxs47UbuDPqI7VHouSL8A9pRqA=="}]}},"0.4.2-3":{"name":"tower","version":"0.4.2-3","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","underscore.logger":">= 0.3.1","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","mint":">= 0.3.4","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"2.x","URIjs":">= 1.4.2","moment":">= 1.5.1","node-uuid":">= 1.3.0","geolib":">= 0.0.1","superagent":">= 0.9.2","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","coffee-script":">= 1.3.3","wrench":">= 1.3.8","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0"},"devDependencies":{"findit":">= 0.1.1","ejs":">= 0.6.1"},"testDependencies":{"stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 0.8.1","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 0.9.9-8","coffee-script":">= 1.3.3","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.8.7","socket.io-client":">= 0.9.5","fibers":"~0.6.8"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"codo","postinstall":"$(./bin/dependencies)"},"readme":"# Tower.js <img src=\"http://i.imgur.com/e3VLW.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower-docs\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If your up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Contributor Note\n\nAll of the base ideas are now pretty much in the Tower codebase, now it's just a matter of fleshing out the edge cases and a few implementations. Here's what's new:\n\n- Background jobs in Redis. The `Model.enqueue` and `Model#enqueue` methods are convention for off-loading expensive tasks to the background. You then run `cake work` and it will start the [kue](https://github.com/LearnBoost/kue) background worker to process items in the different redis queues. That process is running in a totally separate environment, but they can communicate b/c of redis' nice pub/sub api. This still needs to be fleshed out and tested a bit more but the basics are there.\n- Attachments. File uploading is working, as well as image resizing with imagemagick. I've started working on post-processing using background redis jobs as well. Tower should have a standard set of attachment \"processors\" to make uploading/processing attachments dead-simple (it's still pretty hard in Rails). This includes from any format to standard formats (video/audio/docs/images/etc.), video/audio/image processing/compression, text extraction and resizing, and document processing (pdf text extraction, MS Word to text, etc.). It's all pretty straight forward, just need to wrap command-line tools. See http://documentcloud.github.com/docsplit/.\n- Authentication. I don't think I've merged the authentication code yet, but an older version is here: https://github.com/viatropos/tower-authentication-example. The whole logging in with email/facebook/etc. should be completely solved. Right now mongodb session support is working locally, I will merge it when I finish with some other stuff.\n- Subdomains. Subdomains should be first-class citizens. We need to thoroughly test them in production. JSONP support exists (to do `GET` requests across domains), need to test that out. Need to get a better/leaner URL parser, but what's in there now works. Need to test authentication/sessions/cookies across subdomains.\n- Authorization. I've started on the authorization system (inspired from [cancan](https://github.com/ryanb/cancan/)). It works and is pretty awesome :). Just need to add some controller hooks to make it plug-and-chug.\n- Mass-assignment protection. I've implemented the basics of \"mass assignment protection\" (see the [Rails Security Guide](http://guides.rubyonrails.org/security.html#mass-assignment)), need to test it out a bit more. Also need to handle input sanitization.\n- Embedded Documents. I've mapped out how this could be implemented but it's still on the todo list.\n- Associations (hasMany, hasManyThrough, belongsTo, hasOne). They all work well (tested manually on the client as well, pretty awesome seeing hasManyThrough relations save on the client). There's a good amount of work to be done on making sure `user.address == address.user`, that kind of reflection stuff (especially for binding on the view). Wrote down a lot of ideas on how to implement an \"identity map\", but we have to be careful about garbage collection if we're going to store references to the request/controller objects in some hidden \"thread\" (see some of the recent commits for notes - early/mid July). Also need to make the validations/callbacks more robust for `acceptsNestedAttributesFor`, but it's all working at a basic level.\n- The Cursor. The cursor is _super_ awesome :). There's a ton more ideas on how to make it even more awesome, but for now it does what it's supposed to. I'd like to simplify the notification system eventually (telling the client of model changes).\n- User stamping. This should be a fundamental part of the model layer (similar to time stamping). The base mixin has been started but isn't ready yet - it requires setting up the identity-map/thread idea so you can pass around the `currentUser` transparently between cursors/models in the context of a single request.\n- Versioning. Versioning is a tricky concept to implement, and it is not required for all apps. But it is generic enough and useful enough that it is going to be included in Tower (eventually as a separate sub-package). It allows you to keep a history of model changes (and alongside userstamping, who made those changes). I have started this as well.\n- Soft deleting models. Sometimes you want to allow users to \"delete\" their data, but you don't _really_ want it deleted from the database. To do this you just add a `deletedAt` field to your model, and then make it so all queries by default ignore models without `deletedAt == null`. You want this kind of stuff to do things like \"restore your deleted account\", or just know what's happened historically in your app (as a startup for example).\n- Ember Views. This is the next big thing to do, but it's really independent of Tower. Tower can create some helpers like form builders and whatnot, but that might take a long time - particularly b/c there's going to be a lot of work put in to make sure performance is top-notch with all those views.\n- Client Routes. The base code for mapping routes.coffee into the Ember routing system is there, but the Ember API is changing weekly almost so I haven't gotten back to it. It should only take a few hours to wire up.\n\nIf you're excited to work on one of these things let me know and I'll point you to where things are and all that. Once all of this stuff is reasonably complete (mid August hopefully), this will merge into master. From there it's going to be \"robustifying\" everything, and hardcore performance tuning.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nIf you would like to mess around with the tower source code, clone it and start the grunt watcher to compile all of the coffeescripts:\n\n```\nmake watch\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Views\n\nViews adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n## Examples\n\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n## Unsolved Complexities\n\n- Handling transactions from the client. How would you save the data for credit/account (subtract one record, add to another) so if one fails both revert back (if you try to keep it simplified and only POST individual records at a time)? You can do embedded models on MongoDB, and transactions on MySQL perhaps. Then if `acceptsNestedAttributesFor` is specified it will send nested data in JSON POST rather than separate. Obviously it's better to not do this on the server, but we should see if it's possible to do otherwise, and if not, publicize why.\n\n## Decisions (need to finalize)\n\n- for uniqueness validation, if it fails on the client, should it try fetching the record from the server? (and loading the record into the client memory store). Reasons for include having to do less work as a coder (lazy loads data). Reasons against include making HTTP requests to the server without necessarily expecting to - or you may not want it to fetch. Perhaps you can specify an option (`lazy: true`) or something, and on the client if true it will make the request (or `autofetch: true`)\n- For non-transactional (yet still complex) associations, such as `group hasMany users through memberships`, you can save one record at a time, so the client should be instant. But if the first record created fails (say you do `group.members.create()`, which creates a user, then a membership tying the two together), what should the client tell the user? Some suggest a global notification (perhaps an alert bar) saying a more generic message such as \"please refresh the page, some data is out of sync\". But if the data is very important, ideally the code would know how to take the user (who might click this notification) to a form to try saving the `hasMany through` association again. If it continues to fail, it's probably either a bug in the code, or we should be able to know if the server is having issues (like it's crashed or power went out) - then if it's a bug we can have them notify us (some button perhaps) or if it's a real server problem we prepared for we can notify something like \"sorry, having server issues, try again later\". Other that that, it's up to you to build the validations properly so the data is saved\n\n## Todo\n\n- use require in the browser to lazy load scripts\n- gruntjs\n- term-css\n- https://github.com/kuno/GeoIP\n- global timestamps/userstamps config boolean, to DRY model `@timestamps()` if desired\n- make tower into subpackages: (model/client, model/server, model/shared, controller/client, etc...)\n- http://jsperf.com/angular-vs-knockout-vs-ember/2\n\n## New Stuff (api is todo, can access now through Tower.router)\n\n``` coffeescript\n@resources 'posts'\n@namespace 'admin', ->\n  @resources 'posts'\n```\n\n``` coffeescript\nTower.urlFor(App.Post)\nTower.urlFor('root.posts.index')\n```\n\n``` coffeescript\n# GET\nApp.indexPosts(title: 'A') # App.action, Tower.action, which one?\nApp.showPost(id: 1)\nApp.newPost()\nApp.editPost(id: 1)\n# Non-GET\nApp.createPost()\nApp.updatePost(id: 1)\nApp.destroyPost(id: 1)\n```\n\n``` html\n{{#each post in App.postsController.all}}\n<a {{action editPost post href=true}}>Edit</a>\n{{/each}}\n```\n\n``` coffeescript\n# @todo\nApp.indexAdminPosts() # /admin/posts\nApp.indexPostComments(postId: 1) # /posts/1/comments\n```\n\n## Changelog\n\n- `brew install tree`, then you can type command `tree` to see project structure (https://github.com/cowboy/grunt-node-example)\n- todo: need to test installing different versions of node with https://github.com/creationix/nvm\n- https://gist.github.com/1398757\n\n## Contributing to Tower\n\n### Running Tests\n\nRun server tests:\n\n```\nmake test\n```\n\nTo run client tests, first start the test server on port `3210`, and then run phantomjs:\n\n```\nnode test/example -p 3210\n```","_id":"tower@0.4.2-3","dist":{"shasum":"3bf5427f9a73fd741fd2eca2a067df18fc4c22bf","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-3.tgz","integrity":"sha512-pKAr5o88BEcVNQK66nRylUkI6cP6xuQu2U0u3f0+QgzXfTzYkt9IzIkrFVZ2pzna/iVndnUATupYTLBG3gnyng==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCxsKXx8CeFLXjcPZfOAEaEasTphD+JP36k1eEVzjNq7gIhANfIbeoMEPqd/nU47jaKQMFNH5WDQ02Z/cd2TjT45gx+"}]}},"0.4.2-4":{"name":"tower","version":"0.4.2-4","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","underscore.logger":">= 0.3.1","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","mint":">= 0.3.4","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"3.x","URIjs":">= 1.4.2","moment":">= 1.7.0","node-uuid":">= 1.3.0","geolib":">= 1.1.8","superagent":">= 0.9.4","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","coffee-script":">= 1.3.3","wrench":">= 1.3.8","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0","crc":"~0.2.0","ansi":"~0.1.2","connect":">= 2.4.6","fresh":">= 0.1.0"},"devDependencies":{"findit":">= 0.1.1","ejs":">= 0.6.1","Faker":">= 0.1.3"},"testDependencies":{"stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.7","coffee-script":">= 1.3.3","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs","postinstall":"$(./bin/dependencies)"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If your up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-4","dist":{"shasum":"901d23e52549eb437564dea1195afa942c5c6caf","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-4.tgz","integrity":"sha512-Zu6VDpB/No1AVa6YpGkrU85SSmtHfXH2+LfDtxYBeDt8zVU45QAPLBTxoNrt3GKQMcycwdtprA51bhMIGUIx+A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHOkXH8GbR6VUEDt5L+W+V/Q4GCEoKEhlxKW/CmbhhoDAiB7vPXDlaPiVHGD2QSd1d3DTf0E1f6/87Y1q1NPxYTmZg=="}]}},"0.4.2-5":{"name":"tower","version":"0.4.2-5","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","underscore.logger":">= 0.3.1","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","mint":">= 0.3.4","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"3.x","URIjs":">= 1.4.2","moment":">= 1.7.0","node-uuid":">= 1.3.0","geolib":">= 1.1.8","superagent":">= 0.9.4","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","coffee-script":">= 1.3.3","wrench":">= 1.3.8","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0","crc":"~0.2.0","ansi":"~0.1.2","connect":">= 2.4.6","fresh":">= 0.1.0","which":">= 1.0.5"},"devDependencies":{"findit":">= 0.1.1","ejs":">= 0.6.1","Faker":">= 0.1.3"},"testDependencies":{"stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.7","coffee-script":">= 1.3.3","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs","postinstall":"make install-dependencies"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If you're up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-5","dist":{"shasum":"79e528abe4c7a3daad92660cfc0083bcfe6f5077","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-5.tgz","integrity":"sha512-q9QXa2WjP9ReROfVxfob+N3zExfJ5GTEp+aNeeKFK8ur1NlmaAPtOuzsywpXAZpAvMnsi4cfb0ysSMbgZQX9Nw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHUuIAVik1bOOgnA/JyEcE+WZ4OZjSMsazYWymXHFgEvAiBzklpS89rtjLXblrhAsGIL9tIE/3VbuSwnGjAe6lwEaw=="}]}},"0.4.2-6":{"name":"tower","version":"0.4.2-6","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","underscore.logger":">= 0.3.1","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","mint":">= 0.3.4","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"3.x","URIjs":">= 1.4.2","moment":">= 1.7.0","node-uuid":">= 1.3.0","geolib":">= 1.1.8","superagent":">= 0.9.4","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","coffee-script":">= 1.3.3","wrench":">= 1.3.8","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0","crc":"~0.2.0","ansi":"~0.1.2","connect":">= 2.4.6","fresh":">= 0.1.0","which":">= 1.0.5"},"devDependencies":{"findit":">= 0.1.1","ejs":">= 0.6.1","Faker":">= 0.1.3"},"testDependencies":{"stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.7","coffee-script":">= 1.3.3","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs","postinstall":"make install-dependencies"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If you're up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-6","dist":{"shasum":"d1b5eeb5f8398ddace7dbe5c3adcafe91f71e582","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-6.tgz","integrity":"sha512-KSki8+6wCYzWvKtv1wXppL50IeopwuFTQ7Vn7/0uuuauBzVU57FLh2hJSLu/5flgep8gZWfcV7N0MV2hpkqHSw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCl+Jlk4mEN7WfLiGKtLOmGEuk0t58pGIUUNkg6XJkh0wIgbtl02Ufj1b5eabnuvlopYblb+m7LldnKGVka+dOkO8I="}]}},"0.4.2-7":{"name":"tower","version":"0.4.2-7","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","underscore.logger":">= 0.3.1","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","mint":">= 0.3.4","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"3.x","URIjs":">= 1.4.2","moment":">= 1.7.0","node-uuid":">= 1.3.0","geolib":">= 1.1.8","superagent":">= 0.9.4","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","coffee-script":">= 1.3.3","wrench":">= 1.3.8","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0","crc":"~0.2.0","ansi":"~0.1.2","connect":">= 2.4.6","fresh":">= 0.1.0","which":">= 1.0.5"},"devDependencies":{"findit":">= 0.1.1","ejs":">= 0.6.1","Faker":">= 0.1.3"},"testDependencies":{"stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.7","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs","postinstall":"make install-dependencies"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If you're up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-7","dist":{"shasum":"63bfa7e498e25c5453421331b2da69bdda3aa515","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-7.tgz","integrity":"sha512-Ns+vPrfOH5TYcHsLxkfBSGWRknimTXOWzLLTJF+94p+yT55W+DrjArOosDmp+5YrP0/FLJV/pMQuN+s376uCPw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCcLdNUAIiR6pnUeVKkCkS2V2re1c/m1+EBv9NWrbNbdgIhAN5g9sK1ip/ufXRVryXpsME4WEM2IpCRkHO0+MvwlgM+"}]}},"0.4.2-8":{"name":"tower","version":"0.4.2-8","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","underscore.logger":">= 0.3.1","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","mint":">= 0.3.4","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"3.x","URIjs":">= 1.4.2","moment":">= 1.7.0","node-uuid":">= 1.3.0","geolib":">= 1.1.8","superagent":">= 0.9.4","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","coffee-script":">= 1.3.3","wrench":">= 1.3.8","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0","crc":"~0.2.0","ansi":"~0.1.2","connect":">= 2.4.6","fresh":">= 0.1.0","which":">= 1.0.5"},"devDependencies":{"findit":">= 0.1.1","ejs":">= 0.6.1","Faker":">= 0.1.3"},"testDependencies":{"stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.7","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs","postinstall":"make install-dependencies"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If you're up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-8","dist":{"shasum":"c2b44fdb5f4da731abb7d9dd75343c79fae39643","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-8.tgz","integrity":"sha512-3lvd4orJCoRsMYqZZ8lqqAAS1HJ2cWMsxzurV+Zo5WdUqHKnZx2MUTG3me2MPwTPdXnUWOHtaXDrX0qe80V1hg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDNlXGHZ2gJILizIDwtH3Fi/I1i1v9Z/UfymYHb55G0DgIhALc8sqCW7TIro1AtaONKeArD81G9uBlYmu1NfMpzPGsZ"}]}},"0.4.2-9":{"name":"tower","version":"0.4.2-9","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","underscore.logger":">= 0.3.1","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","mint":">= 0.3.4","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"3.x","URIjs":">= 1.4.2","moment":">= 1.7.0","node-uuid":">= 1.3.0","geolib":">= 1.1.8","superagent":">= 0.9.4","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","coffee-script":">= 1.3.3","wrench":">= 1.3.8","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0","crc":"~0.2.0","ansi":"~0.1.2","connect":">= 2.4.6","fresh":">= 0.1.0","which":">= 1.0.5"},"devDependencies":{"findit":">= 0.1.1","ejs":">= 0.6.1","Faker":">= 0.1.3"},"testDependencies":{"stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.7","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs","postinstall":"make install-dependencies"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If you're up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-9","dist":{"shasum":"0d1e92c4c4e2389cde7f76157a2f9754d9771248","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-9.tgz","integrity":"sha512-wheSpnEWv0+1dUKI1Id9AMA4dTZJVxHRVZ/78P5PW0d80PEZRy2qudYiQexEPrwPVj/p2RsEXiAhwGCf9EJWeA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDTtQcOi1EdrvukJcEKMwgooNBpMBsl1NhMOVQmkPyW/AiEA/iZpsyouszZnIDOymC8/FtnoVcNtaZyQK/IP2fEcNlQ="}]}},"0.4.2-10":{"name":"tower","version":"0.4.2-10","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","underscore.logger":">= 0.3.1","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","mint":">= 0.3.4","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"3.x","URIjs":">= 1.4.2","moment":">= 1.7.0","node-uuid":">= 1.3.0","geolib":">= 1.1.8","superagent":">= 0.9.4","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","coffee-script":">= 1.3.3","wrench":">= 1.3.8","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0","crc":"~0.2.0","ansi":"~0.1.2","connect":">= 2.4.6","fresh":">= 0.1.0","which":">= 1.0.5"},"devDependencies":{"findit":">= 0.1.1","ejs":">= 0.6.1","Faker":">= 0.1.3"},"testDependencies":{"stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.7","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs","postinstall":"make install-dependencies"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If you're up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-10","dist":{"shasum":"14b501ac9450bfb5d107d5f3a8dacf0093ca17af","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-10.tgz","integrity":"sha512-gBf5+AubpYEybXVtzzDFB+q2dtLqSJ9f3OWj4fpCKT2F5bP8knuw8yvqVRTr54D3qFYeTIk/PqSgiQNacK6MGA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC0Py7dxKbDlxmmTLqIbI3a9POPpu2DtzijgEmA8QO7wwIhAJ9SeSQ6b+MXifkgBqcwAhB9X/ROG0L3wur3qbscb7CV"}]}},"0.4.2-11":{"name":"tower","version":"0.4.2-11","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","underscore.logger":">= 0.3.1","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","mint":">= 0.3.4","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"3.x","URIjs":">= 1.4.2","moment":">= 1.7.0","node-uuid":">= 1.3.0","geolib":">= 1.1.8","superagent":">= 0.9.4","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","coffee-script":">= 1.3.3","wrench":">= 1.3.8","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0","crc":"~0.2.0","ansi":"~0.1.2","connect":">= 2.4.6","fresh":">= 0.1.0","which":">= 1.0.5"},"devDependencies":{"findit":">= 0.1.1","ejs":">= 0.6.1","Faker":">= 0.1.3"},"testDependencies":{"stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.7","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs","postinstall":"make install-dependencies"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If you're up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-11","dist":{"shasum":"f159e805b3716d6189da0d6e5c37a2e963de54b1","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-11.tgz","integrity":"sha512-eCfHCDoV+2eozAT/gX+Y7wnUWIwSwDGNAeKJ9C5XN6Mc253ZEP9R/hkf5KMj3fI3MwUXqqtkXN5DACNl3Pc/rw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGf7pFPnWQyz1QyjIJLxuuveyWe/tY8OXrtmaDMY0MYeAiAeqGRc8tZHZxNg1iNBWA2iMRWwDGMfzo3QwwVy/jmr5w=="}]}},"0.4.2-12":{"name":"tower","version":"0.4.2-12","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","underscore.logger":">= 0.3.1","mime":">= 1.2.4","qs":">= 0.3.1","async":">= 0.1.12","mint":">= 0.3.4","pathfinder":">= 0.1.5","commander":">= 0.4.0","express":"3.x","URIjs":">= 1.4.2","moment":">= 1.7.0","node-uuid":">= 1.3.0","geolib":">= 1.1.8","superagent":">= 0.9.4","validator":">= 0.4.5","accounting":">= 0.3.2","inflection":">= 1.2.0","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","coffee-script":">= 1.3.3","wrench":">= 1.3.8","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0","crc":"~0.2.0","ansi":"~0.1.2","connect":">= 2.4.6","fresh":">= 0.1.0","which":">= 1.0.5"},"devDependencies":{"findit":">= 0.1.1","ejs":">= 0.6.1","Faker":">= 0.1.3"},"testDependencies":{"stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.7","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs","postinstall":"make install-dependencies"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If you're up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-12","dist":{"shasum":"65899e11aab2f1569537a1bb21c71f49f70c5258","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-12.tgz","integrity":"sha512-hAw2kTNCu+ShoT9D3O2oXZnzWMj8BkQNWbYBUpaJdYBc4jLWOUV/2UREhwIOygNmgOPfQu8HFr66Xet28pJHGQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDQ2l/ig7NvtQd0JyIvXqDSvOHE0RzDdpCgtkU+doV4IwIgUpP5uKKv40+3wD2lHTI1gvfvfUAiR/RgvQd3JY97/Rs="}]}},"0.4.2-13":{"name":"tower","version":"0.4.2-13","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":"~1.3.3","underscore.string":">= 2.x","superagent":">= 0.9.4","inflection":">= 1.2.3","wrench":">= 1.3.8","which":">= 1.0.5","ansi":"~0.1.2","term-css":"~1.0.0","pathfinder":">= 0.0.1","commander":">= 0.4.0"},"devDependencies":{"findit":">= 0.1.1","ejs":">= 0.6.1","Faker":">= 0.1.3"},"testDependencies":{"stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.7","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{"mime":">= 1.2.4","async":">= 0.1.12","mint":">= 0.3.4","qs":">= 0.3.1","crc":"~0.2.0","express":"3.x","URIjs":">= 1.4.2","moment":">= 1.7.0","node-uuid":">= 1.3.0","geolib":">= 1.1.8","validator":">= 0.4.5","accounting":">= 0.3.2","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","coffee-script":">= 1.3.3","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0","connect":">= 2.4.6","fresh":">= 0.1.0","grunt-contrib-less":"~0.3.0"},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs","postinstall":"make post-install"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If you're up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-13","dist":{"shasum":"1ae41a031fcfd55d8f2c468334f420f20ae00fb2","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-13.tgz","integrity":"sha512-8p5Pt1oIFT7xCAFY5mJ0xSFrBgFqDMvLAd55ShfjqrZNeozRokM2YT6fUPVtlZvFkCxtDtvNZles++xtqfbLTQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC71i/l361tf1buYsPc2Ms4xVqV5dybPnN12C1Wjdc1HgIgfVpiP2jIXmDo01sK6zoxfvLaCOpmOLkQ1ODr9R9XhTA="}]}},"0.4.2-14":{"name":"tower","version":"0.4.2-14","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":"~1.3.3","underscore.string":">= 2.x","superagent":">= 0.9.4","inflection":">= 1.2.3","wrench":">= 1.3.8","which":">= 1.0.5","ansi":"~0.1.2","term-css":"~1.0.0","pathfinder":">= 0.0.1","commander":">= 0.4.0","mime":">= 1.2.4","async":">= 0.1.12","mint":">= 0.3.4","qs":">= 0.3.1","crc":"~0.2.0","express":"3.x","URIjs":">= 1.4.2","moment":">= 1.7.0","node-uuid":">= 1.3.0","geolib":">= 1.1.8","validator":">= 0.4.5","accounting":">= 0.3.2","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","coffee-script":">= 1.3.3","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0","connect":">= 2.4.6","fresh":">= 0.1.0","grunt-contrib-less":"~0.3.0"},"devDependencies":{"findit":">= 0.1.1","ejs":">= 0.6.1","Faker":">= 0.1.3"},"testDependencies":{"stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.7","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs","postinstall":"make post-install"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If you're up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-14","dist":{"shasum":"c46693ba40d600ba2d6dee218463b995faa5613a","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-14.tgz","integrity":"sha512-W4txX2/mG26Ks083xOXxRwBuptBPSGII2qg/4ifH1rdkrPXDuuyC4i439FzH8Wt41Pg1RmZpcX8ZIsxw72I+ow==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAz1K1s/kJzxUIbGl2+Auew227PS/B9QOCAp8x/soBnhAiBPJw4pOg4QOMa2RmPnPNTkatTBPY6dSHcem6Z9huf4Ow=="}]}},"0.4.2-15":{"name":"tower","version":"0.4.2-15","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"Sebastian Hoitz"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"Nov Matake"},{"name":"abovethewater"},{"name":"Scott Tesoriere","email":"scott@tesoriere.com"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":"~1.3.3","underscore.string":">= 2.x","superagent":">= 0.9.4","inflection":">= 1.2.3","wrench":">= 1.3.8","which":">= 1.0.5","ansi":"~0.1.2","term-css":"~1.0.0","pathfinder":">= 0.0.1","commander":">= 0.4.0","mime":">= 1.2.4","async":">= 0.1.12","mint":">= 0.3.4","qs":">= 0.3.1","crc":"~0.2.0","express":"3.x","URIjs":">= 1.4.2","moment":">= 1.7.0","node-uuid":">= 1.3.0","geolib":">= 1.1.8","validator":">= 0.4.5","accounting":">= 0.3.2","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","coffee-script":">= 1.3.3","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0","connect":">= 2.4.6","fresh":">= 0.1.0","grunt-contrib-less":"~0.3.0"},"devDependencies":{"findit":">= 0.1.1","ejs":">= 0.6.1","Faker":">= 0.1.3"},"testDependencies":{"stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.10","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs","postinstall":"make post-install"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If you're up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-15","dist":{"shasum":"9464578c78ee99d2e81a5f617bec01a8e72ddadb","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-15.tgz","integrity":"sha512-mwKUIM1WMEyPYmjMK7Ydtup3aDVYiUjnxlSkC1neXjbb/Lf1Y5UmWxLjbg6J0yI/F4HxKxBVVO9h+fDHVgOZEQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBEeQBM9W4eAvscWjbwmPN/z3ki3Gfq6JFdcqQe1vy71AiA9U9xQTd/4UTUrXLo0PeqlUBLClB34oBPFTO2Zkq4QjQ=="}]}},"0.4.2-16":{"name":"tower","version":"0.4.2-16","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"TheHydroImpulse","email":"dnfagnan@gmail.com"},{"name":"Sebastian Hoitz"},{"name":"scottkf","email":"scott@tesoriere.com"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"j-mcnally"},{"name":"abovethewater"},{"name":"Nov Matake"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","superagent":">= 0.9.4","inflection":">= 1.2.3","wrench":">= 1.3.8","which":">= 1.0.5","ansi":"~0.1.2","term-css":"~1.0.0","pathfinder":">= 0.0.1","commander":">= 0.4.0","mime":">= 1.2.4","node-uuid":">= 1.3.0"},"devDependencies":{"findit":">= 0.1.1","ejs":">= 0.6.1","Faker":">= 0.1.3"},"testDependencies":{"coffee-script":">= 1.3.3","stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.10","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{"async":">= 0.1.12","mint":">= 0.3.4","qs":">= 0.3.1","crc":"~0.2.0","express":"3.x","URIjs":">= 1.4.2","moment":">= 1.7.0","geolib":">= 1.1.8","validator":">= 0.4.5","accounting":">= 0.3.2","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0","connect":">= 2.4.6","fresh":">= 0.1.0","grunt-contrib-less":"~0.3.0"},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs","postinstall":"make post-install"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If you're up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-16","dist":{"shasum":"b872caee14ba08ea6845d03e1d4790f650bb8d00","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-16.tgz","integrity":"sha512-hhYdrhonKe7OfKYkAxF5Jui0UKORIkEHF7tqKINxSzfq1Gv6O34sF1g78agjq4he9YfNKl2SQKHV40ZvSiIIkQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB4U92jAA93W/vq2ZwiYeiYvnGnerHjpffFj5jV7J6HXAiA4z6ygMEVHgWfLgytT0fVZ+89bgVHnBfNuicA7llVxRw=="}]}},"0.4.2-17":{"name":"tower","version":"0.4.2-17","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"TheHydroImpulse","email":"dnfagnan@gmail.com"},{"name":"Sebastian Hoitz"},{"name":"scottkf","email":"scott@tesoriere.com"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"j-mcnally"},{"name":"abovethewater"},{"name":"Nov Matake"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","superagent":">= 0.9.4","inflection":">= 1.2.3","wrench":">= 1.3.8","which":">= 1.0.5","ansi":"~0.1.2","term-css":"~1.0.0","commander":">= 0.4.0","mime":">= 1.2.4","node-uuid":">= 1.3.0","ejs":">= 0.6.1"},"devDependencies":{},"testDependencies":{"coffee-script":">= 1.3.3","stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.10","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","Faker":">= 0.1.3","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{"async":">= 0.1.12","mint":">= 0.3.4","qs":">= 0.3.1","crc":"~0.2.0","express":"3.x","URIjs":">= 1.4.2","moment":">= 1.7.0","geolib":">= 1.1.8","validator":">= 0.4.5","accounting":">= 0.3.2","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0","connect":">= 2.4.6","fresh":">= 0.1.0","grunt-contrib-less":"~0.3.0"},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs","postinstall":"make post-install"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If you're up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool:\n\n```\nnpm install grunt -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-17","dist":{"shasum":"77f3096c29dc2bffd0b13cac4ddb5acc1f137a33","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-17.tgz","integrity":"sha512-sNfZMDIhc4oaBYJyHkeO3Uh7oT1/vZS+VbF0LylFc2pTvMfVIsBIJ08tlb3UDbE8xg8EshH2CpU5YhlYNUDkgg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE5mZKfUt34FqNcab3Nrp+qVh6NfRa8XEfd2RvK0Lf9JAiA3QJ2iFRCagsZ4CW0K13vRpBn4pf4n/sZ4pikh2dwsJg=="}]}},"0.4.2-18":{"name":"tower","version":"0.4.2-18","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"TheHydroImpulse","email":"dnfagnan@gmail.com"},{"name":"Sebastian Hoitz"},{"name":"scottkf","email":"scott@tesoriere.com"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"j-mcnally"},{"name":"abovethewater"},{"name":"Nov Matake"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","superagent":">= 0.9.4","inflection":">= 1.2.3","wrench":">= 1.3.8","which":">= 1.0.5","ansi":"~0.1.2","term-css":"~1.0.0","commander":">= 0.4.0","mime":">= 1.2.4","node-uuid":">= 1.3.0","ejs":">= 0.6.1","async":">= 0.1.12","mint":">= 0.3.4","qs":">= 0.3.1","crc":"~0.2.0","express":"3.x","URIjs":">= 1.4.2","moment":">= 1.7.0","geolib":">= 1.1.8","validator":">= 0.4.5","accounting":">= 0.3.2","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0","connect":">= 2.4.6","fresh":">= 0.1.0","grunt-contrib-less":"~0.3.0"},"devDependencies":{},"testDependencies":{"coffee-script":">= 1.3.3","stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.10","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","Faker":">= 0.1.3","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If you're up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool, and coffee-script:\n\n```\nnpm install grunt -g\nnpm install coffee-script -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\nmake install-dependencies\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-18","dist":{"shasum":"52872d0da7441f6afdd03c49cf27a3e77f24dc18","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-18.tgz","integrity":"sha512-HVYyTVttgsYDMTbtortHSIr1okIMBEY1FPqK/tSq/r95XsvIt8mrmMmaIBOfYpT7gUWdYDbLn/p0D6Cgh9VCzA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC4XbxabAQ3nAgJyO2QpC2grYaDO6apNI11PxdvUr3k3QIhAPu2eoZbk0eug0e2a7H7GInbUtC/jUbrbVFdrGgZ4iYR"}]}},"0.4.2-19":{"name":"tower","version":"0.4.2-19","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"TheHydroImpulse","email":"dnfagnan@gmail.com"},{"name":"Sebastian Hoitz"},{"name":"scottkf","email":"scott@tesoriere.com"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"j-mcnally"},{"name":"abovethewater"},{"name":"Nov Matake"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","superagent":">= 0.9.4","inflection":">= 1.2.3","wrench":">= 1.3.8","which":">= 1.0.5","ansi":"~0.1.2","term-css":"~1.0.0","commander":">= 0.4.0","mime":">= 1.2.4","node-uuid":">= 1.3.0","ejs":">= 0.6.1","async":">= 0.1.12","mint":">= 0.3.4","qs":">= 0.3.1","crc":"~0.2.0","express":"3.x","URIjs":">= 1.4.2","moment":">= 1.7.0","geolib":">= 1.1.8","validator":">= 0.4.5","accounting":">= 0.3.2","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0","connect":">= 2.4.6","fresh":">= 0.1.0","grunt-contrib-less":"~0.3.0"},"devDependencies":{},"testDependencies":{"coffee-script":">= 1.3.3","stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.10","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","Faker":">= 0.1.3","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If you're up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool, and coffee-script:\n\n```\nnpm install grunt -g\nnpm install coffee-script -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\nnpm install\nmake install-dependencies\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-19","dist":{"shasum":"517368b794ba06cccd6dd960f6b9ffeb46ef548e","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-19.tgz","integrity":"sha512-meX5xMhBhr2G0RSOxl3sEcx/AuwVOCxGF0KTuBAGCZ9L4Yx9BW1o+lavfDQbqGNOjUknLfiaOrKFxztHOsEaqQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC8gNbt6qUR7vJDYwv5KpL8vg6cP8E29G1u4bugkEZsHAiEA0CLpoDxSwJE2gGEPb8PWfNLvEMpfjd8D1l7QCMWgMKk="}]}},"0.4.2-20":{"name":"tower","version":"0.4.2-20","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"TheHydroImpulse","email":"dnfagnan@gmail.com"},{"name":"Sebastian Hoitz"},{"name":"scottkf","email":"scott@tesoriere.com"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"j-mcnally"},{"name":"abovethewater"},{"name":"Nov Matake"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.3.3","underscore.string":">= 2.x","superagent":">= 0.9.4","inflection":">= 1.2.3","wrench":">= 1.3.8","which":">= 1.0.5","ansi":"~0.1.2","term-css":"~1.0.0","commander":">= 1.0.5","mime":">= 1.2.4","node-uuid":">= 1.3.0","ejs":">= 0.6.1","async":">= 0.1.12","mint":">= 0.3.4","qs":">= 0.3.1","crc":"~0.2.0","express":"3.x","URIjs":">= 1.4.2","moment":">= 1.7.0","geolib":">= 1.1.8","validator":">= 0.4.5","accounting":">= 0.3.2","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","useragent":">= 1.0.5","gm":"~1.4.1","temp":"~0.4.0","connect":">= 2.4.6","fresh":">= 0.1.0","grunt-contrib-less":"~0.3.0"},"devDependencies":{},"testDependencies":{"coffee-script":">= 1.3.3","stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.10","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","Faker":">= 0.1.3","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If you're up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database)\n- Redis (background jobs)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby.  Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou can grab the latest client tower.js [here](http://cloud.github.com/downloads/viatropos/tower/tower.js), although you don't need to (when you generate a new app it will be downloaded automatically).\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool, and coffee-script:\n\n```\nnpm install grunt -g\nnpm install coffee-script -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\n```\ntower new app\ncd app\nnpm install\ncake watch\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\nnpm install\nmake install-dependencies\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-20","dist":{"shasum":"26efcb5658160137baa2710e3d960e5fd528a7a4","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-20.tgz","integrity":"sha512-NLpJhvzgpGaY0bOedOUQJNvqZo8rc1a7vbiY8dH7HUcL8HzdPkg0iBtIMN9kui1WPafixh7mbYOrCdX41mLkAA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCy8RY8QSpcImPyGeNQLGzfGErSLfFROcS5I8H5AxH9nAIgRkzCWS0CR5pHPzhCyPnRkls0OZe6KHy4hWQBi2Yie5w="}]}},"0.4.2-21":{"name":"tower","version":"0.4.2-21","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"TheHydroImpulse","email":"dnfagnan@gmail.com"},{"name":"Sebastian Hoitz"},{"name":"scottkf","email":"scott@tesoriere.com"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"j-mcnally"},{"name":"abovethewater"},{"name":"Nov Matake"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.4.2","underscore.string":">= 2.x","inflection":">= 1.2.3","commander":">= 1.0.5","mime":">= 1.2.4","node-uuid":">= 1.3.0","ejs":">= 0.6.1","async":">= 0.1.12","mint":">= 0.3.4","qs":">= 0.3.1","moment":">= 1.7.0","geolib":">= 1.1.8","validator":">= 0.4.5","accounting":">= 0.3.2","ember-metal-node":">= 1.0.0-pre","ember-runtime-node":">= 1.0.0-pre","ember-states-node":">= 1.0.0-pre","useragent":">= 1.0.5","connect":">= 2.4.6","fresh":">= 0.1.0","express":"3.x","URIjs":"~1.7.2","which":"~1.0.5","superagent":"~0.9.5","crc":"~0.2.0","ansi":"~0.1.2","term-css":"~1.0.0","wrench":"~1.3.9","gm":"~1.4.1","temp":"~0.4.0","grunt-contrib-less":"~0.3.0"},"devDependencies":{},"testDependencies":{"coffee-script":"1.3.3","stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.10","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","Faker":">= 0.1.3","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If you're up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database, it's optional. Tower can just be used in the browser)\n- Redis (background jobs, also optional)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby. Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool, and coffee-script:\n\n```\nnpm install grunt -g\nnpm install coffee-script -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\nIn one terminal window, generate your app and start your server:\n\n```\ntower new app\ncd app\nnpm install\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nThen in a second terminal window, start the watcher so files compile when they are changed:\n\n```\ncd app\ncake watch\n```\n\nBy having two separate windows, you can modify your code without having to run your server, and coffeescript/stylus/less tasks (or any task in your `grunt` file) will still be executed.\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:bundle\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\nnpm install\nmake install-dependencies\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-21","dist":{"shasum":"8922237508f32801517ad8d2b809c21dd5344ff5","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-21.tgz","integrity":"sha512-WOCh4T9R6hpGUb5sTY7sbBuBGx6jfndMtmA3por1VsMLrCTYy0KEl3vqFpsjGkU6dW7hHbjVuj4MCd4PVsqRWg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFdWKB7sO1Zgsej3d9AAYfTHpQlaJ9l+y3C7QGqSBEbXAiEAkNt5cNfYwqkawkzr9L4H8olwI9ni6hjuE0lAnPJCjDc="}]}},"0.4.2-22":{"name":"tower","version":"0.4.2-22","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"TheHydroImpulse","email":"dnfagnan@gmail.com"},{"name":"Sebastian Hoitz"},{"name":"scottkf","email":"scott@tesoriere.com"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"j-mcnally"},{"name":"abovethewater"},{"name":"Nov Matake"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.4.2","underscore.string":">= 2.x","inflection":">= 1.2.3","commander":">= 1.0.5","mime":">= 1.2.4","node-uuid":">= 1.3.0","ejs":">= 0.6.1","async":">= 0.1.12","mint":">= 0.3.4","qs":">= 0.3.1","moment":">= 1.7.0","geolib":">= 1.1.8","validator":">= 0.4.5","accounting":">= 0.3.2","ember-metal-node":">= 1.0.0-pre.2","ember-runtime-node":">= 1.0.0-pre.2","ember-states-node":">= 1.0.0-pre.2","ember-application-node":">= 1.0.0-pre.2","ember-routing-node":">= 1.0.0-pre.2","useragent":">= 1.0.5","connect":">= 2.4.6","fresh":">= 0.1.0","express":"3.x","URIjs":"~1.7.2","which":"~1.0.5","superagent":"~0.9.5","crc":"~0.2.0","ansi":"~0.1.2","term-css":"~1.0.0","wrench":"~1.3.9","gm":"~1.4.1","temp":"~0.4.0","grunt-contrib-less":"~0.3.0"},"devDependencies":{},"testDependencies":{"coffee-script":"~1.3.3","stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.10","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","Faker":">= 0.1.3","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node's Connect and Express, modeled after Ruby on Rails.  Built for the client and server from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we're going. If you're up for it please contribute! The 0.5.0 release will have most of the features and will be roughly equivalent to a beta release. From there, it's performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nMaster branch will always be functional, and for the most part in sync with the version installed through the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database, it's optional. Tower can just be used in the browser)\n- Redis (background jobs, also optional)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and ajax) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby. Includes a controller architecture that works the same on both the client and server, modeled after Rails.  The routing API is pretty much exactly like Rails 3's.  Templates work on client and server as well (and you can swap in any template engine no problem).  Includes asset pipeline that works just like Rails 3's - minifies and gzips assets with an md5-hashed name for optimal browser caching, only if you so desire.  And it includes a watcher that automatically injects javascripts and stylesheets into the browser as you develop.  It solves a lot of our problems, hope it solves yours too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool, and coffee-script:\n\n```\nnpm install grunt -g\nnpm install coffee-script -g\n```\n\nFinally, make sure you have mongodb installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start redis:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\nIn one terminal window, generate your app and start your server:\n\n```\ntower new app\ncd app\nnpm install\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nThen in a second terminal window, start the watcher so files compile when they are changed:\n\n```\ncd app\ncake watch\n```\n\nBy having two separate windows, you can modify your code without having to run your server, and coffeescript/stylus/less tasks (or any task in your `grunt` file) will still be executed.\n\nAlso note, grunt's watcher doesn't currently get notified when new files are created. So if you run the `tower generate` command, or otherwise create files, stop and rerun the `cake watch` command. You also might want to check out `grunt-contrib-watch` which was recently created and may solve this issue (I haven't tried it yet though).\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo restart your server automatically if it crashes, run with forever:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n  \n  @hasOne 'address', embed: true\n  \n  @hasMany 'posts'\n  @hasMany 'comments'\n  \n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n  \n  @validates 'firstName', 'email', presence: true\n  \n  @after 'create', 'welcome'\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n  \n  @belongsTo 'author', type: 'User'\n  \n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n  \n  @before 'validate', 'slugify'\n  \n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n  \n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n  \n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n  \n  @resources 'posts', ->\n    @resources 'comments'\n    \n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n      \n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n    \n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n    \n  create: ->\n    @post = App.Post.build(@params.post)\n    \n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n    \n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n    \n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n    \n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n    \n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt's all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n    \n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n    \n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n    \n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere's the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify exactly how you want to compile your files for the client so it's as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:bundle\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\nnpm install\nmake install-dependencies\n```\n\n### Building Tower\n\nYou can build Tower manually with:\n\n```\nmake\n```\n\nOr you can have it recompile the files when you change them:\n\n```\nmake watch\n```\n\n### \"Linking\" Tower\n\nYou can symlink your local tower repo to your global npm node_modules directory, which makes it so you can use it in your apps (so if you make changes to the tower repo, you'll see them in your app). Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don't have phantomjs you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"tower@0.4.2-22","dist":{"shasum":"163aa41b08fe555b3990d731949083c05aec7ea4","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-22.tgz","integrity":"sha512-RyPEY7FmkvOTE78fBW7KKltjJ/C41MlsKanKYNXbltkmvjYzeE3zPUfJyJcbo7n+shmKaimddljTIhKdYZQQkQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDwAx09nbp13GUQaOpJTy1l6AHtMJhsDAInjZSfpx+FfwIgGgtoRvKep+6c/jRxPFRU19V4+6HT5t/aa8Lngy4JoNM="}]}},"0.4.2-23":{"name":"tower","version":"0.4.2-23","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"TheHydroImpulse","email":"dnfagnan@gmail.com"},{"name":"Sebastian Hoitz"},{"name":"scottkf","email":"scott@tesoriere.com"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"j-mcnally"},{"name":"abovethewater"},{"name":"Nov Matake"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.4.2","underscore.string":">= 2.x","inflection":">= 1.2.3","commander":">= 1.0.5","mime":">= 1.2.4","node-uuid":">= 1.3.0","ejs":">= 0.6.1","async":">= 0.1.12","mint":">= 0.3.4","qs":">= 0.3.1","moment":">= 1.7.0","geolib":">= 1.1.8","validator":">= 0.4.5","accounting":">= 0.3.2","ember-metal-node":">= 1.0.0-pre.2","ember-runtime-node":">= 1.0.0-pre.2","ember-states-node":">= 1.0.0-pre.2","ember-application-node":">= 1.0.0-pre.2","ember-routing-node":">= 1.0.0-pre.2","useragent":">= 1.0.5","connect":">= 2.4.6","fresh":">= 0.1.0","express":"3.x","URIjs":"~1.7.2","which":"~1.0.5","superagent":"~0.9.5","crc":"~0.2.0","ansi":"~0.1.2","term-css":"~1.0.0","wrench":"~1.3.9","gm":"~1.4.1","temp":"~0.4.0","grunt-contrib-less":"~0.3.0"},"devDependencies":{},"testDependencies":{"coffee-script":"~1.3.3","stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.10","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","Faker":">= 0.1.3","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node’s Connect and Express, modeled after Ruby on Rails.  Built for the client *and* server, from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we’re going. If you’re up for it, please contribute!\n\nThe 0.5.0 release will have most of the features, and will roughly be equivalent to a beta release. From there, it’s performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nThe `master` branch will always be functional, and (for the most part) in sync with the version you can install from the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database, it’s optional. Tower can just be used in the browser)\n- Redis (background jobs, also optional)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and AJAX), and MongoDB support.  Tower is modeled after ActiveRecord and Mongoid for Ruby. Includes a controller architecture that works the same for both client and server, modeled after Rails.  The routing API is like that of Rails 3.  Templates also work on client and server—and you can swap in any template engine, no problem.  Includes asset pipeline that works just like Rails 3 (minifies and gzips assets with an md5-hashed name for optimal browser caching, if you desire).  And it includes a watcher that automatically injects javascripts and stylesheets into the browser *as you develop*.\n\nIt solves a lot of our problems. We hope it solves yours, too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool, and `coffee-script`:\n\n```\nnpm install grunt -g\nnpm install coffee-script -g\n```\n\nFinally, make sure you have `mongodb` installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start `redis`:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\nIn your terminal, generate your app and start your server:\n\n```\ntower new app\ncd app\nnpm install\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nThen, in a second terminal, start the watcher. This will automatically compile  files when they change:\n\n```\ncd app\ncake watch\n```\n\nBy having two separate windows, you can modify your code without having to run your server, and coffeescript/stylus/less tasks will still be executed.  (And the same goes for any task in your `grunt` file.)\n\nAlso note, grunt’s watcher doesn’t currently get notified when new files are created. So if you run the `tower generate` command (or otherwise create files), stop and rerun the `cake watch` command. You also might want to check out `grunt-contrib-watch`, which was recently created, and may solve this issue. (I haven’t tried it yet, though.)\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo automatically restart your server if it crashes, run with `forever`:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n\n  @hasOne 'address', embed: true\n\n  @hasMany 'posts'\n  @hasMany 'comments'\n\n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n\n  @validates 'firstName', 'email', presence: true\n\n  @after 'create', 'welcome'\n\n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n\n  @belongsTo 'author', type: 'User'\n\n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n\n  @before 'validate', 'slugify'\n\n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n\n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n\n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n\n  @resources 'posts', ->\n    @resources 'comments'\n\n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n\n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n\n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n\n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n\n  create: ->\n    @post = App.Post.build(@params.post)\n\n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n\n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n\n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n\n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n\n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It’s much more powerful than Jade, and it’s just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt’s all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that’s built in!  So for the simple case you don’t even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do its thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware, so you have access to `request` and `response` objects—just like you would on the server.\n\n## Middleware\n\nIt’s built on [connect](http://github.com/sencha/connect), so you can use any  middleware library you like.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n\n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n\n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n\n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere’s the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor` (and wherever else you might put things).  The default is to use Stylus for CSS in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify *exactly* how you want to compile your files for the client, to ensure it’s as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:bundle\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\nnpm install\nmake install-dependencies\n```\n\n### Building Tower\n\nYou can build tower manually with:\n\n```\nmake\n```\n\nOr, you can have it recompile files whenever you change them:\n\n```\nmake watch\n```\n\n### “Linking” Tower\n\nYou can symlink your local tower repository to your global npm `node_modules` directory, which allows you use it in your apps. That way, if you make changes to the tower repository, you’ll see them in your app! Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don’t have `phantomjs`, you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","readmeFilename":"README.md","_id":"tower@0.4.2-23","dist":{"shasum":"e55b1045aa38bda9b00481d2c84c370f5d05fec7","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-23.tgz","integrity":"sha512-NtZGQod0vLg64IJjIKTiKoM+RnH9mXw/ht6G7lUbCEW5TgeNUGDztIjBsCMUmsOPEzpxGkR2etrph/hKPKBfSA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEJMmSKSiMEi7bMEjIPeaNZVWhf12gUGS9PU2tlKRcT+AiEAtNnjJT/mw2U2qNI0OhFcxAQHSbXfPR6MOy7aFXyjQEI="}]},"_npmVersion":"1.1.69","_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"}},"0.4.2-24":{"name":"tower","version":"0.4.2-24","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"TheHydroImpulse","email":"dnfagnan@gmail.com"},{"name":"Sebastian Hoitz"},{"name":"scottkf","email":"scott@tesoriere.com"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"j-mcnally"},{"name":"abovethewater"},{"name":"Nov Matake"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.4.2","underscore.string":">= 2.x","inflection":">= 1.2.3","commander":">= 1.0.5","mime":">= 1.2.4","node-uuid":">= 1.3.0","ejs":">= 0.6.1","async":">= 0.1.12","mint":">= 0.3.4","qs":">= 0.3.1","moment":">= 1.7.0","geolib":">= 1.1.8","validator":">= 0.4.5","accounting":">= 0.3.2","ember-metal-node":">= 1.0.0-pre.2","ember-runtime-node":">= 1.0.0-pre.2","ember-states-node":">= 1.0.0-pre.2","ember-application-node":">= 1.0.0-pre.2","ember-routing-node":">= 1.0.0-pre.2","useragent":">= 1.0.5","connect":">= 2.4.6","fresh":">= 0.1.0","express":"3.x","URIjs":"~1.7.2","which":"~1.0.5","superagent":"~0.9.5","crc":"~0.2.0","ansi":"~0.1.2","term-css":"~1.0.0","wrench":"~1.3.9","gm":"~1.4.1","temp":"~0.4.0","grunt-contrib-less":"~0.3.0"},"devDependencies":{},"testDependencies":{"coffee-script":"~1.3.3","stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.10","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","Faker":">= 0.1.3","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node’s Connect and Express, modeled after Ruby on Rails.  Built for the client *and* server, from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we’re going. If you’re up for it, please contribute!\n\nThe 0.5.0 release will have most of the features, and will roughly be equivalent to a beta release. From there, it’s performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nThe `master` branch will always be functional, and (for the most part) in sync with the version you can install from the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database, it’s optional. Tower can just be used in the browser)\n- Redis (background jobs, also optional)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and AJAX), and MongoDB support.  Tower is modeled after ActiveRecord and Mongoid for Ruby. Includes a controller architecture that works the same for both client and server, modeled after Rails.  The routing API is like that of Rails 3.  Templates also work on client and server—and you can swap in any template engine, no problem.  Includes asset pipeline that works just like Rails 3 (minifies and gzips assets with an md5-hashed name for optimal browser caching, if you desire).  And it includes a watcher that automatically injects javascripts and stylesheets into the browser *as you develop*.\n\nIt solves a lot of our problems. We hope it solves yours, too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool, and `coffee-script`:\n\n```\nnpm install grunt -g\nnpm install coffee-script -g\n```\n\nFinally, make sure you have `mongodb` installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start `redis`:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\nIn your terminal, generate your app and start your server:\n\n```\ntower new app\ncd app\nnpm install\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nThen, in a second terminal, start the watcher. This will automatically compile  files when they change:\n\n```\ncd app\ncake watch\n```\n\nBy having two separate windows, you can modify your code without having to run your server, and coffeescript/stylus/less tasks will still be executed.  (And the same goes for any task in your `grunt` file.)\n\nAlso note, grunt’s watcher doesn’t currently get notified when new files are created. So if you run the `tower generate` command (or otherwise create files), stop and rerun the `cake watch` command. You also might want to check out `grunt-contrib-watch`, which was recently created, and may solve this issue. (I haven’t tried it yet, though.)\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo automatically restart your server if it crashes, run with `forever`:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n\n  @hasOne 'address', embed: true\n\n  @hasMany 'posts'\n  @hasMany 'comments'\n\n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n\n  @validates 'firstName', 'email', presence: true\n\n  @after 'create', 'welcome'\n\n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n\n  @belongsTo 'author', type: 'User'\n\n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n\n  @before 'validate', 'slugify'\n\n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n\n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n\n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n\n  @resources 'posts', ->\n    @resources 'comments'\n\n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n\n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n\n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n\n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n\n  create: ->\n    @post = App.Post.build(@params.post)\n\n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n\n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n\n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n\n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n\n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It’s much more powerful than Jade, and it’s just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt’s all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that’s built in!  So for the simple case you don’t even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do its thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware, so you have access to `request` and `response` objects—just like you would on the server.\n\n## Middleware\n\nIt’s built on [connect](http://github.com/sencha/connect), so you can use any  middleware library you like.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n\n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n\n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n\n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere’s the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor` (and wherever else you might put things).  The default is to use Stylus for CSS in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify *exactly* how you want to compile your files for the client, to ensure it’s as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:bundle\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\nnpm install\nmake install-dependencies\n```\n\n### Building Tower\n\nYou can build tower manually with:\n\n```\nmake\n```\n\nOr, you can have it recompile files whenever you change them:\n\n```\nmake watch\n```\n\n### “Linking” Tower\n\nYou can symlink your local tower repository to your global npm `node_modules` directory, which allows you use it in your apps. That way, if you make changes to the tower repository, you’ll see them in your app! Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don’t have `phantomjs`, you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","readmeFilename":"README.md","_id":"tower@0.4.2-24","dist":{"shasum":"2243cf913cc662a3d17b71622848c49b7b2c3389","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-24.tgz","integrity":"sha512-IihGEA1f1AcQyC4WeCVLHTACOUBpeqTkMnZn1abMQNmgfOuHJS0g2n0PpfXvRFMMJiSSsY7oqfqnpRvk5/GtHg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEMkmV+JnQhTkkbZTD6SHKerbaNJ6tbw7tHhESCqRDdkAiEA6HLPSv347G/kczpTJo06ARyRox7gvGcKC9op7crKWO0="}]},"_npmVersion":"1.1.69","_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"}},"0.4.2-25":{"name":"tower","version":"0.4.2-25","description":"Full Stack Web Framework for Node.js and the Browser","homepage":"http://viatropos.github.com/tower","main":"./index.js","author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"keywords":["mvc","web-framework","ruby-on-rails","express","tower","framework","rails","node"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"edubkendo"},{"name":"TheHydroImpulse","email":"dnfagnan@gmail.com"},{"name":"Sebastian Hoitz"},{"name":"scottkf","email":"scott@tesoriere.com"},{"name":"Jai-gouk Kim"},{"name":"Dave Myron"},{"name":"Vyacheslav Voronchuk"},{"name":"j-mcnally"},{"name":"abovethewater"},{"name":"Nov Matake"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/viatropos/tower/issues"},"repository":{"type":"git","url":"https://github.com/viatropos/tower.git"},"engines":{"node":">= 0.6.0"},"directories":{"lib":"./lib"},"bin":{"tower":"./bin/tower"},"dependencies":{"underscore":">= 1.4.2","underscore.string":">= 2.x","inflection":">= 1.2.3","commander":">= 1.0.5","mime":">= 1.2.4","node-uuid":">= 1.3.0","ejs":">= 0.6.1","async":">= 0.1.12","mint":">= 0.3.4","qs":">= 0.3.1","moment":">= 1.7.0","geolib":">= 1.1.8","validator":">= 0.4.5","accounting":">= 0.3.2","ember-metal-node":">= 1.0.0-pre.2","ember-runtime-node":">= 1.0.0-pre.2","ember-states-node":">= 1.0.0-pre.2","ember-application-node":">= 1.0.0-pre.2","ember-routing-node":">= 1.0.0-pre.2","useragent":">= 1.0.5","connect":">= 2.4.6","fresh":">= 0.1.0","express":"3.x","URIjs":"~1.7.2","which":"~1.0.5","superagent":"~0.9.5","crc":"~0.2.0","ansi":"~0.1.2","term-css":"~1.0.0","wrench":"~1.3.9","gm":"~1.4.1","temp":"~0.4.0","grunt-contrib-less":"~0.3.0"},"devDependencies":{},"testDependencies":{"coffee-script":"~1.3.3","stylus":">= 0.29.0","uglify-js":">= 1.1.1","mocha":">= 1.5.0","chai":">= 0.3.3","sinon":">= 1.3.1","eco":">= 0.1.0","mustache":">= 0.4.0","jade":">= 0.22.0","kue":">= 0.3.4","mongodb":">= 1.1.10","coffeecup":">= 0.3.17","gzip":">= 0.1.0","chokidar":"~0.4.0","knox":"0.0.11","socket.io":">= 0.9.10","socket.io-client":">= 0.9.10","fibers":"~0.6.8","cli-table":"0.0.2","ttys":"0.0.3","cheerio":">= 0.10.0","Faker":">= 0.1.3","colors":"~0.6.0-1"},"globalDependencies":{},"localDependencies":{},"scripts":{"test":"make test","start":"grunt start --config ./grunt.coffee","docs":"make docs"},"readme":"# Tower.js <img src=\"http://cloud.github.com/downloads/viatropos/tower/tower.png\"/>\n\n> Full Stack Web Framework for Node.js and the Browser.\n\nBuilt on top of Node’s Connect and Express, modeled after Ruby on Rails.  Built for the client *and* server, from the ground up.\n\n[![Build Status](https://secure.travis-ci.org/viatropos/tower.png)](http://travis-ci.org/viatropos/tower)\n\nFollow me [@viatropos](http://twitter.com/viatropos).\n\n- **IRC**: #towerjs on irc.freenode.net\n- **Issues**: https://github.com/viatropos/tower/issues\n- **Ask a question**: http://stackoverflow.com/questions/tagged/towerjs\n- **Roadmap**: https://github.com/viatropos/tower/blob/master/ROADMAP.md\n- **Latest Docs**: https://github.com/viatropos/tower/wiki\n\nNote, Tower is still very early alpha. Check out the [roadmap](https://github.com/viatropos/tower/blob/master/ROADMAP.md) to see where we’re going. If you’re up for it, please contribute!\n\nThe 0.5.0 release will have most of the features, and will roughly be equivalent to a beta release. From there, it’s performance optimization, workflow streamlining, and creating some awesome examples. 1.0 will be a plug-and-chug real-time app framework.\n\nThe `master` branch will always be functional, and (for the most part) in sync with the version you can install from the npm registry.\n\n## Default Development Stack\n\n- Ember\n- jQuery\n- Handlebars (templating)\n- Stylus (LESS is also supported)\n- MongoDB (database, it’s optional. Tower can just be used in the browser)\n- Redis (background jobs, also optional)\n- Mocha (tests)\n- CoffeeScript\n- Twitter Bootstrap\n\nIncludes a database-agnostic ORM with browser (memory and AJAX), and MongoDB support.  Tower is modeled after ActiveRecord and Mongoid for Ruby. Includes a controller architecture that works the same for both client and server, modeled after Rails.  The routing API is like that of Rails 3.  Templates also work on client and server—and you can swap in any template engine, no problem.  Includes asset pipeline that works just like Rails 3 (minifies and gzips assets with an md5-hashed name for optimal browser caching, if you desire).  And it includes a watcher that automatically injects javascripts and stylesheets into the browser *as you develop*.\n\nIt solves a lot of our problems. We hope it solves yours, too.\n\n## Install\n\n```\nnpm install tower -g\n```\n\nYou will also need [grunt](https://github.com/cowboy/grunt), an awesome build tool, and `coffee-script`:\n\n```\nnpm install grunt -g\nnpm install coffee-script -g\n```\n\nFinally, make sure you have `mongodb` installed and running:\n\n```\nbrew install mongodb\nmongod # starts server\n```\n\nIf you would like to try out the background-worker code, you can also install and start `redis`:\n\n```\nbrew install redis\nredis-server\n```\n\n## Generate\n\nIn your terminal, generate your app and start your server:\n\n```\ntower new app\ncd app\nnpm install\ntower generate scaffold Post title:string body:text\ntower generate scaffold User firstName:string lastName:string email:string\nnode server\n```\n\nThen, in a second terminal, start the watcher. This will automatically compile  files when they change:\n\n```\ncd app\ncake watch\n```\n\nBy having two separate windows, you can modify your code without having to run your server, and coffeescript/stylus/less tasks will still be executed.  (And the same goes for any task in your `grunt` file.)\n\nAlso note, grunt’s watcher doesn’t currently get notified when new files are created. So if you run the `tower generate` command (or otherwise create files), stop and rerun the `cake watch` command. You also might want to check out `grunt-contrib-watch`, which was recently created, and may solve this issue. (I haven’t tried it yet, though.)\n\nIf you run into an error during `npm install`, remove the `node_modules` folder and try again.\n\nTo automatically restart your server if it crashes, run with `forever`:\n\n```\nnpm install forever -g\nforever server.js\n```\n\n## Application\n\n``` coffeescript\n# app/config/shared/application.coffee\nglobal.App = Tower.Application.create()\n```\n\n## Models\n\n``` coffeescript\n# app/models/shared/user.coffee\nclass App.User extends Tower.Model\n  @field 'firstName', required: true\n  @field 'lastName'\n  @field 'email', format: /\\w+@\\w+.com/\n  @field 'activatedAt', type: 'Date', default: -> new Date()\n\n  @hasOne 'address', embed: true\n\n  @hasMany 'posts'\n  @hasMany 'comments'\n\n  @scope 'recent', -> createdAt: '>=': -> _(3).days().ago().toDate()\n\n  @validates 'firstName', 'email', presence: true\n\n  @after 'create', 'welcome'\n\n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n```\n\n``` coffeescript\n# app/models/shared/post.coffee\nclass App.Post extends Tower.Model\n  @field 'title'\n  @field 'body'\n  @field 'tags', type: ['String'], default: []\n  @field 'slug'\n\n  @belongsTo 'author', type: 'User'\n\n  @hasMany 'comments', as: 'commentable'\n  @hasMany 'commenters', through: 'comments', type: 'User'\n\n  @before 'validate', 'slugify'\n\n  slugify: ->\n    @set 'slug', @get('title').replace(/[^a-z0-9]+/g, '-').toLowerCase()\n```\n\n``` coffeescript\n# app/models/shared/comment.coffee\nclass App.Comment extends Tower.Model\n  @field 'message'\n\n  @belongsTo 'author', type: 'User'\n  @belongsTo 'commentable', polymorphic: true\n```\n\n``` coffeescript\n# app/models/shared/address.coffee\nclass App.Address extends Tower.Model\n  @field 'street'\n  @field 'city'\n  @field 'state'\n  @field 'zip'\n  @field 'coordinates', type: 'Geo'\n\n  @belongsTo 'user', embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nApp.User\n  .where(createdAt: '>=': _(2).days().ago(), '<=': new Date())\n  .desc('createdAt')\n  .asc('firstName')\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser  = App.User.first()\n\n# hasMany 'posts'\nposts = user.get('posts').where(title: 'First Post').first()\npost  = user.get('posts').build(title: 'A Post!')\npost  = user.get('posts').create(title: 'A Saved Post!')\nposts = user.get('posts').all()\n\npost  = App.Post.first()\n\n# belongsTo 'author'\nuser  = post.get('author')\n```\n\n### Validations\n\n``` coffeescript\nuser = App.User.build()\nuser.save()         #=> false\nuser.get('errors')  #=> {\"email\": [\"Email must be present\"]}\nuser.set('email', 'me@gmail.com')\nuser.save()         #=> true\nuser.get('errors')  #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nApp.routes ->\n  @match '/login', 'sessions#new', via: 'get', as: 'login'\n  @match '/logout', 'sessions#destroy', via: 'get', as: 'logout'\n\n  @resources 'posts', ->\n    @resources 'comments'\n\n  @namespace 'admin', ->\n    @resources 'users'\n    @resources 'posts', ->\n      @resources 'comments'\n\n  @constraints subdomain: /^api$/, ->\n    @resources 'posts', ->\n      @resources 'comments'\n\n  @match '(/*path)', to: 'application#index', via: 'get'\n```\n\n## Controllers\n\n``` coffeescript\n# app/controllers/server/postsController.coffee\nclass App.PostsController extends Tower.Controller\n  index: ->\n    App.Post.all (error, posts) =>\n      @render 'index', locals: posts: posts\n\n  new: ->\n    @post = App.Post.build()\n    @render 'new'\n\n  create: ->\n    @post = App.Post.build(@params.post)\n\n    super (success, failure) ->\n      @success.html => @render 'posts/edit'\n      @success.json => @render text: 'success!'\n      @failure.html => @render text: 'Error', status: 404\n      @failure.json => @render text: 'Error', status: 404\n\n  show: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'show'\n\n  edit: ->\n    App.Post.find @params.id, (error, post) =>\n      @render 'edit'\n\n  update: ->\n    App.Post.find @params.id, (error, post) =>\n      post.updateAttributes @params.post, (error) =>\n        @redirectTo action: 'show'\n\n  destroy: ->\n    App.Post.find @params.id, (error, post) =>\n      post.destroy (error) =>\n        @redirectTo action: 'index'\n```\n\n## Views\n\nViews are all Ember.\n\n## Templates\n\nTemplates adhere to the [Twitter Bootstrap 2.x](http://twitter.github.com/bootstrap/) markup conventions.\n\nThe default templating engine is [CoffeeCup](http://easydoc.org/coffeecup), which is pure CoffeeScript.  It’s much more powerful than Jade, and it’s just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Mint.js](http://github.com/viatropos/mint.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Styles\n\nIt’s all using Twitter Bootstrap, so check out their docs.  http://twitter.github.com/bootstrap/\n\nActually, all that’s built in!  So for the simple case you don’t even need to write anything in your controllers (skinny controllers, fat models).  The default implementation is actually a lot more robust than that, just wanted to show a simple example.\n\n## Databases\n\n``` coffeescript\n# app/config/server/databases.coffee\nmodule.exports =\n  mongodb:\n    development:\n      name: 'app-development'\n      port: 27017\n      host: '127.0.0.1'\n    test:\n      name: 'app-test'\n      port: 27017\n      host: '127.0.0.1'\n    staging:\n      name: 'app-staging'\n      port: 27017\n      host: '127.0.0.1'\n    production:\n      name: 'app-production'\n      port: 27017\n      host: '127.0.0.1'\n```\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: 'me@gmail.com'\n```\n\n## Internationalization\n\n``` coffeescript\n# app/config/shared/locales/en.coffee\nmodule.exports =\n  hello: 'world'\n  forms:\n    titles:\n      signup: 'Signup'\n  pages:\n    titles:\n      home: 'Welcome to %{site}'\n  posts:\n    comments:\n      none: 'No comments'\n      one: '1 comment'\n      other: '%{count} comments'\n  messages:\n    past:\n      none: 'You never had any messages'\n      one: 'You had 1 message'\n      other: 'You had %{count} messages'\n    present:\n      one: 'You have 1 message'\n    future:\n      one: 'You might have 1 message'\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do its thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\n```\n\nThose methods pass through the router and client-side middleware, so you have access to `request` and `response` objects—just like you would on the server.\n\n## Middleware\n\nIt’s built on [connect](http://github.com/sencha/connect), so you can use any  middleware library you like.\n\n## Assets\n\n``` coffeescript\n# app/config/server/assets.coffee\nmodule.exports =\n  javascripts:\n    vendor: [\n      '/vendor/javascripts/jquery.js'\n      '/vendor/javascripts/underscore.js'\n      '/vendor/javascripts/socket.io'\n      '/vendor/javascripts/tower.js'\n    ]\n\n    lib: [\n      '/lib/grid.js'\n      '/lib/profiler.js'\n    ]\n\n    application: [\n      '/app/models/shared/post.js'\n      '/app/models/shared/comment.js'\n    ]\n\n  stylesheets:\n    vendor: [\n      '/vendor/stylesheets/reset.css'\n    ]\n    application: [\n      '/app/assets/stylesheets/application.css'\n      '/app/assets/stylesheets/theme.css'\n    ]\n```\n\n## Structure\n\nHere’s the structure of a newly generated app with a `Post` model:\n\n```\n.\n├── app\n│   ├── config\n│   │   ├── client\n│   │   │   ├── bootstrap.coffee\n│   │   │   └── watch.coffee\n│   │   ├── server\n│   │   │   ├── environments\n│   │   │   │   ├── development.coffee\n│   │   │   │   ├── production.coffee\n│   │   │   │   └── test.coffee\n│   │   │   ├── initializers\n│   │   │   ├── assets.coffee\n│   │   │   ├── bootstrap.coffee\n│   │   │   ├── credentials.coffee\n│   │   │   ├── databases.coffee\n│   │   │   └── session.coffee\n│   │   └── shared\n│   │       ├── locales\n│   │       │   └── en.coffee\n│   │       ├── application.coffee\n│   │       └── routes.coffee\n│   ├── controllers\n│   │   ├── client\n│   │   │   ├── applicationController.coffee\n│   │   │   └── postsController.coffee\n│   │   └── server\n│   │       ├── applicationController.coffee\n│   │       └── postsController.coffee\n│   ├── models\n│   │   ├── client\n│   │   ├── server\n│   │   └── shared\n│   │       └── post.coffee\n│   ├── stylesheets\n│   │   ├── client\n│   │   │   └── application.styl\n│   │   └── server\n│   │       └── email.styl\n│   ├── templates\n│   │   ├── server\n│   │   │   └── layout\n│   │   │       ├── _meta.coffee\n│   │   │       └── application.coffee\n│   │   └── shared\n│   │       ├── layout\n│   │       │   ├── _body.coffee\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _footer.coffee\n│   │       │   ├── _header.coffee\n│   │       │   ├── _navigation.coffee\n│   │       │   └── _sidebar.coffee\n│   │       ├── posts\n│   │       │   ├── _flash.coffee\n│   │       │   ├── _form.coffee\n│   │       │   ├── _item.coffee\n│   │       │   ├── _list.coffee\n│   │       │   ├── _table.coffee\n│   │       │   ├── edit.coffee\n│   │       │   ├── index.coffee\n│   │       │   ├── new.coffee\n│   │       │   └── show.coffee\n│   │       └── welcome.coffee\n│   └── views\n│       └── client\n│           ├── layout\n│           │   └── application.coffee\n│           └── posts\n│               ├── form.coffee\n│               ├── index.coffee\n│               └── show.coffee\n├── data\n│   └── seeds.coffee\n├── lib\n├── log\n├── public\n│   ├── fonts\n│   ├── images\n│   ├── javascripts\n│   ├── stylesheets\n│   ├── swfs\n│   ├── uploads\n│   ├── 404.html\n│   ├── 500.html\n│   ├── favicon.ico\n│   ├── humans.txt\n│   └── robots.txt\n├── scripts\n│   └── tower\n├── test\n│   ├── cases\n│   │   ├── controllers\n│   │   │   ├── client\n│   │   │   └── server\n│   │           └── postsControllerTest.coffee\n│   │   ├── features\n│   │   │   └── client\n│   │   └── models\n│   │       ├── client\n│   │       ├── server\n│   │       └── shared\n│   │           └── postTest.coffee\n│   ├── factories\n│   │   └── postFactory.coffee\n│   ├── client.coffee\n│   ├── mocha.opts\n│   └── server.coffee\n├── tmp\n├── wiki\n│   ├── _sidebar.md\n│   └── home.md\n├── Cakefile\n├── grunt.coffee\n├── package.json\n├── Procfile\n├── README.md\n└── server.js\n```\n\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor` (and wherever else you might put things).  The default is to use Stylus for CSS in `/app/assets/stylesheets`.\n\nBy having this `assets.coffee` file, you can specify *exactly* how you want to compile your files for the client, to ensure it’s as optimized and cacheable as possible in production.\n\n### Minify and Gzip\n\n``` bash\ncake assets:bundle\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Test\n\n``` bash\nnpm test\n```\n\nRun individual test file:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\")\n```\n\nRun test matching pattern:\n\n``` bash\nmocha $(find test -name \"*persistenceTest.coffee\") -g \"string property$\"\n```\n\nRun tests matching directory and pattern:\n\n``` bash\nmocha $(find test -name \"*Test.coffee\" | egrep \"/*view*/\")\n```\n\n[Run tests *not* matching directory and pattern](http://stackoverflow.com/a/12255734/169992):\n\n``` bash\n# run all tests except for client tests\nmocha $(find test -name client -prune -o -name '*Test.coffee' -print)\n```\n\n## Examples\n\n- [Facebook/Twitter Authentication (Passport)](https://github.com/viatropos/tower-authentication-example)\n- [towerjs.org (project site)](https://github.com/viatropos/towerjs.org)\n\n## Contributing to Tower\n\n```\ngit clone https://github.com/viatropos/tower.git\ncd tower\nnpm install\nmake install-dependencies\n```\n\n### Building Tower\n\nYou can build tower manually with:\n\n```\nmake\n```\n\nOr, you can have it recompile files whenever you change them:\n\n```\nmake watch\n```\n\n### “Linking” Tower\n\nYou can symlink your local tower repository to your global npm `node_modules` directory, which allows you use it in your apps. That way, if you make changes to the tower repository, you’ll see them in your app! Very useful.\n\nIn the tower repo:\n\n```\nnpm link\n```\n\nIn a tower app:\n\n```\nnpm link tower\n```\n\nIf you want to try installing tower from the remote npm registry, you can just unlink it and run `npm install`:\n\n```\nnpm unlink tower\nnpm install tower\n```\n\nUsing `npm link` makes it very easy to mess with the source.\n\n### Running Tests\n\nIn the tower repo, run server tests with:\n\n```\nmake test-server\n```\n\nTo run client tests, first compile the test app and start its server:\n\n```\nmake build-test-client\nmake start-test-client\n```\n\nThen run the tests (uses phantomjs)\n\n```\nmake test-client\n```\n\nIf you don’t have `phantomjs`, you can install it with:\n\n```\nbrew install phantomjs\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","readmeFilename":"README.md","_id":"tower@0.4.2-25","dist":{"shasum":"afc6455f2d1d6fdc9617dc9e30933e129031e089","tarball":"https://registry.npmjs.org/tower/-/tower-0.4.2-25.tgz","integrity":"sha512-Se/LdlfLIWFz8N97+CS19XFm4AfouPBn4PIPMgjFLOwoMXZgHJjwEbOXwycrktYFGDHtsLNenf8SL6V3qQiiRA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHQbWKqEJQiXtWUeXdv+PC8Epx95eKUmh3Zk/aQFNyi+AiEA8bEU4yEFiEpUq6oU0r3OqOkm7Lim9KzPQxnp+q/XmJk="}]},"_npmVersion":"1.1.69","_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"}},"0.5.0":{"name":"tower","version":"0.5.0","main":"./index.js","description":"Small components for building apps, manipulating data, and managing a distributed infrastructure.","homepage":"http://towerjs.org/","keywords":["mvc","web-framework","express","tower","framework","node","client","server"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"abovethewater"},{"name":"Dave Myron"},{"name":"edubkendo"},{"name":"j-mcnally"},{"name":"Jai-gouk Kim"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"},{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"Nov Matake"},{"name":"scottkf","email":"scott@tesoriere.com"},{"name":"Sebastian Hoitz"},{"name":"TheHydroImpulse","email":"dnfagnan@gmail.com"},{"name":"Vyacheslav Voronchuk"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/tower/tower/issues"},"repository":{"type":"git","url":"https://github.com/tower/tower.git"},"engines":{"node":">= 0.10.0"},"dependencies":{"tower-cli":"0.1.0","tower-resource":"0.1.0","tower-query":"0.1.0","tower-adapter":"0.1.0","tower-router":"0.1.0","tower-route":"0.1.0","tower-validator":"0.1.0","tower-type":"0.1.0","tower-memory-adapter":"0.1.0"},"devDependencies":{},"readme":"# Tower\n\nSmall components for building apps, manipulating data, and managing a distributed infrastructure.\n\nTower is very low level now. It has minimal dependencies. It doesn't depend on jQuery, underscore, mongodb, or any such \"limiting\" factor. It's all JavaScript. Each micro component is around 1kb, so if you wanted to make things super lean, you can just grab the bare bones you need.\n\nThe source for the guides on the site are here: https://github.com/tower/guides. They're very much a work in progress.\n\n## Installation\n\nnode.js:\n\n```bash\n$ npm install tower\n```\n\nbrowser:\n\n```bash\n$ component install tower/tower\n```\n\n## Example\n\nThis main module is just a collection of small, individual components to make it easy to get going. See the `/tower/<name>` repositories for details on how to use each one. Enjoy!\n\n```js\nvar tower = require('tower');\n\ntower.resource;\ntower.query;\ntower.adapter;\ntower.router;\ntower.route;\ntower.validator;\ntower.type;\ntower.memory;\n```\n\nAll of those modules are available on both the client and the server.\n\nIf you're on the client, you also have template rendering components (they're just about ready for the server too):\n\n```js\ntower.template;\ntower.content;\ntower.directive;\n```\n\n## License\n\nMIT.","readmeFilename":"README.md","_id":"tower@0.5.0","dist":{"shasum":"dbfdd4e95645f4384b30ea4bbb1542dd270a826b","tarball":"https://registry.npmjs.org/tower/-/tower-0.5.0.tgz","integrity":"sha512-iRlVRF8h1+NaRJ+Xp3LvI9awrA/eZxrCKE9qxKAtYnlqtHaMu9YfJIE7G/2YbilKH+TO7mNIhwb3ve5pDEnmcA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDM1bWxKB7307vQrwUzFy9svkkSOAG/LlUuUT2zWpVHSgIhAP/U4FvVdzkMpBQIn3J2TqlQ+hKV+6CtxBNKIK6ZoDYr"}]},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"},"directories":{}},"0.5.1":{"name":"tower","version":"0.5.1","main":"./index.js","description":"Small components for building apps, manipulating data, and managing a distributed infrastructure.","homepage":"http://towerjs.org/","keywords":["mvc","web-framework","express","tower","framework","node","client","server"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"abovethewater"},{"name":"Dave Myron"},{"name":"edubkendo"},{"name":"j-mcnally"},{"name":"Jai-gouk Kim"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"},{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"Nov Matake"},{"name":"scottkf","email":"scott@tesoriere.com"},{"name":"Sebastian Hoitz"},{"name":"TheHydroImpulse","email":"dnfagnan@gmail.com"},{"name":"Vyacheslav Voronchuk"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/tower/tower/issues"},"repository":{"type":"git","url":"https://github.com/tower/tower.git"},"engines":{"node":">= 0.10.0"},"bin":{"tower":"./bin/tower"},"dependencies":{"commander":"*","tower-server":"*","tower-cookbook":"*","tower-console":"*","tower-fs":">= 0.5.0-pre2","tower-resource":"0.1.0","tower-query":"0.1.0","tower-adapter":"0.1.0","tower-router":"0.1.0","tower-route":"0.1.0","tower-validator":"0.1.0","tower-type":"0.1.0","tower-memory-adapter":"0.1.0"},"readme":"# Tower.js\n\nSmall components for building apps, manipulating data, and managing a distributed infrastructure.\n\nTower is very low level now. It has minimal dependencies. It doesn't depend on jQuery, underscore, mongodb, or any such \"limiting\" factor. It's all JavaScript. Each micro component is around 1kb, so if you wanted to make things super lean, you can just grab the bare bones you need.\n\nSome things that were in 0.4.0 aren't there yet in 0.5.0, in particular relations. However, the new way you build modules makes writing these things much easier. This time around solid API principles are in place. Everything must be fast (performance), small (file size), and simple, so it requires minimal mental energy to dig into the code. Needless to say, this is still super alpha software.\n\nIf there's anything in particular you're wondering about, join in the #towerjs IRC.\n\nThe source for the guides on the site are here: https://github.com/tower/guides. They're very much a work in progress.\n\n## Installation\n\nnode.js:\n\n```bash\n$ npm install tower\n```\n\nto get the cli:\n\n```bash\n$ npm install tower-cli -g\n```\n\nbrowser:\n\n```bash\n$ component install tower/tower\n```\n\nThis is installed through [component](https://github.com/component/component).\n\n## Example\n\nThis main module is just a collection of tiny components to make it easy to get going. See the [individual repositories](https://github.com/tower) for details on how to use each one. Enjoy!\n\n```js\nvar tower = require('tower');\n\ntower.resource;\ntower.query;\ntower.adapter;\ntower.router;\ntower.route;\ntower.validator;\ntower.type;\ntower.memory;\n```\n\nAll of those modules are available on both the client and the server.\n\nIf you're on the client, you also have template rendering components (they're just about ready for the server too):\n\n```js\ntower.template;\ntower.content;\ntower.directive;\n```\n\n## Tower Cli\n\n```bash\n$ tower <verb> <object> [options]\n```\n\n### Examples\n\n```bash\n$ tower create recipe my-recipe\n$ tower install recipe my-recipe\n$ tower start mongodb\n$ tower stop mongodb\n$ tower enter mongodb\n$ tower start\n$ tower stop\n```\n\n## License\n\nMIT.","readmeFilename":"README.md","_id":"tower@0.5.1","dist":{"shasum":"96895c4205c3a08b4fabd4cd50191494be85a28c","tarball":"https://registry.npmjs.org/tower/-/tower-0.5.1.tgz","integrity":"sha512-SvT576wrcM0xPjueXd9MUbXgV2QxW6q4oXNvUW/X3ipiqeN5MYuuQHhFJwk7/yH51hW8XAIPVo9kC6+H/+UcdA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF8v9yAsZPva2TM0Ah5VbK2AZnGMl8iKZ8UrNzfaIJMcAiBtNjZf5MO5hIFeXxGtSantG6HI92CEYseei1w6fqSUTg=="}]},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"}},"0.5.11":{"name":"tower","version":"0.5.11","main":"./index.js","description":"Small components for building apps, manipulating data, and managing a distributed infrastructure.","homepage":"http://towerjs.org/","keywords":["mvc","web-framework","express","tower","framework","node","client","server"],"maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"}],"contributors":[{"name":"abovethewater"},{"name":"Dave Myron"},{"name":"edubkendo"},{"name":"j-mcnally"},{"name":"Jai-gouk Kim"},{"name":"Kristian Mandrup","email":"kmandrup@gmail.com"},{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},{"name":"Nov Matake"},{"name":"scottkf","email":"scott@tesoriere.com"},{"name":"Sebastian Hoitz"},{"name":"TheHydroImpulse","email":"dnfagnan@gmail.com"},{"name":"Vyacheslav Voronchuk"}],"licenses":[{"type":"MIT","url":"http://mths.be/mit"}],"bugs":{"url":"https://github.com/tower/tower/issues"},"repository":{"type":"git","url":"https://github.com/tower/tower.git"},"engines":{"node":">= 0.10.0"},"bin":{"tower":"./bin/tower"},"dependencies":{"commander":"*","tower-server":"*","tower-cookbook":"*","tower-console":"*","tower-fs":">= 0.5.0-pre2","tower-resource":"0.1.0","tower-query":"0.1.0","tower-adapter":"0.1.0","tower-router":"0.1.0","tower-route":"0.1.0","tower-validator":"0.1.0","tower-type":"0.1.0","tower-memory-adapter":"0.1.0"},"readme":"# Tower.js\n\nSmall components for building apps, manipulating data, and managing a distributed infrastructure.\n\nTower is very low level now. It has minimal dependencies. It doesn't depend on jQuery, underscore, mongodb, or any such \"limiting\" factor. It's all JavaScript. Each micro component is around 1kb, so if you wanted to make things super lean, you can just grab the bare bones you need.\n\nSome things that were in 0.4.0 aren't there yet in 0.5.0, in particular relations. However, the new way you build modules makes writing these things much easier. This time around solid API principles are in place. Everything must be fast (performance), small (file size), and simple, so it requires minimal mental energy to dig into the code. Needless to say, this is still super alpha software.\n\nIf there's anything in particular you're wondering about, join in the #towerjs IRC.\n\nThe source for the guides on the site are here: https://github.com/tower/guides. They're very much a work in progress.\n\n## Installation\n\nnode.js:\n\n```bash\n$ npm install tower\n```\n\nto get the cli:\n\n```bash\n$ npm install tower-cli -g\n```\n\nbrowser:\n\n```bash\n$ component install tower/tower\n```\n\nThis is installed through [component](https://github.com/component/component).\n\n## Example\n\nThis main module is just a collection of tiny components to make it easy to get going. See the [individual repositories](https://github.com/tower) for details on how to use each one. Enjoy!\n\n```js\nvar tower = require('tower');\n\ntower.resource;\ntower.query;\ntower.adapter;\ntower.router;\ntower.route;\ntower.validator;\ntower.type;\ntower.memory;\n```\n\nAll of those modules are available on both the client and the server.\n\nIf you're on the client, you also have template rendering components (they're just about ready for the server too):\n\n```js\ntower.template;\ntower.content;\ntower.directive;\n```\n\n## Tower Cli\n\n```bash\n$ tower <verb> <object> [options]\n```\n\n### Examples\n\n```bash\n$ tower create recipe my-recipe\n$ tower install recipe my-recipe\n$ tower start mongodb\n$ tower stop mongodb\n$ tower enter mongodb\n$ tower start\n$ tower stop\n```\n\n## License\n\nMIT.","readmeFilename":"README.md","_id":"tower@0.5.11","dist":{"shasum":"b91d5d1fa03c93d026598037dfdab46d26b2cbe7","tarball":"https://registry.npmjs.org/tower/-/tower-0.5.11.tgz","integrity":"sha512-WG/uz+u5aoG0XGHXnbNJSuqu+Tnm8yN0MwqqDtrJJglTBAKZZ891Jox0F97pbCHUUFSBKqE3/4MmmycKm5YqBw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDU7dj2zT9Hy7sgmpviSeo9OW+KgnOp/TsmEXShzvocIgIhAPc7Q3tgwBjvZzVEfae0XRB5WgPBa7FOWJ5OQgIoGHZZ"}]},"_from":".","_npmVersion":"1.3.8","_npmUser":{"name":"viatropos","email":"lancejpollard@gmail.com"}}},"readme":"# Tower.js\n\n> Full Stack Web Framework for Node.js and the Browser.  Minified & Gzipped: 15.7kb\n\n## Install\n\n``` bash\nnpm install tower -d\n```\n\n## Generator\n\n``` bash\ntower new my-app\n```\n\n## Structure\n\nHere's how you might organize a blog:\n\n``` bash\n.\n|-- app\n|   |-- controllers\n|   |   |-- admin\n|   |   |   |-- postsController.coffee\n|   |   |   `-- usersController.coffee\n|   |   |-- commentsController.coffee\n|   |   |-- postsController.coffee\n|   |   |-- sessionsController.coffee\n|   |   `-- usersController.coffee\n|   |-- models\n|   |   |-- post.coffee\n|   |   `-- user.coffee\n|   |-- views\n|   |   |-- admin\n|   |   |   `-- posts\n|   |   |       |-- _form.coffee\n|   |   |       |-- edit.coffee\n|   |   |       |-- index.coffee\n|   |   |       |-- new.coffee\n|   |   |       |-- show.coffee\n|   |   |-- layouts\n|   |   |   `-- application.coffee\n|   |   |-- shared\n|   |   `-- posts\n|   |       |-- index.coffee\n|   |       `-- show.coffee\n|   `-- helpers\n|       |-- admin\n|       |   |-- postsHelper.coffee\n|       |   `-- tagsHelper.coffee\n|       `-- postsHelper.coffee\n`-- config\n|    |-- application.coffee\n|    |-- locale\n|        `-- en.coffee\n|    |-- routes.coffee\n`-- spec\n|    |-- helper.coffee\n|    |-- models\n|    |   |-- postSpec.coffee\n|    |   |-- userSpec.coffee\n|    `-- acceptance\n|        |-- login.coffee\n|        |-- signup.coffee\n|        `-- posts.coffee\n```\n\n## Application\n\n``` coffeescript\n# config/application.coffee\nclass App extends Tower.Application\n  @config.encoding = \"utf-8\"\n  @config.filterParameters += [\"password\", \"password_confirmation\"]\n  @config.loadPaths += [\"./themes\"]\n  \nApp.initialize()\n```\n\n## Models\n\n``` coffeescript\nclass App.Post extends Tower.Model\n  @field \"title\"\n  @field \"body\"\n  @field \"tags\", type: [\"String\"], default: []\n  @field \"slug\"\n  \n  @key \"slug\"\n  \n  @belongsTo \"author\", type: \"User\"\n  \n  @hasMany \"comments\", as: \"commentable\"\n  @hasMany \"commenters\", through: \"comments\", source: \"author\"\n  \n  @before \"validate\", \"slugify\"\n  \n  slugify: ->\n    @slug = @title.replace(/^[a-z0-9]+/g, \"-\").toLowerCase()\n  \nclass App.Comment extends Tower.Model\n  @field \"message\"\n  \n  @belongsTo \"author\", type: \"User\"\n  @belongsTo \"commentable\", polymorphic: true\n  \nclass App.User extends Tower.Model\n  @field \"firstName\"\n  @field \"lastName\"\n  @field \"email\"\n  @field \"activatedAt\", type: \"Date\", default: -> new Date()\n  \n  @hasOne \"address\", embed: true\n  \n  @hasMany \"posts\"\n  @hasmany \"comments\", through: \"posts\"\n  \n  @scope \"thisWeek\", -> @where(createdAt: \">=\": -> require('moment')().subtract('days', 7))\n  \n  @validate \"firstName\", presence: true\n  \n  @after \"create\", \"welcome\"\n  \n  welcome: ->\n    Tower.Mailer.welcome(@).deliver()\n  \nclass App.Address extends Tower.Model\n  @field \"street\"\n  @field \"city\"\n  @field \"state\"\n  @field \"zip\"\n  @field \"coordinates\", type: \"Geo\"\n  \n  @belongsTo \"user\", embed: true\n```\n\n### Chainable Scopes, Queries, and Pagination\n\n``` coffeescript\nUser\n  .where(createdAt: \">=\": _(2).days().ago(), \"<=\": new Date())\n  .within(radius: 2)\n  .desc(\"createdAt\")\n  .asc(\"firstName\")\n  .paginate(page: 5)\n  .all()\n```\n\n### Associations\n\n``` coffeescript\nuser = User.first()\n\n# hasMany \"posts\"\nposts = user.posts().where(title: \"First Post\").first()\npost  = user.posts().build(title: \"A Post!\")\npost  = user.posts().create(title: \"A Saved Post!\")\nposts = user.posts().all()\n\n# hasMany \"comments\", through: \"posts\"\ncomments  = user.comments().where(message: /(javascript)/).limit(10).all()\n\n# eager load associations\nPost.includes(\"author\").where(author: firstName: \"=~\": \"Baldwin\").all()\nPost.includes(\"author\").where(\"author.firstName\": \"=~\": \"Baldwin\").all()\nUser.includes(\"posts\").where(\"posts.title\": \"Welcome\").all()\n```\n\n### Validations\n\n``` coffeescript\nuser = new User\nuser.save() #=> false\nuser.errors #=> {\"email\": [\"Email must be present\"]}\nuser.email  = \"me@gmail.com\"\nuser.save() #=> true\nuser.errors #=> {}\n```\n\n## Routes\n\n``` coffeescript\n# config/routes.coffee\nTower.Route.draw ->\n  @match \"/login\", \"sessions#new\", via: \"get\", as: \"login\"\n  @match \"/logout\", \"sessions#destroy\", via: \"get\", as: \"logout\"\n  \n  @resources \"posts\", ->\n    @resources \"comments\"\n    \n  @namespace \"admin\", ->\n    @resources \"users\"\n    @resources \"posts\", ->\n      @resources \"comments\"\n      \n  @constraints subdomain: /^api$/, ->\n    @resources \"posts\", ->\n      @resources \"comments\"\n      \n  @match \"(/*path)\", to: \"application#index\", via: \"get\"\n```\n\nRoutes are really just models, `Tower.Route`.  You can add and remove and search them however you like:\n\n``` coffeescript\nTower.Route.where(pattern: \"=~\": \"/posts\").first()\n```\n\n## Views\n\n### Forms\n\n``` coffeescript\n# app/views/posts/new.coffee\nformFor @post, ->\n  fieldset ->\n    legend \"Basic Info\"\n    field \"title\"\n    field \"body\", as: \"text\"\n  submit \"Save\"\n```\n\n### Tables\n\n``` coffeescript\n# app/views/posts/index.coffee\ntableFor @posts, ->\n  thead ->\n    tcell \"Title\"\n    tcell \"Author\"\n  tbody ->\n    for post in @posts\n      trow \n        tcell post.title\n        tcell post.author.name\n  tfoot ->\n    pagination @posts\n```\n\n### Layouts\n\n``` coffeescript\n# app/views/layouts/application.coffee\ndoctype 5\nhtml ->\n  head ->\n    meta charset: 'utf-8'\n    title \"#{@title or 'Untitled'} | My awesome website\"\n    meta name: 'description', content: @desc if @desc?\n    stylesheets \"vendor\", \"application\"\n    javascripts \"vendor\", \"lib\", \"application\"\n  body ->\n    header ->\n      h1 @title or 'Untitled'\n      nav ->\n        ul ->\n          (li -> a href: '/', -> 'Home') unless @path is '/'\n          li -> a href: '/chunky', -> 'Bacon!'\n          switch @user.role\n            when 'owner', 'admin'\n              li -> a href: '/admin', -> 'Secret Stuff'\n            when 'vip'\n              li -> a href: '/vip', -> 'Exclusive Stuff'\n            else\n              li -> a href: '/commoners', -> 'Just Stuff'\n    section ->\n      yield()\n    footer ->\n      p shoutify('bye')\n```\n\nThe default templating engine is [CoffeeKup](http://coffeekup.org/), which is pure coffeescript.  It's much more powerful than Jade, and it's just as performant if not more so.  You can set Jade or any other templating engine as the default by setting `Tower.View.engine = \"jade\"` in `config/application`.  Tower uses [Shift.js](http://github.com/viatropos/shift.js), which is a normalized interface to most of the Node.js templating languages.\n\n## Controllers\n\n``` coffeescript\nclass PostsController extends Tower.Controller\n  index: ->\n    @posts = Post.all()\n    \n  new: ->\n    @post = new Post\n    \n  create: ->\n    @post = new Post(@params.post)\n    \n    super (success, failure) ->\n      @success.html -> @render \"posts/edit\"\n      @success.json -> @render text: \"success!\"\n      @failure.html -> @render text: \"Error\", status: 404\n      @failure.json -> @render text: \"Error\", status: 404\n    \n  show: ->\n    @post = Post.find(@params.id)\n    \n  edit: ->\n    @post = Post.find(@params.id)\n    \n  update: ->\n    @post = Post.find(@params.id)\n    \n  destroy: ->\n    @post = Post.find(@params.id)\n```\n\nActually, all that's built in!  So for the simple case you don't even need to write anything in your controllers (skinny controllers, fat models).\n\n## Mailers\n\n``` coffeescript\nclass App.Notification extends Tower.Mailer\n  # app/views/mailers/welcome.coffee template\n  @welcome: (user) ->\n    @mail to: user.email, from: \"me@gmail.com\"\n```\n\n## Internationalization\n\n``` coffeescript\nen:\n  hello: \"world\"\n  forms:\n    titles:\n      signup: \"Signup\"\n  pages:\n    titles:\n      home: \"Welcome to %{site}\"\n  posts:\n    comments:\n      none: \"No comments\"\n      one: \"1 comment\"\n      other: \"%{count} comments\"\n  messages:\n    past:\n      none: \"You never had any messages\"\n      one: \"You had 1 message\"\n      other: \"You had %{count} messages\"\n    present:\n      one: \"You have 1 message\"\n    future:\n      one: \"You might have 1 message\"\n```\n\n## Helpers\n\nSince all of the controller/routing code is available on the client, you can go directly through that system just like you would the server.\n\n``` coffeescript\n# Just request the url, and let it do it's thing\nTower.get '/posts'\n\n# Same thing, this time passing parameters\nTower.get '/posts', createdAt: \"2011-10-26..2011-10-31\"\n\n# Dynamic\nTower.urlFor(Post.first()) #=> \"/posts/the-id\"\nTower.navigate Tower.urlFor(post)\n```\n\nThose methods pass through the router and client-side middleware so you have access to `request` and `response` objects like you would on the server.\n\n## Middleware\n\nIt's built on [connect](http://github.com/sencha/connect), so you can use any of the middleware libs out there.\n\n## Assets\n\n``` coffeescript\n# config/assets.coffee\nTower.assets =\n  javascripts:\n    vendor: [\n      \"/vendor/javascripts/jquery.js\"\n      \"/vendor/javascripts/underscore.js\"\n      \"/vendor/javascripts/socket.io\"\n      \"/vendor/javascripts/tower.js\"\n    ]\n    \n    lib: [\n      \"/lib/grid.js\"\n      \"/lib/profiler.js\"\n    ]\n    \n    application: [\n      \"/app/models/post.js\"\n      \"/app/models/comment.js\"\n    ]\n    \n  stylesheets:\n    vendor: [\n      \"/vendor/stylesheets/reset.css\"\n    ]\n    application: [\n      \"/app/assets/stylesheets/application.css\"\n      \"/app/assets/stylesheets/theme.css\"\n    ]\n```\n\nAll assets are read from `/public`, which is the compiled output of everything in `/app`, `/lib`, `/vendor`, and wherever else you might put things.  The default is to use stylus for css in `/app/assets/stylesheets`.\n\n### Minify and Gzip\n\n``` bash\ncake assets:compile\n```\n\n### Push to S3\n\n``` bash\ncake assets:publish\n```\n\n## Watchfile\n\n``` coffeescript\nrequire('design.io').extension('watchfile')\n\n# stylesheet watcher\nrequire(\"design.io-stylesheets\")\n  ignore: /(public|node_modules|zzz|less)/\n  outputPath: (path) ->\n    \"public/stylesheets/#{path}\".replace(/\\.(css|styl|less)$/, \".css\")\n\n# javascript watcher\nrequire(\"design.io-javascripts\")\n  ignore:   /(public|node_modules|server|spec.*[sS]pec)/\n  outputPath: (path) ->\n    \"public/javascripts/#{path}\".replace(/\\.(js|coffee)$/, \".js\")\n    \nwatch /app\\/views\\/.+\\.mustache/\n  update: (path) ->\n    # do anything!\n```\n\n## Test, Develop, Minify\n\n``` bash\ncake spec\ncake coffee\ncake minify\n```\n\n## License\n\n(The MIT License)\n\nCopyright &copy; 2012 [Lance Pollard](http://twitter.com/viatropos) &lt;lancejpollard@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","maintainers":[{"name":"viatropos","email":"lancejpollard@gmail.com"},{"name":"thehydroimpulse","email":"dnfagnan@gmail.com"}],"time":{"modified":"2022-06-27T19:11:11.161Z","created":"2011-12-23T03:20:18.093Z","0.3.0":"2011-12-23T03:20:20.536Z","0.3.1":"2012-01-24T01:28:16.307Z","0.3.2":"2012-01-30T21:51:03.454Z","0.3.9":"2012-02-26T06:12:49.593Z","0.3.9-1":"2012-02-26T06:16:59.648Z","0.3.9-2":"2012-02-26T06:23:05.914Z","0.3.9-3":"2012-02-26T06:35:46.769Z","0.3.9-4":"2012-02-26T06:37:12.275Z","0.3.9-5":"2012-02-26T06:42:44.868Z","0.3.9-6":"2012-02-29T01:22:17.831Z","0.3.9-7":"2012-02-29T01:30:59.817Z","0.3.9-8":"2012-03-07T05:54:04.549Z","0.3.9-9":"2012-03-07T06:06:08.039Z","0.3.9-10":"2012-03-09T18:44:36.040Z","0.3.9-11":"2012-03-10T19:27:10.355Z","0.3.9-12":"2012-03-15T06:25:58.847Z","0.3.9-13":"2012-04-03T21:04:29.795Z","0.4.0":"2012-04-03T21:15:03.559Z","0.4.0-2":"2012-04-08T23:45:55.446Z","0.4.0-3":"2012-04-11T23:15:45.113Z","0.4.0-5":"2012-04-15T23:47:48.697Z","0.4.0-6":"2012-04-16T00:45:47.902Z","0.4.0-7":"2012-04-16T00:46:52.672Z","0.4.0-8":"2012-04-16T01:55:48.839Z","0.4.0-9":"2012-04-16T04:28:24.756Z","0.4.0-10":"2012-04-19T08:20:08.343Z","0.4.0-11":"2012-04-26T07:47:49.022Z","0.4.0-12":"2012-04-26T08:03:33.761Z","0.4.0-13":"2012-05-02T16:29:10.631Z","0.4.1":"2012-08-24T02:36:36.003Z","0.4.2-pre":"2012-09-13T08:03:01.825Z","0.4.2-pree":"2012-09-13T08:10:27.952Z","0.4.2":"2012-09-13T08:17:41.922Z","0.4.2-1":"2012-09-13T08:24:32.222Z","0.4.2-2":"2012-09-18T02:43:50.424Z","0.4.2-3":"2012-09-18T04:17:49.633Z","0.4.2-4":"2012-09-26T23:31:37.500Z","0.4.2-5":"2012-10-02T01:48:22.169Z","0.4.2-6":"2012-10-02T03:19:03.547Z","0.4.2-7":"2012-10-02T07:20:26.472Z","0.4.2-8":"2012-10-02T07:37:48.525Z","0.4.2-9":"2012-10-02T10:04:05.151Z","0.4.2-10":"2012-10-02T10:25:34.516Z","0.4.2-11":"2012-10-02T21:03:28.026Z","0.4.2-12":"2012-10-02T21:08:00.085Z","0.4.2-13":"2012-10-06T05:36:06.139Z","0.4.2-14":"2012-10-06T05:45:06.581Z","0.4.2-15":"2012-10-09T04:31:58.619Z","0.4.2-16":"2012-10-09T05:59:51.831Z","0.4.2-17":"2012-10-09T10:21:59.168Z","0.4.2-18":"2012-10-09T11:05:14.025Z","0.4.2-19":"2012-10-09T19:59:32.163Z","0.4.2-20":"2012-10-10T11:19:48.197Z","0.4.2-21":"2012-10-30T01:55:23.423Z","0.4.2-22":"2012-11-02T03:15:05.143Z","0.4.2-23":"2013-02-13T08:00:45.057Z","0.4.2-24":"2013-02-13T08:03:19.958Z","0.4.2-25":"2013-02-13T08:04:45.054Z","0.5.0":"2013-06-24T06:33:51.791Z","0.5.1":"2013-09-10T01:32:34.782Z","0.5.11":"2013-09-12T04:32:27.212Z"},"author":{"name":"Lance Pollard","email":"lancejpollard@gmail.com"},"repository":{"type":"git","url":"https://github.com/tower/tower.git"},"users":{"ebababi":true,"tunnckocore":true}}