Support named route groups; canonical namespaces

This commit is contained in:
Garrett Mills 2021-03-21 21:10:42 -05:00
parent a93cd6d192
commit e8fdb04ae8
Signed by: garrettmills
GPG Key ID: D2BF5FBA8298F246
2 changed files with 60 additions and 2 deletions

View File

@ -1,16 +1,39 @@
import {Collection} from "@extollo/util"
import {Collection, ErrorWithContext} from "@extollo/util"
import {AppClass} from "../../lifecycle/AppClass"
import {RouteHandler} from "./Route"
import {Container} from "@extollo/di"
import {Logging} from "../../service/Logging";
export class RouteGroup extends AppClass {
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}>()
public static getCurrentGroupHierarchy(): RouteGroup[] {
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(
public readonly group: () => void | Promise<void>,
public readonly prefix: string

View File

@ -2,7 +2,7 @@
* Base type for a canonical definition.
*/
import {Canon} from "./Canon";
import {universalPath, UniversalPath} from "@extollo/util";
import {universalPath, UniversalPath, ErrorWithContext} from "@extollo/util";
import {Logging} from "./Logging";
import {Inject} from "@extollo/di";
import * as nodePath from 'path'
@ -14,6 +14,8 @@ export interface CanonicalDefinition {
imported: any,
}
export type CanonicalResolver<T> = (key: string) => T | undefined
/**
* Base type for a canonical name reference.
*/
@ -55,6 +57,12 @@ export abstract class Canonical<T> extends Unit {
*/
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.
* @param {string} reference
@ -86,9 +94,36 @@ export abstract class Canonical<T> extends Unit {
}
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]
}
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() {
for await ( const entry of this.path.walk() ) {
if ( !entry.endsWith(this.suffix) ) {