• Stars
    star
    165
  • Rank 228,906 (Top 5 %)
  • Language
    JavaScript
  • License
    BSD 3-Clause "New...
  • Created almost 8 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Use the FS as your micro router

fs-router

Use the FS as your micro router Build Status Coverage Status JavaScript Style Guide

"features"

  • ✅ 0 runtime dependencies
  • ✅ < 100 loc
  • ✅ little or no config
  • ✅ parameterized paths
  • ✅ parses query string

intent

Micro is a fantastic library, but does not come with a router. After using next.js and really enjoying the "fs as router" paradigm, I thought it might be nice to do the same with micro.

This is the simplest approach I could think of to create a flexible router that stays out of your way with an intuitive API.

usage

router usage

// index.js
const { send } = require('micro')
let match = require('fs-router')(__dirname + '/routes')

module.exports = async function(req, res) {
  let matched = match(req)
  if (matched) return await matched(req, res)
  send(res, 404, { error: 'Not found' })
}

The above usage assumes you have a folder called routes next to the index.js file, that looks something like this:

routes/
├── foo
│   └── :param
│       └── thing.js
└── things
    └── :id.js

the above tree would generate the following routes:

/foo/:param/thing
/things/:id

defining a route

// routes/foo/bar.js
const { send } = require('micro')

// respond to specific methods by exposing their verbs
module.exports.GET = async function(req, res) {
  // fs-router decorates your req object with param and query hashes
  send(res, 200, { params: req.params, query: req.query })
}

path parameters

// routes/foos/:id.js
const { send } = require('micro')

// responds to any method at /foos/* (but not /foos or /foos/bar/baz)
module.exports = async function(req, res) {
  // params are always required when in a path, and the
  send(res, 200, { id: req.params.id })
}

works great with async/await

const { send, json } = require('micro')
const qs = require('querystring')
require('isomorphic-fetch')

module.exports.GET = async function(req, res) {
  const query = qs.stringify(req.query)
  const data = await json(req)
  const res = await fetch(`http://some-url.com?${query}`)
  const response = await res.json()
  send(res, 200, response)
}

typescript Use esModuleInterop and commonjs to import

// tsconfig.json
{
  "compilerOptions": {
    "module": "commonjs",
    "esModuleInterop": true,
    ...config
  }
}

use the RequestHandler type from this lib

import { RequestHandler } from 'fs-router'

export const GET: RequestHandler = async (req, res) => {
    // req.params and req.query will be typed correctly
    send(res, 200, { params: req.params, query: req.query })
}

A full typescript example is available in the examples directory

priority

module.exports.GET = async function(req, res) {
  send(res, 200, {})
}
// all routes are sorted by this property - the higher numbers are matched first.
// kind of like a z-index for your routes.
// note that equal priority will just sort based on the fs in the case of a collision, which is not guaranteed order on OSX/Linux
module.exports.priority = -1

custom path

// routes/whatever.js
module.exports.GET = async function(req, res) {
  send(res, 200, {})
}
// exposing a "path" will override the fs-generated one.
// This is nice if you wanted to avoid making a really deep tree for a one-off path (like for oauth callbacks)
// or if you just want to avoid putting `:` in your file/folder names or something
module.exports.path = '/foo/bar'

index routes

// routes/index.js
module.exports.GET = async function(req, res) {
  return 'hello!'
}
// The above route would be reachable at / and /index.
// This works for deep paths (/thing/index.js maps to /thing and /thing/index)
// and even for params (/thing/:param/index.js maps to /thing/* and /thing/*/index).

filter routes

// index.js
const { send } = require('micro')

// set up config to filter only paths including `foo`
const config = {filter: f => f.indexOf('foo') !== -1}

// pass config to `fs-router` as optional second paramater
let match = require('fs-router')(__dirname + '/routes', config)

module.exports = async function(req, res) {
  let matched = match(req)
  if (matched) return await matched(req, res)
  send(res, 404, { error: 'Not found' })
}

The above usage assumes you have a folder called routes next to the index.js file, that looks something like this:

routes/
├── foo
│   ├── index.js
│   └── thing.js
└── bar
    ├── index.js
    ├── foo.js
    └── thing.js

the above tree would generate the following routes:

/foo
/foo/thing
/bar/foo

Multiple file extensions

// index.js
const { send } = require('micro')

// set up the config to both include .js and .ts files.
const config = {ext: ['.js', '.ts']}

// pass config to `fs-router` as optional second paramater
let match = require('fs-router')(__dirname + '/routes', config)

module.exports = async function(req, res) {
  let matched = match(req)
  if (matched) return await matched(req, res)
  send(res, 404, { error: 'Not found' })
}

More Repositories

1

jss

