# frozen_string_literal: true require 'dry/plugins/config' require 'delegate' require 'forwardable' # noinspection YARDTagsInspection module Dry module Plugins # @abstract A delegator providing Plugin DSL class Plugin < SimpleDelegator extend Forwardable # @overload initialize(registry, name, plugin) # @param registry [Registry] # @param name [#to_s] # @overload initialize(registry, plugin) # @param registry [Registry] # @param plugin [Module] def initialize(registry, name, plugin = nil) @__registry__ = registry plugin = name if name.is_a?(Module) self.name = name self.plugin = plugin if plugin end # @!method config # @return [Config] def_delegators :@__registry__, :config # Module with actual plugin data # @return [Module] def __getobj__ super do __setobj__ load end end alias plugin __getobj__ # @param plugin [Module] def __setobj__(plugin) self.name = plugin if plugin super(plugin) end alias plugin= __setobj__ # @return [Symbol] attr_reader :name # @param name [#to_s] # @return [Symbol] def name=(name) name = name.to_s @name = Inflecto.underscore(Inflecto.demodulize(name)).to_sym unless name.empty? end # @param host [Module] # @param configuration [Proc] # # @return [] def call(host, &configuration) load_dependencies(host) host.send(:include, plugin) if plugin.const_defined?(Plugins.config.class_interface_name) host.extend(plugin.const_get(Plugins.config.class_interface_name)) end configure(host, &configuration) if configuration host.used_plugins << name host end alias plug call # Resolves the plug-in `Module` from the {Registry} # @return [Module] def load @__registry__.resolve(name) end # Load plugin and plugin dependencies (if declared) # # @param host [Module] def load_dependencies(host) return unless plugin.respond_to?(Plugins.config.load_dependencies_method) plugin.public_send(Plugins.config.load_dependencies_method, host) end # Configure the `host` using `configuration` # @param host [Module] # @param configuration [Proc] def configure(host, &configuration) if plugin.respond_to?(Plugins.config.configure_method) return plugin.public_send(Plugins.config.configure_method, host, &configuration) end host.module_eval(&configuration) end end end end