import { Resovler } from './Resovler'; export declare type Binding = { id: any; value: BindCallback; singleton: boolean; cachedValue?: unknown; }; /** * Shape of lookup node pulled using `ioc.lookup` method. This node * can be passed to `ioc.use`, or `ioc.make` or `ioc.useEsm` to * skip many checks and resolve the binding right away. */ export declare type LookupNode = { namespace: NameSapceType; type: 'binding' | 'autoload'; }; export declare type BindCallback = (app?: Container) => unknown; export declare type NameSapceType = Function | string | symbol; /** * Shape of autoloaded cache entry */ export declare type AutoloadCacheItem = { diskPath: string; cachedValue: any; }; export declare class Container { constructor(); protected _basePath: string; static instance: Container; private bindings; /** * Copy of aliases */ private aliases; /** * Autoloaded directories under a namespace */ autoloads: { [namespace: string]: string; }; /** * An array of autoloaded aliases, stored along side with * `autoloads` for a quick lookup on keys */ autoloadedAliases: string[]; /** * Autoloaded cache to improve the `require` speed, which is dog slow. */ private autoloadsCache; private injector; private _fakes; private _proxiesEnabled; protected _instances: Map; /** * Flush the container of all bindings and resolved instances. * * @return void */ flush(): void; /** * Set the globally available instance of the container. * * @return static */ static getInstance(): T; /** * Set the shared instance of the container. */ static setInstance(container: any): any | null; /** * Instruct IoC container to use proxies when returning * bindings from `use` and `make` methods. */ useProxies(enable?: boolean): this; /** * Wraps object and class to a proxy for enabling the fakes * API */ private wrapAsProxy; /** * Use the binding by resolving it from the container. The resolve method * does some great work to resolve the value for you. * * 1. The name will be searched for an existing binding. * 2. Checked against aliases. * 3. Checked against autoloaded directories. * 4. Fallback to Node.js `require` call. * * @example * ```js * app.use('View') // alias * app.use('Module/Src/View') // binding * app.use('App/Services/User') // Autoload * app.use('lodash') // Fallback to Node.js require * ``` */ use(namespace: NameSapceType): T; instance(name: string, instance: any): T; useFake(namespace: NameSapceType, value: any): T; /** * A boolean telling if a fake exists for a binding or * not. */ hasFake(namespace: NameSapceType): boolean; /** * Register a singleton binding in the container. * * @example * ```js * app.singleton('App/User', function () { * return new User() * }) * ``` */ singleton(namespace: NameSapceType, concrete: Function | BindCallback): void; /** * Register a binding with the container. * * @example * ```js * app.bind('App/User', function () { * return new User() * }) * ``` */ bind(namespace: NameSapceType, concrete: Function | BindCallback, singleton?: boolean): void; /** * Register a fake for an existing binding. The fakes only work when * `TNGRAPHQL_IOC_PROXY` environment variable is set to `true`. tngraphql * will set it to true automatically during testing. * * NOTE: The return value of fakes is always cached, since multiple * calls to `use` after that should point to a same return value. * * @example * ```ts * app.fake('App/User', function () { * return new FakeUser() * }) * ``` */ fake(namespace: NameSapceType, concrete: Function | BindCallback): void; /** * Get the callback to be used when building a type. * * @param namespace * @param concrete */ getClosure(namespace: NameSapceType, concrete: Function | BindCallback): (app: any, args: any) => any; /** * Define alias for an existing binding. IoC container doesn't handle uniqueness * conflicts for you and it's upto you to make sure that all aliases are * unique. * * Use method [[hasAlias]] to know, if an alias already exists. */ alias(namespace: NameSapceType, alias: string): void; make(concrete: NameSapceType, args?: any[], binding?: boolean): T; /** * Resolves a namespace and injects it's dependencies to it */ resolveAndMake(node: LookupNode, args?: string[], binding?: boolean): any; /** * Resolve the value for a namespace by trying all possible * combinations of `bindings`, `aliases`, `autoloading` * and finally falling back to `nodejs require`. */ resolve(node: LookupNode, args?: any[]): any; /** * Returns the binding return value. This method must be called when * [[hasBinding]] returns true. */ private resolveBinding; /** * Load a file from the disk using Node.js require method. The output of * require is further cached to improve peformance. * * Make sure to call this method when [[isAutoloadNamespace]] returns true. */ private resolveAutoload; /** * Returns the base namespace for an autoloaded namespace. * * @example * ```js * app.autoload(join(__dirname, 'app'), 'App') * * app.getAutoloadBaseNamespace('App/Services/Foo') // returns App * ``` */ getAutoloadBaseNamespace(namespace: string): string | undefined; compileNamespace(namespace: string, prefixNamespace?: string): string; /** * Lookup a namespace and return it's lookup node. The lookup node can speed * up resolving of namespaces via `use`, `useEsm` or `make` methods. */ lookup(namespace: NameSapceType, prefixNamespace?: string): LookupNode | null; /** * Returns a boolean telling if binding for a given namespace * exists or not. Also optionally check for aliases too. * * @example * ```js * app.hasBinding('Module/Src/View') // namespace * app.hasBinding('View') // alias * ``` */ hasBinding(namespace: NameSapceType, checkAliases?: boolean): boolean; /** * Returns a boolean telling if an alias * exists */ hasAlias(name: string): boolean; /** * Returns the complete namespace for a given alias. To avoid * `undefined` values, it is recommended to use `hasAlias` * before using this method. */ getAliasNamespace(namespace: string): NameSapceType | undefined; /** * Returns a boolean telling if namespace is part of autoloads or not. * This method results may vary from the [[use]] method, since * the `use` method gives prefrence to the `bindings` first. * * ### NOTE: * Check the following example carefully. * * @example * ```js * // Define autoload namespace * app.autoload(join(__dirname, 'app'), 'App') * * app.bind('App/Services/Foo', () => { * }) * * // return true * app.isAutoloadNamespace('App/Services/Foo') * * // Returns value from `bind` and not disk * app.use('isAutoloadNamespace') * ``` */ isAutoloadNamespace(namespace: string): boolean; /** * Execute a callback by resolving bindings from the container and only * executed when all bindings exists in the container. * * This is a clean way to use bindings, when you are not that user application * is using them or not. * * ```js * boot () { * this.app.with(['App/Src/Auth'], (Auth) => { * Auth.extend('mongo', 'serializer', function () { * return new MongoSerializer() * }) * }) * } * ``` */ with(namespaces: NameSapceType[], callback: (...args: any[]) => void): void; /** * Define an alias for an existing directory and require * files without fighting with relative paths. * ``` */ autoload(directoryPath: string, namespace: string): void; call(target: any, method: any, args?: any[]): any; /** * Returns the resolver instance to resolve Ioc container bindings with * little ease. Since, the IoCResolver uses an in-memory cache to * improve the lookup speed, we suggest keeping a reference to * the output of this method to leverage caching */ getResolver(fallbackMethod?: string, rcNamespaceKey?: string, fallbackNamespace?: string): Resovler; /** * Restore the fake */ restore(name: NameSapceType): void; /** * Clear all of the instances from the container. * * @return void */ forgetInstances(): void; /** * Drop all of the stale instances and aliases. * * @param string $abstract * @return void */ protected dropStaleInstances(name: NameSapceType): void; }