Skip to content

Commit 6684511

Browse files
authored
Merge branch 'main' into null-object-parameters
2 parents ba6b613 + a9d1ee1 commit 6684511

13 files changed

+347
-67
lines changed

.github/dependabot.yml

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "github-actions"
4+
directory: "/"
5+
commit-message:
6+
# Prefix all commit messages with "chore: "
7+
prefix: "chore"
8+
schedule:
9+
interval: "monthly"
10+
open-pull-requests-limit: 10
11+
12+
- package-ecosystem: "npm"
13+
directory: "/"
14+
commit-message:
15+
# Prefix all commit messages with "chore: "
16+
prefix: "chore"
17+
schedule:
18+
interval: "weekly"
19+
open-pull-requests-limit: 10
20+
groups:
21+
# Production dependencies without breaking changes
22+
dependencies:
23+
dependency-type: "production"
24+
update-types:
25+
- "minor"
26+
- "patch"
27+
# Production dependencies with breaking changes
28+
dependencies-major:
29+
dependency-type: "production"
30+
update-types:
31+
- "major"
32+
# Development dependencies
33+
dev-dependencies:
34+
dependency-type: "development"

.github/workflows/node.js.yml

+33-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
name: Node CI
22

3-
on: [push, pull_request]
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- next
8+
pull_request:
49

510
permissions:
611
contents: read
@@ -12,17 +17,25 @@ jobs:
1217

1318
strategy:
1419
matrix:
15-
node-version: [14.x, 16.x, 18.x, 20.x]
16-
os: [ubuntu-latest, windows-latest, macOS-latest]
20+
node-version:
21+
- 14
22+
- 16
23+
- 18
24+
- 20
25+
- 21
26+
os:
27+
- ubuntu-latest
28+
- windows-latest
29+
- macOS-latest
1730
exclude:
1831
- os: windows-latest
19-
node-version: 14.x
32+
node-version: 14
2033

2134
steps:
22-
- uses: actions/checkout@v3
35+
- uses: actions/checkout@v4
2336

2437
- name: Use Node.js ${{ matrix.node-version }}
25-
uses: actions/setup-node@v3
38+
uses: actions/setup-node@v4
2639
with:
2740
node-version: ${{ matrix.node-version }}
2841

@@ -41,3 +54,17 @@ jobs:
4154
- name: Type Definitions
4255
run: |
4356
npm run test:typescript
57+
58+
automerge:
59+
if: >
60+
github.event_name == 'pull_request' && github.event.pull_request.user.login == 'dependabot[bot]'
61+
needs: test
62+
runs-on: ubuntu-latest
63+
permissions:
64+
actions: write
65+
pull-requests: write
66+
contents: write
67+
steps:
68+
- uses: fastify/github-action-merge-dependabot@9e7bfb249c69139d7bdcd8d984f9665edd49020b # v3.10.1
69+
with:
70+
github-token: ${{ secrets.GITHUB_TOKEN }}

.taprc

-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
11
ts: false
22
jsx: false
33
flow: false
4-
branches: 90
5-
functions: 90
6-
lines: 90
7-
statements: 90

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -443,8 +443,8 @@ router.hasRoute('GET', '/:file(^\\D+).jpg')
443443
// => false
444444
```
445445

446-
```js
447446
#### lookup(request, response, [context], [done])
447+
448448
Start a new search, `request` and `response` are the server req/res objects.<br>
449449
If a route is found it will automatically call the handler, otherwise the default route will be called.<br>
450450
The url is sanitized internally, all the parameters and wildcards are decoded automatically.

index.js

+26-36
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
'~': 126 - ~
2626
*/
2727

