我的node项目首次提交!!!
This commit is contained in:
34
node_modules/find-my-way/.github/dependabot.yml
generated
vendored
Normal file
34
node_modules/find-my-way/.github/dependabot.yml
generated
vendored
Normal 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
67
node_modules/find-my-way/.github/workflows/node.js.yml
generated
vendored
Normal 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
21
node_modules/find-my-way/LICENSE
generated
vendored
Normal 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
823
node_modules/find-my-way/README.md
generated
vendored
Normal file
@@ -0,0 +1,823 @@
|
||||
# find-my-way
|
||||
|
||||
[](http://standardjs.com/) [](https://github.com/delvedor/find-my-way/actions/workflows/node.js.yml) [](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
35
node_modules/find-my-way/benchmark/bench-thread.js
generated
vendored
Normal 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
156
node_modules/find-my-way/benchmark/bench.js
generated
vendored
Normal 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
113
node_modules/find-my-way/benchmark/compare-branches.js
generated
vendored
Normal 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
55
node_modules/find-my-way/benchmark/uri-decoding.js
generated
vendored
Normal 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
29
node_modules/find-my-way/example.js
generated
vendored
Normal 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
237
node_modules/find-my-way/index.d.ts
generated
vendored
Normal 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
828
node_modules/find-my-way/index.js
generated
vendored
Normal 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
170
node_modules/find-my-way/lib/constrainer.js
generated
vendored
Normal 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
174
node_modules/find-my-way/lib/handler-storage.js
generated
vendored
Normal 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
13
node_modules/find-my-way/lib/http-methods.js
generated
vendored
Normal 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
228
node_modules/find-my-way/lib/node.js
generated
vendored
Normal 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
8
node_modules/find-my-way/lib/null-object.js
generated
vendored
Normal 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
168
node_modules/find-my-way/lib/pretty-print.js
generated
vendored
Normal 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
36
node_modules/find-my-way/lib/strategies/accept-host.js
generated
vendored
Normal 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')
|
||||
}
|
||||
}
|
||||
64
node_modules/find-my-way/lib/strategies/accept-version.js
generated
vendored
Normal file
64
node_modules/find-my-way/lib/strategies/accept-version.js
generated
vendored
Normal 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
15
node_modules/find-my-way/lib/strategies/http-method.js
generated
vendored
Normal 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
96
node_modules/find-my-way/lib/url-sanitizer.js
generated
vendored
Normal 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
57
node_modules/find-my-way/package.json
generated
vendored
Normal 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
230
node_modules/find-my-way/test/case-insensitive.test.js
generated
vendored
Normal 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)
|
||||
})
|
||||
130
node_modules/find-my-way/test/constraint.custom-versioning.test.js
generated
vendored
Normal file
130
node_modules/find-my-way/test/constraint.custom-versioning.test.js
generated
vendored
Normal 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.')
|
||||
)
|
||||
})
|
||||
111
node_modules/find-my-way/test/constraint.custom.async.test.js
generated
vendored
Normal file
111
node_modules/find-my-way/test/constraint.custom.async.test.js
generated
vendored
Normal 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
273
node_modules/find-my-way/test/constraint.custom.test.js
generated
vendored
Normal 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)
|
||||
})
|
||||
289
node_modules/find-my-way/test/constraint.default-versioning.test.js
generated
vendored
Normal file
289
node_modules/find-my-way/test/constraint.default-versioning.test.js
generated
vendored
Normal 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
104
node_modules/find-my-way/test/constraint.host.test.js
generated
vendored
Normal 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
108
node_modules/find-my-way/test/constraints.test.js
generated
vendored
Normal 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)
|
||||
})
|
||||
46
node_modules/find-my-way/test/custom-querystring-parser.test.js
generated
vendored
Normal file
46
node_modules/find-my-way/test/custom-querystring-parser.test.js
generated
vendored
Normal 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
484
node_modules/find-my-way/test/errors.test.js
generated
vendored
Normal 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 \'{}\'')
|
||||
}
|
||||
})
|
||||
})
|
||||
34
node_modules/find-my-way/test/fastify-issue-3129.test.js
generated
vendored
Normal file
34
node_modules/find-my-way/test/fastify-issue-3129.test.js
generated
vendored
Normal 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
|
||||
)
|
||||
})
|
||||
23
node_modules/find-my-way/test/fastify-issue-3957.test.js
generated
vendored
Normal file
23
node_modules/find-my-way/test/fastify-issue-3957.test.js
generated
vendored
Normal 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
275
node_modules/find-my-way/test/find-route.test.js
generated
vendored
Normal 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
16
node_modules/find-my-way/test/find.test.js
generated
vendored
Normal 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
13
node_modules/find-my-way/test/for-in-loop.test.js
generated
vendored
Normal 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
30
node_modules/find-my-way/test/full-url.test.js
generated
vendored
Normal 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
218
node_modules/find-my-way/test/has-route.test.js
generated
vendored
Normal 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
27
node_modules/find-my-way/test/host-storage.test.js
generated
vendored
Normal 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')
|
||||
})
|
||||
44
node_modules/find-my-way/test/http2/constraint.host.test.js
generated
vendored
Normal file
44
node_modules/find-my-way/test/http2/constraint.host.test.js
generated
vendored
Normal 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
31
node_modules/find-my-way/test/issue-101.test.js
generated
vendored
Normal 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
206
node_modules/find-my-way/test/issue-104.test.js
generated
vendored
Normal 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
31
node_modules/find-my-way/test/issue-110.test.js
generated
vendored
Normal 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
80
node_modules/find-my-way/test/issue-132.test.js
generated
vendored
Normal 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
24
node_modules/find-my-way/test/issue-145.test.js
generated
vendored
Normal 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
21
node_modules/find-my-way/test/issue-149.test.js
generated
vendored
Normal 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
54
node_modules/find-my-way/test/issue-151.test.js
generated
vendored
Normal 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
21
node_modules/find-my-way/test/issue-154.test.js
generated
vendored
Normal 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
88
node_modules/find-my-way/test/issue-161.test.js
generated
vendored
Normal 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
397
node_modules/find-my-way/test/issue-17.test.js
generated
vendored
Normal 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
80
node_modules/find-my-way/test/issue-175.test.js
generated
vendored
Normal 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
18
node_modules/find-my-way/test/issue-182.test.js
generated
vendored
Normal 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
44
node_modules/find-my-way/test/issue-190.test.js
generated
vendored
Normal 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
79
node_modules/find-my-way/test/issue-20.test.js
generated
vendored
Normal 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
121
node_modules/find-my-way/test/issue-206.test.js
generated
vendored
Normal 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
50
node_modules/find-my-way/test/issue-221.test.js
generated
vendored
Normal 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
94
node_modules/find-my-way/test/issue-234.test.js
generated
vendored
Normal 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
119
node_modules/find-my-way/test/issue-238.test.js
generated
vendored
Normal 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
30
node_modules/find-my-way/test/issue-240.test.js
generated
vendored
Normal 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
32
node_modules/find-my-way/test/issue-241.test.js
generated
vendored
Normal 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
51
node_modules/find-my-way/test/issue-247.test.js
generated
vendored
Normal 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
31
node_modules/find-my-way/test/issue-254.test.js
generated
vendored
Normal 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
618
node_modules/find-my-way/test/issue-28.test.js
generated
vendored
Normal 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
14
node_modules/find-my-way/test/issue-280.test.js
generated
vendored
Normal 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
37
node_modules/find-my-way/test/issue-285.test.js
generated
vendored
Normal 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
231
node_modules/find-my-way/test/issue-330.test.js
generated
vendored
Normal 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
149
node_modules/find-my-way/test/issue-44.test.js
generated
vendored
Normal 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
75
node_modules/find-my-way/test/issue-46.test.js
generated
vendored
Normal 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
108
node_modules/find-my-way/test/issue-49.test.js
generated
vendored
Normal 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
131
node_modules/find-my-way/test/issue-59.test.js
generated
vendored
Normal 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
28
node_modules/find-my-way/test/issue-62.test.js
generated
vendored
Normal 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
23
node_modules/find-my-way/test/issue-63.test.js
generated
vendored
Normal 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
50
node_modules/find-my-way/test/issue-67.test.js
generated
vendored
Normal 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
19
node_modules/find-my-way/test/issue-93.test.js
generated
vendored
Normal 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
29
node_modules/find-my-way/test/lookup-async.test.js
generated
vendored
Normal 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
58
node_modules/find-my-way/test/lookup.test.js
generated
vendored
Normal 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
17
node_modules/find-my-way/test/matching-order.test.js
generated
vendored
Normal 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
44
node_modules/find-my-way/test/max-param-length.test.js
generated
vendored
Normal 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
830
node_modules/find-my-way/test/methods.test.js
generated
vendored
Normal 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
36
node_modules/find-my-way/test/null-object.test.js
generated
vendored
Normal 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
72
node_modules/find-my-way/test/on-bad-url.test.js
generated
vendored
Normal 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
216
node_modules/find-my-way/test/optional-params.test.js
generated
vendored
Normal 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
126
node_modules/find-my-way/test/params-collisions.test.js
generated
vendored
Normal 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)
|
||||
})
|
||||
53
node_modules/find-my-way/test/path-params-match.test.js
generated
vendored
Normal file
53
node_modules/find-my-way/test/path-params-match.test.js
generated
vendored
Normal 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
596
node_modules/find-my-way/test/pretty-print-tree.test.js
generated
vendored
Normal 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
680
node_modules/find-my-way/test/pretty-print.test.js
generated
vendored
Normal 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
54
node_modules/find-my-way/test/querystring.test.js
generated
vendored
Normal 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
269
node_modules/find-my-way/test/regex.test.js
generated
vendored
Normal 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' })
|
||||
})
|
||||
45
node_modules/find-my-way/test/routes-registered.test.js
generated
vendored
Normal file
45
node_modules/find-my-way/test/routes-registered.test.js
generated
vendored
Normal 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
368
node_modules/find-my-way/test/server.test.js
generated
vendored
Normal 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
44
node_modules/find-my-way/test/shorthands.test.js
generated
vendored
Normal 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
49
node_modules/find-my-way/test/store.test.js
generated
vendored
Normal 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
182
node_modules/find-my-way/test/types/router.test-d.ts
generated
vendored
Normal 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('', () => {}));
|
||||
}
|
||||
Reference in New Issue
Block a user