require 'hanami/utils' module Hanami # Registered components # # @since 0.9.0 # @api private # # @see Hanami::Components module Components # rubocop:disable Metrics/ModuleLength # Require the entire project # # @since 0.9.0 # @api private register 'all' do requires 'logger', 'code', 'mailer', 'model', 'apps', 'finalizers' resolve { true } end # Setup project's logger # # @since 1.0.0 # @api private register 'logger' do prepare do require 'hanami/logger' end resolve do |configuration| if configuration.logger.is_a?(Array) if logger_interface?(configuration.logger.first) configuration.logger.first else Hanami::Logger.new(Hanami.environment.project_name, *configuration.logger) end end end end # Check if code reloading is enabled # # @since 0.9.0 # @api private register 'code_reloading' do prepare do begin require 'shotgun' rescue LoadError # rubocop:disable Lint/HandleExceptions end end resolve do !!(defined?(Shotgun) && # rubocop:disable Style/DoubleNegation Components['environment'].code_reloading?) end end # @api private register 'code' do run do directory = Hanami.root.join('lib') if Hanami.code_reloading? Utils.reload!(directory) else Utils.require!(directory) end end end # Tries to load hanami-model, if available for the project # # @since 0.9.0 # @api private # # @example With hanami-model # Hanami::Components.resolve('model') # Hanami::Components['model'] # => true # # @example Without hanami-model # Hanami::Components.resolve('model') # Hanami::Components['model'] # => nil register 'model' do requires 'logger', 'model.configuration', 'model.sql' resolve do if Components['model.configuration'] Hanami::Model.load! Hanami::Model.configuration.logger = Components['logger'] true end end end # Tries to evaluate hanami-model configuration, if available for the project # # @since 0.9.0 # @api private # # @example With hanami-model # Hanami::Components.resolve('model.configuration') # Hanami::Components['model.configuration'].class # => Hanami::Model::Configuration # # @example Without hanami-model # Hanami::Components.resolve('model.configuration') # Hanami::Components['model.configuration'].class # => NilClass register 'model.configuration' do requires 'model.bundled' resolve do |configuration| if Components['model.bundled'] Hanami::Model.instance_variable_set(:@configuration, nil) if Hanami.code_reloading? Hanami::Model.configure(&configuration.model) Hanami::Model.configuration end end end # Tries to evaluate hanami-model configuration, if available for the project # and it doesn't activate migrations logger # # @since 1.1.0 # @api private # # @example With hanami-model # Hanami::Components.resolve('model.configuration.no_logger') # Hanami::Components['model.configuration.no_logger'].class # => Hanami::Model::Configuration # # @example Without hanami-model # Hanami::Components.resolve('model.configuration.no_logger') # Hanami::Components['model.configuration.no_logger'].class # => NilClass register 'model.configuration.no_logger' do requires 'model.bundled' prepare do require 'stringio' end resolve do |configuration| if Components['model.bundled'] Hanami::Model.configure(&configuration.model) Hanami::Model.config.migrations_logger(StringIO.new) Hanami::Model.configuration end end end # Tries to load SQL support for hanami, if available for the project # # @since 0.9.0 # @api private # # @example With hanami-model # Hanami::Components.resolve('model.sql') # Hanami::Components['model.sql'] # => true # # @example Without hanami-model # Hanami::Components.resolve('model.sql') # Hanami::Components['model.sql'] # => nil register 'model.sql' do requires 'model.configuration' prepare do begin require 'hanami/model/sql' rescue LoadError # rubocop:disable Lint/HandleExceptions end end resolve do true if defined?(Hanami::Model::Sql) end end # Check if hanami-model is bundled # # @since 0.9.0 # @api private # # @example With hanami-model # Hanami::Components.resolve('model.bundled') # Hanami::Components['model.bundled'] # => true # # @example Without hanami-model # Hanami::Components.resolve('model.bundled') # Hanami::Components['model.bundled'] # => nil register 'model.bundled' do prepare do begin require 'hanami/model' rescue LoadError # rubocop:disable Lint/HandleExceptions end end resolve do true if defined?(Hanami::Model) end end # Tries to evaluate hanami-mailer configuration # # @since 1.0.0 # @api private # # @example With hanami-mailer # Hanami::Components.resolve('mailer.configuration') # Hanami::Components['mailer.configuration'].class # => Hanami::Mailer::Configuration register 'mailer.configuration' do prepare do require 'hanami/mailer' require 'hanami/mailer/glue' end resolve do |configuration| unless configuration.mailer_settings.empty? if Hanami.code_reloading? && !Hanami::Mailer.configuration.nil? Hanami::Mailer.configuration = Hanami::Mailer.configuration.dup end configuration.mailer_settings.each do |settings| Hanami::Mailer.configure(&settings) Hanami::Mailer.configuration.mailers.each do |mailer| mailer.configuration = Hanami::Mailer.configuration.duplicate Hanami::Mailer.configuration.copy!(mailer) end end Hanami::Mailer.configuration end end end # Tries to load hanami-mailer # # @since 1.0.0 # @api private # # @example # Hanami::Components.resolve('mailer') # Hanami::Components['mailer'] # => true register 'mailer' do requires 'mailer.configuration' resolve do if Components['mailer.configuration'] Hanami::Mailer.load! true end end end # Loads the routes for all the mounted Hanami/Rack applications # # This is used only by `hanami routes` command. # # @since 0.9.0 # @api private register 'routes.inspector' do requires 'apps.configurations' prepare do require 'hanami/components/routes_inspector' end resolve do |configuration| RoutesInspector.new(configuration) end end # Loads all the Hanami applications in the project # # @since 0.9.0 # @api private register 'apps' do resolve do |configuration| configuration.apps do |app| component('app').call(app) end true end end # Evaluates all the Hanami applications' configurations in the project # # @since 0.9.0 # @api private register 'apps.configurations' do resolve do |configuration| configuration.apps do |app| component('app.configuration').call(app) end true end end # Evaluates all the Hanami assets configurations for each application in the project # # This is used only by `hanami assets precompile` command. # # @since 0.9.0 # @api private register 'apps.assets.configurations' do requires 'apps.configurations' prepare do require 'hanami/components/app/assets' end resolve do |configuration| [].tap do |result| configuration.apps do |app| result << Components::App::Assets.resolve(app) end end end end # Finalizers for the project # # @since 0.9.0 # @api private register 'finalizers' do requires 'plugins', 'finalizers.initializers' resolve { true } end # Load project initializers # # @since 0.9.0 # @api private register 'finalizers.initializers' do run do Hanami::Utils.require!( Hanami.root.join('config', 'initializers') ) end end # Load plugins # # @since 1.2.0 # @api private register 'plugins' do resolve do |configuration| Hanami.plugins.each do |plugin_configuration| configuration.instance_eval(&plugin_configuration) end end end # Configure, load and finalize a Hanami application in the project # # @since 0.9.0 # @api private register 'app' do run do |app| ['app.configuration', 'app.frameworks', 'app.code', 'app.routes', 'app.finalizer'].each do |c| component(c).call(app) end resolved(app.app_name, true) end end # Evaluate the configuration of a single Hanami application in the project # # @since 0.9.0 # @api private register 'app.configuration' do run do |app| resolved("#{app.app_name}.configuration") do ApplicationConfiguration.new(app.namespace, app.configurations, app.path_prefix).tap do |config| app.configuration = config end end end end # Evaluate Hanami frameworks configurations of a single Hanami application in the project # # @since 0.9.0 # @api private register 'app.frameworks' do run do |app| ['app.controller', 'app.view', 'app.assets'].each do |c| component(c).call(app) end end end # Evaluate hanami-controller configuration of a single Hanami application in the project # # @since 0.9.0 # @api private register 'app.controller' do prepare do require 'hanami/components/app/controller' end run do |app| Components::App::Controller.resolve(app) end end # Evaluate hanami-view configuration of a single Hanami application in the project # # @since 0.9.0 # @api private register 'app.view' do prepare do require 'hanami/components/app/view' end run do |app| Components::App::View.resolve(app) end end # Evaluate hanami-assets configuration of a single Hanami application in the project # # @since 0.9.0 # @api private register 'app.assets' do prepare do require 'hanami/components/app/assets' end run do |app| Components::App::Assets.resolve(app) end end # Load the code for a single Hanami application in the project # # @since 0.9.0 # @api private register 'app.code' do run do |app| config = app.configuration config.load_paths.load! end end # Load the routes for a single Hanami application in the project # # @since 0.9.0 # @api private register 'app.routes' do prepare do require 'hanami/components/app/routes' end run do |app| Components::App::Routes.resolve(app) end end # Finalize a single Hanami application in the project # # @since 0.9.0 # @api private register 'app.finalizer' do run do |app| config = app.configuration namespace = app.namespace config.middleware.load! namespace.module_eval %(#{namespace}::Controller.load!) namespace.module_eval %(#{namespace}::View.load!) namespace.module_eval %(#{namespace}::Assets.load!) end end end end