28-
const assert = require('assert')
28+
const assert = require('node:assert')
2929
const querystring = require('fast-querystring')
3030
const isRegexSafe = require('safe-regex2')
3131
const deepEqual = require('fast-deep-equal')
@@ -344,7 +344,6 @@ Router.prototype.findRoute = function findNode (method, path, constraints = {})
344344
const isRegexParam = charCode === 40
345345
const isStaticPart = charCode === 45 || charCode === 46
346346
const isEndOfNode = charCode === 47 || j === pattern.length
347-
348347
if (isRegexParam || isStaticPart || isEndOfNode) {
349348
const paramName = pattern.slice(lastParamStartIndex, j)
350349
params.push(paramName)
@@ -407,9 +406,7 @@ Router.prototype.findRoute = function findNode (method, path, constraints = {})
407406
// add the wildcard parameter
408407
params.push('*')
409408
currentNode = currentNode.getWildcardChild()
410-
if (currentNode === null) {
411-
return null
412-
}
409+
413410
parentNodePathIndex = i + 1
414411

415412
if (i !== pattern.length - 1) {
@@ -422,10 +419,6 @@ Router.prototype.findRoute = function findNode (method, path, constraints = {})
422419
pattern = pattern.toLowerCase()
423420
}
424421

425-
if (pattern === '*') {
426-
pattern = '/*'
427-
}
428-
429422
for (const existRoute of this.routes) {
430423
const routeConstraints = existRoute.opts.constraints || {}
431424
if (
@@ -436,7 +429,7 @@ Router.prototype.findRoute = function findNode (method, path, constraints = {})
436429
return {
437430
handler: existRoute.handler,
438431
store: existRoute.store,
439-
params: existRoute.params || []
432+
params: existRoute.params
440433
}
441434
}
442435
}
@@ -642,37 +635,36 @@ Router.prototype.find = function find (method, path, derivedConstraints) {
642635
continue
643636
}
644637

645-
if (currentNode.kind === NODE_TYPES.PARAMETRIC) {
646-
let paramEndIndex = originPath.indexOf('/', pathIndex)
647-
if (paramEndIndex === -1) {
648-
paramEndIndex = pathLen
649-
}
638+
// parametric node
639+
let paramEndIndex = originPath.indexOf('/', pathIndex)
640+
if (paramEndIndex === -1) {
641+
paramEndIndex = pathLen
642+
}
650643

651-
let param = originPath.slice(pathIndex, paramEndIndex)
652-
if (shouldDecodeParam) {
653-
param = safeDecodeURIComponent(param)
654-
}
644+
let param = originPath.slice(pathIndex, paramEndIndex)
645+
if (shouldDecodeParam) {
646+
param = safeDecodeURIComponent(param)
647+
}
655648

656-
if (currentNode.isRegex) {
657-
const matchedParameters = currentNode.regex.exec(param)
658-
if (matchedParameters === null) continue
649+
if (currentNode.isRegex) {
650+
const matchedParameters = currentNode.regex.exec(param)
651+
if (matchedParameters === null) continue
659652

660-
for (let i = 1; i < matchedParameters.length; i++) {
661-
const matchedParam = matchedParameters[i]
662-
if (matchedParam.length > maxParamLength) {
663-
return null
664-
}
665-
params.push(matchedParam)
666-
}
667-
} else {
668-
if (param.length > maxParamLength) {
653+
for (let i = 1; i < matchedParameters.length; i++) {
654+
const matchedParam = matchedParameters[i]
655+
if (matchedParam.length > maxParamLength) {
669656
return null
670657
}
671-
params.push(param)
658+
params.push(matchedParam)
672659
}
673-
674-
pathIndex = paramEndIndex
660+
} else {
661+
if (param.length > maxParamLength) {
662+
return null
663+
}
664+
params.push(param)
675665
}
666+
667+
pathIndex = paramEndIndex
676668
}
677669
}
678670

@@ -742,8 +734,6 @@ for (const i in httpMethods) {
742734
const m = httpMethods[i]
743735
const methodName = m.toLowerCase()
744736

745-
if (Router.prototype[methodName]) throw new Error('Method already exists: ' + methodName)
746-
747737
Router.prototype[methodName] = function (path, handler, store) {
748738
return this.on(m, path, handler, store)
749739
}

lib/constrainer.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
const acceptVersionStrategy = require('./strategies/accept-version')
44
const acceptHostStrategy = require('./strategies/accept-host')
5-
const assert = require('assert')
5+
const assert = require('node:assert')
66

77
class Constrainer {
88
constructor (customStrategies) {
@@ -153,10 +153,8 @@ class Constrainer {
153153
if (!strategy.isCustom) {
154154
if (key === 'version') {
155155
lines.push(' version: req.headers[\'accept-version\'],')
156-
} else if (key === 'host') {
157-
lines.push(' host: req.headers.host || req.headers[\':authority\'],')
158156
} else {
159-
throw new Error('unknown non-custom strategy for compiling constraint derivation function')
157+
lines.push(' host: req.headers.host || req.headers[\':authority\'],')
160158
}
161159
} else {
162160
lines.push(` ${strategy.name}: this.strategies.${key}.deriveConstraint(req, ctx),`)

lib/node.js

+1-4
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,7 @@ class StaticNode extends ParentNode {
129129
}
130130

131131
getWildcardChild () {
132-
if (this.wildcardChild) {
133-
return this.wildcardChild
134-
}
135-
return null
132+
return this.wildcardChild
136133
}
137134

138135
createWildcardChild () {

lib/strategies/accept-host.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
'use strict'
2-
const assert = require('assert')
2+
const assert = require('node:assert')
33

44
function HostStorage () {
55
const hosts = {}

lib/strategies/accept-version.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict'
22

3-
const assert = require('assert')
3+
const assert = require('node:assert')
44

55
function SemVerStore () {
66
if (!(this instanceof SemVerStore)) {
@@ -20,7 +20,11 @@ SemVerStore.prototype.set = function (version, store) {
2020
}
2121
let [major, minor, patch] = version.split('.')
2222

23-
major = Number(major) || 0
23+
if (isNaN(major)) {
24+
throw new TypeError('Major version must be a numeric value')
25+
}
26+
27+
major = Number(major)
2428
minor = Number(minor) || 0
2529
patch = Number(patch) || 0
2630

@@ -38,7 +42,7 @@ SemVerStore.prototype.set = function (version, store) {
3842
this.store[`${major}.x.x`] = store
3943
}
4044

41-
if (patch >= (this.store[`${major}.${minor}`] || 0)) {
45+
if (patch >= (this.maxPatches[`${major}.${minor}`] || 0)) {
4246
this.maxPatches[`${major}.${minor}`] = patch
4347
this.store[`${major}.${minor}.x`] = store
4448
}

lib/strategies/http-method.js

+1-4
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ module.exports = {
99
set: (type, store) => { handlers[type] = store }
1010
}
1111
},
12-
deriveConstraint: (req) => {
13-
/* istanbul ignore next */
14-
return req.method
15-
},
12+
deriveConstraint: /* istanbul ignore next */ (req) => req.method,
1613
mustMatchWhenDerived: true
1714
}

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"chalk": "^4.1.2",
4141
"inquirer": "^8.2.4",
4242
"pre-commit": "^1.2.2",
43+
"proxyquire": "^2.1.3",
4344
"rfdc": "^1.3.0",
4445
"simple-git": "^3.7.1",
4546
"standard": "^14.3.4",
@@ -50,7 +51,7 @@
5051
"dependencies": {
5152
"fast-deep-equal": "^3.1.3",
5253
"fast-querystring": "^1.0.0",
53-
"safe-regex2": "^2.0.0"
54+
"safe-regex2": "^3.1.0"
5455
},
5556
"tsd": {
5657
"directory": "test/types"

test/constraint.custom.async.test.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const t = require('tap')
44
const test = t.test
55
const FindMyWay = require('..')
6+
const rfdc = require('rfdc')({ proto: true })
67

78
const customHeaderConstraint = {
89
name: 'requestedBy',
@@ -23,11 +24,14 @@ const customHeaderConstraint = {
2324
}
2425
}
2526

26-
test('should derive async constraint', t => {
27+
test('should derive multiple async constraints', t => {
2728
t.plan(2)
2829

29-
const router = FindMyWay({ constraints: { requestedBy: customHeaderConstraint } })
30-
router.on('GET', '/', { constraints: { requestedBy: 'node' } }, () => 'asyncHandler')
30+
const customHeaderConstraint2 = rfdc(customHeaderConstraint)
31+
customHeaderConstraint2.name = 'requestedBy2'
32+
33+
const router = FindMyWay({ constraints: { requestedBy: customHeaderConstraint, requestedBy2: customHeaderConstraint2 } })
34+
router.on('GET', '/', { constraints: { requestedBy: 'node', requestedBy2: 'node' } }, () => 'asyncHandler')
3135

3236
router.lookup(
3337
{

0 commit comments

Comments
 (0)