Class: Kraftwerk::App

Inherits:
Object
  • Object
show all
Includes:
Hanami::Utils::ClassAttribute
Defined in:
lib/kraftwerk/app.rb,
lib/kraftwerk/app/components.rb,
lib/kraftwerk/app/dependencies.rb,
lib/kraftwerk/app/configuration.rb

Constant Summary collapse

RoutingAlreadyDefined =
Class.new(StandardError)
DependenciesAlreadyDefined =
Class.new(StandardError)
AlreadyConfigured =
Class.new(StandardError)

Class Method Summary collapse

Class Method Details

.create_components!Object

Creates components Configuration must be present and final at this point



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/kraftwerk/app/components.rb', line 9

def self.create_components!
  kraftwerk_app = self
  config = self::Configuration
  klass = Class.new do
    extend Dry::Container::Mixin

    # Rack application for use in config.ru
    register(:rack_app, memoize: true) do
      router = resolve(:router)
      reloader = resolve(:reloader)

      Rack::Builder.new do
        use Kraftwerk::Middleware::Reloader.new(reloader)
        use Hanami::Middleware::BodyParser, :json
        use Kraftwerk::Middleware::RequestTelemetry, kraftwerk_app
        run router
      end
    end

    register(:router, memoize: true) do
      kraftwerk_app::Configuration.routing.routes
    end

    register(:reloader, memoize: true) do
      if config.reloading_enabled
        require 'zeitwerk'
        loader = Zeitwerk::Loader.new
        config.autoload_paths.each { |path| loader.push_dir(path) }
        loader.enable_reloading
        loader.setup
        loader
      else
        # fake reloader
        Class.new do
          def reload; end
        end
      end
    end

    register(:telemetry, memoize: true) do
      Kraftwerk::Telemetry.new
    end
  end

  self.const_set('Components', klass)
end

.create_configuration!(namespace) ⇒ Object

Creates class holding app configuration



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/kraftwerk/app/configuration.rb', line 6

def self.create_configuration!(namespace)
  klass = Class.new do
    extend Dry::Core::ClassAttributes

    defines :logger
    logger ::Logger.new($stdout)

    defines :reloading_enabled
    reloading_enabled ENV['RACK_ENV'] != 'production'

    defines :autoload_paths
    autoload_paths File.directory?('endpoints') ? ['endpoints'] : []

    defines :routing
  end

  namespace.const_set('Configuration', klass)
end

.create_dependencies!(&block) ⇒ Object



7
8
9
10
11
12
13
14
# File 'lib/kraftwerk/app/dependencies.rb', line 7

def self.create_dependencies!(&block)
  klass = Class.new do
    extend Dry::Container::Mixin
    instance_exec(&block)
  end
  
  self.const_set('Dependencies', Dry::AutoInject(klass))
end

.dependencies(&block) ⇒ Object



54
55
56
57
58
59
# File 'lib/kraftwerk/app.rb', line 54

def dependencies(&block)
  return self.create_dependencies!(&Proc.new(&block)) unless defined?(self::Dependencies)
  
  raise DependenciesAlreadyDefined if block_given?
  self::Dependencies
end

.inherited(base) ⇒ Object



23
24
25
# File 'lib/kraftwerk/app.rb', line 23

def self.inherited(base)
  create_configuration!(base)
end

.initialize!Object

Initializes all the machinery Should only be called once



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/kraftwerk/app.rb', line 29

def self.initialize!
  self::Configuration.freeze
  create_components!

  require 'kraftwerk/logger/dev_logger'
  logger = Kraftwerk::Logger::DevLogger.new($stdout)

  self::Components['telemetry'].attach(
    'kraftwerk-request-start-log',
    [:kraftwerk, :request, :start],
    &logger.method(:handle_request_start)
  )
  self::Components['telemetry'].attach(
    'kraftwerk-request-finish-log',
    [:kraftwerk, :request, :finish],
    &logger.method(:handle_request_finish)
  )
end

.rack_appObject



61
62
63
# File 'lib/kraftwerk/app.rb', line 61

def rack_app
  self::Components[:rack_app]
end

.routing(&block) ⇒ Object



49
50
51
52
# File 'lib/kraftwerk/app.rb', line 49

def routing(&block)
  raise RoutingAlreadyDefined unless self::Configuration.routing.nil?
  self::Configuration.routing Kraftwerk::Router.new(&Proc.new(&block))
end