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

flauta

v0.1.2

Published

A rails-like server-side router for centralized route declaration. Includes path helpers and a printer script to inform you what routes are set and their properties.

Downloads

6

Readme

Flauta

npm flauta license Build Status docs view source on github

Flauta is configuration library that aims to provide a single-location routing DSL for server applications. If you've used Rails before think config/routes.rb. Currently supports only Express.

Some features include:

  • Single file to declare all routes for use with Express.
  • Simple DSL to describe route endpoints; includes regular HTTP verbs, declaring resources, and namespace support.
  • Generated path helper functions for easily returning valid paths, with support for parameter replacements.
  • Script to print out the route declarations in an easy-to-consume format. Invalid routes are printed with the corresponding error.
  • Support for using babel-register in all requires in case you are writing application code that needs to be compiled first.

Install

$ npm install --save flauta

# or

$ yarn add flauta

Usage

  1. Create a routes file somewhere in your server-side code (e.g. server/routes.js).
  2. Populate the routes file with two functions: register and resolve. (See below for description and example)
  3. Import your register function into the server file which creates your Express application and pass the express app to the register function.
  4. Optionally print your route declaration by running flauta path/to/routes.js
  5. Bask in the glory of being able to easily understand which routes your server supports.

Example

Define your routes:

// myapp/server/routes.js
import R from 'ramda'
import flauta from 'flauta'

// Provide a registration function pre-bound to your resolved routes
export const register = (app) => flauta.register(app, resolve())

// Define and resolve your routes. "Resolving" means to require all the controllers and ensure
// the expected handler functions are exported by those modules.
export const resolve = R.once(() => flauta.resolve([

  // Configures the router to look for all your controllers in the server/controllers/ file tree.
  // NOTE: Since flauta will require your controllers for you, the base require path MUST be an
  // aboslute path. I recommend using path.join(__dirname, '../../../path/to/my/controllers')
  // as it will handle relative path resolution to the current directory of the routes.js file.
  flauta.namespace({path: '/', require: path.join(__dirname, 'controllers')}, [

    // Creates a route for the path / to be served by your server/controllers/home.js controller
    // with the exported function 'root' handling the request.
    flauta.get('/', 'home', 'root'),

    // If the resource doesn't have a corresponding controller it won't be registered
    // and a warning will be printed when you print your route definitions (see below).
    flauta.resource('bogus'),

    // Nested namespaces join url and require paths with their parent
    flauta.namespace({path: 'api/v1', require: 'api/v1'}, [
      // Creates 5 endpoints for working with the "users" resource:
      // + GET /api/v1/users (handler = index)
      // + GET /api/v1/users/:id (handler = show)
      // + POST /api/v1/users (handler = create)
      // + PATCH /api/v1/users/:id (handler = update)
      // + DELETE /api/v1/users/:id (handler = destroy)
      flauta.resources('users'),

      // Optionally restrict endpoints to register with 'only' or 'except' options:
      flauta.resources('todos', {only: ['index', 'create', 'show']}),

      // The inverse of above is:
      // flauta.resources('todos', {except: ['update', 'destroy']}),

      // ...
    ]),

    // ...
  ]),

  // ...
]))

Then in your server file, import your register function and provide it with your express app:

// server/app.js

import express from 'express'
import { register } from './routes'

const app = express()
register(app)
app.listen(process.env.PORT)

Controller definitions

With flauta, a controller is simply a normal JS file that exports the expected handler functions. These functions are exactly the same as you would write in a normal express app. If you want to have middleware wrapping your endpoint handler just export an array of function references, the last being the route handler.

An example without middleware:

// myapp/server/controllers/home.js

export function root(req, res) {
  res.json({ message: 'Hello, World!' })
}

An example with middelware:

// myapp/server/controllers/home.js

function authMiddleware(req, res, next) { ... }
function loggerMiddleware(req, res, next) { ... }

function rootHandler(req, res) {
  res.json({ message: 'Hello, World!' })
}

export const root = [authMiddleware, loggerMiddleware, rootHandler]

Printing your route definitions

In addition to the nicety of having all your routes defined in one place, we can actually provide a way to print them to see the resolved state of your server side routes, meaning we can know exactly which modules are required and used by our server, and which functions they expose to handle which endpoints. The printer script is also babel-aware.

# If you don't need babel
$ ./node_modules/.bin/flauta path/to/my/routes.js
[Valid Routes]
Path Helper     Verb      URI Pattern          Controller Module                                      Handler
                GET       /                    /code/src/myapp/app/server/controllers/home            root
                POST      /api/v1/users        /code/src/myapp/app/server/controllers/api/v1/users    create
                DELETE    /api/v1/users/:id    /code/src/myapp/app/server/controllers/api/v1/users    destroy
api-v1-users    GET       /api/v1/users        /code/src/myapp/app/server/controllers/api/v1/users    index
api-v1-user     GET       /api/v1/users/:id    /code/src/myapp/app/server/controllers/api/v1/users    show
                PATCH     /api/v1/users/:id    /code/src/myapp/app/server/controllers/api/v1/users    update
                POST      /api/v1/todos        /code/src/myapp/app/server/controllers/api/v1/todos    create
api-v1-todos    GET       /api/v1/todos        /code/src/myapp/app/server/controllers/api/v1/todos    index
api-v1-todo     GET       /api/v1/todos/:id    /code/src/myapp/app/server/controllers/api/v1/todos    show
[Invalid Routes]
Verb      URI Pattern    Controller Module                               Handler    Error
POST      /bogus         /code/src/myapp/app/server/controllers/bogus    create     Cannot find module '/code/src/myapp/app/server/controllers/bogus'
DELETE    /bogus/:id     /code/src/myapp/app/server/controllers/bogus    destroy    Cannot find module '/code/src/myapp/app/server/controllers/bogus'
GET       /bogus         /code/src/myapp/app/server/controllers/bogus    index      Cannot find module '/code/src/myapp/app/server/controllers/bogus'
GET       /bogus/:id     /code/src/myapp/app/server/controllers/bogus    show       Cannot find module '/code/src/myapp/app/server/controllers/bogus'
PATCH     /bogus/:id     /code/src/myapp/app/server/controllers/bogus    update     Cannot find module '/code/src/myapp/app/server/controllers/bogus'
# Or if you need to use babel-register
$ ./node_modules/.bin/flauta --babel -- path/to/my/routes.js

Using path helpers

// myapp/server/routes.js
import R from 'ramda'
import flauta from 'flauta'

export const resolve = R.once(() => flauta.resolve([
  flauta.namespace({path: '/', require: path.join(__dirname, 'controllers')}, [
    flauta.resources('users'),

    flauta.namespace({path: 'api/v1', require: 'api/v1'}, [
      flauta.resources('todos'),
    ]),
  ]),
]))

// somewhere else in your app
import { resolve } from '../path/to/server/routes'

const { paths } = resolve()

paths.users() // => '/users'
paths.user({ id: '123' }) // => '/users/123'

paths['api-v1-todos']() // => '/api/v1/todos'
paths['api-v1-todo']({ id: '123' }) // => '/api/v1/todos/123'