npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

praha

v0.0.1

Published

a node.js microframework inspired by rails

Downloads

6

Readme

praha: a node.js micro-framework

Yes, another node.js framework. One that will try to help you while trying not to raising your technical debt.

Features

Current features:

  • Used on top of express.
  • Micro-components only. Nothing is loaded unless you ask for it.
  • Inspired by a framework-hater's use of RoR 4.
  • Intelligent routing inspired by Rail's "before_action".

Coming soon:

  • Kinda a bit Active-Record like objects management.

Goals:

  • Separation of concerns. No two modules must ever be dependent of one another.
  • No intrusive patterns, no DSL to learn, no unexpected behaviours, no "it's my way or the highway",...
  • Only use the minimal amount of "convention-over-configuration" and automation of tasks.

Installation

$ npm install praha

No -g folly. This is designed to ease your life, not make you learn how to use a new CLI tool.

Routing

Just have all your routes together in a folder (or in two or more folders if you feel like a rebel). If you want to follow even better practices, you separate your resources in multiple files (ie: one resource per file seems like a good ratio).

All functions exported from a .js file are mapped to routes based on their export key's name. Since praha is designed to be non-intrusive, your module.exports must also contain a _praha key whose value is truthy to opt-in for usage by praha.

To use the praha router in your express app, simply use it as a middleware with the path to your route folder as an argument.

app.use(require('praha/lib/router')(__dirname + '/routes'));

If you have routes in multiple folders, you can of course use the middleware multiple times.

Default Rails-style mapping

The first way to define routes is to follow Rails conventions: index, show, new, create, edit, update and delete will map to the same routes these methods generate in Rails.

// in a file named "articles.js"
index   // GET /articles
show    // GET /articles/:id
new     // GET /articles/new
create  // POST /articles
edit    // GET /articles/:id/edit
update  // PUT /articles/:id
delete  // DELETE /articles/:id

This should be enough for basic CRUD. Note that you can opt-out any time you want: only use index and show, don't use create and edit,... you're free to go another way.

Custom routes mapping

The second way (custom-diy) is to write your routes in camelCases. If the first word is one of get/post/put/delete, it will be used as the method. Otherwise, the default method is GET. All following words will then tie to a subfolder.

// in a file named "articles.js"
getLatest   // GET /articles/latest
postCurrent     // POST /articles/current

If your route needs to use parameters capture, specify the parameters name in an array tied to the parameters value of your route function. In simpler words:

// in a file named "articles.js"
function getId(req,res,next) {};
function deleteCommentsComment(req,res,next) {};
getId.parameters = ['id'];
deleteIdCommentsComment.parameters = ['id','comment'];

// Will result in
GET /articles/:id
DELETE /articles/:id/comments/:comment

You can also remove the "/articles" prefix (or use another prefix) by setting the _alias key in your exports to false or to the alias string.

// in a file named "sessions.js"
module.exports = {
  _praha: true,
  _alias: false,
  postLogin: function(req,res,next){},
  deleteLogout: function(req,res,next){}
}

// Will result in
POST /login
DELETE /logout

Using beforeAction to tie multiple logics to a route

Similar to Rail's before_action, you can specify multiple middlewares that will be passed before specifics routes. No DSL though. Just set your route's beforeAction key to an array of middlewares you want to pass through.

// in a file named "articles.js"
function getId(req, res, next) { // GET /articles/:id
  // TODO: Render article
}

function putId(req, res, next) { // PUT /articles/:id
  // TODO: Edit article
}

function deleteId(req, res, next) { // DELETE /articles/:id
  // TODO: Delete article
}

function beforeSetArticle(req, res, next) {
  // TODO: Find article in DB and tie it to `req` or 404.
}
function beforeCheckUserIsSelfOrAdmin(req, res, next) {
  // TODO: Check user is playing with his own post or 401
}

[getId, putId, deleteId].forEach(function (c) {
  c.parameters = ['id'];
});

getId.beforeAction = [ beforeSetArticle ];
[getId, putId, deleteId].forEach(function (c) {
  c.beforeAction = [ beforeSetArticle, beforeCheckUserIsSelfOrAdmin ];
});

Here are the routes you will get and the middlewares they will pass through:

GET /articles/:id
- beforeSetArticle
- getId

PUT /articles/:id
- beforeSetArticle
- beforeCheckUserIsSelfOrAdmin
- putId

DELETE /articles:
- beforeSetArticle
- beforeCheckUserIsSelfOrAdmin
- deleteId

Debug

The debug module by visionmedia is used for debugging. Everything runs under the "praha" namespace. To see what goes under the hood, try DEBUG=praha* node app.js.