Support named route groups; canonical namespaces
This commit is contained in:
parent
a93cd6d192
commit
e8fdb04ae8
@ -1,16 +1,39 @@
|
|||||||
import {Collection} from "@extollo/util"
|
import {Collection, ErrorWithContext} from "@extollo/util"
|
||||||
import {AppClass} from "../../lifecycle/AppClass"
|
import {AppClass} from "../../lifecycle/AppClass"
|
||||||
import {RouteHandler} from "./Route"
|
import {RouteHandler} from "./Route"
|
||||||
|
import {Container} from "@extollo/di"
|
||||||
|
import {Logging} from "../../service/Logging";
|
||||||
|
|
||||||
export class RouteGroup extends AppClass {
|
export class RouteGroup extends AppClass {
|
||||||
private static currentGroupNesting: RouteGroup[] = []
|
private static currentGroupNesting: RouteGroup[] = []
|
||||||
|
|
||||||
|
protected static namedGroups: {[key: string]: () => void } = {}
|
||||||
|
|
||||||
protected middlewares: Collection<{ stage: 'pre' | 'post', handler: RouteHandler }> = new Collection<{stage: "pre" | "post"; handler: RouteHandler}>()
|
protected middlewares: Collection<{ stage: 'pre' | 'post', handler: RouteHandler }> = new Collection<{stage: "pre" | "post"; handler: RouteHandler}>()
|
||||||
|
|
||||||
public static getCurrentGroupHierarchy(): RouteGroup[] {
|
public static getCurrentGroupHierarchy(): RouteGroup[] {
|
||||||
return [...this.currentGroupNesting]
|
return [...this.currentGroupNesting]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static named(name: string, define: () => void) {
|
||||||
|
if ( this.namedGroups[name] ) {
|
||||||
|
Container.getContainer()
|
||||||
|
.make<Logging>(Logging)
|
||||||
|
.warn(`Replacing named route group: ${name}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.namedGroups[name] = define
|
||||||
|
}
|
||||||
|
|
||||||
|
public static include(name: string) {
|
||||||
|
if (!this.namedGroups[name]) {
|
||||||
|
throw new ErrorWithContext(`No route group exists with name: ${name}`, {name})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.namedGroups[name]()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public readonly group: () => void | Promise<void>,
|
public readonly group: () => void | Promise<void>,
|
||||||
public readonly prefix: string
|
public readonly prefix: string
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* Base type for a canonical definition.
|
* Base type for a canonical definition.
|
||||||
*/
|
*/
|
||||||
import {Canon} from "./Canon";
|
import {Canon} from "./Canon";
|
||||||
import {universalPath, UniversalPath} from "@extollo/util";
|
import {universalPath, UniversalPath, ErrorWithContext} from "@extollo/util";
|
||||||
import {Logging} from "./Logging";
|
import {Logging} from "./Logging";
|
||||||
import {Inject} from "@extollo/di";
|
import {Inject} from "@extollo/di";
|
||||||
import * as nodePath from 'path'
|
import * as nodePath from 'path'
|
||||||
@ -14,6 +14,8 @@ export interface CanonicalDefinition {
|
|||||||
imported: any,
|
imported: any,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type CanonicalResolver<T> = (key: string) => T | undefined
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base type for a canonical name reference.
|
* Base type for a canonical name reference.
|
||||||
*/
|
*/
|
||||||
@ -55,6 +57,12 @@ export abstract class Canonical<T> extends Unit {
|
|||||||
*/
|
*/
|
||||||
protected loadedItems: { [key: string]: T } = {}
|
protected loadedItems: { [key: string]: T } = {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object mapping canonical namespaces to resolver functions.
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
protected loadedNamespaces: { [key: string]: CanonicalResolver<T> } = {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a canonical reference from its string form to a CanonicalReference.
|
* Resolve a canonical reference from its string form to a CanonicalReference.
|
||||||
* @param {string} reference
|
* @param {string} reference
|
||||||
@ -86,9 +94,36 @@ export abstract class Canonical<T> extends Unit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public get(key: string): T | undefined {
|
public get(key: string): T | undefined {
|
||||||
|
if ( key.startsWith('@') ) {
|
||||||
|
const [namespace, ...rest] = key.split(':')
|
||||||
|
key = rest.join(':')
|
||||||
|
|
||||||
|
if ( !this.loadedNamespaces[namespace] ) {
|
||||||
|
throw new ErrorWithContext(`Unable to find namespace for ${this.canonicalItem}: ${namespace}`, {
|
||||||
|
canonicalItem: this.canonicalItem,
|
||||||
|
namespace,
|
||||||
|
key,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.loadedNamespaces[namespace](key)
|
||||||
|
}
|
||||||
|
|
||||||
return this.loadedItems[key]
|
return this.loadedItems[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public registerNamespace(name: string, resolver: CanonicalResolver<T>) {
|
||||||
|
if ( !name.startsWith('@') ) {
|
||||||
|
throw new ErrorWithContext(`Canonical namespaces must start with @.`, { name })
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( this.loadedNamespaces[name] ) {
|
||||||
|
this.logging.warn(`Replacing canonical namespace resolver for: ${name}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loadedNamespaces[name] = resolver
|
||||||
|
}
|
||||||
|
|
||||||
public async up() {
|
public async up() {
|
||||||
for await ( const entry of this.path.walk() ) {
|
for await ( const entry of this.path.walk() ) {
|
||||||
if ( !entry.endsWith(this.suffix) ) {
|
if ( !entry.endsWith(this.suffix) ) {
|
||||||
|
Loading…
Reference in New Issue
Block a user