Add support for functions in router

Can add a function as to match a route. The function takes in a string
url segment and returns some value if the route matches or returns null
or undefined for no match.

Example usage:

function toInt(part) {
  var results = /^(\d+)$/.exec(part)
  return results ? parseInt(results[0], 10) : null
}

var router = new Router()
router.add(['/by/order', toInt], function (val) {
  // val === 123
})

router.route('/by/order/123')
master
Buddy Sandidge 9 years ago
parent a317aa86a8
commit 7c34964dff

@ -1,14 +1,17 @@
'use strict'
var utils = require('./utils')
var noop = utils.noop
var assign = utils.assign
var isFunction = utils.isFunction
var isRegExp = utils.isRegExp
var isString = utils.isString
var noop = utils.noop
function RouteNode (options) {
options = options || {}
this._children = Object.create(null)
this._regExs = Object.create(null)
this._funcs = Object.create(null)
}
assign(RouteNode.prototype, {
@ -29,8 +32,10 @@ assign(RouteNode.prototype, {
if (isString(part)) {
node = this._children[part]
} else {
} else if (isRegExp(part)) {
this._regExs[part] = part
} else if (isFunction(part)) {
this._funcs[part] = part
}
if (node == null) {
@ -56,42 +61,54 @@ assign(RouteNode.prototype, {
if (results && results.node) {
return results.node.get(parts, args.concat(results.args), done)
} else {
return done(new Error('not found'))
results = this._getFunctionChild(part)
if (results && results.node) {
return results.node.get(parts, args.concat(results.args), done)
} else {
return done(new Error('not found'))
}
}
}
},
_getRegexChild: function _getRegexChild(part) {
var childKey = null
var args = []
var self = this
Object.keys(this._regExs).forEach(function checkRegex(key) {
if (childKey) {
return
return Object.keys(this._regExs).reduce(function checkRegex(memo, key) {
if (memo) {
return memo
}
var regex = self._regExs[key]
var results = regex.exec(part)
var lastIndex = null
if (results) {
childKey = key
if (!results) {
return null
}
var lastIndex = null
var args = []
while (results && results.index !== lastIndex) {
args = args.concat(results[0])
lastIndex = results.index
results = regex.exec(part)
}
})
return {args: args, key: key, node: self._children[key]}
}, null)
},
if (childKey) {
return {
args: args,
key: childKey,
node: this._children[childKey]
_getFunctionChild: function _getFunctionChild(part) {
var self = this
return Object.keys(self._funcs).reduce(function checkFunc(memo, key) {
if (memo) {
return memo
}
} else {
return null
}
var func = self._funcs[key]
var result = func(part)
if (result) {
return {args: [result], key: key, node: self._children[key]}
} else {
return null
}
}, null)
}
})

@ -31,8 +31,8 @@ function checkType(type) {
}
}
// add isRegExp, isArray
['RegExp', 'Array'].forEach(function addIsChecks(type) {
// add isRegExp, isArray, isFunction
['RegExp', 'Array', 'Function'].forEach(function addIsChecks(type) {
utils['is' + type] = checkType(type)
})

@ -58,5 +58,25 @@ module.exports = describe('RouteNode', function () {
})
})
it('→ get route with function', function (done) {
function toInt(part) {
var results = /^(\d+)$/.exec(part)
if (results) {
return parseInt(results[0], 10)
} else {
return null
}
}
node.add(['by', 'id', toInt], callback, context)
node.get(['by', 'id', '123'], [], function (err, func, cbContext, args) {
expect(err).toBe(null, err && err.message)
expect(func).toBe(callback)
expect(cbContext).toBe(context)
expect(args).toEqual([123])
done()
})
})
})
})

@ -75,4 +75,25 @@ describe('Router', function () {
done()
})
})
it('→ get based on function', function (done) {
function toInt(part) {
var results = /^(\d+)$/.exec(part)
if (results) {
return parseInt(results[0], 10)
} else {
return null
}
}
var router = new Router()
router.add(['by', 'order', toInt], function (val) {
expect(val).toBe(123)
})
router.route('/by/order/123', function (err) {
expect(err).toBe(null, err && err.message)
done()
})
})
})

@ -4,6 +4,7 @@ var utils = require('../lib/utils')
var assign = utils.assign
var forEach = utils.forEach
var isArray = utils.isArray
var isFunction = utils.isFunction
var isRegExp = utils.isRegExp
var isString = utils.isString
var noop = utils.noop
@ -58,6 +59,24 @@ describe('utils', function () {
})
})
describe('→ isFunction', function () {
it('→ true for function', function () {
expect(isFunction(function () {})).toBe(true)
})
it('→ false for array', function () {
expect(isFunction([])).toBe(false)
})
it('→ false for regex', function () {
expect(isFunction(/some regex/)).toBe(false)
})
it('→ false for strings', function () {
expect(isFunction('some string')).toBe(false)
})
})
describe('→ forEach', function () {
it('→ does not call properties on prototype', function () {
var count = 0

Loading…
Cancel
Save