import {Container, MaybeDependency, MaybeFactory} from './Container' import {DependencyKey} from './types' /** * A container that uses some parent container as a base, but * can have other factories distinct from that parent. * * If an instance is not found in this container, it will be resolved from * the parent container. * * However, if an instance IS found in this container, it will ALWAYS be * resolved from this container, rather than the parent. * * This can be used to create scope-specific containers that can still resolve * the global dependencies, while keeping scope-specific dependencies separate. * * @example * The Request class from @extollo/lib is a ScopedContainer. It can resolve * all dependencies that exist in the global Container, but it can also have * request-specific services (like the Session) injected into it. * * @extends Container */ export class ScopedContainer extends Container { /** * Create a new scoped container based on a parent container instance. * @param container */ public static fromParent(container: Container): ScopedContainer { return new ScopedContainer(container) } constructor( private parentContainer: Container, ) { super() this.registerSingletonInstance(ScopedContainer, this) } hasInstance(key: DependencyKey): boolean { return super.hasInstance(key) || this.parentContainer.hasInstance(key) } hasKey(key: DependencyKey): boolean { return super.hasKey(key) || this.parentContainer.hasKey(key) } getExistingInstance(key: DependencyKey): MaybeDependency { const inst = super.getExistingInstance(key) if ( inst ) { return inst } return this.parentContainer.getExistingInstance(key) } resolve(key: DependencyKey): MaybeFactory { const factory = super.resolve(key) if ( factory ) { return factory } return this.parentContainer?.resolve(key) } }