{"version":3,"file":"index.cjs","names":[],"sources":["../src/tokens.ts","../src/container.ts","../src/utils.ts","../src/modules.ts"],"sourcesContent":["/**\n * @ignore\n * Binding token for mandatory value\n */\nexport type RequiredToken<T> = {\n  symbol: symbol;\n  type?: T; // Anchor for Typescript type inference.\n  isOptional?: false;\n};\n\n/**\n * @ignore\n * Binding token for optional value\n */\nexport type OptionalToken<T> = {\n  symbol: symbol;\n  type?: T; // Anchor for Typescript type inference.\n  isOptional: true;\n  optionalValue: T;\n};\n\n/**\n * Binding token\n */\nexport type Token<T> = RequiredToken<T> | OptionalToken<T>;\n\n/**\n * Token options\n */\nexport type TokenOptions =\n  | {\n      /**\n       * Key for token's symbol. It allows to create shareable tokens.\n       */\n      key: string;\n\n      /** @ignore */\n      description?: undefined;\n    }\n  | {\n      /** Description for better error messages */\n      description?: string;\n\n      /** @ignore */\n      key?: undefined;\n    };\n\n/**\n * Creates a new binding token.\n * @param description - Token description for better error messages.\n */\nexport function token<T>(description?: string): Token<T>;\n/**\n * Creates a new binding token.\n * @param options - Token description for better error messages.\n */ export function token<T>(options?: TokenOptions): Token<T>;\nexport function token<T>(options?: TokenOptions | string): Token<T> {\n  const normalized: TokenOptions | undefined =\n    typeof options === 'string' ? { description: options } : options;\n\n  const symbol: symbol = normalized?.key\n    ? Symbol.for(normalized.key)\n    : Symbol(normalized?.description);\n\n  return { symbol };\n}\n\n/**\n * Decorate a token with an optional value.\n * This value is be used as default value in case a container does not have registered token.\n * @param token - Existed token.\n * @param optionalValue - Default value for the resolver.\n */\nexport function optional<T>(\n  token: Token<T>,\n  optionalValue: T,\n): OptionalToken<T>;\nexport function optional<T>(token: Token<T>): OptionalToken<T | undefined>;\nexport function optional<T>(\n  token: Token<T>,\n  optionalValue?: T,\n): OptionalToken<T | undefined> {\n  return {\n    symbol: token.symbol,\n    isOptional: true,\n    optionalValue,\n  };\n}\n","import { Token, token } from './tokens';\n\n/**\n * ResolverError is thrown by the resolver when a token is not found in a container.\n */\nexport class ResolverError extends Error {\n  constructor(message: string) {\n    super(message);\n    Object.setPrototypeOf(this, new.target.prototype);\n    this.name = 'ResolverError';\n  }\n}\n\n/**\n * @see https://github.com/mnasyrov/ditox#factory-lifetimes\n */\nexport type FactoryScope = 'scoped' | 'singleton' | 'transient';\n\n/**\n * Options for factory binding.\n *\n * `scope` types:\n *   - `singleton` - **This is the default**. The value is created and cached by the most distant parent container which owns the factory function.\n *   - `scoped` - The value is created and cached by the nearest container which owns the factory function.\n *   - `transient` - The value is created every time it is resolved.\n *\n * `scoped` and `singleton` scopes can have `onRemoved` callback. It is called when a token is removed from the container.\n */\nexport type FactoryOptions<T> =\n  | {\n      scope?: 'scoped' | 'singleton';\n      onRemoved?: (value: T) => void;\n    }\n  | {\n      scope: 'transient';\n    };\n\n/**\n * Dependency container.\n */\nexport type Container = {\n  /**\n   * Binds a value for the token\n   */\n  bindValue<T>(token: Token<T>, value: T): void;\n\n  /**\n   * Binds a factory for the token.\n   */\n  bindFactory<T>(\n    token: Token<T>,\n    factory: (container: Container) => T,\n    options?: FactoryOptions<T>,\n  ): void;\n\n  /**\n   * Checks if the token is registered in the container hierarchy.\n   */\n  hasToken(token: Token<unknown>): boolean;\n\n  /**\n   * Returns a resolved value by the token, or returns `undefined` in case the token is not found.\n   */\n  get<T>(token: Token<T>): T | undefined;\n\n  /**\n   * Returns a resolved value by the token or throws `ResolverError` in case the token is not found.\n   */\n  resolve<T>(token: Token<T>): T;\n\n  /**\n   * Removes a binding for the token.\n   */\n  remove<T>(token: Token<T>): void;\n\n  /**\n   * Removes all bindings in the container.\n   */\n  removeAll(): void;\n};\n\n/**\n * A subset of Container interface that provides read-only access to dependency resolution.\n * This type is used for parent containers to allow token resolution without exposing mutation methods.\n */\nexport type ContainerResolver = Pick<Container, 'hasToken' | 'get' | 'resolve'>;\n\n/** @internal */\nexport const CONTAINER: Token<Container> = token('ditox.Container');\n/** @internal */\nexport const PARENT_CONTAINERS: Token<ReadonlyArray<Container>> = token(\n  'ditox.ParentContainer',\n);\n/** @internal */\nexport const RESOLVER: Token<Resolver> = token('ditox.Resolver');\n\n/** @internal */\nconst NOT_FOUND = Symbol();\n\n/** @internal */\nconst DEFAULT_SCOPE: FactoryScope = 'singleton';\n\n/** @internal */\ntype FactoryContext<T> = {\n  factory: (container: Container) => T;\n  options?: FactoryOptions<T>;\n};\n\n/** @internal */\ntype ValuesMap = Map<symbol, any>;\n\n/** @internal */\nexport type FactoriesMap = Map<symbol, FactoryContext<any>>;\n\n/** @internal */\nexport const FACTORIES_MAP: Token<FactoriesMap> = token('ditox.FactoriesMap');\n\n/** @internal */\ntype Resolver = <T>(token: Token<T>, origin: Container) => T | typeof NOT_FOUND;\n\n/** @internal */\nfunction getScope<T>(options?: FactoryOptions<T>): FactoryScope {\n  return options?.scope ?? DEFAULT_SCOPE;\n}\n\n/** @internal */\nfunction getOnRemoved<T>(options: FactoryOptions<T>) {\n  return options.scope === undefined ||\n    options.scope === 'scoped' ||\n    options.scope === 'singleton'\n    ? options.onRemoved\n    : undefined;\n}\n\n/** @internal */\nfunction isInternalToken<T>(token: Token<T>): boolean {\n  return (\n    token.symbol === CONTAINER.symbol ||\n    token.symbol === PARENT_CONTAINERS.symbol ||\n    token.symbol === RESOLVER.symbol\n  );\n}\n\n/**\n * Creates a new dependency container.\n *\n * Container can have an optional parent to chain token resolution. The parent is used in case the current container does not have a registered token.\n *\n * @param parentArg - Optional parent container or an array of containers.\n */\nexport function createContainer(\n  parentArg?: ContainerResolver | ReadonlyArray<ContainerResolver>,\n): Container {\n  const parents: ReadonlyArray<ContainerResolver> | undefined = parentArg\n    ? Array.isArray(parentArg)\n      ? [...parentArg]\n      : [parentArg]\n    : undefined;\n\n  const values: ValuesMap = new Map<symbol, any>();\n  const factories: FactoriesMap = new Map<symbol, FactoryContext<any>>();\n\n  const container: Container = {\n    bindValue<T>(token: Token<T>, value: T): void {\n      if (isInternalToken(token)) {\n        return;\n      }\n\n      values.set(token.symbol, value);\n    },\n\n    bindFactory<T>(\n      token: Token<T>,\n      factory: (container: Container) => T,\n      options?: FactoryOptions<T>,\n    ): void {\n      if (isInternalToken(token)) {\n        return;\n      }\n\n      factories.set(token.symbol, { factory, options });\n    },\n\n    remove<T>(token: Token<T>): void {\n      if (isInternalToken(token)) {\n        return;\n      }\n\n      const options = factories.get(token.symbol)?.options;\n      if (options) {\n        executeOnRemoved(token.symbol, options);\n      }\n\n      values.delete(token.symbol);\n      factories.delete(token.symbol);\n    },\n\n    removeAll(): void {\n      factories.forEach((context, tokenSymbol) => {\n        if (context.options) {\n          executeOnRemoved(tokenSymbol, context.options);\n        }\n      });\n\n      values.clear();\n      factories.clear();\n      bindInternalTokens();\n    },\n\n    hasToken(token: Token<unknown>): boolean {\n      return (\n        values.has(token.symbol) ||\n        factories.has(token.symbol) ||\n        parentContainersHaveToken(parents, token)\n      );\n    },\n\n    get<T>(token: Token<T>): T | undefined {\n      const value = resolver(token, container);\n      if (value !== NOT_FOUND) {\n        return value;\n      }\n\n      if (token.isOptional) {\n        return token.optionalValue;\n      }\n\n      return undefined;\n    },\n\n    resolve<T>(token: Token<T>): T {\n      const value = resolver(token, container);\n      if (value !== NOT_FOUND) {\n        return value;\n      }\n\n      if (token.isOptional) {\n        return token.optionalValue;\n      }\n\n      throw new ResolverError(\n        `Token \"${token.symbol.description ?? ''}\" is not provided`,\n      );\n    },\n  };\n\n  function resolver<T>(\n    token: Token<T>,\n    origin: Container,\n  ): T | typeof NOT_FOUND {\n    const value = values.get(token.symbol);\n    const hasValue = value !== undefined || values.has(token.symbol);\n\n    if (hasValue && origin === container) {\n      return value;\n    }\n\n    const factoryContext = factories.get(token.symbol);\n    if (factoryContext) {\n      const scope = getScope(factoryContext.options);\n\n      switch (scope) {\n        case 'singleton': {\n          if (hasValue) {\n            return value;\n          } else if (parentContainersHaveToken(parents, token)) {\n            break;\n          } else {\n            // Cache the value in the same container where the factory is registered.\n            const value = factoryContext.factory(container);\n            container.bindValue(token, value);\n            return value;\n          }\n        }\n\n        case 'scoped': {\n          if (hasValue) {\n            return value;\n          } else {\n            // Create a value within the factory's container and cache it.\n            const value = factoryContext.factory(container);\n            container.bindValue(token, value);\n            return value;\n          }\n        }\n\n        case 'transient': {\n          // Create a value within the origin container and don't cache it.\n          return factoryContext.factory(origin);\n        }\n      }\n    }\n\n    if (hasValue) {\n      return value;\n    }\n\n    if (parents) {\n      return parentContainersResolveToken(parents, token, origin);\n    }\n\n    return NOT_FOUND;\n  }\n\n  function executeOnRemoved<T>(\n    tokenSymbol: symbol,\n    options: FactoryOptions<T>,\n  ) {\n    const onRemoved = getOnRemoved(options);\n    if (onRemoved) {\n      const value = values.get(tokenSymbol);\n      if (value !== undefined || values.has(tokenSymbol)) {\n        onRemoved(value);\n      }\n    }\n  }\n\n  function bindInternalTokens() {\n    values.set(CONTAINER.symbol, container);\n    values.set(RESOLVER.symbol, resolver);\n    values.set(FACTORIES_MAP.symbol, factories);\n\n    if (parents) {\n      values.set(PARENT_CONTAINERS.symbol, parents);\n    }\n  }\n\n  bindInternalTokens();\n  return container;\n}\n\nfunction parentContainersHaveToken<T>(\n  parents: ReadonlyArray<ContainerResolver> | undefined,\n  token: Token<T>,\n): boolean {\n  if (!parents) return false;\n\n  for (let i = 0; i < parents.length; i++) {\n    if (parents[i].hasToken(token)) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\nfunction parentContainersResolveToken<T>(\n  parents: ReadonlyArray<ContainerResolver>,\n  token: Token<T>,\n  origin: Container,\n): T | typeof NOT_FOUND {\n  for (const parentContainer of parents) {\n    const parentResolver = parentContainer.get(RESOLVER);\n    if (parentResolver) {\n      const resolved = parentResolver(token, origin);\n      if (resolved !== NOT_FOUND) {\n        return resolved;\n      }\n    }\n  }\n\n  return NOT_FOUND;\n}\n","import type { Container } from './container';\nimport { Token } from './tokens';\n\ntype ValuesProps = { [key: string]: unknown };\ntype TokenProps<Props extends ValuesProps> = {\n  [K in keyof Props]: Token<Props[K]>;\n};\n\n/**\n * Checks if a value is the token\n */\nexport function isToken<T>(value: unknown): value is Token<T> {\n  return (\n    value !== undefined &&\n    value !== null &&\n    typeof value === 'object' &&\n    'symbol' in value &&\n    typeof (value as any).symbol === 'symbol'\n  );\n}\n\n/**\n * Rebinds the array by the token with added new value.\n * @param container - Dependency container.\n * @param token - Token for an array of values.\n * @param value - New value which is added to the end of the array.\n */\nexport function bindMultiValue<T>(\n  container: Container,\n  token: Token<ReadonlyArray<T>>,\n  value: T,\n): void {\n  const prevValues = container.get(token) ?? [];\n  const nextValues = [...prevValues, value];\n  container.bindValue(token, nextValues);\n}\n\n/**\n * Tries to resolve a value by the provided token.\n *\n * If an argument is an object which has tokens as its properties,\n * then returns an object containing resolved values as properties.\n\n * If a token is not found, then `undefined` value is used.\n *\n * @example\n * ```ts\n * const value = tryResolveValue(container, tokenA);\n * console.log(value); // 1\n *\n * const props = tryResolveValue(container, {a: tokenA, b: tokenB});\n * console.log(props); // {a: 1, b: 2}\n * ```\n */\nexport function tryResolveValue<\n  Tokens extends Token<unknown> | { [key: string]: Token<unknown> },\n  Values extends Tokens extends Token<infer V>\n    ? V | undefined\n    : Tokens extends TokenProps<infer Props>\n      ? Partial<Props>\n      : never,\n>(container: Container, token: Tokens): Values {\n  if (isToken(token)) {\n    return container.get(token) as Values;\n  }\n\n  const obj: any = {};\n  Object.keys(token).forEach((key) => (obj[key] = container.get(token[key])));\n  return obj;\n}\n\n/**\n * Returns an array of resolved values or objects with resolved values.\n *\n * If an item of the array is an object which has tokens as its properties,\n * then returns an object containing resolved values as properties.\n\n * If a token is not found, then `undefined` value is used.\n *\n * @example\n * ```ts\n * const items1 = tryResolveValues(container, tokenA);\n * console.log(items1); // [1]\n *\n * const items2 = tryResolveValues(container, tokenA, {a: tokenA, b: tokenB});\n * console.log(items2); // [1, {a: 1, b: 2}]\n * ```\n */\nexport function tryResolveValues<\n  Tokens extends (Token<unknown> | { [key: string]: Token<unknown> })[],\n  Values extends {\n    [K in keyof Tokens]: Tokens[K] extends Token<infer V>\n      ? V | undefined\n      : Tokens[K] extends TokenProps<infer Props>\n        ? Partial<Props>\n        : never;\n  },\n>(container: Container, ...tokens: Tokens): Values {\n  return tokens.map((item) => tryResolveValue(container, item)) as Values;\n}\n\n/**\n * Resolves a value by the provided token.\n *\n * If an argument is an object which has tokens as its properties,\n * then returns an object containing resolved values as properties.\n\n * If a value is not found by the token, then `ResolverError` is thrown.\n *\n * @example\n * ```ts\n * const value = resolveValue(container, tokenA);\n * console.log(value); // 1\n *\n * const props = resolveValue(container, {a: tokenA, b: tokenB});\n * console.log(props); // {a: 1, b: 2}\n * ```\n */\nexport function resolveValue<\n  Tokens extends Token<unknown> | { [key: string]: Token<unknown> },\n  Values extends Tokens extends Token<infer V>\n    ? V\n    : Tokens extends TokenProps<infer Props>\n      ? Props\n      : never,\n>(container: Container, token: Tokens): Values {\n  if (isToken(token)) {\n    return container.resolve(token) as Values;\n  }\n\n  const obj: any = {};\n  Object.keys(token).forEach(\n    (key) => (obj[key] = container.resolve(token[key])),\n  );\n  return obj;\n}\n\n/**\n * Returns an array of resolved values or objects with resolved values.\n *\n * If an item of the array is an object which has tokens as its properties,\n * then returns an object containing resolved values as properties.\n\n * If a token is not found, then `ResolverError` is thrown.\n *\n * @example\n * ```ts\n * const items1 = resolveValues(container, tokenA);\n * console.log(items1); // [1]\n *\n * const items2 = resolveValues(container, tokenA, {a: tokenA, b: tokenB});\n * console.log(items2); // [1, {a: 1, b: 2}]\n * ```\n */\nexport function resolveValues<\n  Tokens extends (Token<unknown> | { [key: string]: Token<unknown> })[],\n  Values extends {\n    [K in keyof Tokens]: Tokens[K] extends Token<infer V>\n      ? V\n      : Tokens[K] extends TokenProps<infer Props>\n        ? Props\n        : never;\n  },\n>(container: Container, ...tokens: Tokens): Values {\n  return tokens.map((item) => resolveValue(container, item)) as Values;\n}\n\n/**\n * Decorates a factory by passing resolved values as factory arguments.\n *\n * If an argument is an object which has tokens as its properties,\n * then returns an object containing resolved values as properties.\n *\n * @param factory - A factory.\n * @param tokens - Tokens which correspond to factory arguments.\n *\n * @return Decorated factory which takes a dependency container as a single argument.\n */\nexport function injectable<\n  Tokens extends (Token<unknown> | { [key: string]: Token<unknown> })[],\n  Values extends {\n    [K in keyof Tokens]: Tokens[K] extends Token<infer V>\n      ? V\n      : Tokens[K] extends TokenProps<infer Props>\n        ? Props\n        : never;\n  },\n  Result,\n>(\n  this: unknown,\n  factory: (...params: Values) => Result,\n  ...tokens: Tokens\n): (container: Container) => Result {\n  return (container) => {\n    const values: Values = resolveValues(container, ...tokens);\n    return factory.apply(this, values);\n  };\n}\n\n/**\n * Decorates a class by passing resolved values as arguments to its constructor.\n *\n * If an argument is an object which has tokens as its properties,\n * then returns an object containing resolved values as properties.\n *\n * @param constructor - Constructor of a class\n * @param tokens - Tokens which correspond to constructor arguments\n *\n * @return A factory function which takes a dependency container as a single argument\n * and returns a new created class.\n */\nexport function injectableClass<\n  Tokens extends (Token<unknown> | { [key: string]: Token<unknown> })[],\n  Values extends {\n    [K in keyof Tokens]: Tokens[K] extends Token<infer V>\n      ? V\n      : Tokens[K] extends TokenProps<infer Props>\n        ? Props\n        : never;\n  },\n  Result,\n>(\n  this: unknown,\n  constructor: new (...params: Values) => Result,\n  ...tokens: Tokens\n): (container: Container) => Result {\n  return injectable<Tokens, Values, Result>(\n    (...values) => new constructor(...values),\n    ...tokens,\n  );\n}\n","import { Container } from './container';\nimport { Token, token } from './tokens';\nimport { injectable } from './utils';\n\ntype AnyObject = Record<string, any>;\ntype EmptyObject = Record<string, never>;\n\ntype ModuleController = {\n  /** Dispose the module and clean its resources */\n  destroy?: () => void;\n};\n\n/**\n * Dependency module\n *\n * @example\n * ```ts\n * type LoggerModule = Module<{\n *   logger: Logger;\n * }>;\n * ```\n */\nexport type Module<ModuleProps extends AnyObject = EmptyObject> =\n  ModuleController & ModuleProps;\n\ntype GetModuleProps<T> = T extends Module<infer Props> ? Props : never;\n\n/**\n * Description how to bind the module in declarative way.\n *\n * @example\n * ```ts\n * const LOGGER_MODULE: ModuleDeclaration<LoggerModule> = {\n *   token: LOGGER_MODULE_TOKEN,\n *   factory: (container) => {\n *     const transport = container.resolve(TRANSPORT_TOKEN).open();\n *     return {\n *       logger: { log: (message) => transport.write(message) },\n *       destroy: () => transport.close(),\n *     }\n *   },\n *   exports: {\n *     logger: LOGGER_TOKEN,\n *   },\n * };\n * ```\n */\nexport type ModuleDeclaration<T extends Module<AnyObject>> = {\n  /** Token for the module */\n  token: Token<T>;\n\n  /** Modules for binding  */\n  imports?: ReadonlyArray<ModuleBindingEntry>;\n\n  /** Factory of the module */\n  factory: (container: Container) => T;\n\n  /** Dictionary of module properties which are bound to tokens. */\n  exports?: {\n    [K in keyof GetModuleProps<T>]?: Token<GetModuleProps<T>[K]>;\n  };\n\n  /** Callback could be used to prepare an environment. It is called before binding the module. */\n  beforeBinding?: (container: Container) => void;\n\n  /** Callback could be used to export complex dependencies from the module. It is called after binding the module.  */\n  afterBinding?: (container: Container) => void;\n\n  /**\n   * Strategy for executing the factory:\n   *   - `lazy` - **This is the default**. The factory is called when the module is resolved.\n   *   - `eager` - The factory is called immediately after the module is bound to the container.\n   */\n  strategy?: 'eager' | 'lazy';\n};\n\nexport type AnyModuleDeclaration = ModuleDeclaration<Module<AnyObject>>;\n\n/**\n * Options for module binding.\n *\n * `scope` types:\n *   - `singleton` - **This is the default**. The value is created and cached by the most distant parent container which owns the factory function.\n *   - `scoped` - The value is created and cached by the nearest container which owns the factory function.\n */\nexport type BindModuleOptions = {\n  scope?: 'scoped' | 'singleton';\n};\n\ntype ModuleDeclarationWithOptions = {\n  module: ModuleDeclaration<AnyObject>;\n  options: BindModuleOptions;\n};\n\nexport type ModuleBindingEntry =\n  | ModuleDeclaration<AnyObject>\n  | ModuleDeclarationWithOptions;\n\n/**\n * Binds the dependency module to the container\n * @param container - Dependency container.\n * @param moduleDeclaration - Declaration of the dependency module.\n * @param options - Options for module binding.\n *\n * @example\n * ```ts\n * bindModule(container, LOGGER_MODULE);\n * ```\n */\nexport function bindModule<T extends Module<AnyObject>>(\n  container: Container,\n  moduleDeclaration: ModuleDeclaration<T>,\n  options?: BindModuleOptions,\n): void {\n  const rootEntry: ModuleBindingEntry = {\n    module: moduleDeclaration,\n    options: options ?? {},\n  };\n\n  const bfsVisits = new Set<ModuleBindingEntry>([rootEntry]);\n  const bfsQueue: ModuleBindingEntry[] = [rootEntry];\n\n  let bfsIndex = 0;\n  while (bfsIndex < bfsQueue.length) {\n    const entry = bfsQueue[bfsIndex];\n\n    const m = 'module' in entry ? entry.module : entry;\n\n    m.imports?.forEach((depEntry) => {\n      if (!bfsVisits.has(depEntry)) {\n        bfsVisits.add(depEntry);\n        bfsQueue.push(depEntry);\n      }\n    });\n\n    bfsIndex++;\n  }\n\n  for (let i = 0; i < bfsQueue.length; i++) {\n    const entry = bfsQueue[i];\n    const m = 'module' in entry ? entry.module : entry;\n    m.beforeBinding?.(container);\n  }\n\n  for (let i = 0; i < bfsQueue.length; i++) {\n    const entry = bfsQueue[i];\n    bindModuleEntry(container, entry);\n  }\n\n  for (let i = bfsQueue.length - 1; i >= 0; i--) {\n    const entry = bfsQueue[i];\n    const m = 'module' in entry ? entry.module : entry;\n    m.afterBinding?.(container);\n  }\n\n  for (let i = bfsQueue.length - 1; i >= 0; i--) {\n    const entry = bfsQueue[i];\n    const m = 'module' in entry ? entry.module : entry;\n    if (m.strategy === 'eager') {\n      container.resolve(m.token);\n    }\n  }\n}\n\nfunction bindModuleEntry(\n  container: Container,\n  entry: ModuleBindingEntry,\n): void {\n  let module: ModuleDeclaration<AnyObject>;\n  let options: BindModuleOptions | undefined;\n\n  if ('module' in entry) {\n    module = entry.module;\n    options = entry.options;\n  } else {\n    module = entry;\n  }\n\n  const scope = options?.scope;\n  const exportedValueTokens = new Set<Token<unknown>>();\n  const moduleExports = module.exports;\n\n  if (moduleExports) {\n    const keys = Object.keys(moduleExports);\n\n    keys.forEach((valueKey) => {\n      const valueToken = moduleExports[valueKey];\n      if (valueToken) {\n        exportedValueTokens.add(valueToken);\n\n        container.bindFactory(\n          valueToken,\n          injectable((module) => module[valueKey], module.token),\n          { scope },\n        );\n      }\n    });\n  }\n\n  container.bindFactory(module.token, module.factory, {\n    scope,\n    onRemoved: (moduleInstance) => {\n      if (moduleInstance.destroy) {\n        moduleInstance.destroy();\n      }\n\n      exportedValueTokens.forEach((valueToken) => container.remove(valueToken));\n      exportedValueTokens.clear();\n    },\n  });\n}\n\n/**\n * Binds dependency modules to the container\n *\n * @param container - Dependency container for binding\n * @param modules - Array of module binding entries: module declaration or `{module: ModuleDeclaration, options: BindModuleOptions}` objects.\n */\nexport function bindModules(\n  container: Container,\n  modules: ReadonlyArray<ModuleBindingEntry>,\n): void {\n  modules.forEach((entry) => {\n    if ('module' in entry) {\n      bindModule(container, entry.module, entry.options);\n    } else {\n      bindModule(container, entry);\n    }\n  });\n}\n\n/**\n * Declares a module binding\n *\n * @param declaration - a module declaration\n * @param declaration.token - optional field\n *\n *  @example\n * ```ts\n * const LOGGER_MODULE = declareModule<LoggerModule>({\n *   factory: (container) => {\n *     const transport = container.resolve(TRANSPORT_TOKEN).open();\n *     return {\n *       logger: { log: (message) => transport.write(message) },\n *       destroy: () => transport.close(),\n *     }\n *   },\n *   exports: {\n *     logger: LOGGER_TOKEN,\n *   },\n * });\n * ```\n */\nexport function declareModule<T extends Module<AnyObject>>(\n  declaration: Omit<ModuleDeclaration<T>, 'token'> &\n    Partial<Pick<ModuleDeclaration<T>, 'token'>>,\n): ModuleDeclaration<T> {\n  return { ...declaration, token: declaration.token ?? token() };\n}\n\n/**\n * @deprecated Use `declareModule` instead\n *\n * Declares bindings of several modules\n *\n * @param modules - module declaration entries\n */\nexport function declareModuleBindings(\n  modules: ReadonlyArray<ModuleBindingEntry>,\n): ModuleDeclaration<Module> {\n  return declareModule({\n    factory: () => ({}),\n    imports: modules,\n  });\n}\n"],"mappings":"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"}