lib/hanami/configuration.rb in hanami-2.0.0.alpha8 vs lib/hanami/configuration.rb in hanami-2.0.0.beta1

- old
+ new

@@ -5,82 +5,173 @@ require "concurrent/array" require "dry/configurable" require "dry/inflector" require "pathname" -require_relative "application/settings/dotenv_store" +require_relative "constants" require_relative "configuration/logger" -require_relative "configuration/middleware" require_relative "configuration/router" require_relative "configuration/sessions" -require_relative "configuration/source_dirs" -require_relative "constants" +require_relative "settings/dotenv_store" +require_relative "slice/routing/middleware/stack" module Hanami - # Hanami application configuration + # Hanami app configuration # # @since 2.0.0 class Configuration include Dry::Configurable + setting :root, constructor: ->(path) { Pathname(path) if path } + + setting :no_auto_register_paths, default: %w[entities] + + setting :inflector, default: Dry::Inflector.new + + setting :settings_store, default: Hanami::Settings::DotenvStore + + setting :slices do + setting :shared_component_keys, default: %w[ + inflector + logger + notifications + rack.monitor + routes + settings + ] + end + + setting :base_url, default: "http://0.0.0.0:2300", constructor: ->(url) { URI(url) } + + setting :sessions, default: :null, constructor: ->(*args) { Sessions.new(*args) } + + setting :logger, cloneable: true + DEFAULT_ENVIRONMENTS = Concurrent::Hash.new { |h, k| h[k] = Concurrent::Array.new } private_constant :DEFAULT_ENVIRONMENTS - attr_reader :application_name + # @return [Symbol] The name of the application + # + # @api public + attr_reader :app_name + + # @return [String] The current environment + # + # @api public attr_reader :env + # @return [Hanami::Configuration::Actions] + # + # @api public attr_reader :actions + + # @return [Hanami::Slice::Routing::Middleware::Stack] + # + # @api public attr_reader :middleware + + # @api private + alias_method :middleware_stack, :middleware + + # @return [Hanami::Configuration::Router] + # + # @api public attr_reader :router - attr_reader :views, :assets + # @return [Hanami::Configuration::Views] + # + # @api public + attr_reader :views + + # @return [Hanami::Assets::AppConfiguration] + # + # @api public + attr_reader :assets + + # @return [Concurrent::Hash] A hash of default environments + # + # @api private attr_reader :environments private :environments - # rubocop:disable Metrics/AbcSize - def initialize(application_name:, env:) - @application_name = application_name + # @api private + def initialize(app_name:, env:) + @app_name = app_name @environments = DEFAULT_ENVIRONMENTS.clone @env = env # Some default setting values must be assigned at initialize-time to ensure they - # have appropriate values for the current application + # have appropriate values for the current app self.root = Dir.pwd - self.settings_store = Application::Settings::DotenvStore.new.with_dotenv_loaded + self.settings_store = Hanami::Settings::DotenvStore.new.with_dotenv_loaded - config.logger = Configuration::Logger.new(env: env, application_name: application_name) + config.logger = Configuration::Logger.new(env: env, app_name: app_name) - @assets = load_dependent_config("hanami/assets/application_configuration") { - Hanami::Assets::ApplicationConfiguration.new + @assets = load_dependent_config("hanami/assets/app_configuration") { + Hanami::Assets::AppConfiguration.new } @actions = load_dependent_config("hanami/action") { require_relative "configuration/actions" Actions.new } - @middleware = Middleware.new + @middleware = Slice::Routing::Middleware::Stack.new @router = Router.new(self) @views = load_dependent_config("hanami/view") { require_relative "configuration/views" Views.new } yield self if block_given? end - # rubocop:enable Metrics/AbcSize + # Apply configuration for the given environment + # + # @param env [String] the environment name + # + # @return [Hanami::Configuration] + # + # @api public def environment(env_name, &block) environments[env_name] << block apply_env_config self end + # Configure application's inflections + # + # @see https://dry-rb.org/gems/dry-inflector + # + # @return [Dry::Inflector] + # + # @api public + def inflections(&block) + self.inflector = Dry::Inflector.new(&block) + end + + # @api private + def initialize_copy(source) + super + + @app_name = app_name.dup + @environments = environments.dup + + @assets = source.assets.dup + @actions = source.actions.dup + @middleware = source.middleware.dup + @router = source.router.dup.tap do |router| + router.instance_variable_set(:@base_configuration, self) + end + @views = source.views.dup + end + + # @api private def finalize! apply_env_config # Finalize nested configurations assets.finalize! @@ -90,72 +181,53 @@ router.finalize! super end - setting :root, constructor: -> path { Pathname(path) } - - setting :inflector, default: Dry::Inflector.new - - def inflections(&block) - self.inflector = Dry::Inflector.new(&block) - end - - setting :logger, cloneable: true - + # Set a default global logger instance + # + # @api public def logger=(logger_instance) @logger_instance = logger_instance end + # Return configured logger instance + # + # @api public def logger_instance @logger_instance || logger.instance end - setting :settings_path, default: File.join("config", "settings") - - setting :settings_class_name, default: "Settings" - - setting :settings_store, default: Application::Settings::DotenvStore - - setting :source_dirs, default: Configuration::SourceDirs.new, cloneable: true - - setting :base_url, default: "http://0.0.0.0:2300", constructor: -> url { URI(url) } - - def for_each_middleware(&blk) - stack = middleware.stack.dup - stack += sessions.middleware if sessions.enabled? - - stack.each(&blk) - end - - setting :sessions, default: :null, constructor: -> *args { Sessions.new(*args) } - private + # @api private def apply_env_config(env = self.env) environments[env].each do |block| instance_eval(&block) end end + # @api private def load_dependent_config(require_path, &block) require require_path yield rescue LoadError => e raise e unless e.path == require_path require_relative "configuration/null_configuration" NullConfiguration.new end + # @api private def method_missing(name, *args, &block) if config.respond_to?(name) config.public_send(name, *args, &block) else super end end + # @api private def respond_to_missing?(name, _incude_all = false) config.respond_to?(name) || super end end end