A styleguide generator based on kss (https://github.com/kneath/kss), but built in node.js
JavaScript
25
star
2

reply

A bot for replying to twitter posts that match criteria
JavaScript
23
star
3

node-facebook-open-graph

Open graph actions made easier.
JavaScript
19
star
4

absolutize-links

A bash script to convert relative node_modules symlinks to absolute ones, so we can use with docker volumes.
Shell
17
star
5

node-caption

Node utility for captioning images via imageMagick
JavaScript
12
star
6

node-wordgenerator

Quick and dirty wordlist based word generator for inspiration when naming shit
JavaScript
11
star
7

Urza

Urza is a node framework for rapid and modular development.
JavaScript
10
star
8

heartbot

Hubot fork for We Heart It
CoffeeScript
8
star
9

node-config-heroku

An adapter for node-config (https://github.com/lorenwest/node-config) that sticks configs in heroku env variables instead of reading from the FS.
JavaScript
7
star
10

metapixel

A github fork of metapixel (http://www.complang.tuwien.ac.at/schani/metapixel/)
C
6
star
11

winston-sns

A Simple Notification System Transport for winston (http://www.github.com/flatiron/winston)
CoffeeScript
6
star
12

slashbot

A hubot-like chat bot for slack.
JavaScript
5
star
13

archival

Content-first, database-free, very durable websites.
Rust
4
star
14

facebook-access-code-generator

Quick little node server for generating facebook access codes.
JavaScript
4
star
15

node-fastpass

A node.js library for getsatisfaction fastpass (single sign-on)
JavaScript
4
star
16

now-deploy

A deploy script for use with now and multiple now.json files
Shell
4
star
17

ember-jsonapi

Create automatic JSONAPI endpoints based on incredibly simple JSON schemas.
JavaScript
3
star
18

reply-web

Web interface for reply bot making webapp
JavaScript
3
star
19

mailgun-proxy

A server for proxying requests to mailgun (while overlaying private keys)
JavaScript
3
star
20

VinylScrobbler

Scrobble tracks from an audio stream, e.g. a record player.
Python
3
star
21

remote-skip

A server to run on a mac that allows programatic skip button pressing via an http endpoint
JavaScript
3
star
22

CSS3-for-IE

A Javascript and PHP solution for IE's lack of CSS3 selector support
PHP
2
star
23

npm-package

fetches the package information for an npm package
JavaScript
2
star
24

passport-khan

Khan Academy passport strategy
JavaScript
2
star
25

top-tracks

Fetch your top tracks from your listen history for a given time range. Auto generate your best of 20XX playlists!
JavaScript
2
star
26

festival-playlist-generator

Festival Playlist Generator
JavaScript
2
star
27

secret-words

A Secret Words game to play when you're stuck at home and so are all your friends
TypeScript
2
star
28

archival-editor

An editor app for archival websites
Rust
2
star
29

Followers

Mac App for managing twitter followers
Objective-C
2
star
30

xctool-node

Node wrapper around XCTool (experimental)
JavaScript
2
star
31

jsonapi-express

Automatically generate jsonapi endpoints from simple schemas
JavaScript
2
star
32

superagent-relative

Make server-side requests to relative URLs with superagent
JavaScript
1
star
33

wishedBot

hubot for getwished.
CoffeeScript
1
star
34

easyProxy

Boilerplate code for setting up node-http-proxy.
JavaScript
1
star
35

cluster-danzig

A plugin for murdering children when the master process dies.
JavaScript
1
star
36

Baysic

Web site for Baysic
JavaScript
1
star
37

upd8

An HTML-friendly javascript mini-framework
TypeScript
1
star
38

ScavengerHunt

A Site for the Annual Summer Scavenger Hunt
JavaScript
1
star
39

drinkingsubtitles-webplayer

A web video player for drinking subtitles, for adding or viewing drinking game subtitles.
JavaScript
1
star
40

proxy-experiment

ES6 proxies experiment
JavaScript
1
star
41

netlify-lambda-types

Netlify Lambda typescript definitions
1
star
42

node-passbook

Passbook pkpass file generator
1
star
43

xraytv-video-generator

Generate MTV-style randomized spastic videos
JavaScript
1
star
44

bootstrap-app

boilerplate stuff for making node websites
JavaScript
1
star
45

archival-docs

Documentation for Archival, built with Archival
Liquid
1
star
46

jsonapi-schema

A parser for simple JSON schema definitions that serialize to JSONAPI
JavaScript
1
star
47

jsonapi-knex

Knex operations for jsonapi-express
JavaScript
1
star
48

environmentVisualizer

A visualization for csv data about temperature, humidity & time in a home.
JavaScript
1
star
49

weather-view

A weather widget written in React
TypeScript
1
star
50

load-secrets

Platform agnostic secrets loader for ~/.secrets/project-name.env or process.env
JavaScript
1
star
51

archival-website

A template repo used when creating archival websites
Shell
1
star
52

ancient-morse-translator

Just a fun coding exercise.
JavaScript
1
star