Socket
Socket
Sign inDemoInstall

route-trie

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

route-trie - npm Package Compare versions

Comparing version 2.0.2 to 2.1.0

151

index.js

@@ -7,5 +7,5 @@ // **Github:** https://github.com/zensh/route-trie

const wordReg = /^\w+$/
const doubleColonReg = /::\w*$/
const suffixReg = /\+[A-Za-z0-9!$%&'*+,-.:;=@_~]*$/
const doubleColonReg = /::[A-Za-z0-9!$%&'*+,-.:;=@_~]*$/
const trimSlashReg = /^\//
const multiSlashReg = /\/{2,}/
const fixMultiSlashReg = /\/{2,}/g

@@ -39,3 +39,3 @@

if (typeof pattern !== 'string') throw new TypeError('Pattern must be string.')
if (multiSlashReg.test(pattern)) throw new Error('Multi-slash existhis.')
if (pattern.includes('//')) throw new Error('Multi-slash existhis.')
let _pattern = pattern.replace(trimSlashReg, '')

@@ -62,3 +62,3 @@ let node = defineNode(this.root, _pattern.split('/'), this.ignoreCase)

let end = path.length
let res = new Matched()
let matched = new Matched()
let parent = this.root

@@ -76,9 +76,9 @@ for (let i = 1; i <= end; i++) {

if (this.tsr && frag === '' && i === end && parent.endpoint) {
res.tsr = path.slice(0, end - 1)
matched.tsr = path.slice(0, end - 1)
if (this.fpr && fixedLen > 0) {
res.fpr = res.tsr
res.tsr = ''
matched.fpr = matched.tsr
matched.tsr = ''
}
}
return res
return matched
}

@@ -89,6 +89,9 @@

if (parent.wildcard) {
res.params[parent.name] = path.slice(start, end)
matched.params[parent.name] = path.slice(start, end)
break
} else {
res.params[parent.name] = frag
if (parent.suffix !== '') {
frag = frag.slice(0, frag.length - parent.suffix.length)
}
matched.params[parent.name] = frag
}

@@ -100,16 +103,16 @@ }

if (parent.endpoint) {
res.node = parent
matched.node = parent
if (this.fpr && fixedLen > 0) {
res.fpr = path
res.node = null
matched.fpr = path
matched.node = null
}
} else if (this.tsr && parent.children[''] != null) {
// TrailingSlashRedirect: /acb/efg -> /acb/efg/
res.tsr = path + '/'
matched.tsr = path + '/'
if (this.fpr && fixedLen > 0) {
res.fpr = res.tsr
res.tsr = ''
matched.fpr = matched.tsr
matched.tsr = ''
}
}
return res
return matched
}

@@ -137,6 +140,8 @@ }

this.pattern = ''
this.frag = ''
this.suffix = ''
this.regex = null
this.endpoint = false
this.wildcard = false
this.varyChild = null
this.varyChildren = []
this.parent = parent

@@ -169,2 +174,10 @@ this.children = Object.create(null)

}
getFrags () {
let frags = this.frag
if (this.parent != null) {
frags = this.parent.getFrags() + '/' + frags
}
return frags
}
}

@@ -187,10 +200,19 @@

