@adonisjs/fold
Version:
A simple and straight forward implementation for IoC container in JavaScript
1 lines • 79.8 kB
Source Map (JSON)
{"version":3,"sources":["../src/container.ts","../src/debug.ts","../src/helpers.ts","../src/deferred_promise.ts","../src/resolver.ts","../src/provider.ts","../src/contextual_bindings_builder.ts","../src/decorators/inject.ts","../src/module_caller.ts","../src/module_importer.ts","../src/module_expression.ts"],"sourcesContent":["/*\n * @adonisjs/fold\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { inspect } from 'node:util'\nimport { InvalidArgumentsException } from '@poppinss/utils'\n\nimport type {\n Make,\n Hooks,\n Swaps,\n Bindings,\n BindingKey,\n Constructor,\n ErrorCreator,\n HookCallback,\n BindingValues,\n BindingResolver,\n ExtractFunctions,\n ContainerOptions,\n AbstractConstructor,\n ContextualBindings,\n} from './types.js'\n\nimport debug from './debug.js'\nimport { enqueue, isClass } from './helpers.js'\nimport { ContainerResolver } from './resolver.js'\nimport { ContextBindingsBuilder } from './contextual_bindings_builder.js'\n\n/**\n * The container class exposes the API to register bindings, values\n * and resolve them.\n *\n * Known bindings types can be defined at the time of the constructing\n * the container.\n *\n * ```ts\n * new Container<{ 'route': Route, encryption: Encryption }>()\n * ```\n *\n * You can resolve bindings and construct classes as follows\n *\n * ```ts\n * await container.make(BINDING_NAME)\n * await container.make(CLASS_CONSTRUCTOR)\n * ```\n */\nexport class Container<KnownBindings extends Record<any, any>> {\n /**\n * A set of defined aliases for the bindings\n */\n #aliases: Map<Partial<keyof KnownBindings>, keyof KnownBindings | AbstractConstructor<any>> =\n new Map()\n\n /**\n * Contextual bindings are same as binding, but instead defined\n * for a parent class constructor.\n *\n * The contextual bindings can only be registered for class constructors, because\n * that is what gets injected to the class.\n */\n #contextualBindings: Map<Constructor<any>, ContextualBindings> = new Map()\n\n /**\n * A collection of bindings with registered swapped implementations. Swaps can only\n * be define for a class, because the goal is swap the dependency tree defined\n * using the Inject decorator and inject decorator does not take anything\n * other than a class.\n */\n #swaps: Swaps = new Map()\n\n /**\n * Registered bindings. Singleton and normal bindings, both are\n * registered inside the bindings map\n */\n #bindings: Bindings = new Map()\n\n /**\n * Registered bindings as values. The values are preferred over the bindings.\n */\n #bindingValues: BindingValues = new Map()\n\n /**\n * Registered hooks.\n */\n #hooks: Hooks = new Map()\n\n /**\n * Container options\n */\n #options: ContainerOptions\n\n constructor(options?: ContainerOptions) {\n this.#options = options || {}\n }\n\n /**\n * Define an emitter instance to use\n */\n useEmitter(emitter: Exclude<ContainerOptions['emitter'], undefined>) {\n this.#options.emitter = emitter\n return this\n }\n\n /**\n * Create a container resolver to resolve bindings, or make classes.\n *\n * ```ts\n * const resolver = container.createResolver()\n * await resolver.make(CLASS_CONSTRUCTOR)\n * ```\n *\n * Bind values with the resolver. Resolver values are isolated from the\n * container.\n *\n * ```ts\n * resolver.bindValue(HttpContext, new HttpContext())\n * await resolver.make(UsersController)\n * ```\n */\n createResolver() {\n return new ContainerResolver<KnownBindings>(\n {\n bindings: this.#bindings,\n bindingValues: this.#bindingValues,\n swaps: this.#swaps,\n hooks: this.#hooks,\n aliases: this.#aliases,\n contextualBindings: this.#contextualBindings,\n },\n this.#options\n )\n }\n\n /**\n * Find if the container has a binding registered using the\n * \"bind\", the \"singleton\", or the \"bindValue\" methods.\n */\n hasBinding<Binding extends keyof KnownBindings>(binding: Binding): boolean\n hasBinding(binding: BindingKey): boolean\n hasBinding(binding: BindingKey): boolean {\n return (\n this.#aliases.has(binding) || this.#bindingValues.has(binding) || this.#bindings.has(binding)\n )\n }\n\n /**\n * Find if the container has all the bindings registered using the\n * \"bind\", the \"singleton\", or the \"bindValue\" methods.\n */\n hasAllBindings<Binding extends keyof KnownBindings>(bindings: Binding[]): boolean\n hasAllBindings(binding: BindingKey[]): boolean\n hasAllBindings(bindings: BindingKey[]): boolean {\n return bindings.every((binding) => this.hasBinding(binding))\n }\n\n /**\n * Resolves the binding or constructor a class instance as follows.\n *\n * - Resolve the binding from the values (if registered)\n * - Resolve the binding from the bindings (if registered)\n * - If binding is a class, then create a instance of it. The constructor\n * dependencies are further resolved as well.\n * - All other values are returned as it is.\n *\n * ```ts\n * await container.make('route')\n * await container.make(Database)\n * ```\n */\n make<Binding extends keyof KnownBindings>(\n binding: Binding,\n runtimeValues?: any[],\n createError?: ErrorCreator\n ): Promise<Binding extends string | symbol ? KnownBindings[Binding] : Make<Binding>>\n make<Binding>(\n binding: Binding,\n runtimeValues?: any[],\n createError?: ErrorCreator\n ): Promise<Make<Binding>>\n make<Binding>(\n binding: Binding,\n runtimeValues?: any[],\n createError?: ErrorCreator\n ): Promise<Make<Binding>> {\n return this.createResolver().make<Binding>(binding, runtimeValues, createError)\n }\n\n /**\n * Call a method on an object by injecting its dependencies. The method\n * dependencies are resolved in the same manner as a class constructor\n * dependencies.\n *\n * ```ts\n * await container.call(await container.make(UsersController), 'index')\n * ```\n */\n call<Value extends Record<any, any>, Method extends ExtractFunctions<Value>>(\n value: Value,\n method: Method,\n runtimeValues?: any[],\n createError?: ErrorCreator\n ): Promise<ReturnType<Value[Method]>> {\n return this.createResolver().call(value, method, runtimeValues, createError)\n }\n\n /**\n * Register an alias for a binding. The value can be a reference\n * to an existing binding or to a class constructor that will\n * instantiate to the same value as the alias.\n */\n alias<Alias extends keyof KnownBindings>(\n /**\n * An alias must always be defined as a string or a symbol. Classes cannot be\n * aliases\n */\n alias: Alias extends string | symbol ? Alias : never,\n\n /**\n * The value should either be the constructor point to the alias value\n * or reference to binding that has the same value as the alias\n */\n value:\n | AbstractConstructor<KnownBindings[Alias]>\n | Exclude<\n {\n [K in keyof KnownBindings]: KnownBindings[K] extends KnownBindings[Alias] ? K : never\n }[keyof KnownBindings],\n Alias\n >\n ): void {\n if (typeof alias !== 'string' && typeof alias !== 'symbol') {\n throw new InvalidArgumentsException(\n 'The container alias key must be of type \"string\" or \"symbol\"'\n )\n }\n\n this.#aliases.set(alias, value)\n }\n\n /**\n * Register a binding inside the container. The method receives a\n * key-value pair.\n *\n * - Key can be a string, symbol or a constructor.\n * - The value is always a factory function to construct the dependency.\n *\n * ```ts\n * container.bind('route', () => new Route())\n * await container.make('route')\n *\n * container.bind(Route, () => new Route())\n * await container.make(Route)\n *\n * const routeSymbol = Symbol('route')\n * container.bind(routeSymbol, () => new Route())\n * await container.make(routeSymbol)\n * ```\n */\n bind<Binding extends keyof KnownBindings>(\n /**\n * Need to narrow down the \"Binding\" for the case where \"KnownBindings\" are <any, any>\n */\n binding: Binding extends string | symbol ? Binding : never,\n resolver: BindingResolver<KnownBindings, KnownBindings[Binding]>\n ): void\n bind<Binding extends AbstractConstructor<any>>(\n binding: Binding,\n resolver: BindingResolver<KnownBindings, InstanceType<Binding>>\n ): void\n bind<Binding>(\n binding: Binding,\n resolver: BindingResolver<\n KnownBindings,\n Binding extends AbstractConstructor<infer A>\n ? A\n : Binding extends keyof KnownBindings\n ? KnownBindings[Binding]\n : never\n >\n ): void {\n if (typeof binding !== 'string' && typeof binding !== 'symbol' && !isClass(binding)) {\n throw new InvalidArgumentsException(\n 'The container binding key must be of type \"string\", \"symbol\", or a \"class constructor\"'\n )\n }\n\n debug('adding binding to container \"%O\"', binding)\n this.#bindings.set(binding, { resolver, isSingleton: false })\n }\n\n /**\n * Register a binding as a value\n *\n * ```ts\n * container.bindValue(Route, new Route())\n * ```\n */\n bindValue<Binding extends keyof KnownBindings>(\n /**\n * Need to narrow down the \"Binding\" for the case where \"KnownBindings\" are <any, any>\n */\n binding: Binding extends string | symbol ? Binding : never,\n value: KnownBindings[Binding]\n ): void\n bindValue<Binding extends AbstractConstructor<any>>(\n binding: Binding,\n value: InstanceType<Binding>\n ): void\n bindValue<Binding>(\n binding: Binding,\n value: Binding extends AbstractConstructor<infer A>\n ? A\n : Binding extends keyof KnownBindings\n ? KnownBindings[Binding]\n : never\n ): void {\n if (typeof binding !== 'string' && typeof binding !== 'symbol' && !isClass(binding)) {\n throw new InvalidArgumentsException(\n 'The container binding key must be of type \"string\", \"symbol\", or a \"class constructor\"'\n )\n }\n\n debug('adding value to container %O', binding)\n this.#bindingValues.set(binding, value)\n }\n\n /**\n * Register a binding as a single. The singleton method is same\n * as the bind method, but the factory function is invoked\n * only once.\n *\n * ```ts\n * container.singleton('route', () => new Route())\n * await container.make('route')\n *\n * container.singleton(Route, () => new Route())\n * await container.make(Route)\n *\n * const routeSymbol = Symbol('route')\n * container.singleton(routeSymbol, () => new Route())\n * await container.make(routeSymbol)\n * ```\n */\n singleton<Binding extends keyof KnownBindings>(\n /**\n * Need to narrow down the \"Binding\" for the case where \"KnownBindings\" are <any, any>\n */\n binding: Binding extends string | symbol ? Binding : never,\n resolver: BindingResolver<KnownBindings, KnownBindings[Binding]>\n ): void\n singleton<Binding extends AbstractConstructor<any>>(\n binding: Binding,\n resolver: BindingResolver<KnownBindings, InstanceType<Binding>>\n ): void\n singleton<Binding>(\n binding: Binding,\n resolver: BindingResolver<\n KnownBindings,\n Binding extends AbstractConstructor<infer A>\n ? A\n : Binding extends keyof KnownBindings\n ? KnownBindings[Binding]\n : never\n >\n ): void {\n if (typeof binding !== 'string' && typeof binding !== 'symbol' && !isClass(binding)) {\n throw new InvalidArgumentsException(\n 'The container binding key must be of type \"string\", \"symbol\", or a \"class constructor\"'\n )\n }\n\n debug('adding singleton to container %O', binding)\n this.#bindings.set(binding, { resolver: enqueue(resolver), isSingleton: true })\n }\n\n /**\n * Define a fake implementation for a binding or a class constructor.\n * Fakes have the highest priority when resolving dependencies\n * from the container.\n */\n swap<Binding extends AbstractConstructor<any>>(\n binding: Binding,\n resolver: BindingResolver<KnownBindings, InstanceType<Binding>>\n ): void {\n if (!isClass(binding)) {\n throw new InvalidArgumentsException(\n `Cannot call swap on value \"${inspect(binding)}\". Only classes can be swapped`\n )\n }\n\n debug('defining swap for %O', binding)\n this.#swaps.set(binding, resolver)\n }\n\n /**\n * Restore binding by removing its swap\n */\n restore(binding: AbstractConstructor<any>) {\n debug('removing swap for %s', binding)\n this.#swaps.delete(binding)\n }\n\n /**\n * Restore mentioned or all bindings by removing\n * their swaps\n */\n restoreAll(bindings?: AbstractConstructor<any>[]) {\n if (!bindings) {\n debug('removing all swaps')\n this.#swaps.clear()\n return\n }\n\n for (let binding of bindings) {\n this.restore(binding)\n }\n }\n\n /**\n * Define hooks to be executed after a binding has been resolved\n * from the container.\n *\n * The hooks are executed for\n *\n * - Bindings\n * - Only once for singletons\n * - And class constructor\n *\n * In other words, the hooks are not executed for direct values registered\n * with the container\n */\n resolving<Binding extends keyof KnownBindings>(\n binding: Binding extends string | symbol ? Binding : never,\n callback: HookCallback<KnownBindings, KnownBindings[Binding]>\n ): void\n resolving<Binding extends AbstractConstructor<any>>(\n binding: Binding,\n callback: HookCallback<KnownBindings, InstanceType<Binding>>\n ): void\n resolving<Binding extends BindingKey>(\n binding: Binding,\n callback: Binding extends AbstractConstructor<infer A>\n ? HookCallback<KnownBindings, A>\n : Binding extends keyof KnownBindings\n ? HookCallback<KnownBindings, KnownBindings[Binding]>\n : never\n ): void {\n binding = (this.#aliases.get(binding) as Binding) || binding\n\n if (!this.#hooks.has(binding)) {\n this.#hooks.set(binding, new Set())\n }\n\n const callbacks = this.#hooks.get(binding)!\n callbacks.add(callback)\n }\n\n /**\n * Create a contextual builder to define contextual bindings\n */\n when(parent: Constructor<any>): ContextBindingsBuilder<KnownBindings, AbstractConstructor<any>> {\n return new ContextBindingsBuilder(parent, this)\n }\n\n /**\n * Add a contextual binding for a given class constructor. A\n * contextual takes a parent, parent's dependency and a callback\n * to self resolve the dependency.\n *\n * For example:\n * - When \"UsersController\"\n * - Asks for \"Hash class\"\n * - Provide \"Argon2\" implementation\n */\n contextualBinding<Binding extends AbstractConstructor<any>>(\n parent: Constructor<any>,\n binding: Binding,\n resolver: BindingResolver<KnownBindings, Make<Binding>>\n ): void {\n if (!isClass(binding)) {\n throw new InvalidArgumentsException(\n `The binding value for contextual binding should be class`\n )\n }\n if (!isClass(parent)) {\n throw new InvalidArgumentsException(`The parent value for contextual binding should be class`)\n }\n\n debug('adding contextual binding %O to %O', binding, parent)\n\n /**\n * Create map for the parent if doesn't already exists\n */\n if (!this.#contextualBindings.has(parent)) {\n this.#contextualBindings.set(parent, new Map())\n }\n\n const parentBindings = this.#contextualBindings.get(parent)!\n parentBindings.set(binding, { resolver })\n }\n}\n","/*\n * @adonisjs/fold\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { debuglog } from 'node:util'\nexport default debuglog('adonisjs:fold')\n","/*\n * @adonisjs/fold\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { RuntimeException } from '@poppinss/utils'\n\nimport type { Constructor } from './types.js'\nimport { Deferred } from './deferred_promise.js'\n\n/**\n * Type guard and check if value is a class constructor. Plain old\n * functions are not considered as class constructor.\n */\nexport function isClass<T>(value: unknown): value is Constructor<T> {\n return typeof value === 'function' && value.toString().startsWith('class ')\n}\n\n/**\n * Runs a function inside an async function. This ensure that syncrohonous\n * errors are handled in the same way rejected promise is handled\n */\nasync function runAsAsync(callback: Function, args: any[]) {\n return callback(...args)\n}\n\n/**\n * Converts a function to a self contained queue, where each call to\n * the function is queued until the first call resolves or rejects.\n *\n * After the first call, the value is cached and used forever.\n */\nexport function enqueue(callback: Function) {\n /**\n * A flag to know if we are in the middleware of computing the\n * value.\n */\n let isComputingValue = false\n\n /**\n * The computed after the callback resolves\n */\n let computedValue: { value?: any; completed: boolean } = { completed: false }\n\n /**\n * The computed error the callback resolves\n */\n let computedError: { error?: any; completed: boolean } = { completed: false }\n\n /**\n * The internal queue of deferred promises.\n */\n let queue: Deferred<any>[] = []\n\n /**\n * Resolve pending queue promises\n */\n function resolvePromises(value: any) {\n isComputingValue = false\n computedValue.completed = true\n computedValue.value = value\n queue.forEach((promise) => promise.resolve(value))\n queue = []\n }\n\n /**\n * Reject pending queue promises\n */\n function rejectPromises(error: any) {\n isComputingValue = false\n computedError.completed = true\n computedError.error = error\n queue.forEach((promise) => promise.reject(error))\n queue = []\n }\n\n return function (...args: any): Promise<{ value: any; cached: boolean }> {\n /**\n * Already has value\n */\n if (computedValue.completed) {\n return computedValue.value\n }\n\n /**\n * Already ended with error\n */\n if (computedError.completed) {\n throw computedError.error\n }\n\n /**\n * In process, returning a deferred promise\n */\n if (isComputingValue) {\n const promise = new Deferred<{ value: any; cached: true }>()\n queue.push(promise)\n return promise.promise\n }\n\n isComputingValue = true\n\n /**\n * We could have removed this promise in favor of async/await. But then\n * we will have to call \"resolvePromises\" before returning the value.\n * However, we want the following promise to resolve first and\n * then resolve all other deferred promises.\n */\n return new Promise((resolve, reject) => {\n runAsAsync(callback, args)\n .then((value) => {\n resolve({ value, cached: false })\n resolvePromises({ value, cached: true })\n })\n .catch((error) => {\n reject(error)\n rejectPromises(error)\n })\n })\n }\n}\n\n/**\n * Dynamically import a module and ensure it has a default export\n */\nexport async function resolveDefault(importPath: string, parentURL: URL | string) {\n const resolvedPath = await import.meta.resolve!(importPath, parentURL)\n const moduleExports = await import(resolvedPath)\n\n /**\n * Make sure a default export exists\n */\n if (!moduleExports.default) {\n throw new RuntimeException(`Missing export default from \"${importPath}\" module`, {\n cause: {\n source: resolvedPath,\n },\n })\n }\n\n return moduleExports.default\n}\n","/*\n * @adonisjs/fold\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\n/**\n * Exports the `resolve` and the reject methods as part of the\n * class public API.\n *\n * It allows resolving and rejecting promises outside of the\n * class constructor.\n */\nexport class Deferred<T> {\n resolve!: (value: T | PromiseLike<T>) => void\n reject!: (reason?: any) => void\n promise: Promise<T> = new Promise<T>((resolve, reject) => {\n this.reject = reject\n this.resolve = resolve\n })\n}\n","/*\n * @adonisjs/fold\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { inspect } from 'node:util'\nimport { InvalidArgumentsException, RuntimeException } from '@poppinss/utils'\n\nimport type {\n Make,\n Hooks,\n Swaps,\n Bindings,\n BindingKey,\n Constructor,\n ErrorCreator,\n BindingValues,\n BindingResolver,\n ExtractFunctions,\n ContainerOptions,\n ContextualBindings,\n AbstractConstructor,\n InspectableConstructor,\n} from './types.js'\nimport debug from './debug.js'\nimport { isClass } from './helpers.js'\nimport { containerProvider } from './provider.js'\n\n/**\n * Container resolver exposes the APIs to resolve bindings. You can think\n * of resolver as an isolated container instance, with only the APIs\n * to resolve bindings.\n *\n * ```ts\n * const container = new Container()\n * const resolver = container.createResolver()\n *\n * await resolver.make(BINDING_NAME)\n * await resolver.make(CLASS_CONSTRUCTOR)\n * ```\n */\nexport class ContainerResolver<KnownBindings extends Record<any, any>> {\n /**\n * Reference to the container aliases. They are shared between the container\n * and resolver.\n *\n * We do not mutate this property within the resolver\n */\n #containerAliases: Map<\n Partial<keyof KnownBindings>,\n keyof KnownBindings | AbstractConstructor<any>\n >\n\n /**\n * Pre-registered contextual bindings. They are shared between the container\n * and resolver.\n *\n * We do not mutate this property within the resolver\n */\n #containerContextualBindings: Map<Constructor<any>, ContextualBindings>\n\n /**\n * Pre-registered bindings. They are shared between the container\n * and resolver.\n *\n * We do not mutate this property within the resolver\n */\n #containerBindings: Bindings\n\n /**\n * Pre-registered bindings. They are shared between the container\n * and resolver.\n *\n * We mutate this property within the resolver to set singleton\n * cached values\n */\n #containerBindingValues: BindingValues\n\n /**\n * Pre-registered swaps for bindings. They are shared between\n * the container and resolver.\n *\n * We do not mutate this property within the resolver\n */\n #containerSwaps: Swaps\n\n /**\n * Reference to the container hooks\n */\n #containerHooks: Hooks\n\n /**\n * Binding values local to the resolver\n */\n #bindingValues: BindingValues = new Map()\n\n /**\n * Container options\n */\n #options: ContainerOptions\n\n constructor(\n container: {\n bindings: Bindings\n bindingValues: BindingValues\n swaps: Swaps\n hooks: Hooks\n aliases: Map<Partial<keyof KnownBindings>, keyof KnownBindings | AbstractConstructor<any>>\n contextualBindings: Map<Constructor<any>, ContextualBindings>\n },\n options: ContainerOptions\n ) {\n this.#containerBindings = container.bindings\n this.#containerBindingValues = container.bindingValues\n this.#containerSwaps = container.swaps\n this.#containerHooks = container.hooks\n this.#containerAliases = container.aliases\n this.#containerContextualBindings = container.contextualBindings\n this.#options = options\n }\n\n /**\n * Constructs exception for invalid binding value\n */\n #invalidBindingException(\n parent: any,\n binding: any,\n createError: ErrorCreator\n ): InvalidArgumentsException {\n if (parent) {\n const error = createError(`Cannot inject \"${inspect(binding)}\" in \"[class ${parent.name}]\"`)\n error.help = 'The value is not a valid class'\n return error\n }\n\n return createError(`Cannot construct value \"${inspect(binding)}\" using container`)\n }\n\n /**\n * Constructs exception for binding with missing dependencies\n */\n #missingDependenciesException(parent: any, binding: any, createError: ErrorCreator) {\n if (parent) {\n const error = createError(\n `Cannot inject \"[class ${binding.name}]\" in \"[class ${parent.name}]\"`\n )\n error.help = `Container is not able to resolve \"${parent.name}\" class dependencies. Did you forget to use @inject() decorator?`\n return error\n }\n\n return createError(\n `Cannot construct \"[class ${binding.name}]\" class. Container is not able to resolve its dependencies. Did you forget to use @inject() decorator?`\n )\n }\n\n /**\n * Returns the provider for the class constructor\n */\n #getBindingProvider(binding: InspectableConstructor) {\n return binding.containerProvider\n }\n\n /**\n * Returns the binding resolver for a parent and a binding. Returns\n * undefined when no contextual binding exists\n */\n #getBindingResolver(\n parent: any,\n binding: AbstractConstructor<any>\n ): BindingResolver<KnownBindings, any> | undefined {\n const parentBindings = this.#containerContextualBindings.get(parent)\n if (!parentBindings) {\n return\n }\n\n const bindingResolver = parentBindings.get(binding)\n if (!bindingResolver) {\n return\n }\n\n return bindingResolver.resolver\n }\n\n /**\n * Notify emitter\n */\n #emit(binding: BindingKey, value: any) {\n if (!this.#options.emitter) {\n return\n }\n this.#options.emitter.emit('container_binding:resolved', { binding, value })\n }\n\n /**\n * Execute hooks for a given binding\n */\n async #execHooks(binding: BindingKey, value: any) {\n const callbacks = this.#containerHooks.get(binding)\n if (!callbacks || callbacks.size === 0) {\n return\n }\n\n for (let callback of callbacks) {\n await callback(value, this)\n }\n }\n\n /**\n * Find if the resolver has a binding registered using the\n * \"bind\", the \"singleton\", or the \"bindValue\" methods.\n */\n hasBinding<Binding extends keyof KnownBindings>(binding: Binding): boolean\n hasBinding(binding: BindingKey): boolean\n hasBinding(binding: BindingKey): boolean {\n return (\n this.#containerAliases.has(binding) ||\n this.#bindingValues.has(binding) ||\n this.#containerBindingValues.has(binding) ||\n this.#containerBindings.has(binding)\n )\n }\n\n /**\n * Find if the resolver has all the bindings registered using the\n * \"bind\", the \"singleton\", or the \"bindValue\" methods.\n */\n hasAllBindings<Binding extends keyof KnownBindings>(bindings: Binding[]): boolean\n hasAllBindings(bindings: BindingKey[]): boolean\n hasAllBindings(bindings: BindingKey[]): boolean {\n return bindings.every((binding) => this.hasBinding(binding))\n }\n\n /**\n * Resolves binding in context of a parent. The method is same as\n * the \"make\" method, but instead takes a parent class\n * constructor.\n */\n async resolveFor<Binding>(\n parent: unknown,\n binding: Binding,\n runtimeValues?: any[],\n createError: ErrorCreator = (message) => new RuntimeException(message)\n ): Promise<Make<Binding>> {\n const isAClass = isClass<Binding>(binding)\n\n /**\n * Raise exception when the binding is not a string, a class constructor\n * or a symbol.\n */\n if (typeof binding !== 'string' && typeof binding !== 'symbol' && !isAClass) {\n throw this.#invalidBindingException(parent, binding, createError)\n }\n\n /**\n * Entertain swaps with highest priority. The swaps can only exists for\n * class constructors.\n */\n if (isAClass && this.#containerSwaps.has(binding)) {\n const resolver = this.#containerSwaps.get(binding)!\n const value = await resolver(this, runtimeValues)\n\n if (debug.enabled) {\n debug('resolved swap for binding %O, resolved value :%O', binding, value)\n }\n\n /**\n * Executing hooks and emitting events for the swaps is\n * debatable for now\n */\n await this.#execHooks(binding, value)\n this.#emit(binding, value)\n return value\n }\n\n /**\n * Resolving contextual binding. Contextual bindings can only exists for\n * class constructors\n */\n const contextualResolver = isAClass && this.#getBindingResolver(parent, binding)\n if (contextualResolver) {\n const value = await contextualResolver(this, runtimeValues)\n\n if (debug.enabled) {\n debug('resolved using contextual resolver binding %O, resolved value :%O', binding, value)\n }\n\n await this.#execHooks(binding, value)\n this.#emit(binding, value)\n\n return value\n }\n\n /**\n * First priority is given to the RESOLVER binding values\n */\n if (this.#bindingValues.has(binding)) {\n const value = this.#bindingValues.get(binding)\n\n if (debug.enabled) {\n debug('resolved from resolver values %O, resolved value :%O', binding, value)\n }\n\n this.#emit(binding, value)\n return value\n }\n\n /**\n * Next priority is given to the CONTAINER binding values\n */\n if (this.#containerBindingValues.has(binding)) {\n const value = this.#containerBindingValues.get(binding)\n\n if (debug.enabled) {\n debug('resolved from container values %O, resolved value :%O', binding, value)\n }\n\n this.#emit(binding, value)\n return value\n }\n\n /**\n * Followed by the CONTAINER bindings\n */\n if (this.#containerBindings.has(binding)) {\n const { resolver, isSingleton } = this.#containerBindings.get(binding)!\n let value\n let executeHooks = isSingleton ? false : true\n\n /**\n * Invoke binding resolver to get the value. In case of singleton,\n * the \"enqueue\" method returns an object with the value and a\n * boolean telling if a cached value is resolved.\n */\n if (isSingleton) {\n const result = await resolver(this, runtimeValues)\n value = result.value\n executeHooks = !result.cached\n } else {\n value = await resolver(this, runtimeValues)\n }\n\n if (debug.enabled) {\n debug('resolved binding %O, resolved value :%O', binding, value)\n }\n\n if (executeHooks) {\n await this.#execHooks(binding, value)\n }\n this.#emit(binding, value)\n\n return value\n }\n\n /**\n * Create an instance of the class with its constructor\n * dependencies.\n */\n if (isAClass) {\n let dependencies: any[] = []\n const classConstructor: InspectableConstructor = binding\n\n const bindingProvider = this.#getBindingProvider(classConstructor)\n if (bindingProvider) {\n dependencies = await bindingProvider(\n classConstructor,\n '_constructor',\n this,\n containerProvider,\n runtimeValues\n )\n } else {\n dependencies = await containerProvider(\n classConstructor,\n '_constructor',\n this,\n runtimeValues\n )\n }\n\n /**\n * Class has dependencies for which we do not have runtime values and neither\n * we have typehints. Therefore we throw an exception\n */\n if (dependencies.length < classConstructor.length) {\n throw this.#missingDependenciesException(parent, binding, createError)\n }\n\n const value = new binding(...dependencies) as Promise<Make<Binding>>\n\n if (debug.enabled) {\n debug('constructed class %O, resolved value :%O', binding, value)\n }\n\n await this.#execHooks(binding, value)\n this.#emit(binding, value)\n\n return value\n }\n\n throw createError(`Cannot resolve binding \"${String(binding)}\" from the container`)\n }\n\n /**\n * Resolves the binding or constructor a class instance as follows.\n *\n * - Resolve the binding from the values (if registered)\n * - Resolve the binding from the bindings (if registered)\n * - If binding is a class, then create a instance of it. The constructor\n * dependencies are further resolved as well.\n * - All other values are returned as it is.\n *\n * ```ts\n * await resolver.make('route')\n * await resolver.make(Database)\n * ```\n */\n make<Binding extends keyof KnownBindings>(\n binding: Binding,\n runtimeValues?: any[],\n createError?: ErrorCreator\n ): Promise<Binding extends string | symbol ? KnownBindings[Binding] : Make<Binding>>\n make<Binding>(\n binding: Binding,\n runtimeValues?: any[],\n createError?: ErrorCreator\n ): Promise<Make<Binding>>\n async make<Binding>(\n binding: Binding,\n runtimeValues?: any[],\n createError?: ErrorCreator\n ): Promise<Make<Binding>> {\n /**\n * Make alias\n */\n if (this.#containerAliases.has(binding)) {\n return this.resolveFor(null, this.#containerAliases.get(binding), runtimeValues, createError)\n }\n\n return this.resolveFor(null, binding, runtimeValues, createError)\n }\n\n /**\n * Call a method on an object by injecting its dependencies. The method\n * dependencies are resolved in the same manner as a class constructor\n * dependencies.\n *\n * ```ts\n * await resolver.call(await resolver.make(UsersController), 'index')\n * ```\n */\n async call<Value extends Record<any, any>, Method extends ExtractFunctions<Value>>(\n value: Value,\n method: Method,\n runtimeValues?: any[],\n createError: ErrorCreator = (message) => new RuntimeException(message)\n ): Promise<ReturnType<Value[Method]>> {\n if (typeof value[method] !== 'function') {\n throw createError(`Missing method \"${String(method)}\" on \"${inspect(value)}\"`)\n }\n\n if (debug.enabled) {\n debug('calling method %s, on value :%O', method, value)\n }\n\n let dependencies: any[] = []\n const binding = value.constructor\n\n const bindingProvider = this.#getBindingProvider(binding)\n if (bindingProvider) {\n dependencies = await bindingProvider(binding, method, this, containerProvider, runtimeValues)\n } else {\n dependencies = await containerProvider(binding, method, this, runtimeValues)\n }\n\n /**\n * Method has dependencies for which we do not have runtime values and neither\n * we have typehints. Therefore we throw an exception\n */\n if (dependencies.length < value[method].length) {\n throw createError(\n `Cannot call \"${binding.name}.${String(\n method\n )}\" method. Container is not able to resolve its dependencies. Did you forget to use @inject() decorator?`\n )\n }\n\n return value[method](...dependencies)\n }\n\n /**\n * Register a binding as a value\n *\n * ```ts\n * container.bindValue(Route, new Route())\n * ```\n */\n bindValue<Binding extends keyof KnownBindings>(\n /**\n * Need to narrow down the \"Binding\" for the case where \"KnownBindings\" are <any, any>\n */\n binding: Binding extends string | symbol ? Binding : never,\n value: KnownBindings[Binding]\n ): void\n bindValue<Binding extends AbstractConstructor<any>>(\n binding: Binding,\n value: InstanceType<Binding>\n ): void\n bindValue<Binding>(\n binding: Binding,\n value: Binding extends AbstractConstructor<infer A>\n ? A\n : Binding extends keyof KnownBindings\n ? KnownBindings[Binding]\n : never\n ): void {\n if (typeof binding !== 'string' && typeof binding !== 'symbol' && !isClass(binding)) {\n throw new InvalidArgumentsException(\n 'The container binding key must be of type \"string\", \"symbol\", or a \"class constructor\"'\n )\n }\n\n debug('adding value to resolver \"%O\"', binding)\n this.#bindingValues.set(binding, value)\n }\n}\n","/*\n * @adonisjs/fold\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport debug from './debug.js'\nimport type { ContainerResolver } from './resolver.js'\nimport type { InspectableConstructor } from './types.js'\n\n/**\n * The default provider for resolving dependencies. It uses the resolver\n * to resolve all the values.\n */\nexport async function containerProvider(\n binding: InspectableConstructor,\n property: string | symbol | number,\n resolver: ContainerResolver<any>,\n runtimeValues?: any[]\n) {\n const values = runtimeValues || []\n\n /**\n * Return early when the class does not have static \"containerInjections\"\n * property or if there are no injections for the given property\n */\n if (!binding.containerInjections || !binding.containerInjections[property]) {\n return values\n }\n\n const injections = binding.containerInjections[property].dependencies\n const createError = binding.containerInjections[property].createError\n\n /**\n * If the length of runtime values is more than the injections\n * length, then we make sure to return all the runtime\n * values and fill undefined slots with container lookup\n */\n if (values.length > injections.length) {\n if (debug.enabled) {\n debug(\n 'created resolver plan. target: \"[class %s]\", property: \"%s\", injections: %O',\n binding.name,\n property,\n values.map((value, index) => {\n if (value !== undefined) {\n return value\n }\n\n return injections[index]\n })\n )\n }\n\n return Promise.all(\n values.map((value, index) => {\n if (value !== undefined) {\n return value\n }\n\n const injection = injections[index]\n return resolver.resolveFor(binding, injection, undefined, createError)\n })\n )\n }\n\n /**\n * Otherwise, we go through the injections, giving\n * priority to the runtime values for a given index.\n */\n if (debug.enabled) {\n debug(\n 'created resolver plan. target: \"[class %s]\", property: \"%s\", injections: %O',\n binding.name,\n property,\n injections.map((injection, index) => {\n if (values[index] !== undefined) {\n return values[index]\n }\n\n return injection\n })\n )\n }\n\n return Promise.all(\n injections.map((injection, index) => {\n if (values[index] !== undefined) {\n return values[index]\n }\n\n return resolver.resolveFor(binding, injection, undefined, createError)\n })\n )\n}\n","/*\n * @adonisjs/fold\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { RuntimeException } from '@poppinss/utils'\nimport type { Container } from './container.js'\nimport type { AbstractConstructor, BindingResolver, Constructor, Make } from './types.js'\n\n/**\n * A fluent builder to register contextual bindings with the\n * container.\n */\nexport class ContextBindingsBuilder<\n KnownBindings extends Record<any, any>,\n PinnedBinding extends AbstractConstructor<any>,\n> {\n /**\n * The parent for whom to define the contextual\n * binding\n */\n #parent: Constructor<any>\n\n /**\n * The binding the parent asks for\n */\n #binding?: PinnedBinding\n\n /**\n * Container instance for registering the contextual\n * bindings\n */\n #container: Container<KnownBindings>\n\n constructor(parent: Constructor<any>, container: Container<KnownBindings>) {\n this.#parent = parent\n this.#container = container\n }\n\n /**\n * Specify the binding for which to register a custom\n * resolver.\n */\n asksFor<Binding extends PinnedBinding>(\n binding: Binding\n ): ContextBindingsBuilder<KnownBindings, Binding> {\n this.#binding = binding\n return this as unknown as ContextBindingsBuilder<KnownBindings, Binding>\n }\n\n /**\n * Provide a resolver to resolve the parent dependency\n */\n provide(resolver: BindingResolver<KnownBindings, Make<PinnedBinding>>): void {\n if (!this.#binding) {\n throw new RuntimeException(\n 'Missing value for contextual binding. Call \"asksFor\" method before calling the \"provide\" method'\n )\n }\n\n this.#container.contextualBinding<PinnedBinding>(this.#parent, this.#binding, resolver)\n }\n}\n","/*\n * @adonisjs/fold\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { defineStaticProperty, RuntimeException } from '@poppinss/utils'\n\nimport debug from '../debug.js'\nimport { ErrorCreator, InspectableConstructor } from '../types.js'\n\n/**\n * Creating a debugging error that points to the source\n * using the @inject decorator\n */\nfunction createDebuggingError(original: Error) {\n return function createError(message: string) {\n const error = new RuntimeException(message)\n error.stack = original.stack\n return error\n }\n}\n\n/**\n * Initiating the \"containerInjections\" property on the target, which is assumed\n * to be the class constructor.\n */\nfunction initiateContainerInjections(\n target: any,\n method: string | symbol,\n createError: ErrorCreator\n) {\n defineStaticProperty(target, 'containerInjections', { initialValue: {}, strategy: 'inherit' })\n target.containerInjections[method] = {\n createError,\n dependencies: [],\n }\n}\n\n/**\n * Defining the injections for the constructor of the class using\n * reflection\n */\nfunction defineConstructorInjections(target: InspectableConstructor, createError: ErrorCreator) {\n const params = Reflect.getMetadata('design:paramtypes', target)\n /* c8 ignore next 3 */\n if (!params) {\n return\n }\n\n initiateContainerInjections(target, '_constructor', createError)\n if (debug.enabled) {\n debug('defining constructor injections for %O, params %O', `[class: ${target.name}]`, params)\n }\n\n for (const param of params) {\n target.containerInjections!._constructor.dependencies.push(param)\n }\n}\n\n/**\n * Defining the injections for the class instance method\n */\nfunction defineMethodInjections(target: any, method: string | symbol, createError: ErrorCreator) {\n const constructor = target.constructor as InspectableConstructor\n const params = Reflect.getMetadata('design:paramtypes', target, method)\n /* c8 ignore next 3 */\n if (!params) {\n return\n }\n\n initiateContainerInjections(constructor, method, createError)\n if (debug.enabled) {\n debug(\n 'defining method injections for %O, method %O, params %O',\n `[class ${constructor.name}]`,\n method,\n params\n )\n }\n\n for (const param of params) {\n constructor.containerInjections![method].dependencies.push(param)\n }\n}\n\n/**\n * The \"@inject\" decorator uses Reflection to inspect the dependencies of a class\n * or a method and defines them as metaData on the class for the container to\n * discover them.\n */\nexport function inject() {\n /**\n * Creating an error builder for the inject decorator, so that\n * the stack trace can point back to the code that used\n * the decorator\n */\n const createError = createDebuggingError(new Error())\n\n function injectDecorator<C extends Function>(target: C): void\n function injectDecorator(target: any, propertyKey: string | symbol): void\n function injectDecorator(target: any, propertyKey?: string | symbol): void {\n if (!propertyKey) {\n defineConstructorInjections(target, createError)\n return\n }\n\n defineMethodInjections(target, propertyKey, createError)\n }\n\n return injectDecorator\n}\n","/*\n * @adonisjs/fold\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { Container } from './container.js'\nimport { ContainerResolver } from './resolver.js'\nimport type { ModuleHandler, ModuleCallable, Constructor } from './types.js'\n\n/**\n * The moduleCaller works around a very specific pattern we use with\n * AdonisJS, ie to construct classes and call methods using the\n * container.\n *\n * For example: Controllers of AdonisJS allows defining a controller\n * as follows\n *\n * ```ts\n * route.get('/', [HomeController, 'index'])\n * ```\n *\n * Behind the scenes, we have to run following operations in order to call the\n * handle method on the defined middleware.\n *\n * - Create an instance of the controller class using the container.\n * - Call the method using the container. Hence having the ability to use\n * DI\n */\nexport function moduleCaller(target: Constructor<any>, method: string) {\n return {\n /**\n * Converts the class reference to a callable function. Invoking this method\n * internally creates a new instance of the class using the container and\n * invokes the method using the container.\n *\n * You can create a callable function using the container instance as shown below\n *\n * ```ts\n * const fn = moduleCaller(HomeController, 'handle')\n * .toCallable(container)\n *\n * // Call the function and pass context to it\n * await fn(ctx)\n * ```\n *\n * Another option is to not pass the container at the time of creating\n * the callable function, but instead pass a resolver instance at\n * the time of calling the function\n *\n * ```ts\n * const fn = moduleCaller(HomeController, 'handle')\n * .toCallable()\n *\n * // Call the function and pass context to it\n * const resolver = container.createResolver()\n * await fn(resolver, ctx)\n * ```\n */\n toCallable<\n T extends Container<any> | ContainerResolver<any> | undefined = undefined,\n Args extends any[] = any[],\n >(container?: T): ModuleCallable<T, Args> {\n /**\n * When container defined at the time of the calling this function,\n * we will use it to inside the return function\n */\n if (container) {\n return async function (...args: Args) {\n return container.call(await container.make(target), method, args)\n } as ModuleCallable<T, Args>\n }\n\n /**\n * Otherwise the return function asks for the resolver or container\n */\n return async function (resolver: ContainerResolver<any> | Container<any>, ...args: Args) {\n return resolver.call(await resolver.make(target), method, args)\n } as ModuleCallable<T, Args>\n },\n\n /**\n * Converts the class reference to an object with handle method. Invoking this\n * method internally creates a new instance of the class using the container\n * and invokes the method using the container.\n *\n * You can create a handle method object using the container instance as shown below\n *\n * ```ts\n * const handler = moduleCaller(HomeController, 'handle')\n * .toHandleMethod(container)\n *\n * // Call the function and pass context to it\n * await handler.handle(ctx)\n * ```\n *\n * Another option is to not pass the container at the time of creating\n * the handle method object, but instead pass a resolver instance at\n * the time of calling the function\n *\n * ```ts\n * const handler = moduleCaller(HomeController, 'handle')\n * .toHandleMethod()\n *\n * // Call the function and pass context to it\n * const resolver = container.createResolver()\n * await handler.handle(resolver, ctx)\n * ```\n */\n toHandleMethod<\n T extends Container<any> | ContainerResolver<any> | undefined = undefined,\n Args extends any[] = any[],\n >(container?: T): ModuleHandler<T, Args> {\n if (container) {\n return {\n name: `${target.name}.${method}`,\n async handle(...args: Args) {\n return container.call(await container.make(target), method, args)\n },\n } as ModuleHandler<T, Args>\n }\n\n return {\n name: `${target.name}.${method}`,\n async handle(resolver: ContainerResolver<any> | Container<any>, ...args: Args) {\n return resolver.call(await resolver.make(target), method, args)\n },\n } as ModuleHandler<T, Args>\n },\n }\n}\n","/*\n * @adonisjs/fold\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { importDefault } from '@poppinss/utils'\n\nimport { Container } from './container.js'\nimport { ContainerResolver } from './resolver.js'\nimport type { ModuleHandler, ModuleCallable, Constructor } from './types.js'\n\n/**\n * The moduleImporter module works around a very specific pattern we use\n * with AdonisJS, ie to lazy load modules by wrapping import calls inside\n * a callback.\n *\n * For example: Middleware of AdonisJS allows registering middleware as an\n * array of import calls.\n *\n * ```ts\n * defineMiddleware([\n * () => import('#middleware/silent_auth')\n * ])\n *\n * defineMiddleware({\n * auth: () => import('#middleware/auth')\n * })\n * ```\n *\n * Behind the scenes, we have to run following operations in order to call the\n * handle method on the def