- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
require "concurrent/hash"
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Containable
           
        
      
        
          
- 
            
            
              
            
            
  # Provides safe registration and resolution of dependencies.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  class Builder < Module
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def initialize dependencies = Concurrent::Hash.new, register: Register, resolver: Resolver
           
        
      
        
          
- 
            
              175
            
            
              
            
            
      super()
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              175
            
            
              
            
            
      @dependencies = dependencies
           
        
      
        
          
- 
            
              175
            
            
              
            
            
      @register = register.new dependencies
           
        
      
        
          
- 
            
              175
            
            
              
            
            
      @resolver = resolver.new dependencies
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              2275
            
            
              
            
            
      private_methods.grep(/\A(define)_/).sort.each { |method| __send__ method }
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              175
            
            
              
            
            
      alias_method :[]=, :register
           
        
      
        
          
- 
            
              175
            
            
              
            
            
      alias_method :[], :resolve
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              175
            
            
              
            
            
      freeze
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def extended descendant
           
        
      
        
          
- 
            
              174
            
            
              
                
                  then: 3
                
              
                
                  else: 171
                
              
            
            
      fail TypeError, "Only a module can be a container." if descendant.is_a? Class
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              171
            
            
              
            
            
      super
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      descendant.class_eval "private_class_method :dependencies", __FILE__, __LINE__
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    private
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    attr_reader :dependencies, :register, :resolver
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def define_dependencies target = dependencies
           
        
      
        
          
- 
            
              413
            
            
              
            
            
      define_method(:dependencies) { target }
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def define_register target = register
           
        
      
        
          
- 
            
              175
            
            
              
            
            
      define_method :register do |key, value = nil, as: :cache, &block|
           
        
      
        
          
- 
            
              142
            
            
              
                
                  then: 9
                
              
                
                  else: 133
                
              
            
            
        fail FrozenError, "Can't modify frozen container." if dependencies.frozen?
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              133
            
            
              
            
            
        target.call key, value, as:, &block
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def define_namespace target = register
           
        
      
        
          
- 
            
              187
            
            
              
            
            
      define_method(:namespace) { |name, &block| target.namespace name, &block }
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def define_resolve target = resolver
           
        
      
        
          
- 
            
              238
            
            
              
            
            
      define_method(:resolve) { |key| target.call key }
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def define_each target = dependencies
           
        
      
        
          
- 
            
              198
            
            
              
            
            
      define_method(:each) { |&block| target.transform_values(&:first).each(&block) }
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def define_each_key target = dependencies
           
        
      
        
          
- 
            
              181
            
            
              
            
            
      define_method(:each_key) { |&block| target.each_key(&block) }
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def define_key? target = dependencies
           
        
      
        
          
- 
            
              209
            
            
              
            
            
      define_method(:key?) { |name| target.key? name }
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def define_keys target = dependencies
           
        
      
        
          
- 
            
              181
            
            
              
            
            
      define_method(:keys) { target.keys }
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def define_clone
           
        
      
        
          
- 
            
              175
            
            
              
            
            
      define_method :clone do
           
        
      
        
          
- 
            
              24
            
            
              
                
                  then: 3
                
              
                
                  else: 9
                
              
            
            
        dup.tap { |duplicate| duplicate.freeze if dependencies.frozen? }
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def define_dup target = self.class,
           
        
      
        
          
- 
            
            
              
            
            
                   local_register: register.class,
           
        
      
        
          
- 
            
            
              
            
            
                   local_resolver: resolver.class
           
        
      
        
          
- 
            
              175
            
            
              
            
            
      define_method :dup do
           
        
      
        
          
- 
            
              18
            
            
              
            
            
        instance = target.new dependencies.dup, register: local_register, resolver: local_resolver
           
        
      
        
          
- 
            
              18
            
            
              
            
            
        Module.new.set_temporary_name("containable").extend instance
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def define_freeze
           
        
      
        
          
- 
            
              199
            
            
              
            
            
      define_method(:freeze) { dependencies.freeze and self }
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def define_frozen?
           
        
      
        
          
- 
            
              190
            
            
              
            
            
      define_method(:frozen?) { dependencies.frozen? }
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
end