Skip to content

Commit 08052d8

Browse files
billymoonjesseditson
authored andcommitted
Add optional config with custom filter option and standard js linting (#3)
* conform to standard js linting rules * add yarn lock file * ignore .DS_Store files * add route filter config item
1 parent 4492000 commit 08052d8

21 files changed

+1659
-22
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
logs
33
*.log
44
npm-debug.log*
5+
.DS_Store
56

67
# Coverage directory used by tools like istanbul
78
coverage

README.md

+38
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Use the FS as your micro router
33
[![Build Status](https://travis-ci.org/jesseditson/fs-router.svg?branch=master)](https://travis-ci.org/jesseditson/fs-router)
44
[![Coverage Status](https://coveralls.io/repos/github/jesseditson/fs-router/badge.svg?branch=master)](https://coveralls.io/github/jesseditson/fs-router?branch=master)
5+
[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
56

67
### "features"
78

@@ -121,3 +122,40 @@ module.exports.GET = async function(req, res) {
121122
// This works for deep paths (/thing/index.js maps to /thing and /thing/index)
122123
// and even for params (/thing/:param/index.js maps to /thing/* and /thing/*/index).
123124
```
125+
126+
**filter routes**
127+
```javascript
128+
// index.js
129+
const { send } = require('micro')
130+
131+
// set up config to filter only paths including `foo`
132+
const config = {filter: f => f.indexOf('foo') !== -1}
133+
134+
// pass config to `fs-router` as optional second paramater
135+
let match = require('fs-router')(__dirname + '/routes', config)
136+
137+
module.exports = async function(req, res) {
138+
let matched = match(req)
139+
if (matched) return await matched(req, res)
140+
send(res, 404, { error: 'Not found' })
141+
}
142+
```
143+
144+
The above usage assumes you have a folder called `routes` next to the `index.js` file, that looks something like this:
145+
```
146+
routes/
147+
├── foo
148+
│ ├── index.js
149+
│ └── thing.js
150+
└── bar
151+
├── index.js
152+
├── foo.js
153+
└── thing.js
154+
```
155+
156+
the above tree would generate the following routes:
157+
```
158+
/foo
159+
/foo/thing
160+
/bar/foo
161+
```

index.js

+10-8
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,21 @@ const path = require('path')
22
const fs = require('fs')
33
const qs = require('querystring')
44

5-
const paramPattern = /:([^\/]+)/
5+
const paramPattern = /:([^/]+)/
66
// takes routes and decorates them with a 'match' method that will return { params, query } if a path matches
7-
function addMatch(route) {
7+
function addMatch (route) {
88
let routePath = route.path
99
let paramNames = []
1010
let matched
1111
// find any paths prefixed with a `:`, and treat them as capture groups
12-
while (matched = routePath.match(paramPattern)) {
13-
routePath = routePath.replace(paramPattern, '([^\?\/]+)')
12+
while ((matched = routePath.match(paramPattern)) !== null) {
13+
routePath = routePath.replace(paramPattern, '([^?/]+)')
1414
paramNames.push(matched[1])
1515
}
1616
// if a route ends with `index`, allow matching that route without matching the `index` part
1717
if (path.basename(routePath) === 'index') {
1818
route.isIndex = true
19-
routePath = routePath.replace(/\/index$/, '\/?(:?index)?')
19+
routePath = routePath.replace(/\/index$/, '/?(:?index)?')
2020
}
2121
// create a regex with our path
2222
let pattern = new RegExp(`^${routePath}(\\?(.*)|$)`, 'i')
@@ -36,7 +36,7 @@ function addMatch(route) {
3636
}
3737

3838
// recursively searches for all js files inside a directory tree, and returns their full paths
39-
function findRoutes(dir) {
39+
function findRoutes (dir) {
4040
let files = fs.readdirSync(dir)
4141
let resolve = f => path.join(dir, f)
4242
let routes = files.filter(f => path.extname(f) === '.js').map(resolve)
@@ -45,8 +45,10 @@ function findRoutes(dir) {
4545
}
4646

4747
const val = v => (typeof v === 'undefined' ? 0 : v)
48-
module.exports = function router(routesDir) {
48+
module.exports = function router (routesDir, config) {
4949
const routes = findRoutes(routesDir)
50+
// if filter function is set, filter routes
51+
.filter(config && config.filter || function () { return true })
5052
// require route files, then add a 'path' property to them
5153
// the path is in the form of '/path/file', relative to routesDir
5254
.map(routeFile => {
@@ -68,7 +70,7 @@ module.exports = function router(routesDir) {
6870
.sort((a, b) => val(a.priority) < val(b.priority) ? 1 : -1)
6971

7072
// generated match method - call with a req object to get a route.
71-
return function match(req) {
73+
return function match (req) {
7274
let routeFn = r => r[req.method] || (typeof r === 'function' && r)
7375
let found = routes.find(r => {
7476
let matched = r.match(req.url)

test/custom-filter-test.js

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const path = require('path')
2+
const test = require('tape')
3+
const router = require('..')
4+
5+
// set up config to filter only paths ending `index.js`
6+
const config = {filter: f => /(?:^|\/)index.js$/.test(f)}
7+
8+
let match = router(path.join(__dirname, '/fixtures/filter'), config)
9+
10+
test('include non-filtered root path', t => {
11+
t.plan(2)
12+
let req = { url: '/', method: 'GET' }
13+
t.equal(typeof match(req), 'function', 'returns the route function')
14+
t.equal(match(req)(), 'index', 'route function is callable')
15+
})
16+
17+
test('include non-filtered nested path', t => {
18+
t.plan(2)
19+
let req = { url: '/thing', method: 'GET' }
20+
t.equal(typeof match(req), 'function', 'returns the route function')
21+
t.equal(match(req)(), 'thing', 'route function is callable')
22+
})
23+
24+
test('exclude filtered root path', t => {
25+
t.plan(1)
26+
let req = { url: '/other', method: 'GET' }
27+
t.equal(typeof match(req), 'undefined', 'excludes filtered paths')
28+
})
29+
30+
test('exclude filtered nested path', t => {
31+
t.plan(1)
32+
let req = { url: '/thing/other', method: 'GET' }
33+
t.equal(typeof match(req), 'undefined', 'excludes filtered paths')
34+
})

test/custom-path-test.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
const path = require('path')
12
const test = require('tape')
23
const router = require('..')
34

4-
let match = router(__dirname + '/fixtures/custom')
5+
let match = router(path.join(__dirname, '/fixtures/custom'))
56

67
test('uses custom path if provided', t => {
78
t.plan(1)
@@ -12,7 +13,7 @@ test('uses custom path if provided', t => {
1213
test('uses properly parses params in custom path', t => {
1314
t.plan(1)
1415
let req = { url: '/random/custom/foo', method: 'GET' }
15-
let fn = match(req)
16+
match(req)
1617
t.equal(req.params.param, 'foo', 'param is correct')
1718
})
1819

test/fixtures/custom/custom.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
module.exports = function() {}
1+
module.exports = function () {}
22
module.exports.path = '/random/custom/:param'

test/fixtures/filter/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = () => 'index'

test/fixtures/filter/other.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = () => 'other'

test/fixtures/filter/thing/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = () => 'thing'

test/fixtures/filter/thing/other.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = () => 'other'

test/fixtures/params/:root/:why.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
module.exports = function() {}
2-
module.exports.priority = -1;
1+
module.exports = function () {}
2+
module.exports.priority = -1

test/fixtures/params/:root/thing.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
module.exports = function() {}
1+
module.exports = function () {}
+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
module.exports = function() {}
1+
module.exports = function () {}

test/fixtures/params/things/:id.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
module.exports = function() {}
1+
module.exports = function () {}

test/fixtures/simple/foo/bar.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
module.exports = function() {
1+
module.exports = function () {
22
return 'bar'
33
}

test/index-test.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
const path = require('path')
12
const test = require('tape')
23
const router = require('..')
34

4-
let match = router(__dirname + '/fixtures/index')
5+
let match = router(path.join(__dirname, '/fixtures/index'))
56

67
test('uses index.js when the root is requested', t => {
78
t.plan(2)

test/params-test.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
const path = require('path')
12
const test = require('tape')
23
const router = require('..')
34

4-
let match = router(__dirname + '/fixtures/params')
5+
let match = router(path.join(__dirname, '/fixtures/params'))
56

67
test('files starting with `:` are treated as path params', t => {
78
t.plan(1)

test/priority-test.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
const path = require('path')
12
const test = require('tape')
23
const router = require('..')
34

4-
let match = router(__dirname + '/fixtures/priority')
5+
let match = router(path.join(__dirname, '/fixtures/priority'))
56

67
test('matches high priority on collision with default', t => {
78
t.plan(1)

test/simple-test.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
const path = require('path')
12
const test = require('tape')
23
const router = require('..')
34

4-
let match = router(__dirname + '/fixtures/simple')
5+
let match = router(path.join(__dirname, '/fixtures/simple'))
56

67
test('sets up routes from the fs', t => {
78
t.plan(2)

test/verbs-test.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
const path = require('path')
12
const test = require('tape')
23
const router = require('..')
34

4-
let match = router(__dirname + '/fixtures/verbs')
5+
let match = router(path.join(__dirname, '/fixtures/verbs'))
56
const verbs = ['GET', 'PUT', 'POST', 'PATCH', 'DELETE', 'OPTIONS']
67

78
test('correctly maps various verbs', t => {

0 commit comments

Comments
 (0)