function matchNode (parent, frag) {
let child = parent.children[frag]
if (child == null) {
child = parent.varyChild
if (child != null && child.regex != null && !child.regex.test(frag)) {
child = null
if (parent.children[frag] != null) {
return parent.children[frag]
}
for (let child of parent.varyChildren) {
let _frag = frag
if (child.suffix !== '') {
if (frag === child.suffix || !frag.endsWith(child.suffix)) {
continue
}
_frag = frag.slice(0, frag.length - child.suffix.length)
}
if (child.regex != null && !child.regex.test(_frag)) {
continue
}
return child
}
return child
return null
}

@@ -219,39 +241,68 @@

} else if (frag[0] === ':') {
let regex
let name = frag.slice(1)
let trailing = name[name.length - 1]
if (trailing === ')') {
let index = name.indexOf('(')
if (index > 0) {
regex = name.slice(index + 1, name.length - 1)
if (regex.length > 0) {
name = name.slice(0, index)
node.regex = new RegExp(regex)
} else {
throw new Error(`Invalid pattern: "${frag}"`)
switch (name[name.length - 1]) {
case '*':
name = name.slice(0, name.length - 1)
node.wildcard = true
break
default:
let i = name.search(suffixReg)
if (i >= 0) {
node.suffix = name.slice(i + 1)
name = name.slice(0, i)
if (node.suffix === '') {
throw new Error(`invalid pattern: "${node.getFrags()}"`)
}
}
}
} else if (trailing === '*') {
name = name.slice(0, name.length - 1)
node.wildcard = true
if (name[name.length - 1] === ')') {
let i = name.indexOf('(')
if (i > 0) {
let regex = name.slice(i + 1, name.length - 1)
if (regex.length > 0) {
name = name.slice(0, i)
node.regex = new RegExp(regex)
} else {
throw new Error(`Invalid pattern: "${node.getFrags()}"`)
}
}
}
}
// name must be word characters `[0-9A-Za-z_]`
if (!wordReg.test(name)) {
throw new Error(`Invalid pattern: "${frag}"`)
throw new Error(`Invalid pattern: "${node.getFrags()}"`)
}
node.name = name
let child = parent.varyChild
if (child != null) {
if (child.name !== name || child.wildcard !== node.wildcard) {
throw new Error(`Invalid pattern: "${frag}"`)
for (let child of parent.varyChildren) {
if (child.name !== node.name) {
throw new Error(`invalid pattern: "${node.getFrags()}"`)
}
if (child.regex != null && child.regex.toString() !== node.regex.toString()) {
throw new Error(`Invalid pattern: "${frag}"`)
if (child.wildcard) {
if (!node.wildcard) {
throw new Error(`can't define "${node.getFrags()}" after "${child.getFrags()}"`)
}
return child
}
return child
if (child.suffix === '' && child.regex == null && (node.suffix !== '' || node.regex != null)) {
throw new Error(`can't define "${node.getFrags()}" after "${child.getFrags()}"`)
}
if (child.suffix === node.suffix) {
if (child.regex == null && node.regex == null) {
return child
}
if (child.regex != null && node.regex != null && child.regex.toString() === node.regex.toString()) {
return child
}
if (child.regex == null && node.regex != null) {
throw new Error(`invalid pattern: "${node.getFrags()}"`)
}
}
}
parent.varyChild = node
parent.varyChildren.push(node)
} else if (frag[0] === '*' || frag[0] === '(' || frag[0] === ')') {
throw new Error(`Invalid pattern: "${frag}"`)
throw new Error(`Invalid pattern: "${node.getFrags()}"`)
} else {

@@ -264,5 +315,5 @@ parent.children[_frag] = node

Trie.NAME = 'Trie'
Trie.VERSION = 'v2.0.2'
Trie.VERSION = 'v2.1.0'
Trie.Node = Node
Trie.Matched = Matched
module.exports = Trie.Trie = Trie

@@ -7,3 +7,3 @@ {

],
"version": "2.0.2",
"version": "2.1.0",
"license": "MIT",

@@ -17,3 +17,3 @@ "main": "index.js",

"engines": {
"node": ">= 4"
"node": ">= 4.0.0"
},

@@ -32,4 +32,4 @@ "homepage": "https://github.com/zensh/route-trie",

"devDependencies": {
"standard": "^8.6.0",
"tman": "^1.6.4",
"standard": "^9.0.2",
"tman": "^1.6.6",
"istanbul": "^0.4.5"

@@ -36,0 +36,0 @@ },

@@ -1,3 +0,3 @@

route-trie
====
# route-trie
A minimal and powerful trie based url path router for Node.js.

@@ -30,9 +30,11 @@

## Features:
## Features
1. Support named parameter
1. Support regexp
2. Fixed path automatic redirection
3. Trailing slash automatic redirection
4. Support `405 Method Not Allowed`
5. Best Performance
1. Support suffix matching
1. Fixed path automatic redirection
1. Trailing slash automatic redirection
1. Support `405 Method Not Allowed`
1. Best Performance

@@ -74,3 +76,3 @@ ## Installation

The defined pattern can contain three types of parameters:
The defined pattern can contain six types of parameters:

@@ -80,4 +82,6 @@ | Syntax | Description |

| `:name` | named parameter |
| `:name(regexp)` | named with regexp parameter |
| `:name+suffix` | named parameter with suffix matching |
| `:name(regexp)+suffix` | named with regexp parameter and suffix matching |
| `:name*` | named with catch-all parameter |
| `:name(regexp)` | named with regexp parameter |
| `::name` | not named parameter, it is literal `:name` |

@@ -94,2 +98,30 @@

Named with regexp parameters match anything using regexp until the next '/' or the path end:
Defined: `/api/:type/:ID(^\d+$)`
```
/api/user/123 matched: type="user", ID="123"
/api/user no match
/api/user/abc no match
/api/user/123/comments no match
```
Named parameters with suffix, such as [Google API Design](https://cloud.google.com/apis/design/custom_methods):
Defined: `/api/:resource/:ID+:undelete`
```
/api/file/123 no match
/api/file/123:undelete matched: resource="file", ID="123"
/api/file/123:undelete/comments no match
```
Named with regexp parameters and suffix:
Defined: `/api/:resource/:ID(^\d+$)+:cancel`
```
/api/task/123 no match
/api/task/123:cancel matched: resource="task", ID="123"
/api/task/abc:cancel no match
```
Named with catch-all parameters match anything until the path end, including the directory index (the '/' before the catch-all). Since they match anything until the end, catch-all parameters must always be the final path element.

@@ -104,18 +136,8 @@

Named with regexp parameters match anything using regexp until the next '/' or the path end:
Defined: `/api/:type/:ID(^\\d+$)`
The value of parameters is saved on the `Matched.Params`. Retrieve the value of a parameter by name:
```
/api/user/123 matched: type="user", ID="123"
/api/user no match
/api/user/abc no match
/api/user/123/comments no match
type := matched.Params("type")
id := matched.Params("ID")
```
The value of parameters is saved on the `matched.params`. Retrieve the value of a parameter by name:
```
let type = matched.params.type
let id = matched.Params.ID
```
**Notice for regex pattern:**

@@ -122,0 +144,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc