generated from sapphiredev/sapphire-template
-
-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(router)!: change router system (#590)
Added `Route#path`, which is an array of each path part Added `RouteStore#router`, which is a tree router structure Added `ApiRequest#routerNode`, which is the matched node in the router Added `ApiRequest#route`, which is the matched route Added `ApiResponse#methodNotAllowed()` Added event `routerBranchMethodNotAllowed` Added listener to send `405 Method Not Allowed` where applicable Added tests to ensure the router's correct functionality BREAKING CHANGE: Moved `RouteStore#match` to a listener BREAKING CHANGE: Replaced `node:events` with `@vladfrangu/async_event_emitter` BREAKING CHANGE: Removed `route` parameter in the `Middleware#run` method, use `request.route` instead BREAKING CHANGE: Removed `Route#router` property BREAKING CHANGE: Removed `RouteStore#methods` property BREAKING CHANGE: Removed objects in router events, use `request.route` and `request.routerNode` instead BREAKING CHANGE: Renamed `ServerEvents` enum to `ServerEvent` BREAKING CHANGE: Renamed event `match` to `routerFound` BREAKING CHANGE: Renamed event `noMatch` to `routerBranchNotFound`
- Loading branch information
Showing
28 changed files
with
728 additions
and
258 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,13 @@ | ||
import { LoaderStrategy } from '@sapphire/pieces'; | ||
import { Collection } from 'discord.js'; | ||
import type { Route } from './Route'; | ||
import type { RouteStore } from './RouteStore'; | ||
|
||
export class RouteLoaderStrategy extends LoaderStrategy<Route> { | ||
public override onLoad(store: RouteStore, piece: Route): void { | ||
for (const method of piece.methods) { | ||
store.methods.ensure(method, () => new Collection()).set(piece, piece.router); | ||
} | ||
store.router.add(piece); | ||
} | ||
|
||
public override onUnload(store: RouteStore, piece: Route): void { | ||
for (const method of piece.methods) { | ||
const methods = store.methods.get(method); | ||
if (typeof methods === 'undefined') continue; | ||
|
||
methods.delete(piece); | ||
if (methods.size === 0) store.methods.delete(method); | ||
} | ||
store.router.remove(piece); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,73 +1,15 @@ | ||
import { Store } from '@sapphire/pieces'; | ||
import { isNullish } from '@sapphire/utilities'; | ||
import { Collection } from 'discord.js'; | ||
import { URLSearchParams } from 'url'; | ||
import type { RouteData } from '../utils/RouteData'; | ||
import { Route } from './Route'; | ||
import { RouteLoaderStrategy } from './RouteLoaderStrategy'; | ||
import type { MethodName } from './http/HttpMethods'; | ||
|
||
const slash = '/'.charCodeAt(0); | ||
import { RouterRoot } from './router/RouterRoot'; | ||
|
||
/** | ||
* @since 1.0.0 | ||
*/ | ||
export class RouteStore extends Store<Route, 'routes'> { | ||
public readonly methods = new Collection<MethodName, Collection<Route, RouteData>>(); | ||
public readonly router = new RouterRoot(); | ||
|
||
public constructor() { | ||
super(Route, { name: 'routes', strategy: new RouteLoaderStrategy() }); | ||
} | ||
|
||
public match(request: Route.Request): Route | null { | ||
const { method } = request; | ||
|
||
// If there is no method, we can't match a route so return null | ||
if (typeof method === 'undefined') { | ||
return null; | ||
} | ||
|
||
// We get all the routes that are tied to the provided method to have a smaller list to filter through | ||
const methodTable = this.methods.get(method as MethodName); | ||
|
||
// If there are no routes of the provided type then we won't find any route so we return null | ||
if (isNullish(methodTable)) { | ||
return null; | ||
} | ||
|
||
const { splits, querystring } = this.parseURL(request.url); | ||
|
||
for (const [route, router] of methodTable.entries()) { | ||
const result = router.match(splits); | ||
if (result === null) continue; | ||
|
||
request.params = result; | ||
request.query = Object.fromEntries(new URLSearchParams(querystring).entries()); | ||
|
||
return route; | ||
} | ||
|
||
return null; | ||
} | ||
|
||
private parseURL(url = '') { | ||
const index = url.indexOf('?'); | ||
|
||
let pathname: string; | ||
let querystring: string; | ||
if (index === -1) { | ||
pathname = url; | ||
querystring = ''; | ||
} else { | ||
pathname = url.substring(0, index); | ||
querystring = url.substring(index + 1); | ||
} | ||
|
||
if (pathname.charCodeAt(0) === slash) pathname = pathname.substring(1); | ||
if (pathname.length > 0 && pathname.charCodeAt(pathname.length - 1) === slash) pathname = pathname.substring(0, pathname.length - 1); | ||
|
||
const splits = pathname.split('/'); | ||
|
||
return { splits, querystring }; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.