lib/src/http/routing/RouteGroup.ts

116 lines
3.2 KiB
TypeScript
Raw Normal View History

2021-06-03 03:36:25 +00:00
import {Collection, ErrorWithContext} from '../../util'
import {AppClass} from '../../lifecycle/AppClass'
import {RouteHandler} from './Route'
import {Container} from '../../di'
import {Logging} from '../../service/Logging'
2021-03-25 13:50:13 +00:00
/**
* Class that defines a group of Routes in the application, with a prefix.
*/
export class RouteGroup extends AppClass {
2021-03-25 13:50:13 +00:00
/**
* The current set of nested groups. This is used when compiling route groups.
* @private
*/
private static currentGroupNesting: RouteGroup[] = []
2021-03-25 13:50:13 +00:00
/**
* Mapping of group names to group registration functions.
* @protected
*/
protected static namedGroups: {[key: string]: () => void } = {}
2021-03-25 13:50:13 +00:00
/**
* Array of middlewares that should apply to all routes in this group.
* @protected
*/
2021-06-03 03:36:25 +00:00
protected middlewares: Collection<{ stage: 'pre' | 'post', handler: RouteHandler }> = new Collection<{stage: 'pre' | 'post'; handler: RouteHandler}>()
2021-03-09 15:42:19 +00:00
2021-03-25 13:50:13 +00:00
/**
* Get the current group nesting.
*/
public static getCurrentGroupHierarchy(): RouteGroup[] {
return [...this.currentGroupNesting]
}
2021-03-25 13:50:13 +00:00
/**
* Create a new named group that can be registered at a later time, by name.
*
* @example
* ```typescript
* RouteGroup.named('auth', () => {
* Route.group('/auth', () => {
* Route.get('/login', 'auth:Forms.getLogin')
* })
* })
* ```
*
* @param name
* @param define
*/
2021-06-03 03:36:25 +00:00
public static named(name: string, define: () => void): void {
if ( this.namedGroups[name] ) {
Container.getContainer()
.make<Logging>(Logging)
.warn(`Replacing named route group: ${name}`)
}
this.namedGroups[name] = define
}
2021-03-25 13:50:13 +00:00
/**
* Register the routes from a named group by calling its registration function.
*
* @example
* From the example above, we can register the auth `/auth/*` routes, like so:
* ```typescript
* RouteGroup.include('auth')
* ```
*
* @param name
*/
2021-06-03 03:36:25 +00:00
public static include(name: string): void {
if (!this.namedGroups[name]) {
throw new ErrorWithContext(`No route group exists with name: ${name}`, {name})
}
this.namedGroups[name]()
}
constructor(
2021-03-25 13:50:13 +00:00
/** Function to register routes for this group. */
public readonly group: () => void | Promise<void>,
2021-03-25 13:50:13 +00:00
/** The route prefix of this group. */
2021-06-03 03:36:25 +00:00
public readonly prefix: string,
) {
super()
}
2021-03-09 15:42:19 +00:00
2021-03-25 13:50:13 +00:00
/** Register the given middleware to be applied before all routes in this group. */
2021-06-03 03:36:25 +00:00
pre(middleware: RouteHandler): this {
2021-03-09 15:42:19 +00:00
this.middlewares.push({
stage: 'pre',
2021-06-03 03:36:25 +00:00
handler: middleware,
2021-03-09 15:42:19 +00:00
})
return this
}
2021-03-25 13:50:13 +00:00
/** Register the given middleware to be applied after all routes in this group. */
2021-06-03 03:36:25 +00:00
post(middleware: RouteHandler): this {
2021-03-09 15:42:19 +00:00
this.middlewares.push({
stage: 'post',
handler: middleware,
})
return this
}
2021-03-25 13:50:13 +00:00
/** Return the middlewares that apply to this group. */
2021-06-03 03:36:25 +00:00
getGroupMiddlewareDefinitions(): Collection<{ stage: 'pre' | 'post', handler: RouteHandler }> {
2021-03-09 15:42:19 +00:00
return this.middlewares
}
}