import {Canonical} from './Canonical' import {Singleton} from '../di' import {Maybe} from '../util' /** * Error throw when a duplicate canonical key is registered. * @extends Error */ export class DuplicateResolverKeyError extends Error { constructor(key: string) { super(`There is already a canonical unit with the scope ${key} registered.`) } } /** * Error throw when a key that isn't registered with the service. * @extends Error */ export class NoSuchCanonicalResolverKeyError extends Error { constructor(key: string) { super(`There is no such canonical unit with the scope ${key} registered.`) } } /** * Service used to access various canonical resources. */ @Singleton() export class Canon { /** * The resources registered with this service. Map of canonical service name * to canonical service instance. * @type object */ protected resources: { [key: string]: Canonical } = {} /** * Get a canonical resource by its name key. * @param {string} key * @return Canonical */ resource(key: string): Canonical { if ( !this.resources[key] ) { throw new NoSuchCanonicalResolverKeyError(key) } return this.resources[key] as Canonical } /** * Get a canonical item from a fully-qualified canonical name. * This is just a quality-of-life wrapper around `this.resource(...).get(...)`. * @param key */ getFromFullyQualified(key: string): Maybe { const [namespace, ...parts] = key.split('::') const unqualified = parts.join('::') return this.resource(namespace).get(unqualified) } /** * Register a canonical resource. * @param {Canonical} unit */ registerCanonical(unit: Canonical): void { const key = unit.canonicalItems if ( this.resources[key] ) { throw new DuplicateResolverKeyError(key) } this.resources[key] = unit } }