我的node项目首次提交!!!

This commit is contained in:
heiye111
2025-09-20 22:05:58 +08:00
commit 48600edffc
2539 changed files with 365006 additions and 0 deletions

34
node_modules/find-my-way/.github/dependabot.yml generated vendored Normal file
View File

@@ -0,0 +1,34 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
commit-message:
# Prefix all commit messages with "chore: "
prefix: "chore"
schedule:
interval: "monthly"
open-pull-requests-limit: 10
- package-ecosystem: "npm"
directory: "/"
commit-message:
# Prefix all commit messages with "chore: "
prefix: "chore"
schedule:
interval: "monthly"
open-pull-requests-limit: 10
groups:
# Production dependencies without breaking changes
dependencies:
dependency-type: "production"
update-types:
- "minor"
- "patch"
# Production dependencies with breaking changes
dependencies-major:
dependency-type: "production"
update-types:
- "major"
# Development dependencies
dev-dependencies:
dependency-type: "development"

67
node_modules/find-my-way/.github/workflows/node.js.yml generated vendored Normal file
View File

@@ -0,0 +1,67 @@
name: Node CI
on:
push:
branches:
- main
- next
pull_request:
permissions:
contents: read
jobs:
test:
name: Test
runs-on: ${{ matrix.os }}
strategy:
matrix:
node-version:
- 20
- 22
os:
- ubuntu-latest
- windows-latest
- macOS-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0
with:
check-latest: true
node-version: ${{ matrix.node-version }}
- name: Install
run: |
npm install --ignore-scripts
- name: Lint
run: |
npm run test:lint
- name: Test
run: |
npm test
- name: Type Definitions
run: |
npm run test:typescript
automerge:
if: >
github.event_name == 'pull_request' && github.event.pull_request.user.login == 'dependabot[bot]'
needs: test
runs-on: ubuntu-latest
permissions:
actions: write
pull-requests: write
contents: write
steps:
- uses: fastify/github-action-merge-dependabot@e820d631adb1d8ab16c3b93e5afe713450884a4a # v3.11.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

21
node_modules/find-my-way/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017-2019 Tomas Della Vedova
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

823
node_modules/find-my-way/README.md generated vendored Normal file
View File

@@ -0,0 +1,823 @@
# find-my-way
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](http://standardjs.com/) [![Node CI](https://github.com/delvedor/find-my-way/actions/workflows/node.js.yml/badge.svg)](https://github.com/delvedor/find-my-way/actions/workflows/node.js.yml) [![NPM downloads](https://img.shields.io/npm/dm/find-my-way.svg?style=flat)](https://www.npmjs.com/package/find-my-way)
A crazy fast HTTP router, internally uses an highly performant [Radix Tree](https://en.wikipedia.org/wiki/Radix_tree) (aka compact [Prefix Tree](https://en.wikipedia.org/wiki/Trie)), supports route params, wildcards, and it's framework independent.
If you want to see a benchmark comparison with the most commonly used routers, see [here](https://github.com/delvedor/router-benchmark).<br>
Do you need a real-world example that uses this router? Check out [Fastify](https://github.com/fastify/fastify) or [Restify](https://github.com/restify/node-restify).
- [Install](#install)
- [Usage](#usage)
- [API](#api)
- [FindMyWay([options])](#findmywayoptions)
- [on(method, path, [opts], handler, [store])](#onmethod-path-opts-handler-store)
- [Versioned routes](#versioned-routes)
- [default](#default)
- [custom](#custom)
- [on(methods[], path, [opts], handler, [store])](#onmethods-path-opts-handler-store)
- [Supported path formats](#supported-path-formats)
- [Match order](#match-order)
- [Supported methods](#supported-methods)
- [off(methods[], path, [constraints])](#offmethods-path-constraints)
- [off(methods, path)](#offmethods-path)
- [off(methods, path, constraints)](#offmethods-path-constraints-1)
- [off(methods[], path)](#offmethods-path-1)
- [off(methods[], path, constraints)](#offmethods-path-constraints-2)
- [findRoute (method, path, [constraints])](#findroute-method-path-constraints)
- [hasRoute (method, path, [constraints])](#hasroute-method-path-constraints)
- [lookup(request, response, [context], [done])](#lookuprequest-response-context-done)
- [find(method, path, [constraints])](#findmethod-path-constraints)
- [prettyPrint([{ method: 'GET', commonPrefix: false, includeMeta: true || [] }])](#prettyprint-commonprefix-false-includemeta-true---)
- [reset()](#reset)
- [routes](#routes)
- [Caveats](#caveats)
- [Shorthand methods](#shorthand-methods)
- [Constraints](#constraints)
- [Custom Constraint Strategies](#custom-constraint-strategies)
- [Acknowledgements](#acknowledgements)
- [License](#license)
<a name="install"></a>
## Install
```
npm i find-my-way --save
```
<a name="usage"></a>
## Usage
```js
const http = require('http')
const router = require('find-my-way')()
router.on('GET', '/', (req, res, params) => {
res.end('{"message":"hello world"}')
})
const server = http.createServer((req, res) => {
router.lookup(req, res)
})
server.listen(3000, err => {
if (err) throw err
console.log('Server listening on: http://localhost:3000')
})
```
<a name="api"></a>
## API
<a name="constructor"></a>
#### FindMyWay([options])
Instance a new router.<br>
You can pass a default route with the option `defaultRoute`.
```js
const router = require('find-my-way')({
defaultRoute: (req, res) => {
res.statusCode = 404
res.end()
}
})
```
In case of a badly formatted url *(eg: `/hello/%world`)*, by default `find-my-way` will invoke the `defaultRoute`, unless you specify the `onBadUrl` option:
```js
const router = require('find-my-way')({
onBadUrl: (path, req, res) => {
res.statusCode = 400
res.end(`Bad path: ${path}`)
}
})
```
Trailing slashes can be ignored by supplying the `ignoreTrailingSlash` option:
```js
const router = require('find-my-way')({
ignoreTrailingSlash: true
})
function handler (req, res, params) {
res.end('foo')
}
// maps "/foo/" and "/foo" to `handler`
router.on('GET', '/foo/', handler)
```
Duplicate slashes can be ignored by supplying the `ignoreDuplicateSlashes` option:
```js
const router = require('find-my-way')({
ignoreDuplicateSlashes: true
})
function handler (req, res, params) {
res.end('foo')
}
// maps "/foo", "//foo", "///foo", etc to `handler`
router.on('GET', '////foo', handler)
```
Note that when `ignoreTrailingSlash` and `ignoreDuplicateSlashes` are both set to true, duplicate slashes will first be removed and then trailing slashes will, meaning `//a//b//c//` will be converted to `/a/b/c`.
You can set a custom length for parameters in parametric *(standard, regex and multi)* routes by using `maxParamLength` option, the default value is 100 characters.<br/>
*If the maximum length limit is reached, the default route will be invoked.*
```js
const router = require('find-my-way')({
maxParamLength: 500
})
```
If you are using a regex based route, `find-my-way` will throw an error if detects potentially catastrophic exponential-time regular expressions *(internally uses [`safe-regex2`](https://github.com/fastify/safe-regex2))*.<br/>
If you want to disable this behavior, pass the option `allowUnsafeRegex`.
```js
const router = require('find-my-way')({
allowUnsafeRegex: true
})
```
According to [RFC3986](https://tools.ietf.org/html/rfc3986#section-6.2.2.1), find-my-way is case sensitive by default.
You can disable this by setting the `caseSensitive` option to `false`:
in that case, all paths will be matched as lowercase, but the route parameters or wildcards will maintain their original letter casing. You can turn off case sensitivity with:
```js
const router = require('find-my-way')({
caseSensitive: false
})
```
The default query string parser that find-my-way uses is [fast-querystring](https://www.npmjs.com/package/fast-querystring) module. You can change this default setting by passing the option querystringParser and use a custom one, such as [qs](https://www.npmjs.com/package/qs).
```js
const qs = require('qs')
const router = require('find-my-way')({
querystringParser: str => qs.parse(str)
})
router.on('GET', '/', (req, res, params, store, searchParams) => {
assert.equal(searchParams, { foo: 'bar', baz: 'faz' })
})
router.lookup({ method: 'GET', url: '/?foo=bar&baz=faz' }, null)
```
According to [RFC3986](https://www.rfc-editor.org/rfc/rfc3986#section-3.4), find-my-way separates path and query string with `?` character. But earlier versions also used `;` as delimiter character. To support this behaviour, add the `useSemicolonDelimiter` option to `true`:
```js
const router = require('find-my-way')({
useSemicolonDelimiter: true
})
```
You can assign a `buildPrettyMeta` function to sanitize a route's `store` object to use with the `prettyPrint` functions. This function should accept a single object and return an object.
```js
const privateKey = new Symbol('private key')
const store = { token: '12345', [privateKey]: 'private value' }
const router = require('find-my-way')({
buildPrettyMeta: route => {
const cleanMeta = Object.assign({}, route.store)
// remove private properties
Object.keys(cleanMeta).forEach(k => {
if (typeof k === 'symbol') delete cleanMeta[k]
})
return cleanMeta // this will show up in the pretty print output!
}
})
store[privateKey] = 'private value'
router.on('GET', '/hello_world', (req, res) => {}, store)
router.prettyPrint()
//└── / (-)
// └── hello_world (GET)
// • (token) "12345"
```
<a name="on"></a>
#### on(method, path, [opts], handler, [store])
Register a new route.
```js
router.on('GET', '/example', (req, res, params, store, searchParams) => {
// your code
})
```
Last argument, `store` is used to pass an object that you can access later inside the handler function. If needed, `store` can be updated.
```js
router.on('GET', '/example', (req, res, params, store) => {
assert.equal(store, { message: 'hello world' })
}, { message: 'hello world' })
```
##### Versioned routes
If needed, you can provide a `version` route constraint, which will allow you to declare multiple versions of the same route that are used selectively when requests ask for different version using the `Accept-Version` header. This is useful if you want to support several different behaviours for a given route and different clients select among them.
If you never configure a versioned route, the `'Accept-Version'` header will be ignored. Remember to set a [Vary](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary) header in your responses with the value you are using for defining the versioning (e.g.: 'Accept-Version'), to prevent cache poisoning attacks. You can also configure this as part your Proxy/CDN.
###### default
<a name="semver"></a>
The default versioning strategy follows the [semver](https://semver.org/) specification. When using `lookup`, `find-my-way` will automatically detect the `Accept-Version` header and route the request accordingly. Internally `find-my-way` uses the [`semver-store`](https://github.com/delvedor/semver-store) to get the correct version of the route; *advanced ranges* and *pre-releases* currently are not supported.
*Be aware that using this feature will cause a degradation of the overall performances of the router.*
```js
router.on('GET', '/example', { constraints: { version: '1.2.0' }}, (req, res, params) => {
res.end('Hello from 1.2.0!')
})
router.on('GET', '/example', { constraints: { version: '2.4.0' }}, (req, res, params) => {
res.end('Hello from 2.4.0!')
})
// The 'Accept-Version' header could be '1.2.0' as well as '*', '2.x' or '2.4.x'
```
If you declare multiple versions with the same *major* or *minor* `find-my-way` will always choose the highest compatible with the `Accept-Version` header value.
###### custom
It's also possible to define a [custom versioning strategy](#custom-versioning) during the `find-my-way` initialization. In this case the logic of matching the request to the specific handler depends on the versioning strategy you use.
##### on(methods[], path, [opts], handler, [store])
Register a new route for each method specified in the `methods` array.
It comes handy when you need to declare multiple routes with the same handler but different methods.
```js
router.on(['GET', 'POST'], '/example', (req, res, params) => {
// your code
})
```
<a name="supported-path-formats"></a>
##### Supported path formats
To register a **parametric** path, use the *colon* before the parameter name. For **wildcard** use the *star*.
*Remember that static routes are always inserted before parametric and wildcard.*
```js
// parametric
router.on('GET', '/example/:userId', (req, res, params) => {}))
router.on('GET', '/example/:userId/:secretToken', (req, res, params) => {}))
// wildcard
router.on('GET', '/example/*', (req, res, params) => {}))
```
Regular expression routes are supported as well, but pay attention, RegExp are very expensive in term of performance!<br>
If you want to declare a regular expression route, you must put the regular expression inside round parenthesis after the parameter name.
```js
// parametric with regexp
router.on('GET', '/example/:file(^\\d+).png', () => {}))
```
It's possible to define more than one parameter within the same couple of slash ("/"). Such as:
```js
router.on('GET', '/example/near/:lat-:lng/radius/:r', (req, res, params) => {}))
```
*Remember in this case to use the dash ("-") as parameters separator.*
Finally it's possible to have multiple parameters with RegExp.
```js
router.on('GET', '/example/at/:hour(^\\d{2})h:minute(^\\d{2})m', (req, res, params) => {}))
```
In this case as parameter separator it's possible to use whatever character is not matched by the regular expression.
The last parameter can be made optional if you add a question mark ("?") at the end of the parameters name.
```js
router.on('GET', '/example/posts/:id?', (req, res, params) => {}))
```
In this case you can request `/example/posts` as well as `/example/posts/1`. The optional param will be undefined if not specified.
Having a route with multiple parameters may affect negatively the performance, so prefer single parameter approach whenever possible, especially on routes which are on the hot path of your application.
**Note** that you must encode the parameters containing [reserved characters](https://www.rfc-editor.org/rfc/rfc3986#section-2.2).
<a name="match-order"></a>
##### Match order
The routing algorithm matches one node at a time (where the node is a string between two slashes),
this means that it cannot know if a route is static or dynamic until it finishes to match the URL.
The nodes are matched in the following order:
1. static
2. parametric node with static ending
3. parametric(regex)/multi-parametric
4. parametric
5. wildcard
So if you declare the following routes
- `/foo/filename.png` - static route
- `/foo/:filename.png` - route with param `filename` and static ending `.png`
- `/foo/:filename.:ext` - route with two params `filename` and `ext`
- `/foo/:filename` - route with one param `filename`
- `/*` - wildcard route
You will have next matching rules:
- the static node would have the highest priority. It will be matched only if incoming URL equals `/foo/filename.png`
- the parametric node with a static ending would have the higher priority than other parametric nodes without it. This node would match any filenames with `.png` extension. If one node static ending ends with another node static ending, the node with a longer static ending would have higher priority.
- `/foo/:filename.png.png` - higher priority, more specific route
- `/foo/:filename.png` - lower priority
- the multi-parametric node (or any regexp node) without static ending would have lower priority than parametric node with static ending and higher priority than generic parametric node. You can declare only one node like that for the same route (see [caveats](#caveats)). It would match any filenames with any extensions.
- the parametric node has lower priority than any other parametric node. It would match any filenames, even if they don't have an extension.
- the wildcard node has the lowest priority of all nodes.
Once a url has been matched, `find-my-way` will figure out which handler registered for that path matches the request if there are any constraints.
`find-my-way` will check the most constrained handlers first, which means the handlers with the most keys in the `constraints` object.
> If you just want a path containing a colon without declaring a parameter, use a double colon.
> For example, `/name::customVerb` will be interpreted as `/name:customVerb`
<a name="supported-methods"></a>
##### Supported methods
The router is able to route all HTTP methods defined by [`http` core module](https://nodejs.org/api/http.html#http_http_methods).
<a name="off"></a>
#### off(methods[], path, [constraints])
Used to deregister routes.
<a name="off-without-constraints"></a>
##### off(methods, path)
If no constraint argument is passed, all routes with identical path and method are deregistered, regardless of whether
a route has constraints or not.
```js
router.on('GET', '/example', { constraints: { host: 'fastify.io' } })
router.on('GET', '/example', { constraints: { version: '1.x' } })
router.on('GET', '/example')
// Deregisters all 3 routes registered above
router.off('GET', '/example')
```
##### off(methods, path, constraints)
If a constraint object is specified, only those routes are deleted that have the same constraints as well as the
identical path and method. If an empty object is passed, only unconstrained routes will be deleted.
```js
router.on('GET', '/example', { constraints: { host: 'fastify.io' } })
router.on('GET', '/example', { constraints: { version: '1.x' } })
router.on('GET', '/example')
// Deregisters only the third route without constraints
router.off('GET', '/example', {})
// Deregisters only the first route
router.off('GET', '/example', { host: 'fastify.io' })
```
##### off(methods[], path)
Deregister a route for each method specified in the methods array. It comes handy when you need to deregister multiple
routes with the same path but different methods. As explained above, the constraints will be ignored here.
```js
router.on('GET', '/example', { constraints: { host: 'fastify.io' } })
router.on('POST', '/example', { constraints: { version: '1.x' } })
router.on('PUT', '/example')
// Deregisters all 3 routes registered above
router.off(['POST', 'GET', 'PUT'], '/example')
```
##### off(methods[], path, constraints)
```js
router.on('GET', '/example', { constraints: { host: 'fastify.io' } }) // first route
router.on('POST', '/example', { constraints: { host: 'fastify.io' } }) // second route
router.on('POST', '/example', { constraints: { host: 'google.de' } }) // third route
router.on('GET', '/example') // fourth route
router.on('POST', '/example') // fifth route
// Deregisters only first and second route
router.off(['POST', 'GET'], '/example', { host: 'fastify.io' })
// Deregisters only fourth and fifth route
router.off(['POST', 'GET'], '/example', {})
```
#### findRoute (method, path, [constraints])
Finds a route by server route's path (not like `find` which finds a route by the url). Returns the route object if found, otherwise returns `null`. `findRoute` does not compare routes paths directly, instead it compares only paths patters. This means that `findRoute` will return a route even if the path passed to it does not match the route's path exactly. For example, if a route is registered with the path `/example/:param1`, `findRoute` will return the route if the path passed to it is `/example/:param2`.
```js
const handler = (req, res, params) => {
res.end('Hello World!')
}
router.on('GET', '/:file(^\\S+).png', handler)
router.findRoute('GET', '/:file(^\\S+).png')
// => { handler: Function, store: Object, params: ['file'] }
router.findRoute('GET', '/:file(^\\D+).jpg')
// => null
```
```js
const handler = (req, res, params) => {
res.end('Hello World!')
}
router.on('GET', '/:param1', handler)
router.findRoute('GET', '/:param1')
// => { handler: Function, store: Object, params: ['param1'] }
router.findRoute('GET', '/:param2')
// => { handler: Function, store: Object, params: ['param1'] }
```
#### hasRoute (method, path, [constraints])
Checks if a route exists by server route's path (see `findRoute` for more details). Returns `true` if found, otherwise returns `false`.
```js
router.on('GET', '/:file(^\\S+).png', handler)
router.hasRoute('GET', '/:file(^\\S+).png')
// => true
router.hasRoute('GET', '/:file(^\\D+).jpg')
// => false
```
#### lookup(request, response, [context], [done])
Start a new search, `request` and `response` are the server req/res objects.<br>
If a route is found it will automatically call the handler, otherwise the default route will be called.<br>
The url is sanitized internally, all the parameters and wildcards are decoded automatically.
```js
router.lookup(req, res)
```
`lookup` accepts an optional context which will be the value of `this` when executing a handler
```js
router.on('GET', '*', function(req, res) {
res.end(this.greeting);
})
router.lookup(req, res, { greeting: 'Hello, World!' })
```
`lookup` accepts an optional `done` callback for case when you use an async `deriveConstraint` function.
```js
router.on('GET', '*', function(req, res) {
res.end({ hello: 'world' });
})
router.lookup(req, res, (err) => {
if (err !== null) {
// handle error
}
console.log('Handler executed!!!');
})
```
<a name="find"></a>
#### find(method, path, [constraints])
Return (if present) the route registered in *method:path*.<br>
The path must be sanitized, all the parameters and wildcards are decoded automatically.<br/>
An object with routing constraints should usually be passed as `constraints`, containing keys like the `host` for the request, the `version` for the route to be matched, or other custom constraint values. If the router is using the default versioning strategy, the version value should be conform to the [semver](https://semver.org/) specification. If you want to use the existing constraint strategies to derive the constraint values from an incoming request, use `lookup` instead of `find`. If no value is passed for `constraints`, the router won't match any constrained routes. If using constrained routes, passing `undefined` for the constraints leads to undefined behavior and should be avoided.
```js
router.find('GET', '/example', { host: 'fastify.io' })
// => { handler: Function, params: Object, store: Object}
// => null
router.find('GET', '/example', { host: 'fastify.io', version: '1.x' })
// => { handler: Function, params: Object, store: Object}
// => null
```
<a name="pretty-print"></a>
#### prettyPrint([{ commonPrefix: false, includeMeta: true || [] }])
`find-my-way` builds a tree of routes for each HTTP method. If you call the `prettyPrint`
without specifying an HTTP method, it will merge all the trees to one and print it.
The merged tree does't represent the internal router structure. Don't use it for debugging.
```js
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/hello', () => {})
findMyWay.on('GET', '/testing', () => {})
findMyWay.on('GET', '/testing/:param', () => {})
findMyWay.on('PUT', '/update', () => {})
console.log(findMyWay.prettyPrint())
// └── /
// ├── test (GET)
// │ ├── /hello (GET)
// │ └── ing (GET)
// │ └── /
// │ └── :param (GET)
// └── update (PUT)
```
If you want to print the internal tree, you can specify the `method` param.
Printed tree will represent the internal router structure. Use it for debugging.
```js
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/hello', () => {})
findMyWay.on('GET', '/testing', () => {})
findMyWay.on('GET', '/testing/:param', () => {})
findMyWay.on('PUT', '/update', () => {})
console.log(findMyWay.prettyPrint({ method: 'GET' }))
// └── /
// └── test (GET)
// ├── /hello (GET)
// └── ing (GET)
// └── /
// └── :param (GET)
console.log(findMyWay.prettyPrint({ method: 'PUT' }))
// └── /
// └── update (PUT)
```
`prettyPrint` accepts an optional setting to print compressed routes. This is useful
when you have a large number of routes with common prefixes. Doesn't represent the
internal router structure. **Don't use it for debugging.**
```js
console.log(findMyWay.prettyPrint({ commonPrefix: false }))
// ├── /test (GET)
// │ ├── /hello (GET)
// │ └── ing (GET)
// │ └── /:param (GET)
// └── /update (PUT)
```
To include a display of the `store` data passed to individual routes, the
option `includeMeta` may be passed. If set to `true` all items will be
displayed, this can also be set to an array specifying which keys (if
present) should be displayed. This information can be further sanitized
by specifying a `buildPrettyMeta` function which consumes and returns
an object.
```js
findMyWay.on('GET', '/test', () => {}, { onRequest: () => {}, authIDs: [1, 2, 3] })
findMyWay.on('GET', '/test/hello', () => {}, { token: 'df123-4567' })
findMyWay.on('GET', '/testing', () => {})
findMyWay.on('GET', '/testing/:param', () => {})
findMyWay.on('PUT', '/update', () => {})
console.log(findMyWay.prettyPrint({ commonPrefix: false, includeMeta: ['onRequest'] }))
// ├── /test (GET)
// │ • (onRequest) "onRequest()"
// │ ├── /hello (GET)
// │ └── ing (GET)
// │ └── /:param (GET)
// └── /update (PUT)
console.log(findMyWay.prettyPrint({ commonPrefix: false, includeMeta: true }))
// ├── /test (GET)
// │ • (onRequest) "onRequest()"
// │ • (authIDs) [1,2,3]
// │ ├── /hello (GET)
// │ │ • (token) "df123-4567"
// │ └── ing (GET)
// │ └── /:param (GET)
// └── /update (PUT)
```
<a name="reset"></a>
#### reset()
Empty router.
```js
router.reset()
```
<a name="routes"></a>
#### routes
Return the all routes **registered** at moment, useful for debugging.
```js
const findMyWay = require('find-my-way')()
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/hello', () => {})
console.log(findMyWay.routes)
// Will print
// [
// {
// method: 'GET',
// path: '/test',
// opts: {},
// handler: [Function],
// store: undefined
// },
// {
// method: 'GET',
// path: '/test/hello',
// opts: {},
// handler: [Function],
// store: undefined
// }
// ]
```
#### Caveats
* It's not possible to register two routes which differs only for their parameters, because internally they would be seen as the same route. In a such case you'll get an early error during the route registration phase. An example is worth thousand words:
```js
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {}
})
findMyWay.on('GET', '/user/:userId(^\\d+)', (req, res, params) => {})
findMyWay.on('GET', '/user/:username(^[a-z]+)', (req, res, params) => {})
// Method 'GET' already declared for route ':'
```
<a name="shorthand-methods"></a>
#### Shorthand methods
If you want an even nicer api, you can also use the shorthand methods to declare your routes.
For each HTTP supported method, there's the shorthand method. For example:
```js
router.get(path, handler [, store])
router.delete(path, handler [, store])
router.head(path, handler [, store])
router.patch(path, handler [, store])
router.post(path, handler [, store])
router.put(path, handler [, store])
router.options(path, handler [, store])
// ...
```
If you need a route that supports *all* methods you can use the `all` api.
```js
router.all(path, handler [, store])
```
<a name="lookup"></a>
## Constraints
`find-my-way` supports restricting handlers to only match certain requests for the same path. This can be used to support different versions of the same route that conform to a [semver](#semver) based versioning strategy, or restricting some routes to only be available on hosts. `find-my-way` has the semver based versioning strategy and a regex based hostname constraint strategy built in.
To constrain a route to only match sometimes, pass `constraints` to the route options when registering the route:
```js
findMyWay.on('GET', '/', { constraints: { version: '1.0.2' } }, (req, res) => {
// will only run when the request's Accept-Version header asks for a version semver compatible with 1.0.2, like 1.x, or 1.0.x.
})
findMyWay.on('GET', '/', { constraints: { host: 'example.com' } }, (req, res) => {
// will only run when the request's Host header is `example.com`
})
```
Constraints can be combined, and route handlers will only match if __all__ of the constraints for the handler match the request. `find-my-way` does a boolean AND with each route constraint, not an OR.
`find-my-way` will try to match the most constrained handlers first before handler with fewer or no constraints.
<a name="custom-constraint-strategies"></a>
### Custom Constraint Strategies
Custom constraining strategies can be added and are matched against incoming requests while trying to maintain `find-my-way`'s high performance. To register a new type of constraint, you must add a new constraint strategy that knows how to match values to handlers, and that knows how to get the constraint value from a request. Register strategies when constructing a router or use the addConstraintStrategy method.
Add a custom constrain strategy when constructing a router:
```js
const customResponseTypeStrategy = {
// strategy name for referencing in the route handler `constraints` options
name: 'accept',
// storage factory for storing routes in the find-my-way route tree
storage: function () {
let handlers = {}
return {
get: (type) => { return handlers[type] || null },
set: (type, store) => { handlers[type] = store }
}
},
// function to get the value of the constraint from each incoming request
deriveConstraint: (req, ctx) => {
return req.headers['accept']
},
// optional flag marking if handlers without constraints can match requests that have a value for this constraint
mustMatchWhenDerived: true
}
const router = FindMyWay({ constraints: { accept: customResponseTypeStrategy } });
```
Add an async custom constrain strategy when constructing a router:
```js
const asyncCustomResponseTypeStrategy = {
// strategy name for referencing in the route handler `constraints` options
name: 'accept',
// storage factory for storing routes in the find-my-way route tree
storage: function () {
let handlers = {}
return {
get: (type) => { return handlers[type] || null },
set: (type, store) => { handlers[type] = store }
}
},
// function to get the value of the constraint from each incoming request
deriveConstraint: (req, ctx, done) => {
done(null, req.headers['accept'])
},
// optional flag marking if handlers without constraints can match requests that have a value for this constraint
mustMatchWhenDerived: true
}
const router = FindMyWay({ constraints: { accept: asyncCustomResponseTypeStrategy } });
```
Add a custom constraint strategy using the `addConstraintStrategy` method:
```js
const customResponseTypeStrategy = {
// strategy name for referencing in the route handler `constraints` options
name: 'accept',
// storage factory for storing routes in the find-my-way route tree
storage: function () {
let handlers = {}
return {
get: (type) => { return handlers[type] || null },
set: (type, store) => { handlers[type] = store }
}
},
// function to get the value of the constraint from each incoming request
deriveConstraint: (req, ctx) => {
return req.headers['accept']
},
// optional flag marking if handlers without constraints can match requests that have a value for this constraint
mustMatchWhenDerived: true
}
const router = FindMyWay();
router.addConstraintStrategy(customResponseTypeStrategy);
```
Once a custom constraint strategy is registered, routes can be added that are constrained using it:
```js
findMyWay.on('GET', '/', { constraints: { accept: 'application/fancy+json' } }, (req, res) => {
// will only run when the request's Accept header asks for 'application/fancy+json'
})
findMyWay.on('GET', '/', { constraints: { accept: 'application/fancy+xml' } }, (req, res) => {
// will only run when the request's Accept header asks for 'application/fancy+xml'
})
```
Constraint strategies should be careful to make the `deriveConstraint` function performant as it is run for every request matched by the router. See the `lib/strategies` directory for examples of the built in constraint strategies.
<a name="custom-versioning"></a>
By default, `find-my-way` uses a built in strategies for the version constraint that uses semantic version based matching logic, which is detailed [below](#semver). It is possible to define an alternative strategy:
```js
const customVersioning = {
// replace the built in version strategy
name: 'version',
// provide a storage factory to store handlers in a simple way
storage: function () {
let versions = {}
return {
get: (version) => { return versions[version] || null },
set: (version, store) => { versions[version] = store }
}
},
deriveConstraint: (req, ctx) => {
return req.headers['accept']
},
mustMatchWhenDerived: true, // if the request is asking for a version, don't match un-version-constrained handlers
validate (value) { // optional validate function, validates the assigned value at route-configuration (the .on function) time (not the runtime-value)
assert(typeof value === 'string', 'Version should be a string')
}
}
const router = FindMyWay({ constraints: { version: customVersioning } });
```
The custom strategy object should contain next properties:
* `storage` - a factory function to store lists of handlers for each possible constraint value. The storage object can use domain-specific storage mechanisms to store handlers in a way that makes sense for the constraint at hand. See `lib/strategies` for examples, like the `version` constraint strategy that matches using semantic versions, or the `host` strategy that allows both exact and regex host constraints.
* `deriveConstraint` - the function to determine the value of this constraint given a request
The signature of the functions and objects must match the one from the example above.
*Please, be aware, if you use your own constraining strategy - you use it on your own risk. This can lead both to the performance degradation and bugs which are not related to `find-my-way` itself!*
<a name="acknowledgements"></a>
## Acknowledgements
It is inspired by the [echo](https://github.com/labstack/echo) router, some parts have been extracted from [trekjs](https://github.com/trekjs) router.
<a name="sponsor"></a>
#### Past sponsor
- [LetzDoIt](http://www.letzdoitapp.com/)
<a name="license"></a>
## License
**[find-my-way - MIT](https://github.com/delvedor/find-my-way/blob/master/LICENSE)**<br>
**[trekjs/router - MIT](https://github.com/trekjs/router/blob/master/LICENSE)**
Copyright © 2017-2019 Tomas Della Vedova

35
node_modules/find-my-way/benchmark/bench-thread.js generated vendored Normal file
View File

@@ -0,0 +1,35 @@
'use strict'
const { workerData: benchmark, parentPort } = require('worker_threads')
const Benchmark = require('benchmark')
// The default number of samples for Benchmark seems to be low enough that it
// can generate results with significant variance (~2%) for this benchmark
// suite. This makes it sometimes a bit confusing to actually evaluate impact of
// changes on performance. Setting the minimum of samples to 500 results in
// significantly lower variance on my local setup for this tests suite, and
// gives me higher confidence in benchmark results.
Benchmark.options.minSamples = 500
const suite = Benchmark.Suite()
const FindMyWay = require('..')
const findMyWay = new FindMyWay()
for (const { method, url, opts } of benchmark.setupURLs) {
if (opts !== undefined) {
findMyWay.on(method, url, opts, () => true)
} else {
findMyWay.on(method, url, () => true)
}
}
suite
.add(benchmark.name, () => {
findMyWay.lookup(...benchmark.arguments)
})
.on('cycle', (event) => {
parentPort.postMessage(String(event.target))
})
.on('complete', () => {})
.run()

156
node_modules/find-my-way/benchmark/bench.js generated vendored Normal file
View File

@@ -0,0 +1,156 @@
'use strict'
const path = require('path')
const { Worker } = require('worker_threads')
const BENCH_THREAD_PATH = path.join(__dirname, 'bench-thread.js')
const benchmarks = [
{
name: 'lookup root "/" route',
setupURLs: [{ method: 'GET', url: '/' }],
arguments: [{ method: 'GET', url: '/' }]
},
{
name: 'lookup short static route',
setupURLs: [{ method: 'GET', url: '/static' }],
arguments: [{ method: 'GET', url: '/static' }]
},
{
name: 'lookup long static route',
setupURLs: [{ method: 'GET', url: '/static/static/static/static/static' }],
arguments: [{ method: 'GET', url: '/static/static/static/static/static' }]
},
{
name: 'lookup long static route (common prefix)',
setupURLs: [
{ method: 'GET', url: '/static' },
{ method: 'GET', url: '/static/static' },
{ method: 'GET', url: '/static/static/static' },
{ method: 'GET', url: '/static/static/static/static' },
{ method: 'GET', url: '/static/static/static/static/static' }
],
arguments: [{ method: 'GET', url: '/static/static/static/static/static' }]
},
{
name: 'lookup short parametric route',
setupURLs: [{ method: 'GET', url: '/:param' }],
arguments: [{ method: 'GET', url: '/param1' }]
},
{
name: 'lookup long parametric route',
setupURLs: [{ method: 'GET', url: '/:param' }],
arguments: [{ method: 'GET', url: '/longParamParamParamParamParamParam' }]
},
{
name: 'lookup short parametric route (encoded unoptimized)',
setupURLs: [{ method: 'GET', url: '/:param' }],
arguments: [{ method: 'GET', url: '/param%2B' }]
},
{
name: 'lookup short parametric route (encoded optimized)',
setupURLs: [{ method: 'GET', url: '/:param' }],
arguments: [{ method: 'GET', url: '/param%20' }]
},
{
name: 'lookup parametric route with two short params',
setupURLs: [{ method: 'GET', url: '/:param1/:param2' }],
arguments: [{ method: 'GET', url: '/param1/param2' }]
},
{
name: 'lookup multi-parametric route with two short params',
setupURLs: [{ method: 'GET', url: '/:param1-:param2' }],
arguments: [{ method: 'GET', url: '/param1-param2' }]
},
{
name: 'lookup multi-parametric route with two short regex params',
setupURLs: [{ method: 'GET', url: '/:param1([a-z]*)1:param2([a-z]*)2' }],
arguments: [{ method: 'GET', url: '/param1param2' }]
},
{
name: 'lookup long static + parametric route',
setupURLs: [{ method: 'GET', url: '/static/:param1/static/:param2/static' }],
arguments: [{ method: 'GET', url: '/static/param1/static/param2/static' }]
},
{
name: 'lookup short wildcard route',
setupURLs: [{ method: 'GET', url: '/*' }],
arguments: [{ method: 'GET', url: '/static' }]
},
{
name: 'lookup long wildcard route',
setupURLs: [{ method: 'GET', url: '/*' }],
arguments: [{ method: 'GET', url: '/static/static/static/static/static' }]
},
{
name: 'lookup root route on constrained router',
setupURLs: [
{ method: 'GET', url: '/' },
{ method: 'GET', url: '/static', opts: { constraints: { version: '1.2.0' } } },
{ method: 'GET', url: '/static', opts: { constraints: { version: '2.0.0', host: 'example.com' } } },
{ method: 'GET', url: '/static', opts: { constraints: { version: '2.0.0', host: 'fastify.io' } } }
],
arguments: [{ method: 'GET', url: '/', headers: { host: 'fastify.io' } }]
},
{
name: 'lookup short static unconstraint route',
setupURLs: [
{ method: 'GET', url: '/static', opts: {} },
{ method: 'GET', url: '/static', opts: { constraints: { version: '2.0.0', host: 'example.com' } } },
{ method: 'GET', url: '/static', opts: { constraints: { version: '2.0.0', host: 'fastify.io' } } }
],
arguments: [{ method: 'GET', url: '/static', headers: {} }]
},
{
name: 'lookup short static versioned route',
setupURLs: [
{ method: 'GET', url: '/static', opts: { constraints: { version: '1.2.0' } } },
{ method: 'GET', url: '/static', opts: { constraints: { version: '2.0.0', host: 'example.com' } } },
{ method: 'GET', url: '/static', opts: { constraints: { version: '2.0.0', host: 'fastify.io' } } }
],
arguments: [{ method: 'GET', url: '/static', headers: { 'accept-version': '1.x', host: 'fastify.io' } }]
},
{
name: 'lookup short static constrained (version & host) route',
setupURLs: [
{ method: 'GET', url: '/static', opts: { constraints: { version: '1.2.0' } } },
{ method: 'GET', url: '/static', opts: { constraints: { version: '2.0.0', host: 'example.com' } } },
{ method: 'GET', url: '/static', opts: { constraints: { version: '2.0.0', host: 'fastify.io' } } }
],
arguments: [{ method: 'GET', url: '/static', headers: { 'accept-version': '2.x', host: 'fastify.io' } }]
}
]
async function runBenchmark (benchmark) {
const worker = new Worker(BENCH_THREAD_PATH, { workerData: benchmark })
return new Promise((resolve, reject) => {
let result = null
worker.on('error', reject)
worker.on('message', (benchResult) => {
result = benchResult
})
worker.on('exit', (code) => {
if (code === 0) {
resolve(result)
} else {
reject(new Error(`Worker stopped with exit code ${code}`))
}
})
})
}
async function runBenchmarks () {
let maxNameLength = 0
for (const benchmark of benchmarks) {
maxNameLength = Math.max(benchmark.name.length, maxNameLength)
}
for (const benchmark of benchmarks) {
benchmark.name = benchmark.name.padEnd(maxNameLength, '.')
const resultMessage = await runBenchmark(benchmark)
console.log(resultMessage)
}
}
runBenchmarks()

113
node_modules/find-my-way/benchmark/compare-branches.js generated vendored Normal file
View File

@@ -0,0 +1,113 @@
'use strict'
const { spawn } = require('child_process')
const chalk = require('chalk')
const inquirer = require('inquirer')
const simpleGit = require('simple-git')
const git = simpleGit(process.cwd())
const COMMAND = 'npm run bench'
const DEFAULT_BRANCH = 'main'
const PERCENT_THRESHOLD = 5
async function selectBranchName (message, branches) {
const result = await inquirer.prompt([{
type: 'list',
name: 'branch',
choices: branches,
loop: false,
pageSize: 20,
message
}])
return result.branch
}
async function executeCommandOnBranch (command, branch) {
console.log(chalk.grey(`Checking out "${branch}"`))
await git.checkout(branch)
console.log(chalk.grey(`Execute "${command}"`))
const childProcess = spawn(command, { stdio: 'pipe', shell: true })
let result = ''
childProcess.stdout.on('data', (data) => {
process.stdout.write(data.toString())
result += data.toString()
})
await new Promise(resolve => childProcess.on('close', resolve))
console.log()
return parseBenchmarksStdout(result)
}
function parseBenchmarksStdout (text) {
const results = []
for (const line of text.split('\n')) {
const match = /^(.+?)(\.*) x (.+) ops\/sec .*$/.exec(line)
if (match !== null) {
results.push({
name: match[1],
alignedName: match[1] + match[2],
result: parseInt(match[3].replaceAll(',', ''))
})
}
}
return results
}
function compareResults (featureBranch, mainBranch) {
for (const { name, alignedName, result: mainBranchResult } of mainBranch) {
const featureBranchBenchmark = featureBranch.find(result => result.name === name)
if (featureBranchBenchmark) {
const featureBranchResult = featureBranchBenchmark.result
const percent = (featureBranchResult - mainBranchResult) * 100 / mainBranchResult
const roundedPercent = Math.round(percent * 100) / 100
const percentString = roundedPercent > 0 ? `+${roundedPercent}%` : `${roundedPercent}%`
const message = alignedName + percentString.padStart(7, '.')
if (roundedPercent > PERCENT_THRESHOLD) {
console.log(chalk.green(message))
} else if (roundedPercent < -PERCENT_THRESHOLD) {
console.log(chalk.red(message))
} else {
console.log(message)
}
}
}
}
(async function () {
const branches = await git.branch()
const currentBranch = branches.branches[branches.current]
let featureBranch = null
let mainBranch = null
if (process.argv[2] === '--ci') {
featureBranch = currentBranch.name
mainBranch = DEFAULT_BRANCH
} else {
featureBranch = await selectBranchName('Select the branch you want to compare (feature branch):', branches.all)
mainBranch = await selectBranchName('Select the branch you want to compare with (main branch):', branches.all)
}
try {
const featureBranchResult = await executeCommandOnBranch(COMMAND, featureBranch)
const mainBranchResult = await executeCommandOnBranch(COMMAND, mainBranch)
compareResults(featureBranchResult, mainBranchResult)
} catch (error) {
console.error('Switch to origin branch due to an error', error.message)
}
await git.checkout(currentBranch.commit)
await git.checkout(currentBranch.name)
console.log(chalk.gray(`Back to ${currentBranch.name} ${currentBranch.commit}`))
})()

55
node_modules/find-my-way/benchmark/uri-decoding.js generated vendored Normal file
View File

@@ -0,0 +1,55 @@
'use strict'
const fastDecode = require('fast-decode-uri-component')
const Benchmark = require('benchmark')
Benchmark.options.minSamples = 500
const suite = Benchmark.Suite()
const uri = [
encodeURIComponent(' /?!#@=[](),\'"'),
encodeURIComponent('algunas palabras aquí'),
encodeURIComponent('acde=bdfd'),
encodeURIComponent('много русских букв'),
encodeURIComponent('這裡有些話'),
encodeURIComponent('कुछ शब्द यहाँ'),
encodeURIComponent('✌👀🎠🎡🍺')
]
function safeFastDecode (uri) {
if (uri.indexOf('%') < 0) return uri
try {
return fastDecode(uri)
} catch (e) {
return null // or it can be null
}
}
function safeDecodeURIComponent (uri) {
if (uri.indexOf('%') < 0) return uri
try {
return decodeURIComponent(uri)
} catch (e) {
return null // or it can be null
}
}
uri.forEach(function (u, i) {
suite.add(`safeDecodeURIComponent(${i}) [${u}]`, function () {
safeDecodeURIComponent(u)
})
suite.add(`fastDecode(${i}) [${u}]`, function () {
fastDecode(u)
})
suite.add(`safeFastDecode(${i}) [${u}]`, function () {
safeFastDecode(u)
})
})
suite
.on('cycle', function (event) {
console.log(String(event.target))
})
.on('complete', function () {
})
.run()

29
node_modules/find-my-way/example.js generated vendored Normal file
View File

@@ -0,0 +1,29 @@
'use strict'
const http = require('http')
const router = require('./')({
defaultRoute: (req, res) => {
res.end('not found')
}
})
router.on('GET', '/test', (req, res, params) => {
res.end('{"hello":"world"}')
})
router.on('GET', '/:test', (req, res, params) => {
res.end(JSON.stringify(params))
})
router.on('GET', '/text/hello', (req, res, params) => {
res.end('{"winter":"is here"}')
})
const server = http.createServer((req, res) => {
router.lookup(req, res)
})
server.listen(3000, err => {
if (err) throw err
console.log('Server listening on: http://localhost:3000')
})

237
node_modules/find-my-way/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,237 @@
import { IncomingMessage, ServerResponse } from 'http';
import { Http2ServerRequest, Http2ServerResponse } from 'http2';
declare function Router<V extends Router.HTTPVersion = Router.HTTPVersion.V1>(
config?: Router.Config<V>
): Router.Instance<V>;
declare namespace Router {
enum HTTPVersion {
V1 = 'http1',
V2 = 'http2'
}
type HTTPMethod =
| 'ACL'
| 'BIND'
| 'CHECKOUT'
| 'CONNECT'
| 'COPY'
| 'DELETE'
| 'GET'
| 'HEAD'
| 'LINK'
| 'LOCK'
| 'M-SEARCH'
| 'MERGE'
| 'MKACTIVITY'
| 'MKCALENDAR'
| 'MKCOL'
| 'MOVE'
| 'NOTIFY'
| 'OPTIONS'
| 'PATCH'
| 'POST'
| 'PROPFIND'
| 'PROPPATCH'
| 'PURGE'
| 'PUT'
| 'REBIND'
| 'REPORT'
| 'SEARCH'
| 'SOURCE'
| 'SUBSCRIBE'
| 'TRACE'
| 'UNBIND'
| 'UNLINK'
| 'UNLOCK'
| 'UNSUBSCRIBE';
type Req<V> = V extends HTTPVersion.V1 ? IncomingMessage : Http2ServerRequest;
type Res<V> = V extends HTTPVersion.V1 ? ServerResponse : Http2ServerResponse;
type Handler<V extends HTTPVersion> = (
req: Req<V>,
res: Res<V>,
params: { [k: string]: string | undefined },
store: any,
searchParams: { [k: string]: string }
) => any;
type Done = (err: Error | null, result: any) => void;
interface ConstraintStrategy<V extends HTTPVersion, T = string> {
name: string,
mustMatchWhenDerived?: boolean,
storage() : {
get(value: T) : Handler<V> | null,
set(value: T, handler: Handler<V>) : void,
del?(value: T) : void,
empty?() : void
},
validate?(value: unknown): void,
deriveConstraint<Context>(req: Req<V>, ctx?: Context) : T,
}
type QuerystringParser = (s: string) => unknown;
interface Config<V extends HTTPVersion> {
ignoreTrailingSlash?: boolean;
ignoreDuplicateSlashes?: boolean;
allowUnsafeRegex?: boolean;
caseSensitive?: boolean;
maxParamLength?: number;
querystringParser?: QuerystringParser;
defaultRoute?(
req: Req<V>,
res: Res<V>
): void;
onBadUrl?(
path: string,
req: Req<V>,
res: Res<V>
): void;
constraints? : {
[key: string]: ConstraintStrategy<V>
}
}
interface RouteOptions {
constraints?: { [key: string]: any }
}
interface ShortHandRoute<V extends HTTPVersion> {
(path: string, handler: Handler<V>): void;
(path: string, opts: RouteOptions, handler: Handler<V>): void;
(path: string, handler: Handler<V>, store: any): void;
(path: string, opts: RouteOptions, handler: Handler<V>, store: any): void;
}
interface FindResult<V extends HTTPVersion> {
handler: Handler<V>;
params: { [k: string]: string | undefined };
store: any;
searchParams: { [k: string]: string };
}
interface FindRouteResult<V extends HTTPVersion> {
handler: Handler<V>;
store: any;
params: string[];
}
interface Instance<V extends HTTPVersion> {
on(
method: HTTPMethod | HTTPMethod[],
path: string,
handler: Handler<V>
): void;
on(
method: HTTPMethod | HTTPMethod[],
path: string,
options: RouteOptions,
handler: Handler<V>
): void;
on(
method: HTTPMethod | HTTPMethod[],
path: string,
handler: Handler<V>,
store: any
): void;
on(
method: HTTPMethod | HTTPMethod[],
path: string,
options: RouteOptions,
handler: Handler<V>,
store: any
): void;
off(
method: HTTPMethod | HTTPMethod[],
path: string,
constraints?: { [key: string]: any }
): void;
lookup<Context>(
req: Req<V>,
res: Res<V>,
ctx?: Context | Done,
done?: Done
): any;
find(
method: HTTPMethod,
path: string,
constraints?: { [key: string]: any }
): FindResult<V> | null;
findRoute(
method: HTTPMethod,
path: string,
constraints?: { [key: string]: any }
): FindRouteResult<V> | null;
hasRoute(
method: HTTPMethod,
path: string,
constraints?: { [key: string]: any }
): boolean;
reset(): void;
prettyPrint(): string;
prettyPrint(opts: {
method?: HTTPMethod,
commonPrefix?: boolean,
includeMeta?: boolean | (string | symbol)[]
}): string;
hasConstraintStrategy(strategyName: string): boolean;
addConstraintStrategy(constraintStrategy: ConstraintStrategy<V>): void;
all: ShortHandRoute<V>;
acl: ShortHandRoute<V>;
bind: ShortHandRoute<V>;
checkout: ShortHandRoute<V>;
connect: ShortHandRoute<V>;
copy: ShortHandRoute<V>;
delete: ShortHandRoute<V>;
get: ShortHandRoute<V>;
head: ShortHandRoute<V>;
link: ShortHandRoute<V>;
lock: ShortHandRoute<V>;
'm-search': ShortHandRoute<V>;
merge: ShortHandRoute<V>;
mkactivity: ShortHandRoute<V>;
mkcalendar: ShortHandRoute<V>;
mkcol: ShortHandRoute<V>;
move: ShortHandRoute<V>;
notify: ShortHandRoute<V>;
options: ShortHandRoute<V>;
patch: ShortHandRoute<V>;
post: ShortHandRoute<V>;
propfind: ShortHandRoute<V>;
proppatch: ShortHandRoute<V>;
purge: ShortHandRoute<V>;
put: ShortHandRoute<V>;
rebind: ShortHandRoute<V>;
report: ShortHandRoute<V>;
search: ShortHandRoute<V>;
source: ShortHandRoute<V>;
subscribe: ShortHandRoute<V>;
trace: ShortHandRoute<V>;
unbind: ShortHandRoute<V>;
unlink: ShortHandRoute<V>;
unlock: ShortHandRoute<V>;
unsubscribe: ShortHandRoute<V>;
}
}
export = Router;

828
node_modules/find-my-way/index.js generated vendored Normal file
View File

@@ -0,0 +1,828 @@
'use strict'
/*
Char codes:
'!': 33 - !
'#': 35 - %23
'$': 36 - %24
'%': 37 - %25
'&': 38 - %26
''': 39 - '
'(': 40 - (
')': 41 - )
'*': 42 - *
'+': 43 - %2B
',': 44 - %2C
'-': 45 - -
'.': 46 - .
'/': 47 - %2F
':': 58 - %3A
';': 59 - %3B
'=': 61 - %3D
'?': 63 - %3F
'@': 64 - %40
'_': 95 - _
'~': 126 - ~
*/
const assert = require('node:assert')
const querystring = require('fast-querystring')
const isRegexSafe = require('safe-regex2')
const deepEqual = require('fast-deep-equal')
const { prettyPrintTree } = require('./lib/pretty-print')
const { StaticNode, NODE_TYPES } = require('./lib/node')
const Constrainer = require('./lib/constrainer')
const httpMethods = require('./lib/http-methods')
const httpMethodStrategy = require('./lib/strategies/http-method')
const { safeDecodeURI, safeDecodeURIComponent } = require('./lib/url-sanitizer')
const FULL_PATH_REGEXP = /^https?:\/\/.*?\//
const OPTIONAL_PARAM_REGEXP = /(\/:[^/()]*?)\?(\/?)/
const ESCAPE_REGEXP = /[.*+?^${}()|[\]\\]/g
const REMOVE_DUPLICATE_SLASHES_REGEXP = /\/\/+/g
if (!isRegexSafe(FULL_PATH_REGEXP)) {
throw new Error('the FULL_PATH_REGEXP is not safe, update this module')
}
if (!isRegexSafe(OPTIONAL_PARAM_REGEXP)) {
throw new Error('the OPTIONAL_PARAM_REGEXP is not safe, update this module')
}
if (!isRegexSafe(ESCAPE_REGEXP)) {
throw new Error('the ESCAPE_REGEXP is not safe, update this module')
}
if (!isRegexSafe(REMOVE_DUPLICATE_SLASHES_REGEXP)) {
throw new Error('the REMOVE_DUPLICATE_SLASHES_REGEXP is not safe, update this module')
}
function Router (opts) {
if (!(this instanceof Router)) {
return new Router(opts)
}
opts = opts || {}
this._opts = opts
if (opts.defaultRoute) {
assert(typeof opts.defaultRoute === 'function', 'The default route must be a function')
this.defaultRoute = opts.defaultRoute
} else {
this.defaultRoute = null
}
if (opts.onBadUrl) {
assert(typeof opts.onBadUrl === 'function', 'The bad url handler must be a function')
this.onBadUrl = opts.onBadUrl
} else {
this.onBadUrl = null
}
if (opts.buildPrettyMeta) {
assert(typeof opts.buildPrettyMeta === 'function', 'buildPrettyMeta must be a function')
this.buildPrettyMeta = opts.buildPrettyMeta
} else {
this.buildPrettyMeta = defaultBuildPrettyMeta
}
if (opts.querystringParser) {
assert(typeof opts.querystringParser === 'function', 'querystringParser must be a function')
this.querystringParser = opts.querystringParser
} else {
this.querystringParser = (query) => query.length === 0 ? {} : querystring.parse(query)
}
this.caseSensitive = opts.caseSensitive === undefined ? true : opts.caseSensitive
this.ignoreTrailingSlash = opts.ignoreTrailingSlash || false
this.ignoreDuplicateSlashes = opts.ignoreDuplicateSlashes || false
this.maxParamLength = opts.maxParamLength || 100
this.allowUnsafeRegex = opts.allowUnsafeRegex || false
this.constrainer = new Constrainer(opts.constraints)
this.useSemicolonDelimiter = opts.useSemicolonDelimiter || false
this.routes = []
this.trees = {}
}
Router.prototype.on = function on (method, path, opts, handler, store) {
if (typeof opts === 'function') {
if (handler !== undefined) {
store = handler
}
handler = opts
opts = {}
}
// path validation
assert(typeof path === 'string', 'Path should be a string')
assert(path.length > 0, 'The path could not be empty')
assert(path[0] === '/' || path[0] === '*', 'The first character of a path should be `/` or `*`')
// handler validation
assert(typeof handler === 'function', 'Handler should be a function')
// path ends with optional parameter
const optionalParamMatch = path.match(OPTIONAL_PARAM_REGEXP)
if (optionalParamMatch) {
assert(path.length === optionalParamMatch.index + optionalParamMatch[0].length, 'Optional Parameter needs to be the last parameter of the path')
const pathFull = path.replace(OPTIONAL_PARAM_REGEXP, '$1$2')
const pathOptional = path.replace(OPTIONAL_PARAM_REGEXP, '$2') || '/'
this.on(method, pathFull, opts, handler, store)
this.on(method, pathOptional, opts, handler, store)
return
}
const route = path
if (this.ignoreDuplicateSlashes) {
path = removeDuplicateSlashes(path)
}
if (this.ignoreTrailingSlash) {
path = trimLastSlash(path)
}
const methods = Array.isArray(method) ? method : [method]
for (const method of methods) {
assert(typeof method === 'string', 'Method should be a string')
assert(httpMethods.includes(method), `Method '${method}' is not an http method.`)
this._on(method, path, opts, handler, store, route)
}
}
Router.prototype._on = function _on (method, path, opts, handler, store) {
let constraints = {}
if (opts.constraints !== undefined) {
assert(typeof opts.constraints === 'object' && opts.constraints !== null, 'Constraints should be an object')
if (Object.keys(opts.constraints).length !== 0) {
constraints = opts.constraints
}
}
this.constrainer.validateConstraints(constraints)
// Let the constrainer know if any constraints are being used now
this.constrainer.noteUsage(constraints)
// Boot the tree for this method if it doesn't exist yet
if (this.trees[method] === undefined) {
this.trees[method] = new StaticNode('/')
}
let pattern = path
if (pattern === '*' && this.trees[method].prefix.length !== 0) {
const currentRoot = this.trees[method]
this.trees[method] = new StaticNode('')
this.trees[method].staticChildren['/'] = currentRoot
}
let currentNode = this.trees[method]
let parentNodePathIndex = currentNode.prefix.length
const params = []
for (let i = 0; i <= pattern.length; i++) {
if (pattern.charCodeAt(i) === 58 && pattern.charCodeAt(i + 1) === 58) {
// It's a double colon
i++
continue
}
const isParametricNode = pattern.charCodeAt(i) === 58 && pattern.charCodeAt(i + 1) !== 58
const isWildcardNode = pattern.charCodeAt(i) === 42
if (isParametricNode || isWildcardNode || (i === pattern.length && i !== parentNodePathIndex)) {
let staticNodePath = pattern.slice(parentNodePathIndex, i)
if (!this.caseSensitive) {
staticNodePath = staticNodePath.toLowerCase()
}
staticNodePath = staticNodePath.replaceAll('::', ':')
staticNodePath = staticNodePath.replaceAll('%', '%25')
// add the static part of the route to the tree
currentNode = currentNode.createStaticChild(staticNodePath)
}
if (isParametricNode) {
let isRegexNode = false
let isParamSafe = true
let backtrack = ''
const regexps = []
let lastParamStartIndex = i + 1
for (let j = lastParamStartIndex; ; j++) {
const charCode = pattern.charCodeAt(j)
const isRegexParam = charCode === 40
const isStaticPart = charCode === 45 || charCode === 46
const isEndOfNode = charCode === 47 || j === pattern.length
if (isRegexParam || isStaticPart || isEndOfNode) {
const paramName = pattern.slice(lastParamStartIndex, j)
params.push(paramName)
isRegexNode = isRegexNode || isRegexParam || isStaticPart
if (isRegexParam) {
const endOfRegexIndex = getClosingParenthensePosition(pattern, j)
const regexString = pattern.slice(j, endOfRegexIndex + 1)
if (!this.allowUnsafeRegex) {
assert(isRegexSafe(new RegExp(regexString)), `The regex '${regexString}' is not safe!`)
}
regexps.push(trimRegExpStartAndEnd(regexString))
j = endOfRegexIndex + 1
isParamSafe = true
} else {
regexps.push(isParamSafe ? '(.*?)' : `(${backtrack}|(?:(?!${backtrack}).)*)`)
isParamSafe = false
}
const staticPartStartIndex = j
for (; j < pattern.length; j++) {
const charCode = pattern.charCodeAt(j)
if (charCode === 47) break
if (charCode === 58) {
const nextCharCode = pattern.charCodeAt(j + 1)
if (nextCharCode === 58) j++
else break
}
}
let staticPart = pattern.slice(staticPartStartIndex, j)
if (staticPart) {
staticPart = staticPart.replaceAll('::', ':')
staticPart = staticPart.replaceAll('%', '%25')
regexps.push(backtrack = escapeRegExp(staticPart))
}
lastParamStartIndex = j + 1
if (isEndOfNode || pattern.charCodeAt(j) === 47 || j === pattern.length) {
const nodePattern = isRegexNode ? '()' + staticPart : staticPart
const nodePath = pattern.slice(i, j)
pattern = pattern.slice(0, i + 1) + nodePattern + pattern.slice(j)
i += nodePattern.length
const regex = isRegexNode ? new RegExp('^' + regexps.join('') + '$') : null
currentNode = currentNode.createParametricChild(regex, staticPart || null, nodePath)
parentNodePathIndex = i + 1
break
}
}
}
} else if (isWildcardNode) {
// add the wildcard parameter
params.push('*')
currentNode = currentNode.createWildcardChild()
parentNodePathIndex = i + 1
if (i !== pattern.length - 1) {
throw new Error('Wildcard must be the last character in the route')
}
}
}
if (!this.caseSensitive) {
pattern = pattern.toLowerCase()
}
if (pattern === '*') {
pattern = '/*'
}
for (const existRoute of this.routes) {
const routeConstraints = existRoute.opts.constraints || {}
if (
existRoute.method === method &&
existRoute.pattern === pattern &&
deepEqual(routeConstraints, constraints)
) {
throw new Error(`Method '${method}' already declared for route '${pattern}' with constraints '${JSON.stringify(constraints)}'`)
}
}
const route = { method, path, pattern, params, opts, handler, store }
this.routes.push(route)
currentNode.addRoute(route, this.constrainer)
}
Router.prototype.hasRoute = function hasRoute (method, path, constraints) {
const route = this.findRoute(method, path, constraints)
return route !== null
}
Router.prototype.findRoute = function findNode (method, path, constraints = {}) {
if (this.trees[method] === undefined) {
return null
}
let pattern = path
let currentNode = this.trees[method]
let parentNodePathIndex = currentNode.prefix.length
const params = []
for (let i = 0; i <= pattern.length; i++) {
if (pattern.charCodeAt(i) === 58 && pattern.charCodeAt(i + 1) === 58) {
// It's a double colon
i++
continue
}
const isParametricNode = pattern.charCodeAt(i) === 58 && pattern.charCodeAt(i + 1) !== 58
const isWildcardNode = pattern.charCodeAt(i) === 42
if (isParametricNode || isWildcardNode || (i === pattern.length && i !== parentNodePathIndex)) {
let staticNodePath = pattern.slice(parentNodePathIndex, i)
if (!this.caseSensitive) {
staticNodePath = staticNodePath.toLowerCase()
}
staticNodePath = staticNodePath.replaceAll('::', ':')
staticNodePath = staticNodePath.replaceAll('%', '%25')
// add the static part of the route to the tree
currentNode = currentNode.getStaticChild(staticNodePath)
if (currentNode === null) {
return null
}
}
if (isParametricNode) {
let isRegexNode = false
let isParamSafe = true
let backtrack = ''
const regexps = []
let lastParamStartIndex = i + 1
for (let j = lastParamStartIndex; ; j++) {
const charCode = pattern.charCodeAt(j)
const isRegexParam = charCode === 40
const isStaticPart = charCode === 45 || charCode === 46
const isEndOfNode = charCode === 47 || j === pattern.length
if (isRegexParam || isStaticPart || isEndOfNode) {
const paramName = pattern.slice(lastParamStartIndex, j)
params.push(paramName)
isRegexNode = isRegexNode || isRegexParam || isStaticPart
if (isRegexParam) {
const endOfRegexIndex = getClosingParenthensePosition(pattern, j)
const regexString = pattern.slice(j, endOfRegexIndex + 1)
if (!this.allowUnsafeRegex) {
assert(isRegexSafe(new RegExp(regexString)), `The regex '${regexString}' is not safe!`)
}
regexps.push(trimRegExpStartAndEnd(regexString))
j = endOfRegexIndex + 1
isParamSafe = false
} else {
regexps.push(isParamSafe ? '(.*?)' : `(${backtrack}|(?:(?!${backtrack}).)*)`)
isParamSafe = false
}
const staticPartStartIndex = j
for (; j < pattern.length; j++) {
const charCode = pattern.charCodeAt(j)
if (charCode === 47) break
if (charCode === 58) {
const nextCharCode = pattern.charCodeAt(j + 1)
if (nextCharCode === 58) j++
else break
}
}
let staticPart = pattern.slice(staticPartStartIndex, j)
if (staticPart) {
staticPart = staticPart.replaceAll('::', ':')
staticPart = staticPart.replaceAll('%', '%25')
regexps.push(backtrack = escapeRegExp(staticPart))
}
lastParamStartIndex = j + 1
if (isEndOfNode || pattern.charCodeAt(j) === 47 || j === pattern.length) {
const nodePattern = isRegexNode ? '()' + staticPart : staticPart
const nodePath = pattern.slice(i, j)
pattern = pattern.slice(0, i + 1) + nodePattern + pattern.slice(j)
i += nodePattern.length
const regex = isRegexNode ? new RegExp('^' + regexps.join('') + '$') : null
currentNode = currentNode.getParametricChild(regex, staticPart || null, nodePath)
if (currentNode === null) {
return null
}
parentNodePathIndex = i + 1
break
}
}
}
} else if (isWildcardNode) {
// add the wildcard parameter
params.push('*')
currentNode = currentNode.getWildcardChild()
parentNodePathIndex = i + 1
if (i !== pattern.length - 1) {
throw new Error('Wildcard must be the last character in the route')
}
}
}
if (!this.caseSensitive) {
pattern = pattern.toLowerCase()
}
for (const existRoute of this.routes) {
const routeConstraints = existRoute.opts.constraints || {}
if (
existRoute.method === method &&
existRoute.pattern === pattern &&
deepEqual(routeConstraints, constraints)
) {
return {
handler: existRoute.handler,
store: existRoute.store,
params: existRoute.params
}
}
}
return null
}
Router.prototype.hasConstraintStrategy = function (strategyName) {
return this.constrainer.hasConstraintStrategy(strategyName)
}
Router.prototype.addConstraintStrategy = function (constraints) {
this.constrainer.addConstraintStrategy(constraints)
this._rebuild(this.routes)
}
Router.prototype.reset = function reset () {
this.trees = {}
this.routes = []
}
Router.prototype.off = function off (method, path, constraints) {
// path validation
assert(typeof path === 'string', 'Path should be a string')
assert(path.length > 0, 'The path could not be empty')
assert(path[0] === '/' || path[0] === '*', 'The first character of a path should be `/` or `*`')
// options validation
assert(
typeof constraints === 'undefined' ||
(typeof constraints === 'object' && !Array.isArray(constraints) && constraints !== null),
'Constraints should be an object or undefined.')
// path ends with optional parameter
const optionalParamMatch = path.match(OPTIONAL_PARAM_REGEXP)
if (optionalParamMatch) {
assert(path.length === optionalParamMatch.index + optionalParamMatch[0].length, 'Optional Parameter needs to be the last parameter of the path')
const pathFull = path.replace(OPTIONAL_PARAM_REGEXP, '$1$2')
const pathOptional = path.replace(OPTIONAL_PARAM_REGEXP, '$2')
this.off(method, pathFull, constraints)
this.off(method, pathOptional, constraints)
return
}
if (this.ignoreDuplicateSlashes) {
path = removeDuplicateSlashes(path)
}
if (this.ignoreTrailingSlash) {
path = trimLastSlash(path)
}
const methods = Array.isArray(method) ? method : [method]
for (const method of methods) {
this._off(method, path, constraints)
}
}
Router.prototype._off = function _off (method, path, constraints) {
// method validation
assert(typeof method === 'string', 'Method should be a string')
assert(httpMethods.includes(method), `Method '${method}' is not an http method.`)
function matcherWithoutConstraints (route) {
return method !== route.method || path !== route.path
}
function matcherWithConstraints (route) {
return matcherWithoutConstraints(route) || !deepEqual(constraints, route.opts.constraints || {})
}
const predicate = constraints ? matcherWithConstraints : matcherWithoutConstraints
// Rebuild tree without the specific route
const newRoutes = this.routes.filter(predicate)
this._rebuild(newRoutes)
}
Router.prototype.lookup = function lookup (req, res, ctx, done) {
if (typeof ctx === 'function') {
done = ctx
ctx = undefined
}
if (done === undefined) {
const constraints = this.constrainer.deriveConstraints(req, ctx)
const handle = this.find(req.method, req.url, constraints)
return this.callHandler(handle, req, res, ctx)
}
this.constrainer.deriveConstraints(req, ctx, (err, constraints) => {
if (err !== null) {
done(err)
return
}
try {
const handle = this.find(req.method, req.url, constraints)
const result = this.callHandler(handle, req, res, ctx)
done(null, result)
} catch (err) {
done(err)
}
})
}
Router.prototype.callHandler = function callHandler (handle, req, res, ctx) {
if (handle === null) return this._defaultRoute(req, res, ctx)
return ctx === undefined
? handle.handler(req, res, handle.params, handle.store, handle.searchParams)
: handle.handler.call(ctx, req, res, handle.params, handle.store, handle.searchParams)
}
Router.prototype.find = function find (method, path, derivedConstraints) {
let currentNode = this.trees[method]
if (currentNode === undefined) return null
if (path.charCodeAt(0) !== 47) { // 47 is '/'
path = path.replace(FULL_PATH_REGEXP, '/')
}
// This must be run before sanitizeUrl as the resulting function
// .sliceParameter must be constructed with same URL string used
// throughout the rest of this function.
if (this.ignoreDuplicateSlashes) {
path = removeDuplicateSlashes(path)
}
let sanitizedUrl
let querystring
let shouldDecodeParam
try {
sanitizedUrl = safeDecodeURI(path, this.useSemicolonDelimiter)
path = sanitizedUrl.path
querystring = sanitizedUrl.querystring
shouldDecodeParam = sanitizedUrl.shouldDecodeParam
} catch (error) {
return this._onBadUrl(path)
}
if (this.ignoreTrailingSlash) {
path = trimLastSlash(path)
}
const originPath = path
if (this.caseSensitive === false) {
path = path.toLowerCase()
}
const maxParamLength = this.maxParamLength
let pathIndex = currentNode.prefix.length
const params = []
const pathLen = path.length
const brothersNodesStack = []
while (true) {
if (pathIndex === pathLen && currentNode.isLeafNode) {
const handle = currentNode.handlerStorage.getMatchingHandler(derivedConstraints)
if (handle !== null) {
return {
handler: handle.handler,
store: handle.store,
params: handle._createParamsObject(params),
searchParams: this.querystringParser(querystring)
}
}
}
let node = currentNode.getNextNode(path, pathIndex, brothersNodesStack, params.length)
if (node === null) {
if (brothersNodesStack.length === 0) {
return null
}
const brotherNodeState = brothersNodesStack.pop()
pathIndex = brotherNodeState.brotherPathIndex
params.splice(brotherNodeState.paramsCount)
node = brotherNodeState.brotherNode
}
currentNode = node
// static route
if (currentNode.kind === NODE_TYPES.STATIC) {
pathIndex += currentNode.prefix.length
continue
}
if (currentNode.kind === NODE_TYPES.WILDCARD) {
let param = originPath.slice(pathIndex)
if (shouldDecodeParam) {
param = safeDecodeURIComponent(param)
}
params.push(param)
pathIndex = pathLen
continue
}
// parametric node
let paramEndIndex = originPath.indexOf('/', pathIndex)
if (paramEndIndex === -1) {
paramEndIndex = pathLen
}
let param = originPath.slice(pathIndex, paramEndIndex)
if (shouldDecodeParam) {
param = safeDecodeURIComponent(param)
}
if (currentNode.isRegex) {
const matchedParameters = currentNode.regex.exec(param)
if (matchedParameters === null) continue
for (let i = 1; i < matchedParameters.length; i++) {
const matchedParam = matchedParameters[i]
if (matchedParam.length > maxParamLength) {
return null
}
params.push(matchedParam)
}
} else {
if (param.length > maxParamLength) {
return null
}
params.push(param)
}
pathIndex = paramEndIndex
}
}
Router.prototype._rebuild = function (routes) {
this.reset()
for (const route of routes) {
const { method, path, opts, handler, store } = route
this._on(method, path, opts, handler, store)
}
}
Router.prototype._defaultRoute = function (req, res, ctx) {
if (this.defaultRoute !== null) {
return ctx === undefined
? this.defaultRoute(req, res)
: this.defaultRoute.call(ctx, req, res)
} else {
res.statusCode = 404
res.end()
}
}
Router.prototype._onBadUrl = function (path) {
if (this.onBadUrl === null) {
return null
}
const onBadUrl = this.onBadUrl
return {
handler: (req, res, ctx) => onBadUrl(path, req, res),
params: {},
store: null
}
}
Router.prototype.prettyPrint = function (options = {}) {
const method = options.method
options.buildPrettyMeta = this.buildPrettyMeta.bind(this)
let tree = null
if (method === undefined) {
const { version, host, ...constraints } = this.constrainer.strategies
constraints[httpMethodStrategy.name] = httpMethodStrategy
const mergedRouter = new Router({ ...this._opts, constraints })
const mergedRoutes = this.routes.map(route => {
const constraints = {
...route.opts.constraints,
[httpMethodStrategy.name]: route.method
}
return { ...route, method: 'MERGED', opts: { constraints } }
})
mergedRouter._rebuild(mergedRoutes)
tree = mergedRouter.trees.MERGED
} else {
tree = this.trees[method]
}
if (tree == null) return '(empty tree)'
return prettyPrintTree(tree, options)
}
for (const i in httpMethods) {
/* eslint no-prototype-builtins: "off" */
if (!httpMethods.hasOwnProperty(i)) continue
const m = httpMethods[i]
const methodName = m.toLowerCase()
Router.prototype[methodName] = function (path, handler, store) {
return this.on(m, path, handler, store)
}
}
Router.prototype.all = function (path, handler, store) {
this.on(httpMethods, path, handler, store)
}
module.exports = Router
function escapeRegExp (string) {
return string.replace(ESCAPE_REGEXP, '\\$&')
}
function removeDuplicateSlashes (path) {
return path.indexOf('//') !== -1 ? path.replace(REMOVE_DUPLICATE_SLASHES_REGEXP, '/') : path
}
function trimLastSlash (path) {
if (path.length > 1 && path.charCodeAt(path.length - 1) === 47) {
return path.slice(0, -1)
}
return path
}
function trimRegExpStartAndEnd (regexString) {
// removes chars that marks start "^" and end "$" of regexp
if (regexString.charCodeAt(1) === 94) {
regexString = regexString.slice(0, 1) + regexString.slice(2)
}
if (regexString.charCodeAt(regexString.length - 2) === 36) {
regexString = regexString.slice(0, regexString.length - 2) + regexString.slice(regexString.length - 1)
}
return regexString
}
function getClosingParenthensePosition (path, idx) {
// `path.indexOf()` will always return the first position of the closing parenthese,
// but it's inefficient for grouped or wrong regexp expressions.
// see issues #62 and #63 for more info
let parentheses = 1
while (idx < path.length) {
idx++
// ignore skipped chars "\"
if (path.charCodeAt(idx) === 92) {
idx++
continue
}
if (path.charCodeAt(idx) === 41) {
parentheses--
} else if (path.charCodeAt(idx) === 40) {
parentheses++
}
if (!parentheses) return idx
}
throw new TypeError('Invalid regexp expression in "' + path + '"')
}
function defaultBuildPrettyMeta (route) {
// buildPrettyMeta function must return an object, which will be parsed into key/value pairs for display
if (!route) return {}
if (!route.store) return {}
return Object.assign({}, route.store)
}

170
node_modules/find-my-way/lib/constrainer.js generated vendored Normal file
View File

@@ -0,0 +1,170 @@
'use strict'
const acceptVersionStrategy = require('./strategies/accept-version')
const acceptHostStrategy = require('./strategies/accept-host')
const assert = require('node:assert')
class Constrainer {
constructor (customStrategies) {
this.strategies = {
version: acceptVersionStrategy,
host: acceptHostStrategy
}
this.strategiesInUse = new Set()
this.asyncStrategiesInUse = new Set()
// validate and optimize prototypes of given custom strategies
if (customStrategies) {
for (const strategy of Object.values(customStrategies)) {
this.addConstraintStrategy(strategy)
}
}
}
isStrategyUsed (strategyName) {
return this.strategiesInUse.has(strategyName) ||
this.asyncStrategiesInUse.has(strategyName)
}
hasConstraintStrategy (strategyName) {
const customConstraintStrategy = this.strategies[strategyName]
if (customConstraintStrategy !== undefined) {
return customConstraintStrategy.isCustom ||
this.isStrategyUsed(strategyName)
}
return false
}
addConstraintStrategy (strategy) {
assert(typeof strategy.name === 'string' && strategy.name !== '', 'strategy.name is required.')
assert(strategy.storage && typeof strategy.storage === 'function', 'strategy.storage function is required.')
assert(strategy.deriveConstraint && typeof strategy.deriveConstraint === 'function', 'strategy.deriveConstraint function is required.')
if (this.strategies[strategy.name] && this.strategies[strategy.name].isCustom) {
throw new Error(`There already exists a custom constraint with the name ${strategy.name}.`)
}
if (this.isStrategyUsed(strategy.name)) {
throw new Error(`There already exists a route with ${strategy.name} constraint.`)
}
strategy.isCustom = true
strategy.isAsync = strategy.deriveConstraint.length === 3
this.strategies[strategy.name] = strategy
if (strategy.mustMatchWhenDerived) {
this.noteUsage({ [strategy.name]: strategy })
}
}
deriveConstraints (req, ctx, done) {
const constraints = this.deriveSyncConstraints(req, ctx)
if (done === undefined) {
return constraints
}
this.deriveAsyncConstraints(constraints, req, ctx, done)
}
deriveSyncConstraints (req, ctx) {
return undefined
}
// When new constraints start getting used, we need to rebuild the deriver to derive them. Do so if we see novel constraints used.
noteUsage (constraints) {
if (constraints) {
const beforeSize = this.strategiesInUse.size
for (const key in constraints) {
const strategy = this.strategies[key]
if (strategy.isAsync) {
this.asyncStrategiesInUse.add(key)
} else {
this.strategiesInUse.add(key)
}
}
if (beforeSize !== this.strategiesInUse.size) {
this._buildDeriveConstraints()
}
}
}
newStoreForConstraint (constraint) {
if (!this.strategies[constraint]) {
throw new Error(`No strategy registered for constraint key ${constraint}`)
}
return this.strategies[constraint].storage()
}
validateConstraints (constraints) {
for (const key in constraints) {
const value = constraints[key]
if (typeof value === 'undefined') {
throw new Error('Can\'t pass an undefined constraint value, must pass null or no key at all')
}
const strategy = this.strategies[key]
if (!strategy) {
throw new Error(`No strategy registered for constraint key ${key}`)
}
if (strategy.validate) {
strategy.validate(value)
}
}
}
deriveAsyncConstraints (constraints, req, ctx, done) {
let asyncConstraintsCount = this.asyncStrategiesInUse.size
if (asyncConstraintsCount === 0) {
done(null, constraints)
return
}
constraints = constraints || {}
for (const key of this.asyncStrategiesInUse) {
const strategy = this.strategies[key]
strategy.deriveConstraint(req, ctx, (err, constraintValue) => {
if (err !== null) {
done(err)
return
}
constraints[key] = constraintValue
if (--asyncConstraintsCount === 0) {
done(null, constraints)
}
})
}
}
// Optimization: build a fast function for deriving the constraints for all the strategies at once. We inline the definitions of the version constraint and the host constraint for performance.
// If no constraining strategies are in use (no routes constrain on host, or version, or any custom strategies) then we don't need to derive constraints for each route match, so don't do anything special, and just return undefined
// This allows us to not allocate an object to hold constraint values if no constraints are defined.
_buildDeriveConstraints () {
if (this.strategiesInUse.size === 0) return
const lines = ['return {']
for (const key of this.strategiesInUse) {
const strategy = this.strategies[key]
// Optimization: inline the derivation for the common built in constraints
if (!strategy.isCustom) {
if (key === 'version') {
lines.push(' version: req.headers[\'accept-version\'],')
} else {
lines.push(' host: req.headers.host || req.headers[\':authority\'],')
}
} else {
lines.push(` ${strategy.name}: this.strategies.${key}.deriveConstraint(req, ctx),`)
}
}
lines.push('}')
this.deriveSyncConstraints = new Function('req', 'ctx', lines.join('\n')).bind(this) // eslint-disable-line
}
}
module.exports = Constrainer

174
node_modules/find-my-way/lib/handler-storage.js generated vendored Normal file
View File

@@ -0,0 +1,174 @@
'use strict'
const { NullObject } = require('./null-object')
const httpMethodStrategy = require('./strategies/http-method')
class HandlerStorage {
constructor () {
this.unconstrainedHandler = null // optimized reference to the handler that will match most of the time
this.constraints = []
this.handlers = [] // unoptimized list of handler objects for which the fast matcher function will be compiled
this.constrainedHandlerStores = null
}
// This is the hot path for node handler finding -- change with care!
getMatchingHandler (derivedConstraints) {
if (derivedConstraints === undefined) {
return this.unconstrainedHandler
}
return this._getHandlerMatchingConstraints(derivedConstraints)
}
addHandler (constrainer, route) {
const params = route.params
const constraints = route.opts.constraints || {}
const handlerObject = {
params,
constraints,
handler: route.handler,
store: route.store || null,
_createParamsObject: this._compileCreateParamsObject(params)
}
const constraintsNames = Object.keys(constraints)
if (constraintsNames.length === 0) {
this.unconstrainedHandler = handlerObject
}
for (const constraint of constraintsNames) {
if (!this.constraints.includes(constraint)) {
if (constraint === 'version') {
// always check the version constraint first as it is the most selective
this.constraints.unshift(constraint)
} else {
this.constraints.push(constraint)
}
}
}
const isMergedTree = constraintsNames.includes(httpMethodStrategy.name)
if (!isMergedTree && this.handlers.length >= 31) {
throw new Error('find-my-way supports a maximum of 31 route handlers per node when there are constraints, limit reached')
}
this.handlers.push(handlerObject)
// Sort the most constrained handlers to the front of the list of handlers so they are tested first.
this.handlers.sort((a, b) => Object.keys(a.constraints).length - Object.keys(b.constraints).length)
if (!isMergedTree) {
this._compileGetHandlerMatchingConstraints(constrainer, constraints)
}
}
_compileCreateParamsObject (params) {
const fnBody = []
fnBody.push('const fn = function _createParamsObject (paramsArray) {')
fnBody.push('const params = new NullObject()')
for (let i = 0; i < params.length; i++) {
fnBody.push(`params['${params[i]}'] = paramsArray[${i}]`)
}
fnBody.push('return params')
fnBody.push('}')
fnBody.push('return fn')
return new Function('NullObject', fnBody.join('\n'))(NullObject) // eslint-disable-line
}
_getHandlerMatchingConstraints () {
return null
}
// Builds a store object that maps from constraint values to a bitmap of handler indexes which pass the constraint for a value
// So for a host constraint, this might look like { "fastify.io": 0b0010, "google.ca": 0b0101 }, meaning the 3rd handler is constrainted to fastify.io, and the 2nd and 4th handlers are constrained to google.ca.
// The store's implementation comes from the strategies provided to the Router.
_buildConstraintStore (store, constraint) {
for (let i = 0; i < this.handlers.length; i++) {
const handler = this.handlers[i]
const constraintValue = handler.constraints[constraint]
if (constraintValue !== undefined) {
let indexes = store.get(constraintValue) || 0
indexes |= 1 << i // set the i-th bit for the mask because this handler is constrained by this value https://stackoverflow.com/questions/1436438/how-do-you-set-clear-and-toggle-a-single-bit-in-javascrip
store.set(constraintValue, indexes)
}
}
}
// Builds a bitmask for a given constraint that has a bit for each handler index that is 0 when that handler *is* constrained and 1 when the handler *isnt* constrainted. This is opposite to what might be obvious, but is just for convienience when doing the bitwise operations.
_constrainedIndexBitmask (constraint) {
let mask = 0
for (let i = 0; i < this.handlers.length; i++) {
const handler = this.handlers[i]
const constraintValue = handler.constraints[constraint]
if (constraintValue !== undefined) {
mask |= 1 << i
}
}
return ~mask
}
// Compile a fast function to match the handlers for this node
// The function implements a general case multi-constraint matching algorithm.
// The general idea is this: we have a bunch of handlers, each with a potentially different set of constraints, and sometimes none at all. We're given a list of constraint values and we have to use the constraint-value-comparison strategies to see which handlers match the constraint values passed in.
// We do this by asking each constraint store which handler indexes match the given constraint value for each store. Trickily, the handlers that a store says match are the handlers constrained by that store, but handlers that aren't constrained at all by that store could still match just fine. So, each constraint store can only describe matches for it, and it won't have any bearing on the handlers it doesn't care about. For this reason, we have to ask each stores which handlers match and track which have been matched (or not cared about) by all of them.
// We use bitmaps to represent these lists of matches so we can use bitwise operations to implement this efficiently. Bitmaps are cheap to allocate, let us implement this masking behaviour in one CPU instruction, and are quite compact in memory. We start with a bitmap set to all 1s representing every handler that is a match candidate, and then for each constraint, see which handlers match using the store, and then mask the result by the mask of handlers that that store applies to, and bitwise AND with the candidate list. Phew.
// We consider all this compiling function complexity to be worth it, because the naive implementation that just loops over the handlers asking which stores match is quite a bit slower.
_compileGetHandlerMatchingConstraints (constrainer) {
this.constrainedHandlerStores = {}
for (const constraint of this.constraints) {
const store = constrainer.newStoreForConstraint(constraint)
this.constrainedHandlerStores[constraint] = store
this._buildConstraintStore(store, constraint)
}
const lines = []
lines.push(`
let candidates = ${(1 << this.handlers.length) - 1}
let mask, matches
`)
for (const constraint of this.constraints) {
// Setup the mask for indexes this constraint applies to. The mask bits are set to 1 for each position if the constraint applies.
lines.push(`
mask = ${this._constrainedIndexBitmask(constraint)}
value = derivedConstraints.${constraint}
`)
// If there's no constraint value, none of the handlers constrained by this constraint can match. Remove them from the candidates.
// If there is a constraint value, get the matching indexes bitmap from the store, and mask it down to only the indexes this constraint applies to, and then bitwise and with the candidates list to leave only matching candidates left.
const strategy = constrainer.strategies[constraint]
const matchMask = strategy.mustMatchWhenDerived ? 'matches' : '(matches | mask)'
lines.push(`
if (value === undefined) {
candidates &= mask
} else {
matches = this.constrainedHandlerStores.${constraint}.get(value) || 0
candidates &= ${matchMask}
}
if (candidates === 0) return null;
`)
}
// There are some constraints that can be derived and marked as "must match", where if they are derived, they only match routes that actually have a constraint on the value, like the SemVer version constraint.
// An example: a request comes in for version 1.x, and this node has a handler that matches the path, but there's no version constraint. For SemVer, the find-my-way semantics do not match this handler to that request.
// This function is used by Nodes with handlers to match when they don't have any constrained routes to exclude request that do have must match derived constraints present.
for (const constraint in constrainer.strategies) {
const strategy = constrainer.strategies[constraint]
if (strategy.mustMatchWhenDerived && !this.constraints.includes(constraint)) {
lines.push(`if (derivedConstraints.${constraint} !== undefined) return null`)
}
}
// Return the first handler who's bit is set in the candidates https://stackoverflow.com/questions/18134985/how-to-find-index-of-first-set-bit
lines.push('return this.handlers[Math.floor(Math.log2(candidates))]')
this._getHandlerMatchingConstraints = new Function('derivedConstraints', lines.join('\n')) // eslint-disable-line
}
}
module.exports = HandlerStorage

13
node_modules/find-my-way/lib/http-methods.js generated vendored Normal file
View File

@@ -0,0 +1,13 @@
'use strict'
// defined by Node.js http module, a snapshot from Node.js 22.9.0
const httpMethods = [
'ACL', 'BIND', 'CHECKOUT', 'CONNECT', 'COPY', 'DELETE',
'GET', 'HEAD', 'LINK', 'LOCK', 'M-SEARCH', 'MERGE',
'MKACTIVITY', 'MKCALENDAR', 'MKCOL', 'MOVE', 'NOTIFY', 'OPTIONS',
'PATCH', 'POST', 'PROPFIND', 'PROPPATCH', 'PURGE', 'PUT', 'QUERY',
'REBIND', 'REPORT', 'SEARCH', 'SOURCE', 'SUBSCRIBE', 'TRACE',
'UNBIND', 'UNLINK', 'UNLOCK', 'UNSUBSCRIBE'
]
module.exports = httpMethods

228
node_modules/find-my-way/lib/node.js generated vendored Normal file
View File

@@ -0,0 +1,228 @@
'use strict'
const HandlerStorage = require('./handler-storage')
const NODE_TYPES = {
STATIC: 0,
PARAMETRIC: 1,
WILDCARD: 2
}
class Node {
constructor () {
this.isLeafNode = false
this.routes = null
this.handlerStorage = null
}
addRoute (route, constrainer) {
if (this.routes === null) {
this.routes = []
}
if (this.handlerStorage === null) {
this.handlerStorage = new HandlerStorage()
}
this.isLeafNode = true
this.routes.push(route)
this.handlerStorage.addHandler(constrainer, route)
}
}
class ParentNode extends Node {
constructor () {
super()
this.staticChildren = {}
}
findStaticMatchingChild (path, pathIndex) {
const staticChild = this.staticChildren[path.charAt(pathIndex)]
if (staticChild === undefined || !staticChild.matchPrefix(path, pathIndex)) {
return null
}
return staticChild
}
getStaticChild (path, pathIndex = 0) {
if (path.length === pathIndex) {
return this
}
const staticChild = this.findStaticMatchingChild(path, pathIndex)
if (staticChild) {
return staticChild.getStaticChild(path, pathIndex + staticChild.prefix.length)
}
return null
}
createStaticChild (path) {
if (path.length === 0) {
return this
}
let staticChild = this.staticChildren[path.charAt(0)]
if (staticChild) {
let i = 1
for (; i < staticChild.prefix.length; i++) {
if (path.charCodeAt(i) !== staticChild.prefix.charCodeAt(i)) {
staticChild = staticChild.split(this, i)
break
}
}
return staticChild.createStaticChild(path.slice(i))
}
const label = path.charAt(0)
this.staticChildren[label] = new StaticNode(path)
return this.staticChildren[label]
}
}
class StaticNode extends ParentNode {
constructor (prefix) {
super()
this.prefix = prefix
this.wildcardChild = null
this.parametricChildren = []
this.kind = NODE_TYPES.STATIC
this._compilePrefixMatch()
}
getParametricChild (regex) {
const regexpSource = regex && regex.source
const parametricChild = this.parametricChildren.find(child => {
const childRegexSource = child.regex && child.regex.source
return childRegexSource === regexpSource
})
if (parametricChild) {
return parametricChild
}
return null
}
createParametricChild (regex, staticSuffix, nodePath) {
let parametricChild = this.getParametricChild(regex)
if (parametricChild) {
parametricChild.nodePaths.add(nodePath)
return parametricChild
}
parametricChild = new ParametricNode(regex, staticSuffix, nodePath)
this.parametricChildren.push(parametricChild)
this.parametricChildren.sort((child1, child2) => {
if (!child1.isRegex) return 1
if (!child2.isRegex) return -1
if (child1.staticSuffix === null) return 1
if (child2.staticSuffix === null) return -1
if (child2.staticSuffix.endsWith(child1.staticSuffix)) return 1
if (child1.staticSuffix.endsWith(child2.staticSuffix)) return -1
return 0
})
return parametricChild
}
getWildcardChild () {
return this.wildcardChild
}
createWildcardChild () {
this.wildcardChild = this.getWildcardChild() || new WildcardNode()
return this.wildcardChild
}
split (parentNode, length) {
const parentPrefix = this.prefix.slice(0, length)
const childPrefix = this.prefix.slice(length)
this.prefix = childPrefix
this._compilePrefixMatch()
const staticNode = new StaticNode(parentPrefix)
staticNode.staticChildren[childPrefix.charAt(0)] = this
parentNode.staticChildren[parentPrefix.charAt(0)] = staticNode
return staticNode
}
getNextNode (path, pathIndex, nodeStack, paramsCount) {
let node = this.findStaticMatchingChild(path, pathIndex)
let parametricBrotherNodeIndex = 0
if (node === null) {
if (this.parametricChildren.length === 0) {
return this.wildcardChild
}
node = this.parametricChildren[0]
parametricBrotherNodeIndex = 1
}
if (this.wildcardChild !== null) {
nodeStack.push({
paramsCount,
brotherPathIndex: pathIndex,
brotherNode: this.wildcardChild
})
}
for (let i = this.parametricChildren.length - 1; i >= parametricBrotherNodeIndex; i--) {
nodeStack.push({
paramsCount,
brotherPathIndex: pathIndex,
brotherNode: this.parametricChildren[i]
})
}
return node
}
_compilePrefixMatch () {
if (this.prefix.length === 1) {
this.matchPrefix = () => true
return
}
const lines = []
for (let i = 1; i < this.prefix.length; i++) {
const charCode = this.prefix.charCodeAt(i)
lines.push(`path.charCodeAt(i + ${i}) === ${charCode}`)
}
this.matchPrefix = new Function('path', 'i', `return ${lines.join(' && ')}`) // eslint-disable-line
}
}
class ParametricNode extends ParentNode {
constructor (regex, staticSuffix, nodePath) {
super()
this.isRegex = !!regex
this.regex = regex || null
this.staticSuffix = staticSuffix || null
this.kind = NODE_TYPES.PARAMETRIC
this.nodePaths = new Set([nodePath])
}
getNextNode (path, pathIndex) {
return this.findStaticMatchingChild(path, pathIndex)
}
}
class WildcardNode extends Node {
constructor () {
super()
this.kind = NODE_TYPES.WILDCARD
}
getNextNode () {
return null
}
}
module.exports = { StaticNode, ParametricNode, WildcardNode, NODE_TYPES }

8
node_modules/find-my-way/lib/null-object.js generated vendored Normal file
View File

@@ -0,0 +1,8 @@
'use strict'
const NullObject = function () {}
NullObject.prototype = Object.create(null)
module.exports = {
NullObject
}

168
node_modules/find-my-way/lib/pretty-print.js generated vendored Normal file
View File

@@ -0,0 +1,168 @@
'use strict'
const deepEqual = require('fast-deep-equal')
const httpMethodStrategy = require('./strategies/http-method')
const treeDataSymbol = Symbol('treeData')
function printObjectTree (obj, parentPrefix = '') {
let tree = ''
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
const value = obj[key]
const isLast = i === keys.length - 1
const nodePrefix = isLast ? '└── ' : '├── '
const childPrefix = isLast ? ' ' : '│ '
const nodeData = value[treeDataSymbol] || ''
const prefixedNodeData = nodeData.replaceAll('\n', '\n' + parentPrefix + childPrefix)
tree += parentPrefix + nodePrefix + key + prefixedNodeData + '\n'
tree += printObjectTree(value, parentPrefix + childPrefix)
}
return tree
}
function parseFunctionName (fn) {
let fName = fn.name || ''
fName = fName.replace('bound', '').trim()
fName = (fName || 'anonymous') + '()'
return fName
}
function parseMeta (meta) {
if (Array.isArray(meta)) return meta.map(m => parseMeta(m))
if (typeof meta === 'symbol') return meta.toString()
if (typeof meta === 'function') return parseFunctionName(meta)
return meta
}
function getRouteMetaData (route, options) {
if (!options.includeMeta) return {}
const metaDataObject = options.buildPrettyMeta(route)
const filteredMetaData = {}
let includeMetaKeys = options.includeMeta
if (!Array.isArray(includeMetaKeys)) {
includeMetaKeys = Reflect.ownKeys(metaDataObject)
}
for (const metaKey of includeMetaKeys) {
if (!Object.prototype.hasOwnProperty.call(metaDataObject, metaKey)) continue
const serializedKey = metaKey.toString()
const metaValue = metaDataObject[metaKey]
if (metaValue !== undefined && metaValue !== null) {
const serializedValue = JSON.stringify(parseMeta(metaValue))
filteredMetaData[serializedKey] = serializedValue
}
}
return filteredMetaData
}
function serializeMetaData (metaData) {
let serializedMetaData = ''
for (const [key, value] of Object.entries(metaData)) {
serializedMetaData += `\n• (${key}) ${value}`
}
return serializedMetaData
}
// get original merged tree node route
function normalizeRoute (route) {
const constraints = { ...route.opts.constraints }
const method = constraints[httpMethodStrategy.name]
delete constraints[httpMethodStrategy.name]
return { ...route, method, opts: { constraints } }
}
function serializeRoute (route) {
let serializedRoute = ` (${route.method})`
const constraints = route.opts.constraints || {}
if (Object.keys(constraints).length !== 0) {
serializedRoute += ' ' + JSON.stringify(constraints)
}
serializedRoute += serializeMetaData(route.metaData)
return serializedRoute
}
function mergeSimilarRoutes (routes) {
return routes.reduce((mergedRoutes, route) => {
for (const nodeRoute of mergedRoutes) {
if (
deepEqual(route.opts.constraints, nodeRoute.opts.constraints) &&
deepEqual(route.metaData, nodeRoute.metaData)
) {
nodeRoute.method += ', ' + route.method
return mergedRoutes
}
}
mergedRoutes.push(route)
return mergedRoutes
}, [])
}
function serializeNode (node, prefix, options) {
let routes = node.routes
if (options.method === undefined) {
routes = routes.map(normalizeRoute)
}
routes = routes.map(route => {
route.metaData = getRouteMetaData(route, options)
return route
})
if (options.method === undefined) {
routes = mergeSimilarRoutes(routes)
}
return routes.map(serializeRoute).join(`\n${prefix}`)
}
function buildObjectTree (node, tree, prefix, options) {
if (node.isLeafNode || options.commonPrefix !== false) {
prefix = prefix || '(empty root node)'
tree = tree[prefix] = {}
if (node.isLeafNode) {
tree[treeDataSymbol] = serializeNode(node, prefix, options)
}
prefix = ''
}
if (node.staticChildren) {
for (const child of Object.values(node.staticChildren)) {
buildObjectTree(child, tree, prefix + child.prefix, options)
}
}
if (node.parametricChildren) {
for (const child of Object.values(node.parametricChildren)) {
const childPrefix = Array.from(child.nodePaths).join('|')
buildObjectTree(child, tree, prefix + childPrefix, options)
}
}
if (node.wildcardChild) {
buildObjectTree(node.wildcardChild, tree, '*', options)
}
}
function prettyPrintTree (root, options) {
const objectTree = {}
buildObjectTree(root, objectTree, root.prefix, options)
return printObjectTree(objectTree)
}
module.exports = { prettyPrintTree }

36
node_modules/find-my-way/lib/strategies/accept-host.js generated vendored Normal file
View File

@@ -0,0 +1,36 @@
'use strict'
const assert = require('node:assert')
function HostStorage () {
const hosts = new Map()
const regexHosts = []
return {
get: (host) => {
const exact = hosts.get(host)
if (exact) {
return exact
}
for (const regex of regexHosts) {
if (regex.host.test(host)) {
return regex.value
}
}
},
set: (host, value) => {
if (host instanceof RegExp) {
regexHosts.push({ host, value })
} else {
hosts.set(host, value)
}
}
}
}
module.exports = {
name: 'host',
mustMatchWhenDerived: false,
storage: HostStorage,
validate (value) {
assert(typeof value === 'string' || Object.prototype.toString.call(value) === '[object RegExp]', 'Host should be a string or a RegExp')
}
}

View File

@@ -0,0 +1,64 @@
'use strict'
const assert = require('node:assert')
function SemVerStore () {
if (!(this instanceof SemVerStore)) {
return new SemVerStore()
}
this.store = new Map()
this.maxMajor = 0
this.maxMinors = {}
this.maxPatches = {}
}
SemVerStore.prototype.set = function (version, store) {
if (typeof version !== 'string') {
throw new TypeError('Version should be a string')
}
let [major, minor, patch] = version.split('.', 3)
if (isNaN(major)) {
throw new TypeError('Major version must be a numeric value')
}
major = Number(major)
minor = Number(minor) || 0
patch = Number(patch) || 0
if (major >= this.maxMajor) {
this.maxMajor = major
this.store.set('x', store)
this.store.set('*', store)
this.store.set('x.x', store)
this.store.set('x.x.x', store)
}
if (minor >= (this.maxMinors[major] || 0)) {
this.maxMinors[major] = minor
this.store.set(`${major}.x`, store)
this.store.set(`${major}.x.x`, store)
}
if (patch >= (this.maxPatches[`${major}.${minor}`] || 0)) {
this.maxPatches[`${major}.${minor}`] = patch
this.store.set(`${major}.${minor}.x`, store)
}
this.store.set(`${major}.${minor}.${patch}`, store)
return this
}
SemVerStore.prototype.get = function (version) {
return this.store.get(version)
}
module.exports = {
name: 'version',
mustMatchWhenDerived: true,
storage: SemVerStore,
validate (value) {
assert(typeof value === 'string', 'Version should be a string')
}
}

15
node_modules/find-my-way/lib/strategies/http-method.js generated vendored Normal file
View File

@@ -0,0 +1,15 @@
'use strict'
module.exports = {
name: '__fmw_internal_strategy_merged_tree_http_method__',
storage: function () {
const handlers = new Map()
return {
get: (type) => { return handlers.get(type) || null },
set: (type, store) => { handlers.set(type, store) }
}
},
/* c8 ignore next 1 */
deriveConstraint: (req) => req.method,
mustMatchWhenDerived: true
}

96
node_modules/find-my-way/lib/url-sanitizer.js generated vendored Normal file
View File

@@ -0,0 +1,96 @@
'use strict'
// It must spot all the chars where decodeURIComponent(x) !== decodeURI(x)
// The chars are: # $ & + , / : ; = ? @
function decodeComponentChar (highCharCode, lowCharCode) {
if (highCharCode === 50) {
if (lowCharCode === 53) return '%'
if (lowCharCode === 51) return '#'
if (lowCharCode === 52) return '$'
if (lowCharCode === 54) return '&'
if (lowCharCode === 66) return '+'
if (lowCharCode === 98) return '+'
if (lowCharCode === 67) return ','
if (lowCharCode === 99) return ','
if (lowCharCode === 70) return '/'
if (lowCharCode === 102) return '/'
return null
}
if (highCharCode === 51) {
if (lowCharCode === 65) return ':'
if (lowCharCode === 97) return ':'
if (lowCharCode === 66) return ';'
if (lowCharCode === 98) return ';'
if (lowCharCode === 68) return '='
if (lowCharCode === 100) return '='
if (lowCharCode === 70) return '?'
if (lowCharCode === 102) return '?'
return null
}
if (highCharCode === 52 && lowCharCode === 48) {
return '@'
}
return null
}
function safeDecodeURI (path, useSemicolonDelimiter) {
let shouldDecode = false
let shouldDecodeParam = false
let querystring = ''
for (let i = 1; i < path.length; i++) {
const charCode = path.charCodeAt(i)
if (charCode === 37) {
const highCharCode = path.charCodeAt(i + 1)
const lowCharCode = path.charCodeAt(i + 2)
if (decodeComponentChar(highCharCode, lowCharCode) === null) {
shouldDecode = true
} else {
shouldDecodeParam = true
// %25 - encoded % char. We need to encode one more time to prevent double decoding
if (highCharCode === 50 && lowCharCode === 53) {
shouldDecode = true
path = path.slice(0, i + 1) + '25' + path.slice(i + 1)
i += 2
}
i += 2
}
// Some systems do not follow RFC and separate the path and query
// string with a `;` character (code 59), e.g. `/foo;jsessionid=123456`.
// Thus, we need to split on `;` as well as `?` and `#` if the useSemicolonDelimiter option is enabled.
} else if (charCode === 63 || charCode === 35 || (charCode === 59 && useSemicolonDelimiter)) {
querystring = path.slice(i + 1)
path = path.slice(0, i)
break
}
}
const decodedPath = shouldDecode ? decodeURI(path) : path
return { path: decodedPath, querystring, shouldDecodeParam }
}
function safeDecodeURIComponent (uriComponent) {
const startIndex = uriComponent.indexOf('%')
if (startIndex === -1) return uriComponent
let decoded = ''
let lastIndex = startIndex
for (let i = startIndex; i < uriComponent.length; i++) {
if (uriComponent.charCodeAt(i) === 37) {
const highCharCode = uriComponent.charCodeAt(i + 1)
const lowCharCode = uriComponent.charCodeAt(i + 2)
const decodedChar = decodeComponentChar(highCharCode, lowCharCode)
decoded += uriComponent.slice(lastIndex, i) + decodedChar
lastIndex = i + 3
}
}
return uriComponent.slice(0, startIndex) + decoded + uriComponent.slice(lastIndex)
}
module.exports = { safeDecodeURI, safeDecodeURIComponent }

57
node_modules/find-my-way/package.json generated vendored Normal file
View File

@@ -0,0 +1,57 @@
{
"name": "find-my-way",
"version": "9.3.0",
"description": "Crazy fast http radix based router",
"main": "index.js",
"type": "commonjs",
"types": "index.d.ts",
"scripts": {
"bench": "node ./benchmark/bench.js",
"bench:cmp": "node ./benchmark/compare-branches.js",
"bench:cmp:ci": "node ./benchmark/compare-branches.js --ci",
"test:lint": "standard",
"test:typescript": "tsd",
"test": "standard && borp && npm run test:typescript"
},
"repository": {
"type": "git",
"url": "git+https://github.com/delvedor/find-my-way.git"
},
"keywords": [
"http",
"router",
"radix",
"fast",
"speed"
],
"engines": {
"node": ">=20"
},
"author": "Tomas Della Vedova - @delvedor (http://delved.org)",
"license": "MIT",
"bugs": {
"url": "https://github.com/delvedor/find-my-way/issues"
},
"homepage": "https://github.com/delvedor/find-my-way#readme",
"devDependencies": {
"@types/node": "^22.10.2",
"benchmark": "^2.1.4",
"borp": "^0.19.0",
"chalk": "^5.4.1",
"inquirer": "^12.3.0",
"pre-commit": "^1.2.2",
"proxyquire": "^2.1.3",
"rfdc": "^1.3.0",
"simple-git": "^3.7.1",
"standard": "^17.0.0",
"tsd": "^0.31.0"
},
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-querystring": "^1.0.0",
"safe-regex2": "^5.0.0"
},
"tsd": {
"directory": "test/types"
}
}

230
node_modules/find-my-way/test/case-insensitive.test.js generated vendored Normal file
View File

@@ -0,0 +1,230 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('case insensitive static routes of level 1', t => {
t.plan(1)
const findMyWay = FindMyWay({
caseSensitive: false,
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/woo', (req, res, params) => {
t.assert.ok('we should be here')
})
findMyWay.lookup({ method: 'GET', url: '/WOO', headers: {} }, null)
})
test('case insensitive static routes of level 2', t => {
t.plan(1)
const findMyWay = FindMyWay({
caseSensitive: false,
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/foo/woo', (req, res, params) => {
t.assert.ok('we should be here')
})
findMyWay.lookup({ method: 'GET', url: '/FoO/WOO', headers: {} }, null)
})
test('case insensitive static routes of level 3', t => {
t.plan(1)
const findMyWay = FindMyWay({
caseSensitive: false,
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/foo/bar/woo', (req, res, params) => {
t.assert.ok('we should be here')
})
findMyWay.lookup({ method: 'GET', url: '/Foo/bAR/WoO', headers: {} }, null)
})
test('parametric case insensitive', t => {
t.plan(1)
const findMyWay = FindMyWay({
caseSensitive: false,
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/foo/:param', (req, res, params) => {
t.assert.equal(params.param, 'bAR')
})
findMyWay.lookup({ method: 'GET', url: '/Foo/bAR', headers: {} }, null)
})
test('parametric case insensitive with a static part', t => {
t.plan(1)
const findMyWay = FindMyWay({
caseSensitive: false,
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/foo/my-:param', (req, res, params) => {
t.assert.equal(params.param, 'bAR')
})
findMyWay.lookup({ method: 'GET', url: '/Foo/MY-bAR', headers: {} }, null)
})
test('parametric case insensitive with capital letter', t => {
t.plan(1)
const findMyWay = FindMyWay({
caseSensitive: false,
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/foo/:Param', (req, res, params) => {
t.assert.equal(params.Param, 'bAR')
})
findMyWay.lookup({ method: 'GET', url: '/Foo/bAR', headers: {} }, null)
})
test('case insensitive with capital letter in static path with param', t => {
t.plan(1)
const findMyWay = FindMyWay({
caseSensitive: false,
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/Foo/bar/:param', (req, res, params) => {
t.assert.equal(params.param, 'baZ')
})
findMyWay.lookup({ method: 'GET', url: '/foo/bar/baZ', headers: {} }, null)
})
test('case insensitive with multiple paths containing capital letter in static path with param', t => {
/*
* This is a reproduction of the issue documented at
* https://github.com/delvedor/find-my-way/issues/96.
*/
t.plan(2)
const findMyWay = FindMyWay({
caseSensitive: false,
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/Foo/bar/:param', (req, res, params) => {
t.assert.equal(params.param, 'baZ')
})
findMyWay.on('GET', '/Foo/baz/:param', (req, res, params) => {
t.assert.equal(params.param, 'baR')
})
findMyWay.lookup({ method: 'GET', url: '/foo/bar/baZ', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/foo/baz/baR', headers: {} }, null)
})
test('case insensitive with multiple mixed-case params within same slash couple', t => {
t.plan(2)
const findMyWay = FindMyWay({
caseSensitive: false,
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/foo/:param1-:param2', (req, res, params) => {
t.assert.equal(params.param1, 'My')
t.assert.equal(params.param2, 'bAR')
})
findMyWay.lookup({ method: 'GET', url: '/FOO/My-bAR', headers: {} }, null)
})
test('case insensitive with multiple mixed-case params', t => {
t.plan(2)
const findMyWay = FindMyWay({
caseSensitive: false,
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/foo/:param1/:param2', (req, res, params) => {
t.assert.equal(params.param1, 'My')
t.assert.equal(params.param2, 'bAR')
})
findMyWay.lookup({ method: 'GET', url: '/FOO/My/bAR', headers: {} }, null)
})
test('case insensitive with wildcard', t => {
t.plan(1)
const findMyWay = FindMyWay({
caseSensitive: false,
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/foo/*', (req, res, params) => {
t.assert.equal(params['*'], 'baR')
})
findMyWay.lookup({ method: 'GET', url: '/FOO/baR', headers: {} }, null)
})
test('parametric case insensitive with multiple routes', t => {
t.plan(6)
const findMyWay = FindMyWay({
caseSensitive: false,
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('POST', '/foo/:param/Static/:userId/Save', (req, res, params) => {
t.assert.equal(params.param, 'bAR')
t.assert.equal(params.userId, 'one')
})
findMyWay.on('POST', '/foo/:param/Static/:userId/Update', (req, res, params) => {
t.assert.equal(params.param, 'Bar')
t.assert.equal(params.userId, 'two')
})
findMyWay.on('POST', '/foo/:param/Static/:userId/CANCEL', (req, res, params) => {
t.assert.equal(params.param, 'bAR')
t.assert.equal(params.userId, 'THREE')
})
findMyWay.lookup({ method: 'POST', url: '/foo/bAR/static/one/SAVE', headers: {} }, null)
findMyWay.lookup({ method: 'POST', url: '/fOO/Bar/Static/two/update', headers: {} }, null)
findMyWay.lookup({ method: 'POST', url: '/Foo/bAR/STATIC/THREE/cAnCeL', headers: {} }, null)
})

View File

@@ -0,0 +1,130 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
const noop = () => { }
const customVersioning = {
name: 'version',
// storage factory
storage: function () {
let versions = {}
return {
get: (version) => { return versions[version] || null },
set: (version, store) => { versions[version] = store },
del: (version) => { delete versions[version] },
empty: () => { versions = {} }
}
},
deriveConstraint: (req, ctx) => {
return req.headers.accept
}
}
test('A route could support multiple versions (find) / 1', t => {
t.plan(5)
const findMyWay = FindMyWay({ constraints: { version: customVersioning } })
findMyWay.on('GET', '/', { constraints: { version: 'application/vnd.example.api+json;version=2' } }, noop)
findMyWay.on('GET', '/', { constraints: { version: 'application/vnd.example.api+json;version=3' } }, noop)
t.assert.ok(findMyWay.find('GET', '/', { version: 'application/vnd.example.api+json;version=2' }))
t.assert.ok(findMyWay.find('GET', '/', { version: 'application/vnd.example.api+json;version=3' }))
t.assert.ok(!findMyWay.find('GET', '/', { version: 'application/vnd.example.api+json;version=4' }))
t.assert.ok(!findMyWay.find('GET', '/', { version: 'application/vnd.example.api+json;version=5' }))
t.assert.ok(!findMyWay.find('GET', '/', { version: 'application/vnd.example.api+json;version=6' }))
})
test('A route could support multiple versions (find) / 1 (add strategy outside constructor)', t => {
t.plan(5)
const findMyWay = FindMyWay()
findMyWay.addConstraintStrategy(customVersioning)
findMyWay.on('GET', '/', { constraints: { version: 'application/vnd.example.api+json;version=2' } }, noop)
findMyWay.on('GET', '/', { constraints: { version: 'application/vnd.example.api+json;version=3' } }, noop)
t.assert.ok(findMyWay.find('GET', '/', { version: 'application/vnd.example.api+json;version=2' }))
t.assert.ok(findMyWay.find('GET', '/', { version: 'application/vnd.example.api+json;version=3' }))
t.assert.ok(!findMyWay.find('GET', '/', { version: 'application/vnd.example.api+json;version=4' }))
t.assert.ok(!findMyWay.find('GET', '/', { version: 'application/vnd.example.api+json;version=5' }))
t.assert.ok(!findMyWay.find('GET', '/', { version: 'application/vnd.example.api+json;version=6' }))
})
test('Overriding default strategies uses the custom deriveConstraint function', t => {
t.plan(2)
const findMyWay = FindMyWay({ constraints: { version: customVersioning } })
findMyWay.on('GET', '/', { constraints: { version: 'application/vnd.example.api+json;version=2' } }, (req, res, params) => {
t.assert.equal(req.headers.accept, 'application/vnd.example.api+json;version=2')
})
findMyWay.on('GET', '/', { constraints: { version: 'application/vnd.example.api+json;version=3' } }, (req, res, params) => {
t.assert.equal(req.headers.accept, 'application/vnd.example.api+json;version=3')
})
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { accept: 'application/vnd.example.api+json;version=2' }
})
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { accept: 'application/vnd.example.api+json;version=3' }
})
})
test('Overriding default strategies uses the custom deriveConstraint function (add strategy outside constructor)', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.addConstraintStrategy(customVersioning)
findMyWay.on('GET', '/', { constraints: { version: 'application/vnd.example.api+json;version=2' } }, (req, res, params) => {
t.assert.equal(req.headers.accept, 'application/vnd.example.api+json;version=2')
})
findMyWay.on('GET', '/', { constraints: { version: 'application/vnd.example.api+json;version=3' } }, (req, res, params) => {
t.assert.equal(req.headers.accept, 'application/vnd.example.api+json;version=3')
})
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { accept: 'application/vnd.example.api+json;version=2' }
})
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { accept: 'application/vnd.example.api+json;version=3' }
})
})
test('Overriding custom strategies throws as error (add strategy outside constructor)', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.addConstraintStrategy(customVersioning)
t.assert.throws(() => findMyWay.addConstraintStrategy(customVersioning),
new Error('There already exists a custom constraint with the name version.')
)
})
test('Overriding default strategies after defining a route with constraint', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', { constraints: { host: 'fastify.io', version: '1.0.0' } }, () => {})
t.assert.throws(() => findMyWay.addConstraintStrategy(customVersioning),
new Error('There already exists a route with version constraint.')
)
})

View File

@@ -0,0 +1,111 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
const rfdc = require('rfdc')({ proto: true })
const customHeaderConstraint = {
name: 'requestedBy',
storage: function () {
const requestedBys = {}
return {
get: (requestedBy) => { return requestedBys[requestedBy] || null },
set: (requestedBy, store) => { requestedBys[requestedBy] = store }
}
},
deriveConstraint: (req, ctx, done) => {
if (req.headers['user-agent'] === 'wrong') {
done(new Error('wrong user-agent'))
return
}
done(null, req.headers['user-agent'])
}
}
test('should derive multiple async constraints', t => {
t.plan(2)
const customHeaderConstraint2 = rfdc(customHeaderConstraint)
customHeaderConstraint2.name = 'requestedBy2'
const router = FindMyWay({ constraints: { requestedBy: customHeaderConstraint, requestedBy2: customHeaderConstraint2 } })
router.on('GET', '/', { constraints: { requestedBy: 'node', requestedBy2: 'node' } }, () => 'asyncHandler')
router.lookup(
{
method: 'GET',
url: '/',
headers: {
'user-agent': 'node'
}
},
null,
(err, result) => {
t.assert.equal(err, null)
t.assert.equal(result, 'asyncHandler')
}
)
})
test('lookup should return an error from deriveConstraint', t => {
t.plan(2)
const router = FindMyWay({ constraints: { requestedBy: customHeaderConstraint } })
router.on('GET', '/', { constraints: { requestedBy: 'node' } }, () => 'asyncHandler')
router.lookup(
{
method: 'GET',
url: '/',
headers: {
'user-agent': 'wrong'
}
},
null,
(err, result) => {
t.assert.deepStrictEqual(err, new Error('wrong user-agent'))
t.assert.equal(result, undefined)
}
)
})
test('should derive sync and async constraints', t => {
t.plan(4)
const router = FindMyWay({ constraints: { requestedBy: customHeaderConstraint } })
router.on('GET', '/', { constraints: { version: '1.0.0', requestedBy: 'node' } }, () => 'asyncHandlerV1')
router.on('GET', '/', { constraints: { version: '2.0.0', requestedBy: 'node' } }, () => 'asyncHandlerV2')
router.lookup(
{
method: 'GET',
url: '/',
headers: {
'user-agent': 'node',
'accept-version': '1.0.0'
}
},
null,
(err, result) => {
t.assert.equal(err, null)
t.assert.equal(result, 'asyncHandlerV1')
}
)
router.lookup(
{
method: 'GET',
url: '/',
headers: {
'user-agent': 'node',
'accept-version': '2.0.0'
}
},
null,
(err, result) => {
t.assert.equal(err, null)
t.assert.equal(result, 'asyncHandlerV2')
}
)
})

273
node_modules/find-my-way/test/constraint.custom.test.js generated vendored Normal file
View File

@@ -0,0 +1,273 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
const alpha = () => { }
const beta = () => { }
const gamma = () => { }
const delta = () => { }
const customHeaderConstraint = {
name: 'requestedBy',
storage: function () {
let requestedBys = {}
return {
get: (requestedBy) => { return requestedBys[requestedBy] || null },
set: (requestedBy, store) => { requestedBys[requestedBy] = store },
del: (requestedBy) => { delete requestedBys[requestedBy] },
empty: () => { requestedBys = {} }
}
},
deriveConstraint: (req, ctx) => {
return req.headers['user-agent']
}
}
test('A route could support a custom constraint strategy', t => {
t.plan(3)
const findMyWay = FindMyWay({ constraints: { requestedBy: customHeaderConstraint } })
findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl' } }, alpha)
findMyWay.on('GET', '/', { constraints: { requestedBy: 'wget' } }, beta)
t.assert.equal(findMyWay.find('GET', '/', { requestedBy: 'curl' }).handler, alpha)
t.assert.equal(findMyWay.find('GET', '/', { requestedBy: 'wget' }).handler, beta)
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'chrome' }))
})
test('A route could support a custom constraint strategy (add strategy outside constructor)', t => {
t.plan(3)
const findMyWay = FindMyWay()
findMyWay.addConstraintStrategy(customHeaderConstraint)
findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl' } }, alpha)
findMyWay.on('GET', '/', { constraints: { requestedBy: 'wget' } }, beta)
t.assert.equal(findMyWay.find('GET', '/', { requestedBy: 'curl' }).handler, alpha)
t.assert.equal(findMyWay.find('GET', '/', { requestedBy: 'wget' }).handler, beta)
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'chrome' }))
})
test('A route could support a custom constraint strategy while versioned', t => {
t.plan(8)
const findMyWay = FindMyWay({ constraints: { requestedBy: customHeaderConstraint } })
findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl', version: '1.0.0' } }, alpha)
findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl', version: '2.0.0' } }, beta)
findMyWay.on('GET', '/', { constraints: { requestedBy: 'wget', version: '2.0.0' } }, gamma)
findMyWay.on('GET', '/', { constraints: { requestedBy: 'wget', version: '3.0.0' } }, delta)
t.assert.equal(findMyWay.find('GET', '/', { requestedBy: 'curl', version: '1.x' }).handler, alpha)
t.assert.equal(findMyWay.find('GET', '/', { requestedBy: 'curl', version: '2.x' }).handler, beta)
t.assert.equal(findMyWay.find('GET', '/', { requestedBy: 'wget', version: '2.x' }).handler, gamma)
t.assert.equal(findMyWay.find('GET', '/', { requestedBy: 'wget', version: '3.x' }).handler, delta)
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'chrome' }))
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'chrome', version: '1.x' }))
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'curl', version: '3.x' }))
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'wget', version: '1.x' }))
})
test('A route could support a custom constraint strategy while versioned (add strategy outside constructor)', t => {
t.plan(8)
const findMyWay = FindMyWay()
findMyWay.addConstraintStrategy(customHeaderConstraint)
findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl', version: '1.0.0' } }, alpha)
findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl', version: '2.0.0' } }, beta)
findMyWay.on('GET', '/', { constraints: { requestedBy: 'wget', version: '2.0.0' } }, gamma)
findMyWay.on('GET', '/', { constraints: { requestedBy: 'wget', version: '3.0.0' } }, delta)
t.assert.equal(findMyWay.find('GET', '/', { requestedBy: 'curl', version: '1.x' }).handler, alpha)
t.assert.equal(findMyWay.find('GET', '/', { requestedBy: 'curl', version: '2.x' }).handler, beta)
t.assert.equal(findMyWay.find('GET', '/', { requestedBy: 'wget', version: '2.x' }).handler, gamma)
t.assert.equal(findMyWay.find('GET', '/', { requestedBy: 'wget', version: '3.x' }).handler, delta)
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'chrome' }))
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'chrome', version: '1.x' }))
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'curl', version: '3.x' }))
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'wget', version: '1.x' }))
})
test('A route could support a custom constraint strategy while versioned and host constrained', t => {
t.plan(9)
const findMyWay = FindMyWay({ constraints: { requestedBy: customHeaderConstraint } })
findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl', version: '1.0.0', host: 'fastify.io' } }, alpha)
findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl', version: '2.0.0', host: 'fastify.io' } }, beta)
findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl', version: '2.0.0', host: 'example.io' } }, delta)
t.assert.equal(findMyWay.find('GET', '/', { requestedBy: 'curl', version: '1.x', host: 'fastify.io' }).handler, alpha)
t.assert.equal(findMyWay.find('GET', '/', { requestedBy: 'curl', version: '2.x', host: 'fastify.io' }).handler, beta)
t.assert.equal(findMyWay.find('GET', '/', { requestedBy: 'curl', version: '2.x', host: 'example.io' }).handler, delta)
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'chrome' }))
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'chrome', version: '1.x' }))
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'curl', version: '1.x' }))
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'curl', version: '2.x' }))
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'curl', version: '3.x', host: 'fastify.io' }))
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'curl', version: '1.x', host: 'example.io' }))
})
test('A route could support a custom constraint strategy while versioned and host constrained (add strategy outside constructor)', t => {
t.plan(9)
const findMyWay = FindMyWay()
findMyWay.addConstraintStrategy(customHeaderConstraint)
findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl', version: '1.0.0', host: 'fastify.io' } }, alpha)
findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl', version: '2.0.0', host: 'fastify.io' } }, beta)
findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl', version: '2.0.0', host: 'example.io' } }, delta)
t.assert.equal(findMyWay.find('GET', '/', { requestedBy: 'curl', version: '1.x', host: 'fastify.io' }).handler, alpha)
t.assert.equal(findMyWay.find('GET', '/', { requestedBy: 'curl', version: '2.x', host: 'fastify.io' }).handler, beta)
t.assert.equal(findMyWay.find('GET', '/', { requestedBy: 'curl', version: '2.x', host: 'example.io' }).handler, delta)
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'chrome' }))
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'chrome', version: '1.x' }))
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'curl', version: '1.x' }))
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'curl', version: '2.x' }))
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'curl', version: '3.x', host: 'fastify.io' }))
t.assert.ok(!findMyWay.find('GET', '/', { requestedBy: 'curl', version: '1.x', host: 'example.io' }))
})
test('Custom constraint strategies can set mustMatchWhenDerived flag to true which prevents matches to unconstrained routes when a constraint is derived and there are no other routes', t => {
t.plan(1)
const findMyWay = FindMyWay({
constraints: {
requestedBy: {
...customHeaderConstraint,
mustMatchWhenDerived: true
}
},
defaultRoute (req, res) {
t.assert.ok('pass')
}
})
findMyWay.on('GET', '/', {}, () => t.assert.assert.fail())
findMyWay.lookup({ method: 'GET', url: '/', headers: { 'user-agent': 'node' } }, null)
})
test('Custom constraint strategies can set mustMatchWhenDerived flag to true which prevents matches to unconstrained routes when a constraint is derived and there are no other routes (add strategy outside constructor)', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute (req, res) {
t.assert.ok('pass')
}
})
findMyWay.addConstraintStrategy({
...customHeaderConstraint,
mustMatchWhenDerived: true
})
findMyWay.on('GET', '/', {}, () => t.assert.assert.fail())
findMyWay.lookup({ method: 'GET', url: '/', headers: { 'user-agent': 'node' } }, null)
})
test('Custom constraint strategies can set mustMatchWhenDerived flag to true which prevents matches to unconstrained routes when a constraint is derived when there are constrained routes', t => {
t.plan(1)
const findMyWay = FindMyWay({
constraints: {
requestedBy: {
...customHeaderConstraint,
mustMatchWhenDerived: true
}
},
defaultRoute (req, res) {
t.assert.ok('pass')
}
})
findMyWay.on('GET', '/', {}, () => t.assert.assert.fail())
findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl' } }, () => t.assert.assert.fail())
findMyWay.on('GET', '/', { constraints: { requestedBy: 'wget' } }, () => t.assert.assert.fail())
findMyWay.lookup({ method: 'GET', url: '/', headers: { 'user-agent': 'node' } }, null)
})
test('Custom constraint strategies can set mustMatchWhenDerived flag to true which prevents matches to unconstrained routes when a constraint is derived when there are constrained routes (add strategy outside constructor)', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute (req, res) {
t.assert.ok('pass')
}
})
findMyWay.addConstraintStrategy({
...customHeaderConstraint,
mustMatchWhenDerived: true
})
findMyWay.on('GET', '/', {}, () => t.assert.assert.fail())
findMyWay.on('GET', '/', { constraints: { requestedBy: 'curl' } }, () => t.assert.assert.fail())
findMyWay.on('GET', '/', { constraints: { requestedBy: 'wget' } }, () => t.assert.assert.fail())
findMyWay.lookup({ method: 'GET', url: '/', headers: { 'user-agent': 'node' } }, null)
})
test('Custom constraint strategies can set mustMatchWhenDerived flag to false which allows matches to unconstrained routes when a constraint is derived', t => {
t.plan(1)
const findMyWay = FindMyWay({
constraints: {
requestedBy: {
...customHeaderConstraint,
mustMatchWhenDerived: false
}
},
defaultRoute (req, res) {
t.assert.assert.fail()
}
})
findMyWay.on('GET', '/', {}, () => t.assert.ok('pass'))
findMyWay.lookup({ method: 'GET', url: '/', headers: { 'user-agent': 'node' } }, null)
})
test('Custom constraint strategies can set mustMatchWhenDerived flag to false which allows matches to unconstrained routes when a constraint is derived (add strategy outside constructor)', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute (req, res) {
t.assert.ok('pass')
}
})
findMyWay.addConstraintStrategy({
...customHeaderConstraint,
mustMatchWhenDerived: true
})
findMyWay.on('GET', '/', {}, () => t.assert.ok('pass'))
findMyWay.lookup({ method: 'GET', url: '/', headers: { 'user-agent': 'node' } }, null)
})
test('Has constraint strategy method test', t => {
t.plan(2)
const findMyWay = FindMyWay()
t.assert.deepEqual(findMyWay.hasConstraintStrategy(customHeaderConstraint.name), false)
findMyWay.addConstraintStrategy(customHeaderConstraint)
t.assert.deepEqual(findMyWay.hasConstraintStrategy(customHeaderConstraint.name), true)
})

View File

@@ -0,0 +1,289 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
const noop = () => { }
test('A route could support multiple versions (find) / 1', t => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', { constraints: { version: '1.2.3' } }, noop)
findMyWay.on('GET', '/', { constraints: { version: '3.2.0' } }, noop)
t.assert.ok(findMyWay.find('GET', '/', { version: '1.x' }))
t.assert.ok(findMyWay.find('GET', '/', { version: '1.2.3' }))
t.assert.ok(findMyWay.find('GET', '/', { version: '3.x' }))
t.assert.ok(findMyWay.find('GET', '/', { version: '3.2.0' }))
t.assert.ok(!findMyWay.find('GET', '/', { version: '2.x' }))
t.assert.ok(!findMyWay.find('GET', '/', { version: '2.3.4' }))
t.assert.ok(!findMyWay.find('GET', '/', { version: '3.2.1' }))
})
test('A route could support multiple versions (find) / 2', t => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', { constraints: { version: '1.2.3' } }, noop)
findMyWay.on('GET', '/test', { constraints: { version: '3.2.0' } }, noop)
t.assert.ok(findMyWay.find('GET', '/test', { version: '1.x' }))
t.assert.ok(findMyWay.find('GET', '/test', { version: '1.2.3' }))
t.assert.ok(findMyWay.find('GET', '/test', { version: '3.x' }))
t.assert.ok(findMyWay.find('GET', '/test', { version: '3.2.0' }))
t.assert.ok(!findMyWay.find('GET', '/test', { version: '2.x' }))
t.assert.ok(!findMyWay.find('GET', '/test', { version: '2.3.4' }))
t.assert.ok(!findMyWay.find('GET', '/test', { version: '3.2.1' }))
})
test('A route could support multiple versions (find) / 3', t => {
t.plan(10)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test/:id/hello', { constraints: { version: '1.2.3' } }, noop)
findMyWay.on('GET', '/test/:id/hello', { constraints: { version: '3.2.0' } }, noop)
findMyWay.on('GET', '/test/name/hello', { constraints: { version: '4.0.0' } }, noop)
t.assert.ok(findMyWay.find('GET', '/test/1234/hello', { version: '1.x' }))
t.assert.ok(findMyWay.find('GET', '/test/1234/hello', { version: '1.2.3' }))
t.assert.ok(findMyWay.find('GET', '/test/1234/hello', { version: '3.x' }))
t.assert.ok(findMyWay.find('GET', '/test/1234/hello', { version: '3.2.0' }))
t.assert.ok(findMyWay.find('GET', '/test/name/hello', { version: '4.x' }))
t.assert.ok(findMyWay.find('GET', '/test/name/hello', { version: '3.x' }))
t.assert.ok(!findMyWay.find('GET', '/test/1234/hello', { version: '2.x' }))
t.assert.ok(!findMyWay.find('GET', '/test/1234/hello', { version: '2.3.4' }))
t.assert.ok(!findMyWay.find('GET', '/test/1234/hello', { version: '3.2.1' }))
t.assert.ok(!findMyWay.find('GET', '/test/1234/hello', { version: '4.x' }))
})
test('A route could support multiple versions (find) / 4', t => {
t.plan(8)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test/*', { constraints: { version: '1.2.3' } }, noop)
findMyWay.on('GET', '/test/hello', { constraints: { version: '3.2.0' } }, noop)
t.assert.ok(findMyWay.find('GET', '/test/1234/hello', { version: '1.x' }))
t.assert.ok(findMyWay.find('GET', '/test/1234/hello', { version: '1.2.3' }))
t.assert.ok(findMyWay.find('GET', '/test/hello', { version: '3.x' }))
t.assert.ok(findMyWay.find('GET', '/test/hello', { version: '3.2.0' }))
t.assert.ok(!findMyWay.find('GET', '/test/1234/hello', { version: '3.2.0' }))
t.assert.ok(!findMyWay.find('GET', '/test/1234/hello', { version: '3.x' }))
t.assert.ok(!findMyWay.find('GET', '/test/1234/hello', { version: '2.x' }))
t.assert.ok(!findMyWay.find('GET', '/test/hello', { version: '2.x' }))
})
test('A route could support multiple versions (find) / 5', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', { constraints: { version: '1.2.3' } }, () => false)
findMyWay.on('GET', '/', { constraints: { version: '3.2.0' } }, () => true)
t.assert.ok(findMyWay.find('GET', '/', { version: '*' }).handler())
})
test('Find with a version but without versioned routes', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', noop)
t.assert.ok(!findMyWay.find('GET', '/', { version: '1.x' }))
})
test('A route could support multiple versions (lookup)', t => {
t.plan(7)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
const versions = ['2.x', '2.3.4', '3.2.1']
t.assert.ok(versions.indexOf(req.headers['accept-version']) > -1)
}
})
findMyWay.on('GET', '/', { constraints: { version: '1.2.3' } }, (req, res) => {
const versions = ['1.x', '1.2.3']
t.assert.ok(versions.indexOf(req.headers['accept-version']) > -1)
})
findMyWay.on('GET', '/', { constraints: { version: '3.2.0' } }, (req, res) => {
const versions = ['3.x', '3.2.0']
t.assert.ok(versions.indexOf(req.headers['accept-version']) > -1)
})
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { 'accept-version': '1.x' }
}, null)
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { 'accept-version': '1.2.3' }
}, null)
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { 'accept-version': '3.x' }
}, null)
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { 'accept-version': '3.2.0' }
}, null)
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { 'accept-version': '2.x' }
}, null)
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { 'accept-version': '2.3.4' }
}, null)
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { 'accept-version': '3.2.1' }
}, null)
})
test('It should always choose the highest version of a route', t => {
t.plan(3)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', { constraints: { version: '2.3.0' } }, (req, res) => {
t.assert.fail('We should not be here')
})
findMyWay.on('GET', '/', { constraints: { version: '2.4.0' } }, (req, res) => {
t.assert.ok('Yeah!')
})
findMyWay.on('GET', '/', { constraints: { version: '3.3.0' } }, (req, res) => {
t.assert.ok('Yeah!')
})
findMyWay.on('GET', '/', { constraints: { version: '3.2.0' } }, (req, res) => {
t.assert.fail('We should not be here')
})
findMyWay.on('GET', '/', { constraints: { version: '3.2.2' } }, (req, res) => {
t.assert.fail('We should not be here')
})
findMyWay.on('GET', '/', { constraints: { version: '4.4.0' } }, (req, res) => {
t.assert.fail('We should not be here')
})
findMyWay.on('GET', '/', { constraints: { version: '4.3.2' } }, (req, res) => {
t.assert.ok('Yeah!')
})
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { 'accept-version': '2.x' }
}, null)
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { 'accept-version': '3.x' }
}, null)
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { 'accept-version': '4.3.x' }
}, null)
})
test('Declare the same route with and without version', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', noop)
findMyWay.on('GET', '/', { constraints: { version: '1.2.0' } }, noop)
t.assert.ok(findMyWay.find('GET', '/', { version: '1.x' }))
t.assert.ok(findMyWay.find('GET', '/', {}))
})
test('It should throw if you declare multiple times the same route', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', { constraints: { version: '1.2.3' } }, noop)
try {
findMyWay.on('GET', '/', { constraints: { version: '1.2.3' } }, noop)
t.assert.fail('It should throw')
} catch (err) {
t.assert.equal(err.message, 'Method \'GET\' already declared for route \'/\' with constraints \'{"version":"1.2.3"}\'')
}
})
test('Versioning won\'t work if there are no versioned routes', t => {
t.plan(2)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('We should not be here')
}
})
findMyWay.on('GET', '/', (req, res) => {
t.assert.ok('Yeah!')
})
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { 'accept-version': '2.x' }
}, null)
findMyWay.lookup({
method: 'GET',
url: '/'
}, null)
})
test('Unversioned routes aren\'t triggered when unknown versions are requested', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.ok('We should be here')
}
})
findMyWay.on('GET', '/', (req, res) => {
t.assert.fail('unversioned route shouldnt be hit!')
})
findMyWay.on('GET', '/', { constraints: { version: '1.0.0' } }, (req, res) => {
t.assert.fail('versioned route shouldnt be hit for wrong version!')
})
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { 'accept-version': '2.x' }
}, null)
})

104
node_modules/find-my-way/test/constraint.host.test.js generated vendored Normal file
View File

@@ -0,0 +1,104 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
const alpha = () => { }
const beta = () => { }
const gamma = () => { }
test('A route supports multiple host constraints', t => {
t.plan(4)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', {}, alpha)
findMyWay.on('GET', '/', { constraints: { host: 'fastify.io' } }, beta)
findMyWay.on('GET', '/', { constraints: { host: 'example.com' } }, gamma)
t.assert.equal(findMyWay.find('GET', '/', {}).handler, alpha)
t.assert.equal(findMyWay.find('GET', '/', { host: 'something-else.io' }).handler, alpha)
t.assert.equal(findMyWay.find('GET', '/', { host: 'fastify.io' }).handler, beta)
t.assert.equal(findMyWay.find('GET', '/', { host: 'example.com' }).handler, gamma)
})
test('A route supports wildcard host constraints', t => {
t.plan(4)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', { constraints: { host: 'fastify.io' } }, beta)
findMyWay.on('GET', '/', { constraints: { host: /.*\.fastify\.io/ } }, gamma)
t.assert.equal(findMyWay.find('GET', '/', { host: 'fastify.io' }).handler, beta)
t.assert.equal(findMyWay.find('GET', '/', { host: 'foo.fastify.io' }).handler, gamma)
t.assert.equal(findMyWay.find('GET', '/', { host: 'bar.fastify.io' }).handler, gamma)
t.assert.ok(!findMyWay.find('GET', '/', { host: 'example.com' }))
})
test('A route supports multiple host constraints (lookup)', t => {
t.plan(4)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', {}, (req, res) => {})
findMyWay.on('GET', '/', { constraints: { host: 'fastify.io' } }, (req, res) => {
t.assert.equal(req.headers.host, 'fastify.io')
})
findMyWay.on('GET', '/', { constraints: { host: 'example.com' } }, (req, res) => {
t.assert.equal(req.headers.host, 'example.com')
})
findMyWay.on('GET', '/', { constraints: { host: /.+\.fancy\.ca/ } }, (req, res) => {
t.assert.ok(req.headers.host.endsWith('.fancy.ca'))
})
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { host: 'fastify.io' }
})
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { host: 'example.com' }
})
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { host: 'foo.fancy.ca' }
})
findMyWay.lookup({
method: 'GET',
url: '/',
headers: { host: 'bar.fancy.ca' }
})
})
test('A route supports up to 31 host constraints', (t) => {
t.plan(1)
const findMyWay = FindMyWay()
for (let i = 0; i < 31; i++) {
const host = `h${i.toString().padStart(2, '0')}`
findMyWay.on('GET', '/', { constraints: { host } }, alpha)
}
t.assert.equal(findMyWay.find('GET', '/', { host: 'h01' }).handler, alpha)
})
test('A route throws when constraint limit exceeded', (t) => {
t.plan(1)
const findMyWay = FindMyWay()
for (let i = 0; i < 31; i++) {
const host = `h${i.toString().padStart(2, '0')}`
findMyWay.on('GET', '/', { constraints: { host } }, alpha)
}
t.assert.throws(
() => findMyWay.on('GET', '/', { constraints: { host: 'h31' } }, beta),
new Error('find-my-way supports a maximum of 31 route handlers per node when there are constraints, limit reached')
)
})

108
node_modules/find-my-way/test/constraints.test.js generated vendored Normal file
View File

@@ -0,0 +1,108 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
const alpha = () => { }
const beta = () => { }
const gamma = () => { }
test('A route could support multiple host constraints while versioned', t => {
t.plan(6)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', { constraints: { host: 'fastify.io', version: '1.1.0' } }, beta)
findMyWay.on('GET', '/', { constraints: { host: 'fastify.io', version: '2.1.0' } }, gamma)
t.assert.equal(findMyWay.find('GET', '/', { host: 'fastify.io', version: '1.x' }).handler, beta)
t.assert.equal(findMyWay.find('GET', '/', { host: 'fastify.io', version: '1.1.x' }).handler, beta)
t.assert.equal(findMyWay.find('GET', '/', { host: 'fastify.io', version: '2.x' }).handler, gamma)
t.assert.equal(findMyWay.find('GET', '/', { host: 'fastify.io', version: '2.1.x' }).handler, gamma)
t.assert.ok(!findMyWay.find('GET', '/', { host: 'fastify.io', version: '3.x' }))
t.assert.ok(!findMyWay.find('GET', '/', { host: 'something-else.io', version: '1.x' }))
})
test('Constrained routes are matched before unconstrainted routes when the constrained route is added last', t => {
t.plan(3)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', {}, alpha)
findMyWay.on('GET', '/', { constraints: { host: 'fastify.io' } }, beta)
t.assert.equal(findMyWay.find('GET', '/', {}).handler, alpha)
t.assert.equal(findMyWay.find('GET', '/', { host: 'fastify.io' }).handler, beta)
t.assert.equal(findMyWay.find('GET', '/', { host: 'example.com' }).handler, alpha)
})
test('Constrained routes are matched before unconstrainted routes when the constrained route is added first', t => {
t.plan(3)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', { constraints: { host: 'fastify.io' } }, beta)
findMyWay.on('GET', '/', {}, alpha)
t.assert.equal(findMyWay.find('GET', '/', {}).handler, alpha)
t.assert.equal(findMyWay.find('GET', '/', { host: 'fastify.io' }).handler, beta)
t.assert.equal(findMyWay.find('GET', '/', { host: 'example.com' }).handler, alpha)
})
test('Routes with multiple constraints are matched before routes with one constraint when the doubly-constrained route is added last', t => {
t.plan(3)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', { constraints: { host: 'fastify.io' } }, alpha)
findMyWay.on('GET', '/', { constraints: { host: 'fastify.io', version: '1.0.0' } }, beta)
t.assert.equal(findMyWay.find('GET', '/', { host: 'fastify.io' }).handler, alpha)
t.assert.equal(findMyWay.find('GET', '/', { host: 'fastify.io', version: '1.0.0' }).handler, beta)
t.assert.equal(findMyWay.find('GET', '/', { host: 'fastify.io', version: '2.0.0' }), null)
})
test('Routes with multiple constraints are matched before routes with one constraint when the doubly-constrained route is added first', t => {
t.plan(3)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', { constraints: { host: 'fastify.io', version: '1.0.0' } }, beta)
findMyWay.on('GET', '/', { constraints: { host: 'fastify.io' } }, alpha)
t.assert.equal(findMyWay.find('GET', '/', { host: 'fastify.io' }).handler, alpha)
t.assert.equal(findMyWay.find('GET', '/', { host: 'fastify.io', version: '1.0.0' }).handler, beta)
t.assert.equal(findMyWay.find('GET', '/', { host: 'fastify.io', version: '2.0.0' }), null)
})
test('Routes with multiple constraints are matched before routes with one constraint before unconstrained routes', t => {
t.plan(3)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', { constraints: { host: 'fastify.io', version: '1.0.0' } }, beta)
findMyWay.on('GET', '/', { constraints: { host: 'fastify.io' } }, alpha)
findMyWay.on('GET', '/', { constraints: {} }, gamma)
t.assert.equal(findMyWay.find('GET', '/', { host: 'fastify.io', version: '1.0.0' }).handler, beta)
t.assert.equal(findMyWay.find('GET', '/', { host: 'fastify.io', version: '2.0.0' }), null)
t.assert.equal(findMyWay.find('GET', '/', { host: 'example.io' }).handler, gamma)
})
test('Has constraint strategy method test', t => {
t.plan(6)
const findMyWay = FindMyWay()
t.assert.deepEqual(findMyWay.hasConstraintStrategy('version'), false)
t.assert.deepEqual(findMyWay.hasConstraintStrategy('host'), false)
findMyWay.on('GET', '/', { constraints: { host: 'fastify.io' } }, () => {})
t.assert.deepEqual(findMyWay.hasConstraintStrategy('version'), false)
t.assert.deepEqual(findMyWay.hasConstraintStrategy('host'), true)
findMyWay.on('GET', '/', { constraints: { host: 'fastify.io', version: '1.0.0' } }, () => {})
t.assert.deepEqual(findMyWay.hasConstraintStrategy('version'), true)
t.assert.deepEqual(findMyWay.hasConstraintStrategy('host'), true)
})

View File

@@ -0,0 +1,46 @@
'use strict'
const { test } = require('node:test')
const querystring = require('fast-querystring')
const FindMyWay = require('../')
test('Custom querystring parser', t => {
t.plan(2)
const findMyWay = FindMyWay({
querystringParser: function (str) {
t.assert.equal(str, 'foo=bar&baz=faz')
return querystring.parse(str)
}
})
findMyWay.on('GET', '/', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/?foo=bar&baz=faz').searchParams, { foo: 'bar', baz: 'faz' })
})
test('Custom querystring parser should be called also if there is nothing to parse', t => {
t.plan(2)
const findMyWay = FindMyWay({
querystringParser: function (str) {
t.assert.equal(str, '')
return querystring.parse(str)
}
})
findMyWay.on('GET', '/', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/').searchParams, {})
})
test('Querystring without value', t => {
t.plan(2)
const findMyWay = FindMyWay({
querystringParser: function (str) {
t.assert.equal(str, 'foo')
return querystring.parse(str)
}
})
findMyWay.on('GET', '/', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/?foo').searchParams, { foo: '' })
})

484
node_modules/find-my-way/test/errors.test.js generated vendored Normal file
View File

@@ -0,0 +1,484 @@
'use strict'
const { test, describe } = require('node:test')
const FindMyWay = require('../')
test('Method should be a string', t => {
t.plan(1)
const findMyWay = FindMyWay()
try {
findMyWay.on(0, '/test', () => {})
t.assert.fail('method shoukd be a string')
} catch (e) {
t.assert.equal(e.message, 'Method should be a string')
}
})
test('Method should be a string [ignoreTrailingSlash=true]', t => {
t.plan(1)
const findMyWay = FindMyWay({ ignoreTrailingSlash: true })
try {
findMyWay.on(0, '/test', () => {})
t.assert.fail('method shoukd be a string')
} catch (e) {
t.assert.equal(e.message, 'Method should be a string')
}
})
test('Method should be a string [ignoreDuplicateSlashes=true]', t => {
t.plan(1)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
try {
findMyWay.on(0, '/test', () => {})
t.assert.fail('method shoukd be a string')
} catch (e) {
t.assert.equal(e.message, 'Method should be a string')
}
})
test('Method should be a string (array)', t => {
t.plan(1)
const findMyWay = FindMyWay()
try {
findMyWay.on(['GET', 0], '/test', () => {})
t.assert.fail('method shoukd be a string')
} catch (e) {
t.assert.equal(e.message, 'Method should be a string')
}
})
test('Method should be a string (array) [ignoreTrailingSlash=true]', t => {
t.plan(1)
const findMyWay = FindMyWay({ ignoreTrailingSlash: true })
try {
findMyWay.on(['GET', 0], '/test', () => {})
t.assert.fail('method shoukd be a string')
} catch (e) {
t.assert.equal(e.message, 'Method should be a string')
}
})
test('Method should be a string (array) [ignoreDuplicateSlashes=true]', t => {
t.plan(1)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
try {
findMyWay.on(['GET', 0], '/test', () => {})
t.assert.fail('method shoukd be a string')
} catch (e) {
t.assert.equal(e.message, 'Method should be a string')
}
})
test('Path should be a string', t => {
t.plan(1)
const findMyWay = FindMyWay()
try {
findMyWay.on('GET', 0, () => {})
t.assert.fail('path should be a string')
} catch (e) {
t.assert.equal(e.message, 'Path should be a string')
}
})
test('Path should be a string [ignoreTrailingSlash=true]', t => {
t.plan(1)
const findMyWay = FindMyWay({ ignoreTrailingSlash: true })
try {
findMyWay.on('GET', 0, () => {})
t.assert.fail('path should be a string')
} catch (e) {
t.assert.equal(e.message, 'Path should be a string')
}
})
test('Path should be a string [ignoreDuplicateSlashes=true]', t => {
t.plan(1)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
try {
findMyWay.on('GET', 0, () => {})
t.assert.fail('path should be a string')
} catch (e) {
t.assert.equal(e.message, 'Path should be a string')
}
})
test('The path could not be empty', t => {
t.plan(1)
const findMyWay = FindMyWay()
try {
findMyWay.on('GET', '', () => {})
t.assert.fail('The path could not be empty')
} catch (e) {
t.assert.equal(e.message, 'The path could not be empty')
}
})
test('The path could not be empty [ignoreTrailingSlash=true]', t => {
t.plan(1)
const findMyWay = FindMyWay({ ignoreTrailingSlash: true })
try {
findMyWay.on('GET', '', () => {})
t.assert.fail('The path could not be empty')
} catch (e) {
t.assert.equal(e.message, 'The path could not be empty')
}
})
test('The path could not be empty [ignoreDuplicateSlashes=true]', t => {
t.plan(1)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
try {
findMyWay.on('GET', '', () => {})
t.assert.fail('The path could not be empty')
} catch (e) {
t.assert.equal(e.message, 'The path could not be empty')
}
})
test('The first character of a path should be `/` or `*`', t => {
t.plan(1)
const findMyWay = FindMyWay()
try {
findMyWay.on('GET', 'a', () => {})
t.assert.fail('The first character of a path should be `/` or `*`')
} catch (e) {
t.assert.equal(e.message, 'The first character of a path should be `/` or `*`')
}
})
test('The first character of a path should be `/` or `*` [ignoreTrailingSlash=true]', t => {
t.plan(1)
const findMyWay = FindMyWay({ ignoreTrailingSlash: true })
try {
findMyWay.on('GET', 'a', () => {})
t.assert.fail('The first character of a path should be `/` or `*`')
} catch (e) {
t.assert.equal(e.message, 'The first character of a path should be `/` or `*`')
}
})
test('The first character of a path should be `/` or `*` [ignoreDuplicateSlashes=true]', t => {
t.plan(1)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
try {
findMyWay.on('GET', 'a', () => {})
t.assert.fail('The first character of a path should be `/` or `*`')
} catch (e) {
t.assert.equal(e.message, 'The first character of a path should be `/` or `*`')
}
})
test('Handler should be a function', t => {
t.plan(1)
const findMyWay = FindMyWay()
try {
findMyWay.on('GET', '/test', 0)
t.assert.fail('handler should be a function')
} catch (e) {
t.assert.equal(e.message, 'Handler should be a function')
}
})
test('Method is not an http method.', t => {
t.plan(1)
const findMyWay = FindMyWay()
try {
findMyWay.on('GETT', '/test', () => {})
t.assert.fail('method is not a valid http method')
} catch (e) {
t.assert.equal(e.message, 'Method \'GETT\' is not an http method.')
}
})
test('Method is not an http method. (array)', t => {
t.plan(1)
const findMyWay = FindMyWay()
try {
findMyWay.on(['POST', 'GETT'], '/test', () => {})
t.assert.fail('method is not a valid http method')
} catch (e) {
t.assert.equal(e.message, 'Method \'GETT\' is not an http method.')
}
})
test('The default route must be a function', t => {
t.plan(1)
try {
FindMyWay({
defaultRoute: '/404'
})
t.assert.fail('default route must be a function')
} catch (e) {
t.assert.equal(e.message, 'The default route must be a function')
}
})
test('Method already declared', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
try {
findMyWay.on('GET', '/test', () => {})
t.assert.fail('method already declared')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test\' with constraints \'{}\'')
}
})
test('Method already declared if * is used', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/*', () => {})
try {
findMyWay.on('GET', '*', () => {})
t.assert.fail('should throw error')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/*\' with constraints \'{}\'')
}
})
test('Method already declared if /* is used', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '*', () => {})
try {
findMyWay.on('GET', '/*', () => {})
t.assert.fail('should throw error')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/*\' with constraints \'{}\'')
}
})
describe('Method already declared [ignoreTrailingSlash=true]', t => {
test('without trailing slash', t => {
t.plan(2)
const findMyWay = FindMyWay({ ignoreTrailingSlash: true })
findMyWay.on('GET', '/test', () => {})
try {
findMyWay.on('GET', '/test', () => {})
t.assert.fail('method already declared')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test\' with constraints \'{}\'')
}
try {
findMyWay.on('GET', '/test/', () => {})
t.assert.fail('method already declared')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test\' with constraints \'{}\'')
}
})
test('with trailing slash', t => {
t.plan(2)
const findMyWay = FindMyWay({ ignoreTrailingSlash: true })
findMyWay.on('GET', '/test/', () => {})
try {
findMyWay.on('GET', '/test', () => {})
t.assert.fail('method already declared')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test\' with constraints \'{}\'')
}
try {
findMyWay.on('GET', '/test/', () => {})
t.assert.fail('method already declared')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test\' with constraints \'{}\'')
}
})
})
describe('Method already declared [ignoreDuplicateSlashes=true]', t => {
test('without duplicate slashes', t => {
t.plan(2)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
findMyWay.on('GET', '/test', () => {})
try {
findMyWay.on('GET', '/test', () => {})
t.assert.fail('method already declared')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test\' with constraints \'{}\'')
}
try {
findMyWay.on('GET', '//test', () => {})
t.assert.fail('method already declared')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test\' with constraints \'{}\'')
}
})
test('with duplicate slashes', t => {
t.plan(2)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
findMyWay.on('GET', '//test', () => {})
try {
findMyWay.on('GET', '/test', () => {})
t.assert.fail('method already declared')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test\' with constraints \'{}\'')
}
try {
findMyWay.on('GET', '//test', () => {})
t.assert.fail('method already declared')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test\' with constraints \'{}\'')
}
})
})
test('Method already declared nested route', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/hello', () => {})
findMyWay.on('GET', '/test/world', () => {})
try {
findMyWay.on('GET', '/test/hello', () => {})
t.assert.fail('method already delcared in nested route')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test/hello\' with constraints \'{}\'')
}
})
describe('Method already declared nested route [ignoreTrailingSlash=true]', t => {
test('without trailing slash', t => {
t.plan(2)
const findMyWay = FindMyWay({ ignoreTrailingSlash: true })
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/hello', () => {})
findMyWay.on('GET', '/test/world', () => {})
try {
findMyWay.on('GET', '/test/hello', () => {})
t.assert.fail('method already declared')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test/hello\' with constraints \'{}\'')
}
try {
findMyWay.on('GET', '/test/hello/', () => {})
t.assert.fail('method already declared')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test/hello\' with constraints \'{}\'')
}
})
test('Method already declared with constraints', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', { constraints: { host: 'fastify.io' } }, () => {})
try {
findMyWay.on('GET', '/test', { constraints: { host: 'fastify.io' } }, () => {})
t.assert.fail('method already declared')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test\' with constraints \'{"host":"fastify.io"}\'')
}
})
test('with trailing slash', t => {
t.plan(2)
const findMyWay = FindMyWay({ ignoreTrailingSlash: true })
findMyWay.on('GET', '/test/', () => {})
findMyWay.on('GET', '/test/hello/', () => {})
findMyWay.on('GET', '/test/world/', () => {})
try {
findMyWay.on('GET', '/test/hello', () => {})
t.assert.fail('method already declared')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test/hello\' with constraints \'{}\'')
}
try {
findMyWay.on('GET', '/test/hello/', () => {})
t.assert.fail('method already declared')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test/hello\' with constraints \'{}\'')
}
})
})
describe('Method already declared nested route [ignoreDuplicateSlashes=true]', t => {
test('without duplicate slashes', t => {
t.plan(2)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/hello', () => {})
findMyWay.on('GET', '/test/world', () => {})
try {
findMyWay.on('GET', '/test/hello', () => {})
t.assert.fail('method already declared')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test/hello\' with constraints \'{}\'')
}
try {
findMyWay.on('GET', '/test//hello', () => {})
t.assert.fail('method already declared')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test/hello\' with constraints \'{}\'')
}
})
test('with duplicate slashes', t => {
t.plan(2)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
findMyWay.on('GET', '/test/', () => {})
findMyWay.on('GET', '/test//hello', () => {})
findMyWay.on('GET', '/test//world', () => {})
try {
findMyWay.on('GET', '/test/hello', () => {})
t.assert.fail('method already declared')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test/hello\' with constraints \'{}\'')
}
try {
findMyWay.on('GET', '/test//hello', () => {})
t.assert.fail('method already declared')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/test/hello\' with constraints \'{}\'')
}
})
})

View File

@@ -0,0 +1,34 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('contain param and wildcard together', t => {
t.plan(4)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '/:lang/item/:id', (req, res, params) => {
t.assert.deepEqual(params.lang, 'fr')
t.assert.deepEqual(params.id, '12345')
})
findMyWay.on('GET', '/:lang/item/*', (req, res, params) => {
t.assert.deepEqual(params.lang, 'fr')
t.assert.deepEqual(params['*'], '12345/edit')
})
findMyWay.lookup(
{ method: 'GET', url: '/fr/item/12345', headers: {} },
null
)
findMyWay.lookup(
{ method: 'GET', url: '/fr/item/12345/edit', headers: {} },
null
)
})

View File

@@ -0,0 +1,23 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('wildcard should not limit by maxParamLength', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '*', (req, res, params) => {
t.assert.deepEqual(params['*'], '/portfolios/b5859fb9-6c76-4db8-b3d1-337c5be3fd8b/instruments/2a694406-b43f-439d-aa11-0c814805c930/positions')
})
findMyWay.lookup(
{ method: 'GET', url: '/portfolios/b5859fb9-6c76-4db8-b3d1-337c5be3fd8b/instruments/2a694406-b43f-439d-aa11-0c814805c930/positions', headers: {} },
null
)
})

275
node_modules/find-my-way/test/find-route.test.js generated vendored Normal file
View File

@@ -0,0 +1,275 @@
'use strict'
const { test } = require('node:test')
const rfdc = require('rfdc')({ proto: true })
const FindMyWay = require('..')
function equalRouters (t, router1, router2) {
t.assert.deepStrictEqual(router1._opts, router2._opts)
t.assert.deepEqual(router1.routes, router2.routes)
t.assert.deepEqual(JSON.stringify(router1.trees), JSON.stringify(router2.trees))
t.assert.deepStrictEqual(router1.constrainer.strategies, router2.constrainer.strategies)
t.assert.deepStrictEqual(
router1.constrainer.strategiesInUse,
router2.constrainer.strategiesInUse
)
t.assert.deepStrictEqual(
router1.constrainer.asyncStrategiesInUse,
router2.constrainer.asyncStrategiesInUse
)
}
test('findRoute returns null if there is no routes', (t) => {
t.plan(7)
const findMyWay = FindMyWay()
const fundMyWayClone = rfdc(findMyWay)
const route = findMyWay.findRoute('GET', '/example')
t.assert.equal(route, null)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('findRoute returns handler and store for a static route', (t) => {
t.plan(9)
const findMyWay = FindMyWay()
const handler = () => {}
const store = { hello: 'world' }
findMyWay.on('GET', '/example', handler, store)
const fundMyWayClone = rfdc(findMyWay)
const route = findMyWay.findRoute('GET', '/example')
t.assert.equal(route.handler, handler)
t.assert.equal(route.store, store)
t.assert.deepEqual(route.params, [])
equalRouters(t, findMyWay, fundMyWayClone)
})
test('findRoute returns null for a static route', (t) => {
t.plan(7)
const findMyWay = FindMyWay()
const handler = () => {}
findMyWay.on('GET', '/example', handler)
const fundMyWayClone = rfdc(findMyWay)
const route = findMyWay.findRoute('GET', '/example1')
t.assert.equal(route, null)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('findRoute returns handler and params for a parametric route', (t) => {
t.plan(8)
const findMyWay = FindMyWay()
const handler = () => {}
findMyWay.on('GET', '/:param', handler)
const fundMyWayClone = rfdc(findMyWay)
const route = findMyWay.findRoute('GET', '/:param')
t.assert.equal(route.handler, handler)
t.assert.deepEqual(route.params, ['param'])
equalRouters(t, findMyWay, fundMyWayClone)
})
test('findRoute returns null for a parametric route', (t) => {
t.plan(7)
const findMyWay = FindMyWay()
const handler = () => {}
findMyWay.on('GET', '/foo/:param', handler)
const fundMyWayClone = rfdc(findMyWay)
const route = findMyWay.findRoute('GET', '/bar/:param')
t.assert.equal(route, null)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('findRoute returns handler and params for a parametric route with static suffix', (t) => {
t.plan(8)
const findMyWay = FindMyWay()
const handler = () => {}
findMyWay.on('GET', '/:param-static', handler)
const fundMyWayClone = rfdc(findMyWay)
const route = findMyWay.findRoute('GET', '/:param-static')
t.assert.equal(route.handler, handler)
t.assert.deepEqual(route.params, ['param'])
equalRouters(t, findMyWay, fundMyWayClone)
})
test('findRoute returns null for a parametric route with static suffix', (t) => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:param-static1', () => {})
const fundMyWayClone = rfdc(findMyWay)
const route = findMyWay.findRoute('GET', '/:param-static2')
t.assert.equal(route, null)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('findRoute returns handler and original params even if a param name different', (t) => {
t.plan(8)
const findMyWay = FindMyWay()
const handler = () => {}
findMyWay.on('GET', '/:param1', handler)
const fundMyWayClone = rfdc(findMyWay)
const route = findMyWay.findRoute('GET', '/:param2')
t.assert.equal(route.handler, handler)
t.assert.deepEqual(route.params, ['param1'])
equalRouters(t, findMyWay, fundMyWayClone)
})
test('findRoute returns handler and params for a multi-parametric route', (t) => {
t.plan(8)
const findMyWay = FindMyWay()
const handler = () => {}
findMyWay.on('GET', '/:param1-:param2', handler)
const fundMyWayClone = rfdc(findMyWay)
const route = findMyWay.findRoute('GET', '/:param1-:param2')
t.assert.equal(route.handler, handler)
t.assert.deepEqual(route.params, ['param1', 'param2'])
equalRouters(t, findMyWay, fundMyWayClone)
})
test('findRoute returns null for a multi-parametric route', (t) => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/foo/:param1-:param2/bar1', () => {})
const fundMyWayClone = rfdc(findMyWay)
const route = findMyWay.findRoute('GET', '/foo/:param1-:param2/bar2')
t.assert.equal(route, null)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('findRoute returns handler and regexp param for a regexp route', (t) => {
t.plan(8)
const findMyWay = FindMyWay()
const handler = () => {}
findMyWay.on('GET', '/:param(^\\d+$)', handler)
const fundMyWayClone = rfdc(findMyWay)
const route = findMyWay.findRoute('GET', '/:param(^\\d+$)')
t.assert.equal(route.handler, handler)
t.assert.deepEqual(route.params, ['param'])
equalRouters(t, findMyWay, fundMyWayClone)
})
test('findRoute returns null for a regexp route', (t) => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:file(^\\S+).png', () => {})
const fundMyWayClone = rfdc(findMyWay)
const route = findMyWay.findRoute('GET', '/:file(^\\D+).png')
t.assert.equal(route, null)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('findRoute returns handler and wildcard param for a wildcard route', (t) => {
t.plan(8)
const findMyWay = FindMyWay()
const handler = () => {}
findMyWay.on('GET', '/example/*', handler)
const fundMyWayClone = rfdc(findMyWay)
const route = findMyWay.findRoute('GET', '/example/*')
t.assert.equal(route.handler, handler)
t.assert.deepEqual(route.params, ['*'])
equalRouters(t, findMyWay, fundMyWayClone)
})
test('findRoute returns null for a wildcard route', (t) => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/foo1/*', () => {})
const fundMyWayClone = rfdc(findMyWay)
const route = findMyWay.findRoute('GET', '/foo2/*')
t.assert.equal(route, null)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('findRoute returns handler for a constrained route', (t) => {
t.plan(9)
const findMyWay = FindMyWay()
const handler = () => {}
findMyWay.on(
'GET',
'/example',
{ constraints: { version: '1.0.0' } },
handler
)
const fundMyWayClone = rfdc(findMyWay)
{
const route = findMyWay.findRoute('GET', '/example')
t.assert.equal(route, null)
}
{
const route = findMyWay.findRoute('GET', '/example', { version: '1.0.0' })
t.assert.equal(route.handler, handler)
}
{
const route = findMyWay.findRoute('GET', '/example', { version: '2.0.0' })
t.assert.equal(route, null)
}
equalRouters(t, findMyWay, fundMyWayClone)
})

16
node_modules/find-my-way/test/find.test.js generated vendored Normal file
View File

@@ -0,0 +1,16 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
test('find calls can pass no constraints', t => {
t.plan(3)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/a', () => {})
findMyWay.on('GET', '/a/b', () => {})
t.assert.ok(findMyWay.find('GET', '/a'))
t.assert.ok(findMyWay.find('GET', '/a/b'))
t.assert.ok(!findMyWay.find('GET', '/a/b/c'))
})

13
node_modules/find-my-way/test/for-in-loop.test.js generated vendored Normal file
View File

@@ -0,0 +1,13 @@
'use strict'
/* eslint no-extend-native: off */
const { test } = require('node:test')
// Something could extend the Array prototype
Array.prototype.test = null
test('for-in-loop', t => {
t.assert.doesNotThrow(() => {
require('../')
})
})

30
node_modules/find-my-way/test/full-url.test.js generated vendored Normal file
View File

@@ -0,0 +1,30 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('full-url', t => {
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a', (req, res) => {
res.end('{"message":"hello world"}')
})
findMyWay.on('GET', '/a/:id', (req, res) => {
res.end('{"message":"hello world"}')
})
t.assert.deepEqual(findMyWay.find('GET', 'http://localhost/a', { host: 'localhost' }), findMyWay.find('GET', '/a', { host: 'localhost' }))
t.assert.deepEqual(findMyWay.find('GET', 'http://localhost:8080/a', { host: 'localhost' }), findMyWay.find('GET', '/a', { host: 'localhost' }))
t.assert.deepEqual(findMyWay.find('GET', 'http://123.123.123.123/a', {}), findMyWay.find('GET', '/a', {}))
t.assert.deepEqual(findMyWay.find('GET', 'https://localhost/a', { host: 'localhost' }), findMyWay.find('GET', '/a', { host: 'localhost' }))
t.assert.deepEqual(findMyWay.find('GET', 'http://localhost/a/100', { host: 'localhost' }), findMyWay.find('GET', '/a/100', { host: 'localhost' }))
t.assert.deepEqual(findMyWay.find('GET', 'http://localhost:8080/a/100', { host: 'localhost' }), findMyWay.find('GET', '/a/100', { host: 'localhost' }))
t.assert.deepEqual(findMyWay.find('GET', 'http://123.123.123.123/a/100', {}), findMyWay.find('GET', '/a/100', {}))
t.assert.deepEqual(findMyWay.find('GET', 'https://localhost/a/100', { host: 'localhost' }), findMyWay.find('GET', '/a/100', { host: 'localhost' }))
})

218
node_modules/find-my-way/test/has-route.test.js generated vendored Normal file
View File

@@ -0,0 +1,218 @@
'use strict'
const { test } = require('node:test')
const rfdc = require('rfdc')({ proto: true })
const FindMyWay = require('..')
function equalRouters (t, router1, router2) {
t.assert.deepStrictEqual(router1._opts, router2._opts)
t.assert.deepEqual(router1.routes, router2.routes)
t.assert.deepEqual(JSON.stringify(router1.trees), JSON.stringify(router2.trees))
t.assert.deepStrictEqual(
router1.constrainer.strategies,
router2.constrainer.strategies
)
t.assert.deepStrictEqual(
router1.constrainer.strategiesInUse,
router2.constrainer.strategiesInUse
)
t.assert.deepStrictEqual(
router1.constrainer.asyncStrategiesInUse,
router2.constrainer.asyncStrategiesInUse
)
}
test('hasRoute returns false if there is no routes', t => {
t.plan(7)
const findMyWay = FindMyWay()
const fundMyWayClone = rfdc(findMyWay)
const hasRoute = findMyWay.hasRoute('GET', '/example')
t.assert.equal(hasRoute, false)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('hasRoute returns true for a static route', t => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/example', () => {})
const fundMyWayClone = rfdc(findMyWay)
const hasRoute = findMyWay.hasRoute('GET', '/example')
t.assert.equal(hasRoute, true)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('hasRoute returns false for a static route', t => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/example', () => {})
const fundMyWayClone = rfdc(findMyWay)
const hasRoute = findMyWay.hasRoute('GET', '/example1')
t.assert.equal(hasRoute, false)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('hasRoute returns true for a parametric route', t => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:param', () => {})
const fundMyWayClone = rfdc(findMyWay)
const hasRoute = findMyWay.hasRoute('GET', '/:param')
t.assert.equal(hasRoute, true)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('hasRoute returns false for a parametric route', t => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/foo/:param', () => {})
const fundMyWayClone = rfdc(findMyWay)
const hasRoute = findMyWay.hasRoute('GET', '/bar/:param')
t.assert.equal(hasRoute, false)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('hasRoute returns true for a parametric route with static suffix', t => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:param-static', () => {})
const fundMyWayClone = rfdc(findMyWay)
const hasRoute = findMyWay.hasRoute('GET', '/:param-static')
t.assert.equal(hasRoute, true)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('hasRoute returns false for a parametric route with static suffix', t => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:param-static1', () => {})
const fundMyWayClone = rfdc(findMyWay)
const hasRoute = findMyWay.hasRoute('GET', '/:param-static2')
t.assert.equal(hasRoute, false)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('hasRoute returns true even if a param name different', t => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:param1', () => {})
const fundMyWayClone = rfdc(findMyWay)
const hasRoute = findMyWay.hasRoute('GET', '/:param2')
t.assert.equal(hasRoute, true)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('hasRoute returns true for a multi-parametric route', t => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:param1-:param2', () => {})
const fundMyWayClone = rfdc(findMyWay)
const hasRoute = findMyWay.hasRoute('GET', '/:param1-:param2')
t.assert.equal(hasRoute, true)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('hasRoute returns false for a multi-parametric route', t => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/foo/:param1-:param2/bar1', () => {})
const fundMyWayClone = rfdc(findMyWay)
const hasRoute = findMyWay.hasRoute('GET', '/foo/:param1-:param2/bar2')
t.assert.equal(hasRoute, false)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('hasRoute returns true for a regexp route', t => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:param(^\\d+$)', () => {})
const fundMyWayClone = rfdc(findMyWay)
const hasRoute = findMyWay.hasRoute('GET', '/:param(^\\d+$)')
t.assert.equal(hasRoute, true)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('hasRoute returns false for a regexp route', t => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:file(^\\S+).png', () => {})
const fundMyWayClone = rfdc(findMyWay)
const hasRoute = findMyWay.hasRoute('GET', '/:file(^\\D+).png')
t.assert.equal(hasRoute, false)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('hasRoute returns true for a wildcard route', t => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/example/*', () => {})
const fundMyWayClone = rfdc(findMyWay)
const hasRoute = findMyWay.hasRoute('GET', '/example/*')
t.assert.equal(hasRoute, true)
equalRouters(t, findMyWay, fundMyWayClone)
})
test('hasRoute returns false for a wildcard route', t => {
t.plan(7)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/foo1/*', () => {})
const fundMyWayClone = rfdc(findMyWay)
const hasRoute = findMyWay.hasRoute('GET', '/foo2/*')
t.assert.equal(hasRoute, false)
equalRouters(t, findMyWay, fundMyWayClone)
})

27
node_modules/find-my-way/test/host-storage.test.js generated vendored Normal file
View File

@@ -0,0 +1,27 @@
const acceptHostStrategy = require('../lib/strategies/accept-host')
const { test } = require('node:test')
test('can get hosts by exact matches', async (t) => {
const storage = acceptHostStrategy.storage()
t.assert.equal(storage.get('fastify.io'), undefined)
storage.set('fastify.io', true)
t.assert.equal(storage.get('fastify.io'), true)
})
test('can get hosts by regexp matches', async (t) => {
const storage = acceptHostStrategy.storage()
t.assert.equal(storage.get('fastify.io'), undefined)
storage.set(/.+fastify\.io/, true)
t.assert.equal(storage.get('foo.fastify.io'), true)
t.assert.equal(storage.get('bar.fastify.io'), true)
})
test('exact host matches take precendence over regexp matches', async (t) => {
const storage = acceptHostStrategy.storage()
storage.set(/.+fastify\.io/, 'wildcard')
storage.set('auth.fastify.io', 'exact')
t.assert.equal(storage.get('foo.fastify.io'), 'wildcard')
t.assert.equal(storage.get('bar.fastify.io'), 'wildcard')
t.assert.equal(storage.get('auth.fastify.io'), 'exact')
})

View File

@@ -0,0 +1,44 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../..')
test('A route supports host constraints under http2 protocol', t => {
t.plan(3)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', {}, (req, res) => {
t.assert.assert.fail()
})
findMyWay.on('GET', '/', { constraints: { host: 'fastify.io' } }, (req, res) => {
t.assert.equal(req.headers[':authority'], 'fastify.io')
})
findMyWay.on('GET', '/', { constraints: { host: /.+\.de/ } }, (req, res) => {
t.assert.ok(req.headers[':authority'].endsWith('.de'))
})
findMyWay.lookup({
method: 'GET',
url: '/',
headers: {
':authority': 'fastify.io'
}
})
findMyWay.lookup({
method: 'GET',
url: '/',
headers: {
':authority': 'fastify.de'
}
})
findMyWay.lookup({
method: 'GET',
url: '/',
headers: {
':authority': 'find-my-way.de'
}
})
})

31
node_modules/find-my-way/test/issue-101.test.js generated vendored Normal file
View File

@@ -0,0 +1,31 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('Falling back for node\'s parametric brother', t => {
t.plan(3)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/:namespace/:type/:id', () => {})
findMyWay.on('GET', '/:namespace/jobs/:name/run', () => {})
t.assert.deepEqual(
findMyWay.find('GET', '/test_namespace/test_type/test_id').params,
{ namespace: 'test_namespace', type: 'test_type', id: 'test_id' }
)
t.assert.deepEqual(
findMyWay.find('GET', '/test_namespace/jobss/test_id').params,
{ namespace: 'test_namespace', type: 'jobss', id: 'test_id' }
)
t.assert.deepEqual(
findMyWay.find('GET', '/test_namespace/jobs/test_id').params,
{ namespace: 'test_namespace', type: 'jobs', id: 'test_id' }
)
})

206
node_modules/find-my-way/test/issue-104.test.js generated vendored Normal file
View File

@@ -0,0 +1,206 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('Nested static parametric route, url with parameter common prefix > 1', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a/bbbb', (req, res) => {
res.end('{"message":"hello world"}')
})
findMyWay.on('GET', '/a/bbaa', (req, res) => {
res.end('{"message":"hello world"}')
})
findMyWay.on('GET', '/a/babb', (req, res) => {
res.end('{"message":"hello world"}')
})
findMyWay.on('DELETE', '/a/:id', (req, res) => {
res.end('{"message":"hello world"}')
})
t.assert.deepEqual(findMyWay.find('DELETE', '/a/bbar').params, { id: 'bbar' })
})
test('Parametric route, url with parameter common prefix > 1', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/aaa', (req, res) => {
res.end('{"message":"hello world"}')
})
findMyWay.on('GET', '/aabb', (req, res) => {
res.end('{"message":"hello world"}')
})
findMyWay.on('GET', '/abc', (req, res) => {
res.end('{"message":"hello world"}')
})
findMyWay.on('GET', '/:id', (req, res) => {
res.end('{"message":"hello world"}')
})
t.assert.deepEqual(findMyWay.find('GET', '/aab').params, { id: 'aab' })
})
test('Parametric route, url with multi parameter common prefix > 1', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/:id/aaa/:id2', (req, res) => {
res.end('{"message":"hello world"}')
})
findMyWay.on('GET', '/:id/aabb/:id2', (req, res) => {
res.end('{"message":"hello world"}')
})
findMyWay.on('GET', '/:id/abc/:id2', (req, res) => {
res.end('{"message":"hello world"}')
})
findMyWay.on('GET', '/:a/:b', (req, res) => {
res.end('{"message":"hello world"}')
})
t.assert.deepEqual(findMyWay.find('GET', '/hello/aab').params, { a: 'hello', b: 'aab' })
})
test('Mixed routes, url with parameter common prefix > 1', t => {
t.plan(11)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/test', (req, res, params) => {
res.end('{"hello":"world"}')
})
findMyWay.on('GET', '/testify', (req, res, params) => {
res.end('{"hello":"world"}')
})
findMyWay.on('GET', '/test/hello', (req, res, params) => {
res.end('{"hello":"world"}')
})
findMyWay.on('GET', '/test/hello/test', (req, res, params) => {
res.end('{"hello":"world"}')
})
findMyWay.on('GET', '/te/:a', (req, res, params) => {
res.end('{"hello":"world"}')
})
findMyWay.on('GET', '/test/hello/:b', (req, res, params) => {
res.end('{"hello":"world"}')
})
findMyWay.on('GET', '/:c', (req, res, params) => {
res.end('{"hello":"world"}')
})
findMyWay.on('GET', '/text/hello', (req, res, params) => {
res.end('{"hello":"world"}')
})
findMyWay.on('GET', '/text/:d', (req, res, params) => {
res.end('{"winter":"is here"}')
})
findMyWay.on('GET', '/text/:e/test', (req, res, params) => {
res.end('{"winter":"is here"}')
})
t.assert.deepEqual(findMyWay.find('GET', '/test').params, {})
t.assert.deepEqual(findMyWay.find('GET', '/testify').params, {})
t.assert.deepEqual(findMyWay.find('GET', '/test/hello').params, {})
t.assert.deepEqual(findMyWay.find('GET', '/test/hello/test').params, {})
t.assert.deepEqual(findMyWay.find('GET', '/te/hello').params, { a: 'hello' })
t.assert.deepEqual(findMyWay.find('GET', '/te/').params, { a: '' })
t.assert.deepEqual(findMyWay.find('GET', '/testy').params, { c: 'testy' })
t.assert.deepEqual(findMyWay.find('GET', '/besty').params, { c: 'besty' })
t.assert.deepEqual(findMyWay.find('GET', '/text/hellos/test').params, { e: 'hellos' })
t.assert.deepEqual(findMyWay.find('GET', '/te/hello/'), null)
t.assert.deepEqual(findMyWay.find('GET', '/te/hellos/testy'), null)
})
test('Parent parametric brother should not rewrite child node parametric brother', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/text/hello', (req, res, params) => {
res.end('{"hello":"world"}')
})
findMyWay.on('GET', '/text/:e/test', (req, res, params) => {
res.end('{"winter":"is here"}')
})
findMyWay.on('GET', '/:c', (req, res, params) => {
res.end('{"hello":"world"}')
})
t.assert.deepEqual(findMyWay.find('GET', '/text/hellos/test').params, { e: 'hellos' })
})
test('Mixed parametric routes, with last defined route being static', t => {
t.plan(4)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/test', (req, res, params) => {
res.end('{"hello":"world"}')
})
findMyWay.on('GET', '/test/:a', (req, res, params) => {
res.end('{"hello":"world"}')
})
findMyWay.on('GET', '/test/hello/:b', (req, res, params) => {
res.end('{"hello":"world"}')
})
findMyWay.on('GET', '/test/hello/:c/test', (req, res, params) => {
res.end('{"hello":"world"}')
})
findMyWay.on('GET', '/test/hello/:c/:k', (req, res, params) => {
res.end('{"hello":"world"}')
})
findMyWay.on('GET', '/test/world', (req, res, params) => {
res.end('{"hello":"world"}')
})
t.assert.deepEqual(findMyWay.find('GET', '/test/hello').params, { a: 'hello' })
t.assert.deepEqual(findMyWay.find('GET', '/test/hello/world/test').params, { c: 'world' })
t.assert.deepEqual(findMyWay.find('GET', '/test/hello/world/te').params, { c: 'world', k: 'te' })
t.assert.deepEqual(findMyWay.find('GET', '/test/hello/world/testy').params, { c: 'world', k: 'testy' })
})

31
node_modules/find-my-way/test/issue-110.test.js generated vendored Normal file
View File

@@ -0,0 +1,31 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('Nested static parametric route, url with parameter common prefix > 1', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/api/foo/b2', (req, res) => {
res.end('{"message":"hello world"}')
})
findMyWay.on('GET', '/api/foo/bar/qux', (req, res) => {
res.end('{"message":"hello world"}')
})
findMyWay.on('GET', '/api/foo/:id/bar', (req, res) => {
res.end('{"message":"hello world"}')
})
findMyWay.on('GET', '/foo', (req, res) => {
res.end('{"message":"hello world"}')
})
t.assert.deepEqual(findMyWay.find('GET', '/api/foo/b-123/bar').params, { id: 'b-123' })
})

80
node_modules/find-my-way/test/issue-132.test.js generated vendored Normal file
View File

@@ -0,0 +1,80 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('Wildcard mixed with dynamic and common prefix / 1', t => {
t.plan(5)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('OPTIONS', '/*', (req, res, params) => {
t.assert.equal(req.method, 'OPTIONS')
})
findMyWay.on('GET', '/obj/params/*', (req, res, params) => {
t.assert.equal(req.method, 'GET')
})
findMyWay.on('GET', '/obj/:id', (req, res, params) => {
t.assert.equal(req.method, 'GET')
})
findMyWay.on('GET', '/obj_params/*', (req, res, params) => {
t.assert.equal(req.method, 'GET')
})
findMyWay.lookup({ method: 'OPTIONS', url: '/obj/params', headers: {} }, null)
findMyWay.lookup({ method: 'OPTIONS', url: '/obj/params/12', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/obj/params/12', headers: {} }, null)
findMyWay.lookup({ method: 'OPTIONS', url: '/obj_params/12', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/obj_params/12', headers: {} }, null)
})
test('Wildcard mixed with dynamic and common prefix / 2', t => {
t.plan(6)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('OPTIONS', '/*', (req, res, params) => {
t.assert.equal(req.method, 'OPTIONS')
})
findMyWay.on('OPTIONS', '/obj/*', (req, res, params) => {
t.assert.equal(req.method, 'OPTIONS')
})
findMyWay.on('GET', '/obj/params/*', (req, res, params) => {
t.assert.equal(req.method, 'GET')
})
findMyWay.on('GET', '/obj/:id', (req, res, params) => {
t.assert.equal(req.method, 'GET')
})
findMyWay.on('GET', '/obj_params/*', (req, res, params) => {
t.assert.equal(req.method, 'GET')
})
findMyWay.lookup({ method: 'OPTIONS', url: '/obj_params/params', headers: {} }, null)
findMyWay.lookup({ method: 'OPTIONS', url: '/obj/params', headers: {} }, null)
findMyWay.lookup({ method: 'OPTIONS', url: '/obj/params/12', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/obj/params/12', headers: {} }, null)
findMyWay.lookup({ method: 'OPTIONS', url: '/obj_params/12', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/obj_params/12', headers: {} }, null)
})

24
node_modules/find-my-way/test/issue-145.test.js generated vendored Normal file
View File

@@ -0,0 +1,24 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('issue-145', (t) => {
t.plan(8)
const findMyWay = FindMyWay({ ignoreTrailingSlash: true })
const fixedPath = function staticPath () {}
const varPath = function parameterPath () {}
findMyWay.on('GET', '/a/b', fixedPath)
findMyWay.on('GET', '/a/:pam/c', varPath)
t.assert.equal(findMyWay.find('GET', '/a/b').handler, fixedPath)
t.assert.equal(findMyWay.find('GET', '/a/b/').handler, fixedPath)
t.assert.equal(findMyWay.find('GET', '/a/b/c').handler, varPath)
t.assert.equal(findMyWay.find('GET', '/a/b/c/').handler, varPath)
t.assert.equal(findMyWay.find('GET', '/a/foo/c').handler, varPath)
t.assert.equal(findMyWay.find('GET', '/a/foo/c/').handler, varPath)
t.assert.ok(!findMyWay.find('GET', '/a/c'))
t.assert.ok(!findMyWay.find('GET', '/a/c/'))
})

21
node_modules/find-my-way/test/issue-149.test.js generated vendored Normal file
View File

@@ -0,0 +1,21 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('Falling back for node\'s parametric brother', t => {
t.plan(3)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/foo/:id', () => {})
findMyWay.on('GET', '/foo/:color/:id', () => {})
findMyWay.on('GET', '/foo/red', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/foo/red/123').params, { color: 'red', id: '123' })
t.assert.deepEqual(findMyWay.find('GET', '/foo/blue/123').params, { color: 'blue', id: '123' })
t.assert.deepEqual(findMyWay.find('GET', '/foo/red').params, {})
})

54
node_modules/find-my-way/test/issue-151.test.js generated vendored Normal file
View File

@@ -0,0 +1,54 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('Wildcard route should not be blocked by Parametric with different method / 1', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('OPTIONS', '/*', (req, res, params) => {
t.assert.fail('Should not be here')
})
findMyWay.on('OPTIONS', '/obj/*', (req, res, params) => {
t.assert.equal(req.method, 'OPTIONS')
})
findMyWay.on('GET', '/obj/:id', (req, res, params) => {
t.assert.fail('Should not be GET')
})
findMyWay.lookup({ method: 'OPTIONS', url: '/obj/params', headers: {} }, null)
})
test('Wildcard route should not be blocked by Parametric with different method / 2', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('OPTIONS', '/*', { version: '1.2.3' }, (req, res, params) => {
t.assert.fail('Should not be here')
})
findMyWay.on('OPTIONS', '/obj/*', { version: '1.2.3' }, (req, res, params) => {
t.assert.equal(req.method, 'OPTIONS')
})
findMyWay.on('GET', '/obj/:id', { version: '1.2.3' }, (req, res, params) => {
t.assert.fail('Should not be GET')
})
findMyWay.lookup({
method: 'OPTIONS',
url: '/obj/params',
headers: { 'accept-version': '1.2.3' }
}, null)
})

21
node_modules/find-my-way/test/issue-154.test.js generated vendored Normal file
View File

@@ -0,0 +1,21 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
const noop = () => {}
test('Should throw when not sending a string', t => {
t.plan(3)
const findMyWay = FindMyWay()
t.assert.throws(() => {
findMyWay.on('GET', '/t1', { constraints: { version: 42 } }, noop)
})
t.assert.throws(() => {
findMyWay.on('GET', '/t2', { constraints: { version: null } }, noop)
})
t.assert.throws(() => {
findMyWay.on('GET', '/t2', { constraints: { version: true } }, noop)
})
})

88
node_modules/find-my-way/test/issue-161.test.js generated vendored Normal file
View File

@@ -0,0 +1,88 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('Falling back for node\'s parametric brother without ignoreTrailingSlash', t => {
t.plan(4)
const findMyWay = FindMyWay({
ignoreTrailingSlash: false,
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/static/param1', () => {})
findMyWay.on('GET', '/static/param2', () => {})
findMyWay.on('GET', '/static/:paramA/next', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/static/param1').params, {})
t.assert.deepEqual(findMyWay.find('GET', '/static/param2').params, {})
t.assert.deepEqual(findMyWay.find('GET', '/static/paramOther/next').params, { paramA: 'paramOther' })
t.assert.deepEqual(findMyWay.find('GET', '/static/param1/next').params, { paramA: 'param1' })
})
test('Falling back for node\'s parametric brother with ignoreTrailingSlash', t => {
t.plan(4)
const findMyWay = FindMyWay({
ignoreTrailingSlash: true,
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/static/param1', () => {})
findMyWay.on('GET', '/static/param2', () => {})
findMyWay.on('GET', '/static/:paramA/next', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/static/param1').params, {})
t.assert.deepEqual(findMyWay.find('GET', '/static/param2').params, {})
t.assert.deepEqual(findMyWay.find('GET', '/static/paramOther/next').params, { paramA: 'paramOther' })
t.assert.deepEqual(findMyWay.find('GET', '/static/param1/next').params, { paramA: 'param1' })
})
test('Falling back for node\'s parametric brother without ignoreTrailingSlash', t => {
t.plan(4)
const findMyWay = FindMyWay({
ignoreTrailingSlash: false,
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/static/param1', () => {})
findMyWay.on('GET', '/static/param2', () => {})
findMyWay.on('GET', '/static/:paramA/next', () => {})
findMyWay.on('GET', '/static/param1/next/param3', () => {})
findMyWay.on('GET', '/static/param1/next/param4', () => {})
findMyWay.on('GET', '/static/:paramA/next/:paramB/other', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/static/param1/next/param3').params, {})
t.assert.deepEqual(findMyWay.find('GET', '/static/param1/next/param4').params, {})
t.assert.deepEqual(findMyWay.find('GET', '/static/paramOther/next/paramOther2/other').params, { paramA: 'paramOther', paramB: 'paramOther2' })
t.assert.deepEqual(findMyWay.find('GET', '/static/param1/next/param3/other').params, { paramA: 'param1', paramB: 'param3' })
})
test('Falling back for node\'s parametric brother with ignoreTrailingSlash', t => {
t.plan(4)
const findMyWay = FindMyWay({
ignoreTrailingSlash: true,
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/static/param1', () => {})
findMyWay.on('GET', '/static/param2', () => {})
findMyWay.on('GET', '/static/:paramA/next', () => {})
findMyWay.on('GET', '/static/param1/next/param3', () => {})
findMyWay.on('GET', '/static/param1/next/param4', () => {})
findMyWay.on('GET', '/static/:paramA/next/:paramB/other', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/static/param1/next/param3').params, {})
t.assert.deepEqual(findMyWay.find('GET', '/static/param1/next/param4').params, {})
t.assert.deepEqual(findMyWay.find('GET', '/static/paramOther/next/paramOther2/other').params, { paramA: 'paramOther', paramB: 'paramOther2' })
t.assert.deepEqual(findMyWay.find('GET', '/static/param1/next/param3/other').params, { paramA: 'param1', paramB: 'param3' })
})

397
node_modules/find-my-way/test/issue-17.test.js generated vendored Normal file
View File

@@ -0,0 +1,397 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('Parametric route, request.url contains dash', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a/:param/b', (req, res, params) => {
t.assert.equal(params.param, 'foo-bar')
})
findMyWay.lookup({ method: 'GET', url: '/a/foo-bar/b', headers: {} }, null)
})
test('Parametric route with fixed suffix', t => {
t.plan(6)
const findMyWay = FindMyWay({
defaultRoute: () => t.assert.fail('Should not be defaultRoute')
})
findMyWay.on('GET', '/a/:param-static', () => {})
findMyWay.on('GET', '/b/:param.static', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/a/param-static', {}).params, { param: 'param' })
t.assert.deepEqual(findMyWay.find('GET', '/b/param.static', {}).params, { param: 'param' })
t.assert.deepEqual(findMyWay.find('GET', '/a/param-param-static', {}).params, { param: 'param-param' })
t.assert.deepEqual(findMyWay.find('GET', '/b/param.param.static', {}).params, { param: 'param.param' })
t.assert.deepEqual(findMyWay.find('GET', '/a/param.param-static', {}).params, { param: 'param.param' })
t.assert.deepEqual(findMyWay.find('GET', '/b/param-param.static', {}).params, { param: 'param-param' })
})
test('Regex param exceeds max parameter length', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.ok('route not matched')
}
})
findMyWay.on('GET', '/a/:param(^\\w{3})', (req, res, params) => {
t.assert.fail('regex match')
})
findMyWay.lookup({ method: 'GET', url: '/a/fool', headers: {} }, null)
})
test('Parametric route with regexp and fixed suffix / 1', t => {
t.plan(4)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.ok('route not matched')
}
})
findMyWay.on('GET', '/a/:param(^\\w{3})bar', (req, res, params) => {
t.assert.fail('regex match')
})
findMyWay.lookup({ method: 'GET', url: '/a/$mebar', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/a/foolol', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/a/foobaz', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/a/foolbar', headers: {} }, null)
})
test('Parametric route with regexp and fixed suffix / 2', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a/:param(^\\w{3})bar', (req, res, params) => {
t.assert.equal(params.param, 'foo')
})
findMyWay.lookup({ method: 'GET', url: '/a/foobar', headers: {} }, null)
})
test('Parametric route with regexp and fixed suffix / 3', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a/:param(^\\w{3}-\\w{3})foo', (req, res, params) => {
t.assert.equal(params.param, 'abc-def')
})
findMyWay.lookup({ method: 'GET', url: '/a/abc-deffoo', headers: {} }, null)
})
test('Multi parametric route / 1', t => {
t.plan(4)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a/:p1-:p2', (req, res, params) => {
t.assert.equal(params.p1, 'foo')
t.assert.equal(params.p2, 'bar')
})
findMyWay.on('GET', '/b/:p1.:p2', (req, res, params) => {
t.assert.equal(params.p1, 'foo')
t.assert.equal(params.p2, 'bar')
})
findMyWay.lookup({ method: 'GET', url: '/a/foo-bar', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/b/foo.bar', headers: {} }, null)
})
test('Multi parametric route / 2', t => {
t.plan(4)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a/:p1-:p2', (req, res, params) => {
t.assert.equal(params.p1, 'foo-bar')
t.assert.equal(params.p2, 'baz')
})
findMyWay.on('GET', '/b/:p1.:p2', (req, res, params) => {
t.assert.equal(params.p1, 'foo')
t.assert.equal(params.p2, 'bar-baz')
})
findMyWay.lookup({ method: 'GET', url: '/a/foo-bar-baz', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/b/foo.bar-baz', headers: {} }, null)
})
test('Multi parametric route / 3', t => {
t.plan(4)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a/:p_1-:$p', (req, res, params) => {
t.assert.equal(params.p_1, 'foo')
t.assert.equal(params.$p, 'bar')
})
findMyWay.on('GET', '/b/:p_1.:$p', (req, res, params) => {
t.assert.equal(params.p_1, 'foo')
t.assert.equal(params.$p, 'bar')
})
findMyWay.lookup({ method: 'GET', url: '/a/foo-bar', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/b/foo.bar', headers: {} }, null)
})
test('Multi parametric route / 4', t => {
t.plan(2)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.ok('Everything good')
}
})
findMyWay.on('GET', '/a/:p1-:p2', (req, res, params) => {
t.assert.fail('Should not match this route')
})
findMyWay.on('GET', '/b/:p1.:p2', (req, res, params) => {
t.assert.fail('Should not match this route')
})
findMyWay.lookup({ method: 'GET', url: '/a/foo', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/b/foo', headers: {} }, null)
})
test('Multi parametric route with regexp / 1', t => {
t.plan(2)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/at/:hour(^\\d+)h:minute(^\\d+)m', (req, res, params) => {
t.assert.equal(params.hour, '0')
t.assert.equal(params.minute, '42')
})
findMyWay.lookup({ method: 'GET', url: '/at/0h42m', headers: {} }, null)
})
test('Multi parametric route with colon separator', t => {
t.plan(3)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/:param(.*)::suffix', (req, res, params) => {
t.assert.equal(params.param, 'foo')
})
findMyWay.on('GET', '/:param1(.*)::suffix1-:param2(.*)::suffix2/static', (req, res, params) => {
t.assert.equal(params.param1, 'foo')
t.assert.equal(params.param2, 'bar')
})
findMyWay.lookup({ method: 'GET', url: '/foo:suffix', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/foo:suffix1-bar:suffix2/static', headers: {} }, null)
})
test('Multi parametric route with regexp / 2', t => {
t.plan(8)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a/:uuid(^[\\d-]{19})-:user(^\\w+)', (req, res, params) => {
t.assert.equal(params.uuid, '1111-2222-3333-4444')
t.assert.equal(params.user, 'foo')
})
findMyWay.on('GET', '/a/:uuid(^[\\d-]{19})-:user(^\\w+)/account', (req, res, params) => {
t.assert.equal(params.uuid, '1111-2222-3333-4445')
t.assert.equal(params.user, 'bar')
})
findMyWay.on('GET', '/b/:uuid(^[\\d-]{19}).:user(^\\w+)', (req, res, params) => {
t.assert.equal(params.uuid, '1111-2222-3333-4444')
t.assert.equal(params.user, 'foo')
})
findMyWay.on('GET', '/b/:uuid(^[\\d-]{19}).:user(^\\w+)/account', (req, res, params) => {
t.assert.equal(params.uuid, '1111-2222-3333-4445')
t.assert.equal(params.user, 'bar')
})
findMyWay.lookup({ method: 'GET', url: '/a/1111-2222-3333-4444-foo', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/a/1111-2222-3333-4445-bar/account', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/b/1111-2222-3333-4444.foo', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/b/1111-2222-3333-4445.bar/account', headers: {} }, null)
})
test('Multi parametric route with fixed suffix', t => {
t.plan(4)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a/:p1-:p2-baz', (req, res, params) => {
t.assert.equal(params.p1, 'foo')
t.assert.equal(params.p2, 'bar')
})
findMyWay.on('GET', '/b/:p1.:p2-baz', (req, res, params) => {
t.assert.equal(params.p1, 'foo')
t.assert.equal(params.p2, 'bar')
})
findMyWay.lookup({ method: 'GET', url: '/a/foo-bar-baz', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/b/foo.bar-baz', headers: {} }, null)
})
test('Multi parametric route with regexp and fixed suffix', t => {
t.plan(4)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a/:p1(^\\w+)-:p2(^\\w+)-kuux', (req, res, params) => {
t.assert.equal(params.p1, 'foo')
t.assert.equal(params.p2, 'barbaz')
})
findMyWay.on('GET', '/b/:p1(^\\w+).:p2(^\\w+)-kuux', (req, res, params) => {
t.assert.equal(params.p1, 'foo')
t.assert.equal(params.p2, 'barbaz')
})
findMyWay.lookup({ method: 'GET', url: '/a/foo-barbaz-kuux', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/b/foo.barbaz-kuux', headers: {} }, null)
})
test('Multi parametric route with wildcard', t => {
t.plan(4)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a/:p1-:p2/*', (req, res, params) => {
t.assert.equal(params.p1, 'foo')
t.assert.equal(params.p2, 'bar')
})
findMyWay.on('GET', '/b/:p1.:p2/*', (req, res, params) => {
t.assert.equal(params.p1, 'foo')
t.assert.equal(params.p2, 'bar')
})
findMyWay.lookup({ method: 'GET', url: '/a/foo-bar/baz', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/b/foo.bar/baz', headers: {} }, null)
})
test('Nested multi parametric route', t => {
t.plan(6)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a/:p1-:p2/b/:p3', (req, res, params) => {
t.assert.equal(params.p1, 'foo')
t.assert.equal(params.p2, 'bar')
t.assert.equal(params.p3, 'baz')
})
findMyWay.on('GET', '/b/:p1.:p2/b/:p3', (req, res, params) => {
t.assert.equal(params.p1, 'foo')
t.assert.equal(params.p2, 'bar')
t.assert.equal(params.p3, 'baz')
})
findMyWay.lookup({ method: 'GET', url: '/a/foo-bar/b/baz', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/b/foo.bar/b/baz', headers: {} }, null)
})
test('Nested multi parametric route with regexp / 1', t => {
t.plan(6)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a/:p1(^\\w{3})-:p2(^\\d+)/b/:p3', (req, res, params) => {
t.assert.equal(params.p1, 'foo')
t.assert.equal(params.p2, '42')
t.assert.equal(params.p3, 'bar')
})
findMyWay.on('GET', '/b/:p1(^\\w{3}).:p2(^\\d+)/b/:p3', (req, res, params) => {
t.assert.equal(params.p1, 'foo')
t.assert.equal(params.p2, '42')
t.assert.equal(params.p3, 'bar')
})
findMyWay.lookup({ method: 'GET', url: '/a/foo-42/b/bar', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/b/foo.42/b/bar', headers: {} }, null)
})
test('Nested multi parametric route with regexp / 2', t => {
t.plan(6)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a/:p1(^\\w{3})-:p2/b/:p3', (req, res, params) => {
t.assert.equal(params.p1, 'foo')
t.assert.equal(params.p2, '42')
t.assert.equal(params.p3, 'bar')
})
findMyWay.on('GET', '/b/:p1(^\\w{3}).:p2/b/:p3', (req, res, params) => {
t.assert.equal(params.p1, 'foo')
t.assert.equal(params.p2, '42')
t.assert.equal(params.p3, 'bar')
})
findMyWay.lookup({ method: 'GET', url: '/a/foo-42/b/bar', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/b/foo.42/b/bar', headers: {} }, null)
})

80
node_modules/find-my-way/test/issue-175.test.js generated vendored Normal file
View File

@@ -0,0 +1,80 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
test('double colon is replaced with single colon, no parameters', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: () => t.assert.fail('should not be default route')
})
function handler (req, res, params) {
t.assert.deepEqual(params, {})
}
findMyWay.on('GET', '/name::customVerb', handler)
findMyWay.lookup({ method: 'GET', url: '/name:customVerb' }, null)
})
test('exactly one match for static route with colon', t => {
t.plan(2)
const findMyWay = FindMyWay()
function handler () {}
findMyWay.on('GET', '/name::customVerb', handler)
t.assert.equal(findMyWay.find('GET', '/name:customVerb').handler, handler)
t.assert.equal(findMyWay.find('GET', '/name:test'), null)
})
test('double colon is replaced with single colon, no parameters, same parent node name', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: () => t.assert.fail('should not be default route')
})
findMyWay.on('GET', '/name', () => {
t.assert.fail('should not be parent route')
})
findMyWay.on('GET', '/name::customVerb', (req, res, params) => {
t.assert.deepEqual(params, {})
})
findMyWay.lookup({ method: 'GET', url: '/name:customVerb', headers: {} }, null)
})
test('double colon is replaced with single colon, default route, same parent node name', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: () => t.assert.ok('should be default route')
})
findMyWay.on('GET', '/name', () => {
t.assert.fail('should not be parent route')
})
findMyWay.on('GET', '/name::customVerb', () => {
t.assert.fail('should not be child route')
})
findMyWay.lookup({ method: 'GET', url: '/name:wrongCustomVerb', headers: {} }, null)
})
test('double colon is replaced with single colon, with parameters', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: () => t.assert.fail('should not be default route')
})
findMyWay.on('GET', '/name1::customVerb1/:param1/name2::customVerb2:param2', (req, res, params) => {
t.assert.deepEqual(params, {
param1: 'value1',
param2: 'value2'
})
})
findMyWay.lookup({ method: 'GET', url: '/name1:customVerb1/value1/name2:customVerb2value2', headers: {} }, null)
})

18
node_modules/find-my-way/test/issue-182.test.js generated vendored Normal file
View File

@@ -0,0 +1,18 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
test('Set method property when splitting node', t => {
t.plan(1)
const findMyWay = FindMyWay()
function handler (req, res, params) {
t.assert.ok()
}
findMyWay.on('GET', '/health-a/health', handler)
findMyWay.on('GET', '/health-b/health', handler)
t.assert.ok(!findMyWay.prettyPrint().includes('undefined'))
})

44
node_modules/find-my-way/test/issue-190.test.js generated vendored Normal file
View File

@@ -0,0 +1,44 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('issue-190', (t) => {
t.plan(6)
const findMyWay = FindMyWay()
let staticCounter = 0
let paramCounter = 0
const staticPath = function staticPath () { staticCounter++ }
const paramPath = function paramPath () { paramCounter++ }
const extraPath = function extraPath () { }
findMyWay.on('GET', '/api/users/award_winners', staticPath)
findMyWay.on('GET', '/api/users/admins', staticPath)
findMyWay.on('GET', '/api/users/:id', paramPath)
findMyWay.on('GET', '/api/:resourceType/foo', extraPath)
t.assert.equal(findMyWay.find('GET', '/api/users/admins').handler, staticPath)
t.assert.equal(findMyWay.find('GET', '/api/users/award_winners').handler, staticPath)
t.assert.equal(findMyWay.find('GET', '/api/users/a766c023-34ec-40d2-923c-e8259a28d2c5').handler, paramPath)
t.assert.equal(findMyWay.find('GET', '/api/users/b766c023-34ec-40d2-923c-e8259a28d2c5').handler, paramPath)
findMyWay.lookup({
method: 'GET',
url: '/api/users/admins',
headers: { }
})
findMyWay.lookup({
method: 'GET',
url: '/api/users/award_winners',
headers: { }
})
findMyWay.lookup({
method: 'GET',
url: '/api/users/a766c023-34ec-40d2-923c-e8259a28d2c5',
headers: { }
})
t.assert.equal(staticCounter, 2)
t.assert.equal(paramCounter, 1)
})

79
node_modules/find-my-way/test/issue-20.test.js generated vendored Normal file
View File

@@ -0,0 +1,79 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('Standard case', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be here')
}
})
findMyWay.on('GET', '/a/:param', (req, res, params) => {
t.assert.equal(params.param, 'perfectly-fine-route')
})
findMyWay.lookup({ method: 'GET', url: '/a/perfectly-fine-route', headers: {} }, null)
})
test('Should be 404 / 1', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.ok('Everything good')
}
})
findMyWay.on('GET', '/a/:param', (req, res, params) => {
t.assert.fail('We should not be here')
})
findMyWay.lookup({ method: 'GET', url: '/a', headers: {} }, null)
})
test('Should be 404 / 2', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.ok('Everything good')
}
})
findMyWay.on('GET', '/a/:param', (req, res, params) => {
t.assert.fail('We should not be here')
})
findMyWay.lookup({ method: 'GET', url: '/a-non-existing-route', headers: {} }, null)
})
test('Should be 404 / 3', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.ok('Everything good')
}
})
findMyWay.on('GET', '/a/:param', (req, res, params) => {
t.assert.fail('We should not be here')
})
findMyWay.lookup({ method: 'GET', url: '/a//', headers: {} }, null)
})
test('Should get an empty parameter', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('We should not be here')
}
})
findMyWay.on('GET', '/a/:param', (req, res, params) => {
t.assert.equal(params.param, '')
})
findMyWay.lookup({ method: 'GET', url: '/a/', headers: {} }, null)
})

121
node_modules/find-my-way/test/issue-206.test.js generated vendored Normal file
View File

@@ -0,0 +1,121 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
test('Decode the URL before the routing', t => {
t.plan(8)
const findMyWay = FindMyWay()
function space (req, res, params) {}
function percentTwenty (req, res, params) {}
function percentTwentyfive (req, res, params) {}
findMyWay.on('GET', '/static/:pathParam', () => {})
findMyWay.on('GET', '/[...]/a .html', space)
findMyWay.on('GET', '/[...]/a%20.html', percentTwenty)
findMyWay.on('GET', '/[...]/a%2520.html', percentTwentyfive)
t.assert.equal(findMyWay.find('GET', '/[...]/a .html').handler, space)
t.assert.equal(findMyWay.find('GET', '/%5B...%5D/a .html').handler, space)
t.assert.equal(findMyWay.find('GET', '/[...]/a%20.html').handler, space, 'a%20 decode is a ')
t.assert.equal(findMyWay.find('GET', '/%5B...%5D/a%20.html').handler, space, 'a%20 decode is a ')
t.assert.equal(findMyWay.find('GET', '/[...]/a%2520.html').handler, percentTwenty, 'a%2520 decode is a%20')
t.assert.equal(findMyWay.find('GET', '/%5B...%5D/a%252520.html').handler, percentTwentyfive, 'a%252520.html is a%2520')
t.assert.equal(findMyWay.find('GET', '/[...]/a .html'), null, 'double space')
t.assert.equal(findMyWay.find('GET', '/static/%25E0%A4%A'), null, 'invalid encoded path param')
})
test('double encoding', t => {
t.plan(8)
const findMyWay = FindMyWay()
function pathParam (req, res, params) {
t.assert.deepEqual(params, this.expect, 'path param')
t.assert.deepEqual(pathParam, this.handler, 'match handler')
}
function regexPathParam (req, res, params) {
t.assert.deepEqual(params, this.expect, 'regex param')
t.assert.deepEqual(regexPathParam, this.handler, 'match handler')
}
function wildcard (req, res, params) {
t.assert.deepEqual(params, this.expect, 'wildcard param')
t.assert.deepEqual(wildcard, this.handler, 'match handler')
}
findMyWay.on('GET', '/:pathParam', pathParam)
findMyWay.on('GET', '/reg/:regExeParam(^.*$)', regexPathParam)
findMyWay.on('GET', '/wild/*', wildcard)
findMyWay.lookup(get('/' + doubleEncode('reg/hash# .png')), null,
{ expect: { pathParam: singleEncode('reg/hash# .png') }, handler: pathParam }
)
findMyWay.lookup(get('/' + doubleEncode('special # $ & + , / : ; = ? @')), null,
{ expect: { pathParam: singleEncode('special # $ & + , / : ; = ? @') }, handler: pathParam }
)
findMyWay.lookup(get('/reg/' + doubleEncode('hash# .png')), null,
{ expect: { regExeParam: singleEncode('hash# .png') }, handler: regexPathParam }
)
findMyWay.lookup(get('/wild/' + doubleEncode('mail@mail.it')), null,
{ expect: { '*': singleEncode('mail@mail.it') }, handler: wildcard }
)
function doubleEncode (str) {
return encodeURIComponent(encodeURIComponent(str))
}
function singleEncode (str) {
return encodeURIComponent(str)
}
})
test('Special chars on path parameter', t => {
t.plan(10)
const findMyWay = FindMyWay()
function pathParam (req, res, params) {
t.assert.deepEqual(params, this.expect, 'path param')
t.assert.deepEqual(pathParam, this.handler, 'match handler')
}
function regexPathParam (req, res, params) {
t.assert.deepEqual(params, this.expect, 'regex param')
t.assert.deepEqual(regexPathParam, this.handler, 'match handler')
}
function staticEncoded (req, res, params) {
t.assert.deepEqual(params, this.expect, 'static match')
t.assert.deepEqual(staticEncoded, this.handler, 'match handler')
}
findMyWay.on('GET', '/:pathParam', pathParam)
findMyWay.on('GET', '/reg/:regExeParam(^\\d+) .png', regexPathParam)
findMyWay.on('GET', '/[...]/a%2520.html', staticEncoded)
findMyWay.lookup(get('/%5B...%5D/a%252520.html'), null, { expect: {}, handler: staticEncoded })
findMyWay.lookup(get('/[...].html'), null, { expect: { pathParam: '[...].html' }, handler: pathParam })
findMyWay.lookup(get('/reg/123 .png'), null, { expect: { regExeParam: '123' }, handler: regexPathParam })
findMyWay.lookup(get('/reg%2F123 .png'), null, { expect: { pathParam: 'reg/123 .png' }, handler: pathParam }) // en encoded / is considered a parameter
findMyWay.lookup(get('/reg/123%20.png'), null, { expect: { regExeParam: '123' }, handler: regexPathParam })
})
test('Multi parametric route with encoded colon separator', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/:param(.*)::suffix', (req, res, params) => {
t.assert.equal(params.param, 'foo-bar')
})
findMyWay.lookup({ method: 'GET', url: '/foo-bar%3Asuffix', headers: {} }, null)
})
function get (url) {
return { method: 'GET', url, headers: {} }
}
// http://localhost:3000/parameter with / in it
// http://localhost:3000/parameter%20with%20%2F%20in%20it
// http://localhost:3000/parameter with %252F in it

50
node_modules/find-my-way/test/issue-221.test.js generated vendored Normal file
View File

@@ -0,0 +1,50 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
test('Should return correct param after switching from static route', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/prefix-:id', () => {})
findMyWay.on('GET', '/prefix-111', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/prefix-1111').params, { id: '1111' })
})
test('Should return correct param after switching from static route', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/prefix-111', () => {})
findMyWay.on('GET', '/prefix-:id/hello', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/prefix-1111/hello').params, { id: '1111' })
})
test('Should return correct param after switching from parametric route', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/prefix-111', () => {})
findMyWay.on('GET', '/prefix-:id/hello', () => {})
findMyWay.on('GET', '/:id', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/prefix-1111-hello').params, { id: 'prefix-1111-hello' })
})
test('Should return correct params after switching from parametric route', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test/:param1/test/:param2/prefix-111', () => {})
findMyWay.on('GET', '/test/:param1/test/:param2/prefix-:id/hello', () => {})
findMyWay.on('GET', '/test/:param1/test/:param2/:id', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/test/value1/test/value2/prefix-1111-hello').params, {
param1: 'value1',
param2: 'value2',
id: 'prefix-1111-hello'
})
})

94
node_modules/find-my-way/test/issue-234.test.js generated vendored Normal file
View File

@@ -0,0 +1,94 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
test('Match static url without encoding option', t => {
t.plan(2)
const findMyWay = FindMyWay()
const handler = () => {}
findMyWay.on('GET', '/🍌', handler)
t.assert.deepEqual(findMyWay.find('GET', '/🍌').handler, handler)
t.assert.deepEqual(findMyWay.find('GET', '/%F0%9F%8D%8C').handler, handler)
})
test('Match parametric url with encoding option', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/🍌/:param', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/🍌/@').params, { param: '@' })
t.assert.deepEqual(findMyWay.find('GET', '/%F0%9F%8D%8C/@').params, { param: '@' })
})
test('Match encoded parametric url with encoding option', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/🍌/:param', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/🍌/%23').params, { param: '#' })
t.assert.deepEqual(findMyWay.find('GET', '/%F0%9F%8D%8C/%23').params, { param: '#' })
})
test('Decode url components', t => {
t.plan(3)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:param1/:param2', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/foo%23bar/foo%23bar').params, { param1: 'foo#bar', param2: 'foo#bar' })
t.assert.deepEqual(findMyWay.find('GET', '/%F0%9F%8D%8C/%F0%9F%8D%8C').params, { param1: '🍌', param2: '🍌' })
t.assert.deepEqual(findMyWay.find('GET', '/%F0%9F%8D%8C/foo%23bar').params, { param1: '🍌', param2: 'foo#bar' })
})
test('Decode url components', t => {
t.plan(5)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/foo🍌bar/:param1/:param2', () => {})
findMyWay.on('GET', '/user/:id', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/foo%F0%9F%8D%8Cbar/foo%23bar/foo%23bar').params, { param1: 'foo#bar', param2: 'foo#bar' })
t.assert.deepEqual(findMyWay.find('GET', '/user/maintainer+tomas').params, { id: 'maintainer+tomas' })
t.assert.deepEqual(findMyWay.find('GET', '/user/maintainer%2Btomas').params, { id: 'maintainer+tomas' })
t.assert.deepEqual(findMyWay.find('GET', '/user/maintainer%20tomas').params, { id: 'maintainer tomas' })
t.assert.deepEqual(findMyWay.find('GET', '/user/maintainer%252Btomas').params, { id: 'maintainer%2Btomas' })
})
test('Decode url components', t => {
t.plan(18)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:param1', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/foo%23bar').params, { param1: 'foo#bar' })
t.assert.deepEqual(findMyWay.find('GET', '/foo%24bar').params, { param1: 'foo$bar' })
t.assert.deepEqual(findMyWay.find('GET', '/foo%26bar').params, { param1: 'foo&bar' })
t.assert.deepEqual(findMyWay.find('GET', '/foo%2bbar').params, { param1: 'foo+bar' })
t.assert.deepEqual(findMyWay.find('GET', '/foo%2Bbar').params, { param1: 'foo+bar' })
t.assert.deepEqual(findMyWay.find('GET', '/foo%2cbar').params, { param1: 'foo,bar' })
t.assert.deepEqual(findMyWay.find('GET', '/foo%2Cbar').params, { param1: 'foo,bar' })
t.assert.deepEqual(findMyWay.find('GET', '/foo%2fbar').params, { param1: 'foo/bar' })
t.assert.deepEqual(findMyWay.find('GET', '/foo%2Fbar').params, { param1: 'foo/bar' })
t.assert.deepEqual(findMyWay.find('GET', '/foo%3abar').params, { param1: 'foo:bar' })
t.assert.deepEqual(findMyWay.find('GET', '/foo%3Abar').params, { param1: 'foo:bar' })
t.assert.deepEqual(findMyWay.find('GET', '/foo%3bbar').params, { param1: 'foo;bar' })
t.assert.deepEqual(findMyWay.find('GET', '/foo%3Bbar').params, { param1: 'foo;bar' })
t.assert.deepEqual(findMyWay.find('GET', '/foo%3dbar').params, { param1: 'foo=bar' })
t.assert.deepEqual(findMyWay.find('GET', '/foo%3Dbar').params, { param1: 'foo=bar' })
t.assert.deepEqual(findMyWay.find('GET', '/foo%3fbar').params, { param1: 'foo?bar' })
t.assert.deepEqual(findMyWay.find('GET', '/foo%3Fbar').params, { param1: 'foo?bar' })
t.assert.deepEqual(findMyWay.find('GET', '/foo%40bar').params, { param1: 'foo@bar' })
})

119
node_modules/find-my-way/test/issue-238.test.js generated vendored Normal file
View File

@@ -0,0 +1,119 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('Multi-parametric tricky path', t => {
t.plan(6)
const findMyWay = FindMyWay({
defaultRoute: () => t.assert.fail('Should not be defaultRoute')
})
findMyWay.on('GET', '/:param1-static-:param2', () => {})
t.assert.deepEqual(
findMyWay.find('GET', '/param1-static-param2', {}).params,
{ param1: 'param1', param2: 'param2' }
)
t.assert.deepEqual(
findMyWay.find('GET', '/param1.1-param1.2-static-param2.1-param2.2', {}).params,
{ param1: 'param1.1-param1.2', param2: 'param2.1-param2.2' }
)
t.assert.deepEqual(
findMyWay.find('GET', '/param1-1-param1-2-static-param2-1-param2-2', {}).params,
{ param1: 'param1-1-param1-2', param2: 'param2-1-param2-2' }
)
t.assert.deepEqual(
findMyWay.find('GET', '/static-static-static', {}).params,
{ param1: 'static', param2: 'static' }
)
t.assert.deepEqual(
findMyWay.find('GET', '/static-static-static-static', {}).params,
{ param1: 'static', param2: 'static-static' }
)
t.assert.deepEqual(
findMyWay.find('GET', '/static-static1-static-static', {}).params,
{ param1: 'static-static1', param2: 'static' }
)
})
test('Multi-parametric nodes with different static ending 1', t => {
t.plan(4)
const findMyWay = FindMyWay({
defaultRoute: () => t.assert.fail('Should not be defaultRoute')
})
const paramHandler = () => {}
const multiParamHandler = () => {}
findMyWay.on('GET', '/v1/foo/:code', paramHandler)
findMyWay.on('GET', '/v1/foo/:code.png', multiParamHandler)
t.assert.deepEqual(findMyWay.find('GET', '/v1/foo/hello', {}).handler, paramHandler)
t.assert.deepEqual(findMyWay.find('GET', '/v1/foo/hello', {}).params, { code: 'hello' })
t.assert.deepEqual(findMyWay.find('GET', '/v1/foo/hello.png', {}).handler, multiParamHandler)
t.assert.deepEqual(findMyWay.find('GET', '/v1/foo/hello.png', {}).params, { code: 'hello' })
})
test('Multi-parametric nodes with different static ending 2', t => {
t.plan(4)
const findMyWay = FindMyWay({
defaultRoute: () => t.assert.fail('Should not be defaultRoute')
})
const jpgHandler = () => {}
const pngHandler = () => {}
findMyWay.on('GET', '/v1/foo/:code.jpg', jpgHandler)
findMyWay.on('GET', '/v1/foo/:code.png', pngHandler)
t.assert.deepEqual(findMyWay.find('GET', '/v1/foo/hello.jpg', {}).handler, jpgHandler)
t.assert.deepEqual(findMyWay.find('GET', '/v1/foo/hello.jpg', {}).params, { code: 'hello' })
t.assert.deepEqual(findMyWay.find('GET', '/v1/foo/hello.png', {}).handler, pngHandler)
t.assert.deepEqual(findMyWay.find('GET', '/v1/foo/hello.png', {}).params, { code: 'hello' })
})
test('Multi-parametric nodes with different static ending 3', t => {
t.plan(4)
const findMyWay = FindMyWay({
defaultRoute: () => t.assert.fail('Should not be defaultRoute')
})
const jpgHandler = () => {}
const pngHandler = () => {}
findMyWay.on('GET', '/v1/foo/:code.jpg/bar', jpgHandler)
findMyWay.on('GET', '/v1/foo/:code.png/bar', pngHandler)
t.assert.deepEqual(findMyWay.find('GET', '/v1/foo/hello.jpg/bar', {}).handler, jpgHandler)
t.assert.deepEqual(findMyWay.find('GET', '/v1/foo/hello.jpg/bar', {}).params, { code: 'hello' })
t.assert.deepEqual(findMyWay.find('GET', '/v1/foo/hello.png/bar', {}).handler, pngHandler)
t.assert.deepEqual(findMyWay.find('GET', '/v1/foo/hello.png/bar', {}).params, { code: 'hello' })
})
test('Multi-parametric nodes with different static ending 4', t => {
t.plan(6)
const findMyWay = FindMyWay({
defaultRoute: () => t.assert.fail('Should not be defaultRoute')
})
const handler = () => {}
const jpgHandler = () => {}
const pngHandler = () => {}
findMyWay.on('GET', '/v1/foo/:code/bar', handler)
findMyWay.on('GET', '/v1/foo/:code.jpg/bar', jpgHandler)
findMyWay.on('GET', '/v1/foo/:code.png/bar', pngHandler)
t.assert.deepEqual(findMyWay.find('GET', '/v1/foo/hello/bar', {}).handler, handler)
t.assert.deepEqual(findMyWay.find('GET', '/v1/foo/hello/bar', {}).params, { code: 'hello' })
t.assert.deepEqual(findMyWay.find('GET', '/v1/foo/hello.jpg/bar', {}).handler, jpgHandler)
t.assert.deepEqual(findMyWay.find('GET', '/v1/foo/hello.jpg/bar', {}).params, { code: 'hello' })
t.assert.deepEqual(findMyWay.find('GET', '/v1/foo/hello.png/bar', {}).handler, pngHandler)
t.assert.deepEqual(findMyWay.find('GET', '/v1/foo/hello.png/bar', {}).params, { code: 'hello' })
})

30
node_modules/find-my-way/test/issue-240.test.js generated vendored Normal file
View File

@@ -0,0 +1,30 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('issue-240: .find matching', (t) => {
t.plan(14)
const findMyWay = FindMyWay({ ignoreDuplicateSlashes: true })
const fixedPath = function staticPath () {}
const varPath = function parameterPath () {}
findMyWay.on('GET', '/a/b', fixedPath)
findMyWay.on('GET', '/a/:pam/c', varPath)
t.assert.equal(findMyWay.find('GET', '/a/b').handler, fixedPath)
t.assert.equal(findMyWay.find('GET', '/a//b').handler, fixedPath)
t.assert.equal(findMyWay.find('GET', '/a/b/c').handler, varPath)
t.assert.equal(findMyWay.find('GET', '/a//b/c').handler, varPath)
t.assert.equal(findMyWay.find('GET', '/a///b/c').handler, varPath)
t.assert.equal(findMyWay.find('GET', '/a//b//c').handler, varPath)
t.assert.equal(findMyWay.find('GET', '/a///b///c').handler, varPath)
t.assert.equal(findMyWay.find('GET', '/a/foo/c').handler, varPath)
t.assert.equal(findMyWay.find('GET', '/a//foo/c').handler, varPath)
t.assert.equal(findMyWay.find('GET', '/a///foo/c').handler, varPath)
t.assert.equal(findMyWay.find('GET', '/a//foo//c').handler, varPath)
t.assert.equal(findMyWay.find('GET', '/a///foo///c').handler, varPath)
t.assert.ok(!findMyWay.find('GET', '/a/c'))
t.assert.ok(!findMyWay.find('GET', '/a//c'))
})

32
node_modules/find-my-way/test/issue-241.test.js generated vendored Normal file
View File

@@ -0,0 +1,32 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
test('Double colon and parametric children', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/::articles', () => {})
findMyWay.on('GET', '/:article_name', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/:articles').params, {})
t.assert.deepEqual(findMyWay.find('GET', '/articles_param').params, { article_name: 'articles_param' })
})
test('Double colon and parametric children', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/::test::foo/:param/::articles', () => {})
findMyWay.on('GET', '/::test::foo/:param/:article_name', () => {})
t.assert.deepEqual(
findMyWay.find('GET', '/:test:foo/param_value1/:articles').params,
{ param: 'param_value1' }
)
t.assert.deepEqual(
findMyWay.find('GET', '/:test:foo/param_value2/articles_param').params,
{ param: 'param_value2', article_name: 'articles_param' }
)
})

51
node_modules/find-my-way/test/issue-247.test.js generated vendored Normal file
View File

@@ -0,0 +1,51 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
test('If there are constraints param, router.off method support filter', t => {
t.plan(12)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/a', { constraints: { host: '1' } }, () => {}, { name: 1 })
findMyWay.on('GET', '/a', { constraints: { host: '2', version: '1.0.0' } }, () => {}, { name: 2 })
findMyWay.on('GET', '/a', { constraints: { host: '2', version: '2.0.0' } }, () => {}, { name: 3 })
t.assert.deepEqual(findMyWay.find('GET', '/a', { host: '1' }).store, { name: 1 })
t.assert.deepEqual(findMyWay.find('GET', '/a', { host: '2', version: '1.0.0' }).store, { name: 2 })
t.assert.deepEqual(findMyWay.find('GET', '/a', { host: '2', version: '2.0.0' }).store, { name: 3 })
findMyWay.off('GET', '/a', { host: '1' })
t.assert.deepEqual(findMyWay.find('GET', '/a', { host: '1' }), null)
t.assert.deepEqual(findMyWay.find('GET', '/a', { host: '2', version: '1.0.0' }).store, { name: 2 })
t.assert.deepEqual(findMyWay.find('GET', '/a', { host: '2', version: '2.0.0' }).store, { name: 3 })
findMyWay.off('GET', '/a', { host: '2', version: '1.0.0' })
t.assert.deepEqual(findMyWay.find('GET', '/a', { host: '1' }), null)
t.assert.deepEqual(findMyWay.find('GET', '/a', { host: '2', version: '1.0.0' }), null)
t.assert.deepEqual(findMyWay.find('GET', '/a', { host: '2', version: '2.0.0' }).store, { name: 3 })
findMyWay.off('GET', '/a', { host: '2', version: '2.0.0' })
t.assert.deepEqual(findMyWay.find('GET', '/a', { host: '1' }), null)
t.assert.deepEqual(findMyWay.find('GET', '/a', { host: '2', version: '1.0.0' }), null)
t.assert.deepEqual(findMyWay.find('GET', '/a', { host: '2', version: '2.0.0' }), null)
})
test('If there are no constraints param, router.off method remove all matched router', t => {
t.plan(4)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/a', { constraints: { host: '1' } }, () => {}, { name: 1 })
findMyWay.on('GET', '/a', { constraints: { host: '2' } }, () => {}, { name: 2 })
t.assert.deepEqual(findMyWay.find('GET', '/a', { host: '1' }).store, { name: 1 })
t.assert.deepEqual(findMyWay.find('GET', '/a', { host: '2' }).store, { name: 2 })
findMyWay.off('GET', '/a')
t.assert.deepEqual(findMyWay.find('GET', '/a', { host: '1' }), null)
t.assert.deepEqual(findMyWay.find('GET', '/a', { host: '2' }), null)
})

31
node_modules/find-my-way/test/issue-254.test.js generated vendored Normal file
View File

@@ -0,0 +1,31 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
test('Constraints should not be overrided when multiple router is created', t => {
t.plan(1)
const constraint = {
name: 'secret',
storage: function () {
const secrets = {}
return {
get: (secret) => { return secrets[secret] || null },
set: (secret, store) => { secrets[secret] = store }
}
},
deriveConstraint: (req, ctx) => {
return req.headers['x-secret']
},
validate () { return true }
}
const router1 = FindMyWay({ constraints: { secret: constraint } })
FindMyWay()
router1.on('GET', '/', { constraints: { secret: 'alpha' } }, () => {})
router1.find('GET', '/', { secret: 'alpha' })
t.assert.ok('constraints is not overrided')
})

618
node_modules/find-my-way/test/issue-28.test.js generated vendored Normal file
View File

@@ -0,0 +1,618 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('wildcard (more complex test)', t => {
t.plan(3)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '/test/*', (req, res, params) => {
switch (params['*']) {
case 'hello':
t.assert.ok('correct parameter')
break
case 'hello/world':
t.assert.ok('correct parameter')
break
case '':
t.assert.ok('correct parameter')
break
default:
t.assert.fail('wrong parameter: ' + params['*'])
}
})
findMyWay.lookup(
{ method: 'GET', url: '/test/hello', headers: {} },
null
)
findMyWay.lookup(
{ method: 'GET', url: '/test/hello/world', headers: {} },
null
)
findMyWay.lookup(
{ method: 'GET', url: '/test/', headers: {} },
null
)
})
test('Wildcard inside a node with a static route but different method', t => {
t.plan(2)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '/test/hello', (req, res, params) => {
t.assert.equal(req.method, 'GET')
})
findMyWay.on('OPTIONS', '/*', (req, res, params) => {
t.assert.equal(req.method, 'OPTIONS')
})
findMyWay.lookup(
{ method: 'GET', url: '/test/hello', headers: {} },
null
)
findMyWay.lookup(
{ method: 'OPTIONS', url: '/test/hello', headers: {} },
null
)
})
test('Wildcard inside a node with a static route but different method (more complex case)', t => {
t.plan(5)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
if (req.url === '/test/helloo' && req.method === 'GET') {
t.assert.ok('Everything fine')
} else {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
}
})
findMyWay.on('GET', '/test/hello', (req, res, params) => {
t.assert.equal(req.method, 'GET')
})
findMyWay.on('OPTIONS', '/*', (req, res, params) => {
t.assert.equal(req.method, 'OPTIONS')
})
findMyWay.lookup(
{ method: 'GET', url: '/test/hello', headers: {} },
null
)
findMyWay.lookup(
{ method: 'GET', url: '/test/helloo', headers: {} },
null
)
findMyWay.lookup(
{ method: 'OPTIONS', url: '/test/', headers: {} },
null
)
findMyWay.lookup(
{ method: 'OPTIONS', url: '/test', headers: {} },
null
)
findMyWay.lookup(
{ method: 'OPTIONS', url: '/test/helloo', headers: {} },
null
)
})
test('Wildcard edge cases', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '/test1/foo', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/test2/foo', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('OPTIONS', '/*', (req, res, params) => {
t.assert.equal(params['*'], 'test1/foo')
})
findMyWay.lookup(
{ method: 'OPTIONS', url: '/test1/foo', headers: {} },
null
)
})
test('Wildcard edge cases same method', t => {
t.plan(2)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('OPTIONS', '/test1/foo', (req, res, params) => {
t.assert.equal(req.method, 'OPTIONS')
})
findMyWay.on('OPTIONS', '/test2/foo', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('OPTIONS', '/*', (req, res, params) => {
t.assert.equal(params['*'], 'test/foo')
})
findMyWay.lookup(
{ method: 'OPTIONS', url: '/test1/foo', headers: {} },
null
)
findMyWay.lookup(
{ method: 'OPTIONS', url: '/test/foo', headers: {} },
null
)
})
test('Wildcard and parametric edge cases', t => {
t.plan(3)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('OPTIONS', '/test1/foo', (req, res, params) => {
t.assert.equal(req.method, 'OPTIONS')
})
findMyWay.on('OPTIONS', '/test2/foo', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/:test/foo', (req, res, params) => {
t.assert.equal(params.test, 'example')
})
findMyWay.on('OPTIONS', '/*', (req, res, params) => {
t.assert.equal(params['*'], 'test/foo/hey')
})
findMyWay.lookup(
{ method: 'OPTIONS', url: '/test1/foo', headers: {} },
null
)
findMyWay.lookup(
{ method: 'OPTIONS', url: '/test/foo/hey', headers: {} },
null
)
findMyWay.lookup(
{ method: 'GET', url: '/example/foo', headers: {} },
null
)
})
test('Mixed wildcard and static with same method', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '/foo1/bar1/baz', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo1/bar2/baz', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo2/bar2/baz', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '*', (req, res, params) => {
t.assert.equal(params['*'], '/foo1/bar1/kuux')
})
findMyWay.lookup(
{ method: 'GET', url: '/foo1/bar1/kuux', headers: {} },
null
)
})
test('Nested wildcards case - 1', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo1/*', (req, res, params) => {
t.assert.equal(params['*'], 'bar1/kuux')
})
findMyWay.on('GET', '/foo2/*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.lookup(
{ method: 'GET', url: '/foo1/bar1/kuux', headers: {} },
null
)
})
test('Nested wildcards case - 2', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '/foo2/*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo1/*', (req, res, params) => {
t.assert.equal(params['*'], 'bar1/kuux')
})
findMyWay.on('GET', '*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.lookup(
{ method: 'GET', url: '/foo1/bar1/kuux', headers: {} },
null
)
})
test('Nested wildcards with parametric and static - 1', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo1/*', (req, res, params) => {
t.assert.equal(params['*'], 'bar1/kuux')
})
findMyWay.on('GET', '/foo2/*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo3/:param', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo4/param', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.lookup(
{ method: 'GET', url: '/foo1/bar1/kuux', headers: {} },
null
)
})
test('Nested wildcards with parametric and static - 2', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo1/*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo2/*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo3/:param', (req, res, params) => {
t.assert.equal(params.param, 'bar1')
})
findMyWay.on('GET', '/foo4/param', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.lookup(
{ method: 'GET', url: '/foo3/bar1', headers: {} },
null
)
})
test('Nested wildcards with parametric and static - 3', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo1/*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo2/*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo3/:param', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo4/param', (req, res, params) => {
t.assert.equal(req.url, '/foo4/param')
})
findMyWay.lookup(
{ method: 'GET', url: '/foo4/param', headers: {} },
null
)
})
test('Nested wildcards with parametric and static - 4', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo1/*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo2/*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo3/:param', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo1/param', (req, res, params) => {
t.assert.equal(req.url, '/foo1/param')
})
findMyWay.lookup(
{ method: 'GET', url: '/foo1/param', headers: {} },
null
)
})
test('Nested wildcards with parametric and static - 5', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo1/*', (req, res, params) => {
t.assert.equal(params['*'], 'param/hello/test/long/routee')
})
findMyWay.on('GET', '/foo2/*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo3/:param', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo1/param/hello/test/long/route', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.lookup(
{ method: 'GET', url: '/foo1/param/hello/test/long/routee', headers: {} },
null
)
})
test('Nested wildcards with parametric and static - 6', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '*', (req, res, params) => {
t.assert.equal(params['*'], '/foo4/param/hello/test/long/routee')
})
findMyWay.on('GET', '/foo1/*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo2/*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo3/:param', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo4/param/hello/test/long/route', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.lookup(
{ method: 'GET', url: '/foo4/param/hello/test/long/routee', headers: {} },
null
)
})
test('Nested wildcards with parametric and static - 7', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo1/*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo2/*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo3/:param', (req, res, params) => {
t.assert.equal(params.param, 'hello')
})
findMyWay.on('GET', '/foo3/*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo4/example/hello/test/long/route', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.lookup(
{ method: 'GET', url: '/foo3/hello', headers: {} },
null
)
})
test('Nested wildcards with parametric and static - 8', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo1/*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo2/*', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo3/:param', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo3/*', (req, res, params) => {
t.assert.equal(params['*'], 'hello/world')
})
findMyWay.on('GET', '/foo4/param/hello/test/long/route', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.lookup(
{ method: 'GET', url: '/foo3/hello/world', headers: {} },
null
)
})
test('Wildcard node with constraints', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '*', { constraints: { host: 'fastify.io' } }, (req, res, params) => {
t.assert.equal(params['*'], '/foo1/foo3')
})
findMyWay.on('GET', '/foo1/*', { constraints: { host: 'something-else.io' } }, (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.on('GET', '/foo1/foo2', (req, res, params) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
})
findMyWay.lookup(
{ method: 'GET', url: '/foo1/foo3', headers: { host: 'fastify.io' } },
null
)
})
test('Wildcard must be the last character in the route', (t) => {
t.plan(6)
const expectedError = new Error('Wildcard must be the last character in the route')
const findMyWay = FindMyWay()
t.assert.throws(() => findMyWay.on('GET', '*1', () => {}), expectedError)
t.assert.throws(() => findMyWay.on('GET', '*/', () => {}), expectedError)
t.assert.throws(() => findMyWay.on('GET', '*?', () => {}), expectedError)
t.assert.throws(() => findMyWay.on('GET', '/foo*123', () => {}), expectedError)
t.assert.throws(() => findMyWay.on('GET', '/foo*?', () => {}), expectedError)
t.assert.throws(() => findMyWay.on('GET', '/foo*/', () => {}), expectedError)
})

14
node_modules/find-my-way/test/issue-280.test.js generated vendored Normal file
View File

@@ -0,0 +1,14 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('Wildcard route match when regexp route fails', (t) => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:a(a)', () => {})
findMyWay.on('GET', '/*', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/b', {}).params, { '*': 'b' })
})

37
node_modules/find-my-way/test/issue-285.test.js generated vendored Normal file
View File

@@ -0,0 +1,37 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('Parametric regex match with similar routes', (t) => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:a(a)', () => {})
findMyWay.on('GET', '/:param/static', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/a', {}).params, { a: 'a' })
t.assert.deepEqual(findMyWay.find('GET', '/param/static', {}).params, { param: 'param' })
})
test('Parametric regex match with similar routes', (t) => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:a(a)', () => {})
findMyWay.on('GET', '/:b(b)/static', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/a', {}).params, { a: 'a' })
t.assert.deepEqual(findMyWay.find('GET', '/b/static', {}).params, { b: 'b' })
})
test('Parametric regex match with similar routes', (t) => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:a(a)/static', { constraints: { version: '1.0.0' } }, () => {})
findMyWay.on('GET', '/:b(b)/static', { constraints: { version: '2.0.0' } }, () => {})
t.assert.deepEqual(findMyWay.find('GET', '/a/static', { version: '1.0.0' }).params, { a: 'a' })
t.assert.deepEqual(findMyWay.find('GET', '/b/static', { version: '2.0.0' }).params, { b: 'b' })
})

231
node_modules/find-my-way/test/issue-330.test.js generated vendored Normal file
View File

@@ -0,0 +1,231 @@
const { test } = require('node:test')
const FindMyWay = require('..')
const proxyquire = require('proxyquire')
const HandlerStorage = require('../lib/handler-storage')
const Constrainer = require('../lib/constrainer')
const { safeDecodeURIComponent } = require('../lib/url-sanitizer')
const acceptVersionStrategy = require('../lib/strategies/accept-version')
const httpMethodStrategy = require('../lib/strategies/http-method')
test('FULL_PATH_REGEXP and OPTIONAL_PARAM_REGEXP should be considered safe', (t) => {
t.plan(1)
t.assert.doesNotThrow(() => require('..'))
})
test('should throw an error for unsafe FULL_PATH_REGEXP', (t) => {
t.plan(1)
t.assert.throws(() => proxyquire('..', {
'safe-regex2': () => false
}), new Error('the FULL_PATH_REGEXP is not safe, update this module'))
})
test('Should throw an error for unsafe OPTIONAL_PARAM_REGEXP', (t) => {
t.plan(1)
let callCount = 0
t.assert.throws(() => proxyquire('..', {
'safe-regex2': () => {
return ++callCount < 2
}
}), new Error('the OPTIONAL_PARAM_REGEXP is not safe, update this module'))
})
test('double colon does not define parametric node', (t) => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/::id', () => {})
const route1 = findMyWay.findRoute('GET', '/::id')
t.assert.deepStrictEqual(route1.params, [])
findMyWay.on('GET', '/:foo(\\d+)::bar', () => {})
const route2 = findMyWay.findRoute('GET', '/:foo(\\d+)::bar')
t.assert.deepStrictEqual(route2.params, ['foo'])
})
test('case insensitive static routes', (t) => {
t.plan(3)
const findMyWay = FindMyWay({
caseSensitive: false
})
findMyWay.on('GET', '/foo', () => {})
findMyWay.on('GET', '/foo/bar', () => {})
findMyWay.on('GET', '/foo/bar/baz', () => {})
t.assert.ok(findMyWay.findRoute('GET', '/FoO'))
t.assert.ok(findMyWay.findRoute('GET', '/FOo/Bar'))
t.assert.ok(findMyWay.findRoute('GET', '/fOo/Bar/bAZ'))
})
test('wildcard must be the last character in the route', (t) => {
t.plan(3)
const expectedError = new Error('Wildcard must be the last character in the route')
const findMyWay = FindMyWay()
findMyWay.on('GET', '*', () => {})
t.assert.throws(() => findMyWay.findRoute('GET', '*1'), expectedError)
t.assert.throws(() => findMyWay.findRoute('GET', '*/'), expectedError)
t.assert.throws(() => findMyWay.findRoute('GET', '*?'), expectedError)
})
test('does not find the route if maxParamLength is exceeded', t => {
t.plan(2)
const findMyWay = FindMyWay({
maxParamLength: 2
})
findMyWay.on('GET', '/:id(\\d+)', () => {})
t.assert.equal(findMyWay.find('GET', '/123'), null)
t.assert.ok(findMyWay.find('GET', '/12'))
})
test('Should check if a regex is safe to use', (t) => {
t.plan(1)
const findMyWay = FindMyWay()
// we must pass a safe regex to register the route
// findRoute will still throws the expected assertion error if we try to access it with unsafe reggex
findMyWay.on('GET', '/test/:id(\\d+)', () => {})
const unSafeRegex = /(x+x+)+y/
t.assert.throws(() => findMyWay.findRoute('GET', `/test/:id(${unSafeRegex.toString()})`), {
message: "The regex '(/(x+x+)+y/)' is not safe!"
})
})
test('Disable safe regex check', (t) => {
t.plan(1)
const findMyWay = FindMyWay({ allowUnsafeRegex: true })
const unSafeRegex = /(x+x+)+y/
findMyWay.on('GET', `/test2/:id(${unSafeRegex.toString()})`, () => {})
t.assert.doesNotThrow(() => findMyWay.findRoute('GET', `/test2/:id(${unSafeRegex.toString()})`))
})
test('throws error if no strategy registered for constraint key', (t) => {
t.plan(2)
const constrainer = new Constrainer()
const error = new Error('No strategy registered for constraint key invalid-constraint')
t.assert.throws(() => constrainer.newStoreForConstraint('invalid-constraint'), error)
t.assert.throws(() => constrainer.validateConstraints({ 'invalid-constraint': 'foo' }), error)
})
test('throws error if pass an undefined constraint value', (t) => {
t.plan(1)
const constrainer = new Constrainer()
const error = new Error('Can\'t pass an undefined constraint value, must pass null or no key at all')
t.assert.throws(() => constrainer.validateConstraints({ key: undefined }), error)
})
test('Constrainer.noteUsage', (t) => {
t.plan(3)
const constrainer = new Constrainer()
t.assert.equal(constrainer.strategiesInUse.size, 0)
constrainer.noteUsage()
t.assert.equal(constrainer.strategiesInUse.size, 0)
constrainer.noteUsage({ host: 'fastify.io' })
t.assert.equal(constrainer.strategiesInUse.size, 1)
})
test('Cannot derive constraints without active strategies.', (t) => {
t.plan(1)
const constrainer = new Constrainer()
const before = constrainer.deriveSyncConstraints
constrainer._buildDeriveConstraints()
t.assert.deepEqual(constrainer.deriveSyncConstraints, before)
})
test('getMatchingHandler should return null if not compiled', (t) => {
t.plan(1)
const handlerStorage = new HandlerStorage()
t.assert.equal(handlerStorage.getMatchingHandler({ foo: 'bar' }), null)
})
test('safeDecodeURIComponent should replace %3x to null for every x that is not a valid lowchar', (t) => {
t.plan(1)
t.assert.equal(safeDecodeURIComponent('Hello%3xWorld'), 'HellonullWorld')
})
test('SemVerStore version should be a string', (t) => {
t.plan(1)
const Storage = acceptVersionStrategy.storage
t.assert.throws(() => new Storage().set(1), new TypeError('Version should be a string'))
})
test('SemVerStore.maxMajor should increase automatically', (t) => {
t.plan(3)
const Storage = acceptVersionStrategy.storage
const storage = new Storage()
t.assert.equal(storage.maxMajor, 0)
storage.set('2')
t.assert.equal(storage.maxMajor, 2)
storage.set('1')
t.assert.equal(storage.maxMajor, 2)
})
test('SemVerStore.maxPatches should increase automatically', (t) => {
t.plan(3)
const Storage = acceptVersionStrategy.storage
const storage = new Storage()
storage.set('2.0.0')
t.assert.deepEqual(storage.maxPatches, { '2.0': 0 })
storage.set('2.0.2')
t.assert.deepEqual(storage.maxPatches, { '2.0': 2 })
storage.set('2.0.1')
t.assert.deepEqual(storage.maxPatches, { '2.0': 2 })
})
test('Major version must be a numeric value', t => {
t.plan(1)
const findMyWay = FindMyWay()
t.assert.throws(() => findMyWay.on('GET', '/test', { constraints: { version: 'x' } }, () => {}),
new TypeError('Major version must be a numeric value'))
})
test('httpMethodStrategy storage handles set and get operations correctly', (t) => {
t.plan(2)
const storage = httpMethodStrategy.storage()
t.assert.equal(storage.get('foo'), null)
storage.set('foo', { bar: 'baz' })
t.assert.deepStrictEqual(storage.get('foo'), { bar: 'baz' })
})
test('if buildPrettyMeta argument is undefined, will return an object', (t) => {
t.plan(1)
const findMyWay = FindMyWay()
t.assert.deepEqual(findMyWay.buildPrettyMeta(), {})
})

149
node_modules/find-my-way/test/issue-44.test.js generated vendored Normal file
View File

@@ -0,0 +1,149 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('Parametric and static with shared prefix / 1', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/woo', (req, res, params) => {
t.assert.fail('we should not be here')
})
findMyWay.on('GET', '/:param', (req, res, params) => {
t.assert.equal(params.param, 'winter')
})
findMyWay.lookup({ method: 'GET', url: '/winter', headers: {} }, null)
})
test('Parametric and static with shared prefix / 2', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/woo', (req, res, params) => {
t.assert.ok('we should be here')
})
findMyWay.on('GET', '/:param', (req, res, params) => {
t.assert.fail('we should not be here')
})
findMyWay.lookup({ method: 'GET', url: '/woo', headers: {} }, null)
})
test('Parametric and static with shared prefix (nested)', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.ok('We should be here')
}
})
findMyWay.on('GET', '/woo', (req, res, params) => {
t.assert.fail('we should not be here')
})
findMyWay.on('GET', '/:param', (req, res, params) => {
t.assert.fail('we should not be here')
})
findMyWay.lookup({ method: 'GET', url: '/winter/coming', headers: {} }, null)
})
test('Parametric and static with shared prefix and different suffix', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('We should not be here')
}
})
findMyWay.on('GET', '/example/shared/nested/test', (req, res, params) => {
t.assert.fail('We should not be here')
})
findMyWay.on('GET', '/example/:param/nested/other', (req, res, params) => {
t.assert.ok('We should be here')
})
findMyWay.lookup({ method: 'GET', url: '/example/shared/nested/other', headers: {} }, null)
})
test('Parametric and static with shared prefix (with wildcard)', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/woo', (req, res, params) => {
t.assert.fail('we should not be here')
})
findMyWay.on('GET', '/:param', (req, res, params) => {
t.assert.equal(params.param, 'winter')
})
findMyWay.on('GET', '/*', (req, res, params) => {
t.assert.fail('we should not be here')
})
findMyWay.lookup({ method: 'GET', url: '/winter', headers: {} }, null)
})
test('Parametric and static with shared prefix (nested with wildcard)', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/woo', (req, res, params) => {
t.assert.fail('we should not be here')
})
findMyWay.on('GET', '/:param', (req, res, params) => {
t.assert.fail('we should not be here')
})
findMyWay.on('GET', '/*', (req, res, params) => {
t.assert.equal(params['*'], 'winter/coming')
})
findMyWay.lookup({ method: 'GET', url: '/winter/coming', headers: {} }, null)
})
test('Parametric and static with shared prefix (nested with split)', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here')
}
})
findMyWay.on('GET', '/woo', (req, res, params) => {
t.assert.fail('we should not be here')
})
findMyWay.on('GET', '/:param', (req, res, params) => {
t.assert.equal(params.param, 'winter')
})
findMyWay.on('GET', '/wo', (req, res, params) => {
t.assert.fail('we should not be here')
})
findMyWay.lookup({ method: 'GET', url: '/winter', headers: {} }, null)
})

75
node_modules/find-my-way/test/issue-46.test.js generated vendored Normal file
View File

@@ -0,0 +1,75 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('If the prefixLen is higher than the pathLen we should not save the wildcard child', t => {
t.plan(3)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.get('/static/*', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/static/').params, { '*': '' })
t.assert.deepEqual(findMyWay.find('GET', '/static/hello').params, { '*': 'hello' })
t.assert.deepEqual(findMyWay.find('GET', '/static'), null)
})
test('If the prefixLen is higher than the pathLen we should not save the wildcard child (mixed routes)', t => {
t.plan(3)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.get('/static/*', () => {})
findMyWay.get('/simple', () => {})
findMyWay.get('/simple/:bar', () => {})
findMyWay.get('/hello', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/static/').params, { '*': '' })
t.assert.deepEqual(findMyWay.find('GET', '/static/hello').params, { '*': 'hello' })
t.assert.deepEqual(findMyWay.find('GET', '/static'), null)
})
test('If the prefixLen is higher than the pathLen we should not save the wildcard child (with a root wildcard)', t => {
t.plan(3)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.get('*', () => {})
findMyWay.get('/static/*', () => {})
findMyWay.get('/simple', () => {})
findMyWay.get('/simple/:bar', () => {})
findMyWay.get('/hello', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/static/').params, { '*': '' })
t.assert.deepEqual(findMyWay.find('GET', '/static/hello').params, { '*': 'hello' })
t.assert.deepEqual(findMyWay.find('GET', '/static').params, { '*': '/static' })
})
test('If the prefixLen is higher than the pathLen we should not save the wildcard child (404)', t => {
t.plan(4)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.get('/static/*', () => {})
findMyWay.get('/simple', () => {})
findMyWay.get('/simple/:bar', () => {})
findMyWay.get('/hello', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/stati'), null)
t.assert.deepEqual(findMyWay.find('GET', '/staticc'), null)
t.assert.deepEqual(findMyWay.find('GET', '/stati/hello'), null)
t.assert.deepEqual(findMyWay.find('GET', '/staticc/hello'), null)
})

108
node_modules/find-my-way/test/issue-49.test.js generated vendored Normal file
View File

@@ -0,0 +1,108 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
const noop = () => {}
test('Defining static route after parametric - 1', t => {
t.plan(3)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/static', noop)
findMyWay.on('GET', '/:param', noop)
t.assert.ok(findMyWay.find('GET', '/static'))
t.assert.ok(findMyWay.find('GET', '/para'))
t.assert.ok(findMyWay.find('GET', '/s'))
})
test('Defining static route after parametric - 2', t => {
t.plan(3)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:param', noop)
findMyWay.on('GET', '/static', noop)
t.assert.ok(findMyWay.find('GET', '/static'))
t.assert.ok(findMyWay.find('GET', '/para'))
t.assert.ok(findMyWay.find('GET', '/s'))
})
test('Defining static route after parametric - 3', t => {
t.plan(4)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:param', noop)
findMyWay.on('GET', '/static', noop)
findMyWay.on('GET', '/other', noop)
t.assert.ok(findMyWay.find('GET', '/static'))
t.assert.ok(findMyWay.find('GET', '/para'))
t.assert.ok(findMyWay.find('GET', '/s'))
t.assert.ok(findMyWay.find('GET', '/o'))
})
test('Defining static route after parametric - 4', t => {
t.plan(4)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/static', noop)
findMyWay.on('GET', '/other', noop)
findMyWay.on('GET', '/:param', noop)
t.assert.ok(findMyWay.find('GET', '/static'))
t.assert.ok(findMyWay.find('GET', '/para'))
t.assert.ok(findMyWay.find('GET', '/s'))
t.assert.ok(findMyWay.find('GET', '/o'))
})
test('Defining static route after parametric - 5', t => {
t.plan(4)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/static', noop)
findMyWay.on('GET', '/:param', noop)
findMyWay.on('GET', '/other', noop)
t.assert.ok(findMyWay.find('GET', '/static'))
t.assert.ok(findMyWay.find('GET', '/para'))
t.assert.ok(findMyWay.find('GET', '/s'))
t.assert.ok(findMyWay.find('GET', '/o'))
})
test('Should produce the same tree - 1', t => {
t.plan(1)
const findMyWay1 = FindMyWay()
const findMyWay2 = FindMyWay()
findMyWay1.on('GET', '/static', noop)
findMyWay1.on('GET', '/:param', noop)
findMyWay2.on('GET', '/:param', noop)
findMyWay2.on('GET', '/static', noop)
t.assert.equal(findMyWay1.tree, findMyWay2.tree)
})
test('Should produce the same tree - 2', t => {
t.plan(3)
const findMyWay1 = FindMyWay()
const findMyWay2 = FindMyWay()
const findMyWay3 = FindMyWay()
findMyWay1.on('GET', '/:param', noop)
findMyWay1.on('GET', '/static', noop)
findMyWay1.on('GET', '/other', noop)
findMyWay2.on('GET', '/static', noop)
findMyWay2.on('GET', '/:param', noop)
findMyWay2.on('GET', '/other', noop)
findMyWay3.on('GET', '/static', noop)
findMyWay3.on('GET', '/other', noop)
findMyWay3.on('GET', '/:param', noop)
t.assert.equal(findMyWay1.tree, findMyWay2.tree)
t.assert.equal(findMyWay2.tree, findMyWay3.tree)
t.assert.equal(findMyWay1.tree, findMyWay3.tree)
})

131
node_modules/find-my-way/test/issue-59.test.js generated vendored Normal file
View File

@@ -0,0 +1,131 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
const noop = () => {}
test('single-character prefix', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/b/', noop)
findMyWay.on('GET', '/b/bulk', noop)
t.assert.equal(findMyWay.find('GET', '/bulk'), null)
})
test('multi-character prefix', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/bu/', noop)
findMyWay.on('GET', '/bu/bulk', noop)
t.assert.equal(findMyWay.find('GET', '/bulk'), null)
})
test('static / 1', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/bb/', noop)
findMyWay.on('GET', '/bb/bulk', noop)
t.assert.equal(findMyWay.find('GET', '/bulk'), null)
})
test('static / 2', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/bb/ff/', noop)
findMyWay.on('GET', '/bb/ff/bulk', noop)
t.assert.equal(findMyWay.find('GET', '/bulk'), null)
t.assert.equal(findMyWay.find('GET', '/ff/bulk'), null)
})
test('static / 3', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/bb/ff/', noop)
findMyWay.on('GET', '/bb/ff/bulk', noop)
findMyWay.on('GET', '/bb/ff/gg/bulk', noop)
findMyWay.on('GET', '/bb/ff/bulk/bulk', noop)
t.assert.equal(findMyWay.find('GET', '/bulk'), null)
})
test('with parameter / 1', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:foo/', noop)
findMyWay.on('GET', '/:foo/bulk', noop)
t.assert.equal(findMyWay.find('GET', '/bulk'), null)
})
test('with parameter / 2', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/bb/', noop)
findMyWay.on('GET', '/bb/:foo', noop)
t.assert.equal(findMyWay.find('GET', '/bulk'), null)
})
test('with parameter / 3', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/bb/ff/', noop)
findMyWay.on('GET', '/bb/ff/:foo', noop)
t.assert.equal(findMyWay.find('GET', '/bulk'), null)
})
test('with parameter / 4', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/bb/:foo/', noop)
findMyWay.on('GET', '/bb/:foo/bulk', noop)
t.assert.equal(findMyWay.find('GET', '/bulk'), null)
})
test('with parameter / 5', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/bb/:foo/aa/', noop)
findMyWay.on('GET', '/bb/:foo/aa/bulk', noop)
t.assert.equal(findMyWay.find('GET', '/bulk'), null)
t.assert.equal(findMyWay.find('GET', '/bb/foo/bulk'), null)
})
test('with parameter / 6', t => {
t.plan(3)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/static/:parametric/static/:parametric', noop)
findMyWay.on('GET', '/static/:parametric/static/:parametric/bulk', noop)
t.assert.equal(findMyWay.find('GET', '/bulk'), null)
t.assert.equal(findMyWay.find('GET', '/static/foo/bulk'), null)
t.assert.notEqual(findMyWay.find('GET', '/static/foo/static/bulk'), null)
})
test('wildcard / 1', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/bb/', noop)
findMyWay.on('GET', '/bb/*', noop)
t.assert.equal(findMyWay.find('GET', '/bulk'), null)
})

28
node_modules/find-my-way/test/issue-62.test.js generated vendored Normal file
View File

@@ -0,0 +1,28 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
const noop = function () {}
test('issue-62', (t) => {
t.plan(2)
const findMyWay = FindMyWay({ allowUnsafeRegex: true })
findMyWay.on('GET', '/foo/:id(([a-f0-9]{3},?)+)', noop)
t.assert.ok(!findMyWay.find('GET', '/foo/qwerty'))
t.assert.ok(findMyWay.find('GET', '/foo/bac,1ea'))
})
test('issue-62 - escape chars', (t) => {
const findMyWay = FindMyWay()
t.plan(2)
findMyWay.get('/foo/:param(\\([a-f0-9]{3}\\))', noop)
t.assert.ok(!findMyWay.find('GET', '/foo/abc'))
t.assert.ok(findMyWay.find('GET', '/foo/(abc)', {}))
})

23
node_modules/find-my-way/test/issue-63.test.js generated vendored Normal file
View File

@@ -0,0 +1,23 @@
'use strict'
const { test } = require('node:test')
const factory = require('../')
const noop = function () {}
test('issue-63', (t) => {
t.plan(2)
const fmw = factory()
t.assert.throws(function () {
fmw.on('GET', '/foo/:id(a', noop)
})
try {
fmw.on('GET', '/foo/:id(a', noop)
t.assert.fail('should fail')
} catch (err) {
t.assert.equal(err.message, 'Invalid regexp expression in "/foo/:id(a"')
}
})

50
node_modules/find-my-way/test/issue-67.test.js generated vendored Normal file
View File

@@ -0,0 +1,50 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
const noop = () => {}
test('static routes', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/b/', noop)
findMyWay.on('GET', '/b/bulk', noop)
findMyWay.on('GET', '/b/ulk', noop)
t.assert.equal(findMyWay.find('GET', '/bulk'), null)
})
test('parametric routes', t => {
t.plan(5)
const findMyWay = FindMyWay()
function foo () { }
findMyWay.on('GET', '/foo/:fooParam', foo)
findMyWay.on('GET', '/foo/bar/:barParam', noop)
findMyWay.on('GET', '/foo/search', noop)
findMyWay.on('GET', '/foo/submit', noop)
t.assert.equal(findMyWay.find('GET', '/foo/awesome-parameter').handler, foo)
t.assert.equal(findMyWay.find('GET', '/foo/b-first-character').handler, foo)
t.assert.equal(findMyWay.find('GET', '/foo/s-first-character').handler, foo)
t.assert.equal(findMyWay.find('GET', '/foo/se-prefix').handler, foo)
t.assert.equal(findMyWay.find('GET', '/foo/sx-prefix').handler, foo)
})
test('parametric with common prefix', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', noop)
findMyWay.on('GET', '/:test', (req, res, params) => {
t.assert.deepEqual(
{ test: 'text' },
params
)
})
findMyWay.on('GET', '/text/hello', noop)
findMyWay.lookup({ url: '/text', method: 'GET', headers: {} })
})

19
node_modules/find-my-way/test/issue-93.test.js generated vendored Normal file
View File

@@ -0,0 +1,19 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
const noop = () => {}
test('Should keep semver store when split node', t => {
t.plan(4)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/t1', { constraints: { version: '1.0.0' } }, noop)
findMyWay.on('GET', '/t2', { constraints: { version: '2.1.0' } }, noop)
t.assert.ok(findMyWay.find('GET', '/t1', { version: '1.0.0' }))
t.assert.ok(findMyWay.find('GET', '/t2', { version: '2.x' }))
t.assert.ok(!findMyWay.find('GET', '/t1', { version: '2.x' }))
t.assert.ok(!findMyWay.find('GET', '/t2', { version: '1.0.0' }))
})

29
node_modules/find-my-way/test/lookup-async.test.js generated vendored Normal file
View File

@@ -0,0 +1,29 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
test('should return result in the done callback', t => {
t.plan(2)
const router = FindMyWay()
router.on('GET', '/', () => 'asyncHandlerResult')
router.lookup({ method: 'GET', url: '/' }, null, (err, result) => {
t.assert.equal(err, null)
t.assert.equal(result, 'asyncHandlerResult')
})
})
test('should return an error in the done callback', t => {
t.plan(2)
const router = FindMyWay()
const error = new Error('ASYNC_HANDLER_ERROR')
router.on('GET', '/', () => { throw error })
router.lookup({ method: 'GET', url: '/' }, null, (err, result) => {
t.assert.equal(err, error)
t.assert.equal(result, undefined)
})
})

58
node_modules/find-my-way/test/lookup.test.js generated vendored Normal file
View File

@@ -0,0 +1,58 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
test('lookup calls route handler with no context', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/example', function handle (req, res, params) {
// without context, this will be the result object returned from router.find
t.assert.equal(this.handler, handle)
})
findMyWay.lookup({ method: 'GET', url: '/example', headers: {} }, null)
})
test('lookup calls route handler with context as scope', t => {
t.plan(1)
const findMyWay = FindMyWay()
const ctx = { foo: 'bar' }
findMyWay.on('GET', '/example', function handle (req, res, params) {
t.assert.equal(this, ctx)
})
findMyWay.lookup({ method: 'GET', url: '/example', headers: {} }, null, ctx)
})
test('lookup calls default route handler with no context', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute (req, res) {
// without context, the default route's scope is the router itself
t.assert.equal(this, findMyWay)
}
})
findMyWay.lookup({ method: 'GET', url: '/example', headers: {} }, null)
})
test('lookup calls default route handler with context as scope', t => {
t.plan(1)
const ctx = { foo: 'bar' }
const findMyWay = FindMyWay({
defaultRoute (req, res) {
t.assert.equal(this, ctx)
}
})
findMyWay.lookup({ method: 'GET', url: '/example', headers: {} }, null, ctx)
})

17
node_modules/find-my-way/test/matching-order.test.js generated vendored Normal file
View File

@@ -0,0 +1,17 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
test('Matching order', t => {
t.plan(3)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/foo/bar/static', { constraints: { host: 'test' } }, () => {})
findMyWay.on('GET', '/foo/bar/*', () => {})
findMyWay.on('GET', '/foo/:param/static', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/foo/bar/static', { host: 'test' }).params, {})
t.assert.deepEqual(findMyWay.find('GET', '/foo/bar/static').params, { '*': 'static' })
t.assert.deepEqual(findMyWay.find('GET', '/foo/value/static').params, { param: 'value' })
})

44
node_modules/find-my-way/test/max-param-length.test.js generated vendored Normal file
View File

@@ -0,0 +1,44 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('maxParamLength default value is 500', t => {
t.plan(1)
const findMyWay = FindMyWay()
t.assert.equal(findMyWay.maxParamLength, 100)
})
test('maxParamLength should set the maximum length for a parametric route', t => {
t.plan(1)
const findMyWay = FindMyWay({ maxParamLength: 10 })
findMyWay.on('GET', '/test/:param', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/test/123456789abcd'), null)
})
test('maxParamLength should set the maximum length for a parametric (regex) route', t => {
t.plan(1)
const findMyWay = FindMyWay({ maxParamLength: 10 })
findMyWay.on('GET', '/test/:param(^\\d+$)', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/test/123456789abcd'), null)
})
test('maxParamLength should set the maximum length for a parametric (multi) route', t => {
t.plan(1)
const findMyWay = FindMyWay({ maxParamLength: 10 })
findMyWay.on('GET', '/test/:param-bar', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/test/123456789abcd'), null)
})
test('maxParamLength should set the maximum length for a parametric (regex with suffix) route', t => {
t.plan(1)
const findMyWay = FindMyWay({ maxParamLength: 10 })
findMyWay.on('GET', '/test/:param(^\\w{3})bar', () => {})
t.assert.deepEqual(findMyWay.find('GET', '/test/123456789abcd'), null)
})

830
node_modules/find-my-way/test/methods.test.js generated vendored Normal file
View File

@@ -0,0 +1,830 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('the router is an object with methods', t => {
t.plan(4)
const findMyWay = FindMyWay()
t.assert.equal(typeof findMyWay.on, 'function')
t.assert.equal(typeof findMyWay.off, 'function')
t.assert.equal(typeof findMyWay.lookup, 'function')
t.assert.equal(typeof findMyWay.find, 'function')
})
test('on throws for invalid method', t => {
t.plan(1)
const findMyWay = FindMyWay()
t.assert.throws(() => {
findMyWay.on('INVALID', '/a/b')
})
})
test('on throws for invalid path', t => {
t.plan(3)
const findMyWay = FindMyWay()
// Non string
t.assert.throws(() => {
findMyWay.on('GET', 1)
})
// Empty
t.assert.throws(() => {
findMyWay.on('GET', '')
})
// Doesn't start with / or *
t.assert.throws(() => {
findMyWay.on('GET', 'invalid')
})
})
test('register a route', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {
t.assert.ok('inside the handler')
})
findMyWay.lookup({ method: 'GET', url: '/test', headers: {} }, null)
})
test('register a route with multiple methods', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on(['GET', 'POST'], '/test', () => {
t.assert.ok('inside the handler')
})
findMyWay.lookup({ method: 'GET', url: '/test', headers: {} }, null)
findMyWay.lookup({ method: 'POST', url: '/test', headers: {} }, null)
})
test('does not register /test/*/ when ignoreTrailingSlash is true', t => {
t.plan(1)
const findMyWay = FindMyWay({
ignoreTrailingSlash: true
})
findMyWay.on('GET', '/test/*', () => {})
t.assert.equal(
findMyWay.routes.filter((r) => r.path.includes('/test')).length,
1
)
})
test('off throws for invalid method', t => {
t.plan(1)
const findMyWay = FindMyWay()
t.assert.throws(() => {
findMyWay.off('INVALID', '/a/b')
})
})
test('off throws for invalid path', t => {
t.plan(3)
const findMyWay = FindMyWay()
// Non string
t.assert.throws(() => {
findMyWay.off('GET', 1)
})
// Empty
t.assert.throws(() => {
findMyWay.off('GET', '')
})
// Doesn't start with / or *
t.assert.throws(() => {
findMyWay.off('GET', 'invalid')
})
})
test('off with nested wildcards with parametric and static', t => {
t.plan(3)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('we should not be here, the url is: ' + req.url)
}
})
findMyWay.on('GET', '*', (req, res, params) => {
t.assert.equal(params['*'], '/foo2/first/second')
})
findMyWay.on('GET', '/foo1/*', () => {})
findMyWay.on('GET', '/foo2/*', () => {})
findMyWay.on('GET', '/foo3/:param', () => {})
findMyWay.on('GET', '/foo3/*', () => {})
findMyWay.on('GET', '/foo4/param/hello/test/long/route', () => {})
const route1 = findMyWay.find('GET', '/foo3/first/second')
t.assert.equal(route1.params['*'], 'first/second')
findMyWay.off('GET', '/foo3/*')
const route2 = findMyWay.find('GET', '/foo3/first/second')
t.assert.equal(route2.params['*'], '/foo3/first/second')
findMyWay.off('GET', '/foo2/*')
findMyWay.lookup(
{ method: 'GET', url: '/foo2/first/second', headers: {} },
null
)
})
test('off removes all routes when ignoreTrailingSlash is true', t => {
t.plan(6)
const findMyWay = FindMyWay({
ignoreTrailingSlash: true
})
findMyWay.on('GET', '/test1/', () => {})
t.assert.equal(findMyWay.routes.length, 1)
findMyWay.on('GET', '/test2', () => {})
t.assert.equal(findMyWay.routes.length, 2)
findMyWay.off('GET', '/test1')
t.assert.equal(findMyWay.routes.length, 1)
t.assert.equal(
findMyWay.routes.filter((r) => r.path === '/test2').length,
1
)
t.assert.equal(
findMyWay.routes.filter((r) => r.path === '/test2/').length,
0
)
findMyWay.off('GET', '/test2/')
t.assert.equal(findMyWay.routes.length, 0)
})
test('off removes all routes when ignoreDuplicateSlashes is true', t => {
t.plan(6)
const findMyWay = FindMyWay({
ignoreDuplicateSlashes: true
})
findMyWay.on('GET', '//test1', () => {})
t.assert.equal(findMyWay.routes.length, 1)
findMyWay.on('GET', '/test2', () => {})
t.assert.equal(findMyWay.routes.length, 2)
findMyWay.off('GET', '/test1')
t.assert.equal(findMyWay.routes.length, 1)
t.assert.equal(
findMyWay.routes.filter((r) => r.path === '/test2').length,
1
)
t.assert.equal(
findMyWay.routes.filter((r) => r.path === '//test2').length,
0
)
findMyWay.off('GET', '//test2')
t.assert.equal(findMyWay.routes.length, 0)
})
test('deregister a route without children', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/a', () => {})
findMyWay.on('GET', '/a/b', () => {})
findMyWay.off('GET', '/a/b')
t.assert.ok(findMyWay.find('GET', '/a'))
t.assert.ok(!findMyWay.find('GET', '/a/b'))
})
test('deregister a route with children', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/a', () => {})
findMyWay.on('GET', '/a/b', () => {})
findMyWay.off('GET', '/a')
t.assert.ok(!findMyWay.find('GET', '/a'))
t.assert.ok(findMyWay.find('GET', '/a/b'))
})
test('deregister a route by method', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on(['GET', 'POST'], '/a', () => {})
findMyWay.off('GET', '/a')
t.assert.ok(!findMyWay.find('GET', '/a'))
t.assert.ok(findMyWay.find('POST', '/a'))
})
test('deregister a route with multiple methods', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on(['GET', 'POST'], '/a', () => {})
findMyWay.off(['GET', 'POST'], '/a')
t.assert.ok(!findMyWay.find('GET', '/a'))
t.assert.ok(!findMyWay.find('POST', '/a'))
})
test('reset a router', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on(['GET', 'POST'], '/a', () => {})
findMyWay.reset()
t.assert.ok(!findMyWay.find('GET', '/a'))
t.assert.ok(!findMyWay.find('POST', '/a'))
})
test('default route', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: () => {
t.assert.ok('inside the default route')
}
})
findMyWay.lookup({ method: 'GET', url: '/test', headers: {} }, null)
})
test('parametric route', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test/:id', (req, res, params) => {
t.assert.equal(params.id, 'hello')
})
findMyWay.lookup({ method: 'GET', url: '/test/hello', headers: {} }, null)
})
test('multiple parametric route', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test/:id', (req, res, params) => {
t.assert.equal(params.id, 'hello')
})
findMyWay.on('GET', '/other-test/:id', (req, res, params) => {
t.assert.equal(params.id, 'world')
})
findMyWay.lookup({ method: 'GET', url: '/test/hello', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/other-test/world', headers: {} }, null)
})
test('multiple parametric route with the same prefix', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test/:id', (req, res, params) => {
t.assert.equal(params.id, 'hello')
})
findMyWay.on('GET', '/test/:id/world', (req, res, params) => {
t.assert.equal(params.id, 'world')
})
findMyWay.lookup({ method: 'GET', url: '/test/hello', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/world/world', headers: {} }, null)
})
test('nested parametric route', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test/:hello/test/:world', (req, res, params) => {
t.assert.equal(params.hello, 'hello')
t.assert.equal(params.world, 'world')
})
findMyWay.lookup({ method: 'GET', url: '/test/hello/test/world', headers: {} }, null)
})
test('nested parametric route with same prefix', t => {
t.plan(3)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', (req, res, params) => {
t.assert.ok('inside route')
})
findMyWay.on('GET', '/test/:hello/test/:world', (req, res, params) => {
t.assert.equal(params.hello, 'hello')
t.assert.equal(params.world, 'world')
})
findMyWay.lookup({ method: 'GET', url: '/test', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/hello/test/world', headers: {} }, null)
})
test('long route', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/abc/def/ghi/lmn/opq/rst/uvz', (req, res, params) => {
t.assert.ok('inside long path')
})
findMyWay.lookup({ method: 'GET', url: '/abc/def/ghi/lmn/opq/rst/uvz', headers: {} }, null)
})
test('long parametric route', t => {
t.plan(3)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/abc/:def/ghi/:lmn/opq/:rst/uvz', (req, res, params) => {
t.assert.equal(params.def, 'def')
t.assert.equal(params.lmn, 'lmn')
t.assert.equal(params.rst, 'rst')
})
findMyWay.lookup({ method: 'GET', url: '/abc/def/ghi/lmn/opq/rst/uvz', headers: {} }, null)
})
test('long parametric route with common prefix', t => {
t.plan(9)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', (req, res, params) => {
throw new Error('I shoul not be here')
})
findMyWay.on('GET', '/abc', (req, res, params) => {
throw new Error('I shoul not be here')
})
findMyWay.on('GET', '/abc/:def', (req, res, params) => {
t.assert.equal(params.def, 'def')
})
findMyWay.on('GET', '/abc/:def/ghi/:lmn', (req, res, params) => {
t.assert.equal(params.def, 'def')
t.assert.equal(params.lmn, 'lmn')
})
findMyWay.on('GET', '/abc/:def/ghi/:lmn/opq/:rst', (req, res, params) => {
t.assert.equal(params.def, 'def')
t.assert.equal(params.lmn, 'lmn')
t.assert.equal(params.rst, 'rst')
})
findMyWay.on('GET', '/abc/:def/ghi/:lmn/opq/:rst/uvz', (req, res, params) => {
t.assert.equal(params.def, 'def')
t.assert.equal(params.lmn, 'lmn')
t.assert.equal(params.rst, 'rst')
})
findMyWay.lookup({ method: 'GET', url: '/abc/def', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/abc/def/ghi/lmn', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/abc/def/ghi/lmn/opq/rst', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/abc/def/ghi/lmn/opq/rst/uvz', headers: {} }, null)
})
test('common prefix', t => {
t.plan(4)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/f', (req, res, params) => {
t.assert.ok('inside route')
})
findMyWay.on('GET', '/ff', (req, res, params) => {
t.assert.ok('inside route')
})
findMyWay.on('GET', '/ffa', (req, res, params) => {
t.assert.ok('inside route')
})
findMyWay.on('GET', '/ffb', (req, res, params) => {
t.assert.ok('inside route')
})
findMyWay.lookup({ method: 'GET', url: '/f', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/ff', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/ffa', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/ffb', headers: {} }, null)
})
test('wildcard', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test/*', (req, res, params) => {
t.assert.equal(params['*'], 'hello')
})
findMyWay.lookup(
{ method: 'GET', url: '/test/hello', headers: {} },
null
)
})
test('catch all wildcard', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '*', (req, res, params) => {
t.assert.equal(params['*'], '/test/hello')
})
findMyWay.lookup(
{ method: 'GET', url: '/test/hello', headers: {} },
null
)
})
test('find should return the route', t => {
t.plan(1)
const findMyWay = FindMyWay()
const fn = () => {}
findMyWay.on('GET', '/test', fn)
t.assert.deepEqual(
findMyWay.find('GET', '/test'),
{ handler: fn, params: {}, store: null, searchParams: {} }
)
})
test('find should return the route with params', t => {
t.plan(1)
const findMyWay = FindMyWay()
const fn = () => {}
findMyWay.on('GET', '/test/:id', fn)
t.assert.deepEqual(
findMyWay.find('GET', '/test/hello'),
{ handler: fn, params: { id: 'hello' }, store: null, searchParams: {} }
)
})
test('find should return a null handler if the route does not exist', t => {
t.plan(1)
const findMyWay = FindMyWay()
t.assert.deepEqual(
findMyWay.find('GET', '/test'),
null
)
})
test('should decode the uri - parametric', t => {
t.plan(1)
const findMyWay = FindMyWay()
const fn = () => {}
findMyWay.on('GET', '/test/:id', fn)
t.assert.deepEqual(
findMyWay.find('GET', '/test/he%2Fllo'),
{ handler: fn, params: { id: 'he/llo' }, store: null, searchParams: {} }
)
})
test('should decode the uri - wildcard', t => {
t.plan(1)
const findMyWay = FindMyWay()
const fn = () => {}
findMyWay.on('GET', '/test/*', fn)
t.assert.deepEqual(
findMyWay.find('GET', '/test/he%2Fllo'),
{ handler: fn, params: { '*': 'he/llo' }, store: null, searchParams: {} }
)
})
test('safe decodeURIComponent', t => {
t.plan(1)
const findMyWay = FindMyWay()
const fn = () => {}
findMyWay.on('GET', '/test/:id', fn)
t.assert.deepEqual(
findMyWay.find('GET', '/test/hel%"Flo'),
null
)
})
test('safe decodeURIComponent - nested route', t => {
t.plan(1)
const findMyWay = FindMyWay()
const fn = () => {}
findMyWay.on('GET', '/test/hello/world/:id/blah', fn)
t.assert.deepEqual(
findMyWay.find('GET', '/test/hello/world/hel%"Flo/blah'),
null
)
})
test('safe decodeURIComponent - wildcard', t => {
t.plan(1)
const findMyWay = FindMyWay()
const fn = () => {}
findMyWay.on('GET', '/test/*', fn)
t.assert.deepEqual(
findMyWay.find('GET', '/test/hel%"Flo'),
null
)
})
test('static routes should be inserted before parametric / 1', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test/hello', () => {
t.assert.ok('inside correct handler')
})
findMyWay.on('GET', '/test/:id', () => {
t.assert.fail('wrong handler')
})
findMyWay.lookup({ method: 'GET', url: '/test/hello', headers: {} }, null)
})
test('static routes should be inserted before parametric / 2', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test/:id', () => {
t.assert.fail('wrong handler')
})
findMyWay.on('GET', '/test/hello', () => {
t.assert.ok('inside correct handler')
})
findMyWay.lookup({ method: 'GET', url: '/test/hello', headers: {} }, null)
})
test('static routes should be inserted before parametric / 3', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:id', () => {
t.assert.fail('wrong handler')
})
findMyWay.on('GET', '/test', () => {
t.assert.ok('inside correct handler')
})
findMyWay.on('GET', '/test/:id', () => {
t.assert.fail('wrong handler')
})
findMyWay.on('GET', '/test/hello', () => {
t.assert.ok('inside correct handler')
})
findMyWay.lookup({ method: 'GET', url: '/test', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/hello', headers: {} }, null)
})
test('static routes should be inserted before parametric / 4', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/:id', () => {
t.assert.ok('inside correct handler')
})
findMyWay.on('GET', '/test', () => {
t.assert.fail('wrong handler')
})
findMyWay.on('GET', '/test/:id', () => {
t.assert.ok('inside correct handler')
})
findMyWay.on('GET', '/test/hello', () => {
t.assert.fail('wrong handler')
})
findMyWay.lookup({ method: 'GET', url: '/test/id', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/id', headers: {} }, null)
})
test('Static parametric with shared part of the path', t => {
t.plan(2)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.equal(req.url, '/example/shared/nested/oopss')
}
})
findMyWay.on('GET', '/example/shared/nested/test', (req, res, params) => {
t.assert.fail('We should not be here')
})
findMyWay.on('GET', '/example/:param/nested/oops', (req, res, params) => {
t.assert.equal(params.param, 'other')
})
findMyWay.lookup({ method: 'GET', url: '/example/shared/nested/oopss', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/example/other/nested/oops', headers: {} }, null)
})
test('parametric route with different method', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test/:id', (req, res, params) => {
t.assert.equal(params.id, 'hello')
})
findMyWay.on('POST', '/test/:other', (req, res, params) => {
t.assert.equal(params.other, 'world')
})
findMyWay.lookup({ method: 'GET', url: '/test/hello', headers: {} }, null)
findMyWay.lookup({ method: 'POST', url: '/test/world', headers: {} }, null)
})
test('params does not keep the object reference', (t, done) => {
t.plan(2)
const findMyWay = FindMyWay()
let first = true
findMyWay.on('GET', '/test/:id', (req, res, params) => {
if (first) {
setTimeout(() => {
t.assert.equal(params.id, 'hello')
}, 10)
} else {
setTimeout(() => {
t.assert.equal(params.id, 'world')
done()
}, 10)
}
first = false
})
findMyWay.lookup({ method: 'GET', url: '/test/hello', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/world', headers: {} }, null)
})
test('Unsupported method (static)', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.ok('Everything ok')
}
})
findMyWay.on('GET', '/', (req, res, params) => {
t.assert.fail('We should not be here')
})
findMyWay.lookup({ method: 'TROLL', url: '/', headers: {} }, null)
})
test('Unsupported method (wildcard)', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.ok('Everything ok')
}
})
findMyWay.on('GET', '*', (req, res, params) => {
t.assert.fail('We should not be here')
})
findMyWay.lookup({ method: 'TROLL', url: '/hello/world', headers: {} }, null)
})
test('Unsupported method (static find)', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/', () => {})
t.assert.deepEqual(findMyWay.find('TROLL', '/'), null)
})
test('Unsupported method (wildcard find)', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '*', () => {})
t.assert.deepEqual(findMyWay.find('TROLL', '/hello/world'), null)
})
test('register all known HTTP methods', t => {
t.plan(6)
const findMyWay = FindMyWay()
const httpMethods = require('../lib/http-methods')
const handlers = {}
for (const i in httpMethods) {
const m = httpMethods[i]
handlers[m] = function myHandler () {}
findMyWay.on(m, '/test', handlers[m])
}
t.assert.ok(findMyWay.find('COPY', '/test'))
t.assert.equal(findMyWay.find('COPY', '/test').handler, handlers.COPY)
t.assert.ok(findMyWay.find('SUBSCRIBE', '/test'))
t.assert.equal(findMyWay.find('SUBSCRIBE', '/test').handler, handlers.SUBSCRIBE)
t.assert.ok(findMyWay.find('M-SEARCH', '/test'))
t.assert.equal(findMyWay.find('M-SEARCH', '/test').handler, handlers['M-SEARCH'])
})
test('off removes all routes without checking constraints if no constraints are specified', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', {}, (req, res) => {})
findMyWay.on('GET', '/test', { constraints: { host: 'example.com' } }, (req, res) => {})
findMyWay.off('GET', '/test')
t.assert.equal(findMyWay.routes.length, 0)
})
test('off removes only constrainted routes if constraints are specified', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', {}, (req, res) => {})
findMyWay.on('GET', '/test', { constraints: { host: 'example.com' } }, (req, res) => {})
findMyWay.off('GET', '/test', { host: 'example.com' })
t.assert.equal(findMyWay.routes.length, 1)
t.assert.ok(!findMyWay.routes[0].opts.constraints)
})
test('off removes no routes if provided constraints does not match any registered route', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', {}, (req, res) => {})
findMyWay.on('GET', '/test', { constraints: { version: '2.x' } }, (req, res) => {})
findMyWay.on('GET', '/test', { constraints: { version: '3.x' } }, (req, res) => {})
findMyWay.off('GET', '/test', { version: '1.x' })
t.assert.equal(findMyWay.routes.length, 3)
})
test('off validates that constraints is an object or undefined', t => {
t.plan(6)
const findMyWay = FindMyWay()
t.assert.throws(() => findMyWay.off('GET', '/', 2))
t.assert.throws(() => findMyWay.off('GET', '/', 'should throw'))
t.assert.throws(() => findMyWay.off('GET', '/', []))
t.assert.doesNotThrow(() => findMyWay.off('GET', '/', undefined))
t.assert.doesNotThrow(() => findMyWay.off('GET', '/', {}))
t.assert.doesNotThrow(() => findMyWay.off('GET', '/'))
})
test('off removes only unconstrainted route if an empty object is given as constraints', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.get('/', {}, () => {})
findMyWay.get('/', { constraints: { host: 'fastify.io' } }, () => {})
findMyWay.off('GET', '/', {})
t.assert.equal(findMyWay.routes.length, 1)
t.assert.equal(findMyWay.routes[0].opts.constraints.host, 'fastify.io')
})

36
node_modules/find-my-way/test/null-object.test.js generated vendored Normal file
View File

@@ -0,0 +1,36 @@
'use strict'
const { test } = require('node:test')
const { NullObject } = require('../lib/null-object')
test('NullObject', t => {
t.plan(2)
const nullObject = new NullObject()
t.assert.ok(nullObject instanceof NullObject)
t.assert.ok(typeof nullObject === 'object')
})
test('has no methods from generic Object class', t => {
function getAllPropertyNames (obj) {
const props = []
do {
Object.getOwnPropertyNames(obj).forEach(function (prop) {
if (props.indexOf(prop) === -1) {
props.push(prop)
}
})
} while (obj = Object.getPrototypeOf(obj)) // eslint-disable-line
return props
}
const propertyNames = getAllPropertyNames({})
t.plan(propertyNames.length + 1)
const nullObject = new NullObject()
for (const propertyName of propertyNames) {
t.assert.ok(!(propertyName in nullObject), propertyName)
}
t.assert.equal(getAllPropertyNames(nullObject).length, 0)
})

72
node_modules/find-my-way/test/on-bad-url.test.js generated vendored Normal file
View File

@@ -0,0 +1,72 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('If onBadUrl is defined, then a bad url should be handled differently (find)', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
},
onBadUrl: (path, req, res) => {
t.assert.equal(path, '/%world', { todo: 'this is not executed' })
}
})
findMyWay.on('GET', '/hello/:id', (req, res) => {
t.assert.fail('Should not be here')
})
const handle = findMyWay.find('GET', '/hello/%world')
t.assert.notDeepStrictEqual(handle, null)
})
test('If onBadUrl is defined, then a bad url should be handled differently (lookup)', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
},
onBadUrl: (path, req, res) => {
t.assert.equal(path, '/hello/%world')
}
})
findMyWay.on('GET', '/hello/:id', (req, res) => {
t.assert.fail('Should not be here')
})
findMyWay.lookup({ method: 'GET', url: '/hello/%world', headers: {} }, null)
})
test('If onBadUrl is not defined, then we should call the defaultRoute (find)', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/hello/:id', (req, res) => {
t.assert.fail('Should not be here')
})
const handle = findMyWay.find('GET', '/hello/%world')
t.assert.equal(handle, null)
})
test('If onBadUrl is not defined, then we should call the defaultRoute (lookup)', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.ok('Everything fine')
}
})
findMyWay.on('GET', '/hello/:id', (req, res) => {
t.assert.fail('Should not be here')
})
findMyWay.lookup({ method: 'GET', url: '/hello/%world', headers: {} }, null)
})

216
node_modules/find-my-way/test/optional-params.test.js generated vendored Normal file
View File

@@ -0,0 +1,216 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('Test route with optional parameter', (t) => {
t.plan(2)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a/:param/b/:optional?', (req, res, params) => {
if (params.optional) {
t.assert.equal(params.optional, 'foo')
} else {
t.assert.equal(params.optional, undefined)
}
})
findMyWay.lookup({ method: 'GET', url: '/a/foo-bar/b', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/a/foo-bar/b/foo', headers: {} }, null)
})
test('Test for duplicate route with optional param', (t) => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/foo/:bar?', (req, res, params) => {})
try {
findMyWay.on('GET', '/foo', (req, res, params) => {})
t.assert.fail('method is already declared for route with optional param')
} catch (e) {
t.assert.equal(e.message, 'Method \'GET\' already declared for route \'/foo\' with constraints \'{}\'')
}
})
test('Test for param with ? not at the end', (t) => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
try {
findMyWay.on('GET', '/foo/:bar?/baz', (req, res, params) => {})
t.assert.fail('Optional Param in the middle of the path is not allowed')
} catch (e) {
t.assert.equal(e.message, 'Optional Parameter needs to be the last parameter of the path')
}
})
test('Multi parametric route with optional param', (t) => {
t.plan(2)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a/:p1-:p2?', (req, res, params) => {
if (params.p1 && params.p2) {
t.assert.equal(params.p1, 'foo-bar')
t.assert.equal(params.p2, 'baz')
}
})
findMyWay.lookup({ method: 'GET', url: '/a/foo-bar-baz', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/a', headers: {} }, null)
})
test('Optional Parameter with ignoreTrailingSlash = true', (t) => {
t.plan(4)
const findMyWay = FindMyWay({
ignoreTrailingSlash: true,
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/test/hello/:optional?', (req, res, params) => {
if (params.optional) {
t.assert.equal(params.optional, 'foo')
} else {
t.assert.equal(params.optional, undefined)
}
})
findMyWay.lookup({ method: 'GET', url: '/test/hello/', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/hello', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/hello/foo', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/hello/foo/', headers: {} }, null)
})
test('Optional Parameter with ignoreTrailingSlash = false', (t) => {
t.plan(4)
const findMyWay = FindMyWay({
ignoreTrailingSlash: false,
defaultRoute: (req, res) => {
t.assert.equal(req.url, '/test/hello/foo/')
}
})
findMyWay.on('GET', '/test/hello/:optional?', (req, res, params) => {
if (req.url === '/test/hello/') {
t.assert.deepEqual(params, { optional: '' })
} else if (req.url === '/test/hello') {
t.assert.deepEqual(params, {})
} else if (req.url === '/test/hello/foo') {
t.assert.deepEqual(params, { optional: 'foo' })
}
})
findMyWay.lookup({ method: 'GET', url: '/test/hello/', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/hello', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/hello/foo', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/hello/foo/', headers: {} }, null)
})
test('Optional Parameter with ignoreDuplicateSlashes = true', (t) => {
t.plan(4)
const findMyWay = FindMyWay({
ignoreDuplicateSlashes: true,
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/test/hello/:optional?', (req, res, params) => {
if (params.optional) {
t.assert.equal(params.optional, 'foo')
} else {
t.assert.equal(params.optional, undefined)
}
})
findMyWay.lookup({ method: 'GET', url: '/test//hello', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/hello', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/hello/foo', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test//hello//foo', headers: {} }, null)
})
test('Optional Parameter with ignoreDuplicateSlashes = false', (t) => {
t.plan(4)
const findMyWay = FindMyWay({
ignoreDuplicateSlashes: false,
defaultRoute: (req, res) => {
if (req.url === '/test//hello') {
t.assert.deepEqual(req.params, undefined)
} else if (req.url === '/test//hello/foo') {
t.assert.deepEqual(req.params, undefined)
}
}
})
findMyWay.on('GET', '/test/hello/:optional?', (req, res, params) => {
if (req.url === '/test/hello/') {
t.assert.deepEqual(params, { optional: '' })
} else if (req.url === '/test/hello') {
t.assert.deepEqual(params, {})
} else if (req.url === '/test/hello/foo') {
t.assert.deepEqual(params, { optional: 'foo' })
}
})
findMyWay.lookup({ method: 'GET', url: '/test//hello', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/hello', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/hello/foo', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test//hello/foo', headers: {} }, null)
})
test('deregister a route with optional param', (t) => {
t.plan(4)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/a/:param/b/:optional?', (req, res, params) => {})
t.assert.ok(findMyWay.find('GET', '/a/:param/b'))
t.assert.ok(findMyWay.find('GET', '/a/:param/b/:optional'))
findMyWay.off('GET', '/a/:param/b/:optional?')
t.assert.ok(!findMyWay.find('GET', '/a/:param/b'))
t.assert.ok(!findMyWay.find('GET', '/a/:param/b/:optional'))
})
test('optional parameter on root', (t) => {
t.plan(2)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
t.assert.fail('Should not be defaultRoute')
}
})
findMyWay.on('GET', '/:optional?', (req, res, params) => {
if (params.optional) {
t.assert.equal(params.optional, 'foo')
} else {
t.assert.equal(params.optional, undefined)
}
})
findMyWay.lookup({ method: 'GET', url: '/', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/foo', headers: {} }, null)
})

126
node_modules/find-my-way/test/params-collisions.test.js generated vendored Normal file
View File

@@ -0,0 +1,126 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('..')
test('should setup parametric and regexp node', t => {
t.plan(2)
const findMyWay = FindMyWay()
const paramHandler = () => {}
const regexpHandler = () => {}
findMyWay.on('GET', '/foo/:bar', paramHandler)
findMyWay.on('GET', '/foo/:bar(123)', regexpHandler)
t.assert.equal(findMyWay.find('GET', '/foo/value').handler, paramHandler)
t.assert.equal(findMyWay.find('GET', '/foo/123').handler, regexpHandler)
})
test('should setup parametric and multi-parametric node', t => {
t.plan(2)
const findMyWay = FindMyWay()
const paramHandler = () => {}
const regexpHandler = () => {}
findMyWay.on('GET', '/foo/:bar', paramHandler)
findMyWay.on('GET', '/foo/:bar.png', regexpHandler)
t.assert.equal(findMyWay.find('GET', '/foo/value').handler, paramHandler)
t.assert.equal(findMyWay.find('GET', '/foo/value.png').handler, regexpHandler)
})
test('should throw when set upping two parametric nodes', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/foo/:bar', () => {})
t.assert.throws(() => findMyWay.on('GET', '/foo/:baz', () => {}))
})
test('should throw when set upping two regexp nodes', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/foo/:bar(123)', () => {})
t.assert.throws(() => findMyWay.on('GET', '/foo/:bar(456)', () => {}))
})
test('should set up two parametric nodes with static ending', t => {
t.plan(2)
const findMyWay = FindMyWay()
const paramHandler1 = () => {}
const paramHandler2 = () => {}
findMyWay.on('GET', '/foo/:bar.png', paramHandler1)
findMyWay.on('GET', '/foo/:bar.jpeg', paramHandler2)
t.assert.equal(findMyWay.find('GET', '/foo/value.png').handler, paramHandler1)
t.assert.equal(findMyWay.find('GET', '/foo/value.jpeg').handler, paramHandler2)
})
test('should set up two regexp nodes with static ending', t => {
t.plan(2)
const findMyWay = FindMyWay()
const paramHandler1 = () => {}
const paramHandler2 = () => {}
findMyWay.on('GET', '/foo/:bar(123).png', paramHandler1)
findMyWay.on('GET', '/foo/:bar(456).jpeg', paramHandler2)
t.assert.equal(findMyWay.find('GET', '/foo/123.png').handler, paramHandler1)
t.assert.equal(findMyWay.find('GET', '/foo/456.jpeg').handler, paramHandler2)
})
test('node with longer static suffix should have higher priority', t => {
t.plan(2)
const findMyWay = FindMyWay()
const paramHandler1 = () => {}
const paramHandler2 = () => {}
findMyWay.on('GET', '/foo/:bar.png', paramHandler1)
findMyWay.on('GET', '/foo/:bar.png.png', paramHandler2)
t.assert.equal(findMyWay.find('GET', '/foo/value.png').handler, paramHandler1)
t.assert.equal(findMyWay.find('GET', '/foo/value.png.png').handler, paramHandler2)
})
test('node with longer static suffix should have higher priority', t => {
t.plan(2)
const findMyWay = FindMyWay()
const paramHandler1 = () => {}
const paramHandler2 = () => {}
findMyWay.on('GET', '/foo/:bar.png.png', paramHandler2)
findMyWay.on('GET', '/foo/:bar.png', paramHandler1)
t.assert.equal(findMyWay.find('GET', '/foo/value.png').handler, paramHandler1)
t.assert.equal(findMyWay.find('GET', '/foo/value.png.png').handler, paramHandler2)
})
test('should set up regexp node and node with static ending', t => {
t.plan(2)
const regexHandler = () => {}
const multiParamHandler = () => {}
const findMyWay = FindMyWay()
findMyWay.on('GET', '/foo/:bar(123)', regexHandler)
findMyWay.on('GET', '/foo/:bar(123).jpeg', multiParamHandler)
t.assert.equal(findMyWay.find('GET', '/foo/123.jpeg').handler, multiParamHandler)
t.assert.equal(findMyWay.find('GET', '/foo/123').handler, regexHandler)
})

View File

@@ -0,0 +1,53 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('path params match', (t) => {
t.plan(24)
const findMyWay = FindMyWay({ ignoreTrailingSlash: true, ignoreDuplicateSlashes: true })
const b1Path = function b1StaticPath () {}
const b2Path = function b2StaticPath () {}
const cPath = function cStaticPath () {}
const paramPath = function parameterPath () {}
findMyWay.on('GET', '/ab1', b1Path)
findMyWay.on('GET', '/ab2', b2Path)
findMyWay.on('GET', '/ac', cPath)
findMyWay.on('GET', '/:pam', paramPath)
t.assert.equal(findMyWay.find('GET', '/ab1').handler, b1Path)
t.assert.equal(findMyWay.find('GET', '/ab1/').handler, b1Path)
t.assert.equal(findMyWay.find('GET', '//ab1').handler, b1Path)
t.assert.equal(findMyWay.find('GET', '//ab1//').handler, b1Path)
t.assert.equal(findMyWay.find('GET', '/ab2').handler, b2Path)
t.assert.equal(findMyWay.find('GET', '/ab2/').handler, b2Path)
t.assert.equal(findMyWay.find('GET', '//ab2').handler, b2Path)
t.assert.equal(findMyWay.find('GET', '//ab2//').handler, b2Path)
t.assert.equal(findMyWay.find('GET', '/ac').handler, cPath)
t.assert.equal(findMyWay.find('GET', '/ac/').handler, cPath)
t.assert.equal(findMyWay.find('GET', '//ac').handler, cPath)
t.assert.equal(findMyWay.find('GET', '//ac//').handler, cPath)
t.assert.equal(findMyWay.find('GET', '/foo').handler, paramPath)
t.assert.equal(findMyWay.find('GET', '/foo/').handler, paramPath)
t.assert.equal(findMyWay.find('GET', '//foo').handler, paramPath)
t.assert.equal(findMyWay.find('GET', '//foo//').handler, paramPath)
const noTrailingSlashRet = findMyWay.find('GET', '/abcdef')
t.assert.equal(noTrailingSlashRet.handler, paramPath)
t.assert.deepEqual(noTrailingSlashRet.params, { pam: 'abcdef' })
const trailingSlashRet = findMyWay.find('GET', '/abcdef/')
t.assert.equal(trailingSlashRet.handler, paramPath)
t.assert.deepEqual(trailingSlashRet.params, { pam: 'abcdef' })
const noDuplicateSlashRet = findMyWay.find('GET', '/abcdef')
t.assert.equal(noDuplicateSlashRet.handler, paramPath)
t.assert.deepEqual(noDuplicateSlashRet.params, { pam: 'abcdef' })
const duplicateSlashRet = findMyWay.find('GET', '//abcdef')
t.assert.equal(duplicateSlashRet.handler, paramPath)
t.assert.deepEqual(duplicateSlashRet.params, { pam: 'abcdef' })
})

596
node_modules/find-my-way/test/pretty-print-tree.test.js generated vendored Normal file
View File

@@ -0,0 +1,596 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('pretty print - empty tree', t => {
t.plan(2)
const findMyWay = FindMyWay()
const tree = findMyWay.prettyPrint({ method: 'GET' })
const expected = '(empty tree)'
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - static routes', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/hello', () => {})
findMyWay.on('GET', '/hello/world', () => {})
const tree = findMyWay.prettyPrint({ method: 'GET' })
const expected = `\
└── /
├── test (GET)
│ └── /hello (GET)
└── hello/world (GET)
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - parametric routes', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/:hello', () => {})
findMyWay.on('GET', '/hello/:world', () => {})
const tree = findMyWay.prettyPrint({ method: 'GET' })
const expected = `\
└── /
├── test (GET)
│ └── /
│ └── :hello (GET)
└── hello/
└── :world (GET)
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - parametric routes', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/static', () => {})
findMyWay.on('GET', '/static/:param/suffix1', () => {})
findMyWay.on('GET', '/static/:param(123)/suffix2', () => {})
findMyWay.on('GET', '/static/:param(123).end/suffix3', () => {})
findMyWay.on('GET', '/static/:param1(123).:param2(456)/suffix4', () => {})
const tree = findMyWay.prettyPrint({ method: 'GET' })
const expected = `\
└── /
└── static (GET)
└── /
├── :param(123).end
│ └── /suffix3 (GET)
├── :param(123)
│ └── /suffix2 (GET)
├── :param1(123).:param2(456)
│ └── /suffix4 (GET)
└── :param
└── /suffix1 (GET)
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - parametric routes', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/static', () => {})
findMyWay.on('GET', '/static/:param/suffix1', () => {})
findMyWay.on('GET', '/static/:param(123)/suffix2', () => {})
findMyWay.on('GET', '/static/:param(123).end/suffix3', () => {})
findMyWay.on('GET', '/static/:param1(123).:param2(456)/suffix4', () => {})
const tree = findMyWay.prettyPrint({ method: 'GET', commonPrefix: false })
const expected = `\
└── /static (GET)
├── /:param(123).end/suffix3 (GET)
├── /:param(123)/suffix2 (GET)
├── /:param1(123).:param2(456)/suffix4 (GET)
└── /:param/suffix1 (GET)
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - mixed parametric routes', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/:hello', () => {})
findMyWay.on('POST', '/test/:hello', () => {})
findMyWay.on('GET', '/test/:hello/world', () => {})
const tree = findMyWay.prettyPrint({ method: 'GET' })
const expected = `\
└── /
└── test (GET)
└── /
└── :hello (GET)
└── /world (GET)
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - wildcard routes', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/*', () => {})
findMyWay.on('GET', '/hello/*', () => {})
const tree = findMyWay.prettyPrint({ method: 'GET' })
const expected = `\
└── /
├── test (GET)
│ └── /
│ └── * (GET)
└── hello/
└── * (GET)
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - parametric routes with same parent and followed by a static route which has the same prefix with the former routes', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/hello/:id', () => {})
findMyWay.on('POST', '/test/hello/:id', () => {})
findMyWay.on('GET', '/test/helloworld', () => {})
const tree = findMyWay.prettyPrint({ method: 'GET' })
const expected = `\
└── /
└── test (GET)
└── /hello
├── /
│ └── :id (GET)
└── world (GET)
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - constrained parametric routes', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test', { constraints: { host: 'auth.fastify.io' } }, () => {})
findMyWay.on('GET', '/test/:hello', () => {})
findMyWay.on('GET', '/test/:hello', { constraints: { version: '1.1.2' } }, () => {})
findMyWay.on('GET', '/test/:hello', { constraints: { version: '2.0.0' } }, () => {})
const tree = findMyWay.prettyPrint({ method: 'GET' })
const expected = `\
└── /
└── test (GET)
test (GET) {"host":"auth.fastify.io"}
└── /
└── :hello (GET)
:hello (GET) {"version":"1.1.2"}
:hello (GET) {"version":"2.0.0"}
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - multiple parameters are drawn appropriately', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
// routes with a nested parameter (i.e. no handler for the /:param) were breaking the display
findMyWay.on('GET', '/test/:hello/there/:ladies', () => {})
findMyWay.on('GET', '/test/:hello/there/:ladies/and/:gents', () => {})
findMyWay.on('GET', '/test/are/:you/:ready/to/:rock', () => {})
const tree = findMyWay.prettyPrint({ method: 'GET', commonPrefix: false })
const expected = `\
└── /test (GET)
├── /are/:you/:ready/to/:rock (GET)
└── /:hello/there/:ladies (GET)
└── /and/:gents (GET)
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print commonPrefix - use routes array to draw flattened routes', t => {
t.plan(4)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/hello', () => {})
findMyWay.on('GET', '/testing', () => {})
findMyWay.on('GET', '/testing/:param', () => {})
findMyWay.on('GET', '/update', () => {})
const radixTree = findMyWay.prettyPrint({ method: 'GET', commonPrefix: true })
const arrayTree = findMyWay.prettyPrint({ method: 'GET', commonPrefix: false })
const radixExpected = `\
└── /
├── test (GET)
│ ├── /hello (GET)
│ └── ing (GET)
│ └── /
│ └── :param (GET)
└── update (GET)
`
const arrayExpected = `\
├── /test (GET)
│ ├── /hello (GET)
│ └── ing (GET)
│ └── /:param (GET)
└── /update (GET)
`
t.assert.equal(typeof radixTree, 'string')
t.assert.equal(radixTree, radixExpected)
t.assert.equal(typeof arrayTree, 'string')
t.assert.equal(arrayTree, arrayExpected)
})
test('pretty print commonPrefix - handle wildcard root', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '*', () => {})
findMyWay.on('GET', '/test/hello', () => {})
findMyWay.on('GET', '/testing', () => {})
findMyWay.on('GET', '/testing/:param', () => {})
findMyWay.on('PUT', '/update', () => {})
const arrayTree = findMyWay.prettyPrint({ method: 'GET', commonPrefix: false })
const arrayExpected = `\
├── /test/hello (GET)
├── /testing (GET)
│ └── /:param (GET)
└── * (GET)
`
t.assert.equal(typeof arrayTree, 'string')
t.assert.equal(arrayTree, arrayExpected)
})
test('pretty print commonPrefix - handle wildcard root', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '*', () => {})
findMyWay.on('GET', '/test/hello', () => {})
findMyWay.on('GET', '/testing', () => {})
findMyWay.on('GET', '/testing/:param', () => {})
findMyWay.on('PUT', '/update', () => {})
const radixTree = findMyWay.prettyPrint({ method: 'GET' })
const radixExpected = `\
└── (empty root node)
├── /
│ └── test
│ ├── /hello (GET)
│ └── ing (GET)
│ └── /
│ └── :param (GET)
└── * (GET)
`
t.assert.equal(typeof radixTree, 'string')
t.assert.equal(radixTree, radixExpected)
})
test('pretty print commonPrefix - handle constrained routes', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test', { constraints: { host: 'auth.fastify.io' } }, () => {})
findMyWay.on('GET', '/test/:hello', () => {})
findMyWay.on('PUT', '/test/:hello', () => {})
findMyWay.on('GET', '/test/:hello', { constraints: { version: '1.1.2' } }, () => {})
findMyWay.on('GET', '/test/:hello', { constraints: { version: '2.0.0' } }, () => {})
const arrayTree = findMyWay.prettyPrint({ method: 'GET', commonPrefix: false })
const arrayExpected = `\
└── /test (GET)
/test (GET) {"host":"auth.fastify.io"}
└── /:hello (GET)
/:hello (GET) {"version":"1.1.2"}
/:hello (GET) {"version":"2.0.0"}
`
t.assert.equal(typeof arrayTree, 'string')
t.assert.equal(arrayTree, arrayExpected)
})
test('pretty print includeMeta - commonPrefix: true', t => {
t.plan(6)
const findMyWay = FindMyWay()
const namedFunction = () => {}
const store = {
onRequest: [() => {}, namedFunction],
onTimeout: [() => {}],
genericMeta: 'meta',
mixedMeta: ['mixed items', { an: 'object' }],
objectMeta: { one: '1', two: 2 },
functionMeta: namedFunction
}
store[Symbol('symbolKey')] = Symbol('symbolValue')
findMyWay.on('GET', '/test', () => {}, store)
findMyWay.on('GET', '/test', { constraints: { host: 'auth.fastify.io' } }, () => {}, store)
findMyWay.on('GET', '/testing/:hello', () => {}, store)
findMyWay.on('PUT', '/tested/:hello', () => {}, store)
findMyWay.on('GET', '/test/:hello', { constraints: { version: '1.1.2' } }, () => {})
findMyWay.on('GET', '/test/:hello', { constraints: { version: '2.0.0' } }, () => {})
const radixTree = findMyWay.prettyPrint({
method: 'GET',
commonPrefix: true,
includeMeta: true
})
const radixTreeExpected = `\
└── /
└── test (GET)
• (onRequest) ["anonymous()","namedFunction()"]
• (onTimeout) ["anonymous()"]
• (genericMeta) "meta"
• (mixedMeta) ["mixed items",{"an":"object"}]
• (objectMeta) {"one":"1","two":2}
• (functionMeta) "namedFunction()"
• (Symbol(symbolKey)) "Symbol(symbolValue)"
test (GET) {"host":"auth.fastify.io"}
• (onRequest) ["anonymous()","namedFunction()"]
• (onTimeout) ["anonymous()"]
• (genericMeta) "meta"
• (mixedMeta) ["mixed items",{"an":"object"}]
• (objectMeta) {"one":"1","two":2}
• (functionMeta) "namedFunction()"
• (Symbol(symbolKey)) "Symbol(symbolValue)"
├── ing/
│ └── :hello (GET)
│ • (onRequest) ["anonymous()","namedFunction()"]
│ • (onTimeout) ["anonymous()"]
│ • (genericMeta) "meta"
│ • (mixedMeta) ["mixed items",{"an":"object"}]
│ • (objectMeta) {"one":"1","two":2}
│ • (functionMeta) "namedFunction()"
│ • (Symbol(symbolKey)) "Symbol(symbolValue)"
└── /
└── :hello (GET) {"version":"1.1.2"}
:hello (GET) {"version":"2.0.0"}
`
const radixTreeSpecific = findMyWay.prettyPrint({
method: 'GET',
commonPrefix: true,
includeMeta: ['onTimeout', 'objectMeta', 'nonExistent']
})
const radixTreeSpecificExpected = `\
└── /
└── test (GET)
• (onTimeout) ["anonymous()"]
• (objectMeta) {"one":"1","two":2}
test (GET) {"host":"auth.fastify.io"}
• (onTimeout) ["anonymous()"]
• (objectMeta) {"one":"1","two":2}
├── ing/
│ └── :hello (GET)
│ • (onTimeout) ["anonymous()"]
│ • (objectMeta) {"one":"1","two":2}
└── /
└── :hello (GET) {"version":"1.1.2"}
:hello (GET) {"version":"2.0.0"}
`
const radixTreeNoMeta = findMyWay.prettyPrint({
method: 'GET',
commonPrefix: true,
includeMeta: false
})
const radixTreeNoMetaExpected = `\
└── /
└── test (GET)
test (GET) {"host":"auth.fastify.io"}
├── ing/
│ └── :hello (GET)
└── /
└── :hello (GET) {"version":"1.1.2"}
:hello (GET) {"version":"2.0.0"}
`
t.assert.equal(typeof radixTree, 'string')
t.assert.equal(radixTree, radixTreeExpected)
t.assert.equal(typeof radixTreeSpecific, 'string')
t.assert.equal(radixTreeSpecific, radixTreeSpecificExpected)
t.assert.equal(typeof radixTreeNoMeta, 'string')
t.assert.equal(radixTreeNoMeta, radixTreeNoMetaExpected)
})
test('pretty print includeMeta - commonPrefix: false', t => {
t.plan(6)
const findMyWay = FindMyWay()
const namedFunction = () => {}
const store = {
onRequest: [() => {}, namedFunction],
onTimeout: [() => {}],
genericMeta: 'meta',
mixedMeta: ['mixed items', { an: 'object' }],
objectMeta: { one: '1', two: 2 },
functionMeta: namedFunction
}
store[Symbol('symbolKey')] = Symbol('symbolValue')
findMyWay.on('GET', '/test', () => {}, store)
findMyWay.on('GET', '/test', { constraints: { host: 'auth.fastify.io' } }, () => {}, store)
findMyWay.on('GET', '/testing/:hello', () => {}, store)
findMyWay.on('PUT', '/tested/:hello', () => {}, store)
findMyWay.on('GET', '/test/:hello', { constraints: { version: '1.1.2' } }, () => {})
findMyWay.on('GET', '/test/:hello', { constraints: { version: '2.0.0' } }, () => {})
const arrayTree = findMyWay.prettyPrint({
method: 'GET',
commonPrefix: false,
includeMeta: true
})
const arrayExpected = `\
└── /test (GET)
• (onRequest) ["anonymous()","namedFunction()"]
• (onTimeout) ["anonymous()"]
• (genericMeta) "meta"
• (mixedMeta) ["mixed items",{"an":"object"}]
• (objectMeta) {"one":"1","two":2}
• (functionMeta) "namedFunction()"
• (Symbol(symbolKey)) "Symbol(symbolValue)"
/test (GET) {"host":"auth.fastify.io"}
• (onRequest) ["anonymous()","namedFunction()"]
• (onTimeout) ["anonymous()"]
• (genericMeta) "meta"
• (mixedMeta) ["mixed items",{"an":"object"}]
• (objectMeta) {"one":"1","two":2}
• (functionMeta) "namedFunction()"
• (Symbol(symbolKey)) "Symbol(symbolValue)"
├── ing/:hello (GET)
│ • (onRequest) ["anonymous()","namedFunction()"]
│ • (onTimeout) ["anonymous()"]
│ • (genericMeta) "meta"
│ • (mixedMeta) ["mixed items",{"an":"object"}]
│ • (objectMeta) {"one":"1","two":2}
│ • (functionMeta) "namedFunction()"
│ • (Symbol(symbolKey)) "Symbol(symbolValue)"
└── /:hello (GET) {"version":"1.1.2"}
/:hello (GET) {"version":"2.0.0"}
`
const arraySpecific = findMyWay.prettyPrint({
method: 'GET',
commonPrefix: false,
includeMeta: ['onRequest', 'mixedMeta', 'nonExistent']
})
const arraySpecificExpected = `\
└── /test (GET)
• (onRequest) ["anonymous()","namedFunction()"]
• (mixedMeta) ["mixed items",{"an":"object"}]
/test (GET) {"host":"auth.fastify.io"}
• (onRequest) ["anonymous()","namedFunction()"]
• (mixedMeta) ["mixed items",{"an":"object"}]
├── ing/:hello (GET)
│ • (onRequest) ["anonymous()","namedFunction()"]
│ • (mixedMeta) ["mixed items",{"an":"object"}]
└── /:hello (GET) {"version":"1.1.2"}
/:hello (GET) {"version":"2.0.0"}
`
const arrayNoMeta = findMyWay.prettyPrint({
method: 'GET',
commonPrefix: false,
includeMeta: false
})
const arrayNoMetaExpected = `\
└── /test (GET)
/test (GET) {"host":"auth.fastify.io"}
├── ing/:hello (GET)
└── /:hello (GET) {"version":"1.1.2"}
/:hello (GET) {"version":"2.0.0"}
`
t.assert.equal(typeof arrayTree, 'string')
t.assert.equal(arrayTree, arrayExpected)
t.assert.equal(typeof arraySpecific, 'string')
t.assert.equal(arraySpecific, arraySpecificExpected)
t.assert.equal(typeof arrayNoMeta, 'string')
t.assert.equal(arrayNoMeta, arrayNoMetaExpected)
})
test('pretty print includeMeta - buildPrettyMeta function', t => {
t.plan(4)
const findMyWay = FindMyWay({
buildPrettyMeta: route => {
return { metaKey: route.method === 'GET' ? route.path : 'not a GET route' }
}
})
const namedFunction = () => {}
const store = {
onRequest: [() => {}, namedFunction],
onTimeout: [() => {}],
genericMeta: 'meta',
mixedMeta: ['mixed items', { an: 'object' }],
objectMeta: { one: '1', two: 2 },
functionMeta: namedFunction
}
store[Symbol('symbolKey')] = Symbol('symbolValue')
findMyWay.on('GET', '/test', () => {}, store)
findMyWay.on('GET', '/test', { constraints: { host: 'auth.fastify.io' } }, () => {}, store)
findMyWay.on('GET', '/test/:hello', () => {}, store)
findMyWay.on('PUT', '/test/:hello', () => {}, store)
findMyWay.on('GET', '/test/:hello', { constraints: { version: '1.1.2' } }, () => {})
findMyWay.on('GET', '/test/:hello', { constraints: { version: '2.0.0' } }, () => {})
const arrayTree = findMyWay.prettyPrint({
method: 'GET',
commonPrefix: false,
includeMeta: true
})
const arrayExpected = `\
└── /test (GET)
• (metaKey) "/test"
/test (GET) {"host":"auth.fastify.io"}
• (metaKey) "/test"
└── /:hello (GET)
• (metaKey) "/test/:hello"
/:hello (GET) {"version":"1.1.2"}
• (metaKey) "/test/:hello"
/:hello (GET) {"version":"2.0.0"}
• (metaKey) "/test/:hello"
`
const radixTree = findMyWay.prettyPrint({
method: 'GET',
includeMeta: true
})
const radixExpected = `\
└── /
└── test (GET)
• (metaKey) "/test"
test (GET) {"host":"auth.fastify.io"}
• (metaKey) "/test"
└── /
└── :hello (GET)
• (metaKey) "/test/:hello"
:hello (GET) {"version":"1.1.2"}
• (metaKey) "/test/:hello"
:hello (GET) {"version":"2.0.0"}
• (metaKey) "/test/:hello"
`
t.assert.equal(typeof arrayTree, 'string')
t.assert.equal(arrayTree, arrayExpected)
t.assert.equal(typeof radixTree, 'string')
t.assert.equal(radixTree, radixExpected)
})

680
node_modules/find-my-way/test/pretty-print.test.js generated vendored Normal file
View File

@@ -0,0 +1,680 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('pretty print - empty tree', t => {
t.plan(2)
const findMyWay = FindMyWay()
const tree = findMyWay.prettyPrint()
const expected = '(empty tree)'
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - static routes', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/hello', () => {})
findMyWay.on('GET', '/hello/world', () => {})
const tree = findMyWay.prettyPrint()
const expected = `\
└── /
├── test (GET)
│ └── /hello (GET)
└── hello/world (GET)
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - parametric routes', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/:hello', () => {})
findMyWay.on('GET', '/hello/:world', () => {})
const tree = findMyWay.prettyPrint()
const expected = `\
└── /
├── test (GET)
│ └── /
│ └── :hello (GET)
└── hello/
└── :world (GET)
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - parametric routes', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/static', () => {})
findMyWay.on('GET', '/static/:param/suffix1', () => {})
findMyWay.on('GET', '/static/:param(123)/suffix2', () => {})
findMyWay.on('GET', '/static/:param(123).end/suffix3', () => {})
findMyWay.on('GET', '/static/:param1(123).:param2(456)/suffix4', () => {})
const tree = findMyWay.prettyPrint()
const expected = `\
└── /
└── static (GET)
└── /
├── :param(123).end
│ └── /suffix3 (GET)
├── :param(123)
│ └── /suffix2 (GET)
├── :param1(123).:param2(456)
│ └── /suffix4 (GET)
└── :param
└── /suffix1 (GET)
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - parametric routes', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/static', () => {})
findMyWay.on('GET', '/static/:param/suffix1', () => {})
findMyWay.on('GET', '/static/:param(123)/suffix2', () => {})
findMyWay.on('GET', '/static/:param(123).end/suffix3', () => {})
findMyWay.on('GET', '/static/:param1(123).:param2(456)/suffix4', () => {})
const tree = findMyWay.prettyPrint({ commonPrefix: false })
const expected = `\
└── /static (GET)
├── /:param(123).end/suffix3 (GET)
├── /:param(123)/suffix2 (GET)
├── /:param1(123).:param2(456)/suffix4 (GET)
└── /:param/suffix1 (GET)
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - mixed parametric routes', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/:hello', () => {})
findMyWay.on('POST', '/test/:hello', () => {})
findMyWay.on('GET', '/test/:hello/world', () => {})
const tree = findMyWay.prettyPrint()
const expected = `\
└── /
└── test (GET)
└── /
└── :hello (GET, POST)
└── /world (GET)
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - wildcard routes', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/*', () => {})
findMyWay.on('GET', '/hello/*', () => {})
const tree = findMyWay.prettyPrint()
const expected = `\
└── /
├── test (GET)
│ └── /
│ └── * (GET)
└── hello/
└── * (GET)
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - parametric routes with same parent and followed by a static route which has the same prefix with the former routes', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/hello/:id', () => {})
findMyWay.on('POST', '/test/hello/:id', () => {})
findMyWay.on('GET', '/test/helloworld', () => {})
const tree = findMyWay.prettyPrint()
const expected = `\
└── /
└── test (GET)
└── /hello
├── /
│ └── :id (GET, POST)
└── world (GET)
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - constrained parametric routes', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test', { constraints: { host: 'auth.fastify.io' } }, () => {})
findMyWay.on('GET', '/test/:hello', () => {})
findMyWay.on('GET', '/test/:hello', { constraints: { version: '1.1.2' } }, () => {})
findMyWay.on('GET', '/test/:hello', { constraints: { version: '2.0.0' } }, () => {})
const tree = findMyWay.prettyPrint()
const expected = `\
└── /
└── test (GET)
test (GET) {"host":"auth.fastify.io"}
└── /
└── :hello (GET)
:hello (GET) {"version":"1.1.2"}
:hello (GET) {"version":"2.0.0"}
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - multiple parameters are drawn appropriately', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
// routes with a nested parameter (i.e. no handler for the /:param) were breaking the display
findMyWay.on('GET', '/test/:hello/there/:ladies', () => {})
findMyWay.on('GET', '/test/:hello/there/:ladies/and/:gents', () => {})
findMyWay.on('GET', '/test/are/:you/:ready/to/:rock', () => {})
const tree = findMyWay.prettyPrint({ commonPrefix: false })
const expected = `\
└── /test (GET)
├── /are/:you/:ready/to/:rock (GET)
└── /:hello/there/:ladies (GET)
└── /and/:gents (GET)
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print - multiple parameters are drawn appropriately', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
// routes with a nested parameter (i.e. no handler for the /:param) were breaking the display
findMyWay.on('GET', '/test/:hello/there/:ladies', () => {})
findMyWay.on('GET', '/test/:hello/there/:ladies/and/:gents', () => {})
findMyWay.on('GET', '/test/are/:you/:ready/to/:rock', () => {})
const tree = findMyWay.prettyPrint({ commonPrefix: false })
const expected = `\
└── /test (GET)
├── /are/:you/:ready/to/:rock (GET)
└── /:hello/there/:ladies (GET)
└── /and/:gents (GET)
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})
test('pretty print commonPrefix - use routes array to draw flattened routes', t => {
t.plan(4)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test/hello', () => {})
findMyWay.on('GET', '/testing', () => {})
findMyWay.on('GET', '/testing/:param', () => {})
findMyWay.on('PUT', '/update', () => {})
const radixTree = findMyWay.prettyPrint({ commonPrefix: true })
const arrayTree = findMyWay.prettyPrint({ commonPrefix: false })
const radixExpected = `\
└── /
├── test (GET)
│ ├── /hello (GET)
│ └── ing (GET)
│ └── /
│ └── :param (GET)
└── update (PUT)
`
const arrayExpected = `\
├── /test (GET)
│ ├── /hello (GET)
│ └── ing (GET)
│ └── /:param (GET)
└── /update (PUT)
`
t.assert.equal(typeof radixTree, 'string')
t.assert.equal(radixTree, radixExpected)
t.assert.equal(typeof arrayTree, 'string')
t.assert.equal(arrayTree, arrayExpected)
})
test('pretty print commonPrefix - handle wildcard root', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('OPTIONS', '*', () => {})
findMyWay.on('GET', '/test/hello', () => {})
findMyWay.on('GET', '/testing', () => {})
findMyWay.on('GET', '/testing/:param', () => {})
findMyWay.on('PUT', '/update', () => {})
const arrayTree = findMyWay.prettyPrint({ commonPrefix: false })
const arrayExpected = `\
├── /test/hello (GET)
├── /testing (GET)
│ └── /:param (GET)
├── /update (PUT)
└── * (OPTIONS)
`
t.assert.equal(typeof arrayTree, 'string')
t.assert.equal(arrayTree, arrayExpected)
})
test('pretty print commonPrefix - handle wildcard root', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '*', () => {})
findMyWay.on('GET', '/test/hello', () => {})
findMyWay.on('GET', '/testing', () => {})
findMyWay.on('GET', '/testing/:param', () => {})
findMyWay.on('PUT', '/update', () => {})
const radixTree = findMyWay.prettyPrint()
const radixExpected = `\
└── (empty root node)
├── /
│ ├── test
│ │ ├── /hello (GET)
│ │ └── ing (GET)
│ │ └── /
│ │ └── :param (GET)
│ └── update (PUT)
└── * (GET)
`
t.assert.equal(typeof radixTree, 'string')
t.assert.equal(radixTree, radixExpected)
})
test('pretty print commonPrefix - handle constrained routes', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test', { constraints: { host: 'auth.fastify.io' } }, () => {})
findMyWay.on('GET', '/test/:hello', () => {})
findMyWay.on('PUT', '/test/:hello', () => {})
findMyWay.on('GET', '/test/:hello', { constraints: { version: '1.1.2' } }, () => {})
findMyWay.on('GET', '/test/:hello', { constraints: { version: '2.0.0' } }, () => {})
const arrayTree = findMyWay.prettyPrint({ commonPrefix: false })
const arrayExpected = `\
└── /test (GET)
/test (GET) {"host":"auth.fastify.io"}
└── /:hello (GET, PUT)
/:hello (GET) {"version":"1.1.2"}
/:hello (GET) {"version":"2.0.0"}
`
t.assert.equal(typeof arrayTree, 'string')
t.assert.equal(arrayTree, arrayExpected)
})
test('pretty print commonPrefix - handle method constraint', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.addConstraintStrategy({
name: 'method',
storage: function () {
const handlers = {}
return {
get: (type) => { return handlers[type] || null },
set: (type, store) => { handlers[type] = store }
}
},
deriveConstraint: (req) => req.headers['x-method'],
mustMatchWhenDerived: true
})
findMyWay.on('GET', '/test', () => {})
findMyWay.on('GET', '/test', { constraints: { method: 'foo' } }, () => {})
findMyWay.on('GET', '/test/:hello', () => {})
findMyWay.on('PUT', '/test/:hello', () => {})
findMyWay.on('GET', '/test/:hello', { constraints: { method: 'bar' } }, () => {})
findMyWay.on('GET', '/test/:hello', { constraints: { method: 'baz' } }, () => {})
const arrayTree = findMyWay.prettyPrint({
commonPrefix: false,
methodConstraintName: 'methodOverride'
})
const arrayExpected = `\
└── /test (GET)
/test (GET) {"method":"foo"}
└── /:hello (GET, PUT)
/:hello (GET) {"method":"bar"}
/:hello (GET) {"method":"baz"}
`
t.assert.equal(typeof arrayTree, 'string')
t.assert.equal(arrayTree, arrayExpected)
})
test('pretty print includeMeta - commonPrefix: true', t => {
t.plan(6)
const findMyWay = FindMyWay()
const namedFunction = () => {}
const store = {
onRequest: [() => {}, namedFunction],
onTimeout: [() => {}],
genericMeta: 'meta',
mixedMeta: ['mixed items', { an: 'object' }],
objectMeta: { one: '1', two: 2 },
functionMeta: namedFunction
}
store[Symbol('symbolKey')] = Symbol('symbolValue')
findMyWay.on('GET', '/test', () => {}, store)
findMyWay.on('GET', '/test', { constraints: { host: 'auth.fastify.io' } }, () => {}, store)
findMyWay.on('GET', '/testing/:hello', () => {}, store)
findMyWay.on('PUT', '/tested/:hello', () => {}, store)
findMyWay.on('GET', '/test/:hello', { constraints: { version: '1.1.2' } }, () => {})
findMyWay.on('GET', '/test/:hello', { constraints: { version: '2.0.0' } }, () => {})
const radixTree = findMyWay.prettyPrint({ commonPrefix: true, includeMeta: true })
const radixTreeExpected = `\
└── /
└── test (GET)
• (onRequest) ["anonymous()","namedFunction()"]
• (onTimeout) ["anonymous()"]
• (genericMeta) "meta"
• (mixedMeta) ["mixed items",{"an":"object"}]
• (objectMeta) {"one":"1","two":2}
• (functionMeta) "namedFunction()"
• (Symbol(symbolKey)) "Symbol(symbolValue)"
test (GET) {"host":"auth.fastify.io"}
• (onRequest) ["anonymous()","namedFunction()"]
• (onTimeout) ["anonymous()"]
• (genericMeta) "meta"
• (mixedMeta) ["mixed items",{"an":"object"}]
• (objectMeta) {"one":"1","two":2}
• (functionMeta) "namedFunction()"
• (Symbol(symbolKey)) "Symbol(symbolValue)"
├── ing/
│ └── :hello (GET)
│ • (onRequest) ["anonymous()","namedFunction()"]
│ • (onTimeout) ["anonymous()"]
│ • (genericMeta) "meta"
│ • (mixedMeta) ["mixed items",{"an":"object"}]
│ • (objectMeta) {"one":"1","two":2}
│ • (functionMeta) "namedFunction()"
│ • (Symbol(symbolKey)) "Symbol(symbolValue)"
├── ed/
│ └── :hello (PUT)
│ • (onRequest) ["anonymous()","namedFunction()"]
│ • (onTimeout) ["anonymous()"]
│ • (genericMeta) "meta"
│ • (mixedMeta) ["mixed items",{"an":"object"}]
│ • (objectMeta) {"one":"1","two":2}
│ • (functionMeta) "namedFunction()"
│ • (Symbol(symbolKey)) "Symbol(symbolValue)"
└── /
└── :hello (GET) {"version":"1.1.2"}
:hello (GET) {"version":"2.0.0"}
`
const radixTreeSpecific = findMyWay.prettyPrint({ commonPrefix: true, includeMeta: ['onTimeout', 'objectMeta', 'nonExistent'] })
const radixTreeSpecificExpected = `\
└── /
└── test (GET)
• (onTimeout) ["anonymous()"]
• (objectMeta) {"one":"1","two":2}
test (GET) {"host":"auth.fastify.io"}
• (onTimeout) ["anonymous()"]
• (objectMeta) {"one":"1","two":2}
├── ing/
│ └── :hello (GET)
│ • (onTimeout) ["anonymous()"]
│ • (objectMeta) {"one":"1","two":2}
├── ed/
│ └── :hello (PUT)
│ • (onTimeout) ["anonymous()"]
│ • (objectMeta) {"one":"1","two":2}
└── /
└── :hello (GET) {"version":"1.1.2"}
:hello (GET) {"version":"2.0.0"}
`
const radixTreeNoMeta = findMyWay.prettyPrint({ commonPrefix: true, includeMeta: false })
const radixTreeNoMetaExpected = `\
└── /
└── test (GET)
test (GET) {"host":"auth.fastify.io"}
├── ing/
│ └── :hello (GET)
├── ed/
│ └── :hello (PUT)
└── /
└── :hello (GET) {"version":"1.1.2"}
:hello (GET) {"version":"2.0.0"}
`
t.assert.equal(typeof radixTree, 'string')
t.assert.equal(radixTree, radixTreeExpected)
t.assert.equal(typeof radixTreeSpecific, 'string')
t.assert.equal(radixTreeSpecific, radixTreeSpecificExpected)
t.assert.equal(typeof radixTreeNoMeta, 'string')
t.assert.equal(radixTreeNoMeta, radixTreeNoMetaExpected)
})
test('pretty print includeMeta - commonPrefix: false', t => {
t.plan(6)
const findMyWay = FindMyWay()
const namedFunction = () => {}
const store = {
onRequest: [() => {}, namedFunction],
onTimeout: [() => {}],
onError: null,
onRegister: undefined,
genericMeta: 'meta',
mixedMeta: ['mixed items', { an: 'object' }],
objectMeta: { one: '1', two: 2 },
functionMeta: namedFunction
}
store[Symbol('symbolKey')] = Symbol('symbolValue')
findMyWay.on('GET', '/test', () => {}, store)
findMyWay.on('GET', '/test', { constraints: { host: 'auth.fastify.io' } }, () => {}, store)
findMyWay.on('GET', '/testing/:hello', () => {}, store)
findMyWay.on('PUT', '/tested/:hello', () => {}, store)
findMyWay.on('GET', '/test/:hello', { constraints: { version: '1.1.2' } }, () => {})
findMyWay.on('GET', '/test/:hello', { constraints: { version: '2.0.0' } }, () => {})
const arrayTree = findMyWay.prettyPrint({ commonPrefix: false, includeMeta: true })
const arrayExpected = `\
└── /test (GET)
• (onRequest) ["anonymous()","namedFunction()"]
• (onTimeout) ["anonymous()"]
• (genericMeta) "meta"
• (mixedMeta) ["mixed items",{"an":"object"}]
• (objectMeta) {"one":"1","two":2}
• (functionMeta) "namedFunction()"
• (Symbol(symbolKey)) "Symbol(symbolValue)"
/test (GET) {"host":"auth.fastify.io"}
• (onRequest) ["anonymous()","namedFunction()"]
• (onTimeout) ["anonymous()"]
• (genericMeta) "meta"
• (mixedMeta) ["mixed items",{"an":"object"}]
• (objectMeta) {"one":"1","two":2}
• (functionMeta) "namedFunction()"
• (Symbol(symbolKey)) "Symbol(symbolValue)"
├── ing/:hello (GET)
│ • (onRequest) ["anonymous()","namedFunction()"]
│ • (onTimeout) ["anonymous()"]
│ • (genericMeta) "meta"
│ • (mixedMeta) ["mixed items",{"an":"object"}]
│ • (objectMeta) {"one":"1","two":2}
│ • (functionMeta) "namedFunction()"
│ • (Symbol(symbolKey)) "Symbol(symbolValue)"
├── ed/:hello (PUT)
│ • (onRequest) ["anonymous()","namedFunction()"]
│ • (onTimeout) ["anonymous()"]
│ • (genericMeta) "meta"
│ • (mixedMeta) ["mixed items",{"an":"object"}]
│ • (objectMeta) {"one":"1","two":2}
│ • (functionMeta) "namedFunction()"
│ • (Symbol(symbolKey)) "Symbol(symbolValue)"
└── /:hello (GET) {"version":"1.1.2"}
/:hello (GET) {"version":"2.0.0"}
`
const arraySpecific = findMyWay.prettyPrint({ commonPrefix: false, includeMeta: ['onRequest', 'mixedMeta', 'nonExistent'] })
const arraySpecificExpected = `\
└── /test (GET)
• (onRequest) ["anonymous()","namedFunction()"]
• (mixedMeta) ["mixed items",{"an":"object"}]
/test (GET) {"host":"auth.fastify.io"}
• (onRequest) ["anonymous()","namedFunction()"]
• (mixedMeta) ["mixed items",{"an":"object"}]
├── ing/:hello (GET)
│ • (onRequest) ["anonymous()","namedFunction()"]
│ • (mixedMeta) ["mixed items",{"an":"object"}]
├── ed/:hello (PUT)
│ • (onRequest) ["anonymous()","namedFunction()"]
│ • (mixedMeta) ["mixed items",{"an":"object"}]
└── /:hello (GET) {"version":"1.1.2"}
/:hello (GET) {"version":"2.0.0"}
`
const arrayNoMeta = findMyWay.prettyPrint({ commonPrefix: false, includeMeta: false })
const arrayNoMetaExpected = `\
└── /test (GET)
/test (GET) {"host":"auth.fastify.io"}
├── ing/:hello (GET)
├── ed/:hello (PUT)
└── /:hello (GET) {"version":"1.1.2"}
/:hello (GET) {"version":"2.0.0"}
`
t.assert.equal(typeof arrayTree, 'string')
t.assert.equal(arrayTree, arrayExpected)
t.assert.equal(typeof arraySpecific, 'string')
t.assert.equal(arraySpecific, arraySpecificExpected)
t.assert.equal(typeof arrayNoMeta, 'string')
t.assert.equal(arrayNoMeta, arrayNoMetaExpected)
})
test('pretty print includeMeta - buildPrettyMeta function', t => {
t.plan(4)
const findMyWay = FindMyWay({
buildPrettyMeta: route => {
return { metaKey: route.method === 'PUT' ? 'Hide PUT route path' : route.path }
}
})
const namedFunction = () => {}
const store = {
onRequest: [() => {}, namedFunction],
onTimeout: [() => {}],
genericMeta: 'meta',
mixedMeta: ['mixed items', { an: 'object' }],
objectMeta: { one: '1', two: 2 },
functionMeta: namedFunction
}
store[Symbol('symbolKey')] = Symbol('symbolValue')
findMyWay.on('GET', '/test', () => {}, store)
findMyWay.on('GET', '/test', { constraints: { host: 'auth.fastify.io' } }, () => {}, store)
findMyWay.on('GET', '/test/:hello', () => {}, store)
findMyWay.on('PUT', '/test/:hello', () => {}, store)
findMyWay.on('POST', '/test/:hello', () => {}, store)
findMyWay.on('GET', '/test/:hello', { constraints: { version: '1.1.2' } }, () => {})
findMyWay.on('GET', '/test/:hello', { constraints: { version: '2.0.0' } }, () => {})
const arrayTree = findMyWay.prettyPrint({ commonPrefix: false, includeMeta: true })
const arrayExpected = `\
└── /test (GET)
• (metaKey) "/test"
/test (GET) {"host":"auth.fastify.io"}
• (metaKey) "/test"
└── /:hello (GET, POST)
• (metaKey) "/test/:hello"
/:hello (PUT)
• (metaKey) "Hide PUT route path"
/:hello (GET) {"version":"1.1.2"}
• (metaKey) "/test/:hello"
/:hello (GET) {"version":"2.0.0"}
• (metaKey) "/test/:hello"
`
const radixTree = findMyWay.prettyPrint({ includeMeta: true })
const radixExpected = `\
└── /
└── test (GET)
• (metaKey) "/test"
test (GET) {"host":"auth.fastify.io"}
• (metaKey) "/test"
└── /
└── :hello (GET, POST)
• (metaKey) "/test/:hello"
:hello (PUT)
• (metaKey) "Hide PUT route path"
:hello (GET) {"version":"1.1.2"}
• (metaKey) "/test/:hello"
:hello (GET) {"version":"2.0.0"}
• (metaKey) "/test/:hello"
`
t.assert.equal(typeof arrayTree, 'string')
t.assert.equal(arrayTree, arrayExpected)
t.assert.equal(typeof radixTree, 'string')
t.assert.equal(radixTree, radixExpected)
})
test('pretty print - print all methods', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.all('/test', () => {})
const tree = findMyWay.prettyPrint()
const expected = `\
└── /
└── test (ACL, BIND, CHECKOUT, CONNECT, COPY, DELETE, GET, HEAD, LINK, LOCK, \
M-SEARCH, MERGE, MKACTIVITY, MKCALENDAR, MKCOL, MOVE, NOTIFY, OPTIONS, PATCH, \
POST, PROPFIND, PROPPATCH, PURGE, PUT, QUERY, REBIND, REPORT, SEARCH, SOURCE, \
SUBSCRIBE, TRACE, UNBIND, UNLINK, UNLOCK, UNSUBSCRIBE)
`
t.assert.equal(typeof tree, 'string')
t.assert.equal(tree, expected)
})

54
node_modules/find-my-way/test/querystring.test.js generated vendored Normal file
View File

@@ -0,0 +1,54 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('should sanitize the url - query', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', (req, res, params, store, query) => {
t.assert.deepEqual(query, { hello: 'world' })
t.assert.ok('inside the handler')
})
findMyWay.lookup({ method: 'GET', url: '/test?hello=world', headers: {} }, null)
})
test('should sanitize the url - hash', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', (req, res, params, store, query) => {
t.assert.deepEqual(query, { hello: '' })
t.assert.ok('inside the handler')
})
findMyWay.lookup({ method: 'GET', url: '/test#hello', headers: {} }, null)
})
test('handles path and query separated by ; with useSemicolonDelimiter enabled', t => {
t.plan(2)
const findMyWay = FindMyWay({
useSemicolonDelimiter: true
})
findMyWay.on('GET', '/test', (req, res, params, store, query) => {
t.assert.deepEqual(query, { jsessionid: '123456' })
t.assert.ok('inside the handler')
})
findMyWay.lookup({ method: 'GET', url: '/test;jsessionid=123456', headers: {} }, null)
})
test('handles path and query separated by ? using ; in the path', t => {
t.plan(2)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test;jsessionid=123456', (req, res, params, store, query) => {
t.assert.deepEqual(query, { foo: 'bar' })
t.assert.ok('inside the handler')
})
findMyWay.lookup({ method: 'GET', url: '/test;jsessionid=123456?foo=bar', headers: {} }, null)
})

269
node_modules/find-my-way/test/regex.test.js generated vendored Normal file
View File

@@ -0,0 +1,269 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('route with matching regex', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: () => {
t.assert.fail('route not matched')
}
})
findMyWay.on('GET', '/test/:id(^\\d+$)', () => {
t.assert.ok('regex match')
})
findMyWay.lookup({ method: 'GET', url: '/test/12', headers: {} }, null)
})
test('route without matching regex', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: () => {
t.assert.ok('route not matched')
}
})
findMyWay.on('GET', '/test/:id(^\\d+$)', () => {
t.assert.fail('regex match')
})
findMyWay.lookup({ method: 'GET', url: '/test/test', headers: {} }, null)
})
test('route with an extension regex 2', t => {
t.plan(2)
const findMyWay = FindMyWay({
defaultRoute: (req) => {
t.assert.fail(`route not matched: ${req.url}`)
}
})
findMyWay.on('GET', '/test/S/:file(^\\S+).png', () => {
t.assert.ok('regex match')
})
findMyWay.on('GET', '/test/D/:file(^\\D+).png', () => {
t.assert.ok('regex match')
})
findMyWay.lookup({ method: 'GET', url: '/test/S/foo.png', headers: {} }, null)
findMyWay.lookup({ method: 'GET', url: '/test/D/foo.png', headers: {} }, null)
})
test('nested route with matching regex', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: () => {
t.assert.fail('route not matched')
}
})
findMyWay.on('GET', '/test/:id(^\\d+$)/hello', () => {
t.assert.ok('regex match')
})
findMyWay.lookup({ method: 'GET', url: '/test/12/hello', headers: {} }, null)
})
test('mixed nested route with matching regex', t => {
t.plan(2)
const findMyWay = FindMyWay({
defaultRoute: () => {
t.assert.fail('route not matched')
}
})
findMyWay.on('GET', '/test/:id(^\\d+$)/hello/:world', (req, res, params) => {
t.assert.equal(params.id, '12')
t.assert.equal(params.world, 'world')
})
findMyWay.lookup({ method: 'GET', url: '/test/12/hello/world', headers: {} }, null)
})
test('mixed nested route with double matching regex', t => {
t.plan(2)
const findMyWay = FindMyWay({
defaultRoute: () => {
t.assert.fail('route not matched')
}
})
findMyWay.on('GET', '/test/:id(^\\d+$)/hello/:world(^\\d+$)', (req, res, params) => {
t.assert.equal(params.id, '12')
t.assert.equal(params.world, '15')
})
findMyWay.lookup({ method: 'GET', url: '/test/12/hello/15', headers: {} }, null)
})
test('mixed nested route without double matching regex', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: () => {
t.assert.ok('route not matched')
}
})
findMyWay.on('GET', '/test/:id(^\\d+$)/hello/:world(^\\d+$)', (req, res, params) => {
t.assert.fail('route mathed')
})
findMyWay.lookup({ method: 'GET', url: '/test/12/hello/test', headers: {} }, null)
})
test('route with an extension regex', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: () => {
t.assert.fail('route not matched')
}
})
findMyWay.on('GET', '/test/:file(^\\d+).png', () => {
t.assert.ok('regex match')
})
findMyWay.lookup({ method: 'GET', url: '/test/12.png', headers: {} }, null)
})
test('route with an extension regex - no match', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: () => {
t.assert.ok('route not matched')
}
})
findMyWay.on('GET', '/test/:file(^\\d+).png', () => {
t.assert.fail('regex match')
})
findMyWay.lookup({ method: 'GET', url: '/test/aa.png', headers: {} }, null)
})
test('safe decodeURIComponent', t => {
t.plan(1)
const findMyWay = FindMyWay({
defaultRoute: () => {
t.assert.ok('route not matched')
}
})
findMyWay.on('GET', '/test/:id(^\\d+$)', () => {
t.assert.fail('we should not be here')
})
t.assert.deepEqual(
findMyWay.find('GET', '/test/hel%"Flo', {}),
null
)
})
test('Should check if a regex is safe to use', t => {
t.plan(13)
const noop = () => {}
// https://github.com/substack/safe-regex/blob/master/test/regex.js
const good = [
/\bOakland\b/,
/\b(Oakland|San Francisco)\b/i,
/^\d+1337\d+$/i,
/^\d+(1337|404)\d+$/i,
/^\d+(1337|404)*\d+$/i,
RegExp(Array(26).join('a?') + Array(26).join('a'))
]
const bad = [
/^(a?){25}(a){25}$/,
RegExp(Array(27).join('a?') + Array(27).join('a')),
/(x+x+)+y/,
/foo|(x+x+)+y/,
/(a+){10}y/,
/(a+){2}y/,
/(.*){1,32000}[bc]/
]
const findMyWay = FindMyWay()
good.forEach(regex => {
try {
findMyWay.on('GET', `/test/:id(${regex.toString()})`, noop)
t.assert.ok('ok')
findMyWay.off('GET', `/test/:id(${regex.toString()})`)
} catch (err) {
t.assert.fail(err)
}
})
bad.forEach(regex => {
try {
findMyWay.on('GET', `/test/:id(${regex.toString()})`, noop)
t.assert.fail('should throw')
} catch (err) {
t.assert.ok(err)
}
})
})
test('Disable safe regex check', t => {
t.plan(13)
const noop = () => {}
// https://github.com/substack/safe-regex/blob/master/test/regex.js
const good = [
/\bOakland\b/,
/\b(Oakland|San Francisco)\b/i,
/^\d+1337\d+$/i,
/^\d+(1337|404)\d+$/i,
/^\d+(1337|404)*\d+$/i,
RegExp(Array(26).join('a?') + Array(26).join('a'))
]
const bad = [
/^(a?){25}(a){25}$/,
RegExp(Array(27).join('a?') + Array(27).join('a')),
/(x+x+)+y/,
/foo|(x+x+)+y/,
/(a+){10}y/,
/(a+){2}y/,
/(.*){1,32000}[bc]/
]
const findMyWay = FindMyWay({ allowUnsafeRegex: true })
good.forEach(regex => {
try {
findMyWay.on('GET', `/test/:id(${regex.toString()})`, noop)
t.assert.ok('ok')
findMyWay.off('GET', `/test/:id(${regex.toString()})`)
} catch (err) {
t.assert.fail(err)
}
})
bad.forEach(regex => {
try {
findMyWay.on('GET', `/test/:id(${regex.toString()})`, noop)
t.assert.ok('ok')
findMyWay.off('GET', `/test/:id(${regex.toString()})`)
} catch (err) {
t.assert.fail(err)
}
})
})
test('prevent back-tracking', { timeout: 20 }, (t) => {
t.plan(0)
const findMyWay = FindMyWay({
defaultRoute: () => {
t.assert.fail('route not matched')
}
})
findMyWay.on('GET', '/:foo-:bar-', (req, res, params) => {})
findMyWay.find('GET', '/' + '-'.repeat(16000) + 'a', { host: 'fastify.io' })
})

View File

@@ -0,0 +1,45 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
function initializeRoutes (router, handler, quantity) {
for (const x of Array(quantity).keys()) {
router.on('GET', '/test-route-' + x, handler)
}
return router
}
test('verify routes registered', t => {
const assertPerTest = 5
const quantity = 5
// 1 (check length) + quantity of routes * quantity of tests per route
t.plan(1 + (quantity * assertPerTest))
let findMyWay = FindMyWay()
const defaultHandler = (req, res, params) => res.end(JSON.stringify({ hello: 'world' }))
findMyWay = initializeRoutes(findMyWay, defaultHandler, quantity)
t.assert.equal(findMyWay.routes.length, quantity)
findMyWay.routes.forEach((route, idx) => {
t.assert.equal(route.method, 'GET')
t.assert.equal(route.path, '/test-route-' + idx)
t.assert.deepStrictEqual(route.opts, {})
t.assert.equal(route.handler, defaultHandler)
t.assert.equal(route.store, undefined)
})
})
test('verify routes registered and deregister', t => {
// 1 (check length) + quantity of routes * quantity of tests per route
t.plan(2)
let findMyWay = FindMyWay()
const quantity = 2
const defaultHandler = (req, res, params) => res.end(JSON.stringify({ hello: 'world' }))
findMyWay = initializeRoutes(findMyWay, defaultHandler, quantity)
t.assert.equal(findMyWay.routes.length, quantity)
findMyWay.off('GET', '/test-route-0')
t.assert.equal(findMyWay.routes.length, quantity - 1)
})

368
node_modules/find-my-way/test/server.test.js generated vendored Normal file
View File

@@ -0,0 +1,368 @@
'use strict'
const { test } = require('node:test')
const http = require('http')
const FindMyWay = require('../')
test('basic router with http server', (t, done) => {
t.plan(6)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', (req, res, params) => {
t.assert.ok(req)
t.assert.ok(res)
t.assert.ok(params)
res.end(JSON.stringify({ hello: 'world' }))
})
const server = http.createServer((req, res) => {
findMyWay.lookup(req, res)
})
server.listen(0, async err => {
t.assert.ifError(err)
server.unref()
const res = await fetch(`http://localhost:${server.address().port}/test`)
t.assert.equal(res.status, 200)
t.assert.deepEqual(await res.json(), { hello: 'world' })
done()
})
})
test('router with params with http server', (t, done) => {
t.plan(6)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test/:id', (req, res, params) => {
t.assert.ok(req)
t.assert.ok(res)
t.assert.equal(params.id, 'hello')
res.end(JSON.stringify({ hello: 'world' }))
})
const server = http.createServer((req, res) => {
findMyWay.lookup(req, res)
})
server.listen(0, async err => {
t.assert.ifError(err)
server.unref()
const res = await fetch(`http://localhost:${server.address().port}/test/hello`)
t.assert.equal(res.status, 200)
t.assert.deepEqual(await res.json(), { hello: 'world' })
done()
})
})
test('default route', (t, done) => {
t.plan(2)
const findMyWay = FindMyWay({
defaultRoute: (req, res) => {
res.statusCode = 404
res.end()
}
})
const server = http.createServer((req, res) => {
findMyWay.lookup(req, res)
})
server.listen(0, async err => {
t.assert.ifError(err)
server.unref()
const res = await fetch(`http://localhost:${server.address().port}`)
t.assert.equal(res.status, 404)
done()
})
})
test('automatic default route', (t, done) => {
t.plan(2)
const findMyWay = FindMyWay()
const server = http.createServer((req, res) => {
findMyWay.lookup(req, res)
})
server.listen(0, async err => {
t.assert.ifError(err)
server.unref()
const res = await fetch(`http://localhost:${server.address().port}`)
t.assert.equal(res.status, 404)
done()
})
})
test('maps two routes when trailing slash should be trimmed', (t, done) => {
t.plan(21)
const findMyWay = FindMyWay({
ignoreTrailingSlash: true
})
findMyWay.on('GET', '/test/', (req, res, params) => {
t.assert.ok(req)
t.assert.ok(res)
t.assert.ok(params)
res.end('test')
})
findMyWay.on('GET', '/othertest', (req, res, params) => {
t.assert.ok(req)
t.assert.ok(res)
t.assert.ok(params)
res.end('othertest')
})
const server = http.createServer((req, res) => {
findMyWay.lookup(req, res)
})
server.listen(0, async err => {
t.assert.ifError(err)
server.unref()
const baseURL = 'http://localhost:' + server.address().port
let res = await fetch(`${baseURL}/test/`)
t.assert.equal(res.status, 200)
t.assert.deepEqual(await res.text(), 'test')
res = await fetch(`${baseURL}/test`)
t.assert.equal(res.status, 200)
t.assert.deepEqual(await res.text(), 'test')
res = await fetch(`${baseURL}/othertest`)
t.assert.equal(res.status, 200)
t.assert.deepEqual(await res.text(), 'othertest')
res = await fetch(`${baseURL}/othertest/`)
t.assert.equal(res.status, 200)
t.assert.deepEqual(await res.text(), 'othertest')
done()
})
})
test('does not trim trailing slash when ignoreTrailingSlash is false', (t, done) => {
t.plan(7)
const findMyWay = FindMyWay({
ignoreTrailingSlash: false
})
findMyWay.on('GET', '/test/', (req, res, params) => {
t.assert.ok(req)
t.assert.ok(res)
t.assert.ok(params)
res.end('test')
})
const server = http.createServer((req, res) => {
findMyWay.lookup(req, res)
})
server.listen(0, async err => {
t.assert.ifError(err)
server.unref()
const baseURL = 'http://localhost:' + server.address().port
let res = await fetch(`${baseURL}/test/`)
t.assert.equal(res.status, 200)
t.assert.deepEqual(await res.text(), 'test')
res = await fetch(`${baseURL}/test`)
t.assert.equal(res.status, 404)
done()
})
})
test('does not map // when ignoreTrailingSlash is true', (t, done) => {
t.plan(7)
const findMyWay = FindMyWay({
ignoreTrailingSlash: false
})
findMyWay.on('GET', '/', (req, res, params) => {
t.assert.ok(req)
t.assert.ok(res)
t.assert.ok(params)
res.end('test')
})
const server = http.createServer((req, res) => {
findMyWay.lookup(req, res)
})
server.listen(0, async err => {
t.assert.ifError(err)
server.unref()
const baseURL = 'http://localhost:' + server.address().port
let res = await fetch(`${baseURL}/`)
t.assert.equal(res.status, 200)
t.assert.deepEqual(await res.text(), 'test')
res = await fetch(`${baseURL}//`)
t.assert.equal(res.status, 404)
done()
})
})
test('maps two routes when duplicate slashes should be trimmed', (t, done) => {
t.plan(21)
const findMyWay = FindMyWay({
ignoreDuplicateSlashes: true
})
findMyWay.on('GET', '//test', (req, res, params) => {
t.assert.ok(req)
t.assert.ok(res)
t.assert.ok(params)
res.end('test')
})
findMyWay.on('GET', '/othertest', (req, res, params) => {
t.assert.ok(req)
t.assert.ok(res)
t.assert.ok(params)
res.end('othertest')
})
const server = http.createServer((req, res) => {
findMyWay.lookup(req, res)
})
server.listen(0, async err => {
t.assert.ifError(err)
server.unref()
const baseURL = 'http://localhost:' + server.address().port
let res = await fetch(`${baseURL}//test`)
t.assert.equal(res.status, 200)
t.assert.deepEqual(await res.text(), 'test')
res = await fetch(`${baseURL}/test`)
t.assert.equal(res.status, 200)
t.assert.deepEqual(await res.text(), 'test')
res = await fetch(`${baseURL}/othertest`)
t.assert.equal(res.status, 200)
t.assert.deepEqual(await res.text(), 'othertest')
res = await fetch(`${baseURL}//othertest`)
t.assert.equal(res.status, 200)
t.assert.deepEqual(await res.text(), 'othertest')
done()
})
})
test('does not trim duplicate slashes when ignoreDuplicateSlashes is false', (t, done) => {
t.plan(7)
const findMyWay = FindMyWay({
ignoreDuplicateSlashes: false
})
findMyWay.on('GET', '//test', (req, res, params) => {
t.assert.ok(req)
t.assert.ok(res)
t.assert.ok(params)
res.end('test')
})
const server = http.createServer((req, res) => {
findMyWay.lookup(req, res)
})
server.listen(0, async err => {
t.assert.ifError(err)
server.unref()
const baseURL = 'http://localhost:' + server.address().port
let res = await fetch(`${baseURL}//test`)
t.assert.equal(res.status, 200)
t.assert.deepEqual(await res.text(), 'test')
res = await fetch(`${baseURL}/test`)
t.assert.equal(res.status, 404)
done()
})
})
test('does map // when ignoreDuplicateSlashes is true', (t, done) => {
t.plan(11)
const findMyWay = FindMyWay({
ignoreDuplicateSlashes: true
})
findMyWay.on('GET', '/', (req, res, params) => {
t.assert.ok(req)
t.assert.ok(res)
t.assert.ok(params)
res.end('test')
})
const server = http.createServer((req, res) => {
findMyWay.lookup(req, res)
})
server.listen(0, async err => {
t.assert.ifError(err)
server.unref()
const baseURL = 'http://localhost:' + server.address().port
let res = await fetch(`${baseURL}/`)
t.assert.equal(res.status, 200)
t.assert.deepEqual(await res.text(), 'test')
res = await fetch(`${baseURL}//`)
t.assert.equal(res.status, 200)
t.assert.deepEqual(await res.text(), 'test')
done()
})
})
test('versioned routes', (t, done) => {
t.plan(3)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', { constraints: { version: '1.2.3' } }, (req, res, params) => {
res.end('ok')
})
const server = http.createServer((req, res) => {
findMyWay.lookup(req, res)
})
server.listen(0, async err => {
t.assert.ifError(err)
server.unref()
let res = await fetch(`http://localhost:${server.address().port}/test`, {
headers: { 'Accept-Version': '1.2.3' }
})
t.assert.equal(res.status, 200)
res = await fetch(`http://localhost:${server.address().port}/test`, {
headers: { 'Accept-Version': '2.x' }
})
t.assert.equal(res.status, 404)
done()
})
})

44
node_modules/find-my-way/test/shorthands.test.js generated vendored Normal file
View File

@@ -0,0 +1,44 @@
'use strict'
const httpMethods = require('../lib/http-methods')
const { describe, test } = require('node:test')
const FindMyWay = require('../')
describe('should support shorthand', t => {
for (const i in httpMethods) {
const m = httpMethods[i]
const methodName = m.toLowerCase()
test('`.' + methodName + '`', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay[methodName]('/test', () => {
t.assert.ok('inside the handler')
})
findMyWay.lookup({ method: m, url: '/test', headers: {} }, null)
})
}
})
test('should support `.all` shorthand', t => {
t.plan(11)
const findMyWay = FindMyWay()
findMyWay.all('/test', () => {
t.assert.ok('inside the handler')
})
findMyWay.lookup({ method: 'GET', url: '/test', headers: {} }, null)
findMyWay.lookup({ method: 'DELETE', url: '/test', headers: {} }, null)
findMyWay.lookup({ method: 'HEAD', url: '/test', headers: {} }, null)
findMyWay.lookup({ method: 'PATCH', url: '/test', headers: {} }, null)
findMyWay.lookup({ method: 'POST', url: '/test', headers: {} }, null)
findMyWay.lookup({ method: 'PUT', url: '/test', headers: {} }, null)
findMyWay.lookup({ method: 'OPTIONS', url: '/test', headers: {} }, null)
findMyWay.lookup({ method: 'TRACE', url: '/test', headers: {} }, null)
findMyWay.lookup({ method: 'CONNECT', url: '/test', headers: {} }, null)
findMyWay.lookup({ method: 'COPY', url: '/test', headers: {} }, null)
findMyWay.lookup({ method: 'SUBSCRIBE', url: '/test', headers: {} }, null)
})

49
node_modules/find-my-way/test/store.test.js generated vendored Normal file
View File

@@ -0,0 +1,49 @@
'use strict'
const { test } = require('node:test')
const FindMyWay = require('../')
test('handler should have the store object', t => {
t.plan(1)
const findMyWay = FindMyWay()
findMyWay.on('GET', '/test', (req, res, params, store) => {
t.assert.equal(store.hello, 'world')
}, { hello: 'world' })
findMyWay.lookup({ method: 'GET', url: '/test', headers: {} }, null)
})
test('find a store object', t => {
t.plan(1)
const findMyWay = FindMyWay()
const fn = () => {}
findMyWay.on('GET', '/test', fn, { hello: 'world' })
t.assert.deepEqual(findMyWay.find('GET', '/test'), {
handler: fn,
params: {},
store: { hello: 'world' },
searchParams: {}
})
})
test('update the store', t => {
t.plan(2)
const findMyWay = FindMyWay()
let bool = false
findMyWay.on('GET', '/test', (req, res, params, store) => {
if (!bool) {
t.assert.equal(store.hello, 'world')
store.hello = 'hello'
bool = true
findMyWay.lookup({ method: 'GET', url: '/test', headers: {} }, null)
} else {
t.assert.equal(store.hello, 'hello')
}
}, { hello: 'world' })
findMyWay.lookup({ method: 'GET', url: '/test', headers: {} }, null)
})

182
node_modules/find-my-way/test/types/router.test-d.ts generated vendored Normal file
View File

@@ -0,0 +1,182 @@
import { expectType } from 'tsd'
import Router from '../../'
import { Http2ServerRequest, Http2ServerResponse } from 'http2'
import { IncomingMessage, ServerResponse } from 'http'
let http1Req!: IncomingMessage;
let http1Res!: ServerResponse;
let http2Req!: Http2ServerRequest;
let http2Res!: Http2ServerResponse;
let ctx!: { req: IncomingMessage; res: ServerResponse };
let done!: (err: Error | null, result: any) => void;
// HTTP1
{
let handler!: Router.Handler<Router.HTTPVersion.V1>
const router = Router({
ignoreTrailingSlash: true,
ignoreDuplicateSlashes: true,
allowUnsafeRegex: false,
caseSensitive: false,
maxParamLength: 42,
querystringParser: (queryString) => {},
defaultRoute (http1Req, http1Res) {},
onBadUrl (path, http1Req, http1Res) {},
constraints: {
foo: {
name: 'foo',
mustMatchWhenDerived: true,
storage () {
return {
get (version) { return handler },
set (version, handler) {}
}
},
deriveConstraint(req) { return '1.0.0' },
validate(value) { if (typeof value === "string") { throw new Error("invalid")} }
}
}
})
expectType<Router.Instance<Router.HTTPVersion.V1>>(router)
expectType<void>(router.on('GET', '/', () => {}))
expectType<void>(router.on(['GET', 'POST'], '/', () => {}))
expectType<void>(router.on('GET', '/', { constraints: { version: '1.0.0' }}, () => {}))
expectType<void>(router.on('GET', '/', () => {}, {}))
expectType<void>(router.on('GET', '/', {constraints: { version: '1.0.0' }}, () => {}, {}))
expectType<void>(router.get('/', () => {}))
expectType<void>(router.get('/', { constraints: { version: '1.0.0' }}, () => {}))
expectType<void>(router.get('/', () => {}, {}))
expectType<void>(router.get('/', { constraints: { version: '1.0.0' }}, () => {}, {}))
expectType<void>(router.off('GET', '/'))
expectType<void>(router.off(['GET', 'POST'], '/'))
expectType<any>(router.lookup(http1Req, http1Res))
expectType<any>(router.lookup(http1Req, http1Res, done));
expectType<any>(router.lookup(http1Req, http1Res, ctx, done));
expectType<Router.FindResult<Router.HTTPVersion.V1> | null>(router.find('GET', '/'))
expectType<Router.FindResult<Router.HTTPVersion.V1> | null>(router.find('GET', '/', {}))
expectType<Router.FindResult<Router.HTTPVersion.V1> | null>(router.find('GET', '/', {version: '1.0.0'}))
expectType<Router.FindRouteResult<Router.HTTPVersion.V1> | null>(router.findRoute('GET', '/'));
expectType<Router.FindRouteResult<Router.HTTPVersion.V1> | null>(router.findRoute('GET', '/', {}));
expectType<Router.FindRouteResult<Router.HTTPVersion.V1> | null>(router.findRoute('GET', '/', {version: '1.0.0'}));
expectType<void>(router.reset())
expectType<string>(router.prettyPrint())
expectType<string>(router.prettyPrint({ method: 'GET' }))
expectType<string>(router.prettyPrint({ commonPrefix: false }))
expectType<string>(router.prettyPrint({ commonPrefix: true }))
expectType<string>(router.prettyPrint({ includeMeta: true }))
expectType<string>(router.prettyPrint({ includeMeta: ['test', Symbol('test')] }))
}
// HTTP2
{
const constraints: { [key: string]: Router.ConstraintStrategy<Router.HTTPVersion.V2, string> } = {
foo: {
name: 'foo',
mustMatchWhenDerived: true,
storage () {
return {
get (version) { return handler },
set (version, handler) {}
}
},
deriveConstraint(req) { return '1.0.0' },
validate(value) { if (typeof value === "string") { throw new Error("invalid")} }
}
}
let handler!: Router.Handler<Router.HTTPVersion.V2>
const router = Router<Router.HTTPVersion.V2>({
ignoreTrailingSlash: true,
ignoreDuplicateSlashes: true,
allowUnsafeRegex: false,
caseSensitive: false,
maxParamLength: 42,
querystringParser: (queryString) => {},
defaultRoute (http1Req, http1Res) {},
onBadUrl (path, http1Req, http1Res) {},
constraints
})
expectType<Router.Instance<Router.HTTPVersion.V2>>(router)
expectType<void>(router.on('GET', '/', () => {}))
expectType<void>(router.on(['GET', 'POST'], '/', () => {}))
expectType<void>(router.on('GET', '/', { constraints: { version: '1.0.0' }}, () => {}))
expectType<void>(router.on('GET', '/', () => {}, {}))
expectType<void>(router.on('GET', '/', { constraints: { version: '1.0.0' }}, () => {}, {}))
expectType<void>(router.addConstraintStrategy(constraints.foo))
expectType<void>(router.get('/', () => {}))
expectType<void>(router.get('/', { constraints: { version: '1.0.0' }}, () => {}))
expectType<void>(router.get('/', () => {}, {}))
expectType<void>(router.get('/', { constraints: { version: '1.0.0' }}, () => {}, {}))
expectType<void>(router.off('GET', '/'))
expectType<void>(router.off(['GET', 'POST'], '/'))
expectType<any>(router.lookup(http2Req, http2Res))
expectType<any>(router.lookup(http2Req, http2Res, done));
expectType<any>(router.lookup(http2Req, http2Res, ctx, done));
expectType<Router.FindResult<Router.HTTPVersion.V2> | null>(router.find('GET', '/', {}))
expectType<Router.FindResult<Router.HTTPVersion.V2> | null>(router.find('GET', '/', {version: '1.0.0', host: 'fastify.io'}))
expectType<void>(router.reset())
expectType<string>(router.prettyPrint())
}
// Custom Constraint
{
let handler!: Router.Handler<Router.HTTPVersion.V1>
interface AcceptAndContentType { accept?: string, contentType?: string }
const customConstraintWithObject: Router.ConstraintStrategy<Router.HTTPVersion.V1, AcceptAndContentType> = {
name: "customConstraintWithObject",
deriveConstraint<Context>(req: Router.Req<Router.HTTPVersion.V1>, ctx: Context | undefined): AcceptAndContentType {
return {
accept: req.headers.accept,
contentType: req.headers["content-type"]
}
},
validate(value: unknown): void {},
storage () {
return {
get (version) { return handler },
set (version, handler) {}
}
}
}
const storageWithObject = customConstraintWithObject.storage()
const acceptAndContentType: AcceptAndContentType = { accept: 'application/json', contentType: 'application/xml' }
expectType<AcceptAndContentType>(customConstraintWithObject.deriveConstraint(http1Req, http1Res))
expectType<Router.Handler<Router.HTTPVersion.V1> | null>(storageWithObject.get(acceptAndContentType));
expectType<void>(storageWithObject.set(acceptAndContentType, () => {}));
const customConstraintWithDefault: Router.ConstraintStrategy<Router.HTTPVersion.V1> = {
name: "customConstraintWithObject",
deriveConstraint<Context>(req: Router.Req<Router.HTTPVersion.V1>, ctx: Context | undefined): string {
return req.headers.accept ?? ''
},
storage () {
return {
get (version) { return handler },
set (version, handler) {}
}
}
}
const storageWithDefault = customConstraintWithDefault.storage()
expectType<string>(customConstraintWithDefault.deriveConstraint(http1Req, http1Res))
expectType<Router.Handler<Router.HTTPVersion.V1> | null>(storageWithDefault.get(''));
expectType<void>(storageWithDefault.set('', () => {}